scotch-5.1.12b.dfsg/0000755000175300017530000000000011422605430014366 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/grf/0000755000175300017530000000000011145123043015141 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/grf/4elt.grf.gz0000444000175300017530000051655610656300346017161 0ustar hazelscthazelsct[5L[6D?ZJ;9%qde$gy7ko/߿ǧ[}wES=~k+ﯥqtG߿_ #'~9ha;NK]z~~?6V|ڿÒ]gl0kk-~ٟm_(ma ~xw3u3 Cf<[~?w~40O\{þ_aQ!렏h!hz[`s11G`41__爟ƨþqƱFҖhlE-g¯/mio(X"hߏf9<~78UaqúMhuޟ];?/VoV3a,~ۓ?zpq|.D#*N=[ ;~ÏH1hׯşc0 w# =pZࡇmn7 τZa{ cG-s03Wnz'oԿ: ADW_#/?Ya4-8cp{JF~CyEp{Hn_:`'Y~7¢6OB< 'sva _>\3 _tGx=~pן_G#bO~-l'Y~]FףVG~? ?FGDh>p/'4ah75kg?>6~Dun"ShwoP~'C8^,{B?"6t$ߝ;\!Z,.Ll$GS0 Fë5@_84~EN·KHǀ|w[yҽaMK OB /Uph8{d^etާ#H D!wJ1_{/d{ˏX я{^H֏aH3)|bMa3Nc8N.bl|pd7[G<юя-fkt6%hif[d3mmT%Q6HQ%㝸U/|B'$}HGj+ =p?>I#Gmh޿6cÿF?@cHxjI?ZGƁH+[h,Y!*Ub\K8Rݴ;-h)z9b} l(׶/<&-wTL VR*`t:0 D v ?xX0(KDxmp>¤X7?=. RLTйG'@DWOԝl_#{{>˟1ᵟC^m8,j,1$O?E*&"Ke#PZ NP1E n7$]B98HpXЇiƦ`7-O22avo̧{|0|bGᄶOY/X}OgNRj͘v2ݩ?;qZ%[G)ˀD *`0?-^T?}lLe/AN,@rlB$fEBl %:-o#~}}x@8s/ =5tD58VB%V!~i%D 'Ⰶq_\nԅmaA,".+S紴)Xi])jZo XBL\ XB # SJ\;&OMtY2aOY rG+|p%437b +<˪ Nx4!rF4+Gv4+M\, ,k'z8qSGQ!zp ]bNKJHbm~x{,X{3Ѱˡ,e2#>p!;@j9H ?E@[xjklP=z&5K;uK䝐0zU;23.LzP#Z$#+.y=#8<[ 9Z6҈e|"~--c:X}`"JbܱJNq/5ŠRsAkWB7[ƸHy(ᩅx2OAeN>u4vG/㊈tT *A  X)Kk6qeJ< 7*j(7m~g|VM0 meva#:8qt)0b&W㢰=_tpbwZ*mt8&@UOD~,zzmF~W3xf=x&oi cK/+l+c``;^dUfk} J#錾{2'_6sCb>@'^: ēgO}GUDhňnN?—x '5g>Et}ҠLxYrŜ5_UPJGkx\Ɛ}0 CN+ &$T&8Gch("bDF]:;p~G$ nMQ+,>#|JܦlkvfG M<ݷ߯V;(.Jn Pgϰš;NL{{&t5VFڴ-6OL7,h.6H€ȴ+pl! sDw;6D0/$g`}#E=!h@A ʆal5Dേ0[}8DX=0}oD$xBdvՒYu,jq/ᏻ6@? e;FO/J$ðc,"DR O*_a`.2}h ﷥?'Waz4pO. %WRVw#fx><߇WH,i?QQF.?ΤxK b7c]20 z@5(}X K){+ VC^CmÆ܁XIG)KKhF!$ R[0cgŪ$ E:8QQx%9JxûJc1bLۍu1j% u'5ŏn(Ό7ݖcb2 ߮V1DK u+ZH1.ĕDlbCM;0xބ r40 0Wd)%mʀdEڐx/gJ^! XCj#Th€6"1~9E8cRE1)"m U5 #EQx1ū^A!;C3u;a{~!WT3)Mzz>^>{_  b$k7,i X?}ܲ"0QwFрp`' :^{Pq/k>:5t Z=AxCH_?áπ~U@=7Cg;ʗ}2P/ }LwLhW:c)rˆQœ#sh#(rٸ0k T PyD ؎4_'.jħo<~s$14R ?1j#ЉG}Ļ@QV;F?Q Y*Ie<؏'F{z8X ;q)VxfN59~n2^U`wߢ먨<O3zKuKfn$o3FXvީ]Ng"ʼS棏);9Kn'VKAW숩G 7=|tmx:Xs,Pjooxm83WxO_!-3~gd nV'D]aፕTۨXb- &ċD ކp"=a\5F|1r1d\Ӌh""|ɧW#$"ϕwWǛo4"ǽ?#*|D 1Bz<(6 13|t³+EMZ㣀@ ⍱}0m+a>e6x.FڒBH;c!'a-u(~m)r"ƈB {@3=e6uz.N5>bƳ3W=ɵ= 2草V\`M!:'Wŕ!%alb:[`dOѾ87+N'N,:=3>C>[Do8왏(D2=ㅌ(5ڦL;"YRFU|Q qg-U'*_|4hQ4`ۼϥ0=`Ex1u?-1yĉ s>a4|W.~1b>㫳Hӧ% 9ط_;[~1X/ŻOAX~gEK":4ٱo{TQ^Ʉx m`K$`/0R(<5@/b%W&6ӮOo[b59gZ`Rb&\GM{ `d$`݄Q0|1$5Fh@ ) 7кL7.4n@1>i-^#_"H}zYh~Xj~pCn^0t` YfE/1av$1έ0ÿEBLaR[ ⮄O!T*#%AjAh?5qӶD:e7]P3ڎo~f&J#vmrE z+(|xٴ%H&Ohp 'Dg&1Xcg^R> OP q(hSʰ#Æao_/ތBHg܌=HS~%Y#㷘( V :=?OFɧܯ.7 ak9UBy.gH's&mCAe(*F0L@.r 7gĈnsI~KOajYGךB hZ"+ vB$sȌgDpoD[1*qe;!V'V,yܩ ICDqqw#װkȨ,klz9œG_MzǒEW  Dᣖc/!Xތ"bWE:sWė#\qeCT.m`gHoXӇDCiUûC>Zm.D gӄ,j#:-h*%l=p{ĮM"Bh#K'l7ՇmDA[k ZRć'=2[A%%E%v`̈́{a8E" t#HhfXH旓G,"≏b=p Pi$}ĈpǶ -†tvCSU ǯ~ :N #2_g h1&#El,T RRd%Po2wY'mؚ%Lَ=56r)p_f2_+-h^1Ӈ>=vJ [2z[XS쎔ff"@-7[r(EKs%׾$w,O`b"bd~30S]s^yF,?淯TeA#E=£OKX:~}32b}!C᎖v`3 ~Cyd{('JAt?#܁@%/ThqeA*1=M>ZFW{NR+&ƌylyrӢCmm`O53Xƞ83eI‚.)aώ@P-lD9TX-g%ݦf5~"h?/ZP7/I;,x9׎{MxP U]쥴-EX0_&Jgvuy埊k8#\h=ehp>ϐ[=4^b9ZzD!\ˡ}^=߷7q{EgOo:o¥xJ&*hhͫ@mA7q |9<#L#j7Aۭb-\ J/'wL_A@1@&SoBh%pZ جX-h}E€_IO8L 'b 1䞭,,Z^[;'1:(?| .g2l'd,_ICɠar/Ҿhi$f(D_cەlßF_=0gU=whX`PPnv1 !Vl;V ih;ڿXE JO8xJ?l?` iVK!_k Xp쉽CB6F|&⎐6⯫dOHsb4fSk "bQG &el@[݅I/M5(Ec/n^^ aP+1bJ Z>ϒ(Q 4BB;o(S ۇ- jK<#!ຩqw2~}IL*n`cdl1,M W-$k'L`A؝.pe>nAo.|_D G oʾ{}E6gFf!1j ~Ņdwl epSc[ЀPnEM7B&$gSB̀4b;A?Jmۘͽl#gMl<),7 ٛ־:&_GKkPI7[{ׁQ4'T GDZW^$k/kx&uh maa˵|!ͷ@!BKJyi *?_!`8@_5HDƅ_{pt*>w'dtzSy=|ڋ%Мpr(>6cT?pbKpz=j^_,M m$,y`4}mun4 @㴱$*qu1p MoG~BH!hW{ab\Z06o׍Qgsx[_#5QO'Gt~͘zq1va]#,e,1?2!4`(VQ,[8td6%sr h1xul?w]Me:|SM-?幩xXKhGeFKI n~ >ًҙ&=,&q~,0bV0AAp&h }"MLpde߿^2ܪx?AR=yDѮRr%XCmļ`\6ͷܻ 8&g{9`6|7b 댟AOr dҝ\n8߅B)_A+hhoo24ap?YvXS1YL^O9Vno5:$nc`YF]/4bApZ"ۺn1RxY (K30E IȞV҈H.ԧ}>n/Cu{˕RT7${{pF$SkJ,7~HA~k Kzd7I,ДU??C|S`.T;iJ+ g{Ss+5}68JRC(;(t1Ħr{wigCSnv6[@YXq't$D"ӃG#|crV<~ i Ţ RP ;N=r z{Jmة!OpXN@;2vPn2#Xf|_t~Nꂺ %SOᙸa\("]6Vݲ[j3z   lmm@h`*XPpSׯXڕ3ÐD~, rx.Smހ|hPwsӏ#8S1;`oYjd ~FK?) Г c{E<(5Qެ]oVFޞ,#K&afH6-9Yl͙c.DP睑` ctSN-J9C![U͑ix]<ϼ,NvKSYU Gi = *`(1~<zE%|[Evsx=F0d&īF!%Ts[^C @2a rޚPˀ #{/GZ C:%@Vs3q[b*4gEwTK@9g]DA+J6u` r]*%Ν Nb}2j!ף0dixvkќT7uO4Z7~֣4 "0}^nC؟U{oG2@LXwOڻ/WW-E(ךSt2Fh?ط<흳8l%{U| p"JH|΅^fc)H REQ#~DhWp>v:t 4?n R_NnnI!BDt嚱5,oL ~ Goh!:>7qbU;{=WFqz>%bN֍=ٳ6ܱ&_dx ϼ BŎ0LjyTi*"<pY5]G7auГ(_e}cgf2w YYj,ql0\:y4znɍN S {\`,'-/cTQU ӈQ#?`IjNleۋ9\ "C_5uvďTL*.^ā*39g͌ PA!hD(aZGurW_br_vh3[wzŲ7pl,2W #h[bG:eEE \g2G2$g)O=km=udG2י<CeSXǵƗQo0}죒Cu?+xVJ *keԋA/=:J-Yej\ \l R+2m;aP]QX Ve"'ݳNѺFH+ #:E L7*&yd`:~餯'DU $pG??HJ5dWAS|^>ARb-@mQig`pΆUI:4+}QZ}90%T{Ѹw9HmԜ7nQ'Rrs D"r\x}Ϛ:pveFK$i&V^c.F~WF4+XQsN(z9UM'u_wu U1daG=>̃qF5dH,oCb*3;Ek.Y2lbũ6ʹQsn?l?6[@:{3Lģ#:E%(D>6,! j$j-K1mrT#Q?{=Y _JZ}ݬP;kQ?(be6sѳQ{8C'WZ4-$u3x3hL+*TIT*: k0 eHHZ1` =@3x}s+?WyVv *V̝ZUFpJihBءϒ|YRuKg (|Kq8iR ʾGOrO)#2gh໺F|!m%?ZKR: WgOOߗ?J}-N딌|xe *H?`Rz* H߾N`{sUgd/bߺkpi&f-8#=rA$8(BNt_ayNS**@G_L7D а92O@%2:S?+y:*>-cdjW8 A#޾(O}3~d1^sܻo=)zec%Cd "@뤹x3vS|Oqi9ΠsIA)hJ3REI7-CB]Xj OeŃDq^kF/jcc=Dq?[~㴓~-wfi 0)Q2RC5J>.,B[-~2U؆JqH nth$2pQA2껏j2L.PJ5.d¥,᪌r%01Ϻ P8Ӛ$w$^CI(p!Μ>!U!#YZ_'S֑>4KmO?b'Jʴ3YٟHA[S߰:y&%kGn9OQc'zo{'(eb9́?xu#zӲ=MH"Z]DB}|T)[ʶqfIj:KU)OZ+>9"!%>bE _8ٵ( ɷ%}Ი:.&˨tǪA ]>!5<0qjӈjz]GC]BK)3 U# %B'/@ +I'v $ qKJO8u. 1P,#*p+H-e.yRaeg:$a`hNןXd#N䖣}X9F(Cws떗*%lZ#zaL_sk'|\57CbGZ6LafF$e~UIy'SS~ *`,ƬIxReC@Nثb@ƭLpׯw#AnX<%_"cv#>g(?.yk8q0R`mJGΤ-4ʗ-U*l$kI-+>oNA!in}dbb4@ /;I"SdEh B8I p G} 8{%e*Up5dMt$/li)R$a gdj`2WqT)*YT+qmHrARVR|*-p1w32>INPZdQUpɢ>N6 GUo,㗋.@#XeDVuLtcd;ԅN_HL*Æ0x+@Pѫ_ ]%6|%" E!bw2~#8uI0<#Ņ FPR%'.4EUʈF.z2Ǝ_jCbcE:ĭv| ]HIK \#I|%f)o݂+nX{O 7259N= ,/UF~AֽIؔ73#hWת B5}t,i1ňݞa'⽐8)Zj8L$%UzjI4|)dHd("MA䂽2X?dAP ŗ_K^W:-czzMsb 4EEvW=/5d@Eb%{6`5JUʪk]ӑf*Z,n _'2Cʮe;+@2 ßu!rɋc0;IJ[W LKKAM^ZZY_f3!M/TIU +v7̹ \S&*g*(ff6Cb_"/Y9euŝOtT]C@t%68X6O.,Nɉ3Hx@8K"L)J6``]!<\d; TVj\A7CY3 j 2˜lnqrɽ n2aTBG>40.ii4FFp-*E.Ra*q5}a\nI[e:i:R$i6R?tӤӪ<wgV$HY\ $7v'i#$L43>P\::^ 8ۮ?Bu+{EgA.3@'K^MTwH7eBd/{Bc6{jRW|[? FF3WT;\d9bJP+gI3e+{} K8LsY*:.uGA W+6/@\Zw`XSW i=wR)r`:+JYUŒ\{^v^;_EFuմ%QF Qzv?ZBE8R/]?*ӈ j+[J뾔zՉ *PHcRP$[6jee"2N ` 4$Mf6)SyWK%X Zra7΀m@Z͚BrPm!OBҫt 91Zͦ'Iig*KSǭhӇ3i(= NBd^_KIcQ s,:b68b"*AJũBK`t~H: n _.΄x]ڭ3!E^yktX`f;51۳ȠD&YY^HOhPܦ+t'`3fM<¸ ^[%BK'EèjUR1x1!M"c\]776zQU0 3Ww qN,BC>oxU%Nt+%"ݕ )!} 2.Z7Cp Gmu &SJJ%؀2͢'3;kK\pw0vXrw%2R7uŊy+\Y_N v,r [ȑ+G%MLI84Ŏ'bFX pJi|)`v{T9-Z$V8b1R% HDYp甘nE[WO 6ENĂVXv"aY?c^;)гDs2;o0.\ʭ_kd)ဠ914B |N !]"{NmlyigqLb@DKe<]mmbw}H=_p?Pãx>]'+F\qgBr-'2I8XG[;br qWb;%E̿IMsmR$aޓNk37nKVR˦ h;bN[˜]H֑TLjQYd)3\yFu _{#ˡVYxW|>KB&Q' LP/ZKhF/[DK8k^ҐAB90q4l$B{Bqa<")f6eD"90yw'ZPA6Catz3,[Z\4wBQ׺>;5" j:(Ajcף˰yCD[2K'(\J5jRgy?$8B#眾bUf'WQO_`E؂^]2oh;cOEf\%bc ֗ U)PVY!$$c6O-m{!/+VrggGhO^ֆz QuTrF:aH/6O QƇ>>a/';j@ 8!w/tS3š{{ս 0Tǭ+/vUS}lg:(HH8d9mG]5?CSwcs1[ϿYɒ|]815y]F"P^~^z B%!ؚZQuH /Q >BŶLXLXȗ>dVg!0Gl1&2V%MFd )> cQ51F3L'֤C&~1\!HOoyEoZ*=7+IqN֔ ϝC~D,گ1o 2&\8,F`??WO]Bm_@*h9<:oo`)?3jdHPuSVRqpF=,~4&wF!|0!fB-\~ AVB.O1PbP(1`>蹏ˈV7v)9Xx+; h[W}& Fg9_`]fm=F⩴>vz.wAs|Bߖ_.)ʱQ<_\g)˚>hLˁm[7RPkeC ҝ\2Zy,! ӘD\*ZemU3EYX48g+/j㬘A#y?2wNo(;0[+7bA?*8QC` Y"j]X>2֠{9`WN~%CVX:TYkk}-K:y}˃t]bb5XyW^p$+ɐן.=,XՇvHM,PA0Y 8.l?ԗD-V=e+Z<9ήJs%6Cq+,g%O>(|=!L 8tR^ R8e9N(3B_2`(DW  .)r!wF {}/^MJZU#w-[P4D+҃I$Tl0-j(b?<@HDyC.GʈwIJ22=o(BA}SӨd3$RD̖=k3kSTSMalpt{k[pOrmYe%RfYuDaʢIQ^z(8 )8SO32pG>p=+M;ۢ83Ҵ'agվsfi3EK, Mk_gn>Eb{7bL_aNX'Vuq]iQp>9Xr~HSZgh|+&Nls׭>DҧK/\!P PuK#2kj Xq]/2GEiG hJJ16ݹQTı] rI$ݓ K,T^Q.D3v+zxKn791,ɊǬ H[:QiZZxH8Qwzqzqjc;8O"e K ~\$(7VIj(N!6#RVz1IK]S^gq19U۱;GJ[OWHZZ* pBQFeE}e(hۙ @Td.QF[c;({O5bA,!K=;F* ( Z!Ψ0Mtض $}cla]Q Kc$$S$bߺDBkqA+x$62/]#y^\H^}P@xێ*=I]OObԪI"!:zG %0BnL3Jv]@Nf^C XRSOsUDK4b>w@Q/ xg[OcJr}+['a=ثz _q&XNi|qzOv7vq([^jH_SVyb#PNj$qg*.9ҳ9:ĭT ,L 1lx8QoC/ f&κRMt# 2*$:i]?v-c #YBgF:Q岃;nQ{8FzdɹӁ uTgp DWCmCe+c׀EC3@ķAMAʡ/U٨ @}NvE7a:3$=/\zYVU8Lm69(9(A8ZLQqbr,Auh;j<eI . ")I@4P`*Jᅸ@?h KF姕imv2JC-b-ʗ1# wDD(B}JUjIR:)^U7yWPDnEāی5̈́m]{r؊V^24J4*bzE<3( 'U8MwȚ=Ȱx?EtmKqdXj؇<YI5%b - 7a hD4U v@7鎿7R 73N*9SHCQJT%ڇ쌙M(+cߙK:%U.SAKwr's%7qM(> vqvb {F=fI)yC1GR{fWZ mq%[AǑr:r/MY4g0 5T м3"4Yۉ8L92E98&2iDG6bj= Jʜ`h=5[”*J|pMBOfΒ kj'bh+2{O' p$(L*~?ٝg<.#iVmAJ]ܺz_bKLEi|TG w.Ž8SM8x1-Ejv4o%ADәx˾Se몾Bl1P/"Xʹ- `6H`1-(AF /ɒg.s cՏ"|Sg0T OVg(t8GEQ-eO8I*5oc|V믚ݙ*xNQ0N'HiVDڌ<=BmTºފwjD-LeaH$M*qDsI'z5ܥZ18_[jm=6fq_VQ`W"e1s [y@Bk8h'NUb²U~Ķ]jhיŨa0BIrn7{y8]8Qλ.h.R[I4pG*mf$ j,ߴ3u-EZkɝMK nh:(˔qyÝ"q"^VOZy KھCʱr9Ge_2@fb>.yhfP?nVNg &x9 e[~n_9CT>P@]sAk̙,Rh8P[:LXx?j<6VWz3/4܅UIC]z kȶ_1x3Vf3rߐ梥Bxϣp:)rӻrĉa (Em5I0I.Pq.'H[W\+\yCl.o.("ʪZ%l3K΢ f$ w<oG lj2n+n(5vY1&THυv:c]ilWW 9Gy8pZ]V>dQ,Z>^h#͔P"(B\`Il;tMqa ɏUb$$"͏uy SNM {KէJjmfI.}3oz׎9SVi58!N@E4`8$x֛d`U_F~9aOhB$EMXZ:+~QRR6hJ%>0)bl ;BH/֌Yd, [E[k`+.'2nG\#&$ sxtr ɁH Q7Ł(=i^:U|Sq Fd 2C\tu "!>VC#HEf+-zp %w:%%SuH'd E qޤ?ROc w=ł(fPHD8Q?$-Z04';8,9 t qc2zIyvt"Վ0rtKl]qLJZ==:ہv >g '_(ZN;R> M.UTlS3}?F>x>S\v)3Q|&PY9=G;r]jj l,ht/\uƔ%B XqY< .R,9:n"? Ӈ,> L(ʦ_gAڹ􉦀 ^r$ICki0 Z'g-WT]EhکߤR-OHM@5x~􄶧1g͈NC402';ȷ j/ݝo"MHj)vD12_*$*Y]SHvl/P>oc5P*l=%@DK e Fye)cA'kW V c VߥjYrP8}] U<$;8,4>y/ ƭB=MCvBqnld o񐐀]a* 㿏<ahO.`:˹txo;uW2Z}*VTG?oް4 ({]w(2,_Ł)⽿lŖDc@ɂB $f8(:ՑӿUND]@_ܑôYl4m"Z"HC?^cOx#&c]F t gԾ43NKhuʔXhZ Qey(b۩,1;z <)h,.81LJ/#ZA|f,jswBlQ}uez7~Vܺ VV QoLNyid M:aoI狱56͂&N,r$‡":Q15y}wqAj`lѰ<5ދɆD|f&Qg.˛L66fǕ3B r'Rq"a2hn67Rb0 kD+2ޮD,z.!+4#2ثazۢ~/{,m-rzEa+9;t>3SHqj׻%:N6,Do LdkOLPlkӧҦGd/'N :1 2v^`c B:ǿ*~0q5xGa%6'dbSzd]O}|2vV~s;Ye_E˓K^ERl)Ro]hů;7 كrhi?+hQ~~ueg|вXG*3e9rb^uWbw DNhY @:yff޼ND-=$;6y~4v#' ([ BaowE+gxnJreKǛoUs*?#{#3lTF)_[tks@:m׹WC@:R!7r,¶59pqRK nyϧ⃎9$*Y;u@m}ܬ[,H|5ƼZzdJy %sDݕj4I8o3mUG *CmF qrGx%x'ك]L; 7̾B|81+; Xzr 3!b$a7Ӈ dzl=VBD O#?{x3N y ar ,#w*2qdl %A]IǩvEǏ9#BCjH*r\`2@F?0w1ܷdJ#n(3#fndNjC}(<窥x;$(U!S2(¨[V6CHip"I fE+xDF8VdK;@^byĊ8g$ @dN˃LNh t"b+|ł,Xps]᱾Hs9_"X^UҁNFGay3n!X &hzTOfۿKc G e93!nFip3c/`T>Y% 7 3dƽ%_~Y:sͧ7y>0SG౪hTL.&08ooU>MI {° -IK)NB0EIpFmKfȌW@"0GV).#澜eYB7W! 1ZHs!.nqi))²^5M@ࣽmf_`ŴvjYJsً*I{88m^;t* ^3-L%"_L&`9loWM#MՁ8"G>0QaG}KXS`[ gݓɵLJ{kSQrL #&%U܆2A_`,Yٷ~SE?B@2avE8- uesC]}CdR}[BlmX8ǩ'(ΩBWZYH٧\bڗ( i k|$+hzY0R+h( u))Wm'fb&!4Y!f/oFRTU'UDSjz%hq?R?Xo :Ҩ*i[bZuE#HjP6Gދ)o[}+ӄn$}?".=VI/B8$R8+/ԤFH;@1pgߜ3Vi5QowE$EܖȸyM͵yW+f*Θya[TKUo~nG"bᛏ>cWD!`䍊d2|ؤI.By\*pdF]R:e0Ҙ~d4 -,𥸷wZ(wƧ|{ZLl՟${qi/E{q@ڶJ"1P5{W6Wv Ffb:VKpV⇒I7}蛏R<4tFq: |[#0ꊸ]#Q9g#йJG+tWzUث{~u+?2$~w)eUKR}L] K\EUJ ԂTUBeЭ4eDʰ5Z d_W3P_v|UC|:mjEן.Q^@HQkg~ L$1O4`'ָҗk7߃?#%ֲ%$i@x۶uWm=,}[OnY_LWApJ/`/vEU\AF2~ /K}K86ޙC_Cdu;.]'NDpJйd ޫcjb'ePlqZRǩND ]|{mW(T4_to+Ub c3%8Ig;â1T?xɤL:8r" 'N(7w,Hr\^Y c8":㐻| qh{X@m<"<6Ypʐ VJ\Y~]K!̟LI󣰣ЉSFM?w5"W8[p)"B}ڞV&;u&F#cs;+j;g*JTC=MdѮP@+#5OחxPkHxb_8VR#!M)ff6`|5:EO+cd&l4Fˣ(- "-Lv̢%&[ժR);qNǽ}Ǚ©{gn sUw5JtAn'HOm2tr_.+jVGN+3WD_ FŸ(kxeĐ 9P-}׭εz/G6O8!nR)z+V5v/!;jvtSZ[fwKdO+Yss^lya,q %u lWrc7.9yFbҌU':B^jʝ[VlJxUq@jkjS4@Qg$BD8UY8B(hmOm0d{$xbg_kp[6lIIL窔lznqG{99Z/[X LzFذkD5}8)3co -xq? rue8ycen ~?\Aw|6,,o^zhK/(,,E)=W"1sQaRb?R {BI| ?OQ8E[9g C-/52wtT o}g`D~f@SMɨWtOKG'IԔPԴe9ғgXƉtFtNNɚrÕwfÄ#p3ti_߳CXw1x-,.!L_yST6Wrw%B)ZD_^͚ORCI{h=9']-"_pz(%'ϭ ΙE] .nUnu+!%yV1N8ֶ(TC!9GcVP4TDޞq#P_ʥL fAtMnAc(_QG@,*Hq9KUj0+ڑ:X 2/Q.x><6{5x64ҩSu38jdJWВƐcl.77?o fɇʭ,,ѪBE@ҭC:kRέ H`{QV.); ?#.a^ˆ V{ptpO&]44B"rR`v3}0Qg-KehjK@PcHݥq?2gI~ls[ P…? =E0nڶؠQ3o&/W&ّI{ߓS濷1 ޟr&C|5w^j~6]"iE 9| $jM`:/K\>yCDh^ix;4f䄤GƬ[y),VAK 02?\1#:D G9QϾJ1qԌ"d^߳ o XV~c;X1ͭxKV=$zK컎Lg]Cmu\$~Dby%]0*]QR,P~'mgQ66x%Q&A3u7+maqy*6ܐ!/؏'?84r:_LE9Mm{ƾWwyիRUZfXb4 W+BfW$. 㘬G!HN%y> iuJiui܇@G$#8q"Urj򦃪Ao{R*^3%"NĒ 1 jƓ/s8 % 5e t]G8Վk NI Lꆌ-q[sN -vH<;T5_܆Fnde:QSk*:cicS) MTs)wuO适'Y< e}sD\ҙ]xluisiRAwn3^$XDߑ-\Z{U7pNzA#pit~>}P邑BA?~05A 3?ӀV>olZ(8sZa^C*!GWUu;:;p5IYCl+O ̌!,`$r,#ZBqtv*n #Ÿv+g]BFEwX֟q#yӑ|Bdzsh2n4JW-wREΓx6+1$GfJBR =!_QhlˑIBui9 rܲlKvz.@6n'>LF)H;hsNG#$qd*,F _šV o7\UEq(q5RN S$,F T 'p(F_~6;6BPgJ\G  03iιpY=%$V&,~lNfŁoh65fݫ$@`ߒLzQ|% mŤ4ҕ$ۄN]}'܁N(<,~zj|/>"CyTB\@ e,Ba*`%#nN4"+KTLΥYItJ ͿEՒQMTeiVJT<115.Ztb]d%Zg⟁°Ih oc&^VeaMB/==hC@<-Uy䩁jY ]SÙ8f ^ޜlcfg$D%RQ.W&k sAWk0c1fuȄk'MĮ\%+ [h5!+Q\fOKOr3n%9N\S2Ցw;W#7Ϊ􊸥vdIUYFZD}("nT2&sl4;.Ya]}q T7BK 6+9@ZHd<Qƒx%0;7J)r4}F}"eSSFeI%sۙ^0頞L#(t=#'9[a ]9m~Aܓ7;N!9TPI N>҉VrfK;pJ0gje-ApA*m^E=e[{2@dvYj<8$u @h$k;_dnGB%ʬ"io+eU!, 3lN\ $dv3hҚy&?NtH#|3g5br&D=؝)D[45yl8s sqk˴^dҞNnQO/Na.taɚGCO~RaJ ه]Sm'wZ `Nۧ:2N*L" ȣ箚|B4.}iCAF} 31uI/1vo2u8ׁcn ;9HOsИT"rȇl]J:4N=7G|kG<ϵSlz JbbqTXg J*p $b,i?X5. Q:,4SX~gD!{]<*eUɨtJ9yGYIJ2LG(}I9<0rV~$GH\NP!SF*)\_"6881a@& İ*3p7ʑR:GNQ:ȅM\O`u"4Ν]V B-x%,6i]I3u ފP8%EϚRìVYCp#3RK!?w>`xA%:h4i\›I94NKiez3oy7f/I=I.t_I IY޿Y>a}铉Z9P mD Q @rWKӾX]} H2d'xA'lz)^rW+/ c8 ;HO1^Q0Y' MS YZ @*8։Q}z@ԡɨ2VFfm!)Mb㢐 uO3̔`]#v0lqHZOqD2{|wGƱ۾3P,Gs:VF(:|`@s|a}qAܺSHdx"}; K8pyiz?`jC.Xݥ6o VUY9ȴdFkh87yAeNzDAwD'F FX&|HٮfrGmᶟ8~ i2Q9'LHO9}_ĭ2*C-j~C*8G%6"#`b:ŧ2!Ggysd,qj%$5@+Ii[Cbi#$!q˾l:)N~SGdC+ ͷT}t9&D#IDqixtKZu216K "5ZuK :p^$=JlX$qK~d>R)Fڷ ^f"]]8mI谐; '\d!-,HƉMHe3ڕʫ&ꖟ82v_^j }ֵlpصض`y{.A+IJJ]*E|SM?Xi?A vwI=0wCL+sXlܛ5@')G>-[q9a]r(xx\P҈k72`&tLIoQp(_Ez~W=|IHIv%اzb>AvJdx˾8nם'"5ĀRLc+j6ULsSDņ"V?lC>_F}ӝwNI#gƣΎS]E_":ļ\ (3Z>Od3"mvET?̀|?+ %r ~ F˨b. U=_)ve.6t@Ă?#W2$bgm\szs&$`ӧ2?`**Si#[᭣6ÖDiHk:JGϘ. gh^Ҵ_6рQvz5Ȗ}N%M⚟@™{;@0bl7M9:](F ӾVڏ2N`$N6tJH]lJAMJ' 58˩q+U?%diOIߕy"تP9D%̛c +)6qP+ BΏO0t>e)([طz#% #P:&U/N NZ!m>v_ݣcn˰eԂQh O,#Z=T}T37ުRt  YNRkGE΀5Lu+6Y:13F"ĿY+ʘv޵z+kBa( "*VSd2h'ɇh6s!Ȍ ,]Z!"l6#j# 9 8~X`@]~8!uMUc㫸S"s(uw;\uQ=)X5iJr' D]1kLj|Gv(6Vm&9:y4f{׉-#tlϠTM]ɑl)u,Y(+wZɖ(޴K: WEa:b|A99ЫcE6b'Y_;e+Z"0뽟wj84'9&lMF#gE;Gg9Ζ<=3wp\30pd}NL8A& ,N앶}$t_Y8["݁)yWKǹzSMpjBOn`b d]XwAq8gAF.Lĥ=0;~O\Oukd!gmL?Zibq+ "8pre$QSKgUsD_y[):"h>R+ s&^Δ(~*v ' ϱ.) ZIQ\1nul+xm z#ߪ[t_ έ0 ʅ]{03mGg:dJ}Cϲ%^riq=N&"9KA}KԷͦ:ځo^ ^j#aYЩm&԰"od24}-PHXlagO0mcQ LKnj£PVnl'O&ʷ:j<4X=X]P44%9Aɫ0ϔȫf?PӔ..wѵF$UtR^fB*E"\7GyW=2#M&27r?65K[@ ;~#Nh^' EH[gmn#c.wx޷r~CM1"uGL:7s^{_BAa|T=N̥j(A ЦHs+4d)]O䫕Y ֶٞD $")+,91->!4 āc~ SXzfj|OQB0aݶOtExz~UϬK=#x'P[p`qGS-p? 099 h[,h: zy/t*ZN>}j9;+08uH-we *D"Ym2F:pƙ {St/i`PI:F(#KUb,~ӭ@ 0qyШ HORwyzydmU[/.vbUxe%2U"i:Jv m'j; Je^WcJ}ZVOͳ*~*BS'A$&r+o`D0듵o"m['Y]w^T {=אa8m),5h?Bp+@{ykx9%]'tz?B,xH,a8dhv#Yrnzgp/LʗH XqxkW隖SӖ)+"C#>Pi$2B 4'i=;F b|s;|-( e/˓H:82>Gl0S4P uAfTcq![ǯzgENqwQ`X9TqQKYk[$%% ,ޜ't廒RŶTfDx|ӷD>33\^oWKyZhwJA i܁w3'6k_V_ әR1 KO8 SƟ&]w#q4ܡ\Ek]Hkb 췕,?dYDD@KN=_!Ou>A~ƾ]\Lt  #F( Ԁ k4 77Kfy;!!oc,5GJwe)RaƏ,f苛Wg*"83tUfJ_gnfUٕck[^ ͷ ƧV ^e>aDX.dfy9v[TDxwT=_̶a=}F{;Ōb{c S-(̐bD58m˥T8(2-T~;H/(R[5"BI\sSxaS_{cœ7 =s,1_+[5)@t:@,.@0/RUcx<04~Km`|Be?+ {9V9j""c#\Iܣ?8OWtՏHS+@3;}t~f ,fFO6i*S'# (H9B^?iX+x7m{uT4HOc&V󩱻w8t?Ǵe]3|~&ero;D%XeVŽ2tW+tk„V`y Hv t\WRSi=M%>YJ?vz ˫ЁNlZN,c+ϯBes"Z{WXGsBu"Y837$4vDnK } :HTidY(ߎ*S 6^mNkMv>mlhgzDzĶӔmA]2md!,ARDwbdjD)2Lz(eJKb j]*&ƒsssx'|_cGK'Y]w%8dZݦ{j&kZP9gU$m{~\y| cNYRc"zNT}Sp Q1GCOEQP.pO͛~%ytOu[Fl_ji~fR af%*vJE}OҰ"B*NpT\&Fn d"Ne^/0zY@].to*t9pJd4=Q7)3N3Fw:=r$@4"ҿ"+5~) Li:\Q+h9ڇMO oٛkh,ڌWWu^ۿ4~70N koNJU⇈B^QNgoq]+#30?0h++U+q( X,;A/z;~(.Q⸾wbחbCc μ Xswcq-3EQt]O"{vr Mr1)02l [weɛ";UNPutC1RE7Xiy:YLH΋㈒`rGpFŪ "tByCh;<ue>8K(v8(8V >?RBʭ(_Oҷ%: 5zʗ)-Z ?a Щ^|r({yέZˆO|ǮrїQqf)cN4I#5sGbr' d]~N ^ wZ5\&i]A1h6Y"UG$Ej.Gf8;#HБ -Y&Kx^kSzـS9Dj'T~jӁ_'ĺBBEIJOx? Z2tMsW;;}iMl:B33ĩk;Jnzx}%77Jvhͱ+@= Tg:YfK3TUS׸upUɘ]9p`` 8N"} Vϧ ܗH%f}F_`]ޏ3jڗ1Hk]R!ƢWFHJ[)0!GRو3sTz[-"tPoY#7^i,YHr[mQ*[t~-iZ吷؝TBlv#I0+,`BOez]mBF rbrAmzD5l`fy#v;Znr~`tg.&ބ _Q 1Jz]5)sJlC~.au{ip SVe(#%?`u}VKkVLMQ뀍7ˢ='qrE'ha9HLpeɳq;4-I!n̳:rq!A9 !LJ$O8wF5E-ϯ: U"''+|ge*k+waG:0^O-/w4Ufo[쉡4'W=56WpT;/ X)62&MY{V"j)J[F_~MZrgi&ɬ̓pR: Jkt9Vd^n>'ݷ-qD"amIxX Ds*_|\~NJwKZK:.7 ֮qb5i63+~G0~e;0tmVoūtL0 {I@lG0f I3<]}a?Bequ˪G:p=ow<s"BL~3Wv&mǝx o"-cV ;\K8#KM[`ʛ!U{KFr l ndp?Zj5f y#sgpf  0_gRtXVݧQJjwvVͭcIGYEA#ToQjm{ !E 8,HC~)7:@~Sҡ=E"Az v8gԲKw>ZgG L,O;\UНu:|,;!bUlȩE|~T(f!<+3, 9g2JyWR?wpJrunŒWu-'6f{ 3o)IYKh5:-*=)G ǐ3oύ5÷ ?^Ii Bmh;#jJT2`P۩H8$A&$f%. a~N?:jU4=@*N0`#ټVg+ؾ\~ \LKqN߃~ ns"G?Ԯ>JȊh~Cc_ cQ9q_M5;C$@l :kyqӌV<1W5k|Ŭ,tI *rȡ φqΤ%s{? /L`%Dcj1K+kj))?ҷb)m%$hDxJTvYlIVE$B @#^ZuǑ 'F-: qEod՘^x ͝3)lV0ىoí:o۶aժlu0gW UejAxjب/ *V6eG+qfe{fGjY'Z 9/#E:<9։ Z1艣tysb Ү#K{fq\d]~q^F'w7~!'hbx) 7pk4$81Ѿ?"k)@v2#ћȎq^ ԗ٣.񖉝\#F-Y~(,Hq( vLvZ%ŗ赧!ar4nE( az+ [GdVzC(jx5zL3Vqe1pU/R`C4ʺ2rpY57UWV?Jiq 0ZvD+8he- O%3YL\h/4ΑB;@|REQiq*LKrzEV,rDN'k_Ո}{)\D6ֈ4 [,߫ti=*V *@3DpͣO c)tVIKJƹjԊ(BIFp;9$w%㠻)J!]M˦3V? N|I+s&N*ML'򌑒q~XY^Wk>pU^#iU>}Faz ,QpɊ~,7n$Bxgcۤ_U@HR'\IvsFq;2izzNF82@xB۬ShgYY~)A9IZk|Eߣ 7dF=3 |e]Rɀ~s+k u3 ZQs_k<үt]}S. t&/93k|` ݜ'UQԩٳ042MӰ>Wd"?o'=2FDLot<>ff\Yon}ȕE8 qxj$0*tx$لvHd9U O9p1Jwy&QiFQ]]is${w˓1NNmymnܚ\02‚2`͒mTJߌ%0QNߑM6?eW=7}oȰbȏݎȒe@\Β@$.M_!ަEPjC[K x7`)oӒRlDʷZjވ/m7IOvt*E\7rkpHB9l0L11KSUfqU-R̊ f#I0aG\CY=.KM &U?h;ynހtя\w:$`/!8JiHLՂ et!fg,)ʝe_99o P Z1ç[k9%P͔R+&d8cPJyjN*j+äf8TQ6 2&YLW/.PH(qIK@! w2)mu nNR vYg%Es C8!y:i ! pY_ '><(!rԈ/r݊3SDk QY>)Bqa I  O3[Lp?NFY- /Bnx4Pa}+@f8;WxwUG,I3}(.YX|N'~𒨛tJhw4ے}fܷo!j~1m*b㓯!cE-Bwt#_";Y"~7*}2*L6պְ:NL|I hVH{O"g%IuB4zeA讫a'jT5^-t Fa# AXIRĭğ*+e֏<3ɒבW#7T_O! b/_$,rwۮg1Ay1ΑvM6Z+/ծ I?>o-ӟ<`u?r_'[z|'՗S2̯1fVc1vLO-#T}gd+G$BIɌ25A9@abR5 F*E/$doQ{)N4 OSMe~rɉ? G"H%40|v WVSC2?gGXQO>M`ħGP|x\ErP(}TU}˾Ӏ*KGq %7ApC^k uMa^ +~t'XKdo55xg'ӆ՟,b.W7ʈQa[i[[RaK6-4:[uT *D)yvu|k6_ЊMkk  ߵGM2Lb7{E #Xr%9G 9d6DB3ʈqLNZv!:}{f_qiji^aTӬH\8lwi EĽn@b&+gu/'ˍoZu4muNC45 0zs_i]ͮ#Z-NU05A9Rrx! _nοkq .W?ZN`АFf˞R1 ]p;QqHR$#Drzs'1b툹cLi5a;b')<{>?l| /8fJZW@ rr 3}B!珴b|)9FZxT%zv2881uԧ*agUp,Z^:us.tg3L7Oj*@lpc2J^) ;8-qp0ihƦT3t>3D>EWêo+#y}\eҹ'#HG2T. Q ᓒӖ4M NL|\4G@L-Tu>~31FԼgn& U`O,af+ޫS1Fp44W%+;OV,ml5aY([u0F00SS>D#p\?M&1~S,zڈ#qB*"sEoW CPuPy mVdX*&VJG^_ť񊊔VԂxxjFF1t7zigA*؈qO-V<=OVQѪ V:LML5zre|eibZ3t ʼ'*)V5 #E@4bEd荲U J0j7rHO.l쌝("ܝOm&>nR pvVtW1J m'YP,wz1V[4Qq ܢ?2QeeJ\5+HF3ؕB e2g O)!ZFM<̷vH*EfjF}f|dm=3(S?x˵+s6M@?PA0Y(jR>d~X֟hbfC׵+Q!̎(>)g!5X.󧁱VA4yL9 bѳkp6nGMRjNlPOb5Pɍ42zy5jlUt#y1֪ ,d&oݔ6`S UJQfߤ0CH LDxlԴ0(Eh+TpUO  ?8Κvd2>@Tk$"@uˬ07|taw%}Fr$&41@zWRS^< ޯL 14n|"1]NA^;G3lj)|'e?_x]~W;fqЖyl-DUc8D4?%=]$ڀYUFBE &p= 7wQ:"NB|Il_qG$Ħ-/SV y=fO :: $HHeHU IH_U̩ˉ8hHy5@;DgZ[+7`8nc VhsD\{2gqk~]{%NPt_}t35)}F @r1uҸ sG B)vR!;ϢxkJN|j/)3@RjXaF5`lm{ʢ/8cWfg r[+C}"[!D.@)\2GMh~eW{bc.C yo՗MnVNp! ae[t#^+%K tXY $G{=A{yPBl7dߙ1;A[X_DK TR.4L7עiA| Qtu7YYN4&9 6C(eyE~e5IāiI%Kl1Ce0Hle)'fOGxXxm8$Ƈ:'irʞ;aʌG1lZTbPc=Tu(9 byp8R(]<̑os4FvM9 q3U!cqoU r[B™ ć30tb68͜|^wB1jzT`ʠ`Bq.PQݻ㛥q|,)Ʊ_3OA&e} L|g~3[%2~z2KژSuZey߇Z}D->~U%+%$ V*dl'Dߥ$fBaiKe-S^t*eJ-~bfY[ɀ^IP_$u}N.idɴ݈q-*NlP%_@P֯,Bbm$%s_v)lȒ[ GǾraY Ps ~j]eBYƂSwBlz+^p` GF|PrBꫨv==?"X8WUh;48o,^;)B&ٜUӧؽJ鿬u6L>w X7[6$ 8\ -W)`zPkO pMU=Hdn RJ A|:;LB + Xh(zYE' `u,&L}#֕{E>𿅒Q3b1o`atk_mn 5oҬ% B2M4*yI6/>ߕDŘEU,KA=PZhJ i?\pؚmܨO{Ŀ~@QϘrMW$am_r##&494 ujAOm XUd]exxL?uR2GiRģq-?bAk^.~"L ;Q˄—q2TBknH/EF=9?da0490&vVHC:53U@ci8(g^c'l3LdZV!Hx~JiEO̦( Zo뽠FxwdD /qh1ͫ1̏B.Kp)] /24ZkeT_APp d٤2Q'XԨXvĢ*>wˆK]SWd+zcO:|=ey$ t ) ϟ^oeP ~pCد?4oSg͉H1yB%._AJp E[2*VN8Pq 34U>mܪS`9S}FOƖm^W1?m/yUGQ$&4)/,$t.nFJSt(0JztUDpP3R,>\AτQ'e=|~v,b`N26 j=ڧT+៎4aaBGӼbS@Y(lgl6TqZł8C1Mm5A>aAW~JG ieS`玳6jIT@iݿlVC %Äwu@  t  Ql?p)1KvvqV Gk*F4Av|u w@ 1XgY[Ip|`2 %r|8/Ųw*|,`KνJz?p;dOBuh.'j%F5)be8$c8bΙISK"vڛb3!'AǐT&E{zC") JRf>'? Cˆ/X华\eW"#JbRɬ ~&#'·`z"6`Tܖ·.\NvGLuo/էڋĚM|[KB@Lo_}[ )uC PYr`K^dPb5H ©>䬈0IJzr#dQ%҈@e\qh Bf2A%R@MLz֯ GoEq#.ve[w$ OA!f["57> N6>˪pp>70X(`WaOpc^ᶷLgd C'-~ 'jL?UƳ8yT!2cB0%OόWF ^~ijf(J_ƭevaink6aA <)6ב.aSҾjbxT'Q}OP&Wp[v 'f@Sdp&ΐϾM߼̛u+V1/vhL3 p 7BMc_ vJK%c'A70[cLŅ8+.IW ;Wn͹@|x ~y68^M:#cL⛡2[Y -XR'}3;ɩ:JJ0B!XaY2i$@cv\cqdd08ANf+_YiکǛ*vV_J7yJ_~iZ%702RZد/ 66.N7fϭbB,l)QE-vRT/G+i fUUl-8&j_C^8S65ʥ ,"Z8f 89?!Gy-z+ y}Y`?x4U1*V?1d#!'?$R+S w|IY4 5qT[fZ"ޛJtUX&ԏ 7-tbN/)[3?%m_m5mW!h 557,+fвiT `u Ԉ)c_eՂH>iؒVl8eזb F@6-k=Ľrc5G7x 'T=V;ML֣5I_f3X!mUqMB70aW5ӓ/GOQjŕ6M6G1+*0 A:osT1c^ AejPEQv 2 JN(w}[j`[(Lg c!DHeU'Ё G FhUBlp :v3#[ld{1t/bs_Z(8cj8F"$/::qP]ߑs:4oʬ{@C* Fg`8=Ɉl+1c2@bGS<=8J\#|]z+RB.Tlli>Z/@{џ, j2~J% cnF!(!ۜX70T qF3xAֈ|7=jWf1HrZÄ/E Z/5<gϵ*_pOzK,ei|F|h |84M?uRW8pHӻzbʡA4qe ej v t$!m7>G%6Ύ2S>@J^KOJC8A48,D|ď)foIqA_W+ֽ/@2eo^4!M 84ALB= YG~MҘ90\8DBY_Y ¬DEY9M\˱ ٲ2 LL ) Q$64P1V8dԏX:Xt `Q)01*E;幓,ED0KY3_ }L"QFC|O# cUE@~U1j Bk0QXbX1x)B@H":\ j=ɒ#SMCSAe8^+ և9d,GW!  D *f;2]{Ų 8xFLe(/! `Zzr|6{UՄyMءFV*⠵4B;Qu3ZiI03CHb89 7 g e2a'#J]PG4!8$_~Vpb@k:dʅ1-AT*^Gt r@g˞Fϭu'r*0V qygjZ7D 3a [>PLgk32E?׫G9_:S3bP} 5;X |r2i QU0!qSbɌ#QEVR:Q`ޟDkpLkAo:dv30lr KH4)|jWxd4oy}\D킅F *dJ BL9C2;ʗ /cld/}lEH umA3k~pC_,h)tܑ 'qlZ9>V_P #N *t$jy}Wt0t'G>Y[㐢44]-X']j)~Qm#qNe =F"FV͔݀R1դ]^mV?ӈK^3?&wo4×2"eJg4 9u=iaZŞW˿\=G=SK]I2Yc.u^8S(ʨ5\OuL9AXCKu㺐 E,$t7]dqRJi!%!9YPHOVu(-yR5Yxzc\AJ+#re ]9Y4j+MؑWY:Q𬡔hBB97oe4*h -@Vhydִ+3椂l\з߼2O-]ΔkCU (G} =v9 ,#3qߩ0`1zOqOIёEL|? ge>w,r(**Ccrp^1ͫ{(bPT=)#s8*bʿ25iz WPx{}U@AUx%_!Ø-P53̚RpiV}| ͠F]{tZ3-hQ&X[Ms`kL08/~-44kf^!8>W <綠ET3~' !Z+o|C ?eZP*őkl~X( ˗97V`0j9kp.1)!$„e"(7 \ MS7#@ qI}l ,poy^i8438[Ih>[2.O:)=wjX[Z%ΐL'McͰjדN#ѝ ߫˦M&'uQMGz}s \FjJaKhDa΂69 B:0غ.YBP%8nޥi'C!9XU Lwu{` Z V~J em+L_&#/m0+wHh BB N! 2LX(МJꁥlGaԳUYbXхx4gBTY[7t%W Nfͺ2BJ!7E. xI+ԯ&P[Q%56W1h+1 !I15|[1߄2oe">l^Wg B\xsN>:ϰHq5~,{E >А5ZB؂7ɷ>6)h_ d]G&:GX_|)sQ W:y /݇P&wL{wv 8~!!mPp﷣ɭA=129QKpؼAUL 6qY!*<_׾ס=7-]׈:W1R29%*`sɛfQғ`1uIsl VPLo\:VN)}޿Wf\` %6 h}Z 1^SذGf{>]i:f`|-j& Fۊwc d֙nҪw!O4Q,ڔ!zL@f6A6-1 7u=@d =2|Ʒa4=yTkk*w| 8AXrAP0VL-˒ M|iUaCyMBř)H <5j;`~b)Z;_=WS 3v9ǙCkͨNZNFMoi0N`u/ëqYhI7!Qf?82o!̏d8VU qgLr֢7b0b@F|~,|$0Ėqi$WX[ӧSt ٳ#8Ln[+:j&(ġ:Tzg %8V6v79,p(f.m7<k y#as|e gtuKɞrFdei8TT\@aB8Q+()#f e|:ګ|]jIh풑P%^/[-3pʗޜ?Z/*b[IUSk`$":Z$ "~  e$TǔZ-5mP%$OQiж@Q`ݨ9FVW-p˷g2^YUO kQdF]{a:-)TW#&~GyVEQ]HbXB 5V*KyaD+?i`P҈Y҈"}&<4Qͯ$_!Mt{r|<!1 3BLyݮmur#mTVf9jbOVzJɏtD%,4%ԞOKX- Rj% @kW'azAZC&5zd%)߈rfh0L#cPLK57/54bi]hj\`{$8i2aZľGs/9[|WU3dUAUm q8LWpLεB0$뽬ۺcSɹ2ˈ]|z-_n[o8*N|IM~-$& AHEz_i0%u ߎ(hMtC9뭯'Tjz惖c!tL>k=ߒ&3Ύt)|zxsW+ïLɠv'T%; B~>ǀI9H>fMM09TЌA&d.*WGr>J!ZhXO\RWjݨGtƉ:2cݐ|(|L}Zy%yop=&+u D렎<1/MZi!-Ne%4'=eD;_w.G=h4]ḂX2o\YÒw|ܚF"f|jp ?NHt1GfVjUKDx1u+3PҐ&]A _yEO8p'tX7(@:!#+fEiR01U¿^0H?Œns[2r4pM.MY 'aJX`?6T\)0#ۆP3⫐ɄƮB;iCo\-vֈ'4SXA1jJ, ާ'Rjsak.B8w1 ver-Iӝq3o] R4o9 AؙrftwrvR&~j(0z95U+z0hW6kqHWˍk1?z8Acy '!HٞBSոFBEcR M]4uU"e$ַL^dAB/%s|@F*'W'+=2jrw4-v)~t7@mBRCySVkB]3"U( U9^0Bf#UVͻ:3Ǘ>SlIu)?J}J3hnj:08PTg9i84?F N/<7 7f,KNk&ܞ\q~.h<8>,Ujqp"<8.̧^=_Gj$^v"l (23z+U6 w{iqU/~ROhCE0Z*K36&N ]Csr}=МI&~e&aF_Sa80F՗"(6^@Xf rh44~kgDWgܺ"P瓮Q\C ^C1::*]~ aP;2V“8 wLSvh{cWl)AߦnL$L?u.~L~5 '1Ӭ+] EM\f댯Zr/2/8 #R?M-|Jġ@ wxrWؒaE(l%XXC}Q%֝}/Vf]3LT<=B 4#1j*'ύ:z\]]Q5{ag<>l#=C']8N'4'?ߞ\7ų (ƨ=;+pϿ?X~9Gh;+D{4q/8@p;$F!]d%]z)bV؃#YW8E+xV Afb>ͽPS,N2uǶ-և{4FwuסH7?juiʬ''ˣ B6XT$8EP+MA/|4-?&k×йxhȬ F8M&l神<*iFX}c^}+ 03+U-i&?CSAqd|N:Jq:K_҈͇4GjSnL |\B_KL#ba_ =w +f=fNVL3CZEPrKeu B!rȹfa/Kí4kdv%p8C5bCqm1ҿqdQd\Oӷ ~԰i}) 102#1yjU̚P1\5d%Ե)Z}ʹGv^֚N0GEZe2w@[vU ,߫3}tad>#սkժ\ V[6rOxຬf8b,U $l״G-?jv/~p6 'Skw1H0ls*m$<'8Qƛ Am壟oַ[ԡԯNJaZTsUvѠtyE&Q#;G *izT"Mp$APxjBF?c}x-KP&a V5WI1rݓF\5, ,w fNVn"^ҡ'^ -ҀUʸB^M >E$pL|4 7CاUԓZQd}\Gد'>/+rfH ݀\Z",Έf'mkؚ i*c!Ww+Ueگژ !-BKCG!h'7_NwU@]7D/z>`SCձ4kIl&D^ F01ȳ˒:w[K^"_F=m檫9s(ȏ~W7jJN!83' &#trB- A6ZMdqW{R8Tu.)Zu' وQ//jlI22Zlɤ>ez@46ơ/$D]4}Ud}ˀEdIS)Zxѫ+cО0'269Ih ~y)Ӿ(f {*%a̹6'I6asMDNBin84FԴ?Z*0XjLWU+z#UŕD,YKv\m$eB)DV'fi (HZN#*Wp d-xjh tX;~Tǿ930`C,#ĈEV~UC9q&܁N1C抮a)>~ xvtƂC{Θ\&L$) @.az/.A 짚I+%h/ڒuVZ{#u'D0[GW~%VWse`:3=PXOیDL0,Sg(\1A_407t,X1uVחnRNJ/^άX_xt ? {V/#řzg &m-xP,hA r`mdkeb£W$eH*K]`FmәqNvgAtPvfeD35ӡ #&YˆEORYZ܃`5C`M A{`p_i/4faf` $!;eԘw{ 8  3d_gj1Gxk+]2#(@ 46#W0BVA\u@ 3-W&^=S3\?u.ׅ14gj@|<+͌cs}Q0ш71t:wװ~8(%pY3^ (2ofjt$V(qV6eL(W*Y{} ˾KgV*V2bZķ+`<0rq]01<P+ˈ] $16 ԂǠYs i)Hhh;LgQj@+iڐZe-(u¤c;O$,*ZZA'׿7JwTV2g i_@`L*N2g&fYmZglty* >30a"xmߍq ЌxW&9^6=rRImf:C&glӥf@4N7l<8Z)'6͠<6p0N ڂfc8:( r+Vn8qVXmqiѵZa_u~(yrIv/}8Ƕ"++®A-H6# \ tqla/`ЃɔM AxE*|DZ< 2ݥLansii300t H'$Ljfx"n֜Ewl>ǡBN(R<鰡8.w72â6Ute-"$h6ث:r{+W)bG#)+> Pr`hR7'K(/=&`*'[ar9ڲ`{ SW[cV'w6BWtcջ|kH j-٧,z̨8pfgqw깕y܃;ʱdd 5G*#H01iFN3?UbNy>@* d1>\>sOZi> l$.Yg`hٮR쁎l,wi+f}*D)p1Y=46=mO΍X pp*2%WeǔMr]$T(?'iX}{|5G |E`0YPS>d15 f<25Bqx#N7/#Hn]&UE3 p(Wl .̾aWz-e| hi`޹G2xq*B i8+"e^RLqE\;2f`S.dVKΖy8a!&Fygz}u|>׿2Q⁽5}įVב0;ߤVִq؜ zf󪕣ɵ82a2;`0n ]qp̜ڦAI5 ?ul5J#_r uXf4 8gt3 MɍY2͹hjk]ClYQvr%f&[>RQ{F7&LsfWOfuZNT3ix]7 XV-bÜhʮɣ8 4f'XLŹb@iRA8232J^*9QŹi56{9tceԓlEIXs6uW8#A%Zui2Ճ^O;/9k*#h1J_,1eOwth/} o1eY-AgqTq'nYôr}^І20(bM 5H8Y#q+|}Gy ,^ w |kΌd7 5h(H"#AV>z ̗U})k,TY01ҴƤS&XC*f!޿}!TfU P g*͡aOU%wQi?zb6oV5TH~ CIBr4H~2wJ<%=[d75̝ꩡCM|uΆ{u mjB2VFM@0qJ<!_נ',yv`ymqky<> XZ$^Z͏j"^XBQ2 S$c:2WC.G=A4hd|XEt")Z n [ X-_#* D0=X}3rYF!Ps# aHǏ,6\*[+p/\AwgTjuYk_e,p afSp8\Tez+ m8 '9]+ BI?W r|Q/Tp 5£a~7@~ٯTSJq3*A!uOͿ_'en0nI<8C&/ *2ŋg^ߡ= )y/Y~<"WRr=eWKYWg'7j bʒbNևqSL?tPr(0dTV M"U?p`l`%_ eJpF޲8کQy/3 [S$3:Xw>{&7fW٧*=Y jX1:>mk9*v3: M|#,osR`c0YRldi9 ^ _8jU@WGs20HBV)k֟ [3`Ô룴++F.^V~1#,$cgv)"|K Po4edH&m\>"P @`BFbhn@~.¬|:q8>)3NI0l&H>?s+oAas+[f13@ҷPYicsCeYӨ4(yOy9H9xSgy4Qx㱕HYֈЇ?z~Rtn"ԖP6&ޚUHt )Iq0[+/7qPT-tf9p) CS2p\yq  uۡtv&ٕRn4np}a? !\cr91S7D׿)_q6ųR@U7 ^qP|QWe#ݼB/ ;G5.e=euk $7ʿ9H~fΪr\|^*&9Uj&Rŏ=(Rl䚨zŨ@PǼ]&Ix S18>7ZX*7pb)MPG'1jdBLq]7Rz$$'-',⃫" .(K;)QfLe)0Cٮ_>d.7j~v:J}Sܴ$*ZGrv)Nyqf>(Ab2w=O-_d؏C82 :55[W&>9`uȄ$'t:\x,(W|u2` 80aɾ|C0rGڴs&0r"*VyF8Y$y%3:eQ(Aȡ$D6bcX)%1?ӻ>MDeW[|qՎ_P!A''$I BIh}+>$*J M|HJN&8|Ax)d=]{'L:>}RS'i_b&AtH4'2MU`'t`#j' pVn^;Ƿmn0Buz CZ_K.wMUGI4l+QK)=d7y~*OԺ\Zq%~}u0 "\%qJZ[J|K斊gW%Xzi=0f =8蘁S\pkq%ZuE)OqR"uw+ ԷE͵,9ۊ#0Na1+}b HǍb I%2͙|eVJK]EQ~mjJ/gh=D,2ĬxkWt^g&3&˭#u>[cad4ݎF pWۘyEP aYHjfU]0LM =7<#rև>{4<j3 Ipf o _O9cc L Mgh19&A^ Pkx鐠 Xrb%U*`v5KPVJƥeW !jV3H2踮y+PΑ.MP "@C 'iW̙dJ ɶjs곗CThOnȕ55N^YC:NWIX^gԛ%%e9!Ua"ΘӜ>-! ="DCIKeCPV2# Yޢ)@KbX`\u s=r @;uuH}bC})4mFjUB?`LL`AOrer2bd<eqf WZS̷!wɃ0VDaxHO3+sK9!uf.eaڳ_&=[CQ޳Fҽ]]Fr|ma itzfVd\oá7B39~7wbW뒻_^+ī^Q7B <8sj1' +N1S_2y3CR𿴕$ХpC|9]>@99TǞI \x%ݖ+S)!R@Bې_ꩀ0X#}dGDiz߸2/h2Sr+:2l` :l^\|ȫx5Lpż_."< e^\VR<G58?\iU\~ eSP]lMt"B3`d$IV9~.~&>XѴ6 fp~2 9dM*|ZJ*L]OԼ%/:J\w A#Q0${_} m_*/±=% ϕ)|A= P`Yw:C.&!p_3L*?#B88lIDrã"e3 Õdհtg'NF[|a3jGoݭ,m zb4%]a?|z3sFĴj\R,V| + Nwa湀b]@uZdHVR*ƃwedGoNИMJFE4՞I8@o}Ԁ PdHU&OG7z\c" =\WOmx!v>/*M~i Ӄ@{8y ޒd 1c㫅 GbFqVRz>&HL_"Ght ~tc~5(( DtOUשׁPv{RVKuVx)!#N$MJgN=%`P/jy8>e'η~ā$ޒ2"ouv 1jVUfvb}NhWKt0b{ r~?\s'b7@¿*PM hĆ\h>qT -mXAFGrS ^sT~6Rvjj8tI[25SUy%1[+z5zҪQVC=;WS J2񞥘K@(X V#>Pp8+jiUt/ޚziטxp~g畀Ϫ$!aZ6Db"1 [*EAX6d2;%=E:uYCҴ pKc\Tf@f* T8 V\J_q0FqCqMz]0 *j$E`ZN&&6s й)7~%B* ); 11$ NTDt3f_d:2 ެJ=%5)#)NMaKĿC^-T zI1uLĿɢU"hߏj82LSu—`v\P:Z߳Ɣ8$ b)5tԘ&>jIӁ`<n0IBwĕZEu+z -Sq}!K1´&\:!PTubjm\&vr="tF9WI_Z%pCg'I4(^_ 8-M=O03Ӵ 8.![h[r2,v դ:u֬@Z.UGt$QaDTfU!5}_с!ddQG:Ƒe(=y9C UBN q5}~9"# lwmե x#p[&nv5~\3Qc^"3VN:J1 ->@qyH_# %_80lf%-을z•B-}kqqJ˥DU/SͼzJL:Z6l/,31`sz<`{j QWb| 3ٓ9>o *ӗ_#zU*\-_ݿ+al<BdW,㣷khֹ25%q@Vbr|5I53.D5=z9"n'RruÑIoNO{Η3҇ ʱ Tl )6l֝N^' $ =<޺2<+>@5%XR$W%&;R$CԙͺM0Lz*Y%_W\@!eOaGwyTU}Q>$FȌ>4 H\Mq2! "u(@˜?>@g`UFV/|wa?hj@0YL-eU/ Yr>0 ȷ^M/44E&_O.jh$"h|k4=1)f͖+n\j+#@9®;9 ]SiUJ]wSrmIOyY8JaFEo|&{˭dR;@ɼx1|8N<]Mǣ /Z{ҊYz nkJ6}<L@,3 _*f™qb)ʙN7zM\\3 Ecݗ,_^}b[Jd4>b(Y3WbW_@9̪2cAA\0 $#Gj̗cͪk6Qt;ٮEx5[WN O B5:A3}!U(]^?Sb/a[ڏ&4~R2C?x)گvBJՠ,a"U}j|2Valul z98C4Wg(_u_O<,Uq326$Z-\7.UFz̊+w]V!e|_s!@*,Vg0~%nBKP}n NVUz:k_ZeQOM:f0#vd Y+(+K6[lICB! 14iB~'-5ٳA"XZaL}K'ƇHf R ϕI^nTKht N>5Px42\VIfb9bQ@jբ7~vZI!yYBɂ!ivE#h̄ʛn:W/+ޜ(GU଺ZkAdunb{ 6: |ü»I|LW{_z bI*NxeL)M KdW`=ҿH7[X!3id\=q[r J|Hsū$s#aVpdtu@7Až#e f8~|/1AIY??`IWFe)#Ls_-^@oX;_gB*wP6}ˀZk*d9Ћ6s U]Fjݯ$CwSPItJGPe'0 0oU\]wR+L_MG*tVNp|޼?œGʨ%ɼz~0UCR4['(т=X$g>p"&D?/M^KZ0tV5%MG GU :s)8zx4yRAgđz |DUn̿Zdyk;X sU8ԱDp:=_\FH ĭj]g#o ,-~[R1:WP-na/!2s2eN7 ЫOhenK"v;xGh#( g8VڪRF_KP,Owi%2B dF4J<쎧 &M&ksֳԌ# ;GKzC *8ZAHL 5#QpDzV@*z+B#%T[Qf,*B"'+0UWr-gG@w ~ճF|i:i ^)#Xm]%qPԲ_d6Lseaݑ漚S<e 2GZ0q+Qo>ɂ»xWOG&[Sa}Q5%'`{̺_e&((ZAĥ7G%9(^D ܳ.?kcEm^/z 8J2.p%1$e1zV)io>zidF]HI}j lUWҴ}]^.DY Xv b*[dh\mv.b%m#~^8n XƧP`(ګe8jxfcZk|?v,<ܲ 8Ffmr̹3~Z M:rP4Pf uCT c!eO-[%[d [9eǢn+o]hLtAkr? !N"e%qFm>- L@Y0ZUB"!0j%azI1;yr蔝dJntN14V>$i &@St`uB`{.S {]֣@Τm&bM_K{/jm+BqtCT8hRY!1au硓%TqIA[(au&<O6亻j15.Wzy9$dR@nI.bمZiY3Umﴱyrqa83s˩@)g0*.2paEBAֳQS'?_MC]" @F+j|*1>dB$ 2Lp)2nP@i,A:d;vI2DE^Ac:$d$낇ΪM%@4 hM:VO\5`3/ dRET#^er^8 ~6AMx]]/QQ>'aݪBsW#]҃+}//ͫv\&`II.zb9Qah qRKGpQgPIp$zedA[Cל*JY,${*+oK꒗\_5nd՗2zs ~b9瑸хf@;dIV5է s*[]7GȌ𧞯{ā?lGt3N!+a}'$c,gԣՌ0y UxDa`S&Y UnخJ%̿%9 hЅP#yCxAil^c][ |"w;{ MS&W2?hwQͭ[a8.ɦN"$rdy+.fU7 GqyNGd:zzcx~/̘S7 ̡[x_a 9nV`͓/ITU 2ԢCpVRnM;'G)ben0*o2(.!)[p}냅UzCS2{D0L980k[\8ч$Ӫ-uw"כZqDǤgd|K2 3<6_A(DcF.F޳fU>iYjꒋ\L>37EiavlbhX3&Dƅ"mk`.&A$`j`ȸ~6冁d=_G NUr%2B!NQsBrԭ3Z [E$[fI^.eͬ?& J\hif)FzM7T8 LtzIJRə;%9 *YiYB4ԝ% OAE&(dwRG " ic㽚;Jn|7]E**XlKnB7ncG]L}3ʘ":c 䎯EPIiSJ5l  D#%cHçO1:hi'Aeypd_iR$R*n@X-w'#K5 [!do}y <0Ӄ^0Rr;eUZ! #VKq-}n7x&(NAAc>AaCDj 8+ŗ@Z!O bmu;>Q㫁9Z'x*=t_A=&I'YY{rIAzK'ԋ80_t_tWZ|,>L.9:uH`To|s L |)jjkIfG[?'$-50aX/0vqs79 Rf&]1aRd|<ʍ.yJԍt.Ua cYOdS=k$z"NuYO> >~@e&2+u?r4_`o~~rKzrՎ\%65K1ם2,9*NyFl X;iDUk0(' ieBUG0TWuپ\m*ĎOwn>/pL|H4PuX@p{.4RfN⸚nԔx!Z\Wnm @痉tkI UV'*Ns$Nb@Q)g Tʹo/;ſGG3Žo;uUQCGPQ5X^7^B=KM @o!Ыb%SOPi;{ZlCe7V}@ZFuC@ĝ*6m?92^l zRI )yIu o&sVSk`_"<2 #ag"?o(@2d)@2bxn=~|s.tyg^;.!R &UmKFtĬ+:Nrh2S{P OCVׁH4މN6.HF2JAAНBpwݐ׎O`Ѵq]Jy$&F!i&!I ^Z¾kD?7st~% em2p@U>К?RCq\bS,GMꁼ}Ru{(S_=fj! RU ƭHhzk¼:/ [ oN:־r Gn/25S"A 17#NV2 8Q|;h`0|搼 BTvD̬^AP@vWap˶IOܪ=l>q!UUAm?&*7vk2޸okfxߩ;%bYOx ʿ,):ůE-_x n"^qx9Br594`ns1O g[J~WVd{Ƥ%Iz4PCNcK\{#Eu29sσjK<K2S&e<>d:.)&v,[j!=$G`'; ?R" q)`ѓ (\z{e{j V]Mxo_%*tb}bq!KeiW YmVb1^b?p5Dl; m1K ӕNq, y/LbXqz UJqiCЬ04S Ǫ>J27 @(Bk_]YEu{vIc◃4\ >t2+tǾ\7!=)>rkcod^ͧ1(+GHhՅ|ZL` OxXNkH_J^٦&mUcޙ(iKz;XK /e` ;v(R_y罜'/;ԘvO WyUU`r'UA(/,K y@sU4.Sl_gljY7sȋ<1kI Ζ/X!9/8eO7`XT ,4ߋxtE&._5c|*}|? "C212Y_<C0T|5 s?2ed/S;>K38j+ 5/){_޿u7Tϫُ1|΄ Ɓ7u%:oZa)Q t%yiJfr(n9K2Ր-A_WЎ:,jÂ{$& ᖾ@+pIOzK=(ULN2ߟ \'쑌츒ƇWbƉ26tǤO tBj##JǙ<:tߏP&cې%%L[9 FXaRwlj.Vc^FZ0vzᝇ=ay8e5+ ="z\ydovϩӎ.Cݷ^/`jc9]cW)cI h8a| ]AƱJ,i CeTUbj'=t!Br CckZk`]ʁӒ[NiFEg@FEVQ@O3+7]Rrvʼ!˩c2\|2|M c~nlEyr&zrSʻJo\&VX2 e a}00@7x dv xJB97vy]Bqx||ʩsqP-_J2X1w[OBU1`3>eIe D1e.իCA &/]@ y7eGRgK'AseQ@ \TrTG5~׿ysٓh|RߔNdU[iVL=d.:3LOI`G~{A%݇2"$aOA=Wxۙ$+c$d'm7R>0c.BtWx+|qH`-LZxOҧJzGSUJ}x^H"xPjF/s;+5l>GiBRiZ*#W9/<[O } *7Qu_YN3/Y[&LdY0( CA ƞU\^(A\]WGƬ@iSsCC7+%H! V`.5`$(ϯXn[&ٿZȎ/KkwkiӘd|yOv#,؃}H)8Y*ɋf#bt;yAp$1P<='!-Lh6#0@}K(ܵLvnv);G̐6u]LYMMgdo6{Ys؋7i-h6jU1%bT x͙X ґƧ- y>>^$bB"rbJ.Q;e.+3%LdSWa1܌ͤLcEO`ͬ{ћ_ b<*;'=ZfIҧ3}4J dh8x|TGo0ň//I؜,}0F`4ݲO43";fsrkM0SX7쮤:.5Z[:WKBR j̥jƚ>rbRRfF̭1;v̤< ,I)tqIH7U+f1:p'z9_qd9 αDZDФ9l5, !wO%D'W Cú_+5 9bɬ1"8dϹ!h%e|;KorW;]8"~'ےtƒemԵB9i!.%2x ;IznmԏYDacΚbIˌDƱs!6Fz4#`g_10RZ6Q1D\DREcQd0C). KFSRH=};d#"~V-M)]`iė hЁ0ٯfbig:HF րPSfJr"p*p\c=ʍ*@G } -2OH=(Xk98,IaiFSa&vĈvhB|xJc 5 fWƬUFٴOGa`H"u<)_ad 5qÎIʉxfTsEm'TV{"mO*{ 2 q8Q3(:6K~i3ۢM*N _AٖrS4r }Q@R9(6~ޢNh+dzqZ0‡ϑӆ:ܮ,˯} M$Yl%-udVʦB=!}uTԝ`agl_n{?LnRu 3gboO۠~Wʢ`SIj{z|<`xedtp3I1lgދtf_Ing+?'s̷-ۮI"FԎbj<NꃻDf1Qje*3CM4׺|c/؄c'>jeE\>=Wȹi ztΙL z.ߧoNgE(:0S#eQOz0V٨gwsxEîn.kfs&)OoN0*j,@Y6xJ@%ʨ=D8uCuE~> kd{ؚHD̈́B)_'J4C'J0yvRp#M C$&?6f'n@m%L2UroWlJ^")W|5kGL\ CS|!b%OZ%4J<-G 8eٵЮSoW/Pyq Ihfخd,R#/^4Bp4|}C=7ti )jW,PRDsoQj<5m(셹_T!\#蕿=RĬGK+J.k@;@l7NmYͯL䖛-+yu4Ӏ+,m_,xa V{|ȼ=v=7 突"ӕ qGfsPFYIVr8ZVO%l/X1[ͷ۔N@%>y%:]f# #ix~zy uMO/=H1k{hG5T׾PKjk ({yR.+@}+,J$o+:$T`@':WDb b_ȫ៥q+ V6\If[/Q:V4#?ȍ'm)!yٷg!18l N4<ưF8 yȻS (աn|C!W2Eq-KÑY0`&jahŌ6T*wp*#m&: J TqT#v3x| <V`䙿/5yKe/UgB|Ÿ́1FEs\7 5b#S{U",|RKP%g2-7,qX/QLBE+*6e/G4t,.Ӛ^NX:GV[Nv?ܮ2HI$^V fgftߥd<ȯ LE rc{4)zKB2b%Żnk70P0$93>Bٻ&zlLk9 ߤjpWhSXMD(h" 5 Zv*6hQD7UriUx!\HMȠ}<6t[qO 1Ƹl]f^Q.rD|Κ AiL`D59\3S.%+|zF%đ ,b+K6\THjc8,&i-EFK؞D)r]&5Fa%ku\<&xx&ghd}ubJaWz]Wl+njg2Bm3q0d d[IX8r1Ե.0 $__W %ټ>`!( Kdp}|;0xF߻7Z_q.^ƅ^4uǷtJѨZBH€FS8Or0cFr\UD'8^2FAxY&$e2>J]Y`(>GUz OŽnoAz58M-%h˻>X5-"DFi ~ȿ?$`v֟ۇ7J # bגY#;% +3(oO=_^EeU~r3Sl%5oExGDa_b(3\C0]Ej 9[(1k7?4cצhyc=̭t"⭭'_- Ψ&TA@azrqL{'E">peq4b&FEј 4ās{p(3AptCB ,ƓB~%#=pal_ёS;9cz3[F擝݌h2`%nd ,r&{?hrH\{?dhUrOqB'\urqhf"%zN3IźQwmX]=oҧ$d}2F~eq uS*D̟;4 #C(vQaoV*0p$iqZiNR,;p)&d+0z7Owbz?Šv LSh{|w I(}c$C$dedؾ9. -LqS7~WIPjz3T"c;{}.#?Ǘi/$z!iS-!A".t|a!U,jp-eJ~O7v2efծ85KĄYUGAlSwa{֣j%:lo5̾ L-&p8v9ޠb-WO6l{\r?^Cr@2lŮ1,\ 4!b*ȦqAtV*a ਉVJ%pT"w5Iܞ)ѻIdB1[<%1Rh<7W83[Tamk$fg.C,zR%H6l=F$N1;3p"81'e~Bξ2G |kñC8(PgJ9o&C%wR -kP+sӝ\B0l#Js*X$TpN2,ÌdPaD氛V`Մ~P`4D"~Mz7ϧGX \ -_IX4* b_b_B[Ul UT )@35¤*$}M0x 2Zֽ~qZ'zׅkr"d~)^6*z]9+7Nh_vr& ;̅DR¿|sT#'̀'0#.Go4uAmS)GrǨx v&itrjfP $t82փN_RnD~F;vA$pQ{6<ͯ,^yTaUNIrɗo;G'gńErr-0+ٺZxI Hflj;S/5A*lWaQ'͛!!PBV+5 !XOz]ILDQ9jdP3BQ Q4$ȿvJ^4=ŴF@7 TfWM{+jc+`߶T״h?P`jAb3!~.>> Gdc!K+5[q ԝl5'9,7s^ҏVQs7QNdtiU#!Vf$qH iVBλ}E-+LDpWa^YOtXY^0q!ǢI$ ŨA6eԿ!|A0TuOTZɼ+[ߙ e:o5=<xD{J ZrܺPݦhf2{.çA#&yxֆ<OB8dM P5p=vjRI(ʩo*sl 4@f&ǚJ0l؂ߥ$UC"g(:t/3{8$@ZFYNB[7k[Q'X @̵RD~*X(p^eKa^=ڕd:#f\ y̦ +A*?k¾Z|HVS ~50*QO KsUYHנBr쬮 =w8!;+9xbZgDD&vm5yJ­giU ?`޷6t K5Ȅ4r\9^I_yKjhq%to+X0&YVz{T%+2 j *n./HpT  p=,%$[7=FWh_]qa_#H~T&C]VTӄrNiR[ы h_̦TU6s]EVJm#z@odg0ZnyKmc% 1d ~VW^gH_l[$rVKŇX[1劉bjo9 {.5^-)^eѥ<8G@1ɛ:8ZT'!p`XKl@ó{!"@Qk+A|0{e_ r7U|9H-  Uf/c+&+D&_2ěC2Kol]TF|7IΌpEH 9ӣzjCR;hP4Զ- jo-n'D"GuVکOISwOoqP4aSչM`JVxTb3D vǓSLwNe-A;T+ze͋غ& SLKW]ǮXS0o8R~ZV&⩂X"&J!HJPt)Uv̸1nK:&XS%;1x}!BWGڨɚd}h?%bxU8>a+(Hӕm{9;p0Y]ʻ\"J6+'ՇM(ETb -H^|lD.ıUy/G|_x&6 >@e O8W}v4*6kYD͎2mԿ"'V2:3K&ÿ;*x"T'BWV]Wh<8;ᬷcJ`r'ӊ)LŘQy#*;^Kea>v<㏁w#DFtB"!`ى/ݺ@@P0/9 !LsƂM+ ZޗML¼߹O[Geyto:gF}{[a{򡙈8y.NnJoY bB5HbF>̪.5 38cJLh.;A.?,DCJgt:x'krL33.> P$M`ćc=u<dcgnCXNPA< *SA|L~31J}7cmn~ڗ>F7K#) 1ꊼ{kU= r_=fyOژ02'BU$'>K} RNyv№LQ\5q5&d9\f** ofvtpDO奰WQl>`APE;74J87jMna4t*Q'Ωۃv\?=ʊRqK 'Ρ,όx$9͙O<'VBr]/М69Ew7,yJ?O\>x{vyeiߤJo_"@:[o)^@L,*2*Sds`x(n3.E/cA's?gTe =9 $T\+҇퓙QOg`5lhE,SMM]Zd!\6X{n$whϤ[ֱ]gxߪ}ȢPfĴ`np6>(W"2 JYcbTʝ":+g'`oLSg+ءIᲗRې)&gP,Sx~vbG2{S6zpLZ %$7~7D#6%e84~'_B%p6R7Y(<M\Gf!}1mA"63k{(3wU k є;YaE?$qRoɥ?'40qz/M UQS1-nEr C0EWhS>SLi? `J5_FPOls[Jv_W> +0LܫZ)v<@_ "oF$o={{pY1ݾ:at }Zo ?:; ,lT5a~M ܉#[Ƙ>lXF)qQ `F$^3+ǧϷnml=⸜ Nq>K#r3MbƶԮ$'Ρ@I@*P vu(t$΍{00PSh0]Zj>IoblB |6>s'K0ں, ؙPzXq|7$SqӗO#dBBnJly/%:",}уT"l59xJ$ yFnb.4O|n{E qfr,Pޥ2 ѷcfC|>_fW>gt;_K)J$2 D/ne%Ԉ5sơBlڅ\HX7O&^P L=\)z!ino ~||+A8|h / {֘W?(~)Y/IX?~G'HQL6-4+%}vtAwI,IOC1WF8xG)^>)MN8?QQoOS q(6P>(5lx}_aNQ`0{( c.9@E*>uTҘ8I&\oD$ 2AyfI(k@Q>2!}35![h$;+՞Ϝz|xF\={o8 H3'9{ݨNR;%'QAzmӨ(L:41\f3>XbrF @8 >DHQY ] 5Qn3x2s0%7̀XE:U<\qh4B3P_[뭨c~? %kUfW:& Ju+<"UOB|wV/0ĠO4'eaqǖ2~} VyTrz<55 YÀ+xLr&(8.oFʣb`ybVBYC%ZD~hvyy"`9K)9T2 e)OhghtQ|bd+ꎷ4Ѧd=iʡ`4bD!)R|(sI+zD9 xdglT pyOnI4 -h@g0"JV&#K:Ck?sv 35Yhfjk3+Uהi&G'Y &M9B%AE/35Z p (öՃ(8~% ӇMR' ń֛(jV|$uCuvIdFcq,o$4~uި[*{1p[eRX7Z})t9Nk~^ i"~ěa=oMî "3+`r! WmHKF֒L#=0$eLnL4xǢ$ ,]ۊٲs1v~7XG#J-c'RbO)I;0tqzitxPڅyBKCG.9R#.NjكIN"}-尘KvNu-E$-/$@/P/wFJBfL| `#GI5Zu~p0Gyy8(?qi_\O>-uV٨["rz]3م%vd+8d<=0C_W'zE V)l|⛷[~6 wO- ߖi7 K'~giJ|[b52]ćeqo!Me<\0>=cD\ Z$8}]+$-vW g2_?OB?[z֙9lIX?)qR?OŅMяKE|CK:t s2  (`g JR+b"FwI-s#{(pҌm =VYZ3$~սd2P!gR6WdG<:2$/#8ӡR48LmQ:ZǗr#1WE=e . gqKKNJ☥3)!MN3%z Ƭb g-0qh?Pzk֏q޹fqҕbᏛ䔔^(3R\ZBL?[o#r2>eʒSSxhWnN h0xYWQLnm[AA@Qԧبm|MA̛Yme*L ]u¨=htaϟBp('GAz%\|0GTʮ$}04dsfw4 ?wkn#Z;꛷\—^& `]3ߟv+{&oc u֧TY Kwp>)=%,?P=X(1|pJ&Ӳ@kxj6U/\ oX=Jc_frtA7$$2YzT?V餅B9~ PE ʾ /dfLc ֚X"FiPן_ 6|d!M1Ädmx+ӗܹ"~NADkmHJ\!Ym/xI}3|O& 7_Hi'",+zi7Pk:P<:1*,/u6zqLVJa[i 8{2)L0i@$NM%P`푵E? ZJ>f 0*׽WuTPthHBn6 1 YڭiLE[&q$ia6"T\V!!KDFfqV*JTD$\?d}@>=rͳ|ϑD'|Mnp&+=wn#sFc'C[/@mZg*GO`b%`m >cd#Z~F{M4+ǽ+E]#@áMdNbp AaE+KyzSrVg~u8EmFnp]p`RIi}9Ľ623ڄ{"^ L/&| qa S'n sW1CqҾC{sW>e?ww߽JG0g*lH(>kt'i eP{}D֯"X1S|yJ\ȑB@d~tcWgT%䷀\s5l|d'=qL_Jg&G{jyD1B"q_B,ř+Y>naj Z#cnVFN Qh|:?S!ۉ]!7V\D"* >U?ooY,=XjuϠ`MCս # Pa )kYh^2OղOI׉:]/쉼!q>O e*fHeE$ ppz~7ˈVKeLwgD 9@=gO/Rt2b6c"$ܮ<"˜˜*r)oRszx'N,FH@U8ӓ,XXI~Y{>,w>L=/MMkLh19Z뫌 Ɖswݿ* VKWs~`HVܧ#XWmZ#yn)c˼+BJq ~8Ad_P^&fx28MK6f6D2B'Dc-pg)_2˥ia Aq >@ҋH>3t_ ̓NÙ34(] +fD7ưL9l na`L;׳)FK!+pVfj 2$g ?wI:4ɨ  sG՛be<+~`v9$V/ Ž OK{ݓ8!6数fb5ͩG0\?nܲmq {4_0=}7l=2S3 , bɎ  E843:#75)1tbL5 ~QSL&,yQK_$MM1r݀vֿb EVBT}7">-lV^}<F CAM^$–,!s/13S X_fGReǥk;s f\#xg;1Xw.b@HS4 Ȥ W9fI!S+7vpbJ܊ٿOtu{Lj9o sbnFI|8dW<=wzTLX#&B& #BNxDn""`m+5 "&?>>#"#N޼LDEG'BIaW6:x$'x=ẗ!c2`ȏ]lDK``33q[CS51 i0\ &I7{r6$BUGso( fl&sVZ/>9FL$H#_:. c^̜F ȧ7Jbd+H[Tk`}6rKD4L";W 9X"34v{Rk$ )']"s3>xSR>cf8eex cјPt;Yi PNxH{)!zNКՠO*<;Ȉ|A[U<\ TŒ7DR5& ׅ菋nyDp_Fq{[ "DG6[_dWﯢu, Euh*|u6 smGClId<-383{mQ`g.Ztʿ"vg\KuxꀕH+D ZqJXqb>;7}dύ21Wx&pBCJki_qKr ߹AUoj@ޘ\06|eS Z -Hb=tg 4;Da91EmIqG3_ES&{@ϋ(r x |x͍Wچ@"HpxUn9]"MR<֚L;T'ґ(i.N'4`p)1oGvf17B ^d Zy)!ڹ)΂\/H];-N$[/*v]n|<(ޠjupYxʼnI8L}&f 3CϲߵhQ d[ !SqPA 13d Z +#tF+^ckʁq8z%v(`MpQ5ba@?QxG%} kS{HHv+#(Dq_ϊcߧd9z$>w&;M 3xDq]Aǚ1o?d FtLjQU0| Ɲa)2_dI{?: "y38k pyWvʾC~c3L~L)%9_sUxZ3)Hx.1cpWd8g\!x)0ぢ4|arc#$ETU<i@eLbpm` F8GKXz9?0z\>Ii˖bC( Jr +1 ~1yo=!A|eo8%vu_}%iAD$g#P!BAځlHctq'ߗarw'k?.K #[10rtX{%FgVnz_K(_DS E1 02X$#eI} f=n+3lU#pۢe[C `xyO}K]dp=J=-1 >FDa&hǘ8SSbZHuiܿΝܤOMyPoe$-4no7BZuʑ@Ea>>=}Dd bY;cki|j}^TK3=Iĸ=&J|tRkm1yk\qߗ~`;F9oLwu#2g@j_f|uο-QZł|Lqxl=?7S{b*D.g V: aׁ UPAW!*&r kX̚5_-2'[ݡǐtkX٩Qp b%;}#e}DjkF(Y#{0K1"G"iuքO4kԦfH߈ƛ5m o hPUZmӠ7 1xL4 GɐSя 96w>ΣfPVא6c f˛2UV܅˸PX!x!aPŗe<ܳg* _VdWLĜ-P?v0cL&h{V`iҾNىjZD@Ta̠ &1?((`!\}k$aƮ<5V|޾ &<]@|~wsHK߼ϋ+e&& `}V e`:C~9^u&eH⨞VPBtOmas@ZedwQ 4#x S}̈1ap _ y+qj06D4<a&E}\~8 ߹w$hK*k٫@Yld9a]pKE"c {J""e;yO@ f `B:)ĴxC_4X{ZO E'y/Ħ3} y8U#dz)ټ$ê 3h(^=h$D96׏X9}Be9^x _rRۀ\H~pΊ/||~֫ Hp]:Qsl n蟧XvJS+ou3ࢵxދ_G߾a拾 {XZ.eN뮤gU tͭAϟͮoT ?[Ls yr d ,B ~!XYŕ*,Lg"U]noPTgr3.'k[E0ëQ-ً>5 (x!Ri8 ˵LA=Gyx#oJBO1q290003FAC}Pk6E>j|['{ؐڀR#\Zeř96[V_z8 'Zeas%̴߬]Gֲp'*`YiHXpʊ9Q3j8`"|i6 WvTqf58vYM9Ikf;u3Ks  "Hۿ7>/(;K8C3EcvIs׈EvWX19oGBazsO⥞J0C73B-FoK/W)QXkk IBT/y[˄~̺Yd4%QWgҨnak]?+$WT\ľ g^ Za ,`-K\+ `D"g]]Wr+FI}W%\mRЋc."ޤi$n|QVp\WR#2Ues9/˫4̵CvHjDe2px#`sV ^O We8vnF2KUEV ̸*$uzdQw{?磼;m*Y[cSY;q1/Yoħ#ٿu?gH-@ ŷMfk)Vb%WA)70zVQ2o~x# OX3OGyν@⁤;SAJf =s!Cb0]אݜS3b!׮gXf(.mQ~fgK&'>y`zj\]c 4/wZki^b(IƷWx̸t<邪t(,XAJüJ#]Ú{LsG4{khvIp+1{i#x_+qshr5.o@7Ai{;io7, H $٬H]3܃(w+g3T [{8,:⹝ג*uwX3~2WLhgG.[^qd3* ʝ1:t]&O {R#x]rKJh; i] Y_YwgF+lj5#{:~յؠ'z:߀H.߾cBp>`\io(JUPrv~? B 7]:X+pɻ ,AFq⬇,D?Bz#W&h|{rۓOl"̒iUqJE#ݑnYA JnȊe$Y[{=VyBgƌ{vR`xr9dyUݙcsL#˸k##oiad~ SI.#CMm=AZ`voҺw^v" 7lnOg%_=qWىh\bv|f5@v7-qC}a >x70! )% ozDeFyuymřhܖg Q]Kb2_{@G/l T]:_ F$t=5c9,2#~*1:Qcy(׊v#&"#%f"6{W^5ˇ=3&mM'xkM|3ڶ~*7G&vč-G~FN"lrܕV>MquS'רb_g\6V0_籯;11SB;D^S~*>_uOYqX5A䴴W vDRuw#Qbtz+;bEP gGHlŗR ٫n !oˀFr@#,?iu$ଞ*W&((vD`@K) 49 C@^ٕk~aa">bTrI Ȝ淮lĹ2{NhR<|=IQuH)ն]3yA;vҤ<{U ~_k|;>'=Oi믭 v_EjV93 f(ԈRw`"B pK7g!Ҕ nCpG ^Myki"3$G$u >-Q_ R6ɖ@g{:;csJǽ0]~9QbaB.J}U" ~貫;D$;ɫH=(7wY92wa 2kξ]T< D"'U[N&m*DW@Nj?E-W& lD2vHLHjqϏVq6C@<- 6ӡ_ah0T$^u@&KK sl {1 >*T'J3g1%lʦ_V85oAB E$GGVެxgnn &U6`4U }F:aΤ'&0RGTg_}}DXu I/Sħ%ƽn{?W\p]QYJ<Ug Ԃx,bįlv N$-qd2~߸ ԱAMh귎]3f:"6 3: p{RAR1IZxmg-aHߚiTүm"kQ l>{_BmeP$g5:C1-2cz}T>'<9f$= qw La1ʙ93rA==41Fis^dG)@`E6I~mQԬz]x 'Wqt'fI7vP=>&u}кU.昉 dJdw"*M0co7L3Dw&0uI*\"0̐E4뛵b{> xw2(QBg,3Sf->yVb< z?>KH$0Ԙu<;ڝCCu0Onw̺yɷaGӤ$ާl+(UG"nAeX5 brxb#Q zd~x;Xu=/?u@DDg w҆WYKئ_.Sj <8BoKԷ?q&_mL;͊26*G6ni?2%R-mŶ6蹡GH? /26 uYeo>oնqZJs^|i Ջ/>qZF#Iןө2KALbZ4~r .1` ^k  f6?~T ܅Z$GQ&uGSD 7dx0sԈ~6ð&>/\#!bON&]bxQbc=l0^7{=d"O3ƶ-FL$~fa~*a"rFx>I7 IGU(G(4%5^.#\?8#Hsb~ x#ܘ(_Ͳ'~4^IXX*bo+*[;0t ~#8]/k{f8,;ƽ1y@qD;hÆ{ /%>ضy 2O{RB'ug[I鯲;Έ]& 3eDKqBTPjr-f9P{5MN'XncG.,ɵ)9$-~mbWGNp #2_B-0{Q=wvsZj3/uQ^+w{rϏB@ X;fo{jf1H0Q(Kd]v0_!`ژ\"<\a4z Dl͡_enjzt 71,m؛8Ƒ7b~DXū4׶%2o>%W̦ G%^%{[Er QE ߡ3/+(Etk/(f/+mCw^0;%F/of2LEBr?*Dkt7==CW8[/!fEdCj!)2-*o|g꿽,=g|^fxqϿh[7^l{*}7}SD64?r`?з|d>jT$#sc~C;q'ܓ9͟͝kb@.)~RW7fsY|ˍY+yw|oe|` +-q y,̨vD:N&2icwP1.KL4cWx,_LfS} ȇ7_|~ecX/~:&8w\(ZBŦo'߻2\՜ G\6 [sWٺo[NBC}_;ZsS(@0+-8WD&GO)u}wsr b2+BZ/U*|Hy%pΨߑ)ׂK`S:880Ćf5];R׷9 &1]o'O֓ߛO%D1Æ/k2&Y؀/%pfZ@pL uބsi}mR;mAJa=L8r8w'QM%UQ3 D׶V&"Mz$B׼M~e :uħ92c[x^K[ wD/6s?2$ qBM$K = +[7"Y__bIy*Y=mA̰0Vw[rs`nMށ5 D?E@kAs`ryDm9Ib :3Yk&U'B2f;jBE×٩ As~٢_CMu*,lsމ.7umpW?ǸG+QĤc$]3us};7$i?3-md4KS:Qؤ_PD&F#)컧py7w \Csc);E&ٴo)VzU˜P)/m_DptՒyCy&1jH>E0ֻ%w}Uvr~^]fLlRII*qYf-Wsǡ_ְ,M*V望APe=dя;·aL{a h<ۨAޗhQ=bZ(qZ }n?{ɒ=Va%߉^]ECyh!NkM&jMs[Z؟XeHb)8}bP{i1B0c{.$2* r0idh(E@nNlF"~ < ‡-)EK@'H=Aߨ>4: vE3rH$ڛ{s`(;8^u"as㱩Ѳu}ߴ;M};}-Rj툴dcO+:c8VE䝄2 _ 'izԧ<cP3]%[w>Iۿ5/D;<:,@ t17cP _IY˿MZ3TXBE=[Zݲ̫o%׸;Fv]ZPc aa{2SKH8B$&€9W4́'&NP-莣[I+;Fb̫m-"w C|1SW_IyW9 쾜{z*tXΉR_B}GذWdvq% jUZsDLrudORY z u$*d~IL厖D126C}7;>ߟE#Wț3Sb" ֻE:h9XeOf{Ξn 2Ε"O2;UVnUf׻ۮXv[>"CL\@Xȸ|3^Y:b40ʍG7%猐pllndl.3.q&6k)M)ꝅRjdM;wt!2Mi[{] oٕT"6ۗzUBvd=z!*-Dra_e9O'vv+}lENCh "=(( LZy'fwjD$}ӏMD-]ԾNKZkTV>:;|kKb?j9ٿ?}SC[fv4L“llX,6W|ݓ[:Q7-7BGI'd& :V*` BioM=bDn{-&<Z.K+յmsV9X8T6qժ2])^;߄~w+cw^w`hC1ݳos#f#KUhfZM=}4q}>qڴn)@2d4D=Ȼ#/XإwMg%F{%Y;KËk#cD6QC|=~b#{,o673}/v'FyXlboV?+x&ۡ))b>2i=ZSV5&fΈ8~̿ :cČQΈG,?ܥ 9SUrߑocav߁ V`O=ҿdYM? ٲ{NU:GK{[`~4T5SsalWىcy QAw\2ѫɵ\,`>VS{(m0dLj{Fy.fp gCt}'>>#yOf&ς }0rvn> 6}{`g *XR̋ˢ]ëVڄ·)wj9[lDL&Quz ՏͲ{\-e7N%4 WـB\ ~at:NŲaUrê'O_4rd>Cq.jKmR=Ɲa84Qd^h ,=1wHָa-Z*'{v(G,۹,|f>fbxgӛdR^,׽YrK[kksۥa{:1TRVr 7h\~uP];Dq^7MYo!/&w{d*2Lw|UF2 Ǐ\ލ:9j%ʒm~Qd4.w=K|i\)Lכ*k1sۆEҜRq]6lI5DKM6aĦ[;q9snޝL@0<lY4s\Fg-9Z X'{P[< yRkg3U %9o{y _|ѯuC,("{$|c.m{;^]phc.8y$rc{H&xDϝlnTDNrĿDo]-#?DV7ڋ\ F9!8!%J8eGe@sj솭^=8bf/ ^u C;7S^5nNg60g/;l'rQ4ۉСHrRbR^V ;A[*XPg W͑W^U4UUnM6Ϟ7r;U$뼘eE]lKm Yc~,}(tM[Tw A[ƈIIߖd=wD-@ؘ7K 5f2K8=W¨5#*Hc\b&!+l(JGaAazQcx ~BXfD|P02LU؁ywP4deI_}st/uW o+S!}A9ߪ\DdH #U>s0nª][tYKqT!lg֋A(poϝU| "c;&wf,qw^٨ {v8Mθd|]uI48NYv2rxb'#C%bL \Ŕ{[RF6ku&D<_}Ku9irOά;&!Km6n&V@,'nj6ɯ{Gۤ2yCI^9v-,8@4(U6@uTvdvx[ފj\Z8/+U:2Rr,_˵OoWqƉWz.f@E|t90 dHN &PS2Suxi<>WZ97$WˆYAni䋥%xR^̋h^sm{|3G{P!Vd 0CkjGPU+wL2Qy+a;cun]~֎b587Xw38TW|,Ș8u݀eF;KBy}; GQ=c9f"q,=D=Ty b&k r}aȊWVQWj{wC7gg}5wWox0Oi? V8%B [+|وþ-i/lFx]s#7xܟK^v`pZ٠ } =آ+6%˜+XbteHJq=m,RVs7Lxb=Wcv<{a '.$D _-mM V4koB2R Y?jo> Dه8PK#FcWX㷤 i⛅wxJR*Ʀ Ȧ%[Q3 $pulG|r:xؘzv;D7PIϸKn0bZb s|n>"@P+Aq|wnƥUwa6 P)W\~OYkZ;@)@/|_$3Z7Yx3"Kp681 Ce4^]N j\C?IyǍ ieIKGǎG?_r!VEb'ȱufU ʂz;l3{T9_Ƴ Ys3zQ,O8Q .)b}`DP B+V#L2X b(`Uܱ(FW7YK̪hwr#m 0V4}+t߉աR!YAGos]J& ;vh/1͍<1kg1.y?.qqb[8̫ā<#d~J7D,O47=J\b│2E&BGoQms7-7@wkIcUSݒD1,|lo97Lr9yy^1ؾ4>~y ,EٶE%2CFc9lj~oZ H(cy`7!",Mf.*y-ٙfO;cɂIcu/lq8QhW?i, lY θFSMpD)+-wM2-Ʒ1c-q2Q wdUJ>DvO`2<돧<ʌywԩpX}r0U ]Xj)"ȚrhX@}3V<9؎v J 6%/[q;zK67|, LDu}wGaі3s?CG\Ai~f ԱOvaU`LUr{ ֞5o0&;|"WD\FNzgN YUb3]l, &nȶ NEx",LYYD&/ZOid=(IgF'qЕ fŽz'f+ɶbYxmUomPsK\JEWV*f&-)T&] $ZǮҜ:g'j b /cIb'&'sa6]16Jyd&KnMمOYve!_xzƿ ĎgqԃzZ 2T6 .3wY=,4u,:f weՊ]`X5#ZҜh_ YgY)ܾjrq䝖.[llۉuttz{2 Z&r4N0ԪjYzt)< [`=r4e^hD_P{ǻ;Ϛ8gz%_ γNjxBq|_ cqz+=8UϒIY| "Q(\ Lj˺@1x֍ZvԳ{pm2:; .h@l fh+Q8Qso۪j<:D-zc;@(o{v^ ^a౯I{}EV5u.-z`Q~c,( ]щicbnd8@`'9j2;K*?ҷOgEԵsWn᨞/G?uϝɲ2ȵ1274t)oqr-7E3F吖VgI;$*][0 We^7.7 :`m(i&TFTC?.| DF %]Hm묳 ]מ:U@#ZX2g~3vZm 4DA187^c=]TYhƸ&UPkC_- ϐ=@ 4L ^#X_tVpp R X1!R7) \@su_{PáTj:;*2PqA=c\D-[1n[D UY2"BQ;FtôPF4 z_:Ebg&Sj}9{u~"!R L?USݱ܄mAFwvmO< ճ8վUżW>UUX48`wE 6ؚh;1ͨyvCQR^,L[W==|ѕֿxoK-?>|]yMz5MN髴K5_Q6RLCx_-O/097=d]VT k9'=EuC, 'k0)3m}`'^ZWk}F^Tv~>U|SϣR ly׊>~ {0ǫf,56s'kQUDpYB3{Qc9+=_+]}ЭYaۯǬ90RW3O} mXDn1浻5WEIL:WU%vKd%uI*qqx*ȝ=t^]>Ko;ZwZ]j?MeX;TvOo1|ؿ)r\ӌ׶CѦb:wld3Dz~G?j-cjE>*C`~ ТWF޻9N&'3(`&>eOK$ߩ\1fyhR"Xo}Ӵ<3Y8zx,t#i>]H@^} 5X~G6PX4lpEOX9Vpn4V:˳D"6T=Gv>5}6|wUz>];.Pėhf^[N}K HbKo1z*;jzG0l7wr(^r.~G_6~mz V#r2H~C"z.[Q#u-T*C;iU_Ѱ@ą>0rh~Ƹ"Oi;♁_u/*<@RR>≵d .~pΰjjeAlJƆ+QNvY\SFySڹw 5kN*gfnGKņN(% H~[q&ί2Xj PU!zY_aru턎\z-z~|E/=R-=U}8hi.6B7<Q:zoUr`^2\bvmEZhS=rpwLw˃clD=8/vݎBje|{;緟ԠD,P<7=U#OTE>#IŮfhKəO.|kv(#6ܑz*(zO| p]B7קw$r\їz\l7~(-6"G<>KNl代=:d'D+6#nOKCG_R۲s?? ޥ^9KFeʽ>bg%r4^WZZ+5BK}hJ͞p#}%=6I]$R%@f΂J /i?Hfdڒ vy"0'S%"l|f  Sҧ"GQk';w-oap)顷`O% )nNu\xsnȰ M- '}L=+!l0 ׯ˨R&d߃>]qw'<)ŝcKYxJl#rnI}#g*WȭضAFX %>U>.䟶Ě)Z?ocee P_ .j99'NWWU 5@қ3S.$| oL09WG>k u uv]\[3=uԝ*hRv%.Z U]kC_0Sȕ4rc7fcU|xgJz.gL^f79N"DBxެH%㮝J% l7aRdʝEZӗKfk_sRց!T-<jOzΪq`?: 'ߝ)︟#= voV`+: +롾usOAjL'l#ҺxFh6(Hښ鹉b2ѫwP+v _c/;Ȭ޵.vsNz;GkT}Lv: 69VKn2&ʟڽs7'>ezu64s^{ef~iӷ(zEat>?ئ%7I82^WʙK|.r$M߽THel{Zϝ|w<Ǫ)W 'q|莸Oed+qR: mH}ex~`ًS,>7C8~G27W#  kϘ~Ob?܅{FɉbrbWQ1%ܪ*^{FkbZq6ę,eHsc)XTB1/+N;5Qxx|MIG%>͛.W8#}k֨ ;9Jhlfw rZ,"N @CV^ӏ!s%ڡ86G#[X7SPqTݨ7)6\yȦkz8ѕ;f1۪hvchD'/(x A'̦WwEe( ~&g5 j&Ƴ(x% J&Ԟ?%;Ʒn%g,MOŦJ@笓YXMdb9R7#Faß!~nVi&3)HS?*0Nf{mn nNp#g߱ڴ^n;*oV멷=Փ=`yL5]n1>{n6AD41/LXZrq%.ǔ)n]!Ȏ\yv7ehSA@~m02v2J7ACPOG /{)BzlQ"w XW{^Id[A7;>meFuYKAeĈ>]~xBÌ-bûJXReB<h-yͿqӟ^QLC.;ra?jV<(Uֻ${X|@rUkr~^ٔaDq`Hd˓6T[{^7GMXjCͪQQ 0;c}-v%fS/y2Y*KIΒ,ۤ˭~-PrqR-dr*fh#bknT'L+a*2#ml8s0𶝽a,®pr8{3V?lSldّM <1{F^ژYy#Y6@m>d!Զt 9aeO2x 7RuW mԋsY5gy\,wlh1]dn\EU[>~gԸdn.Љd[hWa+VmG-U%uG`?bbŋ=t_'o$ʷ͠u٥L.(`5ʅ@FVFf؄oV8}":"o50Jlӻv8+%2:´:Et_᯺fx,^絶C# W٣hF~uvt,F8b81;Z27!'^]rm~Yk\GqD7Lka)6ū^ d%֡\=b;k6z{TC*k> 졇sJFL^϶Nw K1MePQ1.1I" -+'^9GnnP-Yi3ژqedood`>Z~Q4V㑧#[3/*5xоU/Ki[w1FJ掞Vj8ʇ -HGO|.:4ξ0iƹUhmvFdC0@ED4fw]SU-@1q}Y'S =K5ݮ 2 Akޙ@W+g0refo*ܔ7c޾jjx`WyZ|xpE6LJA@u3gʓ+7=ԊГ[*R on8x泌e Dĉ#k'2 `,؃_'1<5)>nf58 >F^7|j+4Q=u2Xx/uD?1Y?5dh?FtU[ o;h1jQ$㮬~u︎M#Cy׳,J&b&0b0Jw%z d5@xVȋ챢F,gq*TU(nM?1~S̈+! |u(f6႙Zq%,W]0|2Ȓf^l'6y<۸FɫJZâUd@dE.u;0mPzVR4&Vh{.}t*3jm";DIe~Ņ/Zئz4mQF$1n3oc˷bNvF3_ޏCC:ޜu1vbXȿClJӜL)mN#kbگ Xd9).= *uIFĈsӷ)d@W/j 夿{??oT$.ϷLEm#U"1)hҸ;1VY/c F͊♯|KO!^y8?#·?`Եg;li*Huκ 0cDmjȔGJhs6 ]XdKnY6ݻy'%1ged=;׆w,=E38ȱ?jc 8ݓŕͫw Ven\?uT=38(j[٬V\YY* GFλK%ЖH,.!:߫D`*ŁNp؀l)y]1?`Wmg{b@>\ t0}㳍KOQLJ^oGK{Rzg1DS}Wːxe4\7o)o`j|HI-kg=U ޫ ow\yϥ)|cnK 0F{gb8Jε]V,)ƆTpVН&^*˜ݼFؔIK|☋o:փg)y9z-F֞n VU*GXEzD|,w< 2\Q_B[9fΨ35U8|H>c)9]η6#Z3>f[KDwf.ȇިo6es2]dmQ;k[uKxv6[r8J^̃7ܧ|3)" c\UU kA,H~&.1Je^cz7~52 8y}#[02"X2GRZB+ KƈQ?pzLߑ+9RLqt,SanA[,9PuQ4sFSp7 !sX$z1e5GĮkJem#A^Y4];ȿY_~Dw "Y@Q1[ӴQWoU.=R#|q֗QUJ$8qhJWX^k4ssmߟ\h?ȘvaB&g dr{-!==PfHiU@oʰŪ`[70s}|ìusQ0 .Dc3Z2掜'U·aPGgܻC~n ]bR8!8"6N0x ]`}Ļsh`j%Uf!Eazbv(-vqeK; i`Cq֐9},=lrz~+م> r?F@ ; |Gv(gmLwnjUw2?lŦ=뤻*tqZ9=F*a5e@VbU!=5y>؈B媍͢C#%*݅Wq5W_=oH\%ɾuo_ڱ#޻M^bs{K_ C`UjP<;."&& #X,"]Wd ITחUyMp=dkx`ljuFG3eeA^Avʭb-h|#D\?Q>9js]ܩ־=Lmn6PفKn[ǹЉ T>d[ԁs;ogt"ڵ\gxk^_Uf}Wiz(?aUz#[bc_KM$5~7y7uR9 f< }hYʌ9:_BxpqU\wkL vSR2=OX×W>~?%?,لצAjPܪמ蟌:)b8I0y1X89E %:֪@y'^\֛21Cؘg*?"îA* Jq§w t.n׏NFS4tl+!qzmiʬ'z_Puaik;#߮&"c;פ:qZ$mSɅ#bͻɌX绽:f&kwzKrS{6NtU9f~ԄDr.7ܚ#NTMnv51|70T115Tv*_L }VbmX*6/^ i1Fl966.O59!z9J22j% -{0' G>.7?3&j>R7Z@w|²9{v6F;Wk~ jKcZ-e<]e]P'o9:>;g#xux  ɀƮ aEmWdi|Z=c՟^ rjBUV?ph$/8B'>A.k"W.] Ðo{.\ӏ뙞Pqߑ]8[۾CWN樀E&|vGIƵc М;">8Zdf}z=P8%T9V:Y۳% ?\oٍ3b.εN,Εcw4k||= lH̠ĺ@O~Lw,}*W Giab|xbqNDv0yeTUX‘ԧj66\]u7x =gC~U3kV5WkSaqUq=Ys[zF8֭>|fd0Q,E-uw6X(L3&t}zޫF-"`-RX̭W~U?X}  [sֹb*}/vziv_@,fqBf6Hѷ~sX>W[d؈Yc-+IkSp*9$;yYi΀J ND"t{~ٚ765@Cu TY ܙ,K;8*׶"~/kP[GL'LDQ=I׮p;̑[`kY=`e^*Kg? rwi1S"d@+wup\IѼIvg?}uha5NWZWI䝪[_IEm`ofj:O쫞\r$́P֘]Ͱ]r7 ph@}T~쨁SIrʌxӽ(X%ǘw5<#QEqǗyP8SbFhVk[ 6ekjofj5NԶ^B/εԮՅAmDL2ƺkٸ 5&[vxgp񑛶Dm(Ec3W{\wpsp~A.A`XJ'{-jJ|+fߊj5ޭg_Ƃ@{ysj+8vK+˫<+ףFhRO<΋]|hhuUQ\+Vo|$. {ٽ߹D]q硢ʠȏ>v+F+(";iB#DTZ68X߻jѩfqa iUh;qB<| Tp BbM ̝*_«;}ߊիu$sb]ur_ܯ j N/Wn :?;8%Y Bp$o Yz\D|T\\y u-u`-p)-> }AOSdO;k*"Wg}QSjKy 5l Yqm?(J\ ڱ7Uh1T}DeEpo6Jc߾ nst=8;V7CG>. )|U;.2n {eٶ O5L0W7z"/xя|2yۻB͜}V#{9J7db\wTu jSGZQ̪9xEyCaDp4d<ӫzI(8;:u~G/|?>"qpA/sy^U:"h>xlPe+Kˌ.<삍8TNJd^j;6^;0Q\* <Ã|9 wWkn?u^tt=0]ׄKNjw.nϱsljocOVj}3 f|Nr߼vRGyM4y3߼F `%j~:j-fugZߚ`hD9_V›#ƢFw#`X+]!Jߍ@t)}Pt7_fcً%fzPXL;:jPW=K-;O_,VN?~ X'e=|^h8H+=g&vF㨶Wm]+w@GvgLpvx*e?cLzs88CronV^U9W,x;fߓ>fFk~(ϵDq KA'ǵx=^L4 fjuD_rMVr\ ~gͬGĈƧYުEyĽWZޯ-U|kL 3+%VCvԭH9ֳЁX3g Giɹ#$r숻 O|lDk 53?m-Wyn G8. ?xgw39-qJW;^$Ϩ[|쳙]Y#yOȫoimnߡf!Qn۞q|#U]1/""wҮfͨWvoU9Sw&[ ;w~oSjr0ڞp=++RF!"Ļ/].:jZD@Zo,vW.kznkU>seVkY);*+,v"-ڭ|◑5ع s({wrԤxdoUڱ%>:会Nͦ~XFɯ3Q59 qixàE_\޹gLc{S72 bߙYi+qdͧƼ(P oÆ"nz~m}BG>Oj-uUs!'֮`iqUcGwAW0ʫ/;+\T&~B[{޻0C?O\;vx֧  Sñ X܏߾9*9:xsWuDGbS 2Z:Xz: Rbv~U֏<̷xǟ}|6o;v$9t[mXhckw]EYqg9{>k~oZUZ 'ཥ?i r{äz!RdFUu$T 5Zwhn>=U*0.kDVt_\u^7 uX+bOr(UTQ DC\QQ1\J,vn@A$+O*A@hܺ=kG^nz+#T䭾}UrolPqvr?>}ݶ{]5;i{g#{X}NĦO౶m߯ϮmA03g|V߉5TtS f0f݇mU}kt(9 h[ήqZ/Y=*;kڊDzl]ߥ.opD>^U7;v=5س,s.EWwu\;{+~lE m ԜUN~ǵ{?}g7tM{M1=UuNq4ZOq9tY)YǠHX.zH]2/#j<!{V{Domg.*:xv.G{.*9Կk&wՕ7/UX/||xUh8tdjjkGg|dcDZPPn'Sea)^|ۄc'3'RJEvfXћ7gWuaVƚovɦHMdU5__}V" ьq}prJ4MCƴJϧx]R*0.M^д$\T8KKK&wOiYif*n:tz'ĕ1.nƚr.1'K}:zhw%j5wC*k }l^iA~oyV8zsx%-Zg%9P'mNSrtva).t"/;K|,WZ{U]փs1Yc3'mvY5oYZ7='†ֹ\<}`15[7"-hN~' uݏCcYщ%j 9 ރK 5s%/$Xߏ`G͹Jf':TMޕ]õ׽Xrv5PD|,^zo WF'_»ae,2,m[^(/y>kf>7vz Gz6=VD%&_ eN(uZK|R,AumBa54@Fލ{Me||Y9ched]zy%ZSIl|H{殚ơ_JЏI&2Ou\=m?R1U.NxDu-06 bQv(1%a#kQͣ<+T]*we }/nT$#*Rk/\ˊ<֢fn uVTTgܼM_ԧN77iaUF[޿Z8ykoQܿQlUZg^7#ڌCps0Hcֽ~b-yD `;y.|FEPB +^Z|[oY@D\]{L'M}{Φ}!7r-]>X \F(Jr\ b6Kʮ9BOE&?"3_vGLѳU}?8-+pT-c:a՛ά7Y7Qp\1NAAo:O>˶1*1V{ȤImκauVo5oɈQ^݉hUǃc螇bGU'q\F|aώ }\iW^#Qit}&ၹXgĪt2c wqOZt=8'v ͡%ķb Q>VfE'Е;ĵqNډqgj>Nw^fG~*lb\Q&~i0_ZjOi~-5uuFa*qk#JPh9pUnsG>oq/P卑uy`6NW";P42s^;bkI{:aOYKyޛ|ѵZtE1Spnف\*ieG2ZiYqn/~AA|c{q%3}D+Fv|\; F=Q'ޱgw3ޙOg$AQ1g$ϭJcĽ܈5c`uQ.%rRov7ƺBĹB`Z+Z 3'~s@ILghZ=Kd27yѹK7k(ޱj {oW?bXK?ߟSU&"@_Px QS5y/*{6:jU2o n#sɼG;^~ V*M=_ N! ۡ'okkV{&oA~8sZ˨F]moϷ >,و%s2ոYlHWS\*2Tb=}~7J6T/zFJ2n9ա5v=uoqafJ&$?}'q<(ܫÎ Ww> ą;D˿oT+|=Ӎ O=߁h.򑳌S D6LV|@;+K#\jz;wOڬ;4_ ސ͘-#ʡ>fu =VWMgs8)}`e*#+BNjyC͈Yݞ,gr=_N.tŘ2f!jَbVuqe"x8ۑ9wk.r9s/۷G+2Y6cJQoOV5v;n/{ 1p48 NjY~T71#xξ!JВ"D=k-=,kG`FxWd߁̽i 3-?Ax,fdRwZCu*G ͝%b5>9]+A(F4O(,,GyGvYխmF8'5(FffnʘY;&R?wjh*"j6"\ᅤ6p>pF{OTW%(nAbZ+N¿GFƙ鬝3:N~:sN¿GQg-[ndj:C#E>6K1Z:zfosq/ x:{f}8uո{;0Ky~繷+ C@|dD?߱O$Yd8)ҼuHd>v0quTڟWE;=4kܰ81_cӞ4 jTю ۖó5{S!1N|{Wvo[_G9gAlf!Tf!J%gE}k6 aU5 :s{͝D`cQfQWkGԪgwEʠ:yds=.<2?b( o5]NBNQ`xgA+^5͚LGy HAٕsLrob ]j(A`X@3O IBTr۪w1q.o_XOZʳA9b:0p-hDEťGb̕ 6Fuub ܭV2VoUFwN_sK Q$(yheהTaTī(r;֨YӍB qqR#Bu\qn2 r@٥RzTT+Y%~D9uz`* ~i79Z;{.cC?th֊Q nvXX@ lic|wQ DۡG8 =Ziu+QhF3_e!í"}ŖvX3Kh$@j/<.D6Q~ @anh`HDg2Jثe=ĿUsG[Vqqwu?j^Yej7<%w8q9=fޝz'ߍ9~@(][W]IfᏁ֝??? Fhek @'GP_޵dՋ!P1eFR'>0+}77fvv̻QLeuл`v( n}e6,l+f87}Gyշ#hCweusV8tFu}SZS+ԓjYd1O/^e,:wfhqgx=gPEr6c?&5i}q=-k]-Uɷg<1ngiIlU^hPɌΟ88w_pDoޅvv3Ψu= Ԋibu=*Ψw7S@'e/3 "ox0s[2rrx C؛Ȟ&G[eQ1dYWakWn@tu0ZůjP"šFf6x ܬ׏j.bղYo(QUgw=\] 7 r 0v3㪰#TtI+@'J-=*#1.TBE,C1uUs PAfYS3O4TBaYN~׶*U:j]-z/"Z(e h4+kU:Lhiؔ|d|#K{U$ W&OrޤA}U"84ČQdutpyyzͫg3,hdvQ-otN{0%b➘xP#Yѩogkf}]rpYo9u"5O\D,7᫞z]9_:=>ի/=_䬐մC|dEQBvBW*ĤPAaBOTc[$|;HӤ6%ȁG!Dc؀#mڤqz mB %}m=F1Aq*]+c^ь,*u8 Y|̮KX M^5+Ali J_x^cg5ĖlmvvƱ{/#`3A\>x,ѤlDصմN&^Gאec9YP ~G>%ꛑȥ8&r69}+qy%fo祟Mgo7|wq=6W84iZJ4,o8J&?و)R 9v(-K!7{gVD"[NT9ov]dq({ yk!mXؐbXx|sG|'`}g=_酯_!n ~qCn-`wgƚH^2ד -b- }zXg~g:AC?KL:~mpFjc[̃Q0,O<F+> ,ǒොWbmrT`MM+AߡjkTro؀"m;ʺy+O41 jYhu&ԛoŲ%(EZ7 ]D]A~Tr}/b1Nr76Wshp\Za[}1qߝqqaL{7ߕ֪bZ;Vć826$x;=eYvZa?ŽjɄ CV.f{Gkɠ'T4ه[խY%A5eH/p.(u7;,8M9.26OĿ *7Մv*K,k=ݟßTOewFS*%cN8 udZ1jR/8b1Z5P\1ޘTyVOAcw]+[KD#eoUJ7f2u?yǃQuW^oRk7[ݖcA!FCʑwo1x#NtyYRH!]. )_1.PhP:(S,iS {)Mv}GaD6s?'IMN!\CΝTkX`.T :iILؐ.GػAۤx3ٙQ$^WP%e 2s}@Kޙ\e48ē?@oEM|X+w6 2FHo&wd)VDhQ䌧%fk40o;_ȳR(ؠ!N Jd\kQ>aďo1wжR͝Q/Bl^xWiF`UvJ\;*^2t\mܕwh|8?83 'h4bvZ(pәwƿb%.&Bkpy YT#Y76d\r=6kQj%#[| VyvwNF|VfDd0RuW B.'@6*#Z}1V6}ZRu>2澭zMFdACql(#ZQ_aW@#{腙soz_=yruW!32/SS2;{Vk?y2faUvד kT)=wqȿ_ גqEͩ’}FFB|IrDz#TP)xhD?B^2_֥sџP)iuά(+7?Dgx+fJ }KУˬ#qu#Xn;)3U5w^#}V3w"'CgDNo=w_-fVFIn^C|cF]_Z3wQxGhQ wEPс6ܭ1㗷z7*/f`!<_շvWYM%paFնw)qBYh1}U=Ƭ|۪ﻖ}Ψn^y{u zv*4^5wȕ|=qe%orT5F1X>:}T}l'B\b|E߬] q. Ks83F'ތX~eeE{m켺RૈaU+D\uR"wv*S$^ReCz#"HD)Q@4]bD@h ߡ|e*)i_ "ʹWX_Hy" G"hA&a\$Bc Gw"iQuX*t*`JkF! fUtr^32( .Od6Hc]j\$OR = 1/TSNz*KZ^ "i<$~<ͧ0-1YXb? oёp;o!.ʚSX,1,myDR* 0X>cZ-m#^Iʰ4@C|1l^ ϷZgv;C jl=ljX?(gyTG8$Bsy<" zÞGouB;4E3l A'؉BA>WX,pa92yz/"|~bE3cyVly+W|-:7xgT4LC*x!;$;2;A G(U߹r[@HA&W \'Hߌ@,@\E 1ɍNx!~l|Q:b1@<1C}۰3w|AQq߷ L߉F;0Q-a':6~w%Uio[eRęWSEmDkTdDrAxȺOt`$~~摵2B[ $M q0'}WRkI2`IbNmE<=3r߲1O_jʊn+>⦇刱%v 4}TED^Oط*NZ(O'񪷬 J[Q| \ 5~;Gm6hTajݮ1ڻ`V,8Y܈mjnhF=i:elDk2#v2UG5pjM‡qwTxUߞl,!AfFYӚūΟi|j%m7eCTƿӓ[^[ہjYqeOnՖ Z|NxkGr~ Z\a7|-niOWFi߶V-;Y=O|ڕX?ʏb6ޭ; Etk-㟍/y!Q#b{u5BQKlgUtV2 beh#bfYTp؃7+_!q.ک_w0Q}j$qb9I_.χFNY1`[er{1lgҩlE`6a53th׎YJ=F1] .W]8 4_m{a<E`7T'_G(Wj{W4eg>K;^Xi=byr# 6Xeu׆uP{ϛW}{V2[+Xz+#:| a9YI0awZ_^#>ٳd,"'-(j$&(Q,XQnONGF(j&VG.^GD=.9F~ec|q3Y6F#G>qb5G8&W0ۃHZDkYyvлknϪmJ ISwj ѹ[L$wf.u9 #G/և%#&* bNv#NԑD3F ChIO~\Q%Dd]whޓ#ud2scŻ"qb/O0/*WqNpW}fOu2ªu߃eENx_|?,:H ~Oy٫*BF"R_w]r>w[8woc-(D8b'"/ȼ~6Eu׺ݗ1ۭ5gq>VĢ0])*>Jѫ!;c>q;{o;d]w 7|q$W *| mL2d̨絭#{H?"׎^%CȖ88I3+J0^ßā,^}/#Y\D[׷E{{uGql"Z?eĉ}j~TY<2L6v+QhOДȺjuοA:2 ^#iAbB-pepr?]ͣL}>^11kMj.Z90(ă/TTZ}V.DQ:@v# W+E+|Yi?7~_p;wDEx";ơ2~0H6\"xOV3@/-y8wYv{@zre bGq\#>~8qTI1X| >[T Nů8VOt| }ߪd?8f6EKF=0Y34HٿyIvt1A=QUbϟJƫ.[w<85B -> +D~@C[pA` OM= 8w{v.N1]@ 站ጠRBOֹm#x܅=¹z8\B3Pex1oF*Ge .ۯ6E˱.'stk s n됼d y|}KBhycK34{=LE>+]pbzb7Ӫ^Uue R[ w|bk=_ >陃d%莰3"{Av/=Cҧ^ 2+Vh2,=c5aְ_wm=ڵ^󕪽ئu|nN_Y{gs9_ې0%ϴƾ#cig\җ.ȋuu0I7J tLF#n!<KZl~@6iK[7Vs#TВ2um?qPxLKuFvi eMm_5M"Iكx*k$6!jv[3?筰Iˠ!%o$EU=Oeɢ%{9Vj?ھΈʶ?ϵ̣=²d}NH^z*9f.4VjV{|þPغX9Ѱ<5CWy ͥMBho%Iٽ$;Ek,HDEϦ.nkS:Weϑ>rbIYlVC8(=n:1phuy>vE![ϑΈ{Shh22KdmpPUYZ^8ޡsyӣ,<:1[hdօV۸PI<'<0ZKҜb=AΘ.=~KFz~!o~=ct`PZ:#IZO!}-?Cʞ%0Q/jOF~i*l8".ck9Zj0UExf̖{i03jH}*)yc #)=k;OiɳYο2R9ңA<~>Bo=']d}ˀOQMe9N BXg6҉h{!K7Gsⴟ槴4ٰ瓖1:jBZ. CDв/_Fz}@m;ϫa~dI&KM?4ǗFCa!җlޠ<̩yo#6hőM yLG~^O=Һ% 2GolBhȴ3J#^KQZ{:fq/jXFc\^2+Iҁ}h%}tgWVD}Pr%JUϳ&^+Ug9F?ʼR56*k72??= g6% 6{%J Լ:4%#y&)֎:T>ÚwO9Rˍ-ɗzM6ql;n#R{!C+W+'rF˚[ZaZ/5]cQ)W7UG ]m^i=eS]2~Xq$NgXѱD-;z-\:쳭srVz!aϣc}le淂ǣR&e?c%agFJIx>@>BZFõC/dN{Qt{#Bՠ`sϛu _ziR/]^}7r )i-gd*|1Yrׄ^0ڊ >&%Sk|.AL oF6q҈N=/2J[Z[cx*x( %b)Ǟ}oypS_6jVFhl4>J{Qv"M< Cw {W[ UGz5KZr~k|aDp1%gz" yu<›[焱l7m⺐Ina~O$=KMϫ]3"Z]bQ|Pɼz¢k!g(EdDU2yp\3,~+)\z(^QƖ~u==RWXڔ璜d-$*6ê׼v1s͐jV|[f=%(dh~ujsYӵ̜.?>iIl L[A9.f~4ck]SQ!quƾ3 o]6bt3Тo˩YrԫLM eAuS/o%~UgY!'!O_>:ub Uѵ/׌]keu2E)NOg*taCS4>#ul.g/ׂ9I9_th $#1z\Tw$FwCsvi$ψSF-%]~^[HxWH ߄,gZ̍u&|u0ؖ&Lӏ_ƧyIU@ATYuW'G=@ւobM~y[!4(fR @۝}Rf3|iF"tTow6ZX}ݣWE#1CY{3[gƊg?!H! ~~(i μOnI F2P(ۡ_%ֳ'-.Q8%1IT~2:פ1bCxf^CGJM­XgNFhiݲW=[BvTvY0J v[Ҳ7#sV!Y[9Q,~Nkіh!g(xcEfoI+{ K~dKwˬ-˘{N Xilܕe ԆYk:J~uc\D.VݎE{rw4O=_BTٛS=Fj4Sp'ۯ,iֺ ]c?m][3n˃-rpt/˵7w^gRWΌv9Ќ%䒅 i~.y iDR7UVR_߷./ymdyo5KΪԌugq=s?kIe*\51;q#ozOxBŞcLa5\rB3==XbPuvZtd㶬}Fec Z#kRmDFMX[VH繭]OZ,#ѧI3::]\Zmki\W@#eu5z+^Tf@g/gr K@ DrKԶ-_4XsNNÑ!aId$sSΛ_GKEŊVl#tET=NZgWQomN,|oMf`(xrk͖hV+BUE^0\Xcu :v ;{4nԖBu ~)^hV\59EJ˛mKiբ[m8x$ qjGh~YWӥDzݯ*U"Thzo9kuBAFţñheKKL^|!sm6U-^Uh~F!(5Wf˷ZNFŊ۪]TZt TmiN{G5KݞoȮ7h=\W X%|aK$q;uI:;*8HksX<8mDJ+@/lN1 :Ƶ?;,YzNZFxO> B&a?(ez"z[x j_FI.,%8]kC*G~GBΤx o/D6#fEC' ߜSHM8wlKdB_RY8"=xڣQXA}Lb[`C\S,vUmi}Rr,^q6XoGב maAk]͑09QK3ۭ$#"=]+tofWg[ۣ摤&ٖG>)=޵6Xv9G썬9EkÉGpGG\džE؞OD5#JͨC3R 0<ɐ=G4s:-jB9G-z}pPmxg?#)|\E=/~9fb2[ӆruiQ_WjNH6lПDa[։+<8VҤVVTX-(ҿe]^<n{83:֫Q$5ͨWZ%!K%dٺJxxu*J%P 7߃A1_Qì%0 /GKU(kϸK]0o$7! wZڵl6H VQ҇jPPN9d#߈h_ Np[k9.0;\fHb 뢴4C#9la7em?0K(ʌlP-21Ah`MQuL%rƛ9&W %=C<lԬ,Hk^5&y? VYzj^ۭn ܏zW/G_cdnK(!z$&e'|Te~lW]lg$EHARA 2-q0ULg:>FPg#;ԯ0I@ Ғ G+s5XRm4Ь1+$hbў1"M&+Z`hybd4ÔZPbt[2-)R I_կMF!kk>=txڦ:}L]z;բUQ  +YcFgoA.Q`su{\f8[--OGEf=Q\Q?tkf`Y#EbVc[RĺCeχ_eR qnFё^Z'Tb AZ]OsTeGCn[~ۏ ïZ)\RȰ_add԰I\Y=]e}# n5#)}=vVsPR5sj!:e+ߗ0G̓]jH)ѯzz'])k\! Ԟ1u[A cGѿ^Z'sCI-,$hA-:n_%Glɹ^#GQo{^^Sx$Q^ߗpMViRb&NBAdKY 5e;+OztGFh1ݱ=rhi呔edIxcVIGez%k5؊|F-0(/<ѝ5ZafHWb[j5Bɸg~:ߣR ,mJuUQ?C}q19-٨-JgϤ 9FGM4]5z9fZu慖7C$m=P"qyֳpŸt2o!ъZ 7_cUxhm8hp+i]QxܙEzep>\rCo~hݏUsF-gDyyOy%9_G\C?dV#'2{"O.kkǸV/8 Ѐk<8=O(8FK܉3t\5BT@ۨ H) ¾袢hh[yn*`0N}`ÅЀ 'oo\i< .,85hDIG({mvVK`nffhwxgyܑ<|ʓ[KEG? V )1HU.8Vp윎,,i & ָV KA5/bNt_@c`/*T_.y~(]Pȯk"?n1T-(YX׌8(._?MÂZuR=H++UP血.TPf&KA)$wø qc(R`,YW r \.HVȦW:(oeAςsI $:,X gaAb_Ċl?*HX@$HR[HįzPpY2ָ oZ韂%g-+,RS7 9,8^7G UUdKEy 2֩8\SqbJ.3Vp9g91*Wp_}r:C,\8EQZj}J*UO~礵bbmb/Tqb*+N}ÿ+6*Jk"//X?)W b]WRZuQg &6['8)/V1ZܡX8Wn*|KIUs @**BШX/pg}Fn3㥌UV@߯|P+V9@oT,j+sb{k_"^!AEIߊꐵ%רs+*G! JƃJ+a뮢7#ˀy*UT?**U쨨mɪ U>"aE,v|l*>VdH;]Ww6,AH ׈L+ y cRTeE@rpGE!oc@#[.NQq 7V^K*dU.wW8p+~PiSqk6B_,,L^TͪOùٰtj2~VlaOMâzJlÚMÊ#Lo`-C]½V jaKԣ<);AjfUDdVe 0Ocpb-8IdneF&5eff6&cV)fIbA'+8Tq-\WGx'y!9Bypxwy5sx˜x<Ϸ<쓆BJjs{ &Ci,} @.B+_Kc NXAPdf/$ >Xgʿ,_H+.*ï^.$I^i|!cBlq*\| v!T\BJ)¥]H9a%S_^P[km?ǣ%瘠jM_ЫPGvy(tv lݷAjky_M-O6,cc&kO-Fq 78܀F̸qmcNu|Fqhn,N7 ظ7Íb΅{.6 7ko[iauk7ѝ9(:{y!ǂ~؎oҴdf# Yڧ&k6B]8C 4\<oX48z6FolnOmD A톃ޙ$Bݙ%/Lx7@gdëenk#Xވ\7667썝ezkMc$X*XX4ieQdc%}kѧl@&Dx#3܄ld0*dVmV&u, o@7!wZXg3DG&\Sg㣌 >}i6,*Z?S1^j6P}pnx ɭ7DC=FHp/ߗI uW!rGpfkFݨXQ(?s<`ܴ _}"V '* Al!>Xd,,n&VK?;3W1:׵j˃dR QMJD#-x}͚A#h"¦vdSڵM?0^)?8t}Ђϱ4_ٸy9۠EH9r]4;Bbӝ{$FoDzA8 -sk[ۧo#xiPN~X-U6&[5=q~EmǍ76f7™ptmGC7Rx(@bKxz"!AMT [[ߓ]JX#[rΣ`l a雜p"x6|]cWHSUE%]/q\J/v??~ X[f< +gMĪ{J\g팄;1ސ*0z0ۨ) s+_-^xYpT?_;)f d[[/9]Zw|wp ._x_0 Zo!B?Pe(~u4H{gJRxTdI`W=Va+SiT5]Tn[-J S(k | AoFwK'·h.?P;cB_Gڤ@b|V% TWt*P}aA#-baAp0N>/Whąi~ٖNf/8uʐt0.nmz>u8#V i܅u6׭i[婸!}ZT.] m(]XLsJ3|aNrԅe< f-nu;PC2m'hRF\慮0]av ]ɌO:ͯ*W'+/W^.5 F+ST^t9z"5 S*d!V^T]ω֙)Qn΃#8LCQ]^P%UxE*ŧʼnaw _D\{6ϵ~+]p,R:uNI[>+3W6\Tf Ys Wf^\MdM~jogҫ(0) 7_S<:.:\Fc)D`Pr6jx۪eƛ9MG;㍆;7>o4JfJ{\oYsv7 ZuV}xo s,:21r*xˢdSnY{W!fr>c.U,|E7jbcZVc]]T0[ *R^x,[Y!0gc6Ny'DnukQY):)"xWfkYE9nzuvZZk[-M|qxΣWMzum <%m|Y`-#[6a95ڕ͸+-D`u5X;~G_TAnlOiScJ =Sx(&̠.r)`UTƕ&ZMscotch-5.1.12b.dfsg/grf/4elt2.xyz.gz0000444000175300017530000034407210656300346017307 0ustar hazelscthazelsct1ef_4elt2.xyzdM-- ]:,F!ѣϗGgI3 w~g:Ht_L0Z#i2 4m*Hb0 aؠo^ 8dgr+@׬%HK/j?HX.bb<4:߯!?96K@C/#q2.23"X!i_6} ^Cی+i\ 4?&YxrHA5b!_7'hi 2ULZ$f?|:K"!~Sq(]8$ q!dCg;~&\~L@ @o;D8!e{($\x'!YgsC@=Jde= 󳐶D'CN)5KmS}pH!$)$XC!}ꯣ]tHK?s9!W͈ŧy}'Eb&|{bgkMyc"TRL& }D㐈Xg /rS׸c@*ѶE`^O6C'qF*bōvGˍI7!Ò^Bh>tMry#.sTx'~Ctqovb#}o\F*^$*;FN;ܤ%y`J*e#vmUɣXӮtHIwe>$@dOInrRȿQ!,tgTa4/2l4LhCzZXSAŞq罞k?皇\XW"ᐲt^υml_gQxr݉5#Ⱥg!]B:WV~C䚏ƥ'7I\J8U|9n!&[\˯8RS6yH[tG&!tD8IxF,hd%zZ_n%6G%؎u+O?}eGfutzН֩2 m}A^e,_ j@ybPSdˠ|B>y+y ⭢VBϝSK.oϚȃŬ/L:waǐ(bm)txBue]+|hgzKz[>5]s~w3I(sߞ|w+lΒBɅQf*jCIr6RW\OeB􉖐IGn\.p']2]^X|k,wF9Ȱz]Jiaԙ^r,߅$q=Ϊk (GE<]qlFx( }jQGԊ,;p#<yYn]]G!AճկrOGe+muW|$<J2'U;ԊFsWJɜA+c\{5nצR^q4aw ⊺ );<:Ae? ;4wSZ%mpa)]]W~1G#I-srtb]sS\z][0 Ey{G|+"HL bՎ'ylvu\`$}Z ky|n- .U3oo{eMCZTk[ŵ|445vd>Ѱ{FՄd a]Ҵ 2ԕ]`#lbE|J8e\ ﺞX }h%=h]u4fXZ8Otm\"Ɓ.4h(V厂̰vtj]1EZw},:7(fu6s+yh2ibV7J5oD!lݨוհxi6y&E:qvP+wt ]sbE oujؼJ!2 @^% QJ(9(|QJ4;EE]MD 젩5du I[*ЈO{7T^FmKͰyknl(Ŧ/yk :rY x.VX`qC#o Xc0e̷H}hCZFg_}Zm-;2,DžJ5As6gu 7_t)JUꚔ:jM^WPfk&zFc]s̽Z0YzT djhͥ&'YPMugCgЄ$[ WjBܦB(*VhB~n\(ԝQb$О$%]MkKXˋ9;vԲWֲgeyWL {pY6[SP-f20c2+tRTFByƪYZmZuH@CeaWׄmJCAWs͔\{Ѱ20A5p Z0<ahڦey6 >]mFi_Mj#yM]ZReIVY K߆뎵PۊIT*-[ נQ<j?ZFyfT;OʪIEZO  ks%S6iܧ `e[fk"y5tRխGXˤy09R93NL6j y}cR526* s17V;qS[_{<a- +>FD `Yư־V]X| "Iެ}mĕOҤ/G[_QMZMr+w5ʷ}Mz+Bx i>oJ=mk$|G\~x]`sya^4yu*E$yPZo!E$ ûT KI(U2fӼ-a[oA}^R^Ճ {eAʵ>V4 ~{kE1X+ekK6^+rR[@Mr^x؁26|V/BmZFu}Z 1e,0W{^ޮ61a^~[NKu{RNTXAKcRm: =v3gf;3|2ڴ˄?_m[Z: ~X־{k6kq+QroyB-oI-¾2@5biwB'@[zd$[L U i> !@sB'5֤~}%󢙷<5ݣ l([f9ZKjP}Fmjl=6Tآ kZ Orj͞R[oY B>&I~=hjB76ԄJGvjx4!^45t,5J[<4Rf٧ ~Z)(ˠ,OdU4<)4W4_Qúah_\BWG}I-LVC٤@[I0X-K3Y+qPY |^hhVHؿyB ձ,\;1osG긗C91؅Wy_G35{q:Gy-hVNjO%whZk htO+aa1A +m&&' ~yEO!2VԄ6i&āͳޫd/P ,6ԄQ&<n0;ٚhXFF=xY>!Y@ U_ u%V4(=Ya-/EZ=oLHgOԬ C1LXP2]sbbճ#6=^#y^.aCk m˘;W~Ѵ싕ޥ| Mki}.vWF3Kq*.2£+w>+5=ƀP(":Bk:?VZ^xe EV-c|oq2rBN3\eZ;Δ9 Bűֹ@ |܂XzGZ֞6&ج@C#Ǹ .-Ǽ|@aC+Ue&0[ ʈuP"}O=-3 'oȨ ~|st|KFe?Z ~Vϰ< o/Q.O=2x[Z_ 'f<3(ǿ7ԣ2ՌgEU W^^iL̋#(_Ve(}nF;}qPs )j7f71P&l:|J =evȇ 4uh 2 J3R:Ayc8cEKBIqr7ZzȑP~=-k<2K#, 2G3c M,z lǽP)zta R%[zJJ- <žo.VʣY%<#& L1ugjGS>.#k`ȣ響`(Ocqb\ƽ-BO}*qː#vfKcؙ-^-٢ٳH.bg;O3[cG l~eJګgmi/ mr>#G3 <6g|١ &%1Bu Zi:qi;DYP)eg ql+n:Vo`s  O]%!K:Kg5ɷ'aY7LhhB."Ʊ"YGMr_0}PZN({1J0UG>ڟISK|kdCԇue }?_mV궡[!x1`-)ԙ{3rk1tHiiތp̖u&}`#^ʵ<<կT,*Xu[ uɤgOб&E-}BF5;-M^>74s0KxYZr=$yj zu:vQnGzj7B>C@Jz]L~qS1?i'qSOHeٲ߫_:Z&9"0֣EZ>[Ek>~Qr~ {aӳ)R,7O(X]C6RSҀ'ҧ߅YO_r-O'P>xx d)A/YtZe "U? ޮ^ %p+ }J,R1uBWh X6J9+6I02+e$ -WX]?yM,لUڟɑ[˚gm 2= 7He 5̯z֖~CrxgmXNjWJ g8{A׳$l]6@oV*r޻U[q/v[1Qȏ -]|·UBMmc1yl-h:pP]7UB2,;շ7/Aժ1g} =1A5I˸6K?=BoqW8 q.| 82 um$MS2,sEPޗaT3 ۆ=ltȞZFY_bÕ׸T{IQlufcNHh|֌Y[ZJ4"ge '(\Šsn*e~V*oo@JpuLڡO8P#N*7I]ڒ'h c'\쑡ꎮ½hR#e3F*, 穳g&O8c(=LǕ*?U>Z8 dž>cĆ:yȴ`@')?B][K[sNǚb2/FOVDc!1 ]4QS;N(1T1%<$] lD7Z:@3੃amϭdžZ>&Н.*#C@ D<ŃN1A!߯RF[jP0ZaT>&i+DiT 1 ]51 &>^$lv ^լQ׬Nxj੫G=%zkVh} 8;t] ?8&3Fԗ5 @8&3: [|z{huVOB$^O1 [k:46{qL6`MUHܫP_$3[QS5MeF/ɥX/J '뿥H$ztV+d?MO};+ZZ k,]ʿ Gɭ,V@1ЪY[O+W_[>K_C Թ~qun䘺ϸHbx՗6]tƫ/hk>(}{O ^ .P6`gi]NNH5O9!0Ah %3ء9ĂctDV?a|L%Kl/yp 협Hx`Tc#2cڅ`W &'uf&l>&lqww߻!C(Cӹ;e(Fv/c =}V!&Y} >ƫd[1Z- `ZFS,$`(x2+*~zf+}ݭ.D0c\Zg!, pgS˰C~A*ER^p"Az<Af( ڥVLr#6GRۗAW-# CHܫ:#Ck'lQOU>&{"Kcc2{g(*e{e̮c|.'~G# Xk ChLBO!Yʾ_SԚm.&~2G;]@'uSݥ?>ξXSϹ%>V}ܛF_x-v@NoK:i ByɚPhq~Bpź8֣ t$"n;lT'b8jF8tZ&q68կ;AR=@ZYt5v:*I!Kvf %ӵhe}Gd@~\UA-"f B/kՒ# rd2{|䲤8&lsK_[rAk6a+Oh}צk˺jC 8 c[joj< ڟ̬Up?e Kcq?u:0P2ZnPo A> #RpePL~M J yqw(5-E4ZA^Rj+<}D<82Wspv(ϡ<OW 0 kem T_F~<,BgqNG _^&A(1.՗as1@6;3/C&k[T!=j'dMD2؄}2(T``T_OaӬ})Z]4oO z)/#a qe8Wۛ(O}&tVv?5x=Y¬ߎj0A ~qU qf+3j <, VZ*KoGP‚܏<ʝz<Ιg"y[fΒ@P|]oNS;3 -^VI0C;YڶŞI9HS/jLc[jxO` cK $OΓA,&SX )l>;10C۱n9;+-P¼UFLGm2f_H$e"T N=ڱUE8ϭB Ҥ[ )GZ S(,\ej@ڱ׷# L;+Y8)u4hJK։:B`^QrIIco+iЗT=:PPY:ch!(? a,]GmMٜ#8.@-۱RG T@1#Rp †{֛\Gd ou݃gN+;jDt [[|(I z8^ N2Q̗6(gsWo!+H2j ͧ0IR(>Wusb_2vD&w9:2q9~V|O RmAl@<})ĿgĔ j H;6>l) \=mT?v[vlp%0ܱ=e3;!:;נ(];o;wdx8oZr0l$5֗bA$ÑdѬg2\ܲfK*}.TWf"MZ-Eo_rwVǺy-0- G]x(|;禟|2q=(cNgޜy0^??*?gS \ǎ븈+{[&^̕R2>gVQWvr`tyU@?gVu|_nbmr-'BA,# ҙ-V"1$z;ԵT >xoj_e%c>{h1$:-kNXmX0Q9)}Q㷐*Ys\/?g1Yv# 0ޱ%ݻxM;^e1%(cد€MKXy@`g/naN]-?ia]΂VSb[#`J9`4dwly!9I52N! .N{^?-}fr?=[z[6R']ڱ#%c+so0꓁s\KUAg\`Sd0oÀ5$Xe;# wu;|eġ[5s|cBz>.7(Bۯj,[{g5$$PRg@ŏ8 u?u8[رuI'X`4X>5p,ö{C' ?BKَ -Vƞy#jKH3X/xt1H(~Z!qhNIKYwЬ.1?x^k+֐YL %&q [U4MpW{lCs {2L 0^/@W}QwC؝I{@ewscƮ[wUg6S֌Mc7+u?687ь{73wVn/[+/; ύq.ܱU/Pδ5aflK^z̯%DfǞy9N^ő^L\}GO`> YbKS ][ G]"ÈuVlk>IFBdzμxp=mL٪!6>܇fu( zv[M[0 M;-# c6em`gMY]zݟ8N.%sςPN;~,">uǖ.DYǁ%)(Ȏ>N$m*Oz N3xsUAq}lXrCb0fm3Į5ǒUw2'84>EL-_srX,3)D|6*÷Ve=~iǡɈý䩗/ X8emz;IH5A mէ0mB}gծ=lϟ>zl o^"HRܪLfؒYdzigl,ꩋg\ jB>{[I" e 2..?ɃjxK>ssv -kx)y`cKJx}O'Ŗ"l\BjЫ86;F)G!K!;xA\h6y1EV:8܂|]͒8%]ͲNI>cl b¼6˕Q&L\wqЈq[8@k:֋@Oj'Q3tٱŏNy0p|> ^X]cǞyK.|?gޘ<;kٙ#@\VP?#,y3s.àçsp+-&b_x+(T)BwE Vw싿 PN&bvp|m:? ;VWb{וF13/3߱^= [x_$Ld/1E\3;Dx\$=j9Ar /GG>c> ~U%ҚpVVA2BaUzFyEޫN RvC uOFL:FETfWX [XK c[VQٮ=(:%=0Ś= L‡0ۇ} 1[hǷ^O7do ciM'ƶ HQaޒQowj dkmo[^XJ,lՀ~{UXh+ M}}9M;cOGqM[X dK&u[_ܿÎOS1a*>3d:c5c8KLFxB=u.أhtB֩OބyS۾FT%3$%60\{6b rzTeLc#'* 0E []x™EtpSY`l'{nbKDM%moBm\=Oe~7qN9T{QuQ{FLe+Q >&%D?G;h^덱o.c栎c l}C ߜ0c˫oyh=_'9z05c9o <ə'{%e(%ׇW70%9/BmT_̇W8:ܥI[|(T^\}tUsXK<ùr[W6QzsfCeuOj qKvɀ% 6 ,QXWej{y6Of~'Ui[b݂0 {yn~AV}ACФn."+ LmeloQh/ٟ#&fbru!oLIEߙ_jbR^&>w >*gJ{U'{(}e6-M3lq2V[df >cK] sQs"c{%l>/?coxFx~s @܊T%;_Arn9宵W#RְϷ. wx>KGo6?I^"s}4¬q%Y@lg`c% ߜ-wλ}V!ڱf%{\y%d CRޓfG=֯j@nUڣ_>p*38ǟ:8K{%>'Tvloa:\)gLP,yjR?'_T{|^^ ,.wlT/ @V; jm,[[&y~#([[H^ gy3Ph6;kw+0WGzy5*7c 3EB ]1_!pwZ ҙQ1gRau鳧t j}bT♯|)hp忍y\${Ʒv-K œ1/٩Dl}{?#/IswX: rF^flo2V\?xXqK2؍ 䓭 -m!kK34`?{b #qϭ{@"qkr1Cok;峻8`[콡sMOlkoN@o xbV{![oW[?^U/5qvz0sqKvksdz LU/Muߓiy1!#?)>t֐ppʟ>~t1dk0C q=~m/{SF`akꊱ;ǂ1Tp _2`3t)8[^"yy9CQJ5x6Qs lk:||{כ`Iz4x"fyTKR\Y_̇xT6r-,0/Arld#9dkd1} 231|.=`R7x o@1W0+ĞyɄ{XZoy7Ώw@2nq8^{r}siX}X{w ?5py} xRV:KUڰ}R6{_B*hU?.t? bsez~p'\YᖴT;c&1VVח:[NSWK:~vx;#tM{'O$RestA[[Na Ww"BkW9L/<r똚_>߰̓;Fʰ73:}jޫufB)WO_<-P=MIBXI' nxm8?;۱_B cNR%p;p'/{ sE_JDgE9<<ҝqj0qƖm^ƖNgzɾw7cXC^~uR!fow0_bLc"^㐢eƊl 7|*b}H\ LVK/pT [:>ܾ. U{*f`_ cز$14A}R~X5;'JHqrC6k?V^G]>Nכ\>\;՗o|rZӭK:R|^:|MK8lKmh RgߋeJqdAMD@^\+eJKv~{Tdd}WFW:#&eu)Ol$ b=_ C[[ @=s7#)|QF:Z=y!m,QM}qnJPW7︓i{_Zz=(^> -׵vvSpx7Εюn=/h闤sՀMErSKK1\KmKo&KzVJ1,m7W_>_-p[J ZĨgmcK[t-=K@z-\#dS٨c(Z8|2fǻҲV7ij^V rDU/aX3: C6[؈uug:a _/0o:'!6]0:tܮ4K[vP^˪t޹~'~뗏.XS/2MƀWp|$&:{DP(٧ޏO$M?ƇBJ{\eI=zS/b2#wΪ^2^οXc}!':7LA[~WcG?Y(1ՉXUI6O Uu#o\U=׀-*&>zp=}um^h^N{W{Kb_YK+s|Io*c ]fo7hty2'S@ϊC^g6 0Lǡi -v84^b !blq"M dV|}U^ ++>ξPRNo C8YAl8S{+h_9TX)xn\>@/_z~s RXخ:+^>FFm' xu&g"Pr-ޢI͛rlLj޸o{,bkfy'giRѪL.\cz&FE߃]Lã^@uF)? v^E_RzCϴz48J5ApR1Y齎W SNV%I&auKsi$x6Y C_bsΖ:e_)p/8ivNTzlUQ/y!wS+􇜟=EPȣL6PKqo]cO8 *?ڣ́ 疟GsoV~"SCf62^~b`K '\=%}{wLJ_?~z{Ͻ{_~&αdQ3 oֹ`p,>N ~g&0*<ˑgB\Zs^cESԶ#=:{<Onslv߯~ !({Cis vVc|@>V9ԫa3՟,)ϷSW&jaƿؔpxT9mƠs{Foa./>vQG3{pGE JCŻu|N´9؋#ڇE.ϱfGU/>'&&ug;yq2E4 A/>> ,IxqLU#6'-gϒ5Eqvz5DFqޒx׀>(>N,.mm{-&~%vRT ۙEMOx_^߿ؚ7.'>ּM ixi0v^Rwҟ|I_|hL1S[l@Ɍ{幐3m0ǩzN&'yO8uV#>DgQzCs:p}>ju^sTHiGجձ^~7r*vVD}9Mke6PUF}AHFxnz叓I3,qel>Ǯ³貮{> 0@}(?ak(:lu Gp聋&L"f Me>w1Ox;%x)t +Nqc~}zzO\~I0xe,(O8d6Ew0^)o0ן{&rJwYGޝLx^"8>=<@"<MxQ@=!G)S&CJWl&jS̵ ϭ{o :.q%F8?_G~ے- 8,E x8sGEA_>΂ '!{Iq9L>Cb#,F*`_k]<| VpA4Е;~V~b׶yX|zI6uc W3o<5߃yCnjjg s>_&UbnȣXR}Q~=ݦL ׊?gFB?;口Чp(:>ccgs~qur ߏ2xY{7%q*{H>H Ơm'jr[|j&'\{u?diszly!i0mR15gS}HxɣNj,M뿭ݺ T-Cl2t ]߃/V:A^NZpxr&뿩45)>T[zjW}KVP9ܺw/VsK%w6F^f0^-< Nu[K NCKejʌ˥5l{z|=Ҝ{w~Cy^">dҽvlE{Q7 j3̕p٤Z3t-?W-Utݙ L{qr?}Z>_`_2vR_oqDDʱ&YCO@go^>?V{qX;6.yώ|$Vh)*w`Ǟys5G1v.2_Wqs4811|_]?䀵yƞy'zה|Rv۱Q CCԵv'Sf)>%ݺ{5oѽfhwޚF^MPzq g#F.6䠁ckFxÎܰ>mSUziBD/E齲:tt4coD^ͮc>7cp_ [f3z; 'klϡ/wThZ/y0[oy=2 y%>lRw y_=߰ͯ́xY^>b%+8t w)~u *m.P: !W.?/q KĤ>mMqi; ݓ獽aI;v]"bޯc,8arǖߖyz5cMm_yMA9zcSWZރK NMR5c`b}i;8+Q|v>Svʎ/3Vڎ=7]/[[pG1̋rpMi{x87Jrq<&K!{ '6ǯ.8{>w׎3i㬅Vp@?;3%+q2SHw @J;zI~f8sg&싍1~Kz.s@]<\9juL-~S Ro3̔ h>S`g^U _Fs {f:G0V8kY,U 3A^k~fӒs6o:L x~j]qn1~[se%=|Ĉ͊'c?Oxߓb:-1i˕p'6 ͸-Tٯ-eы0W.ZiO,_;~ɾ^9oT3oKl5q./_DKdo]Hsd.M.xU/I{~0GG|3%B6 P:q l VЗL^X~)^^cQu.Q\nsϜCgaqE|p(>dxg VU|p=}|u@s^6=6=xTeϋ5^^WnyL0K"u39юo]#wY3pY 3JĂ\2=8N "p]XCr pvl8 vL vl8X v>Ύ-g_S{Oӯp&cNo.m7xg_2v;֭/y59L]Ǟ-aWVENDws/&rҷg\}>r' .6wc3O륷 JhB|'[{*?-ZU~™\D&Ox^w>-ʲf r5s%𭗟pq I0Aq#VJ0!LjojK=cZ0=ۤ/-o;轷K e+KتR~L ჿIjk,[Y+Jp#Y~sKX>M?׮t?8$Q@͸ܚ7/@boP38Nޗy أϥCSeǏ]2~eר% =u9i}xu̗ۯՅ9>ΰ^;V|>WW>Σ>r2'6+}] z{%n8'HT3q⟠}ljl^zGD,Rybz~Wf:Vqh%Vw]3#+qGo¾+S?(h(=a?c=D'~Ҁ{aKQ hgF= Wi0n(V'Ğ>gA셟jh'=D4zwlɜ( V[g`_8i8CObKr>o 1̊$e챫F]6]/G GS/}oN>J~}ޖns1cXa[2 Bto{\OXP#,c潦B's!LAlra͊6NT%CzOC6Kdvۉտ/C_}+ {y# %y[tDWolvܔ^A.^$͎QKM_e=Ԛ\c:^s"^7x#<ГX2$_:uO^8!g0` c 1}8-:g1rڜ&/k ^(*FC3|_8_?VG^*߷>Y8сc1yDZg܃ YN)>zB ã݇t%vX]DرQ:Ӱfk4>F-nzd8u_^*-'TlR%9EրYsr=vHqd_V;cBAS`w=3oy@&_(̛U+:~&U1G _w3ϼHo+_왷$u9=+zajּ)rH-wfCYO7֦z$ /">z8EU{I=LJ 2vg]c}E?_TIG.E:# w/b&T%~o_M_\CÀOF_2I$XPRf[O//i RAg>?I:W^^-=WQ[7yRbm{(1wvɬTUmoOe ߙO5ɲK{-Q+` |5>^ϳo_>~Ool+;X-MV?c0xnocMVygnܻy繯/[>bu\]#]svWMæc\)WY:~2AK19KߢUаڱΫ[3=xRI\=:1?\4=C72=]5_/X;tx6?{Y4>Z;k:Dq,*xã8o }qq~:g>x5` /:pgVr/ØLs>-|8@9O[ob.%b98NF5@|&9U8ٿ[1^Xʏ%\83o VyK;cϼkݞ/cb?A &^Y_D3p8:*zYu( o =K=y c҉m w(.|gBF %9dԺ3"[:<؂X*/ѿz ӉߺM-ND=k(b˯!y֦uT$bk3zI nt([,3xL={__R%&]W 3rR8;\+cr;y,VsfJǐ qȽWg?#0!)_+@[=1 WΛ=gG_Bb q ٠%I1#1T:Bj R|2l?rά0 0zq;_=wU8΢ghc-b q3o: ?o_ >ЙI.df1nِZ׼DJ 8={GXЙgwS}OSoJq̛ǚ^ftgsԌggֱw>~bkQϑK}Ǟyۗʜ akϾG}Fu#-Z+T9FG (»GQ&^Hy8}H'5'b_ͫJ [o%^*&3/s=,1'#ӸsKxjC*xV'۱o>< 3Q.D¼{X23h0@VtzHc[oq;r_?=]:X|v>g3ӻp7^7_0'(>'Alߤ=k1m;d hqH &b?--@'(Yu\}a97 ߎ_p.t[zIۜTV]{}9{BDZ;vyŒX]$HcϽcR1B<+Q>{ucɒGŪ&<|T}^^7!68WX>N;iO=z4?ښ JpN@Lԕ#MsX}8;_M78W]w=GQ< fAJ)c!SHXu<`ߜ>S{+܃ppc8;g+7vgLrpYp9+5N= r{>X1oE k&Ù7~5/Xؐr-)Jdߴ^׀:9*ݧ-= 9֘BcϼabAϩFiCO]wtz :jc^ӾĞyGr#] x.GgZoM\:}m!oY =Z޵ 8{ũ?j\s56:G4ʹK(JQ9wLq ZZC?+u)F{Քr|5cϼWQa_.F{лO>1`.O8dxuYq|8&ƜraU$M@vOۂ|m{̵R>ש:-NPz|zr& ~=GI1ܥUV/}b*8=i=7{3vn~XŸ3k(%%p; oߺx/37^|@fֽׅ{L7L|.yP-mR=ZZZs1mڬzI3~'ͮY^_Yo PK ~ 9ժd⛨Ǥz}V@_옏~LMhdަ|hP7;V~@]qz$~c_[q|`XO?NS|tYAJ?p v3G5'{Q z/*EI=\'o8#8Y#;\ٹd gG[p=->1&$-G<8|]-><> xTg"~g` 5μe`u5a9#jT^2owz.,ow/|0*yZexJ6v}05㵧$/9 Àyu:(=?3a0!H=Gwfs{ U_j7lϲQ6cfql}1 %+}Y` rD+׽06czxi-ϲ{%!)X).'x藵Óf4rF=% ڥC$R 0*箫mn_b89^NV2N[\ݯ|oь+?aF-[R%8|{q=` u{+?>;K~#๥?9.]4*m>"e>)p^-tKVhʎ^]ň;*&f\F^> .ܻ6u7W=RʒeϕgajaΦ,xw?m{pB^ N8wǯc&TvH9c8/Z07Ol`r Wc<.>Kq!?gI>NbIiT?L͕>&ESA npM8~!sNpeJ/3Bъ^ߊЃa8;W$\'amƀНsYw8~%G=% v5_K&h?RMhOI1}xrd_8mv`XAG-[%k).82V5 (@'LJ\]|N1^s+<Ǽ'V.Odʼ>> [1u#,ͺϱV}6>o^0`I|uXt.xaO8;i4|g_\37Vޙb,}>fw^ƧŽ'KuW:ߔ{3q2_[$7瞾C ]orz-?oU/QƠl~Y'|;U/X~Okc |;Y?qP %];ٯ1b?{0? ~ Ы8Kgw(!UۋQ''8$wS0Բ+zqD9)wܟ[|lRA\o8DZtЄηlp]W{*G[3p|L<7xgG/hf, :ʾ\}1H8ur)G_S u B xpw*t=8NA<39:ŇK;<]μ~Ar)'cN^R>+YɭyKT$ ;{}2eRGG|sϼe{O3oꀷw63=d xױy9!'} \ϼbf?.9vV Zkm  ^za{-^| c JUR=(׷\}DwJeZynpwej3՘|2tZ1\^nЬ8{gr_%_߾&_Ssz;s)@'~O/dkp0޽3W7 J/?aF=0MAϛA9b OkX7J^>^:;u*-a9Isa~ 8M_2A4\S/cwt1ljGocύbf"P,=Q[ϝ|^C9vY8=~zy"FU/1Х+'N8jBL7nIjUWž q>;+>]MW<a8; xQ|#b~/vV8Fi.up}2|t'Q1q2DL8^ItrTA/>n]+2؃ewNA1ʿ./et7YC 0(=@tM֘g;깟z>|,S }X\<'>ƮQ=3gr¾b X|-MPh:\Mv=Hpq\)in4z-3Juêg/G.sK@yI*hP)OF5zWcKkm>N2دL nԶSb$==%ee'xIHO{{=0*[ =y$W&K)߯}buF#z'c)t0@Q~T,b W3c԰9k.1z(4QƮ¨}m flq5niSPXThs(|4j;woc ybT} [b ;)Yf{FןL0.V8@ ~۱'/uܣg}8mΞK,_+w;OrR=<%y /nݱ>9t~|ςa3o{o=ܿu-e7_I~6me}]M˵3bX묷lpGR~lX?Wju^ǎ-<`:4O]}Oq߃s-+Ym؃_6wPy=}}mL ԩ{֛4x6v8y^,μE',Ҿ6[ot-ܝM]w}h Nug?3;k!%|gmkw޳B+Q0uVc0͟p'G1} >N<2pںfНq{5o qvo|,=0YoΠ%eibVx)=7$^2dYokE<8Ci37[u.gĥ3\=t !V=0^ag7 TVoQ;wrǞ /IbKW-G6^rًGy\=aQyOUs {f|G^>/^Z[qZ|BX|`ENLb:jUTggrڝǙ{zu;8N*Wng2p<һ;'~1Ebpy ү7O9WybDLOjr?QM܁c\oڙ/og gRla=7L-:-UXMt4 xƞys#?~͌QK1O[3o3$_/[` gD>ZK3oi kW? :'MUT?18j s,$yǗgn8w -A6!+oquݬ#36JWm_?uΞ9bXU<5co1x63Ƅ}Kt0N]KI;X}=zԀsK|Rw8/ 8xG*` 'TW|gPYWw7yt\$kW^w_B0\ѣrs<9nbua{νKSxM~{ A+8e!Vvxk%D C^ m/|b=wZ7R6kss說YUأJj:8<쓯_l@_W7\KYhO+_Sm`^^G׏ʵ=<b,|qtsҩs>w'[88O9K`/U]W-*~ǹng-CgVSˌ.-ܳd{0n莵{aN;u-[<pt!ۊ#:7S| or~V|}B}U|}WCS<-vq1G{gDϱ@YoOPY|p=tF}}~K>=zb&ǡWƳю=R(8eT{Nbϼo}@;Ğym p%O?x[b\Cm!5^ bmgd炃zlX_}'AB$XC{u?{MBN^gv}03oYls4XZ>>+)|cϼ%$P!]gdiᦾnKbj;x6܏WOmA*ם"D])cOA ?+lZC 6odvInUIi:[:{^${Y8cAl8o ڡ~y+txL鵶Uz J8ާĒ:Q 6Gx.?ً&_c=QʱoPjƞ>GJdOoWKJ$Z'N?DB +(muRJ̈́4%IFohPwhF\gl4x.Yڱ\ݛ&c_Q7X*QoFT|>w{X-1v-U7{?[} "룑K}_Yzxc-4`(nIzWsu0} Sq:ϖ="vl8k70h=VS r%6t|>`?t{=4uߧ9}Tיi@l8ҵoc Pq_ocϼM$ryסϥ{-K OVǛ%ZB-6]OAg#Hd;%=%R/L'xƞ8 ݷ͞_b_:-Wϕ~8wlS3}Ox_֧o(b/?ڏ 7]i]B2.fk12 czYo^Jg >gB&{\BoAi^5s)p|f-oNOVDNLԓ+bpj%b>kĖoߟgӋId3J-^~7{$X!yZYCzIqGyN>Lᷕy"0&Ԋ/߬- xuN|ƾMolo5yc <*c{_&YoefQ/ c?Îùܾ_9>ulQzM^נ"jgf ?ّ;og> :%ÃAOO$x{~|VO-ױ9qX ?ΔX /o+d\.=/'gzyIaž0U[ZrQdz(1q?)Gܼ@v=y3g`>zǨ:{}2 5@ԠX o;8rcחس-=6{-ԥ,xw΄:9c47?|,ch~;^sh5x⼮}ӎ}ɆnR+b{捽NY4?k Yoi1ok;ПlƞyK5cBg7Mƞy@;=6d%\%) w{ԊbLߌ QS'2pOtI0}2& t qjuB+o:y(Á/PLޫ f8c^-{'y4B`|~!T`)utx\5u92r̳wT;T IOt|fw_"ϷK:)a+)Wݖ_.pnX(('6\[L2w~%\K=!c_ߜ ꕱ?ً/cr/%elOcl+MPN7|:&r݃J&z)}6bg5hsﶀ~; 6;/cOdQl䪗H78mU/1 =<1A쾙2_/>` X-1rZ>:eϻ`B^fЇf~T|530ҀJo.E0JU}2 {0OxGe![zx ξ'O^=+ C+Px_>>-Ǻc~ѓ2ˆŽ=x@oA|;F~1;j/MԬg[K[Q8΄}[P7(gxql`8ǝ{w8󶷳^2iA;h fgř|Ϩ{}X# 8Au|bVxZ#R '/TlY^3$ҏuMA.aa=D7Oߝ|2yK"_LsSF>+=q>`D-xg9-AXt-*ܴO>{[Ч\Yi>g${MfݡG) Ѽg xgÛ/\` v?yg^Ň73z_TIDgZJ𷽽OdHbSۺ][( gt}Y~Ǚ=K5F-cXEݴ)3~o,V]K1@+BuHד{<7_׶1{?*cASGKdocXpgY䎡X;)[W> ˠݯ_r`w]fJ{ sQ%ЧЊ%WϱyùzX )b-M;!6!Kwp܂:OзU?ph9`Z8ٔ {J0^Éٰ{uEsZ|}@!o+v oON}kf$H{Tq^;֋Q 0TΊ2ގ:Їafa~gZ[8Λ%5 8a~&c p)<`o]^|Nc8x@}t8mBqS,?Z>>xG=z/IOJ_r7h>DZzw'3o{CP3]T9f{` Vznz;ߴqFP;vdZ8dQ^> ? Hթ}ss~ֿIoDܼys|=\DbO>r\s6J0ރ%c=v`Z~EnrX'Gxdj+&B`7EsEo<j.f$w3T%#`"sV=བ8sae c#<l Qe8b_r~bs{|Ԟ)S=y^bX987 _cS~~6uk$b9bP˴YDfag#pKz7SE{I2H;˚d؝j{Udgu=/i{6RȽZoЈKv~t\ʉ5?4;bϼ9by'PGLx1۾Д0 ;6La3o"97 yWoμ*z{Lszcϼ1،M(uI>N_^5.R4C˸,Y&P{5YC<&O!!y-s1ӧ=9Bse˄جo+WB;q/KغD֕a5Mզ巸xBpol+Wo7[j߳ )cjK;MZښ_{sZsC1vyhĒo='yu׳P؄nx^JĦK-l ޓYOxA=8Kd˿ؽ$>ހiS{}a{޻bpY;vއgN׿`5˿>zU$MQ[iݪ^0ּ%λW~tRTduQ%YQ:2Wghܥ(} #ãҘ>8ޫ'CBOg͹[ѱ|+>L{gȁw x8I F'&f/ȋ#٥|-^|}m}^|]~|w|~#![ p=ZXBo%mJcsp7BUR%g8;b6q|8#-g' L-6{?,mtͫd_qʁbTZ^%#n~mOObWr=5o!դ8>]$芕LG bb⋿C?NsuMg'qV1Էm]^(ӐxKRxnXYk+μBm0?CU掩}y__N;Oح3oi(հEN?3>[z\?޳4񷕟pa(h9iؼV~Tsy <}RK8?J4Bwg\Ͻ;gЩ(4;+*fz(;|_%`T{8Y~|CM$D;Lw2\9-lE9·_}"u{sbwsGn)ƞ|2 cs?1~.vOd16;֡!yem c/IkdI2iҟ[{I{>\oK;YZ7^gE^{NOI70v +v?wHWZ'S/I+UoK~yjKvVՙj4ta_t~坛sozw^j-j2`YcJН^j;[溈χ<''7;VIՉP8 xTlaA/>Ρz->Nz8j$}O->wck޶y0q%[ᷕ?ξ't̹t,I;ɦ4챇o%S䐎R{'Vt08uOqrc>{?ggph^}'XAs-.cK~ wI85@M^{{8;kEp ~b<8&|=8Cz;5LIԝ[ܾ0vc>i}SqUXQ[bzK-$\~Yo7kM_xYoKu C1!qpS*} vs<'j;N̳O.>0b$b2bVT0j?~,abjqt~o5ĝ=IƖNf.UnX_[\])ؓ,(j?ƺDȏ5;:|1v/?5qZu-wٻ=\Av翦9ƕRΫ4^jOW{4{%gvtpU"AcΝj==(~?W+2bһ)Kc([*ڼ2^c76JSz;2 ۹\[(c'{;%U޽gWc>^ݸvBkG/hͬb \ұzç^ {|V(lswԱVQ8s:iPz{ͣΔ{3gb2;U?B9" |ug}''p B~éOf=)^}xF-.4oP/Ihq8/>$[kq8b'l83Wb=(>N)/>:.gfIZ,/ys\|'F (z:Z8θFW/Y8y+ /aaM_{M \/o,Cg_Bq:Q%]7Ik?id~Q8COfܪO}8HȠ28NС)u7NkW+w ib-F緄yKȬd#cϼ%yevr޷.Sڼ=|2|ϼYbSO8uٹc_z 7k}?=:?y,.p"z!EXdG&D =ÿ8z<ŚJFn Co-^{JO'\$y.xu9MW[$Ē7Raˠ^=8v8Op[o;vɕ/.c|LTo-ݗ5c/=٩LOƞ|Ҙ7Ş|r'ٚ{@v9{`D7;=N_9s`Yǻ0 PobO,maN(Ylm_N?op>erZp: z;"?䌍ҫ{/O>d[K2X o쪚c{=fWKHv*8W}S7;zɔ㽀 uH~g{O-7tHSvb< Vqg'Z{,=ZR6cm#{xT5`oKh#)x0*>m h;;-'r$ٱ3b0yaÌ)sSVࣧ˂sGa>,/祿Sa3ܽp=8ξ'!o| gرI Ӱ28F۬3>8Nْtk>ɳw{Mh$}~[d }VSرĦ .luϼC9جٱgA{|k[MݱOavUja[}>R6X=ec왷=v왷0]j_μЁ60̛|voRϼLBmٵV|gKP3b[%|:DkjT%p Z'ؽ}tS|7^9:=iFᱭpI;;jfFؓho|8WqlIOO Wc} Rd^h)fƞzqN_)%Ǜ, x/Y}P(~:[O-髃lJ70^ ܢF^Aא{xMcVvw*?}*<{ɬ`o'c(M9xo܍NỎ}R.u~.Fk!Wܳʱʗ<"Sb2VbwV%HcvtĪ?P7o~~c8{7ܻ9oKzw'ŀ?Ez_ޒ< p:oƮۼc ո0O >䩳8):g wlys[xB<#?ޱo'yf \.gŃ,dH`88N+eX7\2[on\"mh{vaoƺr]zbboSJ*-g?鍍ѺfoKz?rte&Ƴb/٣[ [4sq&bQHSO=$f]5U{][3i,Cϼk`杌 ~[Օ^ 3oIJrnzl>oc_;w)~8I^o'Ldx'M7)wO#Fy-[XYP}#I-'(>Σy=V%ryۃ%nE-_,O/c_Q0ؓdb?É=yI }wX[P՟:≕!]a6"3=ޛr>Ժc| bi5kމr؃,<j,?;`T?@[,LYNM̒=Ɛp76B\s[nyg(qo߈4[JM=o_/=Xwݙ'v(M3ў[819Jf)1P9~~ӯL86>od|0oxYI b}^:O*kh\Ù7/{{cOyX_O۪^ZwǞy;?PF ƹZa80>&K=qycgezos\|l~PP? f1}z^ε \#ԥ|>K p {ckgYo#oFecֱ:ug׶j|mW{pr*_JG+ϵp;?y?9e-LFȆTGzCy kEG/SGsLĦh2`>Z?1Oxr#'晷E3}HS?ߝ,^"kl~o;nlXILxs'ޝd{mRffo_]ޯO3K g7oSXC:>5Qw왷^qcϼ휮*)=Ecϼe![:WCq/pb;}^>ΏR!?Kh=:3o{_M̹ln u Mybn= c=M^>N>bojY펳t ;i)-[1q+{cKugЈe{j[< /d}jwŧ/Ha}}/hrO_P%I,a^ƻwNN1Gի9`oCN-)^ڰť8wJ՟{֛}CzmNm#h1,k [Ox(clKxc[o>a[7'}bI[ҟ!;` WfpޥRc=9wp%;C<6J} Gpwl|N_RƖw2Qg_Rae:8cD@nh^}._-N8)LVk ]vuBH?^>^/0A?& ۪z~z+) C,a{%jvPo7_qV4}ħV 9mq\~8Yj|2{sGO^R=pɽ책 heLm c cwݱU|nmw\o'yߔ->ΞzÉ;puL,;pE3z{lqҜ^Cyե]_ Cjt0Xݐrk7{e{-Kfiӎɺh4C- Ͳt-{-عgo'_왷9oZv왷!KuԎ=z qj@[}Ao1{:Jij u2MigT|gg,;+kWޫxhZoY~{ {7ޫӌh}\JUR@ҟl'iߞzK8Kg폲/h^4QjS;PG:{g-WU$dz;ohrK-o?AƦSo} ڶI-VJ; h1&77s\8yԾI6:zAeG?x+wրϡ>w' $)hܥmgrxT x7iiK={{틁s88fp~jWyq7p$>=#M/hryJ3b3&&YX=Z-6{!pڥ]gd<`g K]wfOpJ'Jv-q2NS[S>/g8GG,ICg\%y@l7̇O~pl2kj\%o+O,7ܻ*>iYXI ޯ%9?jeYy7Fp|ד XRܞL c{ݶ,>7[Ko{%o:ǯ# ~' .,_b?)ݾut ǘ ރ}/Yc>a4y0k֋4x?Nvy٢[u)RԾ3<˱dnF3k_iV_otuզPg=V.yIOqrdr;KQU/Z"G1${lgEr{8'6Hq) Ё{o!:s~D.>rv\/ͼǞyy|zGl"ZO@].KT>;_kkۂv-)kv N 6 qz$g2Y=J8NH C8U~uϥ u\9.>^_q o&g{'SGĞ7wWm^p7+sxĦF9e?K]o߬{㏓hn&/|Y]a tbudC|bӅU]ԕ'[lX<% ԱfC-Hfk3osy8Rpmd#}e$ Kw`_q~8W3Z]ov'bb/n\oWg@nZ}|K/R5ShYoF~vWnyoSڣc|SSzz>54Vl zكYR 3\.~Ѣmd,|3oM#d[ߣvFǫOȻ9x'Lpso_D7͜^GO!}he'l8z{c>=%Ċz*^8::ҡoO_E+Z,Vz+5( G;ƣ/ƐjCqV Bn:sr &{% yNqL]k5d}ŏ.KQ&ETZ1ص7Yk_ysSWz=y%QZ-q = 2ph<-Kg*7 Pqt P_v/ylojd1ďŽ[d^0cz@ʬdciJqbij$x->N;X] 82 s㭺K0R|Ӌ2g[q=0[GvgwyXi^7k:4!cϼeqOkHq4a6@0h$Hq,o4#!ROlumA7EsڬBl1Y3gToq)ڿG_ZMLa?7-_)t?sA1BZH0^Vz;Wu|KV&4n\NԊmP% uџ[%*&/Y5])WU_3 ^ǃ4boMO_ gӰZ~K&pcC{jG7tZt) |iƐZ}*-OR/Q9Օ/ɦf\]OIwiG? xn@sk@?̨k`>!Y闌:;Gן!SYOݩUԹbKyX|ҢCiKk~ҮGE|V,"\(~L Ia.]LMɤ6?zA]/^#w_V3J,>ξQMޏ{y{u:jvVlMgjL^X|bψ%~[\ЂBpX,[,_.ANn=vSqgw8x@*itn07YAui"X*,}HנɅQ XZ+Ws+4X]DU,`3H@lT~tyiTf 5J㙚lu.)>h&י7 dμٔ΍W3]g{f:22|aty[,zZ-μ%zI'HיC/U[Vי7N 3:Sr=- iy) 8YxQj P7GxYSIa {zGV>/T\ĈaoɗjC5 ){jd+LH_D({lb_VɾԮRKRպ~RZ%dJ6_ғb4MRV{@r¼Ғ^'r\qϛTm*G|_}wJvާ&\˫UV*/=߯1>8Y S=i>f_oRj)0V;'{>|b&!7ҷ^BdSNܻ7]_Ch ߙTLMC6{w/0>ߙo=>+y@\$ÝgSn}yWiG, Qm>{7M|''Y!t->̴Q3fT<*_K%z%iߑ%'Gw\%Z|䖀n6joq9m>c㭺i;#noq$ 0c/Pqb!x>o:.>NApj}7M x?S>7MIēEύ7ט;k5]뷨דۏJ{RZ~VbuuU:~dv=\9X8ps)&']Wb_cNƩOԫއ'<-8BڴiP+6^;V'fZ'(_#ijP]p' ص4TD^5-^2.4~cmԼq0Ԯ_l ᮓC-d6μ#Y瓑k[Z $,ly[0 {l.'^'myۇCl֠9d|bϼ=jxl'[喝;gg\K'{K|^fmKD^3}v[Vϼvӝߚ.`TV%&>u飏Yz -ڻ^ ͔j{ Grz ~[ ynZ4%(Kx/?MK=9cn({3={=)y )+ E&͗[;:^G\yMm{=%āX'a/}2/ }2F]t:[J _l}q FdzI R#5:lU=$0T>w=-`Ge<#>sh| `O$Mb;:.ǯ;aU/٭oPn=}/IMI_C?@{lά ߑ/ ϝW捭>aqIŰGFcتs9 fn_ɞ5}fc(~@T69NoF_XKRQ1ˮjWXgo^gdӁ}Yi"-f}c{/3qH 7bpvYXqb!x+G:G6iЛ]ي7Oa e9Aq`vV|ki]dV|K7{h,c BUi'Ҋp}ӬpK;uuqbNQX**- q3o{YQTu^qV8>(/Cl0_][>WNQ}KRzu\$-F$5f׵~ZubU:'(%.^~P?h~a/μxxȢpӔ)I(4vKB.*wZb ])HYo@RGVǙuB8m~cKznbf=6[_Ws+/I^^z։Knb/h%^p^Q|n:m>ޓO7B?{ۧJ(בEgN[7ɟlCutooOlb鹋uoDcTV]'^ػ޸i<,Ku_1}^Ku<8&)wuom/ǹGH|{آs]9 vh{ӯ%;Ы^PR_aK*"x?YвaI!{[~C]le#tZmЋ#dzIx3@"=Թ}kۄ۫u:{bSeVMw ^"N|]RbK[*(x-^86g0m!_w9S!K;f¥A =VY~-f_d/b;\AgY$t)]MciC L:(⿙>XE¹FkNw>|=xnɝܳ]K3oA~v3o_-lzKP%kBkMbg'=Mm]ϼiҠΕpV[J*]ۋʀg.U$2o6+sfm7 d[ol)di{N#m8[oۊoCa sA{dm{}EzK_Ǜ!]m.Jumi9^Gz<{_ !]2E9lc}:}OԜk}K8ƛ+8Jށ{(HvF8}x^؝ Rk<8{uՔ?Yt:>O~=oݟtߔM>wo1{+wik>Ƽz6 mZd:ܳP߶3~lj$ĀclYTdO[y͚hS%g3=[lK]3.YCPT=X=[rg3iӻ'7.OxtG:ugpp:xđ3BHc:x2w=-4[׳AkpJ[-Ǽ!ӊg`q8mu8-5bImcb9&zvxKtRr=J,Pǥ{Z~J5"d7]cN2ޟ|M+@Sg>F='Su-_/ ,ᅞXi3o{{C >mtb5[Z{;r.[M9M!g{YYo {l7mW (?a ϕzl᦯r_3KX{ٰА3oQ%G 5L^%mo]W"$-MC{l1e_y֟KJ.;W\K~b"0__0i%Z{2V^нt+5U>cڇzۡ`c,X+=yź>oo2.ɥ|c}cOP<+,Ncז\W_.Λz<%Ex;os*YWcy;:x7,vԎI{kzbͽ-9}̱|zv0߱Nn-Վ}Խ|hW{b{fZ! }@1߱ShW|\_"j@L}Ns=g7]u\v;w3# 6xU;ג󹱿V'uAUxBS u3{[_pbbfw>oh^~﵎1P } pd|}]{Sox/y5;go;[_̝8uR|ho3c5^O>d;Sg?|} 0XONI X}޸~c50u"u?/џ/{vs|^-^pSKӰcמkvbGZץvA֯!;=_K>{suqмT%2kYݩx,z;uź>O>LS~i3֒㴽"vjx,^s.z屴cs}yžl4쾿z=W[a8^N&үwqVokb3im~so׳8o;RǻFpS2z=ιѨ޹ȥݱΕ~c?x᜷O>x=trKF9z;sZM9 -6?8 ]iXġc{M} 3<v~v=933" {oz>ٱ~Zr2[f^^;=y;}O]bg*&;󍝷O䣗r煏Ċ 3ˆĪǶc?ʣS۱s'u휚R_Ruwg\ze~toy4bv4bگ?h2;R֘_o֍GXmVnn;[j_+bm]qj32?viEoe 5ρV?7mM6q~:k[>ľ齞w _c9kFxc}4x~yx3?˷1M}ÜOw;yk#b}ʘJ?cmY >ki}[W#g חz{z cur =G\_ zxOO%ȼu<3ח#q@>/Q+wBbuR{S:Cƾh(\K\_"߷6b~x0]<'W\wS9>mb QդcMk[6u VٟpVWV:9B&M᝷koi y숮^^?'cOۉySX~igr~t -}cgA(V(ߖ~s ;SNOq GXWVL^Wacח<4[Ik{^L_93m sDd];/6\W:/9V8C{0Oƺ^ygg~Ab9/:60o/9x/>BG ;4}x:y }p}Ic Kos}IQoYZ[V}x)kV</9yzbM<q/ع*K͔{5U'Wb]û|Vj<@}%KE8ptݱ]7<;>j|[u2ٻlN6SyN [+B0ָǙķu_5Yiz8={{N * -6~ycX6}  ݫ&Di3^f{ߦaVA}V]u~7dNvCDU[>b}cWYKy;zXط@C[u_:3~Fog|/Ka󺋼=vcj[t7֞X:Tߗl%IrKZwNcgZx=qx]?k4:n3GQãʇ~cpAϯjbZ禣5xzk;ǾKta5 ȥ?xgS˹+zz߼EVyjCL1\}IY%}iU:/9%2yam5y@/R曮/)Ҭl9K]5 jKV[9Ϛy@aO,P3?bW~/:y>Kc]w#8oɱ~椏!Yfsg3-E؞'.\w|˔l8=wFygm'/s6"/z:r^<Ӟ؁o/q` %XKUo}pR8oj`; yؚd2j!vy>؂\??{ 󒮋lL<`?(dmXy=gKmuN=Pg:;4ӏ!3%,j#c/]`]_RKn'+{4y 0%':(]z?akq . >vlG)Dsbo[=Ƃ<球o?eJcUOqvy} mZuǾ:\ZǺA+K޳㷝3~Ǿ֦N[ZR{ǫU}+r}vL+=V:urwvbw;Ay;{s홸͎\_b!7חDrxb}Wǿzއw zZm{u=|믽e)j'!#4Z~|rzޖ1Lc6N??VQylf(^Y9E>^c[FKthgq4cgY}`\O^7>œq@+|p,sǑu><x=-Sq^#"c79I߱pWE y{O`.F)[ևQyAmeM~gyK N6ۺ^d8boXKFy7j1o&T__Vu}l53ozd6蠇ht}^=qڑQAIO㨮gU 9 ~gx=5Qv1*gd>{)73K^ %g@ z}=& Y7;?g麽1NvӞGGOە}ɀن Dz}P3K?z8Zj5gjɽQ~}tp}?y70':sy,IZx {P Js>?|{=GOX&jV,כy3b;<Rq]lP:#89]x5<ks1Cp]o ܴ dg'&vV'9 ۗj8/9Rz1=ɼ+ol N9U>wb}kS1^7mJP.̉yNÿ]) o`jXv#/W_=49d:%}1o{5=/eq.zoί.vsZf uRUQ1\a?cKJI[u2G~߷eC/5i/.cy/iN-rKN5pR_/1X^2͍[%{[{| ķۂ^Lb;ц7W#xI{ֳe}^R[^Cb컟_ߑt]%2:Mς엟u؍{%{ygSD+g#x>`L#xI3퓟^R'9L7hdK=>t #x\y&K欬? tjG#[Kس`8 m%*sޅ\d/ra ^R:^%tQw *Xތ l/n&ܚ#mKYq trVF69߆ E;?^W|K:}0ϏT^W;%'}3xɴ$p9?^2+9}K׏Z\ t3x2Ucp^z?AQo3x^VSh}I|}a]K&T c}_Q_d෰ ^R{CKGc<h۟Rzp;߿sӂ.b=vzp/1g ^r7y yIഇ%m4Į5lKF_8N+;D yM :ɝD/N0(|;NN& ^x7O7sD2דYMgjϛZKZwb\Z|>oVj;6x֭/I DKى%%1цܱc \%OlwS%q=:+irTzBR+bcl_NZ0KJM d#N%<VۂT67xI{jdA:vg㼤-r%qqJ ^d8 ߋ%Uon_ôzek'nT/и3 %u_Klag_|O'%3GxD+?{5y@aK xIgt^"jZ}U[\PמbPtJu*MfObΰnQLNF?lw6%r~jKtUzR._=N_d'B݊/c [(K쳗IeN&m}\dh%>Gc}~s<>5s@\巰J=6xɬ XX%xB8!bCR\ZNq^Қ6L/i_=W/QS#KV@rׂ^R9^%S@%/Z;Iu2xɜ /<~/ƧSv/ЃJ*W3ϻWaiwddd)H%}7/Yt+&b%defm͉ _Ƽ!|KHkkub- Epq^_} S~dRp۾jQl ^2y1;c?^ ^b9{#Dk=urOR523_' 9/9z~h^53Go ^2')W?߷ /#oRV$xNQ%V0 '6t2qi9N򨽮[76xJ{/ЉPA=/i/so@aiEX% %QU ,xI;: ^2bvo/)gy~3'o ^"؃m~[WWt F5[ڭ\YБ NKvIJKE4xK%9쟳|xhjl%S;u(i C1W%'SXhV/)^doLXCxLǞy1y~p]cM~9Mo=nsm\Z|^y>^BmRdjOuTu^!>g=xISK ^oou;Xp?^WSřtW ^9da+|߂LIMgj ^W9,cA"F A3è󒣩AΠϤQbI*ܩ}yɨ485bGrK;` CKζߖVr^b2@~L u|&w<PZfh;nN+ǣsLX%uN^25%^t},xָ%b "?XC %[@9/Ewp?iKv~ U%A=zO߬%y:X'tpuRxtKbwgK~KZho-[c%?ł5Wsi ^4*e]vbcޒΦ~Xv%6sXՓNa'%k&-NVhQߊ],sv'nY%? q$irewb/h&^jb̺ J'6rI~+{ wl𒑼Nt5A%#ebK%}X "xIϚ_ ^u[k4^TkTo/mr-v> ^-\wz-LzK:/aE1 ^2zҭL5)F_}By zbHI[ z\K[ T/Мc%R݃zp ^ғ7KcoѤ6Ub#ÞV9/ՠ1%]KKP*%v(s[QQng䰊3Kς(jǣC0/ %F%cVPcK4g;ga +xIWրHG.m/FRu0Mҙ2| b%YPKuuǂ ^Je,lW:8~+xɨv*KmN $Nmb3C+xujYx`3y//djcl'k ^bF֨XKV@5.z𒡌ݏ%{~=ڃ弤6!#{ndQMWW۸0V&bur1\@'y7[K\,cF弤Ǧ`~ [Kk oRkyp^R}wr^RFK8{SJpWWP0қ]-u_lqV/IK󒝛 tK{nqXSبZ[K*rGwyɾ -% kS{cCgR=hc<鏎}EKOv:kw-u(u\z/gIMcd26|0jzAVu^GZSh V^4Ti9%-xIXϻ{ψ ^rpKdo34%Ur[Yg1brg?53ގXnfvTIq.~nxbio'b}ˬ դu߱o <5;F~ u \رNM6%n{b]7FŎu^"8X;"xB/rzIԷ l$7Q\2~(K&8x;=-·7^}xvpNJC%wFtz&8 -n6y^|X V%S0%{oOVQTpN*}Y=vݖtЫs= ^)Z~;ׇ%{k"xJgԆ^\wkuKUMkec}җCmyue?Ǿm2Ϫݱ>oo۫bǶxY^)Rc}I0,%b ;筦o_䒑%3]_LjTcG/) %|\uQ(K'/W}@/94=s^c%>ѿ[~9/)|SaK {}P~T0oKz=esj+.;їv% \kxUV/QرgeuR7>+࿧vb]w^P֙J!x BO?K|j9/^N~oht~=b^>&n/8>{8i39/9B^"8/9q/"%%,%JY]T̝^]oݬ!'MxyK3(ox,jSzXXĚǎ}s^2ğ ׭K{&?E[m\ g§ V PٱKZO-%߷;6o|Q7/T9n_k[}8] {7ImOln{pKdi#ͪԆ;6xpc^;>/52&h/Kz:xIFK;Z.XwjY+T߱K ߈sד5 $`-Ak/1U2:%by(%"xtr%\TzΒuRu\xLz6&}SK)D}N*K8oK,0dm.B%{AmWmlj}s^56ޱcA94ƾ7gԗXwu2d6x=ggqؚz9fWwTgK.9- ns_nwlpk:JnfSwOTMaY9nXxwźo%1^!xQ7%7}}ﻬ9OlЯgsi0{1Or08Y2/i)=s^rZ %1y7tbUYG ^/ gK*j^u^?^š"sç̎ޒW;ԃB;C+AgKH=')hvk/a/NPЯ)ļ9/9:kw Ju^tyκwކ,Q<8/Ǘ/Pcw%ҴZW#VRSw`rJ^doKD>Ԝԟ69/9^vt-xIU;`K:xjqryԩwF] ^|~c?oX7sQ/uR%1<=8_^#5/SBЗc*dzp.j'Ku|+&r:/Y#ḟ%?73D'[a38"zޥ/ZK[0%+]l?a'6𔱋ߖVIdFJPzW3\f~>Ө[:d,δڨ%ªI7xD>?|J}Is^2+swc L9/A̹{XJ}^2Eኾr;y =Ix|O -x,r {DK]ԗ/5wۿԫ%y+{k%3Z>ؘߴ0xa)/ryɤ ۃ$u{t d#W;drrX!"/1h_"r3*=Hof~q ƻ3VcdždҋWyI%~؟fq1zZӓ#SEO2}:/i+ź'%W[mZ;e tbԤ7wߝD`MDݼ/ƞ{K䷱_ϗ ^`zoJ֧/):ҺsdX%/wӣ~&TBϐ*tT#͒X:%}Lhʾrȏ{)o c%jϬQKeu^&{}c? ~76^|z%#6xި;٬B7s#K5ufkxUߏFΙb[_4^ߗTo ^YuxbFmG^5d^UݱS1|~cq?fExA֝{{>%qóFS&dž OԎ ?ZX k_$%˨軾cGhR硇NA2u%Ѳ6^W#З6ϻd*y™oS:ٝ0}MڱQ݁~;/9B X#ԗ,wtJ.ם-H8wDw^"E*yޱ>oko*=>okҌ\Wl;7)w;ysԁ}Swl .8:ڹZb oKRr:DS/DwNq/jdx_W=\ ^RY?o(r0bkx00dk ^Pu+z0뎝fםz*;q]ߗsĶ%5i;z-wM[Uw ~&tKlE+eYzu%&a}^f5F\'еu%u#cwĆoh]ߨE.qb-<Y]o7KjҤFgyVw^2PdZ&u+Ƽ0xIQr.#Xy }Kv MЇz;*N5+=xI/{9ϻkM#z]u=T^ g_y"YcV&ܱu{UKs+%җSߝt]ϻK\'?~np.bj+%u[8cx-KsEN0&1436i jUƆ:)Jsr4/x/; c7󎵖b[=s^rzN2dG4Ws.Kj`7^7%d|e_i =ܜ7%d'[Og(Kǃg#xɪ UM1o\wl{Ո>Fߋ\aXmadVWJdw^Sh/)߷4Nd K@m=nZTw:am8/9Yw;o2ϸŹXK5L#xUYc=^"𯶧<-5ӼgKN(fҳd»^كOdI"^k'(W:ub}jwEt:n^bRtTeζ=T1Ì%%IvN'6xIjo !c~zȳF|ro ^q!KRmByKk}8ȽF/љ+X^~'VJN7K҃T^,xIzEi|~OKrzkѿEZ7sKziYvyi"g/C-8K5AMh %*ʺ632^[iwp^"ֳg67| 3{mw(xIz0%KN#N"r>= ^R'k2?{aSr"~[KFJ%|q w/З Q6 N0/1w8/ڦ1xwmy-%A;GzX% 0-b@>#x 5zK~, x]ξF1 b9 ^2&{OatKkӟ/4:E`Ć~[3wsx~^yu*֯76xͣnn7}Zel~;V`l<ة%>bvզc?UxqQZc赗fu^N#aaW%رa/?g^29$%'fօz#ߙK~/xl󒽦jwyI_xlo(s2yl!*<˟MXk5f/X#6: H;ϻ':Da5~>{O`;y4ẫ"Kt[ =gKü9/OdE}Myz&ccEwyvc B=LM%{ޕ>{MK-U9` Fd'i{d~{}/?m=^H K%ߎ։ 5aFqr{N%XLo{0X:n*w9̕˅OlKzLx:/{5!%ɳs|}S[oo%f۷Ӟ[1s!WYȉ]˚|T)GLX>-xIM}1MzT7߷[+1ԑ[28=lYô?y!J%}N۠tԱgy#'eIcxv4B-~zD[b6oKdM%g#=}9/9_=ryf)ToV<#hW ?C77:Ǟ= + >yIWv<-t^v¼ z|׍uVԛN%m T|7 ˠ 0KЃUk44f ༤M~x18/i:sol1 pJalfnKŸso伤z}5B ^R/c޳%+ ,4>gM%xW%kȧ/םzelK^[c~7vD&J+_?o#bh@ߨ%Ž[;yڵ:/Y+tmݗ cp^]ϻAכV}i]kgRWw(赵cx؊__`F>)>c7tp92&g>, "-|CjXヘ:/ٟy rOic8n@Z|s' 3 Iz:H:/@'-ZUz΂S2 7%By?Qyõ|/yɟyw[T%:;c=2#*ΛDX ^BM18/wQ{ dq^b~ -x*% }#K ް믌/b}t񬹴~{)JIr*XSmw]8/.̇· ו`6ɣqHΰh"7< %xhEGӋ;דm!Wu^2&ϰqdžL'5cç& Ղ/I[ycUXtq,̉˴0^׽jc>+|N%xIKvmї9H%xI ;󮱑%Ieݹ8/mY2nN+KZM=d~Tn2q^2[/l*M9ѯ#qVQdZ}wy`YKv.vmoX^v;/ٗH8ʡ4:}yecGTc1 {г>R;oraއwn@+,KaHNu^^^y1Fi z# ^Ro[Uo~7Wre-|&,wwKv=NK֯TQ#zv4 %_l#S~wO| 1'Qȥ.8Εۭ3ϩY!/Q%hIk_]K]oyw%Q% vlKN+z64xɺssKk~9^#]>d1uWkT-kĺo(>'gV%;!h 4D1:=N)yպOF:K87EJ쭤-:๥KN‹ow׬m~Vf(ǠqOKƺNa0DS3ub@u^b3 |yMb=s^bCٛ7=y{zy!=*9Ws2W=v7ͤFV(y/mq^b=:g3mKv.ĆT>I쿎9+VS*d՚z@PS?0 =L#]>W%{K4K˜o:R =C4xIvfE?^9ٯ0'2^٩Qӓ_VD\CT&T>bΩ=z/:/9Z˙p;?W3)}Yw^rn/S%Ү]{cTuWM'4y] Ir!R͆,+ kѷ%]8DJ3UL H5uZwjO읭KNCM>H/79̾ݷ?jĕݾ(Src:ޗb,h0yMĹ:/9KJ5+/KlQZ`dwb%Uh%ols㧐r*ѵݳ m$̢pϻw(` ^w_}W`C^2dc0 s^1|b-|+{>vdC5%cyPXuq^b5ܾWSK=s^rB漤SoBs^r !?_:s^2QpG}2k֜lFv^uAdU'@ 9/9Gmo7d}s=0x:w=u>X,wөwx`wB;=55l)c%[V9^`,e|s^NC;֛]9/Yq>%;A9dC ^T ^ҒnW-޷mKN3_ր@o:8z܇s-{X)m{ٕ}d>/atͷ'يغ_Xv1p]ieݢ~X}c ܇.4%Һgfb漤z~ǜvz&_T7=\3%/kaIbK161xxүXw=6TKN[wh%'N c{x1/Un ONK*ߎ#si%'J 9/)csyS{|y@odOs~g5epV\$ȿK}xpO \CX9/䛕HK=ߨǹ?"]/Նb/9'hw(麮/ѻwQd͍F$QXK&ƻjezk88Oܼ?Kf0 Vv%u>^RbcfJ>^iެ3ylŶVI?ڱ.%Z;Ћz/[{nMs{m/Ѷ!Z5M6z/_㟧ؽ,%g/GTRCjvy>x-YKylGKc=VׅگdgsR{M~}:^"4~X/9;9-i@ߎyQ%j=§AOލ{9M֢F3B" ^^";O?Ҧ`W%#W}ysu&/5מv/r^r<R߇!uuw~@[N0ԯ[5;䔿,x|%폸B_2kMgSq\UOs>/{GxueD5cdžJ+xI[-9nsd$M=ԗi ^Rsas \W-PVYK.Ӟ~v L:FTsdYϰΥ&u^R;yggeϙ܌i9/:aN,D=zҸ~vQ٣xE]M.h9/9^=K(ԡYKZ-3yg`+Zdc]JWkk2vEY*KSW{ZKJ\u^2o־5eì%vsA>Uz)V ,wp,0v޹Pu VX%%wDTo;y=dܽ{?b-^{{}iݯ8뼤vM㵎11\W,x޵o)#C л~A_7ܱWnVmFbVuwnc_,Ёu;M}~tWMcc&Ț`.Z)Nׅ9nQA\ָX?溎^E;()0b}XGu=];n-3la.ڛwE\Ys7>MG4<K(Zu^r>` C %u P~> >r"ƾ)8`;Vi$۱jkއwގ.d\S@jKݱ>o}0еW>nsJV1 \1ιFM6/?뜫$mX1cp>{p Ắ粤ɑvXseϢGw7 ֫4F[O>bh7I}g-NoTi!xJޥ_m`^zmiB_"xv$[Y O_/W9or jrb,j U/ʜwx"'&zb\x ;W.|~kI S:Ęz^ϳm3z.>;dZ@Oꤗps켤j:gK)d|Q%{դ=#uL}\` n3Pp]ϻwCJwy~Z>o޽5zJhq^w(KkJ{p%&ktVim\ %fN3{27"K쪧݃+ع0ޱ5P[;ov&ܱι뛱Y]cXIgMモq^re#VJpρs19/9z>0oKN38QgY7XfmKK"K;Zc w N`yr꼤>Jpw:޳7{Io[xvt ?E0꼤ei|Μᩝm[+}YKZQo&K}=>-wNz;ocWɭy[¼V'vו<>>GDƎ`ykڃ{K&0N;;KgLu>i}f̊ӡv빬jPu^_3mzfjx}˂/)fsϤ#6$K 뎍ݕ~x56;ֿo{FgK ǁ_.zܛ` /tl,NK; u^bc&MXﳲ.[n뼤gjכ%}c :ɘ:/9VMfy]$oo=QG ;5̱jz`r^i8O쵃Tuhɯ_mNu}ϜIbMys^|dO[{-q^ru1lwOS^;Y_%{ gyi6 etNÙĩadއl2's^2W00K ް^p^2xk g/q^2y|NSl'KxcJI_H:Y*#TE}X\S{%O|MoX=jgzK \~{4 yɼ6yɼgЗkѭB>^21kV+k k *:Ξ76tد޴]go䅨۱qsHK+& C%}}Aس!yɾѬc]Z[tǺ^*8nKNkF?n9.Xs)NۡXK6%Vκ8🴻6ak>ޱ3پM[s>m;yw{:qkus^2#17;u7_%sx\:/kTg_no,zɘt^7,s?GPxk|A8w$Z|ãf}us^r~FN?ԁ,5%gC%bs|<>cp^kKut"y_?c}k7t1z+x*}0N/Q:s>/-NDNz:/[vv|Հ3og%A{(>[W~7^I&ӼKzؗ<$J+Q~^Róuz,V^=l ZWW_!VAXsȽ|HUo{獺^;oLs,MVۢt2Y=KٟY,=<%'?^ d%;V~(m8mqOv Zp%-}{xI;Pvx\%(Y{Qp^Ҏ;ߋΛN[ۚgOYZk/}(#Fw ^yI_lTƾyw5FKz}dKF>Kv^#yUr//Ssd,DjĪX/b-x҉Э>8/ѯ~[ž!}9xIco0X%¼;xI{\5'$AkiJ{\8/90yߜ Mk|g5yww^r t9% zb[vؕ^Gs֑p[/QGukzwl+Qg)0W};~<;w<.29py@/:%zVkH 9t>㝷AW~@OxWEY<6ao7cg>Uu';YvhC}ۢAg C=9',=>+>K{>7t0<\_2үXtx%Sr_Nd[x]?羿urS$%5φyz[jʸD=IcpӤld f×jdžk7+xIw}r~kp*kVbz>[pI(ѿv9֚bw5gWiooVή+lzWMִ %pt4wq3]itԡ[ڙ_m@w|~=h'TT:^a'6|n6 )6?̼>Kz9ǭFO --w>i ޷o"П|7v^^7؎ukiLÃ/ۼ@|r4N!6y@Sh跸&3[F<$]7Gz-< 6>"a]Gc3r'Iu(؟}w\<ӑr8:mUzLr1';cxݳg ywᔊ1<9?N ɽc瓾Ks.(whruκ6kZMKM'}%KZ7óvQU/쇢}ct݊;6xIm|փh q%]KDKz1oKr_# ^cd%I/7u>/MF?KSM}qMjKo}wKr_I;>^Dsµ%K-#xIoc@Ol!ݏ^jQ??>^Z/I^~:>^2[wF`/?j%ҳ]xIZ[bC2>^zMKrOn~yIO~b-xIM\ 0%߀oG/w /}$q돳(ޥ{n) ^W9d^S35Kl4kF𒡽'!5x 3xD籤쌭V6x菭5?Yk8y '{*of&hi{"o/I5%y^ /a[q K*jO//wްG K&G!xIK>{'S/<g%ٗur.>^|F&=K$ ^O %g穥FlH|Ǯ;uy |g"=_e/i{@0%I=%ʼ8̥ER ^b #A32?}I%/}l/Ix",k}VW6~Fȥ/Ig ^c&=}MuN%O_R'Qy]+ȣ(ǻB+4Z?k%=1jC4{{%}$b͏ýK=u4׃tY{0gx rSԎϏyx[]hN%u?^rtݏ(5ޥ06޷*D>^yk?xgn5Sxm/Jcurғ}I[֞%9C_)6xRO+ ӗ-K$4ЗT2~9>|zf|vx/5ȣyMXKn>.'8_}*h%6_K3ug z㦺/q^ gVCM7/isq8K_},)%=G"Kg丈;>^ʅudT3߬o^b%׍ykr+݇HϽSۂ@ȧ/i麳1ӗp_>|S8?z԰?jI>}Iɖq}%3"zP%I&X|%J8ǿmQ#|7s9xlE>}IO~WKz}KzU/ѤUy%S՟DK$݇%'wZNS!/ĨO_Yx"$/qUއO_R?%3:t ;[2%ӿD>^(*~ Mۖ;|S9*%=zw%A n/KވF%MH !%x ԕ,%xyҙ/iUp2Lz8KQٳ)}Z>]Ф!s= ^2';8OϛtրL>hmRyZoy[Cb+1sF7zdHA ^2WK h\X_'&$)ӗ㴖b?}l|RlKFG-K sKƆdX#/53ņdd6K4rdK]/I ~d,/E͈~$yE8sAS[/YVXw%%si㏗`/l[yɽOdK ^,xRm_^58/ ^2{> ^2S_Oa%:EDɘ$_WT/0%?3B?^yi_^R[K2'PL)Ĥ/Y%e{A3%SpPc9g+~4=W_$6ClKt^WTeʾK]lu&nFK?} ދKN+3 ]'IFD&=lӗt֓}ʦ/6xI>/iLL7dl)ԳZ@ ^be$fKa4x$7%Cfz烗B=XcX5]^#x^S=l/I [TIKb?9/} |ς(KO_g%vsy^Qw4 ^2ZY?Tjӗa)d.WO_cPg~;y4Z0[Ƶ$xɯǕɣ,xOcW7\/1ϴt]<;R'fK/:͂Ƴ2PcKzlo >}I!/ic/Y^b`=xIq}ծKo"װ?Ƹ'xIG5>/hz?^uH|փdm,N}I%5u'xI|dQkdKjO^hKvƋz%{αoKXO~X5JSO6_'aB>>}`$KzmbC_ 9/irKnio } xI^/Am }}>O!/sA~^ 8LgOy^YxyO/)< ]96xt_K/7}^2StzeIM ^]imõ%6XĵzZ/i0:뗗Xe ߡG@~5%8 ՟RlywOOKRQ>^/u|}VNa~r}XS}Wx}${|~/{{>^3@xUL%oD u3TuUfV-ctKNHM2y\&V=%kc;yM^%aY;ߡO_^`lKZix`㻈9%ІUq֧/L/eO_2o[Kdu!=/rCᅴ>}Lf뼤*18/{Z7(]x~Vf_lf/oJm3M^t2G}%2Sl~)tܾZSVp%R]]Kw:`۱>oGqC/$0[}w Q?{lOjϛ T|>o6R ?jw[KaKTYK/MR}ּcsy^2CU F4pI̽>4FwlԿsD j[ٱ/1ú>{p:In$0^/'/Q2A؎'}d1ߔp~%lej~~g~;V}bdlK=uam@cӗ4|*>7%F1/121)\?} <}O;xu,^w΁yqގc 덹0/?;KJujA>Uq5~/4cdFޝ{ՉoKe/)i_2%r_p̅󒲔ކ=vfCX];9/) 5b>%}l1xI'?->+뛷T3Ka?5xIj cç5@jq{RSƎQV8 oōȱ>oKEaSc#3_'=bЗ\yD5ǖhr^?}I3IJjdž?׭~˹%`kK33Ky%7϶*|1|d26g oK垚W<|g/C۱K*k>wݏ7 ^LL:/9Tay9)%GJXX|;ݬ ^"8oY?̦~d3%:F[ϝvl|]ȻkE#b/0׈OE͔CRy[7qb5@vm>o{K 6SA}KN4[noDޞ{WN5x;9KjV<;/{.hwZ"i&VÿBe:`̅5xIZn% ~U/)m~Ά# L s꼤xt<KdXtevKJ쪛`ޜTrݒ >IF ^J~L\5xIComuݾ=n/);yIȻ5ZZZ0dOLlyD]cp^R%%Kuja>*x 51xA*GJ%` |cL֡,I }I绩)7%-zRW#1Ͽ %'w O_*~6<_g %Y"&1v|ylYi3z`b\4kvC?#yt3;Vg+ja. ?'R=V\wX?Tͱ_Bl%z%9/Yw]ݎ-%]w_2q;Z/8?3ޱ~#y7Z"Zm-Y^:/{ ^2-YPu%sy9co˺[/iK$L 87sDlwEnzYiY='3db17/\W2OmKM/;6t t麞wۜ8gPKM#Gge'hKVaOϭ76n9'VK: /ى-xJX;uyΠdQ}cyZEY]įjKޏ U&[K};ڨoKF ^Rn7F'WF),Gί];_go쌚 ˷ k|/֏߷s^;/9MEnڜ])dTᾺys^k)TxKpyOZ8Ss^ҿ7ﳃy ^R Q>g5>}VQ4?;^  9ϙ~1|>ԢFt|iuHQQ+eS=y%5k0*-Kʤ費1BtzH"N}iكyǶ_>.yIGWnm<8/ُ[nJ{% _aX.0R`𵜬h//ol"Oմ_%g3Ip܃%}$݇OT`)?^2 `L]|KS;Vu%)"\my}iK=(Ǩ'K"#]#8>;=xk?맒<)-oSk</Mu</YwBMYoNp.c]~))XU^)dorPRMs~ O@I=x{!V󒝛Vԅyi`So/y15{{Џ7D`a1x Gkw^4 gymXuom&c뿏hKhIی;bް:ux yaIsv6ϻ=i쉵*cC`:6N<8/Gd c ;- >y֗_q4fBo`k&U;K[ xTw^RT2:鼤H׬>x}%ys^Rѣ|T%KL[GME^2;E/`LRۃLN!K&lvFKlʖb(V>^S|:1F I Sl+ܕ,sSPR>?P;^$olݨ덝 F _5˼zȻ+~rhSyJND[ D{Kzm'*n,xIѿ>oK=*>oxnZWx}7z|p>?=})J߀a]ЗTu{G3WGy}wl􁶅w~d-03%sTډ8+c`^RT}3ouS@E0;Cr;CWޘSh̻Sh>{{zl~"eȘQoȍD7q3fZ2_G`+cއн?>oKyIJ:^Rtxy9g,띆|y뾆!d禽U{cj'"݇00$E _lwʳἤȠzc#V~;Kʰ^$o eME]]ö7޳%>m]%}[*s%]S ^ϝ؏uO)#bż:g/h%^>=KnK'w|"2H{֮}p3oIG򥅿OoŜl|s/Qow𒥓{켤U jKZ@4VԿž%u'xyskr~pL3c-}qS(V1g  Y:XϦ\kt^q}~-~~0o=vlO,YOA?/·fOa+-dSF^Y+q2GugbZ0bC7ۢ>k5+ ^'c=^i wW'I2#\>D %ucp^j:ZyᴨkKCl:ߜKМ:Kf9ٳ=Vw~=(cyJհKv2-ޢ>`/|'!nJyz|f|f\oHx}t_\9QGeԺkd:/ gt3GK#t D[)Tdy39B`]d6s|:zx)$Q1GMz0Kw)F2Gbw2ձ7Kn]t/9'}0Yٱ³ώuQM"YPho%Ckek:/9gbuCUT^|vfy ;%| +=rY.YZ<%7jzAodO0};zLȻ+N%% 6o.j>'Xϻk#3oƹ^R ^Rag!xIŹ3ڭ9&5eu3xIk/Nd=ߒ&7Y ug/9/d 3K݃3/F_uV ɖJg] ^\/x}IY8SSwW ki&Kx~;6K*X;}$Ky%^\,4 ^bŸ8/90a ?^kKX̻׀׵Xn]̛NAuq 廏؉-8Ǒ:Pe~ru(푎!6t =C.3Ŋ}Vٶp+Q@r=5ۍ,|~e<gi7]1l|7+{j-o" ^DP5葫%{g'`lw l'fy֧jCݭ^fh{lԴel؊l4xɺ 3vD,׊ZOu^r,ԡ٢& ^7껅u;Y*kV\=Q?t8b=BY𺞿L ȻOTC3Y·tzeÿnyJ;1xލ>{OnQ%O[KN~!%1ʳ{`Ӈ% oEA͐803핝RYKFdzO]q#Zbߵ=c~dQ6GWxG&XONYʺ|? rEާ+| *y:Yzۢ>s>`2'p^Z%}yFތnФJkĬDޝd?Q QSr +w/-6 9/=(w 59/9xg yws#z!ǜJc=-妚1|xcK{YXYA+ ^2Z!Sן9/9rGC9B_ԐCx~< %6l x>W=:W^ufELq8w_*bCp״XZQmKNsm)ܬ\w cC0kx+OaNw`h=㽋뼤Cz2qLu [k%'H5漤܍;NXl6`1%RA}𡟚5l|ZOwϛ%y._-y|t!J{Y2 $w> µdFm_ӵyTzP>w^wbKw/5}*,xXS:* ^Ob̴/ ^s?,x łƞg3gvk;T}TyM/ %2HԨ)cVւsq1|>kKDx~ur T3_ 9kYylȝ,^Q s 9nr{}2 /?*+Qy>+F"_k ",AXW>D;Uhnq:^6o3g]x#7]--,%;j 弤܎5h-W S~2YKz.jWw3o|hSh 0U{;)VNFoC0Yr^s@!keۧ96bdۓۈ&p.6;qMa`t򺞿Jo>p}߳}{Wk;<.S86ͻF-yt^r^Eb6%'u{9/9@q$;ɧy979"^KNLFܗ8/4zN֛.%g'>me[xg!dt{lK90:%6?K)>xs83V5¿dܜ- +xboa9{b-+ kwrkO,5pK<*GSab}ei*>{;ky4 z. ?0\zi)({(6z- NcC-|}Y[E1/~8noUdAFeWc3 5.^>l ?IO>P+ak󒽪*=ӰgyiKXo[%mGFk9/9+-\Kuj9c=^^||9/S+9]<=TZ?*b鱽zz9m~;vж;b 8ٱٜ9َ}H=)mtԺ8^YccS*blou;P!׫;;g s>;K)knQc[L:x_ب[!p!62Us Ӌ^S׍~FN,^os^ua CKoE8/UoK(m߱^ױwB`;f.}E3:6ga~>џA5T<;6t HųCܨq}qѷS_rF}w@ǿc=(kBdc9zT^B#(UqFXϻQqG%Uu=F*u%\\o{4z`gyi"~IӀZ i\׃j ^{OCEv^2qkwjyQ@1,jݗƼU2Eَrdg7V]Q3-9% gKf&dLn.NV rX?ޱ'"Z߱_s^F/;c}1^'V?9쓿-|zޭ':_E/P}㋍y9 ưu ^{켤+P5\qu^3ir MԨ723~W =KẮGF}=œy>>eW%ݪU_KNZG9/⢈mޱ-,kn:6}%K5IxvwoԢMU[iU%\\zw7{lQر5| Bf3ԭqW@-JMȝXekjλ; 92jByz-Xϻ/ɟ> |7є:gK5~[}*lj:/ٱ{;==NtwT_h{bկ{x6uǚ߇J/JP'/@y[o?it9^"xJ^^WSWKQmh䘭\y's:%;og Ka [jjyp^Hx-t wycYR˗A68~E}@c CK|JK3]wpߧw7K}%/Str 11~΄s ~*};|~_B ɇp^g>dMurD=<'k܇lpU۽j#quur3sQxj[okOo<7z{P~}XdN}aȸRֻ/ǯfpv;osuO*o  (=g_\/ᇷ;{el o,F?-}r=lzyX[6߱OKƾ7E~z^޼MΞf=oG#ư$JjW ~x'^r n{~x!2cbbcsl^r:MXyb'ro/9̥Λ9wLw-zsK_89ީ̉OVo5^vx~-0<^rHf6s~xr>KN|P9}ߺƊKόZ~xyGc_/y8%^@;?LAq~/ynPc|s1~xɁS%gUU΅z~xӞ3v=kTkeZrxc⣌~x#iXx'3V%ĢxLKFc>Kyx#k7'Vy&}m?;ntۘ~uwކ[ r>ygD7ݱpڅMy7߀Vp}Dk"~/y&󋅽}?L8|<< ~ws͚FBzq}\0y3-M̾ye-z^o]z:<RlWw=Ac>/+]w|l=MkIAx?^be=bgta⿱~)c~1;Dk>߱-j@FIzӚ(Scg]x!+߷ ח| /GևΏ`!/YFywz]{V~7-qF]Ũᄂr-9k5gɵxxjK}yIgzK5=.:yݗmnڱ//4 Qy:x]{ #xI5Vr }wxz:/f-xI.}-ww[qt^b29JMp^b),rlU$M=wެ^:9/=9/n/}m%yk?;oId[+-Wy@b _Kt{|*xϜLip^Ǔzc+#Iq^㍷fNyM޳7jiZm//uGY4j:Km軟,<89xp^ϴ2%S[-;KϞ9ΝE*u/}񷽼d@9/i|~OO,0aoP'c%6&}!=̝ =3Ƶwy@{#3/Y?f,]W_k!;s={%V'ckciֵWy;ok&@XMK\c}|6:<)/cn$1W=c_^/iKK_M%33Y:Zfd27ٱ;3A>=e Z ^3sLsL,wIQ,%_ Kҳ~d8[">p0kw ƾb}5kQZ=Fь]u}֗+k戍鼤3N2یy֩KH{ þd:/ѡf9t^bpx~11j;t&Ku3O*{|_;يb3sNؗjd $}X#%"̳+X%}ROP tA3xI^CK?:/Y³A ^IΫXחEI{VVG5E/hdvj;>/6%/AO[\e-q^nt^u٧bǺN籲IytK֠Kt&v%:Sdby yґQ 9t^VIO%j%u5~AK*I_9wެ1ԉi:/ё4pyP4o:/- Km\KXҭ4?I7X kk˚1hcW~7 IPS<$ױ2V @X_'KK ܾe{%&=ձr= ^ܩFa/׭K4Ƃ&r:/4&0۝zX%sG!x$](D%r gTI3]Pf-r= ^2\bd zuW~طnquKx=Zb+]cR%#Fo+/c滞ռF#WNo*b;=F8)49⼤9{Dq^251ތkϝvF;oK yIJR%t`,Kf4ޅu&%$X%uQG*K%JP\kK"u~7Hq^[IO;UKZr^ߖ#]3yE?1q^өG8/Q1t%CV{%8{8z5S}D>D4Iq^2%n/u­$B 8/Y:8J}8/QjCw``dǖs=q^kրۚI c= zt%kIL5m)s^Ҩ }u,Aߜ!wI׵w]g 9L} _&ƺ#Ջtj%Y~^b?u&$YƎܟgR;#G;Xd6~%ȠˊYKzj%ȝ.({~­\7fս%@ة9;PFT+X WMb̪ݹGrHI}%c%>Yyfz LҁFRvۜt)I8yhK\?Y{oiWZ<yI;d@{kKn&݇L9g$mH}%k4M!84%uwrs^g/dJu3cxj#iؿۜ>?}yIVr } =]!%ug9ES{8U,qE!-xI/т[Im|GcQ\t,x$FnoKZw*%"٣Fy` 漤eQ5yIg-:@s^;&r^s^gEoƜ>k^ɿ=ayI"Y/{612z6}H 99/Y8n:/1&VD N!|y*dh6X_hKzք{#Q?Գw%GTE^>DK.m148,gНc(:/YØZ$y&?{O6%c!{"m&fS9kK`t֙38/{yI/>V L-J/XM:dҟ:cJq[x>oK,koSkK`\8/w'WIkm﹩!w:&-]6P*XicnŜ,J<֜7ח <8/)ȇճբ4=zꇱ//8s^^2Kb+=//%qeA^:a%vC8?0v=dgm=dLI9Пv/Ǧҗuy?RJ{;]j%+CXyesl=Zb N`r{f [k47oJtJ2 35V>VV^ͻe͓,6rЌjk `6%i6ޏ u{a8\KZ/χgMk,%)l`7 ":ݛ:g#nKI&"|ԑXם?/PM1O iϷh!Z'5(5rK`CE#TVp9)+()HK$0n-OpPh㤄e )O#Jw4!KlUr o'8$i?hkx E>L,_ƻUsQe֔9@'XnENo3!:/dMͱ)hRLt:/f 1:gf%PUb?]/ɱW j[(tEёUCbj"?)&)bW cj@{;ؘ8†*h0ɡftN/p`n6&hɽvޔdZ*JtʸKc1팯c) -)^m:΄T|1@%fsQИ-I>M(iSE]z1X1b2T qSѯ_qc*Nqc2wx Lґqp#:M:7&3Hw)[n1 Tw3}1/ۦeDIܘHSڥ|gd:2ZS|Ϋu x(#b^S5SeHf=ndĕs]'!T2A*sc?̓78ntc1uj}ooG_Ps\@\4"b2Z-&M\dVc2b2s9sZ'EqL IdibbA"РjLW ¯v5&C  jLdш>k6}ڶx ;'5?L㥛AZkdC_E| u tWٷQ]kAdg{J,tA.:!o;eKhPlh8ŀx&i91AES{#Lf5&C[0tɈPc՘)䏊ƻx"DWc2J|b'Kitbq8w<+,_#t:ɬ\I(y2N?P7Tl}CNqc2SfQ7֋ɠ<0kFc2Q*d+ z1''0d⯟ޑecKFc2H5df\dʅc_ٴ@,wl7%#Jw۝u@.]NUjL&5t:zD!Vc2홼iLft#8ZLvqlbX6'ɨ:@LX Հv_͓E0͓"G y2tq{=2 e1Y$Y2XZ A<>mug8?ZvLf*zEfH5~f^|? Gn$VvKc2;;KҘL%$V#_ߐ'D}d*HV0b2OV2#'R_4qK,ɐwf\71L,{ wAiL&}l4?emiLFפQ7Ihek97&-42gXMaD:.XLPA4&+p_'%T{,$xS p,¤=ʢz> C2ӐZ ,^IRc2fizgtèjlNzS^"֐<Ns]ío˓YS$ ɬa )?f0K1MgAXAitܐa.Ic2մ^Âb"D')O$BR4&(IůW]!&つG?Hl(ɸ$a2}4&S0pί)ĺTy >uv7&Bp.Ldb2 N0ˢs.Z ]<=r0 Q, 1qeDN1#=dO/lc21H[!tֹH7&||K?b2k$} /ݽZ!)DN1B2AU$W J4&hII|"b2c#L*֗_L&q/:lnŷGb2wɤáٱTl1.G)@ iL+?;Y|9ܹ{Ӵ Hc2s}|5i`8)F8dsPM˓a|C{jnN. t{4&ݍǂ1OtZ1G3ddёV)bdkxa}~ Q%ՉrD:eR77t`2Eʺh}@ClԵpIy^ľƢGZu@="DHZ U#W#'YaLf!ԗA3=A/IqO&id= !#lb(:_7Ao%ژ,!b+/&ǭ;tlh˱A`sl$E&mմ1oVZI2s˓!$`AL&uFD<.EGnV&*{¨viiu|HBu:O&@yl8k'C0cצʋhG&[5m?QRI˛-k4k~y;+Iʠ`ɚT轹Yj w'`et|#/$ *ȝN׿cR 7]LϳtVG,<ÍPdᕁ/ *YhH >u8$T^ k2AV$~pVK#v˲0|a+Hގ^eQiћ $i$bC#ic2^Yގ>%(i1dB8~L t1d\DBd<MQ֊N`&zڗoz1rPBwqv]t{G`|} 3>'C6&cFsc2O7@6ARc2#I6z:*-˝D, mLFDM(]~2>>>/FmBV 6&3!rT I+6&3!5ഥ+I͡cëk:nR8Oqp.tz3hEk(s&2$|'HgcQ>PbXAK )vdL+:2ѬڄX*M45VAмoT,;$1~5;Ȥx'VY8o,=bjKu0c{Jŷ ̐ tE]H} _[.t-h=̑}5qю`20G! =̶Vb Xc2o$Zc2ZL/W{15&))ў-gBztz^7%7ľL/Wm.iV&,a>9#;2L|p!+K[^@ˣE[d*C3~`A3 L.nL&|! dM߰'ZC, kLF:]!>ϯv V۶Ldju g'(l[1;NiRӡM2ցJg "DoNTZV *^̾g"2$!~Pn 5 >h)7~NGԯe-C.Lww[ŒV| ;z˲viF ! L߰xt>ӓxȂh,|w'M#;ƽ4¶,1-9#x1 Yga۝d`I۞=]%se{Y氖\Ū($x[ގ~q=e]gw&|%uu;tE4[dǢOn`D.ڥ씮⽑K,#Yc2;ƝWKXAc2ա[AJGnLSG֘JFXc2kL}) %4S:|AGnTYK7w K;ڌHhbY`Z=0{y?~:6 N팇I1G[$'v{La}^dTQޘ̊vA˲_ܤMߠACKg;zugБ 7O&W-.­f9 | 1Xf8@OtH ࢬ(_M oe7jĤG4?n?)68I-,ǿh1a3赒/Nt9ȷ\̷.W4#݋R7W]E&ٜ5L-:sN.0 7q vi4&cXpj1e`H11$Y:{c2KH o19َ!͓)zsd ɨżoLFdp^1M5*nQw<(㗦WOg༴iY+K.nXETXsy,ǛW#IQɃQا; : M/1lvgkeZ"&29A nD?];8'(w{)h02IS(fV 92eOp1N+`?~`KFfor4N^i8|dWt{3&d|ykؘ̙7&3m7Nuc 4`;%G@ůnb,"pq!"pϑ9Z@ #5 뉒XFN#3\771ʂl8 2y6" '5IN F©s:rkDHNЗḌdlʏ蛅< o#^k ݡdNS/.3_&9q_JnK [8HM N(tdL k݄)/_fW' vg&ZYtJLʊ |ѩ[24*xpZϕH94ظJ . 􈺴"xgO7 l3םRBM sN|a p=!7ŻυpMzS +AF~ЕPAL$q;z̲[8#nG_R$ E`2;tW%)= 1LF vLX hFBLj{LfÕV-/~ Jdݷ#;hchunLfrg D}jLAyA od',Fb(D}[)`f.MWl;d {4y2Yl"=- 7}xL#?'fOOYa+D[ݞ&HοoqߗvQoq6P|m?oMTwNF%c`,nXt?HouB{s\|qw/w[:!PX!aq584n|3@txr| $ 9noF01屢'1Qy2dV͓QfYhMzӸP#4o]0hlB!rу~2n~"5_?>E l?9H&=~}QNb^D*>LǮhnzu9/P {Z^f[CGIP ,8KkwʀVe>W7!M٭ Yxw0nm=]j7E'@ΟdtgNYܘ62\Qձ:OA@WJ8ҠΛP'ߎ^2;, (}YHH!Hȯ vkxF莞VIn$=eʜ9)V7_bWG/KW"(θSЅ͓(e+:rVRҽ@;ņ-:}c2d_'L+8XOlL3N|ь˲ (;v->7O&ЦiED)0:}TjvIhZj0MD)6Ty]Apؖfr*z+TәOWSh޽A5(,1(miFS~>?ū͢i"6Eq-n'{b،b b|QG:~)('Ɲ.e5^T*v ({ą0~*lb3(}"\pj>,0p?N5zF?=JviSGb>rHKW]URb8.=;ZMTkSԷDtEHTS{̾|'d<>)OY7 u?)K$|dvO$ٮd;OG2jLYcel4&3MA?Rr[َp64^m.Aq) IA$˺ 6iإ҂x6 DvBb *>@~]Ux@҂|ĠStGp #2m6:a$ámlPvƋ?†e/;ew;9oGI*t8Ν|η|Ng2qoG?45U7#b췣'rQْj+^Ujqn1d*_耮?.2~dp=H[ZJ9I :~ጴQT|Qҥ,سdPqY c\DDFKnI]Ɍ$+Û(`{@#V]*tۦVZ|vu hK^®?Ka[v7qǯryžC)tlGNJlaw-1Pw:{λӾXA ̟~Tۤ`;nq[ፅ$4}}%T/AyOQl;XQ\~t/Ofv]LY zhҟ]r(KMaU4+(;ІKvRQi7L,F3G[E"ns #>&ӠP:AF.)Ⱦv!vvb$ʦw*i(*@?8֪ ϯ;(T=tw844y0>MѢ%WG7 נ묷 S|u w)z烕'v&HOoϳ6g{\tv!KŷO h1|& ϿKwAgi,/,-_+lѾ˜t5v6 DKE^Kv1ŋuĮ͑=̱ +‡`2;|aۧdٰ/s17X@n5{$TռY {?p-(]lLhh3my|Q̚}PbO\d_Vzkj>Sܘ&+ax,tisɄ~#Gk<9 ᜚Q-,uϧ%?d:^E&o JS\!40]@}{tD{m 6=~16C7o",1RӜ&wa;|ن@ywpBQǑ{'p8ŗ:+80m3Bd{JE={ٞڱmaQ]ne`Rŷ[7&ħ؁ϳ|  [ lý|iБ;Ay!xvcOP)aCpϳ odh˺_ŷ| ZN]{scotch-5.1.12b.dfsg/grf/bump.xyz.gz0000444000175300017530000025215410656300346017317 0ustar hazelscthazelsctp0ef_bump.xyzK찭,Vg ķA]xL\tɟH A o??jk??f~8+mq?yYe鿲1^W=&{&]nmmD64}nsNPm3R32.$=I&#/ڤ I/<6Bʋ6BmsEv!E~!69hBmsEBml/q!_#g݋}{xukfs?;NH=. 9 x۴WX 6 R/5@Fc}}^{~!DZٹ{\cm]+E{ܐBrHVَ!9:NoVQ/$y_$YpGܐ_`pͻڅ4 A өfS9:pwxZVj! {S:Fﴖ59. 1a=!e^3}kONhfwzO<#luy==6Èq!=m9#m9b}nsΑ6xl3==\m9R~nsΑss?99Gv9GbΑ?s8cUy#Ǽ5huNSċV罡ыVšVeBEy/Z h/(Ƅ>~sgẹh5/y9[^:gVl1huVlI-ْ{l鋽Esޢ9[boќ-{hΖ[4g^-/{lŋEss:e[g ℾ[c[ۋ5fĵ[c5#[g4|ڽ[g8ℾ[g<ℾ[g@|9[s؞[s[sh5o9[chuh/ZE9[4^:gNjVlu}ꜭNϭҜϭRE:XFV3(/Z/ZXh5c/V2X[˰{kȓ[##O/l5l鋽5lɋ5lɋ5l5l5lsƋ}8/٢{lыsZ{3boboboɜboɜboIfL^-xdޒ{Kfr_--{dޒ߲{Kboif!_-4䋽s9[bo-y4/f9[bo霭boٜboٜboY&_-E/٢{+JF^쭤`{+9޺bqD_/742oZߴʓUMoZ&~$57ž^ ھI>/ゎ7ɽiU.iU'MoZ-}o=BGlx홑~䐼wMyiUmx̖.B'@IɎ®o]x$H_p}:AMrxӪNV⼷7ǿi5.h* ᳌/(i5K޴:ߴʳ8MrAM4iuֆțVgqi5*zUbgA3_xjiu\7{*W{W{*W{kz^[g >C#/[Bޞ[J/Z]eq/Z'!rhuVh5kVzQ^UPi? Z_l~B:~A=U UlU~B [_P l~B[PVTZ*Ъ-B>П%-bV3sa?gkҟ5pol-9[{~Vǽe?g޲qojl5[s-1[!~Ae ^Z\Z_^Z1[J ʥUm[ ڰ1[uH(QZ_P-/(VUҪRi- [/h/< $so9_鯕EjF@ t ;4*{r|Ab=o*O-ݡY쭟r&w蜭c @Meñ췉:cW$c3aaQ:|oų>F` [yA3 :yهzM>V""t^JZY>48q/BWZ3#Ǧ˾Ψ6N}'Rkf7um +yLW9]{klyBRN:[]oG{rqѵ?: 4{_@ ޴:Vg_z2g hƵi.iuΖiukћVʛVƛVqқV}ߴ:Ubz*=C7ҵ ڛVfG[;ޡr=PvCIx,^5B=Vle,ylՓ"}XF4X+1L+>X4gkXUh5#O)>+ƘЌeD/9οKBW,õa94]lEH T@WX ֊<ݕ} yb,c:v]gJjt_YcET1OX'رg X8Xz?ƚ->c͖Ӏ:>}3[%Mr0~q5[L9r_KˠO\y<aX~B;V'/C``uB'OoB@oHm} el3[[VsJ2 "@G;4g.}=jﭦx׾ V,#M+yV)8Z:zJw:~jIC}^ Bt`~2~(v~8cʿn*:TWZS6mfتJW"Hp QM=~V}~A$/cӁk淨ϒ_i;ǥ *} Wժ⑑c\ށ迠]nR3[\ӡيgw_7>!Z\BW|F`{+8wՉUAZ}@Z-C5JzCǂ: eP5X@_SE`NTC_}V:09[oEg?~}#51PnU3qkm~V2(>3[Pޡjv_}-qmb$ҁIXG >'a/eb"u}\? k@}s`2z9 :5>-*P?NOMqV/\2:>yzO,C* V֊eGa^ a- @W,zeP!]Ajnk_'aY:VZ,d,kK?EZ8z~ˠ [F30Uc#pVN=ko)K޺j]9b : 1ȩ5q7hX 'NbR"z龴4M>[KS` we_P'ϬYB'sЪ z0\.{i"4ExDPsGg!г3ҥ$TA{V't`jjRVBLJ}'՟u.z=iѷ՟P!Oc߱ر$ZݡKSDݿ$s',9 Knjw?'!Fu5hIuKl}bsJ蚭rZ>5[9-9u@luE.OwAB?{0U:BcI\ 6i{2PSkaj򠧄^:gk&!gEKIlYjRVzQ%sб;2Gߡߩi`a ,?ؐ : ՀZ09{:R7,1ME^B)-$T>&Mii[Xx:XnijZshEXhL1Qٵ iNl?ǖ>&R_Z4k>Yc"]#M_vg+?UM}:4-?gEϮU@zY'VSڋV)vg+?tt5ڟMWVj6zѪQՋV=v5&4jЬ1q\19TPJSXNGRh|RhG.g-g/gh,Gh֘gh_ PZ S@BcO՟ j? *4hThDhj Th,PXBcRh|\Cm)4>C})4>Cc)4>BS_z2 J? tTh,PXs/Rh|RhGBc8tF*4U-/Th;B~q*4F=hYvfH}ѬjAͼ@_-G=T*kf;4yĻڝ{AXYAM˨?\ak>!"9jLLXX4^(F0?؟grX4n 6̪1I+y*0thJrEdfK@̖ޣ6tVM? \@l*xƤ0(F`V)tb2 $av)@iO9J=?]UcBlCPNZ3_5&Hfhu@mk@|O_۰C>ֵ9W}fUt-:~6A dS\uFЁ-+5Cuqua\A7ngzJC`FIz֘l(nWxȳhZ<4}u:} 3[Z5&Ǖ hUTK_WM* w>ߧ]d2z1 Y&g+kL(ߡE;ݳƤRi?+>ť ΁1ٴ^ࡿJrzؾZ=>UK,ECR/MAlR/OE֘47^;/䀖R/o(-Yc҄AϒՁB?{Sdfߡk&]QraD_P#Ucv.wScRCxc{_WJq퟊UԘȨ|/qد0{݂:گKjry"ꀺϓV+>O|4.jq~X=#ž|.p+'$*:ƂB]0xA Ъ*/h}!}_P X.#wA{ _pۏc,q߆-^ |/ V|졧vɃV'/\] ͚a$ BSɃؤɃg}C3H Dر|>^`y}rxսk{-f[l>v,F!ynV-[;~l,?"+R,Ii][/l?D-63 \/}9Ҳx ,X]6 wDm/XZ& /cy֖ /+X^ 򈵶@^`rye; ,!}϶|ijiwѿzd]& [,-c繸3 ,/kXY /A^`my(A l_!/,B^`ye+{ݷ%to'de{H`{kiiWȦ XJQΡ?#Bٝ}`9B oR I,tVp`BE>Q,js4V0Z]Ԃh0"qkqZ_M(Aw)=]2պXq-Q*됯ЪsbpϏe!P04-K{#Aʸ~]N~4H]k^X݋^0z!}aG?U*i9;9bXV~M`=|HkB{Ze\J??ޕo`m{a8ʟNzt2_X$Ȥ?k1ՂiK(W~i_]XYRtʯ}- `UTMlU~S35Yz zp/-n5'6Q".A 㙂،+#c| /,ε|PٯkR,u}M= N$;?[ v?~av)F>WA<v&G/kV>aM2PX6?Qb!χ Xi#+=PIjGRln֗lDy4]y" Nt?ljfe1}8 9G!>wVVC3bQE 7m;7J;+}Hϐ}aCRôdd޴7-d k2%?"$b`ĜV{(R k'Bwu|H~IvM+N,%ym6y _ҥK6y ^(wZ7_BiW@iW%R1ME{6i%Ǧ݀M~ ݀& 8%2j8%bmyK~]8sގ`kn>doڅFkji<%o*Iq$ɦ]Rj wJqӢ+yaaRݴUX<R޴`XC3yb/*fbc1< ^MYJ7߷틏Z؇h;=[x YӐQco:M qoSd&oo~lm,kj1߲k۪\+pGUV#EqV-F;VAĮ5ʞ/M_oqVyu`i@{"8G +k]o]%Ұ }wY+},Fq|_ zP~ @njW߱6]{߱!Km6킴ى{b_(8%:t/ [zk }1oYNc/ [F'P YEStaaK sǜ˿hs`'vv'J 9b|sI ;:!圃Xׁ{y 2qo{NV -iχ395oS\'sN"A^b[Įy+x?Xp|.sbs<-VW1[~/|\ {; /|Yؑ/^9󆲇'#m_yƉw@T?a]}Ha Mo8#F\_tUoo1l}=j6Ҭ&8:2^VoapĈ滻:ok/qEȝ/Au:7%QqX`2^R-:ŊTJxv3^k]GKTv5L0/Qڴ ]0/uT#%w\ {fHCf`qblpF%̰Mi'MY2gX6_^68 C1LMqކem_;ccz//ÜXZ9/KSnjSU,ӜX]9/ls^`}2ኽ2bۗu ,-رs^`yʲyÏ{\:sq{`co^8-/tѱVرltF2`yl;+i㛹t҉:3g[jW,חN5l,3u_n4+;P+YQ8d=Ng}0C{X f}@VdJYei)`V=N3{LU N)V=[i3ߖ8[(!o^x8ǫET VYm[1 P8q6c&e󚷢u"j5׼8";MYB֥]Vȋpl"_ Mk>6۲q!}y%9 r_qF9ƀWz=¹R8I,W֢V,;kK2>-+ Ue<ӖMmgIҐhy8jw'Cs8 ˚J+c7hS`=,sQ J6[+ߋeOzSOSCL]5yt^5Zt e'qqb5é|a^b3eŷφ)`9gP?ĶC*za+ȷַ̽`#cQׁYsuTpd=BRGpd=0¥ ߬^tGknƕG`XgY({ c-%}/9+}XF]颌},Gmv<eKwQi{/o'׋?)GΛ7?|߸E]ekPԩ20oc gP&[\X;K/9tmޱݯL턵nv[Yq6)8ul~Q7O}oR 5 x9a-1}8wJ=)hi'΅Le@[忰¦.6rϲK4%8Њye.Ջ b|o:`m[qO"/0w'_m'%~Gt}ϸkqV:1욷mgvޏM.kaeJRp}:Z`2yo[(na/k?Y54q:΅r 6:pn_X8=J ë5PcCpp?qv3 eW!*wO7B?'6y߉͸2{z68T[3nb5[x+q&)~?NRdǽ8JR8܊(#6'^g?D wkTie=Tr.u3ʘ͖&_7"8Gk n.8bUC8ǽgqg>ݢYZk 8Z:RG36[}x_'1ih許 lΛ5qe yX Ѭ1}X]ow5оQ]o%nUʸPjjx</{C=ΝVCkԬ1^83NJ߬q=;qDMwXW ®'䗄;Woӥ)Z21GM~ITS jɒFΈG`џen:-N٨,|,NYq8:/]˲&dz^<,{ܲS{Wvߴ޶MѼMQ+M_jY/K&7cخ.N+5Ӧ0oRY2bc6>'3Z3nd𖶥*Zj[zQVS'Mʛ7^_`^PJ8Q^P[z zOM* ^^g!^I^zq9N=,l99oC@Ruvމ-WҺv oOvrolt]:m齎/Amy[zG|p[zT0umVa.p5;k#*ҙ,=},=91]Vr3j1Y:F޷1,؏$ CiRx-Wqnj[.WmxFCϖ+z(/-WwL0K0+ *$Hlb=!ϼջoyǓ0^qmVAϖޫ-І^7X//lҮJiWbkDPGeK﵎iCl^خ9K^@SҜkL=ΞدEx6,5-W)PkKU_(/W*:EՖޫpɡ/-ך؇ M}|v/ZuzC+MP|X/~M=6o[{Kw dOc;?ixKy#nkQ ،W]}xɈ lKNϱ6\,!\c_8<%Y}'?yKv0//pzKl2 vŕnŦΓGhGxq&na3^E=fszgR k'^(9@]O]~XPf"uC۝;uCGt{G͸o_ m|/l eM`nŨEz 0V, : FjUF4qZ%^h~I.ج[!_ҵ>t@Y/3-C0;c5~-29N+C/8K=p.RDWx/!.>f"ÚL!*Kyg)h{%Z{JN@3~ UH%&nwWOV/"HrA_rJKX/)lX9> m6^GC_'vΔz'kO ?uZj u״ØI_GCwҭ3-O}w7 )ēQGCBla!v`?gE(5>_LGnWHKt~P-P KBKY}ZX]^:m835vK+KVr"=K]No1m/i6j {ʉwߥ Olƛw7 ^FxbWOn*zww6{텃a lT.YQr‰-\5mx)ў!M]w j*Ʈ`Mfsܼ=p2Υ,nƹFCj=Kk[b^rbÊ X&/)k\aV6|߶tzkkxiVQ_[^:^p|ckyŘ`Wk:~%\cL.F۝ɯ|i.,'0t`%$[~KqX]Ekkt1uq;>vƍ}?;Fةu׽lw;1?%?׀j׺38^q ?){E] S^+X{,"ּ~fFEgg;5y+c6f8XpK{j@'oX;A;ɆU9X<)NpT7Dεvkz] szV%bv_nf=՜0|{[5Y3Bj=ν~ҪG/S_ؑu,W+V{ج:ui8: YG%}vל;{:*؇uT{جy v`z5+fMj!mja:7|S qKePߖuT}.f=i\YGLk`FQm~߱YGHw|tJ|.GvbmKU,7먬ԓU,U%جځyz`jh#.Ώs+PpjfW<չz5%Fڳ'FkzhcXY/=Z 18!j^{9rIOh GOKWbf94/6c7^K,c]ZOW]vRf_zԆ/s?cc"o[z3VxJw;YT,gn.@NEMlꪅUi1C̦~I?}̿Q@~/^]|)`x/2wZEā#∨1z`JU&هi "9fޔ pagT*_CZ`}(H+Gk ;J c[ |l5+Cyk^r_ ;5.s>W izX8LqfƦ~9a)gIdy#*:ʚ fm jsPl.GoQ tNϔ ׎?Á󗚤gPiڝLkڵl=mVD0=y a|{>:;?N90fp`9SO)vKuf`y V5GlgBvE Gr s'/c[Ƭ+{F/ ڽ%8zx X\#Ve`Rk]jP0 k6s3}{k|aϧ~rWvCKK!؇P#6Un ck@xIvK񆬾qr`'i g2[v+x {]sA 酪oڰ.b齪dw,We{5^o)sbsg-ca36j&op-W {5^{jRuObCKu;*#!LKuYm|[i-욷~u_]o?v+qZx@Kut|o.l_Xc:J< {%˿v'vv'JQ^`'6sq/c~aGFEl;-=NJPҲ}񒡭sQ9p/&-: y162^B;k+oKzOuH~Ii,OB~nW^䗴VFnXXcQ{3^ ]0//ci>GK̻>cSO7~:K[6X_㹿K+nOyvg,xM9oVҷ_`qnwۛv?/^&F{V,-x\g/hnK#w_`F4r7X%VW$}/XZ/ci//\ygFnunݸ%Fnoo/R#w_nzOXJݘ!v,\yg,XM7}X>+o~[ڛ1KXZK#מ4r⊗\ 4r7X ˭`/ F.?cX^/4rK#֖Fn}ۗF ,-ر4r[祑+K#y._oY_;ė~ɥH\OcK.M}inI,-ܲ7Lcir `Fc4rbK#k4r]YyVy挿-Fnmⓜ%]-7Xl76w^0hq~IXz U_#p=~Ij(X ^zUoPksޤԡH@LޫK/QrKFb;9oJMA~I+a间2lk/iVG~ 샯v;yy间/940oKUZ ^%4vsz3{Oyc.в`eaKl.퐍-ᣧ@O$,=IzIe yMO]>~zXJva$EPRK` /nh{X=}];} /lkeʩI<~t\a[X?#7l°ݙ؎SN Affaإ Z|% ee|AQƷƊ[N/{K/3(`ϸr/aS^\cKZ:j4.$V3N=XKtOYqlq0wa=Dq*xK꽪ռ4jI[uO,e=Yo|7i#kڨ JfPSqk?s/uP+'W:=OLq.Ա ^xP(/Q#Z xI?>3^2J͕v*۹U*+^P',xOMߊեX[Kӗ4}#m؞XJM7ؑXNM7XIM7XMM7XKM7XOM7Ky.F[aY X[#5}mX^>t-c|4}b 5\>YY4}{6\qxI/N}xI,N#/pPcTVABxߌGyb-pD}v?["6\k lj/v-(ښpOɺŏw ؙ7ox^b+S4^ 7%-։!6%T(+^"vPZ>z{kR~[ƹpd uD>:E9FA4֙.}McinuwwzV8C]zVrIf~b(t*OvW:zȪǩس^kHK+TnϒCA']V=NuI $+=t[ -y -Y3'0~[>8%slEsz(zAqpC z(Muk(Z^{-~&&uWΎkT,x>9oCk.Ighɋ\gPѬ9k{%fUlwY^nuĦZ#>k'_ 6b9%%w SZzcgS._'o:*5A81zy:fYSs:Qy լDZzF]Ҳ8V!8@ YG%9KϜ3v}F+*;>klڅaڴM~gU*>Kj R 8mXB-~շb_Ru0 c6qĠ/)weØ-~I/~jiU3 6y T"S~US5D۪*zXZӏr7E=nmMa0]ySGe|?yS%X5]yS\Ї{= 8 %銿mK4P{lw,,KVx+~+kuߐ'{%mk5U*s 0ߖa%Wt-%%d-zvv'J=]sE=]sۏ不 w1o.| =Ӆ;A:;tAb[zPnA}qg.JgfJ֓A,2%y x7Z|y=_-6`}KîyywD_Iϓ_Ҹh/oR#/?᪡-Owcl\Zޗ[So8Q fڭg 02U/cX@{샦bɹs0ak,ֳ]COF!)}2rjpуiOBO{{M,0l\SN]ymsoK|sqevʸrhvֵsyasqɍ;G:zHywʏ29Yc CPsf%KZ%pC(6|{&^sx vpRo=%|\G^;~G-x3g~>82 v` S oO=N 28׳Ew azIAxVKx>Fw71;ͱj:nxb^/py"N}61+/2 9&sY&箰/4A6gޫ7Ms-MXS/ԫ ;LKk)G~K~ s`šԥt0UG W)x>zK5}O,})>}xAŧ)ޣ_"!~>eѓ_®`ԓ_r> ?l,-X_"!x_%xbsޢx}$v6U,/]lkQ<\om8{?`ܻQ֙Q 1'~[|~z(1&a\Go}q;zC1o'^Rxa}x(Y:/[x jBŊ0ԋ\9،!Va'h+&fvտuXEU&kgfZN4_8x6)]T,}MvŹ}Xps>J+FX-5}Z8= ?e~ .5[Ψ~kTj^![R؇Rj^+VK|ԼƊlX/GԼFK6햚 Śx(51گ1#݉sQN,c~mSX{beO8V8%]HSχM8fkI1V -}}cNCmj<~uCɪAL+>Yk5 j#Ծ(H ɺ/넃3>6Z u7d|rH9D:ˆusƿ!Kj^#Kk -MX%~I>m~zZOUcelyojKJmbh{fYo:J| ؒgZw^X֛jWòtW 0^^|vr`޴M}ڱUoZ4`Yo:8r%Vi20ȍovCYoJ\8Ӌ'x'%cE O߾Z?osz=iWW,y{Sdī/̛68^zFNX!z|Y[TK?E꽊=`\z?* H3u~Iџ/ɞ⡾z%?c#N9u>v/}?=uY`)uYK];~ntY3V.kjVvb-uY*򌍥:Yczn}g,-]K. ,]եb,uY/8^:z.'/]zPRf|#uY}ӇXN]،o,]V-X/]Vϛ߀{u.6!fgU#k^}`gs]Okr8U=Kzq{XI1G}h̉e3I\C89o^=_ Y5v0Ӫvv޴F_]mKW}9GX^cVP6+\}X~\[]8Ry89oZB@)Unqo^zxӾt 9oՃXenX&s9oV<Ҏ8+|+&̅.?rWD7uQr2XP~aڸw- b?Gu`׼8os4S=?nKصߪ]zQmNA:QX(,Unaty/1`}_Y%.R+G7JEs=K\ƜXYc\;/iQCrS9^ܙnyak]1'E!%za1jRs+E7qO?c1`͌W]3氵}l,ϳp:'!~vlfnp̨y윷㇠W}/M7)D7{w@/rNk4FElX ؞XzNbhh`V{ y/i\%r%9Y qyNFy_7l7}ZѸs7<'OcnlZx;-ZJ=,3}_,?cq GHs|!p`Y6FozC*"f^H=Βt%-؛щM[mo}1={Ik frؼ ؼ S{?@!]X 8^w`W[Rױ3۟W*yc]햺m+^O}ow%6bI[Q|v%};!v@l~{d~ j'SU'v'ob?(Ix`9k,\ج[y^Cd|7{K}QP·᪛Pp`3-:O0\d=u3_8ݨ7qP|xnֿυ1z^])86pS#0OxRq,*FO~qz2}n֩1 e8[l؜7u[0 (!}K%q8JN^_x>&ט.7Sǭ/њv_;}?Nr Vtռa3oweMy'\ a|bgH#(uI}X8k٪!Z}X89^MxP +Kr}̥,`~ ŧ]ؙ a:)OJg|Fia%ؽ$K:-_cJʋ.lOj'`.HNdt3CF?5ǻ%#JIU8ׅWFM8-hWRWg6 9oE'{~bEfEw ٧RSL}B[O*v7ƺE#K `cy~+qk5oQ5 KYs%+z`Gzm|DYs<',!6ug_0(q-|jA'j%NZ[&UXc&GwD8 $gUr8{anҎgw`ӗU-l7:4N˔'8wK8gjCHTo8"ZNz{*Ħ׺8\k' (8kC|]J {3qڇ$MM=:z3Rz6+A|j}D.1Z k2qUl b?>b_8vr>qɧ^PT;uDI7;㓮:v'A8v'7}=,'{عߎؾSMzlT=Y6X^)O5 8>nXK]&#f>Hbwi `7X坲ҟ)͟)1.zNiYqys}^+~κ;vLu/bg]G1%wJZz;YNzF-SKRϨ5#%L4Ju7 y0}<30UcFgq(r}|VV)Oe]u8߄a..{LazwS s /Ӏ/7x)J֐;Ӵ!YB s]7raـd q;`gzܖNB\9w0iwSbYGRtYC^od=N#Etݎǎ\za2 #_X}[ `=I3C<' >,r,rxIr/~Tns|bU99dv|u/2GK;L\u/n r#%.> VY^~b#9g] ,HMG+~C1ءnѱ N؛:Ũ rC9z v~c/dF~3+߷Vj`h^Mۭ^bRj1|-ZdSNl-RxQQcyVj ioQ~ۜM 6mXԽ uj9y7qym{vj{X/p)Ubs㜚z9q>TΨsrNz6!GyVx;RF{ #%_/,UvK65lqʁRs/i-.M *~CKxrKEgUUc_9*x /-5rTZ\N~ nſzxFVxAf/A8-1 KP48%cp3^+Q8cד۝-68; '$ pQS+H9υ._;;aqx&LݢEׁ+VZ]g9r"/%j"#o=Pwp`3ƆN>*.8}s=56*!mpY~G|o.-\;cXǜ7 = ajr/׫x@(N>_!/{}o ަ{8ѤW=WON8D̴z6XsQcN6s sSSQj1p8%Ӣ΁JCL3|^&˜ޠG߀_r![>%v!`1w3%V/^ -%>:[zRc^Gɍ{CV,yAEFI~I|, y>&7_ȽoK/pX&'$p<%QuB@KA 9x[~7^~ˌ7Y{TUXYCx7{Ywqs1K?aB}*6X[Bw>o`C9 L[A0q0\OXrC]~u1佶R%ݻW2o-4~Z/c|/)X:}6A-wP[1j}y^!^NĎ {<0ސrKN8䊗*5M&wߕ劗2z'%,%[wG}ʟ>Мç+pKN(rK $I V5W7/79*wCWrcQj>Yoڤx(g( Ѳ73?j} v'A <Gֈ <:x/!gœ5(_v ;筷RK+5b2QjEX%}I^gP%_ŵĵ%JmO8~Iv|g/͠~&]gK*8pKJHNwU[pDzjlڅ!9oƛu@'yySY:zlPg2ftsrK4*튝I_>y|a_`ЛU,U_ZMVka6~-^٬mm||QQ_zKmS7߀_'9ٞja$f qaKq%򯍢ù:*uY336u3D_C_CK\띴W'ج7Жnboj'y.gE?>;\Ul~FG/  ]8ݏ?N(8 ǩb?8go]8`?8ܞg3vT]8c`M~q`?ή]8֨b?Λ]8b̖?N=zǑǵ珳;q d8%>_IR[{`5^ _ `-볼p|S_يb.P˥uxǩo' P||N)\5. AZCMqY].869b38<*61ɫ]Fz9k gKUE;#v[3 *5 ́{2yK *TEX؇9oZja:ET漍3ogyZCsކꃋC^DuBN:U[yӜ7IIm!՜76Խ5>WycaasK`cgƅ/V( |7zP ~jBmu s6MUK1~9oQ ?6h l7>8BD~ӰsdAADZ]?s9o X1T7==%JyM~ i.~ M.t O5z0|FST0r4KGp %_BR4Q]ksĊVeFFΛ6&9rr4^I yA] 9o4<`"\ʧ'C$Kr7)qӱ9o 9E::vfdXgiKj)W -~ 厫j{Ew=Mǧ'mbY5{Kbg:K ȳk |QAljRca٪ipw.ȵU7^ћ<Ƴ-^4ڸرfh~`yaKN{XXՇn]@b.ޢyܞ ;t?vr\.ߨÙ^oo8l=a47-[~;Pt>\oHlw7+oHmߵjd(o% my+yS捫w+xX66|+WG]7 }Tr 95m`-\c㑺jp_A؛#.t1{ԫFcN㞵Rz`Rֱ3V"qxeO(ͺ东Xᷬq4-qY8US7^z5zǙ]u" f꽪o3ج@ϾQ9asf[۱YhVAֲGWbnqłe=V,-7֍C)FTmq.K?aQ="[gt+oawA-vƕcƇ|q`ԏRxKFzAG;"/99hPdo;I9/lq,x{,.aRjHۧkL-`.R:v| k-"~;A=yK-Pu8W[ E-5sF+>ZsIRN4Ϻ|m.cS_|.̱/}VcbiT{՛;SuD/50k-F˫֮9Yk]>Х |偾%4`q Ey:/ƟlڅX'Din`׽d˫^ ֤7Y5ZOxb w.^:+G}Uc}Hr 'SU^|e̸ ɟpoXOD=K۩V?6'?_OkݞxޓWl,r;A~+KA̧/irÚL]g_X*| z^cmMV ZXk*6B8Ī;x>$]>Q2odyKu< `^8d= Y#op>d=^s|`ag>@\ٗޫ'ץ<Џ[SՑF4=G|zv̅꯳Db8b5b.? l{}.|SGX;YãWL3[zVv[Ze|$O?~g7 q~Q{j zq?C?4S{ }7*<=u=usS[:A}+or!y{#y+zEf2^9Fݓ_ZXGx'.,cޫZj_za5Z> /j6C^MPiu&/hPGl -u/zױx3`%kKM9MT 6m6&]~% Гg^ѓg^h+z6tؾ@Qђ8FR="w2{j o I^pkU>i!w{u3#-J--ǘVE\1(kK0=cdkK8/b6R5[pHߴKخ,M %\޹_m.cKĂ2`3^|]].%,;.X%n1CuC!:Gbq_h~p0x]YpF*pUSSjkZx_W_%W:Kcα$,'|;lO=/ɣ]IB^ l^M: ǟ+!/>^A,N,׊=^{ZAY,WΞ}6ց^c WQeڀBz@{ f=5o UĪDZr_/;q*1ƪoΈ_K[q̿lW"z+oHR+g I19>#W.z9ƪǩM^k>|1pcXU>.lC'v͛^}O욷y>v[]ĮyA!욷ӥyvX[#AkN?w|<YKm8OoKJ|]mz`}!ChM8N{ĉMn`Ǥɀ`sxӮ?&Go(=oV X8Xآ?oGly9Sa){7`P=2%'6msQY'7xFe=EluhQ~[^i}8hCYR@ujgԊʗ+GY>M <l6AfedlxxPK>1tÝQĮPǁK윷.gs7aopF먵}ɟ^}x?NouX>zmIX<Dl'˽Z¡]'rF`d䫨ð2^ҽwxIg:[Kz//}K_dU~rXU&OFkk= /ϳ FϕgY5||d=?yإů\W֊k/佒am {VIO,zž6C;ǝ Eluf}/>~%Fj̉Mr^j*[`1H*~G`@4а:ЭjGkw/M"n"dPĂyYcTjw>?zHY;:c-r`e_x>6sl8f̧;޵luv_G]=ǷKq8_?c^ot~|aeyպu8_wOͫ)6K-qȅװ6qu/^؛FJvBz?4#6qP?qqG?Z_'o4}υ"vt=q1'h(}Aӗ,C2`P~:M?)m,U C=e ˭oM=}U;[GMI>)'x7H]sL8/X>yf?{ON9os46C>n6WN}M=sc=P/ߡиډY8PfT "=&s o1yxP8pzN^D/YpEOY6uFNa>F!GKTy@M9W7+ꨍb ƌ'ǻ3Nq6]'v{ qJ~)rQ&_2v3}nM[`55jmbSWmJ~ _rjD+oZAW)%uG/~= 'A/ps"%zT*ԡ؜7G< 9VJ~ Zځ"Kv>=SpZ'a0f ܙr[Xq:CaK sIq ?FBe~T !%ޗ'3?m1>؊ۗ2E 4lj mq 'W?}Ղ?՘X&+vZjӥ/!w7Zڭ-Kv8T}6 : LYؾ@Z,=hرA//m6x;.W]ܫli2+] |w乾uN^3^51{~L^:^o- ;FZ)HК!S7{J.UUݭut+c(.]:O`/9qON?aw)̫X}Xϼ|pSj[j|0/}..=%؛qUA/́ZczAKx;Spg HwB ', /q$qu%urD5IX^W-$/y~hߖ>Ul٫n]FYmT=K>N?a ߈OXdǟ}~26ne46mvgUKfYmg^ϼ!0x=$j0_2zMޫԳDq/?᪡">|zMz,}HVMyHN?h&Wa[K/?=񒍟8/%TϨI-ZYyVu=K^~DFY~Ga=HPǻ~Iת5aJKs5d cN4@d S_1sIoiB.m1~Y%-@|G0ub!'YcO,CXxmB߬ok-qԬ@GW|/'tyL~pG? Жة_b8Ou8任v@l6,?lp,-')[Y#kq xTmvhƹr}" #4\<;Y{Uc|ֱ8~~)^0o_$W.2&_Fqo=O:O2E?/'Wn18ȡc)vg|u ߑ|e䲎Lw$_9g*_Rk Wur@Jx]܄vyƕ)M劗( a]{Ď1V,Z=sގ{Ipuԇ&WB FMl'JXwV'>uM!}<yC^8i8zb#۠@{^{{ڮ6vI>-[N9h{Ij쬣ab+y):*{<8|Js:- O윷ncf o=qN&DXBY&T<%M41k9UjCȝsz/sFqvtaȭ1O$;1x3! Xlv7:ݹߚ0p1[kފyN\`99EW1 l ۝V5SPX8ʳ>@'bg}@7a'kTO,Ar k-@ r6$e] kKz9@n\S1w+;\AaIiX?7StCTqMޫ:1RM=*fm:0f2yAä~!N2yAkڎkwm6_7G>m5{qAMuD*AӷOᙪghM>W+u|rKR8 ƶcL3>YOjbRCn}bk?:k4.| A=M֬J3\ A3:D-k8<:7̛Fs2%&D8f7%*M=/Q/nPS/Ѫy(|KK!6yAQ ?/^P`ݢY7H^' OZSlM+)r݇ b::r@Lp+)[%VVa'<13ξ'&Xb#}AcTj>0_9?b0%0@+C};=R*m=p꾿UWJOϼ4bc+_OxG<-?a6+澬y1ܣHy+>mM k ߳Үj3|߬ǯF FkJ-ia~_t ?˷po).4xaq*u,m6筗; #7h?uՌ?vF[Z1lOC6T_}w@уfj./l/5 F-zywbhb 8߬éCjZ4FR5߬{{k{ 8za]H^Z75z_zp"샮>qFTp/cr;"YJ7e=NC<ʲa]'lhG72̛vi/mSϋg_4ZzVkeycf8foZ~]hPiYӼuz&z:6|{8m8 uza巩~W.MSk]G`-=z߅Eb uxC5~ض%߹*g囸:ֺ|@1j06My|beg.~ w=V,qzf$؋_r=l,q+?c)}wĞi%w++yn^99e2-sUv;يSUq _ri8X^ Zpso~/_֣[i'l7yARt8#"VEm A[U5KqFUxb? m1ho&sJy>f7}F^CF[f% >SڥN{rֺ ^E_օM!rS>׃sܧaDBOW".z oVjT4㨗N>W8ĐuW1u<8`(yQ7{4\2V%M>rNBĦa~I.lZvemFϑMZv󁒯p:K'Os v'|쁁}P/b],|xI֛zK^O[Yzs㠐;(sqF`Hd._j߬jShVFۥmR4u;0:8%~6:~?8 tb(eΉ]IGE. ԬM ͑E aȝWQr߱ş,ᐓK"nP#ʳşO UΛeىOW-fƽ8#ro!KuXzp7x1҇ L{Z=㙺^uI0o=*GCZZ{-l'ꥎ x^i6 I?^.ee{Q똟{I]HI$PjvVj6uC+G7j& {=lTXY\&[XK(T8'օ='|`#QV`|zH=;+ΝK>.?z-i|yN~?lq]jb٧b-[;&ry<9o~+-o(ʪe\;cZ '6F oԝ~`ӏ*78Գ~[KD#0Ys<@[S 8wx~|aݩn1}؇v㜅Բ˜e=M vߔ& NP=t;* 6:6m}8y/Qglܮ~;K3ͻ.;:V [ξ/iZyJ-jj,)vaқj z֖ojdmጲjK⁓~`468oFKU,K]Y[BA1Gm%C%2/i;,7}r%^Mg-!~R֖>admɋ朵%c3|\'3ܨϘ`-խqո2CuPfY8X1qüQcňs<5+fKnag}tKXKZkgKOHl7Q8 VUt`Usg2_x~<#E۸˝O{`9Ye|OVsj56o4j;bg^sn ɟe}(C߷ϧ_ؙ7(wX6ye'v5jm lw^r0J6y<ݓ;UOװW^5}{'-[>0V"Pzq;!:ε{3;y4 Tt/>zqT~S}vֿ}i$,lϛ;] g:6'vΛt/SsؑI{nFxɸNعߺ~ԧ;ͣҝvxb>NA=+CJ+ܯq%)fȋ?j l~߼q (U׉Kx}Y/o2_Y-g>j0|$̻ !q~uN|[8kq7w8wUE*֊. ~[c>~/;h^%dN s`2z o!n\siv`#"\ ~^#1K~I#إZ3誡^ UC=k7sg:KvmQ8|k{`!ϒh!v:}`/[{/^Pɓ}RI-M3_ -<&U>4T|F%o:\ :pک??lQ=z-jf6-9K!XqEW޼d/{y%$o}zKv_:WTmv%eÁ55}ʹ.7k{[QA{$']..rFȀ]sQ5ybDë Fe=ɨuXYC >x6yxUzi9DK0*4Wy6G/iQ%VEK女>%' zL?`JN^x`ХƫZ cL&KNIw_Q`kPKܫ/KKgyHJ~ɱ l g6\lՁcHcTyŠ3rj%Ol 8->l|*-"QjHߚ wZZ%Ż,3:oኗY0*!K C,~I>߷_<:׳36R.bΝ4}Ě36'6M * 6}Ul <)%RyuARk Njțk]gTis3oV~,}2$G#e7:%G`"H_9wl7ߴ óIJMW`GQ 7.>W6᚟'yN=^FXg/1-9ցySZeKnN%K4oعߤzݬj)wWԹؙ8-fƷ$,1V"J.|`#!$SoQsy?>~bHEdJՉɴH]m0az qxꉕvjx -^6 7Z|l9{h3-|7 lwMA&5 3oz.om8{ qv lkQr8LW -r}`9/)_rza>ٽh7bh7^G.>Wz2'vK{|6{'OqkhW+^d=G+~ؠcx`-KjJ::>诵6uC |l~ߌ Gv-\t688‹=fkیsYo#80V>#+߽R>:9;!nQ<݆Bm5^,5 9ld]q[} l-jproiN?V9.'6\Rr kubiaAOmUO -*g߇5׼$œ5o< gd]g5o%o:@-lYgN?!uSﵵRoci؇{S?䗜JU ·nUsc9ojMa$'$c/䑾Z5:AGrH |,nv\gcΛW?l\'{]6漙i]M1%_ySy/V5r yS|Z;-RBbx5WobsEN86,I?aikN~IGP䗴K[ E5__\*_/V,_*CJ?Աn4$XSW=U|,YΛf|cq %j]؞_R۝v|6Usf`&i5>yUw8sބ WBm}n_ºz30,&z3(9%gY̦yHm>lSwFmty!G:M'y^yRQm<5y:LRp .cz(1/'`>?Ɠy]wCOrc]/߂]܅?@?@;HroUt8Γ>r-9S`El|kJ70caqf}{;6uS*a p"v'{ܰ?y+ vgO }Z~uqKɟt:+ $j Irq_U)oK TP7.4ZP,'ܢHA7$UX:PFn4P<'}AVot?YSeK/j!_N_biȈ+&ī&q&O Ϝ-/Vu9cɟx7] OM&AF.a>[9UjEV>|vd$x_$K{_oxNk4E'W$N^vj/9:iE,H1I?Nv,hj}0.U(*$qL:r"u OFz%=lƕ:X}7o;/12Ģ;8fqckWi$qkh2 q.KSk+^&%'RM}eN vg"=J'6u՚`T_Ba9$}4䆶xN<lyn:f]“>rWO`X;uT g! _M(|o$>yAֳf9yz;̅Kַ0IR<ߋjqې؜gq <UӆϾ8lW $%ٰiY%R>+>?,/G)MOk.gK%<ד_r0#}'_r݁|eKNG}2z9ŵ~|( [wmԁm~( {6挿 hiK}zTce}/C0ɴ^xMI9ekO2o"JpKNqnykhKz";(F_܈8\~ TuqH;}`ɭsGS;NSkH%ܕүco1hNJ^$8C&c%M}` Pk&/5bV;oޙ ۘc6z vTCsOqZMOIxhOqZxڳW֌x/qOy/Ѫ?J[:sB2WrO}x#v^))O ۀضrֿr_zK3؇3,)/iK\jɀJ[iSPMh9ԝ)pT9Kqnu|!q"lM\Oqsz>cϥX]>5oZ>`R9oU觪烦U1-թԫRRnn|bNR>ɟ-,-4V~.zjӯCVsӌ|'vŕC9qO[4][Mg*̛yywJ}lvg_C}qh>aCQ@_SĤj`G}~ߚSmP-w7O^N.n gFuHO7 *4K)yHȅjl|76Kܰv~(yu7*[CdnA:f4,䗌Q4(^5ϕ?džĹPۂjXK: b6M[Y~ ^P'ajP:YKESu\vY,_r_?`'{+!sOE| K튗TrI vKsgPǶ/ӲvZRq߮؇ԝ!8S }aعTsF"6j~ߢ`H;b/v|#NQ52/6hJ9n/Z8@_s1{MZ9j'l> }ǑS̅ƌOpo s1f}׼?-^)Qo |sOKsqq\zjc5ó{K:Ė0Qs{U.V8 Qza>z Wە.~|SuX&5xkUkJ89oVc/X'gW6Y>u=eda;h,YK:zךyzM y8CXA?쏇|7Epl7uz]JKeY#:P[H 4,qχch r8s~'N>sؼ1nW.Xaߴ(ַ?\ef1Ԯ[K:<<'G +^bVr;J.~ɩ \*?)l![M!gDb#p;:r\2:A=@,^J{4&3ހbg *"(y٬d\Ǿ߱K$؇oY:&O^o%w'\qOsg]i{bsLPKNoD+|OQsEGMc=`-k.;ɣբԁaW=Zso 8eyZK~_R8rM<'c' r~oԝQ[daP 9u;y s?zqXw۪ECЛ2^q~it8=%EJ 3oʍqXlz ta3\gޫQѝi.؇Q:KjQƗkeY̍p.}M>W1)my^.0$}=, x 5==8\s cxU]d Zؼ&f>ƣ2uxw@>fUSN&mm/-%K`Gy Oli}KQ,~g<_!G5t ac# Ӌ^[gT]~5lzÄتHDqf{TQI/[ɠ&,~Thq=g/gdz{* ,}etycS0o?zi_غh<ge۱pd]zsWK;Lst o&)> v(RӝyU!?;񨙇*`8w^=^Y>bNqmk"޷!Vxd;z 9ƺ^$֞eK%}'\mNH-1Q'Š!U,o΁so{mNQҀ7x^;EZXOu #@|'K|<~A\0GƘCd~ c`0Ҽ%g5nc;WX|K7;Ė۠z8%iЃcrS'׼B2%EԿM=c׍cO![5nLj×ȍ] ՘{pe:/b`܊_:x_z^;RFmbNmR֨b[Fk(^rŰ7a{6'|ڝIpH9֕ڰrT{QwS?OO=p>[lo%u璉kha'?koݳm@ ts=n8Ƴឪ޴q} vX?*7^dUzm_6k`"a6>}67. ;$Q:{6(zȤy+~w4Y!gdӪޔ ;傜OV=N(* 自!Oض0׽5q}KQ{QJ0W/yxFq_SGd)~->:\WclJؑ8:􁼶}\ qR='8ݞAS֬ѽO@%%78u{iqj&Ml)UWG\,Q*;YzkHc'Cc o,A0ǎs^Ggw{S3w|+~Iۀ1.sސyܿ{=quttX4O>@+dV~F؆{􎥻r<Ug9.gՓYuȉ=[oޟ{ؙ;>xpYt/{-<Y5nF8?wl|Spo^GXwU;ZH+bNxBϊ0<VF[src ؠ=KHvlwɹ'bb^ m/őu>`Kd07_3gbĕhO6FpnQc+ 0F*ӪvǞ|@K6 L| تºН0Ϫ8ק_݊ۆ%6.ՠ)~Izȱފ_U@-Xc\%֡>`[#w܀S~N<+ocQ@,lC6y&L_Ymh8 FWcO5m2vsmQzMɯY3jin~z T ر'oCĞ[6{/1l:l߭)ʶAfuyNmtNЏZ|ϡq|ηgJn^]l߶g[q,&%vg ,<ǏR{o2&K`b+<1(ox^xGwGZ{TVQ?̉W]'3UcOgWƏ$;_zk~ؓFMжت)N=yVwo̯yFwqc:vV>Q^,{XЏQq;a{ǿ-lo|];:=M j'0||s{h| cϸE q߼F':ͱNo7ҲmQ9n{_S{Ku(~b{ϽDPz{9^Bg9uC]J#OYv9ݱ[ a6͌vtCR8K; _%:T@G!6#8ۀ] ؆9s^ Pc+X?WLho {{Fz~W ag*ǿ3KF齊x{\/qmf`NZ+O?Zu[o+~ ھ\/~ s({m4K(ʒnAdLHW7}-n{6'п)5a㤀XEPsr>|>k*grx M@kգ%w%^ŐSo:'ViþzMUJ>Ac+3;i}8צ 碼] y]Q~= wŞEXqZ鸐V{(ZzAZlYotoۊl(ױ~xAďxKk5';q!A3qbM@{y / ^\7X8vm$ؿ âb~[3xANvxA| oՆ(?a7‹pW.տ:ϼƭ$``Hu<\:軂}!s`ˎ-|Dx{h0c3k|C] }%X7K{\qwV}X%ʇq^g^''6'F:`>3ߗ0.Jm['X3nϷ}}ꌬ"ṃчP, j`MŦ>z;Q?ST3ݨoqTzf'6!}O|SX_ n♕AʼnGk(kCf"v5=~4TQZ ݡGwĬ|!>bVot%|9ij5&3H;|4'4'玴cٟww½Zv\kCN}CfT< k'u[oOIz Қm1m] 4lү$K4أ|6#b%.Sk^ D~+v_pһ 1.5 \ǣxx_xK@~+8eޫ`;gJxc_E+:qک:er3cNF &rʔ9YxI8r]o*|QO;_ҝ/< #_"k|kA{[3BwępnJ4;,ñ0)wDM{Pk*/Nc''-p?/I'ck __^{ lC퓖쳳Of|NسON[W}mwlv |@CpŖB92͠q]񫋝N;q{<_b߷1JK7T叓FCx Q[noaV۸ndOkTO'O/[}{vlCmY:OJxuw~ 1ᷕ?Ĝ/'wKlQ$?=-VlqzoY鍵K 3o\3Au]?9X翥a?Ϝ@⽾̇C_Ys]S{oyg)NCv͂CQ{ WtNlѡɱ2^;2e9G̅b;GDi ao*q@?3dz5{-ѫh7gܲqr'3/;;co=>/]:߾9Hpw}ƞ5 (8>{6a68sg Hq03nÍP`θ %n~8c/8޳2[Exm֍;&r\2pZ״ۯ5=ЋyQ9-:׋4ܣ!I<[~{IZ{II >3nHs[gDn}RȏtW9HYiQ@n!_nnÄS~4j?FW:tVlakqi9P3n=F^|sjx> QQ?46m΂5n0-[|$ኽ|.7z[O_N! ꇃs$ݲuӋ[JvKFrz;)$B PxI?9 +369j>ntxk>|Zے ;o |ֳG^ 7=s ߾ nX?i*c9QG[سO09?CM,@Sr__=Шȥ(gvބO&b U33_Ho1.a4yt,r(PtC|Z8(NRl'B0Ύ=F-[:-61'%C ԙ|k8fMqUC͵Q3Y<O$HiY+q'n[jSs>RNV(]5!}d܌Q8ȁBr{.?50V8zzi%γώ{x  אƬvl×o-ޤ<#'Yst\oCܯ,e br^o;0<:X?|ײqb{g%|kMdCInWƞ<t;hY<g/]9P5_z=Pz3nSoqMK$3n1YЁ#`Qi0[9*γfb4h<6sG# {[v۫q{wzXX{fIݴo̓O:ԶYJzLa~ <rKC{ts3@;oz+c仭S0s˓o^55+V%&/K:zmm5i-gq0j>{94xoz;z82OACy'/~I"(cϸMOX+)֮{KcҝqSd6 xʅXI3ɿ#K6D1':&q^GYK''*[ mc0އww'{' Z V͸ѝvCvǎ+U_cgܬMǁ}'J UڌVuª|h'6' ꢝ?;"䄣U-I{LP/z G-!ʝW7r?eOT<աLiJ['o*c='or rGi+5w)u!IF6Q g z9ǎ| b a֛SvOڤzް$lFT@WѱϲXM[8 C60(L~[1 /Y?!@-&WXK MYմ lzFX<Յ}r9ֲc>@5%kޣ_C df =@m?Nj4«c!'F[8X|=ኸQ(8ȃ5xi՛"p:ƖoaLF'{R{ &7C% y3n>qDL,֛f6Xbq3n݈9z=㖝Lu;#Ig%-Hkk?c_xDKֱ? }8Enu[oZovٹb;+Y (#U,{ܱط;/nDUg]w@ܺ|G(?*c}їK#2oqoO$]5l"*IsEQI6b WN#8~8GbCk'3'l;fyvd•=a\YKwnru1KӾ3/glguv-_#%/(Н^}|pcaczN:.SXj:ܿ篔Sm8jtom,)0sLpѣcsw_8cq U)B6~T-0jb{ϸɱ0z͛+ł[23n6i_a{͢jO;㶖1כqwmŞqө3n_⣿kq0w̪ {*=qS{^mg4x?vME2u?ߖgm|wϼe=g7׸ ^-E5n|fojwqm!5nՉj^cwh>fWw9s^[·9x3n_fYw0ϸ { s^wۋ-/(\C'<9Ao23\?_OWp,5Fg ߆Yrl5nX OIУ6 =b3n}'E^w_~7vb1lgzewci:I{ƭ͗1 gܚ:J3n/o=n?~(ש'Vilg^E >/I$ľχdn.+:~Ww=/^E{x S qKk_Hopb_B| |g({Izƭ[ ЭljDZA/ʚJj8cVm ě\7dR,姴-I1gKJq_baIq4 mKl>$m+jXឬ/'W|_c WN)$XNÉ+q^+ Y8tָFtnyI-gܺ1/SϸshOkerc+w𴪣b}pW- YgMvh~Ü,hO(jլmnc|>OzҚ聆OV=x.Lܫ''DlCV."[81:vm~xA# (~}˄ T=vڣ_|f @>?2հy&0ВYzAJ:N9"\9jl5m$k3_mӿI.6߆>X#1 ^%cl/_c޼vsYOs>e}vyw+"a~#a>T=g:޳ޤ{}W[zx)a=;cV,_Ql\-H)Ѵbg? vlut'|cnS-\ӕe۱ZzڬzՎְfe yDBL`gDMsG="~6B\zmBzL PbX=טtp?Nmr+.)Ɩ1-|RGAن ti1m(p__Fn3b)kKg`?^paߵ;|p)DZ6 ^2biߝͪh\??c\%s/;غZE(3bϻ¹Yh𻥇7魇y&'z^E˜>cos~a-$mw7븁9vZ9$(^ۢtCG0O\RVwl݃4ry}v%.cclݨf,WoĹ>; V쨻'blw`dLƸѓvc;F2;pOyvy{q0xN}};` -;`],4<:;̝/(Dܿc,E̦%sPk0^uBz+KݝOI{%2a+~:AW=9'lME/+<5i9cϸu4{D]7$IXF؊=m(ŪWkp/)$CH?K8ۦ`^UK>_Opa+Aп豜,~ 1V)mjqxhߌQpŞqA +M% }4yw@i[z[M-B؎sz 7" +D4}m Vy3 3++E*9vdNm{tFpO'3=>m}FʿAaO / VPI3Dڱ7fW{m]y>>apx'{KñXq^[.q}twĞdޫ/=ļKXoU:yA %UC3Pc737nvӊ=̓@{jwzm}-_qbjt[:zK|?U0s%C㬽 b̦!OPlh IF=^wHg(E8;U3 oYzzX[К82A' :[pz鍾wl-s_qkȯn*Av|V=Η|'Ήݣqj o߱UFF Q82h7_Um9R)O{0[ F mz+8R4}Vօѫ*i焷5nX߽`?Ik ;~֛&I>=;qvcg:YWM'u8S;d;`r zc̺s%̷ WZ} ʹO~T߹$9ض=ɵgcR{ t#PYWؿ1{p3oO{-;HƞqK5_6q˗Ъ[fq3n䇽q{_ =r-;9T["7㦸6[d3bǞ[:8z_ǥ_a. gqA |W76hM/θQql7|4P`*`G䎭掸S/sY/xv^bMԉm(r8(IJx+D#V6qK%W:毟q|߄ug|ا銭qK5tXo~/5loYH\ {ʪY_![~Z[cٌk!>_nS_M/+|V!Wb WT'a#Pclzۄ@J50s)ה=թ Lsޣ\J5- Z+̝!WJ5 o'))}W\Icp*~\*R))~l/x*~IL]? ◄ 벂6$ho+~7dKܒ|+~kѧq+~76]Ʊ={gKK>bKͫgNwZ\C/1xVǻgKl/~x./7RR|G(~u6Ě^Ұ Y:鬋=a]hKT DGcmn8%xGiK *mCTI!cBP_^mWw;;v0%$ՂkK:B=DD /yH}*z%áp.lCK {Om~q|f xq/vuۋ=ټ\*۝@G^tKP IgxɊ'qQ'}^$Ӱ zo=-udwqNh;ӟNo+I&侴qɱic:q@rŎ;Z|DY; qK|ѓa]׵xAEX- < 5o]3ׅ'-:%XUcT>A+㬻ᮬUGaM'T\51~(nu^?\ Xt\N:.1&{]j9^.6_k GwL=ՏLDM=*?OkSQBuթ yƹqgqI`]ϡ 'NzjTms-K˚ɂ: Z~"Z~n:x/)?tʹgܺ sN;zЍ90n_2 (CKY'<*WYo͙q-~Il5OcAG/Ȃ59? TgZk۩7#ٵ-wgզ [zxzπl~3,>W?Ucu{m5'`zF$> ޕ/({Ig([nCKbN /ŏG<~b׸+[ R/]oo=Ժr I7)yڱ àV٪oZ/67 i]ptgz#MTE 3O6|in3nbc\8[cԼV}lm1xbtHe4:7Gy[:= :#Va2'Ԃ[4qҝi [z O\ nzNNf}IsGfЪg첿gp]T=P~zfsSժkgӠҪ'Q|O~cϸ 뭀ǎq6y;֐>IvlQۼ%8MG5nL3nKq v 5V8Sj}2w5ʊ_Ҟ#o;`N Ynhg~%ߚ$xG,~ɗ 'NPf/i9PP`Ll>e1wlqx@+1CK:4|A7+!g/阏ݥ4XG3O d/]m^_Zgp?+~ Jy◈jE|~cwc}Vne7;Ix_/~XFnI4)bl%'`4; z%6c0W; v%?h6.dK߁đ/5u[AFW{%4]/oaLOˋ_+VI◄p뀣/ J`>ˋ_\؆c0M c8pWƺ/~s}r>^x -[-F8ƅk q^xAbPx+lD◸p%ckfX\Kܩψ/qᚊ/~%wK>Ă8 ߭qCzKl cO6n 0c {KT'׬7AcuQ51qϷ4]_o\dP//Q#yKt0 %h9S\/~q{:ã216.Wk6_"{/w&yKF?<\}2:^Axxm r-v'3@5yzZZY3W j{闀 m01V:Juث%̙z;pjZ|z9imwsŭMㅿsj:VgKq0y[Wwƽݑ)Cޕ{qsV\NqFb{t}o4p ^Wz+WιqK`+{wlx u[dE-/wKW-׆S/95ώz2O ;2"mk <[(='m'Nz6'lNCK9KHË[G^o8yǍޱ',ɴA%yت;%/^8?Vg2쓒>7؛K<4h3otx%~8F0~[nҳiQ8<1+_U{y t=5'^xx (5}u>cQx q0~jlm6&~%T~ ݫw/!}/ ݍXWW/w:_vD?MC٣QK%hDK M嗰ZQwԉ$QA,QΞXXAod1nj>U? /0o/p6'^*-Mtc /I5l Z˛VxOώ5n0? ($w_Qxρ7 y#ԲKd@4 /9)% XzD%5!cN%՚g ױ[aC?^2ۋpN9<.vm*y.ޫA8'_]u>+ gߞ7K+_ \%bJS\STlw'j7ZC/ym-Wd Weͯ KcKw&zDCK2$4w j91^PA^luD/YzAA^_[ƍ- n _DcSǜ0<l/F齂@ws&T*"뻣Q9~7hp͗h2;#ϸ X:0{2m0Juпǖ>WҜq۰5nF7ocm팛 ʓYss^gEz`ly>ٮ;:/k]mwbm/D87I⵭X^zx}ݣ[iO&}~  |ϸY{.}=㶦60R(Ɩ CRAԆY) 9Zi?Q,sq48 (Am}WQshikқlo;6QFo'qC Em]߾9}wpw1irm:yL'g-qm3~K>z ˸Ϯkt)nqnF-^|x>wu}Ryw9C|cK_ξ#bj+;BV>PʈȮ~Wy6<1MQ'g{M-]l~}iSK[wq{Զp9j^3n_X157ð Vs|Jw>4Ӯ9Ǿ!쳫ggX8(ֱb3WnULzp,jw~{M'k] qYx ie.μxQK9iqK W{fK2qHSP8_G nCY>{_s>_2m(w+k8'EߗU3[g/dㄳNz/ǧ/wqfy != / [4 /nrYx+侲^7.gkO%:K:c8 /iO};yuKzr[W#*o=Q-mC,~Icfxn%:(/ _{K#[ =tE^ģ\!OW$}7ma\ָa2 4=OvYfKZ(87zwZlCݱ1,AlAA~I나~Ŗ~ISɜzG+K? ol-wJ7l 6K־!VQ0D{buĠmr>jJ[ޗUВ4t2|Xu wJcu,3cFXPN}@{g][Ӷ#qw߹:9w>9{Gͧ:NzWsg^=j^ɻ<)z->yAgʼn#0>>+n6\$M6 𒑝Z3O|[u*JmпQ?)̳:OV}@#riPK|[%E⊽>b(_h0nWd'f`l闠}ث_w{пWd66X2vurr. XQ<O6Dر 3ZsCW~V8Y{lj1pd( Ud >@quK\{K:jl_rl]Vxkqc/ﵓyB2ocrNs /8n;ufΜce H16w'i?jLW: b?\?a5g'']?ant /Y[5a(Dl*?a7 oŖ4jm ׄ5T~5bSƢ\yO%>g'lB{={wlMW෕9Yvڣw?mDv4 , OU:]`nAxfy7z3}2>tG~Ix߉q܆M<x +ޣ.Ik3p,/qqOiI?h1ؼN3op{/3wč⚟jJ}6\1ȀsuwY|7pf񹔰qߙ?I{Ȋb )xvæ.dj#< zyyx CI,/guaf#R?Ը 2Sgָ!fn)gXoyyx9f+w8[z<؜vyxq'l5tKũ[<<'y]_ĕO:Aei|oƲSs$MgziǎO~Ɋ$A0w*VXcη|.1z: Ƣq*cXYkqbr{o|m_ݪ9l ʹs`SgdV=eCxg=1UG5i]늭:*eV<[_k%^ل~(~|0.D7/kӱ ^._2}RJ;MG\xI2[%&I\A2vlwС /íFU=HS@CpV]q闤^2b.+xxymƖ‹۱Ƽ‽K], ٱ8/aB}KesKg[:CW -X/}K8~7yr(~r]ھ /Qg-:%:vYco[Ǡ؁d\=s;{'{q&[*C^ꇧ?F-618^Qy^GzKtN[0l)~Iw9؆va_RyuBq]?zwҾ-Kv7dF5W*GǏo,+Vy8=/$3$.cq,I剑:?/D}PSo>c_| ;%m=5FK3(g%37yٱzϺ_u+6.alR|#Zʜ^9n‚`(^2)'<7b /) lr#b D-lp'8#)m(|[dwt?Wl=ӝJ}vIhCl:Ď'[''pW6z z['L\ C-|r&tcLl'?7nᓩj '}6.>k{ޜԩ! 5+Mi;Aj܄qO >I%73S|HK^갇o# ls7(dgV]F: /O[zA|@Ϧ]])csbo=3c+/v6T/{u0&_b!/X i?k{*~N0nHcVlupV]]@رOdϱ{i~W}ˋ&`xRxIgm3ؐ# Ghc}t|RE8[]|/4t! ָ5g wܔ%g{Ԥq.'-fيIȼ߽uNz5_t`V=N?MVySNyrʤqfԃ[;oc͊T=Nhw.7IՇvsob>c{I_B]0-u8߱P /iTkÓ4ԝ9:w@ʊի-"k5`0T.ib2踬zrq&pq ɭ\6A:lCi [%`~Mī`qz!N:֬ȧXgzm9Sh4[һ! tlC)Y0vqKt67[\K؏^t8 /1A^ /2ثDc}Rxwʷ^hs3Pw ~oC_|ܷN>~8aJ/(29 2nIQ-q {̹Nx2#5nS6XWzfT/8 YW gU0g&i,i=')Ӯ07Y?CJ5ʿEy?+ s B|x}R=R;6yS-lxjVO5OxΪ!MQmk\w-gk"/ prq,:amU'<Ab>ɺC m V8ڰ0_Ҫ܌B~S}BNV=xiómǎ6X6\}eW,qA[n o+$y3xr ֦/ =%gK287S~9 ET.js},Jd*qhO-MBNB~ɤ3ka{+!Uyް6JOعiUKJ]}OXӘr({鎎{jڨ\ z cnoUN~5pzpWkyׁV8\[ /!7ժQ֙ڎcNѪ!?OXUŏ'wo}7jT>֪ǁM'A/Hg(ri㌗V=˙O[7: }V8s orPKɫ;♧rfKB-~I7t\qǍ9YZ ݿbq^Zu c㎱90vd^~7-sr z5 *Sq_WHXͫH۠7Ƹr^P:*꽾̎5njݹ__\u@g˙BGo=z|gָ!vܯAǡ]73.Zo Pj[$jl p{-~ɧoo P!]M'.4,olXf~I" 8]~Ioob}l}O[uT7cR{/OP an==^=Ĝ5л4`|}@l؆1 oj_/CM3LS>H.z끎flj-.8_cQX90D9ڄVN9@LܢؾB{_i'CKz.l\}e.~톿펛ޕ)W?+a ɭ&TԍwzmY /X;i4o%}@uj/KF6^"rvn G[+7~cŦ\!%qm^2w'hƙq#_VxIrhKr06XvK>c:>x "fxI+vw=/ Z6=w[lS^vjĂ^BoS ʿ9((I®%6>6ONKH O !8Zo8A -G>Ƹ6:[Z wwaC&k #O7yI7< ^wkuz5 a{ / Bkpqp?o[ _ Ϯ?N ខkKXsޯ?Nn+(|?k8}wKGYտrX^2HVZW#tེkЏU.ﺩ``{xG..7噛&0<ך<>3O|pz8pO5>@7{OxN$ ;ձw^;rݮ^P'^8)\Uۿh?zW`Bl)kq&sQW=N` ('ت3۠o$/|Z]DZV>^8V8ƣ>Uy+ * W=uqdp[uG\ ʝ9#qM98 "1_/|Vp 3Yu| | WfkW׽^mw˷5{~ј6,oy'.Yy alyNVxIZ׿^=o9O^x|Z/d:$&[%SH;ʬg);;^~YtD:ga^wvoHoK|Pw0'=Vj] :+ bmKyn6KPS(%m|5E b^P\ޕ 6w}q;%I8~p ^:_h#40ŕ;f>.Ww(#mdL@\Wo;+4TK| N&`Qx 㻔ָa^wY67p7D6 /IF%މ߽%aW8 /YONy\(z(Dٯ0(D-! N0oγ/n!Pg7zx\[x_&hm8.^Xۜދz{Abذ /1npK8N1ծG闬؉{I\.J禩CJ$hnxhCtgi~INzLqx ֡/ˎ-@D7.^20/3KbN\Ek'ïQxɋsG]ָxIL~o]Ʊp*d&ԂKjWkL>̀ԋ[zQx ~wlww!%~\# /1ھ:(Xϱ#K>WmU&K K H= /îzB]_t.? /9` /Iq4^\B\DHsS4;X_IYG\\^K^YKun/q#"n/ao>/ijqlg^w_ƍ䭾WڹK纂q\$KGf%{_P8 /ylSzt憺Bl廹{crd{,״xL͋$i4>wI4:)k9 /nJuכ/9g_5?A +3BwMy%t)7wUp뻻 a޼xI8E^2Cn[ksKDۤ # Yx = /IzoX^p)WOz^bMSu(ӊAm,Ğ&?>>B׵xAxbjNPA|K:%:o=N'o0;Ǩv7?a#S7nf]pH 1y1{>~¨%5[U31"ln||-OlzY8c!O[89;~,_%7bҤƚ7oIKz}Z;޽id׬,40#Vm^~IUdKf2A Hdf=i>>МAd:P rTYtI/YH-gf8}@w{}8v}]aTxe@s+Kd~&jwcpkү4 ?IoBN-QMwC0@oQFm^Yx qd<* /a?6V#/^uIC%m2'ulC_rآzwpq%sMPgtυ/|{gq},Cl(dl}nC'tc Wh5 Y%1 _&/fmW#尿i<΋ g/~Tu^.&_b3tQ{ѧE-,~{[F/{rXfDQ#\/քp*~ļ4\VC;ݞ[ m|7YsSw u'.b+m\wO<iuz[廃Z>kWlnFo8ico=N#4[V%yc?%؆/ [S O|rV}wخwSпWNq.M؉m}lB_̫0ׯ~ zw7BY/{OuQ! /Y[ihuQ؆[ /<+~ iUAø]i._x5}%iwb?FJ;Wu{=Jckܐ[ oKC}1Wmjs$LʹoָD^ECQ.VD>lqhC%>ks%뭃Ox^~5ye}K1,wkB1h^Ss{}Y!bkܐcBqڳF5n/^{%V|(w/Ǯ ^sxofu՚\~ bsq΃@츺oPySz-k^{qiѵ0'o=Q#0Sz ׿ q-|[[`tWlM^-TzK<&FV~}/~+~ItӮ' ~Թx|(~I /(7oXo/I؆◄ӝϋ׍K*=k=Wy"4ڇ[6is%=e^]ܱ =GlVl6'쿽%h5Zm N/~IO^{ N~)pS{q\K?uʛ qu<Ү>u_7'bXqš)f'YKrJ}w/_l{ixָ5lϺ]^sl;[͢{~=;V.suOl{V}w赭'Ke>)uPyd=&B]Ws bv }ثǹޡ R|AǘYWy黥gjS=} zxa#%n:.tV[AA'}V[^k7qu di߽![Como+~:.~a' c\ z;eP떀6_bw|Ώؠ{K,רXBR~3ڼF/}w.^!N,~ E^6L)[u$oXPc|cۍ @͛vk>)-[Q]o>|.G3_ IIY b^"p. zd"o{S 18ŇQ?;o0&\u1n蟼)|$N?[޺E x^{s(/ֿOb+3I#i`l^{R F%hƆG Hw=M1Qx}W1n {m9K9:p /Qu^og79⸍!!AKl(8{/كnRhC%C[~[%>{&*`Уǽ/wOU%IKr83ΕgњVxI$w6 /vl^{ʀتO}vq^bP έy^akW9k9[\Wd+v^%H A26yu h0'пgpʳjn=P ՗b5Q碚+ ۱5'<̇K^EH[#/8/cyQxI'D(GIwK%(3z)؆Zom8 V/ם8rw&DL /Nدx#j7W&s^dqWW{u^ Έ\DH$SS&`RxIc /[yIWS@awϱJcQ\_;>C{넍061ƜHљS8w /b]GjgVlj5fo)8aБҡO%%,ՙc6KԘ ^̭~¶'bWRxu34SwR/ .%CKW ryAF90nr %x*C- AY%aJ: /I͡O /Ǵ\DKC%<>%-$i4n6?N\s WűTXDžlA alb#kiiEn` /Xß{Sxɋ.-+iKϾyW2bk` I%,H /q}m|/H%/Fi(灻(X/ 8e, /Qۻ[ /d?N8A~>M黕gLv^9p'kc꾣V܅G= 8qqA{Fy{{ų%wy W5H+ 'ĹW_FF抽3ok;|%o߽uO6 /I'^m>^Bջ #``Rxtƣ$$/Oa £2 R X5nb \XWO+6@f^0GK^=~qFwp\H1\]j^_0X_=v\[?m:¾ í˟ĥB~LL~GD-u Eފ뻞쿩¹iɠ_芽ݤc ZxIzu }K z w|GJm( |S@ yƩ>q#V4t5}Dث͞șK4 ŦKq)&a?ĭ"Z /!-]oj; Ua1ŷtnŁ3zq.a¹{^ܙ ؠ^b0~SkZ헄g/(Śm-Qys&|G1UxkO Em7N7 P^b׌j91KzS@ݺܖ9[<f_Y/^9Ǐ :7s6ӹ p=]~[3c~@ã\"w /Y:^:Ӧc_Ҙo԰J!V<7c7>o:ps{~IK/yۯgp5&A?q}p 8J\6k~j[rvq8[ӓY}VNsg}[{ס~ i|]~ɠ{}.ĩ2]hIo=/i] \(c [qb`\W!K.Dzb^"ī^"N>`_ؠ\7Ů~I0p% 1=zb?ܼaW_~ l 8Ov%XGR/m_2m5v%Gqd䷞㺸F5滶b-ԿVxI4K:i7 /!}umQnFwH"y>bFwkhtOXk/;-K8x dVxNy+Ld0ƅ ~lx٭[\h /Q:*G^r{Z%25/D8sݯn(/,1հ uEs:}abp^2:2p,kP?ض]Whݼ9 mojп4a͸ [+LWa_;~V%7ŧ.NV8-[̅CQ{+WGOl]z$)'zDܞ+I^+)?/Bcl߂֛m87xaňX%=~/?7p>U#^'C:\ͷ{IۉS+?a:.xͿѸooV焳 l=߂3˛18^zގ gio^z6'iv;ҰBs/ą0r^xGg j̽]_Z%o%5T38o^BZ>+YL0sjFY%;6Ś+ ӹ+̝~ᅗX'U1녗K^xb4C%%/gW$W5g)~K$a ^+^_g󋗠Ю5t%IgoW[bñ (78\.>I o}x>[~bqhm8>q%b۾(76* ?x6p{Ǣ?xlp%u pU㍗7K N%` `K1>{kvj.߽Tbcb+vۿ{/i8OS\xɿ;U@Q`/w~?1v.xɿq  /o<5,u>πNC=n}ڞn T (muyё/YxͲ纈]+|5:-Z۴ڜ c'>m=H!|Kwq>}&ےcxɿۨ16(6^+v:0]#Q;xa.)Fڞ+.~RC!}?xmvn{@ac6>Կ[viD(?ay^|L!~椟=J6G^s;W.'<\q6ƍKFs<1K;m${`Zw<_⸟5I=盘[f%6^cѿe^/wڛPKN,2#_mp3lo*5n ͝ /Ox'Cƞ{I<K8L.qkHU^9 vII2`^VNO{%pfmOc%ݙkKvvUwc`lW9ߚosܣo> qv%pݜ2;KȟD3ܔ?-q?KubߦQ8/^P^qj?]@O!ap?N'orGH5? 6Ի[J~A͎͟kO3Û,6^s;` ܕ7^ 㷞~׿uNYoûft_Ono=77ep8#Ī!6⼻ǓD[7&:/niomO=ӟ ;3'7qOYXQxW,WX?x!Θ`Qx J?٨_0>ِO!g;Ba% _8};@euq/}=#>م"_7Vj^ޛs~Vx=C ~[zS{:7Ms%m[?scotch-5.1.12b.dfsg/grf/3elt.grf.gz0000444000175300017530000013624110656300346017145 0ustar hazelscthazelsct[5U[:DOwМ׮1nNm)z؀}nm1~u5{~y?^wپKwߵmCq=#ngֿ_o0_?_n[vy 2ߥ zaz\o1n)pŽ7Fʧm_qmnڎ+!?_KAC1-T 0׿}EC~ o{FP>O:?wHHޡ}iFX-4 I(`+6rv+7*1xHuy#15 [t6qD۱Bƭqv_b5th"l__{#,}J9C_41lV^G'  X(a`'7^i#}c~~x_)͌>`>&m{R><¹G74xe">s}}ޠvܸC OeQV-Np*hsE}~ 9cg8ttw_^a$ϠOр,ntp;Jhy_-;UQgj_7_g=1x@F+^17m(yT; >3G;Dowа ;:;n|Gwv?O[C;#:;~] ןPiV3:' ™EY!i֫@ B){/.N;"cǍ 6ܑ/q_ =XaOYFBԌX _"EZac\侽VwRwߛ0ur + 1pZɭ/thԾNg3)PDmB jFƾS+J~l ǰEoQMeVik.|)kb\d}#"BOaSM*G wiP}`\(2vLj;(*1;o:?[CK90u?]ȿ2E&C߲VƏi"<8m&" x[8}ca] b1G5~9C:q-(#~#b,lcrB[3 ,m(9Ǐ3ѫEjŲWs@E~Qjv <\=Na# mkzZ+3|HDP3SLFJ ENbEElJX8B,m[(xuKwXcxv~\EXcD;lN^ kZA{s9n$ R =%gd!Rbv=7y 5TCX7hP+Sj"7vzy2Xԉ؊jƌ7S !sJ abA_Gm&: aP+[zWKGXIBDlw_,Č+ pD :O&1O㞸wd0C'K1U)ѩ iC% cٴkxd?}?_= ^…z׉E^Hbu1p 3PV6#:48D.VFO+m6 1{KʬXzr\i錱.Ǵ%:_u2ѝbt3%@X,,W킣=^{7/P8\97) b%7u{_GfoL{fIPe~vO)hMu$@z50ʽ-1F>d~AװH`B*#À,_KttYĤ:zFG{**+H3bV]jͦ{ӿv@HzkfOq屷I VU[[NQ#7BO~r{+˾B6C9,. #GyR|Q S}Ab@h =WJDz\!YvCK6gC`A]7[FBJlwHO6ĻAOl65*1-n:B++B⭽2pQ;0g ۑ(<زN ˄}J𥐢Ú^`]?\{Dö/Ⴍ=oݹ"Le&E] P? Gyi_0xL z_!Z<8P6zA-#10s ~6_Mĸ3(}xУi ,i0 ]}ѣ%%FiXM_wč7N^ϱ >6,FTya+tyD%2u<46 C|=l(RoH2hk;@zK0x17$`߀:ų A9e1nGz+mGX r~飷pf LPJN#DHZ5@\]I|z R>w\IL4{:Vz xbg#R.ϣ*ȪO!Y7y1'=Mqee zwvO߃}C Ԧgx# ^ >h>kƘ(4~.MF|~V̑">M>{!d}i_bIxզ-Hg+^zo6}Zn1":0hc ~=$^[#V57U-ajhoy9:=ϓxP˄|ӅWw[n=WYhQs`ľdBN2/#G e:˰X)(s,KE=^ zɿ>u rƂ?5 'yoZ<'>\ x)3KxŊק.xT?JjH^6Q%LwYel!UǓZ|6z%ј=DǸX+W»-.i PQ>~V9WU"Tdc{("~uv;ER=Q٨p7u¾Td1DlRA*&( ^ |S f D.^Iw8E=c5~ݏ}+]wM 9n`vzf ZǥWmA|W  oBY@)a085?[ЯgHū8\* ~H „-yeK~|+2*gl0:d S;C@G w [(&g`MeXH{5qVU)PE-2>@I`W07G| ngr06" q#9`|aa6t4+ bU->2NـbG~ EMTd,`))q;ZH* v}ShN: wPfE ).Ԍ@Qԛ6t n0 s3 B/"P72z.fw?y~V,ag=_fGXw2(sĒqlMm_NJ_Ps/ŗ {r1?} Mr,Zyx[k!12ފ-k8(jomy?;0,dno*l5T+44mB2 d@оGwOT۩eV"] AܡeEu]}[İQ̅bI$nc 2FLJWn@؁8~`bhoX ~Cqp]JԀaN\mَ.ŴixKMfC̰9\O'QN^h1* p%Fe JO^Yx_GCekq(xůlBre2WG]w]6X!9R3Nӑ!^mi/THKč|v`pc"<%TI`jS 0 >xz_c,M:2XeHkT+$^eIڤ\X6ݷ`WXŇ@|b;wŚԪUWWEDjEh᫋&TӼ `U*pb._WYa٦YюoD`/}çwJ a"t zA6j@ ;#]3"NJoBUxg b՘uֲ_3x )7 O.vbʌ DZ\ˉ /_x% Cb>lLIB,5qBiT] ØN+ZW 4T6ru8 8YkXKmC!Rdh8#X@q~Qfį`B~e H(2< 쑉]<ULDBS`auE O~"V|5Ic]j?>!+3P z;#IvЫئkLOTb,ۡvKϓ5?!x4>$DϱnޡOTV·f֠'|[ 򴖚xp!nDᩱ w|Z8ʻi3>31"kȇ-g(m9BdCGbƻ:zO*^-#Bxr]{7v#{{~W o^7-h`f͔c*"#-x؉LXYDbq@&Ũ#AҖC{AU琧{n^L=A:(J2$ i|ciѐ=>L' G "/V-V@NF3{#Giį18ѱM<OE.z^.pڑZbg+nj 4sԘ,Ethh /ht<Uih3:F<[#wϪ_< o:QI="Wǜ„r=Vk]O}[H;5zDj@&zMY7"\-`8|UdɏRxoegb&B,]Sq ^ AE6X=>Kb˺+FQ9*&YpZHr6*H'¯GqOYEqG~p$>@,O`a62J$X@D|J=(?`aW>'=tXeiĭLl1xJY_z /юk6tDd.?7kݫ] ]~_|;%"<x9Ȍ ?BKzE%}O?(\В+1zQG HfO7HG$qooH3]<1QÓ:|[/ R[Yqw{DC%HDts0}מDvq=W$nFB`xG~,vM/ƹCJKxhw~+[ߦP!w.tnнhi4uD ?B˛B^G3{ dDyb\HUt+\\1Y5AlriN4]",sBqcti(YT^e-s'ĈΓ(JJy! p5N!aH󯑠"=qU_'mָyh/0:$n:$ט 7Gn㨁+z]km&+3FY4Z_^BZA엘/ltѕl8ƱaEZYE |%0]<+wIױXiYKF8Q96 4Bx?n^TEE9r08hJx Rg|C)f!`dL{; RѦq9EEGO!zwW|󊳮?Vlҕa*k?m1SHb: XD-ɻ>~QB?=qW$x+Q&EEwGv9ۼ$jճU9b$42u .Db{S|ĻӱEO6!U 7d3/XǢt N'3ApϖaP hh3'_Q7W ႞~\Jx}ǣtY^/à N"KPG6,֢7D{b_w&|?k׭^R D,qVwae M(cot_\y?p` w\,^L|EnLz 4Q\"$RKzKX>'k{u77bUkB'Gˮ9 DwJaqo\}|>v3< e'3Nw]HڛQ^wZB2![X9ZG/!\>{76:.zICIT G@>s#ޥa>FI ilZ-4xx,Lrl<ƌ٠8E(Ð4O_=:teWI[7CgB?ȣY`;̌$A4 E)0c' H|vܐolce_eqН-@d||pɋ=%c$ax:@ K֯I.R#MX,2Α7W.{]5ϭ&ib=lu,r z{5zv`mL޿XZF*썹0 DA1Fk .}'䈾_Tw|uVh5=f'?2MW0cu#jɓa'! {[0cn#MY\E|*G9C, -âr  d))6zIxۥ.QKPƄ*IO<^ʏcd| kb;8(oA!`W=,KE/D=ݢu[e[Ǎycc 9,un_$䘈567lƮ?W$?dmޏ\ @wG0+sT"0a7$= P°{czJ\TaP-A{/yc1,mAs_RFGBР2.ˏ۽+HATuo Ŧ`E\iD 3xhi#x2jA_Ɔ`x Ox[@AܛD𼞞l9vo*ovŻUuH*]I.̝+~]SPB #ty6 8tD|p_BfO@OzC@5^ 8 V. cQ1lgaA-|$ #ރ^ _eÜI2m/-boHRњ؄PXF1P/!!]|j>a^BXGOCXﱕ0ƸM~ZKX2M/Zj JBG^+gIG׆|,w TUCNIxÁ.泌I{ݨ4,׷HFG;|&uiꮧO鼮=(c?*'4حnV8[?'/ qe?}xְO!{?*LQ%elVSi -SM'>3![^w4ܽoNŋx"_w~1e׮u+PN*&<썧OYLFS 3&n M{҄` ?۝ Xȏ&̔ϊJPy_.ah$zFp,IJ(I$S'֘~zCpVXd5i An4R ;Xs:W Ollt1F%?"V`䇈NjOe@`#6'X"?ɣ^%5Gf HʌC'jz># :N٠?;=MyUk;j!gBF(,u´D,^᫻x}%4xυ!Xn~Ԭb.cfYvhSAE+[Lp*=`A9 Rm.t4˘V t0 {iNSA|BlsbHE'ۿC3 RD xC=fQJ8$V$8LFН]$M$DjZ6&f)-*!)8U@2NSH5K͓,+H<[/+?%жvBLN7#R4ϺcVՀ3,ptH57ePrqдN,9EhdU7AV'V,8%-t "F`ᜒ_MjJVҨbAavYxTby*&0!)@#]WW2'hpNvΒsV@'oӌ<(9ӉOb zGy%>{:ޕ1tUu֩jW:,đ3aʷ-=,:]׶iZs ?4]£-:XH';xQn*.Y;N,BK|.|afVUN%Đ$/$DSC4`8lZVBpQK&g>eݫƟ,G"l3kI/AV<*}sեiRO%D;2+H,,TO$}c_K3rĮ}3݅0HbGTFc(Wtu@uRJkc(3HD{V2H_i<)/Ɓt]$Q ]B飌z[s\-!C"n5l'\9cmWBB<aIn/0sARd!\2Ũ-00+x]c5}尧E+ڂ{UYo3\O"^N}NQ>gUSԑ2ɼ5w 5 ͩq ǵIt9 R¦PrvR*^."!>!WaLQjYsڝ |jJ$:v;}{2n|#iQpdF Uo'bvN#lc@caaAZ )oj$R}ɵ u<(_O I:/N^UR|#zuCŷv߄ o?]y*!z7Gڡլ\SzXz7Jc ېƹ X0-JMw^:s(Y#aP`eK,yPT=ɳyL8ת-p YO0U ߋ&n/k`\s 3wux"X2e.KߛuLApt r(9^cÓ;2i|\=oN?i;&_{OaBh" e(&<5\H [I;)IxBf[Un$HپyMN.; wbqV I$㷎-ECExFEMZ Q>f,((j^ڸH T˾e |dSTy*V&Xֿ52Cc^h=]Z뇔)oG#_oI5w )3ﮙ[nM w|S.NW!+7:2qKCL  h/f+j #jE((wTywW" lf @`u 0##\x~Wѱj%\PBP%}ܝ`u$۱ʂT(!M=l:Ѓ舧Lp|WSn":MVZ$7 Y@W>a x8 6{918\q=RIzL| 'dOlg|,L@I1鬫tUsKO٣ۡn(>)`G1JEKgv;CL:ԍ7ҋy+iInj%@qQzEIϝƙX)gqB$gi8( I3ҧ4Do8[?:ϙ=|nmSYQdt&gF] ʜGu 3 TO~ ?`Y4a-xPHKt}VH~hI#D\wu"5x&`Y>V9 p^1hF`(q%G ;{i&~ 7ByqG A[pIB1yJ3 a瘣J*@ W T<\=+SJncȍV;k:of ,),f+!$źʪih)zE,#8=c1*i@-J M]4OH.o)ilT,M=9aJbJݛɝ ?)g,V4%ZVg'2Ժ\TȖD.f\ᗋ2H~!q[:xqZ݈2dm. :|I]j~H _ޝ*fA2bY{:NǹO R.9~5z:*j敯UH. bp@8[aV)UWr/2c‹|i{~t"2ROfʾ^CTJZUNTJߕÌwBxQh&}@<>(prmnPp 1 SݳT 憿$s# ܣҗXxp(NL.śiMD8թ+ 74jPd||gEs~{t%:K$[Q+R;V>UzeyFJj ^'iIML~@>?ʕ8جxWO?r=Tx ФC`GA ) ƮC _t\Ǚ a " 4{ϝzK:7pcaV9MYQL,O*"ש$7Za050:wt=J 49~DZA@oR=66FKA٠T]]5!!$L$g )J>%*/袯iif/%t(?00rPls}fj=5a!% Q 4UܩÎ?׍;4]4ݭVO" Cg!!8:1ap8P]̉,^fiV)Fr` ϨmO£[JH}RϫY Pu58+{XEנEC'ժ?Xk0-kBM3 CpCrȦF;uSU0V5 \ /c8}K5;.De}! )y>` UQ#) iJrNrz^IÑ|=]O3P*~|sv-!/ q\)+R3Ul) =w)[f$VFdpJ6Ѵn*CA2~:5yNw yB}f_H:+E߄iY+~}B(|'5I# `z1If-ɥ b<_4 W8$N,8sLq_Z FdPTQt?)z*&[܇n0R80B[@i%D\#icF ˖$ɪ,ođ&? I4|mk 5i#LِScgw'Méd sr1i~W$^.Sp|WdBHFHdv-J&hݟC"#uкf(k]Yp/AGWz пljӯ(ེhScN}Mtj%>WRG. j@1eoR򐴕$UwHУ:*K#; B]KU3B!QQ_S]y\Ґ*(.{LM{F1'xFޒ,z5uTM :q~@-8I~%uZhW/I~]u=t*Wp.Kګ\iW{#uWa "R KAUFuF )]AC22!4 c߾%-n<~BGV/ysƒ7YQc+E9ey}կDm9YB8~Ik-}!.(@tg!%R'[ Ib@:nr##V{v1X VYܰB䃢ӒEQ\!'SQa%:I;ƔuZ"I:uTlvF f=d)Neqpf| 9r^&V*NH ܾsm%,k: :ňqK.IBcH*3JPQ~s;m\\$xF}H-ai=~R9Np8t,Ck**u!h&F?6{[✻t]Cd)8 Kf/] Ro?-Z¥^Je8ws=&"yFGZ:$-Ov)ڜ QY& O|TS ;n,Nϼ5`-rUr a$m麿XEIwL]Jeߓ`؞TM2-A<4i4Fjjd,Q?&A&nwg;N KwH.+`r"?D0|'k(z("L-~pdWSrUM|68U@Y)P/ͫ4ANV“ Qo$"3t_80|- j:I3s&O6&`$ U[@_AU^Vk@4I8rO[jzWƻUבj iJx'Lgη.> 9~/7<}OҊHC@Ҭ:saD %.ОiN7zsݔ7 b*$Xտ4"m?( M82 G|4:=sdX9b  @Ų͂?Wr IÄV'-Z<Nx{!y.F},g/ +!SͯQd[M~'FK I lu'y9ū0L=:o>K*@IV-&/ys#Ϭ۔l wzIIXw <_BwEU \"S *|MyH_6M@z"T/!$`'/$8p .\j_X0K^5E 0Jd*ή%ZH7E*#bl=X$Sᤵ? ~IeHS GOv:H1 *2!Uyw ( *KKQug½a\b=8+v\Z}fiŒ9&u*Hdʆu M< DZ]o"`c>HtjpW!ۛ(ܥhک-8j瑒X À]$c<'t!/ZQBc4O!0ZKB4N/}q'r_h$ژ٬O.(e+$1/J5U C^OIrgTze1Bubuߞ?aplfl-+]0 FaڽT9pLby}jvwQ+K:0֤yfS9ZJ b_^]p&x45p25'EZ,LHإ\ ( !~>G!Aq Pmԥl^Ј tI9P >%8դŁridKV$O5!3&x}Ū-kg'tH$wT\;8蟬G3n{mq\2ѬYc ^Z55pp Wb8{kOZɯ-_߀qpYA1CלwDwE>~CBHR~~m7ZelJIμV3qk\{J߶G!t0X4NLhP BE' ۵ 8EB4N'*yUh0i8OBY0 WOB|}L 3E3CT16+@b30i[ >E[ǍaDhb];akOF. ]3`a',q OIWQ#sb C=3O/>ES5jIr} !wƮBwjqŋE>TR Vi^\iX{Nd\ }J|6})|\ih/M)!u+}h06 #d tLJH㯸1oJ,N|֥s,FT4Ky3\:iB3m41"7b"PT(Is\K5.9s^ribťQ]Bd\CF7M-X4J˪^QBV' TMf:l_Q[ADHJ""@:0ܢȊ/1 [AVw.-#M cɭD5w H}*FJ v/%CZh~hyO;7AaPX4\M1!0rEc/>I8#4]5Nnzz/84O;Lw]rwxi2\"-K$QEc%|RʭYXD@< &L h+݅Tg7S߲XTVYy޴ K#5i(Cx0b"YivF82HH^o)4HI3y=OGq^咁[h2HF@hAR*Gɕ:X:R:&U39l h0hm*մNl-ּph W(!%p(C>. !«5+}JY11-AA'V aVHz|(JTtGj>l:@P w)!~> \rB79pzT<62B Qx+6 #3.*aإ3ֻ G5z~ķUMwOǎ#c@sJױ +*_<6#)P+5iz8k^Lp—bG4gAÐsU65Hlz{ j(!mX79#Py_JR`2N(_o +Y,h&<w%Gvب_ l8m-h^_sښ͗@5ns5S)PlZ=.:D`|_KM:~z@1M=.񱦆ΰ~ 0)VZ%r)v8O|Kp L:jK)%=ߣMF-7Xig*q~Ua"g{L!r8Vi\dI\ZQ& %"qq"p^QoWbaI=%OyK[ͫLP5lDRa&>L.U\mOR$jD#q"\7I6mt֏YDlQ8cb@ hB̒O>^KԝZS]]&Wf,Ѿ%˷>tя$0%sEnd}U!iIʮ=$FtP57|8HmU<#cK+dCB#K~d vh^C^YFu1.f8oUOpғ0Ì 3T*M ~DV9$5GV2n&h@Jmj^>=ȳU<xz)Y)A$ ]3]RN?Ot=%@':Ұ'r9TI!a#6fޚ=\~'r@C6={dE&-%>\%F+` XhK:M~BhKպ!yMx>5$k@,~i0W**L[įBԋ>€Oݤ}Ԛ_IOgB^k^a:WVqRmo=+;ˀa!hMɂ> MԜ4HV9jڗ ESo,s+Q3c~rjO?b:KWޤhK %u&A8 oHԏzW֠K}ABF -5D C8{қ;9R1DX5K,Q݀+.WgH[$; BA , E5.1R)1Nk2`̲ ]ӉZMK5h1ԗ$ǚjUM9"Չ$ڰcuәM7Jo~>]'B`s:ȯןCXMhqd]@Y&]o`p2Xa)YR!,] _E bhO7X(C Xr.~ߔR2a(_.ifCn))|0~U 1pŔ5*\c$0*kP`\)-M}`Ab\A5Ia[~p}Ҵ3* DJesD zOM7$jFGAI1S &da)-?ҐjA bM2 f!tds*W6kH(.b'w7K$ b4sv'~}`YG%jqj@La-! 2S!j[wƒ=HJas85sZν#GBql$aCwƽ8l"F[?EA!2ҳDKlf'I) (&X]hZ5K= q xV"8k9,0`kGuAB.e{^ /߅abdX쑍ˇ$L4iZ홃aHI˧DjbjE&:ﳮ:Ҥˮ?uMVQ}wwW\L+QRR0GLo~[(iEdȘA7w[dnЭDa`C DO;<`EODֹp t.&[ j2f:<dS}3VLRRMR>pD瑤B\`1{$D]e&J,]Z5 /|CCܭ7T*y5J|p-+TWui5hAEt$8K Ӟɴ\0-YUQ,d~+ ԈЀ|CHx[4]38WY'[ 02nUyAjpHnvXͱό+w S8y7Ⱦy͈5CޡO}d./\EW q\cz!F%8MkDߥ$yn0MלכR^iyh$ICnzJGUA!fWR^& 1~JHID*^_稤DrWTF;4y.q'C*Z~8UH*mTI+aUnZd)mTy Xu} H9 g%X'¬$I)<+xsG-e) .s{RjY?[@8Do+o~c ,+[W9@Joٲ%\a{@qʒ xqCWׯXW:"58ĪG;W>WS\fW92*.usN5 bƂUa 4rO@zugA5%Ýw? h0V.DVB};Cӓ/"$58sbV'ͨWŊ&Z+>Vš[#ScMF}_[ ,B0C$Ow!1r". ,`J'LԦ01#|%SjDS>uI&ZI*kGK&B+^" i<`bTQ`&}#\VFZM%]z +H2)78R>i4ƗYMfUBJh}W'sfƏL~iLT F>-Ss]NęFJ@?0 +JʮKT8.jI2!ӔE0>y}0\"gq,%b9_8C\Cbd&&ۑ!:c ~)D=a"vnzR>vT'Pl -{M2;^XPSJCa?Hc$GױLKAF"MϥU7a3KNyMHK1Q>=cE4mǿjL[N{Jyv^::DE." >L@m5KEBAR\iFČyk@ՙc*]|N[p f F !4\oJ)y^Փqd\[@weW$ OJw&1dzR8t3$KC1Wj#UE~z͞Ʌ8ԛ")f6Lzv8BOVUܥd%)$I"l)dԈK2f.zk2ͤjO!߂-~Ɨ,eqo`_αzY̒9^A~|1#Sziϟ1(f==t)I0!#U]]ȉ^*xd# 3XuVWEXE.;Y9ŕfd5tC8C hNsҬ^>NKK⟻[OPS ϥfA}7IW5k|f c uc[Ak$V:Ayc]ӡ.٧ϖ4&'H"B~Ƽߡ>c1AN_E% SՀ3.P |ЍO-#9'jㄶ+1%N b7`g@_XC.$@ҩ3j56p;d9uf|<ͣk?6YwxfE]2SaØug:I>o &&#?L" 'ܓZ Ubd47Oo$3.Ԭg!XceWި xWz&3lW| 6zv_ (8]7 *ιJ*5 Eۙne)L:%*՜HR="[iGk`h4Ι`TGĥI8q~fRҼN AD =(FE(3P}0L/b;VK  f:“1e{3|mM J:8Bx76nY#/}VafmՈ'xf o%8uv̈́~f<ǀ%cZ0lqfӿDt)|<8 YA"?Cj*d x ~S+-@V5=Yob+@C`1140 B_,4M,EKHpE( a`?r1#FhPA˩FZ*]UR "wjk'ffaJ* ڿe71+J)*abƁ&X{Fk˛hWj.P6v( -ĄҺUc,;E[~?Չ%~Zz U\9. l,l|BĎY(@Eoju]eZ Y.ApW\ZuP&ιhqAfWlU'J#=.JɳY#u@rȐk~>!wB/P[L%dh(GʨC(7BJs]ǯY9V\hD82 ;3G&Qeן0]?* LPDwg23yjAv.nsh|ޝf9jW3>;xnaU\ iY~Ln*KC2ߍ*ݣWJʃ*YoZs4S^۟2F x,Զ1cuV!o]o=W7} L,ڭ6#S1"\^;ti0@Gfj$ߪ <[; 뵳қW K4#$%J4 (ɹԋKLJ)T~2K:4Bd][e#Tp-x7[niV]34'BcJ'!'M5myP}TM@MǾmo]BїѠRWxyj@#,ii7-{}XphyK!IZ RK4Fw1|%MuL7>k@.vLr -N zkSm)_mhZLvN=Le)䦹 κځeiN`~E5 ڴQ&/< 'DcY녫ˇn%0h :\<;qPE 0wR4<tYa|ht~ksYߜ'IHj /c)mI;T{&;Kl ߿X-!0Z##"|-AZUaʨK4Ы `ci#aj) ꬮxR+0Yç袊{w`_!8#L@QhuQ'Lu;1:n*k-w|Ktr-ZʧAN4␀>ui+ {;wE^ -M^v D.zQVNbpr8YyLֳ B䲀K( .W_mǁ0v^_Ϯ^r 4ȝ4xy:{Œt4C5J2tn:rԗ"rIG^z0>ۏ0ΛT>Hc(T}P.'3 |y0=k `41 WAw3=>k% ;|(bi{PNEҖ.V>R'8EƪUL\Zd9*)d@s/꺵c:KxpyUڟ/) ogsc*Źt!0inuӺNXui״ԓ pxQ 󰐛4hC%5J:jW5lߪC.ukR.4/D17|W7L$lizJ<$ĪjH(KIcɜ0ks_1}C8ЖtRo:w\^Zq]ӥUVc]!\1 a%|U[jY kDˍ)4[Fk~irq jX\uiJ'BP#hOXH:Z5op yk+[#;dMGu==5Fa]ӀKBo'xE/]bX&cʹhԝq==ZTX0 L_g?8͏nVB;5V).1Pf@}nj52i8{a4y3Q_ D7BSUڍ[59@s>%T !ŸVH@b t[ H\zQwXկ8B]OY#s9ɸ7&8#2jNƠD ,$u3q)Dٵ^`0WD $tF}):xi;E_ڲǁUiz+?Vr%Pm ߢ D=FL- ZB!BVjPj~wfpzUMԸ) ?y}jgM iAT4nL^na ڴ+z0_wNp'[I ^eȡha~9{q|\Ӭz)P]g&뜫'&꒨s,a{ s벐? 7idΦN5%ZBĝ[<>Hp/=A'6SM2-+wxe.RG(3yEcuՉga@:qeSU~Ke[2|16y`+wIlvg\/3ϾwMp|EMڇ( ,Hz?F:QbQQ#i/"o1R MCUh񾵎@^6fi$Tk]eS]TFb ykQbu;dP~zq.F_ y$1* k<Չf p߁ fNQaʒP:t(  B$L^֪U ]8DoT[*a:kMe`?hAn$[5ݽLό+=D;,%{[uja@ȧ\{a$|Oq9 (K_4鮛LZ ` C UV=0QIoYt 8A Iύ"yӿ\]nl)w}]LyBlNc{c ,+g ~H( (X"븄 [1M@:S&ӓemEfh3 Q$ZiVq^t bYx]zok}K,~YbYW6#,o'-g9t ֛ްNj34^'gMQ'֩w<[ԈϕG7aJыˌznijil?8߼HxKVfԲ=n2mckj X!:|LE n@VI8dG'`XpŎ8QRRE:#~+EmH4 DZpKB|:D΂ghĹ:eYBÉھS8RfB2&7Ҵ M&DM'=fzsIT0QOWQz2edI_ƨI:)9@j~LqJoohz`Q[sSs щm1YY,?aa0֝9jVt5AY"j]&C__% {֪9.D"f!h atU/7憙% fI|' S\R >۰r>6gt1^62UTQ8LVO8h3ښP,HEdiDl,}[QxQt:cոqH騖JVmZ]]So(qFjʇAG2b&˲wݣ7裰-xGszVdq vvd--)tP^.R., ɐVE`i=z@NWLڕ ;35҂O& T4AP8d; $S}X6^ ԍP~)UOVNl4n&3eQ8NM,w^ɖ8Ug,)S ]n2K_WAoM!'Ik)f)P<4vzڛ9?a,q&WUt* z܏gAԀjL$~a$gnd}Xk8P"^a&[s.2sǼ$ Lvl#,O7NIDF*٨IX2*XZ%GD역ip![s'8CwĞ8I<7'WT=(PZTV_m[-}5V}K!^e_ch<SXOH $Pgu)]o%u)#Rg~6wQ;'/R-LnȎ `I9!U6a~C"j.װ?ԙ54_exfډxٔW^Bk~M֡ Ojo" Shhw=Jӂ>IN'QaN ŗihLB<5eP\أ&OY`: i5Xcv')Ѿs@J܅ !fJCā)ZlR v޼LlOc^W`z=9RZ%G~q~dZk?+!œkR.4uB a Jpa7>5 ā˰熊0X ٫ p[efh[╣ iat-\Nj4 c>0ى`XR+s{Aad}N<4J4H/tC05q+u<3  f w41 i Y/ĩ=L|ɤ̚T9emc<$^gly**.4VS SIH')G\3Ώq< |a=%DGT3X@^N+K%=^us]oaJWȟ(7 o*e|z #+}XK-|k[wa=Fl87bOƵ;0Qx*yH aFui>J.]0`za1B IUa3o3XٽDN]!vمaSF>Rj%80y=\s8$ž.+r(xqX*1d ?73^qIw̲O@hd|qܛ@0T'q.fy% 񝺛O7d?r+D3 c' ۿ)B<#k0s.W3P(:z2|Vh$!px>AIGo9^?PQQ,"Ӂ9OA#nKy2a܁߾k"0 P~]w7NnuKJ5K6JAEm5w>NWVH!rtJ14]ˀ44Nޝae3މ _g4ZŸl4=y)v8&5Ij]@')pZ;Њ`uq]fv}:q$bg`C>2Py|y2>×+aPR5lCdP]aV!^:&6iV*?],A,E'&PA׬JHH%M;m(#۬FXN N07 G*A,$%ZwJ<`!dط#ڷR(Qe~s(ҸPxU.iP=A -+1谢12 ..[[ߧ_`:YLM0_aj\˾tW;E8~3ܥD ! `d;I&d:L߬Nm*CO tZm\ WP?^Fi:Y1/SQF"WNw3\578a0>y8 q쑪 _ޝH]NX|lJ ze= ^kefDEcDP .u7"0)pxxtV)𼎙)ռVID8B+mfiKz>S;7 {ZxVtVc @f"6F4Ҫ"dc&ZwxI0ԈJVbZD]רGf' 8G^9YDmQZ%"l]d{;wӛsx*;^rȿ㡚Eu:IԈ Ĩ;y@SS &=ѧ/X.=i8thu.jx>5.GDB&rzo&z3J( wi~K/I%iٗhtjJI\ՔW`B)r-%t%na"R8HLɐ%"ЛMzLK?L]W0D"w-(r EZ^ˀFjo +#W/\JDt66Av l9L|<I:Ng}Ǧs]&zi_#/u%uN$9ɩ<s!FPmed+)?E[IET5'qc:e0^wQcFHܦU,]H !MiJ" XnJZnjbe'iPi0Hןr7?N7L:ѫ_[z E [Z+TJ.оg~d^~sQL.>kXfԝUGcPgzVⳋx:Ko^I'W9?*J>&o/s|D`$2Q<%UdM|PMh3)Yygw|_EHvM}.Ĉ aPT3d<$[hjh9PU7бH"j|ߣ7Q#1m6\#$\^B&ŷ+lѵϯ{XE6 Vu8?wgW9B0,&I^)4PX!D|\Q+ R\\vq%$pw#4ª`fN0G|7[^ BZc|We:s>,K7J4"J̢$.3LBeݶSrm ~Y}|N#v0&jl3R2XnqV `,X927&gzCP0)PДqhO&'S`h!C=àSJVb%>]ՌQXmkЛ\WޤБOT ;K }e'U1]QaCtټOTHBHa@0.kQ4lJ7Q]y*=I8k2KI@-O*NI])]T$X~Fbۉ9_sq>`) IChExl]i` W@G;&uw'M1H@i'8/F7L^f^q}U z%Pܜ7jUix@!M&:B2VO9vk^&L7 V^^~!g8״Xx\RǗdz.Oլ&"xT#k>(_BshIͼ,g5wM7W$%ȳ*4?/Mw}^ՓG<' .h=g# ߪuxn54eьs]"L9v*aA.C] H@- [Kv.{m0:ȍ߃ɫ !'zS͌ .Bh]5$y:Vy:_ġ#^5xITwO9/|%<e\ =[͇>&*.ChrqT7HV7pDۭ)oa9hI>_P-E3?bc 84m9jQ6s]B R5BIY`V|4^KW Jh 1> &%ZCS`D!53|QM7ݶՀ0M WuHC̀hϱ4aowBҋ\e5qsQUng!2bqp2krM.%*˴-%F>%fA?K^&Rү|IuKؒwҜrt|\4JX D$C|q'SBK{Vk72m2JuLjƄnIiz@M\o)|OjU{*\>Ւdqfeiɀb%O e5`"iD{"zN T!~FI ΎڌO/GapqiIJ$#V_q1+C=²a<Llq`6_ȯF{K[b q wgMp[K¸A+{$s'G+5>\FD"_oB 59kUfj\0t',1obsfH|j.u^B&4|Vl naZt2_ah>lbrq%4CmDS1(Kq(sީyW׹[qAoQx7:*0DwA8(+[겤j|J!KW fxXcklF<Ǒ#ߎ@v2~0p%d`+*Bd*\UyN|`!n\3@kCZ5>f _"Iz7pdC wYFTw+#(FPw a~9=೏-" EJy ?P|.˸f4{13YTq7Uj8_4N,Gz8 1fqcdL[ 5đ!xjO,_`)_k03ܖ-fF8I7TH.%fk^> 1C+si.a՞Z"_.v0eaԃ|MAC|Cȑ\}ҹ905 Q?:Eyi Q=-z҃;$j1eъGFjM-qD(ܒ "&L, Nei_b:xIb99:z !g\\)C"g4`/]a4RuNIHӵ /j!IӼ0](/*C мPK&N-/ "~'*'ﮔ%.W".Q[įhE١0U }^$dV _EaX P&W|I=Ћʵ%nr@9˗2xzN5iTZ@'=L.mvK[9z'%iS/[߈T}WH@GC# `!=EQ  {9ޣKtz\KuF~f"VwJ&8'Ҋ^.2k\ib#C. *+pݥRGxC9VXuUw̼*{O=\ 3D{D}7͟>=9`0+Jj:/>hS+ř7-4\E ]ᐤ8p%3KK2 [l=w8ÐmZbP;!vPNW[`t{do5f$3S(ňi,\pK.%5VE/X#׻Gy#f$K32Y&VmY;fXEOH48oG$=BK_PD!:0ni[jEvzhk1xTohix 3fH #npn@B+ bx _Drbāt 搌0ю3LT>%5L,)2[72.o!xh̜iRk^)_2 6 q|E nB-@Ax[( isz.ݐFMÌ)&_@mpe5U; O_OVGeyJԾ%Ԉêb9ڍC$]iխQ  "n2{!(1ӎ1Zܟreᨯ1̸KI^&a])f9 >.6͞-#g(!)5\̫JE&d]&DdQcg*"Aʡ2z/6p9Gc&}JoPƹoGOJ} <$*+`lISSTKrʔZtbAZ<ےRBu3U'PW< 6,B=ɐ|TsTpN7O%2F匮IGE^))4q9`ܭo)uhV޶_iB3Kt9&UE?\ 4͔$hr3*I]7R&1nIهt&D6jEK,~Xj0  tYqˡu^m2pTrw;f2 qR~R(1׭AI&'Z!_:!ZE8)*'n%GEC_I4x/XmO ){~DqX(^&i3>)k)7ܺ .Sa(խԖ#+vko78Xt^:"^V?R-f1ؤ~CR|&=(魚an(л-W6ʏ`xdv]#L.:cf9K<݊Fv!.W9-)1 .㋽raWB&8t* yC8"/ĕ,vhGs^xMy< 8fb,]=pD~̈Z(5&RF+Bz$CS.8R[x] 鼊֮wT{^_PAmbnm~Wi5W)C &5Es$\'*ȯxR vM(ɵ)2و83*6)W[K6M%w&xhAod>Ma"5n0OphDӐi^vZv RftbG 1PwtAxAqWؼjК%n£4Qy:dFȂK#uK坸^ʉpĤx邷`&ȍV]$y:2'Û`JP 3!~Of@C" k;g|efŽAcE 7{S=  o JbȪ]w`E Rۏx)fw kJeaB1߽`nSQ/ ,nj8'G=]RFn9I_߰2׎Sbr?)Mu'oQEd@pYA#AN%fE d4'q&Q&W243 %lfeT}TlUۇH#/%tN _n)D}_OV2qlw8=egI^OX>j!r'D^bܫVH̊ш@*^&Od_a@43ޯt Vs?$ ]ÅVq|轜R(|A4a cRhjfm qBFΌfZbJN6]FbuGt_t'.Su0)fb4${ͼwIr 7q=6ݹ gYtOHNm%& *p BO5nTqyX It[{X!pb 8N}uEK&I)I~t! xBҿdž"*Ĩcpb$g8 qo3>U}jWX~JRÄ](oEpg(7WbC7ުg 'ɲe\eiSITVEki,pi@kVuAz1%)Rdq2M$n6.drfV$AugtK>жc~Is*t!䡄LD:䌗SYϯPj9-X ߖjTܤkk0⦘1tZ!h5AfK_.G":_j r3"st')`fi|N&izS4p4/DIKQ]Kºq I>H}\U7jf@MSO0kmYD'G/抨CAl)!!- `$sO?tbkx"<ַk8XPd$ZY"l2E pe_@u~E5FE~"!$~t =<:nXZTa/.^>?3S>1}$6XqhbR|УQ1N: ;&#KM%f|S8tiˋWlS>)hE+QjNީ q=߉t`ރG{7%ޮe xOn5{+_'>IYs$rDR0/_M$z$| d:1}\ANIhDtX -Bo s6zjkZ*T:ͥϓ1vrVZcu7W$G@3"3:++a"[՗NLwP"$MF!mh)V Y hJ7:oOڈ0$>7uP;_ti~ e ;/]oR9K}an`άVևNӵ]⮰u&xOyŌ.>; rJn`6Itxq78cxL|9ˇ{*NvZ!Uɧ8V! 984ڇBw՟ $ `n, $vdQ~5MU7Ɇm{'o` wF)A`$!Oz~䇕xǤ)fWt13&gEE8cu(?NjIQ'XO$Ob|4c4 s$kh}ȓ$V/i?Qs$uH.=n3 D##ooep'kgjB– /XNKtBh|2{4PKI\BHWI]v0D0&aN$CVBl2+5s6# ztl%3i_Iےw蓴"IR7USI^Ni:I H3 ᜌgeIY#~G&af$) \g^Wȓg楥Xu׈.{s 8MA9`$0#*aZ64FB57n14A-"pUrMֳ&uCxAm[ !Zvm-ܐIw9tY`++k*2w^}=_D].`00O? Qkv81KV`WRQtpiV S%`RCo_td M# Ԓuʎ\쓰ڟRеmw !?ӫ*Wa*tpKVY&ӝ.A?u.4VI fNUB;x.c雅I)s-&q2M5UR hUuPrhzAO9>kY)1E::c,ſ:$ӑ_տ:PQg;:yCcUOCjt=/FϟkZ6xËqtԈ]Ůw+e C&?S0k=}b}T͌)OiNwVoIO'RCtFRzk>J_vK+9sɴw<N45r|m`!R^\Jn'l甏{8O'< { Ajۘ`g9F6My;Nq"׈ZgOUx}Wܢc:6un/MR>4ZjUIS#M/oBIj}ΨOɂчIT5WΑf7Y7,U!]S-=MѴ/y3A)ӵW N[/Ѫj-.AL=}GEr%yk'S+$SǺBge$2]aˬx9Hٿ)a~a!mqG Ő6D(\gmup%2q863|Fi0O A3,z"{1sw??jVM ;rlNev+2˵뀄꾔pD>S?Bm9S.L @}D#@$S< u=3<$W(&43Fߥu0jG~@}*ŷs\Wc~gB ^-CCXqeL}x:@ p qT%ո|uD;zꔨ2Otd;'Ʈ/G]7r0yp81F CN(@ϲawB>xOsh^x`Ƕ.ǣ)#CED"xcΫ0t>AH,Y'4OunZ6scCߎV\b|Øũ& yici=9gzSXS8Q.M[rla ڮQu-v?&#I$14k8w~z*z̪AW bZ% w^ &oOua~ߋYt91MfGz=w5ew;#=zEGbVŧ. 8^o'~G+Di89N_؄ qYSA9Sgl(FbW \%TcUwM019V0ܤ~|SAG<6יbN=> 4QE %S*jҬxyږ%GmK,Լ8eU'IXR៷8Mz[P9H@S8$P+xCzzO֘Kl:2Ӵ{a@|WHcW/sߐX-jYv͏bI\C/Y4/}˧DZ[ ~2QDU <Q> ("f1Ոz+*5ta18! fifZż_ȍA"Ưn0ɺm-Nm6xqLX [8Q,-hbs3M<Uy H:odphjl/vmz~Vi&A|=c,uX1mQwֶr;#6ƕ۠A,S @^[|§7U}`_]/d]o^_97P#scotch-5.1.12b.dfsg/grf/4elt.xyz.gz0000444000175300017530000072140110656300346017220 0ustar hazelscthazelsct1ef_4elt.xyzt[&˪>WesXƝhe&˶j3s_o~?_Ӯ}O߿gu߷p|qkj׽g43~sY ^5 ' ׺\?˟~i}|i cxO?Geso~fwLb M2"H7?= ,|Kew4:6sMݲ?O>M_}q9sӒ4qoZ|%[__wzs_l^B;7GΥ?M_ӿ>v}!=A1moj![SjOfW:={.Gvu[zuy{v~aқ"sy=|M0n=J`O>N[N}>i9/b_<,3便/&okrӲugy q2~;|%wU2=GoQ-/-ǔvW_}6y4>ZXͮkGhT#.m>?Dqa'Zx&iIˡg$\u bcn,Z꒝x!]۷YΙt4-;}}_GdWֶ#cѨmw]Ov8{~+gs*}3IlIOׇYi>mHϐ9iV~$}~|~-"5N_l֎iҽv%<{1K=toz>g -QK{Nn,ub#gȷo\Y#zc.X63n]O#g8 E/Jkвk_ԏysMZvxSWQp GisxI|Q:~si?w{XLvW!GKh?HC'Q;7u#`qJ^sUŚ_Ou%?fhGNh7Zzg9 'ط,7g!zOg_~ZvS篏gn4K=>Օg8ݺB[u{w.V=D>Eu JκaGI|{!659Mwc"H7v2c>U\ߍV bckXMxۗ?.1]8boל=Ϡ?/4N_ɠ[W:,7}AgM.Φ֘rh5V퇖kze6r9ufdA~O=+]Zj>52št^*Y"\%,q/bwg괌ᝯ-[~QB]N=u7hZwtFРP|whR/VGS^j8?#&Bޛ0N%e6/IϵqNK-8ݡ[uwe@zsi {Nԋ{y}-՟"GPˍ0nZ tw3DR=tDF]SPZn]g@Ƀ¿%ܦyuz3'!:Yzz %]yiᖹ(i75 7dJtۍZ|槉b^/Q w^mSf |/UPn9x¥8$^| W'\z2ϜO- bP]kyKwn,k/=#4x5C,C[pa6MAV'jyS#CJ h歆[CWt0oP]=6"oM@utE u4omEQ 4GVe=*>AG0(6~MD\rg:boqUBk |nCкADPDoܱ}kAzb JӤ tSf,&2/`(CzO~n0H#"a7oxׇ'zk7o*Wq W7oSgg<Os`|^_p# ';]ykx;#R l({f]okp}wu(V|^nkxGj_YӼ;9:yhn2 iet"M71{ykJ<Ƨ~MwcɗF= ̎ExMVG?k$|@MĻ:R7vDr<{[ˡ>ŷw[ )P62oFƂr:]ymjàu|^-OV#~ZM0g0 DM{yK Ny `0u|6%`&E[8Hq,~~rtl;*4u\FD7ѫz{4_Ղ! y\6/d@:[. iUgjs`ñ %W:55\\v2}/`йSP7]8_ߕXPYns@pba90%o1\dSĂ=@hJֳLOdWѭTs?XC؆"^L38]&`!? tӭxPS$ H%^L@^YAWU` fhtkK*G5j QVjʺKs۱Jcs?ShW:oz.<XC3b =U؁D3EXNd*'"z LsX.`~\ښz4>*VH?k 4vѧ ϵqkiHb֋c|EG+K/#|/hӫ]5dscG7Ȱ8'L.:o+fFooM+j#UCtc^Uԅ/v-iA ܚljKc.oC|G:{Tqc<5Trro$ lw2o Z\{W CxWT5h3k歉rG-b󨘜r,Oa^.fz Ri!VDZ[m7^9NBM[q Hmjz+BAa6oAD13zJ :L%gGz[ Bt+D킽 A^z8Z}KAn&rbm-5NDO*?[W?5qkHֱp<]>"ԭɏZhcշpZ}:F g~DNjzf%G0ǫƺaP:$~<^6DN$g]M_jt0gx/w4 +Ǻ]6[ĂR75oa_+eXYǼ;7u_g݆ybxXlKvIV uj=xh+[;},%N diq׎/T_߆a{W AqsikKOxW%|D kǸqDg h%ڱPTR,1v_$^;{YQl14$SQ2Y4ߑ| pDG A퇓Ijڽ"+D#<~@;#C 62(՟zvJ."֌NgqO]n:¿b 6SMTaXJel"g{3-]m'Z,Ze e)8O#Dpdx{Kw9"fkTyN3W=.AD؝?wbvk罀24cWnNzԹo:/c]FDgrIwy0T+ft<\?!gႱ-2< 7|;yjtfӸ03{+7dkQyZt7'2\׵q;?)HYSQs}G2D!b`[0coYz6@  Ƞ{$clt̗8!Y9_.\Cm:%#"]ڨ놩70G4Dfqom"/# =FS{ 9Ucm鸷>B7.~Ǽ9뙿$6*]pZ2 !FB[g=ӏUnCLTSML`?SqgV$|(^"f>>!`& N.a*'\{R~k@O+6g?{{k;Ľ*vqx`<-ێ(C[vވ!W$bqo齅h+QDX6uw6:@O{ MH3t8[cŽEj: N<0v)3!tz}Wvʂ_-5v5{ G|֝aio[%6+뺷oso(G/ҭ&B,k{ ո療O,5REmԾ-z -$8E3oD|f߱ ~k~M7/!f6cz}:ˀ 3KQzt,C f'@3eAxZ/]?o91P!ɫv~WkOֱ c%;R _;x 퉊x<^oKIuaqX"*Odj!ކq,CMLp]`{=zu,CX~זPhӌX^0d6ޅl:os;10WYap6~:1係Ӱu,c3St/iva_ GĿ¢&@M ,gޚ.E&. ~N24/ͭ%?Mu' c(c:FxNL[zɳDDmϱ{ 18Rh-=K:N2F7 E+]噢 sKHk.p,@%F`50u,CMJh"t,cX)2'@ b M[#>-zL~x]}^I+Oq{;Eԓ]XUXDc =Zdpo5\'`(o81v@ԃ܎e 6Mfi͢߼:b(SNBO2G@mDǵ?c & ꝌWe (!`6^7@PbϡX䨰a B@od3cca$77N2H2X.zvc|*I# >M+H#T}Fm0Xa'Qq4|sc6}?cde Ԫ8"&CUdp,CMY|-:_SY޿%N9] DetٔrYP XF7cm⯏]?t-HIwN#TWc]/V8zCscjСdOo-2qfpsÇHMnBP<_i2Rr,CMWx+_uۭaarnwJ*Yw,Ƅ$սpA\Mlj=t,|Q? xOGКf-dv,CMDoE{e#%^-H#wIE}1 Lmx: FAK @Ր,Aa}ݸ{&RMhz馆H!4z+-24+3 ns]㙶JuKҜY} :ciEBׇ~#Le f'Iɰ2Նha&ϊ-~Otxs9Ӟ!W_`Xڎea>ݹ1ۆ.CXt$-';=\uqf,g-2Юsܼ@o9Qwo P{T}.6e?o}]Dv4qǎ/e&8Wkc$L7B >{ RjBÎj&XJgj~';4Dch쵋q?']˱ |mQs޻cL4Gc>o-2z*@AdJj`k< \C5onȹr,CM;ړCBLkYe@~SB#2!˱VFr,΋,SzK~9'r^Zpp,r%LUauZ-2\Q8PXچ?ur,CM[j% b"O9ȰRZ@d{ bmJ΍S(/d[L.x˒$ܟ+8BH&˱f<.]J^ˀxVGEXF#B cۣ.2ڤ 7^4z˱FzR{ձ H}K~c9r6&xryj0^$t,CMp:O}OSϴ) 9ZG;] x4yI5e|E53Nhs|20Icc)c: ci(m?u?SMr ;'?$K䄩B{| vh G D.z>Ω{ešXZ-}&.p,C@0{5R݁Ju|(DîgnQ@V[6*XW7%w-f;]@'j7OfM-1~VK n2>t}S#[o(v,`O=JjlޙXq}$Wܠp)k;a<|ٽdZmii:,q/~ oPSpoIC)Ļ)e<ӧ ‐nML % ET"fƛT֙NOsS0YN/tOsSVb inZfR3t>SxĦlIZY~/ގe|N,9%ͱ*Tm`\Vo2>Ң<7gz Xz}(&'#"M"'˃ -G2gL6ybtJO?ZBkxQbs;c6@sxgXLecߤN+Iuy0"Uۦ9Ï֯2sպ]O},|Bm!XԽq8ɫ'Zݐnc R3asˀi/HjԽTm=2>w['RS: -=AT JfmN.f~BMCTmӗ,ޠN9sokJܱ%{1qž< '~Ql$=ݗaDBr|*Pb>,Sz$psgՈJLMBG3SC ~գП~_tWh^yMۈcrV߂/?sSk7 P>eikGV|W^ߙ5[$>c0oS94]. DHOV W/z\+,u WH h*.o'وCay Lr&^wyKK9]+b (#M[Xtwذ^+™M'Ua؅}05ot<GX pM#xd\74oP q0r"3[z!Y.:>kA R64g5wmLt>GvIcb Sm|#6; FM.<"$1=YMA ' dz[|EXg@w\G"XnC ,+D>VkO Ľ@M[ sQu>6^MRY824R>"Be 6S\ݑ>C'SES9"%3H#3oz8>m7tdhOM^M) 21_ڼs !#}/|}Whh1?ϴi&7ޠiAkCwy|hPqSm8;4(+Lmfi\u/I[8H+)eLS+|}޵!sSXp6Fb`X\Bl:"\3K!gsb|73}PQ+ }-00 cM4yKﺱ\|־/`/;ɔ#YV,::yk9 fM) F" bR\Xu5$B#ȦAOI p;vR=@ $BRSQǑ7w5o-]KYmu^qL֚"f-ٟ'|>7y P1av}-@P `x)Mvn7{_\0 3m@kG.8݈)+t[ϗB6oJU ?r>7@OȸueEt[z@YhU{hj ӕӱ84oH!|&+PσH30CS֠o캥"ϪrS瞒1|Ct)λ`B -Metx%ijނZ>(zn7UH>įbmaL־MT6`I1Լ`X 4(x"ݴWJ6@u_;y i4놜{<y C֡XRO/ŵYMA$Sチ#xWV`ݧ]YUVļ<5HO)@ļ(^w uEPz[6 e R>:M!q] d48޺-BױP;=M׹%oM\Yy/mKDo L'׼AK+ad;3x%TN6_ևiB@GKBaH70.2pM׼<Z lư|^{?w|6%+;#+gjB$TzD0^y5u¡MIp:7=pӐX~歏فgqH)g==V\& gJ$Ґe,[L!6~-h7"] ydͩW0Xiwd'ႩM=$ぁMljөz7dPʑ/+6N}IkeXtjt!~bF{*ͦSe\1x"(mMIO=XMծ6˥['mKSNiLh҈t qM]Y"Mt[4uoVƬ0v}xGsȗ%FHןAS՝,2+ߧ~܀>t>SLY,DfVXn:Iku`y M k1,0oa ނgZźUH~fg[~fv:NR LVǦOЈL2노ӽծUz (:hӼ@O)$|S5ykoB_dv ) j4cg%Y-QMђ0o G =;~IJa˼EH=HWbV;[A'?kNw6һ*_@SjnJhpBμ˽eĊ],SUao45ofLLS )<:G9ehM\[W= 7f]M) %Y-p!S |U?O E#,c%hXq(֍&66o-t)'mZ@[Q m pZ{x}Bs0CKWۼ5yJOr} ~U[!9ۼEǪh&%׾)ttwͬ)F.%Ʋ0oiL .:9٣E Ka PI ap-cw9Px=~|qm?q5uoAb_F{[2۸=S%8 nx-ʨԘh9-|?RUK i"8sH,pI,,~WSkZ25c{SݡiwS^Y?1|TM[v^F3-]eƆYX4`9 rS?Krt_"(zż41g>y7=`Z{D.b hiK^Qbb3z J 77']8S2"(>^H^/%uf{2Q[8o^ŵ Y(䅺wb'lF>[TE"(z-kmМ{[}`VHtpmuHv1DVJb_;o#6}!ymG" F(qUKʽ\ں !972R5`Gk:3].%\mȁm5(x;;ak^k)TsTrPQPT=ئemu ,:΁6]` Jfy]@w> u`kz( :,BO0/些]8Q`oapUkiO5}Y>tgv-{|yw9FևF3)&7 xlO^ 8wxY&${$j+nKa3R0->j zy:3M Xnͦ p/77 !hZ@ͦߦM(f-1LMwXn~7=4oBy=M2CPs{~Po$o(ʳtsٞG&\qmS0Je~3qF--2I~".hg7lo 9]#˝8 A1͖ &4ԗ~k*=pI* 4nFv"Ob Z>fcOFvVZTE^f4v&K`B&wcY0B7w!q˗q5N?n 5 sp0 ,_Bo -R+( ND4jpc"7h nyپd-f(.@2fcn .2r>XP 5,%mx 7b H5Nb~[5+Thȇް3e.V ˲ov BFfP7&:V>G][#9S~o )g52g7>.[6lOg[mo5Q$ر Z@OF}w=[rqQx~o1șgFD-Ƙ_ejif+nEky/ sH$1h*Eu60m>|~(`-E\vϳD375^8/־ak~ J{SYo<=n9&-؛ CuP7ۆ)Q 6`=IuiLJ0/]Nq> dPЍ8軭\n[z Rfu%o34G鯓~,&5Zw:$/ޡ4ݨFc UdMfsۂ$sʼDWoXf?ZN%N~sf+!7Ʈ/Z;n U&"lɳЫ-NnEjKXcws g'$ގ/ɸu[}{^$1~[7AsZK4G}$09l9{=R!ηٞ˱ԫo$+xud;3ǎԣENy,f "|󛫈+d%돧7J[t%{:Ӎ 5bىlcyں:f[ͳXƔY "a·7淏SSc{>fim{霞X/(jh{?ɲos+O%e\2>c/Q[T*P ,y! qavR($^a"*ayGYcE37[\[`6C_'-|!7'd ^n~H$k KMo2N]Shokw)EG|붐~&5ڡf2azKћmljwm3mTX%;\jk~}ȡՅO k| T"{[~r|jyVIx̰ua-3 AD)7س(v7]m36=1p42pِhzAEBb~8a{D5bߐ;`R90Aa4)E[jMb G6ZZ>(}mqIWf6dPpZA#pEJ:+7\e@i,R/}_tSf}7Vקmi0~zQ>-uR"noAZS놴4L9k[44ܖ(HƗm5VAgx5 7q[K|8&.ק :)X&v_m琂P_"w671+Al!+ ߔm, -vr,YoQ_7LJÖ{w60VMCb1]motnNbt{ /[p)z'u}:&V(%gFݿ/[ûiZi~c]YgFgFmIǁ0FQAq>P }ī;d>oMG›&An_% g6Lg:DrD/li)٧x=%1Ϛh;5v<%.L}|:PQ[[퓕gx dԴ>tSK/;Q)´W2(淎N!eY]fwjԇQ:c,R85фom5\lADx N$Woq#ng,J\BdxBrsRvQt˾Ry ѱ/POAp m:zwĈ-ceBSV[_;.E-ecB)4tK'9K-[[;o j2w ;^0WEP3rxI#ۅ~^ya8^Q&z}Pb K@xb.3Umw3z&>&t'V]$ǻL 2'ד} fù6I>Et/)7lor|eJ:/A]E0&.|=c]fB]n{ Oj@9Jpdscں,:l7O\WSKUZ7 [ۧ 2d(mbKJԿm?Jt)cO;}S0Ȼ3CQ˞fe%&Y;K%Pc9 =HW9^CE3?lJIt8^B*-b /AxS|~Wwiq ^K[nXAsqCm'pAd؄d1YHf r8vPzl4vYH:u2ɽId>߈'VĹs5L(aj/A7oj %OE Hkm }^ącغ%,kN԰pM!qh) |r [0WJ_>bDn Gwu1Ei}<YU܃]ak~k}u?-Z)i_4fjF>A`+cvp:7 [`6 Y89V ^Ř77I)dKr[d?T]v[RTM=ؚD Ԅ f?rlm'xEzly M o"#o]Q0vہJ-iv0i7g0NX?ؒ9vo@}MD~6 5$߁͋':n۹efQ)S e#D9[!.8oʒYN!v6^hCmd pl!Dzc2GQmbX$ oPRښߎFn8vЗ8n j&^n)w]~Xn`Ͱb8_dEll(ܓ_P(ɻ)6m?ڢq>4hbinko>*&ߠ6802 Gjk~|&& |{4jV',ݜG/!q.]yhNN8mm_\,וf~ .YpXX ms%m[7 iDܼJV[8l op/j8vm~$C"*Z3qQFm quoQlO[97GBo|K3eIlQ%"voᑈ\lE͂}GŒn#߀bNa0/7؈Yosc]o3"7tu3hSZk~ =4Q;I'pڕX.]^e.J}1v85Jr[(}ᜟ>٥|ȃb^ښ&s{F_D>67gs|jAXL [\ln 6X,-ϾJಞ ŷ7Cm#kW>E %Zؚ߰)65Fv`Q(?6l7UvdzM`8J&zūm^Z?#MKS!rO=FZ@ټߚ[%6?ЃZ.Dn aכI/`fwr-;e?yLE;j_p[Գ6@IK0@:LfYE%XcX tOؚ4̏ xr~ԚuBQ}k *YMj?@:\J ktDcq.nAs!%hD74TFnA9^yorzIݙx{J[C-_Nںa^j_ؤloД~uE7_`%IH؈x`_>$yA::.LK4IeF0߄_ KatxV)/w%pxla۷_</!-F=ԐLK: GT8I{s;l嘄Y&LKb)JStDpH`8E;{6󛆩l~,ERb:^Dm(i+4 q//JOa&aQNf/TZF);j9]cRNK!M >a\yVo` }oy7 <1?f7Le-stmgbT8}x t "|h;8^P9N/*Z9/XAENt"6Jsyy%(2\%9^2':=9t+<ƴ~'1/AHڏkX뎗yz%٘G:^ hhol%@ vEniNKp,YrC'mRJ;EjFy:^ Gt߲X蟏x JA\{吓:sDp 3Ÿyo:^ߒG 1)q% jIQٶa9NK0&!9e9^\EGa/6VYY, Ytܶ 6gxɷ8+<5Z=غ*,=xJ̽hP뺌G_ZOKo$;0x dO%0YKD}og(W|dcг |/?Fҟ>+jcl`V/;kg /dgI;x /?cm!&'he-gi/AM1 Ndg/ -*Y~r">#^}%Sc]|5فg=Ԕ\M\Ԁ[`"'^ߠ h~\ތq̈K#ea~9kևjG>Q09**F-DEhX_[(:bϣ΃7 Š3 3$] a-z^эz Mcϝ>eEӲ1 Ļ#&X&LI[۲.ze5/c[VVnKy91A"ߠhovv`#ੱvۏwG%;> NLsV-WS"7z@;L 綝䁢Vb=t qEgmG|5O :"Quk~ߌ W= 98zsoCEMK+r=#w-7LpܶmwZk1v(poz 'S01puʻƽ;kߺ1ON`lʹu5ȨEc1E2x}b;ۛM7LD ź \ S)P]>ٳm`-ðދ|hs~qvru2>^(^lz(Bl\ﱡ4Qp&Tn4e1tqFGmfwA݋^Ɗ-i~ۓ$?Ql]*`A7ud{sߨn.۬%~3~aǡ' gP)_[V-zrq-Aǀ[ |ԆD5aKOV0ArlovBnmQoa]Ru~ H_}y$א~Fn3:1ї̈́}l$O/6Qw(y`AKێۢA@bb0J.gu0&$7%ak~m#_R>:7LַnڇY}oi,jL磆Nw[Ng?h=o-3` wsoBؠ.|o#Yn+6hCP; ~^::m!G]C&+ uo,x0Wrj\FS msp% 1M 7L m@ (Z=@EȜAofMv̛w`0ܶA*3&ۀvi }rfܖk=@_o&7k:C) -pNeHKo}AmMb &ܽEK_zf/"RT3K:m(12^=%(ӂ'z{'#%*>z;Lwfz~:.89Z/}=ZE7P ؚ1Pc|/m٢q+G@`= :+Xa|.FnKN9َPnKԶDQgΊ\z;^©ZUg9`@cKFgYr4&/CηFGr3z%ݛ٧xGn@uoL?Rd|[g,uMSg%Ovrs/x K8A>9xIzhBѴmn;W88u,e&^[ʺ+֏KY:z/f|x mLɇ:b<7AÑuMͤ'-&bH/g=MbQ jܛ]ҊP;{,Ik$stO1ɥ酘+|1o?t1b=oo%;gt[~Ѫqbߠr~Рvښն}I(č4 9R{]}måiA4 BcBn lms[.=[zxsJm\;6/n~*`Mslr L>e6YӅhE'戢al>J?N##ɽo`cp=3;9m 1/V~ PQ54v8ťg*tXGnogjrƸ07AlX}78qv`07k3s. W7Gw>f&JytN6Jo=Wg);g{&k 4̣<=\RxH;${|7(1$!3 ًx REή:krk1bpN3`bW-āӞf~SqZaiir|/BQ/ml ʩ}~S4X*INg7 zE3nR.g3f~ϋMj<{]]>5Fzn~weNoϖRG?j7pP WP6{=ԾY/9֩]4л~~ 5BT&6gn~"`-mo]zQ6j.-{ ܎}xIGtU7Fad4/`U妵9мw'%Dshm@ڋw%{[8 ófq|s]R8^0' KK͢yqY{-I͢x / {. VQ&w0!\Bcє҇x=x qyM3xNkSjjx;lo޹T& FeYp71˨K0k\x F(ZhBȶoRY|܎x RqrFZlPs 4ž?.8/i=4颴϶,=bs/ϙVw/srp[}#%ۓ$&wC:'djn^Lux#;x/́…QD?q䣐me^n@K3:Z}+>@ ~YW+;@FQs#k:}aԏ:Kic L3pC|p8?c9~#^(|h.f;9nެ\`)xIĈ8&<|ecSy!,%^QȎܩ2`u w8f{0q Gy/-.i\h%((hrs[ٸP>@m=lNW4.vXq\wMa侀t%^xtN ₯ߛd:ܐ-'f*m7lqOJ:u5o'>ٲ^8=iY@-OJyx .10ok%Z` mqK'/KHMZw(}]ܶ_/Z[B<% %?<֤y PجqSI/ѷhOK>&WjKG}H/H!!nPC`ܖ:)c8Q3@@02 jh9p|%,#qVYX~ TټEmx-v :H>&a;Npr3qOyخ?XL7ɝ N%^ӬGv`KΏo}g~3q[>(s?6`l=/8/9h`@k]/3/9m14oj^%}j\eԶ&O cPttQ2ow洕e4ꪤfm淎fCo5N&A9+4n3A=bMb=joMo\gHW-~u[L7}"GŚ$^1w7{т9%^ɥ\#(C"8ȗxF2 gBR}K0o[$|B/&s=avPy<1{M[ ou~_ж7-+q(I[jFL]]\#hB!m}wEB4>OX=Bm . Xom3ֈl 'r<>}*${ɮ>,ܛɳd}/ߗ?R1*1%rf}1yE|7OXlԏ0s{p}`iQ?1Gž>O#s}e=빇|,r}0-;>!Kqy„"9^װi-c Ѫ'q]Uzq|=z·ێ}{6{E Ŵ[k3_"Tºwgs)uxsm yIUغ^Pf_jm="=T7غa2<"~"d=v]#kw8cz`Kz#!`gC',) *o-ڀGٙ6V}ʚܯo[Hx/xG:̶s=LCq0 ERþB[e+gy_ iCޏ=\Ezh;8_w'D~ũޏ3M`k91_ޏcgߚ_ bΟ֙G(y?Ė}|&Ќzu# |؜EI\\`ePle=/M!/S~7lF1"_! M[L5"ew@^ȲIOs/!(0 z}~a DFm;a@K'8O;&gbpg 0'ƮavrX2ԵmopnC wF)?vErzȕ8fw%,2[M7\Ba6112F$T8L؞? |x3Ɖcwg mMxX]{oхmς֟:.wvݩ?o1F%pL@hUb>Dʢ :L~^CJ֐ K`;c_$&g=%N.R=YVkC61gma[^_%HD7 stGxcH^"M )?5}yp[)Ċy6 k7\%okwkīmcEku̥ {0[#d\9b_x fÆx[f9c:vN>ބҶ[sr8fw1[v<߻Ut[cQC45fkqwkķ(jt'6;/G0'Z)m@O' {v-=u kt̫2^=.YE IjPP03}QsX;l 8l6 ۡ^ҋ!S87iqh[M lWVL"8#PxGo0.ۆx Ƥ9vj̥;[#vPSA*3vdfAy?9Ǽ%]C|z}:CK`{mG;<&q!ۄAP /P~RbӽS)kվ0)ݒKaߠؼ*vu)O*{ Pz7̑0v6n`u۷;/`c `o]H#lT"{hBl7$[eN ^<v?Ӏ/gL!9/wxbh5/@?v^w7_ ]Kmfk%M=>%r&sQEHN7 90ubčur/ )!ӎx l7mYjBK$lm!V^ IQi3~ж/sF2#Bm-!<'jX#x l0Wb=ցv=wz1 )ya7wqF/Q[L%N;'b# )ob~q5$ߐ@zd {mCqe oU_ %QWy1ۍ )j{iaxȳD.7cO%EЄnq#}P^ [JB^|.1(y+ݔ$G-m(30"XqixE!i_ 'kyg5Ut^w8n}!PoQ[˻Z^<4I8:J\ngG+zz,jf[8P٢7e~n§Ͷ_s /l[Wf&Dã۲lF̢f\9թ r_ "84V-|Mm|[斨AB9dh8d2gs|=ܨ5)>'[ǹP)st!B/zz`3epݖ:.zbR[7bj!~vö-yApN ~[n`01KrlZ7eE+zQ&fk~謯/m5ĉQo7!"'u]ˆrϷɧl)$_&Xak~ӎ5wῢ%>A?,~a~R@;^M;r6o}"3_n叴nK9Z7 S/>Q-6ozYCgL ڈdl60Θ,D<نMW/t+fѲ!nk'hAcPw0N hAܯpp- ?T{>¿1~/ڙ^ -:{V#-Z[Qj,^ŋ# G~m.[4:omy#7(ۃڎoY[yՐIRzmiP4Ei~'Ŀ;c;~9k(4_VrY[w-a5ifI75qIφrǛm ߡwnq/BJf QYtYd-m~[hhQ43m72% F#0|2I5ԉx9͒e@ǘ ·m~ۈ|H!ݓk~Ӵ~˥'2g|m~sRs^R]M31-,m7/ߝ"qWj }E T7HmrD/fgDH1n=6yLrzgn;LidsA:v[FѽCpo^gSFuo.w4o4Q* [epsvD4BE/u6~vx1@CMoPMs"z杽 GL[ R Zo/kz;dytV5FRPؚx>|q[FRz:99-tVܖS~iȽx3}Zr]"2~HoԨ4(5yoZ~9 Ꞔ/  s \gC;;&ҳ=>5j }7,`k~^UuO_KD[3@&Kd&Z̭0zDuJOeL\jk~ js]R\Iniak~냢-T3o[m9_b+zfN~H%I XAe~H.eALޛ<[⻋"J bVyo&Hvx9ܢݯklr??qnքoO~C=F¹oں8tOץIP_m~Hn׌o&23g6 0pe.JG7k8۹%7 qI-n QHu(Z:XnknZ.ez|v~65gjF} *|C/}`Jpے3o͉#eښƢЍfe>v:,l >99 e~B##a~4rzmf~#hòCMq:)T5OH,kpoCi۞-ݷh?jgeqHrLb;ML[H2Ϻʃ߄e[Mawq]u?~rkVb9,|m~beftc8zq==VɳWv 붛8G[cm~_㬸/k~C-%\7HpKf=sSK{h_%1'Nqrʌ?}_Yɷʜ=L pD `ܥ60MƱ/ }#IKK[ю>5?a :fS( 2%Y[,@o~}Kr,H^pD x/qtD=lȭfvc_Po#x 2 az'ax~0'IqF9^`qYl/m=+Sћ< z:^–'$VKmOJL cAa~[O _+0OͦKcsmm*: ?k:^9X8t88lRu~^ l{:^NQ̵FϜO/3"%6s [rz\MKa-K(vc:GvjcGb=8^B;9moƓ[l[dj~΢  E/yAYϾmzMWb.#@8*/e T.7k_5fe:OkXetr[([ɻ{m&5Km qӉgP[qKA;G+Ͻ͌Fէ%;Z7:3u~\\)lW~3q sS~ g@n{;mr٘[ecZ~EmS6B[mj7ep*KmA>zl<D9ខ~C->R"_# m6sCXm~[T[uwRtsFmI\loSaU9ʕ)bgro6j feD~Kuu~;|nб[غߎ@e4$lvOIh̥&jk|o"ErqqNE~q:^ wغ4C["xVsa(QٖVsrpS_K$Ws]bm^pÆ0v^k~((wq-ð|rFO{s*Զ-`5h7N-~sWO(?9=pe,E3jrW$&}=$"Y&?vO%-{EǾ]pZ kEVk-xAkH%[bDm1Umo&V݋n7Olo\wN4(Z/9C:nj(P/|č (rY:]^\]jx+ll gZkĴA97a`:Jڙ7|Vxu> [p:5jvm@o漯X;Dy_otۈR]VC773^6*|EcVd=WX zζ٫^Eyu[XJ rZ3uTPrxr>w5.[إnOJlQHׇp[=R˸PtfRϣB\c=Ki~Q'K/Kִ 3wB4j/Au8F*/2[$@Z+;wG/QۃAJ6\dɖ%6VnK\*_] }'px d7*qIK9wJltyz}W?KF/k@ 5M%, 'C@%ϾwacΗ}dY--|ErdAWSv%Q#30⹎LmXZl1oٶgK~,?ї%jVkR&/PavM /K&!R 28>.K8C<'/"ۜ?Pwz٭\zfvQXA(}2;s\LwrM^A=&֙%?Ǒ1S/|~9^zȩ4z29ƴ/AB@fnGCP>w9-69V jx fLQp˞\EBL^1(K2ᄾ=%sc`iXOmԎa6_َ̦@zsIVnO[!.oO/~^,QGߎL%k=/AkРwaں..X./AlBL`IQ/kێ,@wd~)|u:C.w Ǣ~/Q۵yՔiZrYoif3\lo]{2IEcڎ-u%50ppd5+x :p­ G܎FQ)t`  %1ԏ7"LRMY>;ߠҮ:#RcK0'pqj||_/Y#^6ݡ/YpIVJ-u(E<5ͳz;^y|Ok:\&~)|۠->Ɣu khQA\D#;8./Px_ۤQg!e u/A ^klK4nRwjpCp%w YzF//Y2K}SIzuy*b~2mro5ddHT}+j/ڲ{;^q%DfBCmGu;^eRk/W󹎗,Bm/qYx y! osl7Wg!?>ގhӉᕸdQn;^fdl9 o>QYB7N[Gx"c=϶ ;gF^b{ ;e]a+ϖl Gc,kdBC,ޑŞ԰BTum]HM_r$m{,~W/X :8}MK7̵~͎%k}hR /ɢqw0 xpt(>^Ƶ\<HgrXlw%G83'ơET =9" *q=8[8*'{&5m/}Rx^E<-m۲>6)K@լnj%Z؎gN>)5ϝn^ĖZ^s*8.wso75/y ̀%)M/̆88^i8X G_ؚߤHUK(E3 x/AZʙ6|x}D5<(3KHҪx QbZ;fFEly53r/٥1x_zp e}5xf1?FL|m `mEZYIJձ&/ &@oSw_uA w'?^}/A_oaSY5[?M%`3$T>KwRR˳^p/(M x&[Y:]7mowV\ath$Kz-,u\z7g -/&KZ;ڏ%3 KGI3=Лl/8 KA"P4iZ>\d\OM[*hX!wڍb;,]˘ F]0e1(pxVoc? Z~3Kq!_J6!:\N(Uv 9^r'~LiqqNtЖGAo) ˢ[E}.}AW;8`R,{k/q/'yf~[o]ĈVkM9zX[{M=~}6R7{@$B߂Ct/aYuou:^i3=ܜGKfyς Xd|_1.U; qhy383lodL|㫷KeL%yV;^.7{Wǎ\ƫ8eڵY`NukMM=ʼ/ 'ͤ-{u=9^Zۭx*^7/A*Zcƈ߈|=>}BWul8K&=p{qC>)'jx l7b^,[qMނ:7W%0Z+1٢= x 4;[(.&ߗx A\;m୅N—Cj#7=Vτu<[[jO_qMɹ IJH\$}y@^^~  Q\:M3d"j7ݛ/`v|~q# K)N˘x Wp3Mu+|'soP`LbX|mɳV0!~ uH:f*8fLpozmMt_ın!FhCUpߎ$z 9F|ߠᆍ&i3v|Jᴻo- $>)x ?ђ&8ނf=i=o= 3<3$WBē`2ku]˳ OFgo{ΛKI,^Zs[Ov?xk&>̤r;i;ւUn?߽i#LB^gﰞ->Ҽ 6.m-uvA? +CJ=kfK_9Sˢ-uQ] | krft0Hrhڛ 6Ok?Au#6>b9Jelz7w /Cjͱ==mo I¯Ծ6UosFpጠ9Ewmr}df<)cdwpmPS_6IwAU\2Fђ=ۅA`'qԸ~;,}[a~;M^W!fC/B\k!pi@pY'k,vHh,q78D,p `v W?T*.C-QsQ~8u‡j#x2o6k7;{dn3-`t]vao};oP+am-)XŅ6gvr[ف2i~ׇ!WpA>ox%)n<^vȼn¶s9|>%U\X5 w96VqEN&VݺcSm#.Y9\D^ltGHqт3zwdߠBu!ݝk}35%e,:[Ki~[YE`(~*s$Z,ul<~;9hVxgoQQ+χ~u}א~;x=@e~ML99f~;Ӯ~됱&؜gnϳKLa"G va4<ı& CY:;7P|=v=u8فQ'(ro鬽g]m_}~&g߀ȡ.qa+Ls.FC7ځGg1{fg_8^G jߕ%C/ԕؽ!ִ69s= @^WB4͜򹎗ncꍒ"ATQ ̵ãJϖ5%ˡ5lLى:p% u fqdG?!QK: Z[a[H zqD/(ՙFZ;1y>yN2i~[%P̔qU"r}\Mx//Q*䢈%$g/ce~usg$N9hp-#ǹ .J0 ]Yf :^48W ^uAƑ2[-mo׊b=ؐ蟏p/3wyaRKuVs=xO c-%K{K>4Pő [y{(M<u|=׋x_\}/{Qb}~msF͢2#mT udn~"溎6+k:t[L o0&Ü]VYĶRtub^1u[YϚ#&LaFb46hܯ\ΧRB-I\KŘeNڝ1Zx&ClyL9r$ux'uy/zimp; qMrm⏔9bSlD~/Xg~~D2Ѹ2'O~Mdo+I\.9] Qcpf.ߢQ}/(,xUfDtza۞-녥'IYxغlYWC`1(%}rгRfC-px.PvZžh .}Fɞxnp ڕ; L7u=x1/C"M]v}{:4o~۸6[7F &x '>W(1 _셭j I 񾎗hjV:ڑ\K&32k=%X3^KKݟ3Hq71¸vud^*VIMx ԥGz`ix:^N5g<ot/[f_41m\Kt 1*K:^ !яNZq:^ح3wf>wmG8^rSsg`-iu{H)d`V%i\5O#z/@ QidMB+:^Rjue̯hβ Tb{K e^Rhx ²T C=x r1kCD.}/Yr"1sc9^NVoB:^ehVMVǎ,q-9<~xȻJ<&%K:wj?"b7qgXml9:^A]ތ5fesoz~k/ ^K؅(hx" B' fuda:G]u}\;Xė18 P*i#% uA/.$$uxIѢX+2+_KlpK%H/ĸ// K|嶆yt S_?9%Ԥm1 +3__KZ6SXͤJ7IWM:^^Zg9 YhzЯ'ܛ2[Trލ? P 727aso-L^f6Nwqxغ&X ~ڡyulAwN(&Xn-L8fPfqՒiݧGvg+BMmX/ :\!}K6B\{xH;ݖ ߞG)mmPx&EfE5WհUso8;Et=RN$vW-z [w_`;妡p0azgj{Sg;%ԝ=Gu1Egz}p^Z@[Zlq,t @; Hց{tdq\#7SZbM0KMIaj~iE#Rp݁Z/&磇~/ɖ"I9Ux|]﹎8=eؚ')p3@?26:Oz+h%hԁ3V#0J?.Z%E;ĤesM:^rL<@حxɁ8?y:Oj+nA݅3Ls^%R8I=[K(%yzAjk~zh]rю~ &Z>Ν%ena|!b%|2wrW|KdQx鿖~TDE#28/Q[j̢w6giAm! {ih"+|xəPgHX@ħ9HMK40Cvn<&ImQf41R-:h ~{clo-zm` {3]e7sa$Puuɣ`>z굡f/Q[|_%G?,kxJpAX@27Lq7a-U?*[psӸ ^MJDpνx%5P7(Kz'0FxVܖ|fO.̊S6 ܅ zc_8^)< Y}/QtK=}mmw[M<`?*|xڢdK3т?w-UM." fzkи75}x zV%\&1@γ~uj,Yxز6Kw[}os5ŕ.P\mP:.kM7%65࿧1:^"+z 1 ~(!v</:OYŕG򙱜%`#f٭;ze;f&}xz Cy$ܰuM4@v∗ZkzpF\k7sDyN6q$FhDh0 u-~vl;4X0־E 5W; ~(ꖙ!H{m]VJ`tg+lϳf}출ϐl\N]WloXP/Ih7!0oAm7~{ 6/loHPv{%Uzts;%zu:+@osD?m95VsvB-۩4N%=g{ 6(_mi`bF;lF^9l;q[6IZk`|_q[G#փ%y/`M κ)Gs梟)%9SheH܅tq4kw7s:vFf~ ]g)(lo(~K}&wsojJ2Ԗ=v̄RYN`+;wq:^BK/"W9^r7UCbυQlYYGyKs = /HmoP *Z2BjG7ۚO`L PZ;%ܢ:E/ADE{R/eQGeغ8sW}-7lo'5sdzEa2T)NA3[ᦝ\ ߁5KЊÁW/#̽~;o'GS c-uzf/y`+B?nA| m%c;< nK<5kTzw'$0<1FHoeV!?jԈv^L"_g5ؒʼc>V7eXnpv[ Yġ`CK`H?Y';;-VvSW;)Qn&Δ6Ә@dlXU.bۙ3&E "-ݟ-gzgv_Tz5OqlqD&oC-Ne5 _l[o80o:GZaB]qغfJTS,k}& Zjz~\vtz5B?Umot,x~C Y4>,Ƴy;`qtPH$q(Z#{[d$xSV_Qi<[6l^#M &2E8 qg&$JI_xj~<냒2F#w۵p|TqALu뮶k|عkpeڮg> -g%_fDo tKk^I=Y9wG/r|붜kԤ0aeEl-0-/@I3涸[Ğ(W3Զa=1;cyŹsb F8ۚt[4JJ}PH3+ﻞbYrμ [Aayуu9>uho=LN+XO=ИB Be~# $Έ _4s,qKpz'moroN >ں h Ѯ7'ǂ߂7Jk~9w0~Q>[0cd-ӓhY:|n-u%"oڶgk`,3'z߷X+X72Ș@/F@N`߮-['|MN|jYKkS 'K7Q(<]*ߺ-m:CeuI٘kpTz47~8:ȱ&/ t[ ,qo69|8*:oaٺԣUtꔬw2.Ls٧mOT\yZ%Β9-x"gJN}ť(dfO۲j*y7m_$I_&@{7Z.5bFں cysH~;{sir;P&~Cw,'Лvipo:^ =]5Ĺ/l;8^2g3Y, Ʃrow%e\p}2ud W-OZsKx:^2LLu` Ƹgu-op)+8i$4dw%\gq2q;^2cVPi%CnF: +%>싫8h>Lnh!0v8X+&Gr%rUs6uK#*Tp}.8ؘn ]L`g#KvԒ-qqc\] =[Kȏ5.h<#K 8Y_'\g-JlD\.|x!l<}qxLջֳdkq(#քܒ$-~~UHMGWa%w 3}7Vy;ΚEw&B 42\p] 0m{\}ޭ<~hLCV m 5%KULsuKՄBᮑpoHx )RC:cyl;^2;|l1i73fM [N4lWQK.0~|f_ }?7Mxɜ I;.'οY(^1'1)<^%̇H[Lx EہR?( ghFxɍ$ Xx d0Wft|K^2Me&.zz /;r' %~AY9? /)J>W}Rx vj\v{Ԑ^vvl /C#%P%V&I{~^r/m V%zԛK0{53$e /q [*DKG"Rb߲:Oc%W.dw_7VyCWHya@J~LpgPަ AHw>KЅ`/%/uܽaFp( _,fS]Dž]xɽS#{tXK`F17CAspW^-vsc8 /Y&0Wv%k5 [Ma *o|7WxgoсO;]x Ii6j{93(o{4|C' )S]xɢMIwb;Sގ͂q.dS$IzA觾g^ip 鹽vK6 K5_S^ l|lF#s׈5c7Ax6{j|gK`y @i >L^B^).w0N#dHG(£Ij.SkE`B= /ٍ]a<5> 37hq.dS|^p3>XSl!Go/,%.a-~k)>gمGv翫 ɠ1vO]m@.cMCn tK^r9 \(yWx ,I@,Yp7ʽLpv / ^su% z:_[>KЅܧ5xxf*=bNjOs(y]x](hv >9']m r4 3lp_,EԒ.g3(%J5$g5B' /:͙|83ZUޖqݿn K䇲+=U 'wOrȃ{^B|Cq'T%Qp /!Bi'OrME/Ғ/} r.LC;W毳 vXܫՇYOL&RWK0]>ϊLx f 2y=oKq] N_)JΠt^rqІ/h{]x 4C]IpVM{u7Hbr_5w%(OzHNs,^# |t%K %z`s^%]x ZT0~>bPG-f\>s.@H3zgߦX>&p&nGԁwgk}QM*$ԙ] /1c6vKiR3+^2"q&NБ^-5K5}=i&Uo&7y%wLx ㈏KeV6J7af!^b/ -5y%7Qi&_ZR^]'^fW'^x@@5Zl/AyG㟈-k tq373 p&m :Cl'`x5C%kEJ~70${ĮYYłW|ҾkU:gH=4rh{^,J37(o\2>PBoekLg 0__EyuФ)y;㫟C"X3g'i(o䙟t`WXm ,+ПKϫg$X쬝 c7C{&n~3;(ۢIjLA1Q7;$}ٝC55vwIF%lN덪Qw.+>%8D*ov6[\|oTt#F=A1XZ6,oAS KI ^ó'<N0 wbiP$ͷONg&y=,o< vJ/`덭]4~VgV>AG rvƋOۈzx)wDrAWo)oٯx0m[_jXfa.Z E͂ە7H&g ZlcGX2e%IkoW&jXp.]y>_|oe6g+otw<f;^,o%A)b0VyGD/~wXlFA]yc4?6s+ogh+ۙ+71hǗfW#i6gg|P&}g*o$i3 U2!j:X6>y/6I2~vos-G~ă;Ky0wFzcYpFskg{6d5͌5l&_$OZޠBMu삇8p [VXG([n2;ޛ{ms|.ZZ<.EW UU 7sc[08M4o+WyC q;4V':&+ĐaH&:18X䞻,{v7ϥImo϶6+NdPmyv}lmywq+v~CGyoY_Iv!5Gt7rޛC*opE=Q(*ohݵ0GF;$m늵G:GQ6%|_(^ c!ž9Cx Xxii:>^ҩM+gQ0hy(Ir+w\^#܎=K^=bM%\q8G^s%Z˜X \{)%Fs)DgfpHeE^r"ȩcf|۸Tb1'h>Rp >p!A$oG.64?ż>94@ 8:K`nKhc6%FUЇ]O~vKbCKϠ PZa{ʚL^! _qء=uz⼈}mg|%.Y+;vSxINR^?P`xSxI?t_^rF=W򥽱C_ue6ZIxSPܨ5o 9ϟ6rF?Ԩq`y$_;KCg:^2̊1j<L%hn3=KEb۷|*Sx @*jRޢyWŬ^rzb>ý<,3@x^ے=RÕ֡OdVlg8G}$O%wED[9/95>"ݎ7vay+Sx %~ 쩱޽օI ,=)d㯅֠=)(~w'{ w)V@K<^9W3Sx A?t_ 0쎽{ FkGx6I:ǐBJnXpz֙=P׳o%KQK6|r{(L%eq$ AؐAy|X)c|qziJ^4:_7,\K@qŐI:6rX_K6t;[ 5:ہ76#slN }%w_J ,%X 'W zۨ?R,;ޛAw?dHx{jm'Ehpv^,3AX;z-%G p:AX!v BaWoڂU<'!'+vfCV^re`#q878^A bI*o"gGk𼟵 Dݹhq=(o'zXXmR) 7;glt0?=-v^k4 / Enq{.L?lMx^matמxxjփϖOsu9i;zKx hj"9c =肻}r/A,VI?X0+q89cۋxɢEޢMl/a+.cǿM% ~,_/oK}@ /Ҽ6]Knlaٗc=/A,\*jJ6^/% +p=^gVW޸N~@%?R)=0pΝck|/ڂ ^mS[֝ny}gX0]7=4FSYAٽϻ孠o \#i-#d;CC Y3ukytp~k,R/swߌMyJcr=l{^msIC26SVk; \cMl̂2JM#g$~tI糓k*oXSy ĎKZSy5\?#|t/zuNb})o /i#~Mm5g.)ol6iׅ tTHJ|% ~ѪM%yms /T,G50x׺i"__;KF-T N/bHmx2=^2P#Z2"w76jp\mR:h /Άg&Q0q-db(?X@ cT~ /v~N [xɄ&= `@6%B%l}wo%30kyC) wXx]-"{gܹXgδwB>{%ī= /8(^{ /_5wɶYYקQQc^r_e8{N_{%m%xX#ØLvջ`wMဤR?"sLl /b5߫+u+b7uju\\G̃qk6ˑ[Xo| /=Nkb:^ML48޿(w{NAvKةH[o8[x pF+?I_ȱ s^"_XWmL<įXG^ H-VyΊ3+zy>/>M@Rky;3זI쩯|ܜ`j&M{y:K}1 s8/9@0Y7]%_<_K/if@e?# O ƈҽX%'i|L쁯|sa=Z^r_2p{/Ol4-s5G_;K()_+=qC_qb!^X+LzĒ^ F::K@6m4V[ ^%edEheݼt vSgZ0 ;K6.طgM[XC{(s$Rot qxF_oS爵C`$į1X=MyywEpdӔm36_롈K.ʛ9Y>wv *3m7qqc7hPXͱӋb= Y2<*vMg=5No%2rV`1-o }7W#v(b0ݿD_m/Dx[JﯟCpB paV,_|-6IەQ`j^P:8/ )g(o;eg zhGxCy[F`_p62 mSc̦ia[{B'Ǩ|Vfax; S@5$6oRqD/>Kʫϰ՛]v3|=–GǶݺ>7v5WL{F홖/, w 3-ok6|%4|V̦X|5=}O7T }Iߺ{Tfb}IgT&5ləۢQguٿ*oYmLPgZnHffFGb/;؀ ,/-ۭГsB\E?|||'نa7;,oBg@=^n"Ox71yNU,G\صotC`C6NE/O >ZZεb|K0Ï9%} /pQ< "ӿ7%9$8e%U/ۡoפ&4@'m̟AxXU%}p6RCſ %'^.}fsBxɍEǻ^2]ӈ{ sE|{0cn|P #W%C~B'o8G tc7Lׯr#[Cߐ3}.XKf5k]_KFs^蜼ۄԢtdbo^xbݱ/] %إ0N@j$B Z)>)V[A@ ^`H}oc7_gQwslU0;_Ύ$ObgYFMx '[w&NGI̒&dohz9ψpZ {v_K[=r%@nإX+oJMky۠6mi>|FX!lZ=6Hi慗lj% Io^E:J}-KG#k25^わ ,݈Wx PpɜHty ;i{U\4?/]wͲ'{U;]=o }̸B`&3XбO }@a}0$NljWx qϞXhS`Lxap?yARJqAx vC?b;^?5:x_gK IݙUx*ogP7;CgL.Kb,3 ˿ M:0i6f1?e$^r@&J ރxɍIEO؞wZQPH;h>u%",p38l%[c]9]Leխ7AK4QCދzu>;ycb73%q;gvsw _~vb/IQb-oQxL%J[6Ţ[Ip_Xۍa&7 zIc H xUօ~( RhZÃg}tUި:OOMb?uc)<ݪi:V=@&/MygXxtئv<1-6ON4^&M~k2ֿZ (> 7p]Զ(;t8m7f;]\_ :۬7ys6pډ4_Sl'zP^c*b00fy0Dm|t\Ţ MmǍePp k3b-o*x Ak.XhS}}M/fyPjζKn~-oWꤧyxCш?\).'H؞b78bɫg@W +XXmHϡ-*F2Q|ٕ7I|gmu-o ƢFR,SVړwOXDpoK2xqG <&&2,ow[M:DsQ;,oӯc8O} -;P7Hy1b9?%>y[qËlXۀ=UF5.Cy[wOZB9YCy?.vZ']}+׸Ͳrx1eXܶY}Ss`Zfݣh(~g}9G=?l 3&Ziy_%O y [.nHBNPT,tJOx_Vϙ'a)2_62-os6Ej.gϠ[掃ȩ|j}`r&Kyډ;l#~]ۡ.JO3m5`y#v?vbuɼ[=)_b-oـ7h[XۢZ%NM֋μFdc)eyO r,'Q,4+vb79+c-o0;E!rvCK>|i~rmb^!4;>d*oQ;{ȗq"~ %}ڻB9^.@&wI,o8qNQ`y,fajGTw_%H tz+z^ KG{^qU靕%>KI;s8 :󦹱M|E:aLhldV,ofBZou%hkRx (4S8\b^gWe]z =%&Yi浲O /9b"*LnanU:Vnp3!NK Uxi}}S )SFئX }ݼ-DU=􀤒6GigE33wb)PJʞbw~ }pKWn#KTy[V:y7VyP#iA>hvRp-t\][T%>;Jl3`PEK;yfǟx c &?;N^[{=vۖb9Of3<"V1Lwz~ӌi-HE|v>ڝIiʛſJ;'1kj}4F|:f_m}/73Q=DZgL bƏk.ZDu(ovy&}}mX{I|=VyC[C曾v'wK߱R*o`R}w[6=XOأ>Z̟w*o=S8iĖ˭d^RE:t ;v'h O[7AGOF;^,g(. 9_,;(;0bIcHciw dN=j_h3|y)EIǝv}K߼9 ^}Y/o^fbr-Sy/ox\*mKyP=kj:tzm_X8ՠ$?߶6~>R7#Vyw??by@ϼF]4>~2LQ0Cs VM9X/"#bfQ< .] ÿ~hw6:{rCU~pn`&]Peע(b7 _qWOyW8/:}k,@qg*7)oQ+P+c3z/L{Uv4s X|whP78g=Z!oPcal]OXm vX,5#5o{xɦ0~ߦy>tl=dlk.X|{x ^rY"Vy;sLOt]a^;9oo/>=jN^[q=Qԅq5%{cO5Y}K ,aA{P;SpU.[P*oc?\lr^s {`b&%l2;{\xoK07VyupYqX&Ʋnq.Jy[ T_TH \ /cҁ]{<]|KJ>L®7 ^RP z6x bq}oMe#ބJWUc_?Yn{^q^-zw'[:|yw+F+Mx|uGa j#Vyս'QX0RW@`rt^R6قfr^By'hpp6gUWw \pƼׅMZ]oN2_K8|5$5 ׌gPo(%{^s^ؓM. AxI4 k5Myх@ !}CwYvXT #EDZ.`.C`O+q>њy<.6 ̑ +hC5~axRH>&聾/<];`)&M%UP8<8-p$k.ڴ:r.{Obw]xI5?9 /n&)Ax 4 + nOK &U:"p$ 3Lbd6w׋n*p9rϐv%g $bϋ=%כ} 'r8 /od"v+v{G2@χ@N~@^r_N=ҷiG^[pGž.r}XAt,gpxjВ^u%^q/^&ȌYVH[?n+..?'AxI-GkS^4Nx=%ydf/oz&97wJ^n v̟K^~Ԧx[ًgP*c=oS..D^A{t37MyބTbawRc /u͝jkj /7E!رK܃ixgKxX ,<X / $i5Vݻ-t% > jm[#}oG&tV}x IօTyq^Rm-T7ӅT(_=Mx cR7{ڽ'܅TtHh܃*o8erb- }^R;O˗c ȫ7jw7_Ϳ8bЕp*qcN c_(Wx $M^XzUٿᄍ+B&?慗ܻGCjhH[Qހ^r؂. 'C:Nh?wI-v c=|ewܿ!%=5*owe[bwIX dU >{e#W6&%`GK1IDhu%'psũWxɍťi԰x?XPu!.wcEg6$\>+7@Q 1ctߒuԢB QH*o!py7o[_2@| IJA4(hX%/F&Ų_-[KAx VعICxɍ5-As,'jHdb f)-{M6*. F-ĆV ^yºm95d41~S,Kձ#h+wl{/iVGNZ'Cx ېO{_=^%!k;;K`!r=Fyޠ8#_%7X8#q0i/f5N̋P_[!fFq(GlCx zzSVK@ۈö)GucFf{M0cM};2;3ux%XRѵKCxI4֤֫<΄4Q幃 }>mp@bN;(8cv}/%$΋-|f /i:ȱft'v!#;9C {M6A~jqkN6]m̙{jգ\f/|L7t޹mdCx1(Fp~sU` TUlϖx3b6U Yg/>%@EcJwD#Vy4(;ϼH6%6%goN'^rcw Yl-&=%aGdfiI#G>31qS߫4; 7t%F_|]Wݰr);P:ղ2_#?jPx%ј;nxő߅Qyg+b#F(W^^mׅ[=F>h T5Ѱ~Yz/iV̑ƍұ!qrm/2 {ijRk6Wg*<@uk>64;4_;A'&sI;_:L섽\1'=(N`&;s;N0tfqKU'U qX*oݼf}hs, s!kqx_L%8@AN~|/Kez H51^˛G,< 8S;8a|wIN=co:v /1ƀ ξH[-x^}gc*I%&f v /k.( nWwy LSKD?2f"%ιSxɭC9RxmVpXmggl#9ɖ#Vy;.>t`}Gz<}NsISxI?HPt8Wy;Y/@̾h&^PE"jޏ}{v /̌;b닥Y~={>^Iv ICc/w[Ouj /3h-alߵzh3=&j K(Y֐6;?4Msvw PÛKas^2̟wx} |)] 1X;Kyy+s>keTԁ$^cs#J } ^=`ul#Kxߐfϫ!"eK=RKx <<aet / Y2e  %>% 1w gſ m%dED Ɂuj1N0%aɨ}JSwNד7L/<Ӷ zWy"_P<7+1lz0/RLğ9^Cu %dNj4UaƘ{_<}QC+*ob$>yuۄ TÉ*o7X%͖j ZK8~{{u6}?^r5~,&gZq\n /f<㍹/NN}IٻqDᰥ\—` /4JPns9?u /F`}O_Kn=bx$ш#6?߄LI$3֯;A|#k%Ƣ6#t8?d^&zkvM)wymsjk&.&=%:-no*Χ>΀`9s /ñzs_s!djvR@e *w d}{PL^5 ˿:خXj/KVϱ8Ji{-ynq뺀KxɍE48799Kxɽp~V7[Mx"u}X~3Ə)xq&6.%c\4~+nQ$'\{:^rcy>O-%y%\HU޷u^mjHLN^K/%me<} /Ÿ́]n3u%~/O>Xvk*A /AlO %k ,5yOm /Yps&i4֙ܣbи\Kx |~N"D }ι;~@YC pﻋyD*JNտ w,H'^={.%w_3傄 𒻯|*\~ c7ҾBT/ d {^r򹾘*вU-),%7ka gޤlyK֚&^l2#W /Yf> mZFs /Y^$LwA:ۮ☁ .o;-^㠟Źw֐,o%8FS캵]Cn /."i&ւv-dmU`uK=qܗI49F,h1& ,{_%dgvxl%7 GW.^@g&խF.bc#=᱊kXjH#K[i_j^|^]H/X^r]OTϻ|-dCD=&5޷Ҙ|8/n\8bս}g /#dFQ}n| /#T Bo\/مG/3xgKkdu!Uܿp /jL -@IbNo>Kv5NCŲx5Cn%Yz E >[^ݔfF\f /nW:0[c?` /oI %J_cyMXMM!Y^#r|wH3 N^DԱ(jOx>VǔC-dj<Uq w= 52Kn~Hsm%h? =hKBgFwdN^rUӼ^VIPx FH)GЌcx[x1kp /vY  Y{˧toKgC';ظ?^r0h%p.2ݪ[x |eԶ)-rjJLs^) v9ax^3jLzGx #(_4GL;>KBi~?#Gx WpV3*o?:􍜧>Gx ݴ)PI㯎%xT끑}=J˼wp'P8ݴ5#VyCNS?XjU4uq9K@yV7zc/I<һ˚uU1ʦ77td`2Qc<19p {29zĻB|Y?ʘ˟ǚu[}95BT3(P,idCk 1Zآ#}G=F^u6&gVQdk0^~?CyTOx%g(o淘璪A_=΋;Lʉog(o7j=9t1xfshSG9_ @v*o0fa)9}bXQsl7fT6K3;H=g*o[}xm &Lw{*J6\S u3ͳ04RTQ3Hcx _,10Q"=vu% MmB>Ky^Yw#{v8z!6Ϊ/T!A^9k0jzвa8bI~q!gl 4_M bb'Z⁀½/zHgmrs+f@p/}^74JN/ޯX*vLm-]s3{%˷OR/鯏͞DVJ\Gg^KHh~gVȳɃvz yZl 7i{[*oE7aӍa<[Viqd79O#_4V=AmA%\\5?{0b7?$ϳs#k9Ϡ g{)?  P`8]}=Y|uv7*38J䗷QJK>΅| I0R3BO 6+k,絮Ms3ǻV,zI|ۮ/}y3xb0{ۏ+bOU'O&MހNĸ:ǽYC֣zUxнQZ`3x3|/&a}?oQV\#8Z5}=b9f퀄/ocroJV_Ԥ=Ny=l:'<ҞfηFZ:0o𩢜b,*!AXɸ IϫI~H /ߗI_ Kù>l܂fܗӿc%p+.&u5Us5~zU`=3`-9N%:\G7KYH'j关rDM\=6 ?\K*rmoHxI&]쟵\,pF&}, /~=oKbD}1ӌ.|Giq0VUj.Y5Vi՝ ;3W9?x|7/k'ջ=xVٴ#ݸ_ /?{kS'_lE} /uKI #| +NE~K*d6cWXxI5ɓ$?kx^JmH$r!)k]X]䄍Kj^fhn| '+Z:N7Xb=Mׅ%aQ].T3{^B sn׺ؿz-s:^RMis|C)ovϤ7xO&Gzg"|-EH />bޢsoSxɍe3>a|Ϟ\7be}Y+ɟWxɽR< ^_l#),bML[1X=w -6m ?# Vy;e,K/Ǭ^Rm-Av(0GtZ`Pk=k/s /iB0bO^}tf;_,gwTj_% Q:\5;+&-;K0b-obv>$Q|/ia Ioly,KҎ. KF;AQupcB^f^N^ԗ#}*U*Gꡐ*o='f:7"vIݙb>7K0rdxALAxSs&vc:1} ^;Y([=KZuu9Fg /\^j3Li"m [ŜY !7D,\K!ѫ̏/Yp/|߃\^Qqe[Sfe/ԶEYY qQXfՖ䲺g$VΙyLzT줛^-7o[e>4,ox!PZRfȼ /hH88q /"jBu"nDlEx zWA=Jxɍ]}Ɔ)ֺ^ME]I=} Vyf M|n%s-qjR:[XJ VU-,b^rZf4&bۗZq$9Wty$6zބg""NPA~@^9 \.K0;bJr"'~Wy|sWHV\;c4sհTlO/*o phc^Fo bH1aFj%Ffj`NԒɻw&Ǎic] ۠nOwc5_;KТB!2o,+׎F-}n)K '}Cm[oK [#mImr/NzW,P<6gfnDO7;ΊMܳ$ԽEx b6/8՟ıMe wtȅK0Ҍ-s_,9S(ǘ _,k!^w%4dA33(["Vy3/}km6(K('}bZd~nVK /yCX׆"bbNJ| ۽&in~7/$CQP__/AjܵDHAo~F|pIRϝp^!v)LPhRI%>{A?%5xfQEY,OM3x8֩[ ^<]F8օEgN:%&dP;6z'y$c1!dTb€*}U7mbO]d 8/o$\WAzAp~q^ u-k<7c=N^:˺{'^0y^2:fKȳ*o4LܧJV4ƌǂd ;^Y{T;-{ƕ1+G̲:^fF{>XmgG£`{Fg$eP|MV%^=1֦K4!Vy(N ݙ1p̦ /䎒qi/S%HTY&hXm5)kGxXԇ>5o^BdY Vy{ꈳE&XH5߹P1L(a{T^2 $]k&U{Ww;+n-=ٟ_ό؍U6dB#lbֈWxɠhV驟@ YL*oGFAIU 11ʎ{^,FOO0%n a+ /ߏ q:uҝULgbTMbmu{I^2OrJ(M JGͻȔ5q;V7kĵ.f507~cbK1bOEV,owq>]ݼ:p=/4:GlyأZnZ^2 WO|F:]/1}'INY^2$߾a2=u%p Bg\+*o'k|gHԛUx j^FQV^2F-Mxɍe5 9C / gVttX1h8nI۽,A#ϱAx W$[@F5 "Ux RajIt/M\o{dF^2ex~ha׃i3WsgMΩƍ=/vU|Izr7Vx}tZR6%v* v&UL۽gi8WZ Wb|Uxɜ'i,'эU&MfˡAD61g =ބN[\K jCWr)on=7ZN}]x\oЮqOߣ@VKƋ2s3%7\M+ / >+q-EF~=XZׇ{Ux4 #>9 ڳ7.kw؅;D/%`%~u%{9v+dϷT_҉RL qŦ^2dVs / SyXUC7mqAyݩO{Z2ky[ _5'݊uxW|CK k1Kַ@4:von{sEOo=QU%T][^ro ބ 0UecȞ9O錽Dx=`)3۸ v?-8tJҪ4ТZZ1oLc{3lr< /Y g]h&x"1 k[|ZjɈKeUO+(A^5dS/tm_ԨXXxT^rFґ{%4%fʵ7&XE^XRjk&du6[-5%ѝg =5X9%mK\F\ɵӚ3F3ᓃjw['>*bAC^B!k!aO[24]Nse /ٔ/f=s#Kn&F' Z=m /tq7^y&l~^/_j{ffZP]ABXՑU /iCwlL(& /9脃BA)F͸|Az).LY&Jv /A7 I4MxɹvfOnd́BΜAmxk]x ,Dш?ߙ m+wgϦ /)?Lx m?vhQ| /PScTK\t%}=^O6aJcADl{x-q'ׇKpC0>* ʛ t` ˎU@t.Ny b b_H3*# H:auz[b{2(5!Kg4 mAԛIW~ʛy4; `3s,ezW%wEd^G_)OϨZr8E+7Uh^Yio%7R5p^/ġ:D]x 2?h}Ny$Y~t%~tr۹Tx c7}*ZT$հlONd^9G}wm*/& KX4#݊d\'~K/,- /1 :ϐ elfL?}>7m>'r YN}(ou8s}8}kr[FN$=㡼U3j] 卷K7UNVc^ͱ[cK83SFY.r{^,zһ<9AY^nl85NyITn\YTHg/YDz3)of<4\O{_3ON )Om3їFQi}~ط{XAJy:FwRvh@hq-;~tѸ,m|g&簽'ܗFJΩߥ6ϛ4ja.FKs\[bYmVx\rzL#ɡحmLG}f=mćtY[y {] 5Xn/Had&[ywC-uh~+omb6^@8g*o)Iߦ 4\⾗lЉ8孀<{>Śvw#)%h%nFDE?7Ծۦ [-)?e01~bѮڮ5Ee0vP,/g^_iŢ(ɣak>yǮ)0EiX;g+r{cZW6>孂hGpUGͤ[@^_X'~WySR-5)o$.Joy:Aٞ5;{[XSޠ!mX孙.Z d~,8Oy'^pQSIݢa 2Ӗwk |˰zpmPң&[, Ū)pISO (E/'!$4FQw^r.(Ζud);*oTo|γ;WQϣwd1*ogD_y78cein&XGbaQmєm=ݱ_\ۤtbb97͉+MDb*o&RWvt_d3(o~ڽb&}n~cП14FG;/ >cQ~ᇲ<K~V\O׆K*-\Bx57 =IzY@CxɍMcn3+h>߫B>+Ѐ[Kj|ld>kyLzewJK*'icO%8"ݱC?|{}!BP g׽7>JڳFXckCx f/k~'-Vye@%6r-{~KYޕi]`/6]Zƕ) ŷ)vQK3x 'CX~iઝt7ԵL969{ 9\h:p1?4pUJx5^R7 Ʋ7ڦ8^RM;'=99?Tw1]w&n77!bK*xi| /8~l&'g-QWcc Cx]xQoZ|K*ŋ3~^R23qZw.%pa׈Ex t O=!}/q?+~4}2³Zޚ e! /i5JK}{ If]9o- _gKDg(΄ʡu'957%Z;tiYq /+dd$6kGxIk$gqXDPmSx Yx΃KZ@XIK̘hǯ zX"VyC^))oj_Z'('3M% K3v9j=u /a_̀sR %fTX$+3,}RxI+;tN^<Z@u_K:·i־Z\mXj(|6j /~{ [w^"u ~#Kdžjb񼖷[y% ct|1/ 3L^ /wڑ=;ʗצSxIւs>J%Sxɍ}X3sc4lS_R3(okT50ڵ9ܻ9?Xm^rK 9#[z'HgKzNԊF$wX*o5ɚSxб O%${X s=TL%8{/cLSx LRqϞzzOm /,RS=$1G2Ih="',z=4 x^E5$=mʿ7%/S>[ڲSxݡVɚ/Ӿ^נkͳ-f3tA}keEU&5~h?P[wI%^(/2trrq^$A/(lkKny& ?),3w̍P@;>@'O763(ol&υB|TymKFL&ͦZ`Fmz)ol%~^3Fᄽ Pz9d}ӘcK`J2ywVp#wu"8l@bGwZi6-M%]Ijy+ǠV{,lZ( /rllVO /xr[: mk)q$K TwLa ;dh^0_<0Ay3Yޣw׎aDͻdX孃T]'Ƹ/% 7j-IR^FrK4t V~Xꁸu|zj3Yg]-%q^l/!Vy(dqt~~WyFْ4iqo-Vy8 [a;s%=xmZip /v9BZ_Kp<+?CfJbI TǕ2H}ch^|fan>>@& -F]${:{_.%1\a1s!dlꤻOl+-~Zbmb\1\n /z @v /&L{Q>^2mx ]Kb}vKx8RuFmgi[KV Ҳ.kBT,ìՎ1ރ-Kx, 5Fhπ{ʹKxɍ s47Vxɽ_jXhS 9 y/ϛ+L48Mqo/^2k\ ]wpWDVb'wZK& UK}Gu%d1i^G:o6 d:zfYKn,:$Sf !2hΡ_Kf&I ~*(^㽄L):|l0::v /Z] ;icyCפ@8G__%0 1g /^ 88}%T0-;%dBH /bPK@ҩGˊ9b71gy\l3 RF7)~(Kxɍf3sXK\ -vKxɼWϊr6^2'GlF̻ucQXK&g7\W_m~;.,&]9`TcbBh?Mxɭ;5ϲ 5[Q/3 <ė~Wyz I3nW ;ƿLR/TOܫ[DZe;;F炎c&ܓjSp)aۓ 睖M}6u /usj~͛2Vx 5;'Kd۵9fæj.'K̹/%a},mo)g,ǿcYWb /Y)RdX^lUȧOxک7~OY*o V_xr/%B#l ?X{`cшU Y{A4> f~} /t4^CI{S!%kPj  ~Xr\fE/𒅓7ڜOhn%7v 1O6gn#0N/aci8Q$\c /1Fbp8޷@dg@@[}Uf@$8-zYs#3'@{[@|bMy2{hsE\~3% ">ZtDk zY^m%]T ^h!f6ܳ^=]q1*o~gDg|9d)΋K6 1J+ K6PFO C(WWnϙgc#-dOcu=Hϳ0"N-dว&&[-d@s}g^^BYv0[]b98brf^aß1l.^b`F% kl%w}6ӯ S߶M{OYEnX { E,A\~`?b*@^y5uBc /g" S8,'aXYUcga'QK C2iN'kmjUvP^CG2W5 X{ dL=K.!@B,sU)ul% ]z^X6p o /t >T Qx==lXT%8] [. РQl,Cj;m%X{AwH KCU'a Fçx / \#|=/\.4eQm%W҇!-]#~/x,h&DbcI+ S(ΟK{oq(zTrҮw*u(RoKOG<{/zZvw|7xbU^bNLG*oCk%LkV&q\T*oٌG:3^k'j/W@䍱$̼Ej7龃!Y;;gGu.^2Fj#gRcQ%0Gw8Kkއ(z/a XK ' [;,a# 3ڎةgcCfK%gۡVZ_ l<ڐ4r^>bd=v:Uy֮H=@y&bˋ:ٟҎUS#eFͩ[[1^je_")鰚|lNU:4I~yi6Vm;.wz4%Y^y~fBu֩wq¯־z 5mPW3 ,i<KvS>3xpcֈwi"(:iiۢB+ cTxbYφr{F?+Ad'F hf:4m:{y޺\tݜx32]Xnl;z@ЕCt)}`yfW([ܯwO],Rh,둢!/zY; yz ;vߵ$%}otQ,?佲b-ߛ|cgłs>CJ7LɁ܂H o_y?zO +mbQ;}|yg RK/Ϙҗћ;~z`dN<7P*/,$O+q=fF g*oXܡ['utbA@ϺYOG;F ,T[ТܮuV+cLP}s1a{T3=l6g r5b1ӻI1zަ6xy 9qNmPds s?70 ^^=Yۄ{FA޻=Ky3ۉ7Sh)osZ uZ]o,mR ܱbk齎7^Iu/@wZ$Ve:kX ϝc(}}yzƜ䲑{^lZnП!c d0+vXlcډ-`;[y[?`7}.lnL{uX^QCnmӻj<;On /\NEI;oDp Gu\7HE&h\؊'fpm^=j'?}vsb ~w eVꔝfg4B.lr/[-\%yl/g(v+;7ʧ{,o_F;]KfOoLٽ]F=~ZC;/gN|#ٍmbc۷BU{uNKS]GrHG.ݫyYl7KrX(mkgPPnҠPϠK {%&J^,皓:ֺ^RG [%f)6nq5Ab.߳jUEv: 0`^rkw|0'8[2l cf1jSu%w3qi9^=tchOTdr&k4[L8Kks|gKC=u0$V~ߗg":7Vyl YoȿM% M -ItbN|![X*od닙W|}_)o952ss,N:j7w*o <&nI Ԥ<Pk]xI,r?[KYr3%<烞ڡE`4'H"S$i΄4[ݟa$|Oy/PqF7*2ٽ/w /ibF5Χ(&~]'FK$8(q /ȡ3׃[\P$-浈W/ϱ !ym /inǡL$-\Gnap=/NK8(WYXn1 ;5qW^M:o镐mnQ%Y7=Z׃?s*K`b =Uv~ہݔWFi /iQ;}O7W.&K3AsBI׻Kʼnq xGHO hޏu%%ؒ3KxI KWGo.E(6vUޥKakdovލ]fʹ%(2{bqqڍ//g,^,}{{VAi3(ok+&}yJc`{%X~a#So^rW:z_% (Rq.^z!Žoa ['~f>n^=16sSNʾ%x]/v?|0iq /AyP_s^"w4؛ܕ;IuI wt@%A΋"zG|/i3v>+uoGߩb9[2lJcNjņ?Zw6NmB默rVAXJ^~T\P֔ߕ7`A:gPf}HAjԎK[Qgi}!`t:Z7Vy4s_^mnj1gU{^AcMT$0יgWB']^Vii>d`qyExIG{ ^U[#ٗv+֎pu(oWWxI7Vr_kytJ|@w^&_;J5ߠmO{\ky_>x%5~wjB (KF~Ibw 3H|^ֶvAߐQq7ګ$leQw/)K0FVbE9:~|kВ[_,wa(3(o'nGzAwWc^k ߦX_~ ,օ9C-0~e>pΔ^(ؾ΄niw[W /!4f*J  K`ԋkGzи&Ƌ&Z)(%Ä kܕq}*o(oX3zݫ '8d8Nrʾo%Uu%~t q{ b7S~z3^)9ܕw֌Cm+[_["ifX #Y{r~@XQ3ܬ1"dгТ#Vy7>L1"dpɾAK&C1-L~G4"dx>0iMyA̋1g LP8ͅ % b Rh~,K@fZtzTy*oo7Xo%]mogPގA'Tj /{B_aةX~6Jzll2|\7v+oAN+Bx {SkJ=nlQ=e)eΎ%1Xk~Gئɢ!a > dV^Pk"W뵅r>*o̓*ħ"Vy&éiM1s5=(oXKkRyؠ;/>۷LK`3i v;K&pF_/4_%sU7s￴ݳ3VyTRWy#1d~5u}]x n%#HK6QzxLLC%D2Kn,If,Vy Wښmba$_p2/cM< uۂ5/j;K13Z~+M%@s\t+hR(<Dx wqN\aX~W'tF}!ḵb GS8q'? rz^ɌإXѾ^OQҴ&`kbgf ~-w\?v(HLNUx 6;G^6-B)zci0R)+b︥x^[P;d]ɹ(E{ Y rtz*otaϑ49k.C-4.\Ux aָ`f3?9/rw}>U*os1~b]*o3$=݆VBpmbنN5$FU:`J'ѿA^f, b9ˏ>mbAK:1q /YxcX 7@H;h$*j2ܒ{*/;zXx :o7Yu4NUxZt%xb-zb[")o.;{`zk=ޯy9t*dsO}e#UxɍEw- o{)dw7ܧťm/g_up|Xʛ1vF}nf%[&gU$_Bx=d5wүFvԛfס{Q{uTӭKGcMZ7(Y;ܒW%Qr{y)dV<˹7'\Uxہ4Ζ;^ 6~5p\k=.yV~ /9 qOccMT%B,'=K#ybKnLݹ\Ux]:{j냜'NJȲs&3ձwwXoSQ&~ئs佽b|O fUޠ5J'mKN̚%k&B+LhE) ڴՄܵJi(G?X-2ӫ#Hs քά&k4refWZz..H ?[wG.7Lf n/Mx Z;bu-|:ׄ|3zg^F -zX%g*ԴF T;^,I& ^LAy[h :㿫3$$. / Mx PIЯy /Ԛ- ׼PJU64*!{Mx ea!}i+^ bcf_᧭gޢŶpe } /a[Xko)-EFl}tBqc7:͋x/~s9pX{ B(SImm3%O;FuKw hԛYx bu_1׼r6/(%gMrE \Vq jBFtyiOFFय^sr<7jK oXm4+oBB%ތ{+o[%Wm]yg^ }7ߕ{=-/"d-wܕ7rבp9@Anߺ#4̷x/uTՉ=}Upvbw#Y\uOpV(4[ v}hv3zPpoiCy8@bYqLDw{P8Bvn6x^m+#I|XN6rw67TcX/vCt(dAICXzٿ5Cۚ7gWLߩI[:0>~6 ùƧAǜDnWU;5lSyz.z [6$N!ܣ! M%^|_XPw|q'/*oVk~ɓJ;M͌f;=5Imiy3?͵J[bg)*gc򼭪XjJܯH޷,oŊ}->+4c*q/ok(֬m J/IzXSv$!b9R-M]=\BU>(UXBK kXn3l孂V ,+l[y[l؈m孁ܙY5 Gϒ|\Kc7Vyp(-V0Z/wVޠ, ~Š7Zwnb7BP_*opwuSxu;۠8PI:.sy;f;9.F~,aǶQ&Ҿt »|9Şyѩ}޿] UjO *@B*osS*q;2qw{)QH">+su~ʹmw܃4OygMGzBiޗ 4dU޷ٿbyߤXmS˶;F#X2c>`7 Oyx 46 !U+k5T.3(o-͘WhZak82xYRVe˾SG'RsQ7L~lsenQޠC1`by/dVUCߨ;+M =QKWl^u7PǎOG䖼^mT1qe+̗?kޢ0^bX-V̳%Xj-eK̛k|X9?93[tc*o=^(-'UyC Ku7hP6:wV%f_OJXϫ5(&ߝ:|uo]~UyA;ՃDw{M& mQU"|m~k.Mhs1켱[.Ip>*0]x}Otzd{X孏ܑp_4TqM^RmFSۅT-b^Tgoϫukw3=߱ {J}U}^Rr">:%?q' 6̉_wݤ.{up"pv*ou{3-rS@jM#8Xm_\3vʉU&tYVg(9wIUpR+6mY}Fz FXm%yZʁ@ #~}ۄ`yQU5c /&z\lɂKS^R!;v]ڣ%w>=UмF|9([ )H)uP^C!ڏu~ /4;ߏTyבX0N*ˎ\}5bc}Sw oԅP|8c];w&:8i>ޅzfpP^Lve];KOO(޿M%%FEҹv}o6{-8i$'K5Tg7ڣ(/F<Zs~3(oPyw%;k7@?wK`8B^AgCxIGTKl|N)\,-GKn EN l}=Uޖi$$_pD!o%wjQ17KK%bX0k%BxA}Xf&s9Fhw>g|Jj!I5dyǜ^rS[GỞ><ܝY s,B21|']'<ܳA&73(oX O7y 2}JuS<ηKn"s%mzx;gGw6y_K` !4+%bB@K' X~ /k63֕A㝭}]~Wy[dJzwK*o5wӭ;;^r˽~401sCx ͼY/K[Iw!wvle8мe. Ե+ Q QC^br3v-fA{;YuXw_Ow܍\.uVتʋ|i ފX__ (zlW"4VԦXz#uH'5W{jSx D#ПZt3+ ~5;ۊ$%MZOb /{8VX%sTثp4yPU!gOR|^[ g5X-1Ə ۭ𽍨c|[Ni/1)Τz3鿫.:.1.=(o<'Jܨ_M#+K\Rg||GM L^wf51y^2Q*MzI%Neo޴9B{[b=ܝo;^bM$ZK!{%g/)Fp0 pLx N3YDxr /?umA3V<ܕ^pOB#wgfKVGG΄݌s;׼4'U?_ҋ/חKibK ]˖ WGyK_tK B^sI$zq)du9I:K HP2=(oy <|^L6L^#ΊsHxGt ._O%讂昅Qy78jUvIX稦a!'˦|e۔7:c=ARM%7BM wL*o 4~9Pn@K ';L. Sxbn';F@"Vyۇ$vDSK'> L ./fC#^񶸟 /A~0h)&`۱ޣK6=0L%.rK ]Yx}!ƵX%&gQl+d~˹Eδק]^IQ).ꔭwp튥!8t)Mǚǿ9uz~}NKao=o*}iHT3РO8c+Nܫ>˵_ilߊk.%҄eӢo~//ښܜb yOt` Kxܤ?P>\^ 8l9GQsk=u /A,?u{{8{^孓4Z|0h%d?,⿫u^ J\Kl0~^ GGr%dwj[49^rHx&dP%e!f{xOt~voh&yU%Q0ZmuB/s /}^QQIc x w-%w%@`yMBfWx _rXwG_K08}yҧxx l-?^/`_=Ry8 *d=R=Jx &^JtUڮ#SrH۽K3孁XqZK`m旵4@=,~ /"ߏ e\KNgd~ 8ث /9}ޓ*Jܫ0f-Qp 1]LQ.%H=:&!ԝ별`V4I{a /0ꡝq] s%Mi>s`莭,%|?aܟA.oJ<66`~}H/d=7Ddrɣ/›5b6_dgx b\/? ^A݃ȧ9%~)|uM^EnW,*_H3,%CCOsjw>_K^fֱc~͟a)Y5\&{G-MfBkl~7NS*|/@Zd[Lt2kr—8{.)o~-1IϠOy@xhUFӜ?cj]֛w_ߟvW+،ِܟ5z׻[L~›yފFv7t\]?%ѾnT I;e 5_zb1PrgP Ɖ\SMb_/cr8.4 E,Ey3I 0]7('*ģr^,5enrfW p;!Sa;F44lqήŢO6o-p ]7|6\Vo*o@<88_2Mo$=Ru* "~yN4(91 ߕݻ*o>6u-D08n}'dc8'}7~kq-["nmbͤ{/d)oxImyO%Q!pjLogPX֨["%8a7[-t\Y"w[%c)wۊ"_IJDlY ^>cMgrO4.;"Y쓽Xl0#i|/vODlS,J0y)vyP,&N3؋ޕ7p% Bռ8[?_ߒ,K:Uso HBVm=jV8AwA޼e!Nх,<˜-Sd1:u.ۖŢ b&eh]e7|Y 3E7O}tgK[`z< Rn0kIJP:m^ёgݼ&=ܛ7Хx<~4#TStnlbQ]ͥuLP{VJW,/,C){O6[xy ͞<4%HfǮfy͗VZ~Ԣ7;As%8{~ q{+nY-Z^qo$/LbvˌoyrA7I?ݳO]2`?=$9t9׃- ,v,>5Gosܼ ,յ/\gQKL@c!3GAGYWq6hu>&q6E?b%9sܼcQߴCp7oߋH:XU{0 {0ۤps%[2yv29yw3\kC%s޼BMwKkrLtΛ7tj7d6^#0x0dҚ+]r~cU|^ ְ҈~˝̬=C,捥L] ‘z9̋ 4?Kh/텹x /!̓^nx 9 ^gdlYgٹx &XbVs:bϨ}]P6Nf]'xɎeu|tq^ %Xϋ`17P%'@my[RpS|9c\i(Hʺ^|oyw^_XC~ߺx 4X[B;pϱuKGb_\aT5΢] boΟpұjT^bɻq, Xxɾc8}oF#0aαn "ѷ&s so`&{Yc6%7i˾.^Ot'xWٵNK@W"V;kuCoe<䱜%;"Cv^KJ{]$cIԔ,BϽy?t=u%y/3gbah ՟{Yr.CwCn-nr8s]ޛ49⽸x K(;L5.^R#BW`Gez 8齙zc1;Nn,P\f*6vXsxr8@"7>lvg.z켱(+X&-1.^X uRi~x.a$Q %ߋ@t!bov[Hܩ|.)͋Xh|& dx 50Qʞe)ky u݃cX/UrX“h{/)Fxco1C }Q }rwňurEɚ[ coX$KpЙKʎs&V !?'/^RXs&c}A1uR :~h]Juݼa a38|7Hvx ݵύxɮۀ?G*Kv,^Djr9.^R8R4sx *\LzY`K n>K0 u񒂩m"%-SݒcZ/)E,z%eγ@ܽ*RKʢҿw3]?aZ,9^#.Pa" h]O񯋗&ѵuKvx >C\,H-޳hRj:.^R`aՠ޼ItdYR7S4Т;ٺx E@k2orus̺xI MbwWqôأ )rNmTG%3޼;֩a0qcD[EkC?˩; U{`` p2ؚ]rg}gDlX +hR ro,j~*\ F[cly=H֡#X7K4,jĶ]k 76vk87qc3tWzֿrgYOvboAHYG?qZj'Ӯ}49ͻ ܍5+"nzyb7o4Hc S٭=j`X7Rᵹy{yx B } vw<8RyE?/ٱS[(aKj"2[{]|c%%پ,>L/FՈykP:Kq!OBn䍥D;d9[όHsvU>rmqb6hJDWbZV`p P -7,Ce =歓CKuyȪ-4G?/=, 6?.^RZÀ%E+pmx;C>KvM]F-.^RYYW#/ٯ7vH?ko. x%xqv˽b<[o,uݫ,硓7m7}yo`h$wV+K,'p5-ǟ 14z؛7 -_Nd /k(ke0{ˢ > /^\4UA)&eIh:Ϩ|f(Cgo7oLK/{:9q]SQ /Q${0\[vUN=gKv,Hln+f+EsqՇ?/''8n'F_}xI?\jn9yc3Kz%/i8.~q_߾&:ٔ8>yx iK4o]_7n:^^\.޵pʵǹ~Vi cv[rպgY]M?.^KOttt*^]5QGu,27??s%;Ffؘ];80o]dwT&̪WL;1xIg/Ï%t}T~/^K6nyC?zA5acۖiu_?K/WJRKw%4yazϒ[ '^ Њc2_K:⡈=YX~x..^X0ꩍ[ݳ*`_+L^ce #7C޼U$k27c!؛7ycY2i p&XmV{p|:g`&nw?7x b(Z8DiK Ore`Ờ,<\xeWyfs/u ;w|޼3'dK T˽5?GMϽy zzpޒK|7lU+\>+]B~=b ޭ38%T/Hw |@0o/xb}78E{61}7G%=SW?֞~_\mXyf(^\i\!XBoyܹ#>w5K}\a^`!pm\s/^i% %@i>x HvNʡ-(IYoI/Ap㾻A}Q\ DG b1~c3w jXx >3ppx,`E}{4} @F~(] بE g؋fO\}Qg%(԰+2nJ.^XKڊrcy_p`摼K?w.^KCW"SAg KwۿYS%Pwy$%@؛:&rx x/"m[ 3*}k#9x HPx7zNqa$tAܛ/a^]Vt/g/S̚k~|񉧷؛G5; XD:h]QI-_kk mz*a[;[lbUHꀆeŢN# [vvyyx|1(6RhB-`ptbB!Nl 5NK狗`Ų2w%(GZCu"K;+_ LG4> @5T};7ouHZ'O^}x q͢ co`P q> _d,s$@%@ҿq\s|K q"Iboް;hk&,K&Ĕ8=F[-5Q$9V/^]ea` `KGrϳ` ӉȚKߖ SYp Vg%@@W@!wKNĬ㏚%;|ᵊ%@cV?3%;gu8?X3R%~,Z˾:Px1;ܼA ϲ_:ga@Dr^ к-f0%pKvSPx$/W?x=bnGA=6[,s>iOcA%01C7CQ/q^ܨ0 /9ׇhsl޼M4CwS&V1=x WW.^'lp񅿳oЅif؛ݽ'm}\.^Z.r@ wܛmD;Z6h b{~ .Ux"q=WhXy lKGт&ۮ)vE0%ϭaVN4۱7oOKcogm7o (a 3ԋN-wN]ŏEnހ?H~IX؛7l,k8p㣰%:159xɢ9ҮU[~r.K(͢DҚ>7-/Aهb﷋P :. ,.^kɀwgκx ,|nfb_}p i*%%v'qaqrbv |^d $,x U^sCʍwx vS&ip6X.^)4 ܛT8Cvc?Ϭ\dkq_ğߋ!~9O/^d A=!of1`+>I89 rA=o#^J7{~%ASpFV % ^؁E1gPq/]u ^ؚPmNJi :1Ɏc.>)K;pL!qqr̛LovOUo/c_2qI\[iW? BgrJ8qVml'Rq-27EP[},vR0 ^70))߷. Nd7o&˘[(t^$u+aܼŮgNYCyVInv_bZ>-~ W̛Z9NoD>łYES&qq[%\T?{39TW,6oT`9-Ze޼a1'Z=@fw˃Y=l VCc l7V5|R[7öкyk[ٯ ;eݼ5 w7oYyLeŏٻbn!+jx򽈝'e7oBBuy]dž,>z>-{IeMJ}ni؛7  >l]B 7uY1&ʖg?w6h Syt +Cy7obQk/ Jsw6&}CYJmԯY,L ~9P o_~ɤML;؛vNs={|E2}lnܱ F,s1ECyovz>γ)[,v̗ޅg7oaPsUtwxv""Y,̺R~IM'od +Œg+XP捥)jhƄ",<~-s?hw l%r>o9vDTnplx0a Qs0_Fv*%iR(?X,)f8'cHGĐ|.qyK 8 znɨI;k|$FSn3w}2$.>;--zOW}Gqx׊YԷ8I;7z6z'j&U+\2g?ݼaAgB~7+a{>NeZ,2Mppkp;bkF7oho =.X[(,` }7oB.ZW'فylXrxM=޷zV5,ah[R^/P$;>+h^ds|؛7,7"؛{s&!j>oyCYv3γVʵ} р$XXq\dВ)I歞zy~Ϫ칇VĂL ʬzAݼDҴg>q޼BS .JRw;8x!{X̄|}oZe ^E9dݼXl@$ogK70SvP1g75J&^RxI:"Kj/z;SCʶ0ɋ ~ _+)T/^ϛ/]7x8RF/ٱ]5?/$ ׋\lSH{F݋P͋@# 3Fhc# 菥wAn>˯/I.LI (=o/IG 0Ip_2s ^dPzEv1wK@ƽNK \8K.^I(Ψg;W#ꒋPOVnv/u{D˵\c^$qIG\Ո=y" XYGx }$Z,43z}S9ZoK7y~37o6, 9.^^uKG:HЃNkCx T"}}^.^ACPL%;ﳈ7Ou)dJ|\n3R޼]f)uZ @b1'D[MW{VL \ zXmV|iѺFL{󖐖LxU2m6?k~toK7K-h=ߒkS(v;J$G j/4q3ԻꁴX6c nXHMSxɎH˹aϺj%;VM'.^G ab/^G1?~2~k/)M`TC{QcԵKBch5z"XW/9.^ 5ru/h z؛7Gv?/.^q0۾*Y0DKv,R\Ϸeu_}Zf7o,?TnxIY(}9$,Ӵ[}.^C=5͋좟E6޼"'[6~YyLxɾ(|n4\JGC/ٱxkޟC;ܼaHB^fؔX1;h/ٱ ̄xӆa8]$s/>vӄ6럵d*%ᚎ Ϙ?_ {%;[Dzs!4KrX`Tx.^SMi}Z&EfhRn:Z;W%s~5P] v?C4jpN~,Bo|M}Sd4c%'Y̓rCZ\o>v#zl  XcofY:[Frrhq&ʾXTRG/ҧ7z"1o/a_h0ڥ%;E^j?@^Vԩ%;O]ݿC7%R@|$)=xIa>9:5`%PB8(7o\Y`xSk޼ sy"NJKP^:N񾞧Vn޼5܃)"5AF</?WH/ٱ軧de~;ehˑ$bb@k/ٱ$݁􋗀 h?6-ݱ7o9ǎCx+۱qǻ޼uBWM+ffbaj[K`ߗm^d!4_a0嚨%qV2-4s vJf>/ 1S[tq7o`G>+{F%L H-(Px b{bwችy":c\sv28ufXlJ >@%Alq7xIhK3z6\|_Dg[j~3S9G7IKSR" d#`GDf?Kv,YE /ٱO?!)B8/^R&9#Fyq GxI%!/|-^aM$[]v˽[V%ɤlSw%؜ :?}AV`.[׻mԇ ~_}-o,>.`؀h؝adz~kL?޼-Lf[wKK0%.H</)Ѓ)T%(h#\JF/^Qkr3O _C&X<^dSl"T$u5TpV_ܟT8b̎ G%s8 }~oM5GlL]9~ߋ 6}R $'PNmNp6j"ex QwpY>bN/^̩0s9w.^O(hLAUARZc\fj+hΊF¸xɎEhzN[^e쇙l+­^F qx ! VQdz/BLwxɎ=QWfrf\dׯ7T^z\dW8dx E^EpK*CcJ!5/tFiGq[Gjm7ocY#9{9.^R?)ѹ#vX,7Yb7o4lMvSXOwY,to< K@_y,(K*pEl/ٱجl KHљMӽq=Gp#w5Z͑-o8SsW>A7X#[I~J;3.^k,^6h/viKP`Il8^>ݼ{ˮq}&̞z\\ޗkߌ"LbQ%ޘ jo/ # vy/*e坿x |9Q໶%uP`k,X1Т/ :+wKK!/:K*ԡu ˥%u{[> [K*#Ng=[\Wm\oe KߋTTk@>ʖ{A`ʌ $rl7z,Z^bW؛!2]|%h7)}*%_-*yШ;>%~7ȢPr d\,Rs1;%:Q3t6o7oG!B by]z)؟K ЯnW޼'ii}\& W \^k\. 9Wm\dbٗr*S/GR9.Pc/^RM%{q/ݔd17oA&N`%Ԏ0>Xs]q`\$SĨq\/ԡ%M_Cwq]{AcO. .:O>/b/iš(GKPx{D,Iqq .NiYbk& R?`Dވr_b{Oiſ} XwHXRF(Ö7o/u"}@8qh\ j x1/ٽ>=ۤNd%|L./ٱ,u] ͖hX[ kyRڔ*S?ggY%ǍpKeAO .zD-$uXTso46Züx o&[=m%Hg>OK"-C fU;Q&=%02ý:3co2$hS y7o(}7u^ہJhNpc;}5wyW+A܎ym I"Kv,]^0骭pXgqg;;5/^*^zDw^da $x T5"[6h, '}fۂFcIO{wyL7>cDzR2̋\$z_M:/h^=m\^%h IHDS7y~hEI΋4b6#4+/i8T/qbo ;3ycBp\XްKNzZyRrP2 f9sGJ{]M/i#ռx > ޱ䂣؛NVf+ɟqE647z/^ :߷Y,,9%x> {b%;vPV>ѿvӼxIԢSӸ:؋4jc/8_aMEfAx.ؾ5x m2ewg?my5/^ҠzիlsqBtE͍8WV=2 >9/^gIW6{%4IV% (.ScR./9~]2On]܅/MfWγD{-o;6U ߷[j%yt*9mVny[''7i^M"9aCإbhܡ0|as'7Ec?yĂo$|Q6:h^&`b~?̋%g 6D7o^P70kFy6[hw[X 'J/R٨)Y#{!\Oe{,R*x5OK:g\*<>s_i? zʖfvͳ/79Ζ~ww2ly!EBAo)ly[|. =u {ξ>^/9mM5mou񒳋Oncٺx~iz,І.^QP/@1}Vcd}xɎf]bمDrG^1{kn}SCj]gkO]`*7н3y*7gfYZ7!{|?uꪖ7Y'񅁸쫖0?vm[a˧ς몖EA06`y|wf:Py#А_ecGqLJ/! 8.^ >ˇ+]%?Y{]/ۦ>L/ٱ<ĥ׃*2;\d7}t? qܝ.^ұLKO ({bI)T=ky$4j7}^fyb[px jbi)}5j  ElfIIV9V卂J%ruNZp\7>di&T!g%35%ދ$h-F8'/^. p@ѫ޺x .&O:GG*C{]dba ",&ZfbK;N.^Q K6?3@Ǒ`\bj}ֺx~35Qu\ﰼ/`x& 6@xHJ2,oБ:wQ#ofytAFykL+ʿ7yk\{|8/^[GpN?/ٱ@I(KLWr%V7]/ #B8exhx7oRHz]̤ %6֏)BK:>dϽ{湸xI95txA[;CWşiy[)'#ILkey4h|N>QV/I֎Nw%%ru ͢^.K:pLJtcx TWuց;n,:4||+<*GkAvߥc-oKΝOfy[<@$7x0O=w:eqrQ5?e#w4 .QG UCAۤE=i_2.墎`L`͢~´\?̌”]ZPV ǘb1ro.R->@lub5Fg^m0J9:gno7?建ôXk'7˰cN1Ϻ_KiW0hҨqg`xɜ;(\8S]34nafp_݉YaC' MO:DhO]UAX_uC+^Rъ𒕨o$J9<]9 /Y+K9C0>:_KÃ"gW K K0Ձ*f; U(Ϧ]KS|}5y6`Y_(b-oh*^xv𒅩[EuŗBH6,*\kj~^ Ylด-sҐ}=y# w@b 9 aC#bp~c>jrVƙdzsqttc+=rը+Q"/@ t~Ɏ-=צY踈7/MAykyvP>'oMrU\j夞XcmP=ݳBN=8X˵8Ϻ:pEv2fIr%oxފ3%;`X9){Ʋ$%q,q {Uu1|GlV%hjPCkX,1qK+ϞwkZ:kܤ5K8bAZΊC/104m!rY9Βiy ~3"g/iy|bMcѻbWx7-o\L,r>mOޭuи{WCϨ۩{ĠK%Xf6 k&.av|8 {ߋ XuyRbd zV’޼_&etg%x6C&.^2@qĬ8VE P /^O^𳩗ù/Z7<~mAzU7l gi!ÅQYָ)f)RD q"Vr vtY,>7 eo,oGoṗײ&x {fUj/gy#SXߡ5f(c-o5MEXf*~yΌQWmڄg0sI97o&p˿òX l&eL{.^[ 27iq%yf{F*w؛6 bhK,7t4x +؛7ޢqa]8WxɎ&ԻV}K=5pOtCY}] VRxLXϵUQU Zq/R<z G@'okyxΆcm)[ި= ̞lype77-)?5c-om.v__7ECJO m|ZQ@0~Feۢ^`b@xXc_<t} 79?>.^a,!7o¥{juK/16CrVc>t>]w2U\XtG-{1;;8 7F|k|i{7!:zex w f?~ǦjyC%uwF)XIVM|NKFqw,FF=ʫK -t>{Kp$v2ۂaW?boް0ѷ/mP[/{pN3ixɸv"vGNmRN}uMZw( bVYGgd,P{zOtgv@PU)=6d@o)-[ܛp]eǴ8S /(~%煵,^C̏U;|{<ְU;/r >^dK䗋,lx 3,1c^c\(R?wڱ2^8?񹖷yZ)fIAƔCZnu~i8xp\:X{OqPCˆZ{6 7o ls[^2)rˬ@MvlX^L` ,slxn+QW 6 E\;Pg>@ A &^ s,4&Jz ;mAlP04wLG#w7XoSzQ@A}b-*g=r~̆`؆s]؃&\Տvþccov?C%8I1P&^B^_23/wdžԩoY}H!e?pĵzzfxj%{֗w0d5&e0ޙɊJnky4XӐ /om7c!sax 1KxQL:ϱ%)*'`F8nKH#BQJTlry' dU狗L!fS%Q?ܔ j *CwK@S!\Z4?cs5|T~$P[|_|2s~RXw=oqA wsKXlUB'acѤe5Gm ~w7d.סz .  F9x N:i~_޼%0Ske fEU ꨍ.^X`}Vx  KZ;\`o?=GQj2j\[@>7ǣ {>;?X{[m&/sp]u8占j|:.,oaV<-i*AGϙY"||!Y]/ANPma;&/^3G; G..^2c~up9n_> tZ:J7cp!jY`7+0s-o&}ҳ|7\8NMZ96wtǴ ]lkNla #Y?=6Ylᴣh >{xaMb jܥ1{eƆ~&y+hhgpIO}9dx d DL\ V1WKʈx* XPwVɖ7JMJN4˔qf}=p%F!(f%[Vm̈́5w卻]vvý֡ܚoAeϽA-V;<>byO,pkyaR`Vս i{t*F+}Xް?t`R`stc Mt0>WK"y3 CtOnYE8u? /TQ\W\3] /|6wE,oñ 2cFU /Ox;h.~޼шZiϊ%L j;95o-$'Ƕ%nyO)K:IcXX7AaXs2bxi'<t?ФvsQ1SHPoT /Wӏ+fk,o؝Osa[ pi"zixIG!4B~ʇ)t\oY^eepdw&(pVt?vҵ+] /(fʀ<0v /Ieh>Y1 ZCgT-KԧƏ7͐)ČNH><; ,$*zUK@GpSwl'^*I)7̧^1,`&֩І&s%% S-b fǒCu4s-oXT]a8WW`ۮ@>[w V a5pj'N2O{F/P TX S!aJ-}-o$d/%[E΁?@46aeϧ/-oJ@=^E햷yz]*cc׳v܄OyzyK0ǯ.?+pzKTK\G~"da]Kvl:b$x Hřzlfs$k4> Te}l+{6KW~ qx. /AgY282np-Ѭ_ 7o4I'zf3< %CAr9p{3e˰37.`{y0q /OC}o@t ro.}lx uvT7P~9t՚%xC3}Vt:kk@u΁1f0<ˊ{xuY|X̾Tl @+Ɇ-; a?Po7dP8#FcՒ 4Iky *auꆗ ogtKbO /솗gс3@c-o>M;^ VJTj(D{B"zxTY>5;~膗!!yK|膗L8pNN">xZ`yC4+ \%:u.ќ-3F /m\:c@f7^{[hHG'b-|V2zw / T= ]솗@*Fzu=KJ)3C|iDͧ'^AVł  E[\%'6g5b'^rbk%2c_rN?.KP:w%seرaԔG|vcC/(%Gu%lNV58wu\4[_ |7[qT#W/;+Ix_ػmPJ=20[ͯw| w"gVlrYax/"#yh ݎgf-hCR"zDXNgo8 4OV ?*iykgCQ_n5\jyٗ単nNW"F_ٸ܅F,oPK1.(rd_֩?.*^ +&7E},oXRX{tؗmҔX9ȋr 3Νeya7!.X9.=ByEǮ-aWR0O,gG蟿K /I@1{cN A^#[NbV]%_X}2ԣr|b'Mԏd8n2DE棩[0qW}rc?`|7obVWx~aY,@T'a&fFU&g;h Gh;o#Y[.H%.YjPG/$歠Bw X`#O..h/ qF^`hnc;kŢG,aUUY$GUׇnɵ%h6 sg%=YV !T0UYɽX[M?^ 4_'3axIˇw?4$BLƩ=%7‰"5mH`y+ĩ=F;4{iQ &̇%G6}@gkxI3axIі/fߛ4؞p%TL?[0@P>f#7;='%}Cʳ:~81m 83cK9A-No\HFgBh"{%I}qU皆42q'VMS_!x /4.YY4c+,~I+1ylXIwh:NJ -1ix 1y-s`^ce uwK%wL.'66[ka:74;>so;X0u=:pvixIV>۹SqixIjh:7/<6y,A9>`g0uKz'_YtZFzެF~y%cg;8D|Btb}tZ^҉ 1:>'t w4vZ@з,NK.F(}뀜;ߎBpz%ӷd[{dŮ/5jKWdRC]>sŲ8W-}Z{ ZW蟡]sŁsN%s˄E<XV ~4d`2?N%4d^߽/hBMKhՍ+ş/4eޕxGW>m eF V0c-o$H˕^/%>z'l]h=PghzKDݫKs10;3lj(o[ ~E / !9(Cbk,Reʋp=ڿ^2Y,4J5Q%˝ʫI 5d֞w_L-4dPgC0/g@ڟ:$I,Kg9Oc-o4S+"ǖ k|lPXX`g$4;%ؚ {sex ؜_O@[% } Y7yi\b^Dx(m/K(dC6oX * / b^#[^688g- qYǺZްޟt/mosz,M'I4(Z}OE}-o;2b-oY䚒o,9Cb/ >ťЪ iCZsNPkyAJ@b|Ƶ{]kyC5v`۞#{EcH᱃JR+ٴX?7BqcǂwK?g/z?{,Sg3<<wZjfz&}<ƝVbnCZd?zLC} ;J|XjlMHF ݬ<^$1_fy>W'ExXYy(a[oc^lf,3q573%Oify#Bҕ)7c-ors VE!mXIN8 Z&oFdT4hZNwm ;t^,Xl^Aw?UV#}>ԗ<^rxgy p|Sq^f?Z\\^m@DzT7vR N0 & /9:;E3@ wg&ZwP;r'y0GX]4j gPx^0Fǩ8<;=jDKjUIO#ŧJ^%=Ë{E BnZ/YojZ1h[>^B#̝(ʟK2 fpc /l~F=GlX?<094,BfP!O6ϛ%!%^rIѿ^ə.gQ^a,z҂n"& x Q{MK2Ȇ ~tU,Q#^H8bky57.,%7*Ϧ{T!m+@/Z 8GR\r҆d |: ͋;/ +b:a鱖Rׁۏr׾svBKyX(MVf EZ(g_԰}X=LrP?%Kc+xkyW3"vy,5Uˋ<0 fqT_ek|L鬍F| goHWZް#Tm7Rg>T=z,*pEVc+;{_m7Bk(X=y`= waΛ3<̶X<:~L^鱣^P~9wZ 䖔w8FkQ4 imE栖"{lѫ1Hd 8i]8A2$##p_]* Kr @e` c>-"kdxɾ5E%y8YtZf±%߷zlC>bŜu7 IwxLpX`YisX(O /LX,QR[,<, .Z^\: `"%yRU|\}5 8T3M%_QM[kyCߒRR.c-ogZ5|2$p6j#6X[%Źnx 4Eiꝲ&7,Q硵g_ܟ:*^VߣWANXHY=VaC֎gɪ.`Y!E\XZ9^1Zw /tԾ5ڛ /0ai'28-byoXK 5:I"6y}@Ug%qY$֢-^BGlX|r;;Y⎭h$Rc B]=CA(biW5%M"H2^3_dxI=ڃ~^jK 0G ƘړUŞ7ZS~u|3^Rh7͔ /g@LBc%t%^:M^^ ]?Z&A4❾՞cK kw|mY~/w3^Rfн }HoIY# saxI:(K0w#II6+ /倄* Ѫ5b=oj,hSkycb5uK*y۳*lE] /H(H>|fW/jBG /B3;bO-™K+;^RA }0XvNeE4 15O'0TT tQ(L5f8?+*z;ZfbN /1>Cn8 /7uu+=cyc-f\bD^/[tX[>Vzg,o _ <;^R gO /AoIC@h3lxI=v? %Ci8q BG,hϙO>p=XzѫSab챸K^$^R=@w /?ޥa{IXz*>I?OfK*8Zy<=i6ʑj! b-o MԽ"Z'氼ѫ)ga=(sfx~TPmoBK~f%(bw x3 Vz͕XqX= RFt]ϙ%vTL _K*vz.d"))^ u{9V /lt;G=ixI^f%;BrCWӌXt}݀rZ)$q^1to+=6k] XO<"eᩖ8R}<^R'\܍ fK?:%y?ԙIn.+tg2Veγ%7i $F;iM0fK*Q;p%enI6LW;D/cOj.GwO⅊I]kUbxIKgHsLB=%ƞz(N| gIkLYbxI.+jR{bx (.o>8ZkyK_;`Z[,vl [ /ifscOG/4:#X GaxIHuW`PĿ%ތg ϼu_1xL:߷EϽix u>נR*掵sgy3d퇳ȃMsܪH{#G zb9^] /iLFexp!h=vשӖ7k>;{&Ͼ4(8okKl}D獢87uJ]MC!;=I7C7eLA8 /idߤg_p%``^Bw*wzg3x.4i3w"ڱbxIǬn(7iu>d1N`_RMv]?jv~)i{-ðXx;AXn~1'j.GV;,"`N5'u5bU /` dݥsV:^.!-1V-;C<>P@q~3vT <G֓/NN7T᧢m{NQC}HۡxM[ 3M;޼G.@ѣ=5%z#=d7S6 0U-{^}~ c-o4M~5cK/jCV4 /v>ڣm>tXo^(3r<:;ɜ5wM6OVKP]^&q^!%St3+> ?wg~^ҹg;i*kyË8T?uzzK/;gI&AYst //zSz[5JWtSFy.m(UχqOԇ '2{6Pej^ ps^%h;=Ϝe%>֟o_'K+Ӽn=٣Y#g%!Cj Q?_Ki@F)i>>>Wo-qzvjh5d/-4zF /4\1Dx/ /9@1̉,! 8Dx"z,-:b}3d\wl82r%dFl{Vky#ܐMQ_3d4pb'c-oXqth4KB$Y1^28l{z]X4` x_3d Z9cٛ>w4.kyPpayá(~7VAwhú\_K&կ_^rPn35y0d~W-x߽>4?Ϻ%N9FjE$MU$}@LBO^2|O߲+><" /سUTJ=C|!\0Z^2M酾 /Pz;tK&x6_Qమ}-ocf\?c[$ ꆗ P;m۽놗Ll]A`E| &x{P uyH7 >y!ѵ9b5\Z bJhuK " ?; ( _,f <~̝f7ƣW?G~ajCHz6XP ky+^o68ӱ? /[]Bh / &0K a񽞚Y&n¬U Y'8:u^5wWc6ѓuK&v/=Ƀ^q^2w5Թy9 /U͗Ԟź]σ%Xzx>ꆗ̆zRwN<솗po X!vy2s#XuK&zTl^c1P.6)_r'L2-KUv\^KZWy$nx|jbgwK&Jh,>K"KėvZްϰpo7Zrjm4^|\a|T͌nxd? ~I7djԺZ{~'s-nx lP_?놗A=>8; ,o&܏3z dv4kp;AnN(Z.ņb^Ժ%séܻ%\lj%s ; 97o61o[uG 1F ji;?IZpH%!%GG,%sܩ ,YޓuK&c=~̠,os:/mQLjL5> /T>kMcG^r3%RdXb+w /OM+>醗bkz{lD?vP~ϱ^_}E@"_]o[G4w'3e=1C=ouIez`0U nxɢ#룩3R\7.sd?xfwK <kfkx ˓Z>`x Tm~)gr6j :>K B}n^=]C7wuLUg^=Ts`j܅@} )=*6Y*bAǛf^;YG} / t/ ǘ^ KZW7 273k2zױ'\G C"Z0=oGM!ؖX$妘7LrVϛD-5W%-}vtu=1PNͯ.:5#/gRxXhke [& Ʌ9-.Qz5ay,ڿͯ5b-oJs1,o6DѶ{,kg_qbXG'G!) <ѰKkB_6='wxWnN ;}qwO IR[#V,[\-

Uiy̱q ˜J#\!#X4ǴA[z 7h($ꪍiyWz4"_-;XQq]jcY\;LyLcYx)rEH Hv!J{7Gߡz,tr}^=jey Z{V7 Qg;Sj9a,[7{F SL7~CPjOsugyc3:]u~7H %ԏ{ϵA_y|jcˏVky]^=WZhΡu*zj?~ky8Tb Q|mg_XR_MWӁ@~*~vtsYL7U*uT=Uhdy"TrVH;`GS{s-o# z.5mBǰI0癋3 {Ie~>dy>/Fg\ LL}Q X\5hǒ*:tno?0+}l#Z9y,.Igvfub 3fu,? Pc-oAaB.w)<Yv '}fu1F7~rvC.?g/J3?z g͋ vzMl%+jvbjߛcG[/8S/^iɒZgZ%%I@Cp Jhbg(%bj/P{sq8SZ|3y&3Sby;} H֋X[ߟ^ƝLi1PY0kr0ϳS-oҒsRjy˩^<5FYW爵ezI.$?/51N:44ҤD%fx 5O6ȽXͶb3Kv9٧q|/s-oz!:p0v?<ȅBeT"Ն$g40#Vij{_-Q& /΃>ⱕRh:m^x  ixIj||Is_rMK $@,o0>x]7&Ogj3ixU]VE: /x@Y8 /9"KH&?%4(% ԓxL5zxX*yCoǣv7pԾ%\‡=uqjijnx \PC$X莪{ ]FˌMTxq͟KhA7T7G% R#$Z;LXV93$M P u Cu^H^geN4$A ?/^G'b-oD~ߞXs4.trz .\7.4>3C4Dk/f3ix ?!s` Azֿ,o.&KLKIKP?^$]5}Z>v%Rx^Y~.l{0+/)^AElL:wZdۣNwɖ%yt n%% lՋz>8<-p}k^Ǜdghl +{XIbW`>%d1蒃 /XSy[d4UioJW|ϝBB Zdӣ뇲 /ǻGS+e^Bf*?R PRnbBe*Rbez2' /)G' /)|M7[DG Z 6<] %%lR-y2p_5uu /a=2pGfxI![ؕ+% ;@?^R("u߀fg-K 8S;  /)䁞mzfxI9&%VϵBSwaNgRJEb^fwFXs鈵KwvϽۖ&Et^RȆyv^Z^~¢4I&2@;of*Z0\1|4F$e~^R(|?^NP"kykw?(,oE9m}-o4m]7'$Aσ%Et-6D=BLkN }h{m+@xl$w`=j&KpuVQ[8gW9h&5-쟪/1 w`K 0w{X$nOgwH+ "=Tb*y0-YJ  g$o*n06`,U"29p/-eVXl:/7 _aCNS .p)H#s 85X(5,hpj7I/pGXS.D4}0 %?.lgQړzJ[ .l~I1Z0|r`J<'(dp`>6)[ozYw +Ԑny0 d/^5ZsT(lpeg[B;O g:ıIU,w_8 Wgf U2,ȧH U=<6}'H`Pu+jTy&9]?R B.\H kJ=ce:Lx)`5``ᯕ%ʰ 5pv J9 ]\ӑ7i߹{0 \(TM\.5-4L_ܕ}0#2HgcUbVe=hbI``P}nL!Fw+`ܐzP PoX>2_ ~d LKtZtT.w_CZ*È"2H &({0eg1PQ/[)I"A#-A :(>-a8 Al4__uCnXC\*XRXD rqP3kXUQ9dolRo%Iep>)Ө5 v𾒸4-9 w.Ažـ;(&d=-l%uWmeK^Xt7؆?Y0я?r#fVBI"aO"+MQKL ܉e췿c؋}L ]f+c/{:}TqEp`ȑ ,\,3}pNB%0 + 3 Bүl}q Fz E5$"%9XY~8b5*Fe0cu0M/52$elDj[|gbt;ԕ#)ŀiz:Z:$J9Uu.Feв~lҊYZcvk_?F~ dv0  9C``=d8>6#xzp}GO0Fo!OT6q'd` QQL7"2lG B4 < %&_bpL4%.iғa2HĔ® 8m Mp65'[;MŇanU~5mpQw >VAwߡb RꝒ-`;uLI0L qs>'d(\D[M4x9O|w.#2ȩ7tɯ1<oFn`l oz!28)aφa2;x'0 NB₣8f#28'ן339a2~Ow/Q&dL2莓a2mQ[1Fΐb҂` \gr#"ep⤖.& HUxF Djt5&ӱ !OS 8-~RP&A.ܔ~L 0 Xf#%d`^cآLEw4bh[5LΧ<Ǘr0 W|` gQ^o1Bߩo:[SGMd͌G0qv4ݻ~li} rS>R*кTޛ&5XN>HSpT|x À6SgQT2Lf Yl 6fɐ6Tlĝ0*Ɍ%@U8#Tܼi@W8 ٪10J` }-'fe씥.4\Y d(\z.`அIA2Ls*ӸW2Lfخ󹒩4Lf-a;*FBy6Lx}ϋU6LfO,[>Na207ǖ*4:L3&3(U I˘a2_ij``c!Eep0O(/~gࠝR ڀLa[ U;O<RfepT!,~͆'cX$dh$A<~hQ1~l&3Z$ $,$&3`UR=?l̀h '[_0N'o\gdh{G` ʅ^5Ṟ9);/ 8 4̰Fa2[@`#73QM˒KpI?łCV0`H8|f<Ż+32H%hL3ڧ$>$(/a24z,  YḡRv`d&𕕮S9*a2=1LN3I/{ʌ_0:8l)N r ?@ʍGv!2Hj=V9d O't T.ʅ51&3?&w%<Jdfd&E޸ΆL\sB :VX0,j\K&Un6Lf90+c6Lfbiv>:lYv $5Lf܀C xx0Gg`n RX~ flppM}?7h hH9&0LԠV+0 .&@,k&>YBep|*pa2oK*sqq3b,T<-J1GCd5TF#8>0I?XT,R6nHߝ *Db4h7(x"N@p`j`#,+IDR/5OV w}YSڭ5R,@}Z>`I&gaĊ1{,2X`r~kkIɃWZ/%YuհvA7,G$l|R.'*MWϼ ֔^A~"2\ňx] & :UM)CeHлG"\%[ᚲ3M*9yTe|[ǝʧ<5,`#'1s9WƳ&P8dQe:3naK9-n^Oqldy4dp)0:.-28=+a,bUri g#>Xanh=J m{ B@lkZ `d^LY.m+),㝾 cr1Så3s@=?&ꫤCv- LNb2]_տ}S@Ǵ T:o\L2?Րm$dv0e糹O] _6^Onҹ&eGRTWl$~gJs~ w7V6xAԒZz+0IEjnTa .fAaJ>2 c /'_̷aur,eX'ngF`l=/` T#['ư .j?q`'[am03]AXa&9jА -eϰ aa1aD7xgJtQ0C*ZmpXCeXqiU.&'8UDdN ЌI%oHd +蔪\,`2@ _3zњ~fҔ o@ޔd~r1̣͕x/&# IJ xb0ײ,oT+ 8/nY qdT, SsJ)J,|ÿ,U1s"]U=gK,Xw}VieY+]y.g-wa2%+;"T&sO%۪[gYXAרdXΥSٮ(>[5Aha''[!km8*d]&k;3:'- nCIN Μ8 2HΗB$Rh :dh22HPLWQ"28oմT\5LT'J> ΆP/4?"28#tJe7Č#)6a2rxI/PFe+֤0pa2ʰ*:h^ 9C8#S"2Y{Yb` 6]u5=Ca29*Ìa2rR5G5A͏R~:7fo"Z0e LĪa2CTnt]# ]=a2%sU55y6L1ǐQ~R:.7:h&tH`?0RPd}5LUYR#l\<ȶt]HlΒ qWZjLE6I1L4Tm2 nd f-铊<R8Cwm&*_z΂lL:|t~滗zV{ 0BiUlCDv7`a{-LqfLZʼ~E4-&TS6dkgB/ݫa2&jng]iN/ |d:l&S3ߵngSgd*f)*'g Ƭ,H+|3X7i.[0&FI$oa28M \֡bkt꥖XT>23rx@&SI%j>]˥ȎUd*7llA9d -zM R?0J48RU F~Im5Ld1a (O7TN!]Aa2;PPQ>R>M~: ҕG &SM|J^0LQ*Ud*7q?iK[La2x-pu!Q\L/Md*PN`-Qd*uO;TdR{5`0LpMX&cC)^_cX0Z!ches?Eƴ`"?ݲ9N84LSU-Y 4aUF&a2-䥂 L#X0HYH2ЯɐivT6L8QX =Oxa2:jƪYE4a` &CYQPlj`pzWbR >R3L{`2H۪&Ӹ`>Dp`tBG%wd wCc >lv#f#- +y>E 'Q7d>S'5bJe'x. x?fL#P B&:/\AeA^]C0]BŨ"L -Tťƣ7d`{O T5V; AN-?'npa2)ha2j m+g$^'[Lj4j 0h 0IͮL(%tfLø [iq4.V 1kXO0gZ3L0gt@0/2ʲV`QʉtTDj&9#-&^T#! zgy6 1N0H0tLKJρzt1E+ł)NPuS4s _N&b e,`ҀC&:d:СbAXĭ,λǛa2lȓH@lh4k3LfwT Tzc3LfX42ڀ&a2glU|ΆɐTDbw=.lPU]|&ӱ4pova2Eb;qe%d:LSQ0a 5ΖyQV!}3L S ¡5O/tfm3LOn<3A!9 D!1o"h7qp@Y3L,$F)a2c*'?#0qMSWawCC~)Cx6 K㧒 $dnYg̀M\Yfi ˽z"qv,fRɌ\+wa2;GL>&C %68|\-j!1({m00]JeA$a2؍S1f voL?EFc%a21j"ʵT-{,,`i`Nx/Z0#"L ʯF_t:k&3h ʳ}f0Qa2ԒS$a2;8L:s12H9KËa:-% +D*dId 뤒vr zBGA0pa2i=4-f `\,'y h? |=IwȂ*f̠U +_2șfvJh3LfR02iy9h$ʥ0AGQp"݆f&y 1C`v1Nkvd0ɝq2'7a2ٿML!Xq9Q5Lff.O|)r}i&3H >2Ah`Vu%lmyij niN\`8XGPZ1aesRJqn̤+X!/Ka2DC^š1r)i20ɠpUa! z0HL#5̓aką`lwdC^;MJKT7LH)0d&3A2 0舁dNUva2IZud&uY,A0R.uF  ݞ ol gwe!U7Lc6 2Hk;RX_2h5 ;Rk=;s>Ӄ>=8a2*:A>f0E[#w}M1nc2Qt,פ䷈&hx#Z0pwJs0ERyUut|r`md6n2xHa2 p}V~&n̢uZ0c+# wdGla23=Xk~(l|rwd]44l1G- YKy v/?<8PU$8&Jȴ3k<<{+qTdNa2@%UAǼ--Ƴ^bqQ;3n XX W4,_`=D="2Mve!ωd Jz40#0$=Kb27M~6bn/&SAt03a0A<#D7&!s-f_n cFhh=Lf`Yʀp4yoqrɀ-1Ur*a2s_BK/-~ؚ2xGhuV†ɜ` J-5=G}7?tAP Mu;'K p%+4 1 җ{YXdpdN sb%ɐ '*A;̑Atke~v 0dc5Q.Ģy d0$82hd; <2AW_+ ޑAU'6\;2{EP,0: uTʒr-[a2U}m:{~ @{u>Ha2L7Ry/i٢:'l~A åE&3e!u+0.Z_]Nb0[5(/U&E\XU(R\=fGa[]j>C#2^G{ v䋕ȠA̗NҤVt!D*hM#2HfR*źANi-Eo[F`p>[m4=Yt~ :WE&sA dN0v9#~ʼn=L /C w#0A$Y`NQb{ `)YP&30w+W͉u{~Vn9G%k WѹiRL6 Gu/VdEo ДBX P=}Ҭ_02 \K<2,s"LX!!^IiA1ά̭E'S? 3&`dX[-B#ӥMi98) O?@ #AjKˏؽ?#+&wF_ B 1a2'x<̣ ~:Uؓ/g^:Nd1e_9ճʵɼq$Ng](0qj)qI7e01hLI.Q5{>!DA="E#6" "}~Lz%H/PAmlٙLJh #FsuZj |0MCEn?-%&s*kZx,4f10A}~T ca@BZ$axk$-0EXR&$ Z`24Y< ѡlH\Mm %E+ŒU`2VVu`1.j9|A{,0"0 ݄Kt:h3&w2`"00Ip*(&34_L|,0I}^쟉a`-YL2;tlY`2GD3!\u h9GoLUǽSXT2,0IЩ?&3!rNy 0opKpYuɜ`9 !G8/.zL_ o9qzFep)BB80o@ YX`2 RvӴd3\!77d0KUYc&'FWiyρɬ2Vfj,0CSK,],0#VpR L')72I[Y,L3[b d,Z PʜB Le]l%928,M}YUdZBp̚h tu9űY0C( |p282H.z_}݁ɜo'S1^FYuɜ9,wX Lf^HήJNdN> W,5[YΑ1g`z y@h:"nR1K ?bqd I:d2h$sr<&c$2 ]uw Ng B1dȧ[J"V _6Tzwm #>\1<4$u9&/P>>dm&C0Q 6To}y`2vzO)g/GFVd nu.9s`2L IHo@vY~92V_83td MH7H<<0/k 来3GqIJ.3G72hG }K3݁` N:?8)$L dz4 }8F<A.0mj:{L]bOcL$Tؘpfx`2T۪ĻT&%0 AlT?{`2)g%n$=y`2i` d380D)s7r3dZ2oz`2>}mjOI|DdN=0zE៴'q&TcayȠvfɣrqJ%c"0%7[rdP@K\N|VɸC" D>py}q` ܎!%-գi[{D/iQ S(Dldud ;R`2)|ݤeم ɠ{edvAUE~gKڕvVx}&;0mGDhȂ8:YEd\bPD L&{`2<=g۔Lj ;6 CAx&X cG6dâ?kl{`20A/k3 V#Hs+AL`| 4[Gq쵏" d L "UnXHx`2hQ“eZl?J&Co?LfpYf dpRim6x'6.d [2_:'&d{] 8J;>C5QQ%c!3G9z EYHl?RɣSlw[d}Eu}) A=7;Ș{d*U9TX$U=2H 1"ήu}|DXr\a2B۟aC a2T4ArOyHQu \u} ^U w% B@\Mm#X_0(582نZd]FNT3 gZ ;'%c e`K=Ao 昸HNf0u[v:::G|0v.?Xω0U᧺N}*cd3)dV!蝖.T >LfMN;Ʊ)smpf`4SmU:282ȡV26&enB4x,,7Mhc;,/ pZWqG0f۰/TsJ6 f)^j(3/V U6?o#`=SN|a2 xh{|̂OId Tڔ=ep{~ n^c+ G)Cx90E6qi*"%QҮ Rul<MI@{7YuC;~̂>JT=]mLf*T_7?1)a2F7 >L +IH*dN0TA]+g9UnF~[:@![Y)OMLj iAcrdYSXPuپ<2LTmS6&\ut2$2-R{dҦc 1T Dج; N::Bz̚d8J,_d֬~zt9$xE06zXM05IP1b_}`4_VHxܥT{̚{y7~~̚GH{~̚TTDh|6mѧ`š '*6)&sֵË;P[)MyG7(F:3-!& ͛U?g ֢"a2'd43[{ /ڳ*%>LJ(0; w/]ݷAZQ(_0}\Q5T, mߋ`J gi8UT2823V쟰E0jUQm/PHj+ gAZYa<+YFkw2e:tTeplNgâ+߸AbKS:t(LAMm]C{ ~Eu !a2pH g OY ^Pܫ#$*dAgaKceR14dSdpp6 MЖ&OU.;Dd :}2 aY%xF0$`& 4%Z,K2"A};#_A4D'\6s l I%d,x@50 yn8ġd&ɺRj`2N3`N=AWӡ}'82xe2\aa&8 (14$WA8ĸC(n50^Zm6Re!&$ZK @O1^7QL7o#0ԁl}/&qhTj"-'uW\DbA~B BYx;0 8 `Kz LVfz̝MK ..P`2>3uk*2H16J,K L` Q{^ep`2`X )gw`2D1rU?7$kU, 'a5_dh^!^\rߓhCg]Hz`i|VGYS@{d_k/̓Q96i;tK0.Sa2_ހÖE7P5d QDƸhLUK~(+wLA!UL HtZ0BYM6:(q}ѫ5Jڑ `\jL h: p!9ʜ\K +_dJ uBd&cjS>& 7JG n0Cu#^z?4XH .o@N=.5Ra4A 8P}q[ sZ~Yv9fO AI#na:"a2'S(-%dN0 .c郘B} xHDtW<#i+^Wz]e:AEdpR>eSta2'+KvQ 1Jw 6p} LXq T[tƠ2~wxcPA\U&!+֣^Ğtxd|C;.5y9Fe#EYrz̩&OYQ 8[;(q/8K~_E@:9G/<>=1Z Brd`9W382;@t<3O`{:끎q_ &E2i* )N242ݸ+Ř  jbAz}U\~#C: i<* $m9!1d!3bHĥ&/a2vŞfb"DȰucN‰)0j. PTî6.2R<'et+) ,yCYi?epRteS&lZ#H-E[dp´W-z4E*NLJ rmb GPhBIiA'YZf뵬z7"lC}uO)X DN?ep)dk=L%=/a2;)T$u=LʓḻVd@EN{,.<"x+-lEV~< ~\~.xfs=Lo i*s'~(i["T}Ӧ<oR2)R/.28T FPR78"e}=n:A[Ѿ)]> hPW8n=5[ԦGQƏ'k6"p HXJk#2h`+IA*u݂v6^d`lz;&a2 ݴdiz"/S: 1`YGO,{AؑAX| K$e[ƹ F鄬̐qLؑ 6:q&);2tȵ2*ʍ[jJqG1z ^.h<"92" WeL n&z:;0/Ļ*lUcSgMx`ɜtЮw!Mb`AIܳo&4踖b&-OpdwB|0Q{ ҥ&_wAলtNFi7R^Rd~Ty :͔ن^gI3Kx?Lơ؋ PUc#ɪ{z/NΥ}FJd?Luw9@ &sV:>%TI)j3xF7^ꔋa2Wm~VP`a2(a,,8  f2iF #||=pHĵ?L^TXW0]tZW8XAw/y9|5*N@*ɜ`,p\Evɀ4Կ\6o_~yE0m%0CdxT_0QBXN_&N3?*2SK&}DqWF3)#2?#'a2Pq!Mq~8)@Lj#N=Ƽϸ42ևH&_P@F)@6ŷ`hH %ĵkɜ`0x78Tx}a2NET+\&s5A&sKuZ^ `HVa (ueOؖ)>#T H\ѩrkį 9gq&ED]Pr]+2Ϲ;K[(/3 `;d^*walj&a2q8>9`9+5x(EqC~"VF:O9&&R 7PWepT}0 (zq5U%[K5CNp.N7y &yQ:s@6,28,4"'#7s ҭ[m[N`yfi]vQ !R/w<إ$vU@c96:LϏ@W~10shPJH?L6MOzwdè?L'J1<3epxNegA1 Z>UY UT1ĩs=&᥺=-4w &=uZp!.[LP J:__Z1WW]_`&Τd-oe)CpM.@(ꋙC,L4OM`yq8ġ_p`2(ReE`klSf1q L|&j4=N, W|&׏LɜsJ%gGtg2q~L!M < UP.΁nfpd"N)I.Ƞi.X́L݃P# > ~@Lơ໫#=6 n0cdiFIt0a62F`27i5p_>Wc7*pg GU?bwt.d6fB+wK{mg?FYr`20.0xn_\#rmU_~ɯ S)A TJ3=ĭ7RSmЎAYa2Z,wuvhUdp38u~& c?0Fe*ʖU>Lfb[Xp[*x& wI!u$0DA9zy4?c7 NεUJC`5p(9+Gd6U[,'Jb~Vy͇l oKḳ1ުt>LfS< ~_;Ի8=-@DifdO50fZܱ(CJtI,Ax1VV>>"lDF"pB N' ԧdikw7@? ^.1&s o}uHf @͇`8H}Pޢ 0S4K=dk>Lf {aNB3epJl&FPEh0h28'9FRRȯ`tߙA?rI0(RF\{c!ZiYP^Wr -"lAL*lF282hWmIB'Z4v2-Ad}zm %A -չW:_9ПLd_9_ ̇PQl,$&E:N%Za2'ȯ(b (o֧71r/w7ӽ$;EQd@RM3]1,.D9̠uP3aTM#0 ;iQ,?epϴ~ I"PAٝ L-R7+0~y;P L/-ɣP`(:W^7:v<"25! RN3eU>mX ZUp\d1" 謔+3 L9;d 7Y][e *z9hm :1 VdO:mԬ; L*m9gѬlG ݯ?l 01s1-LS?VB d&shd6M\:A x,J"=S YoFq6o>l&S3`}#0j"氐90?IaTVmA0RM +}/vRm0nLd+R >ɡ+!-e" ᯾$&I\QB87AMLNKA)31/ZR i = ap+ad@@'U1բ1?D݃R^YNu;2萤+S71]D{vȠs|c˼Zg#4]u;2qt VRekW5#uFnej8I繐 W(:Dgǻ LX`RZew{IsqIJ*,+X/^tqn ^u-ZP9< F]'y<\^]dR[j-y/j$82 d̪AR͋%`Bž@l"]_6B{QzIDV}q-n_#g7瀃j՗338< ~lt`&[ V`V2xG0y|^u7͢z4#G:4FˑE/8uZiY^ހ}x΁Igpdpŧx=#/4lq[w"ccD7;2B3IiA#a7Z*2HM'eڎ`(&71KS\ 'W }u^eœ)a{A1^O{YF9uf3)Mx)/ZL/u08V5GSSp%82ȹa= =_ np x1S,7E$ X:լX8Gk&sJGH$\GV`2. W#Wak,̂uc+ s4^.5PƓA` TG'H誡i)ɬ+/9Fb9?ZLc1%]aGb&[A٥̂h2KH&`i #!282 L;QJjSicd)s;^Z`26ȍQb L@9; 4{_LC[AA{n$i%1dd8אsoX;.hmd"jJ}1F LƜkf < L8THo8`}\~,誉H5YZ`2P`b3Ϸ 8!%)"՗ tT__.,*"l J,cal8܋rsd^⋷N JGns\)}_,0Lf182#W&,cD,Ung{D@O*l}-0 x㏑']&,0* mpjپ˛"fCD!,0oo&%&Fu&4~l{'U F`2)ۦPF꬛2820t27q(H8nm6Ąr]b{W,-0P}WychxnBQt T[d ܳŇ"-2/^l Ld"e<[d/(&L'TXˑAKW F9U:Nw-2rҳiKTy Ǫ(9E+/Qzc\μz b'=EgV#>MkA97֖R 9c*B2ߔA CWM O?e%397M DUuEnB&vQ9d P$e|> Ze&+MU@cC0'X ^OZÂmY9S_L,Xr{`2WǭK؆P-:_x!lhuo6RL Lf3rrLLnUyE0L[WgUd2?IߙP)_9Sw0|A <0j5[ꟲT,L`2JR W4ȩVD?{`2k;ZQs' . hH.60"nHcJ&30rJ#,)6A4ԣm=T ~t61"xwJ︓. ?ַA# wdH)cD=0T.: U[)ɌI `?[ Kɜs Dh;? "%D`2FHT L3G9>.O [k2J܀*90ERe4-t#oiEuPrfpdK ހ>=p=[IXcds:hASP%rcxE˰GMTL朂Cphr" ޿`|):#65&7@,tX)2VL*=AJov}l f1cR&3Oӱ:׺6rF7ay`2 gKsm&3!ZՅ]]$)qQ^5,դ`H<#c 8x%SLj Ϋ#DU BX@?#Pj4W`|d?02 ;>E2:#;0cI6kg(=;0ȴGRPoW(;0HbQIJ~]6w`2:N)q' a&3łm+͒eLRuSٛ؁آ\=pl);0cOs#̑AW2Pv.0股!e(;0rܽokLӐ oeիHɘsA: DF`6*cr`2Гў#zL !}`2 5ܟVL sWE ȡpfdqޗ1u\92| L٣߁`aXVw`2%bh~ρxrO :ec1M= O@C=_Tۦ6Ky7_p+"Jم=j2A`l2CAι 5f#NémDQ"*D':u/blj;W:fpdu(୳/Ӗ] ,YQŽ-ˑAl6̈ݮtw :+wQJJ>Fo—g+7Ɲ.0P Rbk\FyG)>̐vŔr!&s%\XꋼȇAN T*`h6`* uï,hEyIY6yρ8=i'9-׍;wKaGW*m0z /nN.`d.#g߾U;0s5ů:V&%0? _0c1Ia%1ܽE ae*s`2z]g49)֗$*n#&HE/5ddіm`7`̧lN,ؑ$82$ϵ7q^:WZBt0"2828p.춲v WPBos{9;.5|,P rLfCLt:̑Ab7xx QFdpBGY(eI ρP}$5|d~\;0>'B>F`2sMZ!P`2{ae˙rn$uG;K[N]m59Y>Ǝ vzKAujSLqϕ#WGz 2hpdpn{6RvdcUvYc?A0I- WMf_0 Avd lZBleC ^1"蕝/mJ+(w=srSM'4?8Un-AEb?282ȁ!ԿuFѯnJlN?* #֑MD2óJpdpqZJ5 E fpRV[fV@u \ _ծG[HFq"uK4Ux]kdM: `hS ?8"is/ ‡AV Wr H12ƈ_H/f")9`QћKab :ftlୃ{Xlۄƅmt"TxM\L`t@;CdݩQ#tZ1̑%LMZ/tdieAox ,8?5٭d҃ ~5r&OՀ  a2 מH>b3e&iޔrˏP^uTɀ* Bg-l9OC%(@50F)x=3ωd0bHRiR^byi-|M/p\p)g6}GNI ّi@PwY\{7Wg`D˩ Wi}I|)4BK4eO@&vrOr'\Hɜ_BʍnE t! Yur L?=U_(O`z4$0USNmTF:c4q=O[T/z:O#\%382Hu[M0 )0OK``j H fԅȑmƼs١}üU rVثt6q)n_0eNEeniYm9}湧i4ah9MН&.}QDJ$#C,8ΟL L}N-+ liصmx382yȢ%P <N${LN D x/>R! jy³-0wL(WtZ`2 /zPH&Ioi 9s?7eAF-0J!lk_e#t獾&Ib3Ekrap+*}H]̋X L7@6\,2 _ b%N ܃t!&;Y>Jb̧ cD#&B1  0}Q0~j!.A L~Gm/_Xb2{[`2sUX,q/-g*JƫdLSY" ]-`?&ٿrLα/yAT2eٱFJ &Cbm\z ^4ۮ-MJ LtGV܃GGedL_| ꢈ)`L`2eʕ?pYH iy_0w/&өe,b-A(Mڔ\=+LǤm394D HpdН"=ڕN ƙ" kHpdwf8 *؊rlok}Xrv&vS*28?k;xa L Nh+ U u{lΏ.K&30 ~Ѓie L b,D`21=$*U`20HĠΖBG ^D|: 8Oe=U!k#0aR96!`u8e=&3h[ѻ&(Ҋ_0e1w>*}=-0e2UHN#HEIɥ/Iw`2cNd LftXP"K%cGym!Θ)&3H=\ Ja2&/-0̳"&  ,Vd3LϯoX`d꿟^=G'卫 ^좁 BhMA0Y]2U45kNf\%h`2 &\ zH YrLf8R+PV<&3]WZj=R&}+*ࢲ#&3f&ޔ-kg@}TnpDqS- I[]L_ܧJ"̇jK7Ҫzo./MsklT/~$;H&3 ǥa&Ĺod&g4qG|ρPljKELfbLwof8Ydp)j#?.Iٿm!~Kd&pp (#'=0$ /%k$WsEl92pj f LY0(HK&/<\Յ-mMuIH5=0 ב5y! 6|cqKw%G1k,GK9=x1821 t䦹عDLf +'Ԁ́ɜ`鎜`l_L xUޖS`;D :(dHX8WA-ld(Q ;&#Qn(D.0@ U&&3!K @㾢!/Ga^hM 7<sc90t}/G)>uDSqq[A0va$(Bsq3GMY妉KNdu~;:j3H5#0UPr9oLyɬ7FwL%t& =@E -=dm&`BuJ`H?Yh l`2 ZnɫԭT' >q@ KHIM`%H0$>}^Ro&< J*L–10nge y q.y ,omP[Kף&@q`-P`CF3xMd U1:Lc-N;J.0|'_* KdH&-cNYW#U!D`2j]TƑ6Sd:6l&x|Crʕ(0sLe4ELd0ZlfS&s׮k65#lDP5%u&`olE9aqM!43ZPƫCuBg>s`2 ?]K' ĥ{o@v2@ M.%\m[S4aT$sۈ ұ*IbcuӤp Lf9D&d&svyeh#zj282H6⚯7 *k"1~6F`2ssE!As|3 B @H52}69%R1nbt cUF#,OK#0(oߘi25fE#QjőUx#0!Ք~ 5Np:Grv#T+%Y}/yZd "?>ɜ4M91>>7 ^ t]ߠ%7!@+T~92i e#0&I ^L1RѶO61bC:c&c4]Ǿog~` $@U71vZUoJj~&sPWZAE3 I?m7m\ݔ?0281GrU  9'lV AGوX*b<'L NS@5?90sZzI#0J*}F,#0sL)| i4?(#0z f?̹I|^l=e&qoF7B L\Ai2829KRB-.T*sC9R&%0'DzSdXZ`L@ˍjʟ!KdrW?zk[~92ifT H R+u~J{QWUOXxEΐLf&=5=h}$F`2N ZRF`2a}:5$/w&C?L5\Nd -!s¡+#iO: /# +<)hF{jK["n;R`2iOm tx EdŅL3Vя v;;"d6dο!G!,#06aIӱOGaGֆnAq``2Npqbu&s)U GUG9q4͓h`2Įi0;wLj R9gᖷ`ܻ%:nlugc_0e[gѝT/UwF#0UdUe.^FdLE$W\*#0tLFEr#DTȪkAL`M"ƃ\ɀ%@rtA) и8E9T|VF`2PN6Q}\& ^CfuekPV SLx8KvISnɀʈ yIɜRZC, 3#0sgڳ{rKNdhJ豱jӥD)ss-O%K:5SGoS糋= >yt*#0AFq~ZCmo feg6! {`s ?Ndxg3'v{mvcC(B~N@F0dJbT&O3/30]&gTِ .1p!\d CAol'%1\,l|k?U h} < 80\NUCr"x@8o lOLj Xԅ27b)%5(ӁG!B>ީ?$82DSA)]҉`y[ DH{&sWP˗턳f`2b.JmMol-NԠ#2416i2ԡG''.(mQ4F`2EZ,_#69OA Lfi:ɅPL# $IjQyϑA] (qt&#WӴK0m 80Эz[Jw#DdUx] B1ǥ9>a3gqyQ1/ؾRiPF_F/g`2e2ئ}Tf`2P[!e0d!#K40P|'^d6g*] raO:>u*g&4m61BEGAk[-ie F4qe&,\մ. [#NU:F? @E k0NMd?X|L'teC+0R& vﮔje| PLjiٌRmX@E2gaa% >gdг{/g Zj9B132:8]A,^Q<]jU+o8wtі#sEe\Aاz /mYCGsE54tGղ ^rgZAH͘+ks? G'aU& E0&Hœд ےd)O R$ΤTRO ^.e—]x IˢE`]g-24/zhUǴ࢘|Vpi%'E],.$-1N ”T zpߢFB#_v\=<2Z:1=2\ia# 1eN̑Mꢶ>T0'rw!X3O|zd6u35\#3 ([I۹/[fYk/߲TxݑABre /_k"l ~-<-0^᭚N˩b$d:R/?\'7,2~Ϸ`C#0NY* A&);J<>k /H,d:%O`d YLzL'"p&y-Pdku`%]4\<$82HfK)Q&WU"Qcн(-=D9ѣrdbS~,U#tk*7LJ ֆK&mW u@ޭVO3``G%eq6Bblv׶jdpJ]&3G'IS\ȒIj߱Xgpd' ZP6Zdp3u9 ~sc.b Y(Z5rGZ-2syRm&#" YH:cK92fU*YAMeȠյ_ Uv )A,j~FW }ݛh@[ȠSwGq; eNaK:G\ԗ CtVZ^AșA7omP(jZ&nA&<#*{YDYV H}pBR#ph4_a6xJ3U#bC乨` WgjL e+N&_d3eJ Ŕd:q E hnpc,W/gT0d C_53!;рP a2ejKWrQ@r Lz@\# krbI tZvgp~ LL`)dRX@c]XiyLrUjH LCX=(%F`2j\H Lm>OAԅTM$\an rZ>;- f`@wN:/ݾL]55@W`2! [ɀ(~~T'i&j,<_*O+QL•}p;a և痢]Hu)iiKS/hr]4 !Lk^G>h*.:+0j qMs`2jG LTQ:G舥,i )Φ~gV`2 u;U*SM^ (;A4&L7dΞ61N4MkTɀw*^ L [JbL B|t\JV`2 M2<#+ÓYɠJd3 SXXod.6vi~)Öa)(UxjDhofM&d:vNM^]kSi~lHHg&ë0+DRE9^Y*8rQڴ_ V'7?==#DAJx T"0reqLs"sh(K@P rل@ l[`2i9 ;(epd0Y082ءYFS#,\-0N!7 .v2nC||j,0N!7F MX`2`ENL)Ie~vE,0f08cR}-ϐ&өT0juLb9)/C Uu fv[-04k1G >ZmD!*C&,3rdD#J ù@ L,0_h"h.#[K [=: LK WP$/c_Px#bt}-g0_̑AS1(p-0/AG-ҬLw(Nq g.d:#R,d/nJl)W-0XJ`])*LAQބ&I#! L7j+*_$TM]Ĭd0 4Q LD3l=L"wWƈ&S`W7dE0X2AcB-0Qε@8(:KU_l[`2M*d I'%60uZCdXU=@ϻĔc"0AD3#lWg~S/%82ṡ4&[E-0Q}Jr-0Lc&s9)N0^A>s`2&]6sPyW_ '4``,@g.*AR2>4?$d0|{ՖD L&0 EA7 qM@f00xNd2)`q  kI`2 E{oF /Ȁaɐ]>gJ#X`20t} ӏ^ن8 TDCp.M[JT {\=e>3Wr`k@G,,0S?Emx˶&3XMvQ ztK̄q3}e6"ӗuR&3Eٳ̩( LfRŦdң{ Rl&,*ơnX`ƇH앂ي:K-_&3;xɥd&ȥťc}d<0Sj\BG&s^TGkrdʬ&N9-/xz`2N4w<2p<09OLİP=0H.E?#0o=/ :D|'L #YV`\=#6HF{dLi+S>(W]`2}]h~V]# _Ƀ ޿`I:Lfi@p_SLfOQB@p wcjM<0hSJ |ρ@Y;Pu IpdЀrͥ2Mpv1Xd&ri``2؆x~"rG Lf:7Tyud&MN,a@ j7&Uw6=0fOuiFsd&qP z`2+Z%82\Ƨpb[ {`2s/!tİe{B̴B٤&3!QUxgPITsg,!V7BȼA&0rʅriQu=XV V h+4D'3ArшPO/xC_`I["{`2 =:^:k#0s_A,;$t67`HYZ"˨k#0S D2& rɠǡ{󈝠cD/I*۰W<Lfם5KQ=0s+Zɿx:T(զGqv{O+]ȠSqSE``2r[!eLfA*bNYs?|c|3LfmnlwYu,,_Wx)p]1".jCe!a!QI@-e{LةF[D=0JVa;' L gu@.*}ԤiJd [YaB<NhLTWsiʶ1 ~DU#TCLo1/+MfIXDžYW?{L0VfSsgLWTjC-d Pb4᎐FɍCU͍10ikľ<07W#P`\u,!>Qsq&cDǕE ϒh({61jGaU^ 4382+2]58OMJ, {{ˑ ?% QR*Ef⦩AXpT"Ey4+FqͤdƝ~\!-yϑA֖JH$Lpw%! te&! ϴNLd΍oc>L܁ZU^YSv`2hzO߱#IVeVkim6"ݕ۳/HLA{G'mD1\>6>C;0CSUe؁mr `L Lz}6|d {7Aռn&܄L 7d݁OyYr@> 0Z݁xBEjM&0Ч [dv`2Ѥeܿ`S%v=PD !v&t/D?;b&ل*U[@g ^dm%c7r.TF)ii g1nj``*`rFL7ظzaK=`]ÚP?pF0ޔuQ$ |yr_l7 테McibCӧ|T;3G6uܳI4K0~о,G\x{nI01>-SxQz\-2Hڼ 뾑o{tF0j&JƃC0 y`)=',wD+ `ng #_0T5/˪A}*5ڵ{fG n$CCD j]q:q/x KEsȠSvl)vp`jTr1"Aݙr/ ( r]H(d$4KN`fl_32Q-dl;J̌ vH$lc ƌ Sd`l32vs'xY@WY Rw*5Z ( A vewHtP0aWT@H8+2fn(MiTl_(z'CA9,;dj xI4(ZoXSE!5}}<ǻ͗a2p_hdPlKp`IyKa2l$A!,K7N |`.n_及>- f^>n^FWIa&k#X՗8eޑEݞ% L r2),s2%;2hTTV;2}k?nb;Ҏ V(4trcܑAԳґ@xw2]MRG R#xt*gS?02kM,&ܻwd)uV?bw^~?ʌ. HB:LG@""sڴ$ V8(ʦdƵlv9d>]Z,^%eXj%}]r]Þ`B2~ wŽ{I  KV2Wdхk/z_k#0N!WSo F\r/OpdswgA:Y( FAP=HeS~92.ީdѵ-.2H&TѨPcjY>T$!2xrJWkx Ek]ی`awE6)_RS9eݾDd b?,ߚo#0=r.z 2 wzݞ:G‰T:K!``2h"KT250Α)Q;@cfUuP=&s>(m[.sVdpD_Ip^ge^VY;,93xJz8ǀ"daPO_5& ~[FXIbY$);F[' 0eLշ|)ɌI %!LP[.50nrVuD̩U`%̩G}؞[n`2;}ϞLfk450A xBV 382ֺ, 5C6d&Xs^MQ̼ĉLw`2,h\l7ȣe޴ȔǝR>r&32o?p)ճɜ~'чU:Q̤jhDqA4AjHGޕ!"/qg{{LPp܆9@zLGkh.d&59T <ӅJQV50)byk=A5Յ LΔdpb?A g<줛ŎT`{eCytȝG[Je!@,uJ0 d! LfRӪo*dYj`2rӋn6('Ssd2.,EqE,0e]o@\50)6a VoZun_,4 &r&?42U_ kg+VVs00 Y=}\PMe+%k#0+u04%);:3/(\X/ŭ9fS~Ӕ|JFK B RNh -0 z-ƹd/Ɣ^+*ZUJdlXK!L~eP>)ˠ+%k̹zˋ B:DDZ`2FroL,6ˁ*s۲?hr[`2x_ *90`{IQE/GZ6:/GlwShE_\yC<##w(N D`D{r+hɠ\tK<ж`kpQ=&㤢U+FU[[ L {;RM^]`2Na&oLmIh8=m .qބWsirSoh :g~ 6,AM^]dp@@ 8#e.z#ϛox( Rhv HoM! EzZ=($Ri'82Px6y϶\`^92H퐊"puhO6#|̬)-"+P&sQxHn$/?LTz K6r`GX.%U]||Fn 녴J7ؑA6IjA\Vwq}q6icw5 NMCք/œ>o|2.2FS d=LTeRU` .(C%1 oHp`TZAA1-@+,@!#YYo ~$.jʫt ԑ?3Kdp Ue )^" ml/ F*zG.o#2W#-tz ¹( MxdpdGRK4EFm`mN^{ ?[r d诃`4v81$L_M"A2J~L^Y,109Ik`*CrQ"}j`9 Y%^gK/+@Nnk|ݻBjD&s17TC3{~ 65 aߩk"ϼ"8tdi6zg 309i: +R9&=1 E`.r?A>nH_MdRDdmNy Ȣʎ0I K *z&/kTuYFa2h*xMA``vMgpB̤KR.7T}0oGFa.&@0t*G! +W-vY},םY>Fd Vf<ƈ }-7 {#.}XԢ0IWUb2E#20_] bةIo\ ލ +#2l2ԉ}D7VupE#0h3T8E 2X5.v =ma2Z$a_Rr9tlI!N@]=$T)]7%epB:/.Bl$lq9 &s1(: v)E?CL4#)V<Hd_9,zj9⒏1kcDץ1eJ!?d&td = @$7)E\sЩ&Cl)y FA?epALxkky%L`2RH}1x]LfggUd @Xn2ђj,TUKeep`)"& <]Щ LfQu^ST,\ݥY(J}&PFk~ HRY"њ(\іh y ]p8y Խ@GRCe &h%9L,̚q7p W'`TДLV 7Qt&/Y:aY''haK ը\*;L9QRT__0xN7/N3bIso|ntuLc{ ɀ|V~s1QG`2S9Y|dm&3Zڵw1"$hf=e{0@fLF@G`2v Su#"2N%+\`Hf;/Zl?qLI9<[70umO7d ҁBS,W)N{gLfqċ?I_JD2p;hd0 IЪjb4&s4$Tfh-llDoep6ZHAu ƭ3+Myu94•_ ·ɜ` hOmNɜQǖkʽ2 T N4I|*P]L| FC~&#!TFkd64D gɫ :n,GFRֲ欑A<J %-2Hw#U<k7f n!,emhAHH!;+c\dYni|BU:7t@r>Lf5\21&Euwî%oep-lSML$)/9!`LhP?a2eF|)22&V`汉8Hp>LW]޳G0.5Sj:\9&DOo %P_#yoGÏ Lyvş}]sLw`2Ρ%5Ph+F`2N)w,'l`2L{@B'g`2J 6"5NMC̡@!ؑ %,~ ˟#-NGT| :@esȹ`k&g`֮L1&.JzBzL&da(f>KU0kݯ'묇` &Q>(G 68bI>`C(m v ]dG' , ߥf=L ت7X10S{& La23 U#A- Dd h(7Eds̈́ċ?M04"H4/ʃjγV&^TKY2C8N%:#s/ 4XDE V2t=dm"əez 9Q"~ &q2o 2uo]Y 6wukD3ց5" gAjd!׈ b1WGd?2zïi~V#2oȨ%>}0[ulS,lXz-NdljMJ^buQ_-8~'jVXPK+j=LƀgafHg~ ՗qc p=L%Z~ *x3?Lπ˨+*X&s$ niTɜ`KNe-/[j-E0ͮep &7ZjRrW`2{鱦 xiCPFƟW`2z)٣~r+0 n( `"+0j"ۣ B`2mXԇPtMS*n81ъ6e`{CU_T$dN0ڒUq͕[vjd Ncb_ٱl vd1fĄ 9l-1,,|3%x\IG d3xyt.u0+TgC@Ԇɘ: Χ,{a2-\ĭ_E*{S-3ZᵇeQ+ Adq 4"/kKVdVبqs;b52H&:0zu'Q5!bShLG (V!0J ]t{AK+ <"8{I%=0rdpt耓SQ0SsdR)AoID&JXJ1*a2f\gs.*=LyB;<=p̸\&8-(quu *jd|Qsi>2WM?1^A3ԠHଔ ̙GR\976@hSg`"+; (\j J &+p ~]Ys!y`28 7zB-lL/pCDZa}UKr=0A-S+gp&h* /"[ Ͷ0ucd9I[Q. le nd6 M شP 92ל5 G#N} @I)\d64#DR_qJ|N@T0{6Ki) qEBW?L>}nLf>M'A!dcCpf۾/ W\&O f 0SI:Hį-0,e):dஇ.0Fq"[dg2sh{$ٷ?L$&s*=Kx/)}X3bE20ݛv;uze*&aB~B'g~0 M1ڊ"ۘ(2"CuOXDl./iraT|A23/& a2pW !7 dzICdl)Sg  P3id mas"ļdN06la/XE_Fs7)6[?epIL+뾁*8?LFKsy{^a2ĂBՖu[\>{ 'I]_dNg Ba2f6'ScAfPP}0=ONrϏ%u~YYd,yu+2H"}+t F2Zj8G= ޗN/ *8?ɜ`TJ w}xa2f"ۄd&sA0.5^U&a3vf^d0\sҁ `94npdP@a2u| ߄n#."0}Ԣ21,I\ya2(pʔYlI 0CP,7o0DSJX?L2C-c0j=qP΂b{^0M%Jdx+ba!5dn4e)ݗ, $NWwX&!YKIos/ B%, 4)AΥmžsKq%23"^[Gw }/Gw\v[R}.A\%^Jl%}?L[*\ɹf/ brdDir_2x6FIuw`2<+1h3 ⊒dW:9';0jV z~V;0VЉHj21Gz鷈㪃&󞲉``ݕHyd " ]}Jp}mb2 EcjFLd~ LfGdh x/Iua0D p:jbH J\εܠԓdn0j濷a=:nV(=/i282wC+~Wz ^*{ Kt y:'ro!2'~<"0w y/~o@B~xq%njrdUӐ_v:ɭm &}Eo#W]_0jtv_0um@N&ulIܾ *h2"e-%_݈ 6:PU.:~ Gxf6~_qh}7="r; n1!옿Nϩ|s. Rh#N/Cu2#wrKYurf,8ASN+l8מAv`%EJe{Foy2F"=/;O9 2{_0*_ TY$ +kY uwLXtU7#g7Ճ|))WW1Zi7[WdpP\eyBDҽ/o Fd\ Q΃q@2/{2a!Yi@i׼ _TίTei VP>"{E'x.(.8oG1#NrG<꫋ ^ߤKGx[dD|u i`ȶ @zp^9V-2HTy/OͶBg PEzInU^spnj^69bRiIX382%mp[__]{vzAx)amfqlS~92))iE|#3"Qxq<' `ZJ;1dpdpO2}M4w9UGiR9<4'+n ƫ˛N`.7=ث^ܥ90J T=qt:%xuݭ92xF0'e=; zd 3EО?p\re_o1J. )0J+ʝ:f`,Q'=N^"v~cun'Ac'w+N b2:in r6 ^Ssm&AmR1NhᲓLruq epdmSK.94u?M92XYk,!&!} )0PrJ;y H.b380M/RJTNp녝U@C?i$'82xў9Iޓt&S!1f)N&lYHVI ^W2NpdYJV/KpdHe>HBS92^|v_s \v &"%ɬ6LJbM\)ˤAB)!3zrM_X Bk/N5'lngˑN2\K-Opd޺ZнPo_^̿_W 9+!.[n`2Tv>@ I L"LN.'Ź6!yA'\~x@?>oaoQ9' p僝 r󠇝N/1 ʯ;0gߐҹAoy&S'ZU>+*ipdp\'\ugUD }"Y*gic^]d Sଅa`Av|VXlNA! 95;b9tGmsh!Ag⨗*0JS ' S ~r Ey[A`2dQmd,{dO70wGQp+GX &́``2["#崲_qo00qV]<49 R^b)Xg&u&S/Rq0g[0xǥq 8q 9|,ל-2~Vɀ ap0W>F`2nJ[>F`2*S>*u Lϊ4||feGp?ؙ*0s;j Un`29HmR&SAN;/n. x-F%Jg!ץdNa".s'7&s,!uo#0J|8$)Puį|uoLJ`2'7c/H/(md&8ݿ  TK|VrL&S t 3ȭ 3 RhEMDXs00?_f&SZHC\cg?UO_+^P#m%a PLcVQ^Z^j`2 #y84t:Ap4G`t&Wvms+Ԑr&C&ZU9f+o@50Fg%UQ@  $`hrG*%ڲ3XˑAj&I %DdGt6N9: `[\KN&Ө[)%4\,^ړU`2>O7(,h`22FJ o;g+Gby,ࢸ8 g Or99}v<4稚LVɜ`*MLT-Nige,dN0 sV^ L掚Y/er,a$TCNpdwb7 `F"s!:.&)WX I5|J]vˁPבPjV[`2Wut͞oa(\Npdz-2i\G:3xF0.bkIy ^ 9*V#7$fEQP6Q_0d[Sd:ADmX”L\E"UnɰN{_OF:enB}ip )!6gn~ ›r/E5 r+¬)Zǹ69 706mDܮҴ=-mnd&InM~Q%-q`2!F :&7 %82T/[zRRadL|PN#Nol_$Y׵~$B X$ ;cid϶d: :BUi/r/xs23X+ S\4A-CWBl EN w8 |0/xM'0>Nod:oSI T;|}^z`2>7G۹Iѭ \=08r@=0K-gȩ("pa ۈ?1QOx #T 4U0/x{H#mEF`2ByrtK2# _Ȣs(]EO/3&d/GIȡ!rp4JG5\)`pjdIw`2947ٗC~92X;2㨒XPRQ'3/=0.W(Cud^9S =2/rh6"IA LfnY&3x]2Xx7"<[ǾXAsm&:LǾ&}j0 λ}ad}Fz`2{'4tz|@_oX#}VqOH=0AjFXƟ v}׳[dF@\>dD{[V̠eW71&382x易' 28288_w'.]wtK?U0z`2'ؾg6 H~U#yN2&3u4d˪;s!&3w;eGTGW\݀-= qw σeo&3thލVC^]dKJSdpd9B!gIw"Uu 4-tH`Lfp#_+wh/ YԐ`} %㎯4w1L#rI`.̀U69nT 0TC[%u֣ӓ&s!m ȤВ}#0:goI ^yJ· ` ^{`29eyt(RN!)Yl282x2=\DdR&TY&3HW0/x\P6y<愑ӓKF`2]NmpKdƥC~&mA)}Kp`g!xWɌMZe |ɜK0 W\ \uɰ*35eLf~{- wf!df!exD9jVa]"_J`2Fh 54>s`2'"c7 W];"&)|R\-S$^6ld ppy_LfVhMH+u|&3)܊*{يɜ`ۜ77)̀mLʜpA҃"=#law[mLfvhRm&sn0M'УgٴFSڪzg3݁Lvu\NvLfiv9I\Gy79e]=.r'Ki"nΌ}`WoTHkRXh`2$v`7U9ұIU0:߷q02+%3 &3pǡ Ц'~)/80'Nv0!A$Suk )9b1G ;[Q=0zC(( T.$j z`2H .՗ RJ7Ο&|L6ǧC'eE;2rR&3D c䅷1 RDv=~ғْ,]D|&`nt JY=0YxvgB7b Lfr+D%&3]),*UZ6z`2#}k _q+L^*"o#0t-/R3|B1ʳ0$A*08h?ouy+eiLSES(eyjwd& ޵JCVLfzz/FG`2h{] d&s~hYךzwkn!f\?мj@ƫEMd&~C6aCdpu sp[#dt]%.0If;V#0]l0᝞+E$.^0}f)$ciS&F`2S>Hd#[%Dd009(-ZrdpoĘ G05d/?$ [}=΍Ȗ0LfU\4L%e{Lfr0Ez%;9`YHe>ZŶ"̐ >_KPLyI \̑AgF?iͳS]o-G\tfGyysq-d&BGhR&̤]yGL\4Xgٳ ój&B5 ș29]|[q[{Upԛ QjwxAE eGl_pd(9_g)A/G`2'\1$?7.``2})g ͇^p{8&j|&\ļW282HBع\KLj n_WU'8\ӴGMe6S_]dp Y" :Zʺ?1gVZt&3eKgTaGqۧ|3HKuX` `aiA& ơW$Mr&cTxmW+,ג)0("zH+1>#0}"Zg>8N+A\Ye|&cG iTXqL or?1%;*.TnLh\!l`2:YSb2/5#0+m)ѐ-zY3R=82H:mU@VLyꋢ\/E ~ߊ#dRMnД~oAb-wCͩF`28 gR1^jLL![yi&seVRᠺ8L ?xm/*cHڌdSu:L5M[C k&s))B[տd)d/j$d<̉فL1&nXاYjE+d}Tb" PIç{#0b*{dF`2FzBg7LJ`2 Gb P!.0l x_w w&sjt+ˑAC *Lf`2F=UCґRa|v'R}&cmG(Qɐ>B /WL7\:&S30<1 mAs׍x/Ǯ8Q 1A:U)\'@H>[[ H\Jwi&cF+ UBhtF8ɘQBxr3Ma3I[ȠYQs %19 mlPV2)4Xr/VY {yBepdp *5NC6ː#:EQg`2?+ LJ`2 V+  L] ΍O30Ü(8&$?30<#Da&sts1$ĞK:& -x G]EۗSf`2~5B `}2^7Y h wq&8{Hs"<M b7KQx7d LfkK|.&C 6Q nLP`2+ 1 ^6me&Ab ^x 6ɜGs0!`GGe͒S@30WMӷ 62>9S6#`eJm 0eVADLW܄~$jY՛Gp`2 ^Vg~:30E,v{rK%6 AU o&8ݫX~? 30:~*Ռ6%30::S3*Eg`2?[Js)OHb305֧8 > ^/N<@wS)0j"<:1h;.o00E*&bZ.0S4M LZ|̚G lEj&Yr;~g`2:']*@,)_w`2 KlXGdm&B6"6~ԃAznɠR1!FݻR&s2M]s`2gmHT1ɐQ'b Eaf`2'X@msY۬ LfQ1Šq"1x4:g`2kaT =ښɬ"N4P yᝁ,6\,̧$,V30jcA:m\P%$7.?>@6\P${lZ>j%xd6\:orO L\ @&ϼ#x/rGyN98r'9= ⒮Wd6)}2& $ͯ];md঍:)'2dc LfsE9T'(-j30];)M&q꜁ɀO9B2J&0\I';'T oI}Nb[V9;h+IWu׵d6GNm4WG@ } ^}CX=kɀꉽNn艺e 6RԽOF{,0S5"]?s2q$aɀ2xo= &M)J`o?lr%)F&*jgl|S{k :I%n2C{GYN, 6v%Im&!^#a/R`2JWL|HSs`25?")pŃ%{d6y2] $v61"ߪ*Oo*0M)8?tj8o#0 &cWRE `N|F?U1"DyʎБ̞܌r` u/W LI%J_ Nw&V/?6fݲps&%0;p&-ӔW_Vp$ Y`2_\[:gfkD>=pP2&gDu/1E_ .QRԯ͕ L6,Z)Q1), LfDdBՎi,0}&b~U_ LjH?ԏfpdU,DU6_ n i^p`22eCip`H lGATšj q$N,>օ&CZ뺊hM@ c$"MdQ3DEN^0'M}j&aGu9IUϯP]LIؑ9 Љ|1BdɐKKq1`tYi( 9 ^'{ /GWې[犝ocD 'ٰu6G6"M441z!W}!I>Ҧq$؅gfdq+ =Edte`vuv4d!%IfdJ!*)ی ҿ{-iC?Co,}cF3@ٌ gYX328o'?}/BMN.mo"[AS"$3 )4 B3qQ ɯ]J"BfZrdm~,~ &JΔ o#2h981"ۆ@ )?[3G/> f+2h1%jv좺DWyS%n+2JFq[M{*"-? L"gkԕ#^$ˑAM{ $ q.lpL6b(锶"T xASFdTa%#$W[B~{Ǡy"8t%.&S6W@ċ.&S aGyev1Rx9R%s fJdT -|1,x@QAy[et#`Lpb2ѩ{u1L෫:If_d]MՁ/Y# ]E& ʔ3G 4!;.; VDs:ln- :M) y R1/cmuMs}Z)U;&NNx>F UzOg R+:Ren]Szmc4`: mrA?]U"M3?V/0!W),W ~|?pȠ_4N[uV #2B1U"79v#NC~/zE k$ݵ`s3jdprx6~ "al"W]m/ kT2̑Az htu+3GVY /T$Xn#qO\}ȠgjOٺrdrEj^[d) Ee=_LT 4p2~5QnL$@6ɜK2Hԅ|~ LSz ʍ\ S?C4 o(D&dy h ?㢤;dSwWC EJz p=L*)ʐܴJh&ST14S51L}(Nhx~V`2: ub8 d"Yɴo3lEx&)ziWU=G_lT/~ps6UW`2 ywqsR-0@ŲO7m3imW0z-R&: 5kZ4 y }*4s=&X$Ι-+06|zL,`\928Ӳׁ5d?+063<\80FQ5trW*908q0~W`2R'@?izLԨ]=^ H|ɸOS /$gp}Cfj`ByV`2"!CcSiXH 9@0TLpLG6 \X03 wa cvo{!|bIjы x;V+_LbjguK9r?쾘LE/ i2b2 KqwsZ\C.ao3b;;K`%5m8-JLdKMt/d.&S)^D;Ŀ˙ɜ`j@ MXx|3jZo7RdNp>Fq1t&mnϏY.wûٝd)8>Mm/dN0G/Bg?"`_L{UR^AH|LC+28*F5n 4h|8ob2Ӥq01Ւ]ncT=3x1c OTpGK/9KVל)7AZSlS45b27b2nkg}x?8TmCP po]ξ tc#TM~fp'vD/&;YBpH q1:YY̳a}%>%BE?:7]+:nQdU1Ճo٦4HIjn0[vJ]7αXe`5: p,=A4p)@}$wTyu#L>5:/ n(da9ogJrE0Y:aT7; sBx4%\ ߷@: ^z3d&2|Vrz (^EL=WkB~974Ij g8ϩ|38(YW^LMQٷXm@W-dNqkR+  rzywY,5 'fp%7+uoQC*q3, Ys+̢ Ks  :e+h?b2XjEp,@_y`iNq b2gqk+yDSI{d:c=O #3x1Js܄16.?؋@  <򄽘 :TC7QOt1x!` '6Edspfy\Ls8 !bM~s{1sbND?ފ|1(BBZ_LS\/e {1̍v)% ry<_7ݮId/&659+}6I:ڲ.&3;|qSNY>X$ozr.QGiT9)/gU.b2@y#co|3'ۻY|3^llbdy*qnu1(@uɠF5d3 #r,^\| P1 ُ+j$6}?7x`*7s6ȊATPf: Gb2 ;E{ ֔1V\>1\01=X\Cyq'3h_wW |3 ݥ⺮fo!Ո~hH:g .4p`)\d뙈rK` %ƅdt*DdN"VPh#^q\.&58423R|m2˅ @9 3K+, <{KHW<`YÂ'5?1 әtHdQ?|QN"w+b2Nnb2 j@k{&fA0U@H&1v>- R40$9_=C0 d|T2dNJUr<]!A13&tB棶?l.W0E]Wbi&{=0-bă޵y1Wg Pe0kΞM!z^oc`::*=MFb_gpBuq\338xO9;-&RtoNnpC8f`c m%53hF!ץ [0 _{1`l:}pvsN3™3G 03*0e ~Ę1J^A%&Y:0V-&gT*1Rj~;\ʫt%&Cv'4_–}r?z d2*~}gChF&`94mLs"l.t&zYCO'(Aƙ/ ] \//𯗺db<R3x.#%zy2QɌ6 {O \ϧ{ @? \,'_+|)+N6V1qx1x2{o.0$_, 0PB"A ޏ{n(NRbT/OfA",=)0pQ L.p}[lZf䣾T`2deB ]UJ 6>Ts{,RW^xx0М$n ɐ{3f/C IyɠIE"_=S >D'0Yf 1MmzP.†d7keF%JwN$yJT[D n : qI9Ӊ#C3d8Cqfcn햿 6T2ǯwհgìEɰY7M^@  Vx .w}> U ֿh AE3'x濼:0B`Y``d.,sIKo\uZeP熟wl{}?8] 7Rg{} Gݶs<uhkɜ!3Y;}=cGL{ 6VUCTK`pu/U;"4mREWWU;.%=_KZetj\&z>|j\+2s\TnjW=+ϩ!_JY\t_Xuk|Qs{yʿr17x1 PlFR;rm\LnToJ#Wd ZP| vLWaȑ-ILC8ݍqB dAΊg\">c2;},$r/MM% HؑF[ TD[3xV x鈙y rd(,A<؟yqKLd[p=sl|tBW&,,(Z~%3c26ƉjrNd`=Î^m`lsCcgK}ipT QH+;c GΡ;a܉v K>]pwu \*1 W4}1{K:&S)oDؾ2)d 06k8] 8!W`힟A57V/Ǒ+=WWo*y_1U-WW4qxنW'26ah^gդʽ<x{~1/_ӹ29,yTd6e4+N{chEU6F290V`!7eqfm9 10 "]ޛqzW؞WDl3{o@o{ NPy`[˿M`;)o)14pNE3ʞB7hwI''tOyo bO [0 Ģ6 Z5U嗽7hH7/y]ޛ8 Se3OzԄ,spV,yfh qOAL=@_?o 76ۃڒy{)H+?yA)8/x&xGN(ߙS~sU'^w9 ZЀ`?ſF*9H-e&aK4p:16[ ,vҷ<Ƹ6@ϕ.]cg7v%ٙ9)?.ᫀh}< YZLV2@[GFFL3,$K5 >ّ9 n7OT w 7iIq*qjDӊ M:.zg޾i,eZ_)!z|$}ZS#类H9 uR^1 93d06dǵ4dƾ7>H5^o+. BٽD|{?lJU04<`+TyU"|Fls_|3>[C") ns3fSX˪>^d`HqeOo7|o5ݾ>↹D1Lp lB67xR| 4UgM$rѥ U"P}yd 7:l/v31 s_d X&U u7mX, 2FٮkHַ3d=AB8ᔛy\& ?#`Mv7g\P,W7%o'l} q1n'n|&*I,%u]3#x|{AR5W(\䫳JC/o˫;_;-? nl84WC;G:rT7p㪺*|nɌ E.L3r6"Jo=AH񘖗:I&c)#.^3fU V|55>9 hJUp1B43`KM7ͩE>G2~ S `:mt!o;r]fSy}=q_MMCa^D~yGP=+E ϞSmXNkKUqm|3Y9[Pn7 t:u^ɩܭOwٟmF.)믎di7f&VR N7K6 :{Þs:w)jnMR`i/ ك\o0w-9aUg..sd:}џ|)`V&E L_A/ ="ئ ^0 }ljA $}u F| V8 B9m̅ ޶ 8oֿI!c KnyAҝy2MƾzɴQC 4`ȷ1! MǸ\K_Nfp `#B}3 +Ro֋q1<(&Wz@Ƀ 6fw׌49=_)zPoNP cZIfhgq¾ygK%q1,xb2>{_gI_Zlq]6<f3oqhhR3r xi=s=UL6Fl>lt*oԿd"23A'*Ӆ\^gam_t-kQGO˵r4Zp/3{ 3 SP97MIAM/{Z4J=s!΢%$Nz&plrlJ5Qu`z2\̼`lhd{g<Ys^E'ϣz."-:B`3?SQ}Hyp-e1^0P|٩d6PI +ul_D ïDeGlV79Yl="̘![[>s 0 ?ͤ4`-`=ڐtÓ`=yk yeD^V$? [{+e=l7ڔI{+TfXmxo0V\98Y퓳 Fs _1AKb ̎7Z.9sLwy7pA^䗝'Cu8xq=*/pf;Nr(Lʝ]~eݧ=ڪ竕>pWE~ރ|N E{ gK_grz @eog>N^`X7P8Ɲ]BFT(0 HK_XhC\ nrwvs9Ҁ9\䶜)wv}9Q=s Li6 !!؜K8ɺ˅AȋH2VHWk{ZWzu)Gʶ6U8[fK!tR/ʗ60-b\_(?#'R#]_ЎjLݵz?th&r5~R՗WM[rZ]".hT|3m|8D Ja{z^̫ du ;/gGM5J9,oY]S`K̢Wqφ_ɏknl.Acsy>l.oEs6R1asi-_7[5{k{Њgߋ{b?6t1e{Ws6b1asm-_7[5[[܊m6n0gfb+oEsa~{\>\[_n[\K}5۬1d\>l~@̸?b1a>m~/c.>>Rl~/c.>l~/c.E>|y9O1a>m~tǜss1b>m~cw>&ǜ3}iJǜ5}̩nǜ8}) 9}̌M513w4[k1?wd_>g1?|Oy,l~o.y}Oylsz#A?~X>=ao- ɶi!k۰#y}m{mBzdo ѿ3lRLے._ )BJB-2<氐tL>-$&c6 I7!$*c I7B2XHYvXRV}ǘR֭1Syn!Ӕ}YHYv!eyb!e;>-yd!c<RїTTѧk<&->-wLћTdyRQ}nRѿSBF%C7R ЭTB~BhBw|-[HM }KHc,$BR?4$_mtY.|}י/(?nS׍mqpN7k -۶4JMX{,,qN,.,nIk4Gϓ&YC{jM ӳs?!glmI+63z"GJKnFD!-qoَj@>4lbMs?)ͤ Hl]%sn9kW-k٪[;˖@ax JRsc\sR'zc:ߚ\_流ːƯV`N6k<@?yY[ Ϫi ~{j5'xCRuK/k_:i]^𞄦 Oc6 0fZ(GVgy UrsX|u'>⮔~j?{ZϚJj_΋foqI*4 WY \#k%~|?t6/2w>&׎и_[\/̡Zd{\Lג_B*=Òc!/%~aYe>uoR#3/ۡ.@Ф s>Rw123(l[ ar׿13CF-cW]:U60k0-M tL>7du YTiB~OC =1,>{ĹY~CH 3w =A =Ɂr:PX9VyL(s:PM!1uLB(#dF(X:PpGy,(#<yX~c@Y+%`+u[~C3!OP<A:ҁ@Bi0<1 y9AOs¦3/C$fI/qVOdylYm?.Phtj2~r;4x'Mt,AK"t`w*_h45,{Y&_~D.:~mF c7? =C_eG-=c{yON|>jQcO81A֬h~Oi߯ق p'Ţ)̳LRkQ2vz[_v_<p[nrPl$1Y|i!gVhj`҈ioXc>1{^AKΏj4gMtE -&i}d+[䤇8a?8)? :b[E뙚 d_}4f[ n3pw ӯMn2CX_ ~o>U~=3KT '~O?jsN|ƑT͜@Dա<>oGUNFf; ~FߦDˆn,/Q߁V?7z3{FuTatY9ɼ--UlLj6kyǚg}T?@~l+|OLӲdf-)٬e}ЁVjx?C idD(ucZ~O&qZ﹈PTZd[ՀBCHr#A'yOu2bU`91[Zn8Cw{;u>t:M5njmו=|zH[Fi虢y᧦4[y豤ng۰m૽S"W_^YT CG8lx$g7G%~WdMLب,7Q=]lRTc{=&]CjJN8d=}XiY^[J }O*d}PmP#V)]C?~cVUtob*dp"e1{2MŬjh ר ..4umʴ}<fe1b*8P{ "oYO;ʕf!$9cծX{C4AB1>-O}OtnLw~+'yxQ-mգ`}XEc+~ޢSoQ?],t `SQhma~ӊ0/MB> [RgF~He=#.O|,뤣u&D\FL0 f+D$4=ct ',W {t(+) K,I_q̖T ?l+|]}6d!R t<]ӇxG=E҇ }I`_x4eMJ{Z)Dm@]̱ ^žm:Mva,wˁCCؑpz-':H29'q4%A걹m-S΍]|WUlmt%]eZӁO流h/}d!tFo<{Mʌ-d+h߹BL!#oZ&!pA:dS#Yuc<-guYu:d-guF翥<1[VLC?<P #,硸/ B~C^*ރpLet^ q%Z~M#@@9yLr!7e9 = p<Cƨm"9NѲBXu{ SPy,h@Dϕ`=DYX84j߈Zd¿ 0SYQY#2h¨FB=ᗪZ|Vk0zyf]%(|iߵz!3e>t$eVO3lr/[ {b̆c[Kl^l[z/ӉNᥞw$s /ӹkY`1?v5ܛ\B"#Wy50vvy5PTHwI|w l*k&C6 ^xB3O_⻕?{{(dM oՕ~ uߘs&gg09|=i?ܭMAc;_Ҵ#i4_!FS1El֐A<.<9=P-qYtàN+ɼ_V^Cƣz$4i2SkEA}*ru.YfTSKsj5sW7"͟Zq`HV<¬& fF NL1'Fn ^ua!.f,°g M왫xwCw=Lǖ~bB-tiJvM*`S>/dQtUL-kz8DQEKP=У!_ "ʥg" zNA$/e5|kpu.h 2r_ҶOhF!/"60HeESRb7vH!ͼ5NM(wyF&ǘV0z\)M2[_{͌23{J赸*(׋dS%HĬ/XC2=!R|:w*q@xH,U4 sL}B!n?3}pmi TShKv{zhY{gI ʿCR~S ϣ3|XP#1&%PS= ̖ĕBm;HwWs1scL@M O#S"13 : $¿ Ĉvajb4tHƂ4`N%$}0 (Oq=`BchշZ-d#)Mc>Io:LӫN (5'Iи95UWi?1I?QBj@AW?9Xx}>2J)=ŻBg UE;L~V&KQZ\z-+`غnU]}>뾠ZO o&'??^V`4|ȓ7^e7~z|hI1À hLâYO>lG﷯AD I@tFF9v3ѷMz:?3Y336z_iʳ.3`qX>GF(p1*X1] EH}ՠ7tuHdoN#]5rc 0(m Y(0LgQˠPQLsDg]b+9 0?QW $Df &CYAc6qRtLr`ۦ<GLsgy߀G f 21 ܲK@&F229_ l(|4Bpakhlwk#LzIwac\JL;:h= w6e#B`'|-J tb$}W |ƯЌMÈ d`{3trabdVQPQ-p( lb$~ 2Yŏ{>HN} #c=̢CcSdшⓞ`.rHq w"4pIr&ѸsN9` [<$z;秉NДWha?Ec B" ^"*`Tic1T3{Ѩ*?dU=]w@Z (J }tODkJq|&.?L<\=_{qXχYל<4Xaap6昞.Z:_cvЩ%j< ·:jBí/' 9Ѐ65(4s(%]ߖ S1 +śxJW>k< vӟ8X= .堚ASV~[_;P;A;*b^4ߖ;n\֩p  p_D!Lo&caJYCYZ_yv`4*rR\/*8cts*I4Ggt aur`NO^0`·4q-Og*-l+mf cV܂ف74-mG]_(Zxd"fCDR:.`N#ۧ`w\%РMv&MauI;8ӄН9ꡞ?u|'@6 5)Ctut1 ! kx'W1I8@|'r"br>7<~.qrx>$|QFɴϕgagc3]:<.+%Ch\wNP\3v 8syEM:|o13ԈjtrPG͌8e9 h-`ZiWx?:%Q}p(f9!۪VKE/x1kXL0ir/ёwŤY15j oDiБOHƒ~ 8z^NoGX6eY?^?臉)d\sݱescH {h̳s4#I%7}qDL9ROZYAnAkUˌ'0.NxI6D8y.^CЏD[M79@gGa dA"7刊((r<&GBjqOA7ڧfㅣ C]} {""u9yY?cA"Sc <;a\Jl@CΛ]>zD߸.nEҌ8!FcݸHykecJ./j5 aj,a"Re:(xՋqC)}[S F5BQC2<)b6 9HL}$q⸇}O}Lz@F$t0ύ8 yFMjD  &T㟄 GQÙ#&ӥ5̏OĨӴgH-yI?dixfYVw4q:#txi1*Qpi s-5brP4RP*՘qيAi>&DbOF iZ#ǹ(XƬ xbO1fDjM ICQ",Ya+ v&f_@, oNR3$hRFgk $EҪO&=\ >')Ȑ&E1)sSUvr_~mӥqZD󥉠BCAPO Q}HϼjP`bW wM eĔIG`Q=6V!E6A0 60sXinS5GJⶪRQCs:JZhF$EE!ȨD>L$ِ2F*L h%E>5Q|TJR`$^nJd*,~./O&n_2)z'i%bL.Dv05AIg~.=$k&QE` \ r<˥׋4٩0{NJ/1"Nb Ƥ 46g;POёSR:ĐioΥY˴J)iV磗K/+Uہ[ #[77b)3brD8] l -Y굕jޏ!1V"A#aO+<[?+';^/i䥮Yө5WA`g4Afu>uj _`Ϛ4uv2c?z:̫O*YK4wN!@ZW 1}}.}Dmd?7o`{~Yy^H+5WM>8B/Ǎ6c[6 dKȒ5Ԣbv$1tRUORdEB2 0 ͂q!M?ɮ<5)hxi%GPIG ,G,e -*=(p10ۉ'%$\|Ձ 8rj3eҼ{NGVzxLWDVY=wxqWk6Vc+d5qT 0*=!I2SwB'j{ЙI9yOW.PNx*ǹ}P.AR^F'U񒨬xj!4>3d‹Xb@PI k%M{-: hѪb; "{8qtm6F6Pcž> $ 4~ӛN>غݗ,uj4S i7̶lL {n|r2zvnrvtOyG :O#3uq^ E} Js.7Nk!}mbgb ^\M[@qMi#b7i^0#/+Rf/LAK1h<V쇉Ca7]kw xIa'p7G8qQk2%\XF4E2T7;1߾~!ʯ[ Ʋ4q =yNId V2B{j-g^dl%-վYdm*RmD+xyED㐀'B{[=qC $Zoyfqtě~ȶw DfWԬ}=V/} rF&ߑfn?i|p.nj^Y&fCkm,]`fVf3|PMe=\:F r>NKϔx^Nulh?ZJu N8Acr$ӍT֥?74#{~ݸdi#Q넍ivp4g3l4@iamg)?Yԓao}mޖN)~"C? F oaM>S~U4ҹ6kޗZ g͡@ZNk ^ր&;l')<6oPM ZgI:# %^ 3cءdy|2/W!S'>h>Fw˨'#kg|xgп:M@3ɜ85t0t܇>hNG%tS K[@ x\z=i oaE6xaYk i@9e.Bb:)©o' k!fm2PYqfvKQgI&Iu@WDp!^q;M rjI"[#L6Ng%3 9fj{vg8A斦aL%'[X: dw^p0Dћ]T}X:^׊*2!6/4k$RV[39;޽S4/l~Ww2-^OfթIbҪFV &WWRfuE>Q46;ƞJWHDz'# In}9^-{8du+MÐR%8D]L]4]hxPU s[=Ft6qi-L o\lp&&7 aKk2Da4Lxk>VkjD;C-䧑s8hH*@7EJpAxHN=y_?pӪj F}"XL 놓=.zgLz퀵Gr58NG|F5%Ӊk 6O} ?gM`TnElɉ>pi 9=)A״tNy^/}NI$0I}rpqv`jӞ#cvIx}̍NZG_apwSSN]ӹT&#٠kOt-􂤢\z ;dKABoGW6 ^7jmbFrU\S'9_fq%*cx&wN_FiF+&\3z]ī$,0 žHAeg2,pNA^cϼ~R/+I`+ƊK.6k۶7m[ިj-(K;!n:y">H8y~&h;ϯnbos,lpI%ߗk0Oit~xP'}{oǷ͉o+b%g%W9rj_T.!rIk47X9RuWS@ A~2oAE^fi0{9h jU kڞº-:NCg48I=C is;Mԍ~ԴB26csirItX?hnIR c :/I1lPSɻNϦ%_37P ƩQYAk:m|pTN_ӥSɚ;-0:lHՃMY[@=P3ـz3kӂ's<k`"r%K@Nݙh,<Fs%$m8hiHKs:j Skj:z3irҍ4՟Za`e5\/CBW-H8V)>V;v*WP[Z?`m?T F@k#K=mtƶ[O)ZT_Z[ 'сn>~'Y1T jcK 6z{3%{4aMUhyKldLPNֹ5gWoϦj"mz-OA=L.]#x~k9Wi!D zEV=O8;otvreNj` lOjz@kϾU]1 ܍ޔLm)cBgT4J[/dl/$y"e!255JAiAwjg;ia+VwBxv#-oͲdBBlWٕTzMS4J'w^M]*]W~@45O\Ŗ27yIh:#@gFf(wJırx|<_mBφ [蔭A$}㚥j PKU`|yt |+upqtArgGq`8`012F&9'HXuU0v%M"Dm IEeb*l]c##f1#s` ;Bݬhe IRSC7i8:l0"r#AZ+c\rܢMnH0b3. n !8u|33GKqLG \Ƌuo@Àd]talc>>`Aڶ58³^, E~Aʐ{nf1qBnCjG L7s^, Q8Ly/8Lo1ݾ1tt$jhN[}d5؆`hKۼEwOվ]ߞjc-9mML3's@4-El ۈH.˟vRxa1j6pS#0ԏ_J=\n =]haH<4Bl8D싙˱m_5B彑kӤJB^򁌟ϗ~ثa;7[HcMh(Fb~Wml'G`],ӟ70pBcuKqYN~uӯirrfCDU 82a'PL33D)PK6'B rJma&^_dHSƊ17= -1q-d^3AKp-N-7П[+GNMZʈyB΢Y!dH8<ӿ_!d酊t*6:eA 5k=e<#="i5HȌۗr);䌪`.rfnVaz#^=>R'-BlF/A .6T\ ;_}=~bNK.ިϢ>:U[ԉdVoƫٳK/z\ kpuk x66tZ`2ȶn$BGMǵ$Kf)=N }Т\[ .,>"f_UDYpzF Rfʿp+\:uȮ#hHs `"f]>rg '>:AV?Hk>nfxB1ruj .{>HZdٜ^tl Ord g`Aa]lU[f^)Hp4F `hTBSos4ŝU< ,QHv;-PYPAuR:̏cDZ$V'3+fhI~&y9} {Mb:fNi5lwr]' ҰD7Hνz`3a5uoLa)05OȮٌbO-״;8vy?RJ"6Z6= hlqigD+Mo6?Wj.Iv=nʠ9G\x jc9S2vS`cxL^ϲ"K]4=e>l Ҏ]պV[[wfXz:q ۲t~<%$ʉ2 g 6&6Y;(aX4c=*53!Z NNWj?T Ͽ̋me cODdcfHѲ`ka1$C&.; ^aZ͑|s9jɚB#&Gn,y8؇ n\b74+vtq7;#!'ҍB f$6ZAHȹ֏:5ق4a]^a7qc*mOKשl,H /;X vqʿccE}g@$Jd$"=Kf*VC)+/!X-tvif)PY`78X ;u8>؎=,f뫍0V hǎ<5\h׉aįiԗ]ռܙE⨑b>-dxx:ovb\DV;^Qv.I/iS;2ѩo=SrvCfckD6L9=u#j.P،c346_"ʬh~4 _Kx-T'_\5],r9=\;H̛RFRd0-0p ?l@sd:؀닷ttoxnE3W.8r!ٱ:SCj vJ]ʹNna^yW;a8+ABr4resJMJ=c~a-NE$k6cJ/,Hk4Y ]闿S= e=z :N>"}}[K;n@e'pRFJћą Y&>{©Ip}2BQ qYE~A2I*?c_jG5ˤ VN#]|, Z0N,Fgy֩? eܺϱL_dTD,s?R&ϭH9 =籆dRץ6?N8ֳϢ~7)ˏcdS:OsX 'pY@|Hَ+3dPshF#0;Nug;g5CMʒI+ߏܜ>&5PcΒٺ/mbd$ 1th$́)qGIL|͋e#HHZ]@N'L MZKҟ8 >eoq|$ӡWt5d}7peYKB~ɱh&iQT'AQ>/fD;dndWY2n 02Շ8eϑ3p{~9kn +yoxx?b:'ڣڵ3K..+yB&N5kz믇7c>#wihrE"B惽{Aʚ2u]TJOǼMwv`?tKyEʼnܮ+MBNZ]];n%E#2N7 ޴V{MlbjcScSn^ +p~6޸Bt664 կQ ŵb]Jp&%k5[:te9:RZo*`FlU N{ɼsԝNp|(3pV2D )Wv\NN$K$ f>戶| 2OVFc!- Pbmqߊq +cO@ Ā44yU~ >6D'G:qdc 4{u-m/f+=p>6,u*>dh@c4yZ[~z]@,_-+'fɩȼ[cYH緞MIoH&M%;e60LʲPr +\hY; Ҵ.߂qD +iݐ_J '痚ׂ=>>FiGuKBr#V3@l9:X&cZh$[sfghH8>NoNo2',xA qw;EwN}q:@ }EsW/jB)ZB8GT~`ܥ5ͩsbs"WOH M7-e{G +Uά׋ )@#N-}qۮzn&f]r 6~zD5:Ev3XءoH*_?t,a^a}<9cQ_Kp$8[ 45|('mMNnvZyuD}|:UǥG}qՈ,k #uˎN3'ˉjlrt"ҀqH4'h;l`8DNBеyUȒiNfF} Cޱitd8.=BA>Fbd|ن@dyg +8Nt*66 ж0]Bp`d1sR>f^E0:M#mD6/9YY =Ȣ[9mXV7t,ׯ|bdٲyZ;mF1ZҾ;#h)q>QSxˇd6q#4jU7n }h,DKdmc-d䫯4gL[];ޯKD&Y6z~4 5ŞxPaYzFnZB8OIxQyB>UrvJDҕ+?TA^FMC&ш SXS0IBSJdno 0[NIӛAM)kUMo6Ew{¾ikjhLMh ^=sr 5[eIopB&^Ƨ>LK z p|گU8 a~? mAii:H9R}L)x­j<`zپi)Z%>챾=[ޜ\ܕlw|9lDYB`j*ʹSZ!ZD e%TKejPez~փcehJ'UYْDqєh.1Klc ",{m}nD/e`D9GЦfY0\j-V8f 6&@K(o_10׶RuQ/"̲snGTX5'LחnZsنd 6wЇi 0hYm4h,VZSgRz8 <>7Kl-]?"X[Ws=t$M Y6sL@hĂjps wFWS]?h]zP1V-?gҰn"vm/7M-O왽gԡ}<[[}~w.#,렽QmxHeֽ!fÁh9۬ y-GYOO RŦ')>Ѝ'2EM̊$be-B֟l|:0p2+\A9xa%jlKmwAh^wP'SF\r6{>BSq1L-ɸdM-tWV5~ )p8?%S/9CMJH46+fp*Kk*h=j酑WG2mD-` RNPوLtK38Ytt,mF}t/3NanwOcS t?l-8zo`gB-`eʀd!n_tpWxn&'o_|?ӱr$+9BhA,F-=o~LN4/-ؙͱD&N&aZuAi'@-j,=N"f ^!Q:eF.u츧 6]Amރ'͵V`tf Z4RXp' aiPU˘'c1Z=aSYϙ($R'1H=4Rpf>R5++k`T}aeFvcjzw3 J*pOw4MJEZ*]yRt *wKHWg\d*8ԍpDm"4^[w!Ʈz;T[-p$hq VyÚW kgDZ#eJSPomVSV#K+-@ ťppFH^Aqwk?fWZ/z׳(Qw6sO ;\UuZ ]}]ߋW7S4#/3Yw6A3k re$"!vuP9vApѓLݔ>3{m-@kJ_ >3U) H}N46Fo3u tGwL*Zqv:hv)|TNFW@>QttYZ=IEahP7E~z=[P7NPqtIMthMÖ00|OSfM;垾X4㞬M4ӡj>WdJ9]z04HS9!8SȶAszUj?nS5uik"GGӥM3:. ഍rOp]T1an)Hn)y;Wp#; oQ vGfY6YDND<\^R}Iu ,:ɶ6#ڄMLne0DfjޗJ&kb 5i(L-CLbQ^xx-glŦ3$U-W_hGA`e\KTeR)t.f۷6^rQvMrTfo|TP` ^i5? m~b[87^]3?*-yq6XKT[e@B!6\B<ߪsd@Á>W. f~'ZKw0V֖\|.1ؕ#ܧh筬7pk-Ku.$n;08ō|:U%F(?E+I^:8㾋T:^rߝDsnDzq`GhWȵ@oJ >@o4oṌ/4GKW8~9np~6 /'pKߢ*Qnz.oo{Uu {AjHtb+\?@N]iw8D>[OqwZrv\ꗞamHumמrTEoOAD ѳ>_/-.k;-BjZfu{ƥUGTK@szmfCW'K{oJ e#}",/ MU!];QZ-u!CwAfkcNUuW- M`|q? hD=-|Лz"9 _b7vfu%v97y*7I+ J8n~XX(T^]BQ$[^cA\xNmr2#Ӂot-iТaH'#[\ߐi595wM"Y#9H)An]}hvSʬk֕bUP khvH Q=())vlw"%Vbhk07ŋֽc0HcÃVJׅ纠 ĵW[]\wQ=XduuUn&-SitedJҕ-)k oS>U$V/z/n<6l}>aʰoQAΝB?/eOC- ??BP7Q v[je5 Tȹ;AB*zq?fr1_pќwk>xͯ#[Xin~B7rľe⢾t}Nd7{ }PM7{wxN}_Z5[m-G;z4 kDAa)槯 kzRxZgOk-l[OIK<\*hʄxw+͖>|x-j5M kIs ~ OKo&E@mSN>m;_Q1e6Q\Vo7zAc(XYSMKѣ~ z9uڥhS.OkWFJVŸvdcTm4ûhO]`ӮjBiᚵ{!N.~~4 i45b miǍ mEr/Z)Yoi7 @#d=߱11u#8< Skɡ&O;{PNP><{s(hi[5Pz}vTʛ7<ȼ{} @>@')6,nb;QxR:(/6lS?vN};TtqAoP<]g }9P;PG;s|/C.P]Pz~%Ю3~yЩq@uFuPrĬC܀ީ;란v:C砺/Z,n6.p~CӒ>)P_A+Ѩ׃eL&N:5u?L'fŪCqXYN([;}uVN4[i^RD0=RQ ߞ]H'H}+u@YzݕwK%[W_f]ƻw%M5J ] ߂ZtmԵ[Ж7]R{pJ][6Mk Л i, 5mX(n+[:ڦh$}Z òh9[ҟ]TM;'f3 E2ٓӐ$|8C2БܦV:9!EW?1s懛?;rzimziC>][J'A)b􄮷DsRhQ$|VG@O{h ϓ0/>y "o8FJd?1zHψ;(-<J )DV5H(Ak41? _|PYd}|ub\߸O=UObo]R80<2NG/˩_Z/F-pP׏7O N$~. c Zży O#?k?OIb!}IE:1z||JHԯB7~EFБA><< UnR8X,@ 똖=ΈZ>fƓT.vzS0w0@昽-mp_f+Gk/XpSzX?`~;X]h${ l\f8δ?EIJr!m@=UyE+N|* ҭnN6] яC3ۡ0>C֩)Y=K $舐*.͜$GCpe$!<76ۛ4>zt ܞS No-}<$,m:'i\80p1dp<O'ͣ*7ijٜn,;Y:!U098݇Cw~H*NG}32W A`n?9-?F N kA&~=qKljC*Dwr_CR[] $ҥ)<续G}N!{9OK:1Ptun~09l0z D ϏTOK"T&WS:йԓOfMpf<8-O&'6$`]p@tStiXGs=uM靖h$8^0.w6݃m'it#`.ts([At::L:xN? S{~`Tp)k>kNJ{׃hot_T0H8ugq8 R'!m7N9ʎ3a9G][ b7)9ݬ[ ϛC>mmG|8H"J0 N7c|ϺaT:އs r5HRv#ze+w<Ŋ|0Ep-"ed$\Z!~N?.prR3r#S"@7,OQa&8gߏUR?xo^6&$f52 ^JU]'?-]Ik?a*Va#p.E%Pduez}h;fCWTWn&[]X v2yHݕ뺑A_x箌T] yɕ4KB' C/MDD}RÑMQW[kc7J'vd#p܋GA6kNBpӂ nL=~Xi%w<%1L:OPK"K/7LC ܏Goz?pIwо~1<ץo$#WdlIE:pU5MV%_%Enwбiӱo8N6ri^42p~<ׯNzO+p$)]uc  dX$_=h| [Na/}P)S! N k('8HPwH^A _+䷹ )'VU)]CӥɉR;4A$[0AmƳއнY^ CzN nttɚÐ׋WZzt^>'„BiYHWDJ ų HDpzd!]TB8JR]C`s ϼNG?=G=U#Gon[PC l.+BΑt[~D#x.1LCη wކy>S:Te\.Gz|_ Z>p9YHW }s9r-KpEnR\.DS1y| L }H^b |;*/#Ys 9zh~Zv2Ak .SCHG#Z tCB9t{Au^ nH_b8k$ 97>x>z%n1n}#pOϘfH҃/> q"sc 7H<~H*ҥoOyy}tAp;4k=uB#v_8׏ uc&W?\Mpp̡4̡yKy \9|<DW tdyR?c[Àؐgq`_$HBl uk>:R.<˥z[o^?.B:8:\m^( rXwse#7qE/dS}s=aw3+ە㔎:(ihyR9,o r3-7&%c? 2puK,sby%%B F-}d?Xm' _dnUnٵ&DOǽPǍYS=i$֢l:GWPr9U.;n'A8^L[٢?dlx &_Zs]d'!oWNmtcAѰyx1{T bNE }mfm,H`> S]\P Gf^E!"bX ,&UK[m-#dE(fEW '% sؠοzr-c?=?lHSgD/O =zZ RQð(wq#(ؠ$D+IgDݔ  `Ϯc@z @(vXF٭g/O iSF__&z)^vz (dA=6~D0t$;] J73U`'tKv~Ͻ'D1PayoXpofgq3fډ/k(˚'P+LH_ \ܻ dhZCb|1q#5bd1{=Sҳ`y Nn5` Txƃq?$%1 ya v=:i0vxbv"#XPҭ @\ pv<*N<N0B w"HKa[0Hh!#$dfIlpp1m"O}5aT/09/{T0H ,ϲӥo2H1\A CGӧ KbdSYv)Cҩ+|bd'8 /~t$;]:nɼ0a|A ^.yQXG`A¢d}`F,=/p3ٝF6@ Tբwz?  F} __kcC!^oDpcGI'oKIkzZ+PxbI~D1Hs*GbE d_@x7vlH*/XPRZP¢U7v)E`]C `ۭ">dDUa~ЩO/=%TW*G8A${?҇ ):vhXIEZ8Ǝ I !}$/23\:uF­ک޶_~XD@ IO[ =(It}hpݐ/ 8S ~ʏA'*5i'bpA gFJ=&jҷuW.8v|OIwSףKA;%1} _?;vpiwnAKo(T&j~nI'D*ztώܐ!g߳_z;n pH* kt N~u_N^D*3o6$IE@;q*ˡ$BB<=eGi~7T~PotA'OR4rݳ2KvIa"#tS{<:z>0B ]9z]?[?בT344s7nIż;$*n]]W?zР!&yًvCH*ʥ5 b[oz[W3"z=gke~Sg$jT#j#Hw GOhqF52{v3)t`fC#v|/t_~H_=~6$O] O!|⃙A9B°/>u_=; (/S]UP#~2åaM&ywAEyTwi  O2 ~Gx㠽|/39JkG 447i" !NF IE@_4c_s/EH#0=9~ 3ho{ZR/O :AN3 3om>XzD n4Eu?8T//=} WL*^eFU~@1(S@BtEĠ xQ48O֩A9:{ bA%5ӥ?BcjWB*φ?WTī~ o^8O!Ə{JjZJy[C o3ݱ>꧳N{htGRy>W"m>C1BoC*񼵸]=t c7H*?Y X} o=ntWr;- {D +96=iT+L.DՍ zWR?HxA-zD t2E@MF#4|h0^H_v(!Iax,A~TKχKw0;[_ȚL]讟p~G] ۞(BI;6ʼnx>)oE#R/:4 aa18 W‰[!DUTT5Y^!e J-Q!^ W7X(wSDBv6[ % uGsW?T_Qږ~;W6>W+ZD:}2=#6C €ȨY?7(zH3F_p7 ןQ5 Wo^a~hw; S4r +sAu#B$|zb @'І:1m0̜ !N}>?A6T'hCAu !n @z!уm*H[@{e8԰ _R,$f@ 8?>SaT1_)АvcՒN\R AʪW85`Y_|_, C"0*p}N%DZXN_gt>)ֵ{ ;/4߳Z ]B/6NF:%`ތiASҧwCQ-N* ;SN D#@R~6? vS s RR9|) a gM}J>4n~m/` Wa|OiUĩ6п jMTUzdKSZ͚Rz9A,F{FJZj<^ U90~=B@JԟVxjԪyCBoZ2:͘?%}wꋲ%^A{ʣj' ?fJɆ @PL !z @^e$.Fn}SA_e ,[73O诶ZPڟ |5Ʒ_=*|%AY*hPO*Aw2DUC::T'FVD-p_e?t :B}aH_hO@BG ~ Pf`;OKBu?ADYgGs1s||8"nW*'t1)txRSX8A{c':CH_=^X{@>d?La~%EUu!T2H.>듒?О_#Au ;??^][[@>u?K sqAbby !81K;lw?e<:7 ]] Z5^;JafQ-Q~˯?]crK3NHTB`z-ohjLi -mWO`uax)<ݾ&mtABo]n)_=|O[mh|) ~wʈZ5Rza j? '@-AdEUpN'SAdʍZ_щ;A} ?XxQQ_oSԷ~qҢ/yʈZQY“N)sAНҢE=Qܩo O/b*8O;#/s]cLz9p WWHaclC*N4E 'yE-=7$d${=FEN @w _ztV.$1yo_QRHQER8A8F:c % w ]ka'6ځ{w_5pj }@ytjS1z}m*uk gnIEt `AR17$lL~KXw_ %iIżq ;/H-)jf;oA ^c&ur;/L/IE yJ@B 7|o7[t7lF`z-oɋ jw$I*];%U-UxʗuX]>~!aKnH٬ OIU3EU R׷Uxʧ/cu5Av) Ux? 6TH,-)_)~սY9?Zx1:˗)Ak@>h ^z t댄[ߐ/tZ8]z]gLdd7 iDwnVQy#$#?Zt^_+7쌏]sՏ Jނu N^1v {į=pg@6S}>=a>hYsB-7uɭo5 z%^giFʉ)$ :hnލ 9ޣBDmw,ߦADuFAC r>FܿcCH[CZ>uJͅD-CVCs;Q-T'0]>DsA =?d-b /"ꄹ!a등lnFvL?sCBn \:i@P iXO'W>1T'1R@A$#!> Iom4')MA$zUkK4b/R4!`x!`|H_Z)M_k3|m}N}'[.}'oXjLM u/=_$oh'm`E/o0DcH_|_PC_~T?Ќ[WJ%9R?|KډF }D#=Nwx~|O:|'K}χ Jx[ʗH*ChOPPQ=$^>k->>԰S:Է7DԦIT/gA ro~QȧLF>C}{mj"_@>%F-%h/tB}SU$?`|OPˈiM TK7S:-ַun489u_Ŀw`FR;QA _GTo~lH*y󿠂I/ԯ#IX?~ N$_PANF">r7 FX rj$ C3 *ho0/C-~ jX k㟟DR}7I߷a=rzMס#u󿠂IC S׃}/aCR톈@ ڃh<Cu7 i.I'/hF@ tC iC5ƍ_H9HwI@oA ҡﲴ^ U)0`1>j꫱!fzmҷ G=f:/tzC6:Y _!}l +sGE| ꤹ#">UէWHGA7˻!NQ? xrpbAR8Q7_չW..{cm'j\c?h]צevn=O>A ' wd|d$_'3^t[?thQK$:1G7*~Ço#iX{@,^>tu}#a~=k?S=WUBTh',H4?:}nx!w9 [#}ݱ~AxiZѝѠF541d:OX?Rvr߇S^_|3h~}΍pyA9Ԯ@AĊ=/Ϩ 4>_|.FM5|C,想z;3{? ./ Fگhp;%6-%.#$H4K; yIL#oCB [%y6t| bBŠ}|t:k aGRn@pNtm#AtwAB'_yn4#"F<N/m4#"FxD#`@cT3?Gq:1m6"$/ 4ȑGj~<_j~O~</$Ǩf_!/_GTڑ$ 0PUyOMMj;&H/KAKv6D#`O [_ejgAIAl8 ~7‰Lԓ"oD-pNnH#htHV.nAp=t 8%}ydB.m4#'wInAp9Q6 ջ}hGN hPH6o}4H'4N|NH4žF%};S/TPN-W.Txn? IPK0>пC{?4>L^#IN]?y+WrHdB򥧀x$9C륗@w<2}Citw$9]£ ܄YZ<>]H#xu:n*8/t~v-MF:ƿ+i돵lT/jNWķy+_Dޑ>.3 PiIRk*>{ 5ȑ:,/a-yQC E}|dJ]+H_H:m`h+a>ҥdc{m# j@0WɄj҇nC ,p@吾l ~|mտm 8׬/8@pܤwԫ$A5!2Dg3T1H6?&&}?Ҥ1T1R6|m6sl &}?2>7?h} c&l MA3A>I`c c&hc3k;Ǩg >IQ@PL1>7?#quH6?f&}?CzRs@PW!}Rk;FJ7 g~3k%w8F8TI_r1s {+|a2ړ C ў$/jX$:C ў$/j،$0Pn'IA=I*סhO jL$wԟ3z˃gBRZxf$KP=>I*\U"hނIR+F{TlCR+&}T!Um>('I#%C>I* IRQX$#DH*:b>xCDNFu@ĩHF}PO"$ IRQX"6$~!bGRkF}Tڸѡ $$~PO _~ bHnt('I IRF}Tzѡp$nt('I IRC5K 7z- 3D|}_7:7 Iz z ՇA.tѹ|^ڍo}ht#lH(Wz5^TpC~@O _ 6=zZګ;5Y_!}C|`rH_^lZ+|mտm UcN} $hpIp̠~LAF~g+Ix AR8]^Ш*i%+j/>P|*)NF;Ap9^~0Rԩ4t4ށUOk?^U~S?d:vG՛W6~lv__C9h}$ ؏{w.tx=QJ~ӰvC>Ut>tԦ_$ olǭUUU%9C^_^aUJw.W$`È_w}u%u$ߧGߖèWw߃D*l'I_vUAwTj;nC|7O;3XWgPc+\5F{?I51#)$|&: \'|({51VEkt ~Q515?H_?Q}HN>4(=}}炄6߫QKIP⥫~9Nn7߫bC{53Vw7U+Yurdh73TStijGVT. W3ThpԦ8msijGS &kcj;'dėLv/WN/W3`>(g\h=_ZyT8> $p|iIR $02T'xn}4H'dKnF׈_1?uLp}_#W.Tx.I_f*Mpay>298hOIN+P7)~F{o$L9?ZP/_o֗C,=\dWo^eVn ^z13NFo~ kBuͤ>#[_tW4U%9E ScOw_4.X_ 4H&T _TPAI?j*ݩ.Jh8戯X#Q}\z?}3^q755Vr#&~,φ䖪ҡY`aU:Zb Vhgtr^PvS Aop{"u.g[ёd}7O}_{6S#?zJ*`O[8PIR?N}z tokD*Ij-1~ ɤ*)#BU?~UYO|9|0[|/>Xp k8+6-|>8p g8|pnW N{kԧv >ӀStON? m8+4|>+)^;| {AB0^:pnW s*=4|/>c@ra4Kja@Ova* ht1^YpC dq|jXoX,Xzq^^ :6Ԉ)?ju~MS4よF{a=GojW@+uCq)L\Fn',) `>5)!E8|?u_vH֟)?j-_o4hIQkzό\z T~Z"|D|z߳5w,8Ur}WfZp]G D| g XottoQ.*[lAA4mmAA4džP=p`az[GP=p򣾅T$D|=ֲxaTto5*j_okTNԷpZֈ*'[lmAJZk z@C5G[GP=pҡΠz@C} ֺֈ S:Zc|5*j_okTNԷpZkԂTNX[P=p`5>ŸTF|3|O9Qdz!ҡ֚Ok@{Jwi[U6|/>Xp Wl[8߫v mWN@ '=C gS?%9;|,B#mza>C} UINeFRZ:An 8)ɩE"I"]K=%9n}Z6.GYp &ʀX?4>~nD[ !m&ӈ973˫uk- Aԓg+p?` =h惆: ?z:hϗV i2 § jehqT0D~h`Cw^<ٺ V˭l)jAxAG| *^qF@#k|QtjD{Tt_|`δz/Oԧ1j$* 㣭A:AnPMumꧮc$m ؝:p~O;@jɫ#/$zv}?$2HF|jSZ#~o)i?7A*[v ҝ߅YjSS9 jSэ>4Sѿ?W݅;;nSKo@wJwH=]@H{6Ջҽz//kS:oߦ~R.=6l@{JwZhPOq^ t_CJwZ?ǍzM֦~z/oS{5ɚ$7/ApA0Swߦ~:|oׂ5A/`u7T1ֈ[᤮c|@0p^cÉ Ŏ ܿwAmꧮcA՟Mu bmꧮcl'oS?uXMu m*NNG6S1F|O] ;oS?u`?zO] ;oS?u]h?zO] Oߦ~N1qktO] 8Mu uj*~ Rt?uFwA,Swߦ~:OE~:O=Q5o#>.4 j9O B yA0SP;H^cԾ#>o5x7ABwv }?1H~^n jVꧮcz~g4H}SP;]cz9kпvǩ]~G_FNAw!ќ^TS~//m v@ *?~H'/`FR~ $7/`ERQ~ 6$7/`GR~ $7/DR1~ r42L2F| *ȩO=A3T r!EERQN@{ Iz`GRH*VNRh[砑/>Z=_gT[3 `ag  V$ nD#>ԯ7 ڷ5O$W :?>o _56 *ȩ">ulT0#HGVgk>h"p`h!p`h#p`ho p`hp"nD#>ul!Nш/5֩0;P#oT/*XTS+`ER4ؐT0 4ؑT0 48T0 48T0 4ȩӈCƩH9u5#0 4T0 4XT0 4XT0 4ؐT0 4ؑT0 48T0 48T0 4ȩӈCΩHGn`hSW#^|0`FRo`h @I0 4ؐT8@I0 48T8~@Ioi/ NFtaAN]x@{I@{IC OPG#mk=h#p`hp p`hp"p`hS8uq`)j_eok:h p`h"n7D#5H*o_PÁH*o_PANF">pjiw^C#k |z`mXaCR;@/!)ڥ|H ߉ *8TN}y }A:uIv>;}Щ3H/t~v~7Dt~O׏m?)q<鳞> N|t_ ~}w^_w8`ԇՍO y_ڹW+oi rxFRXݘ)H^H?Wt n}}a/0SOq}% +si}Y kgOҎC?]:+@k W-">XGʁ">ǀǂԯ@NAt1`0G!}? ,(L։j_'O K?.SPNASR;'OYK?e-SPH]SPNASR;'OKdSR;'OYK?/SPjSPNASR;'O M??6SPHm_'O M?6SP7V_NMD#wR4JhNPO=O=`QLw~ONYM-SVS;OXO=QZྈcT3Sqj~2O|QOW։IeojF-8шՑ'@~ ԉ@!|[ QHmR tQ ~~k>oIm8#)NvsoJU?XM)>~VO|QOډt1@zcT3SOyp}O=։[QjG }?&|~O~O~O~^E|~N|_td }@K?_'>1Su,=Xp'ώC?H;>[ #@@O7ʉt0Sz: @?8?~1O| c2?^bi~꿙O| c2~YO| cf;2~9N| c2~꿹N|EN~꿕v|V>?o[?ߪ'>Oډt>1k??'~5N|och3Su m?j7u|%}M;> Xփ5}m5?C6DՑ4D-?XMCH)6D#9GBӐJ4敄8'VGVSo^IhR twvzsWIUF|rUw_𽕃ߩX_ n:tKG??v<:#QԦ;AՓdݿホQgul<ڑ:-y}sН:P\.;R~n?zװ#Q}\z?o {4B~TCm?ձ|髵~)#!ToX]_CR?F{9H7GTF>ҥz6:.oI!t+_uHI oy~hw!t}mt#]?ToCHRP{ԧ(^AHϷ߃$uy~|GT=t}[G=HQ{>r6d HaX{>rzmM }dJۚAșb|߃ok #g?|G?j?|p#gG|G?l }dJa}V=H9Sa}AȏϷ5߃$ufk#??|GT5L?RX[=H9SѶ{>2zm }L]u߃)uy~hkZ }C]1> ok9Q IoؐT^=)ڥ|>2H>8T!L?A>2H;G&Tc6:#m!?R"V$Q!bCRF>rH6:#mI!+47TƷ1o:R@ }k}|C@>%Am "Ù$!bAR@zSfѡp$nt('IE;z@TlD$g''I6߳N}u]|O[$`H:k l=ߖ/DlH*PO 7:AԧpyC>I*kPO F}"'Oѡp$??F}TSnt('Io>F}Tx} IROѡp$^I*PO _j7:$pqC>I*iPO _Z7: Iz @{ IRF}Trѡp$\ot('I/ IRF}Tѡp$I*PO _7:Wڍ$p~C>I*ePO _7::D0;pql4ύNшF['hO5RKtK ˁ:?mtu2F|Lm7:\:D#>.n %`𿀀T&}T||DLI?ֲ\P _eS=ԧ(^.'I?2F|LI_M$|pqdidHx^{$/?;q}Mw͙@9`X$INCG,_?{F7Փ/: W/tɕ/CtpO_{Yzr!E_==NWɟ(]>r)@]p;+Xy8>Fst Zw-s$ V+*XtrA|Tr NgzOӺbH}-@ݘqc?2uEbG=9_5HtνD3Hă*1Is#w{ g(GwaGg(Fg(FwT75>Fd>FatpUKy賚lrK糚mpg(F^waFg(Fg(FwTc6}>FA6R>F!6R=TGg5(Fg5(Fg(FwaFg(F~g(FvwT#5x=Fd*,i^n6:#r4U#ȳ/s7>_8ռ42#wtP4;:puah+Gj}M܌dnD%{  ^sn1(#0H߽/Q?; # hbh-Lb=)<6`ia,6-,/oZcNX[Eի_i[;:!vheY{NuX/F^ 7"Sf;"fŚ"jz//[WsC 4f ~9; rrM,Ek|`"ӭF;P"f| hu //VfPHH+7>~I}ZU;Ԙ/?+w1s\_?85C+TEVv`EX?~5O(E(p"sEO uEj~H_?=/>~rȿn@MktȿfQg$_{8s*9;cDZx'Ɗ,֕S{\}<#Ŝv}#$;*3G{/hwjs 2δ=B1Dv()#P/=<E-m<ܟQǻX6ϻגw(y%s$Yz N>oVܤ׊seJBg7U4IKYg*5+ڐ{jxZЎ0Ofi%rӥ}f6\"Mr_Zj/iQUB?3*Pz (ciL~ t3uM[Enxs]cES;Pnk~}<5ddOڨNT|r_POJ'3LZ`0ѱ2*xi:,iQ!}$iMm@5LPdi&>ZܰT@/XʑRQ&Guu*4֌(zҟ7MՎ6giX[@w>u >5+z#珰]O]Ȩۃ8DF%P^hS*ܓ \'*nK+tp_D~ TLK=亢<7b^+ ޳_,uI4+*76$P=Ē- n%T_=*a(Mrz4Z0;*(oş[yNHVgR!t%~Fg]bveH*SY\D79;P_N$y]ybTz'ޘ%UtEoCp)-˲S7$ տf_+c{_z{4~+%BWޘc[cM4 \*eWq(hNpj  Ɂ<<=@8iEE5}#2*$Tno r^oǕơ|E0 H+>jamѷg[ZD [yj%o&#KпeL?r5'QQ:s$* f(O\ MҴSIfAu%)79]yqV 2WKW)rCn~ĝsoKR%tyyVR1GV;R_OTMg[]QCFn%FV\w6 $wq(;RWB BYs1E+ sj@G3"آj̺XzLB~E?oiWӟRpѶ TWf TthR@sx 4,&wϖ{R&b@*wB=](F=vRecdWFO)yS̔ײ+rvIO5 vz=r\->b]l!Ңt.E]Ϲ#o&cUz ju18J9#ca.ݯ+l&8C a NN.^uy}ܗzPa݊la"PHnN-5X sYĚrDQt~!e*?GByzu"H;6ScP^9B9M TrK?jIH?H OC'qW?}ꍔW<[mc#Hur~FB 騭3RHHTVGBz|g kw$D1 ?2~FBB:EߑUi;~j '5jHHHeu;:`h#տiQjC4g #?"FN4t0폘\gaHZ*67 Uui }.6؈>[Ƭ%FD4', hD~уN?[? 97^8Dj/͙OcC#1]~uhUYhzLNfI%7Oug|$R$i:WX(3ep93>,4Dns)ȿz1"_yHȞ[Q<ZxNiTwjcN=de]GFpqo,JgMtWB)'\|I+ ?[ Tq+m:n5F+7C zϳꯇJuԃ:#۠u\~|]n.m_  PZõR޾:ݦ^7Z4 ׎uh׃<(SRtL7e210ɯF8ɯ}5M~E=mP`ɟR+TĠhmM&cSV&=JH ǼJTN1+Ռ <ʢkWC!77mox|LnPh)ה*1IŰPMѳQϼ=6~z7- X:$7X,h@̒Ig3e@EE.b;zLa$Pѐߴ}Wn TtjXӶU8BOͥC‡ ӵs^HG H6 7j> l!S~pn*GB @Es˝cHHtGem=YKl+Ko.zZN$޹9*5-+[TPAu)NWҗP@%,PՉڂ9խ3|^s3Ohf>*]AS_.l5'f-.ڠI#d=SP2-}*pM)%̣Qyi͹p0ekh);3H:szlLLl 3JTnkd)4X`]b]9`6e4 aDǓSU|[Tr9)͏qbNY`#JP.i!AK^a<_.)nEm,\,e(o=4svԌv HVfZ1ܬ/@$eӲ;?jUߎ:-GӵZ>G3XxXm|QQGEߩvw^Hwu~!6(?=X;q#w@Rmܵv82*7F.)9L.sKݖ,mصsaReQ+:]#܂UNV=Am^7ߌb1<Cc!ǓK 7$f3%@_&ŸȃFC6)wzw!)G4tY]bwV%OfUN?=l߉*E@O5gemRP~:kPYP`swNia$PT`r k4W\Hœn T0OƲEz5o6 B_i8?PpNDrH"-/dTBAzʻcX*{jTW?^{-ei*5“nnI*IWc+i]顊m=sDZ tzyI\TD*ߋ%FZ~' FJ 59/B"1kB#o$[r'c&lD*xqtW H;D7~q4R_ PJ Fw#-NS ՗+Q$WQ!5C jC4rS'N~HEN nĝdi;(3$ی;C-l~h7D (^Jh"u˸Ta]~iҰUIo&tUyf j}Ev,C:D?yܠJ+kxfSKkᚩպSr+A*g@S>䡣¬SiP 1x2Ȋj򇖝ͧ^ 0@bJ#W"G҈XBJ.G ׮ Tja4ʁ41*\.xk66/ Y <T6C@!`>!͟&V1ܒ LyΎ-h3称[m|(7"DMhTܖ;8bdvvm  NY0I'#m$W 6E~v'BX1l,Ļd+b&:JŠO I% wN.T&5`(iJdM>aLGK#ŗ4r{G(M/I$&ܡ>L- OF8?:"4Zay0GB!c'Xb+ `ER_.n!1 -&7" wz4D*~ztD*|L33f3:bP0\ p% e~z`S `|`r̫yDΚ1j0/?0G@DVgph3dTj)D gcR Jͩ}h54qd}qmC0g?HciɼDRǵK1UDfGԝ4!٣8Z"5\("#ƍ> Z'K\h^<Bw љf @SYZBȩ u"B2,7d,,_>`[/ԶCjHЌgmѷ..M]Z GT#wiH r%8a:L,ھ?hчq(ѧt/PND$r 4 xpڇYPnAJGD?Tw9QF@ QOӇJ>M"g8uDKaknvBA)IxW~8%3d 5x'>B 6Ƒgd#p RawF$1]Oq&۵!4xpԒ9M'aUGA=Id RAi$z;Y`f cSxq"HcNL'$)9$$H7bfZfT QHb$8>byH6=',\^0$D>M>" ~?(3a= A" +L%ID"wJ o 4D*)z@FE*^.z?aJ+X_ҘV7Ǹ}b1P- )I-T] _hR+lh?卉sĂ銚Q9Ɲp$&?GT&"4diW HNHcT|&I@Ӎ81R8Ls#R HH[*I^МJشaԉ2Ghe1}'l3LW쀌ɑ=B'R1sNa!H ܘFĕ8>1)X_(#(޷nQ6מ}1OSIIГE#!AKnV13 ,+ c8q[X@j~RIOpGdR^fEXv <[+Q/  Mfhf qE'Z 6f+W?'rc;15 ̐oy}C$jDÇV<`M F^sFzCsVvM;S> Җ PB75@F^ܸ7B.G92p&$##iEaɥ V;-hBa{&W&7bZ8@NC]ptA]Jݠھ#d0nd˓; G:?e LQC0ì5MkIJb0wJͱ cr?1*IAeib -6-,׮BYF85iӄR L0'mzOiQ2K`H@?q q'&aDcH0|4F;L(0wԌj\S #Ew >I(otԶ%\@J!$#oHi]\a!,7KՈ#h9l|%FZ~"IC/7r|4.F<dx1e (-3`}/@t[3D*JH<>ppX$+@#8%! e_8XBx|bҴ\=0DnV @q03w@ }X^c$Ý@#4<Tu `Bewf'qĝ 2& u)x7!hNrxpP58أf5a{8rOf#!RHpq0DCdj[3<*[Z4+5JDG5?- !yh<27F7%IaNϙ2EQ{3Ej9т"4q xoSK+`cdRec1^G^{CGa }0Z<=jGSlen mI./d(cF 2_p]m &3GH!PJC&mt43õ ŀF$R}*>; OWlmlԈإHnFE7HA{ EKW?Dj2 X^wE7<tVE-10y$t~wM>8ePbA`i_3$m8>F<@&"Yp' kL bE^vQ"e(F}?xb;C!5xbx@=)G*F܉T3(!@H qEv# qНjPr" dBŝ/OB-5 auP$CoL { 9 Dm?L8|Q<¥q;(Kׇjإd[t#$P?!7ۚwB %aj:Vm͞2m>dxEch$X"JA6%F8dtXd۪$~$^is(g2f4Xe^P;q@dFKf@qh1?xxCi~D=i2:.y$Z I9%d&,-SR2T}2 MQj*DB9O ΐ'm=3g f!+]!I.'2G+.'6/5J/r,@C"DN|DrE#HV#gR>2b&=0qA25h ˶?1|l؎B$CiLwiC 4BP $1jzI^\\ECB CS\hUDv cC=.If#{>A 8HN#6t4q 8*ASʗ9OM3h(f( .`CQʳU?YXcd.`'ia[ɫr_KHS;w0  i9`.# 5 5tj.@)$n\ 0LBDBq٠7 ˧ o- DTO2\fjD; 'ıM@" 6$RQ^8H!9ᎁH;1i!@b"R h{>d$RhA*;>@/|!2{wy&B5 $7p p'&-H D*܉I  &-H,D*܉I \bo.i ѹ4>ď .q%-Hpi#J7" *"5@qٴ!xAcX 9r%C%WV.pHKc:04?E/W| : kEv ?o0C#8H?h{ELb&Ht{Mfo-ۗHIF4y\ yGs8'c_R(uw(yy}D*ɦMEХ['q\ږ~T& 7-~6#H1=~\I Ƈ`cRI? Y#)o#!RhK1ج>$ܓiyЂ pÛ Lr5aG Z9oPq'47̓,JzGbR1zOiXаQ}O$6}H1wr34=x1wy԰P" v0wp^cx@B897ujE|s%$@F/X g=U Z7M$n\~?olZy\r4,+P[ mݹnSxʓ6;WQ_s*@G8뼄<%: gb/N cg&5ٝsQD/,lզx`PjɉBN`34mn逸4vKFj.>.>t d8HfK"w?a2MT̏|ݗ;H&< xYDa:8``(VZ± #МJDZؗ&.K@C'h&, +GD k+oh8TcoOۧ/ lHt]qCVӒ̰Zr;P HXTaӃ}f_3EMǿKT`auȿ/m8h0}eߧ>13dBE8.=P 8CͯϿStxlP=>?9-_6ڜ'`58LNWy9X%NQ8ˎ!N+%h#L]@8 -#J Jb90@(3'Bq|>((+4kʆ%\&:x^cg\{~o3E4wc Cw4Ac`kѯiiio3Beqk0@ D}[T<.-:(q> 9HҲ @E:,s^Ydu2UN Bp%r͑Rqб|)o]!6(&h/'{i3R^oJ)+`a@R-?Qo#7y.@Q6QmߓX` P@I=V@{Z9 AW#Zh( 5 )!X/'ӈgs-Qºzx"Lw_;فCnDKvTt`JM8P׾ GWf@5O|p7,/V:xyE(P=  Q&E4D*j}=~%X_D3E2PLՉDP@F@;("~5܉+)"RN4 w)&E4D*܉kE%"쯙zRDcp%fRN#?:ѹtq%vRFA+)"R3@,* _y SsC>9@RĨ.zNq/J,D*? W+% .]J/_% ? WI<[VG%/G"vLz:/^xD[yJG} T|F4.,@C TF!y(?徉>g\Nn,%J $x͖` `z "&"q_k.SDȃp ag $/\%R;\'` Uh4tn cH1z{uPR RVuNZ-PAdYILc!ev XëjRR4Gh]々)`{P GB8,*Ә6"wIG!~B=\ߊ&4yLQV) J9WAm0#% @0eC%6B\8?toRq@C2SY&X( *h6i/=fhPtFA1Vٯ/}NQ7$Q$P$*" :I܈T8qD-\O Fd7?L@od(a$p[%_ qd! RxC@DEח񆀈p H" %W^Txd2  3\Lܸ$7_ ܸP2Qpty+/)nB^hT2xnr&O%\%I" MߟI wa'ȿᇀHŋ$P ?$%ĉjp"<1\< 6]G!qb6Z\p#8Cr]p* f?/v13nܡtG ~`129NI.F1`)(?S:DC*IiN2·#Jԥ'N&@LAō(++_8rӃ!')gsnU &(O]U[Z_oZ %;3x,z8@8Yz %JKK"gRPmONVkj@Ȁ4?g  9 !XD8@4{e|G&MAZtbyV/V{-Z[=,ڜZJ (yVfhݑ* Tդ 1!J3;S֜)KK3A0Lx@dPݖ2#,KϟQfs.DZ A@M)1CijdTCXK`Z12!iSaO#ﯟs =M; +B9"<~? 귀>? USN-:߾fЁbP^i+\`;DQWD[IS@O%Dr!>0SY/Pp<*ol 3Iٸֿ!x5u\}s?"xh;muxay:R,͑Y˃˻l-DCoFNBVm=䖞)ǵ+D/ p@*Q+^u8۔<7мio{j]*h.jpQ^j JLSSIprb 圸SaQBl_uY$:^o-^Ԓ䆭7e˶nBo$ $7Z}s !=4\vK$ 7~^ lNl%0Utp= aco٥5ֹ {}q(xC4:#PߎrHp =SYGg_.Uq~=.G) cOo.YBE__*"o!)"g8pp4t(ץ5[8 "`"RaoBݵG~!0UĈeH 6 _]66دǥWTǛo Q Txt6A2`OrAކ3;p ;NmGE:%|}ƥrGïwj =* Ɖ.Ǜ女 N(یNG~o>ϟ-`O%*|%#A P3:0?.}i'~ g{ԦzcdW>>б_E\\\mLh@s.J@w<W #0 /OfGi] PqŌs%7D- ^:vL.]:\\\,>r9k7Hፔ$Ym?0s)& i=\\s.ȉT"h{h_/ժ@%J_x)RM-yTOPS++ 3p೹jhE:xMiJ,}m{C\ r؟:hA[#-ơZtK_*x|K^S@9GXY1hȡ~kڿחpye=ORjy{q ֤&0oB_D6E-?3_9tUvƸn}s>Ɔ`"Z2@(D2<}lG}8\R> +|4DxBOVp-rK| zJo+-,Կnpђ y?~"fB-Y}xD„`s wF {>D-9#Ro-qOڠ}A T9#a%5Rq8n QdpE"-81$f@<}ȧ&VZAP@/یćLD* ho܌6p}|Ic>йH>?tMWtZðǍ۫-1Ԥ -p@3a0L軕0NAH|I@H/d !·cH^0ї4UaM+"׷'>&wpJjlP2`?!Ʒqaά=Fml`N." A h +jD0TێpL3D2٢1IYn}usvcQat1<̣)"o$[, e?v#w@(]ϿSS;KBBbMa DÚ JcB-4.npl6cemkaYnW_;,SCIZ/${^N%8zEK{ɚ˗B`ҳfSYzIpuBp i5mijO{fAc:Ү0]hM`WS0ɉc|ʁvɧ)gm*d&uMҚjU,W hvU@]ob9͞F=a/Z]*G~\P%^݁6MYL%~ٽ&ŶSi'pWJE(v 6bAyy@\f?kzz ?ǝG~ COT& B@DuN, fDK LS0AO&{i7% i:Jp}K)^nAGDni8q t#o!F$LF6l.}h3-}9醙?LC>8bL#Ȱ`MAPHP^c%4i%b&8y8_k2+1]`bwrГ.un7\v`s'ʇ4FawOa:9$1wb "A'w><'.܈To wb@BGxA 72@0&""vW"v8=2 x-GR0]tgC+ZBhOI԰q ]5_La:x9CXQ 'Hw0?VpZnzX/s R/`jɧ!jĚ2 N(aT֝VS^3"= @)"&rR nЕN,ŅT.A[51^uHѰምpH K(]~jٜJp81&.$@^zM 108hZChàu(ĺuwPK^ ste$#hEу(AR®J,6 Tl +k;KsŖ?.N ڵd<ւL"h@Ӎ6 N$G_w*Mg2fjglVJ$!H /Z Iu*@Sk?mվr41h{_ wWލX ӋS/eg⧼/G2Z`H@"Z:{L;cdA4o_4ҟ9% cYnuQq||k/{;OϗHoEP G:Sq_.b>g iTѬU!-Fpkxiߡ6[rOfD";a{O$yE"A\'>rIrX/Ɍp꜄$Ng'p: 3Fx-W'aϾ'tD*ƃd0pهI='C'd0I {+M %QZGBii^F᯿a ?R\m?MMg  /-p +k Y>'\IF,Ǯṇ Ets!ޏehϨuEPBܟZW$(tP:`]%ePY[=}%P;ۏ֙ZHsSo39C)$ҲpigGMwN7H쾟ڂAFzF=qeNwTopߋwZ=9YtYzNOKo]l8vN;>/ێ~xՋƄechȲ\74/B`^Jsa[}{#(-w9 qlak<75-~!E=hIZzN-=Ja~7Rn)·4 E 31AەZ{?ڱ?T7~C )Cة9éLߟ*>P~eJԞ~ ~[ɏ 4D*`(Ƽ{C3t_hhiH_쟘i1n$:A2ý %9ہk@Ah/NTŷ w=jJWŏH?|pL^6ǟF`S^|9 I!c;%ہJNhpzڷti;Q Wmڂ fz8Gs?%Kp1e mȟsĴg1^TbI*Mۻxy!(ۍm2G[Rx r8xJӮE %$Vc 2p8;Q^[IhI>8S0aJ- R7շ2N`j)F,7*C ;kg*{ڀ$O}N_+:]dRAlF*;N2^JdCu`X1ǿQN9w4{GhovK.'/EVdcJ|5)yGÆ0H t1 ן=w|A2oW>KFҶDa:С+ sp뮐#hZ硦M,=#3%alV0Y̿f rYέFktUO, KT.ma~0nL,4_h Twﯙ_yjWJiI4I6q9Cٝ—@Ӆ/aԖ54=ůiZh& )FJI6KlJ薾/JۆQ~/z[~eHt+˴1XTʶ6-{ SRd8n]MCm`Acz.(x8=/O(b)w[EƆSD$yKrcoIxeHy4}QbvEB7AJ%a "u<:B:"tB )H3ᜃ4L" Skې3Gv5,+yq E6+W'x49q E$RQig&PC8"?h{ۦeP=?pc@> xV8M~i{ˬpK|^Zԏܘ1!tԑ\xlcƗ:xöf;`jIۍ y3 E;DJPl`%@/b+4G/=,TE?le思l& %V&JbL%k~;4퀾+\J DnwC bu.Ȃ@҃Mcp_ -v$=L"Bf$=jlXU#PB:U"I`ۼIfIN=묦4A 4"  V]:;6.K.t{h~L2TREEw4vx ~d gEM7>^@ G*y7ylm(D?{* }I'@(/z(a*2"xdJG/ҮnͪdFⅿnlbCE1%쨨j> lGC7`{ Q2ET8l8r`*Kt l-8SUE `=3oLgȆ-JȁgaBVlM9x"Qhr(!x㥄I`2T<)"P!D_fg ,8wAܝXCm7tb"R1 X\ @iU(!B.uY.ʢI1=lU=E9lp,l-1 S;(&6(%c\#xPDIt#-YԪX/`^>'>Ƭ]\(n %b%ߓ8'J-"K 3Q#١ItcnOkۭ++ Q+a,RU>18yt7d? "Q,\Y44>D՘rfqZ<"B3` ~^y\Գ$@ ~ND!C˚iTmdO?2`ִ}T>`lQj e;tT !ށ?~&1!?mX5]z)?. Ci$eR,hlHZm 7rڨrju;v)ҵI\ڥ%9iQ઩N7? `( 2+z =]fQA>O_> ;qC*W.X]va7)"(ԭdsSc5pD(2uU$ n){VX ic hB,7HO׾pϑ/hۂ[[|myv@ wfRih$8.}kFܰʘGHd9-9f"=?}ˠ3ykK@O[? R=MpIm ~T+ՁvA*rG8d䡹ӮyėHEZ(ۦd(sy5$xKQwtӼQWnD* %+ w(Z%)*W R~X!#r1YT+ Xƌg0Ie?ݡx>A6 Z -9~h ϒW=[^-!'5^)ZvеHgGp9Nz{lXMkrnm|lⓘWUmN#xaU}Q:9Yw*vΨSLZy{W[j5KClՇmk;o+̧!Cu3bx+jWm;GϢS{[cע#k -|g1ڜh1pD)?\NS+YD%[Ovͮ~+]n#O˵rt;tz棩֙uifܽiNMC>cFM׋%Pu_C74)r_?1X9J0y 骹Ɇܚ/;ru^ ~A{m%t]PSJS:#@~M@T'u{m%˛E]󦧶,uo[aQ/çMJ r~d%_)2M>ڍg8T]vD~ 9Nj,7~=RJ}HM@?SȼTmL-KgƪRJ<ŤBche_8*q=/$mAe*YtViGETv=*˩T+|99*oN3)Bn%XpW$'^э܋6V&3Iqp6c|Y a}CYpy ![9+}*dۜJaB.g#+Va3gBRՒ3^ J;83,Uj<sm ?4O鲔_Z!o .2J s{,THsC 6kVHoUn[|nCBS `*ܑE_5$P驮?"f~2 Y״:msj{[Q(ׁ:Kk@W5~\LZ&#,on~7:cMKfCfX0YJ_gMkWĿ͇O*GB>h* ?5poGwO?Pt U`߿nz G_ fztpo=Hxl֭½_ 5*?+U,PR5Q]]ܚT^sD+2 : g.E=KW^}Uٺ Iu wo gx-~%N핪M]J &*GcY )jJB5k?[ OGʏOt|rAcHY8Q *e$>}7q8_Z$=tٝ))G%r uUT./5SgVw騤eI!õ5_K3^B\G");qri P!"e7-`ݩ']Tt ԛ_un')]N0L](G`]Q 8%tg; e+~.=mΪ;ҦS!ggӰeM}2t(WZ-U OAQfͰ)%7l-*$]3\nS/+=6|zMuf6@b z /Lo^zhcA|IǓEJP0Pw•t5nNy $MݜW=]j_w_(Ìu;ʴŐ6ӓ_#%|qt(" os>^̙b =*(>aQsH5nWPj'WD7i~YA)ǑR ;_yih`qwEMP-wI6 (H^{Q vhAALD*r#j)cQ <#7~XVp uZ7Pd6d|R~PK8a)büh"S# L.jE{jLTY)WǑJ~B10YM(3ӽ21ƪUKG}% My0z(5ɨrnI9|/D*X 3R;ԃNL+~[2:|)?q|dr lР|CD*ܓb͓Ȣ< 5;Z "1+-Yg Rj#Y 72,_i?^v1fK6/@$O°b)TĒGkuQþMxeIH2FL$?fny`-sp|Œ雟nsƸx&3C/H^in;裛m ~OTć#?W؇ 7cB4maX>kf/\#ю}b!0ˆM:ѐg]ڧBfҏR%,&GG w`H"ד D[=}s@L$3h[Աff#|?kK9J\tgpҡe`Z@"IZ VqΉ u$ Wb": 33:#!8 UFJP+o 2 2*%waHp&"_YIAULA+$'k'/Tuz2^unfaNi'bT.Z4!w&tcJU|.y#wH'+ږc$Xsz.xeg4hKGӊLJ^^YC92 ( @oNď@)!nrJظ݅އRf+yEy-f&y W/ń)b1Lm@0!ueu T {9(14;M,gfT,OWSFh2J+8Dy/dot۰}P>2]|r2@1KL-&a 3=Vf#~l\*6–dg>cv~M$,23R281e~hxKRܒ\4Lej0/4!3:.&ģN4T핔4h u~(=`FȇQxiNMm³YT{*FrLX3} 9+(f?旍#Ӊc +A;M7*.n$a:I#a M̔୙P ߂I9Å6{~6` N9 M)q h.o\QYA%Ջ05f:X3Cb9 h$´3PӍ03eFx&c`4OԊX2ݰ{% ({t dN_柣9 @w<'.uD*|;& D*<"&g"RqWr &Hg$A5!g:3S 1~}WL7#i&^0JaeRJAfX'0pc,cR^J5}}P(xO C6#y#p}gX>t3|e~((9)E3, YCڇB<H䨎%Prg;C>~ѹZ3K>f:Զ}r|h9#a nIEQL6Ōd8uD7}i %C GA3ohzJ##=֦ ?@g~U|˰CT:b]<0(B (uzr;EcsU3ceGM6#~CJфG$! I^Hb#~p Zj.Y6ڣT4DTzeV~'f^ZL|oPQbkH9aCaeC!.QFl CJ)߆ OȉG5KE6ہǁF99rF({z<)i:$M=ŋe)Z׿BִOr9fj42@ +mkI ;o&ENBoKԲO* 6_A/EsPvW ͕hԄ!}@]fRrq#Ra>'!RM Ty@9шmQO~ʇPϴSyGm8QcZTxHɔP@vyeHE~ LfTH`"or̝k-n_YnⅣCKǰi3?(%>"\c}rΔJ:)+uƤc| 4EWn*%H'H+٬VB&#$-h ޴#-%YN~y"Ȧ9!5Ѵ>>J+Gn#!gJu@śAlrW=r8trC3PhD"w2!+OEҒg]^#YPm?`p{OF"V6OPL;'Dy2J6uQ>r CfR}'/(9u$$uNs =.u-H"k!*fR(+;MCuhh]+R&J/ڳ2( \UpJO]t4Ⱥ\rU Ru|Rqv8hfEc*!k(ho694?&uS.rhf[>fynIѕ4#/{iBk~%{馷%[ 3CRk|^hY^~Q2G.5uKtZOG"I9~qg/ T iX3ȟbYt!R1 A3> dɅT֔lD'Iݍڛ IBѝsvrL Rh>8 o0hE#'o193" dExIJk\!s;5P\C9iz6o7?1+WX#U<ނf ^`|^&b+)^3v@z `ʉԬLBb;rI6{mō9᩸b"=YE/4pf'bt[@Zsd7GIޏѡD+R$U?wR1ԥ"D*<~fViaF#t{u"/,'sxہbt9$C5|"?$x7zKWM\< IqIqQl!!N2C=gXY;^_BQhnD6^<Gv$ZS$R1$/U$W៝ܝ VWASs/V`~1%Vc5քZVSC93Xf;coP"#+ SD}"7L*P^uUrFfDvpSx-fMvځO Υ|`Ia9¿~A5ec \[uaj ՟iq I c^>ذ!*^ mbJ$}8 ~XBJs1VZ?˱rrմ84of~H(aӸR j:$u5(cJ^c`MA 4㐣 6rIE,ńE` 7ӲΏtp&JN\RQ#է<#E4Y7cyw#1`ФLI(B4pB˄i$>dHs _QELYf lXæ-*frxK0n_z1@H:A8SCTtC0n~d__bncI%ŨtJe/NkM$fnfYŭ)qUf LX\abO72 5zyOJdNjȎ+W 2,yyGiGԬJ*Zk쒠t\R&_FZHT8Hrpe/x0T64m*gQGsE]9TSiy  3pUTTN1 OG0MJd[\{c>C2NB̈|9x8%رLu|xM}oV5(PJnͰZI6b3&P'4d:0S_zK} zk=dKIT2x8QxWB:xsh'~ uAL5 21UoyrI2z|!jA. 74Hr1(Y>B~%-&9}g;l|R^Uo(g)i%bO%Ϫ7p )?Γ"v=|aNgɛQ把0Ɇ4կ 8Ps4GtժEZ;K-`h2{E8ZZ : vr2b%PJE BEP!Gȃ'P1dYRZBQiu_ Ä+hc~2\61˜fe=41?N8iUuc;02ѭwʊJNb"ኸ+y 31dXJf cCNpX>5VXӧWt͠'RwJ ASm5BH2E 4RW$L/?qX*ƟUaYN9!6SqyDNl;A/ @ .AWePBbQh$!1\GdP5(R-E!@s7||Xnv!fjVc*+phE]A^RRݘA#NLR4K oiq)A(OIp}P$DTnЈmn:Ƨ[Ҵ==99"D- J!3~)֖<[ۢ Mn>yzfRzןtw;q׍Vsu1G8!d݆ӽBYoLM_Vx!&?b>h"xo,Gi>W*!ԚD2D8d$O+E5c&]$>Z'4G} FV7zٰT05(@$])9ɍ(uBz7KM8ͧ & $2/ fʫY{ (Y6pzL>ۘPRSHzM٨,9q#C[)n7Rf@aW<ѩqA wD?]J*a7/x+mPosWb 4y E +t9E"kH!ɘ>+p!V99-`kfj:"쁍~ y=m /ռ Gld̚h4>nTէ6`D1D#reG5|Mu ;E;ghzK87g:"gB.#b}~=9X.A5w5/q7纸d$I0G()n>0O 9R+NSJK79yFZar>?r+:=IPHE9";mC:z7\Wt RϟaXga8,$'pӆ Aqa˘F6jL69*j|!|; &P%qF[ߧIZpH'te҉Wϟ܍->suꘌLRO) #`AiN'@r87J9$[(''JL!ZlU 3t>Q/Tf ȁu\N)5n.0ȓln|t!s:dGspkhVP?s˞뜾űn $SA,I4Gil|`Cl;ԬLife"")GJl}$PZlDR#5`vMՀ̢jFX/6OңNbدՑZ|3lǧܢwoԎ@ e:C6:Ie A"+B#ࠑyHµW ȇ)B1XH]6~ڗHq*zkiuW6zM >~܏#zj; j~0h3B(}*,? .*j |0o |m4B/&hnh`rWV"E7r BCvdD:iGݻk 0zJ<*'Ht*ZИw _4s8?r3E hf ExlfĉԩAчE'aD6G_*\TPj R y5$IABr-!71z#6 `tm. tT 0!}*GAX>ȝ gzH0$cr 0 H1GH{%Eq)ִmfz]< T{-SD*y1.gxpحܘ)7hwjDe4нqm#Fh<v`}ygzpYB8#"+~(M M h>W"ć.T4T_. 4OWtݳsTQ5ify0Ǝn _hAQdy^l80q9`QB_lǸ,_ =͹~>VzpF1>5/l8^ᔦ@ŠU ]i9P6 Xh^u'4ce[.z0,d]ߠ`ܾ0z/sÀ56pj'-WF.Ky`'v3{ V6;X$6gRt:ܽjtz P-3EEP#`4`ĖJ̏fxb (C VRsvK#P" /%JznN) 9PTW?ݿ{`@a_l]OC#:NR612Vo^h0F.4 H; 0{)\aԐ}! HMF3B!;-Sԏ|E-*LaA䧹 Lڗ5IW|bA 2C$8(݉ZH2C0{۬YO ?%W7` \Q:Xޭ0kg ߂'vө%P8)E:ރ8u Z)0K"(CN Pɋ-]@"X8ru";<ԡdEOQ!fpڈU5<bHC4OB>i# >Brڧ5%v0l#ˁ("a*:4 A>ޫ]tbsQAUHꦠah9qW䧪SF(YfC r+<L;jBfPܬ'IX30b7谺\V7,=n9Dq#oFAw3D P@ ?6D>560 |Aܫ#DbǴc*-@' >@QQD'F, NB,E2Lb,(ڎw9*޿+Z]6B|%i˧v*R>3D`@ӗ+I-dNPSw#M'>|z8b@9w: f{g |RgVǽoաHr59?yra~)mi۳V'b%N?JCSw(xm4z{zxmp`2@C#vEXIÖ1Ώq|qNO+?-# s ~%P{m ~:8D a?JıCii} wD*'xAsB)=y7ҼR%}# h9kX-0R{}?)L|^AzX;ڒ \y{y paH}KځUՎ?re;NO$!\y3p;ղq>`gMxv式ޯ?F]U$ş7O,wC cMeߦ !J`9O?p=PB}9OQOokp24 c!Ѓr|Aa>JDJb֤Jʤ<5y2PRk, JA WQr#˟ &} >}  ,\@7 8-Y7[/|43}A.vjD *D%4cs#=˺nZͻN)i]O>], ?Z1Xә6Ώ9 1B4h1p-h[0wjWqz5 3g)QjBrGT2JKu~К=*ؐ(1GK쫇=2&SJco"J?2.e$Jr)S=@b`*} +GIdeMZ~`y`@A|Zd,:%# O[.f(%&"QA(Q-UK?ƈɅ;Cs]GSbMί'zc +X+ L~nGIMnu0͵d7 iy_ю!pҝÙ1|3ډ4_=8,EB V_p3j&6Ԛp(h7QW/{W$7xx>zdvEFh Pda|&`, ԛ}XE]dz%xIeftr (GN<N" l?"~s۵2;`%){P30OB+7pDYݷAg+W / {h2FdT`(uH|0 i%$Zοj^PX>4xH.CnD38-ca`^^.E#hȎ}!_< FN8pۏ_$r;4Xwh~[_!f" kFBF-ˏQ;{G^i:;ayS3ƒ_):"eG7J,@#6|lEXၒPahtNWCkciaӏ"9ie^ dqg}|~^ \hA~p i ͎EѡlL|:Ӽ+t)OHa~}/̟U+g)IST20T`߿ID Z%½wAEaG<)+R6Inrm<? (ҩu8YM+QZ6kƮ"Z8{,/" t9\v#;L'_`BC?{AqnЙl/<ۨ5^/:".bSTROiQF>-_ Lvr%|3.{5xΟ o.\_YbTTӇKk$L4G9@k^qYg~[ $VZZ] %cІ}汮vڷF҂2-3Y`}Z~[.AS>bߥGiQ'lX5ϟZԒrMYH`)Chy}?A ҂nyq4Z G4XhgX r!Z /eȿS.%c,Y unNQSǣfRO[][=şc z@@-}f %v93^%80anG0$ ԜpT@KV_#K9fV{hM1[F p~ݵ@¡T19?yK=+!E}iVvE֟m[\<v@?0w0lm45{e P/l`@оZ26r;,ra%-JzX]idz^$Μ$k!f3ac_~*Je/%'mkjJ H]҂J%F`0T(u?jV0_ғ3/+#Tzd\)cӚO1#?~Gד !t.wXZcHb*o_ν6֭抑"WF=Tc6lwJ*!qc\-Ƿ-Ӿ3s4sxS'BXY" U%k`/_꼟y=0XErc|\(.ؙϐNgU4{ EgOCzTOc?FkG aS9Dr{:fp84sbc%ydVĤC,*\:jB/:ÉJnѓq<n}Z0da^rEc64Gi<+X u|<%ki;VOǁ? /nXvR(FvtGihͭ Ѱ3|'^vf%o?Iz~z{\|j$&;ٿlPI+0=tƊZWحnOӏJuyIP*\(c|!m 7ұ?vC/QG2g?7! gdۊbYRVʗ[q ʋ5%S4 F4 8npZψQM`(-b03}x J-̞cNcX$Ϳ"ayWg|G9zuqS1vʃ ]_jH CWX m}y\rs׿"xCy/~#7+9';_Ԣɒ(Ci3ʬg喝L)F-z>g{dWynM[boiZ?3WvËZNS{?|^v~3r=DcbyyWJaQ;)NkѺϼЬ O--r[wa3+s/,XƯE?>ۢ)Z~٪>te9|/% j?^p}3fsx~,Ѳ=_0xaIGހuh9l[>6z;{&Y7?V Xh)ܟSWe,` ͅ|[YfX?+>@zPcWmg),_m&Ykk 4GEh7;XgqBr7c0V_{G!pEtj]~D#DѴtXg*ᙇ=,Gs#nnIoIV ]!UȩaW<tjGY%)Pbɾ9;D!Dy|i9npo>xidkK#Ep;W@R_f8(4=P>exw*\wK r*ÝAh]1cJ+==pOs:»p/xE o-*.x7Eޚ "g?J&31>޷]chz \w|b/9ʫvtvoR2Hs4ʓ(BM̐{n(pӜs`{K%J)6uQB\픓BmWΆ?cng}*iV"ʩ]g򿝺-rm'BZ{W6OU=iHp1-\n;>8ؙZhv3u#/^W}x.|ΰ>3v팏c)%Zo% p{KyjeڰIj/e?"t"3oK'4,uZ %Ol?Ha$t'neF_EOzlkJPΩ-4UˡƗmGnzڡގ=Qi=v|uݖ?[ϟX$+kTjZIrtUr4!p>2 |;?(u5bzMpnӳ^_ʛïRW+Ds qS{]Fom~a.\,BVl]k/ 92=NjWMzrWnf%* O8TtNFHy*cȶXy0n^Kdy둶ٱnX~[\o7Wa$iOq[F0S4K#ͻOw%M4vԽGI'_|37{R-&q"\uindJ5F" c ӭNHa^$/u FcdlmEp8?fm2CۨEtV48^KuDSۓ3Ug{a)RTw ~ŽDBh[ug -ʓ<_cPJ5j5vǙSΰ풦|RiR=x5l%|aq+zYvV;_Ua K3:BKV.Iugwz>/f:M**Մn]6Quąߪ W }+1ub^#ul|b jÍYQ &\8_G &{"TnI3ok7:zmDJgݽB֝AWRXsA|}]_q얇Aqk޻LN>-NJA6uVöWGbkǎ2&w;cod<7?NΆft?mc?& пQ*:z}TtEe cs[yWuWdO{1P,q<҂?*-7/!Bb4'i=u2\K=i6s#DU+b}*\t)M({%2VBIEȻ['c@c!W% hihvFD#c\yFأD'Lg̽RK?RۦhN"c/QkftOy4&/a^G+?`J?N?M< J؋֐t'B| ą=o ˻["TJt>_J{ q׶m5b^t~;9ՓZ~nq*#NnnҫOd{Z*?BNdt-aCIW=.j%?V79xF=vmѺ]RmW@ n o27p]do.ZȂ5U5QsSǂJkE֐DCq U4S3Iv*贘aJJF@io;ͻ1P ݜ]5.;Q\moY7vɓGHJgYc n mvx<Ne8#ڨeVEEG <!O%z'V@EyOmGFv=< o'B`Es!C+ogNvcAzB)p1CC9Bd[hlLu7ovg L3IϱyVqCp PVG TTFѳB~++SVM&D9^֩FOg՛϶m [=a,Т۳'Q*'c+E ؚ}ɺ j4bݸ$=]KxZuIQa/VCyi{K Pm{z޼#ѬG+3b=o@D5lofXe:Oav3*?jyV8ٕ:nITN%֧6ӜO TxWE00 T 2fr%P=/avsOZwuJOCJN55Ahh=['a;[Ysh-FaݎHjwt17,nGR3eeJTWk)x)݉%jvƭ4 7mcʖ9! Y"@7|.Y  TWufP\)Fb8K?d`y4GqwW3*>,V"Eȝ`@2ܴpȰbg|)ax A,pa :,0"ta0o[C#T쁼M; ǁL"Q 9B&Hʕ2q~Ѵܷ g|]/jҰ8)ATj.:rXR݋2~}W3vw#~&z4B1?iq R-Z`AdWFVRI{e>u8) ԆU prwKG/gtw># #fF@u'pƞ N9~0"YEg!0"Rq'f`a;$0L +yDC:"8zÈAbЮ{Xg<'с3 e'&7 Ey2ɰzwB4B)C~#MsH7*ˁ^8"Q<"VLgBq LO4xIC"L1n:+-WFQ}?փ/ ˫`ahI'Z"$$wr{)1>/)z2K莌N4T3Gh"IÜ );W6{N t9"@ 3ndF1D*"5!F;N l<ǴN 8H stG8B ` a pqȰ|}"+o? q  ܿ' 2\Tݿ'1\ܒDZ "(JϸG ȡ"{6?>3-!撖1H;1A+ 10#I\2RnTD*IZ.iI#5cX i܁J~2O1F[Pp`a nd}H;m!FuQJ B)I0TTČytHaܿ$5T lK # Ys|=V.Hd> }([;>d;c8rXdtT\-UsGkKt>w NF"I V~gT&`FrG`om̯;G奈В&xi=́Y!"G n YZr:Y9#@$9f9;;!1쀏v ZaoSni-\5Gs|B'//m an9}v Cw[1&A+fRp{ lo}%!#ôV(K8@Hc{# $hkPA#= &gX^KJp4 Rȧ`Ă<2frAT2ma2׻>`3?!i@ӘY{(㍭8/P3N!-pĵO&7pɫ4qfNTe:`ޞ=iI|X3VBte&Ѱ\30DM~deKYh簐+dOTB7b)ܥ4b%*%#$w`t=E܀)Ӎ0JfG RpI,Z!N'p8y0ͼr%(᠕d?ܢNMpLOLZ،?ՓAdXTL?'rfo%qpˣdx-hNEr}'l cñ3[+Dq; М.EG>5\GYzJ0D^ =%h03, :4ŸKw%pj4Ta*"` ZJ0LCw]J0LGwUJ0@4=%]gVD XsdeIk?u2\܈T>xB~#{ _ʇH1tm9CZA~dZ*WMPJOP1;Gdi0U񡙗VlFRM+l\xMmP 1">$ an8HV#gJP,a.Y~,:i #KOQn+"I Qʭ2r : BQ=%aF ѣ¿L̋qxi&o~{NEIaygyJ07䂦 O\"ē HE; "bT|eptnOĄb!R={&\!/f7"#?'G$dE8%;)` g(&>oUe?ӴJ2bdtwL(Y4A8h%qdncQ?h BW_PBΘCtaJž=QA-ֹ%@d4؍JB}*d86@_pASg` S&L ݉kSþd?G[MG f " j@ZC+U"E$JrV\ؓF'0C쇴1rpq8˲ aSlHr-[pa![:zD$ "'"+; VA&A3L q!1EiaLvZXN arɔ]1!'DhCV`jcpb XTdFPh47 D%8,zK4AB,O9Dd 8ssvA' +B$A\n?&B) CY@T FE\`'\P%&+xBEE\2`K&LVddŋ=D/T@Ax1ㄧK2FX8!a\| t~D'N:LVL48 3z?j.3SV` 11d;bɾ(tK 0]Ȋ( >^EHb=B4Q)-QQP\hzX!¨ny08 .)Uc# pdɊlib >%r&#$H☁4I\**PCDW9/z+pw r3q [wjR#Ps_qCp" 9܉+ 0IM,`bpaĈNLVm%6bq1bXr,$"FB b*АHuYqH5ylb>1l(NUxgй,q?"4]ݩY2q[$Q$Sbq?ኡ~$B޷xLP Z\U%\b%H b`k\6!$1#;QJ}SK;GI% ̭bȎ , JYKw}(N"b=_f"{T,?;|i8.٤Po\ )EɊȨc / ^f{{\%(%Q%(z z.3(ddC(ǦK:49c+2􀖝aoVQmNah( V*i( h>+(f!i&mD^/ B#aw?+1p J0 Q%"3`KDf.4q%@΄ 4D{o)dtʣ&+n٤Gv4\:,7hܑ{.R#tDL9,:LV'L yM}f8X{`f4EѤqɍ#O/,1n;//?T V1"NS ¥qɍ vG/A{2dXAV8pct~(bc*sxΒ#o7]!mu';TydiE(j~^pY h.d`,GS+"S48 9ƐZD('t2hH@Æ1#0p~`,e{YD/;G]$αN`Z_/Da>xZy[bLK0@$X0bbe"<@&EweT!~gIN+l2Y!0>L0CEqNmeU|3mK2tx},2B]a['p#c" o$Z'wRW`6X1D! ԱMe ceWm\i:& 3fAOpfr(ؒ`25k/T\e1O庽%ACc( H6@K}&!F\4Av&6 /8pٸ3SF8T.eA#; )cqp1J.7@%#h&*?Ջߒ$)F6&ц2>8BKO#X ]L:͹MP\DqGK\#Yu\iy #Jn9+ 㜴ClD>V fbTTiC$@FJu$45{THF o1xlg+$9Ɋ؄%&lvrȪ;*C B%Oш&m(c$-POYI6B H;<MB)qot w`Cj$^̙>H!V`axf[Q~VOz_2ە hEy4-PK6R vBFSO#LBr50ݨB"la#?t&@)Qs>+x@Efц'Q!9T]䐇i)9-[/Fb]."@ LjM#8vE&h$~z /jт1զ %]fĈ-.[8M\uWrGT#_#8Q!2C,v}j;HЀ;/m6H a$oM]O gK66e&|A[_|#)&ɋl(78G'Kڃ) ^ ꈸ }%YQ+7)vb}&6~&32AT9P"셝fZw`HŁ/`5لWhh5b\i>qX` p(/ݰT ), _,]CTF&U}QbUJ K-yq1m2O.̞kZ V~u~ 5?^>bs#wm+|wEVc/t5_^-cㅐ=/U#<@(oӊqWL+Z:㩙$AW֢!髒ணF+J-A(f7ZpՕbL@!/oi(ҦcYQ"|uQU/U} M4"[J.I:=cKzL?_ύfŠ2U0CcMxv3*m7#r,W2iNɑ`@ qN0moCu94b=Vh` Kr G[QcC̗EGÍ2œ+Ɍ@@f=p혛ˆ `utԬ\{> яm!0_aXn =~j[{޽Gg )XNEA:Tn? &CuJ#;@%&\QLJxN?ӳԒPeWRXX3pR;!9&Ϋ9 wOM5Lq_4Y =W$"\gu'r.(4kСy^UZ&C24 2Ό-k59E~''Xƣm=H \ ]E؁(1J $Z-'}?*ѣɒ%% [ĤP 5M*́M@6oD_"&.L*r$6| }&dΓ iǴpTxH0lJ!H_:؛P >iGYdLæ> El tmKIZlChH^FPbCTPXCM"47(5HaPgEM"LpR"v#Fq,%SبWY|H;J]yuMh"S9qޘ5]Tq:RZVbIF2k9 G|qÝ oؤOf FRXgF;J׏}QT &T|n;p2ѦDIfQĒBMX Wa?G"M5_O$Li@%ˉ Rh::RJ)4x9YA:qVqd cJ2cǒTUq~iuMz\Γ T!x<=xY_Sdڤ5z.PѯS9Fj$RCj%]A番jΙ T虼NR40ʥv~=?Np#VM(_78nM%FÛj w@fkGOI$8 \CnGb^Gt]U>ss~6LY Rw g̓/6KFV4A9e4M|r9=<(8FT#7iYa"EL"[&o@Pgw2^z _"M,ZgBԛ79lF.udшKOV/ZSeeE_?p"uYE#G]-RߪYJ;I[e」͊6NW<|:Vhfu%=Zۥu9uc,.-4tɦUV8̬"œqtu^Ś%L[D#INtDD4LTrg='c P1(!p~T{섳^Þј?7זγ>8'{"\'dzD݅KQiG?TGb[VO2Հ@kFf^{_ Փ痴,Wgns/(j%ZXa]#3/ _Ѐ(]3֮[7a lڮ9nW:]h;->R}G.W j [~?.8לH.d pC;J} pՄ'Xa0{CA\`<]!sA[v:v9fU"KE5nn)jiwL㭜E؏e1S&I8m[4ʴBr[Y%--fy߼0;"ܶ$ `[H#֛ QAf;ẴfVڂPyv1veu晞8f](ix?axkIN :1L;3{u|%Tuse)זTh]%Y]A~\gi@^ly uyq,Aδ?*gq]Xp'+Ɠ l] m}!=:3*l^LCm"Oz +N+v 7#tc\BX-zU ^ȯFFΨk,!DRJDWО`^xVo~re}u.qל|ǁka(jȓ|ېBAFE\y&|6v`q;o82}O+쓿@B4QXs`oa !(GyRʘ j fR&"̮4ii:@Ǯ5WP6/K.z%zpZP5"pJLnc8c})d;5p~ԓ -m+M%A*+2 ESA7' Gr $C^^["MУTto)!+9p=y#dK<pRx9D9}y@&\JYaE-qXLj$(*E{#%[ v99{:HjIY&?^ 纪"7@fp> #;qdw5_2/:eG / )Ј  m_c^6hf}Vٻoɑq`cv6cq%q8$̜:67C;hymP1ag!J+nq.'˽nZ;"'qt:Rϋs?zbϖe>l©=mE-HZsD!C{8ׇߏaq$DJg58Ѝ39pdvZ)N|78i,z9(/i!^.?ΣjΨ_8N rr,X~@!(Á?2`ؐ&M=]G-ߐCdwVup vD.lr' >)Y+^q,8OXŔ3)Rr|mt'E+`#,@$IWO{?yB&ã|1j2Kn`ȯUmq"tll?Xؘ7;(8uz$-p2iGXB>o18"n|C 4=$A^'eO2O2āOq_O$I/8dqH$I/>Z8V 8qy^I Z_xr'vqI$I/4x&| J:IQVZb 8k"G^k"g'H^k"LNB]UƤX$n=/ i jx<=麀qy[D;Qy9[ 9>u՜eOI6;vn3H^gWՀ@dMފr%^oCTImzR8e:þcѿT b0ףˢ"̻nyADIpY4sۇ5E"~d6DkAn)'Bıƅ^P 3O1,C0җсQ-irYJ@ ;@gw5`rE: m"J:TTUhy0Ӻ0W Q&kRa>ZhkZi]ChFr[䛒~"fGET#!YMD 0ƒZS Ԣros$[cTɉT+ʻToiٺϪ!Ĩ)z:itWLT xnH^ "EC RFxM]Q9R:?@4Mh=j@C/no+R6~K8$nV?!M,F/s⧒X^xSM,F/SK,F/K}O=ء⧑X^kbOXl zMߥJ,F/5يvb1zA=ObGQ=*U^/N(j|zC {~V"X^kbLSmv?3TSA/5>7Y2-vλ1}%O'?!1xfP3PDW}3\87ճH^+p*>XK(^gE_r0V/FU^lVꊝxhxӃ2GL"}-2e"g-v 6vRJ~[,ӤNf=$.>uRdVjSyT y4b ;>#-Gﶢ{M@fɉДxnj",9q9)J~;Pk8\uDc֐KE2)E}RDrK \ޕ@8ڎ#Y8ҵ;؆D0: qƒ]m9sџ%0e߼K1ukwo3~]_ͣƟqf'5byA|ɼtECd7ք013{=' aM:*CXdi8nSK?mjg( \؜ixIFYËHm(wGC-Yg`r!3Mf9x5-Zd\’\VNdA[oh6>}׸ K(j৺R趈n>AVv$5<՝%Gbk?Fr/ ]^m唱 Dv!'Yh}|޴TSrrlGUm tG"Cw;[W*l4`SOY45fBIX˜5c0?ak)+75]V ޽Iv_p2ك7Z/Wz7-Pmq[JF%]o~CHcyD,Eh`]ʲy6m}캙81jK:Kx 5Zq$)IVPd\GBpWR=ge+l.fL 6Ϛ_n%S-E#ٛ"o@+7\eD9@ .Ͷgڶn Tnl Am;m[Ԥb6 ?,m!dװCvQQ O3qKV|9H+>_{c&0P8}m-6\ Pȫ3k JsE\,} >=jqN-1:)4uU4t ;ܣÉQc@4"[M@TfҾQpNaO9P`ͣ+(!."`O Gqt_ʏ/7;*2O:TZ.U[lR~ֺ}#zMꉟ)UH:§3Qyj)%2>R^]T;1h@ğn;EcbYdQaG[8ɋ@+@e͊4YkCA?G=Hk{>F~"uDJ=+14u|mU_,8:U*< ÜɋcL6n'i'Z,̈́?]^%ZȃSnmtR8SuAb.4毸S 3։Vjl$ūɞ߬ :w=86 iML;TNc/ qLY1`*ڷd$d'FD6:ĕh!L xd"W=v{38͍':rڬ@ӹ.?$zͶiC=^j}pD(:2̶pypo~09GAˆB\91KR \O0A-MCAQ μMDIGN:uI/k.!P5sy5 SF= f;4@`y0[ptpqGMEB@q.3 -2r@jd,DSI])097\:uHO?z1>XE#b\%^-piB,8HK'L1bƪ\Ś77;TTӐ X U>;ي>mC)f veq*L7ӂYmۜ k+[eS7ɬ, 6 -Xgtsf?;OG ^C8 8\KX%]jȉMܧ) u4`=~( 7گ)?gMzlrxes^"7%~ 79$YU7~vojI7e}σ/9,9B"2ewҶȩIZ-KSDD#֥ʫ׫{Y0ӕKv8)t> /;dNG~l2KAGėZ9#a ON).K -޴ԸYtiQ DZz+o) GOMV$k?prGmK:l$}DIܕG,''pkJ K,7Ya5b-,(EK.[=RĀ@unTxCZne`ۙVޱKw8R`fҌ#pohUH..Ad3SzvaKj)EV(f( _] D*Lڞވl=LG`&fduՔGᖤCGu-\ N?6r"@qhX;KPX .g\Y^?X<1 $^(qQ?[g`qTE"UGp鉢3HlH) '5 >n^FvVv}e<Zb &";}s}|l8*_|zZn4ycN| `8q ;Ε\3P83E|L/W)ds*/wU_PJ6pől$JX(Dvw3}ً??=[#jmh>}EmRhGt .M{z[[٥0mV/#] T~rekMSog٦|aQ4}@7q j/U2f ^ᚲUp|\gH1D8f:H0!|!OIXSO?:yy,Ify{>M`7O,$x1sHR#s2E\pzDH! \@F%hkiB'8'\3aН_A#g̣PQF? SƓ3nEQBu9$^t[Gы.hyizPU(㞮vNhA@L$"#ډJh<:H'FAmY?<(S eI\4®mkDH5\<8s+R(RB,TkFz&qm@H.u`+SךT7IZ!y !"E)eRw,bstnV3,s`BT9ظrIO"n~x'Af8´W|2tҌݶDE)6ת7n \ ry#]"ъ9 2:ȗ(r&}h2IJ`NɝRk<"iDvfpCָCD!LG p:up^+<tMzMD&gm]7!H` 6;f>692&.4p)FAT8j_yPc|b]W.(OwcXPski!Jc40 -CƨƢaWH@ f׬ '[-b !IXy'NTcyg`%^\Uۚ0Ś `xc?y[=$`?I1E86r6̪'`!zz Hid2V%ŌXH/ B#BX D<K8C=Cs,F.9\IăvLH3 7' ȍ9Mt܂G1Md"׏T9Uopa/F/Jܯ5 :,Œk*^.SW4xAej͇e/I nB;d7R1yX|DC-qa MB}ЋDlJPMEQu J*~ 2iBF'NI c6U8?cq""uEGsuXȜ aZt|;Aʒ6FC GpqBQ+t*塉f8B“"_N!%UN~94y2M֨CpH6)rCܙ ]jH7KѸ̃sPrq`rHrSD)%]y#HS_-ހܒ/T'GWc&v!) HľzƐ?>Z`JXEgQTtx;PJ! #ZY&0 B3Ci%N[S(l,NGKUUIEYC.# }CFÀƭB &#/װ8lu<VLQyH[ntGRLpxm,D/"BT$M o#EˆVo"CXA@ &5܈0K^py\y+8@o2`i dmAVQv/@)lűZMyc>;l,vnjPMwޮp[j%%4&9ћ)+Ckq_ ZZTa/kk\|Z6-+yN/6y@Dx`scotch-5.1.12b.dfsg/grf/3elt.xyz.gz0000444000175300017530000014471210656300346017223 0ustar hazelscthazelsctp0ef_3elt.xyzd|Krm-l;pF9@/ЀOJmryX@ )ɢo?f554?@EGϿ'߾(eማi9@Vۗi=KMs|F HnqZ#3G?@b&ݸᣐ%3|7r΃ͰOTH&r,|r!Iq17wL9HmCc) ~Wd9mv~"ݼ/oEKi>M{zюIlcDijܴxH>ES1{ߠ#)TQgC? \Y;ږxߟQ4(+۟hL9c폶 U!^L;2;&]$Ƶsw82f_ \ef̄N*o6Bz*s6oSV]c.ZK#:cY$u< 9`h.r^?, !vu5nd V5}V A_k z׉.?o&ܴeӦQm%[!v#6j)]Fm6jZNmZ0vY1#@OLG^iX]z^ u{{t *^b؊ %>KVt޲PF~:_yiP8]Y_#g>[D !_g]8:7Pe n^o][fg[5\'٭lD\A4̉,)DTP L܁șh7ôzaYNƵoxl"ù^svtmVh$F B^<9+wy- جy=\(eFr.)([^湐ւ18F.AauY>vUos6cl-Dl+("^"VcS>f(av}QMF: Jd.H_^l])eHeAho}:W8 UeSz}֒E?>!FڤC9^T!\Gc ^P[{ϲ>lpv@kL&1BX(OBy~%Xu]2&s?Zl ak<\;7JTwRΓ =nI9OԴQ7|crb/T^ g/#4x^hc6k9OfH/S*?kص[;Tw&!gɾХ-G/P$ƜܡepZzY~tZ~+7kīVn 6_DZV5[d[zυ/T?q>oEMmʂuKo%f0jtط1y" Ӏ'=RRaB @IŅЧ:}h*Vy@o.&HldL[El4Wr%QKFel3D}vʅ[:A҄qxH~1ٽbuc [`¹NuoL֚mYJ4$V E,kVQwFĹt1p.}o99?}s g9?z(l"Z`{a9^Z/45sQZ7)r>D^F:R~+#>s2N߉q@t;DeA"MP5$CE^FZ7АC,O}3ʸ`+6q9!4?YVun OE \8kcS u+s~ 0((uXTpHȋ-8Z,ErwTDe]6~@dQ?Gru2JM:LqxOe#k&M)V*I@XjO)!ZQ JQ[˟.M=7e$t.uԄ gqz_'zv2iȰPmn%2d221c9_:0\R1U|dQa8[Zlm#kBN.Tyx;bb+>1uUZlV~+%v[!4!Є؊NT溎X⢒(Hf2꣕ ^F̘RÝ^F>OG1L/#5&q azifBr^FBlEΚT44[NSpu٪ߊ1"k[" Zl{u[k-,C6!.:=x |I  %$lM/,G/s[!4W#8%Mmb++.vv`)B}ޘ< >7k[twq.bH2:+2#&eT[-gm.4$ hN#A/c-iQwAfFAhS/u>^F>h\]aE P՚r| 7T',9VLOA>s<J-+4pqP߳em ڋ-2,iV4~&*JZ ^lƠ(/T}-UƼ-P@e2[ 8@("!m'PlEɷKVP ">n'W.؊pS@-*-ez^%[_"Qg" IjHAF ]28$ hXډ@ m]h!dڅ>*e \f}XW⨗-]ek˖/j$tي>34 #7C ]p2EV1'BŖ惸v.Wf־Ŗ">?wq5AdѾPvL*r 5-z ^pN{Y:-l.[ic (<4Ӓ%vڲa PւS؊FBG?Pg-B͚ -,S`gKBWW!}b+!+Fʅc+ 1 -]w}PC'eP(lE qk;QDC[/[!u1,lmFtC&{_؛$[HU,D7 95[zmh^lmw%E{C\C]t9'[~owUoaz  ufkx^|R*v5t >4%; AfxlhײggÖY4gMPg,pĴy}WkAĻ``DZ6(`練l-8E9]37[: j͖A )ARZ+XfKA9y &loO$@9^P)>iwfk©\6٪Uz+fˌ7^FlzWӅ͖PQ)h)\ZP2*@k~4QPe#exNea&exEmN ߿c wlkx3Zk[Z(@X)zڦ>ۄcIZFi,ɹ M2bһȁ2v ZˈC_@Z&91d. N;;?V1g?XDZFx%0 T8޴Xqr~fkavm'ELB^gmt}vDhuNw+iCӿ>jkۿg9ilO^ L &ZFdpxت%0{i"l-#YLYm m-cC/7f7LkR#l~,K@P2zK8Jt64ݱ»Qμue\͖L~}MY͖zTc.6[J6ٲlDlfQV>Q][HHqC-W/szm-c/dan22\77-2*ɎK[F"'fPhkyDk-99`Ne>]قˁnhɎ-bNFN n-j$m`Ǻv=EpZFT]@[ˈY8D{Y:>5q#M/o-#8/VFeDY #[(WHzk5>ު,kₜ`rҽe͖_u(j14_is[>& W"يMq2f+ Z tklzf+rqHf+}PMeK@YߗOUPzS h8P*}A0uCmS;k++=Q?~ՙKdePtjUɏ}KUf+\&''DeAU݆>lh,a64Y }ؚ_O MN ! %YL,lh({{kHCƆ6[?1dk4[t6j mUB',l%omxhS# 4[96@l4[O+pefk0cSlq lDXVۄ8E8Vea W Ն'b͇5;vzCxs3iז@9Q˰u59v:\г0*"f˯P8ֻṷX&4[`@Q6i؅'Bl>^ӰЏ Ӈ-#5nh(&aWu[2S娐Xk%Vj]fN{ W%2D^Mqk"휂aex6 fKO?Ɓ!.$$Z^Ml'Z( 6[hK2ZЋr!P2ϡy lrM?ÖVR/k-CeqCAx]Fֵ9Q@bDeR^ǭeThZZfˌӥqwm|ڮe[|?,2 kkZ-19&Z] 21,92%7Ġ/` O^`ǶQqjD};8@(.m-cғ_@0+Z˰w}Zط TA;2LX2 ͖ ~wb }:t#T&k.~_8/8Z0{;ߵ0 eX@pi`yk.dZ-`[ج5+"WzÖWtA7o-cZ>0H*cb,XZF}l=?+ꜟ!Nj-ʑq~ZЇ>g z ri-蒯d:hY չkk]:o-="e~4䬵 ]Ķ=Jd6a+kͼ`;ںމZF\ɧvEf SOl |ׇe×B[˨`:xk!X# ' G~ykx$fxkauAh[r 2dka lxpɩ\ }ykbsd@F)$Pow} IזIY ͆Vmk@5BY$2r~]k2rb6鼵a(BZF 3bJ herfyk*xA@9o-#c}&⼵:9v|aI-$o-#E[ʏAƾZFV" M[(pkruC-n-jymxkY뷖FF*)[˨y 2 Nn]elh [ V5[xJAϭJ'LnV2 hֶVRW*GqIMݼ6')n[cX]wNEp{ ]EV?lu QS Ӈ }G5ClC^)|&OzLuE6[sT߻7[om j v]n70+5WCעpFQaP*O3mxŢ (xgbwGlC[ 3,<x\)뢃h .=~}.NsY͖DRbSٲɇ6ϳd4 fe+rŦDdDlQo'lN%Vu+.COoh|r!akag W̆w<.Zllh(لH zتUjòr\[+d-N~*ĶUV q5[uL m_Fud ŒܧvNY[6Cׁ*csa*caKtXvbdUj`Kj ]\*7&5B41&YU"Vڧ(K1aLO;@[:Y [;CԍUSB֯\c G%6t~rdR%k5Føȧ-!)[?ݸ*:ܾ@׎2.P|<s㸶X[/T1^XagNjC# >Ї-P>e j92xl5;K>l퟇U,2 }V^lash-| A)d cFwm,MJ2M0e侌X^(EkwexӽB*6ˬ4 N=\T?P{ B@yTtЅ{N 4xVۯ>J[lyFׁ⼸PAw[0zj5. յ73zn4)kh>4pQ_fOS7z>OՑxd7btjG5 b(~hX 8fkN!|7 2"@朖lAxC)NCt>#Q>zOxzߟ ؞crϠ}4sL%FGƸ.4zɵ aV,?\+x<U?(N֛(E147~crLܒ-nC@a= 8Фadf%8rs ;y5[bvAmlXr@fKAS lY ll.6WbYpC-}=I{a;˼w۞qi>l8wŒʼ-0dF, /hl ZY{ڎ!c(\F=a5:r4[nC㗼Hɞs GcZ1gŁzPjƷ}lVl=lr\tƥ]:hl!jOVؒ  m ~f+]G`v}·#ρ}Ł3:/ZF>uF v`Зá)IfCEJw]>iH6U&ׄ W҆&. Y 5}`_oPff-""v5[#aiߓ10#kcr:*P(֜LiK Lep%;Go4[3nM9M}e$"c@ֆ6[kN4 @:PGhܱA6[++`j%ڄZ'B-lNpϺ S-t{FImx76[O-Fʝ/lm2QOm-cC;o2jD;k{kZgEhtkPPCdZp ^+piQqjڱQkяs wAkJ]c LOhF=i-1* kjE&Yk-\<@ m⣒-/2F'.Zu; Lhu-dkVtچkFyVD3Gl-cٱ0kmCmng ]$>ae1҂(fk#Ciio) {@6[˘S{Mҙevͽ]SLel(U5M$\5C;K{DnEkZhF ۼVhQEu6|ߖ96Xe!qsVMF)V5bqԱ] oֱxTW#x{m݋*KՎ lI͛@~鴇ZJ]) c~7yS;x>ncOR2C.ZؖsgAAa`Y* whcu^qx贱͛`G=-],?-|LJ~߬t/+q.k+nEc\*[>Q߯ P4P2[mhU7G%6o86o6o19f+l d5[TySz{csp2ƾ'a샲wBҶȖk-FLݺyndzlȱTۻ1s!}xeZkarq؃d+") ϒDº0Rok\|o+a,kp*NNu\;sŒH}x['qخnefǵ~sc`ݛ[k#fyS#[YSQ4< ll6M&IیE >;b 76Q#QHllO"$%mY 5oq{hzh4wJoּ NrZ&Dmڕ|NR '+J(z:o+%=Li%6oJYm5|=Zɶv"![,? #׌b͛&ۥ;u&BN%un$%WͣxzIS п, -xy{_;ml!wys1&vmQ6P,-w;KۼYi [({ .G.`փ/lU ]ӂ߷nMm%ImRۼe:ʩ8׳+j{ N X̸,W5Z/y̓{f?8Z/)7t]&bޤqZgYߍ!AY5 wcWc.؈gchWW>ihm= ۼMሑ;y"|znww8Z/ݴzNi,J{v6K K_0.a^tc7ʚ2|,۴>FTly5z(8?]hM)W \KDԻ8jd֠&>^Bm;yr-d6o~=4<͛k_~k9:Kąu=q^RM>:x^"1&q\Cm[(CvzIڕ3{ we^"A1>PlGIIvZ/wYw'!\J6A%srF֢w3n1mo۪w(jYiF8u9kga]r uzCmGxa5:q/F%:ϾlKt _ϓdK8}ۼOl{"lwV1Z/g{+kPIcy^cۼgN%ۀY#㛣}eqnc޷y`}rFwV%vI5c5zskˤ3Fv4G%5zԵ@s4>XОoD pZ/dJ\V*5^1ZhqJm܍jJۼy.Vh^ ?~BWaXC)]#N%n;I>hϷ^!Q=^R&g;HIۼE$yQhDs=YYhb&]ۼ%/CʢJK~cUo6l,ϒK?o$d+b͡{Kjvi5h!y MAmbn wc[/ Ts.!l*l$*lf\l,ƒX~U^؇ Y"YcrvsjEB [/q[]}CFaKj#W|n%>>vԵ@f(<$ު =w5V3'|^փV0ZgH3nl6f8rjcw'ܤzI+\bf.:K&K dۏl槑oZQ>.jx& D=9[/w1͛3͛WKj*|mOM`Ia7[h{m&zɶmIP%n3"Z/qV͏K$^ o;Hۼ;=߬=}X[ܙzuu}l6KtJc፵F¼zIc qzr & g%5PcۀzI l pNId%1l[ξKbt;y:XsV>k$f}zI, ~V /a7};4o"x>T+6o:Y\~z^򋽾rhƎsrm$T4_^JZb0t^T>XIs7LNP%՜1Ĝz.jt$_[(?O<'[/ Ď%u=Xixi|[͛|NԣV%5ɹm<>[$5xgWMnXNmޒr˥#}ĸ j$duc.) _vq՗B;j?q} ůKr^ߋFn8ixָ V%9eQ8xNՍucfŚzIiޤ]ficcuc7!|Xj$Epo>j$Ō8y9H~s7?/Jcm]m!wJ1zr{.H-EɺrZ/ l+;zIzr]P\TvIbr^>+ z%ȇzIٷ]QyW%hyזR Ȧ)}6(g[/),;Wu%'t\*YŰrzɬ.rNv%76Aӹ~%b5on=Eχ[/),F)i4}ܸdycY͛4m͛ /ySѽ|͆N66oFٴKmEs,)Xa`ʴ}͛a[ >/n65oq}1Fo֭y}&-hY-IyKS;޷yKj%1|5oKxZ69c\CYּ/ck:7Mv/>Z`ξ}Ea>J%iX+|tU cxY?6.;vQwD~6b_/tl氱X)^(k Ð7o亨8dc`1ͪttW4o\7.\kyΧlV4ov]}`ǰVV4oC"N ys̭XҤ:͛c-@ߟ6oqVS^ۊγ^[$ zAl޶=H>1lޒyilR'\/ԱzSW kՠ᭎M3ۜ$BB"rqu<Fc8r=͕۞-=wo^#V69n:n ~-ۼ4h7[GʠmLؔ)WM{WA027Ruysa d=mbLF1݃|ѼŜToZۼ%6 z$}-O]f!{xx|ks :8ռs¼ۼ49 7y ݹ;7:yjYef`-ns`_^>Cni7*]"Kq+idw<]AIv%TM݅ MiD~=b۾> 8oswƪp=\Nύu3 Zy[vj8 :Z/k) 7zN z{S yiD4L{N޳͛ˤxv[8qEf8].l,!EKJP7[/pgykdЃcA=I|pr}.'Ûrcw2Kʴ knRZ/ѩL_Mwۦ8뭗{$ɞq+5zI%PY{n%{GGt7( 5>'5KJP^M!d^׵RlDY#KQ UK Ad%+6Vϝ{KZV/Z/bur}Lpϻ(p;;K ˱6}x s;Gc^b}jH':w SŒKsP/K0~!T_f!]#AZ/1^:}"^e,Tkf+tZ<[/:HKL1]wuўo7t;^ۚ7O[9F{*'#<梳I#K̃c3'4h%վr\@6oAf][dPZT箭 jmԧyqI Oo,{Ҡ#?Auz>d zIusg6j%N5k6K\}zka|9;i%)%j%#9?(md[%+x`\Z[/VF(QzWϧ&,md 0?J[/?xsaC[/41CB[/}0rSj=WE=FX~qA >-cMIzc{%~^kҶbzI ׅT(DŽ1GK[/ ~jϴ{nk'Ğ|Qc1J[/v3 3l?)`J[/+xe};empAS5S ]gTzn%{$ZIo%5.;-7Kr ̌j׵ern\Jy[Cwh޿ᤗ;O6o`&a7\}tl}cƏ#7yscB[/9?9&mK4k(Kgҙz",mʰΪ~q%HSD.]N߬x[񩕶5hzɺNŒŽRoO5ԫKjFc*/n!v?/ﭗ`>9)?Jodce ,5:qHɭe!7{uAK f ys,WPRVUBmz95כ77ΉGcyK͝N~ o%A3K\c#MF{ҽC7գq[%qcŽQ5IߘMJ8JJ-7]<,U>tUj}y.-gѼ9O [ jѼ8fc|t.7ץ0*՘ [&ͱ0aޥ`[Zc}R/k6'-P|xIAF\Zo4BAt46>TkR͂:Q4]}nч &L/aXap-` Sks/kP,~ݸ^y#X>D5>ÛM+css\amk@n]r3M{^<k 5:Z[/ٿ?XZ%}yzI}|P^ۼHQelUГlKjn^ m7MDZ/[HSY%mO/e܇7fo>'ԝ7>n><Ո_oճb]>nv:&[/X)l}ajf#>њ^RyfkiTA>o%aW nTlU&h$g?cA^|aQ;msr/ +~}z%۷ :of3Sq[s[/yl]Ts^"Ju:|s3/K[/fbM!&j~%5Xv?{^wOoϭzH%w8>+2B/>}G;ۼ}h29cBzsܩ;v>UȷV3uөχJJBχ88׸28ا6xftBۨtY=mL T;3k!oS$u5V9&վFccn_[|=MrޅwXog zx|aYc8-?Ҫ'5ռ)/m]·H~\M=0m tm! m{c4t gGЬ"j>/.Û\ ?[%rKlLݜuIׇmz&o*qÛpLq}x^!Pa\Wc!u;&!UzkbΓ6xŕnm׫Pat\%0P؇7MOO0ڛN}Fcǰkam6VxŃ38r٥Be 8^>މcI=muo6gjsMͰ];o&ʶOV<4Sm98o~:(meXc%Û姏7omz5Û/FNEccozLV؇}LWc}rmonX3xߛIwKƒnT o7.)o>y'gQ̈́㪘!$mio@8>io[$ ->2+96?ud#[^pl>s5zW)}j: |xۗ'=/c᭦ќ+q }xۦ92Fc״O>o%|ظ 2&מmۼjW7r%K^t K`|]x[/ڈ ǭԐL |_[ [z91:v7u X}j,1&XṘ;%6iҝii];EZPE`\/YU%F{f;#Tm!3C mXo5d}CK1j,Ոg y>0&[pu9۲O`=VlR>bmWSOGU ۼQM'3irsKj ![Zʧ7,݅H*i]t:X*86Np\X/7WcvRMM[uy6VÛcNhl|am;\g;+ՇAbsCvT+ !\V9D>)熚s4w u5Jwְ-|w khyt[PO?j,5QIcK&᭴ D}=܇wxx$AW s ͜Uϗ²9 W^دf|dÛq=Û7ʝx+co~6dž?YPEo.ujvM?m"U#12<KS^;dc}E<լM P+xx۾\L»ļ٧i#ު'ݱ醺r66Io1'/~]sEJy5Gp6\X ryKog¾v{(rPJgTzcQ33%!ҋ|xNyy]>BϝFcS}xFn_v Փ]+QV*\ZۼKK2J䭗6?3&筗T3yy%U/I lTy3n_o#ysePM|-u5{|x4pxL m}moc|sweMlxgbݶFV?t`qqRQ^C@![5ZˆϝzEk o[[by6:ԗ*,LJurf%EyxXSq s=/DS /E1V#(ߨzzsgc%?2z46k&!Myxo{͋?wT S:ԇsg*ycq`kk }x[f;U.ZgV f\gWcgWUEC6KP:E5o.: ۼmf=zQiÛ`QisCX^_& k^vX0{Wc1bj`Jl;KEc7'{ț7hxƳMoA[^3n!}x+M~o6y6;ȿ0ƾjw0ޒ1N~ ۶5ϊjN4JciMV8!z1 k/r)]exc?Hy359y͛۠\k*Yټ9C'Ι[М*s0vټ}Qe"o:wgJc?f>̇7URÛ-eV%|N7JmA|FcӃ8/m\<`BBwFdcު̝udj,r8A;`}6Xߛ7Twh޶I38B7ygK6ooo᭦Yr,I0}c`PsZc?@ׅbc|Lޛ^ǻ·K雵^3z͛g^9 Q<Z/D=\Щni3gZyǍmByH [r-d. [/LΑ8o5 W)=\߭zzcm{2FccrΩNn^N}Y+w쭗x5VY[/)o~^[/),i4,<ndc gU~j*ּYɦh?Xfj}޴͒{:,1ּUtr;4oPJ9yVYw'vJ/{z̺\q[ ^),[?UE?yqMX+Qkg 5N<K »`{XJ> wX5W/-1k,y{'>{D~[4o6.!oFƽ)l3L.y۴QM6>y Wm[^Kgټb*Kf2yrC΃MfYox*NU6A>!<ޗ_hk[WGSXo?5bo_V(T'1zc`r+{s\ogrWٓzxws>R' =6L]mB;oy-,IU[Cyl3=[Nk # ۼ%v޶ۆyp1~0cڭ8ΰHG.f ySUN;7Ts, 0c6oNjL??:X>Hmޜ~ywcu>@񶋰[\;j)9f,dzyN$5r-]Wcig{MoVXЅ~XwXZљ}xTdNM\PX+w3ÛpPwZ|@MR>}ySe]c;ui4Xk;HfǍ]eZ͔k5t`l|c7K^gC7g^?laRܛҼq ׎4oitÛ^cRz{v,Mz5λ=(6M) |`{+M>5Dz%:.XOW_zc^66V/`;L}פ}zI;ۼ>^捝soDž^mqz9kIgI%Z?zzI>vޡys]uBf%sb KCgh$ߛuc\[ӧ/[/&] KgVb|hĮתPǵz:t덥9m1_,Kaio4fؤjKBs߷2hoNh^b30GzU$u\ۼ-x߱d^?Ϥ>9Q!bn[a`${W?uKLhF]7ŃmD{cq!y`Ҷ^=t6|h^vz6a>Ƕot|T̫Ϭ}j zzq|YkpKLm 6[/1w=΃>p2x%OO>!`^b5Q5]nۼ9k)tc`4]N%2~,4>lr+;˚0g%iƟ_Oz^:`qazrzGe+0[/z(}8KsJ5ǵzI\yMKulť}W E,bBa^쿕t?޻&'jPû[NAvQwߡrf%um*VPO C;Z m.oql}L:Z/q!ݨFʾjlm{J^P/͛魱HZ/ql0̴mԹS,BZ/X^{'CgF CYq2[/qMG -Elfc}z,ų²^=.m|1t5Z/qSc{srXY~[/qO=|=>=ֻ҃m*\xmFyald4TciDk͛jm?̠#J/a`r'̘qʹz &K668f~[%N{0<'[/X\56UZuzT[/{ǺwhªX;XimzG ;"lK<H̝l,11Wx^)>0vcNϲmÀֶZ/X:K* 뒪wOcm; zI\7nz:^) K =UC6K$hꟀzI| :VvghF_d^ԙs6V풌WvXšjCX`+*)Bp^5kt[kuƼzI [Φ_MoKb^\~[?ȻV&W%Asn=1ΰZ/` ׶ۤ*n.Z/ 6Kb'pQj$NJ2oֹ?ׅj$֜4r/5ok)x=m.1'r^rqzI{I߷y[siml,߅2ava|w[m&5%IyoV:ۼLM gll&g6Y7]PlyAkP\uu}9j^g/C߷]2yˋ}H:E9{ -ȫXW7Sy좾3o%UtBaߤ}[/_Sɿؗ*խԋfkV%(4z<3j\;V&gۺGm$/uzIuAQhd_OQK^=6o}: i$ v P#6cv%>y|R>^>֎^3׫DlXp·W[ۼf5(%lD$먤jiFwV+;b2yށ`iR-bPZ/9dmۚ795mz;NRKZ/IErrρB蹭ԄJ"(wFZ/I]^3nhmfqw/KRO?*P:ʥq%wfa[/I9QԶ4{d/dz-S߷+*6&[/Iܷjg?sS5&|K 3ΒK]_m$=Yh\dONQ ^1^LNKxS\Tʉ^?6w,֓I%n;j=/lrZZ/I)[w \[igJ}7_q I"l`R^:hK%_W2zgζaidFgz ֘@K>>y_zɍܙI\zIaVoP*@Q\^rc^4k`ʭĝLYV4sor%j_˭T K=\7yXWwwYZmP߯ʕ辰mlYm6|4_No7o c$⼤+7o3t;x6WRnآxVV<fUzm_<<)ofr :Sy[d_`sqEޏO>lX4zcm&lEYimxE&C>1AVy{'嶆wv%Ѽ YeXhB}M" ږC,TyӋ{lޔk=%7Ջy_/ټ}fI^"ټ F듵̅kwlX+.ۚ7L%~K6o<z?N j|p:k-Ďd%z5oNF53D0ƪWƵ%_tռGk[j^jޜkts>|W&loM:okZ?e?hނfW1y,j9:HWEhK"0oE'L7u:\u4oq;4oos6o7owȃz^};?\M4a<;~1/ԹV tJcBաP NmlrxR|v\6>'k6WmXTBV6H%^WVQQZ76o{!y4ˇļx]6F{t9ե}ԃBW6crI6vkWy;r=Nmp Qy[4 u8sG>Ƽ,ǻ\4o Shk* Am޸̼geosbl\y:%lh&sV/Bw!E/T7ΝgvV=6os`2mdHr\Kf |_͛~z)ưIyxKjVÖwz rwV%C?DۼFC[/XRM-K~l{i% (z0[]Lpo^GPjmdاu>ξKS{%N%zv0~T,뿥;!v,f6A%2ò6֠ՃU1*KFM7֯>6LՌRV؟͛ۡSGT[/>'>K~#_zv9o};b]SAvI%5{ i%OpTćkd7mߛa[?nF8oγS, dvf8oJ|@S[/ٮU1K-}-i^\sU_^0[/<_3[|fQ9^CهMkd_qsް_o8Cnfqso{Q/緱}ogpN] Q]B_-9j7mKl#klY3OznSN[%5ttSP[KF~r%7O~T$=y}8DZΖ~vTf3vΉvl ʔ`G/DBv֘ |;zI,j;zIRόh.$Ûs%9^Ugu>KjHXZ/[zy35#"践^R8s :8Kj My,xv&oZ%5ȹ`kݝTc }ɠw؛ݎÛ$_u&7ʌ+~S9Q}wVxLou9'J(GΘB>->}-XzxOʠ~6|>z[WqzeOo(F~Ğkz'p/$Z%?>o6j@ε$jNgyj9#6ocVhN[kY%pkbo'-F9Dхa"o4Û(~x9𦓵IpxwN:'fSGu7S57 )^+y\w8ڠ -qxOLϲ8Y]qY/TcnqxK̫}$,'HoAVOH~sFĭ9^߱K&MٳKפ8d(&߈l#^N\%Cyjr\$-om,m:?m~jJ/Њ-oՀq^o5l=M 5_=}gm t}=g6@¯Û\Fpx1Vx_7K: AzÛr:>żÛM~،Û-ΝY蹇O~߶0w͒:J#xa?9t_85Ģ0oiSqxsu*%>+S'cZ}A5b>otoV-8<P>ol:|86>:8<%j=ζLgKhSW^G/YoF5K0>utNd ]U/QG/Yc.,^ןc[a td9*}^&0ei@K|k~EoVE=Qo}_K^G/YÌmqNF=}jأ,aw] ?z_I} %K|"xd ɶO/њ|񣗬O?hEԏ^y&xŇ=zɊNjzKV|Gm_ KV~mpA?ˏ^R9OwVXYtdQܳh #G/'(3>;~ro'2`1KQl{[D̏^"޻פt~޷y $ٞ a`YG,KTKG/oIy~u\gG/+DžaK~>^"c=~ިiQo?z%=xDD5G?zgޭPmD$?u sd%pߤ=D}%cG/fKuT,Ԃ{xSO0saFD>=06G/+Q i%ByWIqz8W"òf. k%KpoKr9qq9o~G/cjqҩou6%q7=G/osb8z|kT%#a?=ތScNqs,gӾvD m8z/]Z8z܎I6?g@?6^a̓mOdD~TP ;^\ԃ-^{x[ dp߭*Ȼg\G/Q1/dG/QfɣN1p_Dq6}_G/Q3:?fUW|ߣެ/r|5m,(Νr{xc'ÛsEso!\hr}{K4uF:zwf8z]B9DU\\.>%v}wymN÷mDuqe+XG/Գ5qҕJİvqͫ@"^bJ\fKi8wKLzT>~(5^bŪbovpX^bq9KL?=&>^b >?Rq{%7)_9^bTGP%t|%[K쓋׾L|[$`oއk%~O}RG/2 %'>^VB=*^>s8z/7|8ݾׯ/r\gG/q"z0F>zI{ħ_s%b bIy\gy-)KbXpKbqs~mނb(U6a)s-}yM7刜Û'ۛbo;xK¹R>#yAg3`oqG/G/_m yF!^>{m^R9 u;Dcs*`Ÿed%2莭"햭K->=K;p^K66)6IިKkmUTGw~gcNldc?>Q7[/Ybq^g@rH^Y:U 6x^8߾P}^+3ۼ/` j:'H=%5{xoUx[~x7AQU[ׄjl,=[=CBZŊac7Z~Ve7=ߡg6o=w.p^HOjmj:} ۼyȧWιfcK4Р7y;=6o13oh^o urIKڿ ߡUD}zɊͯ\`}ry7ӳH;^ag8_[ΉV֩/Z/Y1Sb1xc`z?^Btڮ޷Cu.q%urUxK9{"a.6of+p^"1Y#ۼ  i[[/K<Ep^RhW WoTo zx\ּlÛZ{,{xs!hrXow=o 7=Tߟۼ5q^"sZ/JXYZ/ZӷK*)w=~6ogz{:<֬6o[ds^<ƮAF%Bs {mlX1 E.Z/E>6r'a笶ozlWr]/鹱9O}zIy@˺>HT?aKu=%1_K{bd۳}okZ]~۞ |q}>ndsgElz֐L|Оodc!NO:q^ˡw^ς,oԷy{Y8:D/t6I3*}<ݛyxKzkd^WI/' ϨK[/ؠJzIIxcI3͛m%X[1ƢP{(~z+ /sc7ٸ`W8}mHzM}o1}ߡy3JgT(`Y{ /j;ŝz@Xǿ͛$|KE:bv,+}zή}sc`Tz;X'ߴJ8Ynsb@|~cwŜ] KN&=yK|߅F$?t@dao>\WKҝϗwK2&^bs d_X%wÛҜYtg^5XJ@6b(Շ2l"Q%[}7px[yи[/w$@/֢5z*٩{kҙzvք(ᬩǍ͋sǫޒ{W6<6Xߙ)Kt|uĹk< /[/),ŝt Y%:>$Ҥwh/`g+;>ZzhDzƲݷ=AJ%:Ka9=SпÛ_=ukŊwVނ{:rdMa[hsKtRݟ`{&ol61{zI5ēߡyscس[wЃ5 )6o;W! ~ߵy{'9I+X_(_c^ ٢fZ/х=cxK6vq/KtQ=^nQzag^RFaS uIk; b5Ϡۼ`s ?l,yQ՜4i]^EW_L|w&b ЮE5З;[/Q|2wh޶!e%"Qų+>7vKU{n좵#kV`YHٛN>w"5zIaYzTK |;[/Q]A1ۼ)nS@C]:Z/X7c_G7oW66o'1kl,cc;po^}=[/Qqq;4ooǶye^X56o4D ֕I6KrLǜy$ۨVpNO5knw{\38n:n9zIڠ\QMۼغ;$1wĹudX&N-Z/5sf%闹rz]6k*pjcv[݃mNk z߇7cmJx;dc)fjBj*+kaLK*cLm^RL{T=q%6T b"KzQ}ldc9$z%(X8q,`+;JsW%5X·aKl]z}-|m/[bōmdMl(GU#:W%^cu[9ԍmF\p=Kl; (66X?^J5Bըqx}qu6o2/SY%PiC5oԁٸ\I7yz^UX<׷gVKk*\|2q%U}A9zrN}mjxk~mdc=f~]0y3 6yZļz%F={4)Kr|^R%P/lf?lK6vQ߯E߬3zXM5ZX褻pZ/X#m;rAbjdckjaޜeS~f9-;'掺0Zmļz6&a_VV%+ls]*ۚ`HAb^w&roKuq|`jĶNz^Hj2^Zu=K7SZлeya!iX'p=f=`}nTZ/XԣKj%yM؏3{JXj8}W3-l%~QrKP{]6VK6gmKp=)e^8 D[]Hۼm_M̝Y8)dգcjV`-jkkīi'V%(O^ ͧV},}d]("|ȍmޖq/m ]-==WXhwUۼ Fmۇ( 5i['/:#l,1ߞ-zIaɨ^Rj5H%NܱzpiLSؗc\;X[UE%UɵpƒmgԹo2}TƢ#l{id;4rJ)l,wN]hFC%Nz޷'m?B,k >)]nΨyx58&=𖜳7αö^|Z/)}E^ܺ_7 ·q=zvy^ 9 zg^Դ6o\k$:QWK0G|u>=)ϬtF^})6^RIwqI\^N}rt>+/Rpc sg .ԟ@Z/AuIzS[ř񬻽K6+w3=+W lt^1t_gmbNo}3Yzm[zI&܃ծy-\;/C\^W^H%9-߬M& d|%T#>^RX%\66oܿ5r0[(l{rzrO6|-?:^;I%;I+x^{~=g#gK2Y_ߎ-jz$լ C%;9/r?K65:%q^Sh~9J%\E}:sMK*M:I?/ӎzI\hal\nU^`o{փcRW/;I%۪`mzKbMKMڠ^g:gml6ٌA651GVZ/wxzo'H,w֢px96Iuzިrփ?,甝zPWz^x^:`;J[/J j%U9DO[/),MyyޡyC_gU.k̓ S^;X߭kmmMä:o>)qxel\wH{^ ktO[/uqNoD]C[/GwE߬y gשw^ 5zdbJ[/tZ/8li%cM[/tQꏨDEHaLKb,^p¯$g~~Ûs!+֡n=f^^Û~e=)lpLTo3nQ 7Ŷ=^zxO}pxs ͝jS;l_`;>=2:zr_*YzIdz/h%8[zI ^/fqU\tϷ^$K 6AmS&y;).]x-|YH}^B3G/QwV޽pD?%Ju8^Xu{lK'p9zɻKŎ\j^+܌lu+9y[ףاgFu?Y\=Xs\mLmp< ͛ S0V^b(iJ=%F^+OAb^bT?d5X9zw=^]ӧ׎^mƺ:;zɳ}8M>=Ž^؇]8ǎ^Þ[(KW6(wfث}19lq%yM!(g6VͻнZ/ۂgZi{n%yYZ$Ə)'*S^m#0܇Js=@,I ǭdes>,6oc-5zI IDM`|s:̩Z/vg1wkdZ(`lcL8:{`b_Z/ONeTX^~Mc\uzIlXՃ mK&=zI.]t\s-fTg uiv H\KK*Va}sKwiAuf7%sƚtV^{ǘ_bTK[=u}r\iwZ/^oڶ^bKLndAg}z6&JAlXP mzgN_k$ê'Ѧmd;Wu ۼ֪kE'o{*K'20K {s_K c1whQZ͌^ԟ>'#AK66?S^Rh%of18Bes`'K6j-IPB)l_6K҅ul?^Nڙ sʬU1Kk$=4DֱZ%fS^m$.Z/e RLkdk2o$̛AM[/>#ׇ}᭗d**uB\m/j y۬1eୗd&nO>w]^/kr\ĸzIai[P~uv[/)-61goxAJZa׃hӖvro͚i\=ؠxSDŽ_=>Vw-m`sMy[8jټQHF7ڝ{"ټ-z&[ȉ ò^Umצ$ا,{~[Vʘt|M>}N36VAjdqНzj3saV&>;LS\yAc+:C=3uN'l󦘟zOK|5oJ6qM3w'͛ {y4oxk"4oZJfu{u<|ci,9.͛Pw]ci`YtaJf鎕WY[%fI6o\5w֖k,׎Uu7ڼ%>ya,όTw<6]Q-ڒ:On M|n6v}9ݮ<6olO;Gm56XSFwE} Ǻ&ojO u9m`N=[Pqk=_-+=7Sï%poަ|tedy6?1څmުR:XS&Ue!y[T{Vm}<-l>[KV=2[y>C`F&v5G&ѼG)`?XtwGgn+Smۺ:׵ۼO?ľ>͛&϶I"~XεWﱛhތfeų0ټUټeg{6oϼWqCcU9r6o̿(м9_U#vὙ͛!6oAqQiyBsw|˸^gCwx y)72whgr"19.9Xy 2za`ӓ/F\v3*ѭ,l󖟻 uT8ؠ"L{&~jwK;gI^W׋\£?'g`Nz^R{TRa+uQz]ixD%jĞYfkyqmv0̉}zo[ٰ/v^2'S~ 5hdcU^OOϝ}ʂI6oB5uE 3ai?⺰G^S78S>Z/?5hds6hG5o²ntش6o{fhdr &UK t^}P^2-'`9ֱ:[/65fc~KaHhd:c[[[#Z/XTvlw^N؟+Z/<|[D%ӝEjsv22;4oX7e%aw3Ϯ/};t^29WC%Ț6&YTLj/g죚}L, i&@1ĵzɺhd]qMwƚ~z.[u9 s;E%m^d?^\;Y}x\zx3a|>Z/)# Zy a&R*lFyq%LzO5F%+}LPaKV:r -S65giwK1mVc|3[/KƼX}}wV#oz`a~ 7KʚB3X%^3wKJS$(zƮgxof%{8W ǔ60y[C P_K~;ے ۼ-M)g%FB43:[/[}gmD9N6Omބzod%VK6Vh.KGpY蘆e%c{}zpyϞp|nf,1mzÔlSsYulD>9+[/Xc-5lD,S>#zF`|3[/ٷ^t0{=[/<#xBz65gKz;t^"}Js5:?\H}s3m+ud%҉98G7[/\-6o/hC槧KOvSc ^\St^%]zI5N_Kt(grMʵzI]ŽYC%:҂B35"܃lD'.mc:k׳哙c.`^Rkk/!,u,?kL_/>[/х=TϜbzlDerµz :1I=>ǟ.ˬvZ/X/G?N8L̲Uc-fb)[/%{0zrv=KOy{zR='"[5 p>Y^\Q=g6oL]3.[/]hr^N{j`7uȦmDc& K4֧vǡݎS`|k:jzIl50%[/Q\h^R0;[/IΦa Gg㻰ɳn^bDK6V(vplAI y}[/˸ΧJ2K6cC1[/y/Z/aIlļl3{4mQ|NK[rۼͅ}*U{hol6H/Zh歼*' ol_|u~m'tDּO9o,U٧m8þ7^UaX^caWU&l~f i o=Q/m\η?q1hwQMcr7ySe ykdc9dk'~c?5Wa`llm6oK"s`+={lڃmޜz/Z/K&PPia>6o- 4 ۼdbpnl6>s &Co46c\C%.fZsM}$Kx>KZE%?<7mjS^7j5yM}hlzO6˺s|{<'[/A5b^`ol,i6x^ԧ2o%d|soh77y[{_#Z/)}6o"Z>/o%5pc7IWQm>nı0ARa7\/]9Z/ӛPKq&]n-{Aa{gj%eVK3f ~ncBTSZ@9zvyECx^!/|h=_-l{(zʹ߬ 4Zx>^Vmb\Oڻ-gP:'[/٦ǖSq^RX]Jۼx^:~ ۼ%sh^gf.5mXm|QN(nҿFcfL.؇}|C.=[/WxZ/ ӿzBwagcIB{®&Rm1'Ĝ.OUgluw?,TQf`TLoyx:wK]*HI=;Tu yx*z鹇7IMqy}3w8O~ؕ4<餽YpW['zÛSMEXuVyۼ_ߞu6 wcK{sR=4; my~ X[[yv /uxw];yZ7mQ*90o9iZk^~Νmœ*ai.<8f{9fot6XZg ׃~Aw{x̿5遚;{5,[>\gޜϨ}o;b>Ev~s(3ߏ݅+-F1n-d\a-V>SѮvxI7 $~qНed-m]N=eo!*LkwKgqAm|9hd@yd?^KuvWyw̭G/k/mÎov9|K1'rd~|m#bb6݆5Lp;%ݱ#^2V.Ɏ^WznLEÛEK:ه ^2~6L{߶3ws|={x%KuuCΣ_?]';zgMuG/&qqy棿{YG/kWzM'0#oG/Vo,ovx%c7;k_^2[\}KfOiKf!= fT}>{xK>m-o_X^_ƐmzM^.#-SL޷ykwǠmy|RN:z{-K֊ZŪ;mG/kC8`gvò&6.YG/Y:+rK kD{lR=Zwތχ>^G/ fERlfdGh7TÛOK֏^R]Lͼo6_KVי'rcoE^YՓ;=gc_oD}bKf6];*,u&Kݲ^"^zĸ:zL*s7}=tly.]G/vQ_G/{߽Q0'gD}up>ŶYG/_AyEk%bPE}1㸩bԍ=e8:zش^"P\˶ZW:kb"쯻>1K$X%yKuvY?%zb;J&8z`gh`~{_u}u9:ƝKԅbW%_D\@cKghr|so|͛]B쇣:yo?أj6-ޒߣLZgml}_󏷣*i\9g}دO/Aϵ5fsoat_(B{xc.K@%OׅK4oQoWb:z%kmi؏tco~ݾK|}h:W_b͟m0"yIͦAQ^wQKo?-r%΅7yse bT|%M:^K>n=/G/q 3}o=JgnlJKt)'G/ 5W?֘%!xV+ y;zI(r|׷@mJ{S/EWu ~w_ c9zI"G^g*}-H(w84qK"M.5>礽[%IoP G/1s쉼$礼5o`}`QS}'9zIm G/I9-ߚ7gKY߉A$I?j8jr i[ ~ddriUH+ mirj&rc X?X>KfK\fص)~kdc4݌z(׺zɸ>Z[!Z/f1LmdL߳$P% GRZ/9oҋ z2YK*M|4K6HK6}Ț +OJ%4ʚ+_ۗm?'K ZzKS|%%"MKƚ0[Z/+!h$!kRmdO4YzK0ӫΝKkW6El%ØD;zI 5K66<*766o&sPgm|d؃B[/>~jJ\L܃,3ztLlPw{h%%r)%FOcY99zLgxT'E!/6\20F+dnmˌ^O6Z/]k%?8pczI͋pޛk}$I[/Xc; Sz ۼu%dOj%>}X^R#w7!jzI fEKjX +EӘ sE\&S԰zy~ViWD~h_~=P-Pq^"vp^R=틚I^RՋqm.[^l cixs[/ϪP>w6sk>TKj/eTyUK/)@L[/s`-gllzʹW}[/wq[/)E,Smc,zߵ^T&KJ|c>}_~kĖϻ~[/z_ixÛ9EjOҕ W@+grzn%~Qܬi%j>^~qi}v4Cv%M!+m924)EeKnC>/|;}gHKjYR3a'!6KbsS{[T` kmqM>/oX|v !j~7ű?ĵcul<_q+q}fgԶc_)dXwpMsNC[n6o _"Czi^4 kv%= 캱cS|s5[/ӂ{2s־:J5y%5psoIbYr%źgK[/Y5$)pF-I&%pVۭJsZsZ_{y雋oT()[\ [;\1[/-ѿy7*1ds{5 [/2nrY*~[/#a{=l^"5ەnKs/s׍'?}==q=z~j?(/Mɧ_ vc# 'nDb7vYlWg(٭܃.5tA[}'FwMp%7md9;c>S&d]76/esȫ^b O: UحT8aO;؃.ݬ~c۶_szIۭx54T[/{V'0+=%QFRJA{KpaJٓdzI3>~[/@g=lK{U*u->)JQ{{ʟLÙۇy}_sOIzfe,8}gsyvK>5/կ@υz~nLA|?kFB.[e¿E綮|jHTcýzLY%}Zo9z=Լ9x-}yzI5%.jo$̉,`?`gf5 m?+ޗdKEo9q\q<~73ϧ:~\wڙ>9|53๷dcTO(Vo>vI2w,>E;حxK/"ڭxs,76z7sU`` O?GX:zF3z_mV!sI*o߶NyLmmBB^~=:hgfkv^E\[/)l/zBĝ+~8/o]ܨ |{$͵H\{֙8̇zv8,Ϟ:I P/>..O|<&scotch-5.1.12b.dfsg/grf/bump.grf.gz0000444000175300017530000030276710656300346017251 0ustar hazelscthazelsct]d5\]wf):][||Gx1<Owh3*?xX()߻SX:a_UMYI=+'6{/\ƼS7`@k%#?(uy(n?(?>SPmRg{=:u4ϚrH}U_YG곪yӪs9TU~s=P]W?C}ۇMpz\á2>:~.ӈ^Ht7͇2:"tq|ȁqpq\|\CC \6C<p:с8ܖԀA xr< 88Եin\{6P<ҵ@88Ե@88Ե@88Ե@88Ե@88@sC][ CC CC C9 :lPPPPPPAmqpL7'/PW[aim5wC9tkrrj˂'"NUzH':W9I=|b}R# }<(5PP7P쥯g[% i,r 6W>DGs?Grќ4qh~'Gs*0Gr쏾9C}tϑ\G̞=K#M4>ϑ\|k}4h~\ŷGs$Z]%濳g3:}$lFGwlFG̞&|k}4Z>k5f |k})Z>kGϚ5=[g-^t4Z>kGs$7ZHn>}#H99+gH9_uugYe 8g?_Of?_-觎k}ƗGF#S'SG꧖ʜgjјqHj5:i1(ќ jeŷGscB En,wZ1u7bSk}4_M3Gϗ9ef/3GZgBhy9ڛ4?=9ڛ/)E>Z?gfo3GZ2E D| }45_Bi}hYkd>ҿZgfho=|4\DGZ7{߄~h_>s4kGZ6p~}hY h}VBbJg9}i\j4||vhh4V>o >磹*hh[yo}M7>>ϻxvfOhY ||gOhyśof]hY;;||݉S}Dm >ϻx=fOhyɛof]HΞ hY||-S}>}i:߉:ͷGlsoΞ+ёJfO_hy)>>kofGڑy >MO[of3GC D1hyh;>st4ϻXhn}T󼋅5{wG.>}w\ӑ=;y Ailf],|}4j>h~h1}hywG.>}w3}v5(VGc;{wGϟvN A7tc;of)%:翳|}TGwf],|}4Ms>}UK9}wh7H|}4mY>&>%:}ԣDGWzy Ae1ضgy)!l g>֩+GޭFʑv^gHך})Gw{ڳv_u4oor4=o>8?im+}H;||4s4\N9)?>kl~>}6gOhY {>}kWO{J&6g sS/#4ʦr.[ }hY||4g>}-z)面'sDYbҢw&?oz쳮G+H }fI6B{Z䠷ޙ^פ~C^q4T7߿u-dk?veK`MU~߽Α Bk? ӺO>jaɏXyՇW h6T߿.sfk;ƭ'pTZ aN R9XmZl5zTdl=z HNJY0TT~Q*[1WZ\6[m?=?6quG_.Ms55O[t6a>6Pζ!L|CA}Ayk!ּzt5n*h+?E(Z?yi`y K^dd' {u5d/zP4㝁J:AMx c}sGxR(:NB4ʉ2̎B ([Yw_0G90C Jz흆4{\0;G?{\0;)hoՃks57,} O1u];ٟB={?`AS݌.\?5~Z~vGT>vs*Q(mzNDնt0u ѹs_ݔG=nm-n\}+^ju۸hT j!YuCQ*l )fϳ3w}Vuoi߇ejׁ_bfmZvp/dkֽdy1$Z)VWs.D+O[䕁2cK6HuY\ؾ s ҰTsoÍHduɑU-DH\P1v›3.i^n4vP`G=o<>_1KnljwRU| {]Ihd!OZ|txU}s1h1UNq)|A|n.Ʈy%im׹'q_ȓRtO3WEq?NWxY? ;px:̌uA:o;6RӊZ9dPz̓ؓu{kiPiq _Nkݫc`v.QȮS|&!)p.i/kRsvɆg)*z˹g<&^th gZu8[=2 K>RmwW4Үy*"N_;[pW[{<MpӦwa*lUsP5ۜ7jjr:0{5TKnf GtZU*pVJ:05ծv ut^e}T:Ёٯ_&t`l2 l8Cfņ*cy-*,p_J:0[6ئ̚ tgÉ*I mJebMkdXyjÕ:@pf:0lǑFڥ H:4`vX#J̞m6]wT36ZЩ.37Z" VZP=gnn¬z70oo?Lꆁ+עY}pvĕcFnS px* .oC SQ p{i,e0w5{Az& ts앛s𕏕s*0~J:0G8G+l𥱨:0g8L`EЁak,rbq7f@'IP,"L,]R,*L1q3* C!ʨô㐉(Њ%P& (ŤPQ!34Ur7Ŕ P+4搓5 Bsh}cCؤ9b gI̅IЙKx|PCl(`|&Cڌ_Mx^ՆU$8ײ ҢX^M6S,^j4\襚6`"~IiiыX$T,^4-Cϼ&?!:W&K0xEDhRP( HTP)@/PnZAX4SM,K(7`P,^&ډ@/o)T'zͣ8%ЋHҩyM*<4L?uM2)@/"zH ETAXѮP 襛mAX!B7Knz E*`:jw D PzC:`@/ݔN!K?Sb ]LAX"B?hKaj b =N  X SLBx(@/PSTrzxh\CExpFFBSb "Jt !R,^D N$4%cI b "bt -aP,^LLx(@/N& :WQ,^DN(@/HpFDS( O#Ћ6rSH b }QBXț)@/"HP55db "ˆt ]HxB*c"SRm,I@ҋUI 7ܴ\ PnBXoBXb5M_K<`+P,3mA0 &:W0Mչ*U 7Edm;Ce(Kd\*΀=\)@/WܔAzLa0X\rP\Cl \CmdJ :W&7K X$*E Łr۝$ ЋQ)4AzMk0Xl"Bu@%[u!;hB@yU9tM]p1oչ*7Xt"By(KNSbC=PHsY*2T&ڊ f3<K6qP hPX(R gbŁ@mH=ML[X"k(K6Q b t#>Q,T`vCX"o 'j>"[tǁasz-_)u7"3(@OP)@c4\\d.ҋx'oj=1(@l 'BA5 F@RFs麚/&Л"hɊ8$.Ox EjyN^ S& EfP`ws <5 @Ϭ0!mmftC8ȓOso+lڟl<|G4[Li/H`KΒ[9c]7.hWYԩ{u˦s6ۮmWmi}jn,EDeiuKEzx<8 1eU.>ZC: ]_O,LSKs )Y%R@#T2=مM b 3(dTkW m kH`{^izc,.s)L0[3כدmEq|@>7ؿ O[z!~S,A''!|taXu9/JٿH(tAǡ~x_$<K*Е"z@? x@A/qԱ8Ýb RTAz)6DP,^ HL7! Ca&&UC8bQu:TL7D6 :^C\L7!:W67%Ku";:pƃb Rm$XT3nC|t1:^a<t4:n!dAKs#:[_FFzid3rX4G!yP,^ 6%?KI6& Iyl:^(aP}zd2ݠC;tK6+ u r1ѹ*iS,^0ٸ<(@/d%KwP&qKwx&L.|\n21&d@\ۈLtA ğ6#?K6$ӜŽU94O.cL~iNsUns2i li\۠LsDJD/mR9^^ۨLs .Y4;:W6,QaKCܦe/j r.q44tB? {:YZ DaSL .$ffpt!14(zF/e!16(%F<$9]H ԰t!19Ө͏Ӆ#IJ,8]<,e$gհuuQ?F>1L*O:4-_4=i{]YWz@:=>1P*ͺSg?uf]驳/|J>fj]YzC|+~1U*ͺcvf]驱| 0:=>1X7*ݺTߗjć0֏y;a+O<ܔn]ajto>k][Wz;|Ʈҭ+=5Z~cW֕ǀ-߱tJOc–UuU[>dWTӠu8k]abqյ0N5 zXWzj_sî2+=5A[~bW֕Ǥ] JO}c.Lu1k@ua0 z+L}ĩA?F8#Ǻ¬,T豮00N5B[Wzjwa:XWzj#waBXWzj3waJXWzjCwaRXWzjSwaZZW/ ׺ߗjk]a1829z+LOL1|&Iu~1}Iuƾ1~&J'.;2pz|c+՟u/9g]a1_0?1 _ ˀN5ŃYWM_Lb_g]iʾ1}՟u-8>SXW %s9 ?&q0 ]eN}YWF /4˺ĤRM+H2SM+1?qEºҎc@XESXWLvȉ=T/J[ǎ#9 W03׮z[Wo_1b(L1+$G\.{Arz\.)Q]viО \nStM1/ fs43 se5V܀語\? s])w ]$)+2SM^'@I8eXlZ> ZW{5pA"Vv)?4egAt{" :n[ ay^$=/u+n{msֿ@ºy%:=bq Jϋ#ľø]T-*m]\)L5sFMĀUlC|,6NV;2a߅c,*|)຾ Yy:+@ ϫ rw9? Vv/ewM=Rqݻn_NuA[2~AB e2l ǔp%0F_pj:KL XQ ]yl$DU.EgzP{"ʧaXvưz'0-t?+Յ?QrsHRكʴs'49Ht-by4gÎh C*Y9nݷ͍ndF($H@?Ľ9Xq嵲C/xzY_<~RpZN!̃ ^HIFHAGTn8*˦D? 4oKK(s$lF+T7(IBo ]k3?pZ?q?^*)P8]+ ')7T\& >y%/ja%ճ#Bb,gz`=/QRd%t)xa2o&`f%l@+Y¼TZɏ{ZIE}ke=@gZon,ZD}a)x, 1[)@k>|Nɵrl1?OKrmk*r[nNص2pi0ňsq>Fg"{lOzBOMMg‡|a]Ę0Z>Fƫs5<^"ۨ^❐,ɓ[BKRlI"&=$ ' [hTo'eF[=ȝ` NjI#`وQY@ǕAZn4G$c+k 9V>;$V$')$nՈu iV1uקFq٨kRrt2HYȆx_#GFwՀId2_>e9F<;VV$|l-k~ble0S\f@ux- CcgKŕH_'K#Ӡ ji$)ЊAYyЪsdh @:vHXΧ ؙBn:v: >)lhi:Vn f߽u1ڠVpB"{w_-@Ѐu%ޓ$tmapu ٻ8\@ºjflfdmpBFI4@w\Dpe`%\.[Jr$uHXWpsB xq:E5ąr`pĆrpćr:z_A>nkq* XWԸ"Q" ؈#L-: fGH[kJ( _kJ ) ckJ) gkj $+xR{1Tq0TQzI'8H[uE $-: p֕8Sp֕XSp֕&pWА0N]Pi"@Pi"HG ej 6MD$.: $NfG\ kJv kJSv kû8adG+H] XW ccQ8=AFVc''GZ#2zqE$( &n +[$Ѳ%@+"[$Ѷ%@+2H(\# :Vt5}Vиs=K"v' G_@ X$ am!saz 5$.\Oe뷨`@ㅴu-2A8e+Hh]عšE$.\c$jv.D ;Ysz"ޅ!9=QE֜"!xarhkN_E>E S\Š2.Ǻvi$wE0 ceŠb +Ix^x:J+h&!ta6slWXM6l|KJ%?ӵ&δ-XCu:kh$}tWMTXQN„xڮ"Q]aE; 3ckŠx4Gv$/Li +I_mV009+(aPsmWXQPÝQ]aEB A^QaEC  5VDp09V+(a=(b:osgB׵dH3|$a~yѿ]aEJ / #}ŠfHM%{D5%0tITXSர!;}Š +JXbV$İ=^1O40Ű9:+*=(٫(m1͈Pn*׌8(+'**aa܋9 +J8cX +JXcJۜ32ksg׵YgD1$ԯ{u%%{UL{j8sg/I^KGK9ՃŠكŠكŠ&ك*6d vm&y93\4bAr%#?S棡NQA^_GU ̼%{E%̲%{E%ܲ%{Um x73ITDn A^iUĮN#%'uDp A^m_?Q\2{PI{v9jΑWb1'~ 3.ku 돩Wm&/)?^\i%Kgrԝ3ej H3iڌ$a6voD9Աyk?GhiveGukik[WX_@׮"V^G59l H3,$aJvo~„d?dusP 'YBZU'yA%&%{A)&%{A-&46_?6IXrmf[LAwB h'Kd^T6ڷe6p~&FElNZMH; $avxi0x=^ zIN/zTk?!_ìc350'?UӞoS~J?܏zYLN'b O P†Pk O* I.Evse1%(m6c|WD{~E<H\ d?X͉L@X1wK ϳPϣaHyy4 IóPϣaHg>a/vTB_,|RhgG÷?T *Ͻ>0$nȥRק~Sŭdžy ڇ֙pX _cjI0H~$Lt ǔJ'(EO{OX^E$Zb S%uH\/3>Uw Vv))} rdsY׭O6>7dk8\ w_l\&sٔ†.ˡnuKy/ɡ}f]kUaJ^6Eza.b X$7vZJI=ae "'yЭr#AVGS8 [8y8\6rz5r5< 4_\\TBaJk_bdw<g6*(V"H *mWJ F̥U]tջo6^V)Ƨ5_}rM_OksgcU]k2]7'S ׉9KIؽg6ny #a{O8^'['(F"W}恾H.h7N*C $}r.RUo +Kb㽃߮e"׍_%yO>9ZF|juR3^߃vǞ7[.tnJ%o 3Z79пQ`9ȟ:GHXʜ6axmE?.EzWLiSGY/Wqkl+|2{ ?No\z3 ّxwi Ɓ(Au"3`ȩzjqBrEEBNꍷ_OrkZҎHu'ld]qlH7VU6VOk{^Ud ڱ6?8wUJVrZe7{HoFt:v Ul[Vq{:+AN2lhG^o?mͬZݻgC]D6W'iuUVϦA˻UX{ab)VRi+B"_xB/my+B,Pv)I4D6)}X:9<>1~Kj_8!N+1lz\4x߸Byn݉NřDvTȲrKiO-p$(ccԿRNNjE\vvRku am.Q%>Lގ;d=;zu~](Ք\LUmd/P Naw ɥM Mg{DI؟55󳽒Nyd]8E3,%,vz9\M#-_@oq^W| ԯolWc_|ƽ~7H"[]-~ R'^׆nMUu~?Lkr˵$P^+;QI/UIk𺝵DM?a/ e$?i[S/a-'q_j>uYď]'s%r{_P';TձBw7Majt =2Y}y_oJP<½o6)uRK$ϰ}$?vCCT7=Il~ڝd:ɮcCI$ $xk oC׮@߆M"pN6$al(^HwC~$ sp!nT6A8ɋo ŃIXw6/$am(~ܤS$oC@߆IX77$oC~PN2olJts'cC龁$ ūdm(~HP<vw oC&)='Y$am(ި E5:ɋ!{yy@߆]$ ׻IXw6o$c&v|/ߗ -WlA)Kgh׵9?v:'M8+ݕI\Ư˂$nIiaeAx9i-,H'ݖIy nv]$1NsaeA示 {]؁YR^؅YN̂$?Tb$ad %IX.)0,HIa/fAK {1 P]a؋Ygս CW#a؋v{^0,HCuIa/fAKJ {1 P]bUYX<TF?Tve$a9xdYuU:V XuɁaW_'IX.)0,Hsîʂ$TWa ?uchH>N2 {1 ^̂$]^ ]#ܞWJ {1Dub؋Vs:}b؋xoc؋YDד^̂$|P]c؋YO'=oh1d؋Y"^̂$_]^~Q]d؋Y(^̂$|ʰ)<y%˰ )&Y9p{^2Ŭ-o'aF ḧk]?NҌx1sfċ/Hߓ8#^yΈ3!`^ϟgċ 0TX3Lg*b&A3V x1> +F %zLF#^đy=J/f"ɼ?Sa҈3d^ϟ]^ШFGTX4L|RFL}=*.b80oWޥKJ^DDn$o/嗡i"@R ~+qpSMx7|(lgWJɸ YP)1eŨhN՘'{mpy(HIo|>xRI%NOHȠ;mU5>~62V\T*Nz`\+(zmOf~R K/o9+NR? kY$̴DLuYܱ2; u{q7X\̌rʋ3A~;;FO=x⎮I뺳kWugq׀$py]wwHugq7$O*/IX^ם]S'}^ktst{;;F'?⎮I뺳kWugq׀$?IX^ם~Wyq&H,:u^ܽtNZnw/]֟ugqGuY5:iy]wwtM ,uYu 뺳@O*/IX^ם]S'|΋NZnŝgŝWeqVuWeqV}Weq,Tѫ8ӂvF*UYix;S#v,δ` ;zUgZ0H*3(PaG⬺{WeqVI뺳kt,;;N^֟ugq׀$?IX^ם~WeqVey]wwtM?ktstùݝ;;F'?⎮I뺳kmy]ww H,:uY 'zUgN֟ugqGn/ ]֟[]kt,;;F'?⎮,u]!FWYT'pTT1޽$W_3緖d^i|E (*QYRUAtǒpJp8(K1KºeH_/ ^qiZn?qxۥR ZIAY䵔W@'^WvT+guOuyݱB=d~xȺ}zQ׺3>zb:6C&N'_fխuˬPTB~>UuEtYN-Y?̪,.tX?&=> $g%؟tx[?2k}uti>=+Sӡ,L=7c6ƂPK_ ^u%M}-kH·~*3E J1&=)-0%lލ%0R(#cVe>`2g] +hpQGߎP uR7mj䃿cwU~]Z`H޼N`.]D/Wyow6QYKk?krX~r]Қl!`ݦzꖅ7)Grd>y3Cs|#5T5 @+F ~qRl@@eV ׂV$!WX*oT\BZCDFN#)^\ťPZܵ.5 -fuRm`VoqAK3oqAKk^\jHwqAmIRa'0A][5.Ax r-Zj7 w-Kk^\j\AXj\AXj\AXj\ZZܵEP@-wm oqAKk^\Z ⮅V5ȵkƥk&Uff0 ;bi,T86K\+ `ָH7N2k?4!5p-*Ard5hkVV#_ܵEPC"wm~AfmZjA5[ŭ;T3?K]*,2_rlL45 n3T>x|/ǮxVn>|ʧm-pX5ÜkVe^4]MO\(fU-H w@Jy}_2s{AvtO4#f^ZuAM44.8FlyUEN MU')3iwn%r9)Guڦ-L&hV` Ms~ưuM_eA֬f)| 6q[xmYc0%c箽 )43[ ݊P4YSgYMhui߭)_nC[KR"&zU]EW \x8|I߹V5tφ.J45R5/qwqq϶J`;!6M۵^r;LΙu+cmՠ/MqHu!h5]WT? UCN{Yr;n2)c($?  $rݺN=q{z*8 +@oC \G)y"37t)xؽ^+ÎcDBK^ŷ=Ǎ *]TqG؏kt\E_7Xrv/Nn$t<.~K5b >.'YoY%P~2*ܣv xTIx|GuՐzTR ܿ}WƇ٢0ߐko?pEozJmtLpxLT?+`6Q B _u|Siw<їZN˓Iy\N˓I$;OC,cj:$d< o9/OrEdOrX<$ghd< ̗'y$o@r2'y<?R .q5I}%mH`|J~!x|tJv5\d޶!qT/:U[l c*e'ux=N1(x;N1(x?N1(8N1(=//ːி=N1kmn ]ېP$<~wmlCBݵg﮽ېЁ$<~!aIx|W?N1("8N1(~~_!C??Z]]xR]ܵ 7mH(@֟6!IXڳ HsmH@֟ې0$'m(x>إik1d`o^N\Q{n$.A6r ڽ((uHFu HHϏ@_g{>:F 4=ۯlSD?ٞn.!`Ueo@֟kpJtWu7x9N{}K;YnjCE u >{{yķ/|qg'pl"  ?{w $a7 ??H'q@_'w =qGfmwxT;֟=;<Ϟq_viT#T?HCqh@֟<3E`LL1$ޏ|!v/*l'8C(TNqP 8SX?q$ǙIXq@֟/})Kg$aǙbIX'8C(֟3"a;Saۙսϗ>7Kg$aǙIXqh@֟/}):Kg$a=8ΓCg[W~ۙBѾ֟/)tm~-q$?_8S ϗ>H3E|Lс$?_8S >զ8Shw'8C}L3DcKg LCZDz]}LAZDzǙ4ۥǙ4ۥǙ5H/})e'8C.~Ǚ5H3/Y՗MkW_8Sд}3MkW_8S4|LA 3MkW_8S >Μqi j?Lќy~_}Lќ شǙ5H/})hAZqiiǙ1Xq@ݏ|!y;+,'8C(-֟3F@'rfK/gn|?GCJޙ"*-IXhţZI-vH}ZzzS_~oH{|OGg]qRݵgǜt6^6w_w=/TvIWjURKxgARxk o? $8ۭBWGW2!/{LT_DIxmWEFz1!Hwxm8cBD7=&Id|'tMy .◐.vP$2 ᅴ#I%m;SHI?N#34G*.n~|'x0MԑP7h,h?4X6Ϟ_A2HWJYsΑ^ZvGU[%%徕4v5H81S`"?=ɢCnJV"%ܼkIؼwj㻥G͙H^v)@˕n+ m¥E"?1w 4m>N> sF,˝p! Ij|j7JQ Olfc Wk&6 IBW4v5NrBzz'O'ʪ.J(M^oir.%9O᧖^J[9KID%Wҏ=5gqV%r vVm"-5׿3"^ƚ\i\OL(uxÂ^Ocu:6L[wlE5냿 `lPîZPopb+}VbbNur2$#Z>@4a0RagHp;YBq_WXYw}Ýֺqg8 wV@tNVne Br2.Z >A'mv'edX>A'r2p+g8 P  (Ywcttcw,2r2p E C<;o/#;'v tkQ*,w,;an}ÝXA>NX,nB^FmTXk`*,w,oW2SΜ,Y.KU^❟G)*f3_*iNdm GvI>Mrn]UB~~k~ZGs7ڃ@YG}ËJ?; ,*Nc Y?!*UYֲ`=,hB eAB քF}V͉?t$J%R )~'N~'Sm"'j;isRG{I=b}hHU *ևր$?X>Zb}hH{IZ>p#Tӈg*ap#֟zl>j9@TIXP>| $aAG@>~O6܈i3k 7b|Gi~h7e:IKB{x'i^v)>Q_k9wyo[ݞf]Uߩߏ;zbF*,O39\7KZT3]h%v/K2RN{+jvIXfM5+@֏YbmS*D1^;zb>uM5l|!?;}q9^j?4؏O{f;{f8.wPx~븳jqgՌ@w;];{fTyUzC5#J"wP͠?lwP͂㸳j39\aj39\aj39\aj39\aj39\aj39\aj39\aO39\ao*}"WN-V] s+|41w?4ˍ~kݡpWX̡pWX̡pWX̡pWX̡pWX̡pWX̡pWX̡pWX̡pWXpW8>lpW(} ƮE֏rj0/c2T61 xtR 9T5!ZyQ~.p&zE0I]LU$aB%LRSIZa~4 +]Z)E~tH{-&G6U͸#۶B&H" l ?T5A~ "/X` l ?f6խIf]V$Խ7խI[6խI T5A~`%$j$|KH`SՊ3OH`SՌ/,6UMѯY`Mu+@֯Y`צU !uMuk@֯CMu@/,6UMT5A/,6UMzB&Hcj @pVH`SM0 췩n2Il>!MU3'涭 h l n m6UM;05j椌9!}Mpx+>ml~$ql~$Q-{" H>7IXׇf l~$a]$CpAs}n6?6 g6A! H?7IXf l~$a$CpAwn6?A! h o! H+$! H+$! H+$!y[W>mx>إh֟YZ_Fgz^2Z\ե7Z?lgCK% Jᅱ )Z.]--1QN]I׾R 6sqn]?Ff+^$szO xjd,O7~J>5|7$G/tC.&BOw zjnWtCAצy{'`B\Ӈ\;qii jOZv+}e>4G W{J6 jIX?Tir+=[' wkIH 4 p-&4n(VJ4n(VJ 4n(VJ 4n(VoCzPUJȧqCz<@߆b4Ol`׃|7dӸX=*%ӸX=*%ӸX=*%ӸX=*%ӸX= AU)! IXՃRB>Ճ]iܐl}ObObObO߆b۱X= AU)! IXՃRMcC J 4n`AU)TgCzPB8oFvǪ@fC9&]B +N.Hq)YWR(Ip+1I\O̹R }pN27* ͷfUpcn|uVVru df;hq(mv.mg]q$fl*{#b诊ZZ nB>Wfb譄h}~#lZ}|8WUU*qKd|ƻ$L/W_ӫSq\~mHgNz)DeQ߲v >:2M7g"/RXzDPج3.%WsP?\x bBrjRu*3ZuAXl-O@v+g9Vߵh3_7{F.gU,6N-k2XWļ}_R1U*O?" =z~SKpRx(&kCE r-7E Ac.(:"uˏcҮoŇ S:!2Ofާ$ote<ՋR POž -B\ )mB`Dw|}i:6ĥ/N! ''i Mo'dRCN |dgRNictf*)z`J\6~V4EUϊ͚*qY>O.J\r)WEl>NX l,bq ƪU`g[S0V%?}*qYVU"z`J6~8cU|eYVTag[SXWEl>NX_6~8cU|eYVUag[S0VWEl>NX_6~8cUxl,bq ƪYVUag[S0VWEl>NX_6~8cU|eYVUag[S0VWEl>NX_6~8cU|eYVUag[S0VWEl>NX_6~8cU|eYV/v `g[Պl_V^YY <6qԋՂ VjX.WF {+Vw$X.$Iaz*H[CՊhdu^ Зz"e ?|Dv}b-DgȥS/Y1:7kI'yf%y hYfT~ 4 ԐjIHI^8Vq-JH h2h)Lx!G*Hωh =#$oN4DHI׉h o'y$QN4DDIXhgf 9J%$ ; IXٌB?}e&hw&]ohcкIWCRDh_ܫkT6N =ivj˵6vYQƙ]殽Vw~K\hDKs2 ^ѶV44ch[ U]!hm<#oB%YFp\+n W?IK&H";<UVܲmj0[ª=MWȴ3}O+?CcpXuVּ4?]$[bm :!j{=v1/8-:SP<n,I2e &M.楘aTyH IzONlP!4n,T!IkP~ny.3- w;"kЉxq9%߸K˽K榤:(C̏B4ct>&zAѭ}ij΋ʲZ8agT\h]$ \xPσF+OjIHcUq'f!DS\?xK Ѫ|Yf VʵǿvZ;E ::d*WaZ_g3»M ѵq)j袪K-RfiVo w߮ cIȊ0 tkCoȦ >& hZaCvq|VHAs-M0,L}3ּ~V|Ŀ'Z7r%|)Pf |Z$ͩ2j$F&uz3NM4z%")|Zw|v]x[~Ƕ3~Wa,-j=mZ0WQ8҄'aVР#~ut\2P[L 36 _U!l@\} &}>UUEƧU 5\RCa|bA{&5! Bww%9= pJ3=pr߹ -Ԉ q9t˪w[uAVb=\k{}Weh/';<ߨ/f‰G}&IABmL!dlT"V 2YLͪZ4ڐq30b:MV+Vu7^<5~b.y]l(ͷNNپߣL*RZk; ӡVK5ヷ[5%'YI "dzN܉xeM@!әZ^iy1@ ~~az)T8~f)uqi*,Q*A#x=~aU>>| St VyrYL1.M@6.N#wW\dᦞ-:/$4d匭Vlũ]L[t[Ws&z'NHwt?\_6bȾRqۊ3 \nRkg]$JW- 5Ԕhq-tUd]8\wkպ I+PV.Hr"peU_VxUWɪ\c}Z+djwRkZZ dm +%Hx] Tϝ CUe/Nh>Nuzyj -=vq9khE,no?0=5qྫ4S~b.7("KМ2[LA\.ZS& l- ;\a;lQQhP*~A n΋F ohx| "x1ԅzmrQmҴ jC>2yh0RMnR- w[2>'~]AzuO?B{Wxbu! Fj dWOD}T.hؙ$mcL4gD]L$g*ۉ?gr}G? aT IGo|Ԡ{&RR͛{aZn ?ViI L+RViI L+R]AV$0HK ´"-:mar L$88vI:8FޔJpda mIXo9BQ{:f3$J|Klaf@"\{+ә)J߇sI׉rPӇC@b>$э_)K *>$'R9C-v#6XV|cԸ={ SM=ǔSF {CzoyӋ J{ \7~<4/w)4 x;Zx9 e*MVUU_2tN@zN]뷇COaj S|G^ri|tR-Y|}J7HqtM>U? at2๪8g@ Zd]뷠qVUW>プ@#GѪURKLES^-Hk@ Ⱥ:yH>ESΒC?]9bXܠI5Ovpe [,Fl=uW_|,.YwF_qIQYk}swjo#Jc"Fq,`O'|a8kFqO=E>zYk$ =} XR\_!:0K;Df1K/u'-ʺGt[YYwqcbRIl鞟YRnB/b_UuSeR*wsG! ?{(ӐK%Jvn'.xvU1V㓸oE?;0D7v3Hhu!q s0 ^aQ8k8}sܘ/Y׭uL %ݽ5pFH{Z}S-iyl*΄wki$ / Rw4ŭqjQFOQk]¯f=jC+W+&uCS+}=CNjqj1Yu>LJ&Hs$O8;Lb7l 2U? C`ճW*=aSpRQZ+dOd +dOd +dOdS=Ճ U\aS`$aj=5pfL}Ly@?#f!T9-܄@WAleދpXf85E7:''~xoGUï!C' CkD> ʣd{㝗O9_wR]߿%CdUR>-Ov^d</) * · :IX#)0)/Q*1{ӂ$z$;IkAֿŝR I-)~I$Qʜ4Ax=I$эʜ4A"XT& xjsRv:qO,*sIX?N $qN,*s*;>װ6- $am[8m Htp%Iߦ6$Mw dl[8mcQ&H Mw3$Mw 6-$am[8mHtpnlMw mIXN8tpP 'YfN[A5:[X}ic}›߾n@ߦV$Mw;QDL;x٥Qa:UĶ\kjڜ.}(J?Eam,FכTq衖 +Q"%*VJUDnz"Zɮw-}5P! Xi~tj:P?܂p1FDp'!Y,8r0@!4S>ش'p@R Ni3&Lk{O$CR ?ߦpKJ^M5Ph-¡e(^g#S> (ЬIC9ƇU#KijB"K?a:LP_n+lTᆹ%:AʫE?3?O@7gV<&n xq2 py2>[;Qtq*B }bb}OS}F0m/.q_3Fyx!27i!6G*CHpE섣]*\TavŷowwcJU&jkHkP?X,7^[*)baղxm$ƎbJk^217ʑ"׺\FH ޿JzS*!%mxE_(NP8';hR? ٛSC\ǧ&%ԬI@|[BIw-QqWvФ~+;hR?Bz~KTܕ4p!{}&.dD]A[I D?I -QqWvФ~+;hR?Bz~KTܕ4Oz~KTܕ4.}=%*씾weMvJ_>&;D]A׿?IN,QqWvФ~`+;hR?S ETܕ4)}#*lޟ&*섾}weMS}weMꇗMl: duA$ԩIXԩIXt(H$u ճɞ֔ ]KM{FJawlAV =i -HCw=i{hv۝5>o}wmlwn㨷lwnHMڻݹiZ6N܁^i$;.UOߍ/Aל≝R.Aڴ8|A>ׂ$?jlwm.O2p> O6+̓ݭWU? _]{J`wkAtM8^%IiݛAhno)g`mpI1UXV.pܐC}<8 DAVxr# |/f(.^bɥW}Cktɾps6J7~MεkTQ b@c2Rx$|`J4 w3f0.H"$^~i.~1W&F"} +״I~3~dIORc@V|-|Ux\$]j "1Gne ׂ .M/qi뗡+Sk78hPd7W'N,oF8(cb|qZѝ_ U~Xp;b2w׆Jay_OJ- v3o@C烷 ^w`:'oޚ J*Oϡlc|oJ!?b8ϭ9֬*\y㧔^<=<VOȨήj1xCzQz$Q/3)T}W^EЬ{,.=,.fRgUTXY!=p2+P`MX qU$|gMxJ)=6Rk%w\Iβ NT9w%g\?[?w;]=\sS6R+W/ [_}j5@7\LOɃ)p"w0\_&|0!yiĹVZճC4R {_L9'y2S>ɋ̕$O"?Um.M$eί.no?[ Ə J6~I0lWm|z7CQOJO0t֣/yaN$aFe4o}n4M!o!*?g>4yRkp̕!G`KC$&&/hn~V|g{<L8}^!{? tݷSmåQɹy,gZy,\V Q`w-*NJ<.hO ׽!FABt pw3܆slr;p tfyMoj| ؽcHcȥ4/]վmd4_}}sW\zS*ܰs|m $J7<Ð]5R {y+SS3?fɫ[[|KZ;.xvU91It$uAs# H.HySe?57="% ȣJ"֨Trye4"|xz dp]J^y84|RBၟwnIMj &[4V| miz?H.-ViMBzgpЮ jJpҾ:;x;5* Q$!~rp2ttVhU}ѵ/Bg n[OϬ_g9GQ8_A?N3T5eg 1ZJskxxEG #+kؚ)q'+K4 toN.,w^mY\zG^<Hh rHTBS?o WIX MdI!,$cM\$&04.ǯ/C3i" M8D ܁B@}c&~&Ҁ$ MIX.Z&2$'Ey$?tLah\yиGt/иG.04]$OLtL)@VL+h[^&҂|M4$-Ph"H !dD ^͘NLZϫ\Z3nr0H[?.AL3HB퇅_MIoC&RMEk"!X?x!:c|R*acVU N$9U_S~_0PS+!,V 'i|>͹;ip7'"NMjB8q7C/B@&^_ o ?po $ OF˥uq+iK>x=H6!1+$7dAxYZ}qI 4$?7aKreؙBkj!D\ ~SUo13t^xPIi}V OZMVK%HCI ^eB4m&*sQ݌JB/ ȸK%574wc]wCl$us*VS$yv!(qR;^科! )N\_ IX>O &!-|U-igZ]I&NBA2DJ]uJW~$~ɶXI"V7MzEt$gx$|^(Pb7o2\1# 'yk̐ڇ kZ,h_$"Nk'l|b+9)<>_;)n KÙ{JdD&DMINW:I,-ɲ?W~.p 1btfj>B~H^3/Gĭ3)P'C;\|kg> Sk|ÇWsjVO/Qj÷:4|zm ouh=6oz>\[ O7fVSU~4/!?ؼ_/CKO4Hߧp&㬅|D?v)>$vVCCӴOaIS']JЪqbk ׽_ɭ8RULDiޥ*!ȿWZŵTJ\枨(Bv) 0*jwZ=SZs=VM~05W*{Vu4Q' O7Qӝ{$vzj>$>x9$ +O@pݾwU(~~bQ`K$UwU"U?uW8߬Sp%:a/nBXz-y| X Kbz/5V!riKCZuJN;8UKou8Y|y:QOTqQƉe+94U$]wh߷iUk)s ӮUsy}]64bH}]jLݰH] U=07 5c@*+}Ak&W* qrj q-u?})O+*֏\"=+?_C 5{pRNקhm(4:)f|Ҿu~YanHG5cVT$hMIX5cVT$XMIx5cVT$[eEy$9e㻴1*E|AKDu,V,Q]nx\+Y܄Ny0VDuQ$)Ib.3>IE`'Y(_$1KTEi$fH0S>IE`'YB(_$1Q_~J]ONDu#?IE`'Y(_$1KTE$f ݢH0SXlG}y?.Wr}.b$fH0SX?,Q]nKk|%1KTE$fRxIzGB,Q] f o|%"LaODu)1Y,Q] f g|%"Lo|%"LaODuQ$),Q] |ODu)L7K,Q] f $1KTBLODuQ$),Q] f $1KTL-,Q] f $1KTy"U{"Qa'1KTE{?IE`j,Q[ f $1Q__IIX:\{ۉH]P*EwX0~$˛lMvy? = Ğ]QSٳ4~w=.iڴ~$ J WXrY +In'*v7'Tf'3jᮮ|5M-E `NȐ%0՜ OZe;=+O|C׌ {mM,R7sLYl%t͖8L2vwXiDFB=  Ӳw5vjR$sZvZ:k'56aP T#F߶7i?[7U%6.% >?k##\Z1n7 /'`$rCuZÆ 7NSBs?H5lxZwjai*H}CodDKh 9HN4+ $?bQֳ?pIu:H/bQֳ?P^N@X̉-6V@X/{ vTB8a$=' $ɄqnH;w[Xa$7[3T _fh@SؒĆ  f@O@ج$n|Y , \mݥ I8简Y+P}3fk.=$?f}a5 fk$a57+]*A ckM7's:sD1O@ج |5N`kt[3ؚy5+__O#|)[f +NqR.Jw;NJ{?>x?NF{}|q;Hg;y}W+I;,>x>#ݑtiwVG~]&!֊~kwNu|8m$,&R YvĿmlHh?Qs;$V]4(T. ~\.h ?G »w_~ՃSkJ3O\1Hz;VXBpW+vW0I`&?$,R X©ua(ҍH#TCO$}^P!c[WUJDOwq)ڃ ɤ87QFm8Z!2NrЊ!LJbƼ3 ujIVaH?TC$H:$hո4L-}߫jIԵ]KSaerqMouC&Kt(${ǒ6~HNrL akTץArz͝=(Lv}&LL{dcH.Ji7X& e?I$RppiC1jJ ) G6@+ |3k2NL;R#c@h?8)A+x'}0{;Wl51ډyC:mCAhI AW4'1ޑp!H2 9q/MiW~}1$84٦V D"qjʛ1ZUzRUlf떭uo9JqHߖXj-޿މc'_?SVH۪MfG;.-Jh' W4$agEqynMIHvmeNIyc7z<3ތLݟ̯43%jO̯4k'u&pVT8=$fQ!:<} NU.-p~6S_f¥$IX$s|7"$Q'?)?!iUM)]S'iSLguC=PMv;|x~AWܑ;O?I8^,m'-rRT)πJ%8r}uEϭހ$?'tMmg+C'x>L;$mYpnA߻R YTPq?~mXFt_U_Qv'*+PTF?XZa#:|`E޶}}C`U!tOU$>SߪA !dh9CG u$ߺ(R*~ #?o=.V>4_J%d?1?$ P3 ЮֻaI|͡skLDnY<]v !>OڰqGnan?ZYהfӂo!dQ^>yUךZwCX-Y++ݩ߼(t-@%l |[Ecj]؊=,n.Z#7V[C+wxf$,}IƯc9'^yVKY9Z]*lá}| dq~8IJ#xqbE ) A\$ϼbE2 ) A\$Pa9IJ?cfT ȱ|) 1GbES@,y ~Dz hx͹ }8lup,.y]NCʏy>b?XgE}R񱍿?R.V ,2qJp_ρ0Z) U>H_7@1gP)(؀$9|ֵ;og{qIzϦ ';V<ـ L̟Ƕ׳_u*~k~kǨn3{*Rjf?Y*l{2[Np?Fw͇U!TVe⮍mQKBfR <~Zş](n}AT1-C !( mo c]hɆl7Rwf^ml%BO8\@zӉ]K-ݪnޔxW ~Sڵ:ɖ4x‘ o炝ZSHj29w5CS8!o?Ar|v?D4H-:|(<"XOC{ZoeJvOlYNj(xuUk?O~tfT .<'q4溈/[ws;U6$<d/=Mz_ 3bNV}F.or#l;F5A=eT=3yl5<誙:+T~ͦ2-x [5)1"q{z*¬oMF׍sߍnp.alZlE 1#/o"4b2 c_;bա%C'@1>ʼn OꗄO>xM1;io w9^gAb= µ6./窘Zv03˓oL`+-Z$Oh MOh MOh '-Z$O'[_~YK47,^$|YÛoVe { l/ڗwcQ &Ͽ"1L?`Aq{ e?v4[vmJ`o?4IX ǘ>`gZƴ{p,@D?T+s &s&F^'8oG9,I:K6+9'@w$aɬS*Nd|zӜɝ>>xߥꉹ7: A*1Iw\O2x?QU%dLwk( ɘxׂ2?Z/vtǻ$qdLwF2;5i1I'c] 'c] Z͘xׂ$Z0ɘxD'cz] "2'޵Ow5P1=_V'cz1 ^_1}þ?K j$S CDmo3D^ۉh3$+ YćgTXQ3q!tf2#D [2&*>xyTN=Ⱦk{__l΁j5NU2'vV`wCd7oox͛@+^'rf+WXK7ox/@+^9+ZiC /XVx4 /XVغ{^_ޥR ))o2{߶4Cf DSX1;3rLa= lE5 w6f04٘^9veL)3L)~6>̅1qkq `rsa–&wvɞ>ol4._lMU)3{,~mZǂG~: Vu5xm2^qn3\kÌ^n, 'T8;l/aӉZ3A wtZnۖv͏A|lN-߶F {TX|[Jc<;|I4-PliHvL̆XkTK<ߍ_JϷ.RlqOrҿԺ]KZNz) ׁ$~;ی766FNK龈omyi9 *UO|Ab1Ka5dp GAn(hvZνwUjjPNkRn[ V_Wٱ r炩Mg6i8|mlG: TAMĖqm_lwUлZ@Q"u*(ʌ;,ƫ(W%K?t^UUsZ*Q^n$#ZƯ5(ஊVN}:DߟvJ|U]0>xu*W^"fQNeʼڪ}a}RՒ`|HBz)]| XmʕJk ݴ{Y]}j| ?b@bĴ?jU zmIXnn3vG7sҲj?yRĻq@3 6Ah:@K@G/1/׺]]ٴuN*[?xsDa%j?~S'HZʖQɖg?PWsAR\eHqHn>Rrl悦b Qf*@a7'f~8tLmo*=paUj|j ?/vӔ>wNz3Zƥ fspW-ԒP"L\rG3Hq*;*&KqnјeP#mWmVPɁARS3?3t}^h0~:,7~u/X$-L˵{eUJ~.HJk)mDKio<ů`O 39YC~ HUNL$F Znu^$zl/Ck%9j-Z z;ZN{J q^7AO|_N(o}KH#x;OO0O(~$^p xz$|$ "ŜP'HAۻ?+@?D5T)$HyP_l"MBA6D& ϛ$?,MBA_yN>o "iMBAD& =D& ?l' wIXQoo"^wiTÈ7 IX7 IXu7 IX94|o *.7 IXwh$$aI(Hk{'MʡM.J[7|w3wZZmJpckJMboIjz($7dlQK4q:_M.* 檜qZaL BB7Mwh@x]$?}[ue8D,JDjK|لW!Vzo} m.f>]> 2Q׵k m:ssZH'^u%~ph{)~4@m#2mkUp7q$ЊV:^viTBh~kwPeHG~JWw) X?D?âizGϵƮE7N(|ݗORr]k\k'k;>vu񶣬Y J!+_W`~%%)HdK(|s%uf@,~ _IJ KAeO<+C~JX~J;Ϯ4绡]EP|7T+PMUĽB[φW&RafOR'k 27񬩰Zx,w^o9!yKWH$d!}C柴EiL/U֥<̲ھPK$7D^3I9ᛰ!CpAJפTRM$n "I\If4s.V}ߟzYfb}qw~7H R LJa3R!Oqf :bRa8Mݸ?) QA:cCo2̏(IϦNtN ?.|ՒѾWRIwlf( ա~@8 !W;|<75DIaU,HO uQ% w mae(hnSzCQPK 1ujoYxE\jj\WӴI:UCWi/wkzW|/{U;pSV]K+_RS7BBq5E蟟WꡋEBY_u}X_ *eɉZ_G?"׺R!g._ ^~b0DC3?..g.gćK8+PJ>8'I|I_;)8#DK';V; ME ⢎c0 ]IXڷie6J%pM$w<>?.v m{Wsm ]LdlI7Jr]Id;T]Jh9Ɗ?;vcUv?zqv?*?|1hO;9=C{R?UI!Dr7 s{\doFm$;͚$>DU\l&g,Q§pIs"k|nKUe6J%}X3(yϘ|~|>cJ'?$%-gMX=?$ܖmbw|K68 O2$DvD_HUdɌB'[p' ;Ty/(&WS[TA'^yB0(Vs-*xàp;Ds5Т‚hU, 5^N¡ouz;vf3r( ,SwrHw/<kYE_J oJܺlSUw[mAUi"nS;6έ_Wב ; C׿Oc/HPydQ@|Zv _G'NmEI²a'g6c'g5q N.%z4iIu3lZO^>5-f\>ZؔҵJj$$!N$Fs_xMVE\1(l[/1}Oh2 eZZkHdǜze 5u4#wK9o ;(}6D.%U+.+ K^->&[zXMIMm=[/y=!NX_DH a*xdp%eet?-n!ʡ D7bJ}ݰ5YDp A4DM»!r8^J˅kvaI+\a:+X5"DK/%EʮsAT {u? k:n{o{hW5`?0* .|+x̘&Zj}V~K-% _:8T35kB U2Smq11uS~GOB-bUȼe*Ga ߆:H$*"kW©'ڣY+&arQS "1kl.NhG-tO@WVkFM&]itR%nRB>#75ԸPC^C,+lUZ-:=~g]gv%,wr.GեYt7!pquw8pY{j-(/ e!jV\KpUQSe|j\WQ/15f_Fqq2x8dzFGӗ%ōhVyDq<:&AT _vN7O z(^EP@3EGw9Go+JT#dxէE!H!HvSMn/@//Ǖ*y1r_vD W0+38TH#L9甝 QɅR$QuA9Nu48 El KjXa HP:=t@Z`ՒD fv VWs8A"{P y$:AKk?_|@H\4ԨP5u`GVx޵ nwxV0>A󯷾PL4$TͿPŮԉ o+*$WZ]zxs+tZڋW<R'/|ݷ*nx;/nQRzm;wRGB[qTb;)!˹x:v'WTHթJ̸x:q'WTH­wMf>u3s q߻&SSBczY=$<|Vd$$HuYenZ8d5)6-|0 Q`Eќ:&Y4 ϹuRTY0C3^ыaĂB!i9AP"x V:&*^P_UcK Vs/M( $zjCi?RBVR@ JjHH ׁqܽ kŷ{*~~kw/y;©K-TR;=U !R! ̔ϮΖ5%?v;w!G>|jٲqƾDǹe 1BΖ5ăΝ-kL˻Ζ5CV_Ζ5CE>w!Ϲe 1BHwfS/ Vjo!2NBH 5t-qO]Lx :us\|b,י,Fv~(SI9:SM ~GJ#K)fj"(ƒ-cxNN& fݯ;D/N,u7ZZR!{kh_R!$\$))UEB-: e^*G͜J٨e.BM%=ȑTkRu^4ApneZ0SUaW $qc*9'6>]kW'̲GaM;1eR-P(Ҿf9?Z?ZkibpKLg.ɣ~ڪG|^2̙K;I|K:vWrB HofYeO:!$uA_GI4pH4HQ5Q! 'Ϧ-Kx'h>NAow☉7yP!Ҽ#nyW ZG_?QQ! f&ĒG@uS@QM- _uʡ#_ٓB$?EzWb]/E³CZ,>?uIDZ&}KbTf$vi)=*(rPtß{֟ ֊P[J8E_8+NhAEq>=?‹!F9a:brFY:U"e$.G><@bS-Xjg՜Y є()Iɔ} OwV$hN="nH";$ݒ[]ݿя0H%ƃ2m=>rc7A~#Pvg HF×2jTmWAc&s?*(qoh"E Do :/y~,:дz( ]OuZ-φCZ8WTSJv҃'p`B =P䖠z g286w*J?ʈ%g_O},s}P3#/R YqE(*y;=?^*4N"#dNQJf[9$pQq#~Q;AǬGB)3u!˪q7|EKl{r;rƑhHpU WXς-L؉EERsUA& N&d;y5q,<. U:3qRϿ*VrK*HR.;Z[!E_) c1M,GrH;(JX\Ư z׵O=< _iX%Nn^Kf lZ#U8ڎ89޹'\z׫YRx\;;T z?.  /Tx8 L`MZ dڅ~N0{2k "sV"' kk%/qU6hI>++C4eKo uIz۩5~֏J!6? 2F?)Ibu"֏J/emj^Kq4f u9a1t:O٦19V  Z~׊ 1['T (w*{|FxcՕnyjI5we-IWDnf[~P123FYUPuABxPߙ=qBi{E[!!N՞M?Dz{%>tb>s&&x)''վg}F2÷GMIAӡxwIPzR_U/pԲ:~OUBz-P(J Sy-+Bi#*<~/>= {MS_`S/aVm + #3&.l,$K-]LEKBc8jn&n*0$}KR ӯ>؜U,ͮ_5 ]4'YTeĩPIu%uZIj"exK|dՠաAyO.4y?M!IY^Oz8ѬV Gq$>) pKН/dd oP+o'>o{{+t(IVNG<La=uA/TO?T /i>ʈU fC+T%7>>9s%٩+UJz[HՔ;ICG5{)k:HPHEtFȍlzJR YiIta]LC]˺**%pA ,׿ RIPa.wpB򃗄Ղ&+©7 itנjAi>~_P— )#.aʦi uzGzMRUx=B2OD[! McsTZܿR!Նb@gbC@ BMxhIa'd3Ejk%KxewjVKjƛ!F)_WTT8H?$`4 |&NN _ ӄ9>tGK>`jHQoftT*TH+]H.TLX/#xU!Gkw l|'ŗ&AR^Lq;s),Ytzd56͊I z)S7J!'jS~x~H!CVu 9煏Ki!%τvB$PQ 1'<^ ]1b8r|z^}I+QI" M*\"-Bg&(̛ޏ3e]B‘RMm QHYΦSG' # njVyRћ T#Q'E(‹KT%Fm.oBկ<&;$)+"d'g|LПZ_-ƨ^"R /E_+Jo1 X?%PZi"9 _UPH4 Oqj*,iGӛaV*IO$i!.")+/{:鱀bnbAw : ?se?*CIJĩ5mί =sǡ_%9ׄ"M욊ipr"e$NTuuTN:WxM[_2~FC<ͤ$Vǜ|% 'ېf#KN]ÓRF`1:{xg!LjzxPABփ>jjz:~NKTXq8v3!{SgTk;I[طPi&=lWKM g#2y.RMV"%N!ŭX_ރ 痂aj8% *3!֨䍫A=pQ= sj4'K c&V›!BhErT_6CIABMH4^P!)KM<]k%D\ToRuB_+| !@SiT軘^[TaQ7AH4jE'4}}Y;p\e\K?0A/ʈWT򻔹R}=_C$=OD7R.'>-cBu>2VNJԔ~SdHM Kr^B /MzsCMͤKu?ݗs._yB]oI)SdV#ih$Hbe1RN)iM' SR˜is!NTlU-qˎ%)/vN-.-苾tP=e^,)|NB'Q D%Z UubˋzP= D]+8CWM_a>V%*^Y0.'ې_04HzOC2Kܿ8*>aj=j)8&)/~K\U͞ dƕ}iM@┇8oJ嶲Wr qVDt!zpg;D3:NԟBZ94|A3*LLȎӵ#w[Ov:CER,P`9Uܙ;W&.V'0#nSLRd4KћT]QW>\̹:Ox~fƒ,9S_RcPx<~(ǣa " b883ZQNBГ~΂wP%AE/"1Uq l8^"ZD[B=Hp.b5hjOAH4SG>Ί@υ)wY ۤG:HK4 ՓT_> #R1 i[꟨ish|j?i[x$M^?V 'o1^b蚤BKҳ̛}K|vI^T*Ns<^ x1Q Sހǻx"**_~yIJ Лzk!CVC/hG{s' jzRjA}TQmvS;{| , aQPM*^Kz>;{ASPSO6MkgרO-EUwJRh|Pt ~֗ !$~i1+>RUT<1SdG灥2H]kbѹChjDruʼnE-3F%DU4Vg@4xPMf AOqW0X7cre4#ƪg4^xI=!C!B *z_Tb(G% u}_E? wvC v5HGTIpJO%H' c*D4RK)*$z !{Pj3>Usͤ}.Be?e#GwvI!zu0j8W8I_Q+Y 쩉{~/[;^\%͉ꅇMp=`(d@lmV=5A\v2hTmJ \/Өq[1~ uݿcK-.H[7yuG[-O 팸hug+DMܷnM woR'vT鿨=3յ~rO]BF?ze,kyRK[ZݗG:Uxn5=O6ZCyNyWrBsI>z1LqK^xK9?UO)W:e1yN,Jտ:ETbqm ipX zL:2}YI5+cn q*Dbj]ud'+N$L(wSEǑj'ڧ>&Q >T.|uIz:+!NFYILJM=jZ2Ijt% %^jIIod5l)ujzi|꟧Wڿs1GNnnu+ԖBw/9 rup-G(W!xica Q64C0K]Ȍn*jYU[ !PST*$Z]|VvC V/ux7oE%pa 5hjKuSJMޤ-a :%@lr)dN\MԉBlKH݃IwѰfSdBUg5đpp_AݠmWd7tTH>XSR^%O7&!э#pWMuW 8xtYMT{5?[~ԤH O2qod}]x\ qJqFe"߄_Q?=0^?:CYHxMumT`&Gлz@xtJ.|0lg _9=AʰkE+zUVT=17!bOaCP/U AkQɅ,^W쿞4nf Ayȅ/Cr:=VF_-*ƏP_Ca}h%B)D}`J }[x_\7AEmA>uͪ u]"`tP3v_V"/qz*ENߦ&sw&E.oc"a'FBq*X<M`ƹ$УR}%?PQ0xb#)w "J};&HX:z_ &-xnC0pD 3?Wm#cv BxlsmaC32x'Թ5rq>l)gdI=!.d ~ STCTqdADhw^|:a7Nf R&8CWk>nd\DI;)Ѭk%Y΅\R39tN^U8G3!ȓ@gT(8ңU\pOQw{TfyEY}ɿyL`[RB8f) #X^7 D0#K~Yi 'TГzd^M J'!;0# %HOjVIURuե#tlJuUQnYRkQfip?UQUcNGLZ b SɀA-%(9S]1>Bڃ4FLSUQ͇7$WE’$. /cyoA -_["AA(9`.)\ɵ LKq%*A¡o;t=q)<0$hhܲHp$?G%,yGVͩcOX xtu?8>?*hǤ[RlqB#'SER՚ЅЀ-VN@b:*^r$[G¢L8{,(b ad!Dhar.+*IHz6JT^C(AcЩk|r<>EQ+YG2sfPumCvU|ߵCz:,JѼ-%GCf̝)pKtڃY8<>PI=יM򢕼o V:+^3N<C*E#)%4 pi04яsh9VA5f#U}bn!:NR0{yX0g#^'44B$jB (}WN>2t,$6¹SQ+.{ L0 ^N7ڠ>!˪@}IfP܎!=ZֱCU/PSԵ ո%?lS(! /UEB\j]; پWuH;A1Vc, {]2-nS(%+!$lSsь#IgԔŽ*΀'7{B:;oAYY;VTCTE=+ &N[d˫ 8u)(7\vFeapK ;; Y57.wX.$d 25e $)駨lڞlF州t ]VU7Z qG1Bs_E5 oaiצj?EDgQ A”łrh?R G R0z5qq;]㿘 lBXa3;/\TF  c>k%5r8pGTO hWw[=Y$_I (BzTسUv=ف?y')G=$JVb_SA \+r`J?@HܿЫ5 B?8OcyoLbmCs%w"o^ Zl,- VEhI|(0d!9xKh>xacl0r"a*"E.=ԛf`.;nu܅ZdF R5҅;!`9 $Cxy!&T yλzy]P5vw!8"WU$PkvUǿu^Cr@H-^59Nbi_iG {B+EP:ĢD+UP: d o:!5 $u\4PA@vk ʞp.xӢ k@%)Ə29>댯f-f.I1~phK wD:xUnIa&M1*%!|}T`}F~B ~m+pIpy(d]f%&54f`} m .,_6gEMϾDOTETE’ BN_:ti-VO0m!e]C $S8ъp9l# q8DS坞]O,[zoRp"ї>\L #h xA ) !#Փ&QM\WȅAB_Z yrtx0I7"};i q{0YZnD^*w*/"8RnF^RdhF{ںA3 g>gOwQN[*LNzpGVk\Ƨ珺Bip|hH}RP[Ov[B7G/ovIJe.h09B @IBTSTEχFTn\i|Vf(̓/_JREUKOtד8&GBY}KuET8~u_go>|ȷES ch8onjSIS4Ur0s}iV8 ӥ+ |~:oJ(? |f.Bg]:ѝKO6gmASǏZ=."<ڕ  <5,p{19hJ*?{)lo'Zϗ{Wr#wBS5O͚ j9*T"F]<}I~x]sπInE*D)S?Q g5UѽPHьzT<;|/BSmڡ T%_f||6@S9}ą"Y+%4|} O?"Py> :#a'yH~M"O jC6ˡ4q?bXs{"Vxpͪوַ^Su/3`"yw[9 x?'|7]OH6 ٪~$و WďdI>l5oh%Vs! Q.Se}/2ͧ?s q֤A8Mktݢ =39S2{yk<ߩuicJ\$\D]C rh_xIfW8qpbþP"cLTbϗw pknv.BoIBfW;pO0T‹=/c `/w} /n&ѳbfW'ƨ`}b&p펗H-⏀Mw +qZ ޴q  DYX}㢯V F̋&)Ewi As6\B)p1pV'*^oR**?|d<^BxFUKb|J́DYL$?xK'xf$ #NG}rfhE v]TIš /KJ8_ЫjRuVDG^yDOTH<~Q5SXE/N a~ZУvf-x1tSu;%g>R'ļW*9X]1^Uz̮&NvqZУB7' x&mT/q#!PC0Nx,Xڜ}KPCTF߉~%'&YG˽'*dW%W?l٦ j4/dGk[Bpo/\&*'N*B*$-47.;݄7~PU4몗:AK,=N= U)Z?Ļ Zx9\5!hҪH2B"xLrTTp 17bu MB(d|ܢ!wb$0Yl=Ԑu"N&V)FMb‰Üo1\$U ɚYkkINGk+Q=\ LxH?xEG24[]Ǒ:|h]_< QAK+F̥G=H,W/~&#x\K2I¡Ҙ5,$ϭQaK $Z_GBld!Ad 0S~gEpD3$NCf6!$ sY?OdžOոU01~roY&Woz{2͟z^x4ƞ%vhe-DPHhkf$B|o"/]O#i۰$Jb$4Vd_BJ͇LGc!ViI<!qC\8Woe_\$wo M|+FSH4~ЈSF4&TeK^TTHK#ÝQaD7ÈxBaD!ѩ$Èυ}1tYҌ˪Fi0\Ry%q7s+s`_(K6aD.f`_lÈx\x\Q!a˲i3gݿ/pr+cm"m:%o[4\F2e,S>P?.ߵmUdL\-M%\iHxEl/D ׽ƭccrR4xR*ǦVsH`3aյI`7n[S rמ4A+jZ/T#KKj2w1 G^¡C/|EneIvK8tP߃_I +A;%aIWvUၣB)M5Ƹp熇I o56udiVC5_[ Fco;[eI͟gr6;7a$M;ᠧpwQE7KP8xcxOګ^xj@Pk :-=]F PCHj+NW٫Ŭ>.)?9ёk^?^XI?{ntxWoRO*tcF H S A &!+!!$ۺn5.EG[va}E~/_^)Eby+fz&?6\F(0\S*,JzИ cs !k'nM-|fKZWV֨ ix7ma%U+Ȯ=xI1\wgGAVѵF.%'!$z~ ~d++T#ҡ;Wscj5}2"A C >( 9+?֗ LULx_bp4jğ˵Gf$EK1yW8a%^9 ߗCJQFPnxh^qȑ.D ?57O-~I L}î%n2!GKgf$ez~Ea W yWR/12B%L* e$h/ ˒*K~R-$KFЀ( " dY4(krpSa &ߢȉS6q^X*=߷ ʪMC1\$Ke /ǗEʪۅEN?eٔeK%C,3ZoxPUR!a$GxIN5f#{DL]+hE]M8;k27Z ԯ-:M h2^JXu Paj%}Z!ؔAM+Z"@䡉 60ZKp[U#=s %Yy-DCW= m?YHx/ y8 D-aj4şaߞ _)=O?8%F8I\|K̚fz-s ekVr-B\d_6~?tT/&yKΩ-1?=H `'RTO['Zs}˂ŅW瞫O`} ]:8LugX.%94[8u؉P\k`.ʼWۅ*r. RF\^r[M`%|*I\zd`~.+uN@gL8-=P=f,_FDcDcFv5e^UHܤ^-0Լ kjUΒEHI=Us $sc7~1TYBGuo u٠ZAcIy` O Zr'"^R%ͨAߓf^ jhg~D?VKQYx| !2Ws4 sU~ @WF쬃 14gӫk)wݻ2Hꈪj"[ԻfSMUإ#D}ƫ QE{--~9Ȭ$wZ i"aI׿o/_F.9_ BBH4%h!;xI}L-azKIގ[}[*Ԃ>ZedJ*֯S~^ _>O]?o  !Bc  qLz5:HR/MӒdtHU^EB6M# $UjvbBMC?a'2D!K)))*jBoo)DJx*`2Tӗ[O)zpںf$djƏk=,SheM,Y*~ W7v׊\$r%d] I}i`\n*T3^0?t Ԓ= #\4J1|j`n =!dxuU׈n'`)}ըYRxH=k1=jSU'mEHIdUyq'jTI|XhҀ?3`yh9!;}}h/Yx gc* b 3!ԏCxy5pS ߉c: 4*9HKV$E HtBj*^F[fT֗n[*W "*iA5B*e'~܎)E~UכTHMIʌV<:~)*b|e~5~z~$^ԵEs?CK3=RFeIT*T `nHWP$VtQS(/ \?r|ƫʙKެ\bb@n>,I/xy[ڿ\ש/1NτvB8q "A!oV_Vs@ـ s tuyՒW8sm !n_߄W exO+5M߄AoI\Hr`txdٞw jk4r?L(K4W5m*BFrG>aA@ $҄NWo% ̄w& 㓃Uc\L|)k9U\5yi3pEAElc>_7r5VoE_N zxSn+p^d(-%E__:诡c$ETnI n|4iC ^ $ChPj97 y33q6Ȕa^xQnΩ_^ ju;].Y1Թ3Fΰfϟ# Wֽ6WUoPE&GB:72 >r09b&eؿyȐ|΁wrO@H0J9}B : a!S)rε6I:F"#8^F+tBt:""dLߙ˪1R)tA:yGȘL/B>i G%ts$zSF5d#l:YR!;hR7/$D;Ѱ{9Su3s*tJ8ItadINGT=8{+UCpHyMs?^:D#v*.f.0qzSq=s's2Z3\󈝊 εS6܂DQ !-⢗3?/tt" )߷?$ CSKɮkĉbd _hO=IB᧍=mqRSk կ=3oӍ=m45t(WK^}1D%F@H45tΛBXu+r'*!$߾O# $Zz"0 3bur%F%sY oZxz*4Q4pMxOFܖ}Ұmu [h]6;ȥD髡N'zN Ӧg61I Õ}`B;:E=Dgg* _ !AƂNn;*Z4M :+^މؖ\eƯV++Qoa.@{3cZlz zb)v;zEv=T'kSGu h~ '.pL`w_J7]_?"A'_`sTk}j.B ![D5]l=힟SHN=8[nNj$Jꥳ6Ϝxt⤫zj&b'/=ZmvCG\b?iۜte'揞X6']Stbu9Nj}SfSR:mqU=IC{SCvpە?yЉ]"O"ua煏ET?:95~VW'/|]:gqU^X瓔k~x:9’9TV:LJksK-O`CN&=s&)tCy#ss>н:RѲkKA)#KRɚN%@e_2I5v]O`i= hxn2 bh8䔢NE4/w:׾DSK`u*-~!Aw:aDSo;X0_:S܈)=RZ/d.[8-֙"*:1WwHu𞹓H0o+;Xgj_R!խWW @lwHu{pJV1k~(h4rh:)d joK':DN '5oGBQ5nd"&"58A`%)q,ENcٌ`M).^,' %*-'A@EIч#rC*YۅyJRHDS_ډ`%)KI$K8)o2WT_Sщ3A(Q_V %#"'¯&K+{RB¥ߏ2 StO'Rwohk_ES\S$[yy2ȭL"Ie+܁\~VSD9m%!'\$dz;;(<tAyr Jr!gD>9-h 3e~$Ng[3XÐ'E5g|ʓғ`N#(w[Υ//{ȓқ$7]xkΧw-t oQcُ~?{BH!?'խ< !tk(Q=nK׺GC^tR׶vG Cn3^2Ͻ5~^llΒ[tF¯|V?Z]$FevTE7󖘟 }=~? Nհ#=n^fV6/|\&xh~Jq\ѯ1{#ǐ㜿g~_Ti3t3a8m&B;dݫ/zCm`hTP1+N־]x\$xg6{f$eU͡W?4UXJɮd AXJ^e9uTէeH5}F\6N=8e 4=F+?=[GNI'k.f.`S]eH:Yq=s'sAˆtmLDK_s;s*l>0l˅>1" }/M;ml&DO4R&AK~D`T:)! ¾9y'?n6ˆ}c/?ضO6 __f]tNcLن$0D*OOoN dY 'A[3 AEߏir2$L0 -"] `|\ä6=hJI5tK4$F/ۘS#"ˆr72w0 P˲ap$_Ǹ?ãjr`: 엃uV;sE ˆrEx71% hXf_IV.L䃤:FdRj'<ҟ'c%I?/I{uQm5EBNÛ$2XCO,alǏ#PUaXpP|T&s` y`HׅLT, K=RqdK=8鸑 e&׵4ɦR.̄T$*/~Iu?lܺ$!ZjkWj4YCz7.tW4 _ؾ:)B#q]2-9*/+7mVz:qwb»sEMHOtO~r݉3}+g6ڍ[3Ӽv5 |bn4Ulx&b.{Bpi^q U4H1Kk΋td.M ߚԞ,|ؓ |\㷧S)yg&3T^72gP=4.eb'thPTsdQYeUKv2 ݙHq#3%!p&QΦS׿}ӜVݑTm! }rp,;ʒKWxD $GU,K(̘R'OiDYH!GK/sgնpJY/-xGT6cHR 2eДj6֊uYH?#/[XaKd#]Sɢh""dމ)AEt>E=R2C<_٠ȢG*YDtHVE2RSǢ O /ۘhv=VE2q 1[|r&pd.ǠE.j HE)Y $!Ǡ(E[wQQ8,E)^n ۅE$lq\x?V;Rtٰڱ1]!Euw(_t ^l--=86S'[{Lw,?G15I Nc#^鎅m8)'zY M"a#wӟ? }Ec2YetC>_.cC!"|換LPRkh;&L{c!!\l/G F Z~'%["AKİl$q^\$Acc!v(#SR}%>Ν8wA-EA|K6"-:NP094v$u.or1)1DSGBUX:hcHySLhDՋ%M7~d~Jb^}L?4&ޒȦḬXR+ԙ#Av)%$vK9 SG-82pv^u~&ōtx`!w$Ln!GG䑒gJqgX ]x9A)8zLRHG-I5-b,DՉq֞͝:qJetN"&X ,O؄K=ḡW؂3$ _w)_7KsJډ<.Ev.2#4G}2\4ȅ$sz> +ق#N3bh:n\CX+_Gd.q )O-FkQXL}=tEnrھ]L?T5$X.KGT3\ư1qoGɭAM\m)T-\E]E/%}`ώR.n- r?2WW@ ?{|88[  *yynVcJK@?'ipV%HIT%s_"UB`! <z@4 ]@(^]2.*8p3\xra0jt,+L!kRDr¸>%03az4窶w\ڢ\Cxv?0>ӌ8g_x4u >c,d7xܗxIX^g#8ffhPAߦj4\\a*<1ie'A$·IAI X23W!+s;~sLH$!x\$d(ibٰ?Io猕TCǴݠl~%e#MO/SS+:&OYꑗ;Y75i 3 d^\\2x? Y'ĮM=E'm'!mA Dۓ+5f#KYU?.ӏʅ*FR-5kX$laaDg\u H&h2n+#WS^ab+đ-nN\|OSFN<BHCզ|έ: qHDZN['XVۓgQթu bA!͑>Z+y܁ũO& %OMC9NytO-Ey䁩]xIĞrpQiQ$ ӫ k|0<a7RHIN|-Ny4VdݵFz6A0XO%S(R}HѤ@?K!T2%9Hh(x9+@CwQUC[o|V9'5?*zn:U !QPc.ƅ;Pn%nI*$SA8*F:oBпz|WjUNSͮx52pQ5;'vS̝H koE`^x54:.:TTG+hL?/ڢᒮHc/jE#w $I%Un @Ip!Q?hfKD D҂WJl!̥ _Uk"& D)6gIL=לaP7s9kISO & H_&˚lf0s9uh5  &HP i~kx!%Hq´iF;i%H8MLH $+ |9W",^e8".\XPDOK R.Mt&A]x=|h*{ˊ}PADp4-|$/v^>i-Zb-Hz~g\$$l| '[V_҅Go.&8j)Rl(-0B_I#S8C\3 o| гEYC"QE= lH:ߥB 3楗t\&9v5s;s^O#w1DƭrKl:7)J(kkD#keO꿋v* Mp]d}?rOkr5erK=1^I Kn+VagR~=:n^y ĕy]6) 6e&%/ɦ9Z$0m&t?+$"& ϶O6nFێtg.]ffM_g̤~x\$lD/喬&D[o,͵+¡ ,͵5Ta!mօAZTB\ nq$0Ԙa\}BAnR"x$3 !ѣO'kO-5Ԕ0kBװ w*0N=8-Qi4"R:ffMv׮+'&hX7'҉#.&2!3zBHؾWX0 I|dM_VLUVo}!$A?'v6^6A galփ^Talփ^gSalA^Tǂhc.||~b9Yu/`-r.y«|Ȳ%'A/I0^6A3-rdIօ]g4/ޛ a=+OZZ_Lh48ń™LDݳxh&tߙ^a|/N\5i~.* شyZfIOMC_㨼5l{yTpבa6MRzme"qj]7\$zم͕$^o8yVQ5\$ޏ6=yyh͋l.-iX36 bhQ8GGEBeC~k3㐲.$ޘ3zTfSh77K7ٜ!hl(ʓ){8۰6 [uä֯|k8aP$~"X/E{T~U/ђkھ<Fhn`C0?H8W\$] Y^GwC<\ I!-5AbH?SYk% 9 BAGAH4Il_rp&ҨfKz@_"g}B/ADR!%*$Zd=5"$xatMeTN5JhjԫuA%sE _?TNEE o15|ȁ_]T!hO5Qbbm\0׭.i?X7j a:StX5BW`FU^)\ 8xMR쇓xKh$AhNZQ<~-a3/']ay%GZMR8,aNF§C y4SPK\;q&PrxI>O>⬰~zx7*|!DaN%V'LOrB_%$H^Mޏp\P}CcnR&!$E8q?O\(:D]'.|g>qDQJN!Q{B $)wp(BD/ǍJg.qrŕJ_)G."+Q"@?FF$/$5WncK: r,$5'}3\/[ȓ-W70If^FB']/[#!ѓD뀐h%Hu@HڏDISk!bv*TL.ak$yy[ IV#G*$IZ/BH^?QIRwA L R.o M?~ ?'%zHAH0]RRC)_v@~E™rƱJc#8/Տ【x~|?~$$DS?BSԘ#%a5oGq@H4|t|mc!GBp@_"ױqfy:+E^"0ݑL4a#!N'HH0 PELI۱I!M3w2 &/t'7>3S_B>߁-2>?I{/\!q4r&-B>[^xɌ_vJ!DOB`.6͑8}ָs &4-vNI4Biɘ9iSYD*t(~ w<&xB\_˱Iq5qy %zjjC>2A G)6\$Z_{}KJ=)D/)y0͑LܗH0S X6 z,~ k?NA5MrzJRQ#|n~>#M[O7K*cb˷aJH+Oz=.IEgf.[I4h|eԐ2h|=8Qܥ@IT3k$k_|aXHRUõ b3T!-FU?Q S|֖BI-.~LѾn}t]蘧;-FT0@AE4BH8fb3o^-q )DC~J?g{.|獀=[|j {6lڍ 7U,/%]K1j P^54 u ۩DhQVl4Ӛs% Ij"J܉qTOq+ S ᩩKCl*xBZWlud=ũT-6.xLŝN-3ujGH?ueGԴLKK)'$$~N'/I<N]y~A59_ڨİ|Xc=_v=̒VhUF^V|#tU%8ANlfJZur ֯OMGHb%΄]xT!)HѓGRZD_BrvmI'nxj Lmq'Z;/ Wu,GK*+݇ R]Buj|RFHjyt4Rqm-~8_`2A_Gcy,.">:^g,m!2=u-I&$8%dۭ$[4Z(u H-kHj;SIP1jږ:|M+r'{ţ#pBү*m-NxUR[*[i˲iFmHAg0@/)1T/й-5>̺YJ\S›R[>5V⡭ ZB,C]̌lDSj Ywr@:5@xcL f ?9L)3j hYji~-rM1j'DoeKBZxZd&sK돯m-ۤJ[ᔠ _T³) g'5#|Š5NjD'qUxj(PAO^^Ŗq,}Zj8|\SӍcpR^|Iḙ)l§ˆD?zThg'(5 e榬76 5#K+&eqTOΠBF oO\+'q\ TIU{YղȶfOҙIhZ8דUG j݋T#+u!En JsMģǂز"6i8eĬJw=u26C@T ̐-TN[jssnB_\z2VqūWi_"2L*W41H.zf')ՖRU3ck @Ѫd ?f%~dH0.[Vϴ鏘ZTDhk`]a0hR%! `P˽]apqi ]1AXYh*$K99t$<o#VT?gª9$IV{- %P00Gx3V}8 UMH4@Hذ!_~DlzRTP%LJtC1UYs/HsL,5Mp!A֥TsBi鲖mWo&K_Ȋ, K$U%B#HB#U|_RτHKIXG e! b}^')*jMCluA%cg!R݄#%!l t"L Pf-IXhm "!%lImǪ|ϫןcuLOlNHnv1vzSVUfa%dn͔ BHɞd.DqIqBVC4yت<=LT7PD3)q=JL`@cw4Ӓ) Z DqLhRUoǴʌ=LPD+]ℕI&qcZev_L[U%:HPDK4)iU qE2j&!DOB^OܦWdK4t,:}gqmED#w"]'?DZ2v_?籪2vHzPLJUېΏE[Ǭ{[E70;u>D #J0AmDƼtuX{/+Īs9W_Y% 4љVp?ӌ e%m)B+a?bf,+C? T:s>bQZ0̛bMIqؒ8OOr—!x闼Ne.$#f>Iw1㼃< f ]!Qq9v}d?L 6} ?r1;wMA܍|%JrO/;y{B]fqʅje.ͭj 6}&Qhi|gQ]6GORAmxM }Lkv"󕦘eCk<Ӹ𞹓H [uOkh3ftYWfK:Ti%TWItd%Pc!~:I{s: 'ڛA/ѣjM&iB⮏uO&h]a6stjUZv+$3e.ңIxa. ]/RjL0|-L&Ժ-DEOP?j<2`HC5n&ETVۚV_yԿuɊ]sRk-9)DM9Rٶ ۙQLˆ&ל"E|6M&l^\$l_[+Ng`?-i5kѾ:LRBN vGĚ 4Z o;beCjk!A(Y0!jV< %&DZR2pi B MkUum= b?Jdꅗd5ÄyId5}IgGPaB}"8T1L_$%*kf 4m܇Mc.2DzlFPVWM2jRʷ܅7y9Iҥ1չPK4?r1x7QAz8L0?[[ /4fY V$ MFb{Q!CRNڬ}7U%{4&\]\$'Ca%6v98JkPXݾ\I$CDq5LY/2 $uꬵjb8nuURVn/snwuNC~r,R%IaGd^'uTNfsPKтMZhkfaI9 1+QjB5Ԙ$ Ds}n=f]Ȧt4%#o2ѹF71-Yi$8v.B/,ِΕ&^T2/ѹK TRɦx\$$M*|jf(Q.T۹!lR98h/<gR<ʩ_.,r*jp:5S5'5aҋyq dnc.Դ`ԼhU(H;~Zu 0*N_8 Su / 1S"7Qqy4єium o SϟsxMÇLbϩЎN=$Q)ϟ95I'3HGuI~ќD8fj\uZ= nBz 7]ۉVLϷ$9J|M=Gk !RVZE"&s?jw)e+BHC u3O=>"F"5%<i!Cr'gƞx#f!KD׊yl^oY8 AHXHc1pgUTGC"Y6ɺpgz\?+<ghq}X'\:-E_x_II7pw%ډ~, ϓd𖹃HhqX֝'yX;>Q<' IkS]F}qU)dlDϗ: 4V/_t:Ԭht>hsU Tsa ?珵co\hI8`##I:U$GE0i>@Qq`0bh# u" ?JցR??q}G/H|灀 ?tHbGSO G\$:h.>!AHlTsYT2|B04K @-~Gu3sw~J~5YV>_ȥL :QSG>snQ=mX?G rGT/N|UGTV'ˆ@'>K>DWH>D#-I>DC5GM A\/N~pG**!E`|0I}?ؐgK͝GK[Hu݇փj|ǟVn O~˅[ozVˆ'?뗉,R'#O$r|>gu>Cpz &O%3khs0Ú_ .$= geר]_C{U2~Ii?el\'*> kkVF%kRA?kG+_\=I2K=w{NpIaɃD;C_~ؓ=޳3I,{=uNsPa=p-ܤ[rMi_?$"rbDP9?ԣjZ,gh' 8GM،ׁcfW=`@d3 *yMC'WIvP޾_$~[RU^ZG geRB7Aзr I+סuPRd>J 2-u㓭iƴ ln/¦ЀlgKtD ؂Q6}^B/߷O.Guo7s;/d;d`=Vo:EՍoxuu(ˌhUBj/w 6Px{U| ^(.2 C/ n(*Ld U7l'3P73!~t=USB}I |#L AYByuCHHJ HY*D[8ߩ]j5گ,쌂_UN|\WP½Nӯ5~4J s/{7WU@ʌU}Vm/%ƾ\(E=1_~_(eR(I$\7>8jcp.!>1TpܹɛtNoE(I>ޛ(F_AI >m&(K|BנgnHktC  8 8hlv@qVni::wF*wI * p}S E9a[ͭ 󰺵M}|r>{s':|ToO ya99$!ڐ7qf˄xzBQ>Rf q; Zq\`@(4 }w3wzXktn8r[UDx=B ^WF 6e Ȁ- ݄0xlmC48hu*8 |rQ[E}=h>R8'Ճ#P{քW0 <kERġv;q$L*|4&Щ/K6lW;{k~#do0kU!bjttJ< 1xKxքKAb t#~&8pz]j(pҙ Ex'N$scotch-5.1.12b.dfsg/tgt/0000755000175300017530000000000011145123264015166 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/tgt/k6.tgt0000644000175300017530000000001010667023506016223 0ustar hazelscthazelsctcmplt 6 scotch-5.1.12b.dfsg/tgt/m4x8.tgt0000644000175300017530000000001310667023512016503 0ustar hazelscthazelsctmesh2D 4 8 scotch-5.1.12b.dfsg/tgt/p16.tgt0000644000175300017530000000001410667023513016313 0ustar hazelscthazelsctmesh2D 16 1 scotch-5.1.12b.dfsg/tgt/m32x32.tgt0000644000175300017530000000001510667023511016642 0ustar hazelscthazelsctmesh2D 32 32 scotch-5.1.12b.dfsg/tgt/k8.tgt0000644000175300017530000000001010667023507016226 0ustar hazelscthazelsctcmplt 8 scotch-5.1.12b.dfsg/tgt/void.tgt0000644000175300017530000000001010667023515016644 0ustar hazelscthazelsctcmplt 1 scotch-5.1.12b.dfsg/tgt/m27x29.tgt0000644000175300017530000000001510667023511016654 0ustar hazelscthazelsctmesh2D 27 29 scotch-5.1.12b.dfsg/tgt/m8x16.tgt0000644000175300017530000000001410667023513016570 0ustar hazelscthazelsctmesh2D 8 16 scotch-5.1.12b.dfsg/tgt/k4.tgt0000644000175300017530000000001010667023506016221 0ustar hazelscthazelsctcmplt 4 scotch-5.1.12b.dfsg/tgt/m10x20.tgt0000644000175300017530000000001510667023507016640 0ustar hazelscthazelsctmesh2D 10 20 scotch-5.1.12b.dfsg/tgt/m25x27.tgt0000644000175300017530000000001510667023511016650 0ustar hazelscthazelsctmesh2D 25 27 scotch-5.1.12b.dfsg/tgt/m19x21.tgt0000644000175300017530000000001510667023510016644 0ustar hazelscthazelsctmesh2D 19 21 scotch-5.1.12b.dfsg/tgt/m10x10.tgt0000644000175300017530000000001510667023507016637 0ustar hazelscthazelsctmesh2D 10 10 scotch-5.1.12b.dfsg/tgt/m21x23.tgt0000644000175300017530000000001510667023510016637 0ustar hazelscthazelsctmesh2D 21 23 scotch-5.1.12b.dfsg/tgt/k48.tgt0000644000175300017530000000001110667023506016312 0ustar hazelscthazelsctcmplt 48 scotch-5.1.12b.dfsg/tgt/k24.tgt0000644000175300017530000000001110667023506016304 0ustar hazelscthazelsctcmplt 24 scotch-5.1.12b.dfsg/tgt/k512.tgt0000644000175300017530000000001210667023506016367 0ustar hazelscthazelsctcmplt 512 scotch-5.1.12b.dfsg/tgt/k16.tgt0000644000175300017530000000001110667023505016304 0ustar hazelscthazelsctcmplt 16 scotch-5.1.12b.dfsg/tgt/m29x31.tgt0000644000175300017530000000001510667023511016647 0ustar hazelscthazelsctmesh2D 29 31 scotch-5.1.12b.dfsg/tgt/t2x4x8.tgt0000644000175300017530000000001610667023514016771 0ustar hazelscthazelscttorus3D 2 4 8 scotch-5.1.12b.dfsg/tgt/m24x24.tgt0000644000175300017530000000001510667023511016644 0ustar hazelscthazelsctmesh2D 24 24 scotch-5.1.12b.dfsg/tgt/k7.tgt0000644000175300017530000000001010667023507016225 0ustar hazelscthazelsctcmplt 7 scotch-5.1.12b.dfsg/tgt/p128.tgt0000644000175300017530000000001510667023513016400 0ustar hazelscthazelsctmesh2D 128 1 scotch-5.1.12b.dfsg/tgt/p512.tgt0000644000175300017530000000001510667023514016376 0ustar hazelscthazelsctmesh2D 512 1 scotch-5.1.12b.dfsg/tgt/h1.tgt0000644000175300017530000000000710667023503016216 0ustar hazelscthazelscthcub 1 scotch-5.1.12b.dfsg/tgt/m4x4.tgt0000644000175300017530000000001310667023512016477 0ustar hazelscthazelsctmesh2D 4 4 scotch-5.1.12b.dfsg/tgt/m16x32.tgt0000644000175300017530000000001510667023510016643 0ustar hazelscthazelsctmesh2D 16 32 scotch-5.1.12b.dfsg/tgt/p2.tgt0000644000175300017530000000001310667023513016225 0ustar hazelscthazelsctmesh2D 2 1 scotch-5.1.12b.dfsg/tgt/m19x31.tgt0000644000175300017530000000001510667023510016645 0ustar hazelscthazelsctmesh2D 19 31 scotch-5.1.12b.dfsg/tgt/p4.tgt0000644000175300017530000000001310667023514016230 0ustar hazelscthazelsctmesh2D 4 1 scotch-5.1.12b.dfsg/tgt/t4x4x4.tgt0000644000175300017530000000001610667023515016770 0ustar hazelscthazelscttorus3D 4 4 4 scotch-5.1.12b.dfsg/tgt/p256.tgt0000644000175300017530000000001510667023514016403 0ustar hazelscthazelsctmesh2D 256 1 scotch-5.1.12b.dfsg/tgt/p64.tgt0000644000175300017530000000001410667023514016317 0ustar hazelscthazelsctmesh2D 64 1 scotch-5.1.12b.dfsg/tgt/m5x5.tgt0000644000175300017530000000001310667023512016501 0ustar hazelscthazelsctmesh2D 5 5 scotch-5.1.12b.dfsg/tgt/k64.tgt0000644000175300017530000000001110667023507016311 0ustar hazelscthazelsctcmplt 64 scotch-5.1.12b.dfsg/tgt/h4.tgt0000644000175300017530000000000710667023504016222 0ustar hazelscthazelscthcub 4 scotch-5.1.12b.dfsg/tgt/h10.tgt0000644000175300017530000000001010667023503016270 0ustar hazelscthazelscthcub 10 scotch-5.1.12b.dfsg/tgt/h8.tgt0000644000175300017530000000000710667023505016227 0ustar hazelscthazelscthcub 8 scotch-5.1.12b.dfsg/tgt/m2x4x8.tgt0000644000175300017530000000001510667023511016756 0ustar hazelscthazelsctmesh3D 2 4 8 scotch-5.1.12b.dfsg/tgt/m16x16.tgt0000644000175300017530000000001510667023510016645 0ustar hazelscthazelsctmesh2D 16 16 scotch-5.1.12b.dfsg/tgt/m9x7.tgt0000644000175300017530000000001310667023513016510 0ustar hazelscthazelsctmesh2D 9 7 scotch-5.1.12b.dfsg/tgt/m5x7.tgt0000644000175300017530000000001310667023512016503 0ustar hazelscthazelsctmesh2D 5 7 scotch-5.1.12b.dfsg/tgt/k1.tgt0000644000175300017530000000001010667023505016215 0ustar hazelscthazelsctcmplt 1 scotch-5.1.12b.dfsg/tgt/m17x19.tgt0000644000175300017530000000001510667023510016651 0ustar hazelscthazelsctmesh2D 17 19 scotch-5.1.12b.dfsg/tgt/k128.tgt0000644000175300017530000000001210667023505016371 0ustar hazelscthazelsctcmplt 128 scotch-5.1.12b.dfsg/tgt/m2x2.tgt0000644000175300017530000000001310667023511016472 0ustar hazelscthazelsctmesh2D 2 2 scotch-5.1.12b.dfsg/tgt/h7.tgt0000644000175300017530000000000710667023504016225 0ustar hazelscthazelscthcub 7 scotch-5.1.12b.dfsg/tgt/SP2_16.txt0000644000175300017530000000000710667023503016641 0ustar hazelscthazelsctleaf 4 scotch-5.1.12b.dfsg/tgt/k96.tgt0000644000175300017530000000001110667023507016316 0ustar hazelscthazelsctcmplt 96 scotch-5.1.12b.dfsg/tgt/vhcub.tgt0000644000175300017530000000001010667023515017012 0ustar hazelscthazelsctvarhcub scotch-5.1.12b.dfsg/tgt/m9x11.tgt0000644000175300017530000000001410667023513016564 0ustar hazelscthazelsctmesh2D 9 11 scotch-5.1.12b.dfsg/tgt/h6.tgt0000644000175300017530000000000710667023504016224 0ustar hazelscthazelscthcub 6 scotch-5.1.12b.dfsg/tgt/vcmplt.tgt0000644000175300017530000000001110667023515017211 0ustar hazelscthazelsctvarcmplt scotch-5.1.12b.dfsg/tgt/m8x8.tgt0000644000175300017530000000001310667023513016510 0ustar hazelscthazelsctmesh2D 8 8 scotch-5.1.12b.dfsg/tgt/m3x3.tgt0000644000175300017530000000001310667023512016475 0ustar hazelscthazelsctmesh2D 3 3 scotch-5.1.12b.dfsg/tgt/k32.tgt0000644000175300017530000000001110667023506016303 0ustar hazelscthazelsctcmplt 32 scotch-5.1.12b.dfsg/tgt/m23x25.tgt0000644000175300017530000000001510667023510016643 0ustar hazelscthazelsctmesh2D 23 25 scotch-5.1.12b.dfsg/tgt/m64x64.tgt0000644000175300017530000000001510667023512016655 0ustar hazelscthazelsctmesh2D 64 64 scotch-5.1.12b.dfsg/tgt/k256.tgt0000644000175300017530000000001210667023506016374 0ustar hazelscthazelsctcmplt 256 scotch-5.1.12b.dfsg/tgt/k12.tgt0000644000175300017530000000001110667023505016300 0ustar hazelscthazelsctcmplt 12 scotch-5.1.12b.dfsg/tgt/h2.tgt0000644000175300017530000000000710667023504016220 0ustar hazelscthazelscthcub 2 scotch-5.1.12b.dfsg/tgt/h5.tgt0000644000175300017530000000000710667023504016223 0ustar hazelscthazelscthcub 5 scotch-5.1.12b.dfsg/tgt/h3.tgt0000644000175300017530000000000710667023504016221 0ustar hazelscthazelscthcub 3 scotch-5.1.12b.dfsg/tgt/k2.tgt0000644000175300017530000000001010667023505016216 0ustar hazelscthazelsctcmplt 2 scotch-5.1.12b.dfsg/tgt/h9.tgt0000644000175300017530000000000710667023505016230 0ustar hazelscthazelscthcub 9 scotch-5.1.12b.dfsg/tgt/m11x13.tgt0000644000175300017530000000001510667023507016643 0ustar hazelscthazelsctmesh2D 11 13 scotch-5.1.12b.dfsg/tgt/p32.tgt0000644000175300017530000000001410667023514016312 0ustar hazelscthazelsctmesh2D 32 1 scotch-5.1.12b.dfsg/tgt/p8.tgt0000644000175300017530000000001310667023514016234 0ustar hazelscthazelsctmesh2D 8 1 scotch-5.1.12b.dfsg/tgt/T3D_64.tgt0000644000175300017530000000001610667023503016611 0ustar hazelscthazelscttorus3D 4 4 4 scotch-5.1.12b.dfsg/examples/0000755000175300017530000000000011422605451016207 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/examples/scotch_example_1.f0000644000175300017530000001221011422605451021570 0ustar hazelscthazelsct************************************************************ ** ** ** NAME : scotch_example_1.f ** ** ** ** AUTHOR : Francois PELLEGRINI ** ** ** ** FUNCTION : FORTRAN testbed for the LibSCOTCH ** ** library routines. ** ** ** ** DATES : # Version 3.4 : from : 04 feb 2000 ** ** to 07 feb 2000 ** ** # Version 4.0 : from : 13 mar 2005 ** ** to 13 mar 2005 ** ** # Version 5.1 : from : 24 jul 2010 ** ** to 24 jul 2010 ** ** ** ** NOTES : # This program is to be compiled with ** ** the 32-bit version of the libScotch. ** ** It can be deduced from the fact that ** ** indices to be returned by the ** ** SCOTCHFGRAPHDATA routine are plain ** ** "integer" and not "integer*8". ** ** ** *234567***************************************************** PROGRAM SCOTCH_TEST IMPLICIT NONE INCLUDE "scotchf.h" DOUBLEPRECISION SCOTCHGRAPH (SCOTCH_GRAPHDIM) INTEGER VERTNBR DATA VERTNBR / 3 / INTEGER EDGENBR DATA EDGENBR / 4 / INTEGER VERTTAB (4) DATA VERTTAB / 1, 2, 4, 5 / INTEGER EDGETAB (4) DATA EDGETAB / 2, 1, 3, 2 / INTEGER INDXTAB (1) INTEGER IDXVERTNBR INTEGER IDXVERTTABIDX, IDXVENDTABIDX INTEGER IDXVELOTABIDX, IDXVLBLTABIDX INTEGER IDXEDGENBR INTEGER IDXEDGETABIDX, IDXEDLOTABIDX INTEGER IDXBASEVAL, IDXFLAGVAL INTEGER IERR PRINT *, 'Starting' CALL SCOTCHFGRAPHINIT (SCOTCHGRAPH (1), IERR) IF (IERR .NE. 0) THEN PRINT *, 'ERROR : MAIN : Cannot initialize graph' STOP ENDIF CALL SCOTCHFGRAPHBUILD (SCOTCHGRAPH (1), 1, VERTNBR, * VERTTAB (1), VERTTAB (2), * VERTTAB (1), VERTTAB (1), * EDGENBR, * EDGETAB (1), EDGETAB (1), IERR) IF (IERR .NE. 0) THEN PRINT *, 'ERROR : MAIN : Cannot build graph' STOP ENDIF CALL SCOTCHFGRAPHCHECK (SCOTCHGRAPH (1), IERR) IF (IERR .NE. 0) THEN PRINT *, 'ERROR : MAIN : Invalid check' STOP ENDIF PRINT *, 'Outputing original graph' CALL SCOTCHFGRAPHSAVE (SCOTCHGRAPH (1), 1, IERR) IF (IERR .NE. 0) THEN PRINT *, 'ERROR : MAIN : Invalid graph output' STOP ENDIF CALL SCOTCHFGRAPHDATA (SCOTCHGRAPH (1), INDXTAB (1), * IDXBASEVAL, IDXVERTNBR, * IDXVERTTABIDX, IDXVENDTABIDX, * IDXVELOTABIDX, IDXVLBLTABIDX, * IDXEDGENBR, * IDXEDGETABIDX, IDXEDLOTABIDX, * IDXFLAGVAL, IERR); IF (IERR .NE. 0) THEN PRINT *, 'ERROR : MAIN : Cannot get graph data' STOP ENDIF PRINT *, 'Number of vertices : ', IDXVERTNBR PRINT *, 'Index of verttab : ', IDXVERTTABIDX PRINT *, 'Index of vendtab : ', IDXVENDTABIDX PRINT *, 'Index of velotab : ', IDXVELOTABIDX PRINT *, 'Index of vlbltab : ', IDXVLBLTABIDX PRINT *, 'Number of edges : ', IDXEDGENBR PRINT *, 'Index of edgetab : ', IDXEDGETABIDX PRINT *, 'Index of edlotab : ', IDXEDLOTABIDX PRINT *, 'Updating vertex and edge arrays' INDXTAB (IDXVERTTABIDX + 1) = 3 INDXTAB (IDXEDGETABIDX) = 2 INDXTAB (IDXEDGETABIDX + 1) = 3 INDXTAB (IDXEDGETABIDX + 2) = 1 INDXTAB (IDXEDGETABIDX + 3) = 1 PRINT *, 'Outputting updated graph' CALL SCOTCHFGRAPHCHECK (SCOTCHGRAPH (1), IERR) IF (IERR .NE. 0) THEN PRINT *, 'ERROR : MAIN : Invalid check' STOP ENDIF CALL SCOTCHFGRAPHSAVE (SCOTCHGRAPH (1), 1, IERR) IF (IERR .NE. 0) THEN PRINT *, 'ERROR : MAIN : Invalid graph output' STOP ENDIF CALL SCOTCHFGRAPHEXIT (SCOTCHGRAPH (1), IERR) IF (IERR .NE. 0) THEN PRINT *, 'ERROR : MAIN : Cannot destroy graph' STOP ENDIF PRINT *, 'Test complete' RETURN END scotch-5.1.12b.dfsg/examples/scotch_example_2.f900000644000175300017530000001046311422605451021752 0ustar hazelscthazelsct!*********************************************************** !* ** !* NAME : scotch_example_2.f90 ** !* ** !* AUTHOR : Francois PELLEGRINI ** !* Frederic COUDERC ** !* ** !* FUNCTION : FORTRAN testbed for the LibSCOTCH ** !* library routines. ** !* ** !* DATES : # Version 5.1 : from : 24 jul 2010 ** !* to 24 jul 2010 ** !* ** !* NOTES : # This program is to be compiled with ** !* the 64-bit version of the libScotch. ** !* It can be deduced from the fact that ** !* SCOTCH_Num values are declared as ** !* "integer*8" quantities. ** !* ** !* # To be compiled with : gfortran ** !* scotch_example_2.f90 ** !* -L/scotch/lib/path/ -lscotch ** !* -lscotcherr -lz -lpthread -lrt ** !* ** !234567***************************************************** PROGRAM Scotch_test ! USE IFPOSIX implicit none include "scotchf.h" real*8, dimension(Scotch_graphdim) :: Scotchgraph real*8, dimension(Scotch_stratdim) :: Scotchstrat integer :: ierr, file_u integer*8 :: nnt, nelt, i, j, k integer*8 :: base, flag, nparts integer*8, dimension(2) :: indxtab integer*8 :: baseval, vertnbr, vertidx, vendidx, veloidx integer*8 :: vlblidx, edgenbr, edgeidx, edloidx real*8, dimension(:,:), allocatable :: coordinates real*8, dimension(:,:), allocatable :: connectivity real*8, dimension(:,:), allocatable :: neighbors integer*8, dimension(:), allocatable :: part write(6,*) 'Starting' call ScotchFstratInit ( Scotchstrat(1), ierr ) if (ierr /= 0) then write(6,*) 'Scotch error : cannot initialize graph' STOP end if call ScotchFgraphInit ( Scotchgraph(1), ierr ) if (ierr /= 0) then write(6,*) 'Scotch error : cannot initialize strat' STOP end if open(10,iostat=ierr,file="bump.grf") ! call PXFFILENO (10, file_u, ierr) file_u = FNUM (10) base = 1 flag = 0 call ScotchFgraphLoad ( Scotchgraph(1), file_u, base, flag, ierr ) if (ierr /= 0) then write(6,*) 'Scotch error : cannot load graph' STOP end if close(10) call ScotchFgraphData ( Scotchgraph(1), indxtab(1), baseval, & vertnbr, vertidx, vendidx, veloidx, vlblidx, edgenbr, & edgeidx, edloidx ) write(6,*) baseval, vertnbr, vertidx, vendidx, veloidx, vlblidx, & edgenbr, edgeidx, edloidx write(6,*) indxtab(vertidx) write(6,*) indxtab(vendidx) write(6,*) indxtab(veloidx) write(6,*) indxtab(vlblidx) write(6,*) indxtab(edgeidx) write(6,*) indxtab(edloidx) call ScotchFgraphCheck ( Scotchgraph(1), ierr ) if (ierr /= 0) then write(6,*) 'ERROR Scotch : Invalid check' STOP end if open (10,iostat=ierr,file="test.grf") ! call PXFFILENO (10, file_u, ierr) file_u = FNUM (10) call ScotchFgraphSave ( Scotchgraph(1), file_u, ierr ) if (ierr /= 0) then write(6,*) 'ERROR Scotch : Invalid save ' STOP end if close(10) nparts = 8 call ScotchFstratGraphMapChoose ( Scotchstrat(1), & SCOTCH_STRATQUALITY, nparts, 0.01, ierr ) if (ierr /= 0) then write(6,*) 'ERROR Scotch : Cannot initialize partitioning& &strategy' STOP end if allocate(part(1:vertnbr + 1)) call ScotchFgraphPart ( Scotchgraph(1), nparts, Scotchstrat(1), & part(1), ierr ) if (ierr /= 0) then write(6,*) 'ERROR Scotch : Cannot partition graph' STOP end if do i=1,vertnbr + 1 write(10,*) i,part(i) end do call ScotchFgraphExit ( Scotchgraph(1) ) call ScotchFstratExit ( Scotchstrat(1) ) write(6,*) 'Complete' END PROGRAM Scotch_test scotch-5.1.12b.dfsg/README.txt0000644000175300017530000000044211145123754016072 0ustar hazelscthazelsctThe terms under which this copy of the Scotch 5.1 distribution is provided to you are described in file "LICENSE_en.txt", located in the same directory as this file. If you accept them, please refer to file "INSTALL.txt", also located in this directory, for the installation instructions. scotch-5.1.12b.dfsg/src/0000755000175300017530000000000011525464722015170 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/src/Makefile0000644000175300017530000001151611525464722016634 0ustar hazelscthazelsct## Copyright 2004,2007-2011 ENSEIRB, INRIA & CNRS ## ## This file is part of the Scotch software package for static mapping, ## graph partitioning and sparse matrix ordering. ## ## This software is governed by the CeCILL-C license under French law ## and abiding by the rules of distribution of free software. You can ## use, modify and/or redistribute the software under the terms of the ## CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ## URL: "http://www.cecill.info". ## ## As a counterpart to the access to the source code and rights to copy, ## modify and redistribute granted by the license, users are provided ## only with a limited warranty and the software's author, the holder of ## the economic rights, and the successive licensors have only limited ## liability. ## ## In this respect, the user's attention is drawn to the risks associated ## with loading, using, modifying and/or developing or reproducing the ## software by the user in light of its specific status of free software, ## that may mean that it is complicated to manipulate, and that also ## therefore means that it is reserved for developers and experienced ## professionals having in-depth computer knowledge. Users are therefore ## encouraged to load and test the software's suitability as regards ## their requirements in conditions enabling the security of their ## systems and/or data to be ensured and, more generally, to use and ## operate it in the same conditions as regards security. ## ## The fact that you are presently reading this means that you have had ## knowledge of the CeCILL-C license and that you accept its terms. ## VERSION = 5 RELEASE = 1 PATCHLEVEL = 12 .PHONY : clean default install ptscotch realclean required scotch default : scotch required : Makefile.inc ../bin ../include ../lib Makefile.inc : @echo "#####################################################################" @echo "BEFORE COMPILING Scotch OR PT-Scotch, YOU SHOULD HAVE AN APPROPRIATE" @echo "Makefile.inc FILE IN THIS DIRECTORY. PLEASE LOOK INTO DIRECTORY" @echo " ./Make.inc FOR AN EXISTING Makefile.inc FILE THAT FITS YOUR NEED, OR" @echo "USE THEM AS MODELS IN CASE YOU NEED TO BUILD A NEW ONE FOR YOUR" @echo "PARTICULAR PLATFORM." @echo "#####################################################################" @echo "Then, type \"make scotch\" (default) for the sequential library" @echo "and software, or \"make ptscotch\" for the parallel library and" @echo "software." @exit 1 include Makefile.inc prefix ?= /usr/local bindir ?= $(prefix)/bin includedir ?= $(prefix)/include libdir ?= $(prefix)/lib datarootdir ?= $(prefix)/share mandir ?= $(datarootdir)/man ../bin : -$(MKDIR) ../bin ../include : -$(MKDIR) ../include ../lib : -$(MKDIR) ../lib $(bindir) : -$(MKDIR) $(bindir) $(datarootdir) : -$(MKDIR) $(datarootdir) $(includedir) : -$(MKDIR) $(includedir) $(libdir) : -$(MKDIR) $(libdir) $(mandir) : $(datarootdir) -$(MKDIR) $(mandir) $(mandir)/man1 : $(mandir) -$(MKDIR) $(mandir)/man1 scotch : required (cd libscotch ; $(MAKE) VERSION=$(VERSION) RELEASE=$(RELEASE) PATCHLEVEL=$(PATCHLEVEL) scotch && $(MAKE) install) (cd scotch ; $(MAKE) VERSION=$(VERSION) RELEASE=$(RELEASE) PATCHLEVEL=$(PATCHLEVEL) scotch && $(MAKE) install) (cd libscotchmetis ; $(MAKE) scotch && $(MAKE) install) (cd esmumps ; $(MAKE) scotch && $(MAKE) install) ptscotch : required (cd libscotch ; $(MAKE) VERSION=$(VERSION) RELEASE=$(RELEASE) PATCHLEVEL=$(PATCHLEVEL) ptscotch && $(MAKE) ptinstall) (cd scotch ; $(MAKE) VERSION=$(VERSION) RELEASE=$(RELEASE) PATCHLEVEL=$(PATCHLEVEL) ptscotch && $(MAKE) ptinstall) (cd libscotchmetis ; $(MAKE) ptscotch && $(MAKE) ptinstall) (cd esmumps ; $(MAKE) ptscotch && $(MAKE) ptinstall) install : required $(bindir) $(includedir) $(libdir) $(mandir)/man1 -$(CP) -f ../bin/[agm]*$(EXE) $(bindir) -$(CP) -f ../include/*scotch*.h $(includedir) -$(CP) -f ../lib/*scotch*$(LIB) $(libdir) -$(CP) -Rf ../man/* $(mandir) clean : required (cd libscotch ; $(MAKE) clean) (cd scotch ; $(MAKE) clean) (cd libscotchmetis ; $(MAKE) clean) (cd esmumps ; $(MAKE) clean) realclean : required (cd libscotch ; $(MAKE) realclean) (cd scotch ; $(MAKE) realclean) (cd libscotchmetis ; $(MAKE) realclean) (cd esmumps ; $(MAKE) realclean) -$(RM) ../bin/* ../include/* ../lib/* scotch-5.1.12b.dfsg/src/libscotchmetis/0000755000175300017530000000000011212504510020163 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/src/libscotchmetis/Makefile0000644000175300017530000001033211466263523021643 0ustar hazelscthazelsct## Copyright 2007-2010 ENSEIRB, INRIA & CNRS ## ## This file is part of the Scotch software package for static mapping, ## graph partitioning and sparse matrix ordering. ## ## This software is governed by the CeCILL-C license under French law ## and abiding by the rules of distribution of free software. You can ## use, modify and/or redistribute the software under the terms of the ## CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ## URL: "http://www.cecill.info". ## ## As a counterpart to the access to the source code and rights to copy, ## modify and redistribute granted by the license, users are provided ## only with a limited warranty and the software's author, the holder of ## the economic rights, and the successive licensors have only limited ## liability. ## ## In this respect, the user's attention is drawn to the risks associated ## with loading, using, modifying and/or developing or reproducing the ## software by the user in light of its specific status of free software, ## that may mean that it is complicated to manipulate, and that also ## therefore means that it is reserved for developers and experienced ## professionals having in-depth computer knowledge. Users are therefore ## encouraged to load and test the software's suitability as regards ## their requirements in conditions enabling the security of their ## systems and/or data to be ensured and, more generally, to use and ## operate it in the same conditions as regards security. ## ## The fact that you are presently reading this means that you have had ## knowledge of the CeCILL-C license and that you accept its terms. ## bindir = ../../bin includedir = ../../include libdir = ../../lib ## ## General inference rules. ## include ../Makefile.inc %$(OBJ) : %.c $(CC) $(CFLAGS) $(CLIBFLAGS) -I$(includedir) -I../libscotch -c $(<) -o $(@) %$(EXE) : %.c $(CC) $(CFLAGS) -I$(includedir) -I../libscotch $(<) -o $(@) -L$(libdir) $(LDFLAGS) ## ## Project rules. ## .PHONY : ptscotch scotch ptinstall install clean realclean scotch : $(MAKE) CC="$(CCS)" SCOTCHLIB=ptscotch \ libscotchmetis$(LIB) ptscotch : $(MAKE) CFLAGS="$(CFLAGS) -DSCOTCH_PTSCOTCH" CC="$(CCP)" SCOTCHLIB=ptscotch \ libptscotchparmetis$(LIB) install : scotch -$(CP) metis.h $(includedir) -$(CP) libscotchmetis$(LIB) $(libdir) ptinstall : ptscotch -$(CP) parmetis.h $(includedir) -$(CP) libptscotchparmetis$(LIB) $(libdir) clean : -$(RM) *~ *$(OBJ) lib*$(LIB) realclean : clean ## ## Todo list. ## metis_graph_order$(OBJ) : metis_graph_order.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ metis.h metis_graph_order_f$(OBJ) : metis_graph_order_f.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ metis.h metis_graph_part$(OBJ) : metis_graph_part.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ metis.h metis_graph_part_f$(OBJ) : metis_graph_part_f.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ metis.h parmetis_dgraph_order$(OBJ) : parmetis_dgraph_order.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/ptscotch.h \ parmetis.h parmetis_dgraph_order_f$(OBJ) : parmetis_dgraph_order_f.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/ptscotch.h \ parmetis.h parmetis_dgraph_part$(OBJ) : parmetis_dgraph_part.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/ptscotch.h \ parmetis.h parmetis_dgraph_part_f$(OBJ) : parmetis_dgraph_part_f.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/ptscotch.h \ parmetis.h libptscotchparmetis$(LIB) : parmetis_dgraph_order$(OBJ) \ parmetis_dgraph_order_f$(OBJ) \ parmetis_dgraph_part$(OBJ) \ parmetis_dgraph_part_f$(OBJ) $(AR) $(ARFLAGS) $(@) $(^) -$(RANLIB) $(@) libscotchmetis$(LIB) : metis_graph_order$(OBJ) \ metis_graph_order_f$(OBJ) \ metis_graph_part$(OBJ) \ metis_graph_part_f$(OBJ) $(AR) $(ARFLAGS) $(@) $(^) -$(RANLIB) $(@) scotch-5.1.12b.dfsg/src/libscotchmetis/parmetis.h0000644000175300017530000001173311412721201022165 0ustar hazelscthazelsct/********************************************************* ** ** ** WARNING: THIS IS NOT THE ORIGINAL INCLUDE FILE OF ** ** THE ParMeTiS SOFTWARE PACKAGE. ** ** This file is a compatibility include file provided ** ** as part of the Scotch software distribution. ** ** Preferably use the original ParMeTiS include file ** ** to keep definitions of routines not overloaded by ** ** the libPTScotchMeTiS library. ** ** ** *********************************************************/ /* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : parmetis.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Compatibility declaration file for the **/ /** MeTiS interface routines provided by **/ /** the Scotch project. **/ /** **/ /** DATES : # Version 5.0 : from : 17 oct 2007 **/ /** to 18 oct 2007 **/ /** # Version 5.1 : from : 19 jun 2008 **/ /** to 30 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #ifndef __parmetis_h__ #define __parmetis_h__ #include /* Since ParMeTiS does it, do it too */ #endif /* __parmetis_h__ */ #ifdef SCOTCH_METIS_PREFIX #define SCOTCH_METIS_PREFIXL scotch_ #define SCOTCH_METIS_PREFIXU SCOTCH_ #endif /* SCOTCH_METIS_PREFIX */ #ifndef SCOTCH_METIS_PREFIXL #define SCOTCH_METIS_PREFIXL #endif /* SCOTCH_METIS_PREFIXL */ #ifndef SCOTCH_METIS_PREFIXU #define SCOTCH_METIS_PREFIXU #endif /* SCOTCH_METIS_PREFIXU */ #ifndef METISNAMEL #define METISNAMEL(s) METISNAME2(METISNAME3(SCOTCH_METIS_PREFIXL),s) #define METISNAMEU(s) METISNAME2(METISNAME3(SCOTCH_METIS_PREFIXU),s) #define METISNAME2(p,s) METISNAME4(p,s) #define METISNAME3(s) s #define METISNAME4(p,s) p##s #endif /* METISNAMEL */ /* ** The function prototypes. */ void METISNAMEU(ParMETIS_V3_NodeND) (const int * const, int * const, int * const, const int * const, const int * const, int * const, int * const, MPI_Comm * const); void METISNAMEU(ParMETIS_V3_PartGeomKway) (const int * const, int * const, int * const, int * const, int * const, const int * const, const int * const, const int * const, const float * const, const int * const, const int * const, const float * const, const float * const, const int * const, int * const, int * const, MPI_Comm * const); void METISNAMEU(ParMETIS_V3_PartKway) (const int * const, int * const, int * const, int * const, int * const, const int * const, const int * const, const int * const, const int * const, const float * const, const float * const, const int * const, int * const, int * const, MPI_Comm * const); scotch-5.1.12b.dfsg/src/libscotchmetis/metis_graph_part_f.c0000644000175300017530000001471011412716504024201 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : metis_graph_part_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API of **/ /** the compatibility library for the **/ /** MeTiS partitioning routines. **/ /** **/ /** DATES : # Version 5.0 : from : 10 sep 2006 **/ /** to 07 jun 2007 **/ /** # Version 5.1 : from : 30 jun 2010 **/ /** to 30 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "common.h" #include "scotch.h" #include "metis.h" /* Our "metis.h" file */ /**************************************/ /* */ /* These routines are the Fortran API */ /* for the graph ordering routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ METISNAMEU(METIS_PARTGRAPHKWAY), METISNAMEL(metis_partgraphkway), ( \ const int * const n, \ const int * const xadj, \ const int * const adjncy, \ const int * const vwgt, \ const int * const adjwgt, \ const int * const wgtflag, \ const int * const numflag, \ const int * const nparts, \ const int * const options, \ int * const edgecut, \ int * const part), \ (n, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part)) { METISNAMEU(METIS_PartGraphKway) (n, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part); } /* ** */ FORTRAN ( \ METISNAMEU(METIS_PARTGRAPHRECURSIVE), METISNAMEL(metis_partgraphrecursive), ( \ const int * const n, \ const int * const xadj, \ const int * const adjncy, \ const int * const vwgt, \ const int * const adjwgt, \ const int * const wgtflag, \ const int * const numflag, \ const int * const nparts, \ const int * const options, \ int * const edgecut, \ int * const part), \ (n, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part)) { METISNAMEU(METIS_PartGraphRecursive) (n, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part); } /* ** */ FORTRAN ( \ METISNAMEU(METIS_PARTGRAPHVKWAY), METISNAMEL(metis_partgraphvkway), ( \ const int * const n, \ const int * const xadj, \ const int * const adjncy, \ const int * const vwgt, \ const int * const vsize, \ const int * const wgtflag, \ const int * const numflag, \ const int * const nparts, \ const int * const options, \ int * const volume, \ int * const part), \ (n, xadj, adjncy, vwgt, vsize, wgtflag, numflag, nparts, options, volume, part)) { METISNAMEU(METIS_PartGraphVKway) (n, xadj, adjncy, vwgt, vsize, wgtflag, numflag, nparts, options, volume, part); } scotch-5.1.12b.dfsg/src/libscotchmetis/metis_graph_order.c0000644000175300017530000001236711412716504024047 0ustar hazelscthazelsct/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : metis_graph_order.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the compatibility **/ /** library for the MeTiS ordering **/ /** routines. **/ /** **/ /** DATES : # Version 5.0 : from : 08 sep 2006 **/ /** to 07 jun 2007 **/ /** # Version 5.1 : from : 30 jun 2010 **/ /** to 30 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" #include "metis.h" /* Our "metis.h" file */ /************************************/ /* */ /* These routines are the C API for */ /* MeTiS graph ordering routines. */ /* */ /************************************/ /* ** */ void METISNAMEU(METIS_EdgeND) ( const int * const n, const int * const xadj, const int * const adjncy, const int * const numflag, const int * const options, int * const perm, int * const iperm) { METISNAMEU(METIS_NodeWND) (n, xadj, adjncy, NULL, numflag, options, perm, iperm); } /* ** */ void METISNAMEU(METIS_NodeND) ( const int * const n, const int * const xadj, const int * const adjncy, const int * const numflag, const int * const options, int * const perm, int * const iperm) { METISNAMEU(METIS_NodeWND) (n, xadj, adjncy, NULL, numflag, options, perm, iperm); } /* ** */ void METISNAMEU(METIS_NodeWND) ( const int * const n, const int * const xadj, const int * const adjncy, const int * const vwgt, const int * const numflag, const int * const options, int * const perm, int * const iperm) { SCOTCH_Graph grafdat; /* Scotch graph object to interface with libScotch */ SCOTCH_Ordering ordedat; /* Scotch ordering object to interface with libScotch */ SCOTCH_Strat stradat; if (sizeof (SCOTCH_Num) != sizeof (int)) { SCOTCH_errorPrint ("METIS_*ND (as of SCOTCH): SCOTCH_Num type should equate to int"); return; } SCOTCH_graphInit (&grafdat); if (SCOTCH_graphBuild (&grafdat, *numflag, *n, xadj, xadj + 1, vwgt, NULL, xadj[*n] - *numflag, adjncy, NULL) == 0) { SCOTCH_stratInit (&stradat); #ifdef SCOTCH_DEBUG_ALL if (SCOTCH_graphCheck (&grafdat) == 0) /* TRICK: next instruction called only if graph is consistent */ #endif /* SCOTCH_DEBUG_ALL */ { if (SCOTCH_graphOrderInit (&grafdat, &ordedat, iperm, perm, /* MeTiS and Scotch have opposite definitions for (inverse) permutations */ NULL, NULL, NULL) == 0) { SCOTCH_graphOrderCompute (&grafdat, &ordedat, &stradat); SCOTCH_graphOrderExit (&grafdat, &ordedat); } } SCOTCH_stratExit (&stradat); } SCOTCH_graphExit (&grafdat); } scotch-5.1.12b.dfsg/src/libscotchmetis/parmetis_dgraph_order.c0000644000175300017530000002306211412716504024710 0ustar hazelscthazelsct/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : parmetis_dgraph_order.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the compatibility **/ /** library for the ParMeTiS ordering **/ /** routines. **/ /** **/ /** DATES : # Version 5.0 : from : 17 oct 2007 **/ /** to 07 dec 2007 **/ /** # Version 5.1 : from : 18 mar 2009 **/ /** to 30 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "ptscotch.h" #include "parmetis.h" /* Our "parmetis.h" file */ /************************************/ /* */ /* These routines are the C API for */ /* the ParMeTiS graph ordering */ /* routine. */ /* */ /************************************/ static void _SCOTCH_ParMETIS_V3_NodeNDTree ( int * const sizeglbtnd, SCOTCH_Num * const sizeglbtab, SCOTCH_Num * const sepaglbtab, const int levlmax, const int levlnum, const int cblknum, int cblkidx) { int sizeval; sizeval = sizeglbtab[cblknum]; /* Assume node is terminal or has no nested dissection sons */ if (levlnum < levlmax) { if ((sepaglbtab[3 * cblknum] >= 0) && /* If node has at least two sons, assume is is a nested dissection node */ (sepaglbtab[3 * cblknum + 1] >= 0)) { _SCOTCH_ParMETIS_V3_NodeNDTree (sizeglbtnd, sizeglbtab, sepaglbtab, levlmax, levlnum + 1, sepaglbtab[3 * cblknum], (cblkidx << 1) + 1); _SCOTCH_ParMETIS_V3_NodeNDTree (sizeglbtnd, sizeglbtab, sepaglbtab, levlmax, levlnum + 1, sepaglbtab[3 * cblknum + 1], (cblkidx << 1)); sizeval = (sepaglbtab[3 * cblknum + 2] < 0) ? 0 : sizeglbtab[sepaglbtab[3 * cblknum + 2]]; /* Get size of separator, if any */ } } sizeglbtnd[- cblkidx] = sizeval; /* Set size of current column block */ } /* ** */ void METISNAMEU(ParMETIS_V3_NodeND) ( const int * const vtxdist, int * const xadj, int * const adjncy, const int * const numflag, const int * const options, /* Not used */ int * const order, int * const sizes, /* Of size twice the number of processors ; not used */ MPI_Comm * comm) { MPI_Comm proccomm; int procglbnbr; int proclocnum; SCOTCH_Num baseval; SCOTCH_Dgraph grafdat; /* Scotch distributed graph object to interface with libScotch */ SCOTCH_Dordering ordedat; /* Scotch distributed ordering object to interface with libScotch */ SCOTCH_Strat stradat; SCOTCH_Num vertlocnbr; SCOTCH_Num edgelocnbr; if (sizeof (SCOTCH_Num) != sizeof (int)) { SCOTCH_errorPrint ("ParMETIS_V3_NodeND (as of SCOTCH): SCOTCH_Num type should equate to int"); return; } proccomm = *comm; if (SCOTCH_dgraphInit (&grafdat, proccomm) != 0) return; MPI_Comm_size (proccomm, &procglbnbr); MPI_Comm_rank (proccomm, &proclocnum); baseval = *numflag; vertlocnbr = vtxdist[proclocnum + 1] - vtxdist[proclocnum]; edgelocnbr = xadj[vertlocnbr] - baseval; if (sizes != NULL) memSet (sizes, ~0, (2 * procglbnbr - 1) * sizeof (int)); /* Array not used if procglbnbr is not a power of 2 or if error */ if (SCOTCH_dgraphBuild (&grafdat, baseval, vertlocnbr, vertlocnbr, xadj, xadj + 1, NULL, NULL, edgelocnbr, edgelocnbr, adjncy, NULL, NULL) == 0) { SCOTCH_stratInit (&stradat); #ifdef SCOTCH_DEBUG_ALL if (SCOTCH_dgraphCheck (&grafdat) == 0) /* TRICK: next instruction called only if graph is consistent */ #endif /* SCOTCH_DEBUG_ALL */ { if (SCOTCH_dgraphOrderInit (&grafdat, &ordedat) == 0) { int levlmax; int bitsnbr; SCOTCH_Num proctmp; SCOTCH_dgraphOrderCompute (&grafdat, &ordedat, &stradat); SCOTCH_dgraphOrderPerm (&grafdat, &ordedat, order); for (levlmax = -1, bitsnbr = 0, proctmp = procglbnbr; /* Count number of bits set to 1 in procglbnbr */ proctmp != 0; levlmax ++, proctmp >>= 1) bitsnbr += proctmp & 1; if (bitsnbr == 1) { SCOTCH_Num cblkglbnbr; if ((cblkglbnbr = SCOTCH_dgraphOrderCblkDist (&grafdat, &ordedat)) >= 0) { SCOTCH_Num * treeglbtab; SCOTCH_Num * sizeglbtab; SCOTCH_Num * sepaglbtab; if (memAllocGroup ((void **) (void *) &treeglbtab, (size_t) (cblkglbnbr * sizeof (SCOTCH_Num)), &sizeglbtab, (size_t) (cblkglbnbr * sizeof (SCOTCH_Num)), &sepaglbtab, (size_t) (cblkglbnbr * sizeof (SCOTCH_Num) * 3), NULL) != NULL) { if (SCOTCH_dgraphOrderTreeDist (&grafdat, &ordedat, treeglbtab, sizeglbtab) == 0) { SCOTCH_Num rootnum; SCOTCH_Num cblknum; memSet (sepaglbtab, ~0, cblkglbnbr * sizeof (SCOTCH_Num) * 3); for (rootnum = -1, cblknum = 0; cblknum < cblkglbnbr; cblknum ++) { SCOTCH_Num fathnum; fathnum = treeglbtab[cblknum] - baseval; /* Use un-based indices */ if (fathnum < 0) { /* If father index indicates root */ if (rootnum != -1) { /* If another root already found */ rootnum = -1; /* Indicate an error */ break; } rootnum = cblknum; /* Record index of root node */ } else { int i; for (i = 0; i < 3; i ++) { int j; j = 3 * fathnum + i; /* Slot number of prospective son */ if (sepaglbtab[j] < 0) { /* If potentially empty slot found */ if (sepaglbtab[j] == -1) /* If we don't have too many sons */ sepaglbtab[j] = cblknum; /* Add link to son in slot */ break; } } if (i == 3) { /* If no empty slot found */ sepaglbtab[3 * fathnum] = -2; /* Indicate there are too many sons */ break; } } } if ((rootnum >= 0) && (sizes != NULL)) { /* If no error above, go on processing separator tree */ memSet (sizes, 0, (2 * procglbnbr - 1) * sizeof (int)); /* Set array of sizes to 0 by default */ _SCOTCH_ParMETIS_V3_NodeNDTree (sizes + (2 * procglbnbr - 1), sizeglbtab, sepaglbtab, levlmax, 0, rootnum, 1); } } memFree (treeglbtab); /* Free group leader */ } } } SCOTCH_dgraphOrderExit (&grafdat, &ordedat); } } SCOTCH_stratExit (&stradat); } SCOTCH_dgraphExit (&grafdat); } scotch-5.1.12b.dfsg/src/libscotchmetis/metis.h0000644000175300017530000001237011412721201021460 0ustar hazelscthazelsct/********************************************************* ** ** ** WARNING: THIS IS NOT THE ORIGINAL INCLUDE FILE OF ** ** THE MeTiS SOFTWARE PACKAGE. ** ** This file is a compatibility include file provided ** ** as part of the Scotch software distribution. ** ** Preferably use the original MeTiS include file to ** ** keep definitions of routines not overloaded by ** ** the libScotchMeTiS library. ** ** ** *********************************************************/ /* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : metis.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Compatibility declaration file for the **/ /** MeTiS interface routines provided by **/ /** the Scotch project. **/ /** **/ /** DATES : # Version 5.0 : from : 08 sep 2006 **/ /** to 07 jun 2007 **/ /** # Version 5.1 : from : 30 jun 2010 **/ /** to 30 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines. */ #ifdef SCOTCH_METIS_PREFIX #define SCOTCH_METIS_PREFIXL scotch_ #define SCOTCH_METIS_PREFIXU SCOTCH_ #endif /* SCOTCH_METIS_PREFIX */ #ifndef SCOTCH_METIS_PREFIXL #define SCOTCH_METIS_PREFIXL #endif /* SCOTCH_METIS_PREFIXL */ #ifndef SCOTCH_METIS_PREFIXU #define SCOTCH_METIS_PREFIXU #endif /* SCOTCH_METIS_PREFIXU */ #ifndef METISNAMEL #define METISNAMEL(s) METISNAME2(METISNAME3(SCOTCH_METIS_PREFIXL),s) #define METISNAMEU(s) METISNAME2(METISNAME3(SCOTCH_METIS_PREFIXU),s) #define METISNAME2(p,s) METISNAME4(p,s) #define METISNAME3(s) s #define METISNAME4(p,s) p##s #endif /* METISNAMEL */ /* ** The function prototypes. */ void METISNAMEU(METIS_EdgeND) (const int * const, const int * const, const int * const, const int * const, const int * const, int * const, int * const); void METISNAMEU(METIS_NodeND) (const int * const, const int * const, const int * const, const int * const, const int * const, int * const, int * const); void METISNAMEU(METIS_NodeWND) (const int * const, const int * const, const int * const, const int * const, const int * const, const int * const, int * const, int * const); void METISNAMEU(METIS_PartGraphKway) (const int * const, const int * const, const int * const, const int * const, const int * const, const int * const, const int * const, const int * const, const int * const, int * const, int * const); void METISNAMEU(METIS_PartGraphRecursive) (const int * const, const int * const, const int * const, const int * const, const int * const, const int * const, const int * const, const int * const, const int * const, int * const, int * const); void METISNAMEU(METIS_PartGraphVKway) (const int * const, const int * const, const int * const, const int * const, const int * const, const int * const, const int * const, const int * const, const int * const, int * const, int * const); scotch-5.1.12b.dfsg/src/libscotchmetis/parmetis_dgraph_order_f.c0000644000175300017530000000760511412716504025222 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : parmetis_dgraph_order_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API of **/ /** the compatibility library for the **/ /** ParMeTiS ordering routine. **/ /** **/ /** DATES : # Version 5.0 : from : 17 oct 2007 **/ /** to 17 oct 2007 **/ /** # Version 5.1 : from : 30 jun 2010 **/ /** to 30 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "common.h" #include "ptscotch.h" #include "parmetis.h" /* Our "parmetis.h" file */ /**************************************/ /* */ /* These routines are the Fortran API */ /* for the distributed graph ordering */ /* routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ METISNAMEU(PARMETIS_V3_NODEND), METISNAMEL(parmetis_v3_nodend), ( \ const int * const vtxdist, \ int * const xadj, \ int * const adjncy, \ const int * const numflag, \ const int * const options, \ int * const order, \ int * const sizes, \ MPI_Comm * const commptr), \ (vtxdist, xadj, adjncy, numflag, options, order, sizes, commptr)) { METISNAMEU(ParMETIS_V3_NodeND) (vtxdist, xadj, adjncy, numflag, options, order, sizes, commptr); } scotch-5.1.12b.dfsg/src/libscotchmetis/parmetis_dgraph_part_f.c0000644000175300017530000001425311412716504025052 0ustar hazelscthazelsct/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : parmetis_dgraph_part_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API of **/ /** the compatibility library for the **/ /** ParMeTiS partitioning routine. **/ /** **/ /** DATES : # Version 5.1 : from : 19 jun 2008 **/ /** to 30 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "common.h" #include "ptscotch.h" #include "parmetis.h" /* Our "parmetis.h" file */ /**************************************/ /* */ /* These routines are the Fortran API */ /* for the distributed graph ordering */ /* routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ METISNAMEU(PARMETIS_V3_PARTKWAY), METISNAMEL(parmetis_v3_partkway), ( \ const int * const vtxdist, \ int * const xadj, \ int * const adjncy, \ int * const vwgt, \ int * const adjwgt, \ const int * const wgtflag, \ const int * const numflag, \ const int * const ncon, \ const int * const nparts, \ const float * const tpwgts, \ const float * const ubvec, \ const int * const options, \ int * const edgecut, \ int * const part, \ MPI_Comm * const commptr), \ (vtxdist, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, ncon, nparts, tpwgts, ubvec, options, edgecut, part, commptr)) { METISNAMEU(ParMETIS_V3_PartKway) (vtxdist, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, ncon, nparts, tpwgts, ubvec, options, edgecut, part, commptr); } /* ** */ FORTRAN ( \ METISNAMEU(PARMETIS_V3_PARTGEOMKWAY), METISNAMEL(parmetis_v3_partgeomkway), ( \ const int * const vtxdist, \ int * const xadj, \ int * const adjncy, \ int * const vwgt, \ int * const adjwgt, \ const int * const wgtflag, \ const int * const numflag, \ const int * const ndims, \ const float * const xyz, \ const int * const ncon, \ const int * const nparts, \ const float * const tpwgts, \ const float * const ubvec, \ const int * const options, \ int * const edgecut, \ int * const part, \ MPI_Comm * const commptr), \ (vtxdist, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, ndims, xyz, ncon, nparts, tpwgts, ubvec, options, edgecut, part, commptr)) { METISNAMEU(ParMETIS_V3_PartGeomKway) (vtxdist, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, ndims, xyz, ncon, nparts, tpwgts, ubvec, options, edgecut, part, commptr); } scotch-5.1.12b.dfsg/src/libscotchmetis/parmetis_dgraph_part.c0000644000175300017530000001705311412716504024546 0ustar hazelscthazelsct/* Copyright 2008-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : parmetis_dgraph_part.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the compatibility **/ /** library for the ParMeTiS ordering **/ /** routines. **/ /** **/ /** DATES : # Version 5.1 : from : 19 jun 2008 **/ /** to 30 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "ptscotch.h" #include "parmetis.h" /* Our "parmetis.h" file */ /************************************/ /* */ /* These routines are the C API for */ /* the ParMeTiS graph ordering */ /* routine. */ /* */ /************************************/ void METISNAMEU(ParMETIS_V3_PartKway) ( const int * const vtxdist, int * const xadj, int * const adjncy, int * const vwgt, int * const adjwgt, const int * const wgtflag, const int * const numflag, const int * const ncon, /* Not used */ const int * const nparts, const float * const tpwgts, const float * const ubvec, /* Not used */ const int * const options, /* Not used */ int * const edgecut, int * const part, MPI_Comm * comm) { MPI_Comm proccomm; int procglbnbr; int proclocnum; SCOTCH_Num baseval; SCOTCH_Arch archdat; SCOTCH_Dgraph grafdat; /* Scotch distributed graph object to interface with libScotch */ SCOTCH_Dmapping mappdat; /* Scotch distributed mapping object to interface with libScotch */ SCOTCH_Strat stradat; SCOTCH_Num vertlocnbr; SCOTCH_Num * veloloctab; SCOTCH_Num edgelocnbr; SCOTCH_Num * edloloctab; SCOTCH_Num * velotab; double * vwgttab; int i; if (sizeof (SCOTCH_Num) != sizeof (int)) { SCOTCH_errorPrint ("ParMETIS_V3_PartKway (as of SCOTCH): SCOTCH_Num type should equate to int"); return; } if ((vwgttab = malloc (*nparts * sizeof (double))) == NULL) return; if ((velotab = malloc (*nparts * sizeof (SCOTCH_Num))) == NULL) { free (vwgttab); return; } for (i = 0; i < *nparts; i ++) vwgttab[i] = (double) tpwgts[i] * (double) (*nparts); for (i = 0; i < *nparts; i ++) { double deltval; deltval = fabs (vwgttab[i] - floor (vwgttab[i] + 0.5)); if (deltval > 0.01) { int j; deltval = 1.0 / deltval; for (j = 0; j < *nparts; j ++) vwgttab[j] *= deltval; } } for (i = 0; i < *nparts; i ++) velotab[i] = (SCOTCH_Num) (vwgttab[i] + 0.5); proccomm = *comm; if (SCOTCH_dgraphInit (&grafdat, proccomm) != 0) return; MPI_Comm_size (proccomm, &procglbnbr); MPI_Comm_rank (proccomm, &proclocnum); baseval = *numflag; vertlocnbr = vtxdist[proclocnum + 1] - vtxdist[proclocnum]; edgelocnbr = xadj[vertlocnbr] - baseval; veloloctab = ((vwgt != NULL) && ((*wgtflag & 2) != 0)) ? vwgt : NULL; edloloctab = ((adjwgt != NULL) && ((*wgtflag & 1) != 0)) ? adjwgt : NULL; if (SCOTCH_dgraphBuild (&grafdat, baseval, vertlocnbr, vertlocnbr, xadj, xadj + 1, veloloctab, NULL, edgelocnbr, edgelocnbr, adjncy, NULL, edloloctab) == 0) { SCOTCH_stratInit (&stradat); #ifdef SCOTCH_DEBUG_ALL if (SCOTCH_dgraphCheck (&grafdat) == 0) /* TRICK: next instruction called only if graph is consistent */ #endif /* SCOTCH_DEBUG_ALL */ { SCOTCH_archInit (&archdat); if ((SCOTCH_archCmpltw (&archdat, *nparts, velotab) == 0) && (SCOTCH_dgraphMapInit (&grafdat, &mappdat, &archdat, part) == 0)) { SCOTCH_dgraphMapCompute (&grafdat, &mappdat, &stradat); SCOTCH_dgraphMapExit (&grafdat, &mappdat); } SCOTCH_archExit (&archdat); } SCOTCH_stratExit (&stradat); } SCOTCH_dgraphExit (&grafdat); *edgecut = 0; /* TODO : compute real edge cut for people who might want it */ free (vwgttab); free (velotab); if (baseval != 0) { /* MeTiS part array is based, Scotch is not */ SCOTCH_Num vertlocnum; for (vertlocnum = 0; vertlocnum < vertlocnbr; vertlocnum ++) part[vertlocnum] += baseval; } } /* ** */ void METISNAMEU(ParMETIS_V3_PartGeomKway) ( const int * const vtxdist, int * const xadj, int * const adjncy, int * const vwgt, int * const adjwgt, const int * const wgtflag, const int * const numflag, const int * const ndims, /* Not used */ const float * const xyz, /* Not used */ const int * const ncon, /* Not used */ const int * const nparts, const float * const tpwgts, const float * const ubvec, const int * const options, /* Not used */ int * const edgecut, int * const part, MPI_Comm * commptr) { METISNAMEU(ParMETIS_V3_PartKway) (vtxdist, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, ncon, nparts, tpwgts, ubvec, options, edgecut, part, commptr); } scotch-5.1.12b.dfsg/src/libscotchmetis/metis_graph_part.c0000644000175300017530000002644511412716504023704 0ustar hazelscthazelsct/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : metis_graph_part.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the compatibility **/ /** library for the MeTiS partitioning **/ /** routines. **/ /** **/ /** DATES : # Version 5.0 : from : 08 sep 2006 **/ /** to 07 jun 2007 **/ /** # Version 5.1 : from : 06 jun 2009 **/ /** to 30 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" #include "metis.h" /* Our "metis.h" file */ /************************************/ /* */ /* These routines are the C API for */ /* MeTiS graph ordering routines. */ /* */ /************************************/ /* This routine is the interface between MeTiS ** and Scotch. It computes the partition of a ** weighted or unweighted graph. ** It returns: ** - 0 : if the partition could be computed. ** - !0 : on error. */ static int _SCOTCH_METIS_PartGraph ( const int * const n, const int * const xadj, const int * const adjncy, const int * const vwgt, const int * const adjwgt, const int * const numflag, const int * const nparts, int * const part) { SCOTCH_Graph grafdat; /* Scotch graph object to interface with libScotch */ SCOTCH_Strat stradat; SCOTCH_Num baseval; SCOTCH_Num vertnbr; int o; if (sizeof (SCOTCH_Num) != sizeof (int)) { errorPrint ("METIS_PartGraph* (as of SCOTCH): SCOTCH_Num type should equate to int"); return (1); } SCOTCH_graphInit (&grafdat); baseval = *numflag; vertnbr = *n; o = 1; /* Assume something will go wrong */ if (SCOTCH_graphBuild (&grafdat, baseval, vertnbr, xadj, xadj + 1, vwgt, NULL, xadj[vertnbr] - baseval, adjncy, adjwgt) == 0) { SCOTCH_stratInit (&stradat); #ifdef SCOTCH_DEBUG_ALL if (SCOTCH_graphCheck (&grafdat) == 0) /* TRICK: next instruction called only if graph is consistent */ #endif /* SCOTCH_DEBUG_ALL */ o = SCOTCH_graphPart (&grafdat, *nparts, &stradat, part); SCOTCH_stratExit (&stradat); } SCOTCH_graphExit (&grafdat); if (baseval != 0) { /* MeTiS part array is based, Scotch is not */ SCOTCH_Num vertnum; for (vertnum = 0; vertnum < vertnbr; vertnum ++) part[vertnum] += baseval; } return (o); } /* ** */ void METISNAMEU(METIS_PartGraphKway) ( const int * const n, const int * const xadj, const int * const adjncy, const int * const vwgt, const int * const adjwgt, const int * const wgtflag, const int * const numflag, const int * const nparts, const int * const options, int * const edgecut, int * const part) { METISNAMEU(METIS_PartGraphRecursive) (n, xadj, adjncy, vwgt, adjwgt, wgtflag, numflag, nparts, options, edgecut, part); } void METISNAMEU(METIS_PartGraphRecursive) ( const int * const n, const int * const xadj, const int * const adjncy, const int * const vwgt, const int * const adjwgt, const int * const wgtflag, const int * const numflag, const int * const nparts, const int * const options, int * const edgecut, int * const part) { const int * vwgt2; const int * adjwgt2; const int * restrict parttax; const int * restrict verttax; const int * restrict edgetax; int vertnnd; int vertnum; int edgenum; int commcut; vwgt2 = (((*wgtflag & 2) != 0) ? vwgt : NULL); adjwgt2 = (((*wgtflag & 1) != 0) ? adjwgt : NULL); if (_SCOTCH_METIS_PartGraph (n, xadj, adjncy, vwgt2, adjwgt2, numflag, nparts, part) != 0) return; parttax = part - *numflag; verttax = xadj - *numflag; edgetax = adjncy - *numflag; edgenum = *numflag; vertnum = *numflag; vertnnd = *n + vertnum; commcut = 0; if (adjwgt2 == NULL) { /* If graph does not have edge weights */ for ( ; vertnum < vertnnd; vertnum ++) { int edgennd; int partval; partval = parttax[vertnum]; for (edgennd = verttax[vertnum + 1]; edgenum < edgennd; edgenum ++) { if (parttax[edgetax[edgenum]] != partval) commcut ++; } } } else { /* Graph has edge weights */ const int * restrict edlotax; edlotax = adjwgt2 - *numflag; for ( ; vertnum < vertnnd; vertnum ++) { int edgennd; int partval; partval = parttax[vertnum]; for (edgennd = verttax[vertnum + 1]; edgenum < edgennd; edgenum ++) { int vertend; vertend = edgetax[edgenum]; if (parttax[vertend] != partval) commcut += edlotax[edgenum]; } } } *edgecut = commcut / 2; } /* Scotch does not directly consider communication volume. ** Instead, wertex communication loads are added to the edge ** loads so as to emulate this behavior : heavily weighted ** edges, connected to heavily communicating vertices, will ** be less likely to be cut. */ void METISNAMEU(METIS_PartGraphVKway) ( const int * const n, const int * const xadj, const int * const adjncy, const int * const vwgt, const int * const vsize, const int * const wgtflag, const int * const numflag, const int * const nparts, const int * const options, int * const volume, int * const part) { int baseval; const int * vwgt2; const int * vsize2; int vsizval; /* Communication volume of current vertex */ int vertnbr; int vertnum; int edgenum; const int * restrict edgetax; const int * restrict parttax; int * restrict nghbtab; int commvol; vsize2 = ((*wgtflag & 1) != 0) ? vsize : NULL; vwgt2 = ((*wgtflag & 2) != 0) ? vwgt : NULL; baseval = *numflag; vertnbr = *n; edgetax = adjncy - baseval; if (vsize2 == NULL) /* If no communication load data provided */ _SCOTCH_METIS_PartGraph (n, xadj, adjncy, vwgt2, NULL, numflag, nparts, part); else { /* Will have to turn communication volumes into edge loads */ const int * restrict vsiztax; int edgenbr; int * restrict edlotax; int o; edgenbr = xadj[vertnbr] - baseval; if ((edlotax = memAlloc (edgenbr * sizeof (int))) == NULL) return; edlotax -= baseval; /* Base access to edlotax */ vsiztax = vsize2 - baseval; for (vertnum = 0, edgenum = baseval; /* Un-based scan of vertex array xadj */ vertnum < vertnbr; vertnum ++) { int vsizval; /* Communication size of current vertex */ int edgennd; vsizval = vsize2[vertnum]; for (edgennd = xadj[vertnum + 1]; edgenum < edgennd; edgenum ++) { /* Based traversal of edge array adjncy */ int vertend; /* Based end vertex number */ vertend = edgetax[edgenum]; edlotax[edgenum] = vsizval + vsiztax[vertend]; } } o = _SCOTCH_METIS_PartGraph (n, xadj, adjncy, vwgt2, edlotax + baseval, numflag, nparts, part); memFree (edlotax + baseval); if (o != 0) return; } if ((nghbtab = memAlloc (*nparts * sizeof (int))) == NULL) return; memSet (nghbtab, ~0, *nparts * sizeof (int)); parttax = part - baseval; vsizval = 1; /* Assume no vertex communication sizes */ for (vertnum = 0, edgenum = baseval, commvol = 0; /* Un-based scan of vertex array xadj */ vertnum < vertnbr; vertnum ++) { int partval; int edgennd; partval = part[vertnum]; nghbtab[partval] = vertnum; /* Do not count local neighbors in communication volume */ if (vsize2 != NULL) vsizval = vsize2[vertnum]; for (edgennd = xadj[vertnum + 1]; edgenum < edgennd; edgenum ++) { /* Based traversal of edge array adjncy */ int vertend; /* Based end vertex number */ int partend; vertend = edgetax[edgenum]; partend = parttax[vertend]; if (nghbtab[partend] != vertnum) { /* If first neighbor in this part */ nghbtab[partend] = vertnum; /* Set part as accounted for */ commvol += vsizval; } } } *volume = commvol; memFree (nghbtab); } scotch-5.1.12b.dfsg/src/libscotchmetis/metis_graph_order_f.c0000644000175300017530000001233711412716504024351 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : metis_graph_order_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API of **/ /** the compatibility library for the **/ /** MeTiS ordering routines. **/ /** **/ /** DATES : # Version 5.0 : from : 10 sep 2006 **/ /** to 10 sep 2006 **/ /** # Version 5.1 : from : 30 jun 2010 **/ /** to 30 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "common.h" #include "scotch.h" #include "metis.h" /* Our "metis.h" file */ /**************************************/ /* */ /* These routines are the Fortran API */ /* for the graph ordering routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ METISNAMEU(METIS_EDGEND), METISNAMEL(metis_edgend), ( \ const int * const n, \ const int * const xadj, \ const int * const adjncy, \ const int * const numflag, \ const int * const options, \ int * const perm, \ int * const iperm), \ (n, xadj, adjncy, numflag, options, perm, iperm)) { METISNAMEU(METIS_EdgeND) (n, xadj, adjncy, numflag, options, perm, iperm); } /* ** */ FORTRAN ( \ METISNAMEU(METIS_NODEND), METISNAMEL(metis_nodend), ( \ const int * const n, \ const int * const xadj, \ const int * const adjncy, \ const int * const numflag, \ const int * const options, \ int * const perm, \ int * const iperm), \ (n, xadj, adjncy, numflag, options, perm, iperm)) { METISNAMEU(METIS_NodeND) (n, xadj, adjncy, numflag, options, perm, iperm); } /* When an input stream is built from the given ** file handle, it is set as unbuffered, so as to ** allow for multiple stream reads from the same ** file handle. If it were buffered, too many ** input characters would be read on the first ** block read. */ FORTRAN ( \ METISNAMEU(METIS_NODEWND), METISNAMEL(metis_nodewnd), ( \ const int * const n, \ const int * const xadj, \ const int * const adjncy, \ const int * const vwgt, \ const int * const numflag, \ const int * const options, \ int * const perm, \ int * const iperm), \ (n, xadj, adjncy, vwgt, numflag, options, perm, iperm)) { METISNAMEU(METIS_NodeWND) (n, xadj, adjncy, vwgt, numflag, options, perm, iperm); } scotch-5.1.12b.dfsg/src/scotch/0000755000175300017530000000000011426512567016454 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/src/scotch/gtst.h0000644000175300017530000000655311611563204017605 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gtst.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the declarations **/ /** for the source graph analyzer. **/ /** **/ /** DATES : # Version 2.0 : from : 31 oct 1993 **/ /** to 31 oct 1993 **/ /** # Version 3.2 : from : 03 jun 1997 **/ /** to : 03 jun 1997 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to : 19 oct 1998 **/ /** # Version 4.0 : from : 10 sep 2003 **/ /** to : 10 sep 2003 **/ /** **/ /************************************************************/ /* ** The defines. */ /** File name aliases. **/ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 2 /* Number of files which can be arguments */ #define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ #define C_filenamedatout C_fileTab[1].name /* Statistics output file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ #define C_filepntrdatout C_fileTab[1].pntr /* Statistics output file */ scotch-5.1.12b.dfsg/src/scotch/dgscat.h0000644000175300017530000000671611611563204020072 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgscat.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a parallel sparse matrix **/ /** ordering software. **/ /** This module contains the data declara- **/ /** tions for the graph file scattering **/ /** program. **/ /** **/ /** DATES : # Version 5.0 : from : 21 may 2007 **/ /** to : 21 may 2007 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 2 /* Number of files which can be arguments */ #define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ #define C_filenamesrcout C_fileTab[1].name /* Source graph output file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ #define C_filepntrsrcout C_fileTab[1].pntr /* Source graph output file */ /*+ Process flags. +*/ #define C_FLAGNONE 0x0000 /* No flags */ #define C_FLAGCHECK 0x0001 /* Check distributed source graph */ #define C_FLAGDEBUG 0x0002 /* Enable easy debugger attachment */ scotch-5.1.12b.dfsg/src/scotch/gscat.c0000644000175300017530000002632011611563204017712 0ustar hazelscthazelsct/* Copyright 2009-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gscat.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This program writes a centralized **/ /** source graph file in the form of a **/ /** distributed source graph. **/ /** **/ /** DATES : # Version 5.1 : from : 26 apr 2009 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GSCAT #include "module.h" #include "common.h" #include "scotch.h" #include "gscat.h" /* ** The static variables. */ static int C_paraNum = 0; /* Number of parameters */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { /* Usage */ "gscat ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ int main ( int argc, char * argv[]) { SCOTCH_Num p[1] = { 1 }; /* Number of parts */ int i; errorProg ("gscat"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < 1) { /* If number of parameters not reached */ if ((p[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get number of parts */ errorPrint ("main: invalid number of parts '%s'", argv[i]); return (1); } continue; /* Process the other parameters */ } if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "gscat, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2009-2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, 1); /* Open input graph file */ C_graphScat (C_filepntrsrcinp, p[0], C_filenamesrcout); fileBlockClose (C_fileTab, 1); /* Always close explicitely to end eventual (un)compression tasks */ #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } static int C_graphScat ( FILE * const stream, SCOTCH_Num procnbr, char * const nameptr) { SCOTCH_Num versval; SCOTCH_Num propval; char proptab[4]; int flagtab[3]; SCOTCH_Num baseval; SCOTCH_Num vertglbnbr; SCOTCH_Num edgeglbnbr; SCOTCH_Num procnum; if (intLoad (stream, &versval) != 1) { /* Read version number */ errorPrint ("C_graphScat: bad input (1)"); return (1); } if (versval != 0) { /* If version not zero */ errorPrint ("C_graphScat: only centralized graphs supported"); return (1); } if ((intLoad (stream, &vertglbnbr) != 1) || /* Read rest of header */ (intLoad (stream, &edgeglbnbr) != 1) || (intLoad (stream, &baseval) != 1) || (intLoad (stream, &propval) != 1) || (propval < 0) || (propval > 111)) { errorPrint ("C_graphScat: bad input (2)"); return (1); } sprintf (proptab, "%3.3d", (int) propval); /* Compute file properties */ flagtab[0] = proptab[0] - '0'; /* Vertex labels flag */ flagtab[1] = proptab[1] - '0'; /* Edge weights flag */ flagtab[2] = proptab[2] - '0'; /* Vertex loads flag */ for (procnum = 0; procnum < procnbr; procnum ++) { char * nametmp; FILE * ostream; SCOTCH_Num vertlocnbr; SCOTCH_Num vertlocnum; SCOTCH_Num edgelocnbr; nametmp = nameptr; if ((fileNameDistExpand (&nametmp, procnbr, procnum, -1) != 0) || ((ostream = fopen (nametmp, "w+")) == NULL)) { errorPrint ("C_graphScat: cannot open file"); return (1); } memFree (nametmp); /* Expanded name no longer needed */ vertlocnbr = DATASIZE (vertglbnbr, procnbr, procnum); if (fprintf (ostream, "2\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t%015d\n" SCOTCH_NUMSTRING "\t%3s\n", /* Write file header */ (SCOTCH_Num) procnbr, (SCOTCH_Num) procnum, (SCOTCH_Num) vertglbnbr, (SCOTCH_Num) edgeglbnbr, (SCOTCH_Num) vertlocnbr, 0, /* Number of edges not yet known */ (SCOTCH_Num) baseval, proptab) == EOF) { errorPrint ("C_graphScat: bad output (1)"); return (1); } for (vertlocnum = edgelocnbr = 0; vertlocnum < vertlocnbr; vertlocnum ++) { SCOTCH_Num degrval; if (flagtab[0] != 0) { /* If must read label */ SCOTCH_Num vlblval; /* Value where to read vertex label */ if (intLoad (stream, &vlblval) != 1) { /* Read label data */ errorPrint ("C_graphScat: bad input (3)"); return (1); } intSave (ostream, vlblval); putc ('\t', ostream); } if (flagtab[2] != 0) { /* If must read vertex load */ SCOTCH_Num veloval; /* Value where to read vertex load */ if (intLoad (stream, &veloval) != 1) { /* Read vertex load data */ errorPrint ("C_graphScat: bad input (4)"); return (1); } intSave (ostream, veloval); putc ('\t', ostream); } if (intLoad (stream, °rval) != 1) { /* Read vertex degree */ errorPrint ("C_graphScat: bad input (5)"); return (1); } intSave (ostream, degrval); edgelocnbr += degrval; for ( ; degrval > 0; degrval --) { SCOTCH_Num edgeval; /* Value where to read edge end */ if (flagtab[1] != 0) { /* If must read edge load */ SCOTCH_Num edloval; /* Value where to read edge load */ if (intLoad (stream, &edloval) != 1) { /* Read edge load data */ errorPrint ("C_graphScat: bad input (6)"); return (1); } putc ('\t', ostream); intSave (ostream, edloval); } if (intLoad (stream, &edgeval) != 1) { /* Read edge data */ errorPrint ("C_graphScat: bad input (7)"); return (1); } putc ('\t', ostream); intSave (ostream, edgeval); } putc ('\n', ostream); } rewind (ostream); if (fprintf (ostream, "2\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t%015lld\n" SCOTCH_NUMSTRING "\t%3s\n", /* Write file header */ (SCOTCH_Num) procnbr, (SCOTCH_Num) procnum, (SCOTCH_Num) vertglbnbr, (SCOTCH_Num) edgeglbnbr, (SCOTCH_Num) vertlocnbr, (long long) edgelocnbr, /* Now we know the exact number of edges */ (SCOTCH_Num) baseval, proptab) == EOF) { errorPrint ("C_graphScat: bad output (2)"); return (1); } fclose (ostream); } return (0); } scotch-5.1.12b.dfsg/src/scotch/Makefile0000644000175300017530000002653611626034576020131 0ustar hazelscthazelsct## Copyright 2004,2007-2011 ENSEIRB, INRIA & CNRS ## ## This file is part of the Scotch software package for static mapping, ## graph partitioning and sparse matrix ordering. ## ## This software is governed by the CeCILL-C license under French law ## and abiding by the rules of distribution of free software. You can ## use, modify and/or redistribute the software under the terms of the ## CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ## URL: "http://www.cecill.info". ## ## As a counterpart to the access to the source code and rights to copy, ## modify and redistribute granted by the license, users are provided ## only with a limited warranty and the software's author, the holder of ## the economic rights, and the successive licensors have only limited ## liability. ## ## In this respect, the user's attention is drawn to the risks associated ## with loading, using, modifying and/or developing or reproducing the ## software by the user in light of its specific status of free software, ## that may mean that it is complicated to manipulate, and that also ## therefore means that it is reserved for developers and experienced ## professionals having in-depth computer knowledge. Users are therefore ## encouraged to load and test the software's suitability as regards ## their requirements in conditions enabling the security of their ## systems and/or data to be ensured and, more generally, to use and ## operate it in the same conditions as regards security. ## ## The fact that you are presently reading this means that you have had ## knowledge of the CeCILL-C license and that you accept its terms. ## bindir = ../../bin includedir = ../../include libdir = ../../lib ## ## General inference rules. ## include ../Makefile.inc %$(EXE) : %$(OBJ) $(CC) $(CFLAGS) -I$(includedir) -I../libscotch $(<) -o $(@) -L$(libdir) -l$(SCOTCHLIB) -l$(SCOTCHLIB)errexit $(LDFLAGS) %$(OBJ) : %.c $(CC) $(CFLAGS) -I$(includedir) -I../libscotch -c $(<) -o $(@) %$(EXE) : %.c $(CC) $(CFLAGS) -I$(includedir) -I../libscotch $(<) -o $(@) -L$(libdir) -l$(SCOTCHLIB) -l$(SCOTCHLIB)errexit $(LDFLAGS) ## ## Project rules. ## .PHONY : ptscotch scotch ptinstall install clean realclean scotch : clean $(MAKE) CC="$(CCS)" SCOTCHLIB=scotch \ acpl$(EXE) \ amk_ccc$(EXE) \ amk_fft2$(EXE) \ amk_grf$(EXE) \ amk_hy$(EXE) \ amk_m2$(EXE) \ amk_p2$(EXE) \ atst$(EXE) \ gbase$(EXE) \ gcv$(EXE) \ gmap$(EXE) \ gmk_hy$(EXE) \ gmk_m2$(EXE) \ gmk_m3$(EXE) \ gmk_msh$(EXE) \ gmk_ub2$(EXE) \ gmtst$(EXE) \ gord$(EXE) \ gotst$(EXE) \ gout$(EXE) \ gpart$(EXE) \ gscat$(EXE) \ gtst$(EXE) \ mcv$(EXE) \ mmk_m2$(EXE) \ mmk_m3$(EXE) \ mord$(EXE) \ mtst$(EXE) ptscotch : clean $(MAKE) CC="$(CCP)" SCOTCHLIB=ptscotch \ dggath$(EXE) \ dgmap$(EXE) \ dgord$(EXE) \ dgpart$(EXE) \ dgscat$(EXE) \ dgtst$(EXE) install : -$(CP) acpl$(EXE) amk_ccc$(EXE) amk_fft2$(EXE) amk_grf$(EXE) amk_hy$(EXE) amk_m2$(EXE) amk_p2$(EXE) atst$(EXE) gbase$(EXE) gcv$(EXE) gmap$(EXE) gmk_hy$(EXE) gmk_m2$(EXE) gmk_m3$(EXE) gmk_msh$(EXE) gmk_ub2$(EXE) gmtst$(EXE) gord$(EXE) gotst$(EXE) gout$(EXE) gpart$(EXE) *gtst$(EXE) gscat$(EXE) mcv$(EXE) mmk_m2$(EXE) mmk_m3$(EXE) mord$(EXE) mtst$(EXE) $(bindir) ptinstall : -$(CP) dggath$(EXE) dgmap$(EXE) dgord$(EXE) dgpart$(EXE) dgscat$(EXE) dgtst$(EXE) $(bindir) clean : -$(RM) *~ *$(OBJ) acpl$(EXE) amk_ccc$(EXE) amk_fft2$(EXE) amk_grf$(EXE) amk_hy$(EXE) amk_m2$(EXE) amk_p2$(EXE) atst$(EXE) gbase$(EXE) gcv$(EXE) *ggath$(EXE) *gmap$(EXE) gmk_hy$(EXE) gmk_m2$(EXE) gmk_m3$(EXE) gmk_msh$(EXE) gmk_ub2$(EXE) gmtst$(EXE) *gord$(EXE) gotst$(EXE) gout$(EXE) *gpart$(EXE) *gscat$(EXE) *gtst$(EXE) mcv$(EXE) mmk_m2$(EXE) mmk_m3$(EXE) mord$(EXE) mtst$(EXE) realclean : clean ## ## Todo list. ## acpl$(EXE) : acpl.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ acpl.h amk_ccc$(EXE) : amk_ccc.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ amk_ccc.h amk_fft2$(EXE) : amk_fft2.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ amk_fft2.h amk_grf$(EXE) : amk_grf.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ amk_grf.h amk_hy$(EXE) : amk_hy.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ amk_hy.h amk_m2$(EXE) : amk_m2.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ amk_m2.h amk_p2$(EXE) : amk_p2.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ amk_p2.h atst$(EXE) : atst.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ atst.h dggath$(EXE) : dggath.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/ptscotch.h \ $(libdir)/libptscotch$(LIB) \ $(libdir)/libptscotcherrexit$(LIB) \ dggath.h dgmap$(EXE) : dgmap.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/ptscotch.h \ $(libdir)/libptscotch$(LIB) \ $(libdir)/libptscotcherrexit$(LIB) \ dgmap.h dgord$(EXE) : dgord.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/ptscotch.h \ $(libdir)/libptscotch$(LIB) \ $(libdir)/libptscotcherrexit$(LIB) \ dgord.h dgpart$(EXE) : dgmap.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/ptscotch.h \ $(libdir)/libptscotch$(LIB) \ $(libdir)/libptscotcherrexit$(LIB) \ dgmap.h $(CC) $(CFLAGS) -I$(includedir) -I../libscotch $(<) -DSCOTCH_COMPILE_PART -o $(@) -L$(libdir) -l$(SCOTCHLIB) -l$(SCOTCHLIB)errexit $(LDFLAGS) dgscat$(EXE) : dgscat.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/ptscotch.h \ $(libdir)/libptscotch$(LIB) \ $(libdir)/libptscotcherrexit$(LIB) \ dgscat.h dgtst$(EXE) : dgtst.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/ptscotch.h \ $(libdir)/libptscotch$(LIB) \ $(libdir)/libptscotcherrexit$(LIB) \ dgtst.h gbase$(EXE) : gbase.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ gbase.h gcv$(EXE) : gcv.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ gcv.h gmap$(EXE) : gmap.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ gmap.h gmk_hy$(EXE) : gmk_hy.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ gmk_hy.h gmk_m2$(EXE) : gmk_m2.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ gmk_m2.h gmk_m3$(EXE) : gmk_m3.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ gmk_m3.h gmk_msh$(EXE) : gmk_msh.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ gmk_msh.h gmk_ub2$(EXE) : gmk_ub2.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ gmk_ub2.h gmtst$(EXE) : gmtst.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ gmtst.h gord$(EXE) : gord.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ gord.h gotst$(EXE) : gotst.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ gotst.h gout$(EXE) : gout_c.c \ gout_o.c \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) $(CC) $(CFLAGS) -I../libscotch -I$(includedir) gout_c.c gout_o.c -o $(@) -L$(libdir) -lscotch -lscotcherrexit $(LDFLAGS) gpart$(EXE) : gmap.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ gmap.h $(CC) $(CFLAGS) -I$(includedir) -I../libscotch $(<) -DSCOTCH_COMPILE_PART -o $(@) -L$(libdir) -l$(SCOTCHLIB) -l$(SCOTCHLIB)errexit $(LDFLAGS) gscat$(EXE) : gscat.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ gscat.h gtst$(EXE) : gtst.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ gtst.h mcv$(EXE) : mcv.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ mcv.h mmk_m2$(EXE) : mmk_m2.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ mmk_m2.h mmk_m3$(EXE) : mmk_m3.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ mmk_m3.h mord$(EXE) : mord.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ mord.h mtst$(EXE) : mtst.c \ ../libscotch/module.h \ ../libscotch/common.h \ $(includedir)/scotch.h \ $(libdir)/libscotch$(LIB) \ $(libdir)/libscotcherrexit$(LIB) \ mtst.h scotch-5.1.12b.dfsg/src/scotch/amk_grf.h0000644000175300017530000001025111611563204020220 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : amk_grf.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Decomposition architecture builder. **/ /** These lines are the data declarations **/ /** for the program routines. **/ /** **/ /** DATES : # Version 3.0 : from : 06 jul 1995 **/ /** to : 02 oct 1995 **/ /** # Version 3.1 : from : 26 mar 1996 **/ /** to : 26 mar 1996 **/ /** # Version 3.2 : from : 23 apr 1997 **/ /** to : 02 jun 1997 **/ /** # Version 3.3 : from : 15 may 1999 **/ /** to : 15 may 1999 **/ /** # Version 5.1 : from : 17 jul 2011 **/ /** to : 17 jul 2011 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 3 /* Number of files in list */ #define C_FILEARGNBR 2 /* Number of files which can be arguments */ #define C_filenamegrfinp C_fileTab[0].name /* Source graph input file name */ #define C_filenametgtout C_fileTab[1].name /* Architecture output file name */ #define C_filenamevrtinp C_fileTab[2].name /* Vertex list input file name */ #define C_filepntrgrfinp C_fileTab[0].pntr /* Source graph input file */ #define C_filepntrtgtout C_fileTab[1].pntr /* Architecture output file */ #define C_filepntrvrtinp C_fileTab[2].pntr /* Vertex list input file */ /*+ Process flags. +*/ #define C_FLAGVRTINP 0x0001 /* Input vertex list */ #define C_FLAGNONE 0x0000 /* Default flags */ /* ** The type and structure definitions. */ /*+ The sort structure, used to sort graph vertices by label. +*/ typedef struct C_VertSort_ { SCOTCH_Num vlblnum; /*+ Vertex label +*/ SCOTCH_Num vertnum; /*+ Vertex number +*/ } C_VertSort; scotch-5.1.12b.dfsg/src/scotch/amk_ccc.h0000644000175300017530000001356311611563204020203 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : amk_ccc.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the distance map for CCC **/ /** graphs, to be used to build the **/ /** architecture description files for **/ /** these graphs. **/ /** **/ /** DATES : # Version 1.3 : from : 24 apr 1994 **/ /** to : 24 apr 1994 **/ /** # Version 2.0 : from : 13 jul 1994 **/ /** to : 18 jul 1994 **/ /** # Version 3.0 : from : 18 sep 1995 **/ /** to : 18 sep 1995 **/ /** # Version 3.2 : from : 07 may 1997 **/ /** to : 07 may 1997 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 02 oct 1998 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 1 /* Number of files in list */ #define C_filenamearcout C_fileTab[0].name /* Architecture output file name */ #define C_filepntrarcout C_fileTab[0].pntr /* Architecture output file */ /* ** The type and structure definitions. */ /*+ This structure defines a CCC vertex. +*/ typedef struct C_Vertex_ { SCOTCH_Num lvl; /*+ Vertex level +*/ SCOTCH_Num pos; /*+ Vertex position +*/ } C_Vertex; /*+ This structure defines a vertex distance information. +*/ typedef struct C_VertDist_ { int queued; /*+ Flag set if vertex queued +*/ SCOTCH_Num dist; /*+ Distance to initial vertex +*/ } C_VertDist; /*+ This is a neighbor queue element. +*/ typedef struct C_QueueElem_ { C_Vertex vert; /*+ Vertex number +*/ SCOTCH_Num dist; /*+ Distance reached +*/ } C_QueueElem; /*+ This is the distance queue. +*/ typedef struct C_Queue_ { C_QueueElem * tab; /*+ Pointer to queue data +*/ SCOTCH_Num min; /*+ Pointer to first element +*/ SCOTCH_Num max; /*+ Pointer to last element +*/ } C_Queue; /* ** The macro definitions. */ #define C_vertLabl(v) (((v)->lvl << ccdim) | (v)->pos) #define C_queueInit(q,n) ((((q)->tab = (C_QueueElem *) memAlloc ((n) * sizeof (C_QueueElem))) == NULL) ? 1 : 0) #define C_queueExit(q) memFree ((q)->tab) #define C_queueFlush(q) (q)->min = \ (q)->max = 0 #define C_queuePut(q,v,d) ((q)->tab[(q)->max].vert = *(v), \ (q)->tab[(q)->max ++].dist = (d)) #define C_queueGet(q,v,d) (((q)->min < (q)->max) ? (*(v) = (q)->tab[(q)->min].vert, \ *(d) = (q)->tab[(q)->min ++].dist, \ 1) \ : 0) #define C_distaRoot(v) (C_queueFlush (&C_distaQueue), \ C_queuePut (&C_distaQueue, (v), 0), \ C_distaTab[C_vertLabl (v)].queued = 1) #define C_distaGet(v,d) (C_queueGet (&C_distaQueue, (v), (d))) #define C_distaPut(v,d) ((C_distaTab[C_vertLabl (v)].queued == 0) \ ? C_queuePut (&C_distaQueue, (v), d), \ C_distaTab[C_vertLabl (v)].queued = 1 \ : 0) scotch-5.1.12b.dfsg/src/scotch/gcv.h0000644000175300017530000001057711611563204017404 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gcv.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a graph file converter. **/ /** This module contains the data declara- **/ /** tions for the main module. **/ /** **/ /** DATES : # Version 0.0 : from : 02 apr 1993 **/ /** to 02 apr 1993 **/ /** # Version 2.0 : from : 28 oct 1994 **/ /** to 16 nov 1994 **/ /** # Version 3.0 : from : 08 sep 1995 **/ /** to 17 sep 1995 **/ /** # Version 3.1 : from : 22 mar 1996 **/ /** to 22 mar 1996 **/ /** # Version 3.2 : from : 04 oct 1996 **/ /** to 04 mar 1997 **/ /** # Version 3.3 : from : 06 oct 1998 **/ /** to : 06 oct 1998 **/ /** # Version 3.4 : from : 13 oct 1999 **/ /** to : 14 oct 1999 **/ /** # Version 4.0 : from : 29 nov 2003 **/ /** to : 29 nov 2003 **/ /** **/ /************************************************************/ /* ** The defines */ /*+ File name aliases. +*/ #define C_FILENBR 3 /* Number of files in list */ #define C_FILEARGNBR 3 /* Number of files which can be arguments */ #define C_filenamesrcinp C_fileTab[0].name /* External graph input file name */ #define C_filenamesrcout C_fileTab[1].name /* Source graph output file name */ #define C_filenamegeoout C_fileTab[2].name /* Source graph geometry file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* External graph input file */ #define C_filepntrsrcout C_fileTab[1].pntr /* Source graph output file */ #define C_filepntrgeoout C_fileTab[2].pntr /* Source graph geometry file */ /* ** The type and structure definitions. */ /*+ This structure defines the method array element. +*/ typedef struct C_Format_ { char code; /* Format type code */ int (* func) (); /* Function to call */ } C_Format; scotch-5.1.12b.dfsg/src/scotch/dggath.c0000644000175300017530000002067611611563204020057 0ustar hazelscthazelsct/* Copyright 2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dggath.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This program gathers the fragments of a **/ /** distributed graph and saves it as a **/ /** centralized source graph. **/ /** This module contains the main function. **/ /** **/ /** DATES : # Version 5.1 : from : 26 oct 2008 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGGATH #define SCOTCH_PTSCOTCH #include "module.h" #include "common.h" #include "ptscotch.h" #include "dggath.h" /* ** The static and global definitions. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "dggath [ []] ", " -c : Check the input graph after loading", " -h : Display this help", " -r : Set root process for centralized files (default is 0)", " -V : Print program version and copyright", NULL }; /*********************/ /* */ /* The main routine. */ /* */ /*********************/ int main ( int argc, char * argv[]) { SCOTCH_Graph * cgrfptr; SCOTCH_Graph cgrfdat; SCOTCH_Dgraph dgrfdat; int procglbnbr; int proclocnum; int protglbnum; /* Root process */ int flagval; int i; int reduloctab[2]; int reduglbtab[2]; #ifdef SCOTCH_PTHREAD int thrdlvlreqval; int thrdlvlproval; #endif /* SCOTCH_PTHREAD */ errorProg ("dggath"); #ifdef SCOTCH_PTHREAD thrdlvlreqval = MPI_THREAD_MULTIPLE; if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) errorPrint ("main: Cannot initialize (1)"); if (thrdlvlreqval > thrdlvlproval) errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); #else /* SCOTCH_PTHREAD */ if (MPI_Init (&argc, &argv) != MPI_SUCCESS) errorPrint ("main: Cannot initialize (2)"); #endif /* SCOTCH_PTHREAD */ MPI_Comm_size (MPI_COMM_WORLD, &procglbnbr); /* Get communicator data */ MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum); protglbnum = 0; /* Assume root process is process 0 */ if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } flagval = C_FLAGNONE; for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else errorPrint ("main: too many file names given"); } else { /* If found an option name */ switch (argv[i][1]) { case 'C' : case 'c' : flagval |= C_FLAGCHECK; break; #ifdef SCOTCH_DEBUG_ALL case 'D' : case 'd' : flagval |= C_FLAGDEBUG; break; #endif /* SCOTCH_DEBUG_ALL */ case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'R' : /* Root process (if necessary) */ case 'r' : protglbnum = atoi (&argv[i][2]); if ((protglbnum < 0) || (protglbnum >= procglbnbr) || ((protglbnum == 0) && (argv[i][2] != '0'))) { errorPrint ("main: invalid root process number"); } break; case 'V' : case 'v' : fprintf (stderr, "dggath, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); } } } #ifdef SCOTCH_DEBUG_ALL if ((flagval & C_FLAGDEBUG) != 0) { fprintf (stderr, "Proc %4d of %d, pid %d\n", proclocnum, procglbnbr, getpid ()); if (proclocnum == protglbnum) { /* Synchronize on keybord input */ char c; printf ("Waiting for key press...\n"); scanf ("%c", &c); } MPI_Barrier (MPI_COMM_WORLD); } #endif /* SCOTCH_DEBUG_ALL */ fileBlockOpenDist (C_fileTab, C_FILENBR, procglbnbr, proclocnum, protglbnum); /* Open all files */ if (C_filepntrsrcout == NULL) { cgrfptr = NULL; reduloctab[0] = reduloctab[1] = 0; } else { cgrfptr = &cgrfdat; reduloctab[0] = 1; reduloctab[1] = proclocnum; } if (MPI_Allreduce (reduloctab, reduglbtab, 2, MPI_INT, MPI_SUM, MPI_COMM_WORLD) != MPI_SUCCESS) errorPrint ("main: communication error"); if (reduglbtab[0] != 1) errorPrint ("main: should have only one root"); if (reduglbtab[1] != protglbnum) errorPrint ("main: root process mismatch"); SCOTCH_dgraphInit (&dgrfdat, MPI_COMM_WORLD); SCOTCH_dgraphLoad (&dgrfdat, C_filepntrsrcinp, -1, 0); if ((flagval & C_FLAGCHECK) != 0) SCOTCH_dgraphCheck (&dgrfdat); SCOTCH_graphInit (&cgrfdat); SCOTCH_dgraphGather (&dgrfdat, cgrfptr); if (cgrfptr != NULL) SCOTCH_graphSave (cgrfptr, C_filepntrsrcout); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_graphExit (&cgrfdat); SCOTCH_dgraphExit (&dgrfdat); MPI_Finalize (); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/gmtst.c0000644000175300017530000001773211611563204017756 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gmtst.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This program computes statistics on **/ /** graph mappings. **/ /** **/ /** DATES : # Version 3.1 : from : 17 jul 1996 **/ /** to 23 jul 1996 **/ /** # Version 3.2 : from : 02 jun 1997 **/ /** to : 16 jul 1997 **/ /** # Version 3.3 : from : 07 jun 1999 **/ /** to : 07 jun 1999 **/ /** # Version 4.0 : from : 12 feb 2004 **/ /** to 16 nov 2005 **/ /** # Version 5.0 : from : 22 jan 2008 **/ /** to 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GMTST #include "module.h" #include "common.h" #include "scotch.h" #include "gmtst.h" /* ** The static variables. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* The file array */ { "-", NULL, "r" }, { "-", NULL, "r" }, { "-", NULL, "r" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { /* Usage */ "gmtst [ [ [ []]]] ", " -h : Display this help", " -V : Print program version and copyright", "", NULL }; /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ int main ( int argc, char * argv[]) { SCOTCH_Graph grafdat; /* Source graph */ SCOTCH_Num vertnbr; /* Source graph size */ SCOTCH_Num * vlbltab; /* Source graph vertex label array */ SCOTCH_Arch archdat; /* Target architecture */ SCOTCH_Num archnbr; /* Size of the target architecture */ SCOTCH_Mapping mappdat; /* Mapping data */ int i; errorProg ("gmtst"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'M' : /* No mapping flag */ case 'm' : C_filenamemapinp = "-"; /* Default name to avoid opening */ C_filepntrmapinp = NULL; /* NULL file pointer means no file */ break; case 'V' : fprintf (stderr, "gmtst, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ SCOTCH_graphInit (&grafdat); /* Create graph structure */ SCOTCH_graphLoad (&grafdat, C_filepntrsrcinp, -1, 0); /* Read source graph */ SCOTCH_graphData (&grafdat, NULL, /* Get graph characteristics */ &vertnbr, NULL, NULL, NULL, &vlbltab, NULL, NULL, NULL); SCOTCH_archInit (&archdat); /* Create architecture structure */ SCOTCH_archLoad (&archdat, C_filepntrtgtinp); /* Read target architecture */ if (strcmp (SCOTCH_archName (&archdat), "term") == 0) { /* If target architecture is variable-sized */ errorPrint ("main: variable-sized architectures cannot be mapped"); return (1); } archnbr = SCOTCH_archSize (&archdat); /* Get architecture size */ SCOTCH_graphMapInit (&grafdat, &mappdat, &archdat, NULL); /* Create mapping structure */ if (SCOTCH_graphMapLoad (&grafdat, &mappdat, C_filepntrmapinp) != 0) errorPrint ("main: bad input (1)"); SCOTCH_graphMapView (&grafdat, &mappdat, C_filepntrdatout); /* Display mapping statistics */ fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_graphMapExit (&grafdat, &mappdat); SCOTCH_archExit (&archdat); SCOTCH_graphExit (&grafdat); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/mmk_m3.c0000644000175300017530000003042711611563204017777 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mmk_m3.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the source meshes for **/ /** tridimensional mesh source graphs. **/ /** **/ /** DATES : # Version 4.0 : from : 26 sep 2002 **/ /** to : 17 feb 2004 **/ /** # Version 5.0 : from : 13 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /** NOTES : # The nodes and elements of the **/ /** (dX,dY,dZ) mesh are numbered so that **/ /** t(0,0,0) = 0, t(1,0,0) = 1, **/ /** t(dX - 1, 0, 0) = dX - 1, t(0,1,0) = **/ /** dX, t (0, 0, 1) = dX * dY - 1, **/ /** and t(x,y,z) = (z * dY + y) * dX + x. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MMK_M3 #include "module.h" #include "common.h" #include "scotch.h" #include "mmk_m3.h" /* ** The static definitions. */ static int C_paraNum = 0; /* Number of parameters */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* The file array */ { "-", NULL, "w" }, { "-", NULL, "w" } }; static const int C_nghbTab[4] = { 8, 4, 2, 1 }; static const char * C_usageList[] = { "mmk_m3 [ [ []]] ", " -g : Output mesh geometry to ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /****************************************/ /* */ /* The main routine, which computes the */ /* source graph description. */ /* */ /****************************************/ int main ( int argc, char * argv[]) { SCOTCH_Num e[3] = { 1, 1, 1 }; /* Mesh element dimensions */ SCOTCH_Num n[3]; /* Mesh node dimensions */ SCOTCH_Num c[3]; /* Vertex coordinates */ SCOTCH_Num velmnbr; /* First node number */ int flagval; /* Process flags */ int i; errorProg ("mmk_m3"); flagval = C_FLAGDEFAULT; /* Set default flags */ if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < 3) { /* If number of parameters not reached */ if ((e[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get the dimension */ errorPrint ("main: invalid dimension '%s'", argv[i]); return (1); } continue; /* Process the other parameters */ } if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'G' : /* Output mesh geometry */ case 'g' : flagval |= C_FLAGGEOOUT; if (argv[i][2] != '\0') C_filenamegeoout = &argv[i][2]; break; case 'H' : /* Give program usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "mmk_m3, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ n[0] = e[0] + 1; n[1] = e[1] + 1; n[2] = e[2] + 1; velmnbr = e[0] * e[1] * e[2]; fprintf (C_filepntrmshout, "1\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n0\t" SCOTCH_NUMSTRING "\t000\n", /* Print mesh file header */ (SCOTCH_Num) velmnbr, (SCOTCH_Num) (n[0] * n[1] * n[2]), (SCOTCH_Num) ((velmnbr + (n[0] * n[1] * n[2]) - (n[0] * n[1] + n[0] * n[2] + n[1] * n[2]) + n[0] + n[1] + n[2] - 1) * 8), (SCOTCH_Num) velmnbr); for (c[2] = 0; c[2] < e[2]; c[2] ++) { /* Output element neighbor list */ for (c[1] = 0; c[1] < e[1]; c[1] ++) { for (c[0] = 0; c[0] < e[0]; c[0] ++) fprintf (C_filepntrmshout, "8\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", /* Output neighbors of element */ (SCOTCH_Num) ((c[2] * n[1] + c[1]) * n[0] + c[0]), (SCOTCH_Num) ((c[2] * n[1] + c[1]) * n[0] + (c[0] + 1)), (SCOTCH_Num) ((c[2] * n[1] + (c[1] + 1)) * n[0] + c[0]), (SCOTCH_Num) ((c[2] * n[1] + (c[1] + 1)) * n[0] + (c[0] + 1)), (SCOTCH_Num) (((c[2] + 1) * n[1] + c[1]) * n[0] + c[0]), (SCOTCH_Num) (((c[2] + 1) * n[1] + c[1]) * n[0] + (c[0] + 1)), (SCOTCH_Num) (((c[2] + 1) * n[1] + (c[1] + 1)) * n[0] + c[0]), (SCOTCH_Num) (((c[2] + 1) * n[1] + (c[1] + 1)) * n[0] + (c[0] + 1))); } } for (c[2] = 0; c[2] < n[2]; c[2] ++) { /* Output node neighbor list */ for (c[1] = 0; c[1] < n[1]; c[1] ++) { for (c[0] = 0; c[0] < n[0]; c[0] ++) { fprintf (C_filepntrmshout, "%d", /* Output number of neighboring elements */ C_nghbTab[(((c[0] != 0) && (c[0] != e[0])) ? 0 : 1) + (((c[1] != 0) && (c[1] != e[1])) ? 0 : 1) + (((c[2] != 0) && (c[2] != e[2])) ? 0 : 1)]); if (c[2] != 0) { /* Output neighbors of nodes */ if (c[1] != 0) { if (c[0] != 0) fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) (((c[2] - 1) * e[1] + (c[1] - 1)) * e[0] + (c[0] - 1))); if (c[0] != e[0]) fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) (((c[2] - 1) * e[1] + (c[1] - 1)) * e[0] + c[0])); } if (c[1] != e[1]) { if (c[0] != 0) fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) (((c[2] - 1) * e[1] + c[1]) * e[0] + (c[0] - 1))); if (c[0] != e[0]) fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) (((c[2] - 1) * e[1] + c[1]) * e[0] + c[0])); } } if (c[2] != e[2]) { if (c[1] != 0) { if (c[0] != 0) fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[2] * e[1] + (c[1] - 1)) * e[0] + (c[0] - 1))); if (c[0] != e[0]) fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[2] * e[1] + (c[1] - 1)) * e[0] + c[0])); } if (c[1] != e[1]) { if (c[0] != 0) fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[2] * e[1] + c[1]) * e[0] + (c[0] - 1))); if (c[0] != e[0]) fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[2] * e[1] + c[1]) * e[0] + c[0])); } } fprintf (C_filepntrmshout, "\n"); } } } if (flagval & C_FLAGGEOOUT) { /* If geometry is wanted */ fprintf (C_filepntrgeoout, "3\n" SCOTCH_NUMSTRING "\n", /* Output geometry file header */ (SCOTCH_Num) (velmnbr + n[0] * n[1] * n[2])); for (c[2] = 0; c[2] < e[2]; c[2] ++) { /* Output element coordinates */ for (c[1] = 0; c[1] < e[1]; c[1] ++) { for (c[0] = 0; c[0] < e[0]; c[0] ++) fprintf (C_filepntrgeoout, SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING ".5\t" SCOTCH_NUMSTRING ".5\t" SCOTCH_NUMSTRING ".5\n", (SCOTCH_Num) (((c[2] * e[1]) + c[1]) * e[0] + c[0]), (SCOTCH_Num) c[0], (SCOTCH_Num) (e[1] - 1 - c[1]), (SCOTCH_Num) c[2]); } } for (c[2] = 0; c[2] <= e[2]; c[2] ++) { /* Output node coordinates */ for (c[1] = 0; c[1] <= e[1]; c[1] ++) { for (c[0] = 0; c[0] <= e[0]; c[0] ++) fprintf (C_filepntrgeoout, SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", (SCOTCH_Num) (velmnbr + ((c[2] * n[1]) + c[1]) * n[0] + c[0]), (SCOTCH_Num) c[0], (SCOTCH_Num) (e[1] - c[1]), (SCOTCH_Num) c[2]); } } } fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/gotst.c0000644000175300017530000004312411611563204017752 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gotst.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** Bruno MARCUSSEAU (v3.1) **/ /** **/ /** FUNCTION : Graph symbolic factorizer. **/ /** This module contains the main function. **/ /** **/ /** DATES : # Version 4.0 : from : 27 jan 2004 **/ /** to : 28 nov 2005 **/ /** # Version 5.0 : from : 25 jun 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 20 apr 2010 **/ /** to : 14 feb 2011 **/ /** **/ /** NOTES : # The cost analysis routine leaves the **/ /** memory management to malloc and free **/ /** because it is assumed to be the most **/ /** efficient to merge free blocks and **/ /** reallocate them. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GOTST #include "module.h" #include "common.h" #include "scotch.h" #include "gotst.h" /* ** The static and global variables. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[3] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "r" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "gotst [ [ []]] ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /*****************************/ /* */ /* This is the main function */ /* */ /*****************************/ int main ( int argc, char * argv[]) { SCOTCH_Graph grafdat; SCOTCH_Num vertnbr; SCOTCH_Num * verttab; SCOTCH_Num * vendtab; SCOTCH_Num edgenbr; SCOTCH_Num * edgetab; SCOTCH_Num baseval; SCOTCH_Ordering ordedat; SCOTCH_Num * permtab; SCOTCH_Num * peritab; int i; errorProg ("gotst"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give help */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "gotst, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ SCOTCH_graphInit (&grafdat); SCOTCH_graphLoad (&grafdat, C_filepntrgrfinp, -1, 3); SCOTCH_graphData (&grafdat, &baseval, &vertnbr, &verttab, &vendtab, NULL, NULL, &edgenbr, &edgetab, NULL); #ifdef SCOTCH_DEBUG_ALL if (vendtab != (verttab + 1)) { errorPrint ("main: graph should be compact"); return (1); } #endif /* SCOTCH_DEBUG_ALL */ if (memAllocGroup ((void **) (void *) &peritab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), &permtab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), NULL) == NULL) { errorPrint ("main: out of memory"); return (1); } SCOTCH_graphOrderInit (&grafdat, &ordedat, permtab, peritab, NULL, NULL, NULL); SCOTCH_graphOrderLoad (&grafdat, &ordedat, C_filepntrordinp); if (SCOTCH_graphOrderCheck (&grafdat, &ordedat) != 0) { errorPrint ("main: invalid ordering"); return (1); } factorView (baseval, vertnbr, verttab, edgenbr, edgetab, permtab, peritab, C_filepntrdatout); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ memFree (peritab); SCOTCH_graphOrderExit (&grafdat, &ordedat); SCOTCH_graphExit (&grafdat); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } /*************************************/ /* */ /* These routines compute statistics */ /* on orderings. */ /* */ /*************************************/ static int factorView ( const SCOTCH_Num baseval, const SCOTCH_Num vertnbr, const SCOTCH_Num * const verttab, const SCOTCH_Num edgenbr, const SCOTCH_Num * const edgetab, const SCOTCH_Num * const permtab, const SCOTCH_Num * const peritab, FILE * restrict const stream) { SCOTCH_Num * restrict ldadtab; SCOTCH_Num * restrict lsontab; SCOTCH_Num * restrict lbrotab; SCOTCH_Num * restrict fnnztab; double fopcsum; double heigsum; FactorStat statdat; SCOTCH_Num vertnum; int o; if (memAllocGroup ((void **) (void *) &ldadtab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), &lsontab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), &lbrotab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), &fnnztab, (size_t) (vertnbr * sizeof (SCOTCH_Num)), NULL) == NULL) { errorPrint ("factorView: out of memory"); return (1); } statdat.ldadtax = ldadtab - baseval; statdat.lsontax = lsontab - baseval; statdat.lbrotax = lbrotab - baseval; statdat.fnnztax = fnnztab - baseval; if (factorView2 (baseval, vertnbr, verttab - baseval, edgetab - baseval, permtab - baseval, peritab - baseval, ldadtab - baseval, lsontab - baseval, lbrotab - baseval, fnnztab - baseval) != 0) { errorPrint ("factorView: factored matrix too large"); memFree (ldadtab); /* Free group leader */ return (1); } statdat.heigmin = SCOTCH_NUMMAX; statdat.heigmax = statdat.heignbr = 0; heigsum = 0.0L; for (vertnum = 0; vertnum < vertnbr; vertnum ++) { /* Get height sum */ if (ldadtab[vertnum] == -1) /* If column is a root */ factorView3 (&statdat, 1, vertnum + baseval, &heigsum); /* Scan subtree */ } statdat.heigavg = heigsum / (double) statdat.heignbr; statdat.heigdlt = 0.0L; statdat.fnnzsum = 0.0L; fopcsum = 0.0L; for (vertnum = 0; vertnum < vertnbr; vertnum ++) { /* Get delta */ if (ldadtab[vertnum] == -1) /* If column is a root */ factorView4 (&statdat, 1, vertnum + baseval, &fopcsum); } statdat.heigdlt /= (double) statdat.heignbr; o = (fprintf (stream, "O\tLeaf=" SCOTCH_NUMSTRING "\nO\tHeight min=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tavg=%f\tdlt=%f (%5.2f)\n", /* Write tree height statistics */ (SCOTCH_Num) statdat.heignbr, (SCOTCH_Num) statdat.heigmin, (SCOTCH_Num) statdat.heigmax, statdat.heigavg, statdat.heigdlt, ((statdat.heigdlt / statdat.heigavg) * (double) 100.0L)) == EOF); o |= (fprintf (stream, "O\tNNZ=%e\nO\tOPC=%e\n", statdat.fnnzsum, fopcsum) == EOF); if (o != 0) errorPrint ("factorView: bad output"); memFree (ldadtab); /* Free group leader */ return (o); } static int factorView2 ( const SCOTCH_Num baseval, const SCOTCH_Num vertnbr, const SCOTCH_Num * const verttax, const SCOTCH_Num * const edgetax, const SCOTCH_Num * const permtax, const SCOTCH_Num * const peritax, SCOTCH_Num * restrict ldadtax, SCOTCH_Num * restrict lsontax, SCOTCH_Num * restrict lbrotax, SCOTCH_Num * restrict fnnztax) { SCOTCH_Num * restrict frowtab; SCOTCH_Num * restrict fnxttab; SCOTCH_Num ** restrict facttax; SCOTCH_Num vertnnd; SCOTCH_Num pcolnum; memSet (lsontax + baseval, ~0, vertnbr * sizeof (SCOTCH_Num)); /* Assume columns have no sons at all */ if (memAllocGroup ((void **) (void *) &frowtab, (size_t) ((vertnbr + 1) * sizeof (SCOTCH_Num)), &fnxttab, (size_t) ((vertnbr + 1) * sizeof (SCOTCH_Num)), &facttax, (size_t) (vertnbr * sizeof (SCOTCH_Num *)), NULL) == NULL) { errorPrint ("factorView2: out of memory (1)"); return (1); } memSet (facttax, 0, vertnbr * sizeof (SCOTCH_Num *)); /* Set all factored column pointers to NULL */ facttax -= baseval; vertnnd = vertnbr + baseval; for (pcolnum = baseval; pcolnum < vertnnd; pcolnum ++) { /* For all columns of the permuted matrix */ SCOTCH_Num * fcoltab; SCOTCH_Num * restrict fcolptr; SCOTCH_Num frownbr; SCOTCH_Num frowidx; SCOTCH_Num frowidd; SCOTCH_Num scolnum; SCOTCH_Num icolnum; SCOTCH_Num irownum; SCOTCH_Num dcolnum; icolnum = peritax[pcolnum]; /* Get the original number of the column */ frownbr = 1; /* Start array of factored terms for column */ frowtab[0] = pcolnum; /* Add diagonal element as unmoveable starter */ for (irownum = verttax[icolnum]; irownum < verttax[icolnum + 1]; irownum ++) { SCOTCH_Num prownum; prownum = permtax[edgetax[irownum]]; /* Get permuted row */ if (prownum >= pcolnum) frowtab[frownbr ++] = prownum; } intSort1asc1 (frowtab + 1, frownbr - 1); /* Sort rows in ascending order */ frowtab[frownbr ++] = vertnnd; /* Add trailer */ for (frowidx = 0; frowidx < (frownbr - 1); frowidx ++) /* Create initial links */ fnxttab[frowidx] = frowidx + 1; frowidd = frowidx; /* Save index of trailer */ for (scolnum = lsontax[pcolnum]; scolnum != -1; scolnum = lbrotax[scolnum]) { /* For all son columns in elimination tree */ const SCOTCH_Num * restrict srowtab; SCOTCH_Num srownbr; SCOTCH_Num srowidx; SCOTCH_Num frowidx; SCOTCH_Num foldidx; SCOTCH_Num frownum; srowtab = facttax[scolnum]; /* Point to array of factors for son column */ srownbr = fnnztax[scolnum]; /* Get size of array */ for (srowidx = 1, frowidx = 0, foldidx = -1, frownum = frowtab[frowidx]; srowidx < srownbr; srowidx ++) { SCOTCH_Num srownum; srownum = srowtab[srowidx]; while (frownum < srownum) { /* While factor to add not in place */ foldidx = frowidx; /* Skip to next position */ frowidx = fnxttab[frowidx]; frownum = frowtab[frowidx]; } if (srownum == frownum) /* If factor already in column */ continue; frowtab[frownbr] = srownum; /* Add new slot */ fnxttab[frownbr] = frowidx; /* Link new slot */ fnxttab[foldidx] = frownbr; foldidx = frownbr ++; } memFree ((void *) srowtab); /* Free now useless factored column */ #ifdef SCOTCH_DEBUG_ALL facttax[scolnum] = NULL; #endif /* SCOTCH_DEBUG_ALL */ } frownbr -= 2; /* Remove markers from number of extra-diagonals */ fnnztax[pcolnum] = frownbr; /* Save number of extra-diagonals */ if (frownbr <= 0) { /* If factored column has no extra-diagonals */ ldadtax[pcolnum] = -1; /* Column has no father */ #ifdef SCOTCH_DEBUG_ALL lbrotax[pcolnum] = -1; #endif /* SCOTCH_DEBUG_ALL */ continue; /* Skip to next column without allocating or linking */ } if ((fcoltab = memAlloc (frownbr * sizeof (SCOTCH_Num))) == NULL) { /* Allocate array for factored column */ errorPrint ("factorView2: out of memory (2)"); return (1); } for (frowidx = fnxttab[0], fcolptr = fcoltab; frowidx != frowidd; frowidx = fnxttab[frowidx]) /* Fill factored array for column */ *fcolptr ++ = frowtab[frowidx]; dcolnum = fcoltab[0]; /* Get number of father, that it, first extra-diagonal */ ldadtax[pcolnum] = dcolnum; /* Link factored column to the separation tree */ lbrotax[pcolnum] = lsontax[dcolnum]; lsontax[dcolnum] = pcolnum; facttax[pcolnum] = fcoltab; /* Save factored array */ } memFree (frowtab); /* Free group leader */ return (0); } static void factorView3 ( FactorStat * restrict const statptr, SCOTCH_Num levlnum, SCOTCH_Num vertnum, double * restrict const hsumptr) { double hsumtmp; hsumtmp = 0.0; if (statptr->lsontax[vertnum] != -1) { /* If node has descendants */ SCOTCH_Num csonnum; for (csonnum = statptr->lsontax[vertnum]; csonnum != -1; csonnum = statptr->lbrotax[csonnum]) factorView3 (statptr, levlnum + 1, csonnum, &hsumtmp); } else { hsumtmp = (double) levlnum; statptr->heignbr ++; if (levlnum < statptr->heigmin) statptr->heigmin = levlnum; if (levlnum > statptr->heigmax) statptr->heigmax = levlnum; } *hsumptr += hsumtmp; } static void factorView4 ( FactorStat * restrict const statptr, SCOTCH_Num levlnum, SCOTCH_Num vertnum, double * restrict const fopcptr) { SCOTCH_Num fnnztmp; double fopctmp; fnnztmp = statptr->fnnztax[vertnum] + 1; /* Get extra-diagonals, plus diagonal */ fopctmp = (double) fnnztmp; statptr->fnnzsum += fopctmp; fopctmp *= fopctmp; if (statptr->lsontax[vertnum] != -1) { /* If node has descendants */ SCOTCH_Num csonnum; for (csonnum = statptr->lsontax[vertnum]; csonnum != -1; csonnum = statptr->lbrotax[csonnum]) factorView4 (statptr, levlnum + 1, csonnum, &fopctmp); /* Accumulate OPC on local sum */ } else statptr->heigdlt += fabs ((double) levlnum - statptr->heigavg); *fopcptr += fopctmp; /* Aggregate local sum at higher level */ } scotch-5.1.12b.dfsg/src/scotch/mmk_m2.h0000644000175300017530000000634511611563204020005 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mmk_m2.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the data declara- **/ /** tions for the bidimensional finite **/ /** element grid mesh building program. **/ /** **/ /** DATES : # Version 4.0 : from : 26 sep 2002 **/ /** to : 26 sep 2002 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 1 /* Number of files which can be arguments */ #define C_filenamemshout C_fileTab[0].name /* Source mesh output file name */ #define C_filenamegeoout C_fileTab[1].name /* Geometry mesh output file name */ #define C_filepntrmshout C_fileTab[0].pntr /* Source mesh output file */ #define C_filepntrgeoout C_fileTab[1].pntr /* Geometry mesh output file */ /*+ Process flags. +*/ #define C_FLAGGEOOUT 0x0001 /* Output mesh geometry */ #define C_FLAGDEFAULT 0x0000 /* Default flags */ scotch-5.1.12b.dfsg/src/scotch/dgscat.c0000644000175300017530000001746711611563204020072 0ustar hazelscthazelsct/* Copyright 2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgscat.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This program distributes a source graph **/ /** across processors and saves it as a **/ /** distributed source graph. **/ /** This module contains the main function. **/ /** **/ /** DATES : # Version 5.0 : from : 17 may 2007 **/ /** to : 16 jun 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGSCAT #define SCOTCH_PTSCOTCH #include "module.h" #include "common.h" #include "ptscotch.h" #include "dgscat.h" /* ** The static and global definitions. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "dgscat [ []] ", " -c : Check the input graph after loading", " -h : Display this help", " -r : Set root process for centralized files (default is 0)", " -V : Print program version and copyright", NULL }; /*********************/ /* */ /* The main routine. */ /* */ /*********************/ int main ( int argc, char * argv[]) { SCOTCH_Dgraph grafdat; int procglbnbr; int proclocnum; int protglbnum; /* Root process */ int flagval; int i; #ifdef SCOTCH_PTHREAD int thrdlvlreqval; int thrdlvlproval; #endif /* SCOTCH_PTHREAD */ errorProg ("dgscat"); #ifdef SCOTCH_PTHREAD thrdlvlreqval = MPI_THREAD_MULTIPLE; if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) errorPrint ("main: Cannot initialize (1)"); if (thrdlvlreqval > thrdlvlproval) errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); #else /* SCOTCH_PTHREAD */ if (MPI_Init (&argc, &argv) != MPI_SUCCESS) errorPrint ("main: Cannot initialize (2)"); #endif /* SCOTCH_PTHREAD */ MPI_Comm_size (MPI_COMM_WORLD, &procglbnbr); /* Get communicator data */ MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum); protglbnum = 0; /* Assume root process is process 0 */ if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } flagval = C_FLAGNONE; for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else errorPrint ("main: too many file names given"); } else { /* If found an option name */ switch (argv[i][1]) { case 'C' : case 'c' : flagval |= C_FLAGCHECK; break; #ifdef SCOTCH_DEBUG_ALL case 'D' : case 'd' : flagval |= C_FLAGDEBUG; break; #endif /* SCOTCH_DEBUG_ALL */ case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'R' : /* Root process (if necessary) */ case 'r' : protglbnum = atoi (&argv[i][2]); if ((protglbnum < 0) || (protglbnum >= procglbnbr) || ((protglbnum == 0) && (argv[i][2] != '0'))) errorPrint ("main: invalid root process number"); break; case 'V' : case 'v' : fprintf (stderr, "dgscat, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); } } } #ifdef SCOTCH_DEBUG_ALL if ((flagval & C_FLAGDEBUG) != 0) { fprintf (stderr, "Proc %4d of %d, pid %d\n", proclocnum, procglbnbr, getpid ()); if (proclocnum == protglbnum) { /* Synchronize on keybord input */ char c; printf ("Waiting for key press...\n"); scanf ("%c", &c); } MPI_Barrier (MPI_COMM_WORLD); } #endif /* SCOTCH_DEBUG_ALL */ fileBlockOpenDist (C_fileTab, C_FILENBR, procglbnbr, proclocnum, protglbnum); /* Open all files */ SCOTCH_dgraphInit (&grafdat, MPI_COMM_WORLD); SCOTCH_dgraphLoad (&grafdat, C_filepntrsrcinp, -1, 0); if ((flagval & C_FLAGCHECK) != 0) SCOTCH_dgraphCheck (&grafdat); SCOTCH_dgraphSave (&grafdat, C_filepntrsrcout); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_dgraphExit (&grafdat); MPI_Finalize (); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/gmk_ub2.c0000644000175300017530000002132411611563204020136 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gmk_ub2.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the source graph for undirected **/ /** de Bruijn graphs, to be used to build **/ /** the architecture description files for **/ /** these graphs. **/ /** **/ /** DATES : # Version 1.2 : from : 11 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 2.0 : from : 05 nov 1994 **/ /** to 05 nov 1994 **/ /** # Version 3.0 : from : 11 jul 1995 **/ /** to 12 jul 1995 **/ /** # Version 3.2 : from : 03 jun 1997 **/ /** to : 03 jun 1997 **/ /** # Version 3.3 : from : 07 jun 1999 **/ /** to : 07 jun 1999 **/ /** # Version 3.4 : from : 03 feb 2000 **/ /** to : 03 feb 2000 **/ /** # Version 5.0 : from : 22 jan 2008 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GMK_UB2 #include "module.h" #include "common.h" #include "scotch.h" #include "gmk_ub2.h" #define ngbadd(v) if ((v) != vertnum) { \ int k; \ for (k = 0; k < ngbnbr; k ++) \ if ((v) == ngbtab[k]) \ break; \ if (k == ngbnbr) \ ngbtab[ngbnbr ++] = (v); \ } /* ** The static definitions. */ static int C_paraNum = 0; /* Number of parameters */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* The file array */ { "-", NULL, "w" } }; static const char * C_usageList[] = { "gmk_ub2 [] ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /****************************************/ /* */ /* The main routine, which computes the */ /* source graph description. */ /* */ /****************************************/ int main ( int argc, char * argv[]) { SCOTCH_Num ubdim = 1; /* Graph dimension */ SCOTCH_Num ubnbr; /* Number of vertices */ SCOTCH_Num ubbit; /* Most significant bit */ SCOTCH_Num ngbtab[4]; /* Array of neighbors */ int ngbnbr; /* Current number of neighbors */ SCOTCH_Num vertnum; /* Current vertex number */ int i, j; errorProg ("gmk_ub2"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < 1) { /* If number of parameters not reached */ if ((ubdim = (SCOTCH_Num) atol (argv[i])) < 1) { /* Get dimension */ errorPrint ("main: invalid dimension '%s'", argv[i]); return (1); } C_paraNum ++; continue; /* Process the other parameters */ } if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "gmk_ub2, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ ubnbr = 1 << ubdim; /* Compute number of vertices */ ubbit = 1 << (ubdim - 1); /* Bit to add on the left */ fprintf (C_filepntrsrcout, "0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n0\t000\n", (SCOTCH_Num) ubnbr, /* Print number of vertices */ (SCOTCH_Num) (4 * ubnbr - 6)); /* Print number of edges (arcs) */ for (vertnum = 0; vertnum < ubnbr; vertnum ++) { /* For all vertices */ ngbnbr = 0; /* No neighbors defined yet */ ngbadd ((vertnum << 1) & (ubnbr - 1)); /* Register vertex neighbors */ ngbadd (((vertnum << 1) & (ubnbr - 1)) | 1); ngbadd ((vertnum >> 1) & (ubnbr - 1)); ngbadd (((vertnum >> 1) & (ubnbr - 1)) | ubbit); fprintf (C_filepntrsrcout, "%d", ngbnbr); /* Output number of neighbors */ for (j = 0; j < ngbnbr; j ++) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ngbtab[j]); fprintf (C_filepntrsrcout, "\n"); } fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/gout_c.h0000644000175300017530000002020411611563204020071 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gout_c.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a result viewer. **/ /** This module contains the data declara- **/ /** tions for the main module. **/ /** **/ /** DATES : # Version 2.0 : from : 06 oct 1994 **/ /** to 01 nov 1994 **/ /** # Version 3.0 : from : 14 jul 1995 **/ /** to 02 oct 1995 **/ /** # Version 3.2 : from : 02 dec 1996 **/ /** to 05 jun 1998 **/ /** # Version 3.3 : from : 01 jun 1999 **/ /** to 01 jun 1999 **/ /** # Version 4.0 : from : 11 dec 2001 **/ /** to 11 dec 2001 **/ /** # Version 5.0 : from : 13 dec 2007 **/ /** to 15 mar 2008 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 4 /* Number of files in list */ #define C_FILEARGNBR 4 /* Number of files which can be arguments */ #define C_filenamesrcinp C_fileTab[0].name /* Source graph file name */ #define C_filenamegeoinp C_fileTab[1].name /* Source graph geometry file name */ #define C_filenamemapinp C_fileTab[2].name /* Mapping result file name */ #define C_filenamedatout C_fileTab[3].name /* Output data file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ #define C_filepntrgeoinp C_fileTab[1].pntr /* Source graph geometry file */ #define C_filepntrmapinp C_fileTab[2].pntr /* Mapping result input file */ #define C_filepntrdatout C_fileTab[3].pntr /* Data output file */ #define C_filemodemapinp C_fileTab[2].mode /* Mapping result mode */ /*+ Dimension definitions. +*/ #define x c[0] #define y c[1] #define z c[2] /*+ Geometry flags. +*/ #define C_GEOFLAGDEFAULT 0x0001 /* Default geometry flag */ #define C_GEOFLAGUSE 0x0001 /* Use geometry */ #define C_GEOFLAGROTATE 0x0002 /* Rotate the picture by 90 degrees */ #define C_GEOFLAGPERMUT 0x0004 /* Permute Y and Z dimensions */ /* ** The type and structure definitions. */ /*+ This structure defines a source graph. +*/ typedef struct C_Graph_ { SCOTCH_Graph grafdat; /*+ Source graph data +*/ SCOTCH_Num baseval; /*+ Base value +*/ SCOTCH_Num vertnbr; /*+ Number of vertices +*/ SCOTCH_Num * verttab; /*+ Vertex array +*/ SCOTCH_Num * vendtab; /*+ Vertex end array +*/ SCOTCH_Num * vlbltab; /*+ Vertex label array +*/ SCOTCH_Num edgenbr; /*+ Number of edges +*/ SCOTCH_Num * edgetab; /*+ Edge array +*/ } C_Graph; /*+ This structure defines a geometrical vertex. +*/ typedef struct C_GeoVert_ { double c[3]; /*+ Vertex coordinates (x,y,z) +*/ } C_GeoVert; /*+ This structure defines a geometrical mapping which contains the positions of the graph vertices. +*/ typedef struct C_Geometry_ { const C_Graph * grafptr; /*+ Pointer to source graph +*/ C_GeoVert * verttab; /*+ Pointer to coordinates array +*/ } C_Geometry; /*+ This structure defines a domain label mapping, which contains the reference to the mapping source graph. +*/ typedef struct C_Mapping_ { const C_Graph * grafptr; /*+ Pointer to source graph +*/ SCOTCH_Num * labltab; /*+ Pointer to label array +*/ } C_Mapping; /*+ The sort structure, used to sort graph vertices by label. +*/ typedef struct C_VertSort_ { SCOTCH_Num labl; /*+ Vertex label +*/ SCOTCH_Num num; /*+ Vertex number +*/ } C_VertSort; /*+ This structure is the code name array entries. +*/ typedef struct C_ParseCode_ { int code; /*+ Code value +*/ char * name; /*+ Code name +*/ } C_ParseCode; /* This structure defines the code argument array entries. */ typedef struct C_ParseArg_ { const char * name; /*+ Name of the argument +*/ int code; /*+ Code value +*/ const char * format; /*+ scanf-like format; NULL means char, no value +*/ const void * ptr; /*+ Pointer to the argument location +*/ int (* func) (); /*+ Pointer to the argument test function +*/ } C_ParseArg; /* ** The global data declarations. */ extern File C_fileTab[C_FILENBR]; /*+ File array +*/ /* ** The function prototypes. */ int C_geoParse (const char * const); void C_geoInit (C_Geometry * const, const C_Graph * const); void C_geoExit (C_Geometry * const); int C_geoLoad (C_Geometry * const, FILE * const); void C_mapInit (C_Mapping * const, const C_Graph * const); void C_mapExit (C_Mapping * const); int C_mapLoad (C_Mapping * const, FILE * const); int C_parse (const C_ParseCode * const, const C_ParseArg * const, int * const, char * const); scotch-5.1.12b.dfsg/src/scotch/amk_ccc.c0000644000175300017530000002535711611563204020202 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : amk_ccc.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the distance map for CCC **/ /** graphs, to be used to build the archi- **/ /** tecture description files for these **/ /** graphs. **/ /** **/ /** DATES : # Version 1.3 : from : 24 apr 1994 **/ /** to : 24 apr 1994 **/ /** # Version 2.0 : from : 13 jul 1994 **/ /** to : 12 nov 1994 **/ /** # Version 3.0 : from : 18 sep 1995 **/ /** to : 19 sep 1995 **/ /** # Version 3.2 : from : 07 may 1997 **/ /** to : 07 may 1997 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 02 oct 1998 **/ /** # Version 3.4 : from : 03 feb 2000 **/ /** to : 03 feb 2000 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define AMK_CCC #include "module.h" #include "common.h" #include "scotch.h" #include "amk_ccc.h" /* ** The static and global definitions. */ static int C_paraNum = 0; /* Number of parameters */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* The file array */ { "-", NULL, "w" } }; static C_VertDist * C_distaTab; /* Pointer to distance map table */ static C_Queue C_distaQueue; /* Distance queue */ static const char * C_usageList[] = { /* Usage list */ "amk_ccc [] ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /*************************************************/ /* */ /* The main routine, which computes the distance */ /* triangular table. */ /* */ /*************************************************/ int main ( int argc, char * argv[]) { SCOTCH_Num ccdim; /* Dimension of the graph */ SCOTCH_Num ccnbr; /* Number of vertices */ SCOTCH_Num ccbit; /* Mask variable */ SCOTCH_Num ccmax; /* Maximum terminal */ C_Vertex v, w, x; /* Vertex variables */ SCOTCH_Num d; /* Vertex distance to root */ SCOTCH_Num t; /* Vertex terminal value */ SCOTCH_Num i, j, k; errorProg ("amk_ccc"); ccdim = 2; if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < 1) { /* If number of parameters not reached */ if ((ccdim = atoi (argv[i])) < 1) { /* Get the dimension */ errorPrint ("main: invalid dimension '%s'", argv[i]); return (1); } C_paraNum ++; continue; /* Process the other parameters */ } if (C_fileNum < C_FILENBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "amk_ccc, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ ccnbr = ccdim * (1 << ccdim); /* Compute number of vertices */ ccbit = (1 << ccdim) - 1; /* Get maximum position number */ for (ccmax = ((1 << (ccdim + 1)) - 1), i = ccdim - 1; /* Compute biggest terminal value */ i != 0; i >>= 1) ccmax = (ccmax << 1) | (i & 1); fprintf (C_filepntrarcout, "deco\n0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", /* Print the file header */ (SCOTCH_Num) ccnbr, /* Print number of terminal domains */ (SCOTCH_Num) ccmax); /* Print biggest terminal value */ for (v.lvl = 0; v.lvl < ccdim; v.lvl ++) { /* For all levels */ for (v.pos = 0; v.pos <= ccbit; v.pos ++) { /* For all positions in these levels */ t = (1 << ccdim) | v.pos; /* Perform the hypercube cuts */ for (i = v.lvl, j = ccdim; j != 1; ) { /* Perform the cycle cuts */ t <<= 1; k = (j + 1) >> 1; if (i >= k) { /* If upper (smallest) half */ t |= 1; i -= k; j -= k; } else /* If lower (biggest) half */ j = k; } fprintf (C_filepntrarcout, SCOTCH_NUMSTRING "\t1\t" SCOTCH_NUMSTRING "\n", (SCOTCH_Num) C_vertLabl (&v), /* Print terminal label */ (SCOTCH_Num) t); /* Print terminal number */ } } if ((C_queueInit (&C_distaQueue, ccmax) != 0) || /* Allocate the distance array */ ((C_distaTab = (C_VertDist *) memAlloc (ccmax * sizeof (C_VertDist))) == NULL)) { errorPrint ("main: out of memory"); return (1); } for (v.lvl = 0; v.lvl < ccdim; v.lvl ++) { /* For all levels */ for (v.pos = 0; v.pos <= ccbit; v.pos ++) { /* For all positions in these levels */ for (i = 0; i < ccnbr; i ++) /* Initialize vertex table */ C_distaTab[i].queued = 0; /* Vertex not queued yet */ C_distaRoot (&v); /* Set the queue with root v */ while (C_distaGet (&w, &d)) { /* As long as the queue is not empty */ C_distaTab[C_vertLabl (&w)].dist = d; /* Keep the distance information */ d ++; /* Search for neighbors at next level */ x.lvl = w.lvl; /* Add neighbors to queue */ x.pos = w.pos ^ (1 << x.lvl); C_distaPut (&x, d); x.lvl = (w.lvl == 0) ? (ccdim - 1) : (w.lvl - 1); x.pos = w.pos; C_distaPut (&x, d); x.lvl = (w.lvl == (ccdim - 1)) ? 0 : (w.lvl + 1); C_distaPut (&x, d); } if (v.lvl + v.pos > 0) { /* Print distance triangular map line */ fprintf (C_filepntrarcout, SCOTCH_NUMSTRING, (SCOTCH_Num) C_distaTab[0].dist); for (i = 1; i < C_vertLabl (&v); i ++) fprintf (C_filepntrarcout, " " SCOTCH_NUMSTRING, (SCOTCH_Num) C_distaTab[i].dist); fprintf (C_filepntrarcout, "\n"); } } } fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ C_queueExit (&C_distaQueue); memFree (C_distaTab); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/gmap.c0000644000175300017530000004036411627540210017540 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gmap.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a graph mapping software. **/ /** This module contains the main function. **/ /** **/ /** DATES : # Version 0.0 : from : 05 jan 1993 **/ /** to 12 may 1993 **/ /** # Version 1.1 : from : 15 oct 1993 **/ /** to 15 oct 1993 **/ /** # Version 1.3 : from : 06 apr 1994 **/ /** to 18 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 17 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to 18 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 02 oct 1995 **/ /** # Version 3.1 : from : 07 nov 1995 **/ /** to 25 apr 1996 **/ /** # Version 3.2 : from : 24 sep 1996 **/ /** to 26 may 1998 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to : 30 mar 1999 **/ /** # Version 3.4 : from : 03 feb 2000 **/ /** to : 03 feb 2000 **/ /** # Version 4.0 : from : 16 jan 2004 **/ /** to : 27 dec 2004 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 18 jun 2008 **/ /** # Version 5.1 : from : 30 jun 2010 **/ /** to : 31 aug 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GMAP #include "module.h" #include "common.h" #include "scotch.h" #include "gmap.h" /* ** The static variables. */ static int C_partNbr = 1; /* Default number of parts / cluster size */ static int C_paraNum = 0; /* Number of parameters */ static int C_paraNbr = 0; /* No parameters for mapping */ static int C_fileNum = 0; /* Number of file in arg list */ static int C_fileNbr = 4; /* Number of files for mapping */ static File C_fileTab[C_FILENBR] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "r" }, { "-", NULL, "w" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { /* Usage */ "gmap [ [ [ []]]] ", "gpart [] [ [ []]] ", " -b : Load imbalance tolerance (default: 0.05)", " -c : Choose default mapping strategy according to one or several of :", " b : enforce load balance as much as possible", " q : privilege quality over speed (default)", " s : privilege speed over quality", " t : enforce safety", " -h : Display this help", " -m : Set mapping strategy (see user's manual)", " -q : Do graph clustering instead of graph partitioning (for gpart)", " -q : Do graph clustering instead of static mapping (for gmap)", " -s : Force unity weights on :", " e : edges", " v : vertices", " -V : Print program version and copyright", " -v : Set verbose mode to :", " m : mapping information", " s : strategy information", " t : timing information", "", "See default strategy with option '-vs'", NULL }; /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ int main ( int argc, char * argv[]) { SCOTCH_Graph grafdat; /* Source graph */ SCOTCH_Num grafflag; /* Source graph properties */ SCOTCH_Arch archdat; /* Target architecture */ SCOTCH_Strat stradat; /* Mapping strategy */ SCOTCH_Mapping mapdat; /* Mapping data */ Clock runtime[2]; /* Timing variables */ double kbalval; /* Imbalance tolerance value */ int flagval; SCOTCH_Num straval; char * straptr; int i, j; flagval = C_FLAGNONE; /* Default behavior */ kbalval = 0.05; /* Default imbalance */ straval = 0; /* No strategy flags */ straptr = NULL; #ifdef SCOTCH_COMPILE_PART flagval |= C_FLAGPART; C_paraNbr = 1; /* One more parameter */ C_fileNbr = 3; /* One less file to provide */ errorProg ("gpart"); #else errorProg ("gmap"); #endif /* SCOTCH_COMPILE_PART */ intRandInit (); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } grafflag = 0; /* Use vertex and edge weights */ SCOTCH_stratInit (&stradat); /* Set default mapping strategy */ for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < C_paraNbr) { /* If number of parameters not reached */ if ((C_partNbr = atoi (argv[i])) < 1) /* Get the number of parts */ errorPrint ("main: invalid number of parts '%s'", argv[i]); C_paraNum ++; continue; /* Process the other parameters */ } if (C_fileNum < C_fileNbr) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else errorPrint ("main: too many file names given"); } else { /* If found an option name */ switch (argv[i][1]) { case 'B' : case 'b' : flagval |= C_FLAGKBALVAL; kbalval = atof (&argv[i][2]); if ((kbalval < 0.0) || (kbalval > 1.0) || ((kbalval == 0.0) && ((argv[i][2] != '0') && (argv[i][2] != '.')))) { errorPrint ("main: invalid load imbalance ratio"); } break; case 'C' : case 'c' : /* Strategy selection parameters */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'B' : case 'b' : straval |= SCOTCH_STRATBALANCE; break; case 'Q' : case 'q' : straval |= SCOTCH_STRATQUALITY; break; case 'S' : case 's' : straval |= SCOTCH_STRATSPEED; break; case 'T' : case 't' : straval |= SCOTCH_STRATSAFETY; break; default : errorPrint ("main: invalid strategy selection option '%c' after '-C'", argv[i][j]); } } break; case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'M' : case 'm' : straptr = &argv[i][2]; SCOTCH_stratExit (&stradat); SCOTCH_stratInit (&stradat); SCOTCH_stratGraphMap (&stradat, straptr); break; case 'Q' : case 'q' : flagval |= C_FLAGCLUSTER; if ((flagval & C_FLAGPART) != 0) { /* If partitioning program */ if (argv[i][2] != '\0') errorPrint ("main: invalid parameter '%s' after '-q' for gpart", argv[i] + 2); } else { if (argv[i][1] == '\0') errorPrint ("main: missing parameter after '-q' for gmap"); if ((C_partNbr = atoi (argv[i] + 2)) < 1) /* Get maximum cluster load */ errorPrint ("main: invalid cluster load '%s'", argv[i] + 2); } break; case 'S' : case 's' : /* Source graph parameters */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'E' : case 'e' : grafflag |= 2; /* Do not load edge weights */ break; case 'V' : case 'v' : grafflag |= 1; /* Do not load vertex weights */ break; default : errorPrint ("main: invalid source graph option '%c'", argv[i][j]); } } break; case 'V' : fprintf (stderr, "gmap/gpart, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); case 'v' : /* Output control info */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'M' : case 'm' : flagval |= C_FLAGVERBMAP; break; case 'S' : case 's' : flagval |= C_FLAGVERBSTR; break; case 'T' : case 't' : flagval |= C_FLAGVERBTIM; break; default : errorPrint ("main: unprocessed parameter '%c' in '%s'", argv[i][j], argv[i]); } } break; default : errorPrint ("main: unprocessed option '%s'", argv[i]); } } } if ((flagval & C_FLAGPART) != 0) { /* If program run as the partitioner */ C_fileTab[3].name = C_fileTab[2].name; /* Put provided file names at their right place */ C_fileTab[2].name = C_fileTab[1].name; C_fileTab[1].name = "-"; } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ clockInit (&runtime[0]); clockStart (&runtime[0]); SCOTCH_graphInit (&grafdat); /* Create graph structure */ SCOTCH_graphLoad (&grafdat, C_filepntrsrcinp, -1, grafflag); /* Read source graph */ SCOTCH_archInit (&archdat); /* Create architecture structure */ if ((flagval & C_FLAGPART) != 0) { /* If program run as the partitioner */ if ((flagval & C_FLAGCLUSTER) != 0) /* If program run as graph clustering */ SCOTCH_archVcmplt (&archdat); /* Create a variable-sized complete graph */ else /* Program is run as plain graph partitioner */ SCOTCH_archCmplt (&archdat, C_partNbr); /* Create a complete graph of proper size */ } else { SCOTCH_archLoad (&archdat, C_filepntrtgtinp); /* Read target architecture */ if ((flagval & C_FLAGCLUSTER) == 0) /* If part size not to be preserved */ C_partNbr = SCOTCH_archSize (&archdat); else { if (SCOTCH_archVar (&archdat) == 0) errorPrint ("main: non variable-sized architecture provided while '-q' flag set"); } } if (((straval != 0) || ((flagval & C_FLAGKBALVAL) != 0)) && (straptr != NULL)) errorPrint ("main: options '-b' / '-c' and '-m' are exclusive"); if ((flagval & C_FLAGCLUSTER) != 0) /* If clustering wanted */ SCOTCH_stratGraphClusterBuild (&stradat, straval, (SCOTCH_Num) C_partNbr, 1.0, kbalval); else SCOTCH_stratGraphMapBuild (&stradat, straval, (SCOTCH_Num) C_partNbr, kbalval); clockStop (&runtime[0]); /* Get input time */ clockInit (&runtime[1]); clockStart (&runtime[1]); SCOTCH_graphMapInit (&grafdat, &mapdat, &archdat, NULL); SCOTCH_graphMapCompute (&grafdat, &mapdat, &stradat); /* Perform mapping */ clockStop (&runtime[1]); /* Get computation time */ clockStart (&runtime[0]); SCOTCH_graphMapSave (&grafdat, &mapdat, C_filepntrmapout); /* Write mapping */ clockStop (&runtime[0]); /* Get output time */ if (flagval & C_FLAGVERBSTR) { fprintf (C_filepntrlogout, "S\tStrat="); SCOTCH_stratSave (&stradat, C_filepntrlogout); putc ('\n', C_filepntrlogout); } if (flagval & C_FLAGVERBTIM) { fprintf (C_filepntrlogout, "T\tMapping\t\t%g\nT\tI/O\t\t%g\nT\tTotal\t\t%g\n", (double) clockVal (&runtime[1]), (double) clockVal (&runtime[0]), (double) clockVal (&runtime[0]) + (double) clockVal (&runtime[1])); } if (flagval & C_FLAGVERBMAP) SCOTCH_graphMapView (&grafdat, &mapdat, C_filepntrlogout); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_graphMapExit (&grafdat, &mapdat); SCOTCH_graphExit (&grafdat); SCOTCH_stratExit (&stradat); SCOTCH_archExit (&archdat); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/amk_fft2.h0000644000175300017530000001353211611563204020310 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : amk_fft2.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the distance map for FFT **/ /** graphs, to be used to build the archi- **/ /** tecture description files for these **/ /** graphs. **/ /** **/ /** DATES : # Version 1.3 : from : 19 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to : 04 jul 1995 **/ /** # Version 3.2 : from : 07 may 1997 **/ /** to : 07 may 1997 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 02 oct 1998 **/ /** # Version 5.0 : from : 01 jan 2008 **/ /** to : 01 jan 2008 **/ /** **/ /************************************************************/ /* ** The type and structure definitions */ /*+ File name aliases. +*/ #define C_FILENBR 1 /* Number of files in list */ #define C_filenamearcout C_fileTab[0].name /* Architecture output file name */ #define C_filepntrarcout C_fileTab[0].pntr /* Architecture output file */ /*+ This structure defines an FFT vertex. +*/ typedef struct C_Vertex_ { SCOTCH_Num lvl; /*+ Vertex level +*/ SCOTCH_Num pos; /*+ Vertex position +*/ } C_Vertex; /*+ This structure defines a vertex distance information. +*/ typedef struct C_VertDist_ { int queued; /*+ Flag set if vertex queued +*/ SCOTCH_Num dist; /*+ Distance to initial vertex +*/ } C_VertDist; /*+ This is a neighbor queue element. +*/ typedef struct C_QueueElem_ { C_Vertex vert; /*+ Vertex number +*/ SCOTCH_Num dist; /*+ Distance reached +*/ } C_QueueElem; /*+ This is the distance queue. +*/ typedef struct C_Queue_ { C_QueueElem * tab; /*+ Pointer to queue data +*/ SCOTCH_Num min; /*+ Pointer to first element +*/ SCOTCH_Num max; /*+ Pointer to last element +*/ } C_Queue; /* ** The macro definitions. */ #define C_vertLabl(v) (((v)->lvl << fdim) | (v)->pos) #define C_queueInit(q,n) ((((q)->tab = (C_QueueElem *) memAlloc ((n) * sizeof (C_QueueElem))) == NULL) ? 1 : 0) #define C_queueExit(q) memFree ((q)->tab) #define C_queueFlush(q) (q)->min = \ (q)->max = 0 #define C_queuePut(q,v,d) ((q)->tab[(q)->max].vert = *(v), \ (q)->tab[(q)->max ++].dist = (d)) #define C_queueGet(q,v,d) (((q)->min < (q)->max) ? (*(v) = (q)->tab[(q)->min].vert, \ *(d) = (q)->tab[(q)->min ++].dist, \ 1) \ : 0) #define C_distaRoot(v) (C_queueFlush (&C_distaQueue), \ C_queuePut (&C_distaQueue, (v), 0), \ C_distaTab[C_vertLabl (v)].queued = 1) #define C_distaGet(v,d) (C_queueGet (&C_distaQueue, (v), (d))) #define C_distaPut(v,d) ((C_distaTab[C_vertLabl (v)].queued == 0) \ ? C_queuePut (&C_distaQueue, (v), d), \ C_distaTab[C_vertLabl (v)].queued = 1 \ : 0) scotch-5.1.12b.dfsg/src/scotch/gout_o.c0000644000175300017530000012606511611563204020114 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gout_o.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a result viewer. **/ /** This module contains output routines. **/ /** **/ /** DATES : # Version 2.0 : from : 07 oct 1994 **/ /** to 23 dec 1994 **/ /** # Version 3.0 : from : 14 jul 1995 **/ /** to 03 oct 1995 **/ /** # Version 3.1 : from : 28 mar 1996 **/ /** to 03 jun 1996 **/ /** # Version 3.2 : from : 02 dec 1996 **/ /** to 05 jun 1998 **/ /** # Version 3.3 : from : 29 may 1999 **/ /** to : 03 jun 1999 **/ /** # Version 4.0 : from : 11 dec 2001 **/ /** to 11 dec 2001 **/ /** # Version 5.0 : from : 25 may 2007 **/ /** to 18 jun 2007 **/ /** # Version 5.1 : from : 25 oct 2007 **/ /** to 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes */ #define GOUT #include "module.h" #include "common.h" #include "scotch.h" #include "gout_c.h" #include "gout_o.h" /* ** The static and global variables */ static O_OutParam O_outParam = { /* Parameter structure */ O_OUTTYPEINVMESH, /* Default output type */ { 'c', 'v' }, /* OpenInventor mesh defaults */ { 'f' }, /* PostScript matrix defaults */ { 'f', 'g', /* PostScript mesh defaults */ 'v', 'd', 's', { { 0.0, 0.0 } }, { { 1.0, 1.0 } } }, { 'c', 'v', 'a' } }; /* Tulip graph defaults */ static C_ParseCode O_outList[] = { /* Output code list */ { O_OUTTYPEINVMESH, "i" }, { O_OUTTYPEPOSMATR, "m" }, { O_OUTTYPEPOSMESH, "p" }, { O_OUTTYPETULMESH, "t" }, { O_OUTTYPENBR, NULL } }; static C_ParseArg O_outArg[] = { /* Output type argument list */ { "c", O_OUTTYPEINVMESH, NULL, &O_outParam.InvMesh.color }, { "g", O_OUTTYPEINVMESH, NULL, &O_outParam.InvMesh.color }, { "r", O_OUTTYPEINVMESH, NULL, &O_outParam.InvMesh.edge }, { "v", O_OUTTYPEINVMESH, NULL, &O_outParam.InvMesh.edge }, { "e", O_OUTTYPEPOSMATR, NULL, &O_outParam.PosMatr.type }, { "f", O_OUTTYPEPOSMATR, NULL, &O_outParam.PosMatr.type }, { "c", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.color }, { "g", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.color }, { "e", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.type }, { "f", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.type }, { "l", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.clip }, { "s", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.clip }, { "a", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.disk }, { "d", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.disk }, { "r", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.edge }, { "v", O_OUTTYPEPOSMESH, NULL, &O_outParam.PosMesh.edge }, { "x", O_OUTTYPEPOSMESH, "%lf", &O_outParam.PosMesh.min.x }, { "X", O_OUTTYPEPOSMESH, "%lf", &O_outParam.PosMesh.max.x }, { "y", O_OUTTYPEPOSMESH, "%lf", &O_outParam.PosMesh.min.y }, { "Y", O_OUTTYPEPOSMESH, "%lf", &O_outParam.PosMesh.max.y }, { "b", O_OUTTYPETULMESH, NULL, &O_outParam.TulMesh.color }, { "c", O_OUTTYPETULMESH, NULL, &O_outParam.TulMesh.color }, { "r", O_OUTTYPETULMESH, NULL, &O_outParam.TulMesh.edge }, { "v", O_OUTTYPETULMESH, NULL, &O_outParam.TulMesh.edge }, { "a", O_OUTTYPETULMESH, NULL, &O_outParam.TulMesh.disk }, { "d", O_OUTTYPETULMESH, NULL, &O_outParam.TulMesh.disk }, { NULL, O_OUTTYPENBR, "", NULL } }; static double outcolorcoltab[16][3] = { /* Color list */ { 1.00, 0.00, 0.00 }, /* Red */ { 0.00, 1.00, 0.00 }, /* Green */ { 1.00, 1.00, 0.00 }, /* Yellow */ { 0.00, 0.00, 1.00 }, /* Blue */ { 1.00, 0.00, 1.00 }, /* Magenta */ { 0.00, 1.00, 1.00 }, /* Cyan */ { 1.00, 0.50, 0.20 }, /* Orange */ { 0.30, 0.55, 0.00 }, /* Olive */ { 0.72, 0.47, 0.47 }, /* Dark pink */ { 0.33, 0.33, 0.81 }, /* Sea blue */ { 1.00, 0.63, 0.63 }, /* Pink */ { 0.62, 0.44, 0.65 }, /* Violet */ { 0.60, 0.80, 0.70 }, /* Pale green */ { 0.47, 0.20, 0.00 }, /* Brown */ { 0.00, 0.68, 0.68 }, /* Turquoise */ { 0.81, 0.00, 0.40 } }; /* Purple */ static double outcolorblwtab[8][3] = { /* Grey list */ { 1.00, 1.00, 1.00 }, { 0.20, 0.20, 0.20 }, { 0.50, 0.50, 0.50 }, { 0.80, 0.80, 0.80 }, { 0.30, 0.30, 0.30 }, { 0.90, 0.90, 0.90 }, { 0.40, 0.40, 0.40 }, { 0.70, 0.70, 0.70 } }; /****************************************/ /* */ /* This is the color selection routine. */ /* */ /****************************************/ void outColorBlw ( const SCOTCH_Num labl, double color[]) { if (labl == (-1)) { color[0] = color[1] = color[2] = 1.0L; } else { color[0] = (double) outcolorblwtab[labl % 8][0]; color[1] = (double) outcolorblwtab[labl % 8][1]; color[2] = (double) outcolorblwtab[labl % 8][2]; } } void outColorColor ( const SCOTCH_Num labl, double color[]) { if (labl == (-1)) { color[0] = color[1] = color[2] = 1.0L; } else { color[0] = (double) outcolorcoltab[labl % 16][0]; color[1] = (double) outcolorcoltab[labl % 16][1]; color[2] = (double) outcolorcoltab[labl % 16][2]; } } /****************************/ /* */ /* The main output routine. */ /* */ /****************************/ /* This routine parses the output ** option string. ** It returns: ** - 0 : if string successfully scanned. ** - 1 : if invalid options ** - 2 : if invalid option arguments. ** - 3 : if syntax error in string. */ int outDrawParse ( char * const string) { return (C_parse (O_outList, O_outArg, (int * const) (void *) &O_outParam.type, string)); } /* This routine is the generic output call. ** It returns: ** - VOID : in all cases. */ void outDraw ( const C_Graph * const grafptr, /* Graph structure */ const C_Geometry * const geomptr, /* Graph geometry */ const C_Mapping * const mapptr, /* Result mapping */ FILE * const stream) /* Output stream */ { switch (O_outParam.type) { case O_OUTTYPEINVMESH : /* Mesh OpenInventor output type */ outDrawInvMesh (grafptr, geomptr, mapptr, stream); break; case O_OUTTYPEPOSMATR : /* Matrix PostScript output type */ outDrawPosMatr (grafptr, geomptr, mapptr, stream); break; case O_OUTTYPEPOSMESH : /* Mesh PostScript output type */ outDrawPosMesh (grafptr, geomptr, mapptr, stream); break; case O_OUTTYPETULMESH : /* Mesh Tulip output type */ outDrawTulMesh (grafptr, geomptr, mapptr, stream); break; default : errorPrint ("outDraw: invalid output method '%d'", O_outParam.type); } } /****************************************/ /* */ /* This is the Inventor output routine. */ /* */ /****************************************/ int outDrawInvMesh ( const C_Graph * const grafptr, /* Graph structure, sorted by vertex index */ const C_Geometry * const geomptr, /* Graph geometry, sorted by vertex label */ const C_Mapping * const mapptr, /* Result mapping, sorted by vertex label */ FILE * const stream) /* Output stream */ { void (* outcolor) (const SCOTCH_Num, double[]); /* Color routine */ O_InvMeshPath * pattab; /* Array of path building data */ int * idxtab; /* Array of indexes */ int idxnbr; /* Number of indexes */ time_t pictime; /* Creation time */ double color[3]; /* Vertex color */ int i, j, k; if (geomptr->verttab == NULL) { errorPrint ("outDrawInvMesh: geometry not provided"); return (1); } time (&pictime); /* Get current time */ outcolor = (O_outParam.InvMesh.color == 'c') ? outColorColor : outColorBlw; /* Select color output routine */ if (((idxtab = (int *) memAlloc ((grafptr->edgenbr / 2) * 3 * sizeof (int))) == NULL) || ((pattab = (O_InvMeshPath *) memAlloc (grafptr->vertnbr * sizeof (O_InvMeshPath))) == NULL)) { errorPrint ("outDrawInvMesh: out of memory"); if (idxtab != NULL) memFree (idxtab); return (1); } idxnbr = 0; /* No indexes yet */ for (i = 0, j = 0; i < grafptr->vertnbr; i ++) { /* For all vertices */ pattab[i].nbr = 0; /* Compute the number of output paths */ pattab[i].idx = grafptr->verttab[i]; for ( ; j < grafptr->vendtab[i]; j ++) { if ((grafptr->edgetab[j] > i) && /* If it can be an output edge */ ((O_outParam.InvMesh.edge != 'r') || /* And this edge can be drawn */ (mapptr->labltab[i] == mapptr->labltab[grafptr->edgetab[j]]))) pattab[i].nbr ++; /* One more path to higher vertices */ } } for (i = 0; i < grafptr->vertnbr; ) { /* For all vertices */ if (pattab[i].nbr == 0) { /* If no output path for this vertex */ i ++; /* Skip to next vertex */ continue; } j = i; /* Begin with this vertex */ idxtab[idxnbr ++] = j; /* Add it to the current segment */ do { for (k = pattab[j].idx; k < grafptr->vendtab[j]; k ++) { /* Search for first output */ if ((grafptr->edgetab[k] > j) && /* If it can be an output edge */ ((O_outParam.InvMesh.edge != 'r') || /* And this edge can be drawn */ (mapptr->labltab[j] == mapptr->labltab[grafptr->edgetab[k]]))) break; } pattab[j].nbr --; /* One less output path remaining */ pattab[j].idx = k + 1; /* Search from the next position */ j = grafptr->edgetab[k]; /* Get the path end vertex number */ idxtab[idxnbr ++] = j; /* Add it to the current segment */ } while (pattab[j].nbr > 0); /* As long as there is a path */ idxtab[idxnbr ++] = ~0; /* Mark end of path */ } fprintf (stream, "#Inventor V2.0 ascii\n"); /* Write header */ fprintf (stream, "#Title: %s %s %s\n", C_filenamesrcinp, C_filenamegeoinp, C_filenamemapinp); fprintf (stream, "#Creator: out (F. Pellegrini, LaBRI, Bordeaux)\n"); fprintf (stream, "#CreationDate: %s", ctime (&pictime)); if (idxnbr == 0) /* If nothing to write */ return (0); fprintf (stream, "Separator {\n"); fprintf (stream, " LightModel {\n model\t\tBASE_COLOR\n }\n"); fprintf (stream, " DrawStyle {\n style\t\tLINES\n }\n"); fprintf (stream, " MaterialBinding {\n value\t\tPER_VERTEX\n }\n"); fprintf (stream, " Coordinate3 {\n point [\n\t%g\t%g\t%g", /* Write vertex coordinates */ geomptr->verttab[0].x, geomptr->verttab[0].y, geomptr->verttab[0].z); for (i = 1; i < grafptr->vertnbr; i ++) fprintf (stream, ",\n\t%g\t%g\t%g", geomptr->verttab[i].x, geomptr->verttab[i].y, geomptr->verttab[i].z); fprintf (stream, " ]\n }\n"); fprintf (stream, " BaseColor {\n rgb ["); /* Write color vector */ for (i = 0; i < idxnbr - 2; i ++) { if (idxtab[i] != ~0) { outcolor (mapptr->labltab[idxtab[i]], color); fprintf (stream, "\n\t%g\t%g\t%g,", (double) color[0], (double) color[1], (double) color[2]); } } outcolor (mapptr->labltab[idxtab[idxnbr - 2]], color); fprintf (stream, "\n\t%g\t%g\t%g ]\n }\n", (double) color[0], (double) color[1], (double) color[2]); fprintf (stream, " IndexedLineSet {\n coordIndex ["); /* Write set of lines */ for (i = 0; i < idxnbr - 1; i ++) { if ((i % 8) == 0) fprintf (stream, "\n"); if (idxtab[i] == ~0) fprintf (stream, "\t-1,"); else fprintf (stream, "\t%u,", idxtab[i]); } if (((idxnbr - 1) % 8) == 0) fprintf (stream, "\n"); fprintf (stream, "\t-1 ]\n }\n"); fprintf (stream, "}\n"); /* Write end of separator */ #if 0 for (i = 0; i < grafptr->vertnbr; i ++) { /* For all vertices */ outcolor (mapptr->labltab[i], color); fprintf (stream, "Separator { Translation { translation %lg %lg %lg } BaseColor { rgb [ %lg %lg %lg ] } Sphere { radius 0.3 } }\n", geomptr->verttab[i].x, geomptr->verttab[i].y, geomptr->verttab[i].z, (double) color[0], (double) color[1], (double) color[2]); } #endif memFree (pattab); /* Free path array */ memFree (idxtab); /* Free index array */ return (0); } /*************************************************/ /* */ /* This is the PostScript matrix output routine. */ /* */ /*************************************************/ int outDrawPosMatr ( const C_Graph * const grafptr, /* Graph structure, sorted by vertex index */ const C_Geometry * const geomptr, /* Graph geometry, sorted by vertex label */ const C_Mapping * const mapptr, /* Result mapping, sorted by vertex label */ FILE * const stream) /* Output stream */ { SCOTCH_Num * nonztab; /* Array of non-zero entries */ SCOTCH_Num nonzfrst; /* First non-zero entry of area */ SCOTCH_Num nonzlast; /* Last non-zero entry of area */ double pictsize; /* Number of distinct coordinates */ double pictdisp; /* Size of the matrix display (in inches) */ time_t picttime; /* Creation time */ SCOTCH_Num colnum; SCOTCH_Num vertnum; SCOTCH_Num * edgeptr; if ((nonztab = memAlloc ((grafptr->vertnbr + 1) * sizeof (SCOTCH_Num))) == NULL) { errorPrint ("outDrawPosMatr: out of memory"); return (1); } time (&picttime); /* Get current time */ pictsize = (double) (grafptr->vertnbr + 1); /* Get matrix size */ pictdisp = MIN (O_PSPICTWIDTH, O_PSPICTHEIGHT); if (O_outParam.PosMatr.type == 'e') { /* EPSF-type output */ fprintf (stream, "%%!PS-Adobe-2.0 EPSF-2.0\n"); fprintf (stream, "%%%%Title: %s %s %s\n", C_filenamesrcinp, C_filenamegeoinp, C_filenamemapinp); fprintf (stream, "%%%%Creator: out (F. Pellegrini, LaBRI, Bordeaux)\n"); fprintf (stream, "%%%%CreationDate: %s", ctime (&picttime)); fprintf (stream, "%%%%BoundingBox: 0 0 %d %d\n", (int) (pictdisp * O_PSDPI), (int) (pictdisp * O_PSDPI)); fprintf (stream, "%%%%Pages: 0\n"); fprintf (stream, "%%%%EndComments\n"); } else { /* Full page output */ fprintf (stream, "%%!PS-Adobe-2.0\n"); fprintf (stream, "%%%%Title: %s %s %s\n", C_filenamesrcinp, C_filenamegeoinp, C_filenamemapinp); fprintf (stream, "%%%%Creator: out (F. Pellegrini, LaBRI, Bordeaux)\n"); fprintf (stream, "%%%%CreationDate: %s", ctime (&picttime)); } fprintf (stream, "/p { pop } bind def\n"); fprintf (stream, "/h { 3 1 roll exch 2 copy moveto 2 copy 1 add 5 -3 roll 3 1 roll add exch 2 copy lineto 1 add lineto lineto fill } bind def\n"); fprintf (stream, "/v { 3 copy pop moveto 2 copy add exch pop exch 3 copy pop pop 1 add dup 3 -1 roll lineto exch dup 3 1 roll lineto lineto fill } bind def\n"); fprintf (stream, "/b { 3 copy v 3 copy h pop pop } bind def\n"); fprintf (stream, "/c { 1 3 copy v 3 copy h pop pop } bind def\n"); fprintf (stream, "gsave\n"); /* Save the context */ fprintf (stream, "0 setlinecap\n"); /* Perform miter caps */ if (O_outParam.PosMatr.type == 'f') /* If full page output */ fprintf (stream, "%d %d translate\n", /* Center the picture */ (int) (O_PSDPI * (O_PSPAGEWIDTH - pictdisp)) / 2, (int) (O_PSDPI * (O_PSPAGEWIDTH - pictdisp)) / 2); fprintf (stream, "%f %f scale\n", /* Print scaling factor */ (double) O_PSDPI * pictdisp / pictsize, (double) O_PSDPI * pictdisp / pictsize); fprintf (stream, "[ 1 0 0 -1 0 %d ] concat\n", /* Reverse Y coordinate */ (int) (grafptr->vertnbr + 1)); fprintf (stream, "0 setgray newpath\n"); /* Select black color */ for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { colnum = (mapptr->labltab[vertnum] == ~0) ? vertnum : mapptr->labltab[vertnum]; fprintf (stream, SCOTCH_NUMSTRING "\n", /* Set column value */ (SCOTCH_Num) colnum); memset (nonztab, 0, (colnum + 2) * sizeof (SCOTCH_Num)); for (edgeptr = grafptr->edgetab + grafptr->verttab[colnum]; edgeptr < grafptr->edgetab + grafptr->vendtab[colnum]; edgeptr ++) { if (*edgeptr < colnum) nonztab[*edgeptr] = 1; } nonztab[colnum] = 1; /* Diagonal is non-zero */ for (nonzfrst = 0; nonzfrst <= vertnum; nonzfrst ++) { if (nonztab[nonzfrst] != 0) { /* A non-zero has been found */ for (nonzlast = nonzfrst; nonztab[nonzlast] != 0; nonzlast ++) ; if ((nonzlast - nonzfrst) > 1) /* Draw row block coefficient */ fprintf (stream, SCOTCH_NUMSTRING " " SCOTCH_NUMSTRING " b\n", (SCOTCH_Num) nonzfrst, (SCOTCH_Num) (nonzlast - nonzfrst)); else fprintf (stream, SCOTCH_NUMSTRING " c\n", (SCOTCH_Num) nonzfrst); nonzfrst = nonzlast - 1; } } fprintf (stream, "p "); /* Close the column */ } fprintf (stream, "\ngrestore\n"); /* Restore context */ if (O_outParam.PosMatr.type == 'f') /* If full page output */ fprintf (stream, "showpage\n"); /* Display the page */ memFree (nonztab); return (0); } /***********************************************/ /* */ /* This is the PostScript mesh output routine. */ /* */ /***********************************************/ int outDrawPosMesh ( const C_Graph * const grafptr, /* Graph structure, sorted by vertex index */ const C_Geometry * const geomptr, /* Graph geometry, sorted by vertex label */ const C_Mapping * const mapptr, /* Result mapping, sorted by vertex label */ FILE * const stream) /* Output stream */ { int idxnbr; /* Number of indexes */ int * idxtab; /* Array of indexes */ O_PosMeshPath * pattab; /* Array of path building data */ O_PosMeshVertex * pictab; /* Array of 2D coordinates, sorted by vertex index */ O_Point picmin; /* Picture minimum and maximum coordinates */ O_Point picmax; O_Point picdelt; double picscale; /* Scaling factor */ double picsrad; /* Square of circle radius */ time_t pictime; /* Creation time */ double color[3]; /* Color values */ int i, j, k; if (geomptr->verttab == NULL) { errorPrint ("outDrawPosMesh: geometry not provided"); return (1); } time (&pictime); /* Get current time */ if (((pictab = (O_PosMeshVertex *) memAlloc (grafptr->vertnbr * sizeof (O_PosMeshVertex))) == NULL) || ((idxtab = (int *) memAlloc ((grafptr->edgenbr / 2) * 3 * sizeof (int))) == NULL) || ((pattab = (O_PosMeshPath *) memAlloc (grafptr->vertnbr * sizeof (O_PosMeshPath))) == NULL)) { errorPrint ("outDrawPosMesh: out of memory"); if (pictab != NULL) { if (idxtab != NULL) memFree (idxtab); memFree (pictab); } return (1); } for (i = 0; i < grafptr->vertnbr; i ++) { /* For all vertex indices */ pictab[i].pos.x = geomptr->verttab[i].x + /* Project 3D coordinates into 2D ones */ geomptr->verttab[i].z * (O_POSMESHISOCOS * O_POSMESHISOREDUC); pictab[i].pos.y = geomptr->verttab[i].y + geomptr->verttab[i].z * (O_POSMESHISOSIN * O_POSMESHISOREDUC); } picmin.x = picmin.y = 1e30; /* Pre-set coordinates extrema */ picmax.x = picmax.y = -1e30; if (O_outParam.PosMesh.clip == 'l') { /* If clipping encompasses disks */ for (i = 0, j = 0; i < grafptr->vertnbr; i ++) { pictab[i].rad = 1e30; /* Assume a huge square of radius */ for ( ; j < grafptr->vendtab[i]; j ++) { k = grafptr->edgetab[j]; picsrad = (pictab[i].pos.x - pictab[k].pos.x) * (pictab[i].pos.x - pictab[k].pos.x) + (pictab[i].pos.y - pictab[k].pos.y) * (pictab[i].pos.y - pictab[k].pos.y); if (picsrad < pictab[i].rad) /* Get the smallest square of radius */ pictab[i].rad = picsrad; } pictab[i].rad = sqrt (pictab[i].rad) / 2.0; /* Keep the half-distance for radius */ if ((pictab[i].pos.x - pictab[i].rad) < picmin.x) /* Update extrema if necessary */ picmin.x = pictab[i].pos.x - pictab[i].rad; if ((pictab[i].pos.y - pictab[i].rad) < picmin.y) picmin.y = pictab[i].pos.y - pictab[i].rad; if ((pictab[i].pos.x + pictab[i].rad) > picmax.x) picmax.x = pictab[i].pos.x + pictab[i].rad; if ((pictab[i].pos.y + pictab[i].rad) > picmax.y) picmax.y = pictab[i].pos.y + pictab[i].rad; } } else { /* Border clipping */ for (i = 0; i < grafptr->vertnbr; i ++) { /* For all vertex indices */ if (pictab[i].pos.x < picmin.x) /* Update extrema if necessary */ picmin.x = pictab[i].pos.x; if (pictab[i].pos.y < picmin.y) picmin.y = pictab[i].pos.y; if (pictab[i].pos.x > picmax.x) picmax.x = pictab[i].pos.x; if (pictab[i].pos.y > picmax.y) picmax.y = pictab[i].pos.y; } } picdelt.x = picmax.x - picmin.x; /* Compute picture extents */ picdelt.y = picmax.y - picmin.y; picmin.x += picdelt.x * O_outParam.PosMesh.min.x; /* Resize picture (if necessary) */ picmin.y += picdelt.y * O_outParam.PosMesh.min.y; picmax.x -= picdelt.x * (1.0L - O_outParam.PosMesh.max.x); picmax.y -= picdelt.y * (1.0L - O_outParam.PosMesh.max.y); picdelt.x = picmax.x - picmin.x; /* Recompute picture extents */ picdelt.y = picmax.y - picmin.y; picscale = (picdelt.x == 0.0L) /* Compute scaling factor */ ? ((picdelt.y == 0.0L) ? 1.0L : (O_PSPICTHEIGHT / picdelt.y)) : ((picdelt.y == 0.0L) ? (O_PSPICTWIDTH / picdelt.x) : MIN (O_PSPICTWIDTH / picdelt.x, O_PSPICTHEIGHT / picdelt.y)); picdelt.x *= picscale * O_POSMESHPICTRESOL; /* Rescale extents */ picdelt.y *= picscale * O_POSMESHPICTRESOL; for (i = 0; i < grafptr->vertnbr; i ++) { pictab[i].pos.x = (pictab[i].pos.x - picmin.x) * picscale * O_POSMESHPICTRESOL; /* Rescale coordinates */ pictab[i].pos.y = (pictab[i].pos.y - picmin.y) * picscale * O_POSMESHPICTRESOL; } if (O_outParam.PosMesh.disk == 'd') { /* If disks wanted */ for (i = 0, j = 0; i < grafptr->vertnbr; i ++) { pictab[i].rad = 1e30; /* Assume huge square of radius */ for ( ; j < grafptr->vendtab[i]; j ++) { k = grafptr->edgetab[j]; picsrad = (pictab[i].pos.x - pictab[k].pos.x) * (pictab[i].pos.x - pictab[k].pos.x) + (pictab[i].pos.y - pictab[k].pos.y) * (pictab[i].pos.y - pictab[k].pos.y); if (picsrad < pictab[i].rad) /* Get smallest square of radius */ pictab[i].rad = picsrad; } pictab[i].rad = sqrt (pictab[i].rad) / 2.0; /* Keep the half-distance for radius */ if (pictab[i].rad < 1.0L) /* Always get a non-zero radius */ pictab[i].rad = 1.0L; pictab[i].vis = ((pictab[i].pos.x > - pictab[i].rad) && /* Compute vertex visibility */ (pictab[i].pos.x < picdelt.x + pictab[i].rad) && (pictab[i].pos.y > - pictab[i].rad) && (pictab[i].pos.y < picdelt.y + pictab[i].rad)) ? 1 : 0; } } else { /* If disks not wanted */ for (i = 0; i < grafptr->vertnbr; i ++) pictab[i].vis = ((pictab[i].pos.x > 0.0L) && /* Compute vertex visibility */ (pictab[i].pos.x < picdelt.x) && (pictab[i].pos.y > 0.0L) && (pictab[i].pos.y < picdelt.y)) ? 1 : 0; } for (i = 0; i < grafptr->vertnbr; i ++) { pictab[i].pos.x += 0.5L; /* Prepare to switch to integer coordinates */ pictab[i].pos.y += 0.5L; } picdelt.x += 0.5L; picdelt.y += 0.5L; if (O_outParam.PosMesh.color == 'c') { /* If color output */ for (i = 0; i < grafptr->vertnbr; i ++) /* Select color for all vertices */ pictab[i].col = mapptr->labltab[i] % O_POSMESHCOLNBR; } else { /* If gray level output */ for (i = 0; i < grafptr->vertnbr; i ++) { /* Select color for all vertices */ for (j = mapptr->labltab[i] & 255, k = 7, pictab[i].col = 0; /* Half-tone color */ j > 0; /* As long as there are subdivision bits */ j >>= 1, k --) /* (Same as reversing the last 8 bits ) */ pictab[i].col |= ((j & 1) << k); } } for (i = 0, j = 0; i < grafptr->vertnbr; i ++) { /* For all vertices */ pattab[i].nbr = 0; /* Compute the number of output paths */ pattab[i].idx = grafptr->verttab[i]; for ( ; j < grafptr->vendtab[i]; j ++) { if ((grafptr->edgetab[j] > i) && /* If it can be an output edge */ ((pictab[i].vis | pictab[grafptr->edgetab[j]].vis) != 0) && /* And it is visible */ ((O_outParam.PosMesh.edge != 'r') || /* And it can be drawn */ (mapptr->labltab[i] == mapptr->labltab[grafptr->edgetab[j]]))) pattab[i].nbr ++; /* One more path to higher vertices */ } } idxnbr = 0; /* No indexes yet */ for (i = 0; i < grafptr->vertnbr; ) { if (pattab[i].nbr == 0) { /* If no output path */ i ++; /* Skip to the next vertex */ continue; } j = i; /* Begin with this vertex */ idxtab[idxnbr ++] = j; /* Add it to the current segment */ do { for (k = pattab[j].idx; k < grafptr->vendtab[j]; k ++) { /* Search for first output */ if ((grafptr->edgetab[k] > j) && /* If it can be an output edge */ ((pictab[j].vis | pictab[grafptr->edgetab[k]].vis) != 0) && /* And it is visible */ ((O_outParam.InvMesh.edge != 'r') || /* And it can be drawn */ (mapptr->labltab[j] == mapptr->labltab[grafptr->edgetab[k]]))) break; } pattab[j].nbr --; /* One less output path remaining */ pattab[j].idx = k + 1; /* Search from the next position */ j = grafptr->edgetab[k]; /* Get the path end vertex number */ idxtab[idxnbr ++] = j; /* Add it to the current segment */ } while (pattab[j].nbr > 0); /* As long as there is a path */ idxtab[idxnbr ++] = ~0; /* Mark end of path */ } if (O_outParam.PosMesh.type == 'e') { /* EPSF-type output */ fprintf (stream, "%%!PS-Adobe-2.0 EPSF-2.0\n"); fprintf (stream, "%%%%Title: %s %s %s\n", C_filenamesrcinp, C_filenamegeoinp, C_filenamemapinp); fprintf (stream, "%%%%Creator: out (F. Pellegrini, LaBRI, Bordeaux)\n"); fprintf (stream, "%%%%CreationDate: %s", ctime (&pictime)); fprintf (stream, "%%%%BoundingBox: 0 0 %d %d\n", (int) ((picdelt.x * O_PSDPI) / O_POSMESHPICTRESOL), (int) ((picdelt.y * O_PSDPI) / O_POSMESHPICTRESOL)); fprintf (stream, "%%%%Pages: 0\n"); fprintf (stream, "%%%%EndComments\n"); } else { /* Full page output */ fprintf (stream, "%%!PS-Adobe-2.0\n"); fprintf (stream, "%%%%Title: %s %s %s\n", C_filenamesrcinp, C_filenamegeoinp, C_filenamemapinp); fprintf (stream, "%%%%Creator: out (F. Pellegrini, LaBRI, Bordeaux)\n"); fprintf (stream, "%%%%CreationDate: %s", ctime (&pictime)); } fprintf (stream, "/A { 0 360 arc fill } bind def\n"); /* Macro definitions */ if (O_outParam.PosMesh.color == 'c') { /* If color output */ for (i = 0; i < O_POSMESHCOLNBR; i ++) { /* Build color indexes */ outColorColor (i, color); fprintf (stream, "/C%c { %g %g %g setrgbcolor } bind def\n", ('a' + i), color[0], color[1], color[2]); } } fprintf (stream, "/G { 255 div setgray } bind def\n"); fprintf (stream, "/L { lineto stroke } bind def\n"); fprintf (stream, "/l { lineto } bind def\n"); fprintf (stream, "/m { moveto } bind def\n"); fprintf (stream, "gsave\n"); /* Save the context */ fprintf (stream, "1 setlinecap\n"); /* Perform round caps */ if (O_outParam.PosMesh.type == 'f') /* If full page output */ fprintf (stream, "%d %d translate\n", /* Center the picture */ (int) ((O_PSDPI * (O_PSPAGEWIDTH * O_POSMESHPICTRESOL - picdelt.x)) / (2 * O_POSMESHPICTRESOL)), (int) ((O_PSDPI * (O_PSPAGEHEIGHT * O_POSMESHPICTRESOL - picdelt.y)) / (2 * O_POSMESHPICTRESOL))); fprintf (stream, "%f %f scale\n", /* Print scaling factor */ (double) O_PSDPI / O_POSMESHPICTRESOL, (double) O_PSDPI / O_POSMESHPICTRESOL); fprintf (stream, "newpath 0 0 m %d 0 l %d %d l 0 %d l closepath clip\n", /* Clip picture */ (int) picdelt.x, (int) picdelt.x, (int) picdelt.y, (int) picdelt.y); fprintf (stream, "0 G\n"); /* Select black color */ for (i = 0; i < idxnbr; i ++) { fprintf (stream, "%d\t%d\tm\n", /* Set initial point */ (int) pictab[idxtab[i]].pos.x, (int) pictab[idxtab[i]].pos.y); for (i ++; idxtab[i] != ~0; i ++ ) { /* Build path */ fprintf (stream, "%d\t%d\t%c\n", (int) pictab[idxtab[i]].pos.x, (int) pictab[idxtab[i]].pos.y, (idxtab[i + 1] == ~0) ? 'L' : 'l'); } } if (O_outParam.PosMesh.disk == 'd') { /* If disks wanted */ for (i = 0, j = ~0; i < grafptr->vertnbr; i ++) { if ((pictab[i].vis > 0) && /* If disk is visible */ (mapptr->labltab[i] != (-1))) { /* And is mapped */ if ((j == ~0) || (pictab[i].col != pictab[j].col)) { /* Update drawing color */ if (O_outParam.PosMesh.color == 'c') fprintf (stream, "C%c\n", 'a' + pictab[i].col); else fprintf (stream, "%u G\n", pictab[i].col); j = i; /* Record the new current color */ } fprintf (stream, "%d %d %d A\n", /* Draw the disk */ (int) pictab[i].pos.x, (int) pictab[i].pos.y, (int) pictab[i].rad); } } } fprintf (stream, "grestore\n"); /* Restore the context */ if (O_outParam.PosMesh.type == 'f') /* If full page output */ fprintf (stream, "showpage\n"); /* Display the page */ memFree (pattab); memFree (idxtab); memFree (pictab); return (0); } /*************************************/ /* */ /* This is the Tulip output routine. */ /* */ /*************************************/ int outDrawTulMesh ( const C_Graph * const grafptr, /* Graph structure, sorted by vertex index */ const C_Geometry * const geomptr, /* Graph geometry, sorted by vertex label */ const C_Mapping * const mapptr, /* Result mapping, sorted by vertex label */ FILE * const stream) /* Output stream */ { time_t pictime; /* Creation time */ char * pictimeptr; char pictimestr[64]; double color[3]; /* Vertex color */ SCOTCH_Num vertnum; const SCOTCH_Num * edgetax; SCOTCH_Num edgeidx; char c; if (geomptr->verttab == NULL) { errorPrint ("outDrawInvMesh: geometry not provided"); return (1); } time (&pictime); /* Get current time */ pictimeptr = ctime (&pictime); strncpy (pictimestr, pictimeptr, 63); pictimestr[63] = '\0'; pictimestr[strlen (pictimestr) - 1] = '\0'; fprintf (stream, "(tlp \"2.0\"\n(author \"out (F. Pellegrini, LaBRI, Bordeaux)\")\n(date \"%s\")\n(comment \"%s %s %s\")\n", /* Write header */ pictimestr, C_filenamesrcinp, C_filenamegeoinp, C_filenamemapinp); if (grafptr->vertnbr == 0) { /* If nothing to write */ fprintf (stream, ")\n"); return (0); } fprintf (stream, "(nodes\n"); /* Write node list */ for (vertnum = 0; vertnum < (grafptr->vertnbr - 1); vertnum ++) fprintf (stream, SCOTCH_NUMSTRING "%c", (SCOTCH_Num) (vertnum + grafptr->baseval), ((vertnum & 7) == 7) ? '\n' : '\t'); fprintf (stream, SCOTCH_NUMSTRING ")\n", (SCOTCH_Num) (vertnum + grafptr->baseval)); edgetax = grafptr->edgetab - grafptr->baseval; for (vertnum = 0, edgeidx = grafptr->baseval; vertnum < grafptr->vertnbr; vertnum ++) { SCOTCH_Num edgenum; SCOTCH_Num edgennd; for (edgenum = grafptr->verttab[vertnum], edgennd = grafptr->vendtab[vertnum]; edgenum < edgennd; edgenum ++) { SCOTCH_Num vertend; vertend = edgetax[edgenum]; if (vertend <= vertnum) /* True even if baseval=1 and as vertnum unbased */ continue; fprintf (stream, "(edge " SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING ")\n", (SCOTCH_Num) (edgeidx ++), (SCOTCH_Num) (vertnum + grafptr->baseval), (SCOTCH_Num) vertend); } } fprintf (stream, "(property 0 layout \"viewLayout\"\n"); /* Write node coordinates */ c = '\n'; for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { if (vertnum == (grafptr->vertnbr - 1)) c = ')'; fprintf (stream, "(node " SCOTCH_NUMSTRING "\t\"(%lf,%lf,%lf)\")%c", (SCOTCH_Num) (vertnum + grafptr->baseval), (double) geomptr->verttab[vertnum].x, (double) geomptr->verttab[vertnum].y, (double) geomptr->verttab[vertnum].z, c); } fprintf (stream, "\n"); if (O_outParam.TulMesh.color == 'c') { fprintf (stream, "(property 0 color \"viewColor\"\n(default \"(255,255,255,255)\" \"(0,0,0,0)\")\n"); /* Write node color values */ c = '\n'; for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { if (vertnum == (grafptr->vertnbr - 1)) c = ')'; outColorColor (mapptr->labltab[vertnum], color); fprintf (stream, "(node " SCOTCH_NUMSTRING " \"(%d,%d,%d,255)\")%c", (SCOTCH_Num) (vertnum + grafptr->baseval), (int) (color[0] * 255.0), (int) (color[1] * 255.0), (int) (color[2] * 255.0), c); } fprintf (stream, "\n"); } fprintf (stream, "(property 0 size \"viewSize\"\n(default \"(0,0,0)\" \"(0,0,0)\")"); /* Write default node size */ if (O_outParam.TulMesh.disk == 'd') { /* If disks wanted */ const C_GeoVert * geomtax; geomtax = geomptr->verttab - grafptr->baseval; fprintf (stream, "\n"); c = '\n'; for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { SCOTCH_Num edgenum; SCOTCH_Num edgennd; double distmin; C_GeoVert vertpos; if (vertnum == (grafptr->vertnbr - 1)) c = ')'; distmin = 1e30; /* Huge distance assumed */ vertpos.x = geomptr->verttab[vertnum].x; vertpos.y = geomptr->verttab[vertnum].y; vertpos.z = geomptr->verttab[vertnum].z; for (edgenum = grafptr->verttab[vertnum], edgennd = grafptr->vendtab[vertnum]; edgenum < edgennd; edgenum ++) { SCOTCH_Num vertend; double distval; vertend = edgetax[edgenum]; distval = (geomtax[vertend].x - vertpos.x) * (geomtax[vertend].x - vertpos.x) + (geomtax[vertend].y - vertpos.y) * (geomtax[vertend].y - vertpos.y) + (geomtax[vertend].z - vertpos.z) * (geomtax[vertend].z - vertpos.z); if (distval < distmin) distmin = distval; } distmin = sqrt (distmin) * (0.5 * O_TULMESHDISKRATIO); fprintf (stream, "(node " SCOTCH_NUMSTRING " \"(%lf,%lf,%lf)\")%c", (SCOTCH_Num) (vertnum + grafptr->baseval), distmin, distmin, distmin, c); } fprintf (stream, "\n"); } else fprintf (stream, ")\n"); fprintf (stream, ")\n"); return (0); } scotch-5.1.12b.dfsg/src/scotch/gbase.h0000644000175300017530000000576511611563204017711 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gbase.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the declarations **/ /** for the source graph base changer. **/ /** **/ /** DATES : # Version 4.0 : from : 12 may 2006 **/ /** to : 12 may 2006 **/ /** **/ /************************************************************/ /* ** The defines. */ /** File name aliases. **/ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 2 /* Number of files which can be arguments */ #define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ #define C_filenamesrcout C_fileTab[1].name /* Source graph output file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ #define C_filepntrsrcout C_fileTab[1].pntr /* Source graph output file */ scotch-5.1.12b.dfsg/src/scotch/dgtst.c0000644000175300017530000002221011611563204017730 0ustar hazelscthazelsct/* Copyright 2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgtst.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This program gives statistics on **/ /** distributed source graphs. **/ /** **/ /** DATES : # Version 5.0 : from : 23 jun 2007 **/ /** to : 16 jun 2008 **/ /** # Version 5.1 : from : 26 oct 2008 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGTST #define SCOTCH_PTSCOTCH #include "module.h" #include "common.h" #include "ptscotch.h" #include "dgtst.h" /* ** The static and global definitions. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "dgtst [ []] ", " -h : Display this help", " -r : Set root process for centralized files (default is 0)", " -V : Print program version and copyright", NULL }; /*********************/ /* */ /* The main routine. */ /* */ /*********************/ int main ( int argc, char * argv[]) { SCOTCH_Dgraph grafdat; int procglbnbr; int proclocnum; int protglbnum; /* Root process */ SCOTCH_Num vertnbr; SCOTCH_Num velomin; SCOTCH_Num velomax; SCOTCH_Num velosum; double veloavg; double velodlt; SCOTCH_Num degrmin; SCOTCH_Num degrmax; double degravg; double degrdlt; SCOTCH_Num edgenbr; SCOTCH_Num edlomin; SCOTCH_Num edlomax; SCOTCH_Num edlosum; double edloavg; double edlodlt; int flagval; int i; #ifdef SCOTCH_PTHREAD int thrdlvlreqval; int thrdlvlproval; #endif /* SCOTCH_PTHREAD */ errorProg ("dgtst"); #ifdef SCOTCH_PTHREAD thrdlvlreqval = MPI_THREAD_MULTIPLE; if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) errorPrint ("main: Cannot initialize (1)"); if (thrdlvlreqval > thrdlvlproval) errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); #else /* SCOTCH_PTHREAD */ if (MPI_Init (&argc, &argv) != MPI_SUCCESS) errorPrint ("main: Cannot initialize (2)"); #endif /* SCOTCH_PTHREAD */ MPI_Comm_size (MPI_COMM_WORLD, &procglbnbr); /* Get communicator data */ MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum); protglbnum = 0; /* Assume root process is process 0 */ if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } flagval = C_FLAGNONE; for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '+') && /* If found a file name */ ((argv[i][0] != '-') || (argv[i][1] == '\0'))) { if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else errorPrint ("main: too many file names given"); } else { /* If found an option name */ switch (argv[i][1]) { #ifdef SCOTCH_DEBUG_ALL case 'D' : case 'd' : flagval |= C_FLAGDEBUG; break; #endif /* SCOTCH_DEBUG_ALL */ case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'R' : /* Root process (if necessary) */ case 'r' : protglbnum = atoi (&argv[i][2]); if ((protglbnum < 0) || (protglbnum >= procglbnbr) || ((protglbnum == 0) && (argv[i][2] != '0'))) errorPrint ("main: invalid root process number"); break; case 'V' : case 'v' : fprintf (stderr, "dgtst, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); } } } #ifdef SCOTCH_DEBUG_ALL if ((flagval & C_FLAGDEBUG) != 0) { fprintf (stderr, "Proc %4d of %d, pid %d\n", proclocnum, procglbnbr, getpid ()); if (proclocnum == protglbnum) { /* Synchronize on keybord input */ char c; printf ("Waiting for key press...\n"); scanf ("%c", &c); } MPI_Barrier (MPI_COMM_WORLD); } #endif /* SCOTCH_DEBUG_ALL */ fileBlockOpenDist (C_fileTab, C_FILENBR, procglbnbr, proclocnum, protglbnum); /* Open all files */ SCOTCH_dgraphInit (&grafdat, MPI_COMM_WORLD); SCOTCH_dgraphLoad (&grafdat, C_filepntrsrcinp, -1, 0); SCOTCH_dgraphCheck (&grafdat); SCOTCH_dgraphSize (&grafdat, &vertnbr, NULL, &edgenbr, NULL); SCOTCH_dgraphStat (&grafdat, &velomin, &velomax, &velosum, &veloavg, &velodlt, °rmin, °rmax, °ravg, °rdlt, &edlomin, &edlomax, &edlosum, &edloavg, &edlodlt); if (C_filepntrdatout != NULL) { fprintf (C_filepntrdatout, "S\tVertex\tnbr=" SCOTCH_NUMSTRING "\n", (SCOTCH_Num) vertnbr); fprintf (C_filepntrdatout, "S\tVertex load\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", (SCOTCH_Num) velomin, (SCOTCH_Num) velomax, (SCOTCH_Num) velosum, veloavg, velodlt); fprintf (C_filepntrdatout, "S\tVertex degree\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", (SCOTCH_Num) degrmin, (SCOTCH_Num) degrmax, (SCOTCH_Num) edgenbr, degravg, degrdlt); fprintf (C_filepntrdatout, "S\tEdge\tnbr=" SCOTCH_NUMSTRING "\n", (SCOTCH_Num) (edgenbr / 2)); fprintf (C_filepntrdatout, "S\tEdge load\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", (SCOTCH_Num) edlomin, (SCOTCH_Num) edlomax, (SCOTCH_Num) edlosum, edloavg, edlodlt); } fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_dgraphExit (&grafdat); MPI_Finalize (); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/mmk_m3.h0000644000175300017530000000634511611563204020006 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mmk_m3.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the data declara- **/ /** tions for the tridimensional finite **/ /** element grid mesh building program. **/ /** **/ /** DATES : # Version 4.0 : from : 26 sep 2002 **/ /** to : 26 sep 2002 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 1 /* Number of files which can be arguments */ #define C_filenamemshout C_fileTab[0].name /* Source mesh output file name */ #define C_filenamegeoout C_fileTab[1].name /* Geometry mesh output file name */ #define C_filepntrmshout C_fileTab[0].pntr /* Source mesh output file */ #define C_filepntrgeoout C_fileTab[1].pntr /* Geometry mesh output file */ /*+ Process flags. +*/ #define C_FLAGGEOOUT 0x0001 /* Output mesh geometry */ #define C_FLAGDEFAULT 0x0000 /* Default flags */ scotch-5.1.12b.dfsg/src/scotch/mord.h0000644000175300017530000000735311611563204017564 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mord.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a mesh orderer. **/ /** This module contains the data declara- **/ /** tions for the main routine. **/ /** **/ /** DATES : # Version 4.0 : from : 15 nov 2002 **/ /** to : 22 oct 2003 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 4 /* Number of files in list */ #define C_FILEARGNBR 3 /* Number of files which can be arguments */ #define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ #define C_filenameordout C_fileTab[1].name /* Ordering output file name */ #define C_filenamelogout C_fileTab[2].name /* Log file name */ #define C_filenamemapout C_fileTab[3].name /* Separator mapping file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ #define C_filepntrordout C_fileTab[1].pntr /* Ordering output file */ #define C_filepntrlogout C_fileTab[2].pntr /* Log file */ #define C_filepntrmapout C_fileTab[3].pntr /* Separator mapping file */ /*+ Process flags. +*/ #define C_FLAGNONE 0x0000 /* No flags */ #define C_FLAGMAPOUT 0x0001 /* Output mapping data */ #define C_FLAGVERBSTR 0x0002 /* Output strategy string */ #define C_FLAGVERBTIM 0x0004 /* Output timing information */ scotch-5.1.12b.dfsg/src/scotch/mcv.c0000644000175300017530000002054111611563204017375 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mcv.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a mesh file converter. **/ /** This module contains the main function. **/ /** **/ /** DATES : # Version 4.0 : from : 19 jan 2004 **/ /** to : 19 jan 2004 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MCV #include "module.h" #include "common.h" #include "scotch.h" #include "mcv.h" /* ** The static and global variables. */ static int C_inpFormatType = 0; /* Input mesh format */ static char * C_inpFormatData = "\0"; /* Pointer to auxiliary data */ static const C_Format C_inpFormatTab[] = { /* Table of input formats */ { 'B', SCOTCH_meshGeomLoadHabo }, { 'b', SCOTCH_meshGeomLoadHabo }, { 'S', SCOTCH_meshGeomLoadScot }, { 's', SCOTCH_meshGeomLoadScot }, { '\0', NULL } }; static int C_outFormatType = 0; /* Output mesh format */ static char * C_outFormatData = "\0"; /* Pointer to auxiliary data */ static C_Format C_outFormatTab[] = { /* Table of output formats */ { 'S', SCOTCH_meshGeomSaveScot }, { 's', SCOTCH_meshGeomSaveScot }, { '\0', NULL } }; static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[3] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "w" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "mcv [ [ []]] ", " -h : Display this help", " -i : Select input file format", " b : Boeing-Harwell format (elemental)", " s : Scotch format", " -o : Select output file format", " s : Scotch format", " -V : Print program version and copyright", "", "Default option set is : '-Ib -Os'", NULL }; /*****************************/ /* */ /* This is the main function */ /* */ /*****************************/ int main ( int argc, char * argv[]) { SCOTCH_Mesh meshdat; SCOTCH_Geom geomdat; int i, j; errorProg ("mcv"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give help */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'I' : /* Select input file type */ case 'i' : for (j = 0; C_inpFormatTab[j].code != '\0'; j ++) { /* Find proper format code */ if (C_inpFormatTab[j].code == argv[i][2]) { C_inpFormatType = j; C_inpFormatData = &argv[i][3]; break; } } if (C_inpFormatTab[j].code == '\0') { errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } break; case 'O' : /* Select input file type */ case 'o' : for (j = 0; C_outFormatTab[j].code != '\0'; j ++) { /* Find proper format code */ if (C_outFormatTab[j].code == argv[i][2]) { C_outFormatType = j; C_outFormatData = &argv[i][3]; break; } } if (C_inpFormatTab[j].code == '\0') { errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } break; case 'V' : fprintf (stderr, "mcv, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ SCOTCH_meshInit (&meshdat); SCOTCH_geomInit (&geomdat); C_inpFormatTab[C_inpFormatType].func (&meshdat, &geomdat, C_filepntrsrcinp, NULL, C_inpFormatData); #ifdef SCOTCH_DEBUG_ALL if (SCOTCH_meshCheck (&meshdat) != 0) { errorPrint ("main: bad graph structure"); return (1); } #endif /* SCOTCH_DEBUG_ALL */ C_outFormatTab[C_outFormatType].func (&meshdat, &geomdat, C_filepntrsrcout, C_filepntrgeoout, C_outFormatData); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_geomExit (&geomdat); SCOTCH_meshExit (&meshdat); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/amk_hy.c0000644000175300017530000002005711611563204020062 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : amk_hy.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the distance map for hypercube **/ /** graphs, to be used to build the archi- **/ /** tecture description files for these **/ /** graphs. **/ /** **/ /** DATES : # Version 2.0 : from : 14 nov 1994 **/ /** to : 14 nov 1994 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to : 19 sep 1995 **/ /** # Version 3.2 : from : 31 may 1997 **/ /** to : 02 jun 1997 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 02 oct 1998 **/ /** # Version 3.4 : from : 03 feb 2000 **/ /** to : 03 feb 2000 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define AMK_HY #include "module.h" #include "common.h" #include "scotch.h" #include "amk_hy.h" /* ** The static definitions. */ static int C_paraNum = 0; /* Number of parameters */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* The file array */ { "-", NULL, "w" } }; static const char * C_usageList[] = { "amk_hy [] ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /*************************************************/ /* */ /* The main routine, which computes the distance */ /* triangular table. */ /* */ /*************************************************/ int main ( int argc, char * argv[]) { SCOTCH_Num hdim; /* Hypercube dimension */ SCOTCH_Num hnbr; /* Number of hypercube vertices */ SCOTCH_Num hmax; /* Number of domains */ SCOTCH_Num hv0, hv1; SCOTCH_Num i, j; errorProg ("amk_hy"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } hdim = 1; /* Preset hypercube dimension */ for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < 1) { /* If number of parameters not reached */ if ((hdim = atoi (argv[i])) < 1) { /* Get the dimension */ errorPrint ("main: invalid dimension '%s'", argv[i]); return (1); } C_paraNum ++; continue; /* Process the other parameters */ } if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "amk_hy, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ hnbr = 1 << hdim; /* Compute number of terminals */ hmax = (1 << (hdim + 1)) - 1; /* Maximum terminal value */ fprintf (C_filepntrtgtout, "deco\n0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", /* Print the file header */ (SCOTCH_Num) hnbr, /* Print number of terminal domains */ (SCOTCH_Num) hmax); /* Print the biggest terminal value */ for (i = 0; i < hnbr; i ++) /* For all vertices */ fprintf (C_filepntrtgtout, SCOTCH_NUMSTRING "\t1\t" SCOTCH_NUMSTRING "\n", (SCOTCH_Num) i, /* Print terminal label */ (SCOTCH_Num) (hnbr + i)); /* Print terminal number */ for (hv0 = 1; hv0 < hnbr; hv0 ++) { /* For all vertices */ for (hv1 = 0; hv1 < hv0; hv1 ++) { for (i = hv0 ^ hv1, j = 0; i > 0; i >>=1) j += (i & 1); fprintf (C_filepntrtgtout, (hv1 == 0) ? SCOTCH_NUMSTRING : " " SCOTCH_NUMSTRING, (SCOTCH_Num) j); } fprintf (C_filepntrtgtout, "\n"); } fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/amk_p2.c0000644000175300017530000001457711611563204017775 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : amk_p2.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the target architecture file **/ /** for a weighted path with two vertices **/ /** used to bipartition graphs in parts of **/ /** different sizes. **/ /** **/ /** DATES : # Version 3.0 : from : 17 jul 1995 **/ /** to : 17 jul 1995 **/ /** # Version 3.2 : from : 02 jun 1997 **/ /** to : 02 jun 1997 **/ /** # Version 3.4 : from : 03 feb 2000 **/ /** to : 03 feb 2000 **/ /** # Version 5.1 : from : 16 dec 2007 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define AMK_P2 #include "module.h" #include "common.h" #include "scotch.h" #include "amk_p2.h" /* ** The static variables. */ static int C_paraNum = 0; /* Number of parameters */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* File array */ { "-", NULL, "w" } }; static const char * C_usageList[] = { "amk_p2 [ []] ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /************************************/ /* */ /* The main routine, which computes */ /* the decomposition. */ /* */ /************************************/ int main ( int argc, char * argv[]) { int wght[2] = {1, 1}; /* Vertex weights */ int i; errorProg ("amk_p2"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < 2) { /* If number of parameters not reached */ if ((wght[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get vertex weights */ errorPrint ("main: invalid weight '%s'", argv[i]); return (1); } continue; /* Process remaining parameters */ } if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "amk_p2, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ fprintf (C_filepntrtgtout, "cmpltw\t2\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", /* Print target description */ (SCOTCH_Num) wght[0], (SCOTCH_Num) wght[1]); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/gout_c.c0000644000175300017530000007773511611563204020111 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gout_c.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a result viewer. **/ /** This module contains the main function. **/ /** **/ /** DATES : # Version 2.0 : from : 06 oct 1994 **/ /** to 23 dec 1994 **/ /** # Version 3.0 : from : 14 jul 1995 **/ /** to 11 oct 1995 **/ /** # Version 3.1 : from : 27 mar 1996 **/ /** to 03 apr 1996 **/ /** # Version 3.2 : from : 02 dec 1996 **/ /** to 05 jun 1998 **/ /** # Version 3.3 : from : 29 may 1999 **/ /** to : 03 jun 1999 **/ /** # Version 3.4 : from : 03 feb 2000 **/ /** to : 03 feb 2000 **/ /** # Version 4.0 : from : 11 dec 2001 **/ /** to 08 feb 2004 **/ /** # Version 5.0 : from : 25 may 2007 **/ /** to 25 may 2007 **/ /** # Version 5.1 : from : 25 oct 2007 **/ /** to 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes */ #define GOUT #include "module.h" #include "common.h" #include "scotch.h" #include "gout_c.h" #include "gout_o.h" /* ** The static and global variables */ static int C_fileNum = 0; /* Number of file in arg list */ File C_fileTab[C_FILENBR] = { /* The file array; public */ { "-", NULL, "r" }, { "-", NULL, "r" }, { "-", NULL, "r" }, { "-", NULL, "w" } }; static unsigned int C_geoFlag = C_GEOFLAGDEFAULT; /* Geometry flag */ static const char * C_usageList[] = { /* Usage */ "gout [ [ [ []]]] ", " -g : Geometry parameters :", " n : do not read geometry data (matrix display)", " p : permute Y and Z geometry dimensions", " r : rotate geometry by 90 degrees", " -h : Display this help", " -mn : Do not read mapping data", " -Oi[{}] : Open Inventor mesh file :", " c : color output", " g : gray level output", " r : remove cut edges", " v : view cut edges", " -Om[{}] : PostScript matrix file :", " e : EPSF-type output", " f : full-page output", " -Op[{}] : PostScript mesh file :", " c : color output", " g : gray level output", " e : EPSF-type output", " f : full-page output", " s : short clipping (disks excluded)", " l : large clipping (disks included)", " a : avoid displaying disks", " d : display disks", " r : remove cut edges", " v : view cut edges", " X= : maximum x clipping ratio (in [0.0;1.0])", " x= : minimum x clipping ratio", " Y= : maximum y clipping ratio", " y= : minimum y clipping ratio", " -Ot[{}] : Tulip graph file :", " b : b/w output", " c : color output", " a : avoid displaying disks", " d : display disks", " r : remove cut edges", " v : view cut edges", " -V : Print program version and copyright", "", "Default option set is : -Oi{c,v}", NULL }; /*****************************/ /* */ /* This is the main function */ /* */ /*****************************/ int main ( int argc, char * argv[]) { C_Graph grafdat; /* Source graph */ C_Geometry geo; /* Graph geometry */ C_Mapping map; /* Result mapping */ int i, j; errorProg ("gout"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else errorPrint ("main: too many file names given"); } else { /* If found an option name */ switch (argv[i][1]) { case 'G' : /* Geometry parameters */ case 'g' : if ((j = C_geoParse (&argv[i][2])) != 0) errorPrint ("main: error in geometry option string '%d'", j); break; case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'M' : /* No-mapping flag */ case 'm' : if (((argv[i][2] != 'N') && (argv[i][2] != 'n')) || (argv[i][3] != '\0')) errorPrint ("main: error in mapping option string '%s'", &argv[i][2]); C_filenamemapinp = "-"; /* Default name to avoid opening */ C_filepntrmapinp = NULL; /* NULL file pointer means no file */ break; case 'O' : /* Output parameters */ case 'o' : if ((j = outDrawParse (&argv[i][2])) != 0) errorPrint ("main: error in output option string (%d)", j); break; case 'V' : fprintf (stderr, "gout, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: Unprocessed option '%s'", argv[i]); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ SCOTCH_graphInit (&grafdat.grafdat); /* Create graph structure */ SCOTCH_graphLoad (&grafdat.grafdat, C_filepntrsrcinp, 0, 3); /* Read source graph */ SCOTCH_graphData (&grafdat.grafdat, &grafdat.baseval, &grafdat.vertnbr, &grafdat.verttab, &grafdat.vendtab, NULL, &grafdat.vlbltab, &grafdat.edgenbr, &grafdat.edgetab, NULL); C_geoInit (&geo, &grafdat); /* Create geometry structure */ if (C_geoFlag & C_GEOFLAGUSE) /* If geometry is wanted */ C_geoLoad (&geo, C_filepntrgeoinp); /* Read graph geometry */ C_mapInit (&map, &grafdat); /* Create mapping structure */ C_mapLoad (&map, C_filepntrmapinp); /* Read result mapping */ outDraw (&grafdat, &geo, &map, C_filepntrdatout); /* Build and write the output */ fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ C_mapExit (&map); /* Free data structures */ C_geoExit (&geo); SCOTCH_graphExit (&grafdat.grafdat); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } /***********************************/ /* */ /* These routines handle geometry. */ /* */ /***********************************/ /* This routine parses the source graph ** option string. ** It returns: ** - 0 : if string successfully scanned. ** - 1 : if invalid options ** - 2 : if invalid option arguments. ** - 3 : if syntax error in string. */ int C_geoParse ( const char * const string) { const char * cptr; for (cptr = string; ; cptr ++) { switch (*cptr) { case 'N' : /* Do not read geometry data */ case 'n' : C_geoFlag &= ~C_GEOFLAGUSE; break; case 'P' : /* Permute Y and Z */ case 'p' : C_geoFlag |= C_GEOFLAGPERMUT; break; case 'R' : /* If want to rotate */ case 'r' : C_geoFlag |= C_GEOFLAGROTATE; break; case '\0' : return (0); default : return (1); } } } /* This routine creates a geometry with ** respect to a given source graph. ** It returns: ** - VOID : in all cases. */ void C_geoInit ( C_Geometry * const geomptr, const C_Graph * const grafptr) { geomptr->grafptr = grafptr; geomptr->verttab = NULL; } /* This routine deletes a geometry. ** It returns: ** - VOID : in all cases. */ void C_geoExit ( C_Geometry * const geomptr) { if (geomptr->verttab != NULL) /* If there is a geometry array */ memFree (geomptr->verttab); /* Free it */ } /* This routine loads a mapping. ** It returns: ** - 0 : on success. ** - !0 : on error. */ /* This is the comparison function used by the quicksort algorithm, to sort by increasing labels. */ static int C_geoLoad2 ( const C_VertSort * const vert0, const C_VertSort * const vert1) { return ((vert0->labl > vert1->labl) ? 1 : -1); } /** This is the loading routine. **/ int C_geoLoad ( C_Geometry * const geomptr, FILE * const stream) { C_VertSort * vertsorttab; /* Pointer to graph sorting array */ int vertsortflag; /* Flag set if graph data sorted by label */ C_VertSort * geomsorttab; /* Pointer to geometric data sorting array */ int geomsortflag; /* Flag set if geometric data sorted by label */ int geomfiletype; /* Type of geometry file */ SCOTCH_Num geomfilenbr; /* Number of geometric coordinates in file */ SCOTCH_Num geomfileval; /* Value of maximum size for compatibility */ C_GeoVert * geomfiletab; /* Pointer to geometric data read from file */ SCOTCH_Num vertlablval; /* Value of maximum size for compatibility */ SCOTCH_Num i, j; int o; if ((geomptr->verttab == NULL) && /* Allocate geometry if necessary */ ((geomptr->verttab = (C_GeoVert *) memAlloc (geomptr->grafptr->vertnbr * sizeof (C_GeoVert))) == NULL)) { errorPrint ("C_geoLoad: out of memory (1)"); return (1); } if ((fscanf (stream, "%d" SCOTCH_NUMSTRING, /* Read type and number of geometry items */ &geomfiletype, &geomfileval) != 2) || (geomfiletype < 1) || (geomfiletype > 3) || (geomfileval < 1)) { errorPrint ("C_geoLoad: bad input (1)"); return (1); } geomfilenbr = (SCOTCH_Num) geomfileval; if (((geomfiletab = (C_GeoVert *) memAlloc (geomfilenbr * sizeof (C_GeoVert))) == NULL) || ((geomsorttab = (C_VertSort *) memAlloc (geomfilenbr * sizeof (C_VertSort))) == NULL) || ((vertsorttab = (C_VertSort *) memAlloc (geomptr->grafptr->vertnbr * sizeof (C_VertSort))) == NULL)) { errorPrint ("C_geoLoad: out of memory (2)"); if (geomfiletab != NULL) { if (geomsorttab != NULL) memFree (geomsorttab); memFree (geomfiletab); } return (1); } o = 0; geomsortflag = 1; /* Assume geometry data sorted */ switch (geomfiletype) { case 1 : /* Load 2D coordinates array */ for (i = 0; (i < geomfilenbr) && (o == 0); i ++) { if (fscanf (stream, SCOTCH_NUMSTRING "%lf", &vertlablval, &geomfiletab[i].x) != 2) o = 1; geomsorttab[i].labl = (SCOTCH_Num) vertlablval; geomfiletab[i].y = /* No Y and Z coordinates */ geomfiletab[i].z = 0.0; geomsorttab[i].num = i; if (C_geoFlag & C_GEOFLAGROTATE) { /* Rotate picture if necessary */ double t; /* Temporary swap variable */ t = geomfiletab[i].y; geomfiletab[i].y = geomfiletab[i].x; geomfiletab[i].x = - t; } if ((i > 0) && /* Check if geometry data sorted */ (geomsorttab[i].labl < geomsorttab[i - 1].labl)) geomsortflag = 0; /* Geometry data not sorted */ } break; case 2 : /* Load 2D coordinates array */ for (i = 0; (i < geomfilenbr) && (o == 0); i ++) { if (fscanf (stream, SCOTCH_NUMSTRING "%lf%lf", &vertlablval, &geomfiletab[i].x, &geomfiletab[i].y) != 3) o = 1; geomsorttab[i].labl = (SCOTCH_Num) vertlablval; geomfiletab[i].z = 0.0; /* No Z coordinate */ geomsorttab[i].num = i; if (C_geoFlag & C_GEOFLAGROTATE) { /* Rotate picture if necessary */ double t; /* Temporary swap variable */ t = geomfiletab[i].y; geomfiletab[i].y = geomfiletab[i].x; geomfiletab[i].x = - t; } if ((i > 0) && /* Check if geometry data sorted */ (geomsorttab[i].labl < geomsorttab[i - 1].labl)) geomsortflag = 0; /* Geometry data are not sorted */ } break; case 3 : /* Load 3D coordinates array */ for (i = 0; (i < geomfilenbr) && (o == 0); i ++) { if (fscanf (stream, SCOTCH_NUMSTRING "%lf%lf%lf", &vertlablval, &geomfiletab[i].x, &geomfiletab[i].y, &geomfiletab[i].z) != 4) o = 1; geomsorttab[i].labl = (SCOTCH_Num) vertlablval; geomsorttab[i].num = i; if (C_geoFlag & C_GEOFLAGPERMUT) { /* Rotate picture if necessary */ double t; /* Temporary swap variable */ t = geomfiletab[i].z; geomfiletab[i].z = geomfiletab[i].y; geomfiletab[i].y = t; } if ((i > 0) && /* Check if geometry data sorted */ (geomsorttab[i].labl < geomsorttab[i - 1].labl)) geomsortflag = 0; /* Geometry data not sorted */ } break; default : errorPrint ("C_geoLoad: invalid geometry type (%d)", geomfiletype); memFree (vertsorttab); memFree (geomsorttab); memFree (geomfiletab); return (1); } if (o != 0) { errorPrint ("C_geoLoad: bad input (2)"); memFree (vertsorttab); memFree (geomsorttab); memFree (geomfiletab); return (1); } if (geomsortflag != 1) /* If geometry data not sorted */ qsort ((char *) geomsorttab, geomfilenbr, /* Sort sort area by ascending labels */ sizeof (C_VertSort), (int (*) (const void *, const void *)) C_geoLoad2); for (i = 1; i < geomfilenbr; i ++) { /* Check geometric data integrity */ if (geomsorttab[i].labl == geomsorttab[i - 1].labl) { errorPrint ("C_geoLoad: duplicate vertex label"); memFree (vertsorttab); memFree (geomsorttab); memFree (geomfiletab); return (1); } } if (geomptr->grafptr->vlbltab != NULL) { /* If graph has vertex labels */ vertsortflag = 1; /* Assume graph data sorted */ for (i = 0; i < geomptr->grafptr->vertnbr; i ++) { vertsorttab[i].labl = geomptr->grafptr->vlbltab[i]; vertsorttab[i].num = i; if ((i > 0) && /* Check if graph data sorted */ (vertsorttab[i].labl < vertsorttab[i - 1].labl)) vertsortflag = 0; /* Graph data not sorted */ } if (vertsortflag != 1) /* If graph data not sorted */ qsort ((char *) vertsorttab, geomptr->grafptr->vertnbr, /* Sort sort area by ascending labels */ sizeof (C_VertSort), (int (*) (const void *, const void *)) C_geoLoad2); } else { /* Graph does not have vertex labels */ for (i = 0; i < geomptr->grafptr->vertnbr; i ++) { vertsorttab[i].labl = i + geomsorttab[0].labl; /* Use first index as base value */ vertsorttab[i].num = i; } } for (i = 0, j = 0; i < geomptr->grafptr->vertnbr; i ++) { /* For all vertices in graph */ while ((j < geomfilenbr) && (geomsorttab[j].labl < vertsorttab[i].labl)) j ++; /* Search geometry vertex with same label */ if ((j >= geomfilenbr) || (geomsorttab[j].labl > vertsorttab[i].labl)) { /* If label does not exist */ errorPrint ("C_geoLoad: vertex geometry data not found for label '" SCOTCH_NUMSTRING "'", vertsorttab[i].labl); memFree (vertsorttab); memFree (geomsorttab); memFree (geomfiletab); return (1); } geomptr->verttab[vertsorttab[i].num] = geomfiletab[geomsorttab[j ++].num]; } memFree (vertsorttab); memFree (geomsorttab); memFree (geomfiletab); return (0); } /***********************************/ /* */ /* These routines handle mappings. */ /* */ /***********************************/ /* This routine creates a mapping with ** respect to a given source graph. ** It returns: ** - VOID : in all cases. */ void C_mapInit ( C_Mapping * const mapptr, const C_Graph * const grafptr) { mapptr->grafptr = grafptr; mapptr->labltab = NULL; } /* This routine deletes a mapping. ** It returns: ** - VOID : in all cases. */ void C_mapExit ( C_Mapping * const mapptr) { if (mapptr->labltab != NULL) /* If there is a domain array */ memFree (mapptr->labltab); /* Free it */ } /* This routine loads a mapping. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int C_mapLoad ( C_Mapping * const mapptr, FILE * const stream) { C_VertSort * vertsorttab; /* Pointer to graph sorting array */ int vertsortflag; /* Flag set if graph data sorted by label */ C_VertSort * mapsorttab; /* Pointer to mapping data sorting array */ int mapsortflag; /* Flag set if mapping data sorted by label */ SCOTCH_Num mapsortval; /* Value of maximum size for compatibility */ SCOTCH_Num mapfileval; /* Value of maximum size for compatibility */ SCOTCH_Num mapfilenbr; /* Number of mapping pairs in file */ SCOTCH_Num * mapfiletab; /* Pointer to mapping data read from file */ SCOTCH_Num i, j; if ((mapptr->labltab == NULL) && /* Allocate array if necessary */ ((mapptr->labltab = (SCOTCH_Num *) memAlloc (mapptr->grafptr->vertnbr * sizeof (SCOTCH_Num))) == NULL)) { errorPrint ("C_mapLoad: out of memory (1)"); return (1); } memset (mapptr->labltab, ~0, mapptr->grafptr->vertnbr * sizeof (SCOTCH_Num)); /* Pre-initialize mapping */ if (stream == NULL) /* If stream is invalid */ return (0); if ((fscanf (stream, SCOTCH_NUMSTRING, /* Read number of mapping pairs */ &mapfileval) != 1) || (mapfileval < 1)) { errorPrint ("C_mapLoad: bad input (1)"); return (1); } mapfilenbr = (SCOTCH_Num) mapfileval; if (((mapfiletab = (SCOTCH_Num *) memAlloc (mapfilenbr * sizeof (SCOTCH_Num))) == NULL) || ((mapsorttab = (C_VertSort *) memAlloc (mapfilenbr * sizeof (C_VertSort))) == NULL) || ((vertsorttab = (C_VertSort *) memAlloc (mapptr->grafptr->vertnbr * sizeof (C_VertSort))) == NULL)) { errorPrint ("C_mapLoad: out of memory (2)"); if (mapfiletab != NULL) { if (mapsorttab != NULL) memFree (mapsorttab); memFree (mapfiletab); } return (1); } mapsortflag = 1; /* Assume mapping data sorted */ for (i = 0; i < mapfilenbr; i ++) { if (fscanf (stream, SCOTCH_NUMSTRING SCOTCH_NUMSTRING, &mapsortval, &mapfileval) != 2) { errorPrint ("C_mapLoad: bad input (2)"); memFree (vertsorttab); memFree (mapsorttab); memFree (mapfiletab); return (1); } mapsorttab[i].labl = mapsortval; mapsorttab[i].num = i; mapfiletab[i] = mapfileval; if ((i > 0) && /* Check if mapping data sorted */ (mapsorttab[i].labl < mapsorttab[i - 1].labl)) mapsortflag = 0; /* Mapping data not sorted */ } if (mapsortflag != 1) /* If mapping data not sorted */ qsort ((char *) mapsorttab, mapfilenbr, /* Sort sort area by ascending labels */ sizeof (C_VertSort), (int (*) (const void *, const void *)) C_geoLoad2); for (i = 1; i < mapfilenbr; i ++) { /* Check mapping data integrity */ if (mapsorttab[i].labl == mapsorttab[i - 1].labl) { errorPrint ("C_mapLoad: duplicate vertex label"); memFree (vertsorttab); memFree (mapsorttab); memFree (mapfiletab); return (1); } } if (mapptr->grafptr->vlbltab != NULL) { /* If graph has vertex labels */ vertsortflag = 1; /* Assume graph data sorted */ for (i = 0; i < mapptr->grafptr->vertnbr; i ++) { vertsorttab[i].labl = mapptr->grafptr->vlbltab[i]; vertsorttab[i].num = i; if ((i > 0) && /* Check if graph data sorted */ (vertsorttab[i].labl < vertsorttab[i - 1].labl)) vertsortflag = 0; /* Graph data not sorted */ } if (vertsortflag != 1) /* If graph data not sorted */ qsort ((char *) vertsorttab, mapptr->grafptr->vertnbr, /* Sort sort area by ascending labels */ sizeof (C_VertSort), (int (*) (const void *, const void *)) C_geoLoad2); } else { /* Graph does not have vertex labels */ for (i = 0; i < mapptr->grafptr->vertnbr; i ++) { vertsorttab[i].labl = i + mapsorttab[0].labl; /* Use first index as base value */ vertsorttab[i].num = i; } } for (i = 0, j = 0; i < mapptr->grafptr->vertnbr; i ++) { /* For all vertices in graph */ while ((j < mapfilenbr) && (mapsorttab[j].labl < vertsorttab[i].labl)) j ++; /* Search mapping vertex with same label */ if ((j >= mapfilenbr) || (mapsorttab[j].labl > vertsorttab[i].labl)) /* If label does not exist */ continue; /* This vertex has no related mapping data */ mapptr->labltab[vertsorttab[i].num] = mapfiletab[mapsorttab[j ++].num]; } memFree (vertsorttab); memFree (mapsorttab); memFree (mapfiletab); return (0); } /**************************************/ /* */ /* The option string parsing routine. */ /* */ /**************************************/ /* This routine parses an option string. ** It returns: ** - 0 : if string successfully scanned. ** - 1 : if invalid code name. ** - 2 : if invalid arguments for the code. ** - 3 : if syntax error in string. */ int C_parse ( const C_ParseCode * const codeptr, /* Pointer to the code array */ const C_ParseArg * const argptr, /* Pointer to the code argument array */ int * const codeval, /* Pointer to the code value to set */ char * const string) /* Pointer to the string to parse */ { int code; /* Code found */ int codelen; /* Code name length */ char argbuf[128]; /* Buffer for argument scanning */ int arglen; /* Length of the current argument */ char * argbeg; /* Pointer to beginning of argument */ char * argend; /* Pointer to end of argument */ char * argequ; /* Position of the '=' character */ int i, j; code = codelen = 0; /* No code recognized yet */ for (i = 0; codeptr[i].name != NULL; i ++) { /* For all the codes */ if ((strncasecmp (string, /* Find the longest matching code name */ codeptr[i].name, j = strlen (codeptr[i].name)) == 0) && (j > codelen)) { code = codeptr[i].code; codelen = j; } } if (codelen == 0) /* If no code recognized */ return (1); /* Return the error value */ *codeval = code; /* Set the code value */ argbeg = string + codelen; /* Point to the end of the code name */ if (*argbeg == '{') { /* If there are arguments */ argbeg ++; /* Point to argument beginning */ do { /* For all arguments */ argend = strpbrk (argbeg, ",}\0"); /* Search for the argument end */ if (*argend == '\0') /* If there is no end delimiter */ return (3); /* Return the syntax error value */ arglen = ((argend - argbeg) < 127) /* Get argument bounded length */ ? (argend - argbeg) : 127; strncpy (argbuf, argbeg, arglen); /* Copy the argument to the buffer */ argbuf[arglen] = '\0'; /* Mark the end of the argument */ argequ = strpbrk (argbuf, "="); /* Search for the '=' character */ if (argequ != NULL) /* If it exists */ *argequ++ = '\0'; /* Turn it into a separating null */ for (i = 0, j = -1; argptr[i].name != NULL; i ++) { /* Scan all the possible arguments */ if ((argptr[i].code == code) && /* If the proper name is found */ (strcmp (argbuf, argptr[i].name) == 0)) { j = i; /* Record the position */ break; /* Exit the loop */ } } if (j == -1) /* If invalid argument */ return (2); /* Return the proper value */ if (argptr[j].format != NULL) { /* If there is a value to read */ if (argequ == NULL) /* If none has been given however */ return (2); /* Return the error value */ if (sscanf (argequ, /* Try to read the argument value */ argptr[j].format, argptr[j].ptr) != 1) return (2); /* Return if error */ if (argptr[j].func != NULL) /* If there is a control function */ if (argptr[j].func (argptr[j].ptr) != 0) /* If the function fails */ return (2); /* Return the error value */ } else { /* If no value needed */ if (argequ != NULL) /* If there is one however */ return (2); /* Return the error code */ *((char *) argptr[j].ptr) = argbuf[0]; /* Copy the first argument char */ } argbeg = argend + 1; /* Skip the processed argument */ } while (*argend != '}'); /* Loop as long as there are arguments */ } return ((*argbeg == '\0') ? 0 : 3); /* Check if no extraneous characters */ } scotch-5.1.12b.dfsg/src/scotch/gmk_ub2.h0000644000175300017530000000637711611563204020156 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gmk_ub2.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the data declara- **/ /** tions for the de Bruijn source graph **/ /** building program. **/ /** **/ /** DATES : # Version 2.0 : from : 05 nov 1994 **/ /** to 05 nov 1994 **/ /** # Version 3.2 : from : 03 jun 1997 **/ /** to : 03 jun 1997 **/ /** # Version 3.3 : from : 07 jun 1999 **/ /** to : 07 jun 1999 **/ /** # Version 3.3 : from : 07 jun 1999 **/ /** to : 07 jun 1999 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 1 /* Number of files in list */ #define C_FILEARGNBR 1 /* Number of files which can be arguments */ #define C_filenamesrcout C_fileTab[0].name /* Source graph output file name */ #define C_filepntrsrcout C_fileTab[0].pntr /* Source graph output file */ scotch-5.1.12b.dfsg/src/scotch/gmk_msh.c0000644000175300017530000001366211611563204020243 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gmk_msh.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a mesh-to-graph converter. **/ /** This module contains the main function. **/ /** **/ /** DATES : # Version 4.0 : from : 21 jan 2004 **/ /** to : 21 jan 2004 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GMK_MSH #include "module.h" #include "common.h" #include "scotch.h" #include "gmk_msh.h" /* ** The static and global variables. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[2] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "gmk_msh [ []] ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /*****************************/ /* */ /* This is the main function */ /* */ /*****************************/ int main ( int argc, char * argv[]) { SCOTCH_Mesh meshdat; SCOTCH_Graph grafdat; int i; errorProg ("gmk_msh"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give help */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "gmk_msh, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ SCOTCH_meshInit (&meshdat); SCOTCH_graphInit (&grafdat); SCOTCH_meshLoad (&meshdat, C_filepntrmshinp, -1); SCOTCH_meshCheck (&meshdat); SCOTCH_meshGraph (&meshdat, &grafdat); #ifdef SCOTCH_DEBUG_ALL if (SCOTCH_graphCheck (&grafdat) != 0) { errorPrint ("main: bad graph structure"); return (1); } #endif /* SCOTCH_DEBUG_ALL */ SCOTCH_graphSave (&grafdat, C_filepntrgrfout); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_graphExit (&grafdat); SCOTCH_meshExit (&meshdat); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/mtst.h0000644000175300017530000000575511611563204017616 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mtst.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the declarations **/ /** for the source mesh analyzer. **/ /** **/ /** DATES : # Version 4.0 : from : 25 feb 2003 **/ /** to 27 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines. */ /** File name aliases. **/ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 2 /* Number of files which can be arguments */ #define C_filenamesrcinp C_fileTab[0].name /* Source mesh input file name */ #define C_filenamedatout C_fileTab[1].name /* Statistics output file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* Source mesh input file */ #define C_filepntrdatout C_fileTab[1].pntr /* Statistics output file */ scotch-5.1.12b.dfsg/src/scotch/dgmap.h0000644000175300017530000001006311611563204017703 0ustar hazelscthazelsct/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgmap.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a parallel static mapper. **/ /** These lines are the data declaration **/ /** for the main routine. **/ /** **/ /** DATES : # Version 5.1 : from : 12 jun 2008 **/ /** to : 18 jul 2011 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 4 /* Number of files in list */ #define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ #define C_filenametgtinp C_fileTab[1].name /* Target architecture input file name */ #define C_filenamemapout C_fileTab[2].name /* Mapping result output file name */ #define C_filenamelogout C_fileTab[3].name /* Log file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ #define C_filepntrtgtinp C_fileTab[1].pntr /* Target architecture input file */ #define C_filepntrmapout C_fileTab[2].pntr /* Mapping result output file */ #define C_filepntrlogout C_fileTab[3].pntr /* Log file */ /*+ Process flags. +*/ #define C_FLAGNONE 0x0000 /* No flags */ #define C_FLAGPART 0x0001 /* Partitioning */ #define C_FLAGVERBSTR 0x0002 /* Verbose flags */ #define C_FLAGVERBTIM 0x0004 #define C_FLAGVERBMAP 0x0008 #define C_FLAGVERBMEM 0x0010 #define C_FLAGDEBUG 0x0020 /* Debugging */ #define C_FLAGKBALVAL 0x0040 /* Imbalance tolerance */ #define C_FLAGCLUSTER 0x0080 /* Clustering */ /* ** The function prototypes. */ void dgmapStatReduceOp (double *, double *, int *, MPI_Datatype *); scotch-5.1.12b.dfsg/src/scotch/dgord.c0000644000175300017530000003774511611563204017725 0ustar hazelscthazelsct/* Copyright 2007-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgord.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER (v5.0) **/ /** **/ /** FUNCTION : Part of a parallel sparse matrix **/ /** ordering software. **/ /** This module contains the main function. **/ /** **/ /** DATES : # Version 5.0 : from : 30 apr 2006 **/ /** to : 16 jun 2008 **/ /** # Version 5.1 : from : 26 oct 2008 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGORD #define SCOTCH_PTSCOTCH #include #include "module.h" #include "common.h" #include "ptscotch.h" #include "dgord.h" /* ** The static and global definitions. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "w" }, { "-", NULL, "w" }, { "-", NULL, "w" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "dgord [ [ []]] ", " -b : Output block ordering data instead of plain ordering data", " -c : Choose default ordering strategy according to one or several of :", " b : enforce load balance as much as possible", " q : privilege quality over speed (default)", " s : privilege speed over quality", " t : enforce safety", " x : enforce scalability", " -h : Display this help", " -m : Save column block mapping data to ", " -o : Set parallel ordering strategy (see user's manual)", " -r : Set root process for centralized files (default is 0)", " -t : Save partitioning tree data to ", " -V : Print program version and copyright", " -v : Set verbose mode to :", " a : memory allocation information", " s : strategy information", " t : timing information", "", "See default strategy with option '-vs'", NULL }; /*********************/ /* */ /* The main routine. */ /* */ /*********************/ int main ( int argc, char * argv[]) { SCOTCH_Dgraph grafdat; SCOTCH_Dordering ordedat; SCOTCH_Strat stradat; SCOTCH_Num straval; char * straptr; int flagval; int procglbnbr; int proclocnum; int protglbnum; /* Root process */ Clock runtime[2]; /* Timing variables */ double reduloctab[12]; /* 3 * (min, max, sum) */ double reduglbtab[12]; MPI_Datatype redutype; MPI_Op reduop; int i, j; #ifdef SCOTCH_PTHREAD int thrdlvlreqval; int thrdlvlproval; #endif /* SCOTCH_PTHREAD */ errorProg ("dgord"); #ifdef SCOTCH_PTHREAD thrdlvlreqval = MPI_THREAD_MULTIPLE; if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) errorPrint ("main: Cannot initialize (1)"); if (thrdlvlreqval > thrdlvlproval) errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); #else /* SCOTCH_PTHREAD */ if (MPI_Init (&argc, &argv) != MPI_SUCCESS) errorPrint ("main: Cannot initialize (2)"); #endif /* SCOTCH_PTHREAD */ MPI_Comm_size (MPI_COMM_WORLD, &procglbnbr); /* Get communicator data */ MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum); protglbnum = 0; /* Assume root process is process 0 */ intRandInit (); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } flagval = C_FLAGNONE; /* Default behavior */ straval = 0; /* No strategy flags */ straptr = NULL; SCOTCH_stratInit (&stradat); for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else errorPrint ("main: too many file names given"); } else { /* If found an option name */ switch (argv[i][1]) { case 'B' : case 'b' : flagval |= C_FLAGBLOCK; break; case 'C' : case 'c' : /* Strategy selection parameters */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'B' : case 'b' : straval |= SCOTCH_STRATBALANCE; break; case 'Q' : case 'q' : straval |= SCOTCH_STRATQUALITY; break; case 'S' : case 's' : straval |= SCOTCH_STRATSPEED; break; case 'T' : case 't' : straval |= SCOTCH_STRATSAFETY; break; case 'X' : case 'x' : straval |= SCOTCH_STRATSCALABILITY; break; default : errorPrint ("main: invalid strategy selection option '%c'", argv[i][j]); } } break; #ifdef SCOTCH_DEBUG_ALL case 'D' : case 'd' : flagval |= C_FLAGDEBUG; break; #endif /* SCOTCH_DEBUG_ALL */ case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'M' : /* Output separator mapping */ case 'm' : flagval |= C_FLAGMAPOUT; if (argv[i][2] != '\0') C_filenamemapout = &argv[i][2]; break; case 'O' : /* Ordering strategy */ case 'o' : straptr = &argv[i][2]; SCOTCH_stratExit (&stradat); SCOTCH_stratInit (&stradat); SCOTCH_stratDgraphOrder (&stradat, straptr); break; case 'R' : /* Root process (if necessary) */ case 'r' : protglbnum = atoi (&argv[i][2]); if ((protglbnum < 0) || (protglbnum >= procglbnbr) || ((protglbnum == 0) && (argv[i][2] != '0'))) errorPrint ("main: invalid root process number"); break; case 'T' : /* Output separator tree */ case 't' : flagval |= C_FLAGTREOUT; if (argv[i][2] != '\0') C_filenametreout = &argv[i][2]; break; case 'V' : fprintf (stderr, "dgord, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2007-2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); case 'v' : /* Output control info */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'A' : case 'a' : #ifdef COMMON_MEMORY_TRACE flagval |= C_FLAGVERBMEM; #else /* COMMON_MEMORY_TRACE */ errorPrint ("main: not compiled with COMMON_MEMORY_TRACE"); #endif /* COMMON_MEMORY_TRACE */ break; case 'S' : case 's' : flagval |= C_FLAGVERBSTR; break; case 'T' : case 't' : flagval |= C_FLAGVERBTIM; break; default : errorPrint ("main: unprocessed parameter '%c' in '%s'", argv[i][j], argv[i]); } } break; default : errorPrint ("main: unprocessed option '%s'", argv[i]); } } } #ifdef SCOTCH_DEBUG_ALL if ((flagval & C_FLAGDEBUG) != 0) { fprintf (stderr, "Proc %4d of %d, pid %d\n", proclocnum, procglbnbr, getpid ()); if (proclocnum == protglbnum) { /* Synchronize on keybord input */ char c; printf ("Waiting for key press...\n"); scanf ("%c", &c); } MPI_Barrier (MPI_COMM_WORLD); } #endif /* SCOTCH_DEBUG_ALL */ fileBlockOpenDist (C_fileTab, C_FILENBR, procglbnbr, proclocnum, protglbnum); /* Open all files */ clockInit (&runtime[0]); clockStart (&runtime[0]); SCOTCH_dgraphInit (&grafdat, MPI_COMM_WORLD); SCOTCH_dgraphLoad (&grafdat, C_filepntrsrcinp, -1, 0); if (straval != 0) { if (straptr != NULL) errorPrint ("main: options '-c' and '-o' are exclusive"); SCOTCH_stratDgraphOrderBuild (&stradat, straval, (SCOTCH_Num) procglbnbr, 0.2); } clockStop (&runtime[0]); /* Get input time */ clockInit (&runtime[1]); #ifdef SCOTCH_DEBUG_ALL if ((flagval & C_FLAGDEBUG) != 0) MPI_Barrier (MPI_COMM_WORLD); #endif /* SCOTCH_DEBUG_ALL */ clockStart (&runtime[1]); SCOTCH_dgraphGhst (&grafdat); /* Compute it once for good */ SCOTCH_dgraphOrderInit (&grafdat, &ordedat); SCOTCH_dgraphOrderCompute (&grafdat, &ordedat, &stradat); clockStop (&runtime[1]); /* Get ordering time */ #ifdef SCOTCH_DEBUG_ALL if ((flagval & C_FLAGDEBUG) != 0) MPI_Barrier (MPI_COMM_WORLD); #endif /* SCOTCH_DEBUG_ALL */ clockStart (&runtime[0]); if (proclocnum == protglbnum) { if ((flagval & C_FLAGBLOCK) == 0) SCOTCH_dgraphOrderSave (&grafdat, &ordedat, C_filepntrordout); else SCOTCH_dgraphOrderSaveBlock (&grafdat, &ordedat, C_filepntrordout); if ((flagval & C_FLAGMAPOUT) != 0) /* If mapping wanted */ SCOTCH_dgraphOrderSaveMap (&grafdat, &ordedat, C_filepntrmapout); /* Write mapping */ if ((flagval & C_FLAGTREOUT) != 0) /* If separator tree wanted */ SCOTCH_dgraphOrderSaveTree (&grafdat, &ordedat, C_filepntrtreout); /* Write tree */ } else { if ((flagval & C_FLAGBLOCK) == 0) SCOTCH_dgraphOrderSave (&grafdat, &ordedat, NULL); else SCOTCH_dgraphOrderSaveBlock (&grafdat, &ordedat, NULL); if ((flagval & C_FLAGMAPOUT) != 0) SCOTCH_dgraphOrderSaveMap (&grafdat, &ordedat, NULL); if ((flagval & C_FLAGTREOUT) != 0) SCOTCH_dgraphOrderSaveTree (&grafdat, &ordedat, NULL); } clockStop (&runtime[0]); #ifdef SCOTCH_DEBUG_ALL if ((flagval & C_FLAGDEBUG) != 0) MPI_Barrier (MPI_COMM_WORLD); #endif /* SCOTCH_DEBUG_ALL */ MPI_Type_contiguous (3, MPI_DOUBLE, &redutype); MPI_Type_commit (&redutype); MPI_Op_create ((MPI_User_function *) dgordStatReduceOp, 1, &reduop); if ((flagval & C_FLAGVERBTIM) != 0) { reduloctab[0] = reduloctab[1] = reduloctab[2] = (double) clockVal (&runtime[1]); reduloctab[3] = reduloctab[4] = reduloctab[5] = (double) clockVal (&runtime[0]); reduloctab[6] = reduloctab[7] = reduloctab[8] = reduloctab[0] + reduloctab[3]; MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 3, redutype, reduop, MPI_COMM_WORLD); } #ifdef COMMON_MEMORY_TRACE if ((flagval & C_FLAGVERBMEM) != 0) { reduloctab[9] = reduloctab[10] = reduloctab[11] = (double) memMax (); MPI_Allreduce (&reduloctab[9], &reduglbtab[9], 1, redutype, reduop, MPI_COMM_WORLD); } #endif /* COMMON_MEMORY_TRACE */ MPI_Op_free (&reduop); MPI_Type_free (&redutype); if (C_filepntrlogout != NULL) { if ((flagval & C_FLAGVERBSTR) != 0) { fprintf (C_filepntrlogout, "S\tStrat="); SCOTCH_stratSave (&stradat, C_filepntrlogout); putc ('\n', C_filepntrlogout); } if ((flagval & C_FLAGVERBTIM) != 0) { fprintf (C_filepntrlogout, "T\tOrder\tmin=%g\tmax=%g\tavg=%g\nT\tI/O\tmin=%g\tmax=%g\tavg=%g\nT\tTotal\tmin=%g\tmax=%g\tavg=%g\n", reduglbtab[0], reduglbtab[1], reduglbtab[2] / (double) procglbnbr, reduglbtab[3], reduglbtab[4], reduglbtab[5] / (double) procglbnbr, reduglbtab[6], reduglbtab[7], reduglbtab[8] / (double) procglbnbr); } #ifdef COMMON_MEMORY_TRACE if ((flagval & C_FLAGVERBMEM) != 0) fprintf (C_filepntrlogout, "A\tMemory\tmin=%g\tmax=%g\tavg=%g\n", reduglbtab[9], reduglbtab[10], reduglbtab[11] / (double) procglbnbr); #endif /* COMMON_MEMORY_TRACE */ } fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_dgraphOrderExit (&grafdat, &ordedat); SCOTCH_dgraphExit (&grafdat); SCOTCH_stratExit (&stradat); MPI_Finalize (); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } /* Reduction routine for statistics output. */ void dgordStatReduceOp ( double * in, double * inout, int * len, MPI_Datatype * datatype) { int i; for (i = 0; i < *len; i ++) { inout[3 * i] = MIN (in[3 * i], inout[3 * i]); inout[3 * i + 1] = MAX (in[3 * i + 1], inout[3 * i + 1]); inout[3 * i + 2] = in[3 * i + 2] + inout[3 * i + 2]; } } scotch-5.1.12b.dfsg/src/scotch/amk_m2.c0000644000175300017530000003232111611563204017755 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : amk_m2.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the distance map for **/ /** bidimensional mesh graphs, to be used **/ /** to build the architecture description **/ /** files for these graphs. **/ /** **/ /** DATES : # Version 1.3 : from : 21 apr 1994 **/ /** to : 21 apr 1994 **/ /** # Version 2.0 : from : 12 jul 1994 **/ /** to : 12 nov 1994 **/ /** # Version 3.0 : from : 17 jul 1995 **/ /** to : 19 sep 1995 **/ /** # Version 3.2 : from : 31 may 1997 **/ /** to : 02 jun 1997 **/ /** # Version 3.4 : from : 03 feb 2000 **/ /** to : 03 feb 2000 **/ /** # Version 4.0 : from : 09 feb 2004 **/ /** to : 09 feb 2004 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 21 apr 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /** NOTES : # The vertices of the (dX,dY) mesh are **/ /** numbered as terminals so that **/ /** t (0,0)=0, t (1,0) = 1, **/ /** t (dX - 1, 0) = dX - 1, **/ /** t (0,1) = dX, and **/ /** t(x,y) = (y * dX) + x. **/ /** **/ /** # The nested dissection method should **/ /** behave like the architecture built in **/ /** the mapper. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define AMK_M2 #include "module.h" #include "common.h" #include "scotch.h" #include "arch.h" #include "arch_mesh.h" #include "amk_m2.h" /* ** The static definitions. */ static int C_paraNum = 0; /* Number of parameters */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* File array */ { "-", NULL, "w" } }; static const char * C_usageList[] = { "amk_m2 [ []] ", " -h : Display this help", " -m : Decomposition method", " n : Nested dissection (cut biggest dimension)", " o : One-way dissection (y, then x)", " -V : Print program version and copyright", "", "Default option set is : '-Mn'", NULL }; /*************************************************/ /* */ /* The main routine, which computes the distance */ /* triangular table. */ /* */ /*************************************************/ int main ( int argc, char * argv[]) { ArchMesh2 arch; /* Mesh dimensions */ ArchMesh2Dom dom; /* Initial domain */ C_MethType methtype; /* Bipartitioning method */ unsigned int termnbr; /* Number of terminal domains */ unsigned int termmax; /* Maximum terminal number */ unsigned int * termtab; /* Terminal numbers table */ unsigned int x0, y0, x1, y1; int i; errorProg ("amk_m2"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } methtype = C_METHNESTED; arch.c[0] = /* Preset mesh dimensions */ arch.c[1] = 1; for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < 2) { /* If number of parameters not reached */ if ((arch.c[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get the dimension */ errorPrint ("main: invalid dimension '%s'", argv[i]); return (1); } continue; /* Process the other parameters */ } if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'M' : /* Use a built-in method */ case 'm' : switch (argv[i][2]) { case 'N' : /* Nested dissection */ case 'n' : methtype = C_METHNESTED; break; case 'O' : /* One-way dissection */ case 'o' : methtype = C_METHONEWAY; break; default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } break; case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "amk_m2, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ dom.c[0][0] = 0; /* Set the initial domain */ dom.c[0][1] = arch.c[0] - 1; dom.c[1][0] = 0; dom.c[1][1] = arch.c[1] - 1; termnbr = arch.c[0] * arch.c[1]; /* Compute number of terminals */ termmax = 0; /* Maximum terminal value not known yet */ if ((termtab = (unsigned int *) memAlloc (termnbr * sizeof (unsigned int))) == NULL) { /* Allocate terminal array */ errorPrint ("main: out of memory"); return (1); } memset (termtab, -1, termnbr * sizeof (unsigned int)); /* Initilize mapping table */ C_termBipart (&arch, &dom, 1, termtab, &termmax, /* Compute terminal numbers */ (methtype == C_METHNESTED) ? archMesh2DomBipart : C_methBipartOne); fprintf (C_filepntrarcout, "deco\n0\n%u\t%u\n", /* Print file header */ termnbr, /* Print number of terminal domains */ termmax); /* Print biggest terminal value */ for (i = 0; i < termnbr; i ++) /* For all terminals */ fprintf (C_filepntrarcout, "%u\t1\t%u\n", /* Print terminal data */ i, termtab[i]); for (y0 = 0; y0 < arch.c[1]; y0 ++) { /* For all vertices */ for (x0 = 0; x0 < arch.c[0]; x0 ++) { for (y1 = 0; y1 <= y0; y1 ++) { /* Compute distance to smaller vertices */ for (x1 = 0; (x1 < arch.c[0]) && ((y1 < y0) || (x1 < x0)); x1 ++) fprintf (C_filepntrarcout, ((x1 == 0) && (y1 == 0)) ? "%u" : " %u", C_termDist (x0, y0, x1, y1)); } fprintf (C_filepntrarcout, "\n"); } } fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ memFree (termtab); /* Free terminal number array */ #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } /* This routine recursively determines the values ** of all the terminal vertices of the mesh domain, ** and puts them in table. */ void C_termBipart ( ArchMesh2 * archptr, ArchMesh2Dom * domptr, unsigned int num, unsigned int * termtab, unsigned int * termmax, int (* methfunc) ()) { ArchMesh2Dom dom0; ArchMesh2Dom dom1; if (methfunc (archptr, domptr, &dom0, &dom1) == 0) { /* If we can bipartition */ C_termBipart (archptr, &dom0, num + num, termtab, termmax, methfunc); /* Bipartition recursively */ C_termBipart (archptr, &dom1, num + num + 1, termtab, termmax, methfunc); } else { /* If we have reached the end */ termtab[domptr->c[1][0] * archptr->c[0] + /* Set the terminal number */ domptr->c[0][0]] = num; if (*termmax < num) /* If we have reached a new maximum */ *termmax = num; /* Record it */ } } /* This function tries to split a rectangular domain into ** two subdomains using a one-way dissection method, by ** cutting first in the Y dimension, then in the X one. ** It returns: ** - 1 : if the domain has been bipartitioned. ** - 0 : else. */ int C_methBipartOne ( const ArchMesh2 * const archptr, const ArchMesh2Dom * const domptr, ArchMesh2Dom * restrict const dom0ptr, ArchMesh2Dom * restrict const dom1ptr) { if ((domptr->c[0][0] == domptr->c[0][1]) && /* Return if cannot split more */ (domptr->c[1][0] == domptr->c[1][1])) return (0); if (domptr->c[1][1] == domptr->c[1][0]) { /* If the Y dimension cannot be cut */ dom0ptr->c[0][0] = domptr->c[0][0]; /* Cut in the X dimension */ dom0ptr->c[0][1] = (domptr->c[0][0] + domptr->c[0][1]) / 2; dom1ptr->c[0][0] = dom0ptr->c[0][1] + 1; dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; } else { /* If the Y dimension can be cut, cut it */ dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = (domptr->c[1][0] + domptr->c[1][1]) / 2; dom1ptr->c[1][0] = dom0ptr->c[1][1] + 1; dom1ptr->c[1][1] = domptr->c[1][1]; } return (1); } scotch-5.1.12b.dfsg/src/scotch/amk_grf.c0000644000175300017530000002655111611563204020225 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : amk_grf.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the architecture description **/ /** file for any source graph. **/ /** **/ /** DATES : # Version 3.0 : from : 06 jul 1995 **/ /** to : 02 oct 1995 **/ /** # Version 3.1 : from : 26 mar 1996 **/ /** to : 26 mar 1996 **/ /** # Version 3.2 : from : 23 apr 1997 **/ /** to : 03 jun 1998 **/ /** # Version 3.3 : from : 15 may 1999 **/ /** to : 15 may 1999 **/ /** # Version 3.4 : from : 03 feb 2000 **/ /** to : 03 feb 2000 **/ /** # Version 4.0 : from : 11 dec 2001 **/ /** to : 17 mar 2005 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 11 dec 2008 **/ /** to : 17 jul 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define AMK_GRF #include "module.h" #include "common.h" #include "scotch.h" #include "amk_grf.h" /* ** The static variables. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "w" }, { "-", NULL, "r" } }; static const char * C_usageList[] = { /* Usage */ "amk_grf [ []] ", " -b : Apply bipartitioning strategy ", " -h : Display this help", " -l : Load vertex list from ", " -V : Print program version and copyright", "", "Default option set is : '-Bhf{move=1000}/((load0=load)|(load0=0))?x;'", NULL }; /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ int main ( int argc, char * argv[]) { SCOTCH_Strat bipastrat; /* Bipartitioning strategy */ SCOTCH_Arch archdat; /* Target (terminal) architecture */ SCOTCH_Graph grafdat; /* Source graph to turn into architecture */ SCOTCH_Num vertnbr; /* Number of vertices in graph */ SCOTCH_Num * vlbltab; /* Pointer to vertex label array, if present */ SCOTCH_Num listnbr; /* Size of list array */ SCOTCH_Num * listtab; /* Pointer to list array */ C_VertSort * sorttab; /* Vertex label sort area */ SCOTCH_Num baseval; int flagval; /* Process flags */ int i; errorProg ("amk_grf"); intRandInit (); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } flagval = C_FLAGNONE; SCOTCH_stratInit (&bipastrat); for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'B' : /* Bipartitioning strategy */ case 'b' : SCOTCH_stratExit (&bipastrat); SCOTCH_stratInit (&bipastrat); if ((SCOTCH_stratGraphBipart (&bipastrat, &argv[i][2])) != 0) { errorPrint ("main: invalid bipartitioning strategy"); return (1); } break; case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'L' : /* Input vertex list */ case 'l' : flagval |= C_FLAGVRTINP; if (argv[i][2] != '\0') C_filenamevrtinp = &argv[i][2]; break; case 'V' : fprintf (stderr, "amk_grf, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ SCOTCH_graphInit (&grafdat); /* Create graph structure */ SCOTCH_graphLoad (&grafdat, C_filepntrgrfinp, -1, 0); /* Load source graph */ SCOTCH_graphData (&grafdat, &baseval, &vertnbr, NULL, NULL, NULL, /* Get graph data */ &vlbltab, NULL, NULL, NULL); listnbr = 0; /* Initialize vertex list */ listtab = NULL; if (flagval & C_FLAGVRTINP) { /* If list of vertices provided */ SCOTCH_Num listnum; if ((intLoad (C_filepntrvrtinp, &listnbr) != 1) || /* Read list size */ (listnbr < 0) || (listnbr > vertnbr)) { errorPrint ("main: bad list input (1)"); return (1); } if ((listtab = (SCOTCH_Num *) memAlloc (listnbr * sizeof (SCOTCH_Num) + 1)) == NULL) { errorPrint ("main: out of memory (1)"); return (1); } for (listnum = 0; listnum < listnbr; listnum ++) { /* Read list data */ if (intLoad (C_filepntrvrtinp, &listtab[listnum]) != 1) { errorPrint ("main: bad list input (2)"); return (1); } } intSort1asc1 (listtab, listnbr); for (listnum = 0; listnum < listnbr - 1; listnum ++) { /* Search for duplicates */ if (listtab[listnum] == listtab[listnum + 1]) { errorPrint ("main: duplicate list labels"); memFree (listtab); return (1); } } if (vlbltab != NULL) { /* If graph has vertex labels */ SCOTCH_Num vertnum; if ((sorttab = (C_VertSort *) memAlloc (vertnbr * sizeof (C_VertSort))) == NULL) { errorPrint ("main: out of memory (2)"); memFree (listtab); return (1); } for (vertnum = 0; vertnum < vertnbr; vertnum ++) { /* Initialize sort area */ sorttab[vertnum].vlblnum = vlbltab[vertnum]; sorttab[vertnum].vertnum = vertnum; } intSort2asc1 (sorttab, vertnbr); /* Sort by ascending labels */ for (listnum = 0, vertnum = 0; listnum < listnbr; listnum ++) { /* For all labels in list */ while ((vertnum < vertnbr) && (sorttab[vertnum].vlblnum < listtab[listnum])) vertnum ++; /* Search vertex graph with corresponding label */ if ((vertnum >= vertnbr) || /* If label not found */ (sorttab[vertnum].vlblnum > listtab[listnum])) { errorPrint ("main: list label '" SCOTCH_NUMSTRING "' not in graph", (SCOTCH_Num) listtab[listnum]); memFree (sorttab); memFree (listtab); return (1); } listtab[listnum] = sorttab[vertnum ++].vertnum; /* Replace label by number */ } memFree (sorttab); /* Free sort area */ } } SCOTCH_archInit (&archdat); /* Initialize target architecture */ SCOTCH_archBuild (&archdat, &grafdat, listnbr, listtab, &bipastrat); /* Compute architecture */ SCOTCH_archSave (&archdat, C_filepntrtgtout); /* Write target architecture */ fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end potential (un)compression tasks */ SCOTCH_graphExit (&grafdat); /* Free target graph */ SCOTCH_archExit (&archdat); /* Free target architecture */ SCOTCH_stratExit (&bipastrat); /* Free strategy string */ if (listtab != NULL) /* If vertex list provided */ memFree (listtab); /* Free it */ #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/acpl.h0000644000175300017530000000671211611563204017540 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : acpl.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the target archi- **/ /** tecture compilation function defini- **/ /** tions. **/ /** **/ /** DATES : # Version 2.0 : from : 12 nov 1994 **/ /** to : 12 nov 1994 **/ /** # Version 3.0 : from : 06 jul 1995 **/ /** to : 06 jul 1995 **/ /** # Version 3.2 : from : 24 sep 1996 **/ /** to : 01 jun 1997 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 02 oct 1998 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 2 /* Number of files which can be arguments */ #define C_filenametgtinp C_fileTab[0].name /* Target architecture input file name */ #define C_filenametgtout C_fileTab[1].name /* Target architecture output file name */ #define C_filepntrtgtinp C_fileTab[0].pntr /* Target architecture input file */ #define C_filepntrtgtout C_fileTab[1].pntr /* Target architecture output file */ scotch-5.1.12b.dfsg/src/scotch/gord.c0000644000175300017530000002734311611563204017552 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gord.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a sparse matrix graph ordering **/ /** software. **/ /** This module contains the main function. **/ /** **/ /** DATES : # Version 3.2 : from : 24 aug 1996 **/ /** to : 21 aug 1998 **/ /** # Version 3.3 : from : 07 oct 1998 **/ /** to : 31 may 1999 **/ /** # Version 3.4 : from : 07 oct 1998 **/ /** to : 03 feb 2000 **/ /** # Version 4.0 : from : 02 feb 2002 **/ /** to : 08 jan 2006 **/ /** # Version 5.0 : from : 26 jan 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GORD #include "module.h" #include "common.h" #include "scotch.h" #include "gord.h" /* ** The static and global definitions. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "w" }, { "-", NULL, "w" }, { "-", NULL, "w" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "gord [ [ []]] ", " -c : Choose default ordering strategy according to one or several of :", " b : enforce load balance as much as possible", " q : privilege quality over speed (default)", " s : privilege speed over quality", " t : enforce safety", " -h : Display this help", " -m : Save column block mapping data to ", " -o : Set ordering strategy (see user's manual)", " -t : Save partitioning tree data to ", " -V : Print program version and copyright", " -v : Set verbose mode to :", " s : strategy information", " t : timing information", "", "See default strategy with option '-vs'", NULL }; /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ int main ( int argc, char * argv[]) { SCOTCH_Num vertnbr; /* Number of vertices */ SCOTCH_Graph grafdat; /* Source graph */ SCOTCH_Ordering ordedat; /* Graph ordering */ SCOTCH_Num * permtab; /* Permutation array */ SCOTCH_Strat stradat; /* Ordering strategy */ SCOTCH_Num straval; char * straptr; int flagval; Clock runtime[2]; /* Timing variables */ int i, j; errorProg ("gord"); intRandInit (); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } flagval = C_FLAGNONE; /* Default behavior */ straval = 0; /* No strategy flags */ straptr = NULL; SCOTCH_stratInit (&stradat); for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else errorPrint ("main: too many file names given"); } else { /* If found an option name */ switch (argv[i][1]) { case 'C' : case 'c' : /* Strategy selection parameters */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'B' : case 'b' : straval |= SCOTCH_STRATBALANCE; break; case 'Q' : case 'q' : straval |= SCOTCH_STRATQUALITY; break; case 'S' : case 's' : straval |= SCOTCH_STRATSPEED; break; case 'T' : case 't' : straval |= SCOTCH_STRATSAFETY; break; default : errorPrint ("main: invalid strategy selection option '%c'", argv[i][j]); } } break; case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'M' : /* Output separator mapping */ case 'm' : flagval |= C_FLAGMAPOUT; if (argv[i][2] != '\0') C_filenamemapout = &argv[i][2]; break; case 'O' : /* Ordering strategy */ case 'o' : straptr = &argv[i][2]; SCOTCH_stratExit (&stradat); SCOTCH_stratInit (&stradat); SCOTCH_stratGraphOrder (&stradat, straptr); break; case 'T' : /* Output separator tree */ case 't' : flagval |= C_FLAGTREOUT; if (argv[i][2] != '\0') C_filenametreout = &argv[i][2]; break; case 'V' : fprintf (stderr, "gord, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); case 'v' : /* Output control info */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'S' : case 's' : flagval |= C_FLAGVERBSTR; break; case 'T' : case 't' : flagval |= C_FLAGVERBTIM; break; default : errorPrint ("main: unprocessed parameter '%c' in '%s'", argv[i][j], argv[i]); } } break; default : errorPrint ("main: unprocessed option '%s'", argv[i]); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ clockInit (&runtime[0]); clockStart (&runtime[0]); SCOTCH_graphInit (&grafdat); /* Create graph structure */ SCOTCH_graphLoad (&grafdat, C_filepntrsrcinp, -1, 2); /* Read source graph */ SCOTCH_graphSize (&grafdat, &vertnbr, NULL); /* Get graph characteristics */ if (straval != 0) { if (straptr != NULL) errorPrint ("main: options '-c' and '-o' are exclusive"); SCOTCH_stratGraphOrderBuild (&stradat, straval, 0.2); } clockStop (&runtime[0]); /* Get input time */ clockInit (&runtime[1]); clockStart (&runtime[1]); if ((permtab = (SCOTCH_Num *) memAlloc (vertnbr * sizeof (SCOTCH_Num))) == NULL) { errorPrint ("main: out of memory"); return (1); } SCOTCH_graphOrderInit (&grafdat, &ordedat, permtab, NULL, NULL, NULL, NULL); /* Create ordering */ SCOTCH_graphOrderCompute (&grafdat, &ordedat, &stradat); /* Perform ordering */ clockStop (&runtime[1]); /* Get ordering time */ #ifdef SCOTCH_DEBUG_ALL if (SCOTCH_graphOrderCheck (&grafdat, &ordedat) != 0) return (1); #endif /* SCOTCH_DEBUG_ALL */ clockStart (&runtime[0]); SCOTCH_graphOrderSave (&grafdat, &ordedat, C_filepntrordout); /* Write ordering */ if (flagval & C_FLAGMAPOUT) /* If mapping wanted */ SCOTCH_graphOrderSaveMap (&grafdat, &ordedat, C_filepntrmapout); /* Write mapping */ if (flagval & C_FLAGTREOUT) /* If separator tree wanted */ SCOTCH_graphOrderSaveTree (&grafdat, &ordedat, C_filepntrtreout); /* Write tree */ clockStop (&runtime[0]); /* Get output time */ if (flagval & C_FLAGVERBSTR) { fprintf (C_filepntrlogout, "S\tStrat="); SCOTCH_stratSave (&stradat, C_filepntrlogout); putc ('\n', C_filepntrlogout); } if (flagval & C_FLAGVERBTIM) { fprintf (C_filepntrlogout, "T\tOrder\t\t%g\nT\tI/O\t\t%g\nT\tTotal\t\t%g\n", (double) clockVal (&runtime[1]), (double) clockVal (&runtime[0]), (double) clockVal (&runtime[0]) + (double) clockVal (&runtime[1])); } fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_graphOrderExit (&grafdat, &ordedat); SCOTCH_stratExit (&stradat); SCOTCH_graphExit (&grafdat); memFree (permtab); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/mtst.c0000644000175300017530000001653611611563204017610 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mtst.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This program gives statistics on source **/ /** meshes. **/ /** **/ /** DATES : # Version 4.0 : from : 25 feb 2003 **/ /** to 27 jan 2004 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MTST #include "module.h" #include "common.h" #include "scotch.h" #include "mtst.h" /* ** The static definitions. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* The file array */ { "-", NULL, "r" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "mtst [ []] ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ int main ( int argc, char * argv[]) { SCOTCH_Mesh meshdat; SCOTCH_Num velmnbr; SCOTCH_Num vnodnbr; SCOTCH_Num vnlomin; SCOTCH_Num vnlomax; SCOTCH_Num vnlosum; double vnloavg; double vnlodlt; SCOTCH_Num edegmin; SCOTCH_Num edegmax; double edegavg; double edegdlt; SCOTCH_Num ndegmin; SCOTCH_Num ndegmax; double ndegavg; double ndegdlt; SCOTCH_Num edgenbr; int i; errorProg ("mtst"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); exit (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); exit (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); exit (0); case 'V' : fprintf (stderr, "mtst, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); exit (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ SCOTCH_meshInit (&meshdat); SCOTCH_meshLoad (&meshdat, C_filepntrsrcinp, -1); SCOTCH_meshCheck (&meshdat); SCOTCH_meshSize (&meshdat, &velmnbr, &vnodnbr, &edgenbr); SCOTCH_meshStat (&meshdat, &vnlomin, &vnlomax, &vnlosum, &vnloavg, &vnlodlt, &edegmin, &edegmax, &edegavg, &edegdlt, &ndegmin, &ndegmax, &ndegavg, &ndegdlt); fprintf (C_filepntrdatout, "S\tElements\tnbr=" SCOTCH_NUMSTRING "\n", (SCOTCH_Num) velmnbr); fprintf (C_filepntrdatout, "S\tNodes\tnbr=" SCOTCH_NUMSTRING "\n", (SCOTCH_Num) vnodnbr); fprintf (C_filepntrdatout, "S\tNode load\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", (SCOTCH_Num) vnlomin, (SCOTCH_Num) vnlomax, (SCOTCH_Num) vnlosum, vnloavg, vnlodlt); fprintf (C_filepntrdatout, "S\tElement degree\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", (SCOTCH_Num) edegmin, (SCOTCH_Num) edegmax, (SCOTCH_Num) (edgenbr / 2), edegavg, edegdlt); fprintf (C_filepntrdatout, "S\tNode degree\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", (SCOTCH_Num) ndegmin, (SCOTCH_Num) ndegmax, (SCOTCH_Num) (edgenbr / 2), ndegavg, ndegdlt); fprintf (C_filepntrdatout, "S\tEdge\tnbr=" SCOTCH_NUMSTRING "\n", (SCOTCH_Num) (edgenbr / 2)); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_meshExit (&meshdat); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/acpl.c0000644000175300017530000001521011611563204017524 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : acpl.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module compiles target architec- **/ /** ture decomposition files for fast **/ /** loading. **/ /** **/ /** DATES : # Version 2.0 : from : 12 nov 1994 **/ /** to : 12 nov 1994 **/ /** # Version 3.0 : from : 06 jul 1995 **/ /** to : 19 sep 1995 **/ /** # Version 3.2 : from : 24 sep 1996 **/ /** to : 12 may 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 02 oct 1998 **/ /** # Version 3.4 : from : 03 feb 2000 **/ /** to : 03 feb 2000 **/ /** # Version 4.0 : from : 09 feb 2004 **/ /** to : 09 feb 2004 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ACPL #include "module.h" #include "common.h" #include "scotch.h" #include "acpl.h" /* ** The static variables. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "acpl [ []] ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ int main ( int argc, char * argv[]) { SCOTCH_Arch arch; /* Architecture read and written */ int i; errorProg ("acpl"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "acpl, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ SCOTCH_archInit (&arch); /* Initialize architecture structure */ SCOTCH_archLoad (&arch, C_filepntrtgtinp); /* Load architecture */ if (strcmp (SCOTCH_archName (&arch), "deco") != 0) { /* If not a decomposition */ errorPrint ("main: architecture is not decomposition-defined"); return (1); } SCOTCH_archSave (&arch, C_filepntrtgtout); /* Save the compiled architecture */ fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_archExit (&arch); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/amk_m2.h0000644000175300017530000001071311611563204017763 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : amk_m2.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the target architecture file **/ /** for bidimensional mesh graphs. **/ /** Here are the data declaration for the **/ /** target machine architecture functions. **/ /** **/ /** DATES : # Version 1.3 : from : 21 apr 1994 **/ /** to : 22 apr 1994 **/ /** # Version 2.0 : from : 12 jul 1994 **/ /** to : 13 nov 1994 **/ /** # Version 2.0 : from : 18 sep 1995 **/ /** to : 19 sep 1995 **/ /** # Version 3.1 : from : 30 may 1996 **/ /** to : 30 may 1996 **/ /** # Version 3.2 : from : 31 may 1997 **/ /** to : 02 jun 1997 **/ /** # Version 4.0 : from : 09 feb 2004 **/ /** to : 09 feb 2004 **/ /** **/ /************************************************************/ /* ** The defines. */ /** File name aliases. **/ #define C_FILENBR 1 /* Number of files in list */ #define C_FILEARGNBR 1 /* Number of files which can be arguments */ #define C_filenamearcout C_fileTab[0].name /* Architecture output file name */ #define C_filepntrarcout C_fileTab[0].pntr /* Architecture output file */ /* ** The type and structure definitions. */ /** The method type. **/ typedef enum C_MethType_ { C_METHNESTED, /*+ Nested decomposition +*/ C_METHONEWAY /*+ One-way decomposition +*/ } C_MethType; /* ** The function prototypes. */ void C_termBipart (ArchMesh2 *, ArchMesh2Dom *, unsigned int, unsigned int *, unsigned int *, int (*) ()); int C_methBipartOne (const ArchMesh2 * const, const ArchMesh2Dom * const, ArchMesh2Dom * restrict const, ArchMesh2Dom * restrict const); /* ** The macro definitions. */ #ifndef abs #define abs(a) (((a) >= 0) ? (a) : -(a)) #endif /* abs */ #define C_termDist(x0,y0,x1,y1) ((unsigned int) (abs ((int) (x0) - (int) (x1)) + \ abs ((int) (y0) - (int) (y1)))) scotch-5.1.12b.dfsg/src/scotch/dgtst.h0000644000175300017530000000656211611563204017751 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgtst.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a parallel sparse matrix **/ /** ordering software. **/ /** This module contains the data declara- **/ /** tions for the distributed source graph **/ /** analyzer. **/ /** **/ /** DATES : # Version 5.0 : from : 23 jun 2007 **/ /** to : 24 jun 2007 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 2 /* Number of files which can be arguments */ #define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ #define C_filenamedatout C_fileTab[1].name /* Statistics output file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ #define C_filepntrdatout C_fileTab[1].pntr /* Statistics output file */ /*+ Process flags. +*/ #define C_FLAGNONE 0x0000 /* No flags */ #define C_FLAGDEBUG 0x0001 /* Enable easy debugger attachment */ scotch-5.1.12b.dfsg/src/scotch/gcv.c0000644000175300017530000002412511611563204017371 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gcv.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** Bruno MARCUSSEAU (v3.1) **/ /** **/ /** FUNCTION : Part of a graph file converter. **/ /** This module contains the main function. **/ /** **/ /** DATES : # Version 0.0 : from : 02 apr 1993 **/ /** to 02 apr 1993 **/ /** # Version 2.0 : from : 28 oct 1994 **/ /** to 16 nov 1994 **/ /** # Version 3.0 : from : 08 sep 1995 **/ /** to 20 sep 1995 **/ /** # Version 3.1 : from : 22 mar 1996 **/ /** to 22 mar 1996 **/ /** # Version 3.2 : from : 04 oct 1996 **/ /** to 26 may 1997 **/ /** # Version 3.3 : from : 06 oct 1998 **/ /** to : 21 dec 1998 **/ /** # Version 3.4 : from : 05 oct 1999 **/ /** to : 03 feb 2000 **/ /** # Version 4.0 : from : 29 nov 2003 **/ /** to : 19 jan 2004 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 11 jun 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GCV #include "module.h" #include "common.h" #include "scotch.h" #include "gcv.h" /* ** The static and global variables. */ static int C_inpFormatType = 0; /* Input graph format */ static char * C_inpFormatData = "\0"; /* Pointer to auxiliary data */ static const C_Format C_inpFormatTab[] = { /* Table of input formats */ { 'B', SCOTCH_graphGeomLoadHabo }, { 'b', SCOTCH_graphGeomLoadHabo }, { 'C', SCOTCH_graphGeomLoadChac }, { 'c', SCOTCH_graphGeomLoadChac }, { 'M', SCOTCH_graphGeomLoadMmkt }, { 'm', SCOTCH_graphGeomLoadMmkt }, { 'S', SCOTCH_graphGeomLoadScot }, { 's', SCOTCH_graphGeomLoadScot }, { '\0', NULL } }; static int C_outFormatType = 4; /* Output graph format */ static char * C_outFormatData = "\0"; /* Pointer to auxiliary data */ static C_Format C_outFormatTab[] = { /* Table of output formats */ { 'C', SCOTCH_graphGeomSaveChac }, { 'c', SCOTCH_graphGeomSaveChac }, { 'M', SCOTCH_graphGeomSaveMmkt }, { 'm', SCOTCH_graphGeomSaveMmkt }, { 'S', SCOTCH_graphGeomSaveScot }, { 's', SCOTCH_graphGeomSaveScot }, { '\0', NULL } }; static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[3] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "w" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "gcv [ [ []]] ", " -h : Display this help", " -i : Select input file format", " b : Boeing-Harwell format (matrices)", " c : Chaco v2.0 format (adjacency)", " m : Matrix Market format (edges, symmetrized)", " s : Scotch v3.0 format (adjacency)", " -o : Select output file format", " c : Chaco v2.0 format (adjacency)", " m : Matrix Market symmetric pattern format (edges)", " s : Scotch v3.0 format (adjacency)", " -V : Print program version and copyright", "", "Default option set is : '-Ib -Os'", NULL }; /*****************************/ /* */ /* This is the main function */ /* */ /*****************************/ int main ( int argc, char * argv[]) { SCOTCH_Graph grafdat; SCOTCH_Geom geomdat; int i, j; errorProg ("gcv"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give help */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'I' : /* Select input file type */ case 'i' : for (j = 0; C_inpFormatTab[j].code != '\0'; j ++) { /* Find proper format code */ if (C_inpFormatTab[j].code == argv[i][2]) { C_inpFormatType = j; C_inpFormatData = &argv[i][3]; break; } } if (C_inpFormatTab[j].code == '\0') { errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } break; case 'O' : /* Select input file type */ case 'o' : for (j = 0; C_outFormatTab[j].code != '\0'; j ++) { /* Find proper format code */ if (C_outFormatTab[j].code == argv[i][2]) { C_outFormatType = j; C_outFormatData = &argv[i][3]; break; } } if (C_inpFormatTab[j].code == '\0') { errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } break; case 'V' : fprintf (stderr, "gcv, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ SCOTCH_graphInit (&grafdat); SCOTCH_geomInit (&geomdat); C_inpFormatTab[C_inpFormatType].func (&grafdat, &geomdat, C_filepntrsrcinp, NULL, C_inpFormatData); #ifdef SCOTCH_DEBUG_ALL if (SCOTCH_graphCheck (&grafdat) != 0) { errorPrint ("main: bad graph structure"); return (1); } #endif /* SCOTCH_DEBUG_ALL */ C_outFormatTab[C_outFormatType].func (&grafdat, &geomdat, C_filepntrsrcout, C_filepntrgeoout, C_outFormatData); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_geomExit (&geomdat); SCOTCH_graphExit (&grafdat); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/gscat.h0000644000175300017530000000632111611563204017716 0ustar hazelscthazelsct/* Copyright 2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gscat.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the data declara- **/ /** tions for the sequential graph scatter- **/ /** ing program. **/ /** **/ /** DATES : # Version 5.1 : from : 26 apr 2009 **/ /** to : 26 apr 2009 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 2 /* Number of files which can be arguments */ #define C_filenamesrcinp C_fileTab[0].name /* Centralized source graph input file name */ #define C_filenamesrcout C_fileTab[1].name /* Distributed source graph output file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* Centralized source graph input file */ #define C_filepntrsrcout C_fileTab[1].pntr /* Distributed source graph output file */ /* ** The function prototypes. */ static int C_graphScat (FILE * const, SCOTCH_Num, char * const); scotch-5.1.12b.dfsg/src/scotch/gmk_m3.c0000644000175300017530000003120511611563204017764 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gmk_m3.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the source graph for **/ /** tridimensional mesh source graphs. **/ /** **/ /** DATES : # Version 4.0 : from : 11 feb 2002 **/ /** to : 18 may 2004 **/ /** # Version 5.0 : from : 13 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /** NOTES : # The vertices of the (dX,dY,dZ) mesh **/ /** are numbered as terminals so that **/ /** t(0,0,0) = 0, t(1,0,0) = 1, **/ /** t(dX - 1, 0, 0) = dX - 1, t(0,1,0) = **/ /** dX, t (0, 0, 1) = dX * dY - 1, **/ /** and t(x,y,z) = (z * dY + y) * dX + x. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GMK_M3 #include "module.h" #include "common.h" #include "scotch.h" #include "gmk_m3.h" /* ** The static definitions. */ static int C_paraNum = 0; /* Number of parameters */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* The file array */ { "-", NULL, "w" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "gmk_m3 [ [ []]] ", " -b : Set base value for output (0 or 1)", " -g : Output the geometry to ", " -h : Display this help", " -t : Build a torus rather than a mesh", " -V : Print program version and copyright", NULL }; /****************************************/ /* */ /* The main routine, which computes the */ /* source graph description. */ /* */ /****************************************/ int main ( int argc, char * argv[]) { int flagval; /* Process flags */ SCOTCH_Num baseval; /* Base value */ SCOTCH_Num d[3] = { 1, 1, 1 }; /* Mesh dimensions */ SCOTCH_Num c[3]; /* Vertex coordinates */ int i; errorProg ("gmk_m3"); flagval = C_FLAGDEFAULT; /* Set default flags */ baseval = 0; if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < 3) { /* If number of parameters not reached */ if ((d[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get the dimension */ errorPrint ("main: invalid dimension '%s'", argv[i]); return (1); } continue; /* Process the other parameters */ } if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'B' : /* Set base value */ case 'b' : baseval = (SCOTCH_Num) atol (&argv[i][2]); if ((baseval < 0) || (baseval > 1)) { errorPrint ("main: invalid base value '" SCOTCH_NUMSTRING "'", (SCOTCH_Num) baseval); } break; case 'G' : /* Output the geometry */ case 'g' : flagval |= C_FLAGGEOOUT; if (argv[i][2] != '\0') C_filenamegeoout = &argv[i][2]; break; case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'T' : /* Build a torus */ case 't' : flagval |= C_FLAGTORUS; break; case 'V' : fprintf (stderr, "gmk_m3, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ if (flagval & C_FLAGTORUS) { /* Build a torus */ fprintf (C_filepntrsrcout, "0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t000\n", (SCOTCH_Num) (d[0] * d[1] * d[2]), /* Print number of vertices */ (SCOTCH_Num) ((6 * d[0] * d[1] * d[2]) - /* Print number of edges (arcs) */ ((d[0] < 3) ? (2 * d[1] * d[2]) : 0) - ((d[1] < 3) ? (2 * d[0] * d[2]) : 0) - ((d[2] < 3) ? (2 * d[0] * d[1]) : 0)), (SCOTCH_Num) baseval); for (c[2] = 0; c[2] < d[2]; c[2] ++) { /* Output neighbor list */ for (c[1] = 0; c[1] < d[1]; c[1] ++) { for (c[0] = 0; c[0] < d[0]; c[0] ++) { fprintf (C_filepntrsrcout, SCOTCH_NUMSTRING, (SCOTCH_Num) (((d[0] > 2) ? 3 : d[0]) + /* Output number of neighbors */ ((d[1] > 2) ? 3 : d[1]) + ((d[2] > 2) ? 3 : d[2]) - 3)); if (d[2] > 2) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, /* Output the neighbors */ (SCOTCH_Num) ((((c[2] + d[2] - 1) % d[2]) * d[1] + c[1]) * d[0] + c[0] + baseval)); if (d[1] > 2) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[2] * d[1] + ((c[1] + d[1] - 1) % d[1])) * d[0] + c[0] + baseval)); if (d[0] > 2) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) (((c[2] * d[1] + c[1]) * d[0] + (c[0] + d[0] - 1) % d[0])) + baseval); if (d[0] > 1) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[2] * d[1] + c[1]) * d[0] + ((c[0] + 1) % d[0]) + baseval)); if (d[1] > 1) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[2] * d[1] + ((c[1] + 1) % d[1])) * d[0] + c[0] + baseval)); if (d[2] > 1) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((((c[2] + 1) % d[2]) * d[1] + c[1]) * d[0] + c[0] + baseval)); fprintf (C_filepntrsrcout, "\n"); } } } } else { /* Build a mesh */ fprintf (C_filepntrsrcout, "0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t000\n", (SCOTCH_Num) (d[0] * d[1] * d[2]), (SCOTCH_Num) ((d[0] * d[1] * d[2] * 3 - (d[0] * d[1] + d[0] * d[2] + d[1] * d[2])) * 2), (SCOTCH_Num) baseval); for (c[2] = 0; c[2] < d[2]; c[2] ++) { /* Output neighbor list */ for (c[1] = 0; c[1] < d[1]; c[1] ++) { for (c[0] = 0; c[0] < d[0]; c[0] ++) { fprintf (C_filepntrsrcout, "%d", ((c[0] == 0) ? 0 : 1) + /* Output number of neighbors */ ((c[0] == (d[0] - 1)) ? 0 : 1) + ((c[1] == 0) ? 0 : 1) + ((c[1] == (d[1] - 1)) ? 0 : 1) + ((c[2] == 0) ? 0 : 1) + ((c[2] == (d[2] - 1)) ? 0 : 1)); if (c[2] != 0) /* Output the neighbors */ fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) (((c[2] - 1) * d[1] + c[1]) * d[0] + c[0] + baseval)); if (c[1] != 0) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[2] * d[1] + c[1] - 1) * d[0] + c[0] + baseval)); if (c[0] != 0) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[2] * d[1] + c[1]) * d[0] + c[0] - 1 + baseval)); if (c[0] != (d[0] - 1)) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[2] * d[1] + c[1]) * d[0] + c[0] + 1 + baseval)); if (c[1] != (d[1] - 1)) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[2] * d[1] + c[1] + 1) * d[0] + c[0] + baseval)); if (c[2] != (d[2] - 1)) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) (((c[2] + 1) * d[1] + c[1]) * d[0] + c[0] + baseval)); fprintf (C_filepntrsrcout, "\n"); } } } } if (flagval & C_FLAGGEOOUT) { /* If geometry is wanted */ fprintf (C_filepntrgeoout, "3\n" SCOTCH_NUMSTRING "\n", /* Output geometry file header */ (SCOTCH_Num) (d[0] * d[1] * d[2])); for (c[2] = 0; c[2] < d[2]; c[2] ++) { /* Output mesh coordinates */ for (c[1] = 0; c[1] < d[1]; c[1] ++) { for (c[0] = 0; c[0] < d[0]; c[0] ++) fprintf (C_filepntrgeoout, SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", (SCOTCH_Num) ((c[2] * d[1] + c[1]) * d[0] + c[0] + baseval), (SCOTCH_Num) c[0], (SCOTCH_Num) (d[1] - 1 - c[1]), (SCOTCH_Num) c[2]); } } } fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/gmap.h0000644000175300017530000001206511611563204017543 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gmap.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a graph static mapper. **/ /** These lines are the data declaration **/ /** for the main routine. **/ /** **/ /** DATES : # Version 0.0 : from : 05 jan 1993 **/ /** to 12 may 1993 **/ /** # Version 1.3 : from : 09 apr 1994 **/ /** to 30 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 08 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to 09 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 15 aug 1995 **/ /** # Version 3.1 : from : 07 nov 1995 **/ /** to 10 nov 1995 **/ /** # Version 3.2 : from : 04 oct 1996 **/ /** to 18 jul 1997 **/ /** # Version 3.3 : from : 07 oct 1998 **/ /** to : 31 may 1999 **/ /** # Version 4.0 : from : 16 jan 2004 **/ /** to : 16 jan 2004 **/ /** # Version 5.0 : from : 12 jun 2008 **/ /** to : 18 jun 2008 **/ /** # Version 5.1 : from : 28 aug 2010 **/ /** to : 18 jul 2011 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 4 /* Number of files in list */ #define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ #define C_filenametgtinp C_fileTab[1].name /* Target architecture input file name */ #define C_filenamemapout C_fileTab[2].name /* Mapping result output file name */ #define C_filenamelogout C_fileTab[3].name /* Log file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ #define C_filepntrtgtinp C_fileTab[1].pntr /* Target architecture input file */ #define C_filepntrmapout C_fileTab[2].pntr /* Mapping result output file */ #define C_filepntrlogout C_fileTab[3].pntr /* Log file */ /*+ Process flags. +*/ #define C_FLAGNONE 0x0000 /* No flags */ #define C_FLAGPART 0x0001 /* Partitioning */ #define C_FLAGVERBSTR 0x0002 /* Verbose flags */ #define C_FLAGVERBTIM 0x0004 #define C_FLAGVERBMAP 0x0008 #define C_FLAGKBALVAL 0x0010 /* Imbalance tolerance */ #define C_FLAGCLUSTER 0x0020 /* Clustering */ scotch-5.1.12b.dfsg/src/scotch/gmk_m3.h0000644000175300017530000000651611611563204020000 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gmk_m3.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the data declara- **/ /** tions for the tridimensional mesh **/ /** source graph building program. **/ /** **/ /** DATES : # Version 4.0 : from : 11 feb 2002 **/ /** to : 11 feb 2002 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 1 /* Number of files which can be arguments */ #define C_filenamesrcout C_fileTab[0].name /* Source graph output file name */ #define C_filenamegeoout C_fileTab[1].name /* Geometry graph output file name */ #define C_filepntrsrcout C_fileTab[0].pntr /* Source graph output file */ #define C_filepntrgeoout C_fileTab[1].pntr /* Geometry graph output file */ /*+ Process flags. +*/ #define C_FLAGGEOOUT 0x0001 /* Output the geometry graph */ #define C_FLAGTORUS 0x0002 /* Build a torus rather than a mesh */ #define C_FLAGDEFAULT 0x0000 /* Default flags */ scotch-5.1.12b.dfsg/src/scotch/gmtst.h0000644000175300017530000000732211611563204017755 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gmtst.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This program computes statistics on **/ /** graph mappings. **/ /** **/ /** DATES : # Version 3.1 : from : 17 jul 1996 **/ /** to 23 jul 1996 **/ /** # Version 3.2 : from : 02 jun 1997 **/ /** to 02 jun 1997 **/ /** # Version 3.3 : from : 06 jun 1999 **/ /** to 07 jun 1999 **/ /** # Version 4.0 : from : 12 feb 2004 **/ /** to 29 nov 2005 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 4 /* Number of files in list */ #define C_FILEARGNBR 4 /* Number of files which can be arguments */ #define C_filenamesrcinp C_fileTab[0].name /* Source graph file name */ #define C_filenametgtinp C_fileTab[1].name /* Target architecture file name */ #define C_filenamemapinp C_fileTab[2].name /* Mapping result file name */ #define C_filenamedatout C_fileTab[3].name /* Statistics file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ #define C_filepntrtgtinp C_fileTab[1].pntr /* Target architecture file */ #define C_filepntrmapinp C_fileTab[2].pntr /* Mapping result input file */ #define C_filepntrdatout C_fileTab[3].pntr /* Statistics output file */ scotch-5.1.12b.dfsg/src/scotch/gbase.c0000644000175300017530000001445011611563204017673 0ustar hazelscthazelsct/* Copyright 2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gbase.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This program changes the base of source **/ /** graphs. **/ /** **/ /** DATES : # Version 4.0 : from : 12 may 2006 **/ /** to : 12 may 2006 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GBASE #include "module.h" #include "common.h" #include "scotch.h" #include "gbase.h" /* ** The static definitions. */ static int C_paraNum = 0; /* Number of parameters */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* The file array */ { "-", NULL, "r" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "gbase [ []] ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ int main ( int argc, char * argv[]) { SCOTCH_Graph grafdat; /* Source graph */ int baseval; int i; errorProg ("gbase"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); exit (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < 1) { /* If number of parameters not reached */ C_paraNum ++; /* One more parameter */ baseval = atoi (argv[i]); /* Get the base value */ if ((baseval < 0) || (baseval > 1)) { errorPrint ("main: invalid base value '%s'", argv[i]); return (1); } continue; /* Process the other parameters */ } if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); exit (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); exit (0); case 'V' : fprintf (stderr, "gbase, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); exit (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ SCOTCH_graphInit (&grafdat); SCOTCH_graphLoad (&grafdat, C_filepntrsrcinp, (SCOTCH_Num) baseval, 0); SCOTCH_graphSave (&grafdat, C_filepntrsrcout); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_graphExit (&grafdat); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/gmk_hy.c0000644000175300017530000001712511611563204020072 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gmk_hy.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the source graph for hypercube **/ /** graphs. **/ /** **/ /** DATES : # Version 2.0 : from : 03 nov 1994 **/ /** to 03 nov 1994 **/ /** # Version 3.0 : from : 11 jul 1995 **/ /** to 11 jul 1995 **/ /** # Version 3.2 : from : 03 jun 1997 **/ /** to : 03 jun 1997 **/ /** # Version 3.3 : from : 06 oct 1998 **/ /** to : 06 oct 1998 **/ /** # Version 3.4 : from : 03 feb 2000 **/ /** to : 03 feb 2000 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 16 map 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GMK_HY #include "module.h" #include "common.h" #include "scotch.h" #include "gmk_hy.h" /* ** The static definitions. */ static int C_paraNum = 0; /* Number of parameters */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* The file array */ { "-", NULL, "w" } }; static const char * C_usageList[] = { "gmk_hy [] ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /****************************************/ /* */ /* The main routine, which computes the */ /* source graph description. */ /* */ /****************************************/ int main ( int argc, char * argv[]) { SCOTCH_Num hdim = 1; /* Graph dimension */ SCOTCH_Num hnbr; /* Number of vertices */ SCOTCH_Num hbit; /* Most significant bit */ SCOTCH_Num hvrt; SCOTCH_Num hngb; int i; errorProg ("gmk_hy"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); exit (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < 1) { /* If number of parameters not reached */ if ((hdim = atoi (argv[i])) < 1) { /* Get the dimension */ errorPrint ("main: invalid dimension '%s'", argv[i]); exit (1); } C_paraNum ++; continue; /* Process the other parameters */ } if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); exit (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); exit (0); case 'V' : fprintf (stderr, "gmk_hy, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); exit (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ hnbr = 1 << hdim; /* Compute number of vertices */ hbit = 1 << (hdim - 1); /* Compute highest bit value */ fprintf (C_filepntrsrcout, "0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n0\t000\n", (SCOTCH_Num) hnbr, /* Print number of vertices */ (SCOTCH_Num) (hdim * hnbr)); /* Print number of edges (arcs) */ for (hvrt = 0; hvrt < hnbr; hvrt ++) { /* For all vertices */ fprintf (C_filepntrsrcout, "" SCOTCH_NUMSTRING "", (SCOTCH_Num) hdim); /* Output number of neighbors */ for (hngb = hbit; hngb > 0; hngb >>= 1) /* For all vertex bits */ fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, /* Write corresponding neighbor */ (SCOTCH_Num) (hvrt ^ hngb)); fprintf (C_filepntrsrcout, "\n"); } fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/dggath.h0000644000175300017530000000651311611563204020056 0ustar hazelscthazelsct/* Copyright 2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dggath.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the distributed graph file **/ /** gathering program. **/ /** **/ /** DATES : # Version 5.1 : from : 26 oct 2008 **/ /** to : 26 oct 2008 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 2 /* Number of files which can be arguments */ #define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ #define C_filenamesrcout C_fileTab[1].name /* Source graph output file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ #define C_filepntrsrcout C_fileTab[1].pntr /* Source graph output file */ /*+ Process flags. +*/ #define C_FLAGNONE 0x0000 /* No flags */ #define C_FLAGCHECK 0x0001 /* Check distributed source graph */ #define C_FLAGDEBUG 0x0002 /* Enable easy debugger attachment */ scotch-5.1.12b.dfsg/src/scotch/gotst.h0000644000175300017530000001162011611563204017753 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gotst.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a graph scalar factorizer. **/ /** This module contains the data declara- **/ /** tions for the main module. **/ /** **/ /** DATES : # Version 4.0 : from : 27 jan 2004 **/ /** to : 27 jan 2004 **/ /** # Version 5.0 : from : 25 jun 2007 **/ /** to : 25 jul 2007 **/ /** **/ /************************************************************/ /* ** The defines */ /*+ File name aliases. +*/ #define C_FILENBR 3 /* Number of files in list */ #define C_FILEARGNBR 3 /* Number of files which can be arguments */ #define C_filenamegrfinp C_fileTab[0].name /* Graph input file name */ #define C_filenamesrcout C_fileTab[1].name /* Ordering input file name */ #define C_filenamedatout C_fileTab[2].name /* Output data file name */ #define C_filepntrgrfinp C_fileTab[0].pntr /* Graph input file */ #define C_filepntrordinp C_fileTab[1].pntr /* Ordering output file */ #define C_filepntrdatout C_fileTab[2].pntr /* Output data file */ /* ** The type and structure definitions. */ /* Factorization node */ typedef struct C_FactorNode_ { struct C_FactorNode_ * linkdad; /*+ Father of node +*/ struct C_FactorNode_ * linkson; /*+ First son of node +*/ struct C_FactorNode_ * linkbro; /*+ Brother of node +*/ } C_FactorNode; /* Data structure for computing factored matrix statistics. */ typedef struct FactorStat_ { const SCOTCH_Num * ldadtax; const SCOTCH_Num * lsontax; const SCOTCH_Num * lbrotax; SCOTCH_Num heigmin; SCOTCH_Num heigmax; SCOTCH_Num heignbr; double heigavg; double heigdlt; const SCOTCH_Num * fnnztax; double fnnzsum; } FactorStat; /* ** The function prototypes. */ static int factorView (const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, FILE * restrict const); static int factorView2 (const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, SCOTCH_Num * restrict, SCOTCH_Num * restrict, SCOTCH_Num * restrict, SCOTCH_Num * restrict); static void factorView3 (FactorStat * restrict const, SCOTCH_Num, SCOTCH_Num, double * restrict const); static void factorView4 (FactorStat * restrict const, SCOTCH_Num, SCOTCH_Num, double * restrict const); scotch-5.1.12b.dfsg/src/scotch/gord.h0000644000175300017530000001035311611563204017550 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gord.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a sparse matrix graph orderer. **/ /** This module contains the data declara- **/ /** tions for the main routine. **/ /** **/ /** DATES : # Version 3.2 : from : 24 aug 1996 **/ /** to : 20 oct 1997 **/ /** # Version 3.3 : from : 07 oct 1998 **/ /** to : 31 may 1999 **/ /** # Version 4.0 : from : 11 dec 2002 **/ /** to : 27 dec 2004 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 5 /* Number of files in list */ #define C_FILEARGNBR 3 /* Number of files which can be arguments */ #define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ #define C_filenameordout C_fileTab[1].name /* Ordering output file name */ #define C_filenamelogout C_fileTab[2].name /* Log file name */ #define C_filenamemapout C_fileTab[3].name /* Separator mapping file name */ #define C_filenametreout C_fileTab[4].name /* Separator tree file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ #define C_filepntrordout C_fileTab[1].pntr /* Ordering output file */ #define C_filepntrlogout C_fileTab[2].pntr /* Log file */ #define C_filepntrmapout C_fileTab[3].pntr /* Separator mapping file */ #define C_filepntrtreout C_fileTab[4].pntr /* Separator tree file */ /*+ Process flags. +*/ #define C_FLAGNONE 0x0000 /* No flags */ #define C_FLAGMAPOUT 0x0001 /* Output mapping data */ #define C_FLAGTREOUT 0x0002 /* Output separator tree data */ #define C_FLAGVERBSTR 0x0004 /* Output strategy string */ #define C_FLAGVERBTIM 0x0008 /* Output timing information */ scotch-5.1.12b.dfsg/src/scotch/amk_fft2.c0000644000175300017530000002614211611563204020304 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : amk_fft2.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the distance map for FFT **/ /** graphs, to be used to build the archi- **/ /** tecture description files for these **/ /** graphs. **/ /** **/ /** DATES : # Version 1.3 : from : 19 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to : 19 sep 1995 **/ /** # Version 3.2 : from : 07 may 1997 **/ /** to : 07 may 1997 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 02 oct 1998 **/ /** # Version 3.4 : from : 03 feb 2000 **/ /** to : 03 feb 2000 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define AMK_FFT2 #include "module.h" #include "common.h" #include "scotch.h" #include "amk_fft2.h" /* ** The static and global definitions. */ static int C_paraNum = 0; /* Number of parameters */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* The file array */ { "-", NULL, "w" } }; static C_VertDist * C_distaTab; /* Pointer to distance map table */ static C_Queue C_distaQueue; /* Distance queue */ static const char * C_usageList[] = { /* Usage list */ "amk_fft2 [ []] ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /*************************************************/ /* */ /* The main routine, which computes the distance */ /* triangular table. */ /* */ /*************************************************/ int main ( int argc, char * argv[]) { SCOTCH_Num fdim; /* FFT dimension */ SCOTCH_Num fnbr; /* Number of FFT vertices */ SCOTCH_Num fmax; /* Maximum terminal number */ SCOTCH_Num fmsk; /* Position bit mask */ C_Vertex v, w, x; /* A FFT vertex (lvl, pos) */ SCOTCH_Num b, d; /* Mask and bit variables */ SCOTCH_Num i; /* Loop counter */ SCOTCH_Num t; /* Vertex terminal value */ errorProg ("amk_fft2"); fdim = 2; if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < 1) { /* If number of parameters not reached */ if ((fdim = atoi (argv[i])) < 1) { /* Get the dimension */ errorPrint ("main: invalid dimension '%s'", argv[i]); return (1); } C_paraNum ++; continue; /* Process the other parameters */ } if (C_fileNum < C_FILENBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "amk_fft2, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ fnbr = (fdim + 1) * (1 << fdim); /* Compute number of vertices */ fmax = (1 << (fdim * 2 - 1)) - 1; /* Compute maximum terminal number */ fmsk = (1 << fdim) - 1; /* Get maximum position number */ fprintf (C_filepntrarcout, "deco\n0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", /* Print file header */ (SCOTCH_Num) fnbr, /* Print number of terminal domains */ (SCOTCH_Num) fmax); /* Print the biggest terminal value */ for (v.lvl = 0; v.lvl <= fdim; v.lvl ++) { /* For all vertices */ for (v.pos = 0; v.pos <= fmsk; v.pos ++) { for (i = v.lvl, b = 1 << (fdim - 1), t = 1; /* Recurse through the vertical + horizontal cuts */ i <= fdim; i ++, b >>= 1) { t <<= 1; /* Vertical cut: tell if vertex is in left or... */ t |= (v.pos & b) ? 1 : 0; /* right part from the position heaviest bits */ t <<= 1; /* Vertex is still in upper part of horizontal cut */ } if (v.lvl == 0) /* If vertex is in the first level... */ t >>= 2; /* We have gone one step too far */ else { /* Else */ t |= 1; /* This time vertex is in the lower part */ t <<= (v.lvl - 1); /* Make space for the chain bipartition */ t |= v.pos & ((1 << (v.lvl - 1)) - 1); /* Bipartition the chain following the lowest bits */ } printf (((v.lvl == fdim) && (v.pos == fmsk)) /* Print terminal domain number */ ? "%u\n\n" : "%u ", t); } } if ((C_queueInit (&C_distaQueue, fnbr) != 0) || /* Allocate distance array */ ((C_distaTab = (C_VertDist *) memAlloc (fnbr * sizeof (C_VertDist))) == NULL)) { errorPrint ("main: out of memory"); return (1); } for (v.lvl = 0; v.lvl <= fdim; v.lvl ++) { /* For all vertices */ for (v.pos = 0; v.pos <= fmsk; v.pos ++) { for (i = 0; i < fnbr; i ++) /* Initialize the vertex table */ C_distaTab[i].queued = 0; /* Vertex not queued yet */ C_distaRoot (&v); /* Set the queue with root v */ while (C_distaGet (&w, &d)) { /* As long as the queue is not empty */ C_distaTab[C_vertLabl (&w)].dist = d; /* Keep the distance information */ d ++; /* Search for neighbors at next level */ if (w.lvl > 0) { /* Add new neighbors to the queue */ x.lvl = w.lvl - 1; x.pos = w.pos; C_distaPut (&x, d); x.pos = w.pos ^ (1 << (w.lvl - 1)); C_distaPut (&x, d); } if (w.lvl < fdim) { x.lvl = w.lvl + 1; x.pos = w.pos; C_distaPut (&x, d); x.pos = w.pos ^ (1 << w.lvl); C_distaPut (&x, d); } } if (v.lvl + v.pos > 0) { /* Print the distance triangular map line */ fprintf (C_filepntrarcout, SCOTCH_NUMSTRING, (SCOTCH_Num) C_distaTab[0].dist); for (i = 1; i < (v.lvl << fdim) + v.pos; i ++) fprintf (C_filepntrarcout, " " SCOTCH_NUMSTRING, (SCOTCH_Num) C_distaTab[i].dist); fprintf (C_filepntrarcout, "\n"); } } } C_queueExit (&C_distaQueue); memFree (C_distaTab); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/amk_hy.h0000644000175300017530000000707211611563204020071 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : amk_hy.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the target architecture file **/ /** for hypercube graphs. **/ /** Here are the data declaration for the **/ /** target machine architecture functions. **/ /** **/ /** DATES : # Version 2.0 : from : 14 nov 1994 **/ /** to : 14 nov 1994 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to : 07 jul 1995 **/ /** # Version 3.1 : from : 30 may 1996 **/ /** to : 30 may 1996 **/ /** # Version 3.2 : from : 31 may 1997 **/ /** to : 31 may 1997 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 02 oct 1998 **/ /** **/ /************************************************************/ /* ** The defines. */ /** File name aliases. **/ #define C_FILENBR 1 /* Number of files in list */ #define C_FILEARGNBR 1 /* Number of files which can be arguments */ #define C_filenametgtout C_fileTab[0].name /* Architecture output file name */ #define C_filepntrtgtout C_fileTab[0].pntr /* Architecture output file */ /* ** The macro definitions. */ #ifndef abs #define abs(a) (((a) >= 0) ? (a) : -(a)) #endif /* abs */ scotch-5.1.12b.dfsg/src/scotch/atst.c0000644000175300017530000002122511611563204017563 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : atst.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Target architecture graph analyzer. **/ /** **/ /** DATES : # Version 1.3 : from : 17 may 1994 **/ /** to : 17 may 1994 **/ /** # Version 2.0 : from : 11 nov 1994 **/ /** to : 11 nov 1994 **/ /** # Version 3.0 : from : 05 jul 1995 **/ /** to : 19 aug 1995 **/ /** # Version 3.2 : from : 24 sep 1996 **/ /** to : 12 may 1998 **/ /** # Version 3.4 : from : 03 feb 2000 **/ /** to : 03 feb 2000 **/ /** # Version 4.0 : from : 09 feb 2004 **/ /** to : 23 nov 2005 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ATST #include "module.h" #include "common.h" #include "scotch.h" #include "arch.h" #include "arch_deco.h" #include "arch_mesh.h" #include "atst.h" /* ** The static variables. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "atst [ []] ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ int main (argc, argv) int argc; char * argv[]; { Arch archdat; /* The architecture read */ ArchDeco * deco; /* Its decomposition */ ArchDecoDom dom0; ArchDecoDom dom1; Anum dstval; Anum dstmin; Anum dstmax; Anum dstsum; double dstavg; double dstdlt; int i; errorProg ("atst"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "atst, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ archInit (&archdat); /* Initialize architecture structure */ archLoad (&archdat, C_filepntrtgtinp); /* Load architecture */ if (strcmp (archName (&archdat), "deco") != 0) { /* If it is not a decomposition */ errorPrint ("main: architecture is not decomposition-defined"); return (1); } deco = (ArchDeco *) (void *) &archdat.data.dummy; /* Point to the decomposition */ dstmin = (Anum) (((unsigned long) ((Anum) -1)) >> 1); /* Set to maximum number in Anum */ dstmax = 0; dstsum = 0; for (dom0.num = 1; dom0.num <= deco->domvertnbr; dom0.num ++) { /* For all pairs of vertices */ if (archDecoDomSize (deco, &dom0) == 1) { /* If vertex is a terminal */ for (dom1.num = dom0.num + 1; dom1.num <= deco->domvertnbr; dom1.num ++) { if (archDecoDomSize (deco, &dom1) == 1) { /* If vertex is a terminal */ dstval = archDecoDomDist (deco, &dom0, &dom1); /* Compute distance between pairs */ if (dstmin > dstval) dstmin = dstval; if (dstmax < dstval) dstmax = dstval; dstsum += dstval; /* Compute distance between pairs */ } } } } dstavg = (deco->domtermnbr > 1) ? (double) dstsum / (double) (deco->domtermnbr * (deco->domtermnbr - 1) / 2) : 0.0L; dstdlt = 0.0L; for (dom0.num = 1; dom0.num <= deco->domvertnbr; dom0.num ++) { /* For all pairs of vertices */ if (archDecoDomSize (deco, &dom0) == 1) { /* If vertex is a terminal */ for (dom1.num = dom0.num + 1; dom1.num <= deco->domvertnbr; dom1.num ++) { if (archDecoDomSize (deco, &dom1) == 1) /* If vertex is a terminal */ dstdlt += fabs (archDecoDomDist (deco, &dom0, &dom1) - dstavg); } } } if (deco->domtermnbr > 1) dstdlt /= (double) (deco->domtermnbr * (deco->domtermnbr - 1) / 2); fprintf (C_filepntrlogout, "A\tTerminals\tnbr=" SCOTCH_NUMSTRING "\n", (SCOTCH_Num) deco->domtermnbr); fprintf (C_filepntrlogout, "A\tDistance\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", (SCOTCH_Num) dstmin, (SCOTCH_Num) dstmax, dstavg, dstdlt); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ archExit (&archdat); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/gout_o.h0000644000175300017530000002055011611563204020111 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gout_o.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a result viewer. **/ /** This module contains the data declara- **/ /** tions for the output module. **/ /** **/ /** DATES : # Version 2.0 : from : 08 oct 1994 **/ /** to 02 nov 1994 **/ /** # Version 3.0 : from : 14 jul 1995 **/ /** to 03 oct 1995 **/ /** # Version 3.1 : from : 05 apr 1996 **/ /** to 05 apr 1996 **/ /** # Version 3.2 : from : 03 dec 1996 **/ /** to 05 jun 1998 **/ /** # Version 3.3 : from : 02 jun 1999 **/ /** to 02 jun 1999 **/ /** # Version 5.0 : from : 25 may 2007 **/ /** to 25 may 2007 **/ /** # Version 5.1 : from : 25 oct 2007 **/ /** to 26 oct 2007 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Generic PostScript output definitions. +*/ #define O_PSDPI 72 /* PostScript dots-per-inch */ #define O_PSPAGEHEIGHT 11.6 /* PostScript page height (in inches) */ #define O_PSPAGEWIDTH 8.2 /* PostScript page witdh (in inches) */ #define O_PSPICTHEIGHT 10.0 /* PostScript picture height (in inches) */ #define O_PSPICTWIDTH 6.6 /* PostScript picture witdh (in inches) */ /*+ PostScript mesh output definitions. +*/ #define O_POSMESHPICTRESOL 10000.0 /* Picture resolution */ #define O_POSMESHISOCOS 0.866025404 /* cos(30 degrees) */ #define O_POSMESHISOSIN 0.5 /* sin(30 degrees) */ #define O_POSMESHISOREDUC 0.20 /* Z-axis reduction coefficient */ #define O_POSMESHCOLNBR 16 /* Number of colors */ /*+ Tulip graph output definitions. +*/ #define O_TULMESHDISKRATIO 0.1 /* Node disk ratio */ /* ** The type and structure definitions. */ /*+ The 2D point type. +*/ typedef struct O_Point_ { double c[2]; /*+ Page coordinates +*/ } O_Point; /*+ The output type type. +*/ typedef enum O_OutType_ { O_OUTTYPEINVMESH, /*+ Mesh SGI Open Inventor (3D) +*/ O_OUTTYPEPOSMATR, /*+ Matrix PostScript (2D) +*/ O_OUTTYPEPOSMESH, /*+ Mesh PostScript (2D) +*/ O_OUTTYPETULMESH, /*+ Mesh Tulip (3D) +*/ O_OUTTYPENBR /*+ Number of output types +*/ } O_OutType; /*+ The output parameter data structure. +*/ typedef struct O_OutParam_ { O_OutType type; /*+ Output type +*/ struct { /*+ Inventor mesh structure +*/ char color; /*+ 'c' : color; 'g' : gray +*/ char edge; /*+ 'r' : remove; 'v' : view +*/ } InvMesh; struct { /*+ PostScript matrix structure +*/ char type; /*+ 'f' : page; 'e' : EPSF +*/ } PosMatr; struct { /*+ PostScript mesh structure +*/ char type; /*+ 'f' : page; 'e' : EPSF +*/ char color; /*+ 'c' : color; 'g' : gray +*/ char edge; /*+ 'r' : remove; 'v' : view +*/ char disk; /*+ 'd' : draw; 'a' : avoid +*/ char clip; /*+ 'l' : large; 's' : short +*/ O_Point min; /*+ Clipping ratios +*/ O_Point max; } PosMesh; struct { /*+ Tulip graph structure +*/ char color; /*+ 'b' : b/w; 'c' : color +*/ char edge; /*+ 'r' : remove; 'v' : view +*/ char disk; /*+ 'd' : draw; 'a' : avoid +*/ } TulMesh; } O_OutParam; /*+ The Inventor path array element. +*/ typedef struct O_InvMeshPath_ { SCOTCH_Num nbr; /*+ Number of output paths +*/ SCOTCH_Num idx; /*+ Index from which to search +*/ } O_InvMeshPath; /*+ The PostScript path array element. +*/ typedef struct O_PosMeshPath_ { SCOTCH_Num nbr; /*+ Number of output paths +*/ SCOTCH_Num idx; /*+ Index from which to search +*/ } O_PosMeshPath; /*+ The PostScript mesh graph vertex. +*/ typedef struct O_PosMeshVertex_ { int vis; /*+ Visibility flag +*/ O_Point pos; /*+ Point position +*/ double rad; /*+ Disk radius +*/ int col; /*+ Disk color index +*/ } O_PosMeshVertex; /* ** The function prototypes. */ void outColorBlw (const SCOTCH_Num, double[]); void outColorColor (const SCOTCH_Num, double[]); int outDrawParse (char * const); void outDraw (const C_Graph * const, const C_Geometry * const, const C_Mapping * const, FILE * const); int outDrawInvMesh (const C_Graph * const, const C_Geometry * const, const C_Mapping * const, FILE * const); int outDrawPosMatr (const C_Graph * const, const C_Geometry * const, const C_Mapping * const, FILE * const); int outDrawPosMesh (const C_Graph * const, const C_Geometry * const, const C_Mapping * const, FILE * const); int outDrawTulMesh (const C_Graph * const, const C_Geometry * const, const C_Mapping * const, FILE * const); scotch-5.1.12b.dfsg/src/scotch/dgmap.c0000644000175300017530000004770511627540210017712 0ustar hazelscthazelsct/* Copyright 2008-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgmap.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a parallel static mapping **/ /** software. **/ /** This module contains the main function. **/ /** **/ /** DATES : # Version 5.0 : from : 12 jun 2008 **/ /** to : 28 aug 2008 **/ /** # Version 5.1 : from : 26 oct 2008 **/ /** to : 31 aug 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGMAP #define SCOTCH_PTSCOTCH #include #include "module.h" #include "common.h" #include "ptscotch.h" #include "dgmap.h" /* ** The static variables. */ static int C_partNbr = 1; /* Default number of parts / cluster load */ static int C_paraNum = 0; /* Number of parameters */ static int C_paraNbr = 0; /* No parameters for mapping */ static int C_fileNum = 0; /* Number of file in arg list */ static int C_fileNbr = 4; /* Number of files for mapping */ static File C_fileTab[C_FILENBR] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "r" }, { "-", NULL, "w" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { /* Usage */ "dgmap [ [ [ []]]] ", "dgpart [] [ [ []]] ", " -b : Load imbalance tolerance (default: 0.05)", " -c : Choose default mapping strategy according to one or several of :", " b : enforce load balance as much as possible", " q : privilege quality over speed (default)", " s : privilege speed over quality", " t : enforce safety", " x : enforce scalability", " -h : Display this help", " -m : Set parallel mapping strategy (see user's manual)", " -q : Do graph clustering instead of graph partitioning (for dgpart)", " -q : Do graph clustering instead of static mapping (for dgmap)", " -r : Set root process for centralized files (default is 0)", " -s : Force unity weights on :", " e : edges", " v : vertices", " -V : Print program version and copyright", " -v : Set verbose mode to :", " a : memory allocation information", " m : mapping information", " s : strategy information", " t : timing information", "", "See default strategy with option '-vs'", NULL }; /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ int main ( int argc, char * argv[]) { SCOTCH_Dgraph grafdat; /* Source graph */ SCOTCH_Num grafflag; /* Source graph properties */ SCOTCH_Arch archdat; /* Target architecture */ SCOTCH_Dmapping mappdat; /* Mapping data */ SCOTCH_Strat stradat; /* Mapping strategy */ SCOTCH_Num straval; char * straptr; int flagval; double kbalval; /* Imbalance tolerance value */ int procglbnbr; int proclocnum; int protglbnum; /* Root process */ Clock runtime[2]; /* Timing variables */ double reduloctab[12]; /* 3 * (min, max, sum) */ double reduglbtab[12]; MPI_Datatype redutype; MPI_Op reduop; int i, j; #ifdef SCOTCH_PTHREAD int thrdlvlreqval; int thrdlvlproval; #endif /* SCOTCH_PTHREAD */ flagval = C_FLAGNONE; /* Default behavior */ kbalval = 0.05; /* Default imbalance */ straval = 0; /* No strategy flags */ straptr = NULL; #ifdef SCOTCH_COMPILE_PART flagval |= C_FLAGPART; C_paraNbr = 1; /* One more parameter */ C_fileNbr = 3; /* One less file to provide */ errorProg ("dgpart"); #else errorProg ("dgmap"); #endif /* SCOTCH_COMPILE_PART */ #ifdef SCOTCH_PTHREAD thrdlvlreqval = MPI_THREAD_MULTIPLE; if (MPI_Init_thread (&argc, &argv, thrdlvlreqval, &thrdlvlproval) != MPI_SUCCESS) errorPrint ("main: Cannot initialize (1)"); if (thrdlvlreqval > thrdlvlproval) errorPrint ("main: MPI implementation is not thread-safe: recompile without SCOTCH_PTHREAD"); #else /* SCOTCH_PTHREAD */ if (MPI_Init (&argc, &argv) != MPI_SUCCESS) errorPrint ("main: Cannot initialize (2)"); #endif /* SCOTCH_PTHREAD */ MPI_Comm_size (MPI_COMM_WORLD, &procglbnbr); /* Get communicator data */ MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum); protglbnum = 0; /* Assume root process is process 0 */ intRandInit (); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } grafflag = 0; /* Use vertex and edge weights */ SCOTCH_stratInit (&stradat); for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < C_paraNbr) { /* If number of parameters not reached */ if ((C_partNbr = atoi (argv[i])) < 1) /* Get the number of parts */ errorPrint ("main: invalid number of parts '%s'", argv[i]); C_paraNum ++; continue; /* Process the other parameters */ } if (C_fileNum < C_fileNbr) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else errorPrint ("main: too many file names given"); } else { /* If found an option name */ switch (argv[i][1]) { case 'B' : case 'b' : flagval |= C_FLAGKBALVAL; kbalval = atof (&argv[i][2]); if ((kbalval < 0.0) || (kbalval > 1.0) || ((kbalval == 0.0) && ((argv[i][2] != '0') && (argv[i][2] != '.')))) { errorPrint ("main: invalid load imbalance ratio"); } break; case 'C' : case 'c' : /* Strategy selection parameters */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'B' : case 'b' : straval |= SCOTCH_STRATBALANCE; break; case 'Q' : case 'q' : straval |= SCOTCH_STRATQUALITY; break; case 'S' : case 's' : straval |= SCOTCH_STRATSPEED; break; case 'T' : case 't' : straval |= SCOTCH_STRATSAFETY; break; case 'X' : case 'x' : straval |= SCOTCH_STRATSCALABILITY; break; default : errorPrint ("main: invalid strategy selection option '%c'", argv[i][j]); } } break; #ifdef SCOTCH_DEBUG_ALL case 'D' : case 'd' : flagval |= C_FLAGDEBUG; break; #endif /* SCOTCH_DEBUG_ALL */ case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'M' : case 'm' : straptr = &argv[i][2]; SCOTCH_stratExit (&stradat); SCOTCH_stratInit (&stradat); SCOTCH_stratDgraphMap (&stradat, straptr); break; case 'Q' : case 'q' : flagval |= C_FLAGCLUSTER; if ((flagval & C_FLAGPART) != 0) { /* If partitioning program */ if (argv[i][2] != '\0') errorPrint ("main: invalid parameter '%s' after '-q' for dgpart", argv[i] + 2); } else { if (argv[i][1] == '\0') errorPrint ("main: missing parameter after '-q' for dgmap"); if ((C_partNbr = atoi (argv[i] + 2)) < 1) /* Get maximum cluster load */ errorPrint ("main: invalid cluster load '%s'", argv[i] + 2); } break; case 'R' : /* Root process (if necessary) */ case 'r' : protglbnum = atoi (&argv[i][2]); if ((protglbnum < 0) || (protglbnum >= procglbnbr) || ((protglbnum == 0) && (argv[i][2] != '0'))) errorPrint ("main: invalid root process number"); break; case 'S' : case 's' : /* Source graph parameters */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'E' : case 'e' : grafflag |= 2; /* Do not load edge weights */ break; case 'V' : case 'v' : grafflag |= 1; /* Do not load vertex weights */ break; default : errorPrint ("main: invalid source graph option '%c'", argv[i][j]); } } break; case 'V' : fprintf (stderr, "dgmap/dgpart, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2008-2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); case 'v' : /* Output control info */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'A' : case 'a' : #ifdef COMMON_MEMORY_TRACE flagval |= C_FLAGVERBMEM; #else /* COMMON_MEMORY_TRACE */ errorPrint ("main: not compiled with COMMON_MEMORY_TRACE"); #endif /* COMMON_MEMORY_TRACE */ break; case 'M' : case 'm' : flagval |= C_FLAGVERBMAP; break; case 'S' : case 's' : flagval |= C_FLAGVERBSTR; break; case 'T' : case 't' : flagval |= C_FLAGVERBTIM; break; default : errorPrint ("main: unprocessed parameter '%c' in '%s'", argv[i][j], argv[i]); } } break; default : errorPrint ("main: unprocessed option '%s'", argv[i]); } } } if ((flagval & C_FLAGPART) != 0) { /* If program run as the partitioner */ C_fileTab[3].name = C_fileTab[2].name; /* Put provided file names at their right place */ C_fileTab[2].name = C_fileTab[1].name; C_fileTab[1].name = "-"; } #ifdef SCOTCH_DEBUG_ALL if ((flagval & C_FLAGDEBUG) != 0) { fprintf (stderr, "Proc %4d of %d, pid %d\n", proclocnum, procglbnbr, getpid ()); if (proclocnum == protglbnum) { /* Synchronize on keybord input */ char c; printf ("Waiting for key press...\n"); scanf ("%c", &c); } MPI_Barrier (MPI_COMM_WORLD); } #endif /* SCOTCH_DEBUG_ALL */ fileBlockOpenDist (C_fileTab, C_FILENBR, procglbnbr, proclocnum, protglbnum); /* Open all files */ clockInit (&runtime[0]); clockStart (&runtime[0]); SCOTCH_dgraphInit (&grafdat, MPI_COMM_WORLD); /* Initialize distributed source graph */ SCOTCH_dgraphLoad (&grafdat, C_filepntrsrcinp, -1, 0); SCOTCH_archInit (&archdat); /* Create architecture structure */ if ((flagval & C_FLAGPART) != 0) { /* If program run as the partitioner */ if ((flagval & C_FLAGCLUSTER) != 0) /* If program run as graph clustering */ SCOTCH_archVcmplt (&archdat); /* Create a variable-sized complete graph */ else /* Program is run as plain graph partitioner */ SCOTCH_archCmplt (&archdat, C_partNbr); /* Create a complete graph of proper size */ } else { if (C_filepntrtgtinp == NULL) errorPrint ("main: target architecture file not provided"); SCOTCH_archLoad (&archdat, C_filepntrtgtinp); /* Read target architecture */ if ((flagval & C_FLAGCLUSTER) == 0) /* If part size not to be preserved */ C_partNbr = SCOTCH_archSize (&archdat); else { if (SCOTCH_archVar (&archdat) == 0) errorPrint ("main: non variable-sized architecture provided while '-q' flag set"); } } if (((straval != 0) || ((flagval & C_FLAGKBALVAL) != 0)) && (straptr != NULL)) errorPrint ("main: options '-b' / '-c' and '-m' are exclusive"); if ((flagval & C_FLAGCLUSTER) != 0) /* If clustering wanted */ SCOTCH_stratDgraphClusterBuild (&stradat, straval, (SCOTCH_Num) procglbnbr, (SCOTCH_Num) C_partNbr, 1.0, kbalval); else SCOTCH_stratDgraphMapBuild (&stradat, straval, (SCOTCH_Num) procglbnbr, (SCOTCH_Num) C_partNbr, kbalval); clockStop (&runtime[0]); /* Get input time */ clockInit (&runtime[1]); #ifdef SCOTCH_DEBUG_ALL if ((flagval & C_FLAGDEBUG) != 0) MPI_Barrier (MPI_COMM_WORLD); #endif /* SCOTCH_DEBUG_ALL */ clockStart (&runtime[1]); SCOTCH_dgraphGhst (&grafdat); /* Compute it once for good */ SCOTCH_dgraphMapInit (&grafdat, &mappdat, &archdat, NULL); SCOTCH_dgraphMapCompute (&grafdat, &mappdat, &stradat); /* Perform mapping */ clockStop (&runtime[1]); /* Get computation time */ #ifdef SCOTCH_DEBUG_ALL if ((flagval & C_FLAGDEBUG) != 0) MPI_Barrier (MPI_COMM_WORLD); #endif /* SCOTCH_DEBUG_ALL */ clockStart (&runtime[0]); SCOTCH_dgraphMapSave (&grafdat, &mappdat, (proclocnum == protglbnum) ? C_filepntrmapout : NULL); /* Write mapping */ clockStop (&runtime[0]); /* Get output time */ #ifdef SCOTCH_DEBUG_ALL if ((flagval & C_FLAGDEBUG) != 0) MPI_Barrier (MPI_COMM_WORLD); #endif /* SCOTCH_DEBUG_ALL */ MPI_Type_contiguous (3, MPI_DOUBLE, &redutype); MPI_Type_commit (&redutype); MPI_Op_create ((MPI_User_function *) dgmapStatReduceOp, 1, &reduop); if ((flagval & C_FLAGVERBTIM) != 0) { reduloctab[0] = reduloctab[1] = reduloctab[2] = (double) clockVal (&runtime[1]); reduloctab[3] = reduloctab[4] = reduloctab[5] = (double) clockVal (&runtime[0]); reduloctab[6] = reduloctab[7] = reduloctab[8] = reduloctab[0] + reduloctab[3]; MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 3, redutype, reduop, MPI_COMM_WORLD); } #ifdef COMMON_MEMORY_TRACE if ((flagval & C_FLAGVERBMEM) != 0) { reduloctab[9] = reduloctab[10] = reduloctab[11] = (double) memMax (); MPI_Allreduce (&reduloctab[9], &reduglbtab[9], 1, redutype, reduop, MPI_COMM_WORLD); } #endif /* COMMON_MEMORY_TRACE */ MPI_Op_free (&reduop); MPI_Type_free (&redutype); if (C_filepntrlogout != NULL) { if ((flagval & C_FLAGVERBSTR) != 0) { fprintf (C_filepntrlogout, "S\tStrat="); SCOTCH_stratSave (&stradat, C_filepntrlogout); putc ('\n', C_filepntrlogout); } if ((flagval & C_FLAGVERBTIM) != 0) { fprintf (C_filepntrlogout, "T\tMapping\tmin=%g\tmax=%g\tavg=%g\nT\tI/O\tmin=%g\tmax=%g\tavg=%g\nT\tTotal\tmin=%g\tmax=%g\tavg=%g\n", reduglbtab[0], reduglbtab[1], reduglbtab[2] / (double) procglbnbr, reduglbtab[3], reduglbtab[4], reduglbtab[5] / (double) procglbnbr, reduglbtab[6], reduglbtab[7], reduglbtab[8] / (double) procglbnbr); } #ifdef COMMON_MEMORY_TRACE if ((flagval & C_FLAGVERBMEM) != 0) fprintf (C_filepntrlogout, "A\tMemory\tmin=%g\tmax=%g\tavg=%g\n", reduglbtab[9], reduglbtab[10], reduglbtab[11] / (double) procglbnbr); #endif /* COMMON_MEMORY_TRACE */ } if (flagval & C_FLAGVERBMAP) SCOTCH_dgraphMapView (&grafdat, &mappdat, C_filepntrlogout); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_dgraphMapExit (&grafdat, &mappdat); SCOTCH_dgraphExit (&grafdat); SCOTCH_stratExit (&stradat); SCOTCH_archExit (&archdat); MPI_Finalize (); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } /* Reduction routine for statistics output. */ void dgmapStatReduceOp ( double * in, double * inout, int * len, MPI_Datatype * datatype) { int i; for (i = 0; i < *len; i ++) { inout[3 * i] = MIN (in[3 * i], inout[3 * i]); inout[3 * i + 1] = MAX (in[3 * i + 1], inout[3 * i + 1]); inout[3 * i + 2] = in[3 * i + 2] + inout[3 * i + 2]; } } scotch-5.1.12b.dfsg/src/scotch/mord.c0000644000175300017530000003003111611563204017544 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mord.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a mesh reordering software. **/ /** This module contains the main function. **/ /** **/ /** DATES : # Version 4.0 : from : 15 nov 2002 **/ /** to : 06 jan 2006 **/ /** # Version 5.0 : from : 22 jan 2008 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 08 sep 2008 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MORD #include "module.h" #include "common.h" #include "scotch.h" #include "mord.h" /* ** The static and global definitions. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* File array */ { "-", NULL, "r" }, { "-", NULL, "w" }, { "-", NULL, "w" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "mord [ [ []]] ", " -c : Choose default ordering strategy according to one or several of :", " b : enforce load balance as much as possible", " q : privilege quality over speed (default)", " s : privilege speed over quality", " t : enforce safety", " -h : Display this help", " -m : Save column block mapping data to ", " -o : Use mesh ordering strategy (see user's manual)", " (see default strategy with option '-vs')", " -t : Save partitioning tree data to ", " -V : Print program version and copyright", " -v : Set verbose mode to :", " s : strategy information", " t : timing information", NULL }; /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ int main ( int argc, char * argv[]) { SCOTCH_Num vnodnbr; /* Number of nodes */ SCOTCH_Mesh meshdat; /* Source graph */ SCOTCH_Ordering ordedat; /* Graph ordering */ SCOTCH_Num * permtab; /* Permutation array */ SCOTCH_Strat stradat; /* Ordering strategy */ SCOTCH_Num straval; char * straptr; int flagval; Clock runtime[2]; /* Timing variables */ int i, j; errorProg ("mord"); intRandInit (); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } flagval = C_FLAGNONE; /* Default behavior */ straval = 0; /* No strategy flags */ straptr = NULL; SCOTCH_stratInit (&stradat); for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'C' : case 'c' : /* Strategy selection parameters */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'B' : case 'b' : straval |= SCOTCH_STRATBALANCE; break; case 'Q' : case 'q' : straval |= SCOTCH_STRATQUALITY; break; case 'S' : case 's' : straval |= SCOTCH_STRATSPEED; break; case 'T' : case 't' : straval |= SCOTCH_STRATSAFETY; break; default : errorPrint ("main: invalid strategy selection option '%c'", argv[i][j]); } } break; case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'M' : /* Output separator mapping */ case 'm' : flagval |= C_FLAGMAPOUT; if (argv[i][2] != '\0') C_filenamemapout = &argv[i][2]; break; case 'O' : /* Ordering strategy */ case 'o' : straptr = &argv[i][2]; SCOTCH_stratExit (&stradat); SCOTCH_stratInit (&stradat); if ((SCOTCH_stratMeshOrder (&stradat, straptr)) != 0) { errorPrint ("main: invalid ordering strategy"); return (1); } break; case 'V' : fprintf (stderr, "mord, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); break; case 'v' : /* Output control info */ for (j = 2; argv[i][j] != '\0'; j ++) { switch (argv[i][j]) { case 'S' : case 's' : flagval |= C_FLAGVERBSTR; break; case 'T' : case 't' : flagval |= C_FLAGVERBTIM; break; default : errorPrint ("main: unprocessed parameter '%c' in '%s'", argv[i][j], argv[i]); return (1); } } break; default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ clockInit (&runtime[0]); clockStart (&runtime[0]); SCOTCH_meshInit (&meshdat); /* Create mesh structure */ SCOTCH_meshLoad (&meshdat, C_filepntrsrcinp, -1); /* Read source mesh */ SCOTCH_meshSize (&meshdat, NULL, &vnodnbr, NULL); /* Get number of nodes */ if (straval != 0) { if (straptr != NULL) errorPrint ("main: options '-c' and '-o' are exclusive"); SCOTCH_stratMeshOrderBuild (&stradat, straval, 0.1); } clockStop (&runtime[0]); /* Get input time */ clockInit (&runtime[1]); clockStart (&runtime[1]); if ((permtab = (SCOTCH_Num *) memAlloc (vnodnbr * sizeof (SCOTCH_Num))) == NULL) { errorPrint ("main: out of memory"); return (1); } SCOTCH_meshOrderInit (&meshdat, &ordedat, permtab, NULL, NULL, NULL, NULL); /* Create ordering */ SCOTCH_meshOrderCompute (&meshdat, &ordedat, &stradat); /* Perform ordering */ clockStop (&runtime[1]); /* Get ordering time */ #ifdef SCOTCH_DEBUG_ALL if (SCOTCH_meshOrderCheck (&meshdat, &ordedat) != 0) return (1); #endif /* SCOTCH_DEBUG_ALL */ clockStart (&runtime[0]); SCOTCH_meshOrderSave (&meshdat, &ordedat, C_filepntrordout); /* Write ordering */ if (flagval & C_FLAGMAPOUT) /* If mapping wanted */ SCOTCH_meshOrderSaveMap (&meshdat, &ordedat, C_filepntrmapout); /* Write mapping */ clockStop (&runtime[0]); /* Get output time */ if (flagval & C_FLAGVERBSTR) { fprintf (C_filepntrlogout, "S\tStrat="); SCOTCH_stratSave (&stradat, C_filepntrlogout); putc ('\n', C_filepntrlogout); } if (flagval & C_FLAGVERBTIM) { fprintf (C_filepntrlogout, "T\tOrder\t\t%g\nT\tI/O\t\t%g\nT\tTotal\t\t%g\n", (double) clockVal (&runtime[1]), (double) clockVal (&runtime[0]), (double) clockVal (&runtime[0]) + (double) clockVal (&runtime[1])); } fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ SCOTCH_meshOrderExit (&meshdat, &ordedat); SCOTCH_stratExit (&stradat); SCOTCH_meshExit (&meshdat); memFree (permtab); #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } /*******************************************/ /* */ /* Stubs to avoid including target module. */ /* */ /*******************************************/ SCOTCH_Num T_domWght ( const void * const arch, const void * const dom) { errorPrint ("T_domWghtMord: internal error"); return (1); } SCOTCH_Num _SCOTCHTdomWght ( const void * const arch, const void * const dom) { errorPrint ("T_domWghtMord: internal error"); return (1); } SCOTCH_Num T_domDist ( const void * const arch, const void * const dom0, const void * const dom1) { errorPrint ("T_domDistMord: internal error"); return (1); } SCOTCH_Num _SCOTCHTdomDist ( const void * const arch, const void * const dom0, const void * const dom1) { errorPrint ("T_domDistMord: internal error"); return (1); } scotch-5.1.12b.dfsg/src/scotch/gtst.c0000644000175300017530000001771211611563204017577 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gtst.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This program gives statistics on source **/ /** graphs. **/ /** **/ /** DATES : # Version 2.0 : from : 31 oct 1994 **/ /** to 03 nov 1994 **/ /** # Version 3.0 : from : 15 sep 1995 **/ /** to 19 sep 1995 **/ /** # Version 3.2 : from : 03 jun 1997 **/ /** to : 25 may 1998 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to : 19 oct 1998 **/ /** # Version 3.4 : from : 10 oct 1999 **/ /** to 12 oct 1999 **/ /** # Version 4.0 : from : 10 sep 2003 **/ /** to : 10 sep 2003 **/ /** # Version 5.0 : from : 23 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GTST #include "module.h" #include "common.h" #include "scotch.h" #include "gtst.h" /* ** The static definitions. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* The file array */ { "-", NULL, "r" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "gtst [ []] ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ int main ( int argc, char * argv[]) { SCOTCH_Graph grafdat; /* Source graph */ SCOTCH_Num vertnbr; SCOTCH_Num velomin; SCOTCH_Num velomax; SCOTCH_Num velosum; double veloavg; double velodlt; SCOTCH_Num degrmin; SCOTCH_Num degrmax; double degravg; double degrdlt; SCOTCH_Num edgenbr; SCOTCH_Num edlomin; SCOTCH_Num edlomax; SCOTCH_Num edlosum; double edloavg; double edlodlt; int i; errorProg ("gtst"); if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); exit (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_fileNum < C_FILEARGNBR) /* File name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); exit (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); exit (0); case 'V' : fprintf (stderr, "gtst, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); exit (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ SCOTCH_graphInit (&grafdat); SCOTCH_graphLoad (&grafdat, C_filepntrsrcinp, -1, 0); SCOTCH_graphCheck (&grafdat); SCOTCH_graphSize (&grafdat, &vertnbr, &edgenbr); SCOTCH_graphStat (&grafdat, &velomin, &velomax, &velosum, &veloavg, &velodlt, °rmin, °rmax, °ravg, °rdlt, &edlomin, &edlomax, &edlosum, &edloavg, &edlodlt); if (C_filepntrdatout != NULL) { fprintf (C_filepntrdatout, "S\tVertex\tnbr=" SCOTCH_NUMSTRING "\n", (SCOTCH_Num) vertnbr); fprintf (C_filepntrdatout, "S\tVertex load\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", (SCOTCH_Num) velomin, (SCOTCH_Num) velomax, (SCOTCH_Num) velosum, veloavg, velodlt); fprintf (C_filepntrdatout, "S\tVertex degree\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", (SCOTCH_Num) degrmin, (SCOTCH_Num) degrmax, (SCOTCH_Num) edgenbr, degravg, degrdlt); fprintf (C_filepntrdatout, "S\tEdge\tnbr=" SCOTCH_NUMSTRING "\n", (SCOTCH_Num) (edgenbr / 2)); fprintf (C_filepntrdatout, "S\tEdge load\tmin=" SCOTCH_NUMSTRING "\tmax=" SCOTCH_NUMSTRING "\tsum=" SCOTCH_NUMSTRING "\tavg=%g\tdlt=%g\n", (SCOTCH_Num) edlomin, (SCOTCH_Num) edlomax, (SCOTCH_Num) edlosum, edloavg, edlodlt); } SCOTCH_graphExit (&grafdat); fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/gmk_m2.c0000644000175300017530000002776511611563204020003 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gmk_m2.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the source graph for 2D mesh **/ /** graphs. **/ /** **/ /** DATES : # Version 2.0 : from : 30 oct 1994 **/ /** to 08 nov 1994 **/ /** # Version 3.0 : from : 11 jul 1995 **/ /** to 02 oct 1995 **/ /** # Version 3.2 : from : 03 jun 1997 **/ /** to : 03 jun 1997 **/ /** # Version 3.3 : from : 06 oct 1998 **/ /** to : 06 oct 1998 **/ /** # Version 3.4 : from : 03 feb 2000 **/ /** to : 18 may 2004 **/ /** # Version 5.0 : from : 13 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /** NOTES : # The vertices of the (dX,dY) mesh are **/ /** numbered as terminals so that **/ /** t(0,0) = 0, t(1,0) = 1, **/ /** t(dX - 1, 0) = dX - 1, t(0,1) = dX, **/ /** and t(x,y) = (y * dX) + x. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GMK_M2 #include "module.h" #include "common.h" #include "scotch.h" #include "gmk_m2.h" /* ** The static definitions. */ static int C_paraNum = 0; /* Number of parameters */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* The file array */ { "-", NULL, "w" }, { "-", NULL, "w" } }; static const char * C_usageList[] = { "gmk_m2 [ []] ", " -b : Set base value for output (0 or 1)", " -e : Build a 8-neighbor grid rather than a 4-neighbor one", " -g : Output the geometry to ", " -h : Display this help", " -t : Build a torus rather than a mesh", " -V : Print program version and copyright", NULL }; /****************************************/ /* */ /* The main routine, which computes the */ /* source graph description. */ /* */ /****************************************/ int main ( int argc, char * argv[]) { int flagval; /* Process flags */ SCOTCH_Num baseval; /* Base value */ SCOTCH_Num d[2] = { 1, 1 }; /* Mesh dimensions */ SCOTCH_Num c[2]; /* Vertex coordinates */ int i; errorProg ("gmk_m2"); flagval = C_FLAGDEFAULT; /* Set default flags */ baseval = 0; if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < 2) { /* If number of parameters not reached */ if ((d[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get the dimension */ errorPrint ("main: invalid dimension '%s'", argv[i]); return (1); } continue; /* Process the other parameters */ } if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'B' : /* Set base value */ case 'b' : baseval = (SCOTCH_Num) atol (&argv[i][2]); if ((baseval < 0) || (baseval > 1)) { errorPrint ("main: invalid base value '" SCOTCH_NUMSTRING "'", (SCOTCH_Num) baseval); } break; case 'E' : /* Build a finite-element grid */ case 'e' : flagval |= C_FLAGELEM; break; case 'G' : /* Output the geometry */ case 'g' : flagval |= C_FLAGGEOOUT; if (argv[i][2] != '\0') C_filenamegeoout = &argv[i][2]; break; case 'H' : /* Give the usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'T' : /* Build a torus */ case 't' : flagval |= C_FLAGTORUS; break; case 'V' : fprintf (stderr, "gmk_m2, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ if (flagval & C_FLAGELEM) { /* Build a 8-neighbor grid */ errorPrint ("main: elements not supported"); return (1); } if (flagval & C_FLAGTORUS) { /* Build a torus */ fprintf (C_filepntrsrcout, "0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t000\n", (SCOTCH_Num) (d[0] * d[1]), /* Print number of vertices */ (SCOTCH_Num) ((4 * d[0] * d[1]) - /* Print number of edges (arcs) */ ((d[0] < 3) ? (2 * d[1]) : 0) - ((d[1] < 3) ? (2 * d[0]) : 0)), (SCOTCH_Num) baseval); for (c[1] = 0; c[1] < d[1]; c[1] ++) { /* Output neighbor list */ for (c[0] = 0; c[0] < d[0]; c[0] ++) { fprintf (C_filepntrsrcout, SCOTCH_NUMSTRING, (SCOTCH_Num) (((d[0] > 2) ? 3 : d[0]) + /* Output number of neighbors */ ((d[1] > 2) ? 3 : d[1]) - 2)); if (d[1] > 2) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, /* Output the neighbors */ (SCOTCH_Num) (((c[1] + d[1] - 1) % d[1]) * d[0] + c[0] + baseval)); if (d[0] > 2) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[1] * d[0] + (c[0] + d[0] - 1) % d[0]) + baseval)); if (d[0] > 1) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) (c[1] * d[0] + ((c[0] + 1) % d[0]) + baseval)); if (d[1] > 1) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) (((c[1] + 1) % d[1]) * d[0] + c[0] + baseval)); fprintf (C_filepntrsrcout, "\n"); } } } else { /* Build a mesh */ fprintf (C_filepntrsrcout, "0\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t000\n", (SCOTCH_Num) (d[0] * d[1]), (SCOTCH_Num) ((d[0] * d[1] * 2 - (d[0] + d[1])) * 2), (SCOTCH_Num) baseval); for (c[1] = 0; c[1] < d[1]; c[1] ++) { /* Output neighbor list */ for (c[0] = 0; c[0] < d[0]; c[0] ++) { fprintf (C_filepntrsrcout, "%d", ((c[0] == 0) ? 0 : 1) + /* Output number of neighbors */ ((c[0] == (d[0] - 1)) ? 0 : 1) + ((c[1] == 0) ? 0 : 1) + ((c[1] == (d[1] - 1)) ? 0 : 1)); if (c[1] != 0) /* Output the neighbors */ fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[1] - 1) * d[0] + c[0] + baseval)); if (c[0] != 0) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) (c[1] * d[0] + (c[0] - 1) + baseval)); if (c[0] != (d[0] - 1)) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) (c[1] * d[0] + (c[0] + 1) + baseval)); if (c[1] != (d[1] - 1)) fprintf (C_filepntrsrcout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[1] + 1) * d[0] + c[0] + baseval)); fprintf (C_filepntrsrcout, "\n"); } } } if (flagval & C_FLAGGEOOUT) { /* If geometry is wanted */ fprintf (C_filepntrgeoout, "2\n" SCOTCH_NUMSTRING "\n", /* Output geometry file header */ (SCOTCH_Num) (d[0] * d[1])); for (c[1] = 0; c[1] < d[1]; c[1] ++) { /* Output mesh coordinates */ for (c[0] = 0; c[0] < d[0]; c[0] ++) fprintf (C_filepntrgeoout, SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", (SCOTCH_Num) (c[1] * d[0] + c[0] + baseval), (SCOTCH_Num) c[0], (SCOTCH_Num) (d[1] - 1 - c[1])); } } fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/scotch/mcv.h0000644000175300017530000000700711611563204017404 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mcv.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a mesh file converter. **/ /** This module contains the data declara- **/ /** tions for the main module. **/ /** **/ /** DATES : # Version 4.0 : from : 19 jan 2004 **/ /** to : 19 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines */ /*+ File name aliases. +*/ #define C_FILENBR 3 /* Number of files in list */ #define C_FILEARGNBR 3 /* Number of files which can be arguments */ #define C_filenamesrcinp C_fileTab[0].name /* External mesh input file name */ #define C_filenamesrcout C_fileTab[1].name /* Source mesh output file name */ #define C_filenamegeoout C_fileTab[2].name /* Source mesh geometry file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* External mesh input file */ #define C_filepntrsrcout C_fileTab[1].pntr /* Source mesh output file */ #define C_filepntrgeoout C_fileTab[2].pntr /* Source mesh geometry file */ /* ** The type and structure definitions. */ /*+ This structure defines the method array element. +*/ typedef struct C_Format_ { char code; /* Format type code */ int (* func) (); /* Function to call */ } C_Format; scotch-5.1.12b.dfsg/src/scotch/gmk_msh.h0000644000175300017530000000653211611563204020246 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gmk_msh.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a mesh-to-graph converter. **/ /** This module contains the data declara- **/ /** tions for the main module. **/ /** **/ /** DATES : # Version 4.0 : from : 21 jan 2004 **/ /** to : 21 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines */ /*+ File name aliases. +*/ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 2 /* Number of files which can be arguments */ #define C_filenamemshinp C_fileTab[0].name /* External graph input file name */ #define C_filenamegrfout C_fileTab[1].name /* Source graph output file name */ #define C_filepntrmshinp C_fileTab[0].pntr /* External graph input file */ #define C_filepntrgrfout C_fileTab[1].pntr /* Source graph output file */ /* ** The type and structure definitions. */ /*+ This structure defines the method array element. +*/ typedef struct C_Format_ { char code; /* Format type code */ int (* func) (); /* Function to call */ } C_Format; scotch-5.1.12b.dfsg/src/scotch/gmk_m2.h0000644000175300017530000000753511611563204020001 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gmk_m2.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the data declara- **/ /** tions for the bidimensional mesh source **/ /** graph building program. **/ /** **/ /** DATES : # Version 2.0 : from : 30 oct 1994 **/ /** to 08 nov 1994 **/ /** # Version 3.0 : from : 11 jul 1995 **/ /** to 11 jul 1995 **/ /** # Version 3.2 : from : 03 jun 1997 **/ /** to : 03 jun 1997 **/ /** # Version 3.3 : from : 06 oct 1998 **/ /** to : 06 oct 1998 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 1 /* Number of files which can be arguments */ #define C_filenamesrcout C_fileTab[0].name /* Source graph output file name */ #define C_filenamegeoout C_fileTab[1].name /* Geometry graph output file name */ #define C_filepntrsrcout C_fileTab[0].pntr /* Source graph output file */ #define C_filepntrgeoout C_fileTab[1].pntr /* Geometry graph output file */ /*+ Process flags. +*/ #define C_FLAGGEOOUT 0x0001 /* Output the geometry graph */ #define C_FLAGTORUS 0x0002 /* Build a torus rather than a mesh */ #define C_FLAGELEM 0x0004 /* Build a 8-neighbor grid rather than a 4-neighbor one */ #define C_FLAGDEFAULT 0x0000 /* Default flags */ scotch-5.1.12b.dfsg/src/scotch/atst.h0000644000175300017530000000645511611563204017600 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : atst.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Target architecture graph analyzer. **/ /** **/ /** DATES : # Version 1.3 : from : 17 may 1994 **/ /** to : 17 may 1994 **/ /** # Version 2.0 : from : 11 nov 1994 **/ /** to : 11 nov 1994 **/ /** # Version 3.0 : from : 05 jul 1995 **/ /** to : 05 jul 1995 **/ /** # Version 3.2 : from : 01 jun 1997 **/ /** to : 01 jun 1997 **/ /** **/ /************************************************************/ /* ** The defines. */ /** File name aliases. **/ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 2 /* Number of files which can be arguments */ #define C_filenametgtinp C_fileTab[0].name /* Target graph input file name */ #define C_filenamelogout C_fileTab[1].name /* Statistics output file name */ #define C_filepntrtgtinp C_fileTab[0].pntr /* Target graph input file */ #define C_filepntrlogout C_fileTab[1].pntr /* Statistics output file */ scotch-5.1.12b.dfsg/src/scotch/dgord.h0000644000175300017530000001114111611563204017710 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgord.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER **/ /** **/ /** FUNCTION : Part of a parallel sparse matrix **/ /** ordering software. **/ /** This module contains the data declara- **/ /** tions for the main routine. **/ /** **/ /** DATES : # Version 5.0 : from : 30 apr 2006 **/ /** to : 27 may 2008 **/ /** # Version 5.1 : from : 22 nov 2008 **/ /** to : 22 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 5 /* Number of files in list */ #define C_FILEARGNBR 3 /* Number of files which can be arguments */ #define C_filenamesrcinp C_fileTab[0].name /* Source graph input file name */ #define C_filenameordout C_fileTab[1].name /* Ordering output file name */ #define C_filenamelogout C_fileTab[2].name /* Log file name */ #define C_filenamemapout C_fileTab[3].name /* Separator mapping file name */ #define C_filenametreout C_fileTab[4].name /* Separator tree file name */ #define C_filepntrsrcinp C_fileTab[0].pntr /* Source graph input file */ #define C_filepntrordout C_fileTab[1].pntr /* Ordering output file */ #define C_filepntrlogout C_fileTab[2].pntr /* Log file */ #define C_filepntrmapout C_fileTab[3].pntr /* Separator mapping file */ #define C_filepntrtreout C_fileTab[4].pntr /* Separator tre file */ /*+ Process flags. +*/ #define C_FLAGNONE 0x0000 /* No flags */ #define C_FLAGMAPOUT 0x0001 /* Output mapping data */ #define C_FLAGTREOUT 0x0002 /* Output separator tree data */ #define C_FLAGVERBSTR 0x0004 /* Output strategy string */ #define C_FLAGVERBTIM 0x0008 /* Output timing information */ #define C_FLAGVERBMEM 0x0010 /* Output memory information */ #define C_FLAGBLOCK 0x0020 /* Output block ordering */ #define C_FLAGDEBUG 0x0040 /* Debugging */ /* ** The function prototypes. */ void dgordStatReduceOp (double *, double *, int *, MPI_Datatype *); scotch-5.1.12b.dfsg/src/scotch/gmk_hy.h0000644000175300017530000000637711611563204020106 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gmk_hy.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the data declara- **/ /** tions for the hypercube source graph **/ /** building program. **/ /** **/ /** DATES : # Version 2.0 : from : 03 nov 1994 **/ /** to 03 nov 1994 **/ /** # Version 3.0 : from : 11 jul 1995 **/ /** to 11 jul 1995 **/ /** # Version 3.2 : from : 03 jun 1997 **/ /** to : 03 jun 1997 **/ /** # Version 3.3 : from : 06 oct 1998 **/ /** to : 06 oct 1998 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ File name aliases. +*/ #define C_FILENBR 1 /* Number of files in list */ #define C_FILEARGNBR 1 /* Number of files which can be arguments */ #define C_filenamesrcout C_fileTab[0].name /* Source graph output file name */ #define C_filepntrsrcout C_fileTab[0].pntr /* Source graph output file */ scotch-5.1.12b.dfsg/src/scotch/amk_p2.h0000644000175300017530000000630011611563204017763 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : amk_p2.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates the target architecture file **/ /** for a weighted path with two vertices **/ /** used to bipartition graphs in parts of **/ /** different sizes. **/ /** Here are the data declaration for the **/ /** target machine architecture functions. **/ /** **/ /** DATES : # Version 3.0 : from : 17 jul 1995 **/ /** to : 17 jul 1995 **/ /** # Version 3.2 : from : 02 jun 1997 **/ /** to : 02 jun 1997 **/ /** **/ /************************************************************/ /* ** The defines. */ /** File name aliases. **/ #define C_FILENBR 1 /* Number of files in list */ #define C_FILEARGNBR 1 /* Number of files which can be arguments */ #define C_filenametgtout C_fileTab[0].name /* Architecture output file name */ #define C_filepntrtgtout C_fileTab[0].pntr /* Architecture output file */ scotch-5.1.12b.dfsg/src/scotch/mmk_m2.c0000644000175300017530000002417511611563204020001 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mmk_m2.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Creates source meshes for tridimen- **/ /** sional finite element grids. **/ /** **/ /** DATES : # Version 4.0 : from : 26 sep 2002 **/ /** to : 06 feb 2003 **/ /** # Version 5.0 : from : 13 dec 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 01 jul 2010 **/ /** to : 14 feb 2011 **/ /** **/ /** NOTES : # The nodes and elements of the **/ /** (dX,dY) mesh are numbered so that **/ /** t(0,0) = 0, t(1,0) = 1, **/ /** t(dX - 1, 0) = dX - 1, t(0,1) = **/ /** dX, and t(x,y) = y * dX + x. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MMK_M2 #include "module.h" #include "common.h" #include "scotch.h" #include "mmk_m2.h" /* ** The static definitions. */ static int C_paraNum = 0; /* Number of parameters */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* The file array */ { "-", NULL, "w" }, { "-", NULL, "w" } }; static const int C_nghbTab[3] = { 4, 2, 1 }; static const char * C_usageList[] = { "mmk_m2 [ []] ", " -g : Output mesh geometry to ", " -h : Display this help", " -V : Print program version and copyright", NULL }; /****************************************/ /* */ /* The main routine, which computes the */ /* source mesh description. */ /* */ /****************************************/ int main ( int argc, char * argv[]) { SCOTCH_Num e[2] = { 1, 1 }; /* Mesh element dimensions */ SCOTCH_Num n[2]; /* Mesh node dimensions */ SCOTCH_Num c[2]; /* Vertex coordinates */ SCOTCH_Num velmnbr; /* First node number */ int flagval; /* Process flags */ int i; errorProg ("mmk_m2"); flagval = C_FLAGDEFAULT; /* Set default flags */ if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ usagePrint (stdout, C_usageList); return (0); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */ if (C_paraNum < 2) { /* If number of parameters not reached */ if ((e[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get the dimension */ errorPrint ("main: invalid dimension '%s'", argv[i]); return (1); } continue; /* Process the other parameters */ } if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { errorPrint ("main: too many file names given"); return (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'G' : /* Output mesh geometry */ case 'g' : flagval |= C_FLAGGEOOUT; if (argv[i][2] != '\0') C_filenamegeoout = &argv[i][2]; break; case 'H' : /* Give program usage message */ case 'h' : usagePrint (stdout, C_usageList); return (0); case 'V' : fprintf (stderr, "mmk_m2, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : errorPrint ("main: unprocessed option '%s'", argv[i]); return (1); } } } fileBlockOpen (C_fileTab, C_FILENBR); /* Open all files */ n[0] = e[0] + 1; n[1] = e[1] + 1; velmnbr = e[0] * e[1]; fprintf (C_filepntrmshout, "1\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n0\t" SCOTCH_NUMSTRING "\t000\n", /* Print mesh file header */ (SCOTCH_Num) velmnbr, (SCOTCH_Num) (n[0] * n[1]), (SCOTCH_Num) (((velmnbr + n[0] * n[1]) - (e[0] + e[1] + 1)) * 4), (SCOTCH_Num) velmnbr); for (c[1] = 0; c[1] < e[1]; c[1] ++) { /* Output element neighbor list */ for (c[0] = 0; c[0] < e[0]; c[0] ++) { fprintf (C_filepntrmshout, "4\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", /* Output neighbors of element */ (SCOTCH_Num) (c[1] * n[0] + c[0]), (SCOTCH_Num) (c[1] * n[0] + c[0] + 1), (SCOTCH_Num) ((c[1] + 1) * n[0] + c[0]), (SCOTCH_Num) ((c[1] + 1) * n[0] + c[0] + 1)); } } for (c[1] = 0; c[1] < n[1]; c[1] ++) { /* Output node neighbor list */ for (c[0] = 0; c[0] < n[0]; c[0] ++) { fprintf (C_filepntrmshout, "%d", /* Output number of neighboring elements */ C_nghbTab[(((c[0] != 0) && (c[0] != e[0])) ? 0 : 1) + (((c[1] != 0) && (c[1] != e[1])) ? 0 : 1)]); if (c[1] != 0) { /* Output neighbors of nodes */ if (c[0] != 0) fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[1] - 1) * e[0] + (c[0] - 1))); if (c[0] != e[0]) fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) ((c[1] - 1) * e[0] + c[0])); } if (c[1] != e[1]) { if (c[0] != 0) fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) (c[1] * e[0] + (c[0] - 1))); if (c[0] != e[0]) fprintf (C_filepntrmshout, "\t" SCOTCH_NUMSTRING, (SCOTCH_Num) (c[1] * e[0] + c[0])); } fprintf (C_filepntrmshout, "\n"); } } if (flagval & C_FLAGGEOOUT) { /* If geometry is wanted */ fprintf (C_filepntrgeoout, "2\n" SCOTCH_NUMSTRING "\n", /* Output geometry file header */ (SCOTCH_Num) (velmnbr + n[0] * n[1])); for (c[1] = 0; c[1] < e[1]; c[1] ++) { /* Output element coordinates */ for (c[0] = 0; c[0] < e[0]; c[0] ++) fprintf (C_filepntrgeoout, SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING ".5\t" SCOTCH_NUMSTRING ".5\n", (SCOTCH_Num) (c[1] * e[0] + c[0]), (SCOTCH_Num) c[0], (SCOTCH_Num) (e[1] - 1 - c[1])); } for (c[1] = 0; c[1] < n[1]; c[1] ++) { /* Output node coordinates */ for (c[0] = 0; c[0] < n[0]; c[0] ++) fprintf (C_filepntrgeoout, SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n", (SCOTCH_Num) (velmnbr + c[1] * n[0] + c[0]), (SCOTCH_Num) c[0], (SCOTCH_Num) (e[1] - c[1])); } } fileBlockClose (C_fileTab, C_FILENBR); /* Always close explicitely to end eventual (un)compression tasks */ #ifdef COMMON_PTHREAD pthread_exit ((void *) 0); /* Allow potential (un)compression tasks to complete */ #endif /* COMMON_PTHREAD */ return (0); } scotch-5.1.12b.dfsg/src/esmumps/0000755000175300017530000000000011464754444016666 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/src/esmumps/symbol_fax.c0000644000175300017530000006176710667023474021212 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : symbol_fax.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** Jean ROMAN (v0.0) **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** This is the generic block symbolic **/ /** factorization routine. **/ /** **/ /** DATES : # Version 0.0 : from : 22 jul 1998 **/ /** to 29 sep 1998 **/ /** # Version 0.1 : from : 04 apr 1999 **/ /** to 21 apr 1999 **/ /** # Version 0.2 : from : 08 may 2000 **/ /** to 09 may 2000 **/ /** # Version 1.0 : from : 13 mar 2002 **/ /** to 08 jun 2002 **/ /** # Version 1.2 : from : 23 aug 2002 **/ /** to 23 aug 2002 **/ /** # Version 2.0 : from : 21 mar 2003 **/ /** to 21 mar 2003 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #ifndef SYMBOL_FAX_INCLUDED /* If included from other file */ #define SYMBOL_FAX #include "common.h" #include "symbol.h" #include "order.h" #include "fax.h" #include "symbol_fax.h" #endif /* SYMBOL_FAX_INCLUDED */ /***********************************/ /* */ /* Symbolic factorization routine. */ /* */ /***********************************/ /*+ This routine computes the block symbolic *** factorization of the given matrix *** according to the given vertex ordering. *** It returns: *** - 0 : on success. *** - !0 : on error. *** Algorithm: *** The algorithm is implemented in a *** cache-friendly manner, by using a single *** dynamic array which grows along with the *** number of computed blocks. The array is *** decomposed in the following manner: *** - In a first phase, a hash table and a *** sort area are reserved at the end of *** the space of already computed blocks. *** The sort area is created far enough from *** the end of the array of already computed *** blocks such that if there are no contributing *** blocks all new blocks can be created without *** colliding with the sort area. *** - Then, in a second phase, if the current *** column block does have contributing column *** blocks, an area for simply-linked temporary *** blocks is reserved at least after the sort area, *** leaving enough space to create all of the *** corresponding potential new blocks *** just after all the blocks of the previous *** column block (right picture). *** ___________ *** |ccccccccccc| <- bloktab (bloktax) *** |ccccccccccc| *** |ccccccccccc| :ccccccccccc: *** |ccccccccccc| >- Computed blocks ----------< |ccccccccccc| *** |ccccccccccc| |ccccccccccc| *** |-----------| |:::::::::::| *** |hhhhhhhhhhh| <- hashtab = bloknum --------> |bcbcbcbcbcb| *** |hhhhhhhhhhh| | |cbcbcbcbcbc| *** |hhhhhhhhhhh| | |bcbcbcbcbcb| *** |hhhhhhhhhhh| | |cbcbcbcbcbc| *** |-----------| | |bcbcbcbcbcb| *** | | | |-----------| *** |-----------| <- sorttab...... ------------> | | *** |sssssssssss| | | *** |sssssssssss| | | *** |-----------| <- ............................| | *** | | tloktab -> |-----------| *** | | |ttttttttttt| *** | | |ttttttttttt| *** : : |-----------| *** :___________: :___________: *** <- bloktab + blokmax +*/ #ifndef SYMBOL_FAX_INCLUDED #define SYMBOL_FAX_ITERATOR(ngbdptr, vertnum, vertend) \ for (vertend = ngbfrst ((ngbdptr), (vertnum)); \ vertend >= baseval; \ vertend = ngbnext (ngbdptr)) { #define SYMBOL_FAX_VERTEX_DEGREE(ngbdptr, vertnum) \ (ngbdegr ((ngbdptr), (vertnum))) int symbolFax ( SymbolMatrix * const symbptr, /*+ Symbolic block matrix [based] +*/ const INT vertnbr, /*+ Number of vertices +*/ const INT edgenbr, /*+ Number of edges +*/ const INT baseval, /*+ Base value +*/ void * const ngbdptr, /*+ Neighbor bookkeeping area +*/ INT ngbfrst (void * const, const INT), /*+ First neighbor function +*/ INT ngbnext (void * const), /*+ Next neighbor function +*/ INT ngbdegr (void * const, const INT), /*+ Vertex degree function (upper bound) +*/ const Order * const ordeptr) /*+ Matrix ordering +*/ #endif /* SYMBOL_FAX_INCLUDED */ { INT vertnum; /* Vertex number of current column */ INT vertend; /* Current end vertex number */ const INT * restrict permtax; /* Based access to direct permutation array */ const INT * restrict peritax; /* Based access to inverse permutation array */ const INT * restrict rangtax; /* Based access to column block range array */ INT * restrict ctrbtax; /* Based access to array of contribution chains */ SymbolCblk * restrict cblktax; /* Based access to column block array */ INT cblknum; /* Based number of current column block */ INT cblkctr; /* Based number of current contributing column block */ SymbolBlok * restrict bloktax; /* Based access to block array */ INT bloknum; /* Based number of current first free block slot */ INT blokmax; /* Maximum number of blocks in array */ SymbolFaxTlok * restrict tloktab; /* Beginning of array of temporary blocks */ INT ctrbsum; /* Number of contributing blocks for column block */ INT * restrict sorttab; /* Beginning of sort area */ INT sortnbr; /* Number of vertices in sort area and hash table */ INT * restrict hashtab; /* Hash vertex table */ INT hashmsk; /* Mask for access to hash table */ INT colend; /* Column number of vertex neighbor */ permtax = ordeptr->permtab - baseval; /* Compute array bases */ peritax = ordeptr->peritab - baseval; rangtax = ordeptr->rangtab - baseval; blokmax = ordeptr->cblknbr * (2 + edgenbr / vertnbr) + 2; /* Estimate size of initial block array */ { /* Allocate arrays for factoring */ INT * ctrbtab; /* Array for contribution chaining */ SymbolCblk * cblktab; /* Column block array */ SymbolBlok * bloktab; /* Block array */ if (((ctrbtab = (INT *) memAlloc (ordeptr->cblknbr * sizeof (INT))) == NULL) || ((cblktab = (SymbolCblk *) memAlloc ((ordeptr->cblknbr + 1) * sizeof (SymbolCblk))) == NULL) || ((bloktab = (SymbolBlok *) memAlloc (blokmax * sizeof (SymbolBlok))) == NULL)) { errorPrint ("symbolFax: out of memory (1)"); if (ctrbtab != NULL) { if (cblktab != NULL) memFree (cblktab); memFree (ctrbtab); } return (1); } cblktax = cblktab - baseval; /* Set based accesses */ bloktax = bloktab - baseval; ctrbtax = ctrbtab - baseval; memset (ctrbtab, ~0, ordeptr->cblknbr * sizeof (INT)); /* Initialize column block contributions link array */ } bloknum = baseval; for (cblknum = baseval; cblknum < baseval + ordeptr->cblknbr; cblknum ++) { /* For all column blocks */ INT colnum; /* Number of current column [based] */ INT colmax; /* Maximum column index for current column block */ { /* Compute offsets and check for array size */ INT degrsum; INT hashsiz; INT hashmax; INT ctrbtmp; INT sortoft; /* Offset of sort array */ INT tlokoft; /* Offset of temporary block array */ INT tlndoft; /* Offset of end of temporary block array */ INT tlokmax; colnum = rangtax[cblknum]; colmax = rangtax[cblknum + 1]; /* Get maximum column value */ cblktax[cblknum].fcolnum = colnum; /* Set column block data */ cblktax[cblknum].lcolnum = colmax - 1; cblktax[cblknum].bloknum = bloknum; degrsum = 0; for ( ; colnum < colmax; colnum ++) /* For all columns */ degrsum += SYMBOL_FAX_VERTEX_DEGREE (ngbdptr, peritax[colnum]); /* Add column degrees */ for (hashmax = 256; hashmax < degrsum; hashmax *= 2) ; /* Get upper bound on hash table size */ hashsiz = hashmax << 2; /* Fill hash table at 1/4 of capacity */ hashmsk = hashsiz - 1; for (ctrbsum = 0, ctrbtmp = ctrbtax[cblknum]; /* Follow chain of contributing column blocks */ ctrbtmp != ~0; ctrbtmp = ctrbtax[ctrbtmp]) ctrbsum += cblktax[ctrbtmp + 1].bloknum - cblktax[ctrbtmp].bloknum - 2; /* Sum contributing column blocks */ tlokmax = degrsum + ctrbsum; sortoft = tlokmax * sizeof (SymbolBlok); if ((hashsiz * sizeof (INT)) > sortoft) /* Compute offset of sort area */ sortoft = (hashsiz * sizeof (INT)); tlokoft = sortoft + degrsum * sizeof (INT); /* Compute offset of temporary block area */ tlndoft = tlokoft + tlokmax * sizeof (SymbolFaxTlok); /* Compute end of area */ if (((byte *) (bloktax + bloknum) + tlndoft) > /* If not enough room */ ((byte *) (bloktax + blokmax))) { SymbolBlok * bloktmp; /* Temporary pointer for array resizing */ do blokmax = blokmax + (blokmax >> 2) + 4; /* Increase block array size by 25% as long as it does not fit */ while (((byte *) (bloktax + bloknum) + tlndoft) > ((byte *) (bloktax + blokmax))); if ((bloktmp = (SymbolBlok *) memRealloc (bloktax + baseval, (blokmax * sizeof (SymbolBlok)))) == NULL) { errorPrint ("symbolFax: out of memory (2)"); memFree (bloktax + baseval); memFree (cblktax + baseval); memFree (ctrbtax + baseval); return (1); } bloktax = bloktmp - baseval; } hashtab = (INT *) (bloktax + bloknum); sorttab = (INT *) ((byte *) hashtab + sortoft); tloktab = (SymbolFaxTlok *) ((byte *) hashtab + tlokoft); memset (hashtab, ~0, hashsiz * sizeof (INT)); /* Initialize hash table */ } sortnbr = 0; /* No vertices yet */ for (colnum = rangtax[cblknum]; colnum < colmax; colnum ++) { /* For all columns */ INT hashnum; vertnum = peritax[colnum]; /* Get associated vertex */ SYMBOL_FAX_ITERATOR (ngbdptr, vertnum, vertend) /* For all adjacent edges */ colend = permtax[vertend]; /* Get end column number */ if (colend < colmax) /* If end vertex number in left columns */ continue; /* Skip to next neighbor */ for (hashnum = (colend * SYMBOL_FAX_HASHPRIME) & hashmsk; ; /* Search end column in hash table */ hashnum = (hashnum + 1) & hashmsk) { INT * hashptr; hashptr = hashtab + hashnum; /* Point to hash slot */ if (*hashptr == colend) /* If end column in hash table */ break; /* Skip to next end column */ if (*hashptr == ~0) { /* If slot is empty */ *hashptr = colend; /* Set column in hash table */ sorttab[sortnbr ++] = colend; /* Add end column to sort array */ break; } } } /* End of loop on neighbors */ } /* End of loop on columns */ intSort1asc1 (sorttab, sortnbr); /* Sort neighbor array */ cblkctr = cblknum; if (ctrbtax[cblknum] == ~0) { /* If column is not to be updated */ INT sortnum; bloktax[bloknum].frownum = cblktax[cblknum].fcolnum; /* Build diagonal block */ bloktax[bloknum].lrownum = cblktax[cblknum].lcolnum; bloktax[bloknum].cblknum = cblknum; bloktax[bloknum].levfval = 0; bloknum ++; for (sortnum = 0; sortnum < sortnbr; ) { /* For all entries in sorted array */ INT colend; /* Column number of current entry */ colend = sorttab[sortnum]; if (colend >= rangtax[cblkctr + 1]) { /* If column block number to be found */ INT cblktmm; /* Median value */ INT cblktmx; /* Maximum value */ for (cblkctr ++, /* Find new column block by dichotomy */ cblktmx = ordeptr->cblknbr + baseval; cblktmx - cblkctr > 1; ) { cblktmm = (cblktmx + cblkctr) >> 1; if (rangtax[cblktmm] <= colend) cblkctr = cblktmm; else cblktmx = cblktmm; } } bloktax[bloknum].frownum = colend; /* Set beginning of new block */ while ((++ sortnum < sortnbr) && /* Scan extent of block */ (sorttab[sortnum] - 1 == sorttab[sortnum - 1]) && (sorttab[sortnum] < rangtax[cblkctr + 1])) ; bloktax[bloknum].lrownum = sorttab[sortnum - 1]; /* Set end of block */ bloktax[bloknum].cblknum = cblkctr; bloktax[bloknum].levfval = 0; bloknum ++; /* One more block */ } } else { /* Column will be updated */ INT sortnum; /* Current index in sort array */ INT tloknum; /* Current index on temporary block */ INT tlokfre; /* Index of first free block */ tloktab->frownum = cblktax[cblknum].fcolnum; /* Build diagonal chained block */ tloktab->lrownum = cblktax[cblknum].lcolnum; tloktab->cblknum = cblknum; tloktab->nextnum = 1; tloknum = 1; for (sortnum = 0; sortnum < sortnbr; ) { /* For all entries in sorted array */ INT colend; /* Column number of current entry */ colend = sorttab[sortnum]; if (colend >= rangtax[cblkctr + 1]) { /* If column block number to be found */ INT cblktmm; /* Median value */ INT cblktmx; /* Maximum value */ for (cblkctr ++, /* Find new column block by dichotomy */ cblktmx = ordeptr->cblknbr + baseval; cblktmx - cblkctr > 1; ) { cblktmm = (cblktmx + cblkctr) >> 1; if (rangtax[cblktmm] <= colend) cblkctr = cblktmm; else cblktmx = cblktmm; } } tloktab[tloknum].frownum = colend; /* Set beginning of new block */ while ((++ sortnum < sortnbr) && /* Scan extent of block */ (sorttab[sortnum] - 1 == sorttab[sortnum - 1]) && (sorttab[sortnum] < rangtax[cblkctr + 1])) ; tloktab[tloknum].lrownum = sorttab[sortnum - 1]; /* Set end of block */ tloktab[tloknum].cblknum = cblkctr; tloktab[tloknum].nextnum = tloknum + 1; /* Chain block */ tloknum = tloknum + 1; } tloktab[tloknum].frownum = /* Build trailing block */ tloktab[tloknum].lrownum = vertnbr + baseval; tloktab[tloknum].cblknum = ordeptr->cblknbr + baseval; tloktab[tloknum].nextnum = 0; /* Set end of chain (never chain to diagonal block) */ tlokfre = ++ tloknum; /* Build free chain for possible contributing blocks */ for ( ; tloknum < tlokfre + ctrbsum; tloknum = tloknum + 1) tloktab[tloknum].nextnum = tloknum + 1; tloktab[tloknum].nextnum = ~0; /* Set end of free chain */ for (cblkctr = ctrbtax[cblknum]; cblkctr != ~0; cblkctr = ctrbtax[cblkctr]) { /* Follow chain */ INT blokctr; /* Current index of contributing column block */ INT tloklst; /* Index of previous temporary block */ tloklst = 0; /* Previous is diagonal block */ tloknum = 0; /* Current is diagonal block */ for (blokctr = cblktax[cblkctr].bloknum + 2; /* For all blocks in contributing column block */ blokctr < cblktax[cblkctr + 1].bloknum; blokctr ++) { while ((tloktab[tloknum].cblknum < bloktax[blokctr].cblknum) || /* Skip unmatched chained blocks */ (tloktab[tloknum].lrownum < bloktax[blokctr].frownum - 1)) { tloklst = tloknum; tloknum = tloktab[tloknum].nextnum; } if ((bloktax[blokctr].cblknum < tloktab[tloknum].cblknum) || /* If contributing block has no mate */ (bloktax[blokctr].lrownum < tloktab[tloknum].frownum - 1)) { INT tloktmp; #ifdef FAX_DEBUG if (tlokfre == ~0) { errorPrint ("symbolFax: internal error (1)"); memFree (bloktax + baseval); memFree (cblktax + baseval); memFree (ctrbtax + baseval); return (1); } #endif /* FAX_DEBUG */ tloktmp = tloktab[tloklst].nextnum = tlokfre; /* Chain new block */ tloktab[tlokfre].frownum = bloktax[blokctr].frownum; /* Copy block data */ tloktab[tlokfre].lrownum = bloktax[blokctr].lrownum; tloktab[tlokfre].cblknum = bloktax[blokctr].cblknum; tlokfre = tloktab[tlokfre].nextnum; tloktab[tloktmp].nextnum = tloknum; /* Complete chainimg */ tloknum = tloktab[tloklst].nextnum; /* Resume from new block */ continue; /* Process next block */ } if ((bloktax[blokctr].lrownum >= tloktab[tloknum].frownum - 1) && /* Update chained block lower bound */ (bloktax[blokctr].frownum < tloktab[tloknum].frownum)) tloktab[tloknum].frownum = bloktax[blokctr].frownum; if ((bloktax[blokctr].frownum <= tloktab[tloknum].lrownum + 1) && /* Update chained block upper bound */ (bloktax[blokctr].lrownum > tloktab[tloknum].lrownum)) { INT tloktmp; tloktab[tloknum].lrownum = bloktax[blokctr].lrownum; for (tloktmp = tloktab[tloknum].nextnum; /* Aggregate following chained blocks */ (tloktab[tloktmp].cblknum == tloktab[tloknum].cblknum) && (tloktab[tloktmp].frownum <= tloktab[tloknum].lrownum + 1); tloktmp = tloktab[tloknum].nextnum) { if (tloktab[tloktmp].lrownum > tloktab[tloknum].lrownum) /* Merge aggregated block */ tloktab[tloknum].lrownum = tloktab[tloktmp].lrownum; tloktab[tloknum].nextnum = tloktab[tloktmp].nextnum; /* Unlink aggregated block */ tloktab[tloktmp].nextnum = tlokfre; tlokfre = tloktmp; } } } } for (tloknum = 0; /* For all chained blocks */ tloktab[tloknum].nextnum != 0; /* Until trailer block is reached */ tloknum = tloktab[tloknum].nextnum, bloknum ++) { /* Copy block data to block array */ bloktax[bloknum].frownum = tloktab[tloknum].frownum; bloktax[bloknum].lrownum = tloktab[tloknum].lrownum; bloktax[bloknum].cblknum = tloktab[tloknum].cblknum; bloktax[bloknum].levfval = 0; } } if ((bloknum - cblktax[cblknum].bloknum) > 2) { /* If more than one extra-diagonal blocks exist */ ctrbtax[cblknum] = ctrbtax[bloktax[cblktax[cblknum].bloknum + 1].cblknum]; /* Link contributing column blocks */ ctrbtax[bloktax[cblktax[cblknum].bloknum + 1].cblknum] = cblknum; } } cblktax[cblknum].fcolnum = /* Set last column block data */ cblktax[cblknum].lcolnum = vertnbr + baseval; cblktax[cblknum].bloknum = bloknum; memFree (ctrbtax + baseval); /* Free contribution link array */ symbptr->baseval = baseval; /* Fill in matrix fields */ symbptr->cblknbr = ordeptr->cblknbr; symbptr->bloknbr = bloknum - baseval; symbptr->cblktab = cblktax + baseval; symbptr->bloktab = memRealloc (bloktax + baseval, (bloknum - baseval) * sizeof (SymbolBlok)); /* Set array to its exact size */ symbptr->nodenbr = vertnbr; #ifdef FAX_DEBUG if (symbolCheck (symbptr) != 0) { errorPrint ("symbolFax: internal error (2)"); symbolExit (symbptr); return (1); } #endif /* FAX_DEBUG */ return (0); } scotch-5.1.12b.dfsg/src/esmumps/symbol.h0000644000175300017530000002230311464753706020344 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : symbol.h **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** David GOUDIN (v0.0) **/ /** Pascal HENON (v0.0) **/ /** Pierre RAMET (v0.0) **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** These lines are the data declarations **/ /** for the symbolic matrix. **/ /** **/ /** DATES : # Version 0.0 : from : 22 jul 1998 **/ /** to 07 oct 1998 **/ /** # Version 0.1 : from : 21 mar 2002 **/ /** to 21 mar 2002 **/ /** # Version 1.0 : from : 03 jun 2002 **/ /** to 26 jun 2002 **/ /** # Version 1.3 : from : 10 apr 2003 **/ /** to 10 jun 2003 **/ /** # Version 3.0 : from : 28 feb 2004 **/ /** to 03 mar 2005 **/ /** # Version 5.1 : from : 05 nov 2010 **/ /** to 05 nov 2010 **/ /** **/ /************************************************************/ #define SYMBOL_H #define SYMBOL_VERSION 1 /* ** The type and structure definitions. */ /*+ The column block structure. +*/ typedef struct SymbolCblk_ { INT fcolnum; /*+ First column index +*/ INT lcolnum; /*+ Last column index (inclusive) +*/ INT bloknum; /*+ First block in column (diagonal) +*/ } SymbolCblk; /*+ The column block structure. +*/ typedef struct SymbolBlok_ { INT frownum; /*+ First row index +*/ INT lrownum; /*+ Last row index (inclusive) +*/ INT cblknum; /*+ Facing column block +*/ INT levfval; /*+ Level-of-fill value +*/ } SymbolBlok; /*+ The symbolic block matrix. +*/ typedef struct SymbolMatrix_ { INT baseval; /*+ Base value for numberings +*/ INT cblknbr; /*+ Number of column blocks +*/ INT bloknbr; /*+ Number of blocks +*/ SymbolCblk * cblktab; /*+ Array of column blocks [+1,based] +*/ SymbolBlok * bloktab; /*+ Array of blocks [based] +*/ INT nodenbr; /*+ Number of nodes in matrix +*/ } SymbolMatrix; /*+ The type of cost computations. +*/ typedef enum SymbolCostType_ { SYMBOLCOSTLDLT /*+ Crout (i.e. LDLt) cost function +*/ } SymbolCostType; /* Structure for keeping track of selected blocks in the matrix pattern. The values of the tables are the remaining values for the yet unselected blocks. */ typedef struct SymbolKeepBlok_ { INT levfval; /*+ Values for incomplete factorisation +*/ INT nupdval; INT ctrival; INT ctroval; INT hghtval; } SymbolKeepBlok; typedef struct SymbolKeep_ { INT levfmax; /*+ Maximum values for incomplete fax +*/ INT nupdmax; INT ctrimax; INT ctromax; INT hghtmax; byte * keeptab; /*+ Flag array for kept blocks +*/ SymbolKeepBlok * kblktab; /*+ Block parameter array +*/ double * levftab; /*+ Area arrays for selected blocks +*/ double * nupdtab; double * ctritab; double * ctrotab; double * hghttab; } SymbolKeep; /* ** The function prototypes. */ #ifndef SYMBOL #define static #endif int symbolInit (SymbolMatrix * const symbptr); void symbolExit (SymbolMatrix * const symbptr); void symbolRealloc (SymbolMatrix * const symbptr); int symbolLoad (SymbolMatrix * const symbptr, FILE * const stream); int symbolSave (const SymbolMatrix * const symbptr, FILE * const stream); int symbolCheck (const SymbolMatrix * const symbptr); int symbolDraw (const SymbolMatrix * const symbptr, FILE * const stream); int symbolDrawFunc (const SymbolMatrix * const symbptr, int (*) (const SymbolMatrix * const, const SymbolBlok * const, void * const, float * const), int (*) (const SymbolMatrix * const, const SymbolBlok * const, void * const, float * const), void * const, FILE * const stream); void symbolDrawColor (const INT labl, float * const coloptr); #ifdef DOF_H int symbolCost (const SymbolMatrix * const symbptr, const Dof * const deofptr, const SymbolCostType typeval, double * const nnzptr, double * const opcptr); int symbolCosti (const SymbolMatrix * const symbptr, const Dof * const deofptr, const SymbolCostType typeval, const INT levfval, double * const nnzptr, double * const opcptr); int symbolLevf (const SymbolMatrix * const symbptr, INT * const levfmax, INT ** const levftab); int symbolTree (const SymbolMatrix * const symbptr, const Dof * const deofptr, INT * const leafnbr, INT * const heigmin, INT * const heigmax, double * const heigavg, double * const heigdlt); int symbolNonzeros (const SymbolMatrix * const symbptr, FILE * const stream); #endif /* DOF_H */ int symbolKeepInit (SymbolKeep * restrict const keepptr, const SymbolMatrix * const symbptr); void symbolKeepExit (SymbolKeep * restrict const keepptr); void symbolKeepAdd (SymbolKeep * restrict const keepptr, const SymbolMatrix * const symbptr, int (* funcptr) (const SymbolKeepBlok * const, void * const), void * dataptr); void symbolKeepDel (SymbolKeep * restrict const keepptr, const SymbolMatrix * const symbptr, int (* funcptr) (const SymbolKeepBlok * const, void * const), void * dataptr); int symbolKeepCompute (SymbolKeep * restrict const keepptr, const SymbolMatrix * const symbptr); int symbolKeepHisto (SymbolKeep * const keepptr, const SymbolMatrix * const, int (* funcptr) (const SymbolKeepBlok * const, void * const), void * dataptr); int symbolKeepPurge (SymbolKeep * restrict const keepptr, SymbolMatrix * restrict const symbptr); int symbolKeepView (const SymbolKeep * const keepptr, const double nnzlmax, const char * const nameptr); #undef static scotch-5.1.12b.dfsg/src/esmumps/Makefile0000644000175300017530000001072311413455232020314 0ustar hazelscthazelsct## Copyright 2004,2007-2010 ENSEIRB, INRIA & CNRS ## ## This file is part of the Scotch software package for static mapping, ## graph partitioning and sparse matrix ordering. ## ## This software is governed by the CeCILL-C license under French law ## and abiding by the rules of distribution of free software. You can ## use, modify and/or redistribute the software under the terms of the ## CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ## URL: "http://www.cecill.info". ## ## As a counterpart to the access to the source code and rights to copy, ## modify and redistribute granted by the license, users are provided ## only with a limited warranty and the software's author, the holder of ## the economic rights, and the successive licensors have only limited ## liability. ## ## In this respect, the user's attention is drawn to the risks associated ## with loading, using, modifying and/or developing or reproducing the ## software by the user in light of its specific status of free software, ## that may mean that it is complicated to manipulate, and that also ## therefore means that it is reserved for developers and experienced ## professionals having in-depth computer knowledge. Users are therefore ## encouraged to load and test the software's suitability as regards ## their requirements in conditions enabling the security of their ## systems and/or data to be ensured and, more generally, to use and ## operate it in the same conditions as regards security. ## ## The fact that you are presently reading this means that you have had ## knowledge of the CeCILL-C license and that you accept its terms. ## bindir = ../../bin includedir = ../../include libdir = ../../lib ## ## General inference rules. ## include ../Makefile.inc %$(OBJ) : %.c $(CC) $(CFLAGS) $(CLIBFLAGS) -I$(includedir) -c $(<) -o $(@) %$(EXE) : %.c $(CC) $(CFLAGS) -I$(includedir) $(<) -o $(@) -L$(libdir) $(LDFLAGS) -L. -l$(ESMUMPSLIB) -l$(SCOTCHLIB) -l$(SCOTCHLIB)errexit ## ## Project rules. ## .PHONY : ptscotch scotch ptinstall install clean realclean scotch : clean $(MAKE) CC="$(CCS)" CCD="$(CCS)" SCOTCHLIB=scotch ESMUMPSLIB=esmumps \ libesmumps$(LIB) \ main_esmumps$(EXE) ptscotch : clean $(MAKE) CFLAGS="$(CFLAGS) -DSCOTCH_PTSCOTCH" CC=$(CCP) SCOTCHLIB=ptscotch ESMUMPSLIB=ptesmumps \ libesmumps$(LIB) \ main_esmumps$(EXE) install : -$(CP) esmumps.h $(includedir) -$(CP) libesmumps$(LIB) $(libdir) ptinstall : -$(CP) esmumps.h $(includedir) -$(CP) libptesmumps$(LIB) $(libdir) clean : -$(RM) *~ common.h *$(OBJ) lib*$(LIB) main_esmumps$(EXE) realclean : clean ## ## Todo list. ## common.h : ../libscotch/common.h \ module.h $(CAT) $(^) > $(@) graph_graph$(OBJ) : graph_graph.c \ common.h \ $(includedir)/$(SCOTCHLIB).h \ graph.h order$(OBJ) : order.c \ order.h \ common.h \ graph.h order_scotch_graph$(OBJ) : order_scotch_graph.c \ order.h \ common.h \ graph.h \ $(includedir)/$(SCOTCHLIB).h dof$(OBJ) : dof.c \ dof.h \ common.h \ graph.h \ $(includedir)/$(SCOTCHLIB).h symbol$(OBJ) : symbol.c \ symbol.h \ common.h symbol_fax$(OBJ) : symbol_fax.c \ common.h \ graph.h \ symbol.h \ order.h \ fax.h symbol_fax_graph$(OBJ) : symbol_fax_graph.c \ symbol_fax.c \ common.h \ graph.h \ symbol.h \ order.h \ fax.h \ $(includedir)/$(SCOTCHLIB).h esmumps$(OBJ) : esmumps.c \ common.h \ graph.h \ symbol.h \ order.h \ fax.h \ esmumps.h \ $(includedir)/$(SCOTCHLIB).h esmumps_f$(OBJ) : esmumps_f.c \ common.h \ esmumps.h esmumps_strats$(OBJ) : esmumps_strats.c \ common.h \ esmumps.h libesmumps$(LIB) : graph_graph$(OBJ) \ order$(OBJ) \ order_scotch_graph$(OBJ) \ dof$(OBJ) \ symbol$(OBJ) \ symbol_fax_graph$(OBJ) \ esmumps$(OBJ) \ esmumps_f$(OBJ) \ esmumps_strats$(OBJ) $(AR) $(ARFLAGS) lib$(ESMUMPSLIB)$(LIB) $(?) -$(RANLIB) lib$(ESMUMPSLIB)$(LIB) main_esmumps$(EXE) : main_esmumps.c \ common.h \ graph.h \ order.h \ symbol.h \ esmumps.h \ lib$(ESMUMPSLIB)$(LIB) \ $(libdir)/lib$(SCOTCHLIB)$(LIB) \ $(libdir)/lib$(SCOTCHLIB)errexit$(LIB) scotch-5.1.12b.dfsg/src/esmumps/module.h0000644000175300017530000000737611136102550020316 0ustar hazelscthazelsct/* Copyright 2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : module.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This is the global configuration file **/ /** for the ESMUMPS library module. **/ /** **/ /** DATES : # Version 5.1 : from : 22 jan 2009 **/ /** to 22 jan 2009 **/ /** **/ /************************************************************/ #define MODULE_H /* ** Function renaming. */ #if ((! defined SCOTCH_COMMON_EXTERNAL) || (defined SCOTCH_COMMON_RENAME)) #define clockGet _SCOTCHclockGet #define fileNameDistExpand _SCOTCHfileNameDistExpand #define usagePrint _SCOTCHusagePrint #define errorPrint SCOTCH_errorPrint #define errorPrintW SCOTCH_errorPrintW #define errorProg SCOTCH_errorProg #define intLoad _SCOTCHintLoad #define intSave _SCOTCHintSave #define intAscn _SCOTCHintAscn #define intPerm _SCOTCHintPerm #define intRandReset _SCOTCHintRandReset #define intRandInit _SCOTCHintRandInit /* #define intRandVal _SCOTCHintRandVal Already a macro */ #define intSearchDicho _SCOTCHintSearchDicho #define intSort1asc1 _SCOTCHintSort1asc1 #define intSort2asc1 _SCOTCHintSort2asc1 #define intSort2asc2 _SCOTCHintSort2asc2 #define intSort3asc1 _SCOTCHintSort3asc1 #define memAllocGroup _SCOTCHmemAllocGroup #define memReallocGroup _SCOTCHmemReallocGroup #define memOffset _SCOTCHmemOffset #endif /* ((! defined SCOTCH_COMMON_EXTERNAL) || (defined SCOTCH_COMMON_RENAME)) */ scotch-5.1.12b.dfsg/src/esmumps/main_esmumps.c0000644000175300017530000001261311136130272021511 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : main_mumps.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This is the test module for the MUMPS **/ /** interface routine. **/ /** **/ /** DATES : # Version 0.0 : from : 17 may 2001 **/ /** to 17 may 2001 **/ /** # Version 1.0 : from : 17 jun 2005 **/ /** to 17 jun 2005 **/ /** # Version 5.1 : from : 22 jan 2009 **/ /** to 22 jan 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #include "common.h" #ifdef SCOTCH_PTSCOTCH #include "ptscotch.h" #else /* SCOTCH_PTSCOTCH */ #include "scotch.h" #endif /* SCOTCH_PTSCOTCH */ #include "graph.h" #include "esmumps.h" /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ int main (argc, argv) int argc; char * argv[]; { Graph grafdat; /* Graph to load */ INT vertnbr; INT * verttab; INT edgenbr; INT * edgetab; INT * lentab; INT * nvtab; INT * elentab; INT * lasttab; INT pfree; INT ncmpa; INT vertnum; FILE * stream; if (argc != 2) { errorPrint ("main_esmumps: usage: main_esmumps graph_file"); return (1); } graphInit (&grafdat); if ((stream = fopen (argv[1], "r")) == NULL) { errorPrint ("main_esmumps: cannot open graph file"); graphExit (&grafdat); return (1); } if (graphLoad (&grafdat, stream, 1, 3) != 0) { /* Base graph with base value 1, no loads */ errorPrint ("main_esmumps: cannot open graph file"); graphExit (&grafdat); return (1); } fclose (stream); graphData (&grafdat, NULL, &vertnbr, &verttab, NULL, NULL, NULL, &edgenbr, &edgetab, NULL); if ((lentab = (INT *) memAlloc (vertnbr * sizeof (INT))) == NULL) { errorPrint ("main_esmumps: out of memory (1)"); graphExit (&grafdat); return (1); } for (vertnum = 0; vertnum < vertnbr; vertnum ++) { if (verttab[vertnum] == verttab[vertnum + 1]) { lentab[vertnum] = 0; verttab[vertnum] = 0; /* Graph structure no longer valid in Emilio */ } else lentab[vertnum] = verttab[vertnum + 1] - verttab[vertnum]; } if (((nvtab = (INT *) memAlloc (vertnbr * sizeof (INT))) == NULL) || ((elentab = (INT *) memAlloc (vertnbr * sizeof (INT))) == NULL) || ((lasttab = (INT *) memAlloc (vertnbr * sizeof (INT))) == NULL)) { errorPrint ("main_esmumps: out of memory (2)"); if (nvtab != NULL) { if (elentab != NULL) memFree (elentab); memFree (nvtab); } graphExit (&grafdat); return (1); } pfree = edgenbr + 1; ESMUMPSF (&vertnbr, &edgenbr, verttab, &pfree, lentab, edgetab, nvtab, elentab, lasttab, &ncmpa); memFree (lasttab); memFree (elentab); memFree (nvtab); memFree (lentab); graphExit (&grafdat); if (ncmpa < 0) { errorPrint ("main_esmumps: error in ESMUMPSF (%d)", ncmpa); return (1); } exit (0); } scotch-5.1.12b.dfsg/src/esmumps/order.h0000644000175300017530000001350211413455724020144 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : order.h **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** These lines are the data declarations **/ /** for the graph ordering routine. **/ /** **/ /** DATES : # Version 0.0 : from : 22 aug 1998 **/ /** to 01 may 1999 **/ /** # Version 2.0 : from : 25 oct 2003 **/ /** to 02 jul 2010 **/ /** **/ /************************************************************/ #define ORDER_H /* ** The type and structure definitions. */ /*+ Ordering structure. vnodbas holds the base value for node indexings. vnodbas is equal to baseval for graphs, and to vnodbas for meshes. The same holds for rangtab, with rangtab[0] = vnodbas. +*/ typedef struct Order_ { INT cblknbr; /*+ Number of column blocks +*/ INT * rangtab; /*+ Column block range array [based,+1] +*/ INT * permtab; /*+ Permutation array [based] +*/ INT * peritab; /*+ Inverse permutation array [based] +*/ } Order; /* ** The function prototypes. */ #ifndef ORDER #define static #endif int orderInit (Order * const ordeptr); void orderExit (Order * const ordeptr); int orderLoad (Order * const ordeptr, FILE * const stream); int orderSave (const Order * const ordeptr, FILE * const stream); void orderBase (Order * restrict const ordeptr, const INT baseval); int orderCheck (const Order * const ordeptr); int orderGrid2 (Order * const ordeptr, const INT xnbr, const INT ynbr, const INT baseval, const INT xlim, const INT ylim); int orderGrid2C (Order * const ordeptr, const INT xnbr, const INT ynbr, const INT baseval, const INT xlim, const INT ylim); int orderGrid3 (Order * const ordeptr, const INT xnbr, const INT ynbr, const INT znbr, const INT baseval, const INT xlim, const INT ylim, const INT zlim); int orderGrid3C (Order * const ordeptr, const INT xnbr, const INT ynbr, const INT znbr, const INT baseval, const INT xlim, const INT ylim, const INT zlim); #ifdef GRAPH_H int orderGraph (Order * restrict const ordeptr, Graph * restrict const grafptr); int orderGraphList (Order * restrict const ordeptr, Graph * restrict const grafptr, const INT listnbr, const INT * restrict const listtab); int orderGraphStrat (Order * restrict const ordeptr, Graph * restrict const grafptr, const char * restrict const); int orderGraphListStrat (Order * restrict const ordeptr, Graph * restrict const grafptr, const INT listnbr, const INT * restrict const listtab, const char * const); #endif /* GRAPH_H */ #ifdef MESH_H int orderMesh (Order * restrict const ordeptr, Mesh * restrict const meshptr); int orderMeshList (Order * restrict const ordeptr, Mesh * restrict const meshptr, const INT listnbr, const INT * restrict const listtab); int orderMeshStrat (Order * restrict const ordeptr, Mesh * restrict const meshptr, const char * const); int orderMeshListStrat (Order * restrict const ordeptr, Mesh * restrict const meshptr, const INT listnbr, const INT * restrict const listtab, const char * const); #endif /* MESH_H */ #undef static scotch-5.1.12b.dfsg/src/esmumps/dof.c0000644000175300017530000001571711136130334017573 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dof.c **/ /** **/ /** AUTHORS : David GOUDIN **/ /** Pascal HENON **/ /** Francois PELLEGRINI **/ /** Pierre RAMET **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** These lines are the general purpose **/ /** routines for the DOF structure. **/ /** **/ /** DATES : # Version 0.0 : from : 07 oct 1998 **/ /** to 14 oct 1998 **/ /** # Version 3.0 : from : 28 feb 2004 **/ /** to 03 feb 2006 **/ /** # Version 5.1 : from : 22 jan 2009 **/ /** to 22 jan 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DOF #include "common.h" #ifdef SCOTCH_PTSCOTCH #include "ptscotch.h" #else /* SCOTCH_PTSCOTCH */ #include "scotch.h" #endif /* SCOTCH_PTSCOTCH */ #include "graph.h" #include "dof.h" /******************************/ /* */ /* The DOF handling routines. */ /* */ /******************************/ /*+ This routine initializes *** the given DOF structure. *** It returns: *** - 0 : in all cases. +*/ int dofInit ( Dof * const deofptr) { deofptr->baseval = 0; deofptr->nodenbr = 0; deofptr->noddval = 1; /* Set constant, non zero, number of DOFs */ deofptr->noddtab = NULL; return (0); } /*+ This routine frees the contents *** of the given DOF structure. *** It returns: *** - VOID : in all cases. +*/ void dofExit ( Dof * const deofptr) { if (deofptr->noddtab != NULL) memFree (deofptr->noddtab); #ifdef DOF_DEBUG dofInit (deofptr); #endif /* DOF_DEBUG */ } /*+ This routine sets the number of DOFs *** per node to a constant value. *** It returns: *** - VOID : in all cases. +*/ void dofConstant ( Dof * const deofptr, const INT baseval, const INT nodenbr, const INT noddval) { deofptr->baseval = baseval; deofptr->nodenbr = nodenbr; if (deofptr->noddtab != NULL) { /* If DOF array already allocated */ memFree (deofptr->noddtab); /* It is no longer of use */ deofptr->noddtab = NULL; } deofptr->noddval = noddval; } /*+ This routine builds the DOF index *** array from the graph vertex array. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int dofGraph ( Dof * const deofptr, /*+ DOF index array to build [based] +*/ const Graph * const grafptr, /*+ Matrix adjacency structure [based] +*/ const INT deofval, /*+ DOFs per node if no graph vertex load array +*/ const INT * const peritab) /*+ Inverse vertex->node permutation array +*/ { INT baseval; INT vertnbr; INT * velotab; INT edgenbr; SCOTCH_graphData (grafptr, &baseval, &vertnbr, NULL, NULL, &velotab, NULL, &edgenbr, NULL, NULL); deofptr->baseval = baseval; deofptr->nodenbr = vertnbr; if (velotab == NULL) { /* If no vertex weight (i.e. DOF) array */ deofptr->noddtab = NULL; /* No DOF array */ deofptr->noddval = deofval; /* Get node DOF value */ } else { /* Vertex load array present */ #ifdef DOF_CONSTANT deofptr->noddtab = NULL; /* No DOF array */ deofptr->noddval = deofval; #else /* DOF_CONSTANT */ const INT * restrict velotax; /* Based access to grafptr->velotab */ INT nodenum; /* Number of current node */ INT * noddtnd; /* Pointer to end of DOF index array */ INT * noddptr; /* Pointer to current DOF index */ const INT * periptr; deofptr->noddval = 0; /* DOF values are not constant */ if ((deofptr->noddtab = (INT *) memAlloc ((vertnbr + 1) * sizeof (INT))) == NULL) { errorPrint ("dofGraph: out of memory"); return (1); } for (noddptr = deofptr->noddtab, noddtnd = noddptr + vertnbr, periptr = peritab, nodenum = baseval, velotax = velotab - baseval; noddptr < noddtnd; noddptr ++, periptr ++) { *noddptr = nodenum; /* Set index to DOF array */ nodenum += velotax[*periptr]; /* Add number of DOFs for vertex */ } *noddptr = nodenum; /* Set end of DOF array */ #endif /* DOF_CONSTANT */ } return (0); } scotch-5.1.12b.dfsg/src/esmumps/esmumps.c0000644000175300017530000002043511136130317020506 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : esmumps.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains a MUMPS interface **/ /** for the ordering routines of the **/ /** libSCOTCH + Emilio libfax libraries. **/ /** **/ /** DATES : # Version 0.0 : from : 16 may 2001 **/ /** to 04 jun 2001 **/ /** # Version 0.1 : from : 13 feb 2002 **/ /** to 13 feb 2002 **/ /** # Version 1.0 : from : 06 dec 2004 **/ /** to 06 dec 2004 **/ /** # Version 5.1 : from : 22 jan 2009 **/ /** to 22 jan 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ESMUMPS #include "common.h" #ifdef SCOTCH_PTSCOTCH #include "ptscotch.h" #else /* SCOTCH_PTSCOTCH */ #include "scotch.h" #endif /* SCOTCH_PTSCOTCH */ #include "graph.h" #include "dof.h" #include "symbol.h" #include "order.h" #include "fax.h" #include "esmumps.h" /**************************************/ /* */ /* This routine acts as an interface */ /* between ordering software such as */ /* MUMPS and Scotch+Emilio. */ /* */ /**************************************/ /* Meaning of the parameters : ** - n : order of the system (that is, number of columns). ** - iwlen : not used. Here for compatibility. ** - pe : on input, position in array iw of the extra-diagonal ** terms for the considered column. ** on output, -pe(i) is the father of node i in the elimination ** tree if i is a principal variable, or it is the index of ** the principal variable if i is a secondary variable. ** - pfree : number of extra-diagonal terms for the considered ** node (that is, the number of arcs dans le graph for this ** vertex). ** - len : array holding the number of extra-diagonal terms for ** each column. ** - iw : array of extra-diagonal terms (preserved). ** - nv : on output, nv(i) = 0 if variable i is a secondary ** variable, else nv(i) is the number of columns that are ** merged into principal variable i. ** - elen : on output, direct permutation (for MUMPS; the ** meaning of the "direct" and "inverse" permutations is ** just the opposite for Scotch) : ** k=elen(i) <==> column i is the k-th pivot. ** - last : on output, inverse permutation (for MUMPS) : ** i=last(k) <==> column i est le k-th pivot */ int esmumps ( const INT n, const INT iwlen, /* Not used, just here for consistency */ INT * restrict const petab, const INT pfree, INT * restrict const lentab, INT * restrict const iwtab, INT * restrict const nvtab, INT * restrict const elentab, /* Permutations computed for debugging only */ INT * restrict const lasttab) /* Permutations computed for debugging only */ { INT baseval; /* Base value */ INT * restrict vendtab; /* Vertex end array */ Graph grafdat; /* Graph */ Order ordedat; /* Graph ordering */ SymbolMatrix symbdat; /* Block factored matrix */ Dof deofdat; /* Matrix DOF structure */ INT vertnum; INT cblknum; INT colnum; if ((vendtab = memAlloc (n * sizeof (INT))) == NULL) { errorPrint ("esmumps: out of memory"); return (1); } for (vertnum = 0; vertnum < n; vertnum ++) vendtab[vertnum] = petab[vertnum] + lentab[vertnum]; baseval = 1; /* Assume Fortran-based indexing */ graphInit (&grafdat); graphBuildGraph2 (&grafdat, baseval, n, pfree - 1, petab, vendtab, NULL, NULL, iwtab, NULL); dofInit (&deofdat); dofConstant (&deofdat, 1, n, 1); /* One DOF per node, Fortran-based indexing */ orderInit (&ordedat); orderGraph (&ordedat, &grafdat); /* Compute ordering with Scotch */ #ifdef ESMUMPS_DEBUG /* Permutations are output for debugging only */ memCpy (elentab, ordedat.permtab, n * sizeof (INT)); /* Copy permutations */ memCpy (lasttab, ordedat.peritab, n * sizeof (INT)); #endif /* ESMUMPS_DEBUG */ symbolInit (&symbdat); symbolFaxGraph (&symbdat, &grafdat, &ordedat); /* Compute block symbolic factorizaion */ for (cblknum = 0; cblknum < symbdat.cblknbr; cblknum ++) { /* For all column blocks */ INT degnbr; /* True degree of column block */ INT bloknum; for (bloknum = symbdat.cblktab[cblknum].bloknum, degnbr = 0; bloknum < symbdat.cblktab[cblknum + 1].bloknum; bloknum ++) degnbr += symbdat.bloktab[bloknum - baseval].lrownum - symbdat.bloktab[bloknum - baseval].frownum + 1; nvtab[ordedat.peritab[symbdat.cblktab[cblknum].fcolnum - baseval] - baseval] = degnbr; /* Set true block degree */ for (colnum = symbdat.cblktab[cblknum].fcolnum + 1; /* For all secondary variables */ colnum <= symbdat.cblktab[cblknum].lcolnum; colnum ++) { nvtab[ordedat.peritab[colnum - baseval] - baseval] = 0; /* Set nv = 0 and pe = - principal variable */ petab[ordedat.peritab[colnum - baseval] - baseval] = - ordedat.peritab[symbdat.cblktab[cblknum].fcolnum - baseval]; } if (symbdat.cblktab[cblknum].bloknum == /* If column block has no extra-diagonals */ symbdat.cblktab[cblknum + 1].bloknum - 1) /* Then mark block as root of subtree */ petab[ordedat.peritab[symbdat.cblktab[cblknum].fcolnum - baseval] - baseval] = 0; else petab[ordedat.peritab[symbdat.cblktab[cblknum].fcolnum - baseval] - baseval] = - ordedat.peritab[symbdat.cblktab[symbdat.bloktab[symbdat.cblktab[cblknum].bloknum + 1 - baseval].cblknum - baseval].fcolnum - baseval]; } symbolExit (&symbdat); orderExit (&ordedat); dofExit (&deofdat); graphExit (&grafdat); memFree (vendtab); return (0); } scotch-5.1.12b.dfsg/src/esmumps/graph.h0000644000175300017530000001000111136061533020112 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph.h **/ /** **/ /** AUTHORS : David GOUDIN **/ /** Pascal HENON **/ /** Francois PELLEGRINI **/ /** Pierre RAMET **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** These lines are the data declarations **/ /** for the graph structure. **/ /** **/ /** DATES : # Version 0.0 : from : 27 jul 1998 **/ /** to 24 jan 2004 **/ /** # Version 2.0 : from : 28 feb 2004 **/ /** to 23 apr 2004 **/ /** **/ /************************************************************/ #define GRAPH_H /* ** The defines. */ #define Graph SCOTCH_Graph #define graphInit SCOTCH_graphInit #define graphExit SCOTCH_graphExit #define graphLoad SCOTCH_graphLoad #define graphSave SCOTCH_graphSave #define graphBase SCOTCH_graphBase #define graphData SCOTCH_graphData #define graphCheck SCOTCH_graphCheck /* ** The function prototypes. */ #ifndef GRAPH #define static #endif int graphBuild (Graph * const grafptr, const INT baseval, const INT vertnbr, const INT edgenbr, void * const ngbdptr, INT nghbfrstfunc (void * const, const INT), INT nghbnextfunc (void * const)); int graphBuildGraph (Graph * const grafptr, const INT baseval, const INT vertnbr, const INT edgenbr, INT * restrict verttab, INT * restrict velotab, INT * restrict edgetab); int graphBuildGraph2 (Graph * const grafptr, const INT baseval, const INT vertnbr, const INT edgenbr, INT * restrict verttab, INT * restrict vendtab, INT * restrict velotab, INT * restrict vlbltab, INT * restrict edgetab, INT * restrict edlotab); #undef static scotch-5.1.12b.dfsg/src/esmumps/esmumps_strats.c0000644000175300017530000001432110753033505022110 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : esmumps_strats.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains defalut strategy **/ /** building routines for calling Scotch **/ /** from MUMPS. **/ /** **/ /** DATES : # Version 1.0 : from : 08 dec 2003 **/ /** to 08 dec 2003 **/ /** # Version 1.1 : from : 21 jun 2007 **/ /** to 21 jun 2007 **/ /** # Version 5.0 : from : 08 feb 2008 **/ /** to 08 feb 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ESMUMPS #include "common.h" #include "esmumps.h" /**************************************/ /* */ /* This routine creates a strategy */ /* string from the given parameters. */ /* */ /**************************************/ /* Meaning of the parameters : ** - procnbr : number of processors. ** - leafsiz : limit size in vertices of the leaf subgraphs. ** - leorval : type of halo ordering : 0 : HAMD; 1 : HAMF. ** - cminval : minimum number of column blocks. ** - cmaxval : maximum number of column blocks. ** - fratval : maximum fill ratio. ** - verbval : verbose flag if > 0. ** - stream : verbose stream. ** - straptr : pointer to character string of sufficient size ** to hold the resulting Scotch strategy. */ int esmumps_strat1 ( const INT procnbr, const INT leafsiz, const int leorval, const INT cminval, const INT cmaxval, const double fratval, const int verbval, FILE * const stream, char * const straptr) { INT levlval; /* Nested dissection level */ INT procmax; char hamxval; /* Type of halo ordering routine */ for (levlval = 1, procmax = 1; procmax < procnbr; procmax <<= 1, levlval ++) ; /* Compute log2 of procnbr, + 1 */ hamxval = (leorval == 0) ? 'h' : 'f'; /* HAMD if 0, HAMF if 1 */ if (verbval != 0) { fprintf (stream, "Scotch strategy:\n- %ld levels of ND are necessary for %ld processors\n", (long) levlval, (long) procnbr); fprintf (stream, "- If compressed (0.7) graph, then perform %ld levels of ND, then switch to HAM(%c)\n", (long) levlval, (char) hamxval); fprintf (stream, "- If uncompressed graph, then perform at least %ld levels of ND, and proceed\n until graph size less than %ld vertices, then switch to HAM(%c)\n", (long) levlval, (long) leafsiz, (char) hamxval); fprintf (stream, "- At the end of HAM(%c), amalgamate if number of columns not greater than %ld,\n and if either column size is smaller than %ld or fill ratio less than %lf\n", (char) hamxval, (long) cmaxval, (long) cminval, (double) fratval); fprintf (stream, "- During uncoarsening, band graphs of width 3 are used for refinement\n"); fprintf (stream, "- Separators are not split and are ordered in natural order\n"); } sprintf (straptr, "c{rat=0.7,cpr=n{sep=/((levl<%ld)|(vert>%ld))?m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=h{pass=10}f{bal=0.2}}}|m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=h{pass=10}f{bal=0.2}}};,ole=%c{cmin=%ld,cmax=%ld,frat=%lf},ose=s},unc=n{sep=/(levl<%ld)?(m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=h{pass=10}f{bal=0.2}}})|m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=h{pass=10}f{bal=0.2}}};,ole=%c{cmin=%ld,cmax=%ld,frat=%lf},ose=s}}", (long) levlval, (long) leafsiz, (char) hamxval, (long) cminval, (long) cmaxval, (double) fratval, (long) levlval, (char) hamxval, (long) cminval, (long) cmaxval, (double) fratval); return (0); } scotch-5.1.12b.dfsg/src/esmumps/graph_graph.c0000644000175300017530000001422511136130306021275 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_graph.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** These module holds the array graph **/ /** building routine. **/ /** **/ /** DATES : # Version 1.3 : from : 14 oct 2003 **/ /** to 22 jan 2004 **/ /** # Version 2.0 : from : 28 feb 2004 **/ /** to 06 dec 2004 **/ /** # Version 5.1 : from : 22 jan 2009 **/ /** to 22 jan 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GRAPH #include "common.h" #ifdef SCOTCH_PTSCOTCH #include "ptscotch.h" #else /* SCOTCH_PTSCOTCH */ #include "scotch.h" #endif /* SCOTCH_PTSCOTCH */ #include "graph.h" /********************************/ /* */ /* The graph handling routines. */ /* */ /********************************/ /* This routine builds a graph ** structure from the given ** arrays. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int graphBuildGraph ( Graph * const grafptr, /*+ Graph to build +*/ const INT baseval, /*+ Base value +*/ const INT vertnbr, /*+ Number of vertices +*/ const INT edgenbr, /*+ Number of arcs +*/ INT * restrict verttab, /*+ Vertex array +*/ INT * restrict velotab, /*+ Array of vertex weights (DOFs) if not NULL +*/ INT * restrict edgetab) /*+ Edge array +*/ { if (sizeof (INT) != sizeof (SCOTCH_Num)) { /* Check integer consistency */ errorPrint ("graphBuildGraph: inconsistent integer types"); return (1); } SCOTCH_graphBuild (grafptr, baseval, vertnbr, verttab, NULL, velotab, NULL, edgenbr, edgetab, NULL); #ifdef GRAPH_DEBUG if (graphCheck (grafptr) != 0) { /* Check graph consistency */ errorPrint ("graphBuildGraph: inconsistent graph data"); return (1); } #endif /* GRAPH_DEBUG */ return (0); } /* This routine builds a graph ** structure from the given ** arrays, with full libScotch ** features. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int graphBuildGraph2 ( Graph * const grafptr, /*+ Graph to build +*/ const INT baseval, /*+ Base value +*/ const INT vertnbr, /*+ Number of vertices +*/ const INT edgenbr, /*+ Number of arcs +*/ INT * restrict verttab, /*+ Vertex array +*/ INT * restrict vendtab, /*+ Vertex end array +*/ INT * restrict velotab, /*+ Array of vertex weights (DOFs) if not NULL +*/ INT * restrict vlbltab, /*+ Array of vertex labels if not NULL +*/ INT * restrict edgetab, /*+ Edge array +*/ INT * restrict edlotab) /*+ Edge load array +*/ { if (sizeof (INT) != sizeof (SCOTCH_Num)) { /* Check integer consistency */ errorPrint ("graphBuildGraph2: inconsistent integer types"); return (1); } SCOTCH_graphBuild (grafptr, baseval, vertnbr, verttab, vendtab, velotab, vlbltab, edgenbr, edgetab, edlotab); #ifdef GRAPH_DEBUG if (graphCheck (grafptr) != 0) { /* Check graph consistency */ errorPrint ("graphBuildGraph2: inconsistent graph data"); return (1); } #endif /* GRAPH_DEBUG */ return (0); } scotch-5.1.12b.dfsg/src/esmumps/order.c0000644000175300017530000000651311136102133020124 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : order.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** This module computes orderings. **/ /** **/ /** DATES : # Version 0.0 : from : 20 aug 1998 **/ /** to 24 sep 1998 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ORDER #include "common.h" #include "order.h" /***********************************/ /* */ /* The ordering handling routines. */ /* */ /***********************************/ /* This routine initializes the given ** ordering structure. ** It returns: ** - 0 : in all cases. */ int orderInit ( Order * const ordeptr) { memSet (ordeptr, 0, sizeof (Order)); return (0); } /* This routine frees the contents ** of the given ordering. ** It returns: ** - VOID : in all cases. */ void orderExit ( Order * const ordeptr) { if (ordeptr->rangtab != NULL) memFree (ordeptr->rangtab); if (ordeptr->permtab != NULL) memFree (ordeptr->permtab); if (ordeptr->peritab != NULL) memFree (ordeptr->peritab); #ifdef ORDER_DEBUG memSet (ordeptr, ~0, sizeof (Order)); #endif /* ORDER_DEBUG */ } scotch-5.1.12b.dfsg/src/esmumps/esmumps_f.c0000644000175300017530000000704010667023472021023 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : esmumps_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains Fortran MUMPS **/ /** stubs for the ordering routines of the **/ /** libSCOTCH + Emilio libfax libraries. **/ /** **/ /** DATES : # Version 0.0 : from : 16 may 2001 **/ /** to 17 may 2001 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #include "common.h" #include "esmumps.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the MUMPS ordering routine. */ /* */ /**************************************/ FORTRAN ( \ ESMUMPSF, esmumpsf, ( \ const INT * const n, \ const INT * const iwlen, \ INT * const petab, \ const INT * const pfree, \ INT * const lentab, \ INT * const iwtab, \ INT * const nvtab, \ INT * const elentab, \ INT * const lasttab, \ INT * const ncmpa), \ (n, iwlen, petab, pfree, lentab, iwtab, nvtab, elentab, lasttab, ncmpa)) { *ncmpa = esmumps (*n, *iwlen, petab, *pfree, lentab, iwtab, nvtab, elentab, lasttab); } scotch-5.1.12b.dfsg/src/esmumps/symbol.c0000644000175300017530000001144211136064224020323 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : symbol.c **/ /** **/ /** AUTHORS : David GOUDIN **/ /** Pascal HENON **/ /** Francois PELLEGRINI **/ /** Pierre RAMET **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** These lines are the general purpose **/ /** routines for the symbolic matrix. **/ /** **/ /** DATES : # Version 0.0 : from : 22 jul 1998 **/ /** to 07 oct 1998 **/ /** # Version 0.1 : from : 03 dec 1998 **/ /** to 03 dec 1998 **/ /** # Version 3.0 : from : 29 feb 2004 **/ /** to 29 feb 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define SYMBOL #include "common.h" #include "symbol.h" /******************************************/ /* */ /* The symbolic matrix handling routines. */ /* */ /******************************************/ /*+ This routine initializes the given *** symbolic block matrix structure. *** It returns: *** - 0 : in all cases. +*/ int symbolInit ( SymbolMatrix * const symbptr) { memSet (symbptr, 0, sizeof (SymbolMatrix)); return (0); } /*+ This routine frees the contents *** of the given symbolic block matrix. *** It returns: *** - VOID : in all cases. +*/ void symbolExit ( SymbolMatrix * const symbptr) { if (symbptr->cblktab != NULL) memFree (symbptr->cblktab); if (symbptr->bloktab != NULL) memFree (symbptr->bloktab); #ifdef SYMBOL_DEBUG symbolInit (symbptr); #endif /* SYMBOL_DEBUG */ } /*+ This routine reallocates the arrays *** of the given symbolic block matrix. *** It returns: *** - VOID : in all cases. +*/ void symbolRealloc ( SymbolMatrix * const symbptr) { SymbolCblk * cblktab; SymbolBlok * bloktab; if ((cblktab = (SymbolCblk *) memAlloc ((symbptr->cblknbr + 1) * sizeof (SymbolCblk))) == NULL) return; /* Cannot move smallest array */ memCpy (cblktab, symbptr->cblktab, (symbptr->cblknbr + 1) * sizeof (SymbolCblk)); memFree (symbptr->cblktab); /* Move column block array */ symbptr->cblktab = cblktab; if ((bloktab = (SymbolBlok *) memAlloc (symbptr->bloknbr * sizeof (SymbolBlok))) == NULL) return; /* Cannot move array */ memCpy (bloktab, symbptr->bloktab, symbptr->bloknbr * sizeof (SymbolBlok)); memFree (symbptr->bloktab); /* Move column block array */ symbptr->bloktab = bloktab; } scotch-5.1.12b.dfsg/src/esmumps/esmumps.h0000644000175300017530000000606510667023472020531 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : esmumps.h **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the symbolic factorization routine. **/ /** **/ /** DATES : # Version 0.0 : from : 22 jul 1998 **/ /** to 24 sep 1998 **/ /** # Version 0.1 : from : 04 apr 1999 **/ /** to 01 may 1999 **/ /** **/ /************************************************************/ #define ESMUMPS_H /* ** The function prototypes. */ #ifndef ESMUMPS #define static #endif int esmumps (const INT n, const INT iwlen, INT * const pe, const INT pfree, INT * const len, INT * const iw, INT * const nv, INT * const elen, INT * const last); int esmumps_strat1 (const INT procnbr, const INT leafsiz, const int leorval, const INT cminval, const INT cmaxval, const double fratval, const int verbval, FILE * const stream, char * const straptr); #undef static scotch-5.1.12b.dfsg/src/esmumps/order_scotch_graph.c0000644000175300017530000002061111413455602022655 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : order_scotch_graph.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** This is the interface module with the **/ /** libSCOTCH matrix ordering library. **/ /** **/ /** DATES : # Version 0.0 : from : 20 aug 1998 **/ /** to 18 may 1999 **/ /** # Version 1.0 : from : 18 mar 2003 **/ /** to 21 jan 2004 **/ /** # Version 2.0 : from : 28 feb 2004 **/ /** to 04 jan 2005 **/ /** # Version 2.1 : from : 21 jun 2007 **/ /** to 21 jun 2007 **/ /** # Version 5.0 : from : 08 feb 2008 **/ /** to 01 jun 2008 **/ /** # Version 5.1 : from : 22 jan 2009 **/ /** to 02 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ORDER_GRAPH #include "common.h" #ifdef SCOTCH_PTSCOTCH #include "ptscotch.h" #else /* SCOTCH_PTSCOTCH */ #include "scotch.h" #endif /* SCOTCH_PTSCOTCH */ #include "graph.h" #include "order.h" /****************************/ /* */ /* Graph ordering routines. */ /* */ /****************************/ /*+ This routine orders the given *** graph using the Emilio default *** ordering strategy. *** It returns: *** - 0 : if ordering succeeded. *** - !0 : on error. +*/ int orderGraph ( Order * restrict const ordeptr, /*+ Ordering to compute +*/ Graph * restrict const grafptr) /*+ Graph matrix to order +*/ { INT vertnbr; SCOTCH_graphSize (grafptr, &vertnbr, NULL); return (orderGraphList (ordeptr, grafptr, vertnbr, NULL)); } /*+ This routine orders the subgraph of *** the given graph induced by the given *** vertex list, using the Emilio default *** ordering strategy. *** It returns: *** - 0 : if ordering succeeded. *** - !0 : on error. +*/ int orderGraphList ( Order * restrict const ordeptr, /*+ Ordering to compute +*/ Graph * restrict const grafptr, /*+ Graph matrix to order +*/ const INT listnbr, /*+ Number of vertices in list +*/ const INT * restrict const listtab) /*+ Vertex list array +*/ { return (orderGraphListStrat (ordeptr, grafptr, listnbr, listtab, "c{rat=0.7,cpr=n{sep=/(vert>120)?m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=(|h{pass=10})f{bal=0.2}}}|m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=(|h{pass=10})f{bal=0.2}}};,ole=f{cmin=0,cmax=100000,frat=0.0},ose=g},unc=n{sep=/(vert>120)?m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=(|h{pass=10})f{bal=0.2}}}|m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=0.2},org=(|h{pass=10})f{bal=0.2}}};,ole=f{cmin=15,cmax=100000,frat=0.0},ose=g}}")); } /*+ This routine orders the given *** graph using the given ordering *** strategy. *** It returns: *** - 0 : if ordering succeeded. *** - !0 : on error. +*/ int orderGraphStrat ( Order * restrict const ordeptr, /*+ Ordering to compute +*/ Graph * restrict const grafptr, /*+ Graph matrix to order +*/ const char * restrict const stratptr) /*+ Ordering strategy +*/ { INT vertnbr; SCOTCH_graphSize (grafptr, &vertnbr, NULL); return (orderGraphListStrat (ordeptr, grafptr, vertnbr, NULL, stratptr)); } /*+ This routine orders the subgraph of *** the given graph induced by the given *** vertex list, using the given ordering *** strategy. *** It returns: *** - 0 : if ordering succeeded. *** - !0 : on error. +*/ int orderGraphListStrat ( Order * restrict const ordeptr, /*+ Ordering to compute +*/ Graph * restrict const grafptr, /*+ Graph matrix to order +*/ const INT listnbr, /*+ Number of vertices in list +*/ const INT * restrict const listtab, /*+ Vertex list array +*/ const char * restrict const stratptr) /*+ Ordering strategy +*/ { SCOTCH_Strat scotstrat; /* Scotch ordering strategy */ INT baseval; INT vertnbr; INT edgenbr; int o; if (sizeof (INT) != sizeof (SCOTCH_Num)) { /* Check integer consistency */ errorPrint ("orderGraphListStrat: inconsistent integer types"); return (1); } SCOTCH_graphData (grafptr, &baseval, &vertnbr, NULL, NULL, NULL, NULL, &edgenbr, NULL, NULL); if (((ordeptr->permtab = (INT *) memAlloc ( vertnbr * sizeof (INT))) == NULL) || ((ordeptr->peritab = (INT *) memAlloc ( vertnbr * sizeof (INT))) == NULL) || ((ordeptr->rangtab = (INT *) memAlloc ((vertnbr + 1) * sizeof (INT))) == NULL)) { errorPrint ("orderGraphListStrat: out of memory"); orderExit (ordeptr); orderInit (ordeptr); return (1); } SCOTCH_stratInit (&scotstrat); /* Initialize default ordering strategy */ o = SCOTCH_stratGraphOrder (&scotstrat, stratptr); if (o == 0) o = SCOTCH_graphOrderList (grafptr, /* Compute graph ordering */ (SCOTCH_Num) listnbr, (SCOTCH_Num *) listtab, &scotstrat, (SCOTCH_Num *) ordeptr->permtab, (SCOTCH_Num *) ordeptr->peritab, (SCOTCH_Num *) &ordeptr->cblknbr, (SCOTCH_Num *) ordeptr->rangtab, NULL); SCOTCH_stratExit (&scotstrat); if (o != 0) { /* If something failed in Scotch */ orderExit (ordeptr); /* Free ordering arrays */ orderInit (ordeptr); return (1); } #ifdef ORDER_DEBUG if ((ordeptr->rangtab[0] != baseval) || (ordeptr->rangtab[ordeptr->cblknbr] != baseval + vertnbr) || (orderCheck (ordeptr) != 0)) { errorPrint ("orderGraphListStrat: invalid ordering"); } #endif /* ORDER_DEBUG */ ordeptr->rangtab = (INT *) memRealloc (ordeptr->rangtab, (ordeptr->cblknbr + 1) * sizeof (INT)); return (0); } scotch-5.1.12b.dfsg/src/esmumps/symbol_fax_graph.c0000644000175300017530000001324011136130325022334 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : symbol_fax_graph.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** This is the block symbolic factoriza- **/ /** tion routine for graphs. **/ /** **/ /** DATES : # Version 0.0 : from : 22 jul 1998 **/ /** to 29 sep 1998 **/ /** # Version 0.2 : from : 08 may 2000 **/ /** to 09 may 2000 **/ /** # Version 1.0 : from : 01 jun 2002 **/ /** to 03 jun 2002 **/ /** # Version 1.1 : from : 26 jun 2002 **/ /** to 26 jun 2002 **/ /** # Version 2.0 : from : 21 mar 2003 **/ /** to 21 mar 2003 **/ /** # Version 3.0 : from : 02 mar 2004 **/ /** to 02 mar 2004 **/ /** # Version 5.1 : from : 22 jan 2009 **/ /** to 22 jan 2009 **/ /** **/ /** NOTES : # symbolFaxGraph() could have called **/ /** symbolFax() in the regular way, as **/ /** do all of the grid-like factorization **/ /** routines. However, for efficiency **/ /** reasons, we have decided to inline **/ /** symbolFax(), to avoid a function call **/ /** for every arc. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define SYMBOL_FAX #define SYMBOL_FAX_GRAPH #include "common.h" #ifdef SCOTCH_PTSCOTCH #include "ptscotch.h" #else /* SCOTCH_PTSCOTCH */ #include "scotch.h" #endif /* SCOTCH_PTSCOTCH */ #include "graph.h" #include "symbol.h" #include "order.h" #include "fax.h" #include "symbol_fax.h" /***********************************/ /* */ /* Symbolic factorization routine. */ /* */ /***********************************/ /*+ This routine computes the block symbolic *** factorization of the given matrix graph *** according to the given vertex ordering. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int symbolFaxGraph ( SymbolMatrix * const symbptr, /*+ Symbolic block matrix [based] +*/ const Graph * const grafptr, /*+ Matrix adjacency structure [based] +*/ const Order * const ordeptr) /*+ Matrix ordering +*/ { INT baseval; INT vertnbr; INT * verttab; const INT * restrict verttax; INT edgenbr; INT edgenum; INT * edgetab; const INT * restrict edgetax; SCOTCH_graphData (grafptr, &baseval, &vertnbr, &verttab, NULL, NULL, NULL, &edgenbr, &edgetab, NULL); verttax = verttab - baseval; edgetax = edgetab - baseval; #define SYMBOL_FAX_ITERATOR(ngbdptr, vertnum, vertend) \ for (edgenum = verttax[vertnum]; \ edgenum < verttax[vertnum + 1]; \ edgenum ++) { \ vertend = edgetax[edgenum]; #define SYMBOL_FAX_VERTEX_DEGREE(ngbdptr, vertnum) \ (verttax[(vertnum) + 1] - verttax[(vertnum)]) { #define SYMBOL_FAX_INCLUDED #include "symbol_fax.c" } } scotch-5.1.12b.dfsg/src/esmumps/symbol_fax.h0000644000175300017530000000741510667023474021205 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : symbol_fax.h **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** Jean ROMAN (v0.0) **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** These lines are the data declarations **/ /** for the symbolic factorization routine. **/ /** **/ /** DATES : # Version 0.0 : from : 22 jul 1998 **/ /** to 24 sep 1998 **/ /** # Version 0.1 : from : 04 apr 1999 **/ /** to 01 may 1999 **/ /** # Version 1.0 : from : 01 jun 2002 **/ /** to 05 jun 2002 **/ /** # Version 1.1 : from : 26 jun 2002 **/ /** to 26 jun 2002 **/ /** # Version 3.0 : from : 03 mar 2004 **/ /** to 03 mar 2004 **/ /** **/ /************************************************************/ #define SYMBOL_FAX_H /* ** The defines. */ /* Prime number for hashing vertex numbers. */ #define SYMBOL_FAX_HASHPRIME 17 /*+ Prime number for hashing +*/ /* ** The type and structure definitions. */ /*+ The chained column block structure. These blocks are chained in a single linked list for block merge with blocks of left columns. +*/ typedef struct SymbolFaxTlok_ { INT frownum; /*+ First row index +*/ INT lrownum; /*+ Last row index (inclusive) +*/ INT cblknum; /*+ Facing column block +*/ INT nextnum; /*+ Index of next block +*/ } SymbolFaxTlok; scotch-5.1.12b.dfsg/src/esmumps/dof.h0000644000175300017530000001203011136101635017563 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dof.h **/ /** **/ /** AUTHORS : David GOUDIN **/ /** Pascal HENON **/ /** Francois PELLEGRINI **/ /** Pierre RAMET **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** These lines are the data declarations **/ /** for the DOF handling structure. **/ /** **/ /** DATES : # Version 0.0 : from : 07 oct 1998 **/ /** to 16 oct 1998 **/ /** # Version 1.0 : from : 06 jun 2002 **/ /** to 06 jun 2002 **/ /** # Version 3.0 : from : 28 feb 2004 **/ /** to 29 feb 2004 **/ /** **/ /************************************************************/ #define DOF_H #define DOF_CONSTANT /* Constant DOFs for ESMUMPS */ /* ** The type and structure definitions. */ /*+ The DOF structure. This structure is always associated to a Graph structure, which holds the base value. +*/ typedef struct Dof_ { INT baseval; /*+ Base value for indexing +*/ INT nodenbr; /*+ Number of nodes in DOF array +*/ INT noddval; /*+ DOF value for every node (if noddtab == NULL, 0 else) +*/ INT * restrict noddtab; /*+ Array of node->first DOF indexes (if noddval == 0) [+1,based] +*/ } Dof; /* ** The function prototypes. */ #ifndef DOF #define static #endif int dofInit (Dof * const deofptr); void dofExit (Dof * const deofptr); int dofLoad (Dof * const deofptr, FILE * const stream); int dofSave (const Dof * const deofptr, FILE * const stream); void dofConstant (Dof * const deofptr, const INT baseval, const INT nodenbr, const INT noddval); #ifdef GRAPH_H int dofGraph (Dof * const deofptr, const Graph * grafptr, const INT, const INT * const peritab); #endif /* GRAPH_H */ #undef static /* ** The macro definitions. */ #ifdef DOF_CONSTANT #define noddVal(deofptr,nodenum) ((deofptr)->baseval + (deofptr)->noddval * ((nodenum) - (deofptr)->baseval)) #define noddDlt(deofptr,nodenum) ((deofptr)->noddval) #else /* DOF_CONSTANT */ #define noddVal(deofptr,nodenum) (((deofptr)->noddtab != NULL) ? (deofptr)->noddtab[(deofptr)->baseval + (nodenum)] : ((deofptr)->baseval + (deofptr)->noddval * ((nodenum) - (deofptr)->baseval))) #define noddDlt(deofptr,nodenum) (((deofptr)->noddtab != NULL) ? ((deofptr)->noddtab[(deofptr)->baseval + (nodenum) + 1] - (deofptr)->noddtab[(deofptr)->baseval + (nodenum)]) : (deofptr)->noddval) #endif /* DOF_CONSTANT */ scotch-5.1.12b.dfsg/src/esmumps/fax.h0000644000175300017530000001463110667023473017615 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : fax.h **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** Jean ROMAN (v0.0) **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** These lines are the data declarations **/ /** for the symbolic factorization routine. **/ /** **/ /** DATES : # Version 0.0 : from : 22 jul 1998 **/ /** to 24 sep 1998 **/ /** # Version 0.1 : from : 04 apr 1999 **/ /** to 01 may 1999 **/ /** # Version 1.0 : from : 01 jun 2002 **/ /** to 25 jun 2002 **/ /** # Version 1.1 : from : 26 jun 2002 **/ /** to 25 sep 2002 **/ /** # Version 1.3 : from : 17 jun 2003 **/ /** to 17 jul 2003 **/ /** # Version 2.0 : from : 21 mar 2003 **/ /** to 29 oct 2003 **/ /** # Version 2.0 : from : 03 mar 2004 **/ /** to 03 mar 2004 **/ /** # Version 3.0 : from : 23 nov 2004 **/ /** to 03 mar 2005 **/ /** **/ /************************************************************/ #define FAX_H /* ** The function prototypes. */ #ifndef FAX #define static #endif int symbolCompact (SymbolMatrix * const symbptr); int symbolFax (SymbolMatrix * const symbptr, const INT vertnbr, const INT edgenbr, const INT baseval, void * const ngbdptr, INT ngbfrst (void * const, const INT), INT ngbnext (void * const), INT ngbdegr (void * const, const INT), const Order * const ordeptr); #ifdef GRAPH_H int symbolFaxGraph (SymbolMatrix * const symbptr, const Graph * const grafptr, const Order * const ordeptr); #endif /* GRAPH_H */ int symbolFaxGrid2C (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT baseval, const Order * const ordeptr); int symbolFaxGrid2D (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT baseval, const Order * const ordeptr); int symbolFaxGrid2E (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT baseval, const Order * const ordeptr); int symbolFaxGrid3C (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT znbr, const INT baseval, const Order * const ordeptr); int symbolFaxGrid3D (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT znbr, const INT baseval, const Order * const ordeptr); int symbolFaxGrid3E (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT znbr, const INT baseval, const Order * const ordeptr); #ifdef MESH_H int symbolFaxMesh (SymbolMatrix * const symbptr, const Mesh * const meshptr, const Order * const ordeptr); #endif /* MESH_H */ int symbolFaxi (SymbolMatrix * const symbptr, const INT vertnbr, const INT edgenbr, const INT baseval, void * const ngbdptr, INT ngbfrst (void * const, const INT), INT ngbnext (void * const), INT ngbdegr (void * const, const INT), const Order * const ordeptr, const INT levfmax); #ifdef GRAPH_H int symbolFaxiGraph (SymbolMatrix * const symbptr, const Graph * const grafptr, const Order * const ordeptr, const INT levfmax); #endif /* GRAPH_H */ int symbolFaxiGrid2D (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT baseval, const Order * const ordeptr, const INT levfmax); int symbolFaxiGrid2E (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT baseval, const Order * const ordeptr, const INT levfmax); int symbolFaxiGrid3D (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT znbr, const INT baseval, const Order * const ordeptr, const INT levfmax); int symbolFaxiGrid3E (SymbolMatrix * const symbptr, const INT xnbr, const INT ynbr, const INT znbr, const INT baseval, const Order * const ordeptr, const INT levfmax); #undef static scotch-5.1.12b.dfsg/src/libscotch/0000755000175300017530000000000011617553066017144 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/src/libscotch/vdgraph_separate_ml.h0000644000175300017530000001070511631334325023316 0ustar hazelscthazelsct/* Copyright 2007-2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_separate_ml.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER (v5.0) **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the sequential vertex separation **/ /** routine for distributed graphs. **/ /** **/ /** DATES : # Version 5.0 : from : 07 feb 2006 **/ /** to : 03 aug 2007 **/ /** # Version 5.1 : from : 14 dec 2008 **/ /** to : 29 may 2009 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct VdgraphSeparateMlParam_ { INT passnbr; /*+ Number of coarsening passes to go +*/ INT coarnbr; /*+ Minimum number of vertices +*/ INT dupmax; /*+ Maximum number of vertices to do fold-dup +*/ INT duplvlmax; /*+ Maximum level for allowing fold-dup +*/ double coarrat; /*+ Coarsening ratio +*/ Strat * stratlow; /*+ Strategy at lowest level +*/ Strat * stratasc; /*+ Strategy at ascending levels +*/ Strat * stratseq; /*+ Strategy when running on a single processor +*/ INT seqnbr; /*+ Threshold when entering into seq mode +*/ } VdgraphSeparateMlParam; /* ** The function prototypes. */ #ifndef VDGRAPH_SEPARATE_ML #define static #endif static int vdgraphSeparateMlCoarsen (Vdgraph * const, Vdgraph * const, DgraphCoarsenMulti * restrict * const, const VdgraphSeparateMlParam * const); static int vdgraphSeparateMlUncoarsen (Vdgraph *, const Vdgraph * const, const DgraphCoarsenMulti * restrict const); static void vdgraphSeparateMlOpBest (const Gnum * const, Gnum * const, const int * const, const MPI_Datatype * const); int vdgraphSeparateMl (Vdgraph * const, const VdgraphSeparateMlParam * const); static int vdgraphSeparateMl2 (Vdgraph * const, const VdgraphSeparateMlParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_mesh.c0000644000175300017530000004305011631334325021761 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_mesh.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the source **/ /** mesh handling routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 4.0 : from : 23 sep 2002 **/ /** to 11 may 2004 **/ /** # Version 5.1 : from : 17 nov 2010 **/ /** to 17 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the mesh handling routines. */ /* */ /************************************/ /*+ This routine reserves a memory area *** of a size sufficient to store a *** centralized mesh structure. *** It returns: *** - !NULL : if the initialization succeeded. *** - NULL : on error. +*/ SCOTCH_Mesh * SCOTCH_meshAlloc () { return ((SCOTCH_Mesh *) memAlloc (sizeof (SCOTCH_Mesh))); } /*+ This routine initializes the opaque *** mesh structure used to handle meshes *** in the Scotch library. *** It returns: *** - 0 : if the initialization succeeded. *** - !0 : on error. +*/ int SCOTCH_meshInit ( SCOTCH_Mesh * const meshptr) { if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { errorPrint ("SCOTCH_meshInit: internal error (1)"); return (1); } if (sizeof (SCOTCH_Mesh) < sizeof (Mesh)) { errorPrint ("SCOTCH_meshInit: internal error (2)"); return (1); } return (meshInit ((Mesh *) meshptr)); } /*+ This routine frees the contents of the *** given opaque mesh structure. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_meshExit ( SCOTCH_Mesh * const meshptr) { meshExit ((Mesh *) meshptr); } /*+ This routine loads the given opaque mesh *** structure with the data of the given stream. *** The base value allows the user to set the *** mesh base to 0 or 1, or to the base value *** of the stream if the base value is equal *** to -1. *** It returns: *** - 0 : if the loading succeeded. *** - !0 : on error. +*/ int SCOTCH_meshLoad ( SCOTCH_Mesh * const meshptr, FILE * const stream, const SCOTCH_Num baseval) { if ((baseval < -1) || (baseval > 1)) { errorPrint ("SCOTCH_meshLoad: invalid base parameter"); return (1); } return (meshLoad ((Mesh * const) meshptr, stream, (Gnum) baseval)); } /*+ This routine saves the contents of the given *** opaque mesh structure to the given stream. *** It returns: *** - 0 : if the saving succeeded. *** - !0 : on error. +*/ int SCOTCH_meshSave ( const SCOTCH_Mesh * const meshptr, FILE * const stream) { return (meshSave ((const Mesh * const) meshptr, stream)); } /*+ This routine fills the contents of the given *** opaque mesh structure with the data provided *** by the user. The base value allows the user to *** set the mesh base to 0 or 1. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_meshBuild ( SCOTCH_Mesh * const meshptr, /* Mesh structure to fill */ const SCOTCH_Num velmbas, /* Base index for element vertices */ const SCOTCH_Num vnodbas, /* Base index for node vertices */ const SCOTCH_Num velmnbr, /* Number of elements in mesh graph */ const SCOTCH_Num vnodnbr, /* Number of vertices in mesh graph */ const SCOTCH_Num * const verttab, /* Vertex array [vertnbr or vertnbr+1] */ const SCOTCH_Num * const vendtab, /* Vertex end array [vertnbr] */ const SCOTCH_Num * const velotab, /* Element vertex load array */ const SCOTCH_Num * const vnlotab, /* Node vertex load array */ const SCOTCH_Num * const vlbltab, /* Vertex label array */ const SCOTCH_Num edgenbr, /* Number of edges (arcs) */ const SCOTCH_Num * const edgetab) /* Edge array [edgenbr] */ { Mesh * srcmeshptr; /* Pointer to source mesh structure */ Gnum degrmax; /* Maximum degree */ Gnum veisnbr; /* Number of isolated element vertices */ Gnum vertnum; /* Current vertex number */ #ifdef SCOTCH_DEBUG_LIBRARY1 if (sizeof (SCOTCH_Mesh) < sizeof (Mesh)) { errorPrint ("SCOTCH_meshBuild: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_LIBRARY1 */ if ((velmbas < 0) || (vnodbas < 0) || ((velmbas > 1) && (vnodbas > 1))) { errorPrint ("SCOTCH_meshBuild: invalid base parameters"); return (1); } if (((velmbas + velmnbr) != vnodbas) && ((vnodbas + vnodnbr) != velmbas)) { errorPrint ("SCOTCH_meshBuild: invalid element or node range"); return (1); } srcmeshptr = (Mesh *) meshptr; /* Use structure as source mesh */ srcmeshptr->flagval = MESHNONE; srcmeshptr->baseval = MIN (velmbas, vnodbas); srcmeshptr->velmnbr = velmnbr; srcmeshptr->velmbas = velmbas; srcmeshptr->velmnnd = velmbas + velmnbr; srcmeshptr->vnodnbr = vnodnbr; srcmeshptr->vnodbas = vnodbas; srcmeshptr->vnodnnd = vnodbas + vnodnbr; srcmeshptr->verttax = (Gnum *) verttab - srcmeshptr->baseval; srcmeshptr->vendtax = ((vendtab == NULL) || (vendtab == verttab) || (vendtab == verttab + 1)) ? srcmeshptr->verttax + 1 : (Gnum *) vendtab - srcmeshptr->baseval; srcmeshptr->velotax = ((velotab == NULL) || (velotab == verttab)) ? NULL : (Gnum *) velotab - srcmeshptr->velmbas; srcmeshptr->vnlotax = ((vnlotab == NULL) || (vnlotab == verttab)) ? NULL : (Gnum *) vnlotab - srcmeshptr->vnodbas; srcmeshptr->vlbltax = ((vlbltab == NULL) || (vlbltab == verttab)) ? NULL : (Gnum *) vlbltab - srcmeshptr->baseval; srcmeshptr->edgenbr = edgenbr; srcmeshptr->edgetax = (Gnum *) edgetab - srcmeshptr->baseval; if (srcmeshptr->velotax == NULL) /* Compute element vertex load sum */ srcmeshptr->velosum = srcmeshptr->velmnbr; else { Gnum velosum; /* Sum of element vertex loads */ for (vertnum = srcmeshptr->velmbas, velosum = 0; vertnum < srcmeshptr->velmnnd; vertnum ++) velosum += srcmeshptr->velotax[vertnum]; srcmeshptr->velosum = velosum; } if (srcmeshptr->vnlotax == NULL) /* Compute node vertex load sum */ srcmeshptr->vnlosum = srcmeshptr->vnodnbr; else { Gnum vnlosum; /* Sum of node vertex loads */ for (vertnum = srcmeshptr->vnodbas, vnlosum = 0; vertnum < srcmeshptr->vnodnnd; vertnum ++) vnlosum += srcmeshptr->vnlotax[vertnum]; srcmeshptr->vnlosum = vnlosum; } for (vertnum = srcmeshptr->velmbas, veisnbr = degrmax = 0; /* Compute maximum degree */ vertnum < srcmeshptr->velmnnd; vertnum ++) { Gnum degrval; /* Degree of current vertex */ degrval = srcmeshptr->vendtax[vertnum] - srcmeshptr->verttax[vertnum]; if (degrval > degrmax) degrmax = degrval; else if (degrval == 0) /* Count number of isolated element vertices */ veisnbr ++; } srcmeshptr->veisnbr = veisnbr; for (vertnum = srcmeshptr->vnodbas; /* Compute maximum degree */ vertnum < srcmeshptr->vnodnnd; vertnum ++) { Gnum degrval; /* Degree of current vertex */ degrval = srcmeshptr->vendtax[vertnum] - srcmeshptr->verttax[vertnum]; if (degrval > degrmax) degrmax = degrval; } srcmeshptr->degrmax = degrmax; #ifdef SCOTCH_DEBUG_LIBRARY1 if (meshCheck (srcmeshptr) != 0) { errorPrint ("SCOTCH_meshBuild: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_LIBRARY1 */ return (0); } /*+ This routine checks the consistency *** of the given mesh. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_meshCheck ( const SCOTCH_Mesh * const meshptr) { return (meshCheck ((const Mesh * const) meshptr)); } /*+ This routine accesses mesh size data. *** NULL pointers on input indicate unwanted *** data. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_meshSize ( const SCOTCH_Mesh * const meshptr, SCOTCH_Num * const velmnbr, SCOTCH_Num * const vnodnbr, SCOTCH_Num * const edgenbr) { const Mesh * srcmeshptr; srcmeshptr = (Mesh *) meshptr; if (velmnbr != NULL) *velmnbr = (SCOTCH_Num) srcmeshptr->velmnbr; if (vnodnbr != NULL) *vnodnbr = (SCOTCH_Num) srcmeshptr->vnodnbr; if (edgenbr != NULL) *edgenbr = (SCOTCH_Num) srcmeshptr->edgenbr; } /*+ This routine accesses all of the mesh data. *** NULL pointers on input indicate unwanted *** data. NULL pointers on output indicate *** unexisting arrays. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_meshData ( const SCOTCH_Mesh * const meshptr, /* Mesh structure to read */ SCOTCH_Num * const velmbas, /* Base index for elements */ SCOTCH_Num * const vnodbas, /* Base index for nodes */ SCOTCH_Num * const velmnbr, /* Number of elements */ SCOTCH_Num * const vnodnbr, /* Number of nodes */ SCOTCH_Num ** const verttab, /* Vertex array [vertnbr+1] */ SCOTCH_Num ** const vendtab, /* Vertex array [vertnbr] */ SCOTCH_Num ** const velotab, /* Element vertex load array */ SCOTCH_Num ** const vnlotab, /* Vertex load array */ SCOTCH_Num ** const vlbltab, /* Vertex label array */ SCOTCH_Num * const edgenbr, /* Number of edges (arcs) */ SCOTCH_Num ** const edgetab, /* Edge array [edgenbr] */ SCOTCH_Num * const degrnbr) /* Maximum degree */ { const Mesh * srcmeshptr; /* Pointer to source mesh structure */ srcmeshptr = (const Mesh *) meshptr; if (velmnbr != NULL) *velmnbr = srcmeshptr->velmnbr; if (vnodnbr != NULL) *vnodnbr = srcmeshptr->vnodnbr; if (velmbas != NULL) *velmbas = srcmeshptr->velmbas; if (vnodbas != NULL) *vnodbas = srcmeshptr->vnodbas; if (verttab != NULL) *verttab = srcmeshptr->verttax + srcmeshptr->baseval; if (vendtab != NULL) *vendtab = srcmeshptr->vendtax + srcmeshptr->baseval; if (velotab != NULL) *velotab = (srcmeshptr->velotax != NULL) ? (srcmeshptr->velotax + srcmeshptr->velmbas) : NULL; if (vnlotab != NULL) *vnlotab = (srcmeshptr->vnlotax != NULL) ? (srcmeshptr->vnlotax + srcmeshptr->vnodbas) : NULL; if (vlbltab != NULL) *vlbltab = (srcmeshptr->vlbltax != NULL) ? (srcmeshptr->vlbltax + srcmeshptr->baseval) : NULL; if (edgenbr != NULL) *edgenbr = srcmeshptr->edgenbr; if (edgetab != NULL) *edgetab = srcmeshptr->edgetax + srcmeshptr->baseval; if (degrnbr != NULL) *degrnbr = srcmeshptr->degrmax; } /*+ This routine computes statistics *** on the given graph. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_meshStat ( const SCOTCH_Mesh * const meshptr, SCOTCH_Num * const vnlominptr, /* Vertex loads only for nodes */ SCOTCH_Num * const vnlomaxptr, SCOTCH_Num * const vnlosumptr, double * const vnloavgptr, double * const vnlodltptr, SCOTCH_Num * const edegminptr, /* Element degree data */ SCOTCH_Num * const edegmaxptr, double * const edegavgptr, double * const edegdltptr, SCOTCH_Num * const ndegminptr, /* Node degree data */ SCOTCH_Num * const ndegmaxptr, double * const ndegavgptr, double * const ndegdltptr) { const Mesh * restrict srcmeshptr; Gnum vnlomin; Gnum vnlomax; double vnloavg; double vnlodlt; Gnum degrmin; Gnum degrmax; double degravg; double degrdlt; srcmeshptr = (Mesh *) meshptr; vnlodlt = 0.0L; if (srcmeshptr->vnodnbr > 0) { if (srcmeshptr->vnlotax != NULL) { /* If mesh has node vertex loads */ Gnum vnodnum; vnlomin = GNUMMAX; vnlomax = 0; vnloavg = (double) srcmeshptr->vnlosum / (double) srcmeshptr->vnodnbr; for (vnodnum = srcmeshptr->vnodbas; vnodnum < srcmeshptr->vnodnnd; vnodnum ++) { if (srcmeshptr->vnlotax[vnodnum] < vnlomin) /* Account for vertex loads */ vnlomin = srcmeshptr->vnlotax[vnodnum]; if (srcmeshptr->vnlotax[vnodnum] > vnlomax) vnlomax = srcmeshptr->vnlotax[vnodnum]; vnlodlt += fabs ((double) srcmeshptr->vnlotax[vnodnum] - vnloavg); } vnlodlt /= (double) srcmeshptr->vnodnbr; } else { vnlomin = vnlomax = 1; vnloavg = 1.0L; } } else { vnlomin = vnlomax = 0; vnloavg = 0.0L; } if (vnlominptr != NULL) *vnlominptr = (SCOTCH_Num) vnlomin; if (vnlomaxptr != NULL) *vnlomaxptr = (SCOTCH_Num) vnlomax; if (vnlosumptr != NULL) *vnlosumptr = (SCOTCH_Num) srcmeshptr->vnlosum; if (vnloavgptr != NULL) *vnloavgptr = (double) vnloavg; if (vnlodltptr != NULL) *vnlodltptr = (double) vnlodlt; degrmax = 0; degrdlt = 0.0L; if (srcmeshptr->velmnbr > 0) { Gnum velmnum; degrmin = GNUMMAX; degravg = (double) srcmeshptr->edgenbr / (double) (2 * srcmeshptr->velmnbr); for (velmnum = srcmeshptr->velmbas; velmnum < srcmeshptr->velmnnd; velmnum ++) { Gnum degrval; degrval = srcmeshptr->vendtax[velmnum] - srcmeshptr->verttax[velmnum]; /* Get element degree */ if (degrval < degrmin) degrmin = degrval; if (degrval > degrmax) degrmax = degrval; degrdlt += fabs ((double) degrval - degravg); } degrdlt /= (double) srcmeshptr->velmnbr; } else { degrmin = 0; degravg = 0.0L; } if (edegminptr != NULL) *edegminptr = (SCOTCH_Num) degrmin; if (edegmaxptr != NULL) *edegmaxptr = (SCOTCH_Num) degrmax; if (edegavgptr != NULL) *edegavgptr = (double) degravg; if (edegdltptr != NULL) *edegdltptr = (double) degrdlt; degrmax = 0; degrdlt = 0.0L; if (srcmeshptr->vnodnbr > 0) { Gnum vnodnum; degrmin = GNUMMAX; degravg = (double) srcmeshptr->edgenbr / (double) (2 * srcmeshptr->vnodnbr); for (vnodnum = srcmeshptr->vnodbas; vnodnum < srcmeshptr->vnodnnd; vnodnum ++) { Gnum degrval; degrval = srcmeshptr->vendtax[vnodnum] - srcmeshptr->verttax[vnodnum]; /* Get element degree */ if (degrval < degrmin) degrmin = degrval; if (degrval > degrmax) degrmax = degrval; degrdlt += fabs ((double) degrval - degravg); } degrdlt /= (double) srcmeshptr->vnodnbr; } else { degrmin = 0; degravg = 0.0L; } if (ndegminptr != NULL) *ndegminptr = (SCOTCH_Num) degrmin; if (ndegmaxptr != NULL) *ndegmaxptr = (SCOTCH_Num) degrmax; if (ndegavgptr != NULL) *ndegavgptr = (double) degravg; if (ndegdltptr != NULL) *ndegdltptr = (double) degrdlt; } scotch-5.1.12b.dfsg/src/libscotch/graph_list.h0000644000175300017530000001124611631334325021444 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_list.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the source graph functions. **/ /** **/ /** DATES : # Version 0.0 : from : 02 dec 1992 **/ /** to 18 may 1993 **/ /** # Version 1.3 : from : 30 apr 1994 **/ /** to 18 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 18 aug 1994 **/ /** # Version 3.0 : from : 07 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 28 nov 1995 **/ /** to 28 nov 1995 **/ /** # Version 3.2 : from : 07 sep 1996 **/ /** to 15 sep 1998 **/ /** # Version 3.3 : from : 28 sep 1998 **/ /** to 23 mar 1999 **/ /** # Version 3.4 : from : 20 mar 2000 **/ /** to 20 mar 2000 **/ /** # Version 4.0 : from : 24 nov 2001 **/ /** to 27 sep 2002 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ #define GRAPH_LIST_H /* ** The type and structure definitions. */ /*+ The vertex list structure. Since a vertex list always refers to a given graph, vertex indices contained in the vertex list array are based with respect to the base value of the associated graph. However, the array itself is not based. +*/ typedef struct VertList_ { Gnum vnumnbr; /*+ Number of vertices in list +*/ Gnum * vnumtab; /*+ Pointer to vertex array +*/ } VertList; /* ** The function prototypes. */ #ifndef GRAPH_LIST #define static #endif int listInit (VertList *); void listExit (VertList *); int listAlloc (VertList *, Gnum); int listFree (VertList *); int listLoad (VertList *, FILE *); int listSave (VertList *, FILE *); void listSort (VertList *); int listCopy (VertList *, VertList *); #undef static scotch-5.1.12b.dfsg/src/libscotch/bdgraph_bipart_df.h0000644000175300017530000000723611631334325022735 0ustar hazelscthazelsct/* Copyright 2007,2009,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_bipart_df.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the parallel diffusion bipartition- **/ /** ing routine for distributed graphs. **/ /** **/ /** DATES : # Version 5.1 : from : 16 nov 2007 **/ /** to : 14 apr 2011 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Small non-zero float value. +*/ #define BDGRAPHBIPARTDFEPSILON (1.0F / (float) (GNUMMAX)) /*+ Sign masking operator. +*/ #define BDGRAPHBIPARTDFGNUMSGNMSK(i) ((Gnum) 0 - (((Gunum) (i)) >> (sizeof (Gnum) * 8 - 1))) /* ** The type and structure definitions. */ /*+ Job selection policy types. +*/ typedef enum BdgraphBipartDfType_ { BDGRAPHBIPARTDFTYPEBAL = 0, /*+ Balance to average +*/ BDGRAPHBIPARTDFTYPEKEEP /*+ Preserve current imbalance +*/ } BdgraphBipartDfType; /*+ Method parameters. +*/ typedef struct BdgraphBipartDfParam_ { INT passnbr; /*+ Number of passes to do +*/ double cdifval; /*+ Coefficient of diffused load +*/ double cremval; /*+ Coefficient of remaining load +*/ BdgraphBipartDfType typeval; /*+ Type of balance to reach +*/ } BdgraphBipartDfParam; /* ** The function prototypes. */ #ifndef BDGRAPH_BIPART_DF #define static #endif int bdgraphBipartDf (Bdgraph * const, const BdgraphBipartDfParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/dgraph_coarsen_edge.c0000644000175300017530000001657511631334325023260 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_coarsen_edge.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This commodity file contains the edge **/ /** arrays building subroutine which is **/ /** duplicated, with minor modifications, **/ /** into dgraph_coarsen.c. **/ /** **/ /** DATES : # Version 5.2 : from : 11 dec 2008 **/ /** to : 11 dec 2008 **/ /** **/ /************************************************************/ /* This routine performs the coarsening of edges ** with respect to the data structures filled to ** date: ** - the coarmulttax array, which contains the ** coarse index of each local or ghost vertex, ** - the edgercvtab array, which contains compacted ** edge data for all of the remote vertices which ** have been sent to us, ** - the vertloctax array, which contains, for ** multinodes which have a remote vertex, the ** index of the degree and coarse end vertex ** data of the coarse remote vertex. */ void DGRAPHCOARSENEDGENAME ( DgraphCoarsenData * restrict const coarptr) { for (coarvertlocnum = coaredgelocnum = coargrafptr->baseval; /* For all coarse vertices (that is, multinodes) */ coarvertlocnum < coarvertlocnnd; coarvertlocnum ++) { if (multloctax[multlocnum].vertglbnum[1] < 0) { /* If second multinode vertex is remote */ edgedatidx = coarvertloctax[coarvertlocnum]; /* Get index of vertex in remote edge array */ coarvertloctax[coarvertlocnum] = coaredgelocnum; /* Set beginning of coarse vertex array */ multloctax[multlocnum].vertglbnum[1] = fineedgeloctax[-2 - multloctax[multlocnum].vertglbnum[1]]; /* Finalize multinode */ for (fineedgegstnum = edgedataidx + 1, fineedgegstnnd = fineedgegstnum + edgercvtab[edgedataidx]; fineedgegstnum < fineedgegstnnd; ) { Gnum coarvertglbend; /* Number of coarse vertex which is end of fine edge */ Gnum h; coarvertglbend = edgercvtab[fineedgegstnum ++]; fineedlogstval = edgercvtab[fineedgegstnum ++]; if (coarvertglbend != coarvertlocnum + coarvertlocadj) { /* If not end of collapsed edge */ for (h = (coarvertglbend * DGRAPHCOARHASHPRIME) & coarhashmsk; ; h = (h + 1) & coarhashmsk) { if (coarhashtab[h].vertorgnum != coarverloctnum) { /* If old slot */ coarhashtab[h].vertorgnum = coarvertlocnum; /* Mark it in reference array */ coarhashtab[h].vertendnum = coarvertglbend; coarhashtab[h].edgelocnum = coaredgelocnum; coaredgeloctax[coaredgelocnum] = coarvertglbend; /* One more edge created */ DGRAPHCOARSENEDGEEDLOINIT; /* Initialize edge load entry */ coaredgelocnum ++; break; /* Give up hashing */ } if (coarhashtab[h].vertendnum == coarvertglbend) { /* If coarse edge already exists */ DGRAPHCOARSENEDGEEDLOADD; /* Accumulate edge load */ break; /* Give up hashing */ } } } else DGRAPHCOARSENEDGEEDLOSUB; } j = 0; /* Will not explore vertglbnum[1] again */ } else { coarvertloctax[coarvertlocnum] = coaredgelocnum; j = 1; } i = 0; do { /* For all fine edges of multinode vertices */ Gnum fineedgenum; finevertnum = coarmulttax[coarvertnum].vertnum[i]; for (fineedgenum = finegrafptr->verttax[finevertnum]; fineedgenum < finegrafptr->vendtax[finevertnum]; fineedgenum ++) { Gnum coarvertend; /* Number of coarse vertex which is end of fine edge */ Gnum h; coarvertend = finecoartax[finegrafptr->edgetax[fineedgenum]]; if (coarvertend != coarvertnum) { /* If not end of collapsed edge */ for (h = (coarvertend * GRAPHCOARHASHPRIME) & coarhashmsk; ; h = (h + 1) & coarhashmsk) { if (coarhashtab[h].vertorgnum != coarvertnum) { /* If old slot */ coarhashtab[h].vertorgnum = coarvertnum; /* Mark it in reference array */ coarhashtab[h].vertendnum = coarvertend; coarhashtab[h].edgenum = coaredgenum; coargrafptr->edgetax[coaredgenum] = coarvertend; /* One more edge created */ GRAPHCOARSENEDGEEDLOINIT; /* Initialize edge load entry */ coaredgenum ++; break; /* Give up hashing */ } if (coarhashtab[h].vertendnum == coarvertend) { /* If coarse edge already exists */ GRAPHCOARSENEDGEEDLOADD; /* Accumulate edge load */ break; /* Give up hashing */ } } } else GRAPHCOARSENEDGEEDLOSUB; } } while (i ++, finevertnum != coarmulttax[coarvertnum].vertnum[1]); /* Skip to next matched vertex if both vertices not equal */ if (coardegrmax < (coaredgenum - coargrafptr->verttax[coarvertnum])) coardegrmax = coaredgenum - coargrafptr->verttax[coarvertnum]; } } scotch-5.1.12b.dfsg/src/libscotch/dgraph_fold_dup.h0000644000175300017530000000727211631334325022435 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_fold_dup.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the distributed graph duplicate **/ /** folding routine. **/ /** **/ /** DATES : # Version 5.0 : from : 13 aug 2006 **/ /** to 13 aug 2006 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the data passed to the subgraph building threads. +*/ typedef struct DgraphFoldDupData_ { const Dgraph * orggrafptr; /*+ Pointer to original graph +*/ Dgraph * fldgrafptr; /*+ Pointer to folded graph +*/ MPI_Comm fldproccomm; /*+ Communicator to be used in folded graph +*/ int partval; /*+ Part of processes to which to fold +*/ void * vertinfoptrin; /*+ info associated to vertices, like coarmulttax +*/ void * vertinfoptrout; /*+ info associated to vertices, like coarmulttax +*/ MPI_Datatype vertinfotype; /*+ MPI type of previous informations +*/ } DgraphFoldDupData; /* ** The function prototypes. */ #ifndef DGRAPH_FOLD_DUP #define static #endif #ifdef SCOTCH_PTHREAD static void * dgraphFoldDup2 (void *); #endif /* SCOTCH_PTHREAD */ #undef static scotch-5.1.12b.dfsg/src/libscotch/kgraph_map_rb.h0000644000175300017530000001244111631334325022102 0ustar hazelscthazelsct/* Copyright 2004,2007,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kgraph_map_rb.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the Dual Recursive Bipartitioning **/ /** mapping algorithm. **/ /** **/ /** DATES : # Version 0.0 : from : 23 mar 1993 **/ /** to 12 may 1993 **/ /** # Version 1.3 : from : 06 apr 1994 **/ /** to 09 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 04 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to 30 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 15 nov 1995 **/ /** to 15 nov 1995 **/ /** # Version 3.2 : from : 01 oct 1996 **/ /** to 10 jun 1998 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to 17 may 1999 **/ /** # Version 3.4 : from : 12 sep 2001 **/ /** to 06 nov 2001 **/ /** # Version 4.0 : from : 29 nov 2003 **/ /** to 05 may 2006 **/ /** # Version 5.1 : from : 07 oct 2008 **/ /** to 28 mar 2011 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ Job selection policy types. +*/ typedef enum KgraphMapRbPolicy_ { KGRAPHMAPRBPOLIRANDOM = 0, /*+ Random job selection policy +*/ KGRAPHMAPRBPOLILEVEL, /*+ Select job with highest level +*/ KGRAPHMAPRBPOLISIZE, /*+ Select job with largest size +*/ KGRAPHMAPRBPOLINEIGHBOR, /*+ Priority level computed with respect to neighbors +*/ KGRAPHMAPRBPOLINGLEVEL, /*+ Select job with most neighbors of higher level +*/ KGRAPHMAPRBPOLINGSIZE, /*+ Select job with most neighbors of smaller size +*/ KGRAPHMAPRBPOLIOLD /*+ Select job in old style (version 2.x) +*/ } KgraphMapRbPolicy; /*+ Method parameters. +*/ typedef struct KgraphMapRbParam_ { int flagjobtie; /*+ Flag set of job pools are tied +*/ int flagmaptie; /*+ Flag set if mappings are tied +*/ KgraphMapRbPolicy polival; /*+ Job selection policy +*/ Strat * strat; /*+ Bipartitioning strategy used +*/ double kbalval; /*+ K-way imbalance ratio +*/ } KgraphMapRbParam; /* ** The function prototypes. */ #ifndef KGRAPH_MAP_RB #define static #endif int kgraphMapRb (Kgraph * const, const KgraphMapRbParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/dgraph_match_scan.c0000644000175300017530000003320511631334325022727 0ustar hazelscthazelsct/* Copyright 2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_match_scan.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines define a generic scanning **/ /** framework for distributed graph **/ /** matching routines. **/ /** **/ /** DATES : # Version 5.2 : from : 04 dec 2008 **/ /** to : 25 dec 2008 **/ /** **/ /************************************************************/ void DGRAPHMATCHSCANNAME ( DgraphMatchData * restrict const mateptr) { Gnum vertlocnnd; Gnum vertlocadj; Gnum edgekptnbr; Gnum queulocnbr; Gnum matelocnbr; /* TRICK: Initial number of local mated vertices, to which are subtracted single multinodes */ Gnum multlocnbr; Gnum probmax; const Dgraph * restrict const grafptr = mateptr->c.finegrafptr; const Gnum * restrict const vertloctax = grafptr->vertloctax; const Gnum * restrict const vendloctax = grafptr->vendloctax; const Gnum * restrict const edgegsttax = grafptr->edgegsttax; Gnum * restrict const queuloctab = mateptr->queuloctab; Gnum * restrict const mategsttax = mateptr->mategsttax; DgraphCoarsenMulti * restrict const multloctab = mateptr->c.multloctab; DGRAPHMATCHSCANINIT probmax = (Gnum) (mateptr->probval * 32768.0); /* Compute integer threshold of proba value */ vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - grafptr->baseval; vertlocnnd = grafptr->vertlocnnd; matelocnbr = mateptr->matelocnbr; multlocnbr = mateptr->c.multlocnbr; edgekptnbr = mateptr->c.edgekptnbr; if (matelocnbr == 0) { /* If initial pass or nothing useful done */ Gnum vertlocnnt; /* End of useable local vertices */ Gnum vertlocnum; memSet (mategsttax + grafptr->baseval, ~0, grafptr->vertlocnbr * sizeof (Gnum)); /* No local vertices matched to date: wipe all unsatisfied queries */ queulocnbr = 0; /* Build queue from scratch */ for (vertlocnum = grafptr->baseval, vertlocnnt = vertlocnnd; vertlocnum < vertlocnnt; vertlocnum ++) { Gnum edgelocnum; Gnum edgelocnnd; Gnum edgeendnbr; Gnum edgefrenbr; Gnum probval; if (mategsttax[vertlocnum] >= 0) /* If vertex has been matched by one of the previous ones, skip it */ continue; #ifdef SCOTCH_DEBUG_DGRAPH2 if (mategsttax[vertlocnum] < -1) { /* Vertex must not be requesting yet */ errorPrint ("dgraphMatchSc: internal error (1)"); return; } #endif /* SCOTCH_DEBUG_DGRAPH2 */ DGRAPHMATCHSCANCOUNTINIT if (probval > probmax) { /* If vertex not active this turn */ queuloctab[queulocnbr ++] = vertlocnum; /* Enqueue it for next time */ continue; /* Skip to next vertex */ } edgelocnum = vertloctax[vertlocnum]; edgelocnnd = vendloctax[vertlocnum]; if ((edgelocnnd - edgelocnum) == 0) { /* If isolated vertex */ while (mategsttax[-- vertlocnnt] != ~0) ; /* Search for first matchable local "neighbor" */ mategsttax[vertlocnum] = (vertlocnnt + vertlocadj); /* At worst we will stop at vertlocnum */ mategsttax[vertlocnnt] = (vertlocnum + vertlocadj); multloctab[multlocnbr].vertglbnum[0] = (vertlocnum + vertlocadj); multloctab[multlocnbr].vertglbnum[1] = (vertlocnnt + vertlocadj); multlocnbr ++; /* One more coarse vertex created (two more local mates) */ edgekptnbr += vendloctax[vertlocnnt] - vertloctax[vertlocnnt]; /* Add edges of other vertex only */ continue; } for (edgeendnbr = edgefrenbr = 0; edgelocnum < edgelocnnd; edgelocnum ++) { /* For all edges, count yet unmatched ends */ Gnum vertgstend; vertgstend = edgegsttax[edgelocnum]; if (mategsttax[vertgstend] == -1) { /* Count relevant free end vertices */ DGRAPHMATCHSCANCOUNTSELECT } if (mategsttax[vertgstend] < 0) /* Count not yet assigned end vertices */ edgeendnbr ++; } if (edgeendnbr <= 0) { /* If vertex has no possible neighbor */ mategsttax[vertlocnum] = /* Create single multinode */ multloctab[multlocnbr].vertglbnum[0] = multloctab[multlocnbr].vertglbnum[1] = vertlocnum + vertlocadj; multlocnbr ++; /* One more coarse vertex created */ matelocnbr --; /* TRICK: But with only one vertex */ edgekptnbr += edgelocnnd - vertloctax[vertlocnum]; continue; } if (edgefrenbr > 0) { /* If vertex has some free neighbor */ Gnum vertgstend; edgefrenbr = intRandVal (edgefrenbr); /* Select one of them randomly */ for (edgelocnum = vertloctax[vertlocnum]; ; edgelocnum ++) { /* Loop again on edges */ #ifdef SCOTCH_DEBUG_DGRAPH2 if (edgelocnum >= edgelocnnd) { errorPrint ("dgraphMatchSc: internal error (2)"); return; } #endif /* SCOTCH_DEBUG_DGRAPH2 */ vertgstend = edgegsttax[edgelocnum]; if (mategsttax[vertgstend] == -1) { /* If free end vertex found */ if (DGRAPHMATCHSCANFINDSELECT) /* If it is the one we want */ break; /* Exit loop */ } } if (vertgstend >= vertlocnnd) { /* If end vertex is a ghost vertex */ queuloctab[queulocnbr ++] = vertlocnum; /* Enqueue vertex for communication processing */ mategsttax[vertlocnum] = -2 - edgelocnum; /* Local vertex index codes edge number */ } else { /* Perform local matching */ mategsttax[vertlocnum] = (vertgstend + vertlocadj); mategsttax[vertgstend] = (vertlocnum + vertlocadj); multloctab[multlocnbr].vertglbnum[0] = (vertlocnum + vertlocadj); multloctab[multlocnbr].vertglbnum[1] = (vertgstend + vertlocadj); multlocnbr ++; /* One more coarse vertex created (two more local mates) */ edgekptnbr += (edgelocnnd - vertloctax[vertlocnum]) + (vendloctax[vertgstend] - vertloctax[vertgstend]) - 2; /* "-2" for collapsed arcs */ } } else queuloctab[queulocnbr ++] = vertlocnum; /* Enqueue vertex for next time */ } } else { /* Vertices to consider are already enqueued */ Gnum queulocnum; Gnum queulocnew; for (queulocnum = queulocnew = 0, queulocnbr = mateptr->queulocnbr; queulocnum < queulocnbr; queulocnum ++) { /* For all vertices in queue */ Gnum vertlocnum; Gnum mategstnum; vertlocnum = queuloctab[queulocnum]; /* Get current vertex */ mategstnum = mategsttax[vertlocnum]; if (mategstnum > -1) /* If already mated */ continue; /* Find another one */ queuloctab[queulocnew ++] = vertlocnum; if (mategstnum < -1) mategsttax[vertlocnum] = -1; } queulocnbr = queulocnew; for (queulocnum = 0; queulocnum < queulocnbr; queulocnum ++) { /* For all vertices in queue */ Gnum vertlocnum; Gnum edgelocnum; Gnum edgelocnnd; Gnum edgeendnbr; Gnum edgefrenbr; Gnum probval; vertlocnum = queuloctab[queulocnum]; /* Get current vertex */ if (mategsttax[vertlocnum] >= 0) /* If already mated */ continue; /* Find another one */ #ifdef SCOTCH_DEBUG_DGRAPH2 if (mategsttax[vertlocnum] < -1) { /* Vertex must not be requesting yet */ errorPrint ("dgraphMatchSc: internal error (3)"); return; } #endif /* SCOTCH_DEBUG_DGRAPH2 */ DGRAPHMATCHSCANCOUNTINIT if (probval > probmax) /* If vertex not active this turn */ continue; /* Keep vertex enqueued and skip to next vertex */ edgelocnum = vertloctax[vertlocnum]; edgelocnnd = vendloctax[vertlocnum]; /* No need to test for isolated vertices this turn */ for (edgeendnbr = edgefrenbr = 0; edgelocnum < edgelocnnd; edgelocnum ++) { /* For all edges, count yet unmatched ends */ Gnum vertgstend; vertgstend = edgegsttax[edgelocnum]; if (mategsttax[vertgstend] == -1) { /* Count free end vertices */ DGRAPHMATCHSCANCOUNTSELECT } if (mategsttax[vertgstend] < 0) /* Count not yet assigned end vertices */ edgeendnbr ++; } if (edgeendnbr <= 0) { /* If vertex has no possible neighbor */ mategsttax[vertlocnum] = /* Create single multinode */ multloctab[multlocnbr].vertglbnum[0] = multloctab[multlocnbr].vertglbnum[1] = vertlocnum + vertlocadj; multlocnbr ++; /* One more coarse vertex created */ matelocnbr --; /* TRICK: But with only one vertex */ edgekptnbr += edgelocnnd - vertloctax[vertlocnum]; continue; } if (edgefrenbr > 0) { /* If vertex has some free neighbor */ Gnum vertgstend; edgefrenbr = intRandVal (edgefrenbr); /* Select one of them randomly */ for (edgelocnum = vertloctax[vertlocnum]; ; edgelocnum ++) { /* Loop again on edges */ #ifdef SCOTCH_DEBUG_DGRAPH2 if (edgelocnum >= edgelocnnd) { errorPrint ("dgraphMatchSc: internal error (4)"); return; } #endif /* SCOTCH_DEBUG_DGRAPH2 */ vertgstend = edgegsttax[edgelocnum]; if (mategsttax[vertgstend] == -1) { /* If free end vertex found */ if (DGRAPHMATCHSCANFINDSELECT) /* If it is the one we want */ break; /* Exit loop */ } } if (vertgstend >= vertlocnnd) /* If end vertex is a ghost vertex */ mategsttax[vertlocnum] = -2 - edgelocnum; /* Local vertex index codes edge number */ else { /* Perform local matching */ mategsttax[vertlocnum] = (vertgstend + vertlocadj); mategsttax[vertgstend] = (vertlocnum + vertlocadj); multloctab[multlocnbr].vertglbnum[0] = (vertlocnum + vertlocadj); multloctab[multlocnbr].vertglbnum[1] = (vertgstend + vertlocadj); multlocnbr ++; /* One more coarse vertex created (two more local mates) */ edgekptnbr += (edgelocnnd - vertloctax[vertlocnum]) + (vendloctax[vertgstend] - vertloctax[vertgstend]) - 1; } } /* Else vertex stays enqueued */ } } mateptr->matelocnbr = matelocnbr + 2 * (multlocnbr - mateptr->c.multlocnbr); /* TRICK: Two times new multinodes, minus single multinode adjustment */ mateptr->queulocnbr = queulocnbr; mateptr->c.multlocnbr = multlocnbr; mateptr->c.edgekptnbr = edgekptnbr; } scotch-5.1.12b.dfsg/src/libscotch/library_graph_base_f.c0000644000175300017530000000623711631334325023433 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_base_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the source graph handling routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 4.0 : from : 22 apr 2004 **/ /** to 23 apr 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the graph handling routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFGRAPHBASE, scotchfgraphbase, ( \ SCOTCH_Graph * const grafptr, \ const SCOTCH_Num * const basenew, \ SCOTCH_Num * const baseold), \ (grafptr, basenew, baseold)) { *baseold = SCOTCH_graphBase (grafptr, *basenew); } scotch-5.1.12b.dfsg/src/libscotch/arch_cmplt.c0000644000175300017530000002266311631334325021424 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_cmplt.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the complete graph **/ /** target architecture. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 23 dec 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 29 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 08 sep 1995 **/ /** # Version 3.1 : from : 11 jun 1996 **/ /** to 11 jun 1996 **/ /** # Version 3.2 : from : 21 sep 1996 **/ /** to 13 may 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 09 jan 2004 **/ /** to 10 mar 2005 **/ /** # Version 5.1 : from : 19 jan 2008 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ARCH_CMPLT #include "module.h" #include "common.h" #include "arch.h" #include "arch_cmplt.h" /******************************************/ /* */ /* These are the complete graph routines. */ /* */ /******************************************/ /* This routine loads the complete ** graph architecture. ** It returns: ** - 0 : if the architecture has been successfully read. ** - !0 : on error. */ int archCmpltArchLoad ( ArchCmplt * restrict const archptr, FILE * restrict const stream) { long numnbr; #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchCmplt) > sizeof (ArchDummy)) || (sizeof (ArchCmpltDom) > sizeof (ArchDomDummy))) { errorPrint ("archCmpltArchLoad: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if ((fscanf (stream, "%ld", &numnbr) != 1) || (numnbr < 1)) { errorPrint ("archCmpltArchLoad: bad input"); return (1); } archptr->numnbr = (Anum) numnbr; return (0); } /* This routine saves the ** complete graph architecture. ** It returns: ** - 0 : if the architecture has been successfully written. ** - !0 : on error. */ int archCmpltArchSave ( const ArchCmplt * const archptr, FILE * restrict const stream) { #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchCmplt) > sizeof (ArchDummy)) || (sizeof (ArchCmpltDom) > sizeof (ArchDomDummy))) { errorPrint ("archCmpltArchSave: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if (fprintf (stream, ANUMSTRING " ", (Anum) archptr->numnbr) == EOF) { errorPrint ("archCmpltArchSave: bad output"); return (1); } return (0); } /* This function returns the smallest number ** of terminal domain included in the given ** domain. */ ArchDomNum archCmpltDomNum ( const ArchCmplt * const archptr, const ArchCmpltDom * const domptr) { return (domptr->nummin); /* Return vertex number */ } /* This function returns the terminal domain associated ** with the given terminal number in the architecture. ** It returns: ** - 0 : if label is valid and domain has been updated. ** - 1 : if label is invalid. ** - 2 : on error. */ int archCmpltDomTerm ( const ArchCmplt * const archptr, ArchCmpltDom * const domptr, const ArchDomNum domnum) { if (domnum < archptr->numnbr) { /* If valid label */ domptr->nummin = domnum; /* Set the domain */ domptr->numnbr = 1; return (0); } return (1); /* Cannot set domain */ } /* This function returns the number of ** elements in the complete domain. */ Anum archCmpltDomSize ( const ArchCmplt * const archptr, const ArchCmpltDom * const domptr) { return (domptr->numnbr); } /* This function returns the average ** distance between two complete ** subdomains. */ Anum archCmpltDomDist ( const ArchCmplt * const archptr, const ArchCmpltDom * const dom0ptr, const ArchCmpltDom * const dom1ptr) { return (((dom0ptr->nummin == dom1ptr->nummin) && /* All domains are at distance 1 */ (dom0ptr->numnbr == dom1ptr->numnbr)) ? 0 : 1); /* If they are different */ } /* This function sets the biggest ** domain available for this ** architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archCmpltDomFrst ( const ArchCmplt * const archptr, ArchCmpltDom * restrict const domptr) { domptr->nummin = 0; domptr->numnbr = archptr->numnbr; return (0); } /* This routine reads domain information ** from the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archCmpltDomLoad ( const ArchCmplt * const archptr, ArchCmpltDom * restrict const domptr, FILE * const stream) { long nummin; long numnbr; if ((fscanf (stream, "%ld%ld", &nummin, &numnbr) != 2) || (numnbr < 1) || (numnbr + nummin > (long) archptr->numnbr)) { errorPrint ("archCmpltDomLoad: bad input"); return (1); } domptr->nummin = (Anum) nummin; domptr->numnbr = (Anum) numnbr; return (0); } /* This routine saves domain information ** to the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archCmpltDomSave ( const ArchCmplt * const archptr, const ArchCmpltDom * const domptr, FILE * const stream) { if (fprintf (stream, ANUMSTRING " " ANUMSTRING " ", (Anum) domptr->nummin, (Anum) domptr->numnbr) == EOF) { errorPrint ("archCmpltDomSave: bad output"); return (1); } return (0); } /* This function tries to split a complete ** graph domain into two subdomains. ** It returns: ** - 0 : if bipartitioning succeeded. ** - 1 : if bipartitioning could not be performed. ** - 2 : on error. */ int archCmpltDomBipart ( const ArchCmplt * const archptr, const ArchCmpltDom * const domptr, ArchCmpltDom * restrict const dom0ptr, ArchCmpltDom * restrict const dom1ptr) { if (domptr->numnbr <= 1) /* Return if cannot bipartition more */ return (1); dom0ptr->nummin = domptr->nummin; /* Bipartition vertices */ dom0ptr->numnbr = domptr->numnbr / 2; dom1ptr->nummin = domptr->nummin + dom0ptr->numnbr; dom1ptr->numnbr = domptr->numnbr - dom0ptr->numnbr; return (0); } /* This function creates the MPI_Datatype for ** complete graph domains. ** It returns: ** - 0 : if type could be created. ** - 1 : on error. */ #ifdef SCOTCH_PTSCOTCH int archCmpltDomMpiType ( const ArchCmplt * const archptr, MPI_Datatype * const typeptr) { MPI_Type_contiguous (2, ANUM_MPI, typeptr); return (0); } #endif /* SCOTCH_PTSCOTCH */ scotch-5.1.12b.dfsg/src/libscotch/dgraph_match_sync_coll.c0000644000175300017530000005205211631334325023771 0ustar hazelscthazelsct/* Copyright 2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_match_sync_coll.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This routine synchronizes the fragments **/ /** of a distributed matching by means of **/ /** collective communications. **/ /** **/ /** DATES : # Version 5.1 : from : 06 feb 2009 **/ /** to : 22 apr 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH_MATCH #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_coarsen.h" #include "dgraph_match.h" /*************************************/ /* */ /* These routines handle distributed */ /* source graphs. */ /* */ /*************************************/ /* This routine performs a round of communication ** to synchronize enqueued matching requests across ** processors. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphMatchSyncColl ( DgraphMatchData * restrict const mateptr) { Gnum queulocnbr; Gnum queulocnum; Gnum matelocnbr; Gnum multlocnbr; Gnum vertlocadj; Gnum edgekptnbr; int procngbnbr; int procngbidx; int procngbnum; int * restrict vsndcnttab; int * restrict vrcvcnttab; int * restrict vsnddsptab; int * restrict vrcvdsptab; Dgraph * restrict const grafptr = mateptr->c.finegrafptr; const int * restrict const procngbtab = grafptr->procngbtab; int * restrict const procgsttax = mateptr->c.procgsttax; const Gnum * restrict const procvgbtab = mateptr->procvgbtab; const Gnum * restrict const vertloctax = grafptr->vertloctax; const Gnum * restrict const vendloctax = grafptr->vendloctax; const Gnum * restrict const edgeloctax = grafptr->edgeloctax; const Gnum * restrict const edgegsttax = grafptr->edgegsttax; Gnum * restrict const queuloctab = mateptr->queuloctab; Gnum * restrict const mategsttax = mateptr->mategsttax; DgraphCoarsenMulti * restrict const multloctab = mateptr->c.multloctab; int * restrict const nsndidxtab = mateptr->c.nsndidxtab; DgraphCoarsenVert * const vsnddattab = mateptr->c.vsnddattab; /* [norestrict:async] */ procngbnbr = grafptr->procngbnbr; #ifdef SCOTCH_DEBUG_DGRAPH2 if (edgeloctax == NULL) { errorPrint ("dgraphMatchSyncColl: not implemented"); return (1); } if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphMatchSyncColl: communication error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if ((vsnddsptab = memAlloc (4 * grafptr->procglbnbr * sizeof (int))) == NULL) { errorPrint ("dgraphMatchSyncColl: out of memory"); return (1); } vsndcnttab = vsnddsptab + grafptr->procglbnbr; /* TRICK: put vsnddsptab, vsndcnttab, vrcvdsptab in order for memSet() */ vrcvdsptab = vsndcnttab + grafptr->procglbnbr; vrcvcnttab = vrcvdsptab + grafptr->procglbnbr; for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) /* Reset indices for sending messages */ nsndidxtab[procngbnum] = mateptr->c.vsnddsptab[procngbtab[procngbnum]]; vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - grafptr->baseval; for (queulocnum = 0, queulocnbr = mateptr->queulocnbr; queulocnum < queulocnbr; queulocnum ++) { Gnum vertlocnum; Gnum vertgstnum; Gnum edgelocnum; Gnum mategstnum; Gnum mateglbnum; int procngbnum; int vsndidxnum; vertlocnum = queuloctab[queulocnum]; /* Get local vertex index */ mategstnum = mategsttax[vertlocnum]; /* Get mate (edge ?) index */ if (mategstnum >= -1) /* If vertex not willing to mate or matched locally after being considered during matching phase */ continue; edgelocnum = -2 - mategstnum; /* Get local edge to mate ghost vertex */ #ifdef SCOTCH_DEBUG_DGRAPH2 if ((edgelocnum < grafptr->baseval) || (edgelocnum >= (grafptr->edgelocsiz + grafptr->baseval)) || (mategsttax[edgegsttax[edgelocnum]] != -1)) { errorPrint ("dgraphMatchSyncColl: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ mateglbnum = edgeloctax[edgelocnum]; vertgstnum = edgegsttax[edgelocnum]; procngbnum = procgsttax[vertgstnum]; /* Find neighbor owner process */ if (procngbnum < 0) { /* If neighbor not yet computed */ int procngbmax; procngbnum = 0; procngbmax = procngbnbr; while ((procngbmax - procngbnum) > 1) { /* Find owner process by dichotomy on procvgbtab */ int procngbmed; procngbmed = (procngbmax + procngbnum) / 2; if (procvgbtab[procngbmed] > mateglbnum) procngbmax = procngbmed; else procngbnum = procngbmed; } procgsttax[vertgstnum] = procngbnum; } #ifdef SCOTCH_DEBUG_DGRAPH2 if ((grafptr->procvrttab[procngbtab[procngbnum]] > mateglbnum) || (grafptr->procvrttab[procngbtab[procngbnum] + 1] <= mateglbnum)) { errorPrint ("dgraphMatchSyncColl: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ vsndidxnum = nsndidxtab[procngbnum] ++; /* Get position of message in send array */ #ifdef SCOTCH_DEBUG_DGRAPH2 if (vsndidxnum >= mateptr->c.vsnddsptab[procngbtab[procngbnum] + 1]) { errorPrint ("dgraphMatchSyncColl: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ vsnddattab[vsndidxnum].datatab[0] = vertlocnum + vertlocadj; vsnddattab[vsndidxnum].datatab[1] = mateglbnum; } memSet (vsnddsptab, 0, 3 * grafptr->procglbnbr * sizeof (int)); /* TRICK: resets vsnddsptab, vsndcnttab, vrcvdsptab */ for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) { int procglbnum; procglbnum = procngbtab[procngbnum]; vrcvdsptab[procglbnum] = 2 * mateptr->c.vrcvdsptab[procglbnum]; /* Times 2 because a "DgraphCoarsenVert" is two "Gnum"s */ vsnddsptab[procglbnum] = 2 * mateptr->c.vsnddsptab[procglbnum]; vsndcnttab[procglbnum] = 2 * (nsndidxtab[procngbnum] - mateptr->c.vsnddsptab[procglbnum]); } if (MPI_Alltoall (vsndcnttab, 1, MPI_INT, vrcvcnttab, 1, MPI_INT, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphMatchSyncColl: communication error (2)"); return (1); } if (MPI_Alltoallv (vsnddattab, vsndcnttab, vsnddsptab, GNUM_MPI, mateptr->c.vrcvdattab, vrcvcnttab, vrcvdsptab, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphMatchSyncColl: communication error (3)"); return (1); } matelocnbr = mateptr->matelocnbr; multlocnbr = mateptr->c.multlocnbr; edgekptnbr = mateptr->c.edgekptnbr; for (procngbidx = 0; procngbidx < procngbnbr; procngbidx ++) { int procngbnum; int procglbnum; int vrcvidxnnd; int requrcvnum; int requnxtnum; /* Index of location where to pack requests to process when all messages arrive */ procngbnum = (procngbidx + mateptr->c.procngbnxt) % procngbnbr; procglbnum = procngbtab[procngbnum]; vrcvidxnnd = mateptr->c.vrcvdsptab[procglbnum]; if (vrcvcnttab[procglbnum] > 0) { /* If query message is not empty */ Gnum vertsndnbr; /* Number of vertices to be sent to requesting neighbor */ Gnum edgesndnbr; /* Number of edges to be sent to requesting neighbor */ DgraphCoarsenVert * restrict const vrcvdattab = mateptr->c.vrcvdattab; /* Local restrict pointer only when data available */ vertsndnbr = edgesndnbr = 0; for (requrcvnum = requnxtnum = vrcvidxnnd, vrcvidxnnd += (vrcvcnttab[procglbnum] / 2); /* TRICK: each message item costs 2 Gnum's */ requrcvnum < vrcvidxnnd; requrcvnum ++) { Gnum vertglbnum; /* Our global number (the one seen as mate by sender) */ Gnum vertlocnum; /* Our local number (the one seen as mate by sender) */ Gnum vmatglbnum; /* Global number of requesting mate (sender of message) */ Gnum mategstnum; /* The mate we wanted to ask for */ vmatglbnum = vrcvdattab[requrcvnum].datatab[0]; /* Names are opposite because receiving side */ vertglbnum = vrcvdattab[requrcvnum].datatab[1]; vertlocnum = vertglbnum - vertlocadj; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((vertlocnum < grafptr->baseval) || /* If matching request is not directed towards our process */ (vertlocnum >= grafptr->vertlocnnd)) { errorPrint ("dgraphMatchSyncColl: internal error (5)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ mategstnum = mategsttax[vertlocnum]; /* Get our local mating decision data */ if (mategstnum == -1) { /* If local vertex wanted for mating is free */ Gnum edgelocnum; for (edgelocnum = vertloctax[vertlocnum]; edgeloctax[edgelocnum] != vmatglbnum; edgelocnum ++) { #ifdef SCOTCH_DEBUG_DGRAPH2 if (edgelocnum >= vendloctax[vertlocnum]) { errorPrint ("dgraphMatchSyncColl: internal error (6)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ } mategsttax[edgegsttax[edgelocnum]] = vertglbnum; /* We are no longer free */ mategsttax[vertlocnum] = vmatglbnum; /* Leave message as is to acknowledge it */ matelocnbr ++; vertsndnbr ++; edgesndnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; } else if (mategstnum < -1) { /* If local vertex is also asking for mating */ Gnum edgelocnum; Gnum mateglbnum; edgelocnum = -2 - mategstnum; mateglbnum = edgeloctax[edgelocnum]; /* Get global number of our remote mate */ if (mateglbnum == vmatglbnum) { /* If it is with the sender */ Gnum flagval; /* Flag for choosing side to create multinode */ mategsttax[vertlocnum] = mateglbnum; /* Say we are mated to inform future requesting processes in same pass */ mategsttax[edgegsttax[edgelocnum]] = vertglbnum; flagval = (mateglbnum > vertglbnum) ? 1 : 0; /* Compute pseudo-random flag always opposite for both ends */ flagval = ((mateglbnum + (mateglbnum - vertglbnum) * flagval) & 1) ^ flagval; if (flagval == 0) { /* If flag is even, create multinode */ multloctab[multlocnbr].vertglbnum[0] = vertglbnum; multloctab[multlocnbr].vertglbnum[1] = mategstnum; /* Remote mate: negative value */ multlocnbr ++; /* One more coarse vertex created */ edgekptnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; } else { /* If flag is odd, prepare to send vertex data at build time */ vertsndnbr ++; edgesndnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; } /* Go on by destroying message in all cases since both ends know what it is about */ vrcvdattab[requrcvnum --] = vrcvdattab[-- vrcvidxnnd]; /* Replace current message with another one and process it */ matelocnbr ++; /* One more local vertex mated on each side; no messages will tell it */ } else { /* If willing to mate but not with the sender, tell later with whom */ DgraphCoarsenVert vertdat; /* Temporary storage data for swapping vertices */ vertdat = vrcvdattab[requnxtnum]; /* Pack requests to process later at beginning of message */ vrcvdattab[requnxtnum].datatab[0] = vmatglbnum; vrcvdattab[requnxtnum].datatab[1] = -2 - vertlocnum; /* Build appropriate answer to mating request later, when all messages arrived */ if (requnxtnum ++ != requrcvnum) vrcvdattab[requrcvnum] = vertdat; /* Swap vertices if not already at the right place */ } } else /* If already matched, inform sender */ vrcvdattab[requrcvnum].datatab[1] = mategstnum; } mateptr->c.dcntloctab[procglbnum].vertsndnbr += vertsndnbr; mateptr->c.dcntloctab[procglbnum].edgesndnbr += edgesndnbr; } mateptr->c.nrcvidxtab[procngbnum] = vrcvidxnnd; } for (procngbidx = 0; procngbidx < procngbnbr; procngbidx ++) { int procngbnum; int procglbnum; int vsndidxnnd; int vsndidxnum; DgraphCoarsenVert * restrict const vrcvdattab = mateptr->c.vrcvdattab; /* Local restrict pointer only once data received */ procngbnum = (procngbidx + mateptr->c.procngbnxt) % procngbnbr; procglbnum = procngbtab[procngbnum]; vsndidxnnd = mateptr->c.nrcvidxtab[procngbnum]; /* Re-send the messages we have received to acknowledge */ for (vsndidxnum = mateptr->c.vrcvdsptab[procglbnum]; /* Finalize unfinished messages */ vsndidxnum < vsndidxnnd; vsndidxnum ++) { Gnum vertlocnum; Gnum mateglbnum; vertlocnum = vrcvdattab[vsndidxnum].datatab[1]; if (vertlocnum >= 0) /* If no more unfinished messages to process, quit scanning */ break; vertlocnum = -2 - vertlocnum; mateglbnum = mategsttax[vertlocnum]; if (mateglbnum >= 0) /* If vertex we wanted to mate with has been mated in this round */ vrcvdattab[vsndidxnum].datatab[1] = mateglbnum; /* Propagate this information back to the requester */ else { /* Vertex mating data not yet available (maybe in answer) */ vrcvdattab[vsndidxnum] = vrcvdattab[-- vsndidxnnd]; /* Remove message as no reply means not willing */ if (vrcvdattab[vsndidxnum].datatab[1] < 0) /* If replacing message is also to be processed */ vsndidxnum --; /* Do not skip replaced message in next iteration */ } } if (vsndidxnnd < (mateptr->c.vrcvdsptab[procglbnum] + (vrcvcnttab[procglbnum] / 2))) { /* If space created */ vrcvdattab[vsndidxnnd].datatab[0] = /* Indicate end of useful data */ vrcvdattab[vsndidxnnd].datatab[1] = -1; } } if (MPI_Alltoallv (mateptr->c.vrcvdattab, vrcvcnttab, vrcvdsptab, GNUM_MPI, vsnddattab, vsndcnttab, vsnddsptab, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphMatchSyncColl: communication error (3)"); return (1); } for (procngbidx = 0; procngbidx < procngbnbr; procngbidx ++) { int procngbnum; int procglbnum; int vrcvidxnnd; int vrcvidxnum; procngbnum = (procngbidx + mateptr->c.procngbnxt) % procngbnbr; procglbnum = procngbtab[procngbnum]; for (vrcvidxnum = mateptr->c.vsnddsptab[procglbnum], vrcvidxnnd = vrcvidxnum + (vsndcnttab[procglbnum] / 2); /* TRICK: each message item costs 2 Gnum's */ vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { Gnum edgelocnum; Gnum vertglbnum; /* Our global number (the one seen as mate by sender) */ Gnum vertlocnum; /* Our local number (the one seen as mate by sender) */ Gnum vmatglbnum; /* Global number of vertex to which the mate is mated */ Gnum mategstnum; /* The mate we wanted to ask for */ vertglbnum = vsnddattab[vrcvidxnum].datatab[0]; if (vertglbnum == -1) /* If end of useful space reached */ break; vmatglbnum = vsnddattab[vrcvidxnum].datatab[1]; vertlocnum = vertglbnum - vertlocadj; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((vertlocnum < grafptr->baseval) || /* If matching reply is not directed towards our process */ (vertlocnum >= grafptr->vertlocnnd)) { errorPrint ("dgraphMatchSyncColl: internal error (8)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ mategstnum = mategsttax[vertlocnum]; /* Get our local mating decision data */ edgelocnum = -2 - mategstnum; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((mategstnum >= -1) || /* If we did not ask anything or if we were already matched, no reply message should come to us */ ((mategsttax[edgegsttax[edgelocnum]] >= 0) && /* Also, if our prospective mate was itself already set as matched by a previous reply */ (mategsttax[edgegsttax[edgelocnum]] != vertglbnum) && /* And this message is not the positive reply which acknowledges this mating */ (mategsttax[edgegsttax[edgelocnum]] != vmatglbnum))) { /* Or an informative negative reply which gives again the mate of the ghost */ errorPrint ("dgraphMatchSyncColl: internal error (9)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (edgeloctax[edgelocnum] == vmatglbnum) { /* If positive answer from the mate we wanted */ mategsttax[vertlocnum] = vmatglbnum; /* Set local vertex as matched with the mate */ mategsttax[edgegsttax[edgelocnum]] = vertglbnum; /* Update state of ghost mate */ multloctab[multlocnbr].vertglbnum[0] = vertglbnum; multloctab[multlocnbr].vertglbnum[1] = mategstnum; /* Remote mate: negative value */ multlocnbr ++; /* One more coarse vertex created */ matelocnbr ++; edgekptnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; } else { /* If negative answer from the mate we wanted */ mategsttax[vertlocnum] = -1; /* Reset local vertex as free for mating */ mategsttax[edgegsttax[edgelocnum]] = vmatglbnum; /* Update state of unwilling ghost mate */ } } } mateptr->matelocnbr = matelocnbr; mateptr->c.multlocnbr = multlocnbr; mateptr->c.edgekptnbr = edgekptnbr; #ifdef SCOTCH_DEBUG_DGRAPH2 if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphMatchSyncColl: communication error (11)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ memFree (vsnddsptab); return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_scatter.c0000644000175300017530000000654511631334325024027 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_scatter.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted source graph handling routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 28 apr 2006 **/ /** to 12 jul 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "graph.h" #include "dgraph.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the graph handling routines. */ /* */ /************************************/ /*+ This routine scatters the data of a *** centralized graph on a distributed graph. *** It returns: *** - 0 : if the scattering succeeded. *** - !0 : on error. +*/ int SCOTCH_dgraphScatter ( SCOTCH_Dgraph * const dgrfptr, const SCOTCH_Graph * const cgrfptr) { const Graph * srccgrfptr; srccgrfptr = (((void *) cgrfptr) == ((void *) dgrfptr)) ? NULL : (const Graph *) cgrfptr; /* Consider same pointers as flag for non-root process */ return (dgraphScatter ((Dgraph *) dgrfptr, srccgrfptr)); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_halo_f.c0000644000175300017530000001106611631334325023604 0ustar hazelscthazelsct/* Copyright 2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_halo_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the distributed source graph handling **/ /** routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 17 jul 2007 **/ /** to 02 aug 2007 **/ /** # Version 5.1 : from : 09 may 2009 **/ /** to 10 may 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the distributed graph handling */ /* routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFDGRAPHGHST, scotchfdgraphghst, ( \ SCOTCH_Dgraph * const grafptr, \ int * const revaptr), \ (grafptr, revaptr)) { *revaptr = SCOTCH_dgraphGhst (grafptr); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHHALO, scotchfdgraphhalo, ( \ SCOTCH_Dgraph * const grafptr, \ void * const datatab, \ MPI_Fint * const typeptr, \ int * const revaptr), \ (grafptr, datatab, typeptr, revaptr)) { MPI_Datatype typeval; typeval = MPI_Type_f2c (*typeptr); *revaptr = SCOTCH_dgraphHalo (grafptr, datatab, typeval); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHHALOASYNC, scotchfdgraphhaloasync, ( \ SCOTCH_Dgraph * const grafptr, \ void * const datatab, \ MPI_Fint * const typeptr, \ SCOTCH_DgraphHaloReq * const requptr, \ int * const revaptr), \ (grafptr, datatab, typeptr, requptr, revaptr)) { MPI_Datatype typeval; typeval = MPI_Type_f2c (*typeptr); *revaptr = SCOTCH_dgraphHaloAsync (grafptr, datatab, typeval, requptr); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHHALOWAIT, scotchfdgraphhalowait, ( \ SCOTCH_DgraphHaloReq * const requptr, \ int * const revaptr), \ (requptr, revaptr)) { *revaptr = SCOTCH_dgraphHaloWait (requptr); } scotch-5.1.12b.dfsg/src/libscotch/arch_mesh.c0000644000175300017530000005420011631334325021231 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_mesh.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the mesh graph **/ /** target architectures. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 23 dec 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 29 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 08 sep 1995 **/ /** # Version 3.1 : from : 22 jul 1996 **/ /** to 23 jul 1996 **/ /** # Version 3.2 : from : 16 oct 1996 **/ /** to 14 may 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 09 jan 2004 **/ /** to 10 mar 2005 **/ /** # Version 5.1 : from : 21 jan 2008 **/ /** to 11 aug 2010 **/ /** **/ /** NOTES : # The vertices of the (dX,dY) mesh are **/ /** numbered as terminals so that **/ /** t(0,0) = 0, t(1,0) = 1, **/ /** t(dX - 1, 0) = dX - 1, t(0,1) = dX, **/ /** and t(x,y) = (y * dX) + x. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ARCH_MESH #include "module.h" #include "common.h" #include "arch.h" #include "arch_mesh.h" /***********************************************/ /* */ /* These are the 2-dimensional mesh routines. */ /* */ /***********************************************/ /* This routine loads the ** bidimensional mesh architecture. ** It returns: ** - 0 : if the architecture has been successfully read. ** - !0 : on error. */ int archMesh2ArchLoad ( ArchMesh2 * restrict const archptr, FILE * restrict const stream) { #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchMesh2) > sizeof (ArchDummy)) || (sizeof (ArchMesh2Dom) > sizeof (ArchDomDummy))) { errorPrint ("archMesh2ArchLoad: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if ((intLoad (stream, &archptr->c[0]) != 1) || (intLoad (stream, &archptr->c[1]) != 1) || (archptr->c[0] < 1) || (archptr->c[1] < 1)) { errorPrint ("archMesh2ArchLoad: bad input"); return (1); } return (0); } /* This routine saves the ** bidimensional mesh architecture. ** It returns: ** - 0 : if the architecture has been successfully written. ** - !0 : on error. */ int archMesh2ArchSave ( const ArchMesh2 * const archptr, FILE * restrict const stream) { #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchMesh2) > sizeof (ArchDummy)) || (sizeof (ArchMesh2Dom) > sizeof (ArchDomDummy))) { errorPrint ("archMesh2ArchSave: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if (fprintf (stream, ANUMSTRING " " ANUMSTRING " ", (Anum) archptr->c[0], (Anum) archptr->c[1]) == EOF) { errorPrint ("archMesh2ArchSave: bad output"); return (1); } return (0); } /* This function returns the smallest number ** of terminal domain included in the given ** domain. */ ArchDomNum archMesh2DomNum ( const ArchMesh2 * const archptr, const ArchMesh2Dom * const domptr) { return ((domptr->c[1][0] * archptr->c[0]) + domptr->c[0][0]); /* Return vertex number */ } /* This function returns the terminal domain associated ** with the given terminal number in the architecture. ** It returns: ** - 0 : if label is valid and domain has been updated. ** - 1 : if label is invalid. ** - 2 : on error. */ int archMesh2DomTerm ( const ArchMesh2 * const archptr, ArchMesh2Dom * const domptr, const ArchDomNum domnum) { if (domnum < (archptr->c[0] * archptr->c[1])) { /* If valid label */ domptr->c[0][0] = /* Set the domain */ domptr->c[0][1] = domnum % archptr->c[0]; domptr->c[1][0] = domptr->c[1][1] = domnum / archptr->c[0]; return (0); } return (1); /* Cannot set domain */ } /* This function returns the number of ** elements in the rectangular domain. */ Anum archMesh2DomSize ( const ArchMesh2 * const archptr, const ArchMesh2Dom * const domptr) { return ((domptr->c[0][1] - domptr->c[0][0] + 1) * (domptr->c[1][1] - domptr->c[1][0] + 1)); } /* This function returns the average ** distance between two rectangular ** domains (in fact the distance between ** the centers of the domains). */ Anum archMesh2DomDist ( const ArchMesh2 * const archptr, const ArchMesh2Dom * const dom0ptr, const ArchMesh2Dom * const dom1ptr) { return (((abs (dom0ptr->c[0][0] + dom0ptr->c[0][1] - dom1ptr->c[0][0] - dom1ptr->c[0][1]) + 1) / 2) + ((abs (dom0ptr->c[1][0] + dom0ptr->c[1][1] - dom1ptr->c[1][0] - dom1ptr->c[1][1]) + 1) / 2)); } /* This function sets the biggest ** domain available for this ** architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archMesh2DomFrst ( const ArchMesh2 * const archptr, ArchMesh2Dom * restrict const domptr) { domptr->c[0][0] = domptr->c[1][0] = 0; domptr->c[0][1] = archptr->c[0] - 1; domptr->c[1][1] = archptr->c[1] - 1; return (0); } /* This routine reads domain information ** from the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archMesh2DomLoad ( const ArchMesh2 * const archptr, ArchMesh2Dom * restrict const domptr, FILE * restrict const stream) { if ((intLoad (stream, &domptr->c[0][0]) != 1) || (intLoad (stream, &domptr->c[1][0]) != 1) || (intLoad (stream, &domptr->c[0][1]) != 1) || (intLoad (stream, &domptr->c[1][1]) != 1)) { errorPrint ("archMesh2DomLoad: bad input"); return (1); } return (0); } /* This routine saves domain information ** to the given stream. ** - 0 : on success. ** - !0 : on error. */ int archMesh2DomSave ( const ArchMesh2 * const archptr, const ArchMesh2Dom * const domptr, FILE * restrict const stream) { if (fprintf (stream, ANUMSTRING " " ANUMSTRING " " ANUMSTRING " " ANUMSTRING " ", (Anum) domptr->c[0][0], (Anum) domptr->c[1][0], (Anum) domptr->c[0][1], (Anum) domptr->c[1][1]) == EOF) { errorPrint ("archMesh2DomSave: bad output"); return (1); } return (0); } /* These functions try to split a rectangular ** domain into two subdomains. ** It returns: ** - 0 : if bipartitioning succeeded. ** - 1 : if bipartitioning could not be performed. ** - 2 : on error. */ int archMesh2DomBipart ( const ArchMesh2 * const archptr, const ArchMesh2Dom * const domptr, ArchMesh2Dom * restrict const dom0ptr, ArchMesh2Dom * restrict const dom1ptr) { Anum dimsiz[2]; int dimval; /* Dimension along which to split */ dimsiz[0] = domptr->c[0][1] - domptr->c[0][0]; dimsiz[1] = domptr->c[1][1] - domptr->c[1][0]; if ((dimsiz[0] | dimsiz[1]) == 0) /* Return if cannot bipartition more */ return (1); dimval = 1; if ((dimsiz[0] > dimsiz[1]) || /* Split domain in two along largest dimension */ ((dimsiz[0] == dimsiz[1]) && (archptr->c[0] > archptr->c[1]))) dimval = 0; if (dimval == 0) { /* Split across the X dimension */ dom0ptr->c[0][0] = domptr->c[0][0]; dom0ptr->c[0][1] = (domptr->c[0][0] + domptr->c[0][1]) / 2; dom1ptr->c[0][0] = dom0ptr->c[0][1] + 1; dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; } else { /* Split across the Y dimension */ dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = (domptr->c[1][0] + domptr->c[1][1]) / 2; dom1ptr->c[1][0] = dom0ptr->c[1][1] + 1; dom1ptr->c[1][1] = domptr->c[1][1]; } return (0); } int archMesh2DomBipartO ( const ArchMesh2 * const archptr, const ArchMesh2Dom * const domptr, ArchMesh2Dom * restrict const dom0ptr, ArchMesh2Dom * restrict const dom1ptr) { if ((domptr->c[0][0] == domptr->c[0][1]) && /* Return if cannot bipartition more */ (domptr->c[1][0] == domptr->c[1][1])) return (1); if (domptr->c[1][1] == domptr->c[1][0]) { /* If the Y dimension cannot be cut */ dom0ptr->c[0][0] = domptr->c[0][0]; /* Cut in the X dimension */ dom0ptr->c[0][1] = (domptr->c[0][0] + domptr->c[0][1]) / 2; dom1ptr->c[0][0] = dom0ptr->c[0][1] + 1; dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; } else { /* If the Y dimension can be cut, cut it */ dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = (domptr->c[1][0] + domptr->c[1][1]) / 2; dom1ptr->c[1][0] = dom0ptr->c[1][1] + 1; dom1ptr->c[1][1] = domptr->c[1][1]; } return (0); } int archMesh2DomBipartU ( const ArchMesh2 * const archptr, const ArchMesh2Dom * const domptr, ArchMesh2Dom * restrict const dom0ptr, ArchMesh2Dom * restrict const dom1ptr) { if ((domptr->c[0][0] == domptr->c[0][1]) && /* Return if cannot bipartition more */ (domptr->c[1][0] == domptr->c[1][1])) return (1); if ((domptr->c[0][1] - domptr->c[0][0]) > /* Split domain unevenly along largest dimension */ (domptr->c[1][1] - domptr->c[1][0])) { dom0ptr->c[0][0] = domptr->c[0][0]; dom0ptr->c[0][1] = (domptr->c[0][0] + domptr->c[0][1] + domptr->c[0][1]) / 3; dom1ptr->c[0][0] = dom0ptr->c[0][1] + 1; dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; } else { dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = (domptr->c[1][0] + domptr->c[1][1] + domptr->c[1][1]) / 3; dom1ptr->c[1][0] = dom0ptr->c[1][1] + 1; dom1ptr->c[1][1] = domptr->c[1][1]; } return (0); } /* This function creates the MPI_Datatype for ** 2D mesh domains. ** It returns: ** - 0 : if type could be created. ** - 1 : on error. */ #ifdef SCOTCH_PTSCOTCH int archMesh2DomMpiType ( const ArchMesh2 * const archptr, MPI_Datatype * const typeptr) { MPI_Type_contiguous (4, ANUM_MPI, typeptr); return (0); } #endif /* SCOTCH_PTSCOTCH */ /***********************************************/ /* */ /* These are the 3-dimensional mesh routines. */ /* */ /***********************************************/ /* This routine loads the ** tridimensional mesh architecture. ** It returns: ** - 0 : if the architecture has been successfully read. ** - !0 : on error. */ int archMesh3ArchLoad ( ArchMesh3 * restrict const archptr, FILE * restrict const stream) { #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchMesh3) > sizeof (ArchDummy)) || (sizeof (ArchMesh3Dom) > sizeof (ArchDomDummy))) { errorPrint ("archMesh3ArchLoad: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if ((intLoad (stream, &archptr->c[0]) != 1) || (intLoad (stream, &archptr->c[1]) != 1) || (intLoad (stream, &archptr->c[2]) != 1) || (archptr->c[0] < 1) || (archptr->c[1] < 1) || (archptr->c[2] < 1)) { errorPrint ("archMesh3ArchLoad: bad input"); return (1); } return (0); } /* This routine saves the ** tridimensional mesh architecture. ** It returns: ** - 0 : if the architecture has been successfully written. ** - !0 : on error. */ int archMesh3ArchSave ( const ArchMesh3 * const archptr, FILE * restrict const stream) { #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchMesh3) > sizeof (ArchDummy)) || (sizeof (ArchMesh3Dom) > sizeof (ArchDomDummy))) { errorPrint ("archMesh3ArchSave: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if (fprintf (stream, ANUMSTRING " " ANUMSTRING " " ANUMSTRING " ", (Anum) archptr->c[0], (Anum) archptr->c[1], (Anum) archptr->c[2]) == EOF) { errorPrint ("archMesh3ArchSave: bad output"); return (1); } return (0); } /* This function returns the smallest number ** of terminal domain included in the given ** domain. */ ArchDomNum archMesh3DomNum ( const ArchMesh3 * const archptr, const ArchMesh3Dom * const domptr) { return ((((domptr->c[2][0] * archptr->c[1]) + /* Return the vertex number */ domptr->c[1][0]) * archptr->c[0]) + domptr->c[0][0]); } /* This function returns the terminal domain associated ** with the given terminal number in the architecture. ** It returns: ** - 0 : if label is valid and domain has been updated. ** - 1 : if label is invalid. ** - 2 : on error. */ int archMesh3DomTerm ( const ArchMesh3 * const archptr, ArchMesh3Dom * const domptr, const ArchDomNum domnum) { if (domnum < (archptr->c[0] * archptr->c[1] * archptr->c[2])) { /* If valid label */ domptr->c[0][0] = /* Set the domain */ domptr->c[0][1] = domnum % archptr->c[0]; domptr->c[1][0] = domptr->c[1][1] = (domnum / archptr->c[0]) % archptr->c[1]; domptr->c[2][0] = domptr->c[2][1] = domnum / (archptr->c[0] * archptr->c[1]); return (0); } return (1); /* Cannot set domain */ } /* This function returns the number of ** elements in the cubic domain. */ Anum archMesh3DomSize ( const ArchMesh3 * const archptr, const ArchMesh3Dom * const domptr) { return ((domptr->c[0][1] - domptr->c[0][0] + 1) * (domptr->c[1][1] - domptr->c[1][0] + 1) * (domptr->c[2][1] - domptr->c[2][0] + 1)); } /* This function returns the average distance ** between two cubic domains (in fact the ** distance between the centers of the domains). */ Anum archMesh3DomDist ( const ArchMesh3 * const archptr, const ArchMesh3Dom * const dom0ptr, const ArchMesh3Dom * const dom1ptr) { return (((abs (dom0ptr->c[0][0] + dom0ptr->c[0][1] - dom1ptr->c[0][0] - dom1ptr->c[0][1]) + 1) / 2) + ((abs (dom0ptr->c[1][0] + dom0ptr->c[1][1] - dom1ptr->c[1][0] - dom1ptr->c[1][1]) + 1) / 2) + ((abs (dom0ptr->c[2][0] + dom0ptr->c[2][1] - dom1ptr->c[2][0] - dom1ptr->c[2][1]) + 1) / 2)); } /* This function sets the biggest ** domain available for this ** architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archMesh3DomFrst ( const ArchMesh3 * const archptr, ArchMesh3Dom * restrict const domptr) { domptr->c[0][0] = domptr->c[1][0] = domptr->c[2][0] = 0; domptr->c[0][1] = archptr->c[0] - 1; domptr->c[1][1] = archptr->c[1] - 1; domptr->c[2][1] = archptr->c[2] - 1; return (0); } /* This routine reads domain information ** from the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archMesh3DomLoad ( const ArchMesh3 * const archptr, ArchMesh3Dom * restrict const domptr, FILE * restrict const stream) { if ((intLoad (stream, &domptr->c[0][0]) != 1) || (intLoad (stream, &domptr->c[1][0]) != 1) || (intLoad (stream, &domptr->c[2][0]) != 1) || (intLoad (stream, &domptr->c[0][1]) != 1) || (intLoad (stream, &domptr->c[1][1]) != 1) || (intLoad (stream, &domptr->c[2][1]) != 1)) { errorPrint ("archMesh3DomLoad: bad input"); return (1); } return (0); } /* This routine saves domain information ** to the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archMesh3DomSave ( const ArchMesh3 * const archptr, const ArchMesh3Dom * const domptr, FILE * restrict const stream) { if (fprintf (stream, ANUMSTRING " " ANUMSTRING " " ANUMSTRING " " ANUMSTRING " " ANUMSTRING " " ANUMSTRING " ", (Anum) domptr->c[0][0], (Anum) domptr->c[1][0], (Anum) domptr->c[2][0], (Anum) domptr->c[0][1], (Anum) domptr->c[1][1], (Anum) domptr->c[2][1]) == EOF) { errorPrint ("archMesh3DomSave: bad output"); return (1); } return (0); } /* This function tries to split a cubic ** domain into two subdomains. ** It returns: ** - 0 : if bipartitioning succeeded. ** - 1 : if bipartitioning could not be performed. ** - 2 : on error. */ int archMesh3DomBipart ( const ArchMesh3 * const archptr, const ArchMesh3Dom * const domptr, ArchMesh3Dom * restrict const dom0ptr, ArchMesh3Dom * restrict const dom1ptr) { Anum dimsiz[3]; int dimtmp; int dimval; dimsiz[0] = domptr->c[0][1] - domptr->c[0][0]; dimsiz[1] = domptr->c[1][1] - domptr->c[1][0]; dimsiz[2] = domptr->c[2][1] - domptr->c[2][0]; if ((dimsiz[0] | dimsiz[1] | dimsiz[2]) == 0) /* Return if cannot bipartition more */ return (1); dimval = (archptr->c[1] > archptr->c[0]) ? 1 : 0; /* Assume all subdomain dimensions are equal */ if (archptr->c[2] > archptr->c[dimval]) /* Find priviledged dimension */ dimval = 2; dimtmp = dimval; /* Find best dimension */ if (dimsiz[(dimtmp + 1) % 3] > dimsiz[dimval]) dimval = (dimtmp + 1) % 3; if (dimsiz[(dimtmp + 2) % 3] > dimsiz[dimval]) dimval = (dimtmp + 2) % 3; if (dimval == 0) { /* Split domain in two along largest dimension */ dom0ptr->c[0][0] = domptr->c[0][0]; dom0ptr->c[0][1] = (domptr->c[0][0] + domptr->c[0][1]) / 2; dom1ptr->c[0][0] = dom0ptr->c[0][1] + 1; dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; dom0ptr->c[2][0] = dom1ptr->c[2][0] = domptr->c[2][0]; dom0ptr->c[2][1] = dom1ptr->c[2][1] = domptr->c[2][1]; } else if (dimval == 1) { dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = (domptr->c[1][0] + domptr->c[1][1]) / 2; dom1ptr->c[1][0] = dom0ptr->c[1][1] + 1; dom1ptr->c[1][1] = domptr->c[1][1]; dom0ptr->c[2][0] = dom1ptr->c[2][0] = domptr->c[2][0]; dom0ptr->c[2][1] = dom1ptr->c[2][1] = domptr->c[2][1]; } else { dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; dom0ptr->c[2][0] = domptr->c[2][0]; dom0ptr->c[2][1] = (domptr->c[2][0] + domptr->c[2][1]) / 2; dom1ptr->c[2][0] = dom0ptr->c[2][1] + 1; dom1ptr->c[2][1] = domptr->c[2][1]; } return (0); } /* This function creates the MPI_Datatype for ** 3D mesh domains. ** It returns: ** - 0 : if type could be created. ** - 1 : on error. */ #ifdef SCOTCH_PTSCOTCH int archMesh3DomMpiType ( const ArchMesh3 * const archptr, MPI_Datatype * const typeptr) { MPI_Type_contiguous (6, ANUM_MPI, typeptr); return (0); } #endif /* SCOTCH_PTSCOTCH */ scotch-5.1.12b.dfsg/src/libscotch/bdgraph_bipart_ml.h0000644000175300017530000001071111631334325022744 0ustar hazelscthazelsct/* Copyright 2007-2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_bipart_ml.h **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the multi-level bipartition **/ /** routine for distributed graphs. **/ /** **/ /** DATES : # Version 5.1 : from : 30 oct 2007 **/ /** to : 29 oct 2009 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct BdgraphBipartMlParam_ { INT passnbr; /*+ Number of coarsening passes to go +*/ INT coarnbr; /*+ Minimum number of vertices +*/ INT dupmax; /*+ Maximum number of vertices to do fold-dup +*/ INT duplvlmax; /*+ Maximum level for allowing fold-dup +*/ double coarrat; /*+ Coarsening ratio +*/ Strat * stratlow; /*+ Strategy at lowest level +*/ Strat * stratasc; /*+ Strategy at ascending levels +*/ Strat * stratseq; /*+ Strategy when running on a single processor +*/ } BdgraphBipartMlParam; typedef struct BdgraphBipartMlSort_ { Gnum vertnum; /*+ Global vertex index for uncoarsening +*/ Gnum procnum; /*+ Gnum to have same type +*/ } BdgraphBipartMlSort; /* ** The function prototypes. */ #ifndef BDGRAPH_BIPART_ML #define static #endif static int bdgraphBipartMlCoarsen (Bdgraph * const, Bdgraph * const, DgraphCoarsenMulti * restrict * const, const BdgraphBipartMlParam * const); static int bdgraphBipartMlUncoarsen (Bdgraph *, const Bdgraph * const, const DgraphCoarsenMulti * restrict const); static void bdgraphBipartMlOpBest (const Gnum * const, Gnum * const, const int * const, const MPI_Datatype * const); int bdgraphBipartMl (Bdgraph * const, const BdgraphBipartMlParam * const); static int bdgraphBipartMl2 (Bdgraph * const, const BdgraphBipartMlParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_gp.c0000644000175300017530000003057511631334325022603 0ustar hazelscthazelsct/* Copyright 2004,2007,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bipart_gp.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module bipartitions an active **/ /** graph using the Gibbs, Poole, and **/ /** Stockmeyer algorithm. **/ /** **/ /** DATES : # Version 2.0 : from : 02 jun 1994 **/ /** to 05 oct 1994 **/ /** # Version 3.1 : from : 02 may 1996 **/ /** to 02 may 1996 **/ /** # Version 3.2 : from : 21 sep 1996 **/ /** to 13 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 3.4 : from : 01 jun 2001 **/ /** to 01 jun 2001 **/ /** # Version 4.0 : from : 04 nov 2003 **/ /** to 27 nov 2006 **/ /** # Version 5.0 : from : 10 sep 2007 **/ /** to 22 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BGRAPH_BIPART_GP #include "module.h" #include "common.h" #include "graph.h" #include "arch.h" #include "bgraph.h" #include "bgraph_bipart_gp.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the bipartitioning. ** It returns: ** - 0 : if bipartitioning could be computed. ** - 1 : on error. */ int bgraphBipartGp ( Bgraph * restrict const grafptr, const BgraphBipartGpParam * const paraptr) /*+ Method parameters +*/ { BgraphBipartGpQueue queudat; /* Neighbor queue */ BgraphBipartGpVertex * restrict vexxtax; /* Complementary vertex array */ const Gnum * restrict verttax; /* Based access to graph arrays */ const Gnum * restrict vendtax; const Gnum * restrict velotax; const Gnum * restrict edgetax; const Gnum * restrict edlotax; const Gnum * restrict veextax; Gnum compload0dlt; Gnum compsize0; Gnum commloadintn; Gnum commloadextn; Gnum commgainextn; Gnum rootnum; /* Index of potential next root */ if (grafptr->compload0 != grafptr->s.velosum) /* If not all vertices already in part 0 */ bgraphZero (grafptr); /* Move all graph vertices to part 0 */ if (memAllocGroup ((void **) (void *) &queudat.queutab, (size_t) (grafptr->s.vertnbr * sizeof (Gnum)), &vexxtax, (size_t) (grafptr->s.vertnbr * sizeof (BgraphBipartGpVertex)), NULL) == NULL) { errorPrint ("bgraphBipartGp: out of memory"); return (1); } memSet (vexxtax, 0, grafptr->s.vertnbr * sizeof (BgraphBipartGpVertex)); /* Initialize pass numbers */ vexxtax -= grafptr->s.baseval; verttax = grafptr->s.verttax; vendtax = grafptr->s.vendtax; velotax = grafptr->s.velotax; edgetax = grafptr->s.edgetax; edlotax = grafptr->s.edlotax; veextax = grafptr->veextax; compsize0 = grafptr->s.vertnbr; /* All vertices in part zero */ compload0dlt = grafptr->s.velosum - grafptr->compload0avg; commloadintn = 0; commloadextn = grafptr->commloadextn0; commgainextn = grafptr->commgainextn0; for (rootnum = grafptr->s.baseval; /* Loop on connected components */ (rootnum < grafptr->s.vertnnd) && (compload0dlt > 0); rootnum ++) { Gnum passnum; /* Pass number */ Gnum diamnum; /* Number of current diameter vertex */ Gnum diamval; /* Current diameter value */ Gnum diamdeg; /* Degree of current diameter vertex */ int diamflag; /* Flag set if improvement in diameter between passes */ while (vexxtax[rootnum].passnum != 0) /* Find first unallocated vertex */ rootnum ++; for (diamnum = rootnum, diamval = diamdeg = 0, diamflag = 1, passnum = 1; /* Start from root */ (passnum < paraptr->passnbr) && (diamflag -- != 0); passnum ++) { /* Loop if improvements */ bgraphBipartGpQueueFlush (&queudat); /* Flush vertex queue */ bgraphBipartGpQueuePut (&queudat, diamnum); /* Start from diameter vertex */ vexxtax[diamnum].passnum = passnum; /* It has been enqueued */ vexxtax[diamnum].distval = 0; do { /* Loop on vertices in queue */ Gnum vertnum; Gnum distval; Gnum edgenum; vertnum = bgraphBipartGpQueueGet (&queudat); /* Get vertex from queue */ distval = vexxtax[vertnum].distval; /* Get vertex distance */ if ((distval > diamval) || /* If vertex increases diameter */ ((distval == diamval) && /* Or is at diameter distance */ ((vendtax[vertnum] - verttax[vertnum]) < diamdeg))) { /* With smaller degree */ diamnum = vertnum; /* Set it as new diameter vertex */ diamval = distval; diamdeg = vendtax[vertnum] - verttax[vertnum]; diamflag = 1; } distval ++; /* Set neighbor distance */ for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { Gnum vertend; /* End vertex number */ vertend = edgetax[edgenum]; if (vexxtax[vertend].passnum < passnum) { /* If vertex not yet queued */ bgraphBipartGpQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ vexxtax[vertend].passnum = passnum; vexxtax[vertend].distval = distval; } } } while (! bgraphBipartGpQueueEmpty (&queudat)); /* As long as queue is not empty */ } bgraphBipartGpQueueFlush (&queudat); /* Flush vertex queue */ bgraphBipartGpQueuePut (&queudat, diamnum); /* Start from diameter vertex */ vexxtax[diamnum].passnum = passnum; /* It has been enqueued */ vexxtax[diamnum].distval = 0; do { /* Loop on vertices in queue */ Gnum vertnum; Gnum veloval; Gnum veexval; Gnum distval; Gnum edgenum; vertnum = bgraphBipartGpQueueGet (&queudat); /* Get vertex from queue */ veloval = (velotax != NULL) ? velotax[vertnum] : 1; veexval = (veextax != NULL) ? veextax[vertnum] : 0; grafptr->parttax[vertnum] = 1; /* Move selected vertex to part 1 */ compsize0 --; compload0dlt -= veloval; commloadextn += veexval; commgainextn -= veexval * 2; distval = vexxtax[vertnum].distval + 1; for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { Gnum vertend; /* End vertex number */ vertend = edgetax[edgenum]; if (vexxtax[vertend].passnum < passnum) { /* If vertex not yet queued */ bgraphBipartGpQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ vexxtax[vertend].passnum = passnum; vexxtax[vertend].distval = distval; } } } while ((compload0dlt > 0) && (! bgraphBipartGpQueueEmpty (&queudat))); /* As long as balance not achieved and queue is not empty */ if (! bgraphBipartGpQueueEmpty (&queudat)) { /* If frontier non empty */ Gnum edloval; Gnum fronnbr; fronnbr = 0; /* No frontier yet */ edloval = 1; /* Assume no edge loads */ do { Gnum vertnum; Gnum edgenum; vertnum = bgraphBipartGpQueueGet (&queudat); /* Get vertex from queue */ grafptr->frontab[fronnbr ++] = vertnum; #ifdef SCOTCH_DEBUG_BGRAPH2 if (grafptr->parttax[vertnum] != 0) { errorPrint ("bgraphBipartGp: internal error"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { Gnum vertend; /* End vertex number */ vertend = edgetax[edgenum]; if (grafptr->parttax[vertend] == 1) { /* If vertex belongs to other part */ if (edlotax != NULL) edloval = edlotax[edgenum]; commloadintn += edloval; if (vexxtax[vertend].distval != ~0) { /* If neighbor vertex not already put in frontier */ grafptr->frontab[fronnbr ++] = vertend; /* Record it in frontier */ vexxtax[vertend].distval = ~0; /* Set it as recorded */ } } } } while (! bgraphBipartGpQueueEmpty (&queudat)); grafptr->fronnbr = fronnbr; break; /* No need to process rest of graph */ } /* Else grafptr->fronnbr = 0 anyway */ } grafptr->compload0 = grafptr->compload0avg + compload0dlt; grafptr->compload0dlt = compload0dlt; grafptr->compsize0 = compsize0; grafptr->commload = commloadintn * grafptr->domdist + commloadextn; grafptr->commgainextn = commgainextn; grafptr->bbalval = (double) ((grafptr->compload0dlt < 0) ? (- grafptr->compload0dlt) : grafptr->compload0dlt) / (double) grafptr->compload0avg; memFree (queudat.queutab); /* Free group leader */ #ifdef SCOTCH_DEBUG_BGRAPH2 if (bgraphCheck (grafptr) != 0) { errorPrint ("bgraphBipartGp: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_st.c0000644000175300017530000003604011631334325022307 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_st.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the generic call to the **/ /** halo mesh ordering module, using a **/ /** given strategy. **/ /** **/ /** DATES : # Version 4.0 : from : 28 sep 2002 **/ /** to 05 jan 2005 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH_ORDER_ST #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "hgraph.h" #include "mesh.h" #include "hmesh.h" #include "order.h" #include "hgraph_order_st.h" #include "hmesh_order_bl.h" #include "hmesh_order_cp.h" #include "hmesh_order_gp.h" #include "hmesh_order_gr.h" #include "hmesh_order_hd.h" #include "hmesh_order_hf.h" #include "hmesh_order_nd.h" #include "hmesh_order_si.h" #include "hmesh_order_st.h" #include "vmesh.h" #include "vmesh_separate_st.h" /* ** The static and global variables. */ static Hmesh hmeshorderstmeshdummy; /* Dummy mesh for offset computations */ static union { /* Default parameters for block splitting method */ HmeshOrderBlParam param; /* Parameter zone */ StratNodeMethodData padding; /* To avoid reading out of structure */ } hmeshorderstdefaultbl = { { &stratdummy, 8 } }; static union { HmeshOrderCpParam param; StratNodeMethodData padding; } hmeshorderstdefaultcp = { { 0.70L, &stratdummy, &stratdummy } }; static union { /* Default parameters for nested dissection method */ HmeshOrderGpParam param; StratNodeMethodData padding; } hmeshorderstdefaultgp = { { 3 } }; static union { /* Default parameters for nested dissection method */ HmeshOrderGrParam param; StratNodeMethodData padding; } hmeshorderstdefaultgr = { { &stratdummy } }; static union { HmeshOrderHdParam param; StratNodeMethodData padding; } hmeshorderstdefaulthd = { { 1, 1000000, 0.08L } }; static union { HmeshOrderHfParam param; StratNodeMethodData padding; } hmeshorderstdefaulthf = { { 1, 1000000, 0.08L } }; static union { /* Default parameters for nested dissection method */ HmeshOrderNdParam param; StratNodeMethodData padding; } hmeshorderstdefaultnd = { { &stratdummy, &stratdummy, &stratdummy } }; static StratMethodTab hmeshorderstmethtab[] = { /* Mesh ordering methods array */ { HMESHORDERSTMETHBL, "b", hmeshOrderBl, &hmeshorderstdefaultbl }, { HMESHORDERSTMETHCP, "c", hmeshOrderCp, &hmeshorderstdefaultcp }, { HMESHORDERSTMETHGP, "g", hmeshOrderGp, &hmeshorderstdefaultgp }, { HMESHORDERSTMETHGR, "v", hmeshOrderGr, &hmeshorderstdefaultgr }, { HMESHORDERSTMETHHD, "d", hmeshOrderHd, &hmeshorderstdefaulthd }, { HMESHORDERSTMETHHF, "f", hmeshOrderHf, &hmeshorderstdefaulthf }, { HMESHORDERSTMETHND, "n", hmeshOrderNd, &hmeshorderstdefaultnd }, { HMESHORDERSTMETHSI, "s", hmeshOrderSi, NULL }, { -1, NULL, NULL, NULL } }; static StratParamTab hmeshorderstparatab[] = { /* The method parameter list */ { HMESHORDERSTMETHBL, STRATPARAMSTRAT, "strat", (byte *) &hmeshorderstdefaultbl.param, (byte *) &hmeshorderstdefaultbl.param.strat, (void *) &hmeshorderststratab }, { HMESHORDERSTMETHBL, STRATPARAMINT, "cmin", (byte *) &hmeshorderstdefaultbl.param, (byte *) &hmeshorderstdefaultbl.param.cblkmin, NULL }, { HMESHORDERSTMETHCP, STRATPARAMDOUBLE, "rat", (byte *) &hmeshorderstdefaultcp.param, (byte *) &hmeshorderstdefaultcp.param.comprat, NULL }, { HMESHORDERSTMETHCP, STRATPARAMSTRAT, "cpr", (byte *) &hmeshorderstdefaultcp.param, (byte *) &hmeshorderstdefaultcp.param.stratcpr, (void *) &hmeshorderststratab }, { HMESHORDERSTMETHCP, STRATPARAMSTRAT, "unc", (byte *) &hmeshorderstdefaultcp.param, (byte *) &hmeshorderstdefaultcp.param.stratunc, (void *) &hmeshorderststratab }, { HMESHORDERSTMETHGP, STRATPARAMINT, "pass", (byte *) &hmeshorderstdefaultgp.param, (byte *) &hmeshorderstdefaultgp.param.passnbr, NULL }, { HMESHORDERSTMETHGR, STRATPARAMSTRAT, "strat", (byte *) &hmeshorderstdefaultgr.param, (byte *) &hmeshorderstdefaultgr.param.stratptr, (void *) &hgraphorderststratab }, { HMESHORDERSTMETHHD, STRATPARAMINT, "cmin", (byte *) &hmeshorderstdefaulthd.param, (byte *) &hmeshorderstdefaulthd.param.colmin, NULL }, { HMESHORDERSTMETHHD, STRATPARAMINT, "cmax", (byte *) &hmeshorderstdefaulthd.param, (byte *) &hmeshorderstdefaulthd.param.colmax, NULL }, { HMESHORDERSTMETHHD, STRATPARAMDOUBLE, "frat", (byte *) &hmeshorderstdefaulthd.param, (byte *) &hmeshorderstdefaulthd.param.fillrat, NULL }, { HMESHORDERSTMETHHF, STRATPARAMINT, "cmin", (byte *) &hmeshorderstdefaulthf.param, (byte *) &hmeshorderstdefaulthf.param.colmin, NULL }, { HMESHORDERSTMETHHF, STRATPARAMINT, "cmax", (byte *) &hmeshorderstdefaulthf.param, (byte *) &hmeshorderstdefaulthf.param.colmax, NULL }, { HMESHORDERSTMETHHF, STRATPARAMDOUBLE, "frat", (byte *) &hmeshorderstdefaulthf.param, (byte *) &hmeshorderstdefaulthf.param.fillrat, NULL }, { HMESHORDERSTMETHND, STRATPARAMSTRAT, "sep", (byte *) &hmeshorderstdefaultnd.param, (byte *) &hmeshorderstdefaultnd.param.sepstrat, (void *) &vmeshseparateststratab }, { HMESHORDERSTMETHND, STRATPARAMSTRAT, "ole", (byte *) &hmeshorderstdefaultnd.param, (byte *) &hmeshorderstdefaultnd.param.ordstratlea, (void *) &hmeshorderststratab }, { HMESHORDERSTMETHND, STRATPARAMSTRAT, "ose", (byte *) &hmeshorderstdefaultnd.param, (byte *) &hmeshorderstdefaultnd.param.ordstratsep, (void *) &hmeshorderststratab }, { HMESHORDERSTMETHNBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; static StratParamTab hmeshorderstcondtab[] = { /* Mesh condition parameter table */ { STRATNODECOND, STRATPARAMINT, "edge", (byte *) &hmeshorderstmeshdummy, (byte *) &hmeshorderstmeshdummy.m.edgenbr, NULL }, { STRATNODECOND, STRATPARAMINT, "levl", (byte *) &hmeshorderstmeshdummy, (byte *) &hmeshorderstmeshdummy.levlnum, NULL }, { STRATNODECOND, STRATPARAMINT, "load", (byte *) &hmeshorderstmeshdummy, (byte *) &hmeshorderstmeshdummy.vnhlsum, NULL }, { STRATNODECOND, STRATPARAMDOUBLE, "mdeg", (byte *) &hmeshorderstmeshdummy, (byte *) &hmeshorderstmeshdummy.m.degrmax, NULL }, { STRATNODECOND, STRATPARAMINT, "vnod", (byte *) &hmeshorderstmeshdummy, (byte *) &hmeshorderstmeshdummy.vnohnbr, NULL }, { STRATNODECOND, STRATPARAMINT, "velm", (byte *) &hmeshorderstmeshdummy, (byte *) &hmeshorderstmeshdummy.m.velmnbr, NULL }, { STRATNODENBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; StratTab hmeshorderststratab = { /* Strategy tables for mesh ordering methods */ hmeshorderstmethtab, hmeshorderstparatab, hmeshorderstcondtab }; /***********************************/ /* */ /* This routine is the entry point */ /* for the mesh ordering routines. */ /* */ /***********************************/ /* This routine computes an ordering ** with respect to a given strategy. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int hmeshOrderSt ( const Hmesh * restrict const meshptr, /*+ Submesh to which list apply +*/ Order * restrict const ordeptr, /*+ Ordering to complete +*/ const Gnum ordenum, /*+ Index to start ordering at +*/ OrderCblk * restrict const cblkptr, /*+ Current column block +*/ const Strat * restrict const strat) /*+ Mesh ordering strategy +*/ { StratTest val; int o; if (meshptr->vnohnbr == 0) /* Return immediately if nothing to do */ return (0); o = 0; switch (strat->type) { case STRATNODECONCAT : errorPrint ("hmeshOrderSt: concatenation operator not implemented for ordering strategies"); return (1); case STRATNODECOND : o = stratTestEval (strat->data.cond.test, &val, (void *) meshptr); /* Evaluate expression */ if (o == 0) { /* If evaluation was correct */ #ifdef SCOTCH_DEBUG_HMESH2 if ((val.typetest != STRATTESTVAL) && (val.typenode != STRATPARAMLOG)) { errorPrint ("hmeshOrderSt: invalid test result"); o = 1; break; } #endif /* SCOTCH_DEBUG_HMESH2 */ if (val.data.val.vallog == 1) /* If expression is true */ o = hmeshOrderSt (meshptr, ordeptr, ordenum, cblkptr, strat->data.cond.strat[0]); /* Apply first strategy */ else { /* Else if expression is false */ if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ o = hmeshOrderSt (meshptr, ordeptr, ordenum, cblkptr, strat->data.cond.strat[1]); /* Apply second strategy */ } } break; case STRATNODEEMPTY : hmeshOrderSi (meshptr, ordeptr, ordenum, cblkptr); /* Always maintain a coherent ordering */ break; case STRATNODESELECT : errorPrint ("hmeshOrderSt: selection operator not available for mesh ordering strategies"); return (1); #ifdef SCOTCH_DEBUG_HMESH2 case STRATNODEMETHOD : #else /* SCOTCH_DEBUG_HMESH2 */ default : #endif /* SCOTCH_DEBUG_HMESH2 */ return (strat->tabl->methtab[strat->data.method.meth].func (meshptr, ordeptr, ordenum, cblkptr, (void *) &strat->data.method.data)); #ifdef SCOTCH_DEBUG_HMESH2 default : errorPrint ("hmeshOrderSt: invalid parameter"); return (1); #endif /* SCOTCH_DEBUG_HMESH2 */ } return (o); } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_th.h0000644000175300017530000000540211631334325023153 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_th.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the the separator thinner **/ /** vertex separation method. **/ /** **/ /** DATES : # Version 3.3 : from : 17 oct 1998 **/ /** to 17 oct 1998 **/ /** # Version 4.0 : from : 12 dec 2001 **/ /** to 01 jan 2002 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef VGRAPH_SEPARATE_TH #define static #endif int vgraphSeparateTh (Vgraph * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_arch_f.c0000644000175300017530000002560011631334325022250 0ustar hazelscthazelsct/* Copyright 2004,2007,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_arch_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the source graph handling routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 3.4 : from : 02 dec 1999 **/ /** to 15 nov 2001 **/ /** # Version 4.0 : from : 13 jan 2004 **/ /** to 13 jan 2004 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 13 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /*************************************/ /* */ /* These routines are the Fortran */ /* API for the architecture handling */ /* routines. */ /* */ /*************************************/ /* ** */ FORTRAN ( \ SCOTCHFARCHINIT, scotchfarchinit, ( \ SCOTCH_Arch * const archptr, \ int * const revaptr), \ (archptr, revaptr)) { *revaptr = SCOTCH_archInit (archptr); } /* ** */ FORTRAN ( \ SCOTCHFARCHEXIT, scotchfarchexit, ( \ SCOTCH_Arch * const archptr), \ (archptr)) { SCOTCH_archExit (archptr); } /* When an input stream is built from the given ** file handle, it is set as unbuffered, so as to ** allow for multiple stream reads from the same ** file handle. If it were buffered, too many ** input characters would be read on the first ** block read. */ FORTRAN ( \ SCOTCHFARCHLOAD, scotchfarchload, ( \ SCOTCH_Arch * const archptr, \ int * const fileptr, \ int * const revaptr), \ (archptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFARCHLOAD: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFARCHLOAD: cannot open input stream"); close (filenum); *revaptr = 1; return; } setbuf (stream, NULL); /* Do not buffer on input */ o = SCOTCH_archLoad (archptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFARCHSAVE, scotchfarchsave, ( \ const SCOTCH_Arch * const archptr, \ int * const fileptr, \ int * const revaptr), \ (archptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFARCHSAVE: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFARCHSAVE: cannot open output stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_archSave (archptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFARCHNAME, scotchfarchname, ( \ const SCOTCH_Arch * const archptr, \ char * const chartab, \ int * const charptr), \ (archptr, chartab, charptr)) { char * nameptr; /* Name string */ nameptr = SCOTCH_archName (archptr); /* Get architecture name */ strncpy (chartab, nameptr, *charptr); /* Copy architecture name */ } /* ** */ FORTRAN ( \ SCOTCHFARCHSIZE, scotchfarchsize, ( \ const SCOTCH_Arch * const archptr, \ int * const sizeptr), \ (archptr, sizeptr)) { *sizeptr = SCOTCH_archSize (archptr); } /* ** */ FORTRAN ( \ SCOTCHFARCHVAR, scotchfarchvar, ( \ const SCOTCH_Arch * const archptr, \ int * const flagptr), \ (archptr, flagptr)) { *flagptr = SCOTCH_archVar (archptr); } /* ** */ FORTRAN ( \ SCOTCHFARCHCMPLT, scotchfarchcmplt, ( \ SCOTCH_Arch * const archptr, \ const SCOTCH_Num * const archnbr, \ int * const revaptr), \ (archptr, archnbr, revaptr)) { *revaptr = SCOTCH_archCmplt (archptr, *archnbr); } /* ** */ FORTRAN ( \ SCOTCHFARCHCMPLTW, scotchfarchcmpltw, ( \ SCOTCH_Arch * const archptr, \ const SCOTCH_Num * const vertnbr, \ const SCOTCH_Num * const velotab, \ int * const revaptr), \ (archptr, vertnbr, velotab, revaptr)) { *revaptr = SCOTCH_archCmpltw (archptr, *vertnbr, velotab); } /* ** */ FORTRAN ( \ SCOTCHFARCHHCUB, scotchfarchhcub, ( \ SCOTCH_Arch * const archptr, \ const SCOTCH_Num * const dimmax, \ int * const revaptr), \ (archptr, dimmax, revaptr)) { *revaptr = SCOTCH_archHcub (archptr, *dimmax); } /* ** */ FORTRAN ( \ SCOTCHFARCHMESH2, scotchfarchmesh2, ( \ SCOTCH_Arch * const archptr, \ const SCOTCH_Num * const dimxval, \ const SCOTCH_Num * const dimyval, \ int * const revaptr), \ (archptr, dimxval, dimyval, revaptr)) { *revaptr = SCOTCH_archMesh2 (archptr, *dimxval, *dimyval); } /* ** */ FORTRAN ( \ SCOTCHFARCHMESH3, scotchfarchmesh3, ( \ SCOTCH_Arch * const archptr, \ const SCOTCH_Num * const dimxval, \ const SCOTCH_Num * const dimyval, \ const SCOTCH_Num * const dimzval, \ int * const revaptr), \ (archptr, dimxval, dimyval, dimzval, revaptr)) { *revaptr = SCOTCH_archMesh3 (archptr, *dimxval, *dimyval, *dimzval); } /* ** */ FORTRAN ( \ SCOTCHFARCHTLEAF, scotchfarchtleaf, ( \ SCOTCH_Arch * const archptr, \ const SCOTCH_Num * const levlnbr, \ const SCOTCH_Num * const sizetab, \ const SCOTCH_Num * const linktab, \ int * const revaptr), \ (archptr, levlnbr, sizetab, linktab, revaptr)) { *revaptr = SCOTCH_archTleaf (archptr, *levlnbr, sizetab, linktab); } /* ** */ FORTRAN ( \ SCOTCHFARCHTORUS2, scotchfarchtorus2, ( \ SCOTCH_Arch * const archptr, \ const SCOTCH_Num * const dimxval, \ const SCOTCH_Num * const dimyval, \ int * const revaptr), \ (archptr, dimxval, dimyval, revaptr)) { *revaptr = SCOTCH_archTorus2 (archptr, *dimxval, *dimyval); } /* ** */ FORTRAN ( \ SCOTCHFARCHTORUS3, scotchfarchtorus3, ( \ SCOTCH_Arch * const archptr, \ const SCOTCH_Num * const dimxval, \ const SCOTCH_Num * const dimyval, \ const SCOTCH_Num * const dimzval, \ int * const revaptr), \ (archptr, dimxval, dimyval, dimzval, revaptr)) { *revaptr = SCOTCH_archTorus3 (archptr, *dimxval, *dimyval, *dimzval); } /* ** */ FORTRAN ( \ SCOTCHFARCHVCMPLT, scotchfarchvcmplt, ( \ SCOTCH_Arch * const archptr, \ int * const revaptr), \ (archptr, revaptr)) { *revaptr = SCOTCH_archVcmplt (archptr); } /* ** */ FORTRAN ( \ SCOTCHFARCHVHCUB, scotchfarchvhcub, ( \ SCOTCH_Arch * const archptr, \ int * const revaptr), \ (archptr, revaptr)) { *revaptr = SCOTCH_archVhcub (archptr); } scotch-5.1.12b.dfsg/src/libscotch/arch_vhcub.h0000644000175300017530000001073711631334325021420 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_vhcub.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the variable-sized hypercube **/ /** target architecture functions. **/ /** **/ /** DATES : # Version 3.4 : from : 08 nov 2001 **/ /** to 08 nov 2001 **/ /** # Version 4.0 : from : 04 nov 2003 **/ /** to 04 nov 2003 **/ /** # Version 5.1 : from : 21 jan 2008 **/ /** to 21 jan 2008 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ The variable-sized hypercube bipartitioning definitions. +*/ typedef struct ArchVhcub_ { int padding; /*+ No data needed +*/ } ArchVhcub; typedef struct ArchVhcubDom_ { Anum termlvl; /*+ Terminal depth +*/ Anum termnum; /*+ Terminal number +*/ } ArchVhcubDom; /* ** The function prototypes. */ #ifndef ARCH_VHCUB #define static #endif #define archVhcubArchLoad NULL #define archVhcubArchSave NULL #define archVhcubArchFree NULL ArchDomNum archVhcubDomNum (const ArchVhcub * const, const ArchVhcubDom * const); int archVhcubDomTerm (const ArchVhcub * const, ArchVhcubDom * restrict const, const ArchDomNum); Anum archVhcubDomSize (const ArchVhcub * const, const ArchVhcubDom * const); #define archVhcubDomWght archVhcubDomSize Anum archVhcubDomDist (const ArchVhcub * const, const ArchVhcubDom * const, const ArchVhcubDom * const); int archVhcubDomFrst (const ArchVhcub * const, ArchVhcubDom * const); int archVhcubDomLoad (const ArchVhcub * const, ArchVhcubDom * const, FILE * const); int archVhcubDomSave (const ArchVhcub * const, const ArchVhcubDom * const, FILE * const); int archVhcubDomBipart (const ArchVhcub * const, const ArchVhcubDom * const, ArchVhcubDom * restrict const, ArchVhcubDom * restrict const); #ifdef SCOTCH_PTSCOTCH int archVhcubDomMpiType (const ArchVhcub * const, MPI_Datatype * const); #endif /* SCOTCH_PTSCOTCH */ #undef static scotch-5.1.12b.dfsg/src/libscotch/kdgraph_map_rb.h0000644000175300017530000000731411631334325022251 0ustar hazelscthazelsct/* Copyright 2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kdgraph_map_rb.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Jun-Ho HER **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the Parallel Dual Recursive **/ /** Bipartitioning mapping algorithm. **/ /** **/ /** DATES : # Version 5.1 : from : 16 apr 2008 **/ /** to 14 apr 2011 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ Method parameters. +*/ typedef struct KdgraphMapRbParam_ { Strat * stratsep; /*+ Bipartitioning strategy used +*/ Strat * stratseq; /*+ Sequential mapping strategy +*/ double kbalval; /*+ K-way imbalance ratio +*/ } KdgraphMapRbParam; /* ** The function prototypes. */ #ifndef KDGRAPH_MAP_RB #define static #endif DmappingFrag * kdgraphMapRbAdd2 (const Gnum, const Anum); int kdgraphMapRbAddBoth (const Dgraph * restrict const, Dmapping * restrict const, const ArchDom * restrict const, const GraphPart * restrict const); int kdgraphMapRbAddOne (const Dgraph * restrict const, Dmapping * restrict const, const ArchDom * restrict const); int kdgraphMapRbAddPart (const Dgraph * restrict const, Dmapping * restrict const, const ArchDom * restrict const, const Gnum, const GraphPart * const, const GraphPart); int kdgraphMapRb (Kdgraph * const, Kdmapping * const, const KdgraphMapRbParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_map_view_f.c0000644000175300017530000001026711631334325024472 0ustar hazelscthazelsct/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_map_view_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** distributed mapping handling routines **/ /** of the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.1 : from : 27 jul 2008 **/ /** to 27 mar 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the mapping routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFDGRAPHMAPVIEW, scotchfdgraphmapview, ( \ SCOTCH_Dgraph * const grafptr, \ const SCOTCH_Dmapping * const mapptr, \ int * const fileptr, \ int * const revaptr), \ (grafptr, mapptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if (*fileptr == -1) /* If process does not want to open a stream */ stream = NULL; else { if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFDGRAPHMAPVIEW: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFDGRAPHMAPVIEW: cannot open output stream"); close (filenum); *revaptr = 1; return; } } o = SCOTCH_dgraphMapView (grafptr, mapptr, stream); if (stream != NULL) /* If process has an open stream */ fclose (stream); /* This closes filenum too */ *revaptr = o; } scotch-5.1.12b.dfsg/src/libscotch/vgraph.h0000644000175300017530000001164111631334325020576 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for vertex separation routines. **/ /** **/ /** DATES : # Version 3.2 : from : 24 aug 1996 **/ /** to : 17 oct 1997 **/ /** # Version 3.3 : from : 13 mar 1999 **/ /** to : 13 mar 1999 **/ /** # Version 4.0 : from : 11 dec 2001 **/ /** to : 07 jan 2002 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to : 04 nov 2010 **/ /** **/ /************************************************************/ #define VGRAPH_H /* ** The type and structure definitions. */ /*+ Active graph structure. +*/ typedef struct Vgraph_ { Graph s; /*+ Source graph +*/ GraphPart * parttax; /*+ Based part array: 0,1: part; 2: separator +*/ Gnum compload[3]; /*+ Size of both parts and separator +*/ Gnum comploaddlt; /*+ Load difference between both parts +*/ Gnum compsize[2]; /*+ Number of vertices in parts (separator is fronnbr) +*/ Gnum fronnbr; /*+ Number of frontier vertices; TRICK: compsize[2] +*/ Gnum * frontab; /*+ Array of frontier vertex numbers +*/ Gnum levlnum; /*+ Nested dissection or coarsening level +*/ } Vgraph; /*+ The graph separator storing structure. +*/ typedef struct VgraphStore_ { Gnum fronnbr; /*+ Number of frontier nodes +*/ Gnum comploaddlt; /*+ Difference from the average +*/ Gnum compload[2]; /*+ Load in both parts +*/ Gnum compsize0; /*+ Number of vertices in part 0 +*/ byte * datatab; /*+ Variable-sized data array +*/ } VgraphStore; /* ** The function prototypes. */ #ifndef VGRAPH #define static #endif void vgraphExit (Vgraph * const); void vgraphZero (Vgraph * const); int vgraphCheck (const Vgraph * const); int vgraphStoreInit (const Vgraph * const, VgraphStore * const); void vgraphStoreExit (VgraphStore * const); void vgraphStoreSave (const Vgraph * const , VgraphStore * const); void vgraphStoreUpdt (Vgraph * const, const VgraphStore * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/common_sort.c0000644000175300017530000002072511631334325021644 0ustar hazelscthazelsct/* This file is part of the Scotch distribution. It does ** not have the stardard Scotch header with the INRIA ** copyright notice because it is a very slight adaptation ** of the qsort routine of glibc 2.4, taylored to match ** Scotch needs. As Scotch is distributed according to the ** CeCILL-C license, which is LGPL-compatible, no further ** notices are required. */ /* Copyright (C) 1991,1992,1996,1997,1999,2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Douglas C. Schmidt (schmidt@ics.uci.edu). The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ /* If you consider tuning this algorithm, you should consult first: Engineering a sort function; Jon Bentley and M. Douglas McIlroy; Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */ #ifndef MAX_THRESH #define MAX_THRESH 6 #define max_thresh (MAX_THRESH * INTSORTSIZE) /* Variable turned into constant */ /* Stack node declarations used to store unfulfilled partition obligations. */ typedef struct { char *lo; char *hi; } stack_node; /* The next 4 #defines implement a very fast in-line stack abstraction. */ /* The stack needs log (total_elements) entries (we could even subtract log(MAX_THRESH)). Since total_elements has type size_t, we get as upper bound for log (total_elements): bits per byte (CHAR_BIT) * sizeof(size_t). */ #define STACK_SIZE (CHAR_BIT * sizeof (INT)) #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top)) #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi))) #define STACK_NOT_EMPTY (stack < top) #endif /* MAX_THRESH */ /* Order size using quicksort. This implementation incorporates four optimizations discussed in Sedgewick: 1. Non-recursive, using an explicit stack of pointer that store the next array partition to sort. To save time, this maximum amount of space required to store an array of SIZE_MAX is allocated on the stack. Assuming a 32-bit (64 bit) integer for size_t, this needs only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes). Pretty cheap, actually. 2. Chose the pivot element using a median-of-three decision tree. This reduces the probability of selecting a bad pivot value and eliminates certain extraneous comparisons. 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving insertion sort to order the MAX_THRESH items within each partition. This is a big win, since insertion sort is faster for small, mostly sorted array segments. 4. The larger of the two sub-partitions is always pushed onto the stack first, with the algorithm then concentrating on the smaller partition. This *guarantees* no more than log (total_elems) stack size is needed (actually O(1) in this case)! */ /* To be defined : ** INTSORTNAME : Name of function ** INTSORTSIZE : Size of elements to sort ** INTSORTSWAP : Swapping macro ** INTSORTCMP : Comparison function */ void INTSORTNAME ( void * const pbase, /*+ Array to sort +*/ const INT total_elems) /*+ Number of entries to sort +*/ { register char *base_ptr = (char *) pbase; if (total_elems == 0) /* Avoid lossage with unsigned arithmetic below. */ return; if (total_elems > MAX_THRESH) { char *lo = base_ptr; char *hi = &lo[INTSORTSIZE * (total_elems - 1)]; stack_node stack[STACK_SIZE]; stack_node *top = stack; PUSH (NULL, NULL); while (STACK_NOT_EMPTY) { char *left_ptr; char *right_ptr; /* Select median value from among LO, MID, and HI. Rearrange LO and HI so the three values are sorted. This lowers the probability of picking a pathological pivot value and skips a comparison for both the LEFT_PTR and RIGHT_PTR in the while loops. */ char *mid = lo + INTSORTSIZE * ((hi - lo) / INTSORTSIZE >> 1); if (INTSORTCMP ((void *) mid, (void *) lo)) INTSORTSWAP (mid, lo); if (INTSORTCMP ((void *) hi, (void *) mid)) INTSORTSWAP (mid, hi); else goto jump_over; if (INTSORTCMP ((void *) mid, (void *) lo)) INTSORTSWAP (mid, lo); jump_over:; left_ptr = lo + INTSORTSIZE; right_ptr = hi - INTSORTSIZE; /* Here's the famous ``collapse the walls'' section of quicksort. Gotta like those tight inner loops! They are the main reason that this algorithm runs much faster than others. */ do { while (INTSORTCMP ((void *) left_ptr, (void *) mid)) left_ptr += INTSORTSIZE; while (INTSORTCMP ((void *) mid, (void *) right_ptr)) right_ptr -= INTSORTSIZE; if (left_ptr < right_ptr) { INTSORTSWAP (left_ptr, right_ptr); if (mid == left_ptr) mid = right_ptr; else if (mid == right_ptr) mid = left_ptr; left_ptr += INTSORTSIZE; right_ptr -= INTSORTSIZE; } else if (left_ptr == right_ptr) { left_ptr += INTSORTSIZE; right_ptr -= INTSORTSIZE; break; } } while (left_ptr <= right_ptr); /* Set up pointers for next iteration. First determine whether left and right partitions are below the threshold size. If so, ignore one or both. Otherwise, push the larger partition's bounds on the stack and continue sorting the smaller one. */ if ((size_t) (right_ptr - lo) <= max_thresh) { if ((size_t) (hi - left_ptr) <= max_thresh) /* Ignore both small partitions. */ POP (lo, hi); else /* Ignore small left partition. */ lo = left_ptr; } else if ((size_t) (hi - left_ptr) <= max_thresh) /* Ignore small right partition. */ hi = right_ptr; else if ((right_ptr - lo) > (hi - left_ptr)) { /* Push larger left partition indices. */ PUSH (lo, right_ptr); lo = left_ptr; } else { /* Push larger right partition indices. */ PUSH (left_ptr, hi); hi = right_ptr; } } } /* Once the BASE_PTR array is partially sorted by quicksort the rest is completely sorted using insertion sort, since this is efficient for partitions below MAX_THRESH size. BASE_PTR points to the beginning of the array to sort, and END_PTR points at the very last element in the array (*not* one beyond it!). */ #define min(x, y) ((x) < (y) ? (x) : (y)) { char *const end_ptr = &base_ptr[INTSORTSIZE * (total_elems - 1)]; char *tmp_ptr = base_ptr; char *thresh = min(end_ptr, base_ptr + max_thresh); register char *run_ptr; /* Find smallest element in first threshold and place it at the array's beginning. This is the smallest array element, and the operation speeds up insertion sort's inner loop. */ for (run_ptr = tmp_ptr + INTSORTSIZE; run_ptr <= thresh; run_ptr += INTSORTSIZE) if (INTSORTCMP ((void *) run_ptr, (void *) tmp_ptr)) tmp_ptr = run_ptr; if (tmp_ptr != base_ptr) INTSORTSWAP (tmp_ptr, base_ptr); /* Insertion sort, running from left-hand-side up to right-hand-side. */ run_ptr = base_ptr + INTSORTSIZE; while ((run_ptr += INTSORTSIZE) <= end_ptr) { tmp_ptr = run_ptr - INTSORTSIZE; while (INTSORTCMP ((void *) run_ptr, (void *) tmp_ptr)) tmp_ptr -= INTSORTSIZE; tmp_ptr += INTSORTSIZE; if (tmp_ptr != run_ptr) { char *trav; trav = run_ptr + INTSORTSIZE; while (--trav >= run_ptr) { char c = *trav; char *hi, *lo; for (hi = lo = trav; (lo -= INTSORTSIZE) >= tmp_ptr; hi = lo) *hi = *lo; *hi = c; } } } } } scotch-5.1.12b.dfsg/src/libscotch/hdgraph.h0000644000175300017530000001233411631334325020724 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the source halo distributed graph **/ /** structure. **/ /** **/ /** DATES : # Version 5.0 : from : 15 apr 2006 **/ /** to 16 jun 2007 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ #define HDGRAPH_H /* ** The defines. */ /*+ Graph option flags. +*/ #define HDGRAPHFREEVHND 0x0400 /* Free vnhdtab array */ #define HDGRAPHFREETABS (DGRAPHFREETABS | HGRAPHFREEVHND) /* ** The type and structure definitions. */ /*+ Halo distributed graph structure. In order to keep efficiency, distributed halo graphs are not considered as regular graphs as sequential halo graphs were. Halo distributed graphs have a compact vertex array, with halo edges added at the end of each vertex sub-array. They are not visible when considering the vertlocnbr, vertloctax (which is in fact most often of size vhallocnbr + 1 when the graph is compact, as in this case we have vnhdloctax = vertloctax + 1) and vendloctax (which is of size vertlocnbr) of the embedded distributed graph, but can be accessed through vendloctax and vnhdloctax. Halo vertex ends are stored only in edgeloctax, not in edgegsttax, except when graph has only an edgegsttax and no edgeloctax. Since halo vertices have no real existence in distributed graphs, they are simply numbered from baseval. They are converted into real vertices when a distributed halo graph is turned into a sequential halo graph. */ typedef struct Hdgraph_ { Dgraph s; /*+ Source distributed graph +*/ Gnum vhallocnbr; /*+ Local number of halo end vertices +*/ Gnum * vhndloctax; /*+ End vertex array including halo vertex indices +*/ Gnum ehallocnbr; /*+ Local number of halo edges +*/ Gnum levlnum; /*+ Nested dissection level +*/ } Hdgraph; /* ** The function prototypes. */ #ifndef HDGRAPH #define static #endif int hdgraphInit (Hdgraph * const); void hdgraphExit (Hdgraph * const); void hdgraphFree (Hdgraph * const); int hdgraphFold (const Hdgraph *, const int, Hdgraph * const); int hdgraphFold2 (const Hdgraph *, const int, Hdgraph * const, MPI_Comm); int hdgraphCheck (const Hdgraph *); #ifdef HGRAPH_H int hdgraphGather (Hdgraph *, Hgraph *); #endif /* HGRAPH_H */ int hdgraphInduceList (Hdgraph * restrict const, const Gnum, const Gnum * restrict const, Hdgraph * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_halo.c0000644000175300017530000001316411631334325023300 0ustar hazelscthazelsct/* Copyright 2007,2009,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_halo.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted source graph handling routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 17 jul 2007 **/ /** to 02 aug 2007 **/ /** # Version 5.1 : from : 02 jul 2008 **/ /** to 17 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "graph.h" #include "dgraph.h" #include "dgraph_halo.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the graph handling routines. */ /* */ /************************************/ /*+ This routine requests the computation *** of the ghost edge array. *** It returns: *** - 0 : if the computation succeeded. *** - !0 : on error. +*/ int SCOTCH_dgraphGhst ( SCOTCH_Dgraph * const grafptr) { return (dgraphGhst ((Dgraph *) grafptr)); } /*+ This routine requests the computation of the *** ghost edge array in replacement of the global *** edge array. *** It returns: *** - 0 : if the computation succeeded. *** - !0 : on error. +*/ int SCOTCH_dgraphGhstReplace ( SCOTCH_Dgraph * const grafptr) { Dgraph * restrict srcgrafptr; /* Pointer to scotch graph */ DgraphFlag srcflagval; /* Graph properties */ int o; srcgrafptr = (Dgraph *) grafptr; srcflagval = srcgrafptr->flagval; srcgrafptr->flagval |= DGRAPHFREETABS; /* If edge array was not allocated internally, assume it was */ o = dgraphGhstReplace (srcgrafptr); srcgrafptr->flagval = (srcgrafptr->flagval & ~DGRAPHFREETABS) | srcflagval; /* Restore original allocation flag */ return (o); } /*+ This routine spreads local information *** borne by local vertices across the ghost *** vertices of the neighboring processes. *** It returns: *** - 0 : if the exchange succeeded. *** - !0 : on error. +*/ int SCOTCH_dgraphHalo ( SCOTCH_Dgraph * const grafptr, void * const datatab, const MPI_Datatype typeval) { return (dgraphHaloSync ((Dgraph *) grafptr, (byte *) datatab, typeval)); } /*+ This routine spreads local information *** borne by local vertices across the ghost *** vertices of the neighboring processes, in *** an asynchronous way. *** It returns: *** - 0 : if the exchange succeeded. *** - !0 : on error. +*/ int SCOTCH_dgraphHaloAsync ( SCOTCH_Dgraph * const grafptr, void * const datatab, const MPI_Datatype typeval, SCOTCH_DgraphHaloReq * const requptr) { dgraphHaloAsync ((Dgraph *) grafptr, (byte *) datatab, typeval, (DgraphHaloRequest *) requptr); return (0); } /*+ This routine waits for the termination of *** an asynchronous halo request. *** It returns: *** - 0 : if the exchange succeeded. *** - !0 : on error. +*/ int SCOTCH_dgraphHaloWait ( SCOTCH_DgraphHaloReq * const requptr) { return (dgraphHaloWait ((DgraphHaloRequest *) requptr)); } /*+ This routine reserves a memory area *** of a size sufficient to store a *** halo request structure. *** It returns: *** - !NULL : if the initialization succeeded. *** - NULL : on error. +*/ SCOTCH_DgraphHaloReq * SCOTCH_dgraphHaloReqAlloc () { return ((SCOTCH_DgraphHaloReq *) memAlloc (sizeof (SCOTCH_DgraphHaloReq))); } scotch-5.1.12b.dfsg/src/libscotch/common_integer.c0000644000175300017530000003003311631334325022303 0ustar hazelscthazelsct/* Copyright 2004,2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : common_integer.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the generic integer **/ /** type. **/ /** **/ /** DATES : # Version 0.0 : from : 07 sep 1998 **/ /** to 22 sep 1998 **/ /** # Version 0.1 : from : 07 jan 2002 **/ /** to 17 jan 2003 **/ /** # Version 1.0 : from : 23 aug 2005 **/ /** to : 19 dec 2006 **/ /** # Version 2.0 : from : 26 feb 2008 **/ /** to : 26 feb 2008 **/ /** # Version 5.1 : from : 09 nov 2008 **/ /** to : 16 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define COMMON_INTEGER #ifndef COMMON_NOMODULE #include "module.h" #endif /* COMMON_NOMODULE */ #include "common.h" /********************************/ /* */ /* Basic routines for fast I/O. */ /* */ /********************************/ /* Fast read for INT values. ** It returns: ** - 1 : on success. ** - 0 : on error. */ int intLoad ( FILE * const stream, /*+ Stream to read from +*/ INT * const valptr) /*+ Area where to put value +*/ { int sign; /* Sign flag */ int car; /* Character read */ INT val; /* Value */ sign = 0; /* Assume positive constant */ for ( ; ; ) { /* Consume whitespaces and sign */ car = getc (stream); if (isspace (car)) continue; if ((car >= '0') && (car <= '9')) break; if (car == '-') { sign = 1; car = getc (stream); break; } if (car == '+') { car = getc (stream); break; } return (0); } if ((car < '0') || (car > '9')) /* If first char is non numeric */ return (0); /* Then it is an error */ val = car - '0'; /* Get first digit */ for ( ; ; ) { car = getc (stream); if ((car < '0') || (car > '9')) { ungetc (car, stream); break; } val = val * 10 + (car - '0'); /* Accumulate digits */ } *valptr = (sign != 0) ? (- val) : val; /* Set result */ return (1); } /* Write routine for INT values. ** It returns: ** - 1 : on success. ** - 0 : on error. */ int intSave ( FILE * const stream, /*+ Stream to write to +*/ const INT val) /*+ Value to write +*/ { return ((fprintf (stream, INTSTRING, (INT) val) == EOF) ? 0 : 1); } /**********************************/ /* */ /* Permutation building routines. */ /* */ /**********************************/ /* This routine fills an array with ** consecutive INT values, in ** ascending order. ** It returns: ** - VOID : in all cases. */ void intAscn ( INT * const permtab, /*+ Permutation array to build +*/ const INT permnbr, /*+ Number of entries in array +*/ const INT baseval) /*+ Base value +*/ { INT * permtax; INT permnum; INT permnnd; for (permnum = baseval, permnnd = baseval + permnbr, permtax = permtab - baseval; permnum < permnnd; permnum ++) permtax[permnum] = permnum; } /* This routine computes a random permutation ** of an array of INT values. ** It returns: ** - VOID : in all cases. */ void intPerm ( INT * const permtab, /*+ Permutation array to build +*/ const INT permnbr) /*+ Number of entries in array +*/ { INT * permptr; INT permrmn; for (permptr = permtab, permrmn = permnbr; /* Perform random permutation */ permrmn > 0; permptr ++, permrmn --) { INT permnum; INT permtmp; permnum = intRandVal (permrmn); /* Select index to swap */ permtmp = permptr[0]; /* Swap it with current index */ permptr[0] = permptr[permnum]; permptr[permnum] = permtmp; } } /********************/ /* */ /* Random routines. */ /* */ /********************/ static volatile int intrandflag = 0; /*+ Flag set if generator already initialized +*/ static unsigned int intrandseed = 1; /*+ Random seed +*/ /* This routine initializes the pseudo-random ** generator if necessary. In order for multi-sequential ** programs to have exactly the same behavior on any ** process, the random seed does not depend on process ** rank. This routine is not really thread-safe, so it ** should not be called concurrently when it has never ** been initialized before. ** It returns: ** - VOID : in all cases. */ void intRandInit (void) { if (intrandflag == 0) { /* If generator not yet initialized */ #if ! ((defined COMMON_DEBUG) || (defined COMMON_RANDOM_FIXED_SEED) || (defined SCOTCH_DETERMINISTIC)) intrandseed = time (NULL); /* Set random seed if needed */ #endif /* ((defined COMMON_DEBUG) || (defined COMMON_RANDOM_FIXED_SEED)) */ #ifdef COMMON_RANDOM_RAND srand (intrandseed); #else /* COMMON_RANDOM_RAND */ srandom (intrandseed); #endif /* COMMON_RANDOM_RAND */ intrandflag = 1; /* Generator has been initialized */ } } /* This routine reinitializes the pseudo-random ** generator to its initial value. This routine ** is not thread-safe. ** It returns: ** - VOID : in all cases. */ void intRandReset (void) { if (intrandflag != 0) { /* Keep seed computed during first initialization */ #ifdef COMMON_RANDOM_RAND srand (intrandseed); #else /* COMMON_RANDOM_RAND */ srandom (intrandseed); #endif /* COMMON_RANDOM_RAND */ } else intRandInit (); } /*********************/ /* */ /* Sorting routines. */ /* */ /*********************/ /* This routine sorts an array of ** INT values in ascending order ** by their first value, used as key. ** It returns: ** - VOID : in all cases. */ #define INTSORTNAME intSort1asc1 #define INTSORTSIZE (sizeof (INT)) #define INTSORTSWAP(p,q) do { INT t; t = *((INT *) (p)); *((INT *) (p)) = *((INT *) (q)); *((INT *) (q)) = t; } while (0) #define INTSORTCMP(p,q) (*((INT *) (p)) < *((INT *) (q))) #include "common_sort.c" #undef INTSORTNAME #undef INTSORTSIZE #undef INTSORTSWAP #undef INTSORTCMP /* This routine sorts an array of pairs of ** INT values in ascending order by their ** first value, used as key. ** It returns: ** - VOID : in all cases. */ #define INTSORTNAME intSort2asc1 #define INTSORTSIZE (2 * sizeof (INT)) #define INTSORTSWAP(p,q) do { INT t, u; t = *((INT *) (p)); u = *((INT *) (p) + 1); *((INT *) (p)) = *((INT *) (q)); *((INT *) (p) + 1) = *((INT *) (q) + 1); *((INT *) (q)) = t; *((INT *) (q) + 1) = u; } while (0) #define INTSORTCMP(p,q) (*((INT *) (p)) < *((INT *) (q))) #include "common_sort.c" #undef INTSORTNAME #undef INTSORTSIZE #undef INTSORTSWAP #undef INTSORTCMP /* This routine sorts an array of pairs of ** INT values in ascending order by both ** of their values, used as primary and ** secondary keys. ** It returns: ** - VOID : in all cases. */ #define INTSORTNAME intSort2asc2 #define INTSORTSIZE (2 * sizeof (INT)) #define INTSORTSWAP(p,q) do { INT t, u; t = *((INT *) (p)); u = *((INT *) (p) + 1); *((INT *) (p)) = *((INT *) (q)); *((INT *) (p) + 1) = *((INT *) (q) + 1); *((INT *) (q)) = t; *((INT *) (q) + 1) = u; } while (0) #define INTSORTCMP(p,q) ((*((INT *) (p)) < *((INT *) (q))) || ((*((INT *) (p)) == *((INT *) (q))) && (*((INT *) (p) + 1) < *((INT *) (q) + 1)))) #include "common_sort.c" #undef INTSORTNAME #undef INTSORTSIZE #undef INTSORTSWAP #undef INTSORTCMP /* This routine sorts an array of 3-uples of ** INT values in ascending order by their ** first value, used as key. ** It returns: ** - VOID : in all cases. */ #define INTSORTNAME intSort3asc1 #define INTSORTSIZE (3 * sizeof (INT)) #define INTSORTSWAP(p,q) do { INT t, u, v; t = *((INT *) (p)); u = *((INT *) (p) + 1); v = *((INT *) (p) + 2); *((INT *) (p)) = *((INT *) (q)); *((INT *) (p) + 1) = *((INT *) (q) + 1); *((INT *) (p) + 2) = *((INT *) (q) + 2); *((INT *) (q)) = t; *((INT *) (q) + 1) = u; *((INT *) (q) + 2) = v; } while (0) #define INTSORTCMP(p,q) (*((INT *) (p)) < *((INT *) (q))) #include "common_sort.c" #undef INTSORTNAME #undef INTSORTSIZE #undef INTSORTSWAP #undef INTSORTCMP /* This routine sorts an array of 3-uples of ** INT values in ascending order by their ** first and second values, used as primary ** and secondary keys. ** It returns: ** - VOID : in all cases. */ #define INTSORTNAME intSort3asc2 #define INTSORTSIZE (3 * sizeof (INT)) #define INTSORTSWAP(p,q) do { INT t, u, v; t = *((INT *) (p)); u = *((INT *) (p) + 1); v = *((INT *) (p) + 2); *((INT *) (p)) = *((INT *) (q)); *((INT *) (p) + 1) = *((INT *) (q) + 1); *((INT *) (p) + 2) = *((INT *) (q) + 2); *((INT *) (q)) = t; *((INT *) (q) + 1) = u; *((INT *) (q) + 2) = v; } while (0) #define INTSORTCMP(p,q) ((*((INT *) (p)) < *((INT *) (q))) || ((*((INT *) (p)) == *((INT *) (q))) && (*((INT *) (p) + 1) < *((INT *) (q) + 1)))) #include "common_sort.c" #undef INTSORTNAME #undef INTSORTSIZE #undef INTSORTSWAP #undef INTSORTCMP scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_hf.h0000644000175300017530000000703011631334325022425 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_hf.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the block-oriented Halo **/ /** Approximate (Multiple) Minimum Fill **/ /** graph ordering routine. **/ /** **/ /** DATES : # Version 3.4 : from : 15 may 2001 **/ /** to : 15 may 2001 **/ /** # Version 4.0 : from : 10 jan 2003 **/ /** to : 24 jan 2004 **/ /** # Version 5.1 : from : 01 oct 2009 **/ /** to : 01 oct 2009 **/ /** **/ /************************************************************/ /* ** The defines. */ #define HGRAPHORDERHFCOMPRAT 1.2L /*+ Compression ratio +*/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HgraphOrderHfParam_ { INT colmin; /*+ Minimum number of columns +*/ INT colmax; /*+ Maximum number of columns +*/ double fillrat; /*+ Fill-in ratio +*/ } HgraphOrderHfParam; /* ** The function prototypes. */ #ifndef HGRAPH_ORDER_HF #define static #endif int hgraphOrderHf (const Hgraph * const, Order * const, const Gnum, OrderCblk * const, const HgraphOrderHfParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/bdgraph_bipart_bd.h0000644000175300017530000000615211631334325022725 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_bipart_bd.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the band graph bipartitioning **/ /** routine for distributed graphs. **/ /** **/ /** DATES : # Version 5.1 : from : 11 nov 2007 **/ /** to : 15 jul 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct BdgraphBipartBdParam_ { INT distmax; /*+ Width of band surrounding the frontier +*/ Strat * stratbnd; /*+ Strategy for band graph +*/ Strat * stratorg; /*+ Strategy for original graph +*/ } BdgraphBipartBdParam; /* ** The function prototypes. */ #ifndef BDGRAPH_BIPART_BD #define static #endif int bdgraphBipartBd (Bdgraph * const, const BdgraphBipartBdParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_build_grid3d.c0000644000175300017530000000734411631334325024713 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_build_grid3d.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER (v5.0) **/ /** **/ /** FUNCTION : These lines are the distributed source **/ /** graph building routines for 3D grid **/ /** graphs. **/ /** **/ /** DATES : # Version 5.0 : from : 21 jul 2005 **/ /** to : 10 sep 2007 **/ /** # Version 5.1 : from : 05 jun 2010 **/ /** to : 06 jun 2010 **/ /** **/ /************************************************************/ #define LIBRARY #include "module.h" #include "common.h" #include "dgraph.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the graph handling routines. */ /* */ /************************************/ /*+ This routine builds a distributed *** 3D grid or torus graph structure. *** It returns: *** - 0 : if the creation succeeded. *** - !0 : on error. +*/ int SCOTCH_dgraphBuildGrid3D ( SCOTCH_Dgraph * const grafptr, const SCOTCH_Num baseval, /* Base value */ const SCOTCH_Num dimx, /* First dimension */ const SCOTCH_Num dimy, /* Second dimension */ const SCOTCH_Num dimz, /* Third dimension */ const SCOTCH_Num incrval, /* Increment value */ const int flagval) /* Flag value */ { return (dgraphBuildGrid3D ((Dgraph *) grafptr, baseval, dimx, dimy, dimz, incrval, flagval)); } scotch-5.1.12b.dfsg/src/libscotch/gain.h0000644000175300017530000001432011631334325020222 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gain.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the definitions of **/ /** the generic gain tables. **/ /** **/ /** DATES : # Version 0.0 : from : 26 oct 1996 **/ /** to 17 nov 1997 **/ /** # Version 0.1 : from : 10 may 1999 **/ /** to 18 mar 2005 **/ /** # Version 5.0 : from : 24 mar 2008 **/ /** to 01 jun 2008 **/ /** **/ /** NOTES : # Most of the contents of this module **/ /** comes from "map_b_fm" of the SCOTCH **/ /** project. **/ /** **/ /************************************************************/ /* ** The defines. */ #define GAINMAX ((INT) (((UINT) 1 << ((sizeof (INT) << 3) - 1)) - 2)) #define GAIN_LINMAX 1024 /* ** The type and structure definitions. */ /* The gain link data structure. This must be the first item of objects that are linked into gain tables. */ typedef struct GainLink_ { struct GainLink_ * next; /*+ Pointer to next element: FIRST +*/ struct GainLink_ * prev; /*+ Pointer to previous element +*/ struct GainEntr_ * tabl; /*+ Index into the gain table +*/ } GainLink; /* Gain table entry structure. */ typedef struct GainEntr_ { GainLink * next; /*+ Pointer to first element: FIRST +*/ } GainEntr; /* The gain table structure, built from table entries. For trick reasons, the pointer to the first entry must be the first field of the structure. */ typedef struct GainTabl_ { void (* tablAdd) (struct GainTabl_ * const, GainLink * const, const INT); /*+ Add method +*/ INT subbits; /*+ Number of subbits +*/ INT submask; /*+ Subbit mask +*/ INT totsize; /*+ Total table size +*/ GainEntr * tmin; /*+ Non-empty entry of minimum gain +*/ GainEntr * tmax; /*+ Non-empty entry of maximum gain +*/ GainEntr * tend; /*+ Point after last valid gain entry +*/ GainEntr * tabl; /*+ Gain table structure is.. [SIZE - ADJ] +*/ GainEntr tabk[1]; /*+ Split in two for relative access [ADJ] +*/ } GainTabl; /* ** The function prototypes. */ #ifndef GAIN #define static #endif GainTabl * gainTablInit (const INT, const INT); void gainTablExit (GainTabl * const); void gainTablFree (GainTabl * const); void gainTablAddLin (GainTabl * const, GainLink * const, const INT); void gainTablAddLog (GainTabl * const, GainLink * const, const INT); void gainTablDel (GainTabl * const, GainLink * const); GainLink * gainTablFrst (GainTabl * const); GainLink * gainTablNext (GainTabl * const, const GainLink * const); #ifdef SCOTCH_DEBUG_GAIN3 int gainTablCheck (GainEntr * const); static int gainTablCheck2 (GainEntr * const, GainLink * const); #endif /* SCOTCH_DEBUG_GAIN3 */ #undef static /* ** The marco definitions. */ #define gainTablEmpty(tabl) ((tabl)->tmin == (tabl)->tend) #define gainTablAdd(tabl,link,gain) ((tabl)->tablAdd ((tabl), (link), (gain))) #if ((! defined GAIN) && (! defined SCOTCH_DEBUG_GAIN1)) #define gainTablDel(tabl,link) (((GainLink *) (link))->next->prev = ((GainLink *) (link))->prev, \ ((GainLink *) (link))->prev->next = ((GainLink *) (link))->next) #endif /* ((! defined GAIN) && (! defined SCOTCH_DEBUG_GAIN1)) */ scotch-5.1.12b.dfsg/src/libscotch/kdgraph_map_rb.c0000644000175300017530000002165111631334325022244 0ustar hazelscthazelsct/* Copyright 2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kdgraph_map_rb.c **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module performs the Dual Recursive **/ /** Bipartitioning mapping algorithm **/ /** in parallel. **/ /** **/ /** DATES : # Version 5.1 : from : 16 apr 2008 **/ /** to 01 jul 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define KDGRAPH_MAP_RB #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "arch.h" #include "dgraph.h" #include "dmapping.h" #include "kdgraph.h" #include "kdgraph_map_rb.h" #include "kdgraph_map_rb_map.h" #include "kdgraph_map_rb_part.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* These routines add mapping fragments to the distributed ** mapping structure. */ DmappingFrag * kdgraphMapRbAdd2 ( const Gnum vertnbr, const Anum domnnbr) { DmappingFrag * restrict fragptr; if ((fragptr = memAlloc (sizeof (DmappingFrag))) == NULL) { errorPrint ("kdgraphMapRbAdd2: out of memory (1)"); return (NULL); } fragptr->vnumtab = NULL; fragptr->parttab = NULL; fragptr->domntab = NULL; if (((fragptr->vnumtab = memAlloc (vertnbr * sizeof (Gnum))) == NULL) || ((fragptr->parttab = memAlloc (vertnbr * sizeof (Anum))) == NULL) || ((fragptr->domntab = memAlloc (domnnbr * sizeof (ArchDom))) == NULL)) { errorPrint ("kdgraphMapRbAdd2: out of memory (2)"); if (fragptr->domntab != NULL) memFree (fragptr->domntab); if (fragptr->parttab != NULL) memFree (fragptr->parttab); if (fragptr->vnumtab != NULL) memFree (fragptr->vnumtab); return (NULL); } fragptr->vertnbr = vertnbr; fragptr->domnnbr = domnnbr; return (fragptr); } int kdgraphMapRbAddBoth ( const Dgraph * restrict const grafptr, Dmapping * restrict const mappptr, const ArchDom * restrict const domnptr, /*+ Pointer to both subdomains +*/ const GraphPart * restrict const parttab) /*+ Bipartition graph part array +*/ { DmappingFrag * restrict fragptr; Gnum vertlocnum; if ((fragptr = kdgraphMapRbAdd2 (grafptr->vertlocnbr, 2)) == NULL) /* Two domains */ return (1); fragptr->domntab[0] = domnptr[0]; fragptr->domntab[1] = domnptr[1]; if (parttab == NULL) /* If bipartition part array not set */ memSet (fragptr->parttab, 0, grafptr->vertlocnbr * sizeof (Anum)); else { for (vertlocnum = 0; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) fragptr->parttab[vertlocnum] = (Anum) parttab[vertlocnum]; } if (grafptr->vnumloctax != NULL) memCpy (fragptr->vnumtab, grafptr->vnumloctax + grafptr->baseval, fragptr->vertnbr * sizeof (Gnum)); else { Gnum vertlocadj; Gnum vertlocnum; for (vertlocnum = 0, vertlocadj = grafptr->procvrttab[grafptr->proclocnum]; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) fragptr->vnumtab[vertlocnum] = vertlocadj + vertlocnum; } dmapAdd (mappptr, fragptr); return (0); } int kdgraphMapRbAddOne ( const Dgraph * restrict const grafptr, Dmapping * restrict const mappptr, const ArchDom * restrict const domnptr) { DmappingFrag * restrict fragptr; if ((fragptr = kdgraphMapRbAdd2 (grafptr->vertlocnbr, 1)) == NULL) /* Only one domain */ return (1); fragptr->domntab[0] = *domnptr; /* Only one domain for this mapping fragment */ memSet (fragptr->parttab, 0, fragptr->vertnbr * sizeof (Anum)); /* All vertices mapped to it */ if (grafptr->vnumloctax != NULL) memCpy (fragptr->vnumtab, grafptr->vnumloctax + grafptr->baseval, fragptr->vertnbr * sizeof (Gnum)); else { Gnum vertlocadj; Gnum vertlocnum; for (vertlocnum = 0, vertlocadj = grafptr->procvrttab[grafptr->proclocnum]; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) fragptr->vnumtab[vertlocnum] = vertlocadj + vertlocnum; } dmapAdd (mappptr, fragptr); return (0); } int kdgraphMapRbAddPart ( const Dgraph * restrict const grafptr, Dmapping * restrict const mappptr, const ArchDom * restrict const domnptr, /*+ Pointer to one subdomain +*/ const Gnum vertnbr, const GraphPart * const parttab, const GraphPart partval) { DmappingFrag * restrict fragptr; Gnum vertlocnum; Gnum partlocnum; if ((fragptr = kdgraphMapRbAdd2 (vertnbr, 1)) == NULL) /* Only one domain and a limited number of vertices */ return (1); fragptr->domntab[0] = *domnptr; /* Only one domain for this mapping fragment */ memSet (fragptr->parttab, 0, fragptr->vertnbr * sizeof (Anum)); /* All vertices mapped to it */ if (grafptr->vnumloctax != NULL) { const Gnum * restrict vnumtab; for (vertlocnum = partlocnum = 0, vnumtab = grafptr->vnumloctax + grafptr->baseval; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) { if (parttab[vertlocnum] == partval) { #ifdef SCOTCH_DEBUG_KDMAP2 if (partlocnum >= vertnbr) { errorPrint ("kdgraphMapRbAddPart: invalid parameters (1)"); return (1); } #endif /* SCOTCH_DEBUG_KDMAP2 */ fragptr->vnumtab[partlocnum ++] = vnumtab[vertlocnum]; } } } else { Gnum vertlocadj; for (vertlocnum = partlocnum = 0, vertlocadj = grafptr->procvrttab[grafptr->proclocnum]; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) { if (parttab[vertlocnum] == partval) { #ifdef SCOTCH_DEBUG_KDMAP2 if (partlocnum >= vertnbr) { errorPrint ("kdgraphMapRbAddPart: invalid parameters (2)"); return (1); } #endif /* SCOTCH_DEBUG_KDMAP2 */ fragptr->vnumtab[partlocnum ++] = vertlocadj + vertlocnum; } } } #ifdef SCOTCH_DEBUG_KDMAP2 if (partlocnum != vertnbr) { errorPrint ("kdgraphMapRbAddPart: invalid parameters (3)"); return (1); } #endif /* SCOTCH_DEBUG_KDMAP2 */ dmapAdd (mappptr, fragptr); return (0); } /* ** This routine runs the parallel Dual ** Recursive Bipartitioning algorithm. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int kdgraphMapRb ( Kdgraph * restrict const grafptr, Kdmapping * restrict const mappptr, const KdgraphMapRbParam * restrict const paraptr) { if (grafptr->s.vertglbnbr == 0) /* If nothing to do, return immediately */ return (0); return (archPart (&mappptr->mappptr->archdat) /* If target architecture is some flavor of complete graph */ ? kdgraphMapRbPart (grafptr, mappptr, paraptr) : kdgraphMapRbMap (grafptr, mappptr, paraptr)); /* TODO: static mapping */ } scotch-5.1.12b.dfsg/src/libscotch/mesh.h0000644000175300017530000002063511631334325020246 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mesh.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the source mesh functions. **/ /** **/ /** DATES : # Version 4.0 : from : 29 dec 2001 **/ /** to 11 may 2004 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Mesh option flags. +*/ #define MESHNONE 0x0000 /* No options set */ #define MESHFREEEDGE 0x0001 /* Free edgetab array */ #define MESHFREEVERT 0x0002 /* Free verttab array */ #define MESHFREEVEND 0x0004 /* Free verttab array */ #define MESHFREEVNUM 0x0008 /* Free vnumtab array */ #define MESHFREEOTHR 0x0010 /* Free all other arrays */ #define MESHFREETABS 0x001F /* Free all mesh arrays */ #define MESHVERTGROUP 0x0010 /* All vertex arrays grouped */ /*+ The Mesh flag type. +*/ typedef int MeshFlag; /*+ Mesh property flags +*/ /*+ Mesh structure. It is basically a graph structure. It is a bipartite graph in the sense that node vertices are adjacent to element vertices only, and that element vertices are adjacent to node vertices only. Node vertices can all be put before or after element vertices, but node and element vertices cannot be mixed. In most algorithms, elements are put at the beginning because critical algorithms, such as the mesh induction and mesh coarsening routines, start by scanning element edges, such that elements can then be built on the fly before nodes are processed. Furthermore, as halo meshes comprise halo nodes but not halo elements, all halo nodes will be put at the end of the node array, making un-haloing much easier and inexpensive. Vertex global indices are also different, as vnumtab is only valid for (non-halo) node vertices. The base of the vnumtax array is thus vnodbas, and not s.baseval . Moreover, the contents of vnumtab is based with respect to baseval, and not to vnodbas, so that building the inverse permutation does not require to know vnodbas to trim node indices. When vertex loads are available, node loads represent the number of degrees of freedom per node, and element loads should be set as the sum of the vertex loads of all of their adjacent nodes (used by routines such as vmeshSeparateGg). +*/ typedef struct Mesh_ { MeshFlag flagval; /*+ Graph properties +*/ Gnum baseval; /*+ Base index for edge/vertex arrays +*/ Gnum velmnbr; /*+ Number of element vertices +*/ Gnum velmbas; /*+ Based number of first element +*/ Gnum velmnnd; /*+ Based number of first non-element vertex +*/ Gnum veisnbr; /*+ Number of isolated element vertices +*/ Gnum vnodnbr; /*+ Number of node vertices in mesh +*/ Gnum vnodbas; /*+ Based number of first node +*/ Gnum vnodnnd; /*+ Based number of first non-node vertex +*/ Gnum * verttax; /*+ Vertex array [based] +*/ Gnum * vendtax; /*+ End vertex array [based] +*/ Gnum * velotax; /*+ Element vertex load array (if present) +*/ Gnum * vnlotax; /*+ Node vertex load array (if present) +*/ Gnum velosum; /*+ Sum of element vertex weights +*/ Gnum vnlosum; /*+ Sum of node vertex weights +*/ Gnum * vnumtax; /*+ Vertex number in ancestor graph +*/ Gnum * vlbltax; /*+ Vertex label (from file) +*/ Gnum edgenbr; /*+ Number of edges (arcs) in graph +*/ Gnum * edgetax; /*+ Edge array [based] +*/ Gnum degrmax; /*+ Maximum degree +*/ } Mesh; /* ** The function prototypes. */ #ifndef MESH #define static #endif int meshInit (Mesh * const); void meshExit (Mesh * const); void meshFree (Mesh * const); int meshLoad (Mesh * restrict const, FILE * restrict const, const Gnum); int meshSave (const Mesh * restrict const, FILE * restrict const); Gnum meshBase (Mesh * const, const Gnum); int meshGraph (const Mesh * restrict const, Graph * restrict const); int meshInduceList (const Mesh *, Mesh *, const VertList *); int meshInducePart (const Mesh *, Mesh *, const Gnum, const GraphPart *, const GraphPart); int meshInduceSepa (const Mesh * restrict const, const GraphPart * restrict const, const Gnum, const Gnum * restrict const, Mesh * restrict const); int meshCheck (const Mesh * const); int meshReorder (const Mesh * restrict const, Mesh * restrict const); #ifdef GEOM_H int meshGeomLoadHabo (Mesh * restrict const, Geom * restrict const, FILE * const, FILE * const, const char * const); int meshGeomLoadScot (Mesh * restrict const, Geom * restrict const, FILE * const, FILE * const, const char * const); int meshGeomSaveScot (const Mesh * restrict const, const Geom * restrict const, FILE * const, FILE * const, const char * const); #endif /* GEOM_H */ #undef static scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_vw.h0000644000175300017530000000540211631334325023174 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_vw.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the move-all-to-first-subdomain **/ /** separation method. **/ /** **/ /** DATES : # Version 3.3 : from : 31 may 1999 **/ /** to 31 may 1999 **/ /** # Version 4.0 : from : 18 may 2004 **/ /** to 18 may 2004 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef VGRAPH_SEPARATE_VW #define static #endif int vgraphSeparateVw (Vgraph * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/kgraph_map_rb_map.c0000644000175300017530000012030411631334325022730 0ustar hazelscthazelsct/* Copyright 2004,2007-2009,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kgraph_map_rb_map.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module performs the Dual Recursive **/ /** Bipartitioning mapping algorithm. **/ /** **/ /** DATES : # Version 0.0 : from : 31 mar 1993 **/ /** to 31 mar 1993 **/ /** # Version 1.0 : from : 04 oct 1993 **/ /** to 06 oct 1993 **/ /** # Version 1.1 : from : 15 oct 1993 **/ /** to 15 oct 1993 **/ /** # Version 1.3 : from : 09 apr 1994 **/ /** to 11 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 17 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to 18 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 19 oct 1995 **/ /** # Version 3.1 : from : 30 oct 1995 **/ /** to 14 jun 1996 **/ /** # Version 3.2 : from : 23 aug 1996 **/ /** to 07 sep 1998 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to 08 dec 1998 **/ /** # Version 3.4 : from : 01 jun 2001 **/ /** to 07 nov 2001 **/ /** # Version 4.0 : from : 12 jan 2004 **/ /** to 06 mar 2005 **/ /** # Version 5.1 : from : 22 nov 2007 **/ /** to 31 aug 2011 **/ /** **/ /** NOTES : # This code is a complete rewrite of **/ /** the original code of kgraphMapRb(), **/ /** hence the kept history. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define KGRAPH_MAP_RB_MAP #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "arch.h" #include "mapping.h" #include "bgraph.h" #include "bgraph_bipart_st.h" #include "kgraph.h" #include "kgraph_map_rb.h" #include "kgraph_map_rb_map.h" /* ** The static variables. */ static KgraphMapRbMapPoolLink kgraphmaprbmappooldummy; /* Dummy links for pool routines; TRICK */ /************************************/ /* */ /* These routines handle job pools. */ /* */ /************************************/ /* This routine initializes the job pool ** structures. ** It returns: ** - VOID : in all cases. */ static int kgraphMapRbMapPoolInit ( KgraphMapRbMapPoolData * restrict const poolptr, Kgraph * restrict const grafptr, const KgraphMapRbParam * restrict const paraptr) { int flagval; memSet (grafptr->m.parttax + grafptr->m.baseval, 0, grafptr->s.vertnbr * sizeof (ArchDomNum)); /* Initialize partition data */ grafptr->m.domnnbr = 1; /* Only one valid domain to date */ grafptr->m.domntab[0] = grafptr->m.domnorg; /* All vertices are mapped to it */ flagval = 0; poolptr->grafptr = NULL; /* Assume we don't need top level graph data */ if (archVar (&grafptr->m.archdat) != 0) flagval |= KGRAPHMAPRBMAPARCHVAR; if (archPart (&grafptr->m.archdat) != 0) flagval |= KGRAPHMAPRBMAPARCHCMPLT; else poolptr->grafptr = &grafptr->s; /* We will need top-level graph data */ poolptr->linktab[0].prev = poolptr->linktab[0].next = poolptr->linktab[1].prev = poolptr->linktab[1].next = &kgraphmaprbmappooldummy; poolptr->pooltab[0] = &poolptr->linktab[0]; poolptr->pooltab[1] = (paraptr->flagjobtie != 0) ? &poolptr->linktab[0] : &poolptr->linktab[1]; poolptr->polival = ((flagval & KGRAPHMAPRBMAPARCHCMPLT) != 0) ? KGRAPHMAPRBPOLILEVEL : paraptr->polival; poolptr->mappptr = &grafptr->m; /* Will be used at exiting time */ if ((poolptr->jobtab = (KgraphMapRbMapJob *) memAlloc (grafptr->m.domnmax * sizeof (KgraphMapRbMapJob))) == NULL) { errorPrint ("kgraphMapRbMapPoolInit: out of memory (1)"); return (1); } poolptr->domntmp = grafptr->m.domntab; /* Keep track of original domain array */ if (paraptr->flagmaptie != 0) { /* If mappings are tied, use same domain array */ poolptr->domntab = grafptr->m.domntab; flagval |= KGRAPHMAPRBMAPPARTHALF; } else { if ((poolptr->domntab = (ArchDom *) memAlloc (grafptr->m.domnmax * sizeof (ArchDom))) == NULL) { errorPrint ("kgraphMapRbMapPoolInit: out of memory (2)"); memFree (poolptr->jobtab); return (1); } } poolptr->flagval = flagval; return (0); } /* This routine frees all of the internal arrays ** involved in the DRB algorithms. Great care ** should be taken that this routine always ** succeeds, whatever part of the algorithm it ** is called from. ** It returns: ** - VOID : in all cases. */ static void kgraphMapRbMapPoolExit ( KgraphMapRbMapPoolData * restrict const poolptr) { int jobnum; for (jobnum = 0; jobnum < poolptr->mappptr->domnnbr; jobnum ++) { /* For all potential jobs in both pools */ if (poolptr->jobtab[jobnum].poolflag != 0) /* If job slot is active */ graphFree (&poolptr->jobtab[jobnum].grafdat); /* Free job graph, if not clone of original graph */ } if (poolptr->mappptr->domntab != poolptr->domntmp) { /* If current mapping domain array is not original domain array */ if (poolptr->domntab == poolptr->domntmp) { /* If original domain array area was preserved */ memCpy (poolptr->domntmp, poolptr->mappptr->domntab, poolptr->mappptr->domnnbr * sizeof (ArchDom)); /* Just update it */ poolptr->domntab = poolptr->mappptr->domntab; /* Prepare to free the other domain array */ poolptr->mappptr->domntab = poolptr->domntmp; /* Point to original domain array */ } } if (poolptr->domntab != poolptr->mappptr->domntab) /* If mappings were not tied, free second mapping array */ memFree (poolptr->domntab); memFree (poolptr->jobtab); } /* This routine adds a job to pool 1 of the ** given pool data structure. ** It returns: ** - VOID : in all cases. */ static void kgraphMapRbMapPoolAdd ( KgraphMapRbMapPoolLink * restrict const linkptr, KgraphMapRbMapJob * const jobptr) { jobptr->poollink.prev = linkptr; /* Link job in pool: TRICK */ jobptr->poollink.next = linkptr->next; jobptr->poolflag = 1; /* Job is in pool */ jobptr->poolptr = linkptr; /* Point to the pool */ linkptr->next->prev = &jobptr->poollink; linkptr->next = &jobptr->poollink; } /* This routine gets the best job available from ** the given pool, according to the given policy. ** It returns: ** - !NULL : pointer to the job. ** - NULL : if the pool is empty. */ static KgraphMapRbMapJob * kgraphMapRbMapPoolGet ( KgraphMapRbMapPoolData * const poolptr) { KgraphMapRbMapJob * jobbest; /* Best job found */ KgraphMapRbMapJob * jobptr; jobbest = (KgraphMapRbMapJob *) poolptr->pooltab[0]->next; /* Get first job in pool */ for (jobptr = jobbest; /* For all jobs in pool */ jobptr != (KgraphMapRbMapJob *) (void *) &kgraphmaprbmappooldummy; jobptr = (KgraphMapRbMapJob *) jobptr->poollink.next) { if (jobptr->priolvl > jobbest->priolvl) /* If the current job has stronger priority */ jobbest = jobptr; /* Select it as the best job */ } if (jobbest != (KgraphMapRbMapJob *) (void *) &kgraphmaprbmappooldummy) { /* If job found */ jobbest->poollink.next->prev = jobbest->poollink.prev; /* Remove it from pool */ jobbest->poollink.prev->next = jobbest->poollink.next; /* But do not mark it unused */ } else /* Dummy job means no job found */ jobbest = NULL; return (jobbest); } /* This routine adds a job to the given pool ** as the first bipartitioning job. ** It returns: ** - VOID : in all cases. */ static void kgraphMapRbMapPoolFrst ( KgraphMapRbMapPoolData * const poolptr, KgraphMapRbMapJob * const jobptr) /* Job to be added */ { switch (poolptr->polival) { /* Set job priority value */ case KGRAPHMAPRBPOLIRANDOM : jobptr->prioval = jobptr->priolvl = intRandVal (INTVALMAX); break; case KGRAPHMAPRBPOLILEVEL : case KGRAPHMAPRBPOLINGLEVEL : jobptr->prioval = jobptr->grafdat.vertnbr; jobptr->priolvl = 0; break; case KGRAPHMAPRBPOLISIZE : case KGRAPHMAPRBPOLINGSIZE : jobptr->prioval = jobptr->priolvl = jobptr->grafdat.vertnbr; break; #ifdef SCOTCH_DEBUG_KGRAPH2 default : errorPrint ("kgraphMapRbMapPoolFrst: unknown job selection policy"); jobptr->prioval = 0; jobptr->priolvl = 0; return; #endif /* SCOTCH_DEBUG_KGRAPH2 */ } kgraphMapRbMapPoolAdd (poolptr->pooltab[0], jobptr); /* Add job to pool */ } /* This routine updates the given job ** table with both of the given subjob ** data. ** This routine can be called only if ** the parent jobs of the vertices to ** be updated still exist. ** It returns: ** - VOID : in all cases. */ static void kgraphMapRbMapPoolUpdt1 ( KgraphMapRbMapPoolData * const poolptr, const KgraphMapRbMapJob * const joboldptr, /* Job to be removed */ const GraphPart * const parttax, KgraphMapRbMapJob * const jobnewptr, /* Its only active subjob */ const GraphPart partval) { KgraphMapRbMapJob * restrict jobtab; const Anum * restrict mapparttax; /* Based pointer to mapping part array */ const Gnum * restrict topverttax; const Gnum * restrict topvendtax; const Gnum * restrict topedgetax; Gnum prioval; Gnum priolvl; priolvl = 0; /* Prepare for neighbor updating methods */ switch (poolptr->polival) { /* Set job priority value */ case KGRAPHMAPRBPOLIRANDOM : prioval = priolvl = intRandVal (INTVALMAX); break; case KGRAPHMAPRBPOLILEVEL : priolvl = joboldptr->priolvl + 1; case KGRAPHMAPRBPOLINGLEVEL : prioval = joboldptr->prioval - 1; break; case KGRAPHMAPRBPOLISIZE : priolvl = jobnewptr->grafdat.vertnbr; case KGRAPHMAPRBPOLINGSIZE : prioval = jobnewptr->grafdat.vertnbr; break; #ifdef SCOTCH_DEBUG_KGRAPH2 default : errorPrint ("kgraphMapRbMapPoolUpdt1: unknown job selection policy"); jobnewptr->prioval = 0; jobnewptr->priolvl = 0; return; #endif /* SCOTCH_DEBUG_KGRAPH2 */ } jobnewptr->prioval = prioval; if (poolptr->polival >= KGRAPHMAPRBPOLINEIGHBOR) { /* If neighbors have to be updated */ Gnum jobvertnum; Gnum prioold; jobtab = poolptr->jobtab; mapparttax = poolptr->mappptr->parttax; topverttax = poolptr->grafptr->verttax; /* Point to top-level graph arrays */ topvendtax = poolptr->grafptr->vendtax; topedgetax = poolptr->grafptr->edgetax; prioold = joboldptr->prioval; if (joboldptr->grafdat.vertnbr < poolptr->grafptr->vertnbr) { /* If subgraph is not top graph */ const Gnum * restrict jobvnumtax; const Gnum * restrict jobverttax; const Gnum * restrict jobvendtax; jobvnumtax = joboldptr->grafdat.vnumtax; /* Change priority of neighboring jobs of old job */ jobverttax = joboldptr->grafdat.verttax; jobvendtax = joboldptr->grafdat.vendtax; jobnewptr->poolflag = 0; /* TRICK: avoid new job being considered for update */ for (jobvertnum = joboldptr->grafdat.baseval; jobvertnum < joboldptr->grafdat.vertnnd; jobvertnum ++) { Gnum topvertnum; Gnum topedgenum; if (parttax[jobvertnum] == partval) /* If vertex belongs to part which is still alive */ continue; /* Do not consider update part as removed */ topvertnum = jobvnumtax[jobvertnum]; /* If graph is smaller than top graph, then vnumtax must exist */ if ((topvendtax[topvertnum] - topverttax[topvertnum]) == /* If vertex is internal, skip it */ (jobvendtax[jobvertnum] - jobverttax[jobvertnum])) continue; for (topedgenum = topverttax[topvertnum]; topedgenum < topvendtax[topvertnum]; topedgenum ++) { KgraphMapRbMapJob * restrict jobnghbptr; /* (Old ?) job of neighbor vertex */ jobnghbptr = &jobtab[mapparttax[topedgetax[topedgenum]]]; /* Get pointer to neighboring job */ if ((jobnghbptr->poolflag != 0) && /* If neighbor is active */ (jobnghbptr->prioval <= prioold)) /* And had not already a stronger priority */ jobnghbptr->priolvl ++; /* Update neighbor priority */ } } jobnewptr->poolflag = 1; /* TRICK: new job is active again */ } if (jobnewptr->grafdat.vertnbr < poolptr->grafptr->vertnbr) { /* If subgraph is not top graph, update priority of neighbors of new job only */ const Gnum * restrict jobvnumtax; const Gnum * restrict jobverttax; const Gnum * restrict jobvendtax; jobvnumtax = jobnewptr->grafdat.vnumtax; jobverttax = jobnewptr->grafdat.verttax; jobvendtax = jobnewptr->grafdat.vendtax; for (jobvertnum = jobnewptr->grafdat.baseval; jobvertnum < jobnewptr->grafdat.vertnnd; jobvertnum ++) { Gnum topvertnum; Gnum topedgenum; topvertnum = jobvnumtax[jobvertnum]; /* For subjobs jobvnumtax always exists */ if ((topvendtax[topvertnum] - topverttax[topvertnum]) == /* If vertex is internal, skip it */ (jobvendtax[jobvertnum] - jobverttax[jobvertnum])) continue; for (topedgenum = topverttax[topvertnum]; topedgenum < topvendtax[topvertnum]; topedgenum ++) { KgraphMapRbMapJob * restrict jobnghbptr; /* (Old ?) job of neighbor vertex */ jobnghbptr = &jobtab[mapparttax[topedgetax[topedgenum]]]; /* Get pointer to neighboring job */ if (jobnghbptr == jobnewptr) /* If it is the current job, do not consider the edge */ continue; if ((jobnghbptr->poolflag == 0) || /* If neighbor is not active */ (prioval > jobnghbptr->prioval)) /* Or if we have higher priority */ priolvl ++; /* Increase our priority */ else if ((prioval < jobnghbptr->prioval) && /* Else if neighbor has higher one */ (prioold >= jobnghbptr->prioval)) /* Which it did not already have */ jobnghbptr->priolvl ++; /* Update neighbor priority */ } } } } jobnewptr->priolvl = priolvl; kgraphMapRbMapPoolAdd (poolptr->pooltab[1], jobnewptr); /* Add job to pool */ } static void kgraphMapRbMapPoolUpdt2 ( KgraphMapRbMapPoolData * const poolptr, const KgraphMapRbMapJob * const joboldptr, /* Job to be removed */ const GraphPart * const parttax, KgraphMapRbMapJob * const jobnewptr0, /* Its two subjobs */ KgraphMapRbMapJob * const jobnewptr1) { KgraphMapRbMapJob * restrict jobtab; const Anum * restrict mapparttax; /* Based pointer to mapping part array */ const Gnum * restrict jobvnumtax; const Gnum * restrict jobverttax; const Gnum * restrict jobvendtax; const Gnum * restrict topverttax; const Gnum * restrict topvendtax; const Gnum * restrict topedgetax; KgraphMapRbMapJob * restrict jobnewtab[2]; int i; jobnewtab[0] = jobnewptr0; jobnewtab[1] = jobnewptr1; for (i = 1; i >= 0; i --) { KgraphMapRbMapJob * jobnewptr; Gnum prioval; Gnum priolvl; jobnewptr = jobnewtab[i]; /* Get concerned subjob */ priolvl = 0; /* Prepare for neighbor updating methods */ switch (poolptr->polival) { /* Set job priority value */ case KGRAPHMAPRBPOLIRANDOM : prioval = priolvl = intRandVal (INTVALMAX); break; case KGRAPHMAPRBPOLILEVEL : priolvl = joboldptr->priolvl + 1; case KGRAPHMAPRBPOLINGLEVEL : prioval = joboldptr->prioval - 1; break; case KGRAPHMAPRBPOLISIZE : priolvl = jobnewptr->grafdat.vertnbr; case KGRAPHMAPRBPOLINGSIZE : prioval = jobnewptr->grafdat.vertnbr; break; #ifdef SCOTCH_DEBUG_KGRAPH2 default : errorPrint ("kgraphMapRbMapPoolUpdt2: unknown job selection policy"); jobnewptr->prioval = 0; jobnewptr->priolvl = 0; return; #endif /* SCOTCH_DEBUG_KGRAPH2 */ } jobnewptr0->prioval = prioval + 1; /* TRICK: when processing subdomain 1, subdomain 0 has higher priority value */ jobnewptr->prioval = prioval; /* Then in its turn subdomain 0 will have its proper priority value */ if (poolptr->polival >= KGRAPHMAPRBPOLINEIGHBOR) { /* If neighbors have to be updated */ Gnum jobvertnum; Gnum prioold; jobtab = poolptr->jobtab; mapparttax = poolptr->mappptr->parttax; topverttax = poolptr->grafptr->verttax; /* Point to top-level graph arrays */ topvendtax = poolptr->grafptr->vendtax; topedgetax = poolptr->grafptr->edgetax; jobvnumtax = jobnewptr->grafdat.vnumtax; jobverttax = jobnewptr->grafdat.verttax; jobvendtax = jobnewptr->grafdat.vendtax; prioold = joboldptr->prioval; for (jobvertnum = jobnewptr->grafdat.baseval; jobvertnum < jobnewptr->grafdat.vertnnd; jobvertnum ++) { Gnum topvertnum; Gnum topedgenum; topvertnum = jobvnumtax[jobvertnum]; /* For subjobs jobvnumtax always exists */ if ((topvendtax[topvertnum] - topverttax[topvertnum]) == /* If vertex is internal, skip it */ (jobvendtax[jobvertnum] - jobverttax[jobvertnum])) continue; for (topedgenum = topverttax[topvertnum]; topedgenum < topvendtax[topvertnum]; topedgenum ++) { KgraphMapRbMapJob * jobnghbptr; /* (Old ?) job of neighbor vertex */ jobnghbptr = &jobtab[mapparttax[topedgetax[topedgenum]]]; /* Get pointer to neighboring job */ if ((jobnghbptr->poolflag != 0) && /* If neighbor is in active job */ (jobnghbptr->prioval > prioval) && /* Which gained priority over us */ (jobnghbptr->prioval <= prioold)) { jobnghbptr->priolvl ++; /* Update neighbor priority */ } if ((jobnghbptr->poolflag == 0) || /* If neighbor is fully known */ (jobnghbptr->prioval < prioval)) /* Or has smaller priority value */ priolvl ++; /* Then we should be processed */ } } } jobnewptr->priolvl = priolvl; /* Set new priority */ kgraphMapRbMapPoolAdd (poolptr->pooltab[1], jobnewptr); /* Add job to pool */ } } /* ** This routine removes the influence of the ** given job from its neighbor jobs. ** It returns: ** - VOID : in all cases. */ static void kgraphMapRbMapPoolRemv ( KgraphMapRbMapPoolData * const poolptr, const KgraphMapRbMapJob * const joboldptr) /* Job to be removed */ { KgraphMapRbMapJob * restrict jobtab; const Anum * restrict mapparttax; /* Based pointer to mapping part array */ const Gnum * restrict jobvnumtax; const Gnum * restrict jobverttax; const Gnum * restrict jobvendtax; const Gnum * restrict topverttax; const Gnum * restrict topvendtax; const Gnum * restrict topedgetax; if (poolptr->polival >= KGRAPHMAPRBPOLINEIGHBOR) { /* If neighbors have to be modified */ Gnum jobvertnum; Gnum prioold; jobtab = poolptr->jobtab; mapparttax = poolptr->mappptr->parttax; topverttax = poolptr->grafptr->verttax; /* Point to top-level graph arrays */ topvendtax = poolptr->grafptr->vendtax; topedgetax = poolptr->grafptr->edgetax; jobvnumtax = joboldptr->grafdat.vnumtax; jobverttax = joboldptr->grafdat.verttax; jobvendtax = joboldptr->grafdat.vendtax; prioold = joboldptr->prioval; for (jobvertnum = joboldptr->grafdat.baseval; jobvertnum < joboldptr->grafdat.vertnnd; jobvertnum ++) { Gnum topvertnum; /* Source graph vertex number */ Gnum topedgenum; /* Source graph edge number */ topvertnum = (jobvnumtax == NULL) ? jobvertnum : jobvnumtax[jobvertnum]; if ((topvendtax[topvertnum] - topverttax[topvertnum]) == /* If vertex is internal, skip it */ (jobvendtax[jobvertnum] - jobverttax[jobvertnum])) continue; for (topedgenum = topverttax[topvertnum]; topedgenum < topvendtax[topvertnum]; topedgenum ++) { KgraphMapRbMapJob * jobnghbptr; /* (Old ?) job of neighbor vertex */ jobnghbptr = &jobtab[mapparttax[topedgetax[topedgenum]]]; /* Get pointer to neighboring job */ if ((jobnghbptr->poolflag != 0) && /* If neighbor job is active */ (jobnghbptr->prioval <= prioold)) /* And had not already a stronger priority */ jobnghbptr->priolvl ++; /* Increase its priority since we are now inactive */ } } } } /**********************************************/ /* */ /* These routines handle the pool part array. */ /* */ /**********************************************/ static void kgraphMapRbMapPartBoth ( KgraphMapRbMapPoolData * restrict const poolptr, const Bgraph * restrict const bipgrafptr, const Anum * restrict const jobsubnum) { Gnum bipvertnum; const GraphPart * restrict bipparttax; Anum * restrict mapparttax; Anum mappartval1; Anum mappartdlt; bipparttax = bipgrafptr->parttax; mapparttax = poolptr->mappptr->parttax; mappartval1 = jobsubnum[1]; mappartdlt = jobsubnum[0] - jobsubnum[1]; if (bipgrafptr->s.vnumtax != NULL) { const Gnum * restrict bipvnumtax; bipvnumtax = bipgrafptr->s.vnumtax; for (bipvertnum = bipgrafptr->s.baseval; bipvertnum < bipgrafptr->s.vertnnd; bipvertnum ++) mapparttax[bipvnumtax[bipvertnum]] = mappartval1 + ((((Anum) bipparttax[bipvertnum]) - 1) & mappartdlt); } else { for (bipvertnum = bipgrafptr->s.baseval; bipvertnum < bipgrafptr->s.vertnnd; bipvertnum ++) mapparttax[bipvertnum] = mappartval1 + ((((Anum) bipparttax[bipvertnum]) - 1) & mappartdlt); } } static void kgraphMapRbMapPartOne ( KgraphMapRbMapPoolData * restrict const poolptr, const Bgraph * restrict const bipgrafptr, const Anum jobsubnum1) { Gnum bipvertnum; const GraphPart * restrict bipparttax; Anum * restrict mapparttax; bipparttax = bipgrafptr->parttax; mapparttax = poolptr->mappptr->parttax; if (bipgrafptr->s.vnumtax != NULL) { const Gnum * restrict bipvnumtax; bipvnumtax = bipgrafptr->s.vnumtax; for (bipvertnum = bipgrafptr->s.baseval; bipvertnum < bipgrafptr->s.vertnnd; bipvertnum ++) if (bipparttax[bipvertnum] == 1) mapparttax[bipvnumtax[bipvertnum]] = jobsubnum1; } else { for (bipvertnum = bipgrafptr->s.baseval; bipvertnum < bipgrafptr->s.vertnnd; bipvertnum ++) if (bipparttax[bipvertnum] == 1) mapparttax[bipvertnum] = jobsubnum1; } } /********************************************/ /* */ /* This is the entry point for the Dual */ /* Recursive Bipartitioning mapping method. */ /* */ /********************************************/ /* This routine runs the Dual Recursive ** Bipartitioning algorithm. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int kgraphMapRbMap ( Kgraph * restrict const grafptr, const KgraphMapRbParam * restrict const paraptr) { KgraphMapRbMapPoolData pooldat; /* Data for handling jobs and job pools */ ArchDom domsubtab[2]; /* Subdomains of current job domain */ KgraphMapRbMapJob joborgdat; /* Aera to save original job data */ Anum jobsubnum[2]; /* Number of subjob slots in job array */ Gnum jobsubsiz[2]; /* Sizes of subjobs */ Bgraph bipgrafdat; /* Bipartition graph */ double comploadmin; /* Minimum vertex load per target load */ double comploadmax; /* Maximum vertex load per target load */ int i; #ifdef SCOTCH_DEBUG_KGRAPH2 grafptr->m.domnmax = 1; /* Force resizing of job arrays, for debugging */ #endif /* SCOTCH_DEBUG_KGRAPH2 */ if (kgraphMapRbMapPoolInit (&pooldat, grafptr, paraptr) != 0) /* Initialize pool data; done first for kgraphMapRbMapPoolExit() to succeed afterwards */ return (1); if ((((pooldat.flagval & KGRAPHMAPRBMAPARCHVAR) == 0) && (archDomSize (&grafptr->m.archdat, &grafptr->m.domnorg) <= 1)) || /* If single-vertex domain */ (((pooldat.flagval & KGRAPHMAPRBMAPARCHVAR) != 0) && (grafptr->s.vertnbr <= 1))) { /* Or if variable-sized architecture with single vertex graph */ kgraphMapRbMapPoolExit (&pooldat); return (0); /* Job already done */ } pooldat.jobtab[0].domnorg = grafptr->m.domnorg; /* Build first job */ pooldat.jobtab[0].grafdat = grafptr->s; /* Clone original graph as first job graph */ pooldat.jobtab[0].grafdat.flagval &= ~GRAPHFREETABS; /* Do not free its arrays on exit */ kgraphMapRbMapPoolFrst (&pooldat, &pooldat.jobtab[0]); /* Add initial job */ comploadmin = (1.0 - paraptr->kbalval) * grafptr->comploadrat; /* Ratio can have been tilted when working on subgraph */ comploadmax = (1.0 + paraptr->kbalval) * grafptr->comploadrat; while (! kgraphMapRbMapPoolEmpty (&pooldat)) { /* For all non-empty pools */ KgraphMapRbMapJob * joborgptr; /* Pointer to current job */ while ((joborgptr = kgraphMapRbMapPoolGet (&pooldat)) != NULL) { /* For all jobs in pool */ int partval; jobsubnum[0] = joborgptr - pooldat.jobtab; /* Get current (and first son) job slot number before possible move of pointers */ joborgdat = *joborgptr; /* Save current job data (clone graph) */ if (archDomBipart (&grafptr->m.archdat, &joborgdat.domnorg, &domsubtab[0], &domsubtab[1]) != 0) { errorPrint ("kgraphMapRbMap: cannot bipartition domain"); kgraphMapRbMapPoolExit (&pooldat); /* Copied graph will be freed as not yet removed */ return (1); } if (bgraphInit (&bipgrafdat, &joborgdat.grafdat, /* Create bipartition graph */ pooldat.grafptr, pooldat.mappptr, domsubtab) != 0) { errorPrint ("kgraphMapRbMap: cannot create bipartition graph"); kgraphMapRbMapPoolExit (&pooldat); /* Copied graph will be freed as not yet removed */ return (1); } bipgrafdat.s.flagval |= (joborgdat.grafdat.flagval & GRAPHFREETABS); /* Bipartition graph is responsible for freeing the cloned graph data fields */ joborgptr->poolflag = 0; /* Original slot is now considered unused so that cloned graph data will not be freed twice */ if ((pooldat.flagval & KGRAPHMAPRBMAPARCHVAR) == 0) { /* If not variable-sized, impose constraints on bipartition */ double comploadavg; comploadavg = (double) bipgrafdat.s.velosum / (double) archDomWght (&grafptr->m.archdat, &joborgdat.domnorg); bipgrafdat.compload0min = bipgrafdat.compload0avg - (Gnum) MIN ((comploadmax - comploadavg) * (double) bipgrafdat.domwght[0], (comploadavg - comploadmin) * (double) bipgrafdat.domwght[1]); bipgrafdat.compload0max = bipgrafdat.compload0avg + (Gnum) MIN ((comploadavg - comploadmin) * (double) bipgrafdat.domwght[0], (comploadmax - comploadavg) * (double) bipgrafdat.domwght[1]); } if (bgraphBipartSt (&bipgrafdat, paraptr->strat) != 0) { /* Perform bipartitioning */ errorPrint ("kgraphMapRbMap: cannot bipartition job"); bgraphExit (&bipgrafdat); kgraphMapRbMapPoolExit (&pooldat); return (1); } memFree (bipgrafdat.frontab); /* Frontier array of bipartitioning graph is no longer necessary */ bipgrafdat.frontab = NULL; if ((partval = 1, bipgrafdat.compload0 == 0) || /* If no bipartition found */ (partval = 0, bipgrafdat.compload0 == bipgrafdat.s.velosum)) { if (((pooldat.flagval & KGRAPHMAPRBMAPARCHVAR) != 0) || /* If architecture is variable-sized */ (archDomSize (&grafptr->m.archdat, &domsubtab[partval]) <= 1)) { /* Or domain is terminal */ pooldat.domntab[jobsubnum[0]] = joborgdat.domnorg; /* Update domain in next pool */ kgraphMapRbMapPoolRemv (&pooldat, &joborgdat); /* Remove job from pool as long as graph exists */ bgraphExit (&bipgrafdat); /* Free bipartitioning data as well as current graph */ continue; /* Process next job in current pool */ } else { joborgptr->domnorg = /* New job takes same graph and non-empty subdomain */ pooldat.domntab[jobsubnum[0]] = domsubtab[partval]; /* Update domain in next pool */ kgraphMapRbMapPoolUpdt1 (&pooldat, &joborgdat, bipgrafdat.parttax, joborgptr, partval); /* Add job to pool */ continue; /* Process next job in current pool */ } } if ((pooldat.mappptr->domnnbr == pooldat.mappptr->domnmax) && /* If all job slots busy and if cannot resize */ (kgraphMapRbMapPoolResize (&pooldat) != 0)) { errorPrint ("kgraphMapRbMap: cannot resize structures"); kgraphMapRbMapPoolExit (&pooldat); return (1); } jobsubnum[1] = pooldat.mappptr->domnnbr ++; /* Get slot number of new subdomain */ jobsubsiz[1] = bipgrafdat.s.vertnbr - bipgrafdat.compsize0; jobsubsiz[0] = bipgrafdat.compsize0; pooldat.jobtab[jobsubnum[1]].poolflag = 0; /* Assume that new job is inactive in case of premature freeing */ pooldat.mappptr->domntab[jobsubnum[1]] = joborgdat.domnorg; /* Copy original domain to new subdomain as old mapping shares parttax with new */ pooldat.domntab[jobsubnum[0]] = domsubtab[0]; /* Set subdomains of second mapping before relinking subjobs in pool */ pooldat.domntab[jobsubnum[1]] = domsubtab[1]; if ((pooldat.flagval & KGRAPHMAPRBMAPPARTHALF) != 0) /* If can only update second half */ kgraphMapRbMapPartOne (&pooldat, &bipgrafdat, jobsubnum[1]); else kgraphMapRbMapPartBoth (&pooldat, &bipgrafdat, jobsubnum); for (i = 1; i >= 0; i --) { /* For both subdomains */ KgraphMapRbMapJob * jobsubptr; jobsubptr = &pooldat.jobtab[jobsubnum[i]]; /* Point to subdomain job slot */ jobsubptr->poollink.prev = /* Prevent Valgrind from yelling in kgraphMapRbMapPoolResize() */ jobsubptr->poollink.next = NULL; jobsubptr->prioval = /* Prevent Valgrind from yelling in kgraphMapRbMapPoolRemv()/Updt1()/Updt2() */ jobsubptr->priolvl = 0; if ((((pooldat.flagval & KGRAPHMAPRBMAPARCHVAR) == 0) && (archDomSize (&grafptr->m.archdat, &domsubtab[i]) <= 1)) || /* If single-vertex domain */ (((pooldat.flagval & KGRAPHMAPRBMAPARCHVAR) != 0) && (jobsubsiz[i] <= 1))) { /* Or if variable-sized architecture with single vertex graph */ jobsubsiz[i] = 0; /* Cancel subjob */ continue; } partval = i; /* At least this subjob works */ if (graphInducePart (&bipgrafdat.s, bipgrafdat.parttax, jobsubsiz[i], (GraphPart) i, &jobsubptr->grafdat) != 0) { errorPrint ("kgraphMapRbMap: cannot create induced subgraph"); bgraphExit (&bipgrafdat); kgraphMapRbMapPoolExit (&pooldat); return (1); } jobsubptr->poolflag = 1; /* So that graph is freed in case of error on other part */ jobsubptr->domnorg = domsubtab[i]; } if ((jobsubsiz[0] | jobsubsiz[1]) == 0) /* If both subjobs do not need further processing */ kgraphMapRbMapPoolRemv (&pooldat, &joborgdat); else if (jobsubsiz[1 - partval] == 0) /* If one of the subjobs only needs further processing */ kgraphMapRbMapPoolUpdt1 (&pooldat, &joborgdat, bipgrafdat.parttax, &pooldat.jobtab[jobsubnum[partval]], (GraphPart) partval); else kgraphMapRbMapPoolUpdt2 (&pooldat, &joborgdat, bipgrafdat.parttax, &pooldat.jobtab[jobsubnum[0]], &pooldat.jobtab[jobsubnum[1]]); bgraphExit (&bipgrafdat); /* Free bipartition graph data */ } kgraphMapRbMapPoolSwap (&pooldat); /* Swap current and next levels */ } kgraphMapRbMapPoolExit (&pooldat); /* Free internal structures and propagate back new partition */ return (0); } /**********************************************/ /* */ /* These routines handle internal structures. */ /* */ /**********************************************/ /* This routine doubles the size all of the arrays ** involved in handling the target architecture, ** to make room for new domains of variable-sized ** architectures. ** It returns: ** - 0 : if resize succeeded. ** - !0 : if out of memory. */ static int kgraphMapRbMapPoolResize ( KgraphMapRbMapPoolData * restrict const poolptr) { KgraphMapRbMapJob * restrict joboldtab; /* Pointer to old job array */ ArchDom * domnoldtab; /* Temporary pointer to domain array */ Anum domnmax; domnmax = poolptr->mappptr->domnmax * 2; joboldtab = poolptr->jobtab; /* Save old job table address */ if ((poolptr->jobtab = (KgraphMapRbMapJob *) memRealloc (joboldtab, domnmax * sizeof (KgraphMapRbMapJob))) == NULL) { errorPrint ("kgraphMapRbMapPoolResize: out of memory (1)"); poolptr->jobtab = joboldtab; return (1); } if (poolptr->jobtab != joboldtab) { /* If job array moved */ KgraphMapRbMapJob * joboldtnd; /* Pointer to end of old job array */ Anum jobnum; /* Temporary job index */ size_t jobdlt; /* Address delta value */ joboldtnd = joboldtab + poolptr->mappptr->domnmax; jobdlt = (byte *) poolptr->jobtab - (byte *) joboldtab; /* Compute delta between addresses */ for (jobnum = 0; jobnum < poolptr->mappptr->domnmax; jobnum ++) { if ((poolptr->jobtab[jobnum].poollink.prev >= (KgraphMapRbMapPoolLink *) joboldtab) && /* If old pointers within bounds of old array, adjust them */ (poolptr->jobtab[jobnum].poollink.prev < (KgraphMapRbMapPoolLink *) joboldtnd)) poolptr->jobtab[jobnum].poollink.prev = (KgraphMapRbMapPoolLink *) ((byte *) poolptr->jobtab[jobnum].poollink.prev + jobdlt); if ((poolptr->jobtab[jobnum].poollink.next >= (KgraphMapRbMapPoolLink *) joboldtab) && (poolptr->jobtab[jobnum].poollink.next < (KgraphMapRbMapPoolLink *) joboldtnd)) poolptr->jobtab[jobnum].poollink.next = (KgraphMapRbMapPoolLink *) ((byte *) poolptr->jobtab[jobnum].poollink.next + jobdlt); } if (poolptr->linktab[0].next != &kgraphmaprbmappooldummy) /* Update first pool pointer */ poolptr->linktab[0].next = (KgraphMapRbMapPoolLink *) ((byte *) poolptr->linktab[0].next + jobdlt); if (poolptr->pooltab[0] != poolptr->pooltab[1]) { /* If job pools not tied */ if (poolptr->linktab[1].next != &kgraphmaprbmappooldummy) /* Update second pool pointer */ poolptr->linktab[1].next = (KgraphMapRbMapPoolLink *) ((byte *) poolptr->linktab[1].next + jobdlt); } } domnoldtab = poolptr->mappptr->domntab; if ((poolptr->mappptr->domntab = (ArchDom *) memRealloc (domnoldtab, domnmax * sizeof (ArchDom))) == NULL) { errorPrint ("kgraphMapRbMapPoolResize: out of memory (2)"); poolptr->mappptr->domntab = domnoldtab; return (1); } if (poolptr->domntab != domnoldtab) { /* If mappings not tied */ domnoldtab = poolptr->domntab; if ((poolptr->domntab = (ArchDom *) memRealloc (domnoldtab, domnmax * sizeof (ArchDom))) == NULL) { errorPrint ("kgraphMapRbMapPoolResize: out of memory (3)"); poolptr->domntab = domnoldtab; return (1); } } else poolptr->domntab = poolptr->mappptr->domntab; /* Update second domain array in case first one moved */ poolptr->mappptr->domnmax = domnmax; /* Double job slot limit */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_hf.c0000644000175300017530000001606211631334325022425 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_hf.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders a subgraph using **/ /** the block-oriented Halo Approximate **/ /** (Multiple) Minimum Fill algorithm, **/ /** with super-variable accounting **/ /** R2HAMDf4 v2.0). **/ /** **/ /** DATES : # Version 3.4 : from : 15 may 2001 **/ /** to : 23 nov 2001 **/ /** # Version 4.0 : from : 10 jan 2003 **/ /** to : 24 jan 2004 **/ /** # Version 5.0 : from : 10 sep 2007 **/ /** to : 10 sep 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HGRAPH_ORDER_HF #include "module.h" #include "common.h" #include "graph.h" #include "order.h" #include "hgraph.h" #include "hall_order_hf.h" #include "hall_order_hx.h" #include "hgraph_order_hf.h" #include "hgraph_order_hx.h" #include "hgraph_order_si.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hgraphOrderHf ( const Hgraph * restrict const grafptr, Order * restrict const ordeptr, const Gnum ordenum, /*+ Zero-based ordering number +*/ OrderCblk * restrict const cblkptr, /*+ Multiple column-block +*/ const HgraphOrderHfParam * restrict const paraptr) { Gnum nbbuck; Gnum * restrict petab; Gnum pfree; Gnum iwlen; Gnum * restrict iwtab; Gnum * restrict lentab; Gnum * restrict nvartab; Gnum * restrict elentab; Gnum * restrict lasttab; Gnum * restrict leaftab; Gnum * restrict secntab; /* Array of index to first secondary variable */ Gnum * restrict nexttab; /* Array of index of next principal variable */ Gnum * restrict frsttab; Gnum * restrict headtab; /* Head array : nbbuck = 2 * n */ Gnum ncmpa; Gnum n; /* Number of nodes to order (with halo or not) */ int o; if (grafptr->s.vertnbr < paraptr->colmin) /* If graph is too small, order simply */ return (hgraphOrderSi (grafptr, ordeptr, ordenum, cblkptr)); n = grafptr->s.vertnbr; nbbuck = n * 2; iwlen = (Gnum) ((double) grafptr->s.edgenbr * HGRAPHORDERHFCOMPRAT) + 32; if (iwlen < n) /* Prepare to re-use array */ iwlen = n; if (memAllocGroup ((void **) (void *) &petab, (size_t) (n * sizeof (Gnum)), &iwtab, (size_t) (iwlen * sizeof (Gnum)), &lentab, (size_t) (n * sizeof (Gnum)), &nvartab, (size_t) (n * sizeof (Gnum)), &elentab, (size_t) (n * sizeof (Gnum)), &lasttab, (size_t) (n * sizeof (Gnum)), &leaftab, (size_t) (n * sizeof (Gnum)), &frsttab, (size_t) (n * sizeof (Gnum)), &secntab, (size_t) (n * sizeof (Gnum)), &nexttab, (size_t) (n * sizeof (Gnum)), &headtab, (size_t) ((nbbuck + 2) * sizeof (Gnum)), NULL) == NULL) { errorPrint ("hgraphOrderHf: out of memory"); return (1); } hgraphOrderHxFill (grafptr, petab, lentab, iwtab, elentab, &pfree); hallOrderHfR2hamdf4 (n, 0, nbbuck, iwlen, petab, pfree, /* No elements here */ lentab, iwtab, nvartab, elentab, lasttab, &ncmpa, leaftab, secntab, nexttab, frsttab, headtab); if (ncmpa < 0) { errorPrint ("hgraphOrderHf: internal error"); memFree (petab); /* Free group leader */ return (1); } o = hallOrderHxBuild (grafptr->s.baseval, n, grafptr->vnohnbr, grafptr->s.vnumtax, ordeptr, cblkptr, nvartab - grafptr->s.baseval, lentab - grafptr->s.baseval, petab - grafptr->s.baseval, frsttab - grafptr->s.baseval, nexttab - grafptr->s.baseval, secntab - grafptr->s.baseval, iwtab - grafptr->s.baseval, elentab - grafptr->s.baseval, ordeptr->peritab + ordenum, /* Use given inverse permutation as inverse permutation space, never based */ leaftab, paraptr->colmin, paraptr->colmax, (float) paraptr->fillrat); memFree (petab); /* Free group leader */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/vmesh_separate_st.c0000644000175300017530000003267511631334325023030 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh_separate_st.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the global mesh **/ /** separation strategy and method tables. **/ /** **/ /** DATES : # Version 4.0 : from : 20 sep 2002 **/ /** to 08 feb 2003 **/ /** # Version 5.0 : from : 04 aug 2007 **/ /** to 04 aug 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VMESH_SEPARATE_ST #include "module.h" #include "common.h" #include "gain.h" #include "parser.h" #include "graph.h" #include "vgraph.h" #include "vgraph_separate_st.h" #include "mesh.h" #include "mesh_coarsen.h" #include "vmesh.h" #include "vmesh_separate_fm.h" #include "vmesh_separate_gg.h" #include "vmesh_separate_gr.h" #include "vmesh_separate_ml.h" #include "vmesh_separate_zr.h" #include "vmesh_separate_st.h" /* ** The static and global variables. */ static Vmesh vmeshdummy; /* Dummy separator mesh for offset computations */ static union { VmeshSeparateFmParam param; StratNodeMethodData padding; } vmeshseparatedefaultfm = { { 200, 1000, 0.1L } }; static union { VmeshSeparateGgParam param; StratNodeMethodData padding; } vmeshseparatedefaultgg = { { 5 } }; static union { VmeshSeparateGrParam param; StratNodeMethodData padding; } vmeshseparatedefaultgr = { { &stratdummy } }; static union { VmeshSeparateMlParam param; StratNodeMethodData padding; } vmeshseparatedefaultml = { { 1000, 0.8L, MESHCOARSENNGB, &stratdummy, &stratdummy } }; static StratMethodTab vmeshseparatestmethtab[] = { /* Mesh separation methods array */ { VMESHSEPASTMETHFM, "f", vmeshSeparateFm, &vmeshseparatedefaultfm }, { VMESHSEPASTMETHGG, "h", vmeshSeparateGg, &vmeshseparatedefaultgg }, #ifdef SCOTCH_DEBUG_VMESH2 { VMESHSEPASTMETHGR, "v", vmeshSeparateGr, &vmeshseparatedefaultgr }, #endif /* SCOTCH_DEBUG_VMESH2 */ { VMESHSEPASTMETHML, "m", vmeshSeparateMl, &vmeshseparatedefaultml }, { VMESHSEPASTMETHZR, "z", vmeshSeparateZr, NULL }, { -1, NULL, NULL, NULL } }; static StratParamTab vmeshseparatestparatab[] = { /* Mesh separation method parameter list */ { VMESHSEPASTMETHFM, STRATPARAMINT, "move", (byte *) &vmeshseparatedefaultfm.param, (byte *) &vmeshseparatedefaultfm.param.movenbr, NULL }, { VMESHSEPASTMETHFM, STRATPARAMINT, "pass", (byte *) &vmeshseparatedefaultfm.param, (byte *) &vmeshseparatedefaultfm.param.passnbr, NULL }, { VMESHSEPASTMETHFM, STRATPARAMDOUBLE, "bal", (byte *) &vmeshseparatedefaultfm.param, (byte *) &vmeshseparatedefaultfm.param.deltrat, NULL }, { VMESHSEPASTMETHGG, STRATPARAMINT, "pass", (byte *) &vmeshseparatedefaultgg.param, (byte *) &vmeshseparatedefaultgg.param.passnbr, NULL }, #ifdef SCOTCH_DEBUG_VMESH2 { VMESHSEPASTMETHGR, STRATPARAMSTRAT, "strat", (byte *) &vmeshseparatedefaultgr.param, (byte *) &vmeshseparatedefaultgr.param.stratptr, (void *) &vgraphseparateststratab }, #endif /* SCOTCH_DEBUG_VMESH2 */ { VMESHSEPASTMETHML, STRATPARAMSTRAT, "asc", (byte *) &vmeshseparatedefaultml.param, (byte *) &vmeshseparatedefaultml.param.stratasc, (void *) &vmeshseparateststratab }, { VMESHSEPASTMETHML, STRATPARAMSTRAT, "low", (byte *) &vmeshseparatedefaultml.param, (byte *) &vmeshseparatedefaultml.param.stratlow, (void *) &vmeshseparateststratab }, { VMESHSEPASTMETHML, STRATPARAMCASE, "type", (byte *) &vmeshseparatedefaultml.param, (byte *) &vmeshseparatedefaultml.param.coartype, (void *) "hsn" }, { VMESHSEPASTMETHML, STRATPARAMINT, "vnod", (byte *) &vmeshseparatedefaultml.param, (byte *) &vmeshseparatedefaultml.param.vnodnbr, NULL }, { VMESHSEPASTMETHML, STRATPARAMDOUBLE, "rat", (byte *) &vmeshseparatedefaultml.param, (byte *) &vmeshseparatedefaultml.param.coarrat, NULL }, { VMESHSEPASTMETHNBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; static StratParamTab vmeshseparatestcondtab[] = { /* Mesh condition parameter table */ { STRATNODECOND, STRATPARAMINT, "edge", (byte *) &vmeshdummy, (byte *) &vmeshdummy.m.edgenbr, NULL }, { STRATNODECOND, STRATPARAMINT, "levl", (byte *) &vmeshdummy, (byte *) &vmeshdummy.levlnum, NULL }, { STRATNODECOND, STRATPARAMINT, "load", (byte *) &vmeshdummy, (byte *) &vmeshdummy.m.vnlosum, NULL }, { STRATNODECOND, STRATPARAMINT, "velm", (byte *) &vmeshdummy, (byte *) &vmeshdummy.m.velmnbr, NULL }, { STRATNODECOND, STRATPARAMINT, "vnod", (byte *) &vmeshdummy, (byte *) &vmeshdummy.m.vnodnbr, NULL }, { STRATNODENBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; StratTab vmeshseparateststratab = { /* Strategy tables for mesh separation methods */ vmeshseparatestmethtab, vmeshseparatestparatab, vmeshseparatestcondtab }; /*******************************************/ /* */ /* This is the generic separation routine. */ /* */ /*******************************************/ /* This routine computes the separation of ** the given graph according to the given ** strategy. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int vmeshSeparateSt ( Vmesh * restrict const meshptr, /*+ Separation mesh +*/ const Strat * restrict const strat) /*+ Separation strategy +*/ { StratTest val; VmeshStore save[2]; /* Results of the two strategies */ int o; #ifdef SCOTCH_DEBUG_VMESH2 if (sizeof (Gnum) != sizeof (INT)) { errorPrint ("vmeshSeparateSt: invalid type specification for parser variables"); return (1); } if ((sizeof (VmeshSeparateFmParam) > sizeof (StratNodeMethodData)) || (sizeof (VmeshSeparateGgParam) > sizeof (StratNodeMethodData)) || (sizeof (VmeshSeparateGrParam) > sizeof (StratNodeMethodData)) || (sizeof (VmeshSeparateMlParam) > sizeof (StratNodeMethodData))) { errorPrint ("vmeshSeparateSt: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ #ifdef SCOTCH_DEBUG_VMESH1 if (strat->tabl != &vmeshseparateststratab) { errorPrint ("vmeshSeparateSt: invalid parameter (1)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH1 */ o = 0; switch (strat->type) { case STRATNODECONCAT : o = vmeshSeparateSt (meshptr, strat->data.concat.strat[0]); /* Apply first strategy */ if (o == 0) /* If it worked all right */ o |= vmeshSeparateSt (meshptr, strat->data.concat.strat[1]); /* Then apply second strategy */ break; case STRATNODECOND : o = stratTestEval (strat->data.cond.test, &val, (void *) meshptr); /* Evaluate expression */ if (o == 0) { /* If evaluation was correct */ #ifdef SCOTCH_DEBUG_VMESH2 if ((val.typetest != STRATTESTVAL) && (val.typenode != STRATPARAMLOG)) { errorPrint ("vmeshSeparateSt: invalid test result"); o = 1; break; } #endif /* SCOTCH_DEBUG_VMESH2 */ if (val.data.val.vallog == 1) /* If expression is true */ o = vmeshSeparateSt (meshptr, strat->data.cond.strat[0]); /* Apply first strategy */ else { /* Else if expression is false */ if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ o = vmeshSeparateSt (meshptr, strat->data.cond.strat[1]); /* Apply second strategy */ } } break; case STRATNODEEMPTY : break; case STRATNODESELECT : if (((vmeshStoreInit (meshptr, &save[0])) != 0) || /* Allocate save areas */ ((vmeshStoreInit (meshptr, &save[1])) != 0)) { errorPrint ("vmeshSeparateSt: out of memory"); vmeshStoreExit (&save[0]); return (1); } vmeshStoreSave (meshptr, &save[1]); /* Save initial bipartition */ vmeshSeparateSt (meshptr, strat->data.select.strat[0]); /* Apply first strategy */ vmeshStoreSave (meshptr, &save[0]); /* Save its result */ vmeshStoreUpdt (meshptr, &save[1]); /* Restore initial bipartition */ vmeshSeparateSt (meshptr, strat->data.select.strat[1]); /* Apply second strategy */ if ( (save[0].fronnbr < meshptr->fronnbr) || /* If first strategy is better */ ((save[0].fronnbr == meshptr->fronnbr) && (abs (save[0].ncmploaddlt) < abs (meshptr->ncmploaddlt)))) vmeshStoreUpdt (meshptr, &save[0]); /* Restore its result */ vmeshStoreExit (&save[0]); /* Free both save areas */ vmeshStoreExit (&save[1]); break; #ifdef SCOTCH_DEBUG_VMESH1 case STRATNODEMETHOD : #else /* SCOTCH_DEBUG_VMESH1 */ default : #endif /* SCOTCH_DEBUG_VMESH1 */ return (strat->tabl->methtab[strat->data.method.meth].func (meshptr, (void *) &strat->data.method.data)); #ifdef SCOTCH_DEBUG_VMESH1 default : errorPrint ("vmeshSeparateSt: invalid parameter (2)"); return (1); #endif /* SCOTCH_DEBUG_VMESH1 */ } return (o); } scotch-5.1.12b.dfsg/src/libscotch/bdgraph_bipart_st.c0000644000175300017530000004553211631334325022766 0ustar hazelscthazelsct/* Copyright 2007-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_bipart_st.c **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the strategy and **/ /** method tables for distributed graph **/ /** bipartitioning methods. **/ /** **/ /** DATES : # Version 5.1 : from : 10 sep 2007 **/ /** to : 15 apr 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BDGRAPH_BIPART_ST #include "module.h" #include "common.h" #include "gain.h" #include "parser.h" #include "graph.h" #include "arch.h" #include "bgraph.h" #include "bgraph_bipart_st.h" #include "dgraph.h" #include "dgraph_coarsen.h" #include "bdgraph.h" #include "bdgraph_bipart_bd.h" #include "bdgraph_bipart_df.h" #include "bdgraph_bipart_ex.h" #include "bdgraph_bipart_ml.h" #include "bdgraph_bipart_sq.h" #include "bdgraph_bipart_st.h" #include "bdgraph_bipart_zr.h" /* ** The static and global variables. */ static Bdgraph bdgraphdummy; /* Dummy distributed bipartitioned graph for offset computations */ static union { BdgraphBipartBdParam param; StratNodeMethodData padding; } bdgraphbipartstdefaultbd = { { 3, &stratdummy } }; static union { BdgraphBipartDfParam param; StratNodeMethodData padding; } bdgraphbipartstdefaultdf = { { 500, 1.0, 0.0, BDGRAPHBIPARTDFTYPEBAL } }; static union { BdgraphBipartExParam param; StratNodeMethodData padding; } bdgraphbipartstdefaultex = { { 5, 0.005 } }; static union { BdgraphBipartMlParam param; StratNodeMethodData padding; } bdgraphbipartstdefaultml = { { 5, 1000, 100, 0, 0.8L, &stratdummy, &stratdummy, &stratdummy} }; static union { BdgraphBipartSqParam param; StratNodeMethodData padding; } bdgraphbipartstdefaultsq = { { &stratdummy } }; static StratMethodTab bdgraphbipartstmethtab[] = { /* Bipartitioning methods array */ { BDGRAPHBIPARTSTMETHBD, "b", bdgraphBipartBd, &bdgraphbipartstdefaultbd }, { BDGRAPHBIPARTSTMETHDF, "d", bdgraphBipartDf, &bdgraphbipartstdefaultdf }, { BDGRAPHBIPARTSTMETHEX, "x", bdgraphBipartEx, &bdgraphbipartstdefaultex }, { BDGRAPHBIPARTSTMETHML, "m", bdgraphBipartMl, &bdgraphbipartstdefaultml }, { BDGRAPHBIPARTSTMETHSQ, "q", bdgraphBipartSq, &bdgraphbipartstdefaultsq }, { BDGRAPHBIPARTSTMETHZR, "z", bdgraphBipartZr, NULL }, { -1, NULL, NULL, NULL } }; static StratParamTab bdgraphbipartstparatab[] = { /* Method parameter list */ { BDGRAPHBIPARTSTMETHBD, STRATPARAMINT, "width", (byte *) &bdgraphbipartstdefaultbd.param, (byte *) &bdgraphbipartstdefaultbd.param.distmax, NULL }, { BDGRAPHBIPARTSTMETHBD, STRATPARAMSTRAT, "bnd", (byte *) &bdgraphbipartstdefaultbd.param, (byte *) &bdgraphbipartstdefaultbd.param.stratbnd, (void *) &bdgraphbipartststratab }, { BDGRAPHBIPARTSTMETHBD, STRATPARAMSTRAT, "org", (byte *) &bdgraphbipartstdefaultbd.param, (byte *) &bdgraphbipartstdefaultbd.param.stratorg, (void *) &bdgraphbipartststratab }, { BDGRAPHBIPARTSTMETHDF, STRATPARAMINT, "pass", (byte *) &bdgraphbipartstdefaultdf.param, (byte *) &bdgraphbipartstdefaultdf.param.passnbr, NULL }, { BDGRAPHBIPARTSTMETHDF, STRATPARAMDOUBLE, "dif", (byte *) &bdgraphbipartstdefaultdf.param, (byte *) &bdgraphbipartstdefaultdf.param.cdifval, NULL }, { BDGRAPHBIPARTSTMETHDF, STRATPARAMDOUBLE, "rem", (byte *) &bdgraphbipartstdefaultdf.param, (byte *) &bdgraphbipartstdefaultdf.param.cremval, NULL }, { BDGRAPHBIPARTSTMETHDF, STRATPARAMCASE, "type", (byte *) &bdgraphbipartstdefaultdf.param, (byte *) &bdgraphbipartstdefaultdf.param.typeval, (void *) "bk" }, { BDGRAPHBIPARTSTMETHEX, STRATPARAMINT, "sbbt", (byte *) &bdgraphbipartstdefaultex.param, (byte *) &bdgraphbipartstdefaultex.param.sbbtnbr, NULL }, { BDGRAPHBIPARTSTMETHEX, STRATPARAMDOUBLE, "bal", (byte *) &bdgraphbipartstdefaultex.param, (byte *) &bdgraphbipartstdefaultex.param.deltval, NULL }, { BDGRAPHBIPARTSTMETHML, STRATPARAMSTRAT, "asc", (byte *) &bdgraphbipartstdefaultml.param, (byte *) &bdgraphbipartstdefaultml.param.stratasc, (void *) &bdgraphbipartststratab }, { BDGRAPHBIPARTSTMETHML, STRATPARAMSTRAT, "low", (byte *) &bdgraphbipartstdefaultml.param, (byte *) &bdgraphbipartstdefaultml.param.stratlow, (void *) &bdgraphbipartststratab }, { BDGRAPHBIPARTSTMETHML, STRATPARAMSTRAT, "seq", (byte *) &bdgraphbipartstdefaultml.param, (byte *) &bdgraphbipartstdefaultml.param.stratseq, (void *) &bdgraphbipartststratab }, { BDGRAPHBIPARTSTMETHML, STRATPARAMINT, "pass", (byte *) &bdgraphbipartstdefaultml.param, (byte *) &bdgraphbipartstdefaultml.param.passnbr, NULL }, { BDGRAPHBIPARTSTMETHML, STRATPARAMINT, "vert", (byte *) &bdgraphbipartstdefaultml.param, (byte *) &bdgraphbipartstdefaultml.param.coarnbr, NULL }, { BDGRAPHBIPARTSTMETHML, STRATPARAMDOUBLE, "rat", (byte *) &bdgraphbipartstdefaultml.param, (byte *) &bdgraphbipartstdefaultml.param.coarrat, NULL }, { BDGRAPHBIPARTSTMETHSQ, STRATPARAMSTRAT, "strat", (byte *) &bdgraphbipartstdefaultsq.param, (byte *) &bdgraphbipartstdefaultsq.param.strat, (void *) &bgraphbipartststratab }, { BDGRAPHBIPARTSTMETHNBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; static StratParamTab bdgraphbipartstcondtab[] = { /* Active graph condition parameter table */ { STRATNODECOND, STRATPARAMINT, "load", (byte *) &bdgraphdummy, (byte *) &bdgraphdummy.s.veloglbsum, NULL }, { STRATNODECOND, STRATPARAMINT, "load0", (byte *) &bdgraphdummy, (byte *) &bdgraphdummy.compglbload0, NULL }, { STRATNODECOND, STRATPARAMINT, "lmin0", (byte *) &bdgraphdummy, (byte *) &bdgraphdummy.compglbload0min, NULL }, { STRATNODECOND, STRATPARAMINT, "lmax0", (byte *) &bdgraphdummy, (byte *) &bdgraphdummy.compglbload0max, NULL }, { STRATNODECOND, STRATPARAMINT, "edge", (byte *) &bdgraphdummy, (byte *) &bdgraphdummy.s.edgeglbnbr, NULL }, { STRATNODECOND, STRATPARAMINT, "vert", (byte *) &bdgraphdummy, (byte *) &bdgraphdummy.s.vertglbnbr, NULL }, { STRATNODECOND, STRATPARAMINT, "levl", (byte *) &bdgraphdummy, (byte *) &bdgraphdummy.levlnum, NULL }, { STRATNODECOND, STRATPARAMINT, "proc", (byte *) &bdgraphdummy, (byte *) &bdgraphdummy.s.procglbnbr, NULL }, { STRATNODECOND, STRATPARAMINT, "rank", (byte *) &bdgraphdummy, (byte *) &bdgraphdummy.s.proclocnum, NULL }, { STRATNODENBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; StratTab bdgraphbipartststratab = { /* Strategy tables for graph bipartitioning methods */ bdgraphbipartstmethtab, bdgraphbipartstparatab, bdgraphbipartstcondtab }; /***********************************************/ /* */ /* This is the generic bipartitioning routine. */ /* */ /***********************************************/ /* This routine performs the bipartitioning of ** the given active graph according to the ** given strategy. ** It returns: ** - 0 : if bipartitioning could be computed. ** - 1 : on error. */ int bdgraphBipartSt ( Bdgraph * restrict const grafptr, /*+ Active graph to bipartition +*/ const Strat * restrict const strat) /*+ Bipartitioning strategy +*/ { StratTest val; /* Result of condition evaluation */ BdgraphStore savetab[2]; /* Results of the two strategies */ int o; int o2; #ifdef SCOTCH_DEBUG_BDGRAPH2 MPI_Comm proccommold; /*Save area for old communicator */ #endif /* SCOTCH_DEBUG_BDGRAPH2 */ #ifdef SCOTCH_DEBUG_BDGRAPH2 if (sizeof (Gnum) != sizeof (INT)) { errorPrint ("bdgraphBipartSt: invalid type specification for parser variables"); return (1); } if (/*(sizeof (BdgraphBipartFmParam) > sizeof (StratNodeMethodData)) || (sizeof (BdgraphBipartGgParam) > sizeof (StratNodeMethodData)) ||*/ (sizeof (BdgraphBipartMlParam) > sizeof (StratNodeMethodData))) { errorPrint ("bdgraphBipartSt: invalid type specification"); return (1); } /* TODO REMOVE */ #endif /* SCOTCH_DEBUG_BDGRAPH2 */ #ifdef SCOTCH_DEBUG_BDGRAPH1 if ((strat->tabl != &bdgraphbipartststratab) && (strat != &stratdummy)) { errorPrint ("bdgraphBipartSt: invalid parameter (1)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH1 */ o = 0; switch (strat->type) { case STRATNODECONCAT : o = bdgraphBipartSt (grafptr, strat->data.concat.strat[0]); /* Apply the first strategy */ if (o == 0) /* If it worked all right */ o |= bdgraphBipartSt (grafptr, strat->data.concat.strat[1]); /* Then apply second strategy */ break; case STRATNODECOND : o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ if (o == 0) { /* If evaluation was correct */ #ifdef SCOTCH_DEBUG_BDGRAPH2 if ((val.typetest != STRATTESTVAL) || (val.typenode != STRATPARAMLOG)) { errorPrint ("bdgraphBipartSt: invalid test result"); o = 1; break; } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ if (val.data.val.vallog == 1) /* If expression is true */ o = bdgraphBipartSt (grafptr, strat->data.cond.strat[0]); /* Apply first strategy */ else { /* Else if expression is false */ if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ o = bdgraphBipartSt (grafptr, strat->data.cond.strat[1]); /* Apply second strategy */ } } break; case STRATNODEEMPTY : break; case STRATNODESELECT : if (((bdgraphStoreInit (grafptr, &savetab[0])) != 0) || /* Allocate save areas */ ((bdgraphStoreInit (grafptr, &savetab[1])) != 0)) { errorPrint ("bdgraphBipartSt: out of memory"); bdgraphStoreExit (&savetab[0]); return (1); } bdgraphStoreSave (grafptr, &savetab[1]); /* Save initial bipartition */ o = bdgraphBipartSt (grafptr, strat->data.select.strat[0]); /* Apply first strategy */ bdgraphStoreSave (grafptr, &savetab[0]); /* Save its result */ bdgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition */ o2 = bdgraphBipartSt (grafptr, strat->data.select.strat[1]); /* Apply second strategy */ if ((o == 0) || (o2 == 0)) { /* If at least one method did bipartition */ Gnum compglbload0; int b0; int b1; compglbload0 = grafptr->compglbload0avg + savetab[0].compglbload0dlt; b0 = ((compglbload0 < grafptr->compglbload0min) || (compglbload0 > grafptr->compglbload0max)) ? 1 : o; compglbload0 = grafptr->compglbload0avg + savetab[1].compglbload0dlt; b1 = ((compglbload0 < grafptr->compglbload0min) || (compglbload0 > grafptr->compglbload0max)) ? 1 : o2; do { /* Do we want to restore partition 0 ? */ if (b0 > b1) break; if (b0 == b1) { /* If both are valid or invalid */ if (b0 == 0) { /* If both are valid */ if ( (savetab[0].commglbload > grafptr->commglbload) || /* Compare on cut */ ((savetab[0].commglbload == grafptr->commglbload) && (abs (savetab[0].compglbload0dlt) > abs (grafptr->compglbload0dlt)))) break; } else { /* If both are invalid */ if ( (abs (savetab[0].compglbload0dlt) > abs (grafptr->compglbload0dlt)) || /* Compare on imbalance */ ((abs (savetab[0].compglbload0dlt) == abs (grafptr->compglbload0dlt)) && (savetab[0].commglbload > grafptr->commglbload))) break; } } bdgraphStoreUpdt (grafptr, &savetab[0]); /* Restore its result */ } while (0); } if (o2 < o) /* o = min(o,o2): if one biparts, then bipart */ o = o2; /* Else if one stops, then stop, else error */ bdgraphStoreExit (&savetab[0]); /* Free both save areas */ bdgraphStoreExit (&savetab[1]); break; #ifdef SCOTCH_DEBUG_BDGRAPH1 case STRATNODEMETHOD : #else /* SCOTCH_DEBUG_BDGRAPH1 */ default : #endif /* SCOTCH_DEBUG_BDGRAPH1 */ #ifdef SCOTCH_DEBUG_BDGRAPH2 proccommold = grafptr->s.proccomm; /* Create new communicator to isolate method communications */ MPI_Comm_dup (proccommold, &grafptr->s.proccomm); #endif /* SCOTCH_DEBUG_BDGRAPH2 */ o = (strat->tabl->methtab[strat->data.method.meth].func (grafptr, (void *) &strat->data.method.data)); #ifdef SCOTCH_DEBUG_BDGRAPH2 MPI_Comm_free (&grafptr->s.proccomm); /* Restore old communicator */ grafptr->s.proccomm = proccommold; #endif /* SCOTCH_DEBUG_BDGRAPH2 */ #ifdef SCOTCH_DEBUG_BDGRAPH1 break; default : errorPrint ("bdgraphBipartSt: invalid parameter (2)"); return (1); #endif /* SCOTCH_DEBUG_BDGRAPH1 */ } return (o); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_check_f.c0000644000175300017530000000620011631334325023730 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_check_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the distributed source graph handling **/ /** routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 26 aug 2006 **/ /** to 26 aug 2006 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the distributed graph handling */ /* routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFDGRAPHCHECK, scotchfdgraphcheck, ( \ const SCOTCH_Dgraph * const grafptr, \ int * const revaptr), \ (grafptr, revaptr)) { *revaptr = SCOTCH_dgraphCheck (grafptr); } scotch-5.1.12b.dfsg/src/libscotch/order_io.c0000644000175300017530000002361611631334325021111 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : order_io.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles generic orderings. **/ /** **/ /** DATES : # Version 3.2 : from : 19 oct 1996 **/ /** to 27 aug 1998 **/ /** # Version 4.0 : from : 19 dec 2001 **/ /** to 28 jun 2004 **/ /** # Version 5.0 : from : 12 sep 2007 **/ /** to 27 feb 2008 **/ /** # Version 5.1 : from : 11 aug 2010 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ORDER_IO #include "module.h" #include "common.h" #include "graph.h" #include "order.h" /************************************/ /* */ /* These routines handle orderings. */ /* */ /************************************/ /* This routine loads an ordering. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int orderLoad ( Order * restrict const ordeptr, const Gnum * restrict const vlbltab, FILE * restrict const stream) { Gnum * restrict permtab; Gnum vertnum; if (vlbltab != NULL) { errorPrint ("orderLoad: vertex labels not yet supported"); return (1); } if ((permtab = memAlloc (ordeptr->vnodnbr * sizeof (Gnum))) == NULL) { errorPrint ("orderLoad: out of memory"); return (1); } if (intLoad (stream, &ordeptr->vnodnbr) != 1) { errorPrint ("orderLoad: bad input (1)"); memFree (permtab); return (1); } if (vlbltab == NULL) { /* If ordering does not have label array */ for (vertnum = 0; vertnum < ordeptr->vnodnbr; vertnum ++) { Gnum vertval; if ((intLoad (stream, &vertval) != 1) || /* Read item data */ (intLoad (stream, &permtab[vertnum]) != 1)) { errorPrint ("orderLoad: bad input (2)"); memFree (permtab); return (1); } if (vertval != (vertnum + ordeptr->baseval)) { /* Read item data */ errorPrint ("orderLoad: bad input (3)"); memFree (permtab); return (1); } } } orderPeri (permtab, ordeptr->baseval, ordeptr->vnodnbr, ordeptr->peritab, ordeptr->baseval); /* Compute inverse permutation */ memFree (permtab); return (0); } /* This routine saves an ordering. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int orderSave ( const Order * restrict const ordeptr, const Gnum * restrict const vlbltab, FILE * restrict const stream) { const Gnum * restrict vlbltax; Gnum * restrict permtab; Gnum vertnum; vlbltax = (vlbltab != NULL) ? (vlbltab - ordeptr->baseval) : NULL; if ((permtab = memAlloc (ordeptr->vnodnbr * sizeof (Gnum))) == NULL) { errorPrint ("orderSave: out of memory"); return (1); } if (fprintf (stream, GNUMSTRING "\n", (Gnum) ordeptr->vnodnbr) == EOF) { errorPrint ("orderSave: bad output (1)"); memFree (permtab); return (1); } orderPeri (ordeptr->peritab, ordeptr->baseval, ordeptr->vnodnbr, permtab, ordeptr->baseval); /* Compute direct permutation */ if (vlbltax != NULL) { /* If ordering has label array */ for (vertnum = 0; vertnum < ordeptr->vnodnbr; vertnum ++) { if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", (Gnum) vlbltax[vertnum + ordeptr->baseval], (Gnum) vlbltax[permtab[vertnum]]) == EOF) { errorPrint ("orderSave: bad output (2)"); memFree (permtab); return (1); } } } else { for (vertnum = 0; vertnum < ordeptr->vnodnbr; vertnum ++) { if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", (Gnum) (vertnum + ordeptr->baseval), (Gnum) permtab[vertnum]) == EOF) { errorPrint ("orderSave: bad output (3)"); memFree (permtab); return (1); } } } memFree (permtab); return (0); } /* This routine saves the column block ** mapping data of the given ordering. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int orderSaveMap ( const Order * restrict const ordeptr, const Gnum * restrict const vlbltab, FILE * const stream) { const Gnum * restrict vlbltax; const Gnum * restrict peritax; Gnum * restrict rangtab; Gnum * restrict cblktax; Gnum vnodnnd; Gnum vnodnum; Gnum cblknum; int o; if (fprintf (stream, GNUMSTRING "\n", (Gnum) ordeptr->vnodnbr) == EOF) { errorPrint ("orderSaveMap: bad output (1)"); return (1); } if (memAllocGroup ((void **) (void *) &rangtab, (size_t) ((ordeptr->vnodnbr + 1) * sizeof (Gnum)), &cblktax, (size_t) ( ordeptr->vnodnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("orderSaveMap: out of memory"); return (1); } cblktax -= ordeptr->baseval; orderRang (ordeptr, rangtab); peritax = ordeptr->peritab - ordeptr->baseval; for (vnodnum = ordeptr->baseval, vnodnnd = vnodnum + ordeptr->vnodnbr, cblknum = 0; vnodnum < vnodnnd; vnodnum ++) { if (vnodnum >= rangtab[cblknum + 1]) cblknum ++; cblktax[peritax[vnodnum]] = cblknum; } vlbltax = (vlbltab != NULL) ? (vlbltab - ordeptr->baseval) : NULL; for (vnodnum = ordeptr->baseval, o = 0; vnodnum < vnodnnd; vnodnum ++) { if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", (Gnum) ((vlbltax != NULL) ? vlbltax[vnodnum] : vnodnum), (Gnum) cblktax[vnodnum]) == EOF) { errorPrint ("orderSaveMap: bad output (2)"); o = 1; break; } } memFree (rangtab); /* Free memory group leader */ return (o); } /* This routine saves the separator ** tree data of the given ordering. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int orderSaveTree ( const Order * restrict const ordeptr, const Gnum * restrict const vlbltab, FILE * const stream) { const Gnum * restrict vlbltax; const Gnum * restrict peritax; Gnum * restrict rangtab; Gnum * restrict treetab; Gnum * restrict cblktax; Gnum vnodnnd; Gnum vnodnum; Gnum cblknum; int o; if (fprintf (stream, GNUMSTRING "\n", (Gnum) ordeptr->vnodnbr) == EOF) { errorPrint ("orderSaveTree: bad output (1)"); return (1); } if (memAllocGroup ((void **) (void *) &rangtab, (size_t) ((ordeptr->vnodnbr + 1) * sizeof (Gnum)), &treetab, (size_t) ( ordeptr->vnodnbr * sizeof (Gnum)), &cblktax, (size_t) ( ordeptr->vnodnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("orderSaveTree: out of memory"); return (1); } cblktax -= ordeptr->baseval; orderRang (ordeptr, rangtab); orderTree (ordeptr, treetab); peritax = ordeptr->peritab - ordeptr->baseval; for (vnodnum = ordeptr->baseval, vnodnnd = vnodnum + ordeptr->vnodnbr, cblknum = 0; vnodnum < vnodnnd; vnodnum ++) { if (vnodnum >= rangtab[cblknum + 1]) cblknum ++; cblktax[peritax[vnodnum]] = treetab[cblknum]; } vlbltax = (vlbltab != NULL) ? (vlbltab - ordeptr->baseval) : NULL; for (vnodnum = ordeptr->baseval, o = 0; vnodnum < vnodnnd; vnodnum ++) { if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", (Gnum) ((vlbltax != NULL) ? vlbltax[vnodnum] : vnodnum), (Gnum) cblktax[vnodnum]) == EOF) { errorPrint ("orderSaveMap: bad output (2)"); o = 1; break; } } memFree (rangtab); /* Free memory group leader */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/bdgraph_bipart_sq.c0000644000175300017530000003026711631334325022762 0ustar hazelscthazelsct/* Copyright 2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_bipart_sq.c **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module computes a bipartition of a **/ /** given bipartitioned distributed graph **/ /** by moving all (interesting) vertices of **/ /** the given graph to every processor, **/ /** executing a sequential bipartition **/ /** routine, and projecting back the best **/ /** result obtained. **/ /** **/ /** DATES : # Version 5.1 : from : 27 dec 2007 **/ /** to 14 apr 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BDGRAPH_BIPART_SQ #include "module.h" #include "common.h" #include "comm.h" #include "arch.h" #include "parser.h" #include "graph.h" #include "bgraph.h" #include "bgraph_bipart_st.h" #include "dgraph.h" #include "bdgraph.h" #include "bdgraph_bipart_sq.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine is the reduction-loc operator which ** returns in inout[2] the rank of the process which ** holds the best partition. ** It returns: ** - void : in all cases. */ static void bdgraphBipartSqOpBest ( const Gnum * const in, /* First operand */ Gnum * const inout, /* Second and output operand */ const int * const len, /* Number of instances; should be 1, not used */ const MPI_Datatype * const typedat) /* MPI datatype; not used */ { inout[5] |= in[5]; /* Propagate errors */ inout[4] += in[4]; /* Count cases for which a bipartitioning error occured */ if (inout[3] == 1) { /* Handle cases when at least one of them is erroneous */ if (in[3] == 1) return; inout[0] = in[0]; inout[1] = in[1]; inout[2] = in[2]; inout[3] = in[3]; return; } else if (in[3] == 1) return; if ((in[0] < inout[0]) || /* Select best partition */ ((in[0] == inout[0]) && ((in[1] < inout[1]) || ((in[1] == inout[1]) && (in[2] < inout[2]))))) { inout[0] = in[0]; inout[1] = in[1]; inout[2] = in[2]; } } /* This routine computes a partition of the ** given distributed graph by gathering as many ** copies of the graph as there are processes ** sharing the distributed graph, running a ** sequential algorithm on them, and collecting ** the best solution found. ** It returns: ** - 0 : if the bipartition could be computed. ** - !0 : on error. */ int bdgraphBipartSq ( Bdgraph * const dgrfptr, /*+ Distributed graph +*/ const BdgraphBipartSqParam * const paraptr) /*+ Method parameters +*/ { Bgraph cgrfdat; /* Centralized bipartitioned graph structure */ Gnum reduloctab[6]; /* Local array for best bipartition data (7 for Bcast) */ Gnum reduglbtab[6]; /* Global array for best bipartition data */ MPI_Datatype besttypedat; /* Data type for finding best bipartition */ MPI_Op bestoperdat; /* Handle of MPI operator for finding best bipartition */ int bestprocnum; /* Rank of process holding best partition */ Gnum * restrict vnumloctax; Gnum vertlocnum; Gnum complocsize1; Gnum complocload1; Gnum fronlocnbr; int o; if ((MPI_Type_contiguous (6, GNUM_MPI, &besttypedat) != MPI_SUCCESS) || (MPI_Type_commit (&besttypedat) != MPI_SUCCESS) || (MPI_Op_create ((MPI_User_function *) bdgraphBipartSqOpBest, 1, &bestoperdat) != MPI_SUCCESS)) { errorPrint ("bdgraphBipartSq: communication error (1)"); return (1); } reduloctab[0] = /* In case of error, maximum communication load */ reduloctab[1] = GNUMMAX; /* And maximum load imbalance */ reduloctab[2] = dgrfptr->s.proclocnum; reduloctab[3] = /* Assume sequential bipartioning went fine */ reduloctab[4] = 0; reduloctab[5] = 0; /* Assume no errors */ vnumloctax = dgrfptr->s.vnumloctax; /* No need for vertex number array when centralizing graph */ dgrfptr->s.vnumloctax = NULL; o = bdgraphGatherAll (dgrfptr, &cgrfdat); dgrfptr->s.vnumloctax = vnumloctax; /* Restore vertex number array */ if (o != 0) { errorPrint ("bdgraphBipartSq: cannot build centralized graph"); return (1); } if (bgraphBipartSt (&cgrfdat, paraptr->strat) != 0) { /* Bipartition centralized graph */ errorPrint ("bdgraphBipartSq: cannot bipartition centralized graph"); reduloctab[3] = reduloctab[4] = 1; } else { /* Fill local array with local bipartition data */ reduloctab[0] = ((cgrfdat.fronnbr != 0) || ((cgrfdat.compload0 != 0) && ((cgrfdat.s.velosum - cgrfdat.compload0) != 0))) ? cgrfdat.commload : GNUMMAX; /* Partitions with empty bipartitions unwanted if they are completely unbalanced */ reduloctab[1] = cgrfdat.compload0dlt; } if (dgrfptr->partgsttax == NULL) { if (dgraphGhst (&dgrfptr->s) != 0) { /* Compute ghost edge array if not already present, before copying graph fields */ errorPrint ("bdgraphBipartSq: cannot compute ghost edge array"); reduloctab[5] = 1; } else { if ((dgrfptr->partgsttax = (GraphPart *) memAlloc (dgrfptr->s.vertgstnbr * sizeof (GraphPart))) == NULL) { errorPrint ("bdgraphBipartSq: out of memory (1)"); reduloctab[5] = 1; /* Allocated data will be freed along with graph structure */ } dgrfptr->partgsttax -= dgrfptr->s.baseval; } if ((dgrfptr->fronloctab = (Gnum *) memAlloc (dgrfptr->s.vertlocnbr * sizeof (Gnum))) == NULL) { errorPrint ("bdgraphBipartSq: out of memory (2)"); reduloctab[5] = 1; } } if (MPI_Allreduce (reduloctab, reduglbtab, 1, besttypedat, bestoperdat, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartSq: communication error (2)"); return (1); } if ((reduloctab[4] != 0) && (reduloctab[4] != dgrfptr->s.procglbnbr)) { errorPrint ("bdgraphBipartSq: internal error"); return (1); } if ((MPI_Op_free (&bestoperdat) != MPI_SUCCESS) || (MPI_Type_free (&besttypedat) != MPI_SUCCESS)) { errorPrint ("bdgraphBipartSq: communication error (3)"); return (1); } if (reduglbtab[3] != 0) { /* If none of the sequential methods succeeded */ bgraphExit (&cgrfdat); return (1); } bestprocnum = (int) reduglbtab[2]; if (dgrfptr->s.proclocnum == bestprocnum) { /* If process holds best partition */ reduloctab[0] = cgrfdat.compload0; /* Global values to share */ reduloctab[1] = cgrfdat.compsize0; reduloctab[2] = cgrfdat.commload; reduloctab[3] = cgrfdat.commgainextn; reduloctab[4] = cgrfdat.fronnbr; } if (MPI_Bcast (reduloctab, 5, GNUM_MPI, bestprocnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartSq: communication error (4)"); return (1); } dgrfptr->compglbload0 = reduloctab[0]; dgrfptr->compglbload0dlt = reduloctab[0] - dgrfptr->compglbload0avg; dgrfptr->compglbsize0 = reduloctab[1]; dgrfptr->commglbload = reduloctab[2]; dgrfptr->commglbgainextn = reduloctab[3]; dgrfptr->fronglbnbr = reduloctab[4]; if (commScatterv (cgrfdat.parttax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GRAPHPART_MPI, /* No base for sending as procdsptab holds based values */ dgrfptr->partgsttax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GRAPHPART_MPI, bestprocnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartSq: communication error (5)"); return (1); } if (dgraphHaloSync (&dgrfptr->s, (byte *) (dgrfptr->partgsttax + dgrfptr->s.baseval), GRAPHPART_MPI) != 0) { errorPrint ("bdgraphBipartSq: cannot perform halo exchange"); return (1); } complocsize1 = complocload1 = 0; for (vertlocnum = dgrfptr->s.baseval, fronlocnbr = 0; vertlocnum < dgrfptr->s.vertlocnnd; vertlocnum ++) { int partval; Gnum partval1; Gnum commcut; Gnum edgelocnum; partval = dgrfptr->partgsttax[vertlocnum]; partval1 = partval & 1; complocsize1 += partval1; /* Superscalar update */ if (dgrfptr->s.veloloctax != NULL) { Gnum veloval; veloval = dgrfptr->s.veloloctax[vertlocnum]; complocload1 += (-partval1) & veloval; /* Superscalar update */ } for (edgelocnum = dgrfptr->s.vertloctax[vertlocnum], commcut = 0; edgelocnum < dgrfptr->s.vendloctax[vertlocnum]; edgelocnum ++) { /* Build local frontier */ int partend; int partdlt; partend = dgrfptr->partgsttax[dgrfptr->s.edgegsttax[edgelocnum]]; partdlt = partval ^ partend; commcut |= partdlt; } if (commcut != 0) dgrfptr->fronloctab[fronlocnbr ++] = vertlocnum; } dgrfptr->complocsize0 = dgrfptr->s.vertlocnbr - complocsize1; dgrfptr->fronlocnbr = fronlocnbr; if (dgrfptr->s.veloloctax != NULL) dgrfptr->complocload0 = dgrfptr->s.velolocsum - complocload1; else dgrfptr->complocload0 = dgrfptr->complocsize0; bgraphExit (&cgrfdat); #ifdef SCOTCH_DEBUG_BDGRAPH2 if (bdgraphCheck (dgrfptr) != 0) { errorPrint ("bdgraphBipartSq: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/graph_io.h0000644000175300017530000000671411631334325021104 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_io.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the source graph input/output **/ /** functions. **/ /** **/ /** DATES : # Version 0.0 : from : 02 dec 1992 **/ /** to 18 may 1993 **/ /** # Version 1.3 : from : 30 apr 1994 **/ /** to 18 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 18 aug 1994 **/ /** # Version 3.0 : from : 07 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 28 nov 1995 **/ /** to 28 nov 1995 **/ /** # Version 3.2 : from : 07 sep 1996 **/ /** to 15 may 1999 **/ /** # Version 4.0 : from : 25 nov 2001 **/ /** to 25 nov 2001 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef GRAPH_IO #define static #endif int graphLoad2 (const Gnum, const Gnum, const Gnum * const, const Gnum * const, Gnum * const, const Gnum, const Gnum * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/hdgraph_order_st.h0000644000175300017530000000651211631334325022626 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph_order_st.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data **/ /** declarations for the main distributed **/ /** graph ordering routine. **/ /** **/ /** DATES : # Version 5.0 : from : 14 apr 2006 **/ /** to : 14 apr 2006 **/ /** # Version 5.1 : from : 11 nov 2008 **/ /** to : 11 nov 2008 **/ /** **/ /************************************************************/ /* ** The type definitions. */ /*+ Method types. +*/ typedef enum HdgraphOrderStMethodType_ { HDGRAPHORDERSTMETHND = 0, /*+ Nested Dissection +*/ HDGRAPHORDERSTMETHSI, /*+ Simple +*/ HDGRAPHORDERSTMETHSQ, /*+ Sequential method +*/ HDGRAPHORDERSTMETHNBR /*+ Number of methods +*/ } HdgraphOrderStMethodType; /* ** The external declarations. */ extern StratTab hdgraphorderststratab; /* ** The function prototypes. */ #ifndef HDGRAPH_ORDER_ST #define static #endif int hdgraphOrderSt (const Hdgraph * restrict const, DorderCblk * restrict const, const Strat * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/hdgraph_induce.c0000644000175300017530000004362411631334325022254 0ustar hazelscthazelsct/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph_induce.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the halo source **/ /** graph subgraph-making functions. **/ /** **/ /** DATES : # Version 5.0 : from : 19 apr 2006 **/ /** to : 10 sep 2007 **/ /** # Version 5.1 : from : 27 jun 2008 **/ /** to : 22 oct 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HDGRAPH #include "module.h" #include "common.h" #include "dgraph.h" #include "hdgraph.h" /******************************/ /* */ /* These routines handle halo */ /* distributed source graphs. */ /* */ /******************************/ /* This routine builds the graph induced ** by the original graph and the list of ** selected vertices. ** The induced vnumtab array is the global ** translation of the list array if the ** original graph does not have a vnumtab, ** or the proper subset of the original ** vnumtab else. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int hdgraphInduceList ( Hdgraph * restrict const orggrafptr, const Gnum indlistnbr, const Gnum * restrict const indlisttab, /* Local list of kept vertices */ Hdgraph * restrict const indgrafptr) { const Gnum * restrict orgvertloctax; const Gnum * restrict orgvendloctax; const Gnum * restrict orgveloloctax; const Gnum * restrict orgedgegsttax; const Gnum * restrict orgedgeloctax; Gnum * restrict orgindxgsttax; /* Based access to vertex translation array */ Gnum * restrict orgindxhaltax; /* Based access to halo vertex translation array */ Gnum * restrict indvertloctax; Gnum * restrict indveloloctax; Gnum indvertlocnnd; /* Based index of end of local vertex array */ Gnum indvertlocnum; /* Number of current vertex in induced graph */ Gnum indvertglbnum; /* Number of current vertex in global ordering */ Gnum * restrict indvendloctax; Gnum indvelolocnbr; /* Size of local vertex load array */ Gnum indvelolocsum; /* Sum of vertex loads */ Gnum indvhallocnum; /* Number of halo vertex to be declared */ Gnum * restrict indedgeloctax; Gnum indedgelocmax; /* (Approximate) number of edges in induced graph */ Gnum indedgelocsiz; /* Real size of edge array, including halo */ Gnum indedgelocnbr; /* Real number of edges in induced graph */ Gnum indedgelocnum; Gnum inddegrlocmax; /* Local maximum degree over non-halo vertices */ const Gnum * restrict indlisttax; /* Based access to list of kept vertices */ int cheklocval; int chekglbval; if (dgraphGhst (&orggrafptr->s) != 0) { /* Compute ghost edge array if not already present */ errorPrint ("hdgraphInduceList: cannot compute ghost edge array"); return (1); } memSet (indgrafptr, 0, sizeof (Hdgraph)); /* Pre-initialize graph fields */ indgrafptr->s.proccomm = orggrafptr->s.proccomm; indgrafptr->s.procglbnbr = orggrafptr->s.procglbnbr; indgrafptr->s.proclocnum = orggrafptr->s.proclocnum; indgrafptr->s.flagval = (DGRAPHFREEALL ^ DGRAPHFREECOMM) | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; /* For premature freeing on error; do not free vhndloctab as it is grouped with vertloctab */ if (orggrafptr->s.veloloctax != NULL) { indvelolocnbr = indlistnbr; indvelolocsum = 0; } else { indvelolocnbr = 0; indvelolocsum = indlistnbr; } indedgelocmax = orggrafptr->s.edgelocnbr; /* Choose best upper bound on number of edges (avoid multiply overflow) */ if ((orggrafptr->s.degrglbmax > 0) && (indlistnbr < (indedgelocmax / orggrafptr->s.degrglbmax))) indedgelocmax = indlistnbr * orggrafptr->s.degrglbmax; indedgelocmax += orggrafptr->ehallocnbr; cheklocval = chekglbval = 0; if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ &indgrafptr->s.procdsptab, (size_t) ((orggrafptr->s.procglbnbr + 1) * sizeof (Gnum)), &indgrafptr->s.proccnttab, (size_t) (orggrafptr->s.procglbnbr * sizeof (Gnum)), &indgrafptr->s.procngbtab, (size_t) (orggrafptr->s.procglbnbr * sizeof (int)), &indgrafptr->s.procrcvtab, (size_t) (orggrafptr->s.procglbnbr * sizeof (int)), &indgrafptr->s.procsndtab, (size_t) (orggrafptr->s.procglbnbr * sizeof (int)), NULL) == NULL) { errorPrint ("hdgraphInduceList: out of memory (1)"); cheklocval = 1; } else if (memAllocGroup ((void **) (void *) /* Allocate distributed graph public data */ &indgrafptr->s.vertloctax, (size_t) ((indlistnbr + 1) * sizeof (Gnum)), /* Compact vertex arrays */ &indgrafptr->s.vendloctax, (size_t) (indlistnbr * sizeof (Gnum)), /* Vertex end array for non-halo vertices */ &indgrafptr->s.vnumloctax, (size_t) (indlistnbr * sizeof (Gnum)), &indgrafptr->s.veloloctax, (size_t) (indvelolocnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("hdgraphInduceList: out of memory (2)"); cheklocval = 1; } else if (indgrafptr->s.vertloctax -= orggrafptr->s.baseval, indgrafptr->s.vendloctax -= orggrafptr->s.baseval, indgrafptr->s.vnumloctax -= orggrafptr->s.baseval, indgrafptr->s.veloloctax = ((orggrafptr->s.veloloctax != NULL) ? indgrafptr->s.veloloctax - orggrafptr->s.baseval : NULL), memAllocGroup ((void **) (void *) &indgrafptr->s.edgeloctax, (size_t) (indedgelocmax * sizeof (Gnum)), /* Pre-allocate space for edgeloctab */ &orgindxgsttax, (size_t) (orggrafptr->s.vertgstnbr * sizeof (Gnum)), /* orgindxgsttab and orgindxhaltab are at the end */ &orgindxhaltax, (size_t) (orggrafptr->vhallocnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("hdgraphInduceList: out of memory (3)"); cheklocval = 1; } else indgrafptr->s.edgeloctax -= orggrafptr->s.baseval; if (cheklocval != 0) { /* In case of memory error */ Gnum procngbnum; int dummyval; dummyval = -1; chekglbval = 1; if (MPI_Allgather (&dummyval, 1, GNUM_MPI, /* Use proccnttab of orggraf as dummy receive array (will be regenerated) */ orggrafptr->s.proccnttab, 1, GNUM_MPI, indgrafptr->s.proccomm) != MPI_SUCCESS) errorPrint ("hdgraphInduceList: communication error (1)"); for (procngbnum = 1; procngbnum <= orggrafptr->s.procglbnbr; procngbnum ++) /* Rebuild proccnttab of orggraf */ orggrafptr->s.proccnttab[procngbnum - 1] = orggrafptr->s.procdsptab[procngbnum] - orggrafptr->s.procdsptab[procngbnum - 1]; } else { indgrafptr->s.procvrttab = indgrafptr->s.procdsptab; /* Graph does not have holes */ indgrafptr->s.procdsptab[0] = indlistnbr; if (MPI_Allgather (&indgrafptr->s.procdsptab[0], 1, GNUM_MPI, &indgrafptr->s.proccnttab[0], 1, GNUM_MPI, indgrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphInduceList: communication error (2)"); chekglbval = 1; } else { Gnum procngbnum; indgrafptr->s.procdsptab[0] = orggrafptr->s.baseval; /* Build vertex-to-process array */ for (procngbnum = 0; procngbnum < indgrafptr->s.procglbnbr; procngbnum ++) { /* Process potential error flags from other processes */ if (indgrafptr->s.proccnttab[procngbnum] < 0) { /* If error notified by another process */ chekglbval = 1; break; } indgrafptr->s.procdsptab[procngbnum + 1] = indgrafptr->s.procdsptab[procngbnum] + indgrafptr->s.proccnttab[procngbnum]; } } } if (chekglbval != 0) { /* If something went wrong in all of the above */ hdgraphExit (indgrafptr); return (1); } memSet (orgindxgsttax, ~0, orggrafptr->s.vertgstnbr * sizeof (Gnum)); /* Preset index arrays */ orgindxgsttax -= orggrafptr->s.baseval; memSet (orgindxhaltax, ~0, orggrafptr->vhallocnbr * sizeof (Gnum)); orgindxhaltax -= orggrafptr->s.baseval; indlisttax = indlisttab - orggrafptr->s.baseval; indvertlocnnd = indlistnbr + orggrafptr->s.baseval; for (indvertlocnum = orggrafptr->s.baseval, indvertglbnum = indgrafptr->s.procdsptab[indgrafptr->s.proclocnum]; /* Set adjustment for global ordering */ indvertlocnum < indvertlocnnd; indvertlocnum ++, indvertglbnum ++) orgindxgsttax[indlisttax[indvertlocnum]] = indvertglbnum; /* Mark selected vertices */ if (dgraphHaloSync (&orggrafptr->s, (byte *) (orgindxgsttax + orggrafptr->s.baseval), GNUM_MPI) != 0) { /* Share global indexing of subgraph vertices */ errorPrint ("hdgraphInduceList: cannot perform halo exchange"); hdgraphExit (indgrafptr); return (1); } orgvertloctax = orggrafptr->s.vertloctax; orgvendloctax = orggrafptr->s.vendloctax; orgveloloctax = orggrafptr->s.veloloctax; orgedgegsttax = orggrafptr->s.edgegsttax; orgedgeloctax = orggrafptr->s.edgeloctax; indvertloctax = indgrafptr->s.vertloctax; indvendloctax = indgrafptr->s.vendloctax; indveloloctax = indgrafptr->s.veloloctax; indedgeloctax = indgrafptr->s.edgeloctax; inddegrlocmax = 0; for (indvertlocnum = indedgelocnum = indvhallocnum = orggrafptr->s.baseval, indedgelocnbr = 0; indvertlocnum < indvertlocnnd; indvertlocnum ++) { Gnum orgvertlocnum; Gnum orgedgelocnum; Gnum orgdegrlocval; Gnum inddegrlocval; Gnum indedgelocnnd; orgvertlocnum = indlisttax[indvertlocnum]; orgdegrlocval = orgvendloctax[orgvertlocnum] - orgvertloctax[orgvertlocnum]; indvertloctax[indvertlocnum] = indedgelocnum; if (orgveloloctax != NULL) { /* If graph has vertex weights */ indvelolocsum += /* Accumulate vertex loads */ indveloloctax[indvertlocnum] = orgveloloctax[orgvertlocnum]; } indedgelocnnd = indedgelocnum + orgdegrlocval; #ifdef SCOTCH_DEBUG_HDGRAPH2 if (indedgelocnnd > (indedgelocmax + orggrafptr->s.baseval)) { errorPrint ("hdgraphInduceList: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ for (orgedgelocnum = orgvertloctax[orgvertlocnum]; /* Process local and ghost non-halo vertices */ orgedgelocnum < orgvendloctax[orgvertlocnum]; orgedgelocnum ++) { Gnum orgvertlocend; Gnum indvertgstend; orgvertlocend = orgedgegsttax[orgedgelocnum]; #ifdef SCOTCH_DEBUG_HDGRAPH2 if ((orgvertlocend < orggrafptr->s.baseval) || (orgvertlocend > orggrafptr->s.vertgstnnd)) { errorPrint ("hdgraphInduceList: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ indvertgstend = orgindxgsttax[orgvertlocend]; if (indvertgstend >= 0) /* If edge is local or halo */ indedgeloctax[indedgelocnum ++] = indvertgstend; /* Keep it as regular edge */ else { /* If edge is halo edge */ if (indvertgstend == ~0) /* If halo vertex not assigned yet */ orgindxgsttax[orgvertlocend] = indvertgstend = -2 - indvhallocnum ++; /* Set new halo number */ indedgeloctax[-- indedgelocnnd] = -2 - indvertgstend; } } #ifdef SCOTCH_DEBUG_HDGRAPH2 if (indedgelocnnd != indedgelocnum) { errorPrint ("hdgraphInduceList: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ indvendloctax[indvertlocnum] = indedgelocnum; inddegrlocval = indedgelocnum - indvertloctax[indvertlocnum]; indedgelocnbr += inddegrlocval; if (inddegrlocmax < inddegrlocval) inddegrlocmax = inddegrlocval; for (indedgelocnum = indvertloctax[indvertlocnum] + orgdegrlocval; /* Process local halo vertices */ orgedgelocnum < orggrafptr->vhndloctax[orgvertlocnum]; orgedgelocnum ++) { Gnum orgvhallocend; Gnum indvhallocend; orgvhallocend = orgedgeloctax[orgedgelocnum]; /* Halo vertices only exist in the edgeloctab array */ #ifdef SCOTCH_DEBUG_HDGRAPH2 if ((orgvhallocend < orggrafptr->s.baseval) || (orgvhallocend >= (orggrafptr->vhallocnbr + orggrafptr->s.baseval))) { errorPrint ("hdgraphInduceList: inconsistent halo vertex numbers"); hdgraphExit (indgrafptr); return (1); } if (indedgelocnum >= (indedgelocmax + orggrafptr->s.baseval)) { errorPrint ("hdgraphInduceList: internal error (4)"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ indvhallocend = orgindxhaltax[orgvhallocend]; if (indvhallocend == ~0) /* If halo vertex not assigned yet */ orgindxhaltax[orgvhallocend] = indvhallocend = indvhallocnum ++; /* Set new halo number */ indgrafptr->s.edgeloctax[indedgelocnum ++] = indvhallocend; } } indvertloctax[indvertlocnum] = indedgelocnum; /* Mark end of edge array for vhndloctax */ indedgelocsiz = indedgelocnum - orggrafptr->s.baseval; /* Global number of edges, both non-halo and halo */ indgrafptr->s.edgeloctax = memRealloc (indgrafptr->s.edgeloctax + orggrafptr->s.baseval, (size_t) (indedgelocsiz * sizeof (Gnum))); indgrafptr->s.edgeloctax -= orggrafptr->s.baseval; if (orggrafptr->s.vnumloctax != NULL) { /* Adjust vnumloctax */ for (indvertlocnum = orggrafptr->s.baseval; indvertlocnum < indvertlocnnd; indvertlocnum ++) indgrafptr->s.vnumloctax[indvertlocnum] = orggrafptr->s.vnumloctax[indlisttax[indvertlocnum]]; } else { Gnum orgvertglbadj; orgvertglbadj = orggrafptr->s.procvrttab[orggrafptr->s.proclocnum] - orggrafptr->s.baseval; /* Set adjustement for global ordering */ for (indvertlocnum = orggrafptr->s.baseval; indvertlocnum < indvertlocnnd; indvertlocnum ++) indgrafptr->s.vnumloctax[indvertlocnum] = indlisttax[indvertlocnum] + orgvertglbadj; } indgrafptr->vhallocnbr = indvhallocnum - orggrafptr->s.baseval; indgrafptr->vhndloctax = indgrafptr->s.vertloctax + 1; /* Compact edge array with halo vertices */ indgrafptr->ehallocnbr = indedgelocsiz - indedgelocnbr; /* Get number of halo edges by difference */ indgrafptr->levlnum = orggrafptr->levlnum + 1; /* Induced subgraph is one level below */ indgrafptr->s.baseval = orggrafptr->s.baseval; indgrafptr->s.vertlocnbr = indlistnbr; indgrafptr->s.vertlocnnd = indlistnbr + orggrafptr->s.baseval; indgrafptr->s.velolocsum = indvelolocsum; indgrafptr->s.edgelocnbr = indedgelocnbr; indgrafptr->s.edgelocsiz = indedgelocsiz; indgrafptr->s.degrglbmax = orggrafptr->s.degrglbmax; if (dgraphBuild4 (&indgrafptr->s) != 0) { errorPrint ("hdgraphInduceList: cannot build induced graph"); return (1); } #ifdef SCOTCH_DEBUG_HDGRAPH2 if (hdgraphCheck (indgrafptr) != 0) { /* Check graph consistency */ errorPrint ("hdgraphInduceList: internal error (5)"); hdgraphExit (indgrafptr); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/Makefile0000644000175300017530000016127411617606777020627 0ustar hazelscthazelsct## Copyright 2004,2007-2011 ENSEIRB, INRIA & CNRS ## ## This file is part of the Scotch software package for static mapping, ## graph partitioning and sparse matrix ordering. ## ## This software is governed by the CeCILL-C license under French law ## and abiding by the rules of distribution of free software. You can ## use, modify and/or redistribute the software under the terms of the ## CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ## URL: "http://www.cecill.info". ## ## As a counterpart to the access to the source code and rights to copy, ## modify and redistribute granted by the license, users are provided ## only with a limited warranty and the software's author, the holder of ## the economic rights, and the successive licensors have only limited ## liability. ## ## In this respect, the user's attention is drawn to the risks associated ## with loading, using, modifying and/or developing or reproducing the ## software by the user in light of its specific status of free software, ## that may mean that it is complicated to manipulate, and that also ## therefore means that it is reserved for developers and experienced ## professionals having in-depth computer knowledge. Users are therefore ## encouraged to load and test the software's suitability as regards ## their requirements in conditions enabling the security of their ## systems and/or data to be ensured and, more generally, to use and ## operate it in the same conditions as regards security. ## ## The fact that you are presently reading this means that you have had ## knowledge of the CeCILL-C license and that you accept its terms. ## includedir = ../../include libdir = ../../lib ## ## General inference rules. ## include ../Makefile.inc %$(OBJ) : %.c $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -o $(@) %$(EXE) : %.c $(CC) $(CFLAGS) -DSCOTCH_VERSION=$(VERSION) -DSCOTCH_RELEASE=$(RELEASE) -DSCOTCH_PATCHLEVEL=$(PATCHLEVEL) $(<) -o $(@) $(LDFLAGS) ## ## Project rules. ## .PHONY : ptscotch scotch ptinstall install clean realclean scotch : clean $(MAKE) CC="$(CCS)" CCD="$(CCS)" \ scotch.h \ scotchf.h \ libscotch$(LIB) \ libscotcherr$(LIB) \ libscotcherrexit$(LIB) ptscotch : clean $(MAKE) CFLAGS="$(CFLAGS) -DSCOTCH_PTSCOTCH" CC="$(CCP)" \ scotch.h \ scotchf.h \ libptscotch$(LIB) \ libscotch$(LIB) \ libptscotcherr$(LIB) \ libptscotcherrexit$(LIB) install : -$(CP) scotch.h scotchf.h $(includedir) -$(CP) libscotch$(LIB) libscotcherr*$(LIB) $(libdir) ptinstall : -$(CP) scotch.h $(includedir)/ptscotch.h -$(CP) scotchf.h $(includedir)/ptscotchf.h -$(CP) libptscotch*$(LIB) $(libdir) clean : -$(RM) *~ *$(OBJ) lib*$(LIB) parser_yy.c parser_ly.h parser_ll.c *scotch.h *scotchf.h y.output dummysizes$(EXE) realclean : clean ## ## Library dependencies. ## LIBPTSCOTCHDEPS = bdgraph$(OBJ) \ bdgraph_bipart_bd$(OBJ) \ bdgraph_bipart_df$(OBJ) \ bdgraph_bipart_ex$(OBJ) \ bdgraph_bipart_ml$(OBJ) \ bdgraph_bipart_sq$(OBJ) \ bdgraph_bipart_st$(OBJ) \ bdgraph_bipart_zr$(OBJ) \ bdgraph_check$(OBJ) \ bdgraph_gather_all$(OBJ) \ bdgraph_store$(OBJ) \ comm$(OBJ) \ dgraph$(OBJ) \ dgraph_allreduce$(OBJ) \ dgraph_band$(OBJ) \ dgraph_build$(OBJ) \ dgraph_build_grid3d$(OBJ) \ dgraph_build_hcub$(OBJ) \ dgraph_check$(OBJ) \ dgraph_coarsen$(OBJ) \ dgraph_fold$(OBJ) \ dgraph_fold_comm$(OBJ) \ dgraph_fold_dup$(OBJ) \ dgraph_gather$(OBJ) \ dgraph_gather_all$(OBJ) \ dgraph_ghst$(OBJ) \ dgraph_halo$(OBJ) \ dgraph_induce$(OBJ) \ dgraph_io_load$(OBJ) \ dgraph_io_save$(OBJ) \ dgraph_match$(OBJ) \ dgraph_match_sync_coll$(OBJ) \ dgraph_match_sync_ptop$(OBJ) \ dgraph_match_check$(OBJ) \ dgraph_scatter$(OBJ) \ dgraph_view$(OBJ) \ dmapping$(OBJ) \ dmapping_io$(OBJ) \ dorder$(OBJ) \ dorder_gather$(OBJ) \ dorder_io$(OBJ) \ dorder_io_block$(OBJ) \ dorder_io_tree$(OBJ) \ dorder_perm$(OBJ) \ dorder_tree_dist$(OBJ) \ hdgraph$(OBJ) \ hdgraph_check$(OBJ) \ hdgraph_fold$(OBJ) \ hdgraph_gather$(OBJ) \ hdgraph_induce$(OBJ) \ hdgraph_order_nd$(OBJ) \ hdgraph_order_si$(OBJ) \ hdgraph_order_sq$(OBJ) \ hdgraph_order_st$(OBJ) \ kdgraph$(OBJ) \ kdgraph_map_rb$(OBJ) \ kdgraph_map_rb_map$(OBJ) \ kdgraph_map_rb_part$(OBJ) \ kdgraph_map_st$(OBJ) \ library_dgraph$(OBJ) \ library_dgraph_f$(OBJ) \ library_dgraph_build$(OBJ) \ library_dgraph_build_f$(OBJ) \ library_dgraph_build_grid3d$(OBJ) \ library_dgraph_build_grid3d_f$(OBJ) \ library_dgraph_check$(OBJ) \ library_dgraph_check_f$(OBJ) \ library_dgraph_coarsen$(OBJ) \ library_dgraph_coarsen_f$(OBJ) \ library_dgraph_gather$(OBJ) \ library_dgraph_gather_f$(OBJ) \ library_dgraph_halo$(OBJ) \ library_dgraph_halo_f$(OBJ) \ library_dgraph_io_load$(OBJ) \ library_dgraph_io_load_f$(OBJ) \ library_dgraph_io_save$(OBJ) \ library_dgraph_io_save_f$(OBJ) \ library_dgraph_map$(OBJ) \ library_dgraph_map_f$(OBJ) \ library_dgraph_map_view$(OBJ) \ library_dgraph_map_view_f$(OBJ) \ library_dgraph_order$(OBJ) \ library_dgraph_order_f$(OBJ) \ library_dgraph_order_gather$(OBJ) \ library_dgraph_order_gather_f$(OBJ) \ library_dgraph_order_io$(OBJ) \ library_dgraph_order_io_f$(OBJ) \ library_dgraph_order_io_block$(OBJ) \ library_dgraph_order_io_block_f$(OBJ) \ library_dgraph_order_perm$(OBJ) \ library_dgraph_order_perm_f$(OBJ) \ library_dgraph_order_tree_dist$(OBJ) \ library_dgraph_order_tree_dist_f$(OBJ) \ library_dgraph_scatter$(OBJ) \ library_dgraph_scatter_f$(OBJ) \ library_dgraph_stat$(OBJ) \ library_dgraph_stat_f$(OBJ) \ library_dmapping$(OBJ) \ library_dorder$(OBJ) \ vdgraph$(OBJ) \ vdgraph_check$(OBJ) \ vdgraph_gather_all$(OBJ) \ vdgraph_separate_bd$(OBJ) \ vdgraph_separate_df$(OBJ) \ vdgraph_separate_ml$(OBJ) \ vdgraph_separate_sq$(OBJ) \ vdgraph_separate_st$(OBJ) \ vdgraph_separate_zr$(OBJ) \ vdgraph_store$(OBJ) LIBSCOTCHDEPS = arch$(OBJ) \ arch_build$(OBJ) \ arch_cmplt$(OBJ) \ arch_cmpltw$(OBJ) \ arch_deco$(OBJ) \ arch_hcub$(OBJ) \ arch_mesh$(OBJ) \ arch_tleaf$(OBJ) \ arch_torus$(OBJ) \ arch_vcmplt$(OBJ) \ arch_vhcub$(OBJ) \ bgraph$(OBJ) \ bgraph_bipart_bd$(OBJ) \ bgraph_bipart_df$(OBJ) \ bgraph_bipart_ex$(OBJ) \ bgraph_bipart_fm$(OBJ) \ bgraph_bipart_gg$(OBJ) \ bgraph_bipart_gp$(OBJ) \ bgraph_bipart_ml$(OBJ) \ bgraph_bipart_st$(OBJ) \ bgraph_bipart_zr$(OBJ) \ bgraph_check$(OBJ) \ bgraph_store$(OBJ) \ common$(OBJ) \ common_file$(OBJ) \ common_file_compress$(OBJ) \ common_file_uncompress$(OBJ) \ common_integer$(OBJ) \ common_memory$(OBJ) \ common_string$(OBJ) \ common_stub$(OBJ) \ gain$(OBJ) \ geom$(OBJ) \ graph$(OBJ) \ graph_base$(OBJ) \ graph_check$(OBJ) \ graph_coarsen$(OBJ) \ graph_induce$(OBJ) \ graph_io$(OBJ) \ graph_io_chac$(OBJ) \ graph_io_habo$(OBJ) \ graph_io_mmkt$(OBJ) \ graph_io_scot$(OBJ) \ graph_list$(OBJ) \ hall_order_hd$(OBJ) \ hall_order_hf$(OBJ) \ hall_order_hx$(OBJ) \ hgraph$(OBJ) \ hgraph_check$(OBJ) \ hgraph_induce$(OBJ) \ hgraph_order_bl$(OBJ) \ hgraph_order_cp$(OBJ) \ hgraph_order_gp$(OBJ) \ hgraph_order_hd$(OBJ) \ hgraph_order_hf$(OBJ) \ hgraph_order_hx$(OBJ) \ hgraph_order_nd$(OBJ) \ hgraph_order_si$(OBJ) \ hgraph_order_st$(OBJ) \ hmesh$(OBJ) \ hmesh_check$(OBJ) \ hmesh_hgraph$(OBJ) \ hmesh_induce$(OBJ) \ hmesh_mesh$(OBJ) \ hmesh_order_bl$(OBJ) \ hmesh_order_cp$(OBJ) \ hmesh_order_gr$(OBJ) \ hmesh_order_gp$(OBJ) \ hmesh_order_hd$(OBJ) \ hmesh_order_hf$(OBJ) \ hmesh_order_hx$(OBJ) \ hmesh_order_nd$(OBJ) \ hmesh_order_si$(OBJ) \ hmesh_order_st$(OBJ) \ kgraph$(OBJ) \ kgraph_check$(OBJ) \ kgraph_map_ml$(OBJ) \ kgraph_map_rb$(OBJ) \ kgraph_map_rb_map$(OBJ) \ kgraph_map_rb_part$(OBJ) \ kgraph_map_st$(OBJ) \ library_arch$(OBJ) \ library_arch_f$(OBJ) \ library_arch_build$(OBJ) \ library_arch_build_f$(OBJ) \ library_geom$(OBJ) \ library_geom_f$(OBJ) \ library_graph$(OBJ) \ library_graph_f$(OBJ) \ library_graph_base$(OBJ) \ library_graph_base_f$(OBJ) \ library_graph_check$(OBJ) \ library_graph_check_f$(OBJ) \ library_graph_coarsen$(OBJ) \ library_graph_coarsen_f$(OBJ) \ library_graph_io_chac$(OBJ) \ library_graph_io_chac_f$(OBJ) \ library_graph_io_habo$(OBJ) \ library_graph_io_habo_f$(OBJ) \ library_graph_io_mmkt$(OBJ) \ library_graph_io_mmkt_f$(OBJ) \ library_graph_io_scot$(OBJ) \ library_graph_io_scot_f$(OBJ) \ library_graph_map$(OBJ) \ library_graph_map_f$(OBJ) \ library_graph_map_view$(OBJ) \ library_graph_map_view_f$(OBJ) \ library_graph_order$(OBJ) \ library_graph_order_f$(OBJ) \ library_mapping$(OBJ) \ library_mesh$(OBJ) \ library_mesh_f$(OBJ) \ library_mesh_graph$(OBJ) \ library_mesh_graph_f$(OBJ) \ library_mesh_io_habo$(OBJ) \ library_mesh_io_habo_f$(OBJ) \ library_mesh_io_scot$(OBJ) \ library_mesh_io_scot_f$(OBJ) \ library_mesh_order$(OBJ) \ library_mesh_order_f$(OBJ) \ library_order$(OBJ) \ library_parser$(OBJ) \ library_parser_f$(OBJ) \ library_random$(OBJ) \ library_random_f$(OBJ) \ library_strat$(OBJ) \ library_version$(OBJ) \ library_version_f$(OBJ) \ mapping$(OBJ) \ mapping_io$(OBJ) \ mesh$(OBJ) \ mesh_check$(OBJ) \ mesh_coarsen$(OBJ) \ mesh_graph$(OBJ) \ mesh_induce_sepa$(OBJ) \ mesh_io$(OBJ) \ mesh_io_habo$(OBJ) \ mesh_io_scot$(OBJ) \ order$(OBJ) \ order_check$(OBJ) \ order_io$(OBJ) \ parser$(OBJ) \ parser_ll$(OBJ) \ parser_yy$(OBJ) \ vgraph$(OBJ) \ vgraph_check$(OBJ) \ vgraph_separate_bd$(OBJ) \ vgraph_separate_es$(OBJ) \ vgraph_separate_fm$(OBJ) \ vgraph_separate_gg$(OBJ) \ vgraph_separate_gp$(OBJ) \ vgraph_separate_ml$(OBJ) \ vgraph_separate_st$(OBJ) \ vgraph_separate_th$(OBJ) \ vgraph_separate_vw$(OBJ) \ vgraph_separate_zr$(OBJ) \ vgraph_store$(OBJ) \ vmesh$(OBJ) \ vmesh_check$(OBJ) \ vmesh_separate_fm$(OBJ) \ vmesh_separate_gg$(OBJ) \ vmesh_separate_gr$(OBJ) \ vmesh_separate_ml$(OBJ) \ vmesh_separate_zr$(OBJ) \ vmesh_separate_st$(OBJ) \ vmesh_store$(OBJ) ## ## Todo list. ## common$(OBJ) : common.c \ module.h \ common.h $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) common_file$(OBJ) : common_file.c \ module.h \ common.h \ common_file.h $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) common_file_compress$(OBJ) : common_file_compress.c \ module.h \ common.h \ common_file.h \ common_file_compress.h $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) common_file_uncompress$(OBJ) : common_file_uncompress.c \ module.h \ common.h \ common_file.h \ common_file_compress.h $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) common_integer$(OBJ) : common_integer.c \ module.h \ common.h \ common_sort.c $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) common_memory$(OBJ) : common_memory.c \ module.h \ common.h $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) common_string$(OBJ) : common_string.c \ module.h \ common.h $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) common_stub$(OBJ) : common_stub.c \ module.h \ common.h $(CC) $(CFLAGS) $(CLIBFLAGS) -c $(<) -DSCOTCH_COMMON_RENAME -o $(@) arch$(OBJ) : arch.c \ module.h \ common.h \ arch.h \ arch_cmplt.h \ arch_cmpltw.h \ arch_deco.h \ arch_hcub.h \ arch_mesh.h \ arch_tleaf.h \ arch_torus.h \ arch_vcmplt.h \ arch_vhcub.h arch_build$(OBJ) : arch_build.c \ module.h \ common.h \ parser.h \ graph.h \ arch.h \ arch_deco.h \ bgraph.h \ bgraph_bipart_st.h \ arch_build.h arch_cmplt$(OBJ) : arch_cmplt.c \ module.h \ common.h \ arch.h \ arch_cmplt.h arch_cmpltw$(OBJ) : arch_cmpltw.c \ module.h \ common.h \ arch.h \ arch_cmpltw.h arch_deco$(OBJ) : arch_deco.c \ module.h \ common.h \ arch.h \ arch_deco.h arch_hcub$(OBJ) : arch_hcub.c \ module.h \ common.h \ arch.h \ arch_hcub.h arch_mesh$(OBJ) : arch_mesh.c \ module.h \ common.h \ arch.h \ arch_mesh.h arch_tleaf$(OBJ) : arch_tleaf.c \ module.h \ common.h \ arch.h \ arch_tleaf.h arch_torus$(OBJ) : arch_torus.c \ module.h \ common.h \ arch.h \ arch_torus.h arch_vcpmlt$(OBJ) : arch_vcmplt.c \ module.h \ common.h \ arch.h \ arch_vcmplt.h arch_vhcub$(OBJ) : arch_vhcub.c \ module.h \ common.h \ arch.h \ arch_vhcub.h bdgraph$(OBJ) : bdgraph.c \ module.h \ common.h \ arch.h \ dgraph.h \ dmapping.h \ bdgraph.h bdgraph_bipart_bd$(OBJ) : bdgraph_bipart_bd.c \ module.h \ common.h \ parser.h \ arch.h \ dgraph.h \ dgraph_halo.h \ bdgraph.h \ bdgraph_bipart_bd.h \ bdgraph_bipart_st.h bdgraph_bipart_df$(OBJ) : bdgraph_bipart_df.c \ module.h \ common.h \ arch.h \ dgraph.h \ bdgraph.h \ bdgraph_bipart_df.h bdgraph_bipart_ex$(OBJ) : bdgraph_bipart_ex.c \ module.h \ common.h \ arch.h \ dgraph.h \ bdgraph.h \ bdgraph_bipart_ex.h bdgraph_bipart_ml$(OBJ) : bdgraph_bipart_ml.c \ module.h \ common.h \ parser.h \ arch.h \ dgraph.h \ dgraph_coarsen.h \ bdgraph.h \ bdgraph_bipart_ml.h \ bdgraph_bipart_st.h bdgraph_bipart_sq$(OBJ) : bdgraph_bipart_sq.c \ module.h \ common.h \ comm.h \ parser.h \ arch.h \ graph.h \ bgraph.h \ bgraph_bipart_st.h \ dgraph.h \ bdgraph.h \ bdgraph_bipart_sq.h bdgraph_bipart_st$(OBJ) : bdgraph_bipart_st.c \ module.h \ common.h \ gain.h \ parser.h \ graph.h \ arch.h \ bgraph.h \ bgraph_bipart_st.h \ dgraph.h \ dgraph_coarsen.h \ bdgraph.h \ bdgraph_bipart_bd.h \ bdgraph_bipart_df.h \ bdgraph_bipart_ex.h \ bdgraph_bipart_ml.h \ bdgraph_bipart_sq.h \ bdgraph_bipart_st.h \ bdgraph_bipart_zr.h bdgraph_bipart_zr$(OBJ) : bdgraph_bipart_zr.c \ module.h \ common.h \ arch.h \ dgraph.h \ bdgraph.h \ bdgraph_bipart_zr.h bdgraph_check$(OBJ) : bdgraph_check.c \ module.h \ common.h \ arch.h \ dgraph.h \ bdgraph.h bdgraph_gather_all$(OBJ) : bdgraph_gather_all.c \ module.h \ common.h \ comm.h \ arch.h \ graph.h \ bgraph.h \ dgraph.h \ bdgraph.h bdgraph_store$(OBJ) : bdgraph_store.c \ module.h \ common.h \ arch.h \ dgraph.h \ bdgraph.h bgraph$(OBJ) : bgraph.c \ module.h \ common.h \ graph.h \ arch.h \ mapping.h \ bgraph.h bgraph_check$(OBJ) : bgraph_check.c \ module.h \ common.h \ graph.h \ arch.h \ bgraph.h bgraph_bipart_bd$(OBJ) : bgraph_bipart_bd.c \ module.h \ common.h \ parser.h \ graph.h \ arch.h \ bgraph.h \ bgraph_bipart_bd.h \ bgraph_bipart_st.h bgraph_bipart_df$(OBJ) : bgraph_bipart_df.c \ module.h \ common.h \ graph.h \ arch.h \ bgraph.h \ bgraph_bipart_df.h bgraph_bipart_ex$(OBJ) : bgraph_bipart_ex.c \ module.h \ common.h \ gain.h \ graph.h \ arch.h \ bgraph.h \ bgraph_bipart_ex.h \ bgraph_bipart_fm.h \ bgraph_bipart_gg.h bgraph_bipart_fm$(OBJ) : bgraph_bipart_fm.c \ gain.h \ module.h \ common.h \ graph.h \ arch.h \ bgraph.h \ bgraph_bipart_fm.h bgraph_bipart_gg$(OBJ) : bgraph_bipart_gg.c \ gain.h \ module.h \ common.h \ graph.h \ arch.h \ bgraph.h \ bgraph_bipart_gg.h bgraph_bipart_gp$(OBJ) : bgraph_bipart_gp.c \ module.h \ common.h \ graph.h \ arch.h \ bgraph.h \ bgraph_bipart_gp.h bgraph_bipart_ml$(OBJ) : bgraph_bipart_ml.c \ module.h \ common.h \ parser.h \ graph.h \ graph_coarsen.h \ arch.h \ bgraph.h \ bgraph_bipart_ml.h \ bgraph_bipart_st.h bgraph_bipart_st$(OBJ) : bgraph_bipart_st.c \ gain.h \ module.h \ common.h \ parser.h \ graph.h \ arch.h \ bgraph.h \ bgraph_bipart_bd.h \ bgraph_bipart_df.h \ bgraph_bipart_ex.h \ bgraph_bipart_fm.h \ bgraph_bipart_gg.h \ bgraph_bipart_gp.h \ bgraph_bipart_ml.h \ bgraph_bipart_st.h \ bgraph_bipart_zr.h bgraph_bipart_zr$(OBJ) : bgraph_bipart_zr.c \ module.h \ common.h \ graph.h \ arch.h \ bgraph.h \ bgraph_bipart_zr.h bgraph_store$(OBJ) : bgraph_store.c \ module.h \ common.h \ graph.h \ arch.h \ bgraph.h comm$(OBJ) : comm.c \ module.h \ common.h \ comm.h dgraph$(OBJ) : dgraph.c \ module.h \ common.h \ dgraph.h dgraph_allreduce$(OBJ) : dgraph_allreduce.c \ module.h \ common.h \ dgraph.h dgraph_band$(OBJ) : dgraph_band.c \ module.h \ common.h \ dgraph.h dgraph_build$(OBJ) : dgraph_build.c \ module.h \ common.h \ dgraph.h \ dgraph_allreduce.h \ dgraph_build.h dgraph_build_grid3d$(OBJ) : dgraph_build_grid3d.c \ module.h \ common.h \ dgraph.h \ dgraph_build_grid3d.h dgraph_build_hcub$(OBJ) : dgraph_build_hcub.c \ module.h \ common.h \ dgraph.h dgraph_check$(OBJ) : dgraph_check.c \ module.h \ common.h \ dgraph.h dgraph_coarsen$(OBJ) : dgraph_coarsen.c \ module.h \ common.h \ dgraph.h \ dgraph_allreduce.h \ dgraph_coarsen.h \ dgraph_match.h dgraph_fold$(OBJ) : dgraph_fold.c \ module.h \ common.h \ comm.h \ dgraph.h \ dgraph_fold.h \ dgraph_fold_comm.h dgraph_fold_comm$(OBJ) : dgraph_fold_comm.c \ module.h \ common.h \ comm.h \ dgraph.h \ dgraph_fold_comm.h dgraph_fold_dup$(OBJ) : dgraph_fold_dup.c \ module.h \ common.h \ dgraph.h \ dgraph_fold_dup.h dgraph_gather$(OBJ) : dgraph_gather.c \ module.h \ common.h \ graph.h \ dgraph.h dgraph_gather_all$(OBJ) : dgraph_gather_all.c \ module.h \ common.h \ comm.h \ graph.h \ dgraph.h dgraph_ghst$(OBJ) : dgraph_ghst.c \ module.h \ common.h \ dgraph.h \ dgraph_ghst.h dgraph_halo$(OBJ) : dgraph_halo.c \ dgraph_halo_fill.c \ module.h \ common.h \ dgraph.h \ dgraph_halo.h dgraph_induce$(OBJ) : dgraph_induce.c \ module.h \ common.h \ dgraph.h dgraph_io_load$(OBJ) : dgraph_io_load.c \ module.h \ common.h \ dgraph.h \ dgraph_io_load.h dgraph_io_save$(OBJ) : dgraph_io_save.c \ module.h \ common.h \ dgraph.h dgraph_match$(OBJ) : dgraph_match.c \ dgraph_match_scan.c \ module.h \ common.h \ dgraph.h \ dgraph_coarsen.h \ dgraph_match.h dgraph_match_check$(OBJ) : dgraph_match_check.c \ module.h \ common.h \ dgraph.h \ dgraph_coarsen.h \ dgraph_match.h dgraph_match_sync_coll$(OBJ) : dgraph_match_sync_coll.c \ module.h \ common.h \ dgraph.h \ dgraph_coarsen.h \ dgraph_match.h \ graph.h dgraph_match_sync_ptop$(OBJ) : dgraph_match_sync_ptop.c \ module.h \ common.h \ dgraph.h \ dgraph_coarsen.h \ dgraph_match.h \ graph.h dgraph_scatter$(OBJ) : dgraph_scatter.c \ module.h \ common.h \ graph.h \ dgraph.h dgraph_view$(OBJ) : dgraph_view.c \ module.h \ common.h \ dgraph.h dmapping$(OBJ) : dmapping.c \ module.h \ common.h \ arch.h \ dgraph.h \ dmapping.h dmapping_io$(OBJ) : dmapping_io.c \ module.h \ common.h \ comm.h \ arch.h \ dgraph.h \ dgraph_allreduce.h \ dmapping.h dorder$(OBJ) : dorder.c \ module.h \ common.h \ dgraph.h \ dorder.h dorder_gather$(OBJ) : dorder_gather.c \ module.h \ common.h \ dgraph.h \ dorder.h \ dorder_gather.h \ order.h dorder_io$(OBJ) : dorder_io.c \ module.h \ common.h \ comm.h \ dgraph.h \ dorder.h \ order.h dorder_io_block$(OBJ) : dorder_io_block.c \ module.h \ common.h \ dgraph.h \ dorder.h \ order.h dorder_io_tree$(OBJ) : dorder_io_tree.c \ module.h \ common.h \ comm.h \ dgraph.h \ dorder.h \ order.h dorder_perm$(OBJ) : dorder_perm.c \ module.h \ common.h \ dgraph.h \ dorder.h \ dorder_perm.h dorder_tree_dist$(OBJ) : dorder_tree_dist.c \ module.h \ common.h \ dgraph.h \ dorder.h gain$(OBJ) : gain.c \ module.h \ common.h \ gain.h geom$(OBJ) : geom.c \ module.h \ common.h \ geom.h graph$(OBJ) : graph.c \ module.h \ common.h \ graph.h graph_base$(OBJ) : graph_base.c \ module.h \ common.h \ graph.h graph_check$(OBJ) : graph_check.c \ module.h \ common.h \ graph.h graph_coarsen$(OBJ) : graph_coarsen.c \ graph_coarsen_edge.c \ module.h \ common.h \ graph.h graph_induce$(OBJ) : graph_induce.c \ module.h \ common.h \ graph.h \ graph_induce.h graph_io$(OBJ) : graph_io.c \ module.h \ common.h \ graph.h \ graph_io.h graph_io_chac$(OBJ) : graph_io_chac.c \ module.h \ common.h \ geom.h \ graph.h graph_io_habo$(OBJ) : graph_io_habo.c \ module.h \ common.h \ geom.h \ graph.h \ graph_io_habo.h graph_io_mmkt$(OBJ) : graph_io_mmkt.c \ module.h \ common.h \ geom.h \ graph.h graph_io_scot$(OBJ) : graph_io_scot.c \ module.h \ common.h \ geom.h \ graph.h \ graph_io_scot.h graph_list$(OBJ) : graph_list.c \ module.h \ common.h \ graph.h hall_order_hd$(OBJ) : hall_order_hd.c \ module.h \ common.h \ graph.h \ hall_order_hd.h hall_order_hf$(OBJ) : hall_order_hf.c \ module.h \ common.h \ graph.h \ hall_order_hf.h hall_order_hx$(OBJ) : hall_order_hx.c \ module.h \ common.h \ graph.h \ order.h \ hall_order_hx.h hdgraph$(OBJ) : hdgraph.c \ module.h \ common.h \ dgraph.h \ hdgraph.h hdgraph_check$(OBJ) : hdgraph_check.c \ module.h \ common.h \ dgraph.h \ hdgraph.h hdgraph_fold$(OBJ) : hdgraph_fold.c \ module.h \ common.h \ comm.h \ dgraph.h \ dgraph_fold_comm.h \ hdgraph.h \ hdgraph_fold.h hdgraph_gather$(OBJ) : hdgraph_gather.c \ module.h \ common.h \ comm.h \ graph.h \ hgraph.h \ dgraph.h \ hdgraph.h hdgraph_induce$(OBJ) : hdgraph_induce.c \ module.h \ common.h \ dgraph.h \ hdgraph.h hdgraph_order_nd$(OBJ) : hdgraph_order_nd.c \ module.h \ common.h \ parser.h \ graph.h \ order.h \ hgraph.h \ hgraph_order_st.h \ dgraph.h \ dorder.h \ hdgraph.h \ hdgraph_order_nd.h \ hdgraph_order_sq.h \ hdgraph_order_st.h \ vdgraph.h \ vdgraph_separate_st.h hdgraph_order_si$(OBJ) : hdgraph_order_si.c \ module.h \ common.h \ dgraph.h \ dorder.h \ hdgraph.h \ hdgraph_order_si.h hdgraph_order_sq$(OBJ) : hdgraph_order_sq.c \ module.h \ common.h \ parser.h \ graph.h \ order.h \ hgraph.h \ hgraph_order_st.h \ dgraph.h \ dorder.h \ hdgraph.h \ hdgraph_order_sq.h hdgraph_order_st$(OBJ) : hdgraph_order_st.c \ module.h \ common.h \ parser.h \ graph.h \ order.h \ hgraph.h \ hgraph_order_st.h \ dgraph.h \ dorder.h \ hdgraph.h \ hdgraph_order_nd.h \ hdgraph_order_si.h \ hdgraph_order_sq.h \ hdgraph_order_st.h \ vdgraph.h \ vdgraph_separate_st.h hgraph$(OBJ) : hgraph.c \ module.h \ common.h \ graph.h \ hgraph.h hgraph_check$(OBJ) : hgraph_check.c \ module.h \ common.h \ graph.h \ hgraph.h hgraph_induce$(OBJ) : hgraph_induce.c \ hgraph_induce_edge.c \ module.h \ common.h \ graph.h \ hgraph.h \ hgraph_induce.h hgraph_order_bl$(OBJ) : hgraph_order_bl.c \ module.h \ common.h \ parser.h \ graph.h \ order.h \ hgraph.h \ hgraph_order_bl.h hgraph_order_cp$(OBJ) : hgraph_order_cp.c \ module.h \ common.h \ parser.h \ graph.h \ order.h \ hgraph.h \ hgraph_order_cp.h \ hgraph_order_st.h hgraph_order_gp$(OBJ) : hgraph_order_gp.c \ module.h \ common.h \ graph.h \ order.h \ hgraph.h \ hgraph_order_gp.h hgraph_order_hd$(OBJ) : hgraph_order_hd.c \ module.h \ common.h \ graph.h \ order.h \ hgraph.h \ hall_order_hd.h \ hall_order_hx.h \ hgraph_order_hd.h \ hgraph_order_hx.h \ hgraph_order_si.h hgraph_order_hf$(OBJ) : hgraph_order_hf.c \ module.h \ common.h \ graph.h \ order.h \ hgraph.h \ hall_order_hf.h \ hall_order_hx.h \ hgraph_order_hf.h \ hgraph_order_hx.h \ hgraph_order_si.h hgraph_order_hx$(OBJ) : hgraph_order_hx.c \ module.h \ common.h \ graph.h \ hgraph.h \ hgraph_order_hx.h hgraph_order_nd$(OBJ) : hgraph_order_nd.c \ module.h \ common.h \ parser.h \ graph.h \ order.h \ hgraph.h \ hgraph_order_nd.h \ hgraph_order_st.h \ vgraph.h \ vgraph_separate_st.h hgraph_order_si$(OBJ) : hgraph_order_si.c \ module.h \ common.h \ graph.h \ order.h \ hgraph.h \ hgraph_order_si.h hgraph_order_st$(OBJ) : hgraph_order_st.c \ module.h \ common.h \ parser.h \ graph.h \ graph_coarsen.h \ order.h \ hgraph.h \ vgraph.h \ vgraph_separate_st.h \ hgraph_order_bl.h \ hgraph_order_cp.h \ hgraph_order_gp.h \ hgraph_order_hd.h \ hgraph_order_hf.h \ hgraph_order_nd.h \ hgraph_order_si.h \ hgraph_order_st.h hmesh$(OBJ) : hmesh.c \ module.h \ common.h \ graph.h \ mesh.h \ hmesh.h hmesh_check$(OBJ) : hmesh_check.c \ module.h \ common.h \ graph.h \ mesh.h \ hmesh.h hmesh_hgraph$(OBJ) : hmesh_hgraph.c \ module.h \ common.h \ graph.h \ hgraph.h \ mesh.h \ hmesh.h \ hmesh_hgraph.h hmesh_induce$(OBJ) : hmesh_induce.c \ module.h \ common.h \ graph.h \ mesh.h \ hmesh.h hmesh_mesh$(OBJ) : hmesh_mesh.c \ module.h \ common.h \ graph.h \ mesh.h \ hmesh.h hmesh_order_bl$(OBJ) : hmesh_order_bl.c \ module.h \ common.h \ parser.h \ graph.h \ order.h \ mesh.h \ hmesh.h \ hmesh_order_bl.h \ hmesh_order_st.h hmesh_order_cp$(OBJ) : hmesh_order_cp.c \ module.h \ common.h \ parser.h \ graph.h \ order.h \ mesh.h \ hmesh.h \ hmesh_order_cp.h \ hmesh_order_st.h hmesh_order_gp$(OBJ) : hmesh_order_gp.c \ module.h \ common.h \ graph.h \ order.h \ mesh.h \ hmesh.h \ hmesh_order_gp.h hmesh_order_gr$(OBJ) : hmesh_order_gr.c \ module.h \ common.h \ parser.h \ graph.h \ hgraph.h \ hgraph_order_st.h \ order.h \ mesh.h \ hmesh.h \ hmesh_order_gr.h hmesh_order_hd$(OBJ) : hmesh_order_hd.c \ module.h \ common.h \ graph.h \ order.h \ mesh.h \ hmesh.h \ hall_order_hd.h \ hall_order_hx.h \ hmesh_order_hd.h \ hmesh_order_si.h hmesh_order_hf$(OBJ) : hmesh_order_hf.c \ module.h \ common.h \ graph.h \ order.h \ mesh.h \ hmesh.h \ hall_order_hf.h \ hall_order_hx.h \ hmesh_order_hf.h \ hmesh_order_si.h hmesh_order_hx$(OBJ) : hmesh_order_hx.c \ module.h \ common.h \ graph.h \ mesh.h \ hmesh.h \ hmesh_order_hx.h hmesh_order_nd$(OBJ) : hmesh_order_nd.c \ module.h \ common.h \ parser.h \ graph.h \ order.h \ mesh.h \ hmesh.h \ hmesh_order_nd.h \ hmesh_order_st.h \ vmesh.h \ vmesh_separate_st.h hmesh_order_si$(OBJ) : hmesh_order_si.c \ module.h \ common.h \ graph.h \ order.h \ mesh.h \ hmesh.h \ hmesh_order_si.h hmesh_order_st$(OBJ) : hmesh_order_st.c \ module.h \ common.h \ parser.h \ graph.h \ hgraph.h \ hgraph_order_st.h \ mesh.h \ hmesh.h \ order.h \ vmesh_separate_st.h \ hmesh_order_bl.h \ hmesh_order_gp.h \ hmesh_order_gr.h \ hmesh_order_hd.h \ hmesh_order_hf.h \ hmesh_order_nd.h \ hmesh_order_si.h \ hmesh_order_st.h kdgraph$(OBJ) : kdgraph.c \ module.h \ common.h \ arch.h \ dgraph.h \ dmapping.h \ kdgraph.h kdgraph_map_rb$(OBJ) : kdgraph_map_rb.c \ module.h \ common.h \ parser.h \ arch.h \ graph.h \ dgraph.h \ dmapping.h \ kdgraph.h \ kdgraph_map_rb.h \ kdgraph_map_rb_map.h \ kdgraph_map_rb_part.h kdgraph_map_rb_map$(OBJ) : kdgraph_map_rb_map.c \ module.h \ common.h \ parser.h \ arch.h \ graph.h \ bgraph.h \ bgraph_bipart_st.h \ mapping.h \ kgraph.h \ kgraph_map_st.h \ dgraph.h \ dmapping.h \ bdgraph.h \ bdgraph_bipart_st.h \ kdgraph.h \ kdgraph_map_rb.h \ kdgraph_map_rb_map.h \ kdgraph_map_st.h kdgraph_map_rb_part$(OBJ) : kdgraph_map_rb_part.c \ module.h \ common.h \ parser.h \ arch.h \ graph.h \ bgraph.h \ bgraph_bipart_st.h \ mapping.h \ kgraph.h \ kgraph_map_st.h \ dgraph.h \ dmapping.h \ bdgraph.h \ bdgraph_bipart_st.h \ kdgraph.h \ kdgraph_map_rb.h \ kdgraph_map_rb_part.h \ kdgraph_map_st.h kdgraph_map_st$(OBJ) : kdgraph_map_st.c \ module.h \ common.h \ parser.h \ arch.h \ graph.h \ dgraph.h \ dgraph_coarsen.h \ mapping.h \ dmapping.h \ bdgraph.h \ bdgraph_bipart_st.h \ kgraph.h \ kgraph_map_st.h \ kdgraph.h \ kdgraph_map_rb.h \ kdgraph_map_st.h kgraph$(OBJ) : kgraph.c \ module.h \ common.h \ graph.h \ arch.h \ mapping.h \ kgraph.h kgraph_check$(OBJ) : kgraph_check.c \ module.h \ common.h \ graph.h \ arch.h \ mapping.h \ kgraph.h kgraph_map_ml$(OBJ) : kgraph_map_ml.c \ module.h \ common.h \ parser.h \ graph.h \ arch.h \ mapping.h \ kgraph.h \ kgraph_map_ml.h \ kgraph_map_st.h kgraph_map_rb$(OBJ) : kgraph_map_rb.c \ module.h \ common.h \ parser.h \ graph.h \ arch.h \ mapping.h \ bgraph.h \ bgraph_bipart_st.h \ kgraph.h \ kgraph_map_rb.h \ kgraph_map_rb_map.h \ kgraph_map_rb_part.h kgraph_map_rb_map$(OBJ) : kgraph_map_rb_map.c \ module.h \ common.h \ parser.h \ graph.h \ arch.h \ mapping.h \ bgraph.h \ bgraph_bipart_st.h \ kgraph.h \ kgraph_map_rb.h \ kgraph_map_rb_map.h kgraph_map_rb_part$(OBJ) : kgraph_map_rb_part.c \ module.h \ common.h \ parser.h \ graph.h \ arch.h \ mapping.h \ bgraph.h \ bgraph_bipart_st.h \ kgraph.h \ kgraph_map_rb.h \ kgraph_map_rb_part.h kgraph_map_st$(OBJ) : kgraph_map_st.c \ module.h \ common.h \ parser.h \ graph.h \ arch.h \ mapping.h \ bgraph.h \ bgraph_bipart_st.h \ kgraph.h \ kgraph_map_ml.h \ kgraph_map_rb.h \ kgraph_map_st.h library_arch$(OBJ) : library_arch.c \ module.h \ common.h \ graph.h \ arch.h \ arch_cmplt.h \ scotch.h library_arch_f$(OBJ) : library_arch_f.c \ module.h \ common.h \ scotch.h library_arch_build$(OBJ) : library_arch_build.c \ module.h \ common.h \ parser.h \ graph.h \ arch.h \ arch_build.h \ mapping.h \ bgraph.h \ bgraph_bipart_st.h \ scotch.h library_arch_build_f$(OBJ) : library_arch_build_f.c \ module.h \ common.h \ scotch.h library_dgraph$(OBJ) : library_dgraph.c \ module.h \ common.h \ graph.h \ dgraph.h \ scotch.h library_dgraph_f$(OBJ) : library_dgraph_f.c \ module.h \ common.h \ scotch.h library_dgraph_build$(OBJ) : library_dgraph_build.c \ module.h \ common.h \ dgraph.h \ scotch.h library_dgraph_build_f$(OBJ) : library_dgraph_build_f.c \ module.h \ common.h \ scotch.h library_dgraph_build_grid3d$(OBJ): library_dgraph_build_grid3d.c \ module.h \ common.h \ dgraph.h \ scotch.h library_dgraph_build_grid3d_f$(OBJ): library_dgraph_build_grid3d_f.c \ module.h \ common.h \ scotch.h library_dgraph_check$(OBJ) : library_dgraph_check.c \ module.h \ common.h \ dgraph.h \ scotch.h library_dgraph_check_f$(OBJ) : library_dgraph_check_f.c \ module.h \ common.h \ scotch.h library_dgraph_coarsen$(OBJ) : library_dgraph_coarsen.c \ module.h \ common.h \ dgraph.h \ dgraph_coarsen.h \ scotch.h library_dgraph_coarsen_f$(OBJ) : library_dgraph_coarsen_f.c \ module.h \ common.h \ scotch.h library_dgraph_gather$(OBJ) : library_dgraph_gather.c \ module.h \ common.h \ dgraph.h \ scotch.h library_dgraph_gather_f$(OBJ) : library_dgraph_gather_f.c \ module.h \ common.h \ scotch.h library_dgraph_halo$(OBJ) : library_dgraph_halo.c \ module.h \ common.h \ dgraph.h \ dgraph_halo.h \ scotch.h library_dgraph_halo_f$(OBJ) : library_dgraph_halo_f.c \ module.h \ common.h \ scotch.h library_dgraph_io_load$(OBJ) : library_dgraph_io_load.c \ module.h \ common.h \ dgraph.h \ scotch.h library_dgraph_io_load_f$(OBJ) : library_dgraph_io_load_f.c \ module.h \ common.h \ scotch.h library_dgraph_io_save$(OBJ) : library_dgraph_io_save.c \ module.h \ common.h \ dgraph.h \ scotch.h library_dgraph_io_save_f$(OBJ) : library_dgraph_io_save_f.c \ module.h \ common.h \ scotch.h library_dgraph_map$(OBJ) : library_dgraph_map.c \ module.h \ common.h \ parser.h \ arch.h \ dgraph.h \ dmapping.h \ kdgraph.h \ kdgraph_map_st.h \ library_dmapping.h \ scotch.h library_dgraph_map_f$(OBJ) : library_dgraph_map_f.c \ module.h \ common.h \ scotch.h library_dgraph_map_view$(OBJ) : library_dgraph_map_view.c \ module.h \ common.h \ parser.h \ dgraph.h \ dgraph_halo.h \ arch.h \ dmapping.h \ kdgraph.h \ library_dmapping.h \ scotch.h library_dgraph_map_view_f$(OBJ) : library_dgraph_map_view_f.c \ module.h \ common.h \ scotch.h library_dgraph_order$(OBJ) : library_dgraph_order.c \ module.h \ common.h \ parser.h \ dgraph.h \ dorder.h \ hdgraph.h \ hdgraph_order_st.h \ scotch.h library_dgraph_order_f$(OBJ) : library_dgraph_order_f.c \ module.h \ common.h \ scotch.h library_dgraph_order_gather$(OBJ): library_dgraph_order_gather.c \ module.h \ common.h \ dgraph.h \ order.h \ dorder.h \ library_order.h \ scotch.h library_dgraph_order_gather_f$(OBJ): library_dgraph_order_gather_f.c \ module.h \ common.h \ scotch.h library_dgraph_order_io$(OBJ) : library_dgraph_order_io.c \ module.h \ common.h \ graph.h \ dgraph.h \ order.h \ dorder.h \ library_order.h \ scotch.h library_dgraph_order_io_f$(OBJ) : library_dgraph_order_io_f.c \ module.h \ common.h \ scotch.h library_dgraph_order_io_block$(OBJ): library_dgraph_order_io_block.c \ module.h \ common.h \ dgraph.h \ dorder.h \ scotch.h library_dgraph_order_io_block_f$(OBJ): library_dgraph_order_io_block_f.c \ module.h \ common.h \ scotch.h library_dgraph_order_perm$(OBJ) : library_dgraph_order_perm.c \ module.h \ common.h \ dgraph.h \ dorder.h \ scotch.h library_dgraph_order_perm_f$(OBJ): library_dgraph_order_perm_f.c \ module.h \ common.h \ scotch.h library_dgraph_order_tree_dist$(OBJ): library_dgraph_order_tree_dist.c \ module.h \ common.h \ dgraph.h \ dorder.h \ scotch.h library_dgraph_order_tree_dist_f$(OBJ): library_dgraph_order_tree_dist_f.c \ module.h \ common.h \ scotch.h library_dgraph_scatter$(OBJ) : library_dgraph_scatter.c \ module.h \ common.h \ dgraph.h \ scotch.h library_dgraph_scatter_f$(OBJ) : library_dgraph_scatter_f.c \ module.h \ common.h \ scotch.h library_dgraph_stat$(OBJ) : library_dgraph_stat.c \ module.h \ common.h \ dgraph.h \ scotch.h \ library_dgraph_stat.h library_dgraph_stat_f$(OBJ) : library_dgraph_stat_f.c \ module.h \ common.h \ scotch.h library_dmapping$(OBJ) : library_dmapping.c \ module.h \ common.h \ scotch.h library_dorder$(OBJ) : library_dorder.c \ module.h \ common.h \ scotch.h library_error$(OBJ) : library_error.c \ module.h \ common.h \ scotch.h library_error_exit$(OBJ) : library_error_exit.c \ module.h \ common.h \ scotch.h library_geom$(OBJ) : library_geom.c \ module.h \ common.h \ geom.h \ graph.h \ scotch.h library_geom_f$(OBJ) : library_geom_f.c \ module.h \ common.h \ scotch.h library_graph$(OBJ) : library_graph.c \ module.h \ common.h \ graph.h \ graph_io.h \ scotch.h library_graph_f$(OBJ) : library_graph_f.c \ module.h \ common.h \ scotch.h library_graph_base$(OBJ) : library_graph_base.c \ module.h \ common.h \ graph.h \ scotch.h library_graph_base_f$(OBJ) : library_graph_base_f.c \ module.h \ common.h \ scotch.h library_graph_check$(OBJ) : library_graph_check.c \ module.h \ common.h \ graph.h \ scotch.h library_graph_check_f$(OBJ) : library_graph_check_f.c \ module.h \ common.h \ scotch.h library_graph_coarsen$(OBJ) : library_graph_coarsen.c \ module.h \ common.h \ graph.h \ graph_coarsen.h \ scotch.h library_graph_coarsen_f$(OBJ) : library_graph_coarsen_f.c \ module.h \ common.h \ scotch.h library_graph_io_chac$(OBJ) : library_graph_io_chac.c \ module.h \ common.h \ geom.h \ graph.h \ scotch.h library_graph_io_chac_f$(OBJ) : library_graph_io_chac_f.c \ module.h \ common.h \ scotch.h library_graph_io_habo$(OBJ) : library_graph_io_habo.c \ module.h \ common.h \ geom.h \ graph.h \ scotch.h library_graph_io_habo_f$(OBJ) : library_graph_io_habo_f.c \ module.h \ common.h \ scotch.h library_graph_io_mmkt$(OBJ) : library_graph_io_mmkt.c \ module.h \ common.h \ geom.h \ graph.h \ scotch.h library_graph_io_mmkt_f$(OBJ) : library_graph_io_mmkt_f.c \ module.h \ common.h \ scotch.h library_graph_io_scot$(OBJ) : library_graph_io_scot.c \ module.h \ common.h \ geom.h \ graph.h \ scotch.h library_graph_io_scot_f$(OBJ) : library_graph_io_scot_f.c \ module.h \ common.h \ scotch.h library_graph_map$(OBJ) : library_graph_map.c \ module.h \ common.h \ parser.h \ graph.h \ arch.h \ mapping.h \ kgraph.h \ kgraph_map_st.h \ scotch.h library_graph_map_f$(OBJ) : library_graph_map_f.c \ module.h \ common.h \ scotch.h library_graph_map_view$(OBJ) : library_graph_map_view.c \ module.h \ common.h \ parser.h \ graph.h \ arch.h \ mapping.h \ kgraph.h \ library_mapping.h \ library_graph_map_view.h \ scotch.h library_graph_map_view_f$(OBJ) : library_graph_map_view_f.c \ module.h \ common.h \ scotch.h library_graph_order$(OBJ) : library_graph_order.c \ module.h \ common.h \ parser.h \ graph.h \ order.h \ hgraph.h \ hgraph_order_st.h \ library_order.h \ scotch.h library_graph_order_f$(OBJ) : library_graph_order_f.c \ module.h \ common.h \ scotch.h library_mapping$(OBJ) : library_mapping.c \ module.h \ common.h \ scotch.h library_mesh$(OBJ) : library_mesh.c \ module.h \ common.h \ graph.h \ mesh.h \ scotch.h library_mesh_f$(OBJ) : library_mesh_f.c \ module.h \ common.h \ scotch.h library_mesh_graph$(OBJ) : library_mesh_graph.c \ module.h \ common.h \ graph.h \ mesh.h \ scotch.h library_mesh_graph_f$(OBJ) : library_mesh_graph_f.c \ module.h \ common.h \ scotch.h library_mesh_io_habo$(OBJ) : library_mesh_io_habo.c \ module.h \ common.h \ geom.h \ graph.h \ mesh.h \ scotch.h library_mesh_io_habo_f$(OBJ) : library_mesh_io_habo_f.c \ module.h \ common.h \ scotch.h library_mesh_io_scot$(OBJ) : library_mesh_io_scot.c \ module.h \ common.h \ geom.h \ graph.h \ mesh.h \ scotch.h library_mesh_io_scot_f$(OBJ) : library_mesh_io_scot_f.c \ module.h \ common.h \ scotch.h library_mesh_order$(OBJ) : library_mesh_order.c \ module.h \ common.h \ parser.h \ graph.h \ mesh.h \ hmesh.h \ order.h \ hmesh_order_st.h \ scotch.h \ library_order.h library_mesh_order_f$(OBJ) : library_mesh_order_f.c \ module.h \ common.h \ scotch.h library_order$(OBJ) : library_order.c \ module.h \ common.h \ scotch.h library_parser$(OBJ) : library_parser.c \ module.h \ common.h \ parser.h \ scotch.h library_parser_f$(OBJ) : library_parser_f.c \ module.h \ common.h \ scotch.h library_random$(OBJ) : library_random.c \ module.h \ common.h \ scotch.h library_random_f$(OBJ) : library_random_f.c \ module.h \ common.h \ scotch.h library_strat$(OBJ) : library_strat.c \ module.h \ common.h \ scotch.h library_version$(OBJ) : library_version.c \ module.h \ common.h \ scotch.h library_version_f$(OBJ) : library_version_f.c \ module.h \ common.h \ scotch.h mapping$(OBJ) : mapping.c \ module.h \ common.h \ graph.h \ arch.h \ mapping.h mapping_io$(OBJ) : mapping_io.c \ module.h \ common.h \ graph.h \ arch.h \ mapping.h \ mapping_io.h mesh$(OBJ) : mesh.c \ module.h \ common.h \ graph.h \ mesh.h mesh_check$(OBJ) : mesh_check.c \ module.h \ common.h \ graph.h \ mesh.h mesh_coarsen$(OBJ) : mesh_coarsen.c \ module.h \ common.h \ graph.h \ mesh.h mesh_graph$(OBJ) : mesh_graph.c \ module.h \ common.h \ graph.h \ mesh.h \ mesh_graph.h mesh_induce_sepa$(OBJ) : mesh_induce_sepa.c \ module.h \ common.h \ graph.h \ mesh.h \ mesh_induce_sepa.h mesh_io$(OBJ) : mesh_io.c \ module.h \ common.h \ graph.h \ graph_io.h \ mesh.h \ mesh_io.h mesh_io_habo$(OBJ) : mesh_io_habo.c \ module.h \ common.h \ geom.h \ graph.h \ mesh.h mesh_io_scot$(OBJ) : mesh_io_scot.c \ module.h \ common.h \ geom.h \ graph.h \ mesh.h order$(OBJ) : order.c \ module.h \ common.h \ graph.h \ order.h order_check$(OBJ) : order_check.c \ module.h \ common.h \ graph.h \ order.h order_io$(OBJ) : order_io.c \ module.h \ common.h \ graph.h \ order.h parser$(OBJ) : parser.c \ module.h \ common.h \ parser.h \ parser_yy.h parser_ll.c : parser_ll.l \ module.h \ common.h \ parser.h \ parser_ll.h \ parser_ly.h ($(LEX) parser_ll.l && \ $(MV) lex.yy.c parser_ll.c) || \ $(CP) last_resort/parser_ll.c . parser_ll$(OBJ) : parser_ll.c \ parser_ly.h parser_ly.h : parser_yy$(OBJ) parser_yy.c : parser_yy.y \ module.h \ common.h \ parser.h \ parser_yy.h ($(YACC) -d -v parser_yy.y && \ $(MV) y.tab.c parser_yy.c && \ $(MV) y.tab.h parser_ly.h) || \ $(CP) last_resort/parser_ly.h last_resort/parser_yy.c . parser_yy$(OBJ) : parser_yy.c vdgraph$(OBJ) : vdgraph.c \ module.h \ common.h \ dgraph.h \ vdgraph.h vdgraph_check$(OBJ) : vdgraph_check.c \ module.h \ common.h \ dgraph.h \ vdgraph.h vdgraph_gather_all$(OBJ) : vdgraph_gather_all.c \ module.h \ common.h \ comm.h \ graph.h \ vgraph.h \ dgraph.h \ vdgraph.h vdgraph_separate_bd$(OBJ) : vdgraph_separate_bd.c \ module.h \ common.h \ parser.h \ dgraph.h \ vdgraph.h \ vdgraph_separate_bd.h \ vdgraph_separate_st.h vdgraph_separate_df$(OBJ) : vdgraph_separate_df.c \ module.h \ common.h \ dgraph.h \ vdgraph.h \ vdgraph_separate_df.h vdgraph_separate_ml$(OBJ) : vdgraph_separate_ml.c \ module.h \ common.h \ parser.h \ dgraph.h \ dgraph_coarsen.h \ vdgraph.h \ vdgraph_separate_ml.h \ vdgraph_separate_st.h vdgraph_separate_sq$(OBJ) : vdgraph_separate_sq.c \ module.h \ common.h \ comm.h \ parser.h \ graph.h \ vgraph.h \ vgraph_separate_st.h \ dgraph.h \ vdgraph.h \ vdgraph_separate_sq.h vdgraph_separate_st$(OBJ) : vdgraph_separate_st.c \ module.h \ common.h \ parser.h \ graph.h \ vgraph.h \ vgraph_separate_st.h \ dgraph.h \ dgraph_coarsen.h \ vdgraph.h \ vdgraph_separate_bd.h \ vdgraph_separate_df.h \ vdgraph_separate_ml.h \ vdgraph_separate_sq.h \ vdgraph_separate_st.h \ vdgraph_separate_zr.h vdgraph_separate_zr$(OBJ) : vdgraph_separate_zr.c \ module.h \ common.h \ dgraph.h \ vdgraph.h \ vdgraph_separate_zr.h vdgraph_store$(OBJ) : vdgraph_store.c \ module.h \ common.h \ dgraph.h \ vdgraph.h vgraph$(OBJ) : vgraph.c \ module.h \ common.h \ graph.h \ vgraph.h vgraph_check$(OBJ) : vgraph_check.c \ module.h \ common.h \ graph.h \ vgraph.h vgraph_separate_bd$(OBJ) : vgraph_separate_bd.c \ module.h \ common.h \ parser.h \ graph.h \ vgraph.h \ vgraph_separate_bd.h \ vgraph_separate_st.h vgraph_separate_es$(OBJ) : vgraph_separate_es.c \ module.h \ common.h \ parser.h \ graph.h \ arch.h \ mapping.h \ bgraph.h \ bgraph_bipart_st.h \ vgraph.h \ vgraph_separate_es.h vgraph_separate_fm$(OBJ) : vgraph_separate_fm.c \ module.h \ common.h \ gain.h \ graph.h \ vgraph.h \ vgraph_separate_gg.h \ vgraph_separate_fm.h vgraph_separate_gg$(OBJ) : vgraph_separate_gg.c \ module.h \ common.h \ graph.h \ vgraph.h \ vgraph_separate_gg.h vgraph_separate_gp$(OBJ) : vgraph_separate_gp.c \ module.h \ common.h \ graph.h \ vgraph.h \ vgraph_separate_gp.h vgraph_separate_ml$(OBJ) : vgraph_separate_ml.c \ module.h \ common.h \ parser.h \ graph.h \ graph_coarsen.h \ vgraph.h \ vgraph_separate_ml.h \ vgraph_separate_st.h vgraph_separate_mt$(OBJ) : vgraph_separate_mt.c \ module.h \ common.h \ graph.h \ vgraph.h \ vgraph_separate_mt.h vgraph_separate_st$(OBJ) : vgraph_separate_st.c \ gain.h \ module.h \ common.h \ gain.h \ parser.h \ graph.h \ graph_coarsen.h \ arch.h \ mapping.h \ bgraph.h \ bgraph_bipart_st.h \ vgraph.h \ vgraph_separate_bd.h \ vgraph_separate_es.h \ vgraph_separate_fm.h \ vgraph_separate_gg.h \ vgraph_separate_gp.h \ vgraph_separate_ml.h \ vgraph_separate_st.h \ vgraph_separate_th.h \ vgraph_separate_vw.h \ vgraph_separate_zr.h vgraph_separate_th$(OBJ) : vgraph_separate_th.c \ module.h \ common.h \ graph.h \ vgraph.h \ vgraph_separate_th.h vgraph_separate_vw$(OBJ) : vgraph_separate_vw.c \ module.h \ common.h \ graph.h \ vgraph.h \ vgraph_separate_vw.h vgraph_separate_zr$(OBJ) : vgraph_separate_zr.c \ module.h \ common.h \ graph.h \ vgraph.h \ vgraph_separate_zr.h vgraph_store$(OBJ) : vgraph_store.c \ module.h \ common.h \ graph.h \ vgraph.h vmesh$(OBJ) : vmesh.c \ module.h \ common.h \ graph.h \ mesh.h \ vmesh.h vmesh_check$(OBJ) : vmesh_check.c \ module.h \ common.h \ graph.h \ mesh.h \ vmesh.h vmesh_separate_fm$(OBJ) : vmesh_separate_fm.c \ module.h \ common.h \ graph.h \ mesh.h \ vmesh.h \ vmesh_separate_fm.h vmesh_separate_gg$(OBJ) : vmesh_separate_gg.c \ module.h \ common.h \ graph.h \ mesh.h \ vmesh.h \ vmesh_separate_gg.h vmesh_separate_gr$(OBJ) : vmesh_separate_gr.c \ module.h \ common.h \ parser.h \ graph.h \ vgraph.h \ vgraph_separate_st.h \ mesh.h \ vmesh.h \ vmesh_separate_gr.h vmesh_separate_ml$(OBJ) : vmesh_separate_ml.c \ module.h \ common.h \ parser.h \ graph.h \ mesh.h \ mesh_coarsen.h \ vmesh.h \ vmesh_separate_ml.h \ vmesh_separate_st.h vmesh_separate_zr$(OBJ) : vmesh_separate_zr.c \ module.h \ common.h \ graph.h \ mesh.h \ vmesh.h \ vmesh_separate_zr.h vmesh_separate_st$(OBJ) : vmesh_separate_st.c \ gain.h \ module.h \ common.h \ parser.h \ graph.h \ mesh.h \ mesh_coarsen.h \ vmesh.h \ vmesh_separate_fm.h \ vmesh_separate_gg.h \ vmesh_separate_gr.h \ vmesh_separate_ml.h \ vmesh_separate_zr.h \ vmesh_separate_st.h vmesh_store$(OBJ) : vmesh_store.c \ module.h \ common.h \ graph.h \ mesh.h \ vmesh.h dummysizes$(EXE) : dummysizes.c \ module.h \ common.h \ arch.h \ dgraph.h \ dgraph_halo.h \ dorder.h \ geom.h \ graph.h \ library_mapping.h \ library_order.h \ mesh.h \ mapping.h \ order.h \ parser.h $(CCD) $(CFLAGS) -DSCOTCH_VERSION=$(VERSION) -DSCOTCH_RELEASE=$(RELEASE) -DSCOTCH_PATCHLEVEL=$(PATCHLEVEL) $(<) -o $(@) $(LDFLAGS) scotch.h : dummysizes$(EXE) \ library.h ./dummysizes$(EXE) library.h scotch.h scotchf.h : dummysizes$(EXE) \ libraryf.h ./dummysizes$(EXE) libraryf.h scotchf.h libptscotch$(LIB) : $(LIBPTSCOTCHDEPS) $(LIBSCOTCHDEPS) $(AR) $(ARFLAGS) $(@) $(?) -$(RANLIB) $(@) libscotch$(LIB) : $(LIBSCOTCHDEPS) $(AR) $(ARFLAGS) $(@) $(?) -$(RANLIB) $(@) libptscotcherr$(LIB) : library_error$(OBJ) $(AR) $(ARFLAGS) $(@) $(?) -$(RANLIB) $(@) libptscotcherrexit$(LIB) : library_error_exit$(OBJ) $(AR) $(ARFLAGS) $(@) $(?) -$(RANLIB) $(@) libscotcherr$(LIB) : library_error$(OBJ) $(AR) $(ARFLAGS) $(@) $(?) -$(RANLIB) $(@) libscotcherrexit$(LIB) : library_error_exit$(OBJ) $(AR) $(ARFLAGS) $(@) $(?) -$(RANLIB) $(@) scotch-5.1.12b.dfsg/src/libscotch/graph_check.c0000644000175300017530000001666411631334325021552 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_check.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the source graph **/ /** checking function. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to 18 may 1993 **/ /** # Version 1.3 : from : 30 apr 1994 **/ /** to 18 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 31 oct 1994 **/ /** # Version 3.0 : from : 07 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 28 nov 1995 **/ /** to 08 jun 1996 **/ /** # Version 3.2 : from : 07 sep 1996 **/ /** to 15 sep 1998 **/ /** # Version 3.3 : from : 22 sep 1998 **/ /** to 31 dec 1998 **/ /** # Version 4.0 : from : 24 nov 2001 **/ /** to 22 apr 2004 **/ /** # Version 5.0 : from : 13 dec 2006 **/ /** to 02 oct 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GRAPH #include "module.h" #include "common.h" #include "graph.h" /****************************************/ /* */ /* These routines handle source graphs. */ /* */ /****************************************/ /* This routine checks the consistency ** of the given graph. ** It returns: ** - 0 : if graph data are consistent. ** - !0 : on error. */ int graphCheck ( const Graph * const grafptr) { Gnum vertnum; /* Number of current vertex */ Gnum velosum; /* Sum of vertex loads */ Gnum edlosum; /* Sum of edge loads */ Gnum edgenbr; /* Number of edges (arcs) */ Gnum edgenum; /* Number of current edge */ Gnum degrmax; /* Maximum degree */ if (grafptr->vertnbr != (grafptr->vertnnd - grafptr->baseval)) { errorPrint ("graphCheck: invalid vertex numbers"); return (1); } degrmax = edgenbr = 0; velosum = (grafptr->velotax == NULL) ? grafptr->vertnbr : 0; edlosum = (grafptr->edlotax == NULL) ? grafptr->edgenbr : 0; for (vertnum = grafptr->baseval; vertnum < grafptr->vertnnd; vertnum ++) { if ((grafptr->verttax[vertnum] < grafptr->baseval) || (grafptr->vendtax[vertnum] < grafptr->verttax[vertnum])) { errorPrint ("graphCheck: invalid vertex arrays"); return (1); } if ((grafptr->vendtax[vertnum] - grafptr->verttax[vertnum]) > degrmax) degrmax = grafptr->vendtax[vertnum] - grafptr->verttax[vertnum]; edgenbr += grafptr->vendtax[vertnum] - grafptr->verttax[vertnum]; for (edgenum = grafptr->verttax[vertnum]; edgenum < grafptr->vendtax[vertnum]; edgenum ++) { Gnum vertend; /* Number of end vertex */ Gnum edgeend; /* Number of end vertex edge */ vertend = grafptr->edgetax[edgenum]; if (grafptr->edlotax != NULL) edlosum += grafptr->edlotax[edgenum]; if ((vertend < grafptr->baseval) || (vertend >= grafptr->vertnnd)) { /* If invalid edge end */ errorPrint ("graphCheck: invalid edge array"); return (1); } if (vertend == vertnum) { /* Loops not allowed */ errorPrint ("graphCheck: loops not allowed"); return (1); } for (edgeend = grafptr->verttax[vertend]; /* Search for matching arc */ (edgeend < grafptr->vendtax[vertend]) && (grafptr->edgetax[edgeend] != vertnum); edgeend ++) ; if ((edgeend >= grafptr->vendtax[vertend]) || ((grafptr->edlotax != NULL) && (grafptr->edlotax[edgenum] != grafptr->edlotax[edgeend]))) { errorPrint ("graphCheck: arc data do not match"); return (1); } for (edgeend ++; /* Search for duplicate arcs */ (edgeend < grafptr->vendtax[vertend]) && (grafptr->edgetax[edgeend] != vertnum); edgeend ++) ; if (edgeend < grafptr->vendtax[vertend]) { errorPrint ("graphCheck: duplicate arc"); return (1); } } if (grafptr->velotax != NULL) { if (grafptr->velotax[vertnum] < 1) { /* If non-strictly positive loads */ errorPrint ("graphCheck: invalid vertex load array"); return (1); } velosum += grafptr->velotax[vertnum]; /* Accumulate vertex loads */ } } if (grafptr->edgenbr != edgenbr) { errorPrint ("graphCheck: invalid number of edges"); return (1); } if (grafptr->velosum != velosum) { errorPrint ("graphCheck: invalid vertex load sum"); return (1); } if (grafptr->edlosum != edlosum) { errorPrint ("graphCheck: invalid edge load sum"); return (1); } if (grafptr->degrmax < degrmax) { errorPrint ("graphCheck: invalid maximum degree"); return (1); } return (0); } scotch-5.1.12b.dfsg/src/libscotch/dgraph.c0000644000175300017530000002070411631334325020547 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Francois CHATENET (P0.0) **/ /** Sebastien FOUCAULT (P0.0) **/ /** Nicolas GICQUEL (P0.1) **/ /** Jerome LACOSTE (P0.1) **/ /** Cedric CHEVALIER **/ /** **/ /** FUNCTION : This module contains the distributed **/ /** graph data structure handling **/ /** routines. **/ /** **/ /** DATES : # Version P0.0 : from : 01 apr 1997 **/ /** to 01 apr 1997 **/ /** # Version P0.1 : from : 12 apr 1998 **/ /** to 20 jun 1998 **/ /** # Version 5.0 : from : 16 feb 2005 **/ /** to : 17 jul 2008 **/ /** # Version 5.1 : from : 21 jun 2008 **/ /** to : 30 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH #include "module.h" #include "common.h" #include "dgraph.h" /*************************************/ /* */ /* These routines handle distributed */ /* source graphs. */ /* */ /*************************************/ /* This routine initializes a distributed graph ** structure. In order to avoid collective ** communication whenever possible, the allocation ** of send and receive index arrays is not performed ** in the routine itself, but rather delegated to ** subsequent routines such as dgraphBuild. ** However, these arrays will not be freed by ** dgraphFree, but by dgraphExit. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphInit ( Dgraph * restrict const grafptr, /* Distributed graph structure */ MPI_Comm proccomm) /* Communicator to be used for all communications */ { memSet (grafptr, 0, sizeof (Dgraph)); /* Clear public and private graph fields */ grafptr->proccomm = proccomm; /* Set private fields */ MPI_Comm_size (proccomm, &grafptr->procglbnbr); /* Get communicator data */ MPI_Comm_rank (proccomm, &grafptr->proclocnum); return (0); } /* This routine frees the public data of the given ** distributed graph, but not its private data. ** It is not a collective routine, as no communication ** is needed to perform the freeing of memory structures. ** It returns: ** - VOID : in all cases. */ static void dgraphFree2 ( Dgraph * restrict const grafptr) { if ((grafptr->flagval & DGRAPHFREETABS) != 0) { /* If local arrays must be freed */ if (grafptr->vertloctax != NULL) memFree (grafptr->vertloctax + grafptr->baseval); if ((grafptr->flagval & DGRAPHVERTGROUP) == 0) { /* If vertex arrays not grouped */ if (grafptr->vendloctax != (grafptr->vertloctax + 1)) memFree (grafptr->vendloctax + grafptr->baseval); if (grafptr->veloloctax != NULL) memFree (grafptr->veloloctax + grafptr->baseval); if (grafptr->vnumloctax != NULL) memFree (grafptr->vnumloctax + grafptr->baseval); if (grafptr->vlblloctax != NULL) memFree (grafptr->vlblloctax + grafptr->baseval); } if (grafptr->edgeloctax != NULL) memFree (grafptr->edgeloctax + grafptr->baseval); if ((grafptr->flagval & DGRAPHEDGEGROUP) == 0) { /* If edge arrays not grouped */ if (grafptr->edloloctax != NULL) memFree (grafptr->edloloctax + grafptr->baseval); } } if ((grafptr->flagval & DGRAPHFREEPSID) != 0) { /* If process send arrays must be freed */ if (grafptr->procsidtab != NULL) memFree (grafptr->procsidtab); } if ((grafptr->flagval & DGRAPHFREEEDGEGST) != 0) { /* If ghost array must be freed */ if (grafptr->edgegsttax != NULL) memFree (grafptr->edgegsttax + grafptr->baseval); } } void dgraphFree ( Dgraph * restrict const grafptr) { DgraphFlag flagval; MPI_Comm proccomm; /* Data for temporarily saving private data */ int procglbnbr; int proclocnum; Gnum * restrict proccnttab; /* Some communication arrays are "int" and not "Gnum" because of MPI */ Gnum * restrict procdsptab; Gnum * restrict procvrttab; int * restrict procngbtab; int * restrict procrcvtab; int * restrict procsndtab; dgraphFree2 (grafptr); /* Free all user fields */ flagval = grafptr->flagval & (DGRAPHFREEPRIV | DGRAPHFREECOMM); proccomm = grafptr->proccomm; /* Save private fields only */ procglbnbr = grafptr->procglbnbr; proclocnum = grafptr->proclocnum; proccnttab = grafptr->proccnttab; procdsptab = grafptr->procdsptab; procvrttab = grafptr->procvrttab; procngbtab = grafptr->procngbtab; procrcvtab = grafptr->procrcvtab; procsndtab = grafptr->procsndtab; memSet (grafptr, 0, sizeof (Dgraph)); /* Reset all of the graph structure */ grafptr->flagval = flagval; /* Restore private fields */ grafptr->proccomm = proccomm; grafptr->procglbnbr = procglbnbr; grafptr->proclocnum = proclocnum; grafptr->proccnttab = proccnttab; grafptr->procdsptab = procdsptab; grafptr->procvrttab = procvrttab; grafptr->procngbtab = procngbtab; grafptr->procrcvtab = procrcvtab; grafptr->procsndtab = procsndtab; return; } /* This routine destroys a distributed graph structure. ** It is not a collective routine, as no communication ** is needed to perform the freeing of memory structures. ** Private data are always destroyed. If this is not ** wanted, use dgraphFree() instead. ** It returns: ** - VOID : in all cases. */ void dgraphExit ( Dgraph * restrict const grafptr) { if ((grafptr->flagval & DGRAPHFREEPRIV) != 0) /* If private data has to be freed */ if (grafptr->procdsptab != NULL) memFree (grafptr->procdsptab); /* Free group leader of graph private data */ if ((grafptr->flagval & DGRAPHFREECOMM) != 0) /* If communicator has to be freed */ MPI_Comm_free (&grafptr->proccomm); /* Free it */ dgraphFree2 (grafptr); #ifdef SCOTCH_DEBUG_DGRAPH1 memSet (grafptr, 0, sizeof (Dgraph)); #endif /* SCOTCH_DEBUG_DGRAPH1 */ } scotch-5.1.12b.dfsg/src/libscotch/dgraph_coarsen.c0000644000175300017530000013667011631334325022273 0ustar hazelscthazelsct/* Copyright 2007-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_coarsen.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER (v5.0) **/ /** **/ /** FUNCTION : This file implements the coarsening **/ /** phase of the multi-level method. **/ /** The implementation uses several **/ /** processes, which could have several **/ /** threads each (3 at this time). **/ /** **/ /** DATES : # Version 5.0 : from : 27 jul 2005 **/ /** to : 15 may 2008 **/ /** # Version 5.1 : from : 23 jun 2008 **/ /** to : 20 feb 2011 **/ /** **/ /************************************************************/ #define DGRAPH_COARSEN #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_allreduce.h" #include "dgraph_coarsen.h" #include "dgraph_match.h" /******************************/ /* */ /* Graph coarsening routines. */ /* */ /******************************/ static int dgraphCoarsenInit ( DgraphCoarsenData * restrict const coarptr, /*+ Coarsening data structure +*/ Dgraph * restrict const finegrafptr, /*+ Graph to coarsen +*/ Dgraph * restrict const coargrafptr) /*+ Coarse graph to build +*/ { int procglbnbr; int procglbnum; int procngbnbr; int procngbnum; int procngbnxt; int vertrcvnbr; int vertsndnbr; Gnum vertlocnbr; Gnum vertgstnbr; int vdsprcvnum; int vdspsndnum; byte * bufftab; size_t buffsiz; const int * restrict const fineprocngbtab = finegrafptr->procngbtab; const int * restrict const fineprocrcvtab = finegrafptr->procrcvtab; const int * restrict const fineprocsndtab = finegrafptr->procsndtab; vertlocnbr = finegrafptr->vertlocnbr; vertgstnbr = finegrafptr->vertgstnbr; procglbnbr = finegrafptr->procglbnbr; procngbnbr = finegrafptr->procngbnbr; vertrcvnbr = vertgstnbr - vertlocnbr; vertsndnbr = finegrafptr->procsndnbr; if ((coarptr->coarprivptr = memAllocGroup ((void **) (void *) /* Allocate distributed coarse graph private data */ &coargrafptr->procdsptab, (size_t) ((procglbnbr + 1) * sizeof (Gnum)), &coargrafptr->proccnttab, (size_t) (procglbnbr * sizeof (Gnum)), &coargrafptr->procngbtab, (size_t) (procglbnbr * sizeof (int)), &coargrafptr->procrcvtab, (size_t) (procglbnbr * sizeof (int)), &coargrafptr->procsndtab, (size_t) (procglbnbr * sizeof (int)), NULL)) == NULL) { errorPrint ("dgraphCoarsenInit: out of memory (1)"); return (1); } coargrafptr->procvrttab = coargrafptr->procdsptab; /* Coarse graph has no holes */ if ((coarptr->multloctab = memAlloc (vertlocnbr * sizeof (DgraphCoarsenMulti))) == NULL) { errorPrint ("dgraphCoarsenInit: out of memory (2)"); memFree (coarptr->coarprivptr); return (1); } if (memAllocGroup ((void **) (void *) /* Data used up to edge exchange phase at coarse graph build time */ &coarptr->nrcvidxtab, (size_t) (procngbnbr * sizeof (int)), &coarptr->vrcvdsptab, (size_t) ((procglbnbr + 1) * sizeof (int)), /* TRICK: "+1" for size count */ &coarptr->coargsttax, (size_t) (vertgstnbr * sizeof (Gnum)), &coarptr->procgsttax, (size_t) (vertrcvnbr * sizeof (int)), /* TRICK: Only purely ghost part of array will be used */ &coarptr->vrcvdattab, (size_t) (vertrcvnbr * sizeof (DgraphCoarsenVert)), NULL) == NULL) { errorPrint ("dgraphCoarsenInit: out of memory (3)"); memFree (coarptr->multloctab); memFree (coarptr->coarprivptr); return (1); } buffsiz = 2 * MAX ((procngbnbr * sizeof (MPI_Request)), (procglbnbr * sizeof (int))); if (memAllocGroup ((void **) (void *) /* Data released after coarse vertex index exchange phase */ &coarptr->nsndidxtab, (size_t) (procngbnbr * sizeof (int)), &coarptr->vsnddsptab, (size_t) ((procglbnbr + 1) * sizeof (int)), /* TRICK: "+1" for size count check */ &bufftab, (size_t) buffsiz, &coarptr->dcntloctab, (size_t) (procglbnbr * sizeof (DgraphCoarsenCount)), &coarptr->dcntglbtab, (size_t) (procglbnbr * sizeof (DgraphCoarsenCount)), &coarptr->vsnddattab, (size_t) (vertsndnbr * sizeof (DgraphCoarsenVert)), NULL) == NULL) { errorPrint ("dgraphCoarsenInit: out of memory (4)"); memFree (coarptr->nrcvidxtab); memFree (coarptr->multloctab); memFree (coarptr->coarprivptr); return (1); } coarptr->nrcvreqtab = (MPI_Request *) (void *) bufftab; /* TRICK: point-to-point requests and collective arrays share same space */ coarptr->nsndreqtab = coarptr->nrcvreqtab + procngbnbr; coarptr->vrcvcnttab = (int *) (void *) bufftab; coarptr->vsndcnttab = coarptr->vrcvcnttab + procglbnbr; for (procglbnum = 0, vdsprcvnum = vdspsndnum = 0; /* Build communication index arrays */ procglbnum < procglbnbr; procglbnum ++) { coarptr->vrcvdsptab[procglbnum] = vdsprcvnum; coarptr->vsnddsptab[procglbnum] = vdspsndnum; vdsprcvnum += fineprocrcvtab[procglbnum]; vdspsndnum += fineprocsndtab[procglbnum]; } coarptr->vrcvdsptab[procglbnum] = vdsprcvnum; /* Mark end of communication index arrays */ coarptr->vsnddsptab[procglbnum] = vdspsndnum; for (procngbnum = procngbnxt = 0; procngbnum < procngbnbr; procngbnum ++) { if ((procngbnxt == 0) && (fineprocngbtab[procngbnum] > finegrafptr->proclocnum)) { /* Find index of first neighbor of higher rank */ procngbnxt = procngbnum; break; } } coarptr->procngbnxt = procngbnxt; coarptr->coargsttax -= finegrafptr->baseval; coarptr->finegrafptr = finegrafptr; coarptr->coargrafptr = coargrafptr; memSet (coarptr->dcntloctab, 0, procglbnbr * sizeof (DgraphCoarsenCount)); memSet (coarptr->procgsttax, ~0, vertrcvnbr * sizeof (int)); /* Values have not yet been computed */ coarptr->procgsttax -= vertlocnbr + finegrafptr->baseval; /* TRICK: base array such that only purely ghost part is used */ coarptr->edgekptnbr = 0; return (0); } static void dgraphCoarsenExit ( DgraphCoarsenData * restrict const coarptr) /*+ Coarsening data structure +*/ { if (coarptr->nsndidxtab != NULL) /* Auxiliary array is released after first phase of coarse graph building */ memFree (coarptr->nsndidxtab); memFree (coarptr->nrcvidxtab); if (coarptr->multloctab != NULL) /* If multinode array not passed back to calling routine */ memFree (coarptr->multloctab); if (coarptr->coarprivptr != NULL) /* If ownership of coarse graph private data not yet transferred to it */ memFree (coarptr->coarprivptr); } static int dgraphCoarsenBuildColl ( DgraphCoarsenData * restrict const coarptr) { Gnum vertlocadj; int procngbnbr; int procngbnum; Dgraph * restrict const grafptr = coarptr->finegrafptr; const int * restrict const procngbtab = grafptr->procngbtab; Gnum * restrict const coargsttax = coarptr->coargsttax; int * restrict const vsndcnttab = coarptr->vsndcnttab; int * restrict const vrcvdsptab = coarptr->coargrafptr->procrcvtab; /* TRICK: use coarse graph procrcvtab and procsndtab */ int * restrict const vsnddsptab = coarptr->coargrafptr->procsndtab; int * restrict const nrcvidxtab = coarptr->nrcvidxtab; int * restrict const nsndidxtab = coarptr->nsndidxtab; procngbnbr = grafptr->procngbnbr; vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - grafptr->baseval; memSet (vsndcnttab, 0, grafptr->procglbnbr * sizeof (int)); memSet (vrcvdsptab, 0, grafptr->procglbnbr * sizeof (int)); memSet (vsnddsptab, 0, grafptr->procglbnbr * sizeof (int)); for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) { int procglbnum; procglbnum = procngbtab[procngbnum]; vsndcnttab[procglbnum] = 2 * (nsndidxtab[procngbnum] - coarptr->vsnddsptab[procglbnum]); vrcvdsptab[procglbnum] = 2 * coarptr->vrcvdsptab[procglbnum]; vsnddsptab[procglbnum] = 2 * coarptr->vsnddsptab[procglbnum]; } if (MPI_Alltoall (vsndcnttab, 1, MPI_INT, coarptr->vrcvcnttab, 1, MPI_INT, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCoarsenBuildColl: communication error (1)"); return (1); } if (MPI_Alltoallv (coarptr->vsnddattab, vsndcnttab, vsnddsptab, GNUM_MPI, coarptr->vrcvdattab, coarptr->vrcvcnttab, vrcvdsptab, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCoarsenBuildColl: communication error (2)"); return (1); } for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) { /* For all received data chunks */ int vrcvidxnnd; int vrcvidxnum; int procglbnum; int statsiz; const DgraphCoarsenVert * restrict const vrcvdattab = coarptr->vrcvdattab; /* After data is received */ procglbnum = procngbtab[procngbnum]; statsiz = coarptr->vrcvcnttab[procglbnum]; for (vrcvidxnum = coarptr->vrcvdsptab[procglbnum], vrcvidxnnd = vrcvidxnum + (statsiz / 2); /* TRICK: each message item costs 2 Gnum's */ vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { Gnum vertglbnum; /* Our global number (the one seen as mate by sender) */ Gnum vertlocnum; /* Our local number (the one seen as mate by sender) */ Gnum multglbnum; /* Global number of coarse vertex */ vertglbnum = vrcvdattab[vrcvidxnum].datatab[0]; multglbnum = vrcvdattab[vrcvidxnum].datatab[1]; vertlocnum = vertglbnum - vertlocadj; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((vertlocnum < grafptr->baseval) || /* If matching request is not directed towards our process */ (vertlocnum >= grafptr->vertlocnnd)) { errorPrint ("dgraphCoarsenBuildColl: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ coargsttax[vertlocnum] = multglbnum; } nrcvidxtab[procngbnum] = vrcvidxnnd; /* Keep receive end index for preparing edge arrays */ } return (0); } static int dgraphCoarsenBuildPtop ( DgraphCoarsenData * restrict const coarptr) { Gnum vertlocadj; int procngbnbr; int procngbnum; int vrcvreqnbr; Dgraph * restrict const grafptr = coarptr->finegrafptr; const int * restrict const procngbtab = grafptr->procngbtab; Gnum * restrict const coargsttax = coarptr->coargsttax; const int * restrict const vrcvdsptab = coarptr->vrcvdsptab; const int * restrict const vsnddsptab = coarptr->vsnddsptab; int * restrict const nrcvidxtab = coarptr->nrcvidxtab; int * restrict const nsndidxtab = coarptr->nsndidxtab; procngbnbr = grafptr->procngbnbr; vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - grafptr->baseval; if (procngbnbr > 0) { /* No communication else */ procngbnum = coarptr->procngbnxt; /* Post receives in descending order */ do { int procglbnum; procngbnum = (procngbnum + (procngbnbr - 1)) % procngbnbr; /* Pre-decrement neighbor rank */ procglbnum = procngbtab[procngbnum]; if (MPI_Irecv (coarptr->vrcvdattab + vrcvdsptab[procglbnum], 2 * (vrcvdsptab[procglbnum + 1] - vrcvdsptab[procglbnum]), GNUM_MPI, procglbnum, TAGCOARSEN, grafptr->proccomm, &coarptr->nrcvreqtab[procngbnum]) != MPI_SUCCESS) { errorPrint ("dgraphCoarsenBuildPtop: communication error (1)"); return (1); } } while (procngbnum != coarptr->procngbnxt); procngbnum = coarptr->procngbnxt; /* Post sends in ascending order */ do { int procglbnum; procglbnum = procngbtab[procngbnum]; if (MPI_Isend (coarptr->vsnddattab + vsnddsptab[procglbnum], 2 * (nsndidxtab[procngbnum] - vsnddsptab[procglbnum]), GNUM_MPI, procglbnum, TAGCOARSEN, grafptr->proccomm, &coarptr->nsndreqtab[procngbnum]) != MPI_SUCCESS) { errorPrint ("dgraphCoarsenBuildPtop: communication error (2)"); return (1); } procngbnum = (procngbnum + 1) % procngbnbr; /* Post-increment neighbor rank */ } while (procngbnum != coarptr->procngbnxt); } for (vrcvreqnbr = procngbnbr; vrcvreqnbr > 0; vrcvreqnbr --) { /* For all pending receive requests */ int vrcvidxnnd; int vrcvidxnum; int procngbnum; MPI_Status statdat; int statsiz; int o; #ifdef SCOTCH_DETERMINISTIC procngbnum = vrcvreqnbr - 1; o = MPI_Wait (&coarptr->nrcvreqtab[procngbnum], &statdat); #else /* SCOTCH_DETERMINISTIC */ o = MPI_Waitany (procngbnbr, coarptr->nrcvreqtab, &procngbnum, &statdat); #endif /* SCOTCH_DETERMINISTIC */ if ((o != MPI_SUCCESS) || (MPI_Get_count (&statdat, GNUM_MPI, &statsiz) != MPI_SUCCESS)) { errorPrint ("dgraphCoarsenBuildPtop: communication error (3)"); return (1); } #ifdef SCOTCH_DEBUG_DGRAPH2 if (statdat.MPI_SOURCE != procngbtab[procngbnum]) { errorPrint ("dgraphCoarsenBuildPtop: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ { const DgraphCoarsenVert * restrict const vrcvdattab = coarptr->vrcvdattab; /* After data is received */ for (vrcvidxnum = vrcvdsptab[procngbtab[procngbnum]], vrcvidxnnd = vrcvidxnum + (statsiz / 2); /* TRICK: each message item costs 2 Gnum's */ vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { Gnum vertglbnum; /* Our global number (the one seen as mate by sender) */ Gnum vertlocnum; /* Our local number (the one seen as mate by sender) */ Gnum multglbnum; /* Global number of coarse vertex */ vertglbnum = vrcvdattab[vrcvidxnum].datatab[0]; multglbnum = vrcvdattab[vrcvidxnum].datatab[1]; vertlocnum = vertglbnum - vertlocadj; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((vertlocnum < grafptr->baseval) || /* If matching request is not directed towards our process */ (vertlocnum >= grafptr->vertlocnnd)) { errorPrint ("dgraphCoarsenBuildPtop: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ coargsttax[vertlocnum] = multglbnum; } nrcvidxtab[procngbnum] = vrcvidxnnd; /* Keep receive end index for preparing edge arrays */ } } if (MPI_Waitall (procngbnbr, coarptr->nsndreqtab, MPI_STATUSES_IGNORE) != MPI_SUCCESS) { /* Wait for send requests to complete */ errorPrint ("dgraphCoarsenBuildPtop: communication error (4)"); return (1); } return (0); } /* This routine performs the coarsening of edges ** with respect to the coarmulttax array computed ** by dgraphMatch. All data must be available when ** running (all receptions done). This function is ** inspired by libscotch/src/graph_coarsen_edge.c. */ DGRAPHALLREDUCEMAXSUMOP (3, 1) static int dgraphCoarsenBuild ( DgraphCoarsenData * restrict const coarptr) { Gnum vertlocnum; Gnum vertlocadj; Gnum edgelocnbr; Gnum edlolocval; Gnum * restrict ercvdattab; Gnum * restrict esnddattab; int * restrict ercvcnttab; int * restrict esndcnttab; int * restrict ercvdsptab; int * restrict esnddsptab; int ercvdspval; int esnddspval; int ercvdatsiz; int esnddatsiz; DgraphCoarsenMulti * restrict multloctax; Gnum multlocnum; Gnum multlocadj; int procngbnbr; int procngbnum; int procnum; Gnum coarvertglbnum; Gnum coarvertlocnum; Gnum coarvertlocnnd; Gnum * restrict coarvertloctax; Gnum * restrict coarveloloctax; Gnum coarvelolocsum; Gnum coardegrlocmax; Gnum coaredgelocnum; Gnum * restrict coaredgeloctax; Gnum * restrict coaredloloctax; Gnum coarhashnbr; /* Size of hash table */ Gnum coarhashmsk; /* Mask for access hash table */ DgraphCoarsenHash * restrict coarhashtab; /* Table of edges to other multinodes */ Gnum reduloctab[4]; Gnum reduglbtab[4]; int cheklocval; int chekglbval; #ifdef SCOTCH_DEBUG_DGRAPH2 int * restrict ercvdbgtab; #endif /* SCOTCH_DEBUG_DGRAPH2 */ Dgraph * restrict const grafptr = coarptr->finegrafptr; Dgraph * restrict const coargrafptr = coarptr->coargrafptr; Gnum * restrict const coargsttax = coarptr->coargsttax; const int * restrict const procngbtab = grafptr->procngbtab; const int * restrict const procgsttax = coarptr->procgsttax; const Gnum * restrict const vertloctax = grafptr->vertloctax; const Gnum * restrict const vendloctax = grafptr->vendloctax; const Gnum * restrict const veloloctax = grafptr->veloloctax; const Gnum * restrict const edgeloctax = grafptr->edgeloctax; const Gnum * restrict const edgegsttax = grafptr->edgegsttax; const Gnum * restrict const edloloctax = grafptr->edloloctax; const DgraphCoarsenMulti * restrict const multloctab = coarptr->multloctab; DgraphCoarsenVert * const vrcvdattab = coarptr->vrcvdattab; /* [norestrict:async] */ DgraphCoarsenVert * restrict const vsnddattab = coarptr->vsnddattab; int * restrict const nsndidxtab = coarptr->nsndidxtab; #ifdef SCOTCH_DEBUG_DGRAPH2 memSet (coargsttax + grafptr->baseval, ~0, grafptr->vertgstnbr * sizeof (Gnum)); #endif /* SCOTCH_DEBUG_DGRAPH2 */ procngbnbr = grafptr->procngbnbr; for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) /* Reset indices for sending messages */ nsndidxtab[procngbnum] = coarptr->vsnddsptab[procngbtab[procngbnum]]; vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - grafptr->baseval; multlocadj = coarptr->coargrafptr->procdsptab[grafptr->proclocnum]; for (multlocnum = 0; multlocnum < coarptr->multlocnbr; multlocnum ++) { Gnum vertlocnum0; Gnum vertlocnum1; vertlocnum0 = multloctab[multlocnum].vertglbnum[0] - vertlocadj; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((vertlocnum0 < grafptr->baseval) || (vertlocnum0 >= grafptr->vertlocnnd)) { errorPrint ("dgraphCoarsenBuild: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ coargsttax[vertlocnum0] = multlocnum + multlocadj; vertlocnum1 = multloctab[multlocnum].vertglbnum[1]; if (vertlocnum1 >= 0) { /* If second vertex is local */ vertlocnum1 -= vertlocadj; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((vertlocnum1 < grafptr->baseval) || (vertlocnum1 >= grafptr->vertlocnnd)) { errorPrint ("dgraphCoarsenBuild: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ coargsttax[vertlocnum1] = multlocnum + multlocadj; /* Don't care if single multinode */ } else { Gnum edgelocnum; Gnum vertglbnum1; Gnum vertgstnum1; int coarsndidx; int procngbnum; edgelocnum = -2 - vertlocnum1; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((edgelocnum < grafptr->baseval) || (edgelocnum >= (grafptr->edgelocsiz + grafptr->baseval))) { errorPrint ("dgraphCoarsenBuild: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ vertglbnum1 = edgeloctax[edgelocnum]; vertgstnum1 = edgegsttax[edgelocnum]; procngbnum = procgsttax[vertgstnum1]; /* Find neighbor owner process */ if (procngbnum < 0) { /* If neighbor had not been computed */ errorPrint ("dgraphCoarsenBuild: internal error (4)"); return (1); } coarsndidx = nsndidxtab[procngbnum] ++; /* Get position of message in send array */ #ifdef SCOTCH_DEBUG_DGRAPH2 if (coarsndidx >= coarptr->vsnddsptab[procngbtab[procngbnum] + 1]) { errorPrint ("dgraphCoarsenBuild: internal error (5)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ vsnddattab[coarsndidx].datatab[0] = vertglbnum1; vsnddattab[coarsndidx].datatab[1] = multlocnum + multlocadj; /* Send multinode value */ } } coarptr->multloctab = memRealloc (coarptr->multloctab, coarptr->multlocnbr * sizeof (DgraphCoarsenMulti)); /* In the mean time, resize multinode array */ if ((((grafptr->flagval & DGRAPHCOMMPTOP) != 0) ? dgraphCoarsenBuildPtop : dgraphCoarsenBuildColl) (coarptr) != 0) return (1); #ifdef SCOTCH_DEBUG_DGRAPH2 if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCoarsenBuild: communication error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ ercvcnttab = coarptr->coargrafptr->procrcvtab; /* TRICK: re-use some private coarse graph arrays after vertex exchange phase */ ercvdsptab = coarptr->coargrafptr->procsndtab; for (procnum = 0, ercvdspval = 0; procnum < grafptr->procglbnbr; procnum ++) { /* TRICK: dcntglbtab array no longer needed afterwards; can be freed */ ercvdsptab[procnum] = ercvdspval; ercvcnttab[procnum] = coarptr->dcntglbtab[procnum].vertsndnbr * ((veloloctax != NULL) ? 2 : 1) + coarptr->dcntglbtab[procnum].edgesndnbr * ((edloloctax != NULL) ? 2 : 1); ercvdspval += ercvcnttab[procnum]; } memFree (coarptr->nsndidxtab); /* Free now useless work memory */ coarptr->nsndidxtab = NULL; /* This block won't be reclaimed */ #ifdef SCOTCH_DEBUG_DGRAPH2 for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { if (coargsttax[vertlocnum] < 0) { errorPrint ("dgraphCoarsenBuild: invalid matching"); return (1); } } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (dgraphHaloSync (grafptr, coargsttax + grafptr->baseval, GNUM_MPI) != 0) { errorPrint ("dgraphCoarsenBuild: cannot propagate multinode indices"); return (1); } edgelocnbr = coarptr->edgekptnbr + coarptr->edgercvnbr; /* Upper bound on number of edges */ ercvdatsiz = coarptr->vertrcvnbr + coarptr->edgercvnbr; /* Basic size: degrees plus edge data */ esnddatsiz = coarptr->vertsndnbr + coarptr->edgesndnbr; if (grafptr->veloloctax != NULL) { /* Add vertex loads if necessary */ ercvdatsiz += coarptr->vertrcvnbr; esnddatsiz += coarptr->vertsndnbr; } if (grafptr->edloloctax != NULL) { /* Add edge loads if necessary */ ercvdatsiz += coarptr->edgercvnbr; esnddatsiz += coarptr->edgesndnbr; } #ifdef SCOTCH_DEBUG_DGRAPH2 if (ercvdspval != ercvdatsiz) { errorPrint ("dgraphCoarsenBuild: internal error (6)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ for (coarhashmsk = 31; coarhashmsk < grafptr->degrglbmax; coarhashmsk = coarhashmsk * 2 + 1) ; coarhashmsk = coarhashmsk * 4 + 3; coarhashnbr = coarhashmsk + 1; cheklocval = 0; coargrafptr->flagval = DGRAPHFREETABS | DGRAPHFREEPRIV | DGRAPHVERTGROUP; /* Coarse graph is not yet based */ coarptr->coarprivptr = NULL; /* Transfer ownership of private arrays to coarse graph */ if (memAllocGroup ((void **) (void *) &coargrafptr->vertloctax, (size_t) ((coarptr->multlocnbr + 1) * sizeof (Gnum)), &coargrafptr->veloloctax, (size_t) ( coarptr->multlocnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphCoarsenBuild: out of memory (1)"); cheklocval = 1; } else if ((coargrafptr->edgeloctax = memAlloc (edgelocnbr * sizeof (Gnum))) == NULL) { errorPrint ("dgraphCoarsenBuild: out of memory (2)"); cheklocval = 1; } else if ((coargrafptr->edloloctax = memAlloc (edgelocnbr * sizeof (Gnum))) == NULL) { errorPrint ("dgraphCoarsenBuild: out of memory (3)"); cheklocval = 1; } else if ((coarptr->nsndidxtab = memAllocGroup ((void **) (void *) /* TRICK: allow data array to be released on error */ &esndcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), &esnddsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), &esnddattab, (size_t) (esnddatsiz * sizeof (Gnum)), &ercvdattab, (size_t) (ercvdatsiz * sizeof (Gnum)), #ifdef SCOTCH_DEBUG_DGRAPH2 &ercvdbgtab, (size_t) (grafptr->procglbnbr * sizeof (int)), #endif /* SCOTCH_DEBUG_DGRAPH2 */ &coarhashtab, (size_t) (coarhashnbr * sizeof (DgraphCoarsenHash)), NULL)) == NULL) { errorPrint ("dgraphCoarsenBuild: out of memory (4)"); cheklocval = 1; } #ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication cannot be overlapped by a useful one */ if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCoarsenBuild: communication error (2)"); chekglbval = 1; } #else /* SCOTCH_DEBUG_DGRAPH1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_DGRAPH1 */ if (chekglbval != 0) { dgraphExit (coargrafptr); return (1); } memSet (coarhashtab, ~0, coarhashnbr * sizeof (DgraphCoarsenHash)); coargrafptr->baseval = grafptr->baseval; coargrafptr->vertlocnnd = coargrafptr->baseval + coargrafptr->vertlocnbr; coargrafptr->vertloctax -= coargrafptr->baseval; coargrafptr->vendloctax = coargrafptr->vertloctax + 1; /* Graph is compact */ coargrafptr->veloloctax -= coargrafptr->baseval; coargrafptr->edgeloctax -= coargrafptr->baseval; coargrafptr->edloloctax -= coargrafptr->baseval; coargrafptr->proccomm = grafptr->proccomm; coargrafptr->procglbnbr = grafptr->procglbnbr; coargrafptr->proclocnum = grafptr->proclocnum; for (procngbnum = procnum = 0, esnddspval = 0; procngbnum < procngbnbr; procngbnum ++) { int procglbnum; int vrcvidxnnd; int vrcvidxnum; procglbnum = procngbtab[procngbnum]; while (procnum < procglbnum) { /* Fill empty slots */ esnddsptab[procnum] = esnddspval; esndcnttab[procnum] = 0; procnum ++; } esnddsptab[procnum] = esnddspval; for (vrcvidxnum = coarptr->vrcvdsptab[procglbnum], vrcvidxnnd = coarptr->nrcvidxtab[procngbnum]; /* For all multinode requests received, in order */ vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { Gnum vertlocnum; Gnum edgelocnum; Gnum edgelocnnd; vertlocnum = vrcvdattab[vrcvidxnum].datatab[0] - vertlocadj; edgelocnum = vertloctax[vertlocnum]; edgelocnnd = vendloctax[vertlocnum]; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((esnddspval + ((veloloctax != NULL) ? 2 : 1) + ((edloloctax != NULL) ? 2 : 1) * (edgelocnnd - edgelocnum)) > esnddatsiz) { errorPrint ("dgraphCoarsenBuild: internal error (7)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ esnddattab[esnddspval ++] = (edgelocnnd - edgelocnum); /* Write degree */ if (veloloctax != NULL) esnddattab[esnddspval ++] = veloloctax[vertlocnum]; if (edloloctax != NULL) { for ( ; edgelocnum < edgelocnnd; edgelocnum ++) { esnddattab[esnddspval ++] = coargsttax[edgegsttax[edgelocnum]]; esnddattab[esnddspval ++] = edloloctax[edgelocnum]; } } else { for ( ; edgelocnum < edgelocnnd; edgelocnum ++) esnddattab[esnddspval ++] = coargsttax[edgegsttax[edgelocnum]]; } } esndcnttab[procnum] = esnddspval - esnddsptab[procnum]; procnum ++; } while (procnum < grafptr->procglbnbr) { /* Complete fill-in of empty slots */ esnddsptab[procnum] = esnddspval; esndcnttab[procnum] = 0; procnum ++; } #ifdef SCOTCH_DEBUG_DGRAPH2 if (esnddspval != esnddatsiz) { errorPrint ("dgraphCoarsenBuild: internal error (8)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ while (procnum < grafptr->procglbnbr) { /* Complete edge data send displacement array */ esnddsptab[procnum] = esnddspval; esndcnttab[procnum] = 0; procnum ++; } #ifdef SCOTCH_DEBUG_DGRAPH2 if (MPI_Alltoall (esndcnttab, 1, MPI_INT, ercvdbgtab, 1, MPI_INT, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCoarsenBuild: communication error (3)"); return (1); } for (procnum = 0; procnum < grafptr->procglbnbr; procnum ++) { if (ercvdbgtab[procnum] != ercvcnttab[procnum]) { errorPrint ("dgraphCoarsenBuild: internal error (9)"); return (1); } } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (MPI_Alltoallv (esnddattab, esndcnttab, esnddsptab, GNUM_MPI, ercvdattab, ercvcnttab, ercvdsptab, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCoarsenBuild: communication error (4)"); return (1); } for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) ercvdsptab[procngbnum] = ercvdsptab[procngbtab[procngbnum]]; multloctax = coarptr->multloctab - grafptr->baseval; edlolocval = 1; coarvelolocsum = 0; coardegrlocmax = 0; coarvertloctax = coargrafptr->vertloctax; coarveloloctax = coargrafptr->veloloctax; coaredgeloctax = coargrafptr->edgeloctax; coaredloloctax = coargrafptr->edloloctax; for (coarvertlocnum = coaredgelocnum = grafptr->baseval, coarvertglbnum = multlocadj, coarvertlocnnd = coarvertlocnum + coargrafptr->vertlocnbr; coarvertlocnum < coarvertlocnnd; coarvertlocnum ++, coarvertglbnum ++) { Gnum coarvelolocval; Gnum vertlocnum; int i; coarvertloctax[coarvertlocnum] = coaredgelocnum; i = 0; coarvelolocval = 0; vertlocnum = multloctax[coarvertlocnum].vertglbnum[0] - vertlocadj; while (1) { /* Pseudo-infinite loop on both vertices of the multinode */ Gnum vertglbnum; Gnum edgelocnum; Gnum edgelocnnd; Gnum degrlocval; int procngbnum; int ercvidxnum; coarvelolocval += (veloloctax != NULL) ? veloloctax[vertlocnum] : 1; for (edgelocnum = vertloctax[vertlocnum], edgelocnnd = vendloctax[vertlocnum]; /* Loop on edges of first (and sometimes second) local mate */ edgelocnum < edgelocnnd; edgelocnum ++) { Gnum coarvertglbend; Gnum h; coarvertglbend = coargsttax[edgegsttax[edgelocnum]]; if (coarvertglbend == coarvertglbnum) /* If end of collapsed edge */ continue; if (edloloctax != NULL) edlolocval = edloloctax[edgelocnum]; for (h = (coarvertglbend * COARHASHPRIME) & coarhashmsk; ; h = (h + 1) & coarhashmsk) { if (coarhashtab[h].vertorgnum != coarvertglbnum) { /* If old slot */ coarhashtab[h].vertorgnum = coarvertglbnum; /* Mark it in reference array */ coarhashtab[h].vertendnum = coarvertglbend; coarhashtab[h].edgelocnum = coaredgelocnum; #ifdef SCOTCH_DEBUG_DGRAPH2 if (coaredgelocnum >= (edgelocnbr + coargrafptr->baseval)) { errorPrint ("dgraphCoarsenBuild: internal error (10)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ coaredgeloctax[coaredgelocnum] = coarvertglbend; /* One more edge created */ coaredloloctax[coaredgelocnum] = edlolocval; coaredgelocnum ++; break; /* Give up hashing */ } if (coarhashtab[h].vertendnum == coarvertglbend) { /* If coarse edge already exists */ coaredloloctax[coarhashtab[h].edgelocnum] += edlolocval; break; /* Give up hashing */ } } } if (i ++ > 0) /* If second local vertex has been processed, exit */ break; vertglbnum = multloctax[coarvertlocnum].vertglbnum[1]; if (vertglbnum >= 0) { /* If second multinode vertex is local */ if ((vertglbnum - vertlocadj) == vertlocnum) /* If single multinode */ break; vertlocnum = (vertglbnum - vertlocadj); continue; } edgelocnum = -2 - vertglbnum; multloctax[coarvertlocnum].vertglbnum[1] = edgeloctax[edgelocnum]; /* Set second vertex of multinode */ procngbnum = procgsttax[edgegsttax[edgelocnum]]; ercvidxnum = ercvdsptab[procngbnum]; degrlocval = ercvdattab[ercvidxnum ++]; coarvelolocval += (veloloctax != NULL) ? ercvdattab[ercvidxnum ++] : 1; while (degrlocval -- > 0) { Gnum coarvertglbend; Gnum h; coarvertglbend = ercvdattab[ercvidxnum ++]; if (edloloctax != NULL) edlolocval = ercvdattab[ercvidxnum ++]; if (coarvertglbend == coarvertglbnum) /* If end of collapsed edge */ continue; for (h = (coarvertglbend * COARHASHPRIME) & coarhashmsk; ; h = (h + 1) & coarhashmsk) { if (coarhashtab[h].vertorgnum != coarvertglbnum) { /* If old slot */ coarhashtab[h].vertorgnum = coarvertglbnum; /* Mark it in reference array */ coarhashtab[h].vertendnum = coarvertglbend; coarhashtab[h].edgelocnum = coaredgelocnum; #ifdef SCOTCH_DEBUG_DGRAPH2 if (coaredgelocnum >= (edgelocnbr + coargrafptr->baseval)) { errorPrint ("dgraphCoarsenBuild: internal error (11)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ coaredgeloctax[coaredgelocnum] = coarvertglbend; /* One more edge created */ coaredloloctax[coaredgelocnum] = edlolocval; coaredgelocnum ++; break; /* Give up hashing */ } if (coarhashtab[h].vertendnum == coarvertglbend) { /* If coarse edge already exists */ coargrafptr->edloloctax[coarhashtab[h].edgelocnum] += edlolocval; break; /* Give up hashing */ } } } ercvdsptab[procngbnum] = ercvidxnum; /* Write back updated receive index */ break; /* Exit loop after processing remote mate */ } coarvelolocsum += coarvelolocval; coarveloloctax[coarvertlocnum] = coarvelolocval; if (coardegrlocmax < (coaredgelocnum - coarvertloctax[coarvertlocnum])) coardegrlocmax = (coaredgelocnum - coarvertloctax[coarvertlocnum]); } coarvertloctax[coarvertlocnum] = coaredgelocnum; /* Set end of compact edge array */ coargrafptr->velolocsum = coarvelolocsum; coargrafptr->veloglbsum = grafptr->veloglbsum; coargrafptr->edgelocnbr = coargrafptr->edgelocsiz = coaredgelocnum - coargrafptr->baseval; coargrafptr->edgeloctax = memRealloc (coaredgeloctax + coargrafptr->baseval, coargrafptr->edgelocnbr * sizeof (Gnum)); coargrafptr->edgeloctax -= coargrafptr->baseval; coargrafptr->edloloctax = memRealloc (coaredloloctax + coargrafptr->baseval, coargrafptr->edgelocnbr * sizeof (Gnum)); coargrafptr->edloloctax -= coargrafptr->baseval; reduloctab[0] = coargrafptr->vertlocnbr; /* Get maximum over all processes */ reduloctab[1] = coargrafptr->edgelocnbr; reduloctab[2] = coardegrlocmax; /* Get local maximum degree */ reduloctab[3] = coargrafptr->edgelocnbr; if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 3, 1, coargrafptr->proccomm) != 0) { errorPrint ("dgraphCoarsenBuild: communication error (5)"); return (1); } coargrafptr->vertglbmax = reduglbtab[0]; coargrafptr->edgeglbmax = reduglbtab[1]; coargrafptr->degrglbmax = reduglbtab[2]; /* It is now a real global maximum degree */ coargrafptr->edgeglbnbr = reduglbtab[3]; coargrafptr->edgeglbsmx = coargrafptr->edgeglbmax; return (0); } /***************************/ /* */ /* The coarsening routine. */ /* */ /***************************/ /* This routine coarsens the given fine distributed ** graph, as long as the coarsening ratio remains ** below some threshold value and the coarsened graph ** is not too small. ** It returns: ** - 0 : if the graph has been coarsened. ** - 1 : if the graph could not be coarsened. ** - 2 : on error. */ int dgraphCoarsen ( Dgraph * restrict const finegrafptr, /*+ Graph to coarsen +*/ Dgraph * restrict const coargrafptr, /*+ Coarse graph to build +*/ DgraphCoarsenMulti * restrict * const multlocptr, /*+ Pointer to based multinode table +*/ const Gnum passnbr, /*+ Number of coarsening passes to go +*/ const Gnum coarnbr, /*+ Minimum number of coarse vertices +*/ const int foldval, /*+ Allow fold/dup or fold or no fold +*/ const Gnum dupmax, /*+ Minimum number of vertices to do dup +*/ const double coarrat) /*+ Maximum contraction ratio +*/ { DgraphMatchData matedat; /* Matching state data; includes coarsening handling data */ Gnum vertrcvnbr; /* Overall number of vertices to be received from neighbors */ Gnum edgercvnbr; /* Overall number of edges to be received from neighbors */ Gnum vertsndnbr; /* Overall number of vertices to be sent to neighbors */ Gnum edgesndnbr; /* Overall number of edges to be sent to neighbors */ int cheklocval; int chekglbval; Gnum coarvertmax; DgraphCoarsenMulti * multloctax; Gnum passnum; int procnum; int o; memSet (coargrafptr, 0, sizeof (Dgraph)); /* Preset coarse graph data */ *multlocptr = NULL; /* Assume we will not create any multinode array */ #ifdef SCOTCH_DEBUG_DGRAPH1 if (coarrat < 0.5L) /* If impossible coarsening ratio wanted */ return (1); /* We will never succeed */ #endif /* SCOTCH_DEBUG_DGRAPH1 */ coarvertmax = (Gnum) ((double) finegrafptr->vertglbnbr * coarrat); /* Maximum number of coarse vertices */ if (coarvertmax < coarnbr) /* If there are too few vertices in graph */ return (1); /* It is useless to go any further */ if (dgraphGhst (finegrafptr) != 0) { /* Compute ghost edge array of fine graph if not already present */ errorPrint ("dgraphCoarsen: cannot compute ghost edge array"); return (2); } cheklocval = dgraphCoarsenInit (&matedat.c, finegrafptr, coargrafptr); cheklocval |= dgraphMatchInit (&matedat, 0.5F); #ifdef SCOTCH_DEBUG_DGRAPH1 /* This communication cannot be covered by a useful one */ if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, finegrafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCoarsen: communication error (1)"); return (2); } #else /* SCOTCH_DEBUG_DGRAPH1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_DGRAPH1 */ if (chekglbval != 0) return (2); for (passnum = 0; passnum < passnbr; passnum ++) { dgraphMatchHy (&matedat); if ((((finegrafptr->flagval & DGRAPHCOMMPTOP) != 0) ? dgraphMatchSyncPtop : dgraphMatchSyncColl) (&matedat) != 0) { errorPrint ("dgraphCoarsen: cannot perform matching"); dgraphMatchExit (&matedat); dgraphCoarsenExit (&matedat.c); return (2); } } dgraphMatchLy (&matedat); /* All remaining vertices are matched locally */ #ifdef SCOTCH_DEBUG_DGRAPH2 if (dgraphMatchCheck (&matedat) != 0) { errorPrint ("dgraphCoarsen: invalid matching"); dgraphMatchExit (&matedat); dgraphCoarsenExit (&matedat.c); return (2); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ dgraphMatchExit (&matedat); vertsndnbr = edgesndnbr = 0; for (procnum = 0; procnum < finegrafptr->procglbnbr; procnum ++) { vertsndnbr += matedat.c.dcntloctab[procnum].vertsndnbr; edgesndnbr += matedat.c.dcntloctab[procnum].edgesndnbr; matedat.c.dcntloctab[procnum].vertlocnbr = matedat.c.multlocnbr; } matedat.c.vertsndnbr = vertsndnbr; matedat.c.edgesndnbr = edgesndnbr; if (MPI_Alltoall (matedat.c.dcntloctab, 3, GNUM_MPI, matedat.c.dcntglbtab, 3, GNUM_MPI, finegrafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCoarsen: communication error (2)"); return (2); } vertrcvnbr = edgercvnbr = 0; coargrafptr->procdsptab[0] = finegrafptr->baseval; /* Build vertex-to-process array */ for (procnum = 0; procnum < finegrafptr->procglbnbr; procnum ++) { Gnum proccntval; vertrcvnbr += matedat.c.dcntglbtab[procnum].vertsndnbr; edgercvnbr += matedat.c.dcntglbtab[procnum].edgesndnbr; proccntval = matedat.c.dcntglbtab[procnum].vertlocnbr; coargrafptr->proccnttab[procnum] = proccntval; coargrafptr->procdsptab[procnum + 1] = coargrafptr->procdsptab[procnum] + proccntval; } coargrafptr->vertlocnbr = matedat.c.multlocnbr; coargrafptr->vertglbnbr = coargrafptr->procdsptab[finegrafptr->procglbnbr] - finegrafptr->baseval; matedat.c.vertrcvnbr = vertrcvnbr; matedat.c.edgercvnbr = edgercvnbr; if (coargrafptr->vertglbnbr > coarvertmax) { /* If coarsening ratio not met */ dgraphCoarsenExit (&matedat.c); return (1); } if (dgraphCoarsenBuild (&matedat.c) != 0) { /* Build coarse graph */ dgraphCoarsenExit (&matedat.c); return (2); } #ifdef SCOTCH_DEBUG_DGRAPH2 if (dgraphCheck (coargrafptr) != 0) { /* Check graph consistency */ errorPrint ("dgraphCoarsen: inconsistent graph data"); dgraphFree (coargrafptr); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ o = 0; /* Assume everything is now all right */ multloctax = matedat.c.multloctab - finegrafptr->baseval; matedat.c.multloctab = NULL; /* So that it will not be freed */ dgraphCoarsenExit (&matedat.c); #ifdef PTSCOTCH_FOLD_DUP if ((coargrafptr->procglbnbr >= 2) && ((foldval != 0) || (dupmax > (coargrafptr->vertglbnbr / coargrafptr->procglbnbr)))) { Dgraph coargrafdat; /* Coarse graph data before folding */ MPI_Datatype coarmultype; DgraphCoarsenMulti * coarmultptr; MPI_Type_contiguous (2, GNUM_MPI, &coarmultype); /* Define type for MPI transfer */ MPI_Type_commit (&coarmultype); /* Commit new type */ coargrafdat = *coargrafptr; /* Copy unfolded coarse graph data to save array */ coarmultptr = multloctax; if ((foldval < 0) || (dupmax < coargrafdat.vertglbnbr)) { /* Do a simple folding */ memSet (coargrafptr, 0, sizeof (Dgraph)); /* Also reset procglbnbr for unused processes */ o = dgraphFold (&coargrafdat, 0, coargrafptr, (void *) coarmultptr, (void **) (void *) &multloctax, coarmultype); } else { /* Do a duplicant-folding */ int loopval; int dumyval; o = dgraphFoldDup (&coargrafdat, coargrafptr, (void *) coarmultptr, (void **) (void *) &multloctax, coarmultype); loopval = intRandVal (finegrafptr->proclocnum + intRandVal (finegrafptr->proclocnum * 2 + 1) + 1); while (loopval --) /* Desynchronize pseudo-random generator between processes */ dumyval = intRandVal (2); } dgraphExit (&coargrafdat); /* Free unfolded graph */ MPI_Type_free (&coarmultype); memFree (coarmultptr + finegrafptr->baseval); /* TRICK: use preserved baseval */ } #endif /* PTSCOTCH_FOLD_DUP */ *multlocptr = multloctax; return (o); } scotch-5.1.12b.dfsg/src/libscotch/bdgraph_gather_all.c0000644000175300017530000002605211631334325023075 0ustar hazelscthazelsct/* Copyright 2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_gather_all.c **/ /** **/ /** AUTHORS : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the routine which **/ /** builds a centralized Bgraph on all **/ /** processors by gathering the pieces of **/ /** a distributed Bdgraph. **/ /** **/ /** DATES : # Version 5.1 : from : 21 dec 2007 **/ /** to 14 apr 2011 **/ /** **/ /** NOTES : # The definitions of MPI_Gather and **/ /** MPI_Gatherv indicate that elements in **/ /** the receive array should not be **/ /** written more than once. Great care **/ /** should be taken to enforce this rule, **/ /** especially when the number of **/ /** vertices in the centralized graph is **/ /** smaller than the number of **/ /** processors. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #include "module.h" #include "common.h" #include "comm.h" #include "arch.h" #include "graph.h" #include "bgraph.h" #include "dgraph.h" #include "bdgraph.h" /* This function gathers on all processors ** the pieces of a distributed Bdgraph to ** build a centralized Bgraph. ** It returns: ** - 0 : if graph data are consistent. ** - !0 : on error. */ int bdgraphGatherAll ( const Bdgraph * restrict const dgrfptr, /* Distributed graph */ Bgraph * restrict cgrfptr) /* Centralized graph */ { int * restrict froncnttab; /* Count array for gather operations */ int * restrict fronvrttab; /* Displacement array for gather operations */ int fronlocnbr; /* Also int to enforce MPI standard */ int cheklocval; #ifdef SCOTCH_DEBUG_BDGRAPH1 int chekglbval; #endif /* SCOTCH_DEBUG_BDGRAPH1 */ int procnum; cheklocval = 0; #ifdef SCOTCH_DEBUG_BDGRAPH1 if (cgrfptr == NULL) /* Centralized graphs should be provided by all */ cheklocval = 1; if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphGatherAll: communication error (1)"); return (1); } if (chekglbval != 0) { errorPrint ("bdgraphGatherAll: centralized graphs should be provided on every process"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH1 */ if (dgraphGatherAll (&dgrfptr->s, &cgrfptr->s) != 0) { errorPrint ("bdgraphGatherAll: cannot build centralized graph"); return (1); } cgrfptr->s.flagval |= BGRAPHFREEFRON | BGRAPHFREEPART | BGRAPHFREEVEEX; cgrfptr->veextax = NULL; /* In case of error */ cgrfptr->parttax = NULL; cgrfptr->frontab = NULL; if ((cgrfptr->frontab = (Gnum *) memAlloc (cgrfptr->s.vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("bdgraphGatherAll: out of memory (1)"); #ifndef SCOTCH_DEBUG_BDGRAPH1 bgraphExit (cgrfptr); return (1); #else /* SCOTCH_DEBUG_BDGRAPH1 */ cheklocval = 1; #endif /* SCOTCH_DEBUG_BDGRAPH1 */ } else if ((cgrfptr->parttax = (GraphPart *) memAlloc (cgrfptr->s.vertnbr * sizeof (GraphPart))) == NULL) { errorPrint ("bdgraphGatherAll: out of memory (2)"); #ifndef SCOTCH_DEBUG_BDGRAPH1 bgraphExit (cgrfptr); return (1); #else /* SCOTCH_DEBUG_BDGRAPH1 */ cheklocval = 1; #endif /* SCOTCH_DEBUG_BDGRAPH1 */ } else { cgrfptr->parttax -= cgrfptr->s.baseval; if (dgrfptr->veexloctax != NULL) { if ((cgrfptr->veextax = (Gnum *) memAlloc (cgrfptr->s.vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("bdgraphGatherAll: out of memory (3)"); #ifndef SCOTCH_DEBUG_BDGRAPH1 bgraphExit (cgrfptr); return (1); #else /* SCOTCH_DEBUG_BDGRAPH1 */ cheklocval = 1; #endif /* SCOTCH_DEBUG_BDGRAPH1 */ } else cgrfptr->veextax -= cgrfptr->s.baseval; } } #ifdef SCOTCH_DEBUG_BDGRAPH1 if (cheklocval == 0) { #endif /* SCOTCH_DEBUG_BDGRAPH1 */ if (memAllocGroup ((void **) (void *) /* Allocate tempory arrays to gather frontiers */ &froncnttab, (size_t) (dgrfptr->s.procglbnbr * sizeof (int)), &fronvrttab, (size_t) (dgrfptr->s.procglbnbr * sizeof (int)), NULL) == NULL) { errorPrint ("bdgraphGatherAll: out of memory (4)"); #ifndef SCOTCH_DEBUG_BDGRAPH1 bgraphExit (cgrfptr); return (1); } #else /* SCOTCH_DEBUG_BDGRAPH1 */ cheklocval = 1; } } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphGatherAll: communication error (2)"); return (1); } if (chekglbval != 0) { if (froncnttab != NULL) memFree (froncnttab); /* Free group leader */ bgraphExit (cgrfptr); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH1 */ cgrfptr->compload0min = dgrfptr->compglbload0min; /* Set constant fields of the centralized graph as those of the distibuted graph */ cgrfptr->compload0max = dgrfptr->compglbload0max; cgrfptr->compload0avg = dgrfptr->compglbload0avg; cgrfptr->commloadextn0 = dgrfptr->commglbloadextn0; cgrfptr->commgainextn0 = dgrfptr->commglbgainextn0; cgrfptr->domdist = dgrfptr->domdist; cgrfptr->domwght[0] = dgrfptr->domwght[0]; cgrfptr->domwght[1] = dgrfptr->domwght[1]; cgrfptr->levlnum = dgrfptr->levlnum; if (dgrfptr->partgsttax == NULL) { /* If distributed graph does not have a part array yet */ bgraphZero (cgrfptr); memFree (froncnttab); /* Free group leader */ return (0); } if (commAllgatherv (dgrfptr->partgsttax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GRAPHPART_MPI, /* Get parttax of distributed graph */ cgrfptr->parttax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GRAPHPART_MPI, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphGatherAll: communication error (4)"); return (1); } if (dgrfptr->veexloctax != NULL) { if (commAllgatherv (dgrfptr->veexloctax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GNUM_MPI, /* Get veextax of distributed graph */ cgrfptr->veextax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GNUM_MPI, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphGatherAll: communication error (5)"); return (1); } } fronlocnbr = (int) dgrfptr->fronlocnbr; if (MPI_Allgather (&fronlocnbr, 1, MPI_INT, /* Compute how frontiers are distributed */ froncnttab, 1, MPI_INT, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphGatherAll: communication error (6)"); return (1); } fronvrttab[0] = 0; /* Offset 0 for first process */ for (procnum = 1; procnum < dgrfptr->s.procglbnbr; procnum ++) /* Adjust index sub-arrays for all processors except the first one */ fronvrttab[procnum] = fronvrttab[procnum - 1] + froncnttab[procnum - 1]; if (MPI_Allgatherv (dgrfptr->fronloctab, (int) dgrfptr->fronlocnbr, GNUM_MPI, /* Gather frontiers */ cgrfptr->frontab, froncnttab, fronvrttab, GNUM_MPI, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphGatherAll: communication error (7)"); return (1); } for (procnum = 1; procnum < dgrfptr->s.procglbnbr; procnum ++) { /* Adjust index sub-arrays for all processors except the first one */ Gnum vertnum; Gnum vertnnd; for (vertnum = (Gnum) fronvrttab[procnum], vertnnd = (Gnum) fronvrttab[procnum] + (Gnum) froncnttab[procnum]; vertnum < vertnnd; vertnum ++) cgrfptr->frontab[vertnum] += (Gnum) dgrfptr->s.procdsptab[procnum] - dgrfptr->s.baseval; } memFree (froncnttab); /* Free group leader */ for (procnum = 0; procnum < dgrfptr->s.proclocnum; procnum ++) /* Desynchronize random generators across processes */ cheklocval = intRandVal (2); intPerm (cgrfptr->frontab, dgrfptr->fronglbnbr); /* Compute permutation of frontier array to have different solutions on every process */ cgrfptr->compload0 = dgrfptr->compglbload0; /* Update other fields */ cgrfptr->compload0dlt = dgrfptr->compglbload0dlt; cgrfptr->compsize0 = dgrfptr->compglbsize0; cgrfptr->commload = dgrfptr->commglbload; cgrfptr->commgainextn = dgrfptr->commglbgainextn; cgrfptr->commgainextn0 = dgrfptr->commglbgainextn0; cgrfptr->fronnbr = dgrfptr->fronglbnbr; #ifdef SCOTCH_DEBUG_BDGRAPH2 if (bgraphCheck (cgrfptr) != 0) { errorPrint ("bdgraphGatherAll: internal error"); bgraphExit (cgrfptr); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_gather.c0000644000175300017530000001171111631334325023623 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_gather.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted source graph handling routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 12 jul 2007 **/ /** to 17 jul 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "graph.h" #include "dgraph.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the graph handling routines. */ /* */ /************************************/ /*+ This routine gathers the data of a *** distributed graph on a centralized graph. *** It returns: *** - 0 : if the centralization succeeded. *** - !0 : on error. +*/ int SCOTCH_dgraphGather ( const SCOTCH_Dgraph * const dgrfptr, SCOTCH_Graph * const cgrfptr) { Dgraph * restrict srcdgrfptr; Gnum reduloctab[3]; Gnum reduglbtab[3]; srcdgrfptr = (Dgraph *) dgrfptr; if ((cgrfptr != NULL) && (((void *) cgrfptr) != ((void *) dgrfptr))) { /* If centralized graph provided */ reduloctab[0] = 1; /* Process is a potential root */ reduloctab[1] = (Gnum) srcdgrfptr->proclocnum; } else { /* Process is not a root */ reduloctab[0] = 0; reduloctab[1] = 0; } if (srcdgrfptr->edloloctax == NULL) /* Compute sum of edge loads for access to low-level routines */ reduloctab[2] = srcdgrfptr->edgelocnbr; else { Gnum vertlocnum; Gnum edlolocsum; for (vertlocnum = srcdgrfptr->baseval, edlolocsum = 0; vertlocnum < srcdgrfptr->vertlocnnd; vertlocnum ++) { Gnum edgelocnum; Gnum edgelocnnd; for (edgelocnum = srcdgrfptr->vertloctax[vertlocnum], edgelocnnd = srcdgrfptr->vendloctax[vertlocnum]; edgelocnum < edgelocnnd; edgelocnum ++) edlolocsum += srcdgrfptr->edloloctax[edgelocnum]; } reduloctab[2] = edlolocsum; } if (MPI_Allreduce (reduloctab, reduglbtab, 3, GNUM_MPI, MPI_SUM, srcdgrfptr->proccomm) != MPI_SUCCESS) { errorPrint ("SCOTCH_dgraphGather: communication error"); return (1); } if (reduglbtab[0] == 1) /* If only one single root */ return (dgraphGatherAll2 (srcdgrfptr, (Graph *) cgrfptr, reduglbtab[2], (int) reduglbtab[1])); else if (reduglbtab[0] == srcdgrfptr->procglbnbr) /* If all processes are roots */ return (dgraphGatherAll2 (srcdgrfptr, (Graph *) cgrfptr, reduglbtab[2], -1)); errorPrint ("SCOTCH_dgraphGather: invalid number of roots"); return (1); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_mesh.c0000644000175300017530000001536311631334325021427 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_mesh.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the mesh un- **/ /** haloing routine. **/ /** **/ /** DATES : # Version 4.0 : from : 28 apr 2004 **/ /** to 11 may 2004 **/ /** **/ /** NOTES : # From a given halo mesh is created a **/ /** non-halo mesh. When nodes are **/ /** numbered after elements, halo nodes **/ /** are simply removed. When nodes are **/ /** numbered before elements, halo nodes **/ /** are turned into empty elements such **/ /** that the numbering of vertices **/ /** remains continuous, without holes. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH_MESH #include "module.h" #include "common.h" #include "graph.h" #include "hgraph.h" #include "mesh.h" #include "hmesh.h" /***************************************/ /* */ /* The non-halo mesh building routine. */ /* */ /***************************************/ /* This routine builds a non-halo mesh from ** the given halo mesh. ** It returns: ** - 0 : if the non-halo mesh has been successfully built. ** - 1 : on error. */ int hmeshMesh ( const Hmesh * restrict const hmshptr, /*+ Original halo mesh +*/ Mesh * restrict const meshptr) /*+ Mesh to build +*/ { meshptr->baseval = hmshptr->m.baseval; meshptr->veisnbr = hmshptr->m.veisnbr + hmshptr->veihnbr; /* Add halo isolated elements to isolated elements */ meshptr->vnodnbr = hmshptr->vnohnbr; meshptr->vnodbas = hmshptr->m.vnodbas; meshptr->vnodnnd = hmshptr->vnohnbr + hmshptr->m.vnodbas; meshptr->verttax = hmshptr->m.verttax; meshptr->velotax = hmshptr->m.velotax; meshptr->vnlotax = hmshptr->m.vnlotax; /* Use non-halo part of node vertex load array, if any */ meshptr->velosum = hmshptr->m.velosum; meshptr->vnlosum = hmshptr->vnhlsum; meshptr->vnumtax = hmshptr->m.vnumtax; /* The same for vnumtab */ meshptr->vlbltax = NULL; meshptr->edgenbr = hmshptr->enohnbr; meshptr->edgetax = hmshptr->m.edgetax; meshptr->degrmax = hmshptr->m.degrmax; if (hmshptr->vnohnbr == hmshptr->m.vnodnbr) { /* If halo mesh does not have any halo */ meshptr->flagval = MESHNONE; /* Just create a clone of the original mesh */ meshptr->velmnbr = hmshptr->m.velmnbr; meshptr->velmbas = hmshptr->m.velmbas; meshptr->velmnnd = hmshptr->m.velmnnd; meshptr->vendtax = hmshptr->m.vendtax; return (0); } meshptr->flagval = MESHFREEVEND; if (hmshptr->m.velmbas <= hmshptr->m.vnodbas) { /* If elements numbered before nodes */ if ((meshptr->vendtax = memAlloc ((hmshptr->m.velmnbr + hmshptr->vnohnbr) * sizeof (Gnum))) == NULL) { /* Do not keep halo nodes at end of array */ errorPrint ("hmeshHgraph: out of memory (1)"); return (1); } memCpy (meshptr->vendtax, hmshptr->vehdtax + hmshptr->m.velmbas, hmshptr->m.velmnbr * sizeof (Gnum)); memCpy (meshptr->vendtax + hmshptr->m.velmnbr, hmshptr->m.vendtax + hmshptr->m.vnodbas, hmshptr->vnohnbr * sizeof (Gnum)); meshptr->velmnbr = hmshptr->m.velmnbr; meshptr->velmbas = hmshptr->m.velmbas; meshptr->velmnnd = hmshptr->m.velmnnd; } else { /* If nodes numbered before elements */ if ((meshptr->vendtax = memAlloc ((hmshptr->m.velmnbr + hmshptr->m.vnodnbr) * sizeof (Gnum))) == NULL) { /* Turn halo nodes into empty elements */ errorPrint ("hmeshHgraph: out of memory (2)"); return (1); } memCpy (meshptr->vendtax, hmshptr->m.vendtax + hmshptr->m.baseval, hmshptr->vnohnbr * sizeof (Gnum)); /* Copy non-halo node part */ memCpy (meshptr->vendtax + hmshptr->vnohnbr, hmshptr->m.verttax + hmshptr->vnohnnd, hmshptr->m.vnodnbr - hmshptr->vnohnbr * sizeof (Gnum)); /* Create empty fake element part */ memCpy (meshptr->vendtax + hmshptr->m.vnodnbr, hmshptr->vehdtax + hmshptr->m.velmbas, hmshptr->m.velmnbr * sizeof (Gnum)); meshptr->velmnbr = hmshptr->m.velmnbr + hmshptr->m.vnodnbr - hmshptr->vnohnbr; /* Turn halo node vertices into element vertices */ meshptr->velmbas = hmshptr->vnohnnd; meshptr->velmnnd = hmshptr->m.velmnnd; } meshptr->vendtax -= meshptr->baseval; #ifdef SCOTCH_DEBUG_HMESH2 if (meshCheck (meshptr) != 0) { errorPrint ("hmeshMesh: internal error"); return (1); } #endif /* SCOTCH_DEBUG_HMESH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/bgraph_check.c0000644000175300017530000001711011631334325021677 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_check.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the bipartition **/ /** graph consistency checking routine. **/ /** **/ /** DATES : # Version 4.0 : from : 08 jan 2004 **/ /** to 07 dec 2005 **/ /** # Version 5.1 : from : 04 oct 2009 **/ /** to 04 oct 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BGRAPH #include "module.h" #include "common.h" #include "graph.h" #include "arch.h" #include "bgraph.h" /*************************/ /* */ /* These routines handle */ /* bipartition graphs. */ /* */ /*************************/ /* This routine checks the consistency ** of the given bipartition graph. ** It returns: ** - 0 : if graph data are consistent. ** - !0 : on error. */ int bgraphCheck ( const Bgraph * restrict const grafptr) { int * restrict flagtax; /* Frontier flag array */ Gnum vertnum; /* Number of current vertex */ Gnum fronnum; /* Number of frontier vertex */ Gnum compload[2]; Gnum compsize[2]; Gnum commcut[2]; Gnum commloadintn; Gnum commloadextn; Gnum commgainextn; Gnum edloval; const Gnum * restrict const verttax = grafptr->s.verttax; const Gnum * restrict const vendtax = grafptr->s.vendtax; const Gnum * restrict const velotax = grafptr->s.velotax; const Gnum * restrict const edgetax = grafptr->s.edgetax; const Gnum * restrict const edlotax = grafptr->s.edlotax; const GraphPart * restrict const parttax = grafptr->parttax; if ((flagtax = memAlloc (grafptr->s.vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("bgraphCheck: out of memory"); return (1); } memSet (flagtax, ~0, grafptr->s.vertnbr * sizeof (Gnum)); flagtax -= grafptr->s.baseval; if (grafptr->compload0 != (grafptr->compload0avg + grafptr->compload0dlt)) { errorPrint ("bgraphCheck: invalid balance"); return (1); } for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { if ((parttax[vertnum] < 0) || (parttax[vertnum] > 1)) { errorPrint ("bgraphCheck: invalid part array"); return (1); } } if ((grafptr->fronnbr < 0) || (grafptr->fronnbr > grafptr->s.vertnbr)) { errorPrint ("bgraphCheck: invalid number of frontier vertices"); return (1); } for (fronnum = 0; fronnum < grafptr->fronnbr; fronnum ++) { Gnum vertnum; Gnum edgenum; GraphPart partval; GraphPart flagval; vertnum = grafptr->frontab[fronnum]; if ((vertnum < grafptr->s.baseval) || (vertnum >= grafptr->s.vertnnd)) { errorPrint ("bgraphCheck: invalid vertex index in frontier array"); return (1); } if (flagtax[vertnum] != ~0) { errorPrint ("bgraphCheck: duplicate vertex in frontier array"); return (1); } flagtax[vertnum] = 0; partval = parttax[vertnum]; for (edgenum = verttax[vertnum], flagval = 0; edgenum < vendtax[vertnum]; edgenum ++) flagval |= parttax[edgetax[edgenum]] ^ partval; /* Flag set if neighbor part differs from vertex part */ if (flagval == 0) { errorPrint ("bgraphCheck: invalid vertex in frontier array"); return (1); } } compload[0] = compload[1] = 0; compsize[0] = compsize[1] = 0; commloadintn = 0; commloadextn = grafptr->commloadextn0; commgainextn = 0; edloval = 1; /* Assume edges are not weighted */ for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { Gnum partval; /* Part of current vertex */ Gnum edgenum; /* Number of current edge */ partval = (Gnum) parttax[vertnum]; if (grafptr->veextax != NULL) { Gnum veexval; veexval = grafptr->veextax[vertnum]; commloadextn += veexval * partval; commgainextn += veexval * (1 - 2 * partval); } compload[partval] += (velotax == NULL) ? 1 : velotax[vertnum]; compsize[partval] ++; commcut[0] = commcut[1] = 0; for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { int partend; int partdlt; if (edlotax != NULL) edloval = edlotax[edgenum]; partend = parttax[edgetax[edgenum]]; partdlt = partval ^ partend; commcut[partend] ++; commloadintn += partdlt * edloval * partend; /* Only count loads once, when (partend == 1) */ } if ((commcut[0] != 0) && (commcut[1] != 0) && /* If vertex should be in frontier array */ (flagtax[vertnum] != 0)) { errorPrint ("bgraphCheck: vertex should be in frontier array"); return (1); } } if (compsize[0] != grafptr->compsize0) { errorPrint ("bgraphCheck: invalid part size"); return (1); } if ((commloadintn * grafptr->domdist + commloadextn) != grafptr->commload) { errorPrint ("bgraphCheck: invalid communication loads"); return (1); } if (commgainextn != grafptr->commgainextn) { errorPrint ("bgraphCheck: invalid communication gains"); return (1); } memFree (flagtax + grafptr->s.baseval); return (0); } scotch-5.1.12b.dfsg/src/libscotch/mesh_coarsen.c0000644000175300017530000007771511631334325021766 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mesh_coarsen.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the source mesh **/ /** coarsening functions. **/ /** **/ /** DATES : # Version 4.0 : from : 30 jan 2004 **/ /** to 05 may 2004 **/ /** # Version 5.0 : from : 12 sep 2007 **/ /** to 12 sep 2007 **/ /** **/ /** NOTES : # The coarsening process is as follows. **/ /** First, node collapsing is performed, **/ /** such that pairs of matching nodes are **/ /** created, or kept as single nodes. **/ /** Then, elements are built, and merged **/ /** whenever possible. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MESH_COARSEN #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" #include "mesh_coarsen.h" /* ** The static variables. */ static void (* meshCoarFuncTab[MESHCOARSENNBR]) () = { /* Tables of matching routines */ meshCoarsenMatchNg }; /***************************/ /* */ /* The coarsening routine. */ /* */ /***************************/ /* This routine coarsens the given "finemesh" into ** "coarmesh", as long as the coarsening ratio remains ** below some threshold value and the coarsened mesh ** is not too small. ** It returns: ** - 0 : if the mesh has been coarsened. ** - 1 : if the mesh could not be coarsened. ** - 2 : on error. */ int meshCoarsen ( const Mesh * restrict const finemeshptr, /*+ Mesh to coarsen +*/ Mesh * restrict const coarmeshptr, /*+ Coarse mesh to build +*/ Gnum * restrict * const finecoarptr, /*+ Pointer to multinode data +*/ const Gnum coarnbr, /*+ Minimum number of coarse nodes +*/ const double coarrat, /*+ Maximum contraction ratio +*/ const MeshCoarsenType coartype) /*+ Matching type +*/ { Gnum coarhashsiz; /* Size of the hash table */ Gnum coarhashmsk; /* Mask for access to hash table */ MeshCoarsenHngb * restrict coarhngbtab; /* Table of edges to other multinodes */ MeshCoarsenHbdg * restrict coarhbdgtab; /* Table of bridge nodes to other multinodes */ Gnum * restrict coarverttax; /* Pointer to coarse vertex array */ Gnum * restrict coarvelotax; /* Pointer to coarse vertex load array */ Gnum * restrict coaredgetax; /* Pointer to coarse edge array */ Gnum coaredgenbr; /* (Upper bound of) number of edges in mesh */ Gnum coaredgenum; /* Number of current coarse edge */ Gnum coarvertnbr; /* Number of vertices in coarse mesh */ Gnum coarvelmnbr; /* Number of coarse element vertices */ Gnum coarvnodnbr; /* Number of coarse node vertices */ Gnum finevertnbr; /* Number of vertices in fine graph */ Gnum * restrict finecoartax; /* Based access to finecoartab */ Gnum coarvelmnum; /* Number of currently selected coarse element */ Gnum coareelmnum; Gnum coarvnodnum; Gnum coardegrmax; MeshCoarsenMult * restrict finemulttax; Gnum coaredgetmp; size_t coarvelooftval; size_t coaredgeoftval; #ifdef SCOTCH_DEBUG_MESH2 if (coartype >= MESHCOARSENNBR) { errorPrint ("meshCoarsen: invalid parameter"); return (2); } #endif /* SCOTCH_DEBUG_MESH2 */ memSet (coarmeshptr, 0, sizeof (Mesh)); /* Initialize coarse mesh */ coarmeshptr->flagval = GRAPHFREEVERT; coarmeshptr->baseval = finemeshptr->baseval; finevertnbr = finemeshptr->velmnbr + finemeshptr->vnodnbr; if ((finecoartax = (Gnum *) memAlloc (finevertnbr * sizeof (Gnum))) == NULL) { errorPrint ("meshCoarsen: out of memory (1)"); /* Allocate coarse mesh uncoarsening array */ return (2); } memSet (finecoartax, ~0, finevertnbr * sizeof (Gnum)); finecoartax -= finemeshptr->baseval; /* Set based access to finecoartax */ for (coarhashmsk = 31, coarhashsiz = finemeshptr->degrmax * finemeshptr->degrmax - 1; /* Compute size of hash table */ coarhashmsk < coarhashsiz; coarhashmsk = coarhashmsk * 2 + 1) ; coarhashsiz = coarhashmsk + 1; if (memAllocGroup ((void **) (void *) &coarverttax, (size_t) ((finevertnbr + 1) * sizeof (Gnum)), /* Upper bound on number of coarse vertices */ &coarvelotax, (size_t) ( finevertnbr * sizeof (Gnum)), /* Upper bound on number of coarse vertices */ &coaredgetax, (size_t) ( finemeshptr->edgenbr * sizeof (Gnum)), &coarhngbtab, (size_t) ( coarhashsiz * sizeof (MeshCoarsenHngb)), &coarhbdgtab, (size_t) ( coarhashsiz * sizeof (MeshCoarsenHbdg)), &finemulttax, (size_t) ( finemeshptr->velmnbr * sizeof (MeshCoarsenMult)), NULL) == NULL) { errorPrint ("meshCoarsen: out of memory (2)"); /* Allocate coarser mesh structure */ memFree (finecoartax + finemeshptr->baseval); return (2); } memSet (coarhngbtab, ~0, coarhashsiz * sizeof (MeshCoarsenHngb)); memSet (coarhbdgtab, ~0, coarhashsiz * sizeof (MeshCoarsenHbdg)); finemulttax -= coarmeshptr->baseval; #define SCOTCH_DEBUG_MESH3 #ifdef SCOTCH_DEBUG_MESH3 fprintf (stderr, "-------- ENTERING COARSENING ---------\n"); fprintf (stderr, "finenodenbr=%ld, fineelemnbr=%ld, fineedgenbr=%ld, finedegrmax=%ld\n", (long) finemeshptr->vnodnbr, (long) finemeshptr->velmnbr, (long) finemeshptr->edgenbr, (long) finemeshptr->degrmax); #endif /* SCOTCH_DEBUG_MESH3 */ meshCoarFuncTab[coartype] (finemeshptr, finemulttax, finecoartax, &coarvelmnbr, &coarvnodnbr, &coaredgenbr); /* Call proper matching function */ #ifndef DEAD_CODE coarvnodnbr = finemeshptr->vnodnbr; /* TODO : coarvnodnbr estimator is wrong : too tight */ coaredgenbr = finemeshptr->edgenbr; #endif /* DEAD_CODE */ coarvertnbr = coarvelmnbr + coarvnodnbr; memOffset ((void *) coarverttax, &coarverttax, (size_t) ((coarvertnbr + 1) * sizeof (Gnum)), &coarvelotax, (size_t) ( coarvertnbr * sizeof (Gnum)), &coaredgetax, (size_t) ( coaredgenbr * sizeof (Gnum)), NULL); /* Hast tables and finemulttax stay in place */ coarverttax -= coarmeshptr->baseval; coarvelotax -= coarmeshptr->baseval; coaredgetax -= coarmeshptr->baseval; coarmeshptr->velmbas = coarmeshptr->baseval; coarmeshptr->velmnbr = coarvelmnbr; coarmeshptr->velmnnd = coarmeshptr->vnodbas = coarvelmnbr + coarmeshptr->velmbas; for (coarvelmnum = coaredgenum = coarmeshptr->baseval, coarvnodnum = coarmeshptr->vnodbas, coardegrmax = 0; /* For all coarse elements */ coarvelmnum < coarmeshptr->velmnnd; coarvelmnum ++) { Gnum coarveloval; /* Weight of coarsened element */ Gnum coarvnisnum; /* Number of coarse isolated node */ Gnum finevelmnum; /* Number of current element */ int i; coarverttax[coarvelmnum] = coaredgenum; coarvnisnum = ~0; /* No isolated node yet for this element pair */ coarveloval = 0; i = 0; do { /* For both elements of element pair (if they are different) */ Gnum fineeelmnum; finevelmnum = finemulttax[coarvelmnum].finevelmnum[i]; /* Get number of current element */ coarveloval += ((finemeshptr->velotax != NULL) ? finemeshptr->velotax[finevelmnum] : 1); for (fineeelmnum = finemeshptr->verttax[finevelmnum]; fineeelmnum < finemeshptr->vendtax[finevelmnum]; fineeelmnum ++) { Gnum finevnodnum; /* Number of current node neighbor */ Gnum fineenodnum; Gnum finevdegval; Gnum finevnloval; Gnum finevelmend; Gnum coarvnodtmp; Gnum coarhnodtmp; finevnodnum = finemeshptr->edgetax[fineeelmnum]; fineenodnum = finemeshptr->verttax[finevnodnum]; finevdegval = finemeshptr->vendtax[finevnodnum] - fineenodnum; finevnloval = (finemeshptr->vnlotax != NULL) ? finemeshptr->vnlotax[finevnodnum] : 1; if ((finevdegval == 2) && /* If node is an external bridge to another coarse element */ ((finevelmend = (finemeshptr->edgetax[fineenodnum] + finemeshptr->edgetax[fineenodnum + 1] - finevelmnum)) != finemulttax[coarvelmnum].finevelmnum[1 - i])) { Gnum coarvelmend; Gnum coarhelmend; coarvelmend = finecoartax[finevelmend]; /* Get coarse index of end element */ coarvnodtmp = finecoartax[finevnodnum]; /* Get coarse number of fine node */ for (coarhelmend = (coarvelmend * MESHCOARSENHASHPRIME) & coarhashmsk; ; coarhelmend = (coarhelmend + 1) & coarhashmsk) { if (coarhbdgtab[coarhelmend].coarvelmnum != coarvelmnum) { /* If bridge not yet considered */ coarhbdgtab[coarhelmend].coarvelmnum = coarvelmnum; /* Add it to element neighbor list */ coarhbdgtab[coarhelmend].coarvelmend = coarvelmend; if (coarvnodtmp == -1) { /* If bridge nodes not considered before by other element */ coarhbdgtab[coarhelmend].coarvnodnum = /* Assign it */ finecoartax[finevnodnum] = coarvnodtmp = coarvnodnum ++; coarverttax[coarvnodtmp] = 2; /* Prepare the fact that another element will see the node */ coarvelotax[coarvnodtmp] = finevnloval; } coaredgetax[coaredgenum ++] = coarvnodtmp; /* Directly add coarse node to element neighborhood */ break; } if (coarhbdgtab[coarhelmend].coarvelmend == coarvelmend) { /* If bridge already present */ if (coarvnodtmp == -1) { /* If we are the first element to see the bridge node */ finecoartax[finevnodnum] = coarvnodtmp = coarhbdgtab[coarhelmend].coarvnodnum; /* Assign it */ coarvelotax[coarvnodtmp] += finevnloval; /* Update the weight of the node */ } /* Else node already processed with full load, so nothing to do */ break; } } continue; /* Edge has been added or will not be */ } else if (finevdegval < 3) { /* Else if node is isolated or is an internal bridge */ if ((finevdegval == 2) && /* Process bridge edges only once */ (finevelmnum >= finemulttax[coarvelmnum].finevelmnum[1 - i])) continue; if (coarvnisnum == ~0) { /* If no isolated node for this element pair */ coarvnisnum = coarvnodnum ++; /* Create isolated node */ coarverttax[coarvnisnum] = 1; coarvelotax[coarvnisnum] = finevnloval; coaredgetax[coaredgenum ++] = coarvnisnum; } else /* If isolated node already exists */ coarvelotax[coarvnisnum] += finevnloval; /* Add node contribution to it */ finecoartax[finevnodnum] = coarvnisnum; /* Map fine node to isolated node */ continue; } else { coarvnodtmp = finecoartax[finevnodnum]; /* Get coarse number of fine node */ if (coarvnodtmp == ~0) { /* If coarse number not yet assigned */ finecoartax[finevnodnum] = coarvnodtmp = coarvnodnum ++; /* Assign it */ coarverttax[coarvnodtmp] = 0; /* No connections to the node yet */ coarvelotax[coarvnodtmp] = finevnloval; } } for (coarhnodtmp = (coarvnodtmp * MESHCOARSENHASHPRIME) & coarhashmsk; ; coarhnodtmp = (coarhnodtmp + 1) & coarhashmsk) { if (coarhngbtab[coarhnodtmp].coarvelmnum != coarvelmnum) { /* If node neighbor not yet considered */ coarhngbtab[coarhnodtmp].coarvelmnum = coarvelmnum; /* Add it to element neighbor list */ coarhngbtab[coarhnodtmp].coarvnodnum = coarvnodtmp; coaredgetax[coaredgenum ++] = coarvnodtmp; coarverttax[coarvnodtmp] ++; /* One more edge referencing the node */ break; } if (coarhngbtab[coarhnodtmp].coarvnodnum == coarvnodtmp) /* If node already present, nothing to do */ break; } } } while (i ++, finevelmnum != finemulttax[coarvelmnum].finevelmnum[1]); coarvelotax[coarvelmnum] = coarveloval; /* Lose initial weights of elements, if any, to keep coarsening weights */ if ((coaredgenum - coarverttax[coarvelmnum]) > coardegrmax) coardegrmax = (coaredgenum - coarverttax[coarvelmnum]); } coarmeshptr->vnodnnd = coarvnodnum; coarmeshptr->vnodnbr = coarvnodnum - coarmeshptr->vnodbas; coarmeshptr->velosum = finemeshptr->velosum; coarmeshptr->vnlosum = finemeshptr->vnlosum; coarmeshptr->edgenbr = 2 * (coaredgenum - coarmeshptr->baseval); for (coarvnodnum = coarmeshptr->vnodbas, coaredgetmp = coaredgenum; /* Build start indices for node edge sub-arrays */ coarvnodnum < coarmeshptr->vnodnnd; coarvnodnum ++) { Gnum coardegrval; coardegrval = coarverttax[coarvnodnum]; coarverttax[coarvnodnum] = coaredgetmp; coaredgetmp += coardegrval; if (coardegrval > coardegrmax) coardegrmax = coardegrval; } coarmeshptr->degrmax = coardegrmax; for (coarvelmnum = coareelmnum = coarmeshptr->baseval; coarvelmnum < coarmeshptr->velmnnd; coarvelmnum ++) { Gnum coareelmnnd; coareelmnnd = (coarvelmnum < (coarmeshptr->velmnnd - 1)) ? coarverttax[coarvelmnum + 1] : coaredgenum; while (coareelmnum < coareelmnnd) { Gnum coarvnodnum; coarvnodnum = coaredgetax[coareelmnum ++]; coaredgetax[coarverttax[coarvnodnum] ++] = coarvelmnum; } } memMov (&coarverttax[coarmeshptr->vnodbas + 1], /* Re-build start indices for node edge sub-arrays */ &coarverttax[coarmeshptr->vnodbas], coarmeshptr->vnodnbr * sizeof (Gnum)); coarverttax[coarmeshptr->vnodbas] = coaredgenum; coarvelooftval = coarvelotax - coarverttax; coaredgeoftval = coaredgetax - coarverttax; coarverttax = memRealloc (coarverttax + coarmeshptr->baseval, (coaredgeoftval + coarmeshptr->edgenbr) * sizeof (Gnum)); /* Re-allocate array to save space */ coarmeshptr->verttax = coarverttax - coarmeshptr->baseval; coarmeshptr->vendtax = coarmeshptr->verttax + 1; coarmeshptr->velotax = coarmeshptr->verttax + coarvelooftval; coarmeshptr->vnlotax = coarmeshptr->velotax; /* Same array for both vertex load sub-arrays */ coarmeshptr->edgetax = coarmeshptr->verttax + coaredgeoftval; #ifdef SCOTCH_DEBUG_MESH2 if (meshCheck (coarmeshptr) != 0) { /* Check mesh consistency */ errorPrint ("meshCoarsen: internal error (7)"); return (2); } #endif /* SCOTCH_DEBUG_MESH2 */ *finecoarptr = finecoartax; /* Return multinode array */ #ifdef SCOTCH_DEBUG_MESH3 fprintf (stderr, "coarvnodnbr=%ld\tcoarvelmnbr=%ld\tcoaredgenbr=%ld, coardegrmax=%ld\n", (long) coarmeshptr->vnodnbr, (long) coarmeshptr->velmnbr, (long) coarmeshptr->edgenbr, (long) coarmeshptr->degrmax); fprintf (stderr, "-------- EXITING COARSENING ---------\n"); /* TODO REMOVE */ #endif /* SCOTCH_DEBUG_MESH3 */ return (0); } /********************************************/ /* */ /* The matching subroutines. In fact, these */ /* are merging routines, which merge */ /* elements of the fine mesh to form larger */ /* elements in the coarse mesh. */ /* New elements are ordered in increasing */ /* order from baseval, while nodes are */ /* ordered in decreasing order from -2, as */ /* -1 is a reserved flag value used */ /* for labelling non yet considered */ /* vertices. */ /* */ /********************************************/ /* This routine performs elements matching by ** selecting the elements that share most nodes ** with the first element. */ static void meshCoarsenMatchNg ( const Mesh * restrict const finemeshptr, /* Fine mesh to perform matching on */ MeshCoarsenMult * restrict const finemulttax, /* Array of fine multielements */ Gnum * restrict const finecoartax, /* Fine to coarse vertex array */ Gnum * restrict const coarvelmptr, /* Pointer to number of coarse element vertices */ Gnum * restrict const coarvnodptr, /* Pointer to (upper bound on) number of coarse node vertices */ Gnum * restrict const coaredgeptr) /* Pointer to (upper bound on) number of edges */ { Gnum coarvelmnum; /* Number of current coarse element vertex */ Gnum finepertbas; /* Index of base of perturbation area */ Gnum finepertnbr; /* Size of perturbation area */ MeshCoarsenNgHash * restrict finehashtab; /* Hash table of neighbor elements */ Gnum finehashsiz; Gnum finehashmsk; Gnum coarvnodnbr; Gnum coaredgenbr; for (finehashmsk = 31, finehashsiz = finemeshptr->degrmax * finemeshptr->degrmax - 1; /* Compute size of hash table */ finehashmsk < finehashsiz; finehashmsk = finehashmsk * 2 + 1) ; finehashsiz = finehashmsk + 1; if ((finehashtab = (MeshCoarsenNgHash *) memAlloc (finehashsiz * sizeof (MeshCoarsenNgHash))) == NULL) { *coarvelmptr = finemeshptr->velmnbr; /* Indicate no coarsening occured */ return; } memSet (finehashtab, ~0, finehashsiz * sizeof (MeshCoarsenNgHash)); finehashmsk = finehashsiz - 1; coarvelmnum = finemeshptr->baseval; /* Start numbering elements in ascending order */ coarvnodnbr = finemeshptr->vnodnbr; coaredgenbr = finemeshptr->edgenbr; if (finemeshptr->velotax != NULL) { /* If fine mesh has element coarsening vertex weights, perform first pass */ Gnum finevelomin; Gnum finevelomax; Gnum finevelmnum; finevelomin = (3 * finemeshptr->velosum) / (5 * finemeshptr->velmnbr); finevelomax = (5 * finemeshptr->velosum) / finemeshptr->velmnbr; for (finevelmnum = finemeshptr->velmbas; finevelmnum < finemeshptr->velmnnd; finevelmnum ++) { Gnum fineeelmnum; Gnum finehelmnum; Gnum finevnisnbr; /* Number of isolated node vertices */ Gnum finehebsnum; /* Hash number of best matching element */ Gnum finevebsnum; /* Number of best matching element */ Gnum finevnbsnbr; /* Number of nodes shared with best element */ if (finecoartax[finevelmnum] != ~0) /* If element already selected */ continue; if (finemeshptr->velotax[finevelmnum] >= finevelomin) { /* If element is large enough, leave it for the second pass */ if (finemeshptr->velotax[finevelmnum] > finevelomax) { /* Except if it is too large, as then it is not matched */ finecoartax[finevelmnum] = coarvelmnum; finemulttax[coarvelmnum].finevelmnum[0] = finemulttax[coarvelmnum].finevelmnum[1] = finevelmnum; fprintf (stderr, "++ %ld %ld\n", (long) finevelmnum, (long) finemeshptr->velotax[finevelmnum]); /* TODO REMOVE */ coarvelmnum ++; /* One more single vertex created */ } continue; } finecoartax[finevelmnum] = coarvelmnum; /* Set vertex as used so that it will not be considered as an end vertex */ finehelmnum = (finevelmnum * MESHCOARSENHASHPRIME) & finehashmsk; finehashtab[finehelmnum].velmnum = finevelmnum; /* Put element in hash table so that number of end vertex is right even for uncoarsened elements */ finehashtab[finehelmnum].velmend = finevelmnum; finehebsnum = finehelmnum; /* Mate is element itself */ finevnbsnbr = 0; /* Will never be selected */ finevnisnbr = 0; /* No isolated node vertices yet */ for (fineeelmnum = finemeshptr->verttax[finevelmnum]; /* For all node neighbors of current element */ fineeelmnum < finemeshptr->vendtax[finevelmnum]; fineeelmnum ++) { Gnum finevnodnum; Gnum fineenodnum; Gnum fineenodnnd; Gnum finevdegval; Gnum finevnbgval; finevnodnum = finemeshptr->edgetax[fineeelmnum]; fineenodnum = finemeshptr->verttax[finevnodnum]; fineenodnnd = finemeshptr->vendtax[finevnodnum]; finevdegval = fineenodnnd - fineenodnum; if (finevdegval == 1) { /* If node is isolated */ finevnisnbr ++; continue; /* Directly skip to next node */ } finevnbgval = (finevdegval == 2) ? 1 : 0; /* If node is a bridge which connects the element to only one other element */ for ( ; fineenodnum < fineenodnnd; fineenodnum ++) { /* For all elements which are neighbors of current node */ Gnum finevelmend; Gnum finehelmend; Gnum finevnngnbr; /* Current number of neigoboring nodes that connect the two elements */ finevelmend = finemeshptr->edgetax[fineenodnum]; if (finecoartax[finevelmend] != ~0) /* If end element vertex already matched, do not consider it */ continue; for (finehelmend = (finevelmend * MESHCOARSENHASHPRIME) & finehashmsk; ; finehelmend = (finehelmend + 1) & finehashmsk) { if (finehashtab[finehelmend].velmnum != finevelmnum) { /* If element neighbor not yet considered */ finevnngnbr = 1; finehashtab[finehelmend].velmnum = finevelmnum; finehashtab[finehelmend].velmend = finevelmend; finehashtab[finehelmend].vnngnbr = finevnngnbr; finehashtab[finehelmend].vnbgnbr = finevnbgval; } else if (finehashtab[finehelmend].velmend == finevelmend) { /* Else if element found */ finevnngnbr = ++ finehashtab[finehelmend].vnngnbr; finehashtab[finehelmend].vnbgnbr += finevnbgval; } else /* Else go on searching */ continue; if (finevnngnbr > finevnbsnbr) { finehebsnum = finehelmend; finevnbsnbr = finevnngnbr; } break; } } } finevebsnum = finehashtab[finehebsnum].velmend; finemulttax[coarvelmnum].finevelmnum[0] = finevelmnum; /* Set matching pair */ finemulttax[coarvelmnum].finevelmnum[1] = finevebsnum; if (finevelmnum != finevebsnum) { /* If a matching element has been found */ finecoartax[finevebsnum] = coarvelmnum; if (finevnisnbr > 0) finevnisnbr --; coarvnodnbr -= finehashtab[finehebsnum].vnbgnbr + finevnisnbr; coaredgenbr -= 2 * finevnisnbr + 4 * finehashtab[finehebsnum].vnbgnbr; } coarvelmnum ++; /* Number nodes in ascending order */ } } for (finepertbas = finemeshptr->velmbas, /* Run cache-friendly perturbation on elements */ finepertnbr = 2 + intRandVal (MESHCOARSENPERTPRIME - 2); /* Compute perturbation area size */ finepertbas < finemeshptr->velmnnd; finepertbas += finepertnbr) { Gnum finepertval; /* Current index in perturbation area */ if (finepertbas + finepertnbr > finemeshptr->velmnnd) finepertnbr = finemeshptr->velmnnd - finepertbas; finepertval = 0; /* Start from first perturbation element vertex */ do { /* Loop on perturbation element vertices */ Gnum finevelmnum; /* Number of currently selected fine element vertex */ Gnum fineeelmnum; Gnum finehelmnum; Gnum finevnisnbr; /* Number of isolated node vertices */ Gnum finehebsnum; /* Hash number of best matching element */ Gnum finevebsnum; /* Number of best matching element */ Gnum finevnbsnbr; /* Number of nodes shared with best element */ finevelmnum = finepertbas + finepertval; /* Compute corresponding elemennt number */ if (finecoartax[finevelmnum] != ~0) /* If element already selected */ continue; finecoartax[finevelmnum] = coarvelmnum; /* Set vertex as used so that it will not be considered as an end vertex */ finehelmnum = (finevelmnum * MESHCOARSENHASHPRIME) & finehashmsk; finehashtab[finehelmnum].velmnum = finevelmnum; /* Put element in hash table so that number of end vertex is right even for uncoarsened elements */ finehashtab[finehelmnum].velmend = finevelmnum; finehebsnum = finehelmnum; /* Mate is element itself */ finevnbsnbr = 0; /* Will never be selected */ finevnisnbr = 0; /* No isolated node vertices yet */ for (fineeelmnum = finemeshptr->verttax[finevelmnum]; /* For all node neighbors of current element */ fineeelmnum < finemeshptr->vendtax[finevelmnum]; fineeelmnum ++) { Gnum finevnodnum; Gnum fineenodnum; Gnum fineenodnnd; Gnum finevdegval; Gnum finevnbgval; finevnodnum = finemeshptr->edgetax[fineeelmnum]; fineenodnum = finemeshptr->verttax[finevnodnum]; fineenodnnd = finemeshptr->vendtax[finevnodnum]; finevdegval = fineenodnnd - fineenodnum; if (finevdegval == 1) { /* If node is isolated */ finevnisnbr ++; continue; /* Directly skip to next node */ } finevnbgval = (finevdegval == 2) ? 1 : 0; /* If node is a bridge which connects the element to only one other element */ for ( ; fineenodnum < fineenodnnd; fineenodnum ++) { /* For all elements which are neighbors of current node */ Gnum finevelmend; Gnum finehelmend; Gnum finevnngnbr; /* Current number of neigoboring nodes that connect the two elements */ finevelmend = finemeshptr->edgetax[fineenodnum]; if (finecoartax[finevelmend] != ~0) /* If end element vertex already matched, do not consider it */ continue; for (finehelmend = (finevelmend * MESHCOARSENHASHPRIME) & finehashmsk; ; finehelmend = (finehelmend + 1) & finehashmsk) { if (finehashtab[finehelmend].velmnum != finevelmnum) { /* If element neighbor not yet considered */ finevnngnbr = 1; finehashtab[finehelmend].velmnum = finevelmnum; finehashtab[finehelmend].velmend = finevelmend; finehashtab[finehelmend].vnngnbr = finevnngnbr; finehashtab[finehelmend].vnbgnbr = finevnbgval; } else if (finehashtab[finehelmend].velmend == finevelmend) { /* Else if element found */ finevnngnbr = ++ finehashtab[finehelmend].vnngnbr; finehashtab[finehelmend].vnbgnbr += finevnbgval; } else /* Else go on searching */ continue; if (finevnngnbr > finevnbsnbr) { finehebsnum = finehelmend; finevnbsnbr = finevnngnbr; } break; } } } finevebsnum = finehashtab[finehebsnum].velmend; finemulttax[coarvelmnum].finevelmnum[0] = finevelmnum; /* Set matching pair */ finemulttax[coarvelmnum].finevelmnum[1] = finevebsnum; if (finevelmnum != finevebsnum) { /* If a matching element has been found */ finecoartax[finevebsnum] = coarvelmnum; if (finevnisnbr > 0) finevnisnbr --; coarvnodnbr -= finehashtab[finehebsnum].vnbgnbr + finevnisnbr; coaredgenbr -= 2 * finevnisnbr + 4 * finehashtab[finehebsnum].vnbgnbr; } coarvelmnum ++; /* Number nodes in ascending order */ } while ((finepertval = (finepertval + MESHCOARSENPERTPRIME) % finepertnbr) != 0); /* Compute next perturbation index */ } memFree (finehashtab); *coarvelmptr = coarvelmnum - finemeshptr->velmbas; *coarvnodptr = coarvnodnbr; *coaredgeptr = coaredgenbr; return; } scotch-5.1.12b.dfsg/src/libscotch/graph_coarsen.h0000644000175300017530000001413311631334325022121 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_coarsen.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the source graph coarsening **/ /** functions. **/ /** **/ /** DATES : # Version 0.0 : from : 02 dec 1992 **/ /** to 18 may 1993 **/ /** # Version 1.3 : from : 30 apr 1994 **/ /** to 18 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 18 aug 1994 **/ /** # Version 3.0 : from : 07 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 28 nov 1995 **/ /** to 28 nov 1995 **/ /** # Version 3.2 : from : 07 sep 1996 **/ /** to 17 sep 1998 **/ /** # Version 4.0 : from : 13 dec 2001 **/ /** to 05 dec 2004 **/ /** **/ /************************************************************/ /* ** The defines. */ /** Prime number for cache-friendly perturbations. **/ #define GRAPHCOARPERTPRIME 179 /* Prime number */ /** Prime number for hashing vertex numbers. **/ #define GRAPHCOARHASHPRIME 1049 /* Prime number */ /* ** The type and structure definitions. */ /*+ Here are the edge matching function types for coarsening. +*/ typedef enum GraphCoarsenType_ { GRAPHCOARHEM, /*+ Heavy-edge matching +*/ GRAPHCOARSCN, /*+ Scanning (first) matching +*/ GRAPHCOARCSC, /*+ Crystal scanning matching +*/ GRAPHCOARCHE, /*+ Crystal heavy-edge matching +*/ GRAPHCOARNBR /*+ Number of matching types +*/ } GraphCoarsenType; /*+ The multinode table element, which contains pairs of based indices of collapsed vertices. Both values are equal for uncollapsed vertices. As the base values of the fine and coarse graphs may be different, the values of the collapsed vertices are set with respect to the base value of the fine graph. +*/ typedef struct GraphCoarsenMulti_ { Gnum vertnum[2]; /*+ Numbers of the collapsed vertices of a multinode +*/ } GraphCoarsenMulti; /*+ A table made of such elements is used during coarsening to build the edge array of the new graph, after the labeling of the vertices. +*/ typedef struct GraphCoarsenHash_ { Gnum vertorgnum; /*+ Origin vertex (i.e. pass) number +*/ Gnum vertendnum; /*+ Other end vertex number +*/ Gnum edgenum; /*+ Number of corresponding edge +*/ } GraphCoarsenHash; /* ** The function prototypes. */ #ifndef GRAPH_COARSEN #define static #endif int graphCoarsen (const Graph * restrict const, Graph * restrict const, GraphCoarsenMulti * restrict * const, const Gnum, const double, const GraphCoarsenType); static void graphCoarsenEdgeLl (const Graph * const, const Gnum * const, const GraphCoarsenMulti * restrict const, Graph * const, GraphCoarsenHash * const, const Gnum); static void graphCoarsenEdgeLu (const Graph * const, const Gnum * const, const GraphCoarsenMulti * restrict const, Graph * const, GraphCoarsenHash * const, const Gnum); static Gnum graphCoarsenMatchHy (const Graph * const, Gnum *, const Gnum, const Gnum); static Gnum graphCoarsenMatchSc (const Graph * const, Gnum *, const Gnum, const Gnum); static Gnum graphCoarsenMatchCs (const Graph * const, Gnum *, const Gnum, const Gnum); static Gnum graphCoarsenMatchCh (const Graph * const, Gnum *, const Gnum, const Gnum); #undef static scotch-5.1.12b.dfsg/src/libscotch/vdgraph.h0000644000175300017530000001270611631334325020745 0ustar hazelscthazelsct/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for distributed vertex separation **/ /** routines. **/ /** **/ /** DATES : # Version 5.0 : from : 06 feb 2006 **/ /** to : 29 apr 2006 **/ /** # Version 5.1 : from : 07 nov 2007 **/ /** to : 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ Active graph structure. +*/ typedef struct Vdgraph_ { Dgraph s; /*+ Source distributed graph +*/ GraphPart * partgsttax; /*+ Based local part array: 0,1: part; 2: separator +*/ Gnum compglbloaddlt; /*+ Load difference between both parts +*/ Gnum compglbload[3]; /*+ Global loads of both parts and of separator; TRICK: before compglbsize[] +*/ Gnum compglbsize[3]; /*+ Number of vertices in parts; compglbsize[2] is fronglbnbr, the separator +*/ Gnum complocload[3]; /*+ Local loads of both parts and of separator; TRICK: before complocsize[] +*/ Gnum complocsize[3]; /*+ Number of vertices in parts; complocsize[2] is fronlocnbr, the separator +*/ Gnum * fronloctab; /*+ Array of local frontier vertex numbers +*/ Gnum levlnum; /*+ Nested dissection or coarsening level +*/ } Vdgraph; /*+ The graph separator storing structure. +*/ typedef struct VdgraphStore_ { Gnum fronglbnbr; /*+ Number of frontier nodes +*/ Gnum compglbloaddlt; /*+ Difference from the average +*/ Gnum compglbload[2]; /*+ Load in both parts +*/ Gnum compglbsize0; /*+ Number of vertices in part 0 +*/ Gnum complocsize0; /*+ Number of vertices in parts +*/ Gnum fronlocnbr; /*+ Number of local frontier vertices +*/ byte * datatab; /*+ Variable-sized data array +*/ } VdgraphStore; /* ** The function prototypes. */ #ifndef VDGRAPH #define static #endif int vdgraphInit (Vdgraph * restrict const, MPI_Comm); void vdgraphExit (Vdgraph * const); void vdgraphZero (Vdgraph * const); int vdgraphCheck (const Vdgraph * const); #ifdef VGRAPH_H int vdgraphGatherAll (const Vdgraph * restrict const, Vgraph * restrict); #endif /* VGRAPH_H */ int vdgraphStoreInit (const Vdgraph * const, VdgraphStore * const); void vdgraphStoreExit (VdgraphStore * const); void vdgraphStoreSave (const Vdgraph * const , VdgraphStore * const); void vdgraphStoreUpdt (Vdgraph * const, const VdgraphStore * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/kgraph_map_rb_part.h0000644000175300017530000000660011631334325023130 0ustar hazelscthazelsct/* Copyright 2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kgraph_map_rb_part.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the Dual Recursive Bipartitioning **/ /** mapping algorithm. **/ /** **/ /** DATES : # Version 5.1 : from : 22 sep 2008 **/ /** to 14 apr 2011 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the data passed to each bipartitioning job. +*/ typedef struct KgraphMapRbPartData_ { const Graph * topgrafptr; /*+ Pointer to top-level graph +*/ Gnum * topfrontab; /*+ Pointer to top-level frontier array +*/ Gnum topfronnbr; /*+ Current number of frontier vertices +*/ Mapping * mappptr; const KgraphMapRbParam * paraptr; double comploadmin; /*+ Minimum vertex load per target load +*/ double comploadmax; /*+ Maximum vertex load per target load +*/ } KgraphMapRbPartData; /* ** The function prototypes. */ #ifndef KGRAPH_MAP_RB_PART #define static #endif int kgraphMapRbPart (Kgraph * const, const KgraphMapRbParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/vmesh_separate_gr.c0000644000175300017530000001421411631334325022777 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh_separate_gr.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module separates a node separation **/ /** mesh by turning the mesh into a graph **/ /** and using a graph separation strategy. **/ /** **/ /** DATES : # Version 4.0 : from : 13 oct 2003 **/ /** to 13 oct 2003 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VMESH_SEPARATE_GR #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "vgraph.h" #include "vgraph_separate_st.h" #include "mesh.h" #include "vmesh.h" #include "vmesh_separate_gr.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the bipartitioning. ** It returns: ** - 0 : if the bipartitioning could be computed. ** - !0 : on error. */ int vmeshSeparateGr ( Vmesh * restrict const meshptr, /*+ Node separation mesh +*/ const VmeshSeparateGrParam * restrict const paraptr) /*+ Method parameters +*/ { Vgraph grafdat; Gnum fronnum; Gnum velmnum; Gnum ecmpsize1; graphInit (&grafdat.s); if (meshGraph (&meshptr->m, &grafdat.s) != 0) { errorPrint ("vmeshSeparateGr: cannot build graph"); return (1); } grafdat.parttax = meshptr->parttax + (meshptr->m.vnodbas - grafdat.s.baseval); /* Get node area of part array */ grafdat.compload[0] = meshptr->ncmpload[0]; grafdat.compload[1] = meshptr->ncmpload[1]; grafdat.compload[2] = meshptr->ncmpload[2]; grafdat.comploaddlt = meshptr->ncmploaddlt; grafdat.compsize[0] = meshptr->ncmpsize[0]; grafdat.compsize[1] = meshptr->ncmpsize[1]; grafdat.fronnbr = meshptr->fronnbr; grafdat.frontab = meshptr->frontab; /* Re-use frontier array */ grafdat.levlnum = meshptr->levlnum; for (fronnum = 0; fronnum < grafdat.fronnbr; fronnum ++) grafdat.frontab[fronnum] -= (meshptr->m.vnodbas - grafdat.s.baseval); #ifdef SCOTCH_DEBUG_VMESH2 if (vgraphCheck (&grafdat) != 0) { errorPrint ("vmeshSeparateGr: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ if (vgraphSeparateSt (&grafdat, paraptr->stratptr) != 0) { errorPrint ("vmeshSeparateGr: cannot separate graph"); return (1); } for (fronnum = 0; fronnum < grafdat.fronnbr; fronnum ++) /* Restore mesh-based frontier array */ grafdat.frontab[fronnum] += (meshptr->m.vnodbas - grafdat.s.baseval); meshptr->ncmpload[0] = grafdat.compload[0]; meshptr->ncmpload[1] = grafdat.compload[1]; meshptr->ncmpload[2] = grafdat.compload[2]; meshptr->ncmploaddlt = grafdat.comploaddlt; meshptr->ncmpsize[0] = grafdat.compsize[0]; meshptr->ncmpsize[1] = grafdat.compsize[1]; meshptr->fronnbr = grafdat.fronnbr; for (velmnum = meshptr->m.velmbas, ecmpsize1 = 0; velmnum < meshptr->m.velmnnd; velmnum ++) { /* Compute part of all elements */ Gnum eelmnum; GraphPart partval; partval = 0; /* Empty elements move to part 0 */ for (eelmnum = meshptr->m.verttax[velmnum]; eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { Gnum vnodnum; vnodnum = meshptr->m.edgetax[eelmnum]; partval = meshptr->parttax[vnodnum]; if (partval != 2) break; } partval &= 1; /* In case all nodes in separator */ ecmpsize1 += (Gnum) partval; /* Count elements in part 1 */ meshptr->parttax[velmnum] = partval; /* Set part of element */ } meshptr->ecmpsize[0] = meshptr->m.velmnbr - ecmpsize1; meshptr->ecmpsize[1] = ecmpsize1; #ifdef SCOTCH_DEBUG_VMESH2 if (vmeshCheck (meshptr) != 0) { errorPrint ("vmeshSeparateGr: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/vdgraph_separate_sq.c0000644000175300017530000002637511631334325023336 0ustar hazelscthazelsct/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_separate_sq.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module computes a separator of the **/ /** given distributed separator graph by **/ /** moving all (interesting) vertices of **/ /** the given graph to every processor, **/ /** running a sequential vertex separation **/ /** computing, and projecting back the **/ /** best result obtained. **/ /** **/ /** DATES : # Version 5.1 : from : 15 feb 2006 **/ /** to 30 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VDGRAPH_SEPARATE_SQ #include "module.h" #include "common.h" #include "comm.h" #include "parser.h" #include "graph.h" #include "vgraph.h" #include "vgraph_separate_st.h" #include "dgraph.h" #include "vdgraph.h" #include "vdgraph_separate_sq.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine is the reduction-loc operator which ** returns in inout[2] the rank of the process which ** holds the best partition. ** It returns: ** - void : in all cases. */ static void vdgraphSeparateSqOpBest ( const Gnum * const in, /* First operand */ Gnum * const inout, /* Second and output operand */ const int * const len, /* Number of instances; should be 1, not used */ const MPI_Datatype * const typedat) /* MPI datatype; not used */ { if (inout[3] == 1) { /* Handle cases when at least one of them is erroneous */ if (in[3] == 1) return; inout[0] = in[0]; inout[1] = in[1]; inout[2] = in[2]; inout[3] = in[3]; return; } else if (in[3] == 1) return; if ((in[0] < inout[0]) || /* Select best partition */ ((in[0] == inout[0]) && ((in[1] < inout[1]) || ((in[1] == inout[1]) && (in[2] < inout[2]))))) { inout[0] = in[0]; inout[1] = in[1]; inout[2] = in[2]; } } /* This routine computes a partition of the ** given distributed graph by gathering as many ** copies of the graph as there are processes ** sharing the distributed graph, running a ** sequential algorithm on them, and collecting ** the best solution found. ** It returns: ** - 0 : if the bipartitioning could be computed. ** - !0 : on error. */ int vdgraphSeparateSq ( Vdgraph * const dgrfptr, /*+ Distributed graph +*/ const VdgraphSeparateSqParam * const paraptr) /*+ Method parameters +*/ { Vgraph cgrfdat; /* Centralized vertex separator graph structure */ Gnum reduloctab[7]; /* Local array for best separator data (7 for Bcast) */ Gnum reduglbtab[4]; /* Global array for best separator data */ MPI_Datatype besttypedat; /* Data type for finding best separator */ MPI_Op bestoperdat; /* Handle of MPI operator for finding best separator */ int bestprocnum; /* Rank of process holding best partition */ Gnum * restrict vnumloctax; Gnum vertlocnum; Gnum complocsize1; Gnum complocload1; Gnum complocload2; Gnum fronlocnbr; int o; if ((MPI_Type_contiguous (4, GNUM_MPI, &besttypedat) != MPI_SUCCESS) || (MPI_Type_commit (&besttypedat) != MPI_SUCCESS) || (MPI_Op_create ((MPI_User_function *) vdgraphSeparateSqOpBest, 1, &bestoperdat) != MPI_SUCCESS)) { errorPrint ("vdgraphSeparateSq: communication error (1)"); return (1); } reduloctab[0] = /* In case of error, maximum frontier size */ reduloctab[1] = GNUMMAX; /* And maximum load imbalance */ reduloctab[2] = dgrfptr->s.proclocnum; reduloctab[3] = 0; /* Assume sequential separation went fine */ vnumloctax = dgrfptr->s.vnumloctax; /* No need for vertex number array when centralizing graph */ dgrfptr->s.vnumloctax = NULL; o = vdgraphGatherAll (dgrfptr, &cgrfdat); dgrfptr->s.vnumloctax = vnumloctax; /* Restore vertex number array */ if (o != 0) { errorPrint ("vdgraphSeparateSq: cannot build centralized graph"); return (1); } if (vgraphSeparateSt (&cgrfdat, paraptr->strat) != 0) { /* Separate centralized graph */ errorPrint ("vdgraphSeparateSq: cannot separate centralized graph"); reduloctab[3] = 1; } else { /* Fill local array with local separator data */ reduloctab[0] = ((cgrfdat.fronnbr != 0) || ((cgrfdat.compload[0] != 0) && (cgrfdat.compload[1] != 0))) ? cgrfdat.fronnbr : (cgrfdat.fronnbr + cgrfdat.s.vertnbr); /* Partitions with empty separators unwanted if they are completely unbalanced */ reduloctab[1] = cgrfdat.comploaddlt; } if (MPI_Allreduce (reduloctab, reduglbtab, 1, besttypedat, bestoperdat, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphSeparateSq: communication error (2)"); return (1); } #ifdef SCOTCH_DEBUG_VDGRAPH2 if (MPI_Allreduce (&reduglbtab[3], &reduloctab[3], 1, GNUM_MPI, MPI_SUM, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphSeparateSq: communication error (3)"); return (1); } if ((reduloctab[3] != 0) && (reduloctab[3] != dgrfptr->s.procglbnbr)) { errorPrint ("vdgraphSeparateSq: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ if ((MPI_Op_free (&bestoperdat) != MPI_SUCCESS) || (MPI_Type_free (&besttypedat) != MPI_SUCCESS)) { errorPrint ("vdgraphSeparateSq: communication error (4)"); return (1); } if (reduglbtab[3] != 0) { /* If none of the sequential methods succeeded */ vgraphExit (&cgrfdat); return (1); } bestprocnum = (int) reduglbtab[2]; if (dgrfptr->s.proclocnum == bestprocnum) { /* If process holds best partition */ reduloctab[0] = cgrfdat.compload[0]; /* Global values to share */ reduloctab[1] = cgrfdat.compload[1]; reduloctab[2] = cgrfdat.compload[2]; reduloctab[3] = cgrfdat.comploaddlt; reduloctab[4] = cgrfdat.compsize[0]; reduloctab[5] = cgrfdat.compsize[1]; reduloctab[6] = cgrfdat.fronnbr; } if (MPI_Bcast (reduloctab, 7, GNUM_MPI, bestprocnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphSeparateSq: communication error (5)"); return (1); } dgrfptr->compglbload[0] = reduloctab[0]; dgrfptr->compglbload[1] = reduloctab[1]; dgrfptr->compglbload[2] = reduloctab[2]; dgrfptr->compglbloaddlt = reduloctab[3]; dgrfptr->compglbsize[0] = reduloctab[4]; dgrfptr->compglbsize[1] = reduloctab[5]; dgrfptr->compglbsize[2] = reduloctab[6]; if (commScatterv (cgrfdat.parttax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GRAPHPART_MPI, /* No base for sending as procdsptab holds based values */ dgrfptr->partgsttax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GRAPHPART_MPI, bestprocnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphSeparateSq: communication error (6)"); return (1); } complocsize1 = complocload1 = complocload2 = 0; for (vertlocnum = dgrfptr->s.baseval, fronlocnbr = 0; vertlocnum < dgrfptr->s.vertlocnnd; vertlocnum ++) { int partval; Gnum partval1; partval = dgrfptr->partgsttax[vertlocnum]; partval1 = partval & 1; complocsize1 += partval1; /* Superscalar update */ if (partval == 2) /* Build local frontier */ dgrfptr->fronloctab[fronlocnbr ++] = vertlocnum; if (dgrfptr->s.veloloctax != NULL) { Gnum partval2; Gnum veloval; veloval = dgrfptr->s.veloloctax[vertlocnum]; partval2 = (partval >> 1) & 1; complocload1 += (-partval1) & veloval; /* Superscalar update */ complocload2 += (-partval2) & veloval; /* Superscalar update */ } } dgrfptr->complocsize[0] = dgrfptr->s.vertlocnbr - fronlocnbr - complocsize1; dgrfptr->complocsize[1] = complocsize1; dgrfptr->complocsize[2] = fronlocnbr; if (dgrfptr->s.veloloctax != NULL) { dgrfptr->complocload[0] = dgrfptr->s.velolocsum - complocload1 - complocload2; dgrfptr->complocload[1] = complocload1; dgrfptr->complocload[2] = complocload2; } else { dgrfptr->complocload[0] = dgrfptr->complocsize[0]; dgrfptr->complocload[1] = dgrfptr->complocsize[1]; dgrfptr->complocload[2] = fronlocnbr; } vgraphExit (&cgrfdat); #ifdef SCOTCH_DEBUG_VDGRAPH2 if (vdgraphCheck (dgrfptr) != 0) { errorPrint ("vdgraphSeparateSq: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/vdgraph_separate_zr.h0000644000175300017530000000520111631334325023334 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_separate_zr.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the move-all-to-first-subdomain **/ /** distributed separation method. **/ /** **/ /** DATES : # Version 5.0 : from : 07 feb 2006 **/ /** to 07 feb 2006 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef VDGRAPH_SEPARATE_ZR #define static #endif int vdgraphSeparateZr (Vdgraph * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/dgraph_build.c0000644000175300017530000006132711631334325021734 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_build.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Francois CHATENET (P0.0) **/ /** Sebastien FOUCAULT (P0.0) **/ /** Nicolas GICQUEL (P0.1) **/ /** Jerome LACOSTE (P0.1) **/ /** Cedric CHEVALIER **/ /** **/ /** FUNCTION : These lines are the distributed source **/ /** graph building routines. **/ /** **/ /** DATES : # Version P0.1 : from : 01 apr 1997 **/ /** to : 20 jun 1997 **/ /** # Version P0.2 : from : 02 feb 2000 **/ /** to : 02 feb 2000 **/ /** # Version 5.0 : from : 22 jul 2005 **/ /** to : 10 sep 2007 **/ /** # Version 5.1 : from : 30 jul 2010 **/ /** to : 03 nov 2010 **/ /** **/ /************************************************************/ #define DGRAPH #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_allreduce.h" #include "dgraph_build.h" /* This routine builds a distributed graph from ** the local arrays that are passed to it. If ** a vertex label array is given, it is assumed ** that edge ends are given with respect to these ** labels, and thus they are updated so as to be ** given with respect to the implicit (based) ** global numbering. ** As for all routines that build graphs, the private ** fields of the Dgraph structure have to be initialized ** if they are not already. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphBuild ( Dgraph * restrict const grafptr, /* Graph */ const Gnum baseval, /* Base for indexing */ const Gnum vertlocnbr, /* Number of local vertices */ const Gnum vertlocmax, /* Maximum number of local vertices */ Gnum * const vertloctax, /* Local vertex begin array */ Gnum * const vendloctax, /* Local vertex end array */ Gnum * const veloloctax, /* Local vertex load array (if any) */ Gnum * const vnumloctax, /* Local vertex number array (if any) */ Gnum * const vlblloctax, /* Local vertex label array (if any) */ const Gnum edgelocnbr, /* Number of local edges */ const Gnum edgelocsiz, /* Size of local edge array */ Gnum * const edgeloctax, /* Local edge array */ Gnum * const edgegsttax, /* Ghost edge array (if any); not const */ Gnum * const edloloctax) /* Local edge load array (if any) */ { Gnum vertlocnum; Gnum vertlocnnd; Gnum velolocsum; Gnum degrlocmax; /* Local maximum degree */ for (vertlocnum = baseval, vertlocnnd = vertlocnbr + baseval, degrlocmax = 0; vertlocnum < vertlocnnd; vertlocnum ++) { if (degrlocmax < (vendloctax[vertlocnum] - vertloctax[vertlocnum])) degrlocmax = (vendloctax[vertlocnum] - vertloctax[vertlocnum]); } if (veloloctax == NULL) /* Get local vertex load sum */ velolocsum = vertlocnbr; else { Gnum vertlocnum; for (vertlocnum = baseval, velolocsum = 0; vertlocnum < vertlocnnd; vertlocnum ++) velolocsum += veloloctax[vertlocnum]; } return (dgraphBuild2 (grafptr, baseval, vertlocnbr, vertlocmax, vertloctax, vendloctax, veloloctax, velolocsum, vnumloctax, vlblloctax, edgelocnbr, edgelocsiz, edgeloctax, edgegsttax, edloloctax, degrlocmax)); } /* This routine builds a distributed graph from ** the local arrays that are passed to it. If ** a vertex label array is given, it is assumed ** that edge ends are given with respect to these ** labels, and thus they are updated so as to be ** given with respect to the implicit (based) ** global numbering. ** As for all routines that build graphs, the private ** fields of the Dgraph structure have to be initialized ** if they are not already. ** These graphs do not have holes, since procvrttab ** points to procdsptab. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphBuild2 ( Dgraph * restrict const grafptr, /* Graph */ const Gnum baseval, /* Base for indexing */ const Gnum vertlocnbr, /* Number of local vertices */ const Gnum vertlocmax, /* Maximum number of local vertices */ Gnum * const vertloctax, /* Local vertex begin array */ Gnum * const vendloctax, /* Local vertex end array */ Gnum * const veloloctax, /* Local vertex load array (if any) */ const Gnum velolocsum, /* Local sum of vertex loads */ Gnum * const vnumloctax, /* Local vertex number array (if any) */ Gnum * const vlblloctax, /* Local vertex label array (if any) */ const Gnum edgelocnbr, /* Number of local edges */ const Gnum edgelocsiz, /* Size of local edge array */ Gnum * const edgeloctax, /* Local edge array */ Gnum * const edgegsttax, /* Ghost edge array (if any); not const */ Gnum * const edloloctax, /* Local edge load array (if any) */ const Gnum degrlocmax) { Gnum procnum; int reduloctab[2]; int cheklocval; /* Local consistency flag */ #ifdef SCOTCH_DEBUG_DGRAPH2 if ((vertlocmax < vertlocnbr) || (edgelocsiz < edgelocnbr)) { errorPrint ("dgraphBuild2: invalid parameters"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ cheklocval = 0; if (grafptr->procdsptab == NULL) { /* If private data not yet allocated */ int procglbnbr; procglbnbr = grafptr->procglbnbr; if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ &grafptr->procdsptab, (size_t) ((procglbnbr + 1) * sizeof (Gnum)), &grafptr->procvrttab, (size_t) ((procglbnbr + 1) * sizeof (Gnum)), &grafptr->proccnttab, (size_t) (procglbnbr * sizeof (Gnum)), &grafptr->procngbtab, (size_t) (procglbnbr * sizeof (int)), &grafptr->procrcvtab, (size_t) (procglbnbr * sizeof (int)), &grafptr->procsndtab, (size_t) (procglbnbr * sizeof (int)), NULL) == NULL) { int dummytab[procglbnbr * 2]; errorPrint ("dgraphBuild2: out of memory"); reduloctab[0] = reduloctab[1] = -1; if (MPI_Allgather (reduloctab, 2, MPI_INT, /* Use dummy receive array (if can be allocated too) */ dummytab, 2, MPI_INT, grafptr->proccomm) != MPI_SUCCESS) errorPrint ("dgraphBuild2: communication error (1)"); return (1); } } reduloctab[0] = (int) vertlocnbr; reduloctab[1] = (int) vertlocmax; if (MPI_Allgather (reduloctab, 2, MPI_INT, /* Use procngbtab and procrcvtab as a joint allreduce receive array */ grafptr->procngbtab, 2, MPI_INT, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphBuild2: communication error (2)"); return (1); } grafptr->procdsptab[0] = /* Build vertex-to-process array */ grafptr->procvrttab[0] = baseval; for (procnum = 0; procnum < grafptr->procglbnbr; procnum ++) { if (grafptr->procngbtab[procnum] < 0) { /* If error notified by another process during memory allocation */ memFree (grafptr->procdsptab); grafptr->procdsptab = NULL; /* Free memory that has just been allocated */ return (1); } grafptr->procdsptab[procnum + 1] = grafptr->procdsptab[procnum] + (Gnum) grafptr->procngbtab[2 * procnum]; grafptr->procvrttab[procnum + 1] = grafptr->procvrttab[procnum] + (Gnum) grafptr->procngbtab[2 * procnum + 1]; grafptr->proccnttab[procnum] = grafptr->procdsptab[procnum + 1] - grafptr->procdsptab[procnum]; } grafptr->flagval |= DGRAPHFREEPRIV; return (dgraphBuild3 (grafptr, baseval, vertlocnbr, vertloctax, vendloctax, veloloctax, velolocsum, vnumloctax, vlblloctax, edgelocnbr, edgelocsiz, edgeloctax, edgegsttax, edloloctax, degrlocmax)); } /* This routine builds a distributed graph from ** the local arrays that are passed to it. If ** a vertex label array is given, it is assumed ** that edge ends are given with respect to these ** labels, and thus they are updated so as to be ** given with respect to the implicit (based) ** global numbering. ** This alternate interface assumes that the private ** fields of the Dgraph structure have already been ** initialized. ** It returns: ** - 0 : on success. ** - !0 : on error. */ DGRAPHALLREDUCEMAXSUMOP (17, 3) int dgraphBuild3 ( Dgraph * restrict const grafptr, /* Graph */ const Gnum baseval, /* Base for indexing */ const Gnum vertlocnbr, /* Number of local vertices */ Gnum * const vertloctax, /* Local vertex begin array */ Gnum * const vendloctax, /* Local vertex end array */ Gnum * const veloloctax, /* Local vertex load array (if any) */ const Gnum velolocsum, /* Local sum of vertex loads */ Gnum * const vnumloctax, /* Local vertex number array (if any) */ Gnum * const vlblloctax, /* Local vertex label array (if any) */ const Gnum edgelocnbr, /* Number of local edges */ const Gnum edgelocsiz, /* Minimum useful size of local edge array */ Gnum * const edgeloctax, /* Local edge array */ Gnum * const edgegsttax, /* Ghost edge array (if any); not const */ Gnum * const edloloctax, /* Local edge load array (if any) */ const Gnum degrlocmax) { int procglbnbr; /* Number of processes sharing graph data */ int procrcvnum; /* Number of process from which to receive */ int procsndnum; /* Number of process to which to send */ int procngbnbr; /* Number of neighbors processed */ int procngbnum; /* Number of current neighbor process */ int procngbsel; /* Value of the currently used neighbor buffers */ Gnum vertngbmin; /* Smallest vertex number of neighbor process */ Gnum vertlocnum; Gnum edgelocnum; const Gnum * vlbllocptr; /* Pointer to current vertex label */ DgraphLablSortVert * vesongbptr; /* Pointer to current sort cell */ DgraphLablSortVert * vesongbtnd; /* Pointer to end of current sort array */ DgraphLablSortVert * vesongbtab[2]; /* Neighbor vertex sorting array [norestrict:async] */ int vesongbnbr[2]; /* Sizes of both vertex sort arrays */ DgraphLablSortEdge * edsoloctab; /* Local edge sorting array */ DgraphLablSortEdge * edsoloctnd; /* Pointer to end of edge sort array */ DgraphLablSortEdge * edsolocptr; /* Pointer to current sort edge */ MPI_Request requloctab[2]; /* Arrays for pipelined communication */ MPI_Status statloctab[2]; int cheklocval; /* Local consistency flag */ int chekglbval; /* Global consistency flag */ Gnum reduloctab[20]; /* Arrays for reductions */ Gnum reduglbtab[20]; reduloctab[0] = baseval; /* Check argument consistency */ reduloctab[1] = - baseval; reduloctab[2] = (veloloctax != NULL) ? 1 : 0; reduloctab[3] = - reduloctab[2]; reduloctab[4] = (vnumloctax != NULL) ? 1 : 0; reduloctab[5] = - reduloctab[4]; reduloctab[6] = (vlblloctax != NULL) ? 1 : 0; reduloctab[7] = - reduloctab[6]; reduloctab[8] = (edloloctax != NULL) ? 1 : 0; reduloctab[9] = - reduloctab[8]; reduloctab[10] = (edgegsttax != NULL) ? 1 : 0; reduloctab[11] = - reduloctab[10]; reduloctab[12] = vertlocnbr; /* Get maximum number of local vertices */ reduloctab[13] = edgelocnbr; reduloctab[14] = edgelocsiz; reduloctab[15] = degrlocmax; reduloctab[16] = (grafptr->procdsptab == NULL) ? 1 : 0; /* Error if private data not yet allocated */ reduloctab[17] = vertlocnbr; /* Sum local sizes */ reduloctab[18] = velolocsum; reduloctab[19] = edgelocnbr; if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 17, 3, grafptr->proccomm) != 0) { errorPrint ("dgraphBuild3: cannot compute reductions"); return (1); } if (reduglbtab[16] != 0) { errorPrint ("dgraphBuild3: no private data"); return (1); } if ((reduglbtab[1] != - reduglbtab[0]) || (reduglbtab[3] != - reduglbtab[2]) || (reduglbtab[5] != - reduglbtab[4]) || (reduglbtab[7] != - reduglbtab[6]) || (reduglbtab[9] != - reduglbtab[8]) || (reduglbtab[11] != - reduglbtab[10])) { errorPrint ("dgraphBuild3: inconsistent parameters"); return (1); } grafptr->vertglbmax = reduglbtab[12]; /* Set maximum number of local vertices */ grafptr->edgeglbmax = reduglbtab[13]; /* Set maximum number of local edges */ grafptr->edgeglbsmx = reduglbtab[14]; /* Set maximum size of local edge arrays */ grafptr->degrglbmax = reduglbtab[15]; /* Set maximum degree */ grafptr->baseval = baseval; grafptr->vertglbnbr = reduglbtab[17]; /* Set global and local data */ grafptr->vertlocnbr = vertlocnbr; grafptr->vertlocnnd = vertlocnbr + baseval; grafptr->velolocsum = velolocsum; grafptr->veloglbsum = reduglbtab[18]; grafptr->vertloctax = vertloctax; grafptr->vendloctax = vendloctax; grafptr->veloloctax = veloloctax; grafptr->vnumloctax = vnumloctax; grafptr->vlblloctax = vlblloctax; grafptr->edgeglbnbr = reduglbtab[19]; grafptr->edgelocnbr = edgelocnbr; grafptr->edgelocsiz = edgelocsiz; grafptr->edgegsttax = edgegsttax; grafptr->edgeloctax = edgeloctax; grafptr->edloloctax = edloloctax; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((grafptr->procdsptab[grafptr->procglbnbr] - baseval) < grafptr->vertglbnbr) { errorPrint ("dgraphBuild3: invalid process vertex array"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (vlblloctax != NULL) { /* If vertex labels given */ procglbnbr = grafptr->procglbnbr; if (memAllocGroup ((void **) (void *) &vesongbtab[0], (size_t) (grafptr->vertglbmax * sizeof (DgraphLablSortVert)), &vesongbtab[1], (size_t) (grafptr->vertglbmax * sizeof (DgraphLablSortVert)), &edsoloctab, (size_t) (grafptr->edgeglbmax * sizeof (DgraphLablSortEdge)), NULL) == NULL) { errorPrint ("dgraphBuild3: out of memory"); return (1); } for (vertlocnum = 0, vesongbptr = vesongbtab[0], vlbllocptr = vlblloctax + baseval; vertlocnum < vertlocnbr; vertlocnum ++, vesongbptr ++, vlbllocptr ++) { vesongbptr->vlblglbnum = *vlbllocptr; /* Build vertex sort array */ vesongbptr->vertlocnum = vertlocnum; /* Local index is not based */ } intSort2asc1 (vesongbtab[0], vertlocnbr); vesongbnbr[0] = vertlocnbr; /* Set array size */ cheklocval = 0; for (vesongbptr = vesongbtab[0] + 1, vesongbtnd = vesongbtab[0] + vertlocnbr; vesongbptr < vesongbtnd; vesongbptr ++) { if (vesongbptr[0].vlblglbnum == vesongbptr[-1].vlblglbnum) { cheklocval = 1; break; } } #ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication cannot be merged with a useful one */ MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm); #else /* SCOTCH_DEBUG_DGRAPH1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_DGRAPH1 */ if (chekglbval != 0) { errorPrint ("dgraphBuild3: duplicate vertex label (1)"); memFree (vesongbtab[0]); return (1); } for (edsolocptr = edsoloctab, edsoloctnd = edsoloctab + edgelocnbr, edgelocnum = baseval; edsolocptr < edsoloctnd; edsolocptr ++, edgelocnum ++) { edsolocptr->vlblglbnum = edgeloctax[edgelocnum]; edsolocptr->edgelocnum = edgelocnum; } intSort2asc2 (edsoloctab, grafptr->edgelocnbr); procrcvnum = (grafptr->proclocnum + 1) % procglbnbr; /* Compute indices of neighbors */ procsndnum = (grafptr->proclocnum - 1 + procglbnbr) % procglbnbr; for (procngbnbr = 0, procngbsel = 0; /* For all processes */ procngbnbr < procglbnbr; procngbnbr ++, procngbsel = 1 - procngbsel) { procngbnum = (grafptr->proclocnum + procngbnbr) % procglbnbr; /* Get neighbor process */ vertngbmin = grafptr->procdsptab[procngbnum]; /* Get neighbor vertex number range */ if (procngbnbr < (procglbnbr - 1)) { /* If not last iteration */ MPI_Irecv (vesongbtab[1 - procngbsel], 2 * grafptr->vertglbmax, GNUM_MPI, procrcvnum, TAGVLBLLOCTAB, grafptr->proccomm, &requloctab[0]); MPI_Isend (vesongbtab[procngbsel], 2 * vesongbnbr[procngbsel], GNUM_MPI, procsndnum, TAGVLBLLOCTAB, grafptr->proccomm, &requloctab[1]); } if (vesongbnbr[procngbsel] > 0) { /* If neighbor vertex sort array not empty */ for (edsolocptr = edsoloctab, /* Replace label by global vertex number */ vesongbptr = vesongbtab[procngbsel], vesongbtnd = vesongbptr + vesongbnbr[procngbsel]; edsolocptr < edsoloctnd; ) { if (edsolocptr->vlblglbnum == vesongbptr->vlblglbnum) { if (edsolocptr->edgelocnum == -1) /* If edge label already replaced */ cheklocval = 1; /* Set error flag */ else { edgeloctax[edsolocptr->edgelocnum] = vertngbmin + vesongbptr->vertlocnum; edsolocptr->edgelocnum = -1; /* Edge has been processed */ } edsolocptr ++; /* One more edge processed */ continue; /* Go on as quickly as possible */ } if (edsolocptr->vlblglbnum < vesongbptr->vlblglbnum) { edsolocptr ++; /* One more edge processed */ continue; /* Go on as quickly as possible */ } while (edsolocptr->vlblglbnum > vesongbptr->vlblglbnum) { if (++ vesongbptr >= vesongbtnd) { /* Break if all labels processed */ edsolocptr = edsoloctnd; break; } } } } if (procngbnbr < (procglbnbr - 1)) { /* If not last iteration */ MPI_Waitall (2, requloctab, statloctab); /* Wait for communication completion */ MPI_Get_count (&statloctab[0], GNUM_MPI, &vesongbnbr[1 - procngbsel]); vesongbnbr[1 - procngbsel] /= 2; /* Count items, not fields */ } } memFree (vesongbtab[0]); #ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication cannot be merged with a useful one */ MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm); #else /* SCOTCH_DEBUG_DGRAPH1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_DGRAPH1 */ if (chekglbval != 0) { errorPrint ("dgraphBuild3: duplicate vertex label (2)"); return (1); } } return (0); } /* This subroutine computes the reduced values ** of all of the distributed graph fields. ** It does not deal with vertex labels, nor with ** the ghost edge array. ** It returns: ** - 0 : on success. ** - !0 : on error. */ DGRAPHALLREDUCEMAXSUMOP (4, 3) int dgraphBuild4 ( Dgraph * restrict const grafptr) /* Distributed graph */ { Gnum reduloctab[7]; /* Arrays for reductions */ Gnum reduglbtab[7]; reduloctab[0] = grafptr->vertlocnbr; /* Get maximum over all processes */ reduloctab[1] = grafptr->edgelocnbr; reduloctab[2] = grafptr->edgelocsiz; reduloctab[3] = grafptr->degrglbmax; /* Here, degrglbmax may store only a local maximum degree before calling */ reduloctab[4] = grafptr->vertlocnbr; /* Sum local sizes */ reduloctab[5] = grafptr->velolocsum; reduloctab[6] = grafptr->edgelocnbr; if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 4, 3, grafptr->proccomm) != 0) { errorPrint ("dgraphBuild4: cannot compute reductions"); return (1); } grafptr->vertglbmax = reduglbtab[0]; /* Set maximum number of local vertices */ grafptr->edgeglbmax = reduglbtab[1]; /* Set maximum number of local edges */ grafptr->edgeglbsmx = reduglbtab[2]; /* Set maximum size of local edge arrays */ grafptr->degrglbmax = reduglbtab[3]; /* Set maximum degree */ grafptr->vertglbnbr = reduglbtab[4]; grafptr->veloglbsum = reduglbtab[5]; grafptr->edgeglbnbr = reduglbtab[6]; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((grafptr->procdsptab[grafptr->procglbnbr] - grafptr->baseval) < grafptr->vertglbnbr) { errorPrint ("dgraphBuild4: invalid process vertex array"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_match.c0000644000175300017530000002575111631334325021732 0ustar hazelscthazelsct/* Copyright 2008-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_match.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER (v5.0) **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the distributed graph matching **/ /** routines. **/ /** **/ /** DATES : # Version 5.1 : from : 01 dec 2008 **/ /** to : 30 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH_MATCH #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_coarsen.h" #include "dgraph_match.h" /*************************************/ /* */ /* These routines handle distributed */ /* source graphs. */ /* */ /*************************************/ /* This routine initializes a distributed graph ** structure. In order to avoid collective ** communication whenever possible, the allocation ** of send and receive index arrays is not performed ** in the routine itself, but rather delegated to ** subsequent routines such as dgraphBuild. ** However, these arrays will not be freed by ** dgraphFree, but by dgraphExit. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphMatchInit ( DgraphMatchData * restrict const mateptr, const float probval) { Gnum * restrict procvgbtab; int procngbnum; Gnum vertlocnbr; Gnum vertgstnbr; Dgraph * restrict const grafptr = mateptr->c.finegrafptr; const int * restrict const procngbtab = grafptr->procngbtab; const Gnum * restrict const procvrttab = grafptr->procvrttab; vertlocnbr = grafptr->vertlocnbr; vertgstnbr = grafptr->vertgstnbr; if (memAllocGroup ((void **) (void *) &mateptr->procvgbtab, (size_t) ((grafptr->procngbnbr + 1) * sizeof (Gnum)), &mateptr->queuloctab, (size_t) (vertlocnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphMatchInit: out of memory"); return (1); } mateptr->c.multlocnbr = 0; mateptr->mategsttax = mateptr->c.coargsttax; /* TRICK: re-use array */ mateptr->matelocnbr = 0; /* All vertices need to be processed */ mateptr->queulocnbr = 0; mateptr->probval = (grafptr->procngbnbr == 0) ? 1.0F : probval; memSet (mateptr->mategsttax + grafptr->vertlocnnd, ~0, (vertgstnbr - vertlocnbr) * sizeof (Gnum)); /* No ghost vertices matched to date */ for (procngbnum = 0, procvgbtab = mateptr->procvgbtab; procngbnum < grafptr->procngbnbr; procngbnum ++) procvgbtab[procngbnum] = (Gnum) procvrttab[procngbtab[procngbnum]]; procvgbtab[procngbnum] = (Gnum) procvrttab[grafptr->procglbnbr]; /* Mark end */ return (0); } /* This routine frees the contents of a matching ** data structure. ** It returns: ** - VOID : in all cases. */ void dgraphMatchExit ( DgraphMatchData * restrict const mateptr) { memFree (mateptr->procvgbtab); } /* These routines perform a round of computations ** among enqueued vertices to produce matching requests. ** They return: ** - 0 : on success. ** - !0 : on error. */ #define DGRAPHMATCHSCANNAME dgraphMatchSc /* Scan matching (no edge weights) */ #define DGRAPHMATCHSCANINIT #define DGRAPHMATCHSCANCOUNTINIT \ probval = intRandVal (32768); /* Get proba for this vertex */ #define DGRAPHMATCHSCANCOUNTSELECT \ edgefrenbr ++; #define DGRAPHMATCHSCANFINDSELECT \ (edgefrenbr -- == 0) #include "dgraph_match_scan.c" #undef DGRAPHMATCHSCANFINDSELECT #undef DGRAPHMATCHSCANCOUNTSELECT #undef DGRAPHMATCHSCANCOUNTINIT #undef DGRAPHMATCHSCANINIT #undef DGRAPHMATCHSCANNAME #define DGRAPHMATCHSCANNAME dgraphMatchHy /* Heavy edge matching */ #define DGRAPHMATCHSCANINIT \ const Gnum * restrict const edloloctax = mateptr->c.finegrafptr->edloloctax; \ if (edloloctax == NULL) { \ dgraphMatchSc (mateptr); \ return; \ } #define DGRAPHMATCHSCANCOUNTINIT \ Gnum edlolocmax; \ edlolocmax = 0; \ probval = intRandVal (32768); /* Get proba for this vertex */ #define DGRAPHMATCHSCANCOUNTSELECT \ Gnum edlolocval; \ edlolocval = edloloctax[edgelocnum]; \ if (edlolocval > edlolocmax) { \ edlolocmax = edlolocval; \ edgefrenbr = 1; \ } \ else if (edlolocval == edlolocmax) \ edgefrenbr ++; #define DGRAPHMATCHSCANFINDSELECT \ ((edloloctax[edgelocnum] == edlolocmax) && \ (edgefrenbr -- == 0)) #include "dgraph_match_scan.c" #undef DGRAPHMATCHSCANFINDSELECT #undef DGRAPHMATCHSCANCOUNTSELECT #undef DGRAPHMATCHSCANCOUNTINIT #undef DGRAPHMATCHSCANINIT #undef DGRAPHMATCHSCANNAME #define DGRAPHMATCHSCANNAME dgraphMatchLc /* Local scan matching */ #define DGRAPHMATCHSCANINIT #define DGRAPHMATCHSCANCOUNTINIT \ probval = 0; /* Vertices will always be active */ #define DGRAPHMATCHSCANCOUNTSELECT \ if (vertgstend < vertlocnnd) \ edgefrenbr ++; \ else \ edgeendnbr --; #define DGRAPHMATCHSCANFINDSELECT \ ((vertgstend < vertlocnnd) && \ (edgefrenbr -- == 0)) #include "dgraph_match_scan.c" #undef DGRAPHMATCHSCANFINDSELECT #undef DGRAPHMATCHSCANCOUNTSELECT #undef DGRAPHMATCHSCANCOUNTINIT #undef DGRAPHMATCHSCANINIT #undef DGRAPHMATCHSCANNAME #define DGRAPHMATCHSCANNAME dgraphMatchLy /* Local heavy edge matching */ #define DGRAPHMATCHSCANINIT \ const Gnum * restrict const edloloctax = mateptr->c.finegrafptr->edloloctax; \ if (edloloctax == NULL) { \ dgraphMatchLc (mateptr); \ return; \ } #define DGRAPHMATCHSCANCOUNTINIT \ Gnum edlolocmax; \ edlolocmax = 0; \ probval = 0; /* Vertices will always be active */ #define DGRAPHMATCHSCANCOUNTSELECT \ if (vertgstend < vertlocnnd) { \ Gnum edlolocval; \ edlolocval = edloloctax[edgelocnum]; \ if (edlolocval > edlolocmax) { \ edlolocmax = edlolocval; \ edgefrenbr = 1; \ } \ else if (edlolocval == edlolocmax) \ edgefrenbr ++; \ } \ else \ edgeendnbr --; #define DGRAPHMATCHSCANFINDSELECT \ ((vertgstend < vertlocnnd) && \ (edloloctax[edgelocnum] == edlolocmax) && \ (edgefrenbr -- == 0)) #include "dgraph_match_scan.c" #undef DGRAPHMATCHSCANFINDSELECT #undef DGRAPHMATCHSCANCOUNTSELECT #undef DGRAPHMATCHSCANCOUNTINIT #undef DGRAPHMATCHSCANINIT #undef DGRAPHMATCHSCANNAME scotch-5.1.12b.dfsg/src/libscotch/common_stub.c0000644000175300017530000000621111631334325021624 0ustar hazelscthazelsct/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : common_stub.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are common stub routines **/ /** for several systems, used by all **/ /** modules. **/ /** **/ /** DATES : # Version 5.0 : from : 11 may 2008 **/ /** to 11 may 2008 **/ /** # Version 5.1 : from : 27 jun 2010 **/ /** to 01 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define COMMON #ifndef COMMON_NOMODULE #include "module.h" #endif /* COMMON_NOMODULE */ #include "common.h" /* ** The static and global variables. */ int commonStubDummy; /* Dummy variable so that the object file will never be empty */ /******************/ /* */ /* Stub routines. */ /* */ /******************/ #ifdef COMMON_STUB_FORK int fork () { errorPrint ("fork() not implemented on this system"); return (-1); } #endif /* COMMON_STUB_FORK */ scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_st.c0000644000175300017530000004136111631334325023165 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_st.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the global **/ /** separation strategy and method tables. **/ /** **/ /** DATES : # Version 3.2 : from : 25 oct 1996 **/ /** to 14 nov 1997 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 31 may 1999 **/ /** # Version 4.0 : from : 06 jan 2002 **/ /** to 28 mar 2006 **/ /** # Version 5.0 : from : 12 sep 2006 **/ /** to : 02 oct 2007 **/ /** # Version 5.1 : from : 30 oct 2007 **/ /** to : 01 jul 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VGRAPH_SEPARATE_ST #include "module.h" #include "common.h" #include "gain.h" #include "parser.h" #include "graph.h" #include "graph_coarsen.h" #include "arch.h" #include "mapping.h" #include "bgraph.h" #include "bgraph_bipart_st.h" #include "vgraph.h" #include "vgraph_separate_bd.h" #include "vgraph_separate_es.h" #include "vgraph_separate_fm.h" #include "vgraph_separate_gg.h" #include "vgraph_separate_gp.h" #include "vgraph_separate_ml.h" #include "vgraph_separate_th.h" #include "vgraph_separate_st.h" #include "vgraph_separate_vw.h" #include "vgraph_separate_zr.h" /* ** The static and global variables. */ static Vgraph vgraphdummy; /* Dummy separator graph for offset computations */ static union { VgraphSeparateBdParam param; StratNodeMethodData padding; } vgraphseparatedefaultbd = { { 3, &stratdummy, &stratdummy } }; static union { VgraphSeparateEsParam param; StratNodeMethodData padding; } vgraphseparatedefaultes = { { &stratdummy, VGRAPHSEPAESWIDTHTHIN } }; static union { VgraphSeparateFmParam param; StratNodeMethodData padding; } vgraphseparatedefaultfm = { { 200, 1000, 0.1L } }; static union { VgraphSeparateGgParam param; StratNodeMethodData padding; } vgraphseparatedefaultgg = { { 5 } }; static union { VgraphSeparateGpParam param; StratNodeMethodData padding; } vgraphseparatedefaultgp = { { 9 } }; static union { VgraphSeparateMlParam param; StratNodeMethodData padding; } vgraphseparatedefaultml = { { 100, 0.8L, GRAPHCOARHEM, &stratdummy, &stratdummy } }; static StratMethodTab vgraphseparatestmethtab[] = { /* Graph separation methods array */ { VGRAPHSEPASTMETHBD, "b", vgraphSeparateBd, &vgraphseparatedefaultbd }, { VGRAPHSEPASTMETHES, "e", vgraphSeparateEs, &vgraphseparatedefaultes }, { VGRAPHSEPASTMETHFM, "f", vgraphSeparateFm, &vgraphseparatedefaultfm }, { VGRAPHSEPASTMETHGG, "h", vgraphSeparateGg, &vgraphseparatedefaultgg }, { VGRAPHSEPASTMETHGP, "g", vgraphSeparateGp, &vgraphseparatedefaultgp }, { VGRAPHSEPASTMETHML, "m", vgraphSeparateMl, &vgraphseparatedefaultml }, { VGRAPHSEPASTMETHVW, "v", vgraphSeparateVw, NULL }, { VGRAPHSEPASTMETHZR, "z", vgraphSeparateZr, NULL }, { -1, NULL, NULL, NULL } }; static StratParamTab vgraphseparatestparatab[] = { /* Graph separation method parameter list */ { VGRAPHSEPASTMETHBD, STRATPARAMSTRAT, "bnd", (byte *) &vgraphseparatedefaultbd.param, (byte *) &vgraphseparatedefaultbd.param.stratbnd, (void *) &vgraphseparateststratab }, { VGRAPHSEPASTMETHBD, STRATPARAMSTRAT, "org", (byte *) &vgraphseparatedefaultbd.param, (byte *) &vgraphseparatedefaultbd.param.stratorg, (void *) &vgraphseparateststratab }, { VGRAPHSEPASTMETHBD, STRATPARAMINT, "width", (byte *) &vgraphseparatedefaultbd.param, (byte *) &vgraphseparatedefaultbd.param.distmax, NULL }, { VGRAPHSEPASTMETHES, STRATPARAMSTRAT, "strat", (byte *) &vgraphseparatedefaultes.param, (byte *) &vgraphseparatedefaultes.param.strat, (void *) &bgraphbipartststratab }, { VGRAPHSEPASTMETHES, STRATPARAMCASE, "type", (byte *) &vgraphseparatedefaultes.param, (byte *) &vgraphseparatedefaultes.param.widtval, (void *) "tf" }, { VGRAPHSEPASTMETHFM, STRATPARAMINT, "move", (byte *) &vgraphseparatedefaultfm.param, (byte *) &vgraphseparatedefaultfm.param.movenbr, NULL }, { VGRAPHSEPASTMETHFM, STRATPARAMINT, "pass", (byte *) &vgraphseparatedefaultfm.param, (byte *) &vgraphseparatedefaultfm.param.passnbr, NULL }, { VGRAPHSEPASTMETHFM, STRATPARAMDOUBLE, "bal", (byte *) &vgraphseparatedefaultfm.param, (byte *) &vgraphseparatedefaultfm.param.deltrat, NULL }, { VGRAPHSEPASTMETHGG, STRATPARAMINT, "pass", (byte *) &vgraphseparatedefaultgg.param, (byte *) &vgraphseparatedefaultgg.param.passnbr, NULL }, { VGRAPHSEPASTMETHGP, STRATPARAMINT, "pass", (byte *) &vgraphseparatedefaultgp.param, (byte *) &vgraphseparatedefaultgp.param.passnbr, NULL }, { VGRAPHSEPASTMETHML, STRATPARAMSTRAT, "asc", (byte *) &vgraphseparatedefaultml.param, (byte *) &vgraphseparatedefaultml.param.stratasc, (void *) &vgraphseparateststratab }, { VGRAPHSEPASTMETHML, STRATPARAMSTRAT, "low", (byte *) &vgraphseparatedefaultml.param, (byte *) &vgraphseparatedefaultml.param.stratlow, (void *) &vgraphseparateststratab }, { VGRAPHSEPASTMETHML, STRATPARAMCASE, "type", (byte *) &vgraphseparatedefaultml.param, (byte *) &vgraphseparatedefaultml.param.coartype, (void *) "hscd" }, { VGRAPHSEPASTMETHML, STRATPARAMINT, "vert", (byte *) &vgraphseparatedefaultml.param, (byte *) &vgraphseparatedefaultml.param.coarnbr, NULL }, { VGRAPHSEPASTMETHML, STRATPARAMDOUBLE, "rat", (byte *) &vgraphseparatedefaultml.param, (byte *) &vgraphseparatedefaultml.param.coarrat, NULL }, { VGRAPHSEPASTMETHNBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; static StratParamTab vgraphseparatestcondtab[] = { /* Graph condition parameter table */ { STRATNODECOND, STRATPARAMINT, "edge", (byte *) &vgraphdummy, (byte *) &vgraphdummy.s.edgenbr, NULL }, { STRATNODECOND, STRATPARAMINT, "levl", (byte *) &vgraphdummy, (byte *) &vgraphdummy.levlnum, NULL }, { STRATNODECOND, STRATPARAMINT, "load", (byte *) &vgraphdummy, (byte *) &vgraphdummy.s.velosum, NULL }, #ifdef SCOTCH_PTSCOTCH { STRATNODECOND, STRATPARAMINT, "proc", (byte *) &vgraphdummy, (byte *) &vgraphdummy.s.procglbnbr, NULL }, { STRATNODECOND, STRATPARAMINT, "rank", (byte *) &vgraphdummy, (byte *) &vgraphdummy.s.proclocnum, NULL }, #endif /* SCOTCH_PTSCOTCH */ { STRATNODECOND, STRATPARAMINT, "vert", (byte *) &vgraphdummy, (byte *) &vgraphdummy.s.vertnbr, NULL }, { STRATNODENBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; StratTab vgraphseparateststratab = { /* Strategy tables for vertex separation methods */ vgraphseparatestmethtab, vgraphseparatestparatab, vgraphseparatestcondtab }; /*******************************************/ /* */ /* This is the generic separation routine. */ /* */ /*******************************************/ /* This routine computes the separation of ** the given graph according to the given ** strategy. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int vgraphSeparateSt ( Vgraph * restrict const grafptr, /*+ Separation graph +*/ const Strat * restrict const strat) /*+ Separation strategy +*/ { StratTest val; VgraphStore savetab[2]; /* Results of the two strategies */ int o; #ifdef SCOTCH_DEBUG_VGRAPH2 if (sizeof (Gnum) != sizeof (INT)) { errorPrint ("vgraphSeparateSt: invalid type specification for parser variables"); return (1); } if ((sizeof (VgraphSeparateFmParam) > sizeof (StratNodeMethodData)) || (sizeof (VgraphSeparateGgParam) > sizeof (StratNodeMethodData)) || (sizeof (VgraphSeparateGpParam) > sizeof (StratNodeMethodData)) || (sizeof (VgraphSeparateMlParam) > sizeof (StratNodeMethodData))) { errorPrint ("vgraphSeparateSt: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ #ifdef SCOTCH_DEBUG_VGRAPH1 if ((strat->tabl != &vgraphseparateststratab) && (strat != &stratdummy)) { errorPrint ("vgraphSeparateSt: invalid parameter (1)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH1 */ o = 0; switch (strat->type) { case STRATNODECONCAT : o = vgraphSeparateSt (grafptr, strat->data.concat.strat[0]); /* Apply first strategy */ if (o == 0) /* If it worked all right */ o |= vgraphSeparateSt (grafptr, strat->data.concat.strat[1]); /* Then apply second strategy */ break; case STRATNODECOND : o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ if (o == 0) { /* If evaluation was correct */ #ifdef SCOTCH_DEBUG_VGRAPH2 if ((val.typetest != STRATTESTVAL) || (val.typenode != STRATPARAMLOG)) { errorPrint ("vgraphSeparateSt: invalid test result"); o = 1; break; } #endif /* SCOTCH_DEBUG_VGRAPH2 */ if (val.data.val.vallog == 1) /* If expression is true */ o = vgraphSeparateSt (grafptr, strat->data.cond.strat[0]); /* Apply first strategy */ else { /* Else if expression is false */ if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ o = vgraphSeparateSt (grafptr, strat->data.cond.strat[1]); /* Apply second strategy */ } } break; case STRATNODEEMPTY : break; case STRATNODESELECT : if (((vgraphStoreInit (grafptr, &savetab[0])) != 0) || /* Allocate save areas */ ((vgraphStoreInit (grafptr, &savetab[1])) != 0)) { errorPrint ("vgraphSeparateSt: out of memory"); vgraphStoreExit (&savetab[0]); return (1); } vgraphStoreSave (grafptr, &savetab[1]); /* Save initial bipartition */ if (vgraphSeparateSt (grafptr, strat->data.select.strat[0]) != 0) { /* If first strategy didn't work */ vgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition */ vgraphStoreSave (grafptr, &savetab[0]); /* Save it as result */ } else { /* First strategy worked */ vgraphStoreSave (grafptr, &savetab[0]); /* Save its result */ vgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition */ } if (vgraphSeparateSt (grafptr, strat->data.select.strat[1]) != 0) /* If second strategy didn't work */ vgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition as its result */ if ( (savetab[0].fronnbr < grafptr->fronnbr) || /* If first strategy is better */ ((savetab[0].fronnbr == grafptr->fronnbr) && (abs (savetab[0].comploaddlt) < abs (grafptr->comploaddlt)))) vgraphStoreUpdt (grafptr, &savetab[0]); /* Restore its result */ vgraphStoreExit (&savetab[0]); /* Free both save areas */ vgraphStoreExit (&savetab[1]); break; #ifdef SCOTCH_DEBUG_VGRAPH1 case STRATNODEMETHOD : #else /* SCOTCH_DEBUG_VGRAPH1 */ default : #endif /* SCOTCH_DEBUG_VGRAPH1 */ return (strat->tabl->methtab[strat->data.method.meth].func (grafptr, (void *) &strat->data.method.data)); #ifdef SCOTCH_DEBUG_VGRAPH1 default : errorPrint ("vgraphSeparateSt: invalid parameter (2)"); return (1); #endif /* SCOTCH_DEBUG_VGRAPH1 */ } return (o); } scotch-5.1.12b.dfsg/src/libscotch/vdgraph_separate_df.h0000644000175300017530000000701111631334325023273 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_separate_df.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the parallel diffusion separation **/ /** routine for distributed graphs. **/ /** **/ /** DATES : # Version 5.1 : from : 05 nov 2007 **/ /** to : 07 nov 2007 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Small non-zero float value. +*/ #define VDGRAPHSEPARATEDFEPSILON (1.0F / (float) (GNUMMAX)) /*+ Sign masking operator. +*/ #define VDGRAPHSEPARATEDFGNUMSGNMSK(i) ((Gnum) 0 - (((Gunum) (i)) >> (sizeof (Gnum) * 8 - 1))) /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct VdgraphSeparateDfParam_ { INT partval; /*+ Part to aggregate to separator +*/ INT passnbr; /*+ Number of passes to do +*/ double cdifval; /*+ Coefficient of diffused load +*/ double cremval; /*+ Coefficient of remaining load +*/ double deltval; /*+ Maximum imbalance ratio +*/ } VdgraphSeparateDfParam; /* ** The function prototypes. */ #ifndef VDGRAPH_SEPARATE_DF #define static #endif int vdgraphSeparateDf (Vdgraph * const, const VdgraphSeparateDfParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/module.h0000644000175300017530000010660211631334325020576 0ustar hazelscthazelsct/* Copyright 2004,2007-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : module.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This is the global configuration file **/ /** for the whole libSCOTCH library module. **/ /** **/ /** DATES : # Version 3.2 : from : 22 jun 1998 **/ /** to 13 may 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 03 oct 1998 **/ /** # Version 3.4 : from : 01 nov 2001 **/ /** to 01 nov 2001 **/ /** # Version 4.0 : from : 12 dec 2001 **/ /** to 24 nov 2005 **/ /** # Version 5.0 : from : 24 feb 2007 **/ /** to 24 jul 2007 **/ /** # Version 5.1 : from : 25 oct 2007 **/ /** to 20 feb 2011 **/ /** **/ /************************************************************/ #define MODULE_H /* ** Version string. */ #define SCOTCH_VERSION_STRING SCOTCH_VERSION_STRING2(SCOTCH_VERSION) "." SCOTCH_VERSION_STRING2(SCOTCH_RELEASE) "." SCOTCH_VERSION_STRING2(SCOTCH_PATCHLEVEL) #define SCOTCH_VERSION_STRING2(x) SCOTCH_VERSION_STRING3(x) #define SCOTCH_VERSION_STRING3(x) #x /* ** Debug values. */ #ifdef SCOTCH_DEBUG_ALL #ifndef SCOTCH_DEBUG #define SCOTCH_DEBUG #endif /* SCOTCH_DEBUG */ #define SCOTCH_DEBUG_ARCH2 #define SCOTCH_DEBUG_GAIN2 #define SCOTCH_DEBUG_PARSER2 #define SCOTCH_DEBUG_BDGRAPH2 #define SCOTCH_DEBUG_BGRAPH2 #define SCOTCH_DEBUG_DGRAPH2 #define SCOTCH_DEBUG_DMAP2 #define SCOTCH_DEBUG_DORDER2 #define SCOTCH_DEBUG_GEOM2 #define SCOTCH_DEBUG_GRAPH2 #define SCOTCH_DEBUG_HDGRAPH2 #define SCOTCH_DEBUG_HGRAPH2 #define SCOTCH_DEBUG_HMESH2 #define SCOTCH_DEBUG_KDGRAPH2 #define SCOTCH_DEBUG_KGRAPH2 #define SCOTCH_DEBUG_LIBRARY2 #define SCOTCH_DEBUG_MAP2 #define SCOTCH_DEBUG_MESH2 #define SCOTCH_DEBUG_ORDER2 #define SCOTCH_DEBUG_PARSER2 #define SCOTCH_DEBUG_VDGRAPH2 #define SCOTCH_DEBUG_VGRAPH2 #define SCOTCH_DEBUG_VMESH2 #endif /* SCOTCH_DEBUG_ALL */ #ifdef SCOTCH_DEBUG #define SCOTCH_DEBUG_ARCH1 #define SCOTCH_DEBUG_GAIN1 #define SCOTCH_DEBUG_PARSER1 #define SCOTCH_DEBUG_BDGRAPH1 #define SCOTCH_DEBUG_BGRAPH1 #define SCOTCH_DEBUG_DGRAPH1 #define SCOTCH_DEBUG_DMAP1 #define SCOTCH_DEBUG_DORDER1 #define SCOTCH_DEBUG_GEOM1 #define SCOTCH_DEBUG_GRAPH1 #define SCOTCH_DEBUG_HDGRAPH1 #define SCOTCH_DEBUG_HGRAPH1 #define SCOTCH_DEBUG_HMESH1 #define SCOTCH_DEBUG_KDGRAPH1 #define SCOTCH_DEBUG_KGRAPH1 #define SCOTCH_DEBUG_LIBRARY1 #define SCOTCH_DEBUG_MAP1 #define SCOTCH_DEBUG_MESH1 #define SCOTCH_DEBUG_ORDER1 #define SCOTCH_DEBUG_PARSER1 #define SCOTCH_DEBUG_VDGRAPH1 #define SCOTCH_DEBUG_VGRAPH1 #define SCOTCH_DEBUG_VMESH1 #endif /* SCOTCH_DEBUG */ /* ** Function renaming. */ #if ((! defined SCOTCH_COMMON_EXTERNAL) || (defined SCOTCH_COMMON_RENAME)) #define clockGet _SCOTCHclockGet #define commonStubDummy _SCOTCHcommonStubDummy #define errorPrint SCOTCH_errorPrint #define errorPrintW SCOTCH_errorPrintW #define errorProg SCOTCH_errorProg #define fileBlockClose _SCOTCHfileBlockClose #define fileBlockOpen _SCOTCHfileBlockOpen #define fileBlockOpenDist _SCOTCHfileBlockOpenDist #define fileCompress _SCOTCHfileCompress #define fileCompressType _SCOTCHfileCompressType #define fileUncompress _SCOTCHfileUncompress #define fileUncompressType _SCOTCHfileUncompressType #define fileNameDistExpand _SCOTCHfileNameDistExpand #define intLoad _SCOTCHintLoad #define intSave _SCOTCHintSave #define intAscn _SCOTCHintAscn #define intPerm _SCOTCHintPerm #define intRandReset _SCOTCHintRandReset #define intRandInit _SCOTCHintRandInit /* #define intRandVal _SCOTCHintRandVal Already a macro */ #define intSort1asc1 _SCOTCHintSort1asc1 #define intSort2asc1 _SCOTCHintSort2asc1 #define intSort2asc2 _SCOTCHintSort2asc2 #define intSort3asc1 _SCOTCHintSort3asc1 #define intSort3asc2 _SCOTCHintSort3asc2 #define memAllocGroup _SCOTCHmemAllocGroup #define memReallocGroup _SCOTCHmemReallocGroup #define memOffset _SCOTCHmemOffset #define stringSubst _SCOTCHstringSubst #define usagePrint _SCOTCHusagePrint #endif /* ((! defined SCOTCH_COMMON_EXTERNAL) || (defined SCOTCH_COMMON_RENAME)) */ #ifdef SCOTCH_RENAME #define archInit _SCOTCHarchInit #define archExit _SCOTCHarchExit #define archFree _SCOTCHarchFree #define archLoad _SCOTCHarchLoad #define archSave _SCOTCHarchSave /* #define archName _SCOTCHarchName Already a macro */ #define archClass _SCOTCHarchClass #define archClassTab _SCOTCHarchClassTab #define archDomLoad _SCOTCHarchDomLoad #define archDomSave _SCOTCHarchDomSave #ifdef SCOTCH_DEBUG_ARCH2 /* If already redefined */ #define archDomNum _SCOTCHarchDomNum #define archDomTerm _SCOTCHarchDomTerm #define archDomSize _SCOTCHarchDomSize #define archDomWght _SCOTCHarchDomWght #define archDomDist _SCOTCHarchDomDist #define archDomFrst _SCOTCHarchDomFrst #define archDomBipart _SCOTCHarchDomBipart #endif /* SCOTCH_DEBUG_ARCH2 */ #define archDomMpiType _SCOTCHarchDomMpiType #define archBuild _SCOTCHarchBuild #define archCmpltArchLoad _SCOTCHarchCmpltArchLoad #define archCmpltArchSave _SCOTCHarchCmpltArchSave #define archCmpltDomNum _SCOTCHarchCmpltDomNum #define archCmpltDomTerm _SCOTCHarchCmpltDomTerm #define archCmpltDomSize _SCOTCHarchCmpltDomSize /* #define archCmpltDomWght _SCOTCHarchCmpltDomWght Already a macro */ #define archCmpltDomDist _SCOTCHarchCmpltDomDist #define archCmpltDomFrst _SCOTCHarchCmpltDomFrst #define archCmpltDomLoad _SCOTCHarchCmpltDomLoad #define archCmpltDomSave _SCOTCHarchCmpltDomSave #define archCmpltDomBipart _SCOTCHarchCmpltDomBipart #define archCmpltDomMpiType _SCOTCHarchCmpltDomMpiType #define archCmpltwArchBuild _SCOTCHarchCmpltwArchBuild #define archCmpltwArchFree _SCOTCHarchCmpltwArchFree #define archCmpltwArchLoad _SCOTCHarchCmpltwArchLoad #define archCmpltwArchSave _SCOTCHarchCmpltwArchSave #define archCmpltwDomNum _SCOTCHarchCmpltwDomNum #define archCmpltwDomTerm _SCOTCHarchCmpltwDomTerm #define archCmpltwDomSize _SCOTCHarchCmpltwDomSize #define archCmpltwDomWght _SCOTCHarchCmpltwDomWght #define archCmpltwDomDist _SCOTCHarchCmpltwDomDist #define archCmpltwDomFrst _SCOTCHarchCmpltwDomFrst #define archCmpltwDomLoad _SCOTCHarchCmpltwDomLoad #define archCmpltwDomSave _SCOTCHarchCmpltwDomSave #define archCmpltwDomBipart _SCOTCHarchCmpltwDomBipart #define archCmpltwDomMpiType _SCOTCHarchCmpltwDomMpiType #define archDecoArchBuild _SCOTCHarchDecoArchBuild #define archDecoArchFree _SCOTCHarchDecoArchFree #define archDecoArchLoad _SCOTCHarchDecoArchLoad #define archDecoArchSave _SCOTCHarchDecoArchSave #define archDecoDomNum _SCOTCHarchDecoDomNum #define archDecoDomTerm _SCOTCHarchDecoDomTerm #define archDecoDomSize _SCOTCHarchDecoDomSize #define archDecoDomWght _SCOTCHarchDecoDomWght #define archDecoDomDist _SCOTCHarchDecoDomDist #define archDecoDomFrst _SCOTCHarchDecoDomFrst #define archDecoDomLoad _SCOTCHarchDecoDomLoad #define archDecoDomSave _SCOTCHarchDecoDomSave #define archDecoDomBipart _SCOTCHarchDecoDomBipart #define archDecoDomMpiType _SCOTCHarchDecoDomMpiType #define archHcubArchLoad _SCOTCHarchHcubArchLoad #define archHcubArchSave _SCOTCHarchHcubArchSave #define archHcubDomNum _SCOTCHarchHcubDomNum #define archHcubDomTerm _SCOTCHarchHcubDomTerm #define archHcubDomSize _SCOTCHarchHcubDomSize /* #define archHcubDomWght _SCOTCHarchHcubDomWght Already a macro */ #define archHcubDomDist _SCOTCHarchHcubDomDist #define archHcubDomFrst _SCOTCHarchHcubDomFrst #define archHcubDomLoad _SCOTCHarchHcubDomLoad #define archHcubDomSave _SCOTCHarchHcubDomSave #define archHcubDomBipart _SCOTCHarchHcubDomBipart #define archHcubDomMpiType _SCOTCHarchHcubDomMpiType #define archTleafArchLoad _SCOTCHarchTleafArchLoad #define archTleafArchFree _SCOTCHarchTleafArchFree #define archTleafArchSave _SCOTCHarchTleafArchSave #define archTleafDomNum _SCOTCHarchTleafDomNum #define archTleafDomTerm _SCOTCHarchTleafDomTerm #define archTleafDomSize _SCOTCHarchTleafDomSize /* #define archTleafDomWght _SCOTCHarchTleafDomWght Already a macro */ #define archTleafDomDist _SCOTCHarchTleafDomDist #define archTleafDomFrst _SCOTCHarchTleafDomFrst #define archTleafDomLoad _SCOTCHarchTleafDomLoad #define archTleafDomSave _SCOTCHarchTleafDomSave #define archTleafDomBipart _SCOTCHarchTleafDomBipart #define archTleafDomMpiType _SCOTCHarchTleafDomMpiType #define archMesh2ArchLoad _SCOTCHarchMesh2ArchLoad #define archMesh2ArchSave _SCOTCHarchMesh2ArchSave #define archMesh2DomNum _SCOTCHarchMesh2DomNum #define archMesh2DomTerm _SCOTCHarchMesh2DomTerm #define archMesh2DomSize _SCOTCHarchMesh2DomSize /* #define archMesh2DomWght _SCOTCHarchMesh2DomWght Already a macro */ #define archMesh2DomDist _SCOTCHarchMesh2DomDist #define archMesh2DomFrst _SCOTCHarchMesh2DomFrst #define archMesh2DomLoad _SCOTCHarchMesh2DomLoad #define archMesh2DomSave _SCOTCHarchMesh2DomSave #define archMesh2DomBipart _SCOTCHarchMesh2DomBipart #define archMesh2DomBipartO _SCOTCHarchMesh2DomBipartO #define archMesh2DomBipartU _SCOTCHarchMesh2DomBipartU #define archMesh2DomMpiType _SCOTCHarchMesh2DomMpiType #define archMesh3ArchLoad _SCOTCHarchMesh3ArchLoad #define archMesh3ArchSave _SCOTCHarchMesh3ArchSave #define archMesh3DomNum _SCOTCHarchMesh3DomNum #define archMesh3DomTerm _SCOTCHarchMesh3DomTerm #define archMesh3DomSize _SCOTCHarchMesh3DomSize /* #define archMesh3DomWght _SCOTCHarchMesh3DomWght Already a macro */ #define archMesh3DomDist _SCOTCHarchMesh3DomDist #define archMesh3DomFrst _SCOTCHarchMesh3DomFrst #define archMesh3DomLoad _SCOTCHarchMesh3DomLoad #define archMesh3DomSave _SCOTCHarchMesh3DomSave #define archMesh3DomBipart _SCOTCHarchMesh3DomBipart #define archMesh3DomMpiType _SCOTCHarchMesh3DomMpiType #define archTermArchLoad _SCOTCHarchTermArchLoad #define archTermArchSave _SCOTCHarchTermArchSave #define archTermDomNum _SCOTCHarchTermDomNum #define archTermDomTerm _SCOTCHarchTermDomTerm #define archTermDomSize _SCOTCHarchTermDomSize /* #define archTermDomWght _SCOTCHarchTermDomWght Already a macro */ #define archTermDomDist _SCOTCHarchTermDomDist #define archTermDomFrst _SCOTCHarchTermDomFrst #define archTermDomLoad _SCOTCHarchTermDomLoad #define archTermDomSave _SCOTCHarchTermDomSave #define archTermDomBipart _SCOTCHarchTermDomBipart #define archTermDomMpiType _SCOTCHarchTermDomMpiType #define archTorus2ArchLoad _SCOTCHarchTorus2ArchLoad #define archTorus2ArchSave _SCOTCHarchTorus2ArchSave #define archTorus2DomNum _SCOTCHarchTorus2DomNum #define archTorus2DomTerm _SCOTCHarchTorus2DomTerm #define archTorus2DomSize _SCOTCHarchTorus2DomSize /* #define archTorus2DomWght _SCOTCHarchTorus2DomWght Already a macro */ #define archTorus2DomDist _SCOTCHarchTorus2DomDist #define archTorus2DomFrst _SCOTCHarchTorus2DomFrst #define archTorus2DomBipart _SCOTCHarchTorus2DomBipart #define archTorus2DomLoad _SCOTCHarchTorus2DomLoad #define archTorus2DomSave _SCOTCHarchTorus2DomSave #define archTorus2DomBipart _SCOTCHarchTorus2DomBipart #define archTorus2DomMpiType _SCOTCHarchTorus2DomMpiType #define archTorus3ArchLoad _SCOTCHarchTorus3ArchLoad #define archTorus3ArchSave _SCOTCHarchTorus3ArchSave #define archTorus3DomNum _SCOTCHarchTorus3DomNum #define archTorus3DomTerm _SCOTCHarchTorus3DomTerm #define archTorus3DomSize _SCOTCHarchTorus3DomSize /* #define archTorus3DomWght _SCOTCHarchTorus3DomWght Already a macro */ #define archTorus3DomDist _SCOTCHarchTorus3DomDist #define archTorus3DomFrst _SCOTCHarchTorus3DomFrst #define archTorus3DomLoad _SCOTCHarchTorus3DomLoad #define archTorus3DomSave _SCOTCHarchTorus3DomSave #define archTorus3DomBipart _SCOTCHarchTorus3DomBipart #define archTorus3DomMpiType _SCOTCHarchTorus3DomMpiType /* #define archVcmpltArchLoad _SCOTCHarchVcmpltArchLoad Already a macro */ /* #define archVcmpltArchSave _SCOTCHarchVcmpltArchSave Already a macro */ #define archVcmpltDomNum _SCOTCHarchVcmpltDomNum #define archVcmpltDomTerm _SCOTCHarchVcmpltDomTerm #define archVcmpltDomSize _SCOTCHarchVcmpltDomSize /* #define archVcmpltDomWght _SCOTCHarchVcmpltDomWght Already a macro */ #define archVcmpltDomDist _SCOTCHarchVcmpltDomDist #define archVcmpltDomFrst _SCOTCHarchVcmpltDomFrst #define archVcmpltDomBipart _SCOTCHarchVcmpltDomBipart #define archVcmpltDomLoad _SCOTCHarchVcmpltDomLoad #define archVcmpltDomSave _SCOTCHarchVcmpltDomSave #define archVcmpltDomBipart _SCOTCHarchVcmpltDomBipart #define archVcmpltDomMpiType _SCOTCHarchVcmpltDomMpiType /* #define archVhcubArchLoad _SCOTCHarchVhcubArchLoad Already a macro */ /* #define archVhcubArchSave _SCOTCHarchVhcubArchSave Already a macro */ #define archVhcubDomNum _SCOTCHarchVhcubDomNum #define archVhcubDomTerm _SCOTCHarchVhcubDomTerm #define archVhcubDomSize _SCOTCHarchVhcubDomSize /* #define archVhcubDomWght _SCOTCHarchVhcubDomWght Already a macro */ #define archVhcubDomDist _SCOTCHarchVhcubDomDist #define archVhcubDomFrst _SCOTCHarchVhcubDomFrst #define archVhcubDomLoad _SCOTCHarchVhcubDomLoad #define archVhcubDomSave _SCOTCHarchVhcubDomSave #define archVhcubDomBipart _SCOTCHarchVhcubDomBipart #define archVhcubDomMpiType _SCOTCHarchVhcubDomMpiType #define bdgraphInit _SCOTCHbdgraphInit #define bdgraphInit2 _SCOTCHbdgraphInit2 #define bdgraphExit _SCOTCHbdgraphExit #define bdgraphZero _SCOTCHbdgraphZero #define bdgraphbipartststratab _SCOTCHbdgraphbipartststratab #define bdgraphCheck _SCOTCHbdgraphCheck #define bdgraphGatherAll _SCOTCHbdgraphGatherAll #define bdgraphBipartBd _SCOTCHbdgraphBipartBd #define bdgraphBipartDf _SCOTCHbdgraphBipartDf #define bdgraphBipartEx _SCOTCHbdgraphBipartEx #define bdgraphBipartMl _SCOTCHbdgraphBipartMl #define bdgraphBipartSq _SCOTCHbdgraphBipartSq #define bdgraphBipartSt _SCOTCHbdgraphBipartSt #define bdgraphBipartZr _SCOTCHbdgraphBipartZr #define bdgraphStoreInit _SCOTCHbdgraphStoreInit #define bdgraphStoreExit _SCOTCHbdgraphStoreExit #define bdgraphStoreSave _SCOTCHbdgraphStoreSave #define bdgraphStoreUpdt _SCOTCHbdgraphStoreUpdt #define bgraphbipartststratab _SCOTCHbgraphbipartststratab #define bgraphInit _SCOTCHbgraphInit #define bgraphInit2 _SCOTCHbgraphInit2 #define bgraphInit3 _SCOTCHbgraphInit3 #define bgraphExit _SCOTCHbgraphExit #define bgraphCheck _SCOTCHbgraphCheck #define bgraphSwal _SCOTCHbgraphSwal #define bgraphZero _SCOTCHbgraphZero #define bgraphBipartBd _SCOTCHbgraphBipartBd #define bgraphBipartDf _SCOTCHbgraphBipartDf #define bgraphBipartDf2 _SCOTCHbgraphBipartDf2 #define bgraphBipartEx _SCOTCHbgraphBipartEx #define bgraphBipartFm _SCOTCHbgraphBipartFm #define bgraphBipartGg _SCOTCHbgraphBipartGg #define bgraphBipartGp _SCOTCHbgraphBipartGp #define bgraphBipartMl _SCOTCHbgraphBipartMl #define bgraphBipartSt _SCOTCHbgraphBipartSt #define bgraphBipartZr _SCOTCHbgraphBipartZr #define bgraphStoreInit _SCOTCHbgraphStoreInit #define bgraphStoreExit _SCOTCHbgraphStoreExit #define bgraphStoreSave _SCOTCHbgraphStoreSave #define bgraphStoreUpdt _SCOTCHbgraphStoreUpdt #if ((defined INTSIZE64) || (defined COMM)) #define commAllgatherv _SCOTCHcommAllgatherv #define commGatherv _SCOTCHcommGatherv #define commScatterv _SCOTCHcommScatterv #endif /* ((defined INTSIZE64) || (defined COMM)) */ #define dgraphAllreduceMaxSum2 _SCOTCHdgraphAllreduceMaxSum2 #define dgraphBuild _SCOTCHdgraphBuild #define dgraphBuild2 _SCOTCHdgraphBuild2 #define dgraphBuild3 _SCOTCHdgraphBuild3 #define dgraphBuild4 _SCOTCHdgraphBuild4 #define dgraphBuildGrid3D _SCOTCHdgraphBuildGrid3D #define dgraphBuildHcub _SCOTCHdgraphBuildHcub #define dgraphCheck _SCOTCHdgraphCheck #define dgraphBand _SCOTCHdgraphBand #define dgraphBandColl _SCOTCHdgraphBandColl #define dgraphBandPtop _SCOTCHdgraphBandPtop #define dgraphCoarsen _SCOTCHdgraphCoarsen #define dgraphExit _SCOTCHdgraphExit #define dgraphFold _SCOTCHdgraphFold #define dgraphFold2 _SCOTCHdgraphFold2 #define dgraphFoldComm _SCOTCHdgraphFoldComm #define dgraphFoldDup _SCOTCHdgraphFoldDup #define dgraphFree _SCOTCHdgraphFree #define dgraphGather _SCOTCHdgraphGather #define dgraphGatherAll _SCOTCHdgraphGatherAll #define dgraphGatherAll2 _SCOTCHdgraphGatherAll2 /* #define dgraphGhst _SCOTCHdgraphGhst Already a macro */ /* #define dgraphGhstReplace _SCOTCHdgraphGhstReplace Already a macro */ #define dgraphGhst2 _SCOTCHdgraphGhst2 #define dgraphHaloSync _SCOTCHdgraphHaloSync #define dgraphHaloAsync _SCOTCHdgraphHaloAsync #define dgraphHaloWait _SCOTCHdgraphHaloWait #define dgraphHaloCheck _SCOTCHdgraphHaloCheck #define dgraphInduceList _SCOTCHdgraphInduceList #define dgraphInducePart _SCOTCHdgraphInducePart #define dgraphInit _SCOTCHdgraphInit #define dgraphLoad _SCOTCHdgraphLoad #define dgraphMatchInit _SCOTCHdgraphMatchInit #define dgraphMatchExit _SCOTCHdgraphMatchExit #define dgraphMatchSync _SCOTCHdgraphMatchSync #define dgraphMatchSyncColl _SCOTCHdgraphMatchSyncColl #define dgraphMatchSyncPtop _SCOTCHdgraphMatchSyncPtop #define dgraphMatchCheck _SCOTCHdgraphMatchCheck #define dgraphMatchSc _SCOTCHdgraphMatchSc #define dgraphMatchHy _SCOTCHdgraphMatchHy #define dgraphMatchLc _SCOTCHdgraphMatchLc #define dgraphMatchLy _SCOTCHdgraphMatchLy #define dgraphSave _SCOTCHdgraphSave #define dgraphScatter _SCOTCHdgraphScatter #define dgraphView _SCOTCHdgraphView #define dmapInit _SCOTCHdmapInit #define dmapExit _SCOTCHdmapExit #define dmapAdd _SCOTCHdmapAdd #define dmapTerm _SCOTCHdmapTerm #define dmapSave _SCOTCHdmapSave #define dorderDispose _SCOTCHdorderDispose #define dorderExit _SCOTCHdorderExit #define dorderFree _SCOTCHdorderFree #define dorderFrst _SCOTCHdorderFrst #define dorderGather _SCOTCHdorderGather #define dorderGatherTree _SCOTCHdorderGatherTree #define dorderInit _SCOTCHdorderInit #define dorderNew _SCOTCHdorderNew #define dorderNewSequ _SCOTCHdorderNewSequ #define dorderNewSequIndex _SCOTCHdorderNewSequIndex #define dorderPerm _SCOTCHdorderPerm #define dorderSave _SCOTCHdorderSave #define dorderSaveBlock _SCOTCHdorderSaveBlock #define dorderSaveMap _SCOTCHdorderSaveMap #define dorderSaveTree _SCOTCHdorderSaveTree #define dorderSaveTree2 _SCOTCHdorderSaveTree2 #define dorderCblkDist _SCOTCHdorderCblkDist #define dorderTreeDist _SCOTCHdorderTreeDist #define gainTablAddLin _SCOTCHgainTablAddLin #define gainTablAddLog _SCOTCHgainTablAddLog #define gainTablCheck _SCOTCHgainTablCheck #ifdef SCOTCH_DEBUG_GAIN1 /* If not already redefined as accelerated macro */ #define gainTablDel _SCOTCHgainTablDel #endif /* SCOTCH_DEBUG_GAIN1 */ #define gainTablExit _SCOTCHgainTablExit #define gainTablFree _SCOTCHgainTablFree #define gainTablFrst _SCOTCHgainTablFrst #define gainTablInit _SCOTCHgainTablInit #define gainTablNext _SCOTCHgainTablNext #define geomExit _SCOTCHgeomExit #define geomInit _SCOTCHgeomInit #define graphInit _SCOTCHgraphInit #define graphExit _SCOTCHgraphExit #define graphFree _SCOTCHgraphFree #define graphLoad _SCOTCHgraphLoad #define graphLoad2 _SCOTCHgraphLoad2 #define graphSave _SCOTCHgraphSave #define graphBase _SCOTCHgraphBase #define graphCheck _SCOTCHgraphCheck #define graphCoarsen _SCOTCHgraphCoarsen #define graphInduceList _SCOTCHgraphInduceList #define graphInducePart _SCOTCHgraphInducePart #define graphGeomLoadChac _SCOTCHgraphGeomLoadChac #define graphGeomLoadHabo _SCOTCHgraphGeomLoadHabo #define graphGeomLoadMmkt _SCOTCHgraphGeomLoadMmkt #define graphGeomLoadScot _SCOTCHgraphGeomLoadScot #define graphGeomSaveChac _SCOTCHgraphGeomSaveChac #define graphGeomSaveScot _SCOTCHgraphGeomSaveScot #define graphGeomSaveMmkt _SCOTCHgraphGeomSaveMmkt #define graphPtscotch _SCOTCHgraphPtscotch #define hallOrderHdHalmd _SCOTCHhallOrderHdHalmd #define hallOrderHfR2hamdf4 _SCOTCHhallOrderHfR2hamdf4 #define hallOrderHxBuild _SCOTCHhallOrderHxBuild #define hallOrderHxTree _SCOTCHhallOrderHxTree #define hdgraphorderststratab _SCOTCHhdgraphorderststratab #define hdgraphInit _SCOTCHhdgraphInit #define hdgraphExit _SCOTCHhdgraphExit #define hdgraphCheck _SCOTCHhdgraphCheck #define hdgraphFold _SCOTCHhdgraphFold #define hdgraphFold2 _SCOTCHhdgraphFold2 #define hdgraphGather _SCOTCHhdgraphGather #define hdgraphInduceList _SCOTCHhdgraphInduceList #define hdgraphOrderNd _SCOTCHhdgraphOrderNd #define hdgraphOrderSi _SCOTCHhdgraphOrderSi #define hdgraphOrderSq _SCOTCHhdgraphOrderSq #define hdgraphOrderSq2 _SCOTCHhdgraphOrderSq2 #define hdgraphOrderSt _SCOTCHhdgraphOrderSt #define hgraphorderststratab _SCOTCHhgraphorderststratab #define hgraphInit _SCOTCHhgraphInit #define hgraphExit _SCOTCHhgraphExit #define hgraphFree _SCOTCHhgraphFree #define hgraphInduceList _SCOTCHhgraphInduceList #define hgraphCheck _SCOTCHhgraphCheck #define hgraphOrderBl _SCOTCHhgraphOrderBl #define hgraphOrderCp _SCOTCHhgraphOrderCp #define hgraphOrderGp _SCOTCHhgraphOrderGp #define hgraphOrderHd _SCOTCHhgraphOrderHd #define hgraphOrderHf _SCOTCHhgraphOrderHf #define hgraphOrderHxFill _SCOTCHhgraphOrderHxFill #define hgraphOrderNd _SCOTCHhgraphOrderNd #define hgraphOrderSi _SCOTCHhgraphOrderSi #define hgraphOrderSt _SCOTCHhgraphOrderSt #define hmeshorderststratab _SCOTCHhmeshorderststratab #define hmeshExit _SCOTCHhmeshExit #define hmeshBase _SCOTCHhmeshBase #define hmeshCheck _SCOTCHhmeshCheck #define hmeshInducePart _SCOTCHhmeshInducePart #define hmeshHgraph _SCOTCHhmeshHgraph #define hmeshMesh _SCOTCHhmeshMesh #define hmeshOrderBl _SCOTCHhmeshOrderBl #define hmeshOrderCp _SCOTCHhmeshOrderCp #define hmeshOrderGp _SCOTCHhmeshOrderGp #define hmeshOrderGr _SCOTCHhmeshOrderGr #define hmeshOrderHd _SCOTCHhmeshOrderHd #define hmeshOrderHf _SCOTCHhmeshOrderHf #define hmeshOrderHxFill _SCOTCHhmeshOrderHxFill #define hmeshOrderNd _SCOTCHhmeshOrderNd #define hmeshOrderSi _SCOTCHhmeshOrderSi #define hmeshOrderSt _SCOTCHhmeshOrderSt #define kdgraphmapststratab _SCOTCHkdgraphmapststratab #define kdgraphInit _SCOTCHkdgraphInit #define kdgraphExit _SCOTCHkdgraphExit #define kdgraphMapRb _SCOTCHkdgraphMapRb #define kdgraphMapRbAdd2 _SCOTCHkdgraphMapRbAdd2 #define kdgraphMapRbAddBoth _SCOTCHkdgraphMapRbAddBoth #define kdgraphMapRbAddOne _SCOTCHkdgraphMapRbAddOne #define kdgraphMapRbAddPart _SCOTCHkdgraphMapRbAddPart #define kdgraphMapRbMap _SCOTCHkdgraphMapRbMap #define kdgraphMapRbPart _SCOTCHkdgraphMapRbPart #define kdgraphMapSt _SCOTCHkdgraphMapSt #define kgraphmapststratab _SCOTCHkgraphmapststratab #define kgraphInit _SCOTCHkgraphInit #define kgraphExit _SCOTCHkgraphExit #define kgraphCheck _SCOTCHkgraphCheck #define kgraphFrst _SCOTCHkgraphFrst #define kgraphMapMl _SCOTCHkgraphMapMl #define kgraphMapRb _SCOTCHkgraphMapRb #define kgraphMapRbMap _SCOTCHkgraphMapRbMap #define kgraphMapRbPart _SCOTCHkgraphMapRbPart #define kgraphMapSt _SCOTCHkgraphMapSt #define listInit _SCOTCHlistInit #define listExit _SCOTCHlistExit #define listAlloc _SCOTCHlistAlloc #define listFree _SCOTCHlistFree #define listLoad _SCOTCHlistLoad #define listSave _SCOTCHlistSave #define listSort _SCOTCHlistSort #define listCopy _SCOTCHlistCopy #define mapInit _SCOTCHmapInit #define mapInit2 _SCOTCHmapInit2 #define mapExit _SCOTCHmapExit #define mapLoad _SCOTCHmapLoad #define mapSave _SCOTCHmapSave #define meshInit _SCOTCHmeshInit #define meshExit _SCOTCHmeshExit #define meshFree _SCOTCHmeshFree #define meshLoad _SCOTCHmeshLoad #define meshSave _SCOTCHmeshSave #define meshBase _SCOTCHmeshBase #define meshGraph _SCOTCHmeshGraph #define meshCoarsen _SCOTCHmeshCoarsen #define meshInduceList _SCOTCHmeshInduceList #define meshInducePart _SCOTCHmeshInducePart #define meshInduceSepa _SCOTCHmeshInduceSepa #define meshCheck _SCOTCHmeshCheck #define meshGeomLoadHabo _SCOTCHmeshGeomLoadHabo #define meshGeomLoadScot _SCOTCHmeshGeomLoadScot #define meshGeomSaveScot _SCOTCHmeshGeomSaveScot #define orderInit _SCOTCHorderInit #define orderExit _SCOTCHorderExit #define orderLoad _SCOTCHorderLoad #define orderSave _SCOTCHorderSave #define orderSaveMap _SCOTCHorderSaveMap #define orderSaveTree _SCOTCHorderSaveTree #define orderCheck _SCOTCHorderCheck #define orderPeri _SCOTCHorderPeri #define orderRang _SCOTCHorderRang #define orderTree _SCOTCHorderTree #define parsermethtokentab _SCOTCHparsermethtokentab #define parserparamcurr _SCOTCHparserparamcurr #define parserstratcurr _SCOTCHparserstratcurr #define parserstrattab _SCOTCHparserstrattab #define stratdummy _SCOTCHstratdummy #define stratInit _SCOTCHstratInit #define stratExit _SCOTCHstratExit #define stratSave _SCOTCHstratSave #define stratCondEval _SCOTCHstratCondEval #define stratCondExit _SCOTCHstratCondExit #define stratCondSave _SCOTCHstratCondSave #define stratParserInit _SCOTCHstratParserInit #define stratParserInput _SCOTCHstratParserInput #define stratParserLex _SCOTCHstratParserLex #define stratParserRemain _SCOTCHstratParserRemain #define stratParserSelect _SCOTCHstratParserSelect #define stratParserError _SCOTCHstratParserError #define stratParserParse _SCOTCHstratParserParse #define stratParserParse2 _SCOTCHstratParserParse2 #define stratTestEval _SCOTCHstratTestEval #define stratTestExit _SCOTCHstratTestExit #define stratTestSave _SCOTCHstratTestSave #define vdgraphseparateststratab _SCOTCHvdgraphseparateststratab #define vdgraphCheck _SCOTCHvdgraphCheck #define vdgraphExit _SCOTCHvdgraphExit #define vdgraphGatherAll _SCOTCHvdgraphGatherAll #define vdgraphInit _SCOTCHvdgraphInit #define vdgraphSeparateBd _SCOTCHvdgraphSeparateBd #define vdgraphSeparateDf _SCOTCHvdgraphSeparateDf #define vdgraphSeparateMl _SCOTCHvdgraphSeparateMl #define vdgraphSeparateSq _SCOTCHvdgraphSeparateSq #define vdgraphSeparateSt _SCOTCHvdgraphSeparateSt #define vdgraphSeparateZr _SCOTCHvdgraphSeparateZr #define vdgraphStoreExit _SCOTCHvdgraphStoreExit #define vdgraphStoreInit _SCOTCHvdgraphStoreInit #define vdgraphStoreSave _SCOTCHvdgraphStoreSave #define vdgraphStoreUpdt _SCOTCHvdgraphStoreUpdt #define vdgraphZero _SCOTCHvdgraphZero #define vgraphseparateststratab _SCOTCHvgraphseparateststratab #define vgraphInit _SCOTCHvgraphInit #define vgraphExit _SCOTCHvgraphExit #define vgraphCheck _SCOTCHvgraphCheck #define vgraphZero _SCOTCHvgraphZero #define vgraphSeparateBd _SCOTCHvgraphSeparateBd #define vgraphSeparateEs _SCOTCHvgraphSeparateEs #define vgraphSeparateFm _SCOTCHvgraphSeparateFm #define vgraphSeparateGg _SCOTCHvgraphSeparateGg #define vgraphSeparateGp _SCOTCHvgraphSeparateGp #define vgraphSeparateMl _SCOTCHvgraphSeparateMl #define vgraphSeparateMt _SCOTCHvgraphSeparateMt #define vgraphSeparateSt _SCOTCHvgraphSeparateSt #define vgraphSeparateTh _SCOTCHvgraphSeparateTh #define vgraphSeparateVw _SCOTCHvgraphSeparateVw #define vgraphSeparateZr _SCOTCHvgraphSeparateZr #define vgraphStoreInit _SCOTCHvgraphStoreInit #define vgraphStoreExit _SCOTCHvgraphStoreExit #define vgraphStoreSave _SCOTCHvgraphStoreSave #define vgraphStoreUpdt _SCOTCHvgraphStoreUpdt #define vmeshseparateststratab _SCOTCHvmeshseparateststratab #define vmeshExit _SCOTCHvmeshExit #define vmeshCheck _SCOTCHvmeshCheck #define vmeshZero _SCOTCHvmeshZero #define vmeshSeparateFm _SCOTCHvmeshSeparateFm #define vmeshSeparateGg _SCOTCHvmeshSeparateGg #define vmeshSeparateGr _SCOTCHvmeshSeparateGr #define vmeshSeparateMl _SCOTCHvmeshSeparateMl #define vmeshSeparateSt _SCOTCHvmeshSeparateSt #define vmeshSeparateZr _SCOTCHvmeshSeparateZr #define vmeshStoreInit _SCOTCHvmeshStoreInit #define vmeshStoreExit _SCOTCHvmeshStoreExit #define vmeshStoreSave _SCOTCHvmeshStoreSave #define vmeshStoreUpdt _SCOTCHvmeshStoreUpdt #endif /* SCOTCH_RENAME */ scotch-5.1.12b.dfsg/src/libscotch/dgraph_fold.c0000644000175300017530000011020011631334325021542 0ustar hazelscthazelsct/* Copyright 2007-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_fold.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the distributed **/ /** source graph folding function. **/ /** **/ /** DATES : # Version 5.0 : from : 10 aug 2006 **/ /** to : 27 jun 2008 **/ /** # Version 5.1 : from : 12 nov 2008 **/ /** to : 04 jan 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_fold.h" #include "dgraph_fold_comm.h" /******************************/ /* */ /* This routine handles */ /* distributed source graphs. */ /* */ /******************************/ /* This routine builds a folded graph by merging graph ** data to the processes of the first half or to the ** second half of the communicator. ** The key value of the folded communicator is not ** changed as it is not relevant. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphFold ( const Dgraph * restrict const orggrafptr, const int partval, /* 0 for first half, 1 for second half */ Dgraph * restrict const fldgrafptr, const void * restrict const vertinfoptrin, /* Based array of informations which must be kept, like coarmulttax */ void ** restrict const vertinfoptrout, /* Based array of informations which must be kept, like coarmulttax */ MPI_Datatype vertinfotype) { int fldprocnbr; int fldprocnum; /* Index of local process in folded communicator */ int fldproccol; /* Color of receiver or not wanted in communicator */ MPI_Comm fldproccomm; /* Communicator of folded part */ int o; fldprocnbr = (orggrafptr->procglbnbr + 1) / 2; fldprocnum = orggrafptr->proclocnum; if (partval == 1) { fldprocnum = fldprocnum - fldprocnbr; fldprocnbr = orggrafptr->procglbnbr - fldprocnbr; } fldproccol = ((fldprocnum >= 0) && (fldprocnum < fldprocnbr)) ? 0 : MPI_UNDEFINED; if (MPI_Comm_split (orggrafptr->proccomm, fldproccol, fldprocnum, &fldproccomm) != MPI_SUCCESS) { errorPrint ("dgraphFold: communication error"); return (1); } o = dgraphFold2 (orggrafptr, partval, fldgrafptr, fldproccomm, vertinfoptrin, vertinfoptrout, vertinfotype); fldgrafptr->prockeyval = fldproccol; /* Key of folded communicator is always zero if no duplication occurs */ return (o); } int dgraphFold2 ( const Dgraph * restrict const orggrafptr, const int partval, /* 0 for first half, 1 for second half */ Dgraph * restrict const fldgrafptr, MPI_Comm fldproccomm, const void * restrict const vertinfoptrin, /* Based array of informations which must be kept, like coarmulttax */ void ** restrict const vertinfoptrout, /* Based array of informations which must be kept, like coarmulttax */ MPI_Datatype vertinfotype) { int fldcommtypval; /* Type of communication for this process */ DgraphFoldCommData * restrict fldcommdattab; /* Array of two communication data */ Gnum * restrict fldcommvrttab; /* Starting global send indices of communications */ Gnum * restrict fldvertidxtab; /* Start indices of vertex arrays */ Gnum * restrict fldedgeidxtab; /* Start indices of edge arrays */ Gnum * restrict fldedgecnttab; /* Number of edges exchanged during each communication */ Gnum * restrict fldedgecnptab; /* Temporary save for fldedgecnttab for MPI standard */ Gnum fldvertlocnbr; /* Number of vertices in local folded part */ Gnum fldedgelocsiz; /* (Upper bound of) number of edges in folded graph */ Gnum fldedlolocsiz; /* (Upper bound of) number of edge loads in folded graph */ int fldprocglbnbr; int fldproclocnum; /* Index of local process in folded communicator */ int fldvertadjnbr; Gnum * restrict fldvertadjtab; /* Array of global start indices for adjustment slots */ Gnum * restrict fldvertdlttab; /* Array of index adjustments for original global indices */ int cheklocval; int chekglbval; int commmax; int commnbr; int requnbr; MPI_Request * restrict requtab; int vertinfosize; /* Size of one information */ #ifdef SCOTCH_DEBUG_DGRAPH2 if (orggrafptr->vendloctax != (orggrafptr->vertloctax + 1)) { errorPrint ("dgraphFold: graph must be compact"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ fldprocglbnbr = (orggrafptr->procglbnbr + 1) / 2; if (partval == 1) { fldproclocnum = orggrafptr->proclocnum - fldprocglbnbr; fldprocglbnbr = orggrafptr->procglbnbr - fldprocglbnbr; } else fldproclocnum = orggrafptr->proclocnum; fldcommtypval = ((fldproclocnum >= 0) && (fldproclocnum < fldprocglbnbr)) ? DGRAPHFOLDCOMMRECV : DGRAPHFOLDCOMMSEND; if (vertinfoptrin != NULL) MPI_Type_size (vertinfotype, &vertinfosize); cheklocval = 0; fldcommdattab = NULL; fldvertidxtab = NULL; if (fldcommtypval == DGRAPHFOLDCOMMRECV) { /* If we are going to receive */ #ifdef SCOTCH_DEBUG_DGRAPH2 if (fldgrafptr == NULL) { errorPrint ("dgraphFold2: invalid parameters (1)"); return (1); } if (fldproccomm == MPI_COMM_NULL) { errorPrint ("dgraphFold2: invalid parameters (2)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ memSet (fldgrafptr, 0, sizeof (Dgraph)); /* Pre-initialize graph fields */ fldgrafptr->proccomm = fldproccomm; fldgrafptr->procglbnbr = fldprocglbnbr; fldgrafptr->proclocnum = fldproclocnum; fldgrafptr->flagval = DGRAPHFREEALL | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; /* For premature freeing on error */ if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ &fldgrafptr->procdsptab, (size_t) ((fldprocglbnbr + 1) * sizeof (Gnum)), &fldgrafptr->proccnttab, (size_t) (fldprocglbnbr * sizeof (Gnum)), &fldgrafptr->procngbtab, (size_t) (fldprocglbnbr * sizeof (int)), &fldgrafptr->procrcvtab, (size_t) (fldprocglbnbr * sizeof (int)), &fldgrafptr->procsndtab, (size_t) (fldprocglbnbr * sizeof (int)), NULL) == NULL) { errorPrint ("dgraphFold2: out of memory (1)"); cheklocval = 1; } else if (dgraphFoldComm (orggrafptr, partval, &commmax, &fldcommtypval, &fldcommdattab, &fldcommvrttab, /* Process can become a sender receiver */ fldgrafptr->proccnttab, &fldvertadjnbr, &fldvertadjtab, &fldvertdlttab) != 0) { errorPrint ("dgraphFold2: cannot compute folding communications (1)"); cheklocval = 1; } else { Gnum fldvelolocnbr; if ((fldcommtypval & DGRAPHFOLDCOMMSEND) == 0) { /* If process is a normal receiver */ int i; for (i = 0, fldvertlocnbr = 0; (i < commmax) && (fldcommdattab[i].procnum != -1); i ++) fldvertlocnbr += fldcommdattab[i].vertnbr; commnbr = i; fldedgelocsiz = orggrafptr->edgeglbsmx * i; /* Upper bound on received edges */ if ((orggrafptr->degrglbmax > 0) && (fldvertlocnbr < (fldedgelocsiz / orggrafptr->degrglbmax))) /* Choose best upper bound on number of edges (avoid multiply overflow) */ fldedgelocsiz = fldvertlocnbr * orggrafptr->degrglbmax; fldedgelocsiz += orggrafptr->edgelocnbr; /* Add local edges and vertices */ fldvertlocnbr += orggrafptr->vertlocnbr; } else { /* Process is a sender receiver */ fldvertlocnbr = fldcommvrttab[0] - orggrafptr->procvrttab[orggrafptr->proclocnum]; /* Communications will remove vertices */ fldedgelocsiz = orggrafptr->vertloctax[fldvertlocnbr + orggrafptr->baseval] - orggrafptr->baseval; /* Exact number of edges */ fldgrafptr->edgelocnbr = fldgrafptr->edgelocsiz = fldedgelocsiz; } fldvelolocnbr = (orggrafptr->veloloctax != NULL) ? fldvertlocnbr : 0; if (memAllocGroup ((void **) (void *) /* Allocate distributed graph public data */ &fldgrafptr->vertloctax, (size_t) ((fldvertlocnbr + 1) * sizeof (Gnum)), &fldgrafptr->vnumloctax, (size_t) ( fldvertlocnbr * sizeof (Gnum)), &fldgrafptr->veloloctax, (size_t) ( fldvelolocnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphFold2: out of memory (2)"); cheklocval = 1; } else if (fldgrafptr->vertloctax -= orggrafptr->baseval, fldgrafptr->vnumloctax -= orggrafptr->baseval, fldgrafptr->vendloctax = fldgrafptr->vertloctax + 1, /* Folded graph is compact */ fldgrafptr->veloloctax = ((orggrafptr->veloloctax != NULL) ? (fldgrafptr->veloloctax - orggrafptr->baseval) : NULL), fldedlolocsiz = ((orggrafptr->edloloctax != NULL) ? fldedgelocsiz : 0), (fldgrafptr->edgeloctax = memAlloc ((fldedgelocsiz + fldedlolocsiz) * sizeof (Gnum))) == NULL) { /* Allocate single array for both edge arrays */ errorPrint ("dgraphFold2: out of memory (3)"); cheklocval = 1; } else { if (vertinfoptrin != NULL) { if ((*vertinfoptrout = (byte *) memAlloc (fldvertlocnbr * vertinfosize)) == NULL) { errorPrint ("dgraphFold2: out of memory (4)"); cheklocval = 1; } else { *((byte **) vertinfoptrout) -= (vertinfosize * orggrafptr->baseval); } } fldgrafptr->edgeloctax -= orggrafptr->baseval; /* Do not care about the validity of edloloctax at this stage */ } } } else { /* Process is a sender */ #ifdef SCOTCH_DEBUG_HDGRAPH2 if (fldproccomm != MPI_COMM_NULL) { errorPrint ("dgraphFold2: invalid parameters (3)"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ if (dgraphFoldComm (orggrafptr, partval, &commmax, &fldcommtypval, &fldcommdattab, &fldcommvrttab, NULL, NULL, NULL, NULL) != 0) { errorPrint ("dgraphFold2: cannot compute folding communications (2)"); cheklocval = 1; } } if ((cheklocval == 0) && (memAllocGroup ((void **) (void *) /* Allocate folding data */ &fldvertidxtab, (size_t) (commmax * sizeof (Gnum)), &fldedgeidxtab, (size_t) (commmax * sizeof (Gnum)), &fldedgecnttab, (size_t) (commmax * sizeof (Gnum)), &fldedgecnptab, (size_t) (commmax * sizeof (Gnum)), &requtab, (size_t) (commmax * DGRAPHFOLDTAGNBR * sizeof (MPI_Request)), NULL) == NULL)) { errorPrint ("dgraphFold2: out of memory (5)"); cheklocval = 1; } #ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication cannot be merged with a useful one */ if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, orggrafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphFold2: communication error (1)"); chekglbval = 1; } #else /* SCOTCH_DEBUG_DGRAPH1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_DGRAPH1 */ if (chekglbval != 0) { if ((fldcommtypval & DGRAPHFOLDCOMMRECV) != 0) { if (fldvertidxtab != NULL) memFree (fldvertidxtab); /* Free group leader */ if (fldcommdattab != NULL) memFree (fldcommdattab); dgraphExit (fldgrafptr); } return (1); } requnbr = 0; /* Communications without further processing are placed at beginning of array */ if ((fldcommtypval & DGRAPHFOLDCOMMSEND) != 0) { /* If process is (also) a sender */ Gnum vertsndbas; Gnum vertsndnbr; int i; vertsndnbr = ((fldcommtypval & DGRAPHFOLDCOMMRECV) != 0) ? (fldcommvrttab[0] - orggrafptr->procvrttab[orggrafptr->proclocnum]) : 0; /* If process is also a receiver, start sending after kept vertices */ for (i = 0, vertsndbas = orggrafptr->baseval; /* For all send communications to perform */ (i < commmax) && (fldcommdattab[i].procnum != -1) && (cheklocval == 0); i ++) { vertsndbas += vertsndnbr; vertsndnbr = fldcommdattab[i].vertnbr; fldvertidxtab[i] = vertsndbas; fldedgeidxtab[i] = orggrafptr->vertloctax[vertsndbas]; fldedgecnptab[i] = /* Save fldedgecnttab in temporary array to read it while MPI communication in progress */ fldedgecnttab[i] = orggrafptr->vertloctax[vertsndbas + vertsndnbr] - orggrafptr->vertloctax[vertsndbas]; /* Graph is compact */ if (MPI_Isend (&fldedgecnptab[i], 1, GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGVLBLLOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("dgraphFold2: communication error (2)"); cheklocval = 1; } } commnbr = i; for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { if (MPI_Isend (orggrafptr->vertloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGVERTLOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("dgraphFold2: communication error (3)"); cheklocval = 1; } } for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { if (MPI_Isend (orggrafptr->edgeloctax + fldedgeidxtab[i], fldedgecnttab[i], GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGEDGELOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("dgraphFold2: communication error (4)"); cheklocval = 1; } } if (orggrafptr->veloloctax != NULL) { for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { if (MPI_Isend (orggrafptr->veloloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGVELOLOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("dgraphFold2: communication error (5)"); cheklocval = 1; } } } for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { int procsndnum; /* Rank of process to send to */ procsndnum = fldcommdattab[i].procnum; if ((orggrafptr->edloloctax != NULL) && (MPI_Isend (orggrafptr->edloloctax + fldedgeidxtab[i], fldedgecnttab[i], GNUM_MPI, procsndnum, TAGFOLD + TAGEDLOLOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS)) { errorPrint ("dgraphFold2: communication error (6)"); cheklocval = 1; } else if ((orggrafptr->vnumloctax != NULL) && (MPI_Isend (orggrafptr->vnumloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, procsndnum, TAGFOLD + TAGVNUMLOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS)) { errorPrint ("dgraphFold2: communication error (7)"); cheklocval = 1; } else if ((vertinfoptrin != NULL) && (MPI_Isend ((byte *) vertinfoptrin + (fldvertidxtab[i] * vertinfosize), fldcommdattab[i].vertnbr, vertinfotype, procsndnum, TAGFOLD + TAGDATALOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS)) { errorPrint ("dgraphFold2: communication error (8)"); cheklocval = 1; } } } /* Communications of sender-receivers will be completed in the receiving phase */ if ((fldcommtypval & DGRAPHFOLDCOMMRECV) != 0) { /* If process is (also) a receiver */ Gnum orgvertlocnbr; Gnum orgvertlocnnd; Gnum orgvertlocmin; Gnum orgvertlocmax; Gnum fldvertlocadj; Gnum fldvelolocsum; Gnum fldedgelocnum; Gnum fldedgelocnnd; int fldprocnum; int procngbmin; int procngbmax; int i; const Gnum * restrict const orgedgeloctax = orggrafptr->edgeloctax; Gnum * restrict const fldedgeloctax = fldgrafptr->edgeloctax; fldgrafptr->procvrttab = fldgrafptr->procdsptab; /* Graph does not have holes */ fldgrafptr->procdsptab[0] = orggrafptr->baseval; /* Build private data of folded graph and array */ for (fldprocnum = 0; fldprocnum < fldprocglbnbr; fldprocnum ++) /* New subdomain indices start from baseval */ fldgrafptr->procdsptab[fldprocnum + 1] = fldgrafptr->procdsptab[fldprocnum] + fldgrafptr->proccnttab[fldprocnum]; if ((fldcommtypval & DGRAPHFOLDCOMMSEND) == 0) { /* If process is a normal receiver */ Gnum fldedgelocbas; Gnum fldvertrcvbas; Gnum fldvertrcvnbr; for (i = 0, fldvertrcvbas = orggrafptr->vertlocnnd, fldvertrcvnbr = 0; /* For all receive communications to perform */ (i < commnbr) && (cheklocval == 0); i ++) { fldvertrcvbas += fldvertrcvnbr; fldvertrcvnbr = fldcommdattab[i].vertnbr; fldvertidxtab[i] = fldvertrcvbas; if (MPI_Irecv (&fldedgecnttab[i], 1, GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGVLBLLOCTAB, orggrafptr->proccomm, &requtab[DGRAPHFOLDTAGENBR * commmax + i]) != MPI_SUCCESS) { errorPrint ("dgraphFold2: communication error (9)"); cheklocval = 1; } } for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { /* Let these communications progress while we process the edge size messages */ if (MPI_Irecv (fldgrafptr->vertloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGVERTLOCTAB, orggrafptr->proccomm, &requtab[DGRAPHFOLDTAGVERT * commmax + i]) != MPI_SUCCESS) { errorPrint ("dgraphFold2: communication error (10)"); cheklocval = 1; } } MPI_Waitall (commnbr, &requtab[DGRAPHFOLDTAGENBR * commmax], MPI_STATUSES_IGNORE); for (i = 0, fldedgelocbas = orggrafptr->vertloctax[orggrafptr->vertlocnnd]; (i < commnbr) && (cheklocval == 0); i ++) { fldedgeidxtab[i] = fldedgelocbas; fldedgelocbas += fldedgecnttab[i]; if (MPI_Irecv (fldgrafptr->edgeloctax + fldedgeidxtab[i], fldedgecnttab[i], GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGEDGELOCTAB, orggrafptr->proccomm, &requtab[DGRAPHFOLDTAGEDGE * commmax + i]) != MPI_SUCCESS) { errorPrint ("dgraphFold2: communication error (11)"); cheklocval = 1; } } fldgrafptr->edgelocnbr = /* Get number of local edges */ fldgrafptr->edgelocsiz = fldedgelocbas - orggrafptr->baseval; if (orggrafptr->veloloctax != NULL) { for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { if (MPI_Irecv (fldgrafptr->veloloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGVELOLOCTAB, orggrafptr->proccomm, &requtab[DGRAPHFOLDTAGVELO * commmax + i]) != MPI_SUCCESS) { errorPrint ("dgraphFold2: communication error (12)"); cheklocval = 1; } } } if (orggrafptr->edloloctax != NULL) { fldgrafptr->edloloctax = fldgrafptr->edgeloctax + fldgrafptr->edgelocnbr; /* Set start index of edge load array */ for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { if (MPI_Irecv (fldgrafptr->edloloctax + fldedgeidxtab[i], fldedgecnttab[i], GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGEDLOLOCTAB, orggrafptr->proccomm, &requtab[DGRAPHFOLDTAGEDLO * commmax + i]) != MPI_SUCCESS) { errorPrint ("dgraphFold2: communication error (13)"); cheklocval = 1; } } } for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { int procrcvnum; /* Rank of process to receive from */ Gnum vertrcvnbr; procrcvnum = fldcommdattab[i].procnum; vertrcvnbr = fldcommdattab[i].vertnbr; if ((orggrafptr->vnumloctax != NULL) && (MPI_Irecv (fldgrafptr->vnumloctax + fldvertidxtab[i], vertrcvnbr, GNUM_MPI, procrcvnum, TAGFOLD + TAGVNUMLOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS)) { errorPrint ("dgraphFold2: communication error (14)"); cheklocval = 1; } else if ((vertinfoptrin != NULL) && (MPI_Irecv ((byte *) (*vertinfoptrout) + (fldvertidxtab[i] * vertinfosize), vertrcvnbr, vertinfotype, procrcvnum, TAGFOLD + TAGDATALOCTAB, orggrafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS)) { errorPrint ("dgraphFold2: communication error (15)"); cheklocval = 1; } } orgvertlocnbr = orggrafptr->vertlocnbr; /* Process all local vertices */ orgvertlocnnd = orggrafptr->vertlocnnd; if (orggrafptr->vnumloctax == NULL) { /* If original graph does not have vertex numbers, create remote parts of vertex number array */ Gnum fldvertlocnum; Gnum fldvertlocadj; int i; Gnum * restrict const fldvnumloctax = fldgrafptr->vnumloctax; for (i = 0, fldvertlocnum = orgvertlocnnd; i < commnbr; i ++) { Gnum fldvertlocnnd; for (fldvertlocnnd = fldvertlocnum + fldcommdattab[i].vertnbr, fldvertlocadj = fldcommvrttab[i]; fldvertlocnum < fldvertlocnnd; fldvertlocnum ++) fldvnumloctax[fldvertlocnum] = fldvertlocadj ++; } } fldedgelocnnd = orggrafptr->vertloctax[orggrafptr->vertlocnnd]; fldvelolocsum = orggrafptr->velolocsum; /* In case there are vertex loads, we keep all of existing load */ } else { /* Receiver process is also a sender */ orgvertlocnbr = fldvertlocnbr; /* Process only remaining local vertices */ orgvertlocnnd = fldvertlocnbr + orggrafptr->baseval; if (orggrafptr->veloloctax != NULL) { /* If original graph has vertex loads */ Gnum fldvertlocnum; for (fldvertlocnum = orggrafptr->baseval, fldvelolocsum = 0; /* Accumulate load sum of remaining part */ fldvertlocnum < orgvertlocnnd; fldvertlocnum ++) fldvelolocsum += orggrafptr->veloloctax[fldvertlocnum]; } fldedgelocnnd = orggrafptr->vertloctax[orgvertlocnnd]; /* Reorder remaining local part of edge array */ if (orggrafptr->edloloctax != NULL) fldgrafptr->edloloctax = fldgrafptr->edgeloctax + fldgrafptr->edgelocnbr; /* Set start index of edge load array */ commnbr = 0; /* Turn sender-receiver into normal receiver without any communications to perform */ } for (procngbmin = 0, procngbmax = fldvertadjnbr; /* Initialize search accelerator */ procngbmax - procngbmin > 1; ) { int procngbmed; procngbmed = (procngbmax + procngbmin) / 2; if (fldvertadjtab[procngbmed] <= orggrafptr->procvrttab[orggrafptr->proclocnum]) procngbmin = procngbmed; else procngbmax = procngbmed; } orgvertlocmin = fldvertadjtab[procngbmin]; orgvertlocmax = fldvertadjtab[procngbmax]; fldvertlocadj = fldvertdlttab[procngbmin]; for (fldedgelocnum = orggrafptr->baseval; fldedgelocnum < fldedgelocnnd; fldedgelocnum ++) { Gnum orgvertlocend; orgvertlocend = orgedgeloctax[fldedgelocnum]; if ((orgvertlocend >= orgvertlocmin) && /* If end vertex is local */ (orgvertlocend < orgvertlocmax)) fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertlocadj; else { /* End vertex is not local */ int procngbnum; int procngbmax; for (procngbnum = 0, procngbmax = fldvertadjnbr; procngbmax - procngbnum > 1; ) { int procngbmed; procngbmed = (procngbmax + procngbnum) / 2; if (fldvertadjtab[procngbmed] <= orgvertlocend) procngbnum = procngbmed; else procngbmax = procngbmed; } fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertdlttab[procngbnum]; } } if (orggrafptr->veloloctax != NULL) /* If original graph has vertex loads */ memCpy (fldgrafptr->veloloctax + orggrafptr->baseval, /* Copy local part of vertex load array */ orggrafptr->veloloctax + orggrafptr->baseval, orgvertlocnbr * sizeof (Gnum)); if (orggrafptr->edloloctax != NULL) /* If original graph has edge loads */ memCpy (fldgrafptr->edloloctax + orggrafptr->baseval, /* Copy local part of edge load array */ orggrafptr->edloloctax + orggrafptr->baseval, (orggrafptr->vertloctax[orgvertlocnnd] - orggrafptr->baseval) * sizeof (Gnum)); if (orggrafptr->vnumloctax != NULL) /* If original graph has vertex numbers */ memCpy (fldgrafptr->vnumloctax + orggrafptr->baseval, /* Copy local part of vertex number array */ orggrafptr->vnumloctax + orggrafptr->baseval, orgvertlocnbr * sizeof (Gnum)); else { /* Build local part of vertex number array */ Gnum fldvertlocnum; Gnum fldvertlocadj; for (fldvertlocnum = orggrafptr->baseval, fldvertlocadj = orggrafptr->procvrttab[orggrafptr->proclocnum]; fldvertlocnum < orgvertlocnnd; fldvertlocnum ++) fldgrafptr->vnumloctax[fldvertlocnum] = fldvertlocadj ++; } memCpy (fldgrafptr->vertloctax + orggrafptr->baseval, /* Copy local part of vertex array, since it is compact */ orggrafptr->vertloctax + orggrafptr->baseval, orgvertlocnbr * sizeof (Gnum)); /* Last value is not copied */ fldgrafptr->vertloctax[fldvertlocnbr + orggrafptr->baseval] = fldgrafptr->edgelocnbr + orggrafptr->baseval; if (vertinfoptrin != NULL) /* If vertinfo exists */ memCpy ((byte *) (*vertinfoptrout) + (orggrafptr->baseval * vertinfosize), /* Copy local part */ (byte *) vertinfoptrin + (orggrafptr->baseval * vertinfosize), orgvertlocnbr * vertinfosize); for (i = 0; i < commnbr; i ++) { int j; if (MPI_Waitany (commnbr, &requtab[DGRAPHFOLDTAGVERT * commmax], &j, MPI_STATUS_IGNORE) != MPI_SUCCESS) { errorPrint ("dgraphFold2: communication error (16)"); cheklocval = 1; } else { /* Adjust first remote part of vertex array */ Gnum fldvertlocnum; Gnum fldvertlocnnd; Gnum fldvertlocadj; Gnum * restrict const fldvertloctax = fldgrafptr->vertloctax; fldvertlocnum = fldvertidxtab[j]; fldvertlocadj = fldedgeidxtab[j] - fldgrafptr->vertloctax[fldvertlocnum]; for (fldvertlocnnd = fldvertlocnum + fldcommdattab[j].vertnbr; fldvertlocnum < fldvertlocnnd; fldvertlocnum ++) fldvertloctax[fldvertlocnum] += fldvertlocadj; } } for (i = 0; i < commnbr; i ++) { MPI_Status statdat; int j; if (MPI_Waitany (commnbr, &requtab[DGRAPHFOLDTAGEDGE * commmax], &j, &statdat) != MPI_SUCCESS) { errorPrint ("dgraphFold2: communication error (17)"); cheklocval = 1; } else if (cheklocval == 0) { /* Adjust remote part(s) of edge array */ Gnum orgvertlocmin; Gnum orgvertlocmax; Gnum fldvertlocadj; int procngbnum; int procngbmax; Gnum * restrict const fldedgeloctax = fldgrafptr->edgeloctax; #ifdef SCOTCH_DEBUG_DGRAPH2 int fldedgercvnbr; MPI_Get_count (&statdat, GNUM_MPI, &fldedgercvnbr); if (fldedgercvnbr != fldedgecnttab[j]) { errorPrint ("dgraphFold2: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ for (procngbnum = 0, procngbmax = fldvertadjnbr; /* Initialize search accelerator */ procngbmax - procngbnum > 1; ) { int procngbmed; procngbmed = (procngbmax + procngbnum) / 2; if (fldvertadjtab[procngbmed] <= fldcommvrttab[j]) procngbnum = procngbmed; else procngbmax = procngbmed; } orgvertlocmin = fldvertadjtab[procngbnum]; orgvertlocmax = fldvertadjtab[procngbmax]; fldvertlocadj = fldvertdlttab[procngbnum]; for (fldedgelocnum = fldedgeidxtab[j], fldedgelocnnd = fldedgelocnum + fldedgecnttab[j]; fldedgelocnum < fldedgelocnnd; fldedgelocnum ++) { /* Reorder end vertices */ Gnum orgvertlocend; #ifdef SCOTCH_DEBUG_DGRAPH2 if (fldedgelocnum >= (fldgrafptr->edgelocnbr + orggrafptr->baseval)) { errorPrint ("dgraphFold2: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ orgvertlocend = fldedgeloctax[fldedgelocnum]; if ((orgvertlocend >= orgvertlocmin) && /* If end vertex is local */ (orgvertlocend < orgvertlocmax)) fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertlocadj; else { int procngbnum; int procngbmax; for (procngbnum = 0, procngbmax = fldvertadjnbr; procngbmax - procngbnum > 1; ) { int procngbmed; procngbmed = (procngbmax + procngbnum) / 2; if (fldvertadjtab[procngbmed] <= orgvertlocend) procngbnum = procngbmed; else procngbmax = procngbmed; } fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertdlttab[procngbnum]; } } } } if (orggrafptr->veloloctax == NULL) /* If no vertex loads, reset graph vertex load to number of vertices */ fldvelolocsum = fldvertlocnbr; else { /* Graph has vertex loads and load of local part has already been computed */ for (i = 0; i < commnbr; i ++) { int j; if (MPI_Waitany (commnbr, &requtab[DGRAPHFOLDTAGVELO * commmax], &j, MPI_STATUS_IGNORE) != MPI_SUCCESS) { errorPrint ("dgraphFold2: communication error (18)"); cheklocval = 1; } else if (cheklocval == 0) { /* Accumulate vertex loads for received vertex load array */ Gnum fldvertlocnum; Gnum fldvertlocnnd; for (fldvertlocnum = fldvertidxtab[j], fldvertlocnnd = fldvertlocnum + fldcommdattab[j].vertnbr; fldvertlocnum < fldvertlocnnd; fldvertlocnum ++) fldvelolocsum += fldgrafptr->veloloctax[fldvertlocnum]; } } } if ((fldcommtypval & DGRAPHFOLDCOMMSEND) == 0) { /* If process is a normal receiver, edge arrays may have been oversized */ Gnum fldedgeloctmp; fldedgeloctmp = fldgrafptr->edgelocnbr; if (orggrafptr->edloloctax != NULL) { fldedgeloctmp *= 2; if (MPI_Waitall (commnbr, &requtab[DGRAPHFOLDTAGEDLO * commmax], MPI_STATUSES_IGNORE) != MPI_SUCCESS) { /* Wait for edge load sub-arrays */ errorPrint ("dgraphFold2: communication error (19)"); cheklocval = 1; } } fldgrafptr->edgeloctax = memRealloc (fldgrafptr->edgeloctax + orggrafptr->baseval, fldedgeloctmp * sizeof (Gnum)); fldgrafptr->edgeloctax -= orggrafptr->baseval; if (orggrafptr->edloloctax != NULL) fldgrafptr->edloloctax = fldgrafptr->edgeloctax + fldgrafptr->edgelocnbr; } fldgrafptr->baseval = orggrafptr->baseval; fldgrafptr->vertlocnbr = fldvertlocnbr; fldgrafptr->vertlocnnd = fldvertlocnbr + orggrafptr->baseval; fldgrafptr->velolocsum = fldvelolocsum; fldgrafptr->degrglbmax = orggrafptr->degrglbmax; if (dgraphBuild4 (fldgrafptr) != 0) { errorPrint ("dgraphFold2: cannot build folded graph"); dgraphExit (fldgrafptr); return (1); } #ifdef SCOTCH_DEBUG_DGRAPH2 if (dgraphCheck (fldgrafptr) != 0) { /* Check graph consistency; vnumloctab is not checked so no need to wait for it */ errorPrint ("dgraphFold2: internal error (3)"); dgraphExit (fldgrafptr); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ } memFree (fldcommdattab); /* Free group leader */ if (MPI_Waitall (requnbr, requtab, MPI_STATUSES_IGNORE) != MPI_SUCCESS) { /* Wait for all graph data to arrive because graph could be freed afterwards */ errorPrint ("dgraphFold2: communication error (20)"); cheklocval = 1; } memFree (fldvertidxtab); /* Free group leader including request array */ #ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication cannot be merged with a useful one */ if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, orggrafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphFold2: communication error (21)"); chekglbval = 1; } #else /* SCOTCH_DEBUG_DGRAPH1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_DGRAPH1 */ return (chekglbval); } scotch-5.1.12b.dfsg/src/libscotch/common_file.h0000644000175300017530000000547511631334325021606 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : common_file.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the file and file name handling **/ /** routines. **/ /** **/ /** DATES : # Version P0.5 : from : 21 may 2007 **/ /** to 21 may 2007 **/ /** **/ /************************************************************/ #define COMMON_FILE_H /* ** The type and structure definitions. */ /* Expansion string size and associated format string. */ #define FILENAMEDISTEXPANDNBR 10 /* TRICK: Change this value in ssprintf() format strings too */ #define FILENAMEDISTEXPANDSTR "%-10d" /* TRICK: Change this value if FILENAMEDISTEXPANDNBR changes */ scotch-5.1.12b.dfsg/src/libscotch/libraryf.h0000644000175300017530000001111111631334325021111 0ustar hazelscthazelsct!* Copyright 2004,2007,2009,2010 ENSEIRB, INRIA & CNRS !* !* This file is part of the Scotch software package for static mapping, !* graph partitioning and sparse matrix ordering. !* !* This software is governed by the CeCILL-C license under French law !* and abiding by the rules of distribution of free software. You can !* use, modify and/or redistribute the software under the terms of the !* CeCILL-C license as circulated by CEA, CNRS and INRIA at the following !* URL: "http://www.cecill.info". !* !* As a counterpart to the access to the source code and rights to copy, !* modify and redistribute granted by the license, users are provided !* only with a limited warranty and the software's author, the holder of !* the economic rights, and the successive licensors have only limited !* liability. !* !* In this respect, the user's attention is drawn to the risks associated !* with loading, using, modifying and/or developing or reproducing the !* software by the user in light of its specific status of free software, !* that may mean that it is complicated to manipulate, and that also !* therefore means that it is reserved for developers and experienced !* professionals having in-depth computer knowledge. Users are therefore !* encouraged to load and test the software's suitability as regards !* their requirements in conditions enabling the security of their !* systems and/or data to be ensured and, more generally, to use and !* operate it in the same conditions as regards security. !* !* The fact that you are presently reading this means that you have had !* knowledge of the CeCILL-C license and that you accept its terms. !* !*********************************************************** !* ** !* NAME : libraryf.h ** !* ** !* AUTHOR : Francois PELLEGRINI ** !* ** !* FUNCTION : FORTRAN declaration file for the ** !* LibScotch static mapping and sparse ** !* matrix block ordering sequential ** !* library. ** !* ** !* DATES : # Version 3.4 : from : 04 feb 2000 ** !* to 22 oct 2001 ** !* # Version 4.0 : from : 16 jan 2004 ** !* to 16 jan 2004 ** !* # Version 5.0 : from : 26 apr 2006 ** !* to 26 apr 2006 ** !* # Version 5.1 : from : 26 mar 2009 ** !* to 12 feb 2011 ** !* ** !*********************************************************** !* Flag definitions for the strategy !* string selection routines. INTEGER SCOTCH_STRATQUALITY INTEGER SCOTCH_STRATSPEED INTEGER SCOTCH_STRATBALANCE INTEGER SCOTCH_STRATSCALABILITY INTEGER SCOTCH_STRATSAFETY INTEGER SCOTCH_STRATCLUSTER PARAMETER (SCOTCH_STRATQUALITY = 1) PARAMETER (SCOTCH_STRATSPEED = 2) PARAMETER (SCOTCH_STRATBALANCE = 4) PARAMETER (SCOTCH_STRATSAFETY = 8) PARAMETER (SCOTCH_STRATSCALABILITY = 16) PARAMETER (SCOTCH_STRATCLUSTER = 32) !* Size definitions for the SCOTCH opaque !* structures. These structures must be !* allocated as arrays of DOUBLEPRECISION !* values for proper padding. The dummy !* sizes are computed at compile-time by !* program "dummysizes". INTEGER SCOTCH_ARCHDIM INTEGER SCOTCH_DGRAPHDIM INTEGER SCOTCH_DGRAPHHALOREQDIM INTEGER SCOTCH_DORDERDIM INTEGER SCOTCH_GEOMDIM INTEGER SCOTCH_GRAPHDIM INTEGER SCOTCH_MAPDIM INTEGER SCOTCH_MESHDIM INTEGER SCOTCH_ORDERDIM INTEGER SCOTCH_STRATDIM PARAMETER (SCOTCH_ARCHDIM = DUMMYSIZEARCH) PARAMETER (SCOTCH_DGRAPHDIM = DUMMYSIZEDGRAPH) PARAMETER (SCOTCH_DGRAPHHALOREQDIM = DUMMYSIZEDGRAPHHALOREQ) PARAMETER (SCOTCH_DORDERDIM = DUMMYSIZEDORDER) PARAMETER (SCOTCH_GEOMDIM = DUMMYSIZEGEOM) PARAMETER (SCOTCH_GRAPHDIM = DUMMYSIZEGRAPH) PARAMETER (SCOTCH_MAPDIM = DUMMYSIZEMAP) PARAMETER (SCOTCH_MESHDIM = DUMMYSIZEMESH) PARAMETER (SCOTCH_ORDERDIM = DUMMYSIZEORDER) PARAMETER (SCOTCH_STRATDIM = DUMMYSIZESTRAT) scotch-5.1.12b.dfsg/src/libscotch/library_graph.c0000644000175300017530000004516711631334325022141 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the source **/ /** graph handling routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 3.2 : from : 18 aug 1998 **/ /** to 18 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to 01 nov 2001 **/ /** # Version 4.0 : from : 11 dec 2001 **/ /** to 09 dec 2005 **/ /** # Version 5.0 : from : 10 sep 2006 **/ /** to 03 apr 2008 **/ /** # Version 5.1 : from : 17 nov 2010 **/ /** to 17 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "graph.h" #include "graph_io.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the graph handling routines. */ /* */ /************************************/ /*+ This routine reserves a memory area *** of a size sufficient to store a *** centralized graph structure. *** It returns: *** - !NULL : if the initialization succeeded. *** - NULL : on error. +*/ SCOTCH_Graph * SCOTCH_graphAlloc () { return ((SCOTCH_Graph *) memAlloc (sizeof (SCOTCH_Graph))); } /*+ This routine initializes the opaque *** graph structure used to handle graphs *** in the Scotch library. *** It returns: *** - 0 : if the initialization succeeded. *** - !0 : on error. +*/ int SCOTCH_graphInit ( SCOTCH_Graph * const grafptr) { if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { errorPrint ("SCOTCH_graphInit: internal error (1)"); return (1); } if (sizeof (SCOTCH_Graph) < sizeof (Graph)) { errorPrint ("SCOTCH_graphInit: internal error (2)"); return (1); } return (graphInit ((Graph *) grafptr)); } /*+ This routine frees the contents of the *** given opaque graph structure. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_graphExit ( SCOTCH_Graph * const grafptr) { graphExit ((Graph *) grafptr); } /*+ This routine frees the contents of the *** given opaque graph structure. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_graphFree ( SCOTCH_Graph * const grafptr) { graphFree ((Graph *) grafptr); } /*+ This routine loads the given opaque graph *** structure with the data of the given stream. *** The base value allows the user to set the *** graph base to 0 or 1, or to the base value *** of the stream if the base value is equal *** to -1. On input, vertex loads are discarded if *** flagval is 1, edge loads are discarded if flagval *** is 2, and both if flagval is set to 3. *** It returns: *** - 0 : if the loading succeeded. *** - !0 : on error. +*/ int SCOTCH_graphLoad ( SCOTCH_Graph * const grafptr, FILE * const stream, const SCOTCH_Num baseval, const SCOTCH_Num flagval) { GraphFlag srcgrafflag; /* Graph flags */ if ((baseval < -1) || (baseval > 1)) { errorPrint ("SCOTCH_graphLoad: invalid base parameter"); return (1); } if ((flagval < 0) || (flagval > 3)) { errorPrint ("SCOTCH_graphLoad: invalid flag parameter"); return (1); } srcgrafflag = (((flagval & 1) != 0) ? GRAPHIONOLOADVERT : 0) + (((flagval & 2) != 0) ? GRAPHIONOLOADEDGE : 0); return (graphLoad ((Graph * const) grafptr, stream, (Gnum) baseval, srcgrafflag)); } /*+ This routine saves the contents of the given *** opaque graph structure to the given stream. *** It returns: *** - 0 : if the saving succeeded. *** - !0 : on error. +*/ int SCOTCH_graphSave ( const SCOTCH_Graph * const grafptr, FILE * const stream) { return (graphSave ((const Graph * const) grafptr, stream)); } /*+ This routine fills the contents of the given *** opaque graph structure with the data provided *** by the user. The base value allows the user to *** set the graph base to 0 or 1. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphBuild ( SCOTCH_Graph * const grafptr, /* Graph structure to fill */ const SCOTCH_Num baseval, /* Base value */ const SCOTCH_Num vertnbr, /* Number of vertices */ const SCOTCH_Num * const verttab, /* Vertex array [vertnbr or vertnbr+1] */ const SCOTCH_Num * const vendtab, /* Vertex end array [vertnbr] */ const SCOTCH_Num * const velotab, /* Vertex load array */ const SCOTCH_Num * const vlbltab, /* Vertex label array */ const SCOTCH_Num edgenbr, /* Number of edges (arcs) */ const SCOTCH_Num * const edgetab, /* Edge array [edgenbr] */ const SCOTCH_Num * const edlotab) /* Edge load array */ { Graph * srcgrafptr; /* Pointer to source graph structure */ Gnum vertnum; /* Current vertex number */ Gnum degrmax; /* Maximum degree */ #ifdef SCOTCH_DEBUG_LIBRARY1 if (sizeof (SCOTCH_Graph) < sizeof (Graph)) { errorPrint ("SCOTCH_graphBuild: internal error"); return (1); } #endif /* SCOTCH_DEBUG_LIBRARY1 */ if ((baseval < 0) || (baseval > 1)) { errorPrint ("SCOTCH_graphBuild: invalid base parameter"); return (1); } srcgrafptr = (Graph *) grafptr; /* Use structure as source graph */ srcgrafptr->flagval = GRAPHNONE; srcgrafptr->baseval = baseval; srcgrafptr->vertnbr = vertnbr; srcgrafptr->vertnnd = vertnbr + baseval; srcgrafptr->verttax = (Gnum *) verttab - baseval; srcgrafptr->vendtax = ((vendtab == NULL) || (vendtab == verttab) || (vendtab == verttab + 1)) ? srcgrafptr->verttax + 1 : (Gnum *) vendtab - baseval; srcgrafptr->velotax = ((velotab == NULL) || (velotab == verttab)) ? NULL : (Gnum *) velotab - baseval; srcgrafptr->vnumtax = NULL; srcgrafptr->vlbltax = ((vlbltab == NULL) || (vlbltab == verttab)) ? NULL : (Gnum *) vlbltab - baseval; srcgrafptr->edgenbr = edgenbr; srcgrafptr->edgetax = (Gnum *) edgetab - baseval; srcgrafptr->edlotax = ((edlotab == NULL) || (edlotab == edgetab)) ? NULL : (Gnum *) edlotab - baseval; if (srcgrafptr->velotax == NULL) /* Compute vertex load sum */ srcgrafptr->velosum = vertnbr; else { Gnum velosum; /* Sum of vertex loads */ for (vertnum = srcgrafptr->baseval, velosum = 0; vertnum < srcgrafptr->vertnnd; vertnum ++) velosum += srcgrafptr->velotax[vertnum]; srcgrafptr->velosum = velosum; } if (srcgrafptr->edlotax == NULL) { /* If no edge loads */ srcgrafptr->edlosum = srcgrafptr->edgenbr; /* Edge load sum is known */ for (vertnum = srcgrafptr->baseval, degrmax = 0; /* Compute maximum degree only */ vertnum < srcgrafptr->vertnnd; vertnum ++) { Gnum degrval; /* Degree of current vertex */ degrval = srcgrafptr->vendtax[vertnum] - srcgrafptr->verttax[vertnum]; if (degrval > degrmax) degrmax = degrval; } } else { /* Graph has edge loads, compute edge load sum */ Gnum edlosum; for (vertnum = srcgrafptr->baseval, edlosum = degrmax = 0; vertnum < srcgrafptr->vertnnd; vertnum ++) { Gnum edgenum; Gnum degrval; /* Degree of current vertex */ degrval = srcgrafptr->vendtax[vertnum] - srcgrafptr->verttax[vertnum]; if (degrval > degrmax) degrmax = degrval; for (edgenum = srcgrafptr->verttax[vertnum]; edgenum < srcgrafptr->vendtax[vertnum]; edgenum ++) edlosum += srcgrafptr->edlotax[edgenum]; } srcgrafptr->edlosum = edlosum; } srcgrafptr->degrmax = degrmax; #ifdef DEAD_CODE /* Vertex labels only for graph output */ if (srcgrafptr->vlbltax != NULL) { /* If vertex labels provided */ Gnum vlblmax; /* Maximum label value */ for (vlblmax = 0, vertnum = srcgrafptr->baseval; vertnum < srcgrafptr->vertnnd; vertnum ++) { if (srcgrafptr->vlbltax[vertnum] < 0) { errorPrint ("SCOTCH_graphBuild: negative labels not allowed"); return (1); } if (srcgrafptr->vlbltax[vertnum] > vlblmax) /* Get maximum label */ vlblmax = srcgrafptr->vlbltax[vertnum]; } if (graphLoad2 (srcgrafptr->baseval, srcgrafptr->vertnnd, srcgrafptr->verttax, /* Rename edge ends */ srcgrafptr->vendtax, srcgrafptr->edgetax, vlblmax, srcgrafptr->vlbltax) != 0) { errorPrint ("SCOTCH_graphBuild: cannot relabel vertices"); return (1); } } #endif return (0); } /*+ This routine accesses graph size data. *** NULL pointers on input indicate unwanted *** data. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_graphSize ( const SCOTCH_Graph * const grafptr, SCOTCH_Num * const vertnbr, SCOTCH_Num * const edgenbr) { const Graph * srcgrafptr; srcgrafptr = (Graph *) grafptr; if (vertnbr != NULL) *vertnbr = (SCOTCH_Num) (srcgrafptr->vertnbr); if (edgenbr != NULL) *edgenbr = (SCOTCH_Num) srcgrafptr->edgenbr; } /*+ This routine accesses all of the graph data. *** NULL pointers on input indicate unwanted *** data. NULL pointers on output indicate *** unexisting arrays. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_graphData ( const SCOTCH_Graph * const grafptr, /* Graph structure to read */ SCOTCH_Num * const baseptr, /* Base value */ SCOTCH_Num * const vertptr, /* Number of vertices */ SCOTCH_Num ** const verttab, /* Vertex array [vertnbr+1] */ SCOTCH_Num ** const vendtab, /* Vertex array [vertnbr] */ SCOTCH_Num ** const velotab, /* Vertex load array */ SCOTCH_Num ** const vlbltab, /* Vertex label array */ SCOTCH_Num * const edgeptr, /* Number of edges (arcs) */ SCOTCH_Num ** const edgetab, /* Edge array [edgenbr] */ SCOTCH_Num ** const edlotab) /* Edge load array */ { const Graph * srcgrafptr; /* Pointer to source graph structure */ srcgrafptr = (const Graph *) grafptr; if (baseptr != NULL) *baseptr = srcgrafptr->baseval; if (vertptr != NULL) *vertptr = srcgrafptr->vertnbr; if (verttab != NULL) *verttab = srcgrafptr->verttax + srcgrafptr->baseval; if (vendtab != NULL) *vendtab = srcgrafptr->vendtax + srcgrafptr->baseval; if (velotab != NULL) *velotab = (srcgrafptr->velotax != NULL) ? srcgrafptr->velotax + srcgrafptr->baseval : NULL; if (vlbltab != NULL) *vlbltab = (srcgrafptr->vlbltax != NULL) ? srcgrafptr->vlbltax + srcgrafptr->baseval : NULL; if (edgeptr != NULL) *edgeptr = srcgrafptr->edgenbr; if (edgetab != NULL) *edgetab = srcgrafptr->edgetax + srcgrafptr->baseval; if (edlotab != NULL) *edlotab = (srcgrafptr->edlotax != NULL) ? srcgrafptr->edlotax + srcgrafptr->baseval : NULL; } /*+ This routine computes statistics *** on the given graph. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_graphStat ( const SCOTCH_Graph * const grafptr, SCOTCH_Num * const velominptr, SCOTCH_Num * const velomaxptr, SCOTCH_Num * const velosumptr, double * veloavgptr, double * velodltptr, SCOTCH_Num * const degrminptr, SCOTCH_Num * const degrmaxptr, double * degravgptr, double * degrdltptr, SCOTCH_Num * const edlominptr, SCOTCH_Num * const edlomaxptr, SCOTCH_Num * const edlosumptr, double * edloavgptr, double * edlodltptr) { const Graph * srcgrafptr; Gnum vertnum; Gnum vertnbr; Gnum velomin; Gnum velomax; double veloavg; double velodlt; Gnum degrval; Gnum degrmin; Gnum degrmax; double degravg; double degrdlt; Gnum edgenum; Gnum edlomin; Gnum edlomax; Gnum edlosum; double edloavg; double edlodlt; srcgrafptr = (Graph *) grafptr; vertnbr = srcgrafptr->vertnnd - srcgrafptr->baseval; velodlt = 0.0L; if (vertnbr > 0) { if (srcgrafptr->velotax != NULL) { /* If graph has vertex loads */ velomin = GNUMMAX; velomax = 0; veloavg = (double) srcgrafptr->velosum / (double) vertnbr; for (vertnum = srcgrafptr->baseval; vertnum < srcgrafptr->vertnnd; vertnum ++) { if (srcgrafptr->velotax[vertnum] < velomin) /* Account for vertex loads */ velomin = srcgrafptr->velotax[vertnum]; if (srcgrafptr->velotax[vertnum] > velomax) velomax = srcgrafptr->velotax[vertnum]; velodlt += fabs ((double) srcgrafptr->velotax[vertnum] - veloavg); } velodlt /= (double) vertnbr; } else { velomin = velomax = 1; veloavg = 1.0L; } } else { velomin = velomax = 0; veloavg = 0.0L; } if (velominptr != NULL) *velominptr = (SCOTCH_Num) velomin; if (velomaxptr != NULL) *velomaxptr = (SCOTCH_Num) velomax; if (velosumptr != NULL) *velosumptr = (SCOTCH_Num) srcgrafptr->velosum; if (veloavgptr != NULL) *veloavgptr = (double) veloavg; if (velodltptr != NULL) *velodltptr = (double) velodlt; degrmax = 0; degrdlt = 0.0L; if (vertnbr > 0) { degrmin = GNUMMAX; degravg = (double) srcgrafptr->edgenbr / (double) vertnbr; for (vertnum = srcgrafptr->baseval; vertnum < srcgrafptr->vertnnd; vertnum ++) { degrval = srcgrafptr->vendtax[vertnum] - srcgrafptr->verttax[vertnum]; /* Get vertex degree */ if (degrval < degrmin) degrmin = degrval; if (degrval > degrmax) degrmax = degrval; degrdlt += fabs ((double) degrval - degravg); } degrdlt /= (double) vertnbr; } else { degrmin = 0; degravg = 0.0L; } if (degrminptr != NULL) *degrminptr = (SCOTCH_Num) degrmin; if (degrmaxptr != NULL) *degrmaxptr = (SCOTCH_Num) degrmax; if (degravgptr != NULL) *degravgptr = (double) degravg; if (degrdltptr != NULL) *degrdltptr = (double) degrdlt; edlodlt = 0.0L; if (srcgrafptr->edgenbr > 0) { if (srcgrafptr->edlotax != NULL) { /* If graph has edge loads */ edlomin = GNUMMAX; edlomax = 0; edlosum = 0; for (vertnum = srcgrafptr->baseval; vertnum < srcgrafptr->vertnnd; vertnum ++) { for (edgenum = srcgrafptr->verttax[vertnum]; edgenum < srcgrafptr->vendtax[vertnum]; edgenum ++) { /* For all edges */ if (srcgrafptr->edlotax[edgenum] < edlomin) /* Account for edge load */ edlomin = srcgrafptr->edlotax[edgenum]; if (srcgrafptr->edlotax[edgenum] > edlomax) edlomax = srcgrafptr->edlotax[edgenum]; edlosum += srcgrafptr->edlotax[edgenum]; } } edloavg = (double) edlosum / (double) (2 * srcgrafptr->edgenbr); for (vertnum = srcgrafptr->baseval; vertnum < srcgrafptr->vertnnd; vertnum ++) { for (edgenum = srcgrafptr->verttax[vertnum]; edgenum < srcgrafptr->vendtax[vertnum]; edgenum ++) /* For all edges */ edlodlt += fabs ((double) srcgrafptr->edlotax[edgenum] - edloavg); } edlodlt /= (double) srcgrafptr->edgenbr; } else { edlomin = edlomax = 1; edlosum = srcgrafptr->edgenbr / 2; edloavg = 1.0L; } } else { edlomin = edlomax = 0; edlosum = 0; edloavg = 0.0L; } if (edlominptr != NULL) *edlominptr = (SCOTCH_Num) edlomin; if (edlomaxptr != NULL) *edlomaxptr = (SCOTCH_Num) edlomax; if (edlosumptr != NULL) *edlosumptr = (SCOTCH_Num) edlosum; if (edloavgptr != NULL) *edloavgptr = (double) edloavg; if (edlodltptr != NULL) *edlodltptr = (double) edlodlt; } scotch-5.1.12b.dfsg/src/libscotch/dgraph_build_hcub.c0000644000175300017530000002221311631334325022724 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_build_hcub.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER **/ /** **/ /** FUNCTION : These lines are the distributed source **/ /** graph building routines for hypercube **/ /** graphs. **/ /** **/ /** DATES : # Version P0.1 : from : 19 may 1999 **/ /** to : 19 may 1999 **/ /** # Version P0.2 : from : 02 feb 2000 **/ /** to : 02 feb 2000 **/ /** # Version 5.0 : from : 20 jul 2005 **/ /** to : 10 sep 2007 **/ /** # Version 5.1 : from : 12 nov 2008 **/ /** to : 12 nov 2008 **/ /** **/ /************************************************************/ #define DGRAPH #include "module.h" #include "common.h" #include "dgraph.h" /*******************************************/ /* */ /* The distributed graph building routine. */ /* */ /*******************************************/ /* This routine builds a distributed hypercube of ** given dimension. ** Since this routine calls dgraphBuild, the private ** data of the Dgraph structure will be initialized ** by the latter, if needed. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphBuildHcub ( Dgraph * restrict const grafptr, /* Graph */ const Gnum hcubdim, /* Hypercube dimension */ const Gnum baseval, /* Base value */ const Gnum flagval) /* Flags */ { Gnum procngbnum; Gnum vertglbnbr; /* Total number of vertices */ Gnum vertglbnum; /* Global number of current vertex */ Gnum vertlocnbr; /* Number of local vertices */ Gnum velolocnbr; /* Number of local vertex loads */ Gnum vertlocnnd; Gnum vertlocnum; Gnum * restrict vertloctax; Gnum * restrict veloloctax; #ifdef SCOTCH_DEBUG_DGRAPH3 Gnum * restrict vlblloctax; #endif /* SCOTCH_DEBUG_DGRAPH3 */ Gnum edgelocnbr; Gnum * restrict edgeloctax; Gnum edgelocnum; Gnum edlolocnbr; Gnum * restrict edloloctax; int cheklocval; Gnum reduloctab[7]; Gnum reduglbtab[7]; vertglbnbr = 1 << hcubdim; vertlocnbr = DATASIZE (vertglbnbr, grafptr->procglbnbr, grafptr->proclocnum); velolocnbr = ((flagval & 1) != 0) ? vertlocnbr : 0; edgelocnbr = vertlocnbr * hcubdim; /* Set local number of arcs */ edlolocnbr = ((flagval & 2) != 0) ? edgelocnbr : 0; for (procngbnum = 0, vertglbnum = 0; /* Compute index of first local vertex */ procngbnum < grafptr->proclocnum; procngbnum ++) vertglbnum += DATASIZE (vertglbnbr, grafptr->procglbnbr, procngbnum); cheklocval = 0; vertloctax = edgeloctax = NULL; if (memAllocGroup ((void **) (void *) &vertloctax, (size_t) ((vertlocnbr + 1) * sizeof (Gnum)), /* Compact vertex array */ #ifdef SCOTCH_DEBUG_DGRAPH3 &vlblloctax, (size_t) (vertlocnbr * sizeof (Gnum)), #endif /* SCOTCH_DEBUG_DGRAPH3 */ &veloloctax, (size_t) (vertlocnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphBuildHcub: out of memory (1)"); cheklocval = 1; } else if (memAllocGroup ((void **) (void *) &edgeloctax, (size_t) (edgelocnbr * sizeof (Gnum)), &edloloctax, (size_t) (edlolocnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphBuildHcub: out of memory (2)"); cheklocval = 1; } reduloctab[0] = hcubdim; reduloctab[1] = - hcubdim; reduloctab[2] = baseval; reduloctab[3] = - baseval; reduloctab[4] = flagval; reduloctab[5] = - flagval; reduloctab[6] = cheklocval; if (MPI_Allreduce (reduloctab, reduglbtab, 7, GNUM_MPI, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphBuildHcub: communication error"); return (1); } if (reduglbtab[6] != 0) { if (vertloctax != NULL) { if (edgeloctax != NULL) memFree (edgeloctax); memFree (vertloctax); } return (1); } if ((reduglbtab[1] != - reduglbtab[0]) || (reduglbtab[3] != - reduglbtab[2]) || (reduglbtab[5] != - reduglbtab[4])) { errorPrint ("dgraphBuildHcub: inconsistent parameters"); return (1); } vertloctax -= baseval; veloloctax = ((flagval & 1) != 0) ? (veloloctax - baseval) : NULL; edgeloctax -= baseval; edloloctax = ((flagval & 2) != 0) ? (edloloctax - baseval) : NULL; #ifdef SCOTCH_DEBUG_DGRAPH3 vlblloctax -= baseval; #endif /* SCOTCH_DEBUG_DGRAPH3 */ for (vertlocnum = baseval, vertlocnnd = vertlocnbr + baseval, edgelocnum = baseval; vertlocnum < vertlocnnd; vertlocnum ++, vertglbnum ++) { Gnum vertngbbit; /* Bit that differs between neighbors */ if (veloloctax != NULL) veloloctax[vertlocnum] = 1 + (vertglbnum & 3); /* Pseudo random weight (1 to 5) */ #ifdef SCOTCH_DEBUG_DGRAPH3 vlblloctax[vertlocnum] = ((vertglbnum * COARHASHPRIME) % vertglbnbr) + baseval; /* Hash vertices to spread labels */ #endif /* SCOTCH_DEBUG_DGRAPH3 */ vertloctax[vertlocnum] = edgelocnum; for (vertngbbit = 1; vertngbbit < vertglbnbr; vertngbbit <<= 1, edgelocnum ++) { #ifdef SCOTCH_DEBUG_DGRAPH3 edgeloctax[edgelocnum] = (((vertglbnum ^ vertngbbit) * COARHASHPRIME) % vertglbnbr) + baseval; #else /* SCOTCH_DEBUG_DGRAPH3 */ edgeloctax[edgelocnum] = (vertglbnum ^ vertngbbit) + baseval; #endif /* SCOTCH_DEBUG_DGRAPH3 */ if (edloloctax != NULL) edloloctax[edgelocnum] = ((vertglbnum + edgeloctax[edgelocnum]) % 16) + 1; /* Pseudo random weight (1 to 16) */ } } vertloctax[vertlocnum] = edgelocnum; /* Mark end of local vertex array */ #ifdef SCOTCH_DEBUG_DGRAPH2 if (edgelocnum != edgelocnbr + baseval) { errorPrint ("dgraphBuildHcub: internal error"); memFree (vertloctax + baseval); /* Free memory group leader */ return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (dgraphBuild2 (grafptr, baseval, /* Build the distributed graph */ #ifdef SCOTCH_DEBUG_DGRAPH3 vertlocnbr, vertlocnbr, vertloctax, vertloctax + 1, NULL, vertlocnbr, NULL, vlblloctax, #else /* SCOTCH_DEBUG_DGRAPH3 */ vertlocnbr, vertlocnbr, vertloctax, vertloctax + 1, NULL, vertlocnbr, NULL, NULL, #endif /* SCOTCH_DEBUG_DGRAPH3 */ edgelocnbr, edgelocnbr, edgeloctax, NULL, edloloctax, hcubdim) != 0) { memFree (edgeloctax + baseval); /* Free memory group leaders */ memFree (vertloctax + baseval); return (1); } grafptr->flagval |= DGRAPHFREETABS | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; /* Arrays created by the routine itself */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_gp.h0000644000175300017530000001002011631334325023136 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_gp.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the Gibbs, Poole, and Stockmeyer **/ /** graph separation algorithm. **/ /** **/ /** DATES : # Version 4.0 : from : 14 may 2004 **/ /** to 17 may 2004 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ Method parameters. +*/ typedef struct VgraphSeparateGpParam_ { INT passnbr; /*+ Number of passes to do +*/ } VgraphSeparateGpParam; /*+ Complementary vertex structure. +*/ typedef struct VgraphSeparateGpVertex_ { Gnum passnum; /*+ Number of pass when vertex selected +*/ Gnum distval; /*+ Current distance from diameter vertex +*/ } VgraphSeparateGpVertex; /*+ Neighbor queue. +*/ typedef struct VgraphSeparateGpQueue_ { Gnum headnum; /*+ Head of distance queue +*/ Gnum tailnum; /*+ Tail of distance queue +*/ Gnum * queutab; /*+ Array of queue elements +*/ } VgraphSeparateGpQueue; /* ** The function prototypes. */ #ifndef VGRAPH_SEPARATE_GP #define static #endif int vgraphSeparateGp (Vgraph * restrict const, const VgraphSeparateGpParam * restrict const); #undef static /* ** The macro definitions. */ #define vgraphSeparateGpQueueFlush(queue) ((queue)->headnum = (queue)->tailnum = 0) #define vgraphSeparateGpQueueEmpty(queue) ((queue)->headnum <= (queue)->tailnum) #define vgraphSeparateGpQueuePut(queue,vnum) ((queue)->queutab[(queue)->headnum ++] = (vnum)) #define vgraphSeparateGpQueueGet(queue) ((queue)->queutab[(queue)->tailnum ++]) scotch-5.1.12b.dfsg/src/libscotch/arch_vcmplt.h0000644000175300017530000001165511631334325021616 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_vcmplt.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the variable-sized complete graph **/ /** target architecture functions. **/ /** **/ /** DATES : # Version 3.0 : from : 01 jul 1995 **/ /** to 09 aug 1995 **/ /** # Version 3.1 : from : 20 jul 1996 **/ /** to 20 jul 1996 **/ /** # Version 3.2 : from : 15 oct 1996 **/ /** to 14 may 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 3.4 : from : 08 nov 2001 **/ /** to 08 nov 2001 **/ /** # Version 4.0 : from : 05 nov 2003 **/ /** to 05 nov 2003 **/ /** # Version 5.1 : from : 21 jan 2008 **/ /** to 21 jan 2008 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ The variable-sized complete graph bipartitioning definitions. +*/ typedef struct ArchVcmplt_ { int padding; /*+ No data needed +*/ } ArchVcmplt; typedef struct ArchVcmpltDom_ { Anum termnum; /*+ Terminal number +*/ } ArchVcmpltDom; /* ** The function prototypes. */ #ifndef ARCH_VCMPLT #define static #endif #define archVcmpltArchLoad NULL #define archVcmpltArchSave NULL #define archVcmpltArchFree NULL ArchDomNum archVcmpltDomNum (const ArchVcmplt * const, const ArchVcmpltDom * const); int archVcmpltDomTerm (const ArchVcmplt * const, ArchVcmpltDom * restrict const, const ArchDomNum); Anum archVcmpltDomSize (const ArchVcmplt * const, const ArchVcmpltDom * const); #define archVcmpltDomWght archVcmpltDomSize Anum archVcmpltDomDist (const ArchVcmplt * const, const ArchVcmpltDom * const, const ArchVcmpltDom * const); int archVcmpltDomFrst (const ArchVcmplt * const, ArchVcmpltDom * const); int archVcmpltDomLoad (const ArchVcmplt * const, ArchVcmpltDom * const, FILE * const); int archVcmpltDomSave (const ArchVcmplt * const, const ArchVcmpltDom * const, FILE * const); int archVcmpltDomBipart (const ArchVcmplt * const, const ArchVcmpltDom * const, ArchVcmpltDom * restrict const, ArchVcmpltDom * restrict const); #ifdef SCOTCH_PTSCOTCH int archVcmpltDomMpiType (const ArchVcmplt * const, MPI_Datatype * const); #endif /* SCOTCH_PTSCOTCH */ #undef static scotch-5.1.12b.dfsg/src/libscotch/dmapping.h0000644000175300017530000001171111631334325021104 0ustar hazelscthazelsct/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dmapping.h **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** Jun-Ho HER **/ /** **/ /** FUNCTION : These lines are the declarations for **/ /** the parallel mapping handling routines. **/ /** **/ /** DATES : # Version 5.1 : from : 31 mar 2008 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ #define DMAPPING_H /* ** The type definitions. */ /*+ This structure defines a mapping fragment. +*/ typedef struct DmappingFrag_ { struct DmappingFrag_ * nextptr; /*+ Pointer to next fragment +*/ Gnum vertnbr; /*+ Number of local vertices in mapping +*/ Gnum * vnumtab; /*+ Vertex index array +*/ Anum * parttab; /*+ Mapping array [vertlocnbr] +*/ Anum domnnbr; /*+ Local number of domains +*/ ArchDom * domntab; /*+ Array of domains [domnnbr] +*/ } DmappingFrag; /*+ This structure defines an (eventually partial) mapping of a source graph to a target architecture. +*/ typedef struct Dmapping_ { struct DmappingFrag_ * fragptr; /*+ Pointer to first mapping fragment +*/ Gnum fragnbr; /*+ Number of local fragments +*/ Gnum vertlocmax; /*+ Size of biggest local fragment +*/ Gnum vertlocnbr; /*+ Number of local vertices in mapping +*/ Arch archdat; /*+ Architecture data +*/ #ifdef SCOTCH_PTHREAD pthread_mutex_t mutelocdat; /*+ Local mutex for updates +*/ #endif /* SCOTCH_PTHREAD */ } Dmapping; /*+ The sort structure, used to sort mapped vertices. Field vertnum is first and field termnum is a Gnum and not an Anum because of intSort2asc1. +*/ typedef struct DmappingTermSort_ { Gnum vertnum; /*+ Vertex number: FIRST +*/ Gnum termnum; /*+ Direct permutation index +*/ } DmappingTermSort; /* ** The function prototypes. */ #ifndef DMAPPING #define static #endif int dmapInit (Dmapping * restrict const, const Arch * restrict const); void dmapExit (Dmapping * const); void dmapAdd (Dmapping * restrict const, DmappingFrag * restrict const); int dmapSave (const Dmapping * restrict const, const Dgraph * restrict const, FILE * restrict const); int dmapTerm (const Dmapping * restrict const, const Dgraph * restrict const, Gnum * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_mesh_io_scot_f.c0000644000175300017530000001626111631334325024011 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_mesh_io_scot_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** mesh i/o routines of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 4.0 : from : 24 nov 2005 **/ /** to 24 nov 2005 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 27 mar 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the mapping routines. */ /* */ /**************************************/ /* String lengths are passed at the very ** end of the argument list. */ FORTRAN ( \ SCOTCHFMESHGEOMLOADSCOT, scotchfmeshgeomloadscot, ( \ SCOTCH_Mesh * const meshptr, \ SCOTCH_Geom * const geomptr, \ const int * const filegrfptr, \ const int * const filegeoptr, \ const char * const dataptr, /* No use */ \ int * const revaptr, \ const int datanbr), \ (meshptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) { FILE * filegrfstream; /* Streams to build from handles */ FILE * filegeostream; int filegrfnum; /* Duplicated handle */ int filegeonum; int o; if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFMESHGEOMLOADSCOT: cannot duplicate handle (1)"); *revaptr = 1; /* Indicate error */ return; } if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFMESHGEOMLOADSCOT: cannot duplicate handle (2)"); close (filegrfnum); *revaptr = 1; /* Indicate error */ return; } if ((filegrfstream = fdopen (filegrfnum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFMESHGEOMLOADSCOT: cannot open input stream (1)"); close (filegrfnum); close (filegeonum); *revaptr = 1; return; } if ((filegeostream = fdopen (filegeonum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFMESHGEOMLOADSCOT: cannot open input stream (2)"); fclose (filegrfstream); close (filegeonum); *revaptr = 1; return; } o = SCOTCH_meshGeomLoadScot (meshptr, geomptr, filegrfstream, filegeostream, NULL); fclose (filegrfstream); /* This closes file descriptors too */ fclose (filegeostream); *revaptr = o; } /* String lengths are passed at the very ** end of the argument list. */ FORTRAN ( \ SCOTCHFMESHGEOMSAVESCOT, scotchfmeshgeomsavescot, ( \ const SCOTCH_Mesh * const meshptr, \ const SCOTCH_Geom * const geomptr, \ const int * const filegrfptr, \ const int * const filegeoptr, \ const char * const dataptr, /* No use */ \ int * const revaptr, \ const int datanbr), \ (meshptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) { FILE * filegrfstream; /* Streams to build from handles */ FILE * filegeostream; int filegrfnum; /* Duplicated handle */ int filegeonum; int o; if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFMESHGEOMSAVESCOT: cannot duplicate handle (1)"); *revaptr = 1; /* Indicate error */ return; } if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFMESHGEOMSAVESCOT: cannot duplicate handle (2)"); close (filegrfnum); *revaptr = 1; /* Indicate error */ return; } if ((filegrfstream = fdopen (filegrfnum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFMESHGEOMSAVESCOT: cannot open output stream (1)"); close (filegrfnum); close (filegeonum); *revaptr = 1; return; } if ((filegeostream = fdopen (filegeonum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFMESHGEOMSAVESCOT: cannot open output stream (2)"); fclose (filegrfstream); close (filegeonum); *revaptr = 1; return; } o = SCOTCH_meshGeomSaveScot (meshptr, geomptr, filegrfstream, filegeostream, NULL); fclose (filegrfstream); /* This closes file descriptors too */ fclose (filegeostream); *revaptr = o; } scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_cp.c0000644000175300017530000006712711631334325022442 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_cp.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders vertices by compres- **/ /** sing vertices with identical adjacency **/ /** structure. **/ /** **/ /** DATES : # Version 3.2 : from : 29 aug 1998 **/ /** to 12 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 03 jan 1999 **/ /** # Version 4.0 : from : 01 jan 2003 **/ /** to 05 jan 2005 **/ /** # Version 5.0 : from : 29 dec 2006 **/ /** to 22 may 2008 **/ /** # Version 5.1 : from : 01 oct 2009 **/ /** to : 01 oct 2009 **/ /** **/ /** NOTES : # Pre-hashing proves itself extremely **/ /** efficient, since for graphs that **/ /** will be compressed very few writes **/ /** will be performed in the pre-hashing **/ /** array, and for others, for which pre- **/ /** hashing costs much more, it will save **/ /** time in the end. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HGRAPH_ORDER_CP #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "order.h" #include "hgraph.h" #include "hgraph_order_cp.h" #include "hgraph_order_st.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hgraphOrderCp ( const Hgraph * restrict const finegrafptr, Order * restrict const fineordeptr, const Gnum ordenum, /*+ Zero-based ordering number +*/ OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ const HgraphOrderCpParam * const paraptr) { Hgraph coargrafdat; /* Compressed halo subgraph */ Order coarordedat; /* Ordering of compressed halo subgraph */ Gnum * restrict coarperitab; /* Coarse permutation array */ const Gnum * restrict coarperitax; /* Temporary based access to coarperitab */ Gnum coarvertnbr; /* Number of compressed vertices */ Gnum coarvertnum; /* Number of current compressed vertex */ Gnum * restrict coarvsiztax; /* Array of coarse vertex sizes (as number of merged fine vertices) */ Gnum coaredgenbr; /* Number of compressed edges */ Gnum coaredgenum; /* Number of current compressed edge */ Gnum coarenohnnd; /* Position in edge array of first edge of first halo vertex */ Gnum * restrict coarvpostax; /* Position in fine permutation of fine vertices merged into same vertex */ Gnum * restrict finecoartax; /* Original to compressed vertex number array */ HgraphOrderCpMate * restrict finematetab; /* Array of fine vertices that may be compressed with current vertex */ HgraphOrderCpHash * restrict finehashtab; /* Neighbor hash table */ Gnum finehashmsk; /* Mask for access to hash table */ int * restrict finehasptab; /* Pre-hashing table */ Gnum finehaspmsk; /* Mask for access to pre-hashing table */ Gnum * restrict finehsumtax; /* Array of hash values for each original vertex */ Gnum finevertnbr; /* Number of fine vertices in compressed elimination tree */ Gnum finevertnum; /* Number of current original vertex */ Gnum finevsizsum; /* Sum of compressed vertex sizes to build fine inverse permutation */ void * dataptr; /* Flag of memory allocation success */ const Gnum * restrict const fineverttax = finegrafptr->s.verttax; const Gnum * restrict const finevendtax = finegrafptr->s.vendtax; const Gnum * restrict const finevnhdtax = finegrafptr->vnhdtax; const Gnum * restrict const fineedgetax = finegrafptr->s.edgetax; for (finehashmsk = 15; /* Set neighbor hash table sizes */ finehashmsk < finegrafptr->s.degrmax; finehashmsk = finehashmsk * 2 + 1) ; finehashmsk = finehashmsk * 4 + 3; /* Fill hash table at 1/4 of capacity */ if (((finecoartax = (Gnum *) memAlloc (finegrafptr->s.vertnbr * sizeof (Gnum))) == NULL) || (memAllocGroup ((void **) (void *) &finehashtab, (size_t) ((finehashmsk + 1) * sizeof (HgraphOrderCpHash)), &finematetab, (size_t) (finegrafptr->s.degrmax * sizeof (HgraphOrderCpMate)), NULL) == NULL) || ((finehsumtax = (Gnum *) memAlloc (finegrafptr->vnohnbr * sizeof (Gnum))) == NULL)) { errorPrint ("hgraphOrderCp: out of memory (1)"); if (finecoartax != NULL) { if (finehashtab != NULL) memFree (finehashtab); memFree (finecoartax); } return (1); } finehsumtax -= finegrafptr->s.baseval; /* TRICK: do not base finecoartax yet (see later) */ finehasptab = (int *) finecoartax; /* Use finecoartab as temporary pre-hash table */ for (finehaspmsk = 1; /* Get pre-hash mask that fits in finecoartab */ finehaspmsk < finegrafptr->s.vertnbr; /* Smallest (2^i)-1 value >= vertnbr */ finehaspmsk = finehaspmsk * 2 + 1) ; finehaspmsk >>= 1; /* Ensure masked data will always fit into finecoartab array */ finehaspmsk = (finehaspmsk * (sizeof (Gnum) / sizeof (int))) + ((sizeof (Gnum) / sizeof (int)) - 1); if (finehaspmsk >= ((sizeof (int) << (3 + 1)) - 1)) /* Only use 1/8 of array for pre-hashing, for increased cache locality */ finehaspmsk >>= 3; memSet (finehasptab, 0, (finehaspmsk + 1) * sizeof (int)); /* Initialize pre-hash table */ for (finevertnum = finegrafptr->s.baseval, coarvertnbr = finegrafptr->vnohnbr; /* For all non-halo vertices */ finevertnum < finegrafptr->vnohnnd; finevertnum ++) { Gnum fineedgenum; /* Current edge number */ Gnum finehsumval; /* Hash sum value */ Gnum finehsumbit; for (fineedgenum = fineverttax[finevertnum], finehsumval = finevertnum; /* For all edges, including halo edges */ fineedgenum < finevendtax[finevertnum]; fineedgenum ++) finehsumval += fineedgetax[fineedgenum]; finehsumtax[finevertnum] = finehsumval; finehsumbit = finehsumval & ((sizeof (int) << 3) - 1); /* Get bit mask and byte position (division should be optimized into a shift) */ finehsumval /= (sizeof (int) << 3); finehsumval &= finehaspmsk; /* Make hash sum value fit into finehasptab */ coarvertnbr -= (finehasptab[finehsumval] >> finehsumbit) & 1; /* If hash value already in pre-hash table, maybe one more vertex compressed */ finehasptab[finehsumval] |= (1 << finehsumbit); /* Put value into pre-hash table anyway */ } if ((double) coarvertnbr > ((double) finegrafptr->vnohnbr * paraptr->comprat)) { /* If graph needs not be compressed */ memFree (finehsumtax + finegrafptr->s.baseval); memFree (finehashtab); memFree (finecoartax); /* Not yet based */ return (hgraphOrderSt (finegrafptr, fineordeptr, ordenum, cblkptr, paraptr->stratunc)); } finecoartax -= finegrafptr->s.baseval; /* Base finecoartab array */ memSet (finehashtab, ~0, (finehashmsk + 1) * sizeof (HgraphOrderCpHash)); hgraphInit (&coargrafdat); /* Initialize compressed halo graph structure */ coargrafdat.s.baseval = 1; /* Base coarse graph to 1 because hgraphOrderHb and hgraphOrderHf prefer it */ for (finevertnum = finegrafptr->s.baseval, coarvertnbr = coargrafdat.s.baseval, coaredgenbr = finegrafptr->s.edgenbr; /* For all non-halo vertices */ finevertnum < finegrafptr->vnohnnd; finevertnum ++) { Gnum finedegrval; /* Degree of current fine vertex */ Gnum finehsumval; /* Current hash sum value */ Gnum finematenbr; /* Number of mates of current vertex */ Gnum fineedgenum; /* Current edge number */ finedegrval = finevendtax[finevertnum] - fineverttax[finevertnum]; finehsumval = finehsumtax[finevertnum]; finematenbr = 0; /* Reset potential mate array */ for (fineedgenum = fineverttax[finevertnum]; /* For all edges, including halo edges */ fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { Gnum finevertend; finevertend = fineedgetax[fineedgenum]; if ((finevertend < finevertnum) && /* If neighbor has same characteristics */ (finehsumval == finehsumtax[finevertend]) && (finedegrval == (finevendtax[finevertend] - fineverttax[finevertend]))) { Gnum finematenum; Gnum coarvertend; for (finematenum = 0, coarvertend = finecoartax[finevertend]; /* Search if end vertex has already been compressed with some mate */ (finematenum < finematenbr) && (finematetab[finematenum].coarvertend != coarvertend); finematenum ++) ; if (finematenum == finematenbr) { /* If new slot needed */ finematetab[finematenum].coarvertend = coarvertend; /* Build it */ finematetab[finematenum].finevertend = finevertend; finematenbr ++; } } } finecoartax[finevertnum] = coarvertnbr ++; /* Assume no mate found */ if (finematenbr > 0) { /* If potential mates exist */ Gnum fineedgenum; /* Current edge number */ Gnum finehashnum; for (fineedgenum = fineverttax[finevertnum]; /* For all edges, including halo edges */ fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { Gnum finevertend; finevertend = fineedgetax[fineedgenum]; /* Add end vertex to hash table */ for (finehashnum = (finevertend * HGRAPHORDERCPHASHPRIME) & finehashmsk; /* Search for empty slot in hash table */ finehashtab[finehashnum].vertnum == finevertnum; finehashnum = (finehashnum + 1) & finehashmsk) ; finehashtab[finehashnum].vertnum = finevertnum; finehashtab[finehashnum].vertend = finevertend; } for (finehashnum = (finevertnum * HGRAPHORDERCPHASHPRIME) & finehashmsk; /* Add current vertex to hash table */ finehashtab[finehashnum].vertnum == finevertnum; finehashnum = (finehashnum + 1) & finehashmsk) ; finehashtab[finehashnum].vertnum = finevertnum; finehashtab[finehashnum].vertend = finevertnum; finematenbr --; /* Point to first potential mate */ do { /* For all potential mates */ Gnum fineedgenum; /* Current edge number */ Gnum fineedgennd; for (fineedgenum = fineverttax[finematetab[finematenbr].finevertend], /* For all edges, including halo edges */ fineedgennd = finevendtax[finematetab[finematenbr].finevertend]; fineedgenum < fineedgennd; fineedgenum ++) { Gnum finevertend; finevertend = fineedgetax[fineedgenum]; for (finehashnum = (finevertend * HGRAPHORDERCPHASHPRIME) & finehashmsk; ; finehashnum = (finehashnum + 1) & finehashmsk) { if (finehashtab[finehashnum].vertnum != finevertnum) /* If mate neighbor not found in hash table */ goto loop_failed; /* Vertex cannot be merged to mate, so skip to next mate */ if (finehashtab[finehashnum].vertend == finevertend) /* Else if mate neighbor found in hash table */ break; /* Skip to next mate neighbor to find */ } } coarvertnbr --; /* Same adjacency structure */ finecoartax[finevertnum] = finematetab[finematenbr].coarvertend; /* Get number */ coaredgenbr -= finedegrval + 1; /* Remove exceeding edges */ break; loop_failed: ; } while (finematenbr -- > 0); } } coargrafdat.vnohnnd = coarvertnbr; /* Save number of non-halo vertices */ memFree (finehsumtax + finegrafptr->s.baseval); if ((double) (coarvertnbr - coargrafdat.s.baseval) > ((double) finegrafptr->vnohnbr * paraptr->comprat)) { /* If graph needs not be compressed */ memFree (finehashtab); memFree (finecoartax + finegrafptr->s.baseval); return (hgraphOrderSt (finegrafptr, fineordeptr, ordenum, cblkptr, paraptr->stratunc)); } for ( ; finevertnum < finegrafptr->s.vertnnd; finevertnum ++) /* For all halo vertices */ finecoartax[finevertnum] = coarvertnbr ++; /* Halo vertices are never compressed */ coargrafdat.s.flagval = HGRAPHFREETABS | GRAPHVERTGROUP; coargrafdat.s.vertnbr = coarvertnbr - coargrafdat.s.baseval; coargrafdat.s.vertnnd = coarvertnbr; coargrafdat.s.velosum = finegrafptr->s.velosum; coargrafdat.s.degrmax = finegrafptr->s.degrmax; coargrafdat.vnohnbr = coargrafdat.vnohnnd - coargrafdat.s.baseval; coargrafdat.vnlosum = finegrafptr->vnlosum; if (finegrafptr->s.velotax == NULL) { if (finegrafptr->s.vertnbr == finegrafptr->vnohnbr) { /* If no halo present */ dataptr = memAllocGroup ((void **) (void *) &coargrafdat.s.verttax, (size_t) ((coarvertnbr + 1) * sizeof (Gnum)), &coargrafdat.s.velotax, (size_t) (coarvertnbr * sizeof (Gnum)), NULL); coargrafdat.vnhdtax = coargrafdat.s.verttax + 1; } else { dataptr = memAllocGroup ((void **) (void *) &coargrafdat.s.verttax, (size_t) ((coarvertnbr + 1) * sizeof (Gnum)), &coargrafdat.vnhdtax, (size_t) (coargrafdat.vnohnbr * sizeof (Gnum)), &coargrafdat.s.velotax, (size_t) (coarvertnbr * sizeof (Gnum)), NULL); } coarvsiztax = coargrafdat.s.velotax; } else { if (finegrafptr->s.vertnbr == finegrafptr->vnohnbr) { /* If no halo present */ dataptr = memAllocGroup ((void **) (void *) &coargrafdat.s.verttax, (size_t) ((coarvertnbr + 1) * sizeof (Gnum)), &coargrafdat.s.velotax, (size_t) (coarvertnbr * sizeof (Gnum)), &coarvsiztax, (size_t) (coarvertnbr * sizeof (Gnum)), NULL); coargrafdat.vnhdtax = coargrafdat.s.verttax + 1; } else { dataptr = memAllocGroup ((void **) (void *) &coargrafdat.s.verttax, (size_t) ((coarvertnbr + 1) * sizeof (Gnum)), &coargrafdat.vnhdtax, (size_t) (coargrafdat.vnohnbr * sizeof (Gnum)), &coargrafdat.s.velotax, (size_t) (coarvertnbr * sizeof (Gnum)), &coarvsiztax, (size_t) (coarvertnbr * sizeof (Gnum)), NULL); } } if (dataptr != NULL) { dataptr = coargrafdat.s.edgetax = (Gnum *) memAlloc (coaredgenbr * sizeof (Gnum)); } if (dataptr == NULL) { errorPrint ("hgraphOrderCp: out of memory (2)"); hgraphExit (&coargrafdat); memFree (finehashtab); memFree (finecoartax + finegrafptr->s.baseval); return (1); } coargrafdat.s.verttax -= coargrafdat.s.baseval; coargrafdat.s.vendtax = coargrafdat.s.verttax + 1; /* Use compact representation of arrays */ coargrafdat.s.velotax -= coargrafdat.s.baseval; coargrafdat.s.edgetax -= coargrafdat.s.baseval; coargrafdat.vnhdtax -= coargrafdat.s.baseval; coarvsiztax -= coargrafdat.s.baseval; memSet (finehashtab, ~0, (finehashmsk + 1) * sizeof (HgraphOrderCpHash)); for (finevertnum = finegrafptr->s.baseval, coarvertnum = coaredgenum = coargrafdat.s.baseval; /* For all non-halo vertices */ finevertnum < finegrafptr->vnohnnd; finevertnum ++) { Gnum fineedgenum; /* Current edge number */ if (finecoartax[finevertnum] != coarvertnum) continue; coargrafdat.s.verttax[coarvertnum] = coaredgenum; coarvsiztax[coarvertnum] = 1; /* Fill coargrafdat.s.velotax if finegrafptr has no vertex loads */ for (fineedgenum = fineverttax[finevertnum]; /* For all non-halo edges of vertex */ fineedgenum < finevnhdtax[finevertnum]; fineedgenum ++) { Gnum finevertend; Gnum finehashnum; finevertend = fineedgetax[fineedgenum]; if (finecoartax[finevertend] == coarvertnum) { /* If neighbor is merged into us, merge load but do not write edge */ coarvsiztax[coarvertnum] ++; /* Fill coargrafdat.s.velotax if finegrafptr has no vertex loads */ continue; } for (finehashnum = (finecoartax[finevertend] * HGRAPHORDERCPHASHPRIME) & finehashmsk; ; /* Search for end vertex in hash table */ finehashnum = (finehashnum + 1) & finehashmsk) { if (finehashtab[finehashnum].vertnum != coarvertnum) { finehashtab[finehashnum].vertnum = coarvertnum; finehashtab[finehashnum].vertend = finecoartax[finevertend]; coargrafdat.s.edgetax[coaredgenum ++] = finecoartax[finevertend]; break; } if (finehashtab[finehashnum].vertend == finecoartax[finevertend]) break; /* If edge already exists */ } } coargrafdat.vnhdtax[coarvertnum] = coaredgenum; /* Set end of non-halo edge sub-array */ for ( ; fineedgenum < finegrafptr->s.vendtax[finevertnum]; fineedgenum ++) { /* For edges linking to halo vertices */ Gnum finevertend; finevertend = fineedgetax[fineedgenum]; coargrafdat.s.edgetax[coaredgenum ++] = finecoartax[finevertend]; /* Halo vertices are always defined and unique */ } coarvertnum ++; } for (coarenohnnd = coaredgenum; finevertnum < finegrafptr->s.vertnnd; finevertnum ++) { /* For all halo vertices */ Gnum fineedgenum; /* Current edge number */ coargrafdat.s.verttax[coarvertnum] = coaredgenum; coarvsiztax[coarvertnum] = 1; /* Fill coargrafdat.s.velotax if finegrafptr has no vertex loads */ for (fineedgenum = fineverttax[finevertnum]; /* For all edges of halo vertex */ fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { Gnum finevertend; finevertend = fineedgetax[fineedgenum]; coargrafdat.s.edgetax[coaredgenum ++] = finecoartax[finevertend]; } coarvertnum ++; } coargrafdat.s.verttax[coarvertnum] = coaredgenum; /* Set end of compact vertex array */ coargrafdat.s.edlosum = coargrafdat.s.edgenbr = coaredgenum - coargrafdat.s.baseval; coargrafdat.enohsum = coargrafdat.enohnbr = coargrafdat.s.edgenbr - 2 * (coaredgenum - coarenohnnd); if (finegrafptr->s.velotax != NULL) { /* If fine graph has vertex loads */ memSet (coargrafdat.s.velotax + coargrafdat.s.baseval, 0, coargrafdat.s.vertnbr * sizeof (Gnum)); for (finevertnum = finegrafptr->s.baseval; finevertnum < finegrafptr->s.vertnnd; finevertnum ++) /* Compute vertex loads for compressed graph */ coargrafdat.s.velotax[finecoartax[finevertnum]] += finegrafptr->s.velotax[finevertnum]; } memFree (finehashtab); coargrafdat.s.edgetax = (Gnum *) memRealloc (coargrafdat.s.edgetax + coargrafdat.s.baseval, coargrafdat.s.edgenbr * sizeof (Gnum)) - coargrafdat.s.baseval; #ifdef SCOTCH_DEBUG_ORDER2 if (hgraphCheck (&coargrafdat) != 0) { errorPrint ("hgraphOrderCp: internal error (1)"); hgraphExit (&coargrafdat); memFree (finecoartax + finegrafptr->s.baseval); return (1); } #endif /* SCOTCH_DEBUG_ORDER2 */ if ((coarperitab = memAlloc (coargrafdat.s.vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("hgraphOrderCp: out of memory (3)"); hgraphExit (&coargrafdat); memFree (finecoartax + finegrafptr->s.baseval); return (1); } orderInit (&coarordedat, coargrafdat.s.baseval, coargrafdat.s.vertnbr, coarperitab); /* Build ordering of compressed subgraph */ if (hgraphOrderSt (&coargrafdat, &coarordedat, 0, &coarordedat.cblktre, paraptr->stratcpr) != 0) { memFree (coarperitab); hgraphExit (&coargrafdat); memFree (finecoartax + finegrafptr->s.baseval); return (1); } *cblkptr = coarordedat.cblktre; /* Link sub-tree to ordering */ coarordedat.cblktre.cblktab = NULL; /* Unlink sub-tree from sub-ordering */ finevertnbr = hgraphOrderCpTree (coarordedat.peritab, /* Expand sub-tree */ coarvsiztax, cblkptr, 0); #ifdef SCOTCH_DEBUG_ORDER2 if (finevertnbr != finegrafptr->s.vertnbr) { errorPrint ("hgraphOrderCp: internal error (2)"); memFree (coarperitab); hgraphExit (&coargrafdat); memFree (finecoartax + finegrafptr->s.baseval); return (1); } #endif /* SCOTCH_DEBUG_ORDER2 */ fineordeptr->treenbr += coarordedat.treenbr - 1; /* Adjust number of tree nodes */ fineordeptr->cblknbr += coarordedat.cblknbr - 1; /* Adjust number of column blocks */ coarvpostax = coargrafdat.s.verttax; /* Re-cycle verttab (not velotab as may be merged with coarvsiztab) */ coarperitax = coarperitab - coargrafdat.s.baseval; for (coarvertnum = coargrafdat.s.baseval, finevsizsum = 0; /* Compute initial indices for inverse permutation expansion */ coarvertnum < coargrafdat.s.vertnnd; coarvertnum ++) { coarvpostax[coarperitax[coarvertnum]] = finevsizsum; finevsizsum += coarvsiztax[coarperitax[coarvertnum]]; } for (finevertnum = finegrafptr->s.baseval; finevertnum < finegrafptr->s.vertnnd; finevertnum ++) /* Compute fine permutation */ fineordeptr->peritab[coarvpostax[finecoartax[finevertnum]] ++] = finevertnum; memFree (coarperitab); memFree (finecoartax + finegrafptr->s.baseval); orderExit (&coarordedat); hgraphExit (&coargrafdat); /* Free coarvsiztab as part of vertex group */ return (0); } /* This routine turns the coarse elimination ** tree produced by the ordering of the coarse ** graph into a fine elimination tree, according ** to the cardinality of the coarse vertices. ** It returns: ** - !0 : overall number of fine vertices, in all cases. */ static Gnum hgraphOrderCpTree ( const Gnum * restrict const coarperitab, /* Coarse inverse permutation */ const Gnum * restrict const coarvsiztax, /* Array of fine sizes of coarse vertices */ OrderCblk * restrict const coficblkptr, /* Current coarse/fine column block cell */ Gnum coarordenum) /* Compressed vertex to start expansion at */ { Gnum finevertnbr; /* Number of fine vertices in subtree */ finevertnbr = 0; /* No fine vertices yet */ if (coficblkptr->cblktab == NULL) { /* If leaf of column block tree */ Gnum coarvnumnum; for (coarvnumnum = coarordenum; coarvnumnum < coarordenum + coficblkptr->vnodnbr; coarvnumnum ++) finevertnbr += coarvsiztax[coarperitab[coarvnumnum]]; /* Sum-up fine vertices */ } else { Gnum coarvertnbr; /* Number of coarse vertices in cell */ Gnum coarvertsum; /* Number of coarse vertices in subtree */ Gnum coficblknum; /* Index in column block array */ for (coficblknum = 0, coarvertsum = coarordenum; /* Start at current coarse index */ coficblknum < coficblkptr->cblknbr; coficblknum ++) { coarvertnbr = coficblkptr->cblktab[coficblknum].vnodnbr; /* Save number of coarse vertices */ finevertnbr += hgraphOrderCpTree (coarperitab, coarvsiztax, &coficblkptr->cblktab[coficblknum], coarvertsum); coarvertsum += coarvertnbr; /* Sum-up coarse vertices */ } } coficblkptr->vnodnbr = finevertnbr; /* Set number of fine vertices */ return (finevertnbr); /* Return accumulated number */ } scotch-5.1.12b.dfsg/src/libscotch/hdgraph_order_nd.c0000644000175300017530000004633011631334325022576 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph_order_nd.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders distributed graphs **/ /** using the nested dissection algorithm. **/ /** **/ /** DATES : # Version 5.0 : from : 16 apr 2006 **/ /** to 01 mar 2008 **/ /** # Version 5.1 : from : 27 sep 2008 **/ /** to 11 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HDGRAPH_ORDER_ND #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "order.h" #include "hgraph.h" #include "hgraph_order_st.h" #include "dgraph.h" #include "dorder.h" #include "hdgraph.h" #include "hdgraph_order_nd.h" #include "hdgraph_order_sq.h" #include "hdgraph_order_st.h" #include "vdgraph.h" #include "vdgraph_separate_st.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine builds either a centralized or a ** distributed subgraph, according to the number ** of processes in the given part. The calling ** conventions of this routine have been designed ** so as to allow for multi-threading. */ static void * hdgraphOrderNdFold2 ( void * const dataptr) /* Pointer to thread data */ { HdgraphOrderNdData * fldthrdptr; /* Thread input parameters */ HdgraphOrderNdGraph * restrict fldgrafptr; /* Pointer to folded graph area */ Hdgraph indgrafdat; /* Induced distributed halo graph */ void * o; fldthrdptr = (HdgraphOrderNdData *) dataptr; fldgrafptr = fldthrdptr->fldgrafptr; if (hdgraphInduceList (fldthrdptr->orggrafptr, fldthrdptr->indlistnbr, /* Compute unfinished induced subgraph on all processes */ fldthrdptr->indlisttab, &indgrafdat) != 0) return ((void *) 1); o = ((void *) 0); if (fldthrdptr->fldprocnbr > 1) { /* If subpart has several processes, fold a distributed graph */ if (hdgraphFold2 (&indgrafdat, fldthrdptr->fldpartval, /* Fold temporary induced subgraph from all processes */ &fldgrafptr->data.dgrfdat, fldthrdptr->fldproccomm) != 0) o = ((void *) 1); } else { /* Create a centralized graph */ Hgraph * restrict fldcgrfptr; fldcgrfptr = (fldthrdptr->fldprocnum == 0) ? &fldgrafptr->data.cgrfdat : NULL; /* See if we are the receiver */ if (hdgraphGather (&indgrafdat, fldcgrfptr) != 0) /* Gather centralized subgraph from all other processes */ o = ((void *) 1); } hdgraphExit (&indgrafdat); /* Free temporary induced graph */ return (o); } static int hdgraphOrderNdFold ( Hdgraph * restrict const orggrafptr, const Gnum indlistnbr0, /* Number of vertices in subgraph 0 */ const Gnum * restrict const indlisttab0, /* List of vertices in subgraph 0 */ const Gnum indlistnbr1, /* Number of vertices in subgraph 1 */ const Gnum * restrict const indlisttab1, /* List of vertices in subgraph 1 */ HdgraphOrderNdGraph * restrict const fldgrafptr) { HdgraphOrderNdData fldthrdtab[2]; MPI_Comm fldproccomm; int fldprocnbr; int fldprocnum; int fldproccol; int fldpartval; #ifdef SCOTCH_PTHREAD Hdgraph orggrafdat; /* Structure for copying graph fields except communicator */ pthread_t thrdval; /* Data of second thread */ #endif /* SCOTCH_PTHREAD */ int o; if (dgraphGhst (&orggrafptr->s) != 0) { /* Compute ghost edge array if not already present, before copying graph fields */ errorPrint ("hdgraphOrderNdFold: cannot compute ghost edge array"); return (1); } fldprocnbr = (orggrafptr->s.procglbnbr + 1) / 2; /* Median cut on number of processors */ fldthrdtab[0].fldprocnbr = fldprocnbr; fldthrdtab[1].fldprocnbr = orggrafptr->s.procglbnbr - fldprocnbr; if (orggrafptr->s.proclocnum < fldprocnbr) { /* Compute color and rank in two subparts */ fldpartval = 0; fldprocnum = orggrafptr->s.proclocnum; fldthrdtab[0].fldprocnum = fldprocnum; fldthrdtab[1].fldprocnum = -1; fldthrdtab[1].fldproccomm = MPI_COMM_NULL; } else { fldpartval = 1; fldprocnum = orggrafptr->s.proclocnum - fldprocnbr; fldprocnbr = orggrafptr->s.procglbnbr - fldprocnbr; fldthrdtab[0].fldproccomm = MPI_COMM_NULL; fldthrdtab[0].fldprocnum = -1; fldthrdtab[1].fldprocnum = fldprocnum; } fldgrafptr->typeval = HDGRAPHORDERNDTYPEDIST; /* Assume we belong to a distributed subpart */ fldproccol = fldpartval; /* Split color is the part value */ if (fldprocnbr <= 1) { /* If our part will have only one processor */ fldproccol = MPI_UNDEFINED; /* Do not create any sub-communicator for it */ fldgrafptr->typeval = HDGRAPHORDERNDTYPECENT; /* We will host a centralized subgraph */ } if (MPI_Comm_split (orggrafptr->s.proccomm, fldproccol, fldprocnum, &fldproccomm) != MPI_SUCCESS) { errorPrint ("hdgraphOrderNdFold: communication error"); return (1); } fldthrdtab[fldpartval].fldproccomm = fldproccomm; /* Assign folded communicator to proper part */ fldthrdtab[0].orggrafptr = orggrafptr; /* Load data to pass to the subgraph building routines */ fldthrdtab[0].indlistnbr = indlistnbr0; fldthrdtab[0].indlisttab = indlisttab0; fldthrdtab[0].fldgrafptr = fldgrafptr; fldthrdtab[0].fldpartval = 0; fldthrdtab[1].indlistnbr = indlistnbr1; fldthrdtab[1].indlisttab = indlisttab1; fldthrdtab[1].fldgrafptr = fldgrafptr; fldthrdtab[1].fldpartval = 1; #ifdef SCOTCH_PTHREAD orggrafdat = *orggrafptr; /* Create a separate graph structure to change its communicator */ fldthrdtab[1].orggrafptr = &orggrafdat; MPI_Comm_dup (orggrafptr->s.proccomm, &orggrafdat.s.proccomm); /* Duplicate communicator to avoid interferences in communications */ if (pthread_create (&thrdval, NULL, hdgraphOrderNdFold2, (void *) &fldthrdtab[1]) != 0) /* If could not create thread */ o = ((int) (intptr_t) hdgraphOrderNdFold2 ((void *) &fldthrdtab[0])) || /* Perform inductions in sequence */ ((int) (intptr_t) hdgraphOrderNdFold2 ((void *) &fldthrdtab[1])); else { /* Newly created thread is processing subgraph 1, so let's process subgraph 0 */ void * o2; o = (int) (intptr_t) hdgraphOrderNdFold2 ((void *) &fldthrdtab[0]); /* Work on copy with private communicator */ pthread_join (thrdval, &o2); o |= (int) (intptr_t) o2; } MPI_Comm_free (&orggrafdat.s.proccomm); #else /* SCOTCH_PTHREAD */ fldthrdtab[1].orggrafptr = orggrafptr; o = ((int) (intptr_t) hdgraphOrderNdFold2 ((void *) &fldthrdtab[0])) || /* Perform inductions in sequence */ ((int) (intptr_t) hdgraphOrderNdFold2 ((void *) &fldthrdtab[1])); #endif /* SCOTCH_PTHREAD */ return (o); } /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hdgraphOrderNd ( Hdgraph * restrict const grafptr, DorderCblk * restrict const cblkptr, const HdgraphOrderNdParam * restrict const paraptr) { Vdgraph vspgrafdat; /* Vertex separation graph data */ Gnum vspvertlocnum; /* Current vertex in separation graph */ Gnum * restrict vspvnumtab[2]; /* Lists of separated parts */ Gnum * restrict vspvnumptr0; Gnum * restrict vspvnumptr1; Gnum ordeglbval; Gnum vnodglbnbr; Gnum cblkfthnum; HdgraphOrderNdGraph indgrafdat01; /* Induced folded graph area */ DorderCblk * cblkptr01; int partmax; /* Induced part having most vertices */ int procnbr0; /* Number of processes in first part */ int cheklocval; int chekglbval; int o; #ifdef SCOTCH_DEBUG_HDGRAPH2 if (cblkptr->vnodglbnbr != grafptr->s.vertglbnbr) { errorPrint ("hdgraphOrderNd: inconsistent parameters"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ if (grafptr->s.procglbnbr == 1) { /* If we are running on a single process */ HdgraphOrderSqParam paradat; paradat.ordstratseq = paraptr->ordstratseq; return (hdgraphOrderSq (grafptr, cblkptr, ¶dat)); /* Run sequentially */ } if (dgraphGhst (&grafptr->s) != 0) { /* Compute ghost edge array if not already present, to have vertgstnbr (and procsidtab) */ errorPrint ("hdgraphOrderNd: cannot compute ghost edge array"); return (1); } vspgrafdat.s = grafptr->s; /* Get non-halo part of halo distributed graph */ vspgrafdat.s.flagval &= ~DGRAPHFREEALL; /* Do not free contents of separation graph */ vspgrafdat.s.vlblloctax = NULL; /* Never mind about vertex labels in the future */ cheklocval = 0; if ((vspgrafdat.fronloctab = (Gnum *) memAlloc (vspgrafdat.s.vertlocnbr * sizeof (Gnum))) == NULL) { errorPrint ("hdgraphOrderNd: out of memory (1)"); vspgrafdat.partgsttax = NULL; cheklocval = 1; } else if ((vspgrafdat.partgsttax = (GraphPart *) memAlloc (vspgrafdat.s.vertgstnbr * sizeof (GraphPart))) == NULL) { errorPrint ("hdgraphOrderNd: out of memory (2)"); cheklocval = 1; } #ifdef SCOTCH_DEBUG_HDGRAPH1 /* Communication cannot be merged with a useful one */ if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphOrderNd: communication error (1)"); return (1); } #else /* SCOTCH_DEBUG_HDGRAPH1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_HDGRAPH1 */ if (chekglbval != 0) { if (vspgrafdat.fronloctab != NULL) { if (vspgrafdat.partgsttax != NULL) memFree (vspgrafdat.partgsttax); memFree (vspgrafdat.fronloctab); } return (1); } vspgrafdat.partgsttax -= vspgrafdat.s.baseval; vspgrafdat.levlnum = grafptr->levlnum; /* Set level of separation graph as level of halo graph */ vdgraphZero (&vspgrafdat); /* Set all local vertices to part 0 */ if (vdgraphSeparateSt (&vspgrafdat, paraptr->sepstrat) != 0) { /* Separate vertex-separation graph */ memFree (vspgrafdat.partgsttax + vspgrafdat.s.baseval); memFree (vspgrafdat.fronloctab); return (1); } if ((vspgrafdat.compglbsize[0] == 0) || /* If could not separate more */ (vspgrafdat.compglbsize[1] == 0)) { memFree (vspgrafdat.partgsttax + vspgrafdat.s.baseval); /* Free useless space */ memFree (vspgrafdat.fronloctab); hdgraphOrderSt (grafptr, cblkptr, paraptr->ordstratlea); /* Order this leaf */ return (0); /* Leaf has been processed */ } vspvnumtab[0] = vspgrafdat.fronloctab + vspgrafdat.complocsize[2]; /* Build vertex lists within frontier array */ vspvnumtab[1] = vspvnumtab[0] + vspgrafdat.complocsize[0]; vspvnumptr0 = vspvnumtab[0]; vspvnumptr1 = vspvnumtab[1]; for (vspvertlocnum = vspgrafdat.s.baseval; vspvertlocnum < vspgrafdat.s.vertlocnnd; vspvertlocnum ++) { /* Fill lists */ GraphPart partval; partval = vspgrafdat.partgsttax[vspvertlocnum]; if (partval == 0) *vspvnumptr0 ++ = vspvertlocnum; else if (partval == 1) *vspvnumptr1 ++ = vspvertlocnum; } memFree (vspgrafdat.partgsttax + vspgrafdat.s.baseval); /* Free useless space */ #ifdef SCOTCH_DEBUG_HDGRAPH2 vspgrafdat.partgsttax = NULL; /* Will cause bug if re-read */ if ((vspvnumptr0 != vspvnumtab[0] + vspgrafdat.complocsize[0]) || (vspvnumptr1 != vspvnumtab[1] + vspgrafdat.complocsize[1])) { errorPrint ("hdgraphOrderNd: internal error (1)"); memFree (vspgrafdat.fronloctab); /* Free useless space */ return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ cblkptr->typeval = DORDERCBLKNEDI; /* Node becomes a nested dissection node */ o = 0; if (vspgrafdat.compglbsize[2] != 0) { /* If separator not empty */ DorderCblk * cblkptr2; Hdgraph indgrafdat2; cblkptr2 = dorderNew (cblkptr, grafptr->s.proccomm); /* Create separator node */ cblkptr2->ordeglbval = cblkptr->ordeglbval + grafptr->s.vertglbnbr - vspgrafdat.compglbsize[2]; cblkptr2->vnodglbnbr = vspgrafdat.compglbsize[2]; cblkptr2->cblkfthnum = 2; cblkptr->data.nedi.cblkglbnbr = 3; /* It is a three-cell node */ if (dgraphInduceList (&grafptr->s, vspgrafdat.complocsize[2], /* Perform non-halo induction for separator, as it will get highest numbers */ vspgrafdat.fronloctab, &indgrafdat2.s) != 0) { errorPrint ("hdgraphOrderNd: cannot build induced subgraph (1)"); memFree (vspgrafdat.fronloctab); /* Free remaining space */ return (1); } indgrafdat2.vhallocnbr = 0; /* No halo on graph */ indgrafdat2.vhndloctax = indgrafdat2.s.vendloctax; indgrafdat2.ehallocnbr = 0; indgrafdat2.levlnum = 0; /* Separator graph is at level zero not to be suppressed as an intermediate graph */ o = hdgraphOrderSt (&indgrafdat2, cblkptr2, paraptr->ordstratsep); hdgraphExit (&indgrafdat2); dorderDispose (cblkptr2); /* Dispose of separator column block (may be kept as leaf) */ if (o != 0) { memFree (vspgrafdat.fronloctab); /* Free remaining space */ return (1); } } else /* Separator is empty */ cblkptr->data.nedi.cblkglbnbr = 2; /* It is a two-cell tree node */ partmax = (vspgrafdat.compglbsize[0] >= vspgrafdat.compglbsize[1]) ? 0 : 1; /* Get part of largest subgraph */ procnbr0 = (grafptr->s.procglbnbr + 1) / 2; /* Get number of processes in part 0 (always more than in part 1) */ if (grafptr->s.proclocnum < procnbr0) { /* If process will handle part 0 (bigger part if odd number of processes) */ ordeglbval = cblkptr->ordeglbval; vnodglbnbr = vspgrafdat.compglbsize[partmax]; cblkfthnum = 0; } else { /* If process will handle part 1 (smaller part if odd number of processes) */ ordeglbval = cblkptr->ordeglbval + vspgrafdat.compglbsize[partmax]; vnodglbnbr = vspgrafdat.compglbsize[partmax ^ 1]; cblkfthnum = 1; } o = hdgraphOrderNdFold (grafptr, vspgrafdat.complocsize[partmax], vspvnumtab[partmax], vspgrafdat.complocsize[partmax ^ 1], vspvnumtab[partmax ^ 1], &indgrafdat01); if (o == 0) { switch (indgrafdat01.typeval) { case HDGRAPHORDERNDTYPECENT : if ((cblkptr01 = dorderNewSequ (cblkptr)) == NULL) { o = 1; break; } if (grafptr->levlnum > 0) { /* If intermediate level nested dissection graph */ hdgraphExit (grafptr); /* Free graph before going to next level */ dorderDispose (cblkptr); /* Dispose of column block node too */ } cblkptr01->ordeglbval = ordeglbval; cblkptr01->vnodglbnbr = vnodglbnbr; cblkptr01->cblkfthnum = cblkfthnum; o = hdgraphOrderSq2 (&indgrafdat01.data.cgrfdat, cblkptr01, paraptr->ordstratseq); hgraphExit (&indgrafdat01.data.cgrfdat); /* Free centralized graph here as it is last level */ break; /* No need to dispose of final column block as locally created by dorderNewSequ */ #ifdef SCOTCH_DEBUG_HDGRAPH2 case HDGRAPHORDERNDTYPEDIST : #else /* SCOTCH_DEBUG_HDGRAPH2 */ default : #endif /* SCOTCH_DEBUG_HDGRAPH2 */ if ((cblkptr01 = dorderNew (cblkptr, indgrafdat01.data.dgrfdat.s.proccomm)) == NULL) { o = 1; break; } if (grafptr->levlnum > 0) { /* If intermediate level nested dissection graph */ hdgraphExit (grafptr); /* Free graph before going to next level */ dorderDispose (cblkptr); /* Dispose of column block node too */ } cblkptr01->ordeglbval = ordeglbval; cblkptr01->vnodglbnbr = vnodglbnbr; cblkptr01->cblkfthnum = cblkfthnum; o = hdgraphOrderNd (&indgrafdat01.data.dgrfdat, cblkptr01, paraptr); break; #ifdef SCOTCH_DEBUG_HDGRAPH2 default : errorPrint ("hdgraphOrderNd: internal error (2)"); o = 1; #endif /* SCOTCH_DEBUG_HDGRAPH2 */ } } memFree (vspgrafdat.fronloctab); /* Free remaining space */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/library_version_f.c0000644000175300017530000000622511631334325023022 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_version_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** handling API- and version-related **/ /** routines in the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.1 : from : 16 nov 2010 **/ /** to 16 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the version-related routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFVERSION, scotchfversion, ( \ int * const versptr, \ int * const relaptr, \ int * const patcptr), \ (versptr, relaptr, patcptr)) { SCOTCH_version (versptr, relaptr, patcptr); } scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_hx.c0000644000175300017530000001200711631334325022442 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_hx.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains service routines **/ /** for the hgraphOrderH{d|f} ordering **/ /** routines. **/ /** **/ /** DATES : # Version 4.0 : from : 23 jan 2004 **/ /** to : 28 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HGRAPH_ORDER_HX #include "module.h" #include "common.h" #include "graph.h" #include "hgraph.h" #include "hgraph_order_hx.h" /***********************************/ /* */ /* These are the service routines. */ /* */ /***********************************/ /* This routine fills the input arrays for ** the graph ordering routines. ** It returns: ** - void : in all cases. */ void hgraphOrderHxFill ( const Hgraph * restrict const grafptr, Gnum * restrict const petab, Gnum * restrict const lentab, Gnum * restrict const iwtab, Gnum * restrict const elentab, Gnum * restrict const pfreptr) { Gnum * restrict petax; Gnum * restrict iwtax; Gnum * restrict lentax; Gnum * restrict elentax; Gnum vertadj; /* Index adjustment for vertices */ Gnum vertnum; Gnum vertnew; Gnum edgenew; petax = petab - 1; /* Base HAMF arrays at base 1 */ iwtax = iwtab - 1; lentax = lentab - 1; elentax = elentab - 1; vertadj = 1 - grafptr->s.baseval; for (vertnum = grafptr->s.baseval, vertnew = edgenew = 1; /* Process non-halo vertices */ vertnum < grafptr->vnohnnd; vertnum ++, vertnew ++) { Gnum degrval; Gnum edgenum; degrval = grafptr->s.vendtax[vertnum] - grafptr->s.verttax[vertnum]; petax[vertnew] = edgenew; lentax[vertnew] = degrval; elentax[vertnew] = degrval; for (edgenum = grafptr->s.verttax[vertnum]; edgenum < grafptr->s.vendtax[vertnum]; edgenum ++, edgenew ++) iwtax[edgenew] = grafptr->s.edgetax[edgenum] + vertadj; } for ( ; vertnum < grafptr->s.vertnnd; vertnum ++, vertnew ++) { /* Process halo vertices */ Gnum degrval; Gnum edgenum; degrval = grafptr->s.verttax[vertnum] - grafptr->s.vendtax[vertnum]; petax[vertnew] = edgenew; lentax[vertnew] = (degrval != 0) ? degrval : (-1 - grafptr->s.vertnbr); elentax[vertnew] = 0; for (edgenum = grafptr->s.verttax[vertnum]; edgenum < grafptr->s.vendtax[vertnum]; edgenum ++, edgenew ++) iwtax[edgenew] = grafptr->s.edgetax[edgenum] + vertadj; } *pfreptr = edgenew; /* Set index to first free area */ } scotch-5.1.12b.dfsg/src/libscotch/library_arch_build.c0000644000175300017530000001314511631334325023123 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_arch_build.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the target **/ /** architecture building routine of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 3.3 : from : 02 oct 1998 **/ /** to 29 mar 1999 **/ /** # Version 3.4 : from : 01 nov 2001 **/ /** to 01 nov 2001 **/ /** # Version 4.0 : from : 08 mar 2005 **/ /** to 17 mar 2005 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "arch.h" #include "arch_build.h" #include "mapping.h" #include "bgraph.h" #include "bgraph_bipart_st.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the C API for */ /* the architecture building routine. */ /* */ /**************************************/ /*+ This routine parses the given *** bipartitioning strategy. *** It returns: *** - 0 : if string successfully scanned. *** - !0 : on error. +*/ int SCOTCH_stratGraphBipart ( SCOTCH_Strat * const stratptr, const char * const string) { if (*((Strat **) stratptr) != NULL) stratExit (*((Strat **) stratptr)); if ((*((Strat **) stratptr) = stratInit (&bgraphbipartststratab, string)) == NULL) { errorPrint ("SCOTCH_stratBipart: error in bipartitioning strategy"); return (1); } return (0); } /*+ This routine fills the contents of the given *** opaque target structure with the data provided *** by the user. The source graph provided on input *** is turned into a decomposition-defined target *** architecture. *** It returns: *** - 0 : if the computation succeeded. *** - !0 : on error. +*/ int SCOTCH_archBuild ( SCOTCH_Arch * const archptr, /*+ Target architecture to build +*/ const SCOTCH_Graph * const grafptr, /*+ Graph to turn into architecture +*/ const SCOTCH_Num listnbr, /*+ Number of elements in sublist +*/ const SCOTCH_Num * const listptr, /*+ Pointer to sublist +*/ const SCOTCH_Strat * const stratptr) /*+ Bipartitoning strategy +*/ { Strat * bipstratptr; VertList graflistdat; VertList * graflistptr; int o; if ((sizeof (SCOTCH_Num) != sizeof (Gnum)) || (sizeof (SCOTCH_Num) != sizeof (Anum))) { errorPrint ("SCOTCH_archBuild: internal error (1)"); return (1); } if (*((Strat **) stratptr) == NULL) /* Set default mapping strategy if necessary */ *((Strat **) stratptr) = stratInit (&bgraphbipartststratab, "(m{vert=50,low=h{pass=10},asc=f{move=100,bal=0.1}}f{move=100,bal=0.05})(/((load0=load)|(load0=0))?x;)"); bipstratptr = *((Strat **) stratptr); if (bipstratptr->tabl != &bgraphbipartststratab) { errorPrint ("SCOTCH_archBuild: not a bipartitioning strategy"); return (1); } if ((listnbr == ((Graph *) grafptr)->vertnbr) || (listnbr == 0) || (listptr == NULL)) graflistptr = NULL; else { graflistptr = &graflistdat; graflistdat.vnumnbr = (Gnum) listnbr; graflistdat.vnumtab = (Gnum *) listptr; } o = archBuild ((Arch * const) archptr, (const Graph * const) grafptr, graflistptr, bipstratptr); return (o); } scotch-5.1.12b.dfsg/src/libscotch/order_check.c0000644000175300017530000001430511631334325021552 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : order_check.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module checks the consistency of **/ /** orderings. **/ /** **/ /** DATES : # Version 4.0 : from : 19 dec 2001 **/ /** to 20 nov 2003 **/ /** # Version 5.0 : from : 26 jul 2007 **/ /** to 26 jul 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ORDER_CHECK #include "module.h" #include "common.h" #include "graph.h" #include "order.h" /************************************/ /* */ /* These routines handle orderings. */ /* */ /************************************/ /* This routine checks the consistency ** of the given ordering. ** It returns: ** - 0 : if ordering data are consistent. ** - !0 : on error. */ static int orderCheck2 ( const OrderCblk * restrict const cblkptr, Gnum * const cblknbr, Gnum * const treenbr) { if (cblkptr->vnodnbr < 1) { errorPrint ("orderCheck2: invalid number of vertex nodes (1)"); return (1); } if (cblkptr->cblktab != NULL) { /* If node has sons */ Gnum vnodnbr; Gnum cblknum; if (cblkptr->cblknbr <= 0) { errorPrint ("orderCheck2: invalid number of column blocks (1)"); return (1); } *cblknbr += cblkptr->cblknbr - 1; *treenbr += cblkptr->cblknbr; for (cblknum = vnodnbr = 0; cblknum < cblkptr->cblknbr; cblknum ++) { vnodnbr += cblkptr->cblktab[cblknum].vnodnbr; if (orderCheck2 (&cblkptr->cblktab[cblknum], cblknbr, treenbr) != 0) return (1); } if (vnodnbr != cblkptr->vnodnbr) { errorPrint ("orderCheck2: invalid number of vertex nodes (2)"); return (1); } } else if (cblkptr->cblknbr != 0) { errorPrint ("orderCheck2: invalid number of column blocks (2)"); return (1); } return (0); } int orderCheck ( const Order * restrict const ordeptr) { Gnum * restrict permtab; Gnum * restrict permtax; Gnum treenbr; Gnum cblknbr; Gnum vertnnd; Gnum vertnum; if (ordeptr->vnodnbr != ordeptr->cblktre.vnodnbr) { errorPrint ("orderCheck: invalid vertex count"); return (1); } if ((ordeptr->cblknbr < 0) || (ordeptr->cblknbr > ordeptr->treenbr)) { errorPrint ("orderCheck: invalid column block count (1)"); return (1); } if ((permtab = (Gnum *) memAlloc (ordeptr->vnodnbr * sizeof (Gnum))) == NULL) { errorPrint ("orderCheck: out of memory"); return (1); } memSet (permtab, ~0, ordeptr->cblktre.vnodnbr * sizeof (Gnum)); permtax = permtab - ordeptr->baseval; vertnnd = ordeptr->baseval + ordeptr->vnodnbr; for (vertnum = 0; vertnum < ordeptr->vnodnbr; vertnum ++) { if ((ordeptr->peritab[vertnum] < ordeptr->baseval) || /* If index not in range */ (ordeptr->peritab[vertnum] >= vertnnd)) { errorPrint ("orderCheck: invalid index"); memFree (permtab); return (1); } if (permtax[ordeptr->peritab[vertnum]] != ~0) { /* If index already used */ errorPrint ("orderCheck: duplicate index"); memFree (permtab); return (1); } permtax[ordeptr->peritab[vertnum]] = vertnum; /* Set who updated index */ } for (vertnum = 0; vertnum < ordeptr->vnodnbr; vertnum ++) { if (permtab[vertnum] == ~0) { /* If index not used */ errorPrint ("orderCheck: missing index"); memFree (permtab); return (1); } } memFree (permtab); treenbr = /* Assume there is just a root node */ cblknbr = 1; if (orderCheck2 (&ordeptr->cblktre, &cblknbr, &treenbr) != 0) return (1); if (cblknbr != ordeptr->cblknbr) { errorPrint ("orderCheck: invalid number of column blocks"); return (1); } if (treenbr != ordeptr->treenbr) { errorPrint ("orderCheck: invalid number of tree nodes"); return (1); } return (0); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_bl.h0000644000175300017530000000613111631334325022261 0ustar hazelscthazelsct/* Copyright 2004,2007,2009,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_bl.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the block splitting algorithm. **/ /** **/ /** DATES : # Version 4.0 : from : 28 sep 2002 **/ /** to 04 jan 2005 **/ /** # Version 5.1 : from : 01 oct 2009 **/ /** to : 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HmeshOrderBlParam_ { Strat * strat; /*+ Ordering strategy +*/ INT cblkmin; /*+ Block splitting size +*/ } HmeshOrderBlParam; /* ** The function prototypes. */ #ifndef HMESH_ORDER_BL #define static #endif int hmeshOrderBl (const Hmesh * const, Order * const, const Gnum, OrderCblk * const, const HmeshOrderBlParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/geom.h0000644000175300017530000000656611631334325020250 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : geom.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the geometrical data handling **/ /** routines. **/ /** **/ /** DATES : # Version 3.3 : from : 13 dec 1998 **/ /** to 15 dec 1998 **/ /** # Version 3.4 : from : 10 oct 1999 **/ /** to 12 oct 1999 **/ /** # Version 4.0 : from : 24 nov 2001 **/ /** to 18 jan 2004 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ #define GEOM_H /* ** The type and structure definitions. */ /*+ Geometrical graph structure. +*/ typedef struct Geom_ { int dimnnbr; /*+ Geometry type (1, 2, or 3D) +*/ double * geomtab; /*+ Geometrical vertex array +*/ } Geom; /* ** The function prototypes. */ #ifndef GEOM #define static #endif int geomInit (Geom * restrict const); void geomExit (Geom * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/geom.c0000644000175300017530000000663511631334325020240 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : geom.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the geometric **/ /** source graph functions. **/ /** **/ /** DATES : # Version 3.3 : from : 12 dec 1998 **/ /** to 21 dec 1998 **/ /** # Version 4.0 : from : 18 dec 2001 **/ /** to 26 nov 2003 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GEOM #include "module.h" #include "common.h" #include "geom.h" /********************************************/ /* */ /* These routines handle geometrical gdata. */ /* */ /********************************************/ /* This routine initializes a geometrical ** data structure. ** It returns: ** - 0 : in all cases. */ int geomInit ( Geom * restrict const geomptr) { geomptr->dimnnbr = 0; /* Initialize geometry */ geomptr->geomtab = NULL; return (0); } /* This routine frees a geometrical graph structure. ** It returns: ** - VOID : in all cases. */ void geomExit ( Geom * restrict const geomptr) { if (geomptr->geomtab != NULL) memFree (geomptr->geomtab); geomptr->dimnnbr = 0; geomptr->geomtab = NULL; } scotch-5.1.12b.dfsg/src/libscotch/bdgraph_check.c0000644000175300017530000003121211631334325022042 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_check.c **/ /** **/ /** AUTHORS : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the distributed **/ /** bipartition graph consistency checking **/ /** routine. **/ /** **/ /** DATES : # Version 5.1 : from : 10 sep 2007 **/ /** to 22 jul 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #include "module.h" #include "common.h" #include "arch.h" #include "dgraph.h" #include "bdgraph.h" int bdgraphCheck ( const Bdgraph * restrict const grafptr) { Dgraph grafdat; /* Dummy graph for ghost edge array */ MPI_Comm proccomm; /* Graph communicator */ int * restrict flagloctax; /* Frontier flag array */ GraphPart * restrict partgsttax; Gnum fronlocnum; Gnum vertlocnum; /* Number of current vertex */ Gnum complocload[2]; Gnum complocsize[2]; Gnum commcut[2]; Gnum commlocloadintn; Gnum commlocloadextn; Gnum commlocgainextn; Gnum edlolocval; Gnum reduloctab[21]; /* Arrays for reductions */ Gnum reduglbtab[21]; int chekglbval; /* Global consistency flag */ int cheklocval; /* Local consistency flag */ proccomm = grafptr->s.proccomm; if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize */ errorPrint ("bdgraphCheck: communication error (1)"); return (1); } cheklocval = 0; /* Assume everything is all right */ if (grafptr->compglbload0 != (grafptr->compglbload0avg + grafptr->compglbload0dlt)) { errorPrint ("bdgraphCheck: invalid global balance"); cheklocval = 1; } if ((grafptr->fronlocnbr < 0) || (grafptr->fronlocnbr > grafptr->s.vertlocnbr)) { errorPrint ("bdgraphCheck: invalid number of local frontier vertices"); cheklocval |= 4; } if (grafptr->partgsttax != NULL) { for (vertlocnum = grafptr->s.baseval; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { if (grafptr->partgsttax[vertlocnum] > 1) { errorPrint ("bdgraphCheck: invalid local part array"); cheklocval |= 8; break; } } } grafdat = grafptr->s; /* Copy minimal distributed graph data */ if (dgraphGhst (&grafdat) != 0) { /* Create ghost edge array if did not exist */ errorPrint ("bdgraphCheck: cannot compute ghost edge array"); cheklocval |= 16; } if (memAllocGroup ((void **) (void *) &partgsttax, (size_t) (grafdat.vertgstnbr * sizeof (GraphPart)), &flagloctax, (size_t) (grafptr->s.vertlocnbr * sizeof (int)), NULL) == NULL) { errorPrint ("bdgraphCheck: out of memory"); cheklocval |= 32; } else { memSet (flagloctax, ~0, grafptr->s.vertlocnbr * sizeof (int)); flagloctax -= grafptr->s.baseval; for (fronlocnum = 0; fronlocnum < grafptr->fronlocnbr; fronlocnum ++) { Gnum vertlocnum; vertlocnum = grafptr->fronloctab[fronlocnum]; if ((vertlocnum < grafptr->s.baseval) || (vertlocnum >= grafptr->s.vertlocnnd)) { errorPrint ("bdgraphCheck: invalid vertex index in frontier array"); cheklocval |= 64; break; } if (flagloctax[vertlocnum] != ~0) { errorPrint ("bdgraphCheck: duplicate vertex in frontier array"); cheklocval |= 128; break; } flagloctax[vertlocnum] = 0; } } reduloctab[0] = grafptr->commglbload; reduloctab[1] = - grafptr->commglbload; reduloctab[2] = grafptr->compglbload0; reduloctab[3] = - grafptr->compglbload0; reduloctab[4] = grafptr->s.veloglbsum - grafptr->compglbload0; reduloctab[5] = - (grafptr->s.veloglbsum - grafptr->compglbload0); reduloctab[6] = grafptr->compglbsize0; reduloctab[7] = - grafptr->compglbsize0; reduloctab[8] = grafptr->s.vertglbnbr - grafptr->compglbsize0; reduloctab[9] = - (grafptr->s.vertglbnbr - grafptr->compglbsize0); reduloctab[10] = grafptr->commglbgainextn; reduloctab[11] = - grafptr->commglbgainextn; reduloctab[12] = grafptr->commglbgainextn0; reduloctab[13] = - grafptr->commglbgainextn0; reduloctab[14] = grafptr->commglbloadextn0; reduloctab[15] = - grafptr->commglbloadextn0; reduloctab[16] = grafptr->fronglbnbr; reduloctab[17] = - grafptr->fronglbnbr; reduloctab[18] = grafptr->levlnum; reduloctab[19] = - grafptr->levlnum; reduloctab[20] = cheklocval; if (MPI_Allreduce (reduloctab, reduglbtab, 21, GNUM_MPI, MPI_MAX, proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphCheck: communication error (2)"); return (1); } if (reduglbtab[20] != 0) { /* Exit and Return information of previous errors */ if (partgsttax != NULL) memFree (partgsttax); /* Free yet unbased group leader */ return (reduglbtab[20]); } if ((reduglbtab[1] != - reduglbtab[0]) || (reduglbtab[3] != - reduglbtab[2]) || (reduglbtab[5] != - reduglbtab[4]) || (reduglbtab[7] != - reduglbtab[6]) || (reduglbtab[9] != - reduglbtab[8]) || (reduglbtab[11] != - reduglbtab[10]) || (reduglbtab[13] != - reduglbtab[12]) || (reduglbtab[15] != - reduglbtab[14]) || (reduglbtab[17] != - reduglbtab[16]) || (reduglbtab[19] != - reduglbtab[18])) { errorPrint ("bdgraphCheck: inconsistent global graph data"); return (1); } if (grafptr->partgsttax != NULL) memCpy (partgsttax, grafptr->partgsttax + grafptr->s.baseval, grafptr->s.vertlocnbr * sizeof (GraphPart)); /* Copy local part data */ else memSet (partgsttax, 0, grafptr->s.vertlocnbr * sizeof (GraphPart)); dgraphHaloSync (&grafdat, partgsttax, GRAPHPART_MPI); /* Spread yet unbased halo part data across neighboring processes */ partgsttax -= grafptr->s.baseval; cheklocval = 0; for (fronlocnum = 0; fronlocnum < grafptr->fronlocnbr; fronlocnum ++) { Gnum vertlocnum; Gnum edgelocnum; Gnum commcut; int partval; vertlocnum = grafptr->fronloctab[fronlocnum]; partval = partgsttax[vertlocnum]; for (edgelocnum = grafptr->s.vertloctax[vertlocnum], commcut = 0; edgelocnum < grafptr->s.vendloctax[vertlocnum]; edgelocnum ++) { int partdlt; partdlt = partgsttax[grafdat.edgegsttax[edgelocnum]] ^ partval; commcut |= partdlt; } if (commcut == 0) { errorPrint ("bdgraphCheck: invalid vertex in frontier array"); cheklocval |= 1; break; } } complocload[0] = complocload[1] = 0; complocsize[0] = complocsize[1] = 0; commlocloadintn = 0; commlocloadextn = 0; commlocgainextn = 0; edlolocval = 1; /* Assume edges are not weighted */ for (vertlocnum = grafptr->s.baseval; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { Gnum partval; /* Part of current vertex */ Gnum edgelocnum; /* Number of current edge */ partval = (Gnum) partgsttax[vertlocnum]; if (grafptr->veexloctax != NULL) { Gnum veexval; veexval = grafptr->veexloctax[vertlocnum]; commlocloadextn += veexval * partval; commlocgainextn += veexval * (1 - 2 * partval); } complocload[partval] += (grafptr->s.veloloctax == NULL) ? 1 : grafptr->s.veloloctax[vertlocnum]; complocsize[partval] ++; commcut[0] = commcut[1] = 0; for (edgelocnum = grafptr->s.vertloctax[vertlocnum]; edgelocnum < grafptr->s.vendloctax[vertlocnum]; edgelocnum ++) { int partend; int partdlt; if (grafptr->s.edloloctax != NULL) edlolocval = grafptr->s.edloloctax[edgelocnum]; partend = partgsttax[grafdat.edgegsttax[edgelocnum]]; partdlt = partval ^ partend; commcut[partend] ++; commlocloadintn += partdlt * edlolocval; /* Internal load is accounted for twice */ } if ((commcut[0] != 0) && (commcut[1] != 0) && /* If vertex should be in separator */ (flagloctax[vertlocnum] != 0)) { errorPrint ("bdgraphCheck: vertex should be in separator"); cheklocval |= 2; } } if (grafptr->s.edgegsttax != grafdat.edgegsttax) /* If ghost edge array was allocated here, free it manually */ memFree (grafdat.edgegsttax + grafptr->s.baseval); if (grafptr->s.procsidtab != grafdat.procsidtab) /* The same for procsidtab */ memFree (grafdat.procsidtab); memFree (partgsttax + grafptr->s.baseval); /* Free group leader */ if ((cheklocval == 0) && ((complocsize[0] != grafptr->complocsize0) || (complocsize[1] != (grafptr->s.vertlocnbr - grafptr->complocsize0)))) { errorPrint ("bdgraphCheck: invalid local part size"); cheklocval |= 4; } reduloctab[0] = complocload[0]; reduloctab[1] = complocsize[0]; reduloctab[2] = commlocloadintn; /* Twice the internal load; sum globally before dividing by two */ reduloctab[3] = commlocloadextn; reduloctab[4] = commlocgainextn; reduloctab[5] = cheklocval; if (MPI_Allreduce (reduloctab, reduglbtab, 6, GNUM_MPI, MPI_SUM, proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphCheck: communication error (3)"); return (1); } if (reduglbtab[5] != 0) /* Return from previous errors */ return (1); if (grafptr->compglbload0 != reduglbtab[0]) { errorPrint ("bdgraphCheck: invalid global part loads"); cheklocval |= 8; } if (grafptr->compglbsize0 != reduglbtab[1]) { errorPrint ("bdgraphCheck: invalid global part sizes"); cheklocval |= 16; } if (grafptr->commglbload != ((reduglbtab[2] / 2) * grafptr->domdist + reduglbtab[3] + grafptr->commglbloadextn0)) { errorPrint ("bdgraphCheck: invalid global communication loads"); cheklocval |= 32; } if (grafptr->commglbgainextn != reduglbtab[4]) { errorPrint ("bdgraphCheck: invalid global communication gains"); cheklocval |= 64; } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphCheck: communication error (4)"); return (1); } return (chekglbval); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_fold_dup.c0000644000175300017530000001664611631334325022435 0ustar hazelscthazelsct/* Copyright 2007-2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_fold_dup.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module folds a distributed graph **/ /** into two distinct copies, which may **/ /** be different when the number of **/ /** processes is odd. **/ /** **/ /** DATES : # Version 5.0 : from : 10 aug 2006 **/ /** to : 20 jun 2007 **/ /** # Version 5.1 : from : 14 nov 2008 **/ /** to : 28 oct 2009 **/ /** **/ /************************************************************/ #define DGRAPH #define DGRAPH_FOLD_DUP #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_fold_dup.h" /******************************/ /* */ /* This routine handles */ /* distributed source graphs. */ /* */ /******************************/ /* This routine builds two folded graphs of ** a given graph on each of the two halves ** of the processes. The number of processes ** does not need to be even. There is a ** multi-threaded version, as well as a ** sequential one. ** It returns: ** - 0 : on success. ** - !0 : on error. */ #ifdef SCOTCH_PTHREAD static void * dgraphFoldDup2 ( void * const dataptr) /* Pointer to thread data */ { DgraphFoldDupData * fldthrdptr; fldthrdptr = (DgraphFoldDupData *) dataptr; return ((void *) (intptr_t) dgraphFold2 (fldthrdptr->orggrafptr, fldthrdptr->partval, fldthrdptr->fldgrafptr, fldthrdptr->fldproccomm, fldthrdptr->vertinfoptrin, fldthrdptr->vertinfoptrout, fldthrdptr->vertinfotype)); } #endif /* SCOTCH_PTHREAD */ int dgraphFoldDup ( const Dgraph * restrict const orggrafptr, Dgraph * restrict const fldgrafptr, void * restrict const vertinfoptrin, /* Based array of informations which must be kept, like coarmulttax */ void ** restrict const vertinfoptrout, /* Based array of informations which must be kept, like coarmulttax */ MPI_Datatype vertinfotype) { int fldprocnbr; int fldprocnum; int fldproccol; MPI_Comm fldproccommtab[2]; #ifdef SCOTCH_PTHREAD Dgraph orggrafdat; DgraphFoldDupData fldthrdtab[2]; pthread_t thrdval; /* Data of second thread */ #endif /* SCOTCH_PTHREAD */ int o; fldprocnbr = (orggrafptr->procglbnbr + 1) / 2; /* Median cut on number of processors */ if (orggrafptr->proclocnum < fldprocnbr) { /* Compute color and rank in two subparts */ fldproccol = 0; fldprocnum = orggrafptr->proclocnum; fldproccommtab[1] = MPI_COMM_NULL; } else { fldproccol = 1; fldprocnum = orggrafptr->proclocnum - fldprocnbr; fldproccommtab[0] = MPI_COMM_NULL; } if (MPI_Comm_split (orggrafptr->proccomm, fldproccol, fldprocnum, &fldproccommtab[fldproccol]) != MPI_SUCCESS) { errorPrint ("dgraphFoldDup: communication error (1)"); return (1); } #ifdef SCOTCH_PTHREAD orggrafdat = *orggrafptr; /* Create a separate graph structure to change its communicator */ fldthrdtab[0].orggrafptr = orggrafptr; fldthrdtab[0].fldgrafptr = fldgrafptr; fldthrdtab[0].fldproccomm = fldproccommtab[0]; fldthrdtab[0].partval = 0; fldthrdtab[0].vertinfoptrin = vertinfoptrin; fldthrdtab[0].vertinfoptrout = vertinfoptrout; fldthrdtab[0].vertinfotype = vertinfotype; fldthrdtab[1].orggrafptr = &orggrafdat; fldthrdtab[1].fldgrafptr = fldgrafptr; fldthrdtab[1].fldproccomm = fldproccommtab[1]; fldthrdtab[1].partval = 1; fldthrdtab[1].vertinfoptrin = vertinfoptrin; fldthrdtab[1].vertinfoptrout = vertinfoptrout; fldthrdtab[1].vertinfotype = vertinfotype; if (MPI_Comm_dup (orggrafptr->proccomm, &orggrafdat.proccomm) != MPI_SUCCESS) { /* Duplicate communicator to avoid interferences in communications */ errorPrint ("dgraphFoldDup: communication error (2)"); return (1); } if (pthread_create (&thrdval, NULL, dgraphFoldDup2, (void *) &fldthrdtab[1]) != 0) /* If could not create thread */ o = (int) (intptr_t) dgraphFold2 (orggrafptr, 0, fldgrafptr, fldproccommtab[0], vertinfoptrin, vertinfoptrout, vertinfotype) || /* Call routines in sequence */ (int) (intptr_t) dgraphFold2 (orggrafptr, 1, fldgrafptr, fldproccommtab[1], vertinfoptrin, vertinfoptrout, vertinfotype); else { /* Newly created thread is processing subgraph 1, so let's process subgraph 0 */ void * o2; o = (int) (intptr_t) dgraphFoldDup2 ((void *) &fldthrdtab[0]); /* Work on copy with private communicator */ pthread_join (thrdval, &o2); o |= (int) (intptr_t) o2; } MPI_Comm_free (&orggrafdat.proccomm); #else /* SCOTCH_PTHREAD */ o = (dgraphFold2 (orggrafptr, 0, fldgrafptr, fldproccommtab[0], vertinfoptrin, vertinfoptrout, vertinfotype) || /* Call routines in sequence */ dgraphFold2 (orggrafptr, 1, fldgrafptr, fldproccommtab[1], vertinfoptrin, vertinfoptrout, vertinfotype)); #endif /* SCOTCH_PTHREAD */ fldgrafptr->prockeyval = fldproccol; /* Discriminate between folded communicators at same level */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/vdgraph_separate_bd.c0000644000175300017530000002365111631334325023272 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_separate_bd.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER **/ /** **/ /** FUNCTION : This module computes a separator of the **/ /** given distributed separator graph by **/ /** creating a band graph of given witdh **/ /** around the current separator, computing **/ /** an improved separator of the band **/ /** graph, and projecting back the obtained **/ /** separator in the original graph. **/ /** **/ /** DATES : # Version 5.0 : from : 04 mar 2006 **/ /** to : 07 nov 2007 **/ /** # Version 5.1 : from : 11 nov 2007 **/ /** to : 01 mar 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VDGRAPH_SEPARATE_BD #include "module.h" #include "common.h" #include "parser.h" #include "dgraph.h" #include "vdgraph.h" #include "vdgraph_separate_bd.h" #include "vdgraph_separate_st.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine computes a distributed band graph ** of given width around the current separator and ** applies distributed separation routines to it. ** The distributed graph is not guaranteed to be ** balanced at at all. ** It returns: ** - 0 : if the distributed band graph could be computed. ** - !0 : on error. */ int vdgraphSeparateBd ( Vdgraph * const grafptr, /*+ Distributed graph +*/ const VdgraphSeparateBdParam * const paraptr) /*+ Method parameters +*/ { Vdgraph bandgrafdat; /* Vertex separator band graph structure */ Gnum bandvertancnnd; /* End of local vertex array, without anchors */ Gnum bandvertlocnbr1; /* Number of band graph vertices in part 1 except anchor 1 */ Gnum bandvertlocnum; Gnum bandvertlocancadj; /* Flag set when anchor(s) represent unexistent vertices */ Gnum bandvertglbancadj; /* Global adjustment of anchor vertices */ Gnum complocsizeadj0; Gnum complocsizeadj1; Gnum reduloctab[3]; Gnum reduglbtab[3]; Gnum * restrict edloloctax; /* Save value for edge loads while we pretend we don't have them */ Gnum fronlocnum; if (grafptr->compglbsize[2] == 0) /* If no frontier to base on */ return (0); /* Then do nothing */ if (paraptr->distmax < 1) /* If distance is 0 (or less) */ return (0); /* Then do nothing */ edloloctax = grafptr->s.edloloctax; /* Fake no edge loads on original graph as we do not need them */ grafptr->s.edloloctax = NULL; if (dgraphBand (&grafptr->s, grafptr->complocsize[2], grafptr->fronloctab, grafptr->partgsttax, grafptr->complocload[0] + grafptr->complocload[2], grafptr->complocload[1], paraptr->distmax, &bandgrafdat.s, &bandgrafdat.fronloctab, &bandgrafdat.partgsttax, NULL, &bandvertlocnbr1, &bandvertlocancadj) != 0) { grafptr->s.edloloctax = edloloctax; errorPrint ("vdgraphSeparateBd: cannot create band graph"); return (1); } grafptr->s.edloloctax = edloloctax; /* Restore edge loads, if any */ bandgrafdat.complocsize[0] = bandgrafdat.s.vertlocnbr - (bandvertlocnbr1 + 1) - grafptr->complocsize[2]; /* Add 1 for anchor vertex 1 */ bandgrafdat.complocsize[1] = bandvertlocnbr1 + 1; /* Add 1 for anchor vertex 1 */ complocsizeadj0 = grafptr->complocsize[0] - bandgrafdat.complocsize[0]; complocsizeadj1 = grafptr->complocsize[1] - bandgrafdat.complocsize[1]; reduloctab[0] = bandgrafdat.complocsize[0]; reduloctab[1] = bandgrafdat.complocsize[1]; reduloctab[2] = bandvertlocancadj; /* Sum increases in size and load */ if (MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 3, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphSeparateBd: communication error (1)"); return (1); } bandvertglbancadj = reduglbtab[2]; bandgrafdat.compglbload[0] = grafptr->compglbload[0] + bandvertglbancadj; /* All loads are kept in band graph */ bandgrafdat.compglbload[1] = grafptr->compglbload[1] + bandvertglbancadj; bandgrafdat.compglbload[2] = grafptr->compglbload[2]; bandgrafdat.compglbloaddlt = grafptr->compglbloaddlt; /* Balance is not changed by anchor vertices */ bandgrafdat.complocload[0] = grafptr->complocload[0] + bandvertlocancadj; bandgrafdat.complocload[1] = grafptr->complocload[1] + bandvertlocancadj; bandgrafdat.complocload[2] = grafptr->complocload[2]; bandgrafdat.compglbsize[0] = reduglbtab[0]; bandgrafdat.compglbsize[1] = reduglbtab[1]; bandgrafdat.compglbsize[2] = grafptr->compglbsize[2]; /* All separator vertices are kept in band graph */ bandgrafdat.complocsize[2] = grafptr->complocsize[2]; bandgrafdat.levlnum = grafptr->levlnum; #ifdef SCOTCH_DEBUG_VDGRAPH2 if (vdgraphCheck (&bandgrafdat) != 0) { errorPrint ("vdgraphSeparateBd: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ if (vdgraphSeparateSt (&bandgrafdat, paraptr->strat) != 0) { /* Separate distributed band graph */ errorPrint ("vdgraphSeparateBd: cannot separate band graph"); vdgraphExit (&bandgrafdat); return (1); } bandvertancnnd = bandgrafdat.s.vertlocnnd - 2; reduloctab[0] = ((bandgrafdat.partgsttax[bandvertancnnd] == 0) && /* Check if anchor vertices remain in their parts */ (bandgrafdat.partgsttax[bandvertancnnd + 1] == 1)) ? 0 : 1; reduloctab[1] = bandgrafdat.complocsize[0] + complocsizeadj0; reduloctab[2] = bandgrafdat.complocsize[1] + complocsizeadj1; if (MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 3, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphSeparateBd: communication error (2)"); return (1); } if (reduglbtab[0] != 0) { /* If at least one anchor changed of part */ vdgraphExit (&bandgrafdat); /* Then keep original partition */ return (0); } grafptr->compglbload[0] = bandgrafdat.compglbload[0] - bandvertglbancadj; grafptr->compglbload[1] = bandgrafdat.compglbload[1] - bandvertglbancadj; grafptr->compglbload[2] = bandgrafdat.compglbload[2]; grafptr->compglbloaddlt = bandgrafdat.compglbloaddlt; grafptr->compglbsize[0] = reduglbtab[1]; grafptr->compglbsize[1] = reduglbtab[2]; grafptr->compglbsize[2] = bandgrafdat.compglbsize[2]; grafptr->complocload[0] = bandgrafdat.complocload[0] - bandvertlocancadj; grafptr->complocload[1] = bandgrafdat.complocload[1] - bandvertlocancadj; grafptr->complocload[2] = bandgrafdat.complocload[2]; grafptr->complocsize[0] = reduloctab[1]; grafptr->complocsize[1] = reduloctab[2]; grafptr->complocsize[2] = bandgrafdat.complocsize[2]; for (fronlocnum = 0; fronlocnum < bandgrafdat.complocsize[2]; fronlocnum ++) /* Project back separator */ grafptr->fronloctab[fronlocnum] = bandgrafdat.s.vnumloctax[bandgrafdat.fronloctab[fronlocnum]]; for (bandvertlocnum = bandgrafdat.s.baseval; bandvertlocnum < bandvertancnnd; bandvertlocnum ++) /* For all vertices except anchors */ grafptr->partgsttax[bandgrafdat.s.vnumloctax[bandvertlocnum]] = bandgrafdat.partgsttax[bandvertlocnum]; #ifdef SCOTCH_DEBUG_VDGRAPH2 if (vdgraphCheck (grafptr) != 0) { errorPrint ("vdgraphSeparateBd: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ vdgraphExit (&bandgrafdat); return (0); } scotch-5.1.12b.dfsg/src/libscotch/kgraph_map_rb_map.h0000644000175300017530000002064111631334325022740 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kgraph_map_rb_map.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the Dual Recursive Bipartitioning **/ /** mapping algorithm. **/ /** **/ /** DATES : # Version 0.0 : from : 23 mar 1993 **/ /** to 12 may 1993 **/ /** # Version 1.3 : from : 06 apr 1994 **/ /** to 09 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 04 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to 30 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 15 nov 1995 **/ /** to 15 nov 1995 **/ /** # Version 3.2 : from : 01 oct 1996 **/ /** to 10 jun 1998 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to 17 may 1999 **/ /** # Version 3.4 : from : 12 sep 2001 **/ /** to 06 nov 2001 **/ /** # Version 4.0 : from : 29 nov 2003 **/ /** to 05 may 2006 **/ /** # Version 5.1 : from : 30 sep 2008 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Dual recursive bipartitioning option flags. +*/ #define KGRAPHMAPRBMAPARCHVAR 0x0001 /* Variable-sized architecture */ #define KGRAPHMAPRBMAPARCHCMPLT 0x0002 /* Complete-graph architecture */ #define KGRAPHMAPRBMAPPARTHALF 0x0004 /* Only update half of part array as mappings are tied */ /* ** The type and structure definitions. */ /*+ Job pool structures. +*/ typedef struct KgraphMapRbMapPoolLink_ { struct KgraphMapRbMapPoolLink_ * prev; /*+ Pointer to previous link +*/ struct KgraphMapRbMapPoolLink_ * next; /*+ Pointer to next link +*/ } KgraphMapRbMapPoolLink; /*+ This structure defines a job to be performed with respect to a partial mapping of a source graph. +*/ typedef struct KgraphMapRbMapJob_ { KgraphMapRbMapPoolLink poollink; /*+ Link to job pool; TRICK: FIRST +*/ KgraphMapRbMapPoolLink * poolptr; /*+ Pointer to last/current job pool +*/ int poolflag; /*+ Flag set if job in pool +*/ Gnum prioval; /*+ Job priority value by policy +*/ Gnum priolvl; /*+ Priority level computed for this job +*/ ArchDom domnorg; /*+ Domain to which the vertices belong +*/ Graph grafdat; /*+ Job graph data (may be clone of another) +*/ } KgraphMapRbMapJob; /*+ This structure defines the working data, for easier parameter passing. +*/ typedef struct KgraphMapRbMapPoolData_ { int flagval; /*+ Pool flag value +*/ Graph * grafptr; /*+ Pointer to top graph +*/ KgraphMapRbMapPoolLink linktab[2]; /*+ Lists of jobs in pools +*/ KgraphMapRbMapPoolLink * pooltab[2]; /*+ Pointer to pools (same if tied) +*/ KgraphMapRbPolicy polival; /*+ Job selection policy +*/ KgraphMapRbMapJob * jobtab; /*+ Job table +*/ Mapping * mappptr; /*+ Pointer to original mapping: current state +*/ ArchDom * domntab; /*+ Secondary domain array if untied mapping +*/ ArchDom * domntmp; /*+ Pointer to original domain array for exiting +*/ } KgraphMapRbMapPoolData; /* ** The function prototypes. */ #ifndef KGRAPH_MAP_RB_MAP #define static #endif static int kgraphMapRbMapPoolInit (KgraphMapRbMapPoolData * restrict const, Kgraph * restrict const, const KgraphMapRbParam * restrict const); static void kgraphMapRbMapPoolExit (KgraphMapRbMapPoolData * restrict const poolptr); static void kgraphMapRbMapPoolAdd (KgraphMapRbMapPoolLink * restrict const, KgraphMapRbMapJob * const); static KgraphMapRbMapJob * kgraphMapRbMapPoolGet (KgraphMapRbMapPoolData * restrict const); static void kgraphMapRbMapPoolFrst (KgraphMapRbMapPoolData * const, KgraphMapRbMapJob * const); static void kgraphMapRbMapPoolUpdt1 (KgraphMapRbMapPoolData * const, const KgraphMapRbMapJob * const, const GraphPart * const, KgraphMapRbMapJob * const, const GraphPart); static void kgraphMapRbMapPoolUpdt2 (KgraphMapRbMapPoolData * const, const KgraphMapRbMapJob * const, const GraphPart * const, KgraphMapRbMapJob * const, KgraphMapRbMapJob * const); int kgraphMapRbMap (Kgraph * const, const KgraphMapRbParam * const); static int kgraphMapRbMapPoolResize (KgraphMapRbMapPoolData * restrict const); #undef static /* ** The macro definitions. */ #define kgraphMapRbMapPoolEmpty(poolptr) ((poolptr)->pooltab[0]->next == &kgraphmaprbmappooldummy) #define kgraphMapRbMapPoolSwap(poolptr) { ArchDom * domntmp; \ KgraphMapRbMapPoolLink * linktmp; \ linktmp = (poolptr)->pooltab[0]; \ (poolptr)->pooltab[0] = (poolptr)->pooltab[1]; \ (poolptr)->pooltab[1] = linktmp; \ domntmp = (poolptr)->mappptr->domntab; \ (poolptr)->mappptr->domntab = (poolptr)->domntab; \ (poolptr)->domntab = domntmp; } scotch-5.1.12b.dfsg/src/libscotch/hdgraph_order_sq.h0000644000175300017530000000640611631334325022625 0ustar hazelscthazelsct/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph_order_sq.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the halo distributed graph centra- **/ /** lized ordering algorithm. **/ /** **/ /** DATES : # Version 5.1 : from : 11 nov 2008 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HdgraphOrderSqParam_ { Strat * ordstratseq; /*+ Sequential ordering strategy +*/ } HdgraphOrderSqParam; /* ** The function prototypes. */ #ifndef HDGRAPH_ORDER_SQ #define static #endif int hdgraphOrderSq (Hdgraph * const, DorderCblk * const, const HdgraphOrderSqParam * const); int hdgraphOrderSq2 (Hgraph * restrict const, DorderCblk * restrict const, const Strat * restrict const); static DorderNode * hdgraphOrderSqTree (const Order * const); static void hdgraphOrderSqTree2 (DorderNode * const, Gnum * const, const OrderCblk * const, const Gnum, const Gnum); #undef static scotch-5.1.12b.dfsg/src/libscotch/bdgraph_bipart_st.h0000644000175300017530000000714311631334325022767 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_bipart_st.h **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the strategy and method **/ /** tables and the generic entry point for **/ /** the distributed graph bipartitioning **/ /** methods. **/ /** **/ /** DATES : # Version 5.1 : from : 10 sep 2007 **/ /** to 16 jul 2010 **/ /** **/ /************************************************************/ /* ** The type definitions. */ /*+ Method types. +*/ typedef enum BdgraphBipartStMethodType_ { BDGRAPHBIPARTSTMETHBD = 0, /*+ Band (strategy) +*/ BDGRAPHBIPARTSTMETHDF, /*+ Diffusion +*/ BDGRAPHBIPARTSTMETHEX, /*+ Exactifier +*/ BDGRAPHBIPARTSTMETHML, /*+ Multi-level (strategy) +*/ BDGRAPHBIPARTSTMETHSQ, /*+ Sequential Method +*/ BDGRAPHBIPARTSTMETHZR, /*+ Move all to part zero +*/ BDGRAPHBIPARTSTMETHNBR /*+ Number of methods +*/ } BdgraphBipartStMethodType; /* ** The external declarations. */ extern StratTab bdgraphbipartststratab; /* ** The function prototypes. */ #ifndef BDGRAPH_BIPART_ST #define static #endif int bdgraphBipartSt (Bdgraph * const, const Strat * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/dorder_io_tree.c0000644000175300017530000001665511631334325022301 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dorder_io_tree.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles distributed **/ /** orderings. **/ /** **/ /** DATES : # Version 5.0 : from : 26 jul 2007 **/ /** to 26 jul 2007 **/ /** # Version 5.1 : from : 30 jul 2010 **/ /** to 30 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DORDER #include "module.h" #include "common.h" #include "comm.h" #include "dgraph.h" #include "order.h" #include "dorder.h" /************************************/ /* */ /* These routines handle orderings. */ /* */ /************************************/ /* This routine saves a distributed ordering. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dorderSaveTree2 ( const Dorder * restrict const ordeptr, const Dgraph * restrict const grafptr, FILE * restrict const stream, int (* funcptr) (const Order * const, const Gnum * const, FILE * const)) { Order corddat; /* Centralized ordering for tree structure */ Gnum * restrict vlbltab; int procglbnbr; int protnum; int reduloctab[3]; int reduglbtab[3]; int cheklocval; int chekglbval; if (stream != NULL) { /* If file provided */ reduloctab[0] = 1; /* This process is the root */ reduloctab[1] = ordeptr->proclocnum; /* Get its rank */ } else { reduloctab[0] = /* This process is not the root */ reduloctab[1] = 0; } reduloctab[2] = (grafptr->vlblloctax != NULL) ? 1 : 0; /* See if vertex labels provided */ if (MPI_Allreduce (reduloctab, reduglbtab, 3, MPI_INT, MPI_SUM, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderSaveTree2: communication error (1)"); return (1); } if (reduglbtab[0] != 1) { errorPrint ("dorderSaveTree2: should have only one root"); return (1); } MPI_Comm_size (ordeptr->proccomm, &procglbnbr); if ((reduglbtab[2] != 0) && (reduglbtab[2] != procglbnbr)) { errorPrint ("dorderSaveTree2: inconsistent parameters"); return (1); } protnum = (int) reduglbtab[1]; /* Get rank of root process */ cheklocval = 0; vlbltab = NULL; if (reduglbtab[2] != 0) { if (protnum == ordeptr->proclocnum) if ((vlbltab = memAlloc (ordeptr->vnodglbnbr * sizeof (Gnum))) == NULL) { errorPrint ("dorderSaveTree2: out of memory"); cheklocval = 1; } #ifdef SCOTCH_DEBUG_DORDER1 /* Communication cannot be merged with a useful one */ if (MPI_Bcast (&cheklocval, 1, MPI_INT, protnum, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderSaveTree2: communication error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DORDER1 */ if (cheklocval != 0) return (1); if (commGatherv (grafptr->vlblloctax + grafptr->baseval, grafptr->vertlocnbr, GNUM_MPI, vlbltab, grafptr->proccnttab, grafptr->procdsptab, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderSaveTree2: communication error (3)"); return (1); } } if (protnum == ordeptr->proclocnum) cheklocval = orderInit (&corddat, ordeptr->baseval, ordeptr->vnodglbnbr, NULL); #ifdef SCOTCH_DEBUG_DORDER1 /* Communication cannot be merged with a useful one */ if (MPI_Bcast (&cheklocval, 1, MPI_INT, protnum, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderSaveTree2: communication error (4)"); return (1); } #endif /* SCOTCH_DEBUG_DORDER1 */ if (cheklocval != 0) return (1); if (protnum == ordeptr->proclocnum) { cheklocval = dorderGather (ordeptr, &corddat); /* Need inverse permutation too */ if (cheklocval == 0) cheklocval = funcptr (&corddat, vlbltab, stream); orderExit (&corddat); } else cheklocval = dorderGather (ordeptr, NULL); if (vlbltab != NULL) memFree (vlbltab); #ifdef SCOTCH_DEBUG_DORDER1 /* Communication cannot be merged with a useful one */ if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderSaveTree2: communication error (3)"); return (1); } #else /* SCOTCH_DEBUG_DORDER1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_DORDER1 */ return (chekglbval); } /* This routine saves the separator tree ** data of the given distributed ordering. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dorderSaveTree ( const Dorder * restrict const ordeptr, const Dgraph * restrict const grafptr, FILE * restrict const stream) { return (dorderSaveTree2 (ordeptr, grafptr, stream, orderSaveTree)); } /* This routine saves the column block ** mapping data of the given distributed ** ordering. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dorderSaveMap ( const Dorder * restrict const ordeptr, const Dgraph * restrict const grafptr, FILE * restrict const stream) { return (dorderSaveTree2 (ordeptr, grafptr, stream, orderSaveMap)); } scotch-5.1.12b.dfsg/src/libscotch/arch_tleaf.h0000644000175300017530000001407311631334325021401 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_tleaf.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the tree-leaf pseudo-graph target **/ /** architecture functions. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 12 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 30 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 16 aug 1995 **/ /** # Version 3.1 : from : 20 jul 1996 **/ /** to 23 jul 1996 **/ /** # Version 3.2 : from : 10 oct 1996 **/ /** to 14 may 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 10 dec 2003 **/ /** to 10 dec 2003 **/ /** # Version 5.1 : from : 21 jan 2008 **/ /** to 24 jun 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /** The Tree-Leaf graph definitions. **/ typedef struct ArchTleaf_ { Anum levlnbr; /*+ Number of levels +*/ Anum sizeval; /*+ Number of terminal domains in architecture +*/ Anum * sizetab; /*+ Array of cluster sizes, per descending level +*/ Anum * linktab; /*+ Value of extra-cluster link costs +*/ } ArchTleaf; typedef struct ArchTleafDom_ { Anum levlnum; /*+ Current block level +*/ Anum indxmin; /*+ Minimum index in level +*/ Anum indxnbr; /*+ Number of indices in domain +*/ } ArchTleafDom; /* ** The function prototypes. */ #ifndef ARCH_TLEAF #define static #endif int archTleafArchLoad (ArchTleaf * restrict const, FILE * restrict const); int archTleafArchFree (ArchTleaf * restrict const); int archTleafArchSave (const ArchTleaf * const, FILE * restrict const); ArchDomNum archTleafDomNum (const ArchTleaf * const, const ArchTleafDom * const); int archTleafDomTerm (const ArchTleaf * const, ArchTleafDom * restrict const, const ArchDomNum); Anum archTleafDomSize (const ArchTleaf * const, const ArchTleafDom * const); #define archTleafDomWght archTleafDomSize Anum archTleafDomDist (const ArchTleaf * const, const ArchTleafDom * const, const ArchTleafDom * const); int archTleafDomFrst (const ArchTleaf * const, ArchTleafDom * restrict const); int archTleafDomLoad (const ArchTleaf * const, ArchTleafDom * restrict const, FILE * restrict const); int archTleafDomSave (const ArchTleaf * const, const ArchTleafDom * const, FILE * restrict const); int archTleafDomBipart (const ArchTleaf * const, const ArchTleafDom * const, ArchTleafDom * restrict const, ArchTleafDom * restrict const); #ifdef SCOTCH_PTSCOTCH int archTleafDomMpiType (const ArchTleaf * const, MPI_Datatype * const); #endif /* SCOTCH_PTSCOTCH */ #undef static scotch-5.1.12b.dfsg/src/libscotch/hdgraph_order_sq.c0000644000175300017530000002024211631334325022612 0ustar hazelscthazelsct/* Copyright 2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph_order_sq.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders distributed graphs **/ /** by centralizing them on a single **/ /** process and running a sequential **/ /** ordering strategy. **/ /** **/ /** DATES : # Version 5.1 : from : 11 nov 2008 **/ /** to 11 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HDGRAPH_ORDER_SQ #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "order.h" #include "hgraph.h" #include "hgraph_order_st.h" #include "dgraph.h" #include "dorder.h" #include "hdgraph.h" #include "hdgraph_order_sq.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hdgraphOrderSq ( Hdgraph * restrict const grafptr, DorderCblk * restrict const cblkptr, const HdgraphOrderSqParam * restrict const paraptr) { Hgraph cgrfdat; /* Centralized halo graph data */ Hgraph * cgrfptr; /* Pointer to centralized halo graph */ int o; cgrfptr = (grafptr->s.proclocnum == 0) ? &cgrfdat : NULL; /* Set root process */ if (hdgraphGather (grafptr, cgrfptr) != 0) { /* Gather centralized subgraph */ errorPrint ("hdgraphOrderSq: cannot create centralized graph"); return (1); } o = 0; if (cgrfptr != NULL) { o = hdgraphOrderSq2 (&cgrfdat, cblkptr, paraptr->ordstratseq); hgraphFree (&cgrfdat); } return (o); } int hdgraphOrderSq2 ( Hgraph * restrict const grafptr, DorderCblk * restrict const cblkptr, const Strat * restrict const stratptr) { Order corddat; /* Centralized ordering structure */ Gnum * restrict vnumtax; Gnum * restrict peritab; int o; if (orderInit (&corddat, grafptr->s.baseval, cblkptr->vnodglbnbr, NULL) != 0) { errorPrint ("hdgraphOrderSq2: cannot initialize centralized ordering"); return (1); } vnumtax = grafptr->s.vnumtax; /* Save number array of subgraph to order */ grafptr->s.vnumtax = NULL; /* Assume graph does not have one (fake original graph) */ if (hgraphOrderSt (grafptr, &corddat, 0, &corddat.cblktre, stratptr) != 0) { /* Compute sequential ordering */ orderExit (&corddat); return (1); } #ifdef SCOTCH_DEBUG_HDGRAPH2 if (orderCheck (&corddat) != 0) { errorPrint ("hdgraphOrderSq2: invalid centralized ordering"); orderExit (&corddat); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ peritab = corddat.peritab; /* Get permutation array */ if (vnumtax != NULL) { Gnum perinum; grafptr->s.vnumtax = vnumtax; /* Restore vertex number array */ for (perinum = 0; perinum < grafptr->vnohnbr; perinum ++) /* Adjust inverse permutation */ peritab[perinum] = vnumtax[peritab[perinum]]; } cblkptr->typeval = DORDERCBLKLEAF; /* Fill node as leaf */ cblkptr->data.leaf.ordelocval = cblkptr->ordeglbval; cblkptr->data.leaf.vnodlocnbr = cblkptr->vnodglbnbr; cblkptr->data.leaf.periloctab = peritab; cblkptr->data.leaf.nodelocnbr = corddat.treenbr - 1; /* Get number of tree nodes, save for root */ o = 0; if (corddat.treenbr > 1) { cblkptr->data.leaf.cblklocnum = dorderNewSequIndex (cblkptr, corddat.treenbr - 1); /* Reserve local indices for local nodes */ if ((cblkptr->data.leaf.nodeloctab = hdgraphOrderSqTree (&corddat)) == NULL) { errorPrint ("hdgraphOrderSq2: cannot import centralized separation tree"); o = 1; } if (corddat.cblktre.typeval == ORDERCBLKNEDI) /* If root of centralized tree is a nested dissection node */ cblkptr->typeval |= DORDERCBLKNEDI; /* Distributed leaf is also a nested dissection node */ } else cblkptr->data.leaf.nodeloctab = NULL; corddat.flagval = ORDERNONE; /* Do not free permutation array */ orderExit (&corddat); /* Free permutation tree */ return (o); } /* This routine builds the distributed part of ** a distributed halo graph. This is a distinct ** routine to allow for multi-threading. */ static DorderNode * hdgraphOrderSqTree ( const Order * const cordptr) { DorderNode * nodetab; Gnum nodenum; Gnum cblknum; if ((nodetab = memAlloc ((cordptr->treenbr - 1) * sizeof (DorderNode))) == NULL) { /* "- 1" as root of tree will not be copied */ errorPrint ("hdgraphOrderSqTree: out of memory"); return (NULL); } nodenum = 0; /* Start labeling nodes from 0 */ for (cblknum = 0; cblknum < cordptr->cblktre.cblknbr; cblknum ++) hdgraphOrderSqTree2 (nodetab, &nodenum, &cordptr->cblktre.cblktab[cblknum], -1, cblknum); /* Root of tree is labeled "-1" */ #ifdef SCOTCH_DEBUG_HDGRAPH2 if (nodenum != (cordptr->treenbr - 1)) { errorPrint ("hdgraphOrderSqTree: internal error"); return (NULL); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ return (nodetab); } static void hdgraphOrderSqTree2 ( DorderNode * const nodetab, Gnum * const nodeptr, const OrderCblk * const cblkptr, const Gnum fathnum, const Gnum fcbknum) { Gnum nodenum; DorderNode * nodetmp; Gnum cblknum; nodenum = (*nodeptr) ++; nodetmp = &nodetab[nodenum]; nodetmp->fathnum = fathnum; nodetmp->typeval = (Gnum) cblkptr->typeval; nodetmp->vnodnbr = cblkptr->vnodnbr; nodetmp->cblknum = fcbknum; for (cblknum = 0; cblknum < cblkptr->cblknbr; cblknum ++) hdgraphOrderSqTree2 (nodetab, nodeptr, &cblkptr->cblktab[cblknum], nodenum, cblknum); } scotch-5.1.12b.dfsg/src/libscotch/library_graph_io_chac_f.c0000644000175300017530000001633711631334325024110 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_io_chac_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** graph i/o routines of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 4.0 : from : 23 nov 2005 **/ /** to 23 nov 2005 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 27 mar 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the mapping routines. */ /* */ /**************************************/ /* String lengths are passed at the very ** end of the argument list. */ FORTRAN ( \ SCOTCHFGRAPHGEOMLOADCHAC, scotchfgraphgeomloadchac, ( \ SCOTCH_Graph * const grafptr, \ SCOTCH_Geom * const geomptr, \ const int * const filegrfptr, \ const int * const filegeoptr, \ const char * const dataptr, /* No use */ \ int * const revaptr, \ const int datanbr), \ (grafptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) { FILE * filegrfstream; /* Streams to build from handles */ FILE * filegeostream; int filegrfnum; /* Duplicated handle */ int filegeonum; int o; if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHGEOMLOADCHAC: cannot duplicate handle (1)"); *revaptr = 1; /* Indicate error */ return; } if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHGEOMLOADCHAC: cannot duplicate handle (2)"); close (filegrfnum); *revaptr = 1; /* Indicate error */ return; } if ((filegrfstream = fdopen (filegrfnum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHGEOMLOADCHAC: cannot open input stream (1)"); close (filegrfnum); close (filegeonum); *revaptr = 1; return; } if ((filegeostream = fdopen (filegeonum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHGEOMLOADCHAC: cannot open input stream (2)"); fclose (filegrfstream); close (filegeonum); *revaptr = 1; return; } o = SCOTCH_graphGeomLoadChac (grafptr, geomptr, filegrfstream, filegeostream, NULL); fclose (filegrfstream); /* This closes file descriptors too */ fclose (filegeostream); *revaptr = o; } /* String lengths are passed at the very ** end of the argument list. */ FORTRAN ( \ SCOTCHFGRAPHGEOMSAVECHAC, scotchfgraphgeomsavechac, ( \ const SCOTCH_Graph * const grafptr, \ const SCOTCH_Geom * const geomptr, \ const int * const filegrfptr, \ const int * const filegeoptr, \ const char * const dataptr, /* No use */ \ int * const revaptr, \ const int datanbr), \ (grafptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) { FILE * filegrfstream; /* Streams to build from handles */ FILE * filegeostream; int filegrfnum; /* Duplicated handle */ int filegeonum; int o; if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHGEOMSAVECHAC: cannot duplicate handle (1)"); *revaptr = 1; /* Indicate error */ return; } if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHGEOMSAVECHAC: cannot duplicate handle (2)"); close (filegrfnum); *revaptr = 1; /* Indicate error */ return; } if ((filegrfstream = fdopen (filegrfnum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHGEOMSAVECHAC: cannot open output stream (1)"); close (filegrfnum); close (filegeonum); *revaptr = 1; return; } if ((filegeostream = fdopen (filegeonum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHGEOMSAVECHAC: cannot open output stream (2)"); fclose (filegrfstream); close (filegeonum); *revaptr = 1; return; } o = SCOTCH_graphGeomSaveChac (grafptr, geomptr, filegrfstream, filegeostream, NULL); fclose (filegrfstream); /* This closes file descriptors too */ fclose (filegeostream); *revaptr = o; } scotch-5.1.12b.dfsg/src/libscotch/bdgraph_bipart_df.c0000644000175300017530000004561311631334325022731 0ustar hazelscthazelsct/* Copyright 2007,2008,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_bipart_df.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module computes a bipartition of **/ /** the given distributed separator graph **/ /** by applying a diffusion method to what **/ /** is assumed to be a distributed band **/ /** graph. **/ /** **/ /** DATES : # Version 5.1 : from : 16 nov 2007 **/ /** to : 19 jul 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BDGRAPH_BIPART_DF #include "module.h" #include "common.h" #include "arch.h" #include "dgraph.h" #include "bdgraph.h" #include "bdgraph_bipart_df.h" /* ** The static variables. */ static const Gnum bdgraphbipartdfloadone = 1; static const Gnum bdgraphbipartdfloadzero = 0; /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine computes a distributed bipartition ** by diffusion across what is assumed to be a ** distributed band graph. ** It returns: ** - 0 : if the bipartition could be computed. ** - !0 : on error. */ int bdgraphBipartDf ( Bdgraph * const grafptr, /*+ Distributed graph +*/ const BdgraphBipartDfParam * const paraptr) /*+ Method parameters +*/ { float * restrict ielsloctax; /* Inverse of degree array */ float * restrict veexloctax; /* Veexval over domdist */ float * restrict difogsttax; /* Old diffusion value array */ float * restrict difngsttax; /* New diffusion value array */ const Gnum * restrict edgegsttax; Gnum fronlocnum; Gnum veexlocnbr; float vanclocval[2]; float valolocval[2]; /* Fraction of load to remove from anchor vertices at each step */ Gnum vanclocnnd; Gnum vertlocnum; const Gnum * restrict velolocbax; Gnum velolocmsk; const Gnum * restrict edlolocbax; Gnum edlolocmsk; Gnum complocload1; Gnum complocsize1; Gnum commlocloadintn; Gnum commlocloadextn; Gnum commlocgainextn; Gnum reduloctab[6]; Gnum reduglbtab[6]; Gnum passnum; float cdifval; float cremval; int ovflval; /* Overflow flag value */ if (dgraphGhst (&grafptr->s) != 0) { /* Compute ghost edge array if not already present */ errorPrint ("bdgraphBipartDf: cannot compute ghost edge array"); return (1); } reduloctab[0] = grafptr->s.vendloctax[grafptr->s.vertlocnnd - 2] - grafptr->s.vertloctax[grafptr->s.vertlocnnd - 2] - (grafptr->s.procglbnbr - 1); /* Local degree of both anchor vertices, minus edges to other anchors */ reduloctab[1] = grafptr->s.vendloctax[grafptr->s.vertlocnnd - 1] - grafptr->s.vertloctax[grafptr->s.vertlocnnd - 1] - (grafptr->s.procglbnbr - 1); /* Anchor edges have load 1 even for weighted graphs */ if (grafptr->s.veloloctax == NULL) reduloctab[2] = /* Weights of anchors */ reduloctab[3] = 1; else { reduloctab[2] = grafptr->s.veloloctax[grafptr->s.vertlocnnd - 2]; reduloctab[3] = grafptr->s.veloloctax[grafptr->s.vertlocnnd - 1]; } veexlocnbr = (grafptr->veexloctax != NULL) ? grafptr->s.vertlocnbr : 0; if (memAllocGroup ((void **) (void *) &ielsloctax, (size_t) (grafptr->s.vertlocnbr * sizeof (float)), &veexloctax, (size_t) (veexlocnbr * sizeof (float)), &difogsttax, (size_t) (grafptr->s.vertgstnbr * sizeof (float)), &difngsttax, (size_t) (grafptr->s.vertgstnbr * sizeof (float)), NULL) == NULL) { errorPrint ("bdgraphBipartDf: out of memory"); reduloctab[0] = -1; } ielsloctax -= grafptr->s.baseval; difogsttax -= grafptr->s.baseval; difngsttax -= grafptr->s.baseval; veexloctax = (grafptr->veexloctax != NULL) ? (veexloctax - grafptr->s.baseval) : NULL; if (MPI_Allreduce (reduloctab, reduglbtab, 4, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartDf: communication error (1)"); return (1); } if (reduglbtab[0] < 0) { if (ielsloctax != NULL) memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ return (1); } if ((reduglbtab[0] == 0) || /* If graph is too small to have any usable anchors, leave partition as is */ (reduglbtab[1] == 0)) { memFree (ielsloctax + grafptr->s.baseval); if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (grafptr->partgsttax + grafptr->s.baseval), GRAPHPART_MPI) != 0) { errorPrint ("bdgraphBipartDf: cannot propagate part data (1)"); return (1); } return (0); } vanclocval[0] = (float) ((paraptr->typeval == BDGRAPHBIPARTDFTYPEBAL) /* If balanced parts wanted */ ? grafptr->compglbload0avg /* Target is average */ : ( (grafptr->compglbload0 < grafptr->compglbload0min) ? grafptr->compglbload0min : /* Else keep load if not off balance */ ((grafptr->compglbload0 > grafptr->compglbload0max) ? grafptr->compglbload0max : grafptr->compglbload0))); vanclocval[1] = (float) grafptr->s.veloglbsum - vanclocval[0]; vanclocval[0] = - vanclocval[0]; /* Part 0 holds negative values */ valolocval[0] = (float) reduglbtab[2]; /* Compute values to remove from anchor vertices */ valolocval[1] = (float) reduglbtab[3] - BDGRAPHBIPARTDFEPSILON; /* Slightly tilt value to add to part 1 */ vanclocnnd = grafptr->s.vertlocnnd - 2; /* Do not account for anchor vertices in diffusion computations */ if (grafptr->s.edloloctax != NULL) { for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) { Gnum edgelocnum; Gnum edgelocnnd; Gnum edlolocsum; #ifdef SCOTCH_DEBUG_BDGRAPH2 if ((grafptr->s.vendloctax[vertlocnum] - grafptr->s.vertloctax[vertlocnum]) == 0) { errorPrint ("bdgraphBipartDf: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ difogsttax[vertlocnum] = 0.0F; for (edgelocnum = grafptr->s.vertloctax[vertlocnum], edgelocnnd = grafptr->s.vendloctax[vertlocnum], edlolocsum = 0; edgelocnum < edgelocnnd; edgelocnum ++) edlolocsum += grafptr->s.edloloctax[edgelocnum]; ielsloctax[vertlocnum] = 1.0F / (float) edlolocsum; } } else { /* Graph has no edge loads */ for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) { #ifdef SCOTCH_DEBUG_BDGRAPH2 if ((grafptr->s.vendloctax[vertlocnum] - grafptr->s.vertloctax[vertlocnum]) == 0) { errorPrint ("bdgraphBipartDf: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ ielsloctax[vertlocnum] = 1.0F / (float) (grafptr->s.vendloctax[vertlocnum] - grafptr->s.vertloctax[vertlocnum]); difogsttax[vertlocnum] = 0.0F; } } ielsloctax[vanclocnnd] = 1.0F / (float) reduglbtab[0]; ielsloctax[vanclocnnd + 1] = 1.0F / (float) reduglbtab[1]; difogsttax[vanclocnnd] = vanclocval[0] * ielsloctax[vanclocnnd]; /* Load anchor vertices for first pass */ difogsttax[vanclocnnd + 1] = vanclocval[1] * ielsloctax[vanclocnnd + 1]; difngsttax[vanclocnnd] = /* In case of isolated anchors, do not risk overflow because of NaN */ difngsttax[vanclocnnd + 1] = 0.0F; if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (difogsttax + grafptr->s.baseval), MPI_FLOAT) != 0) { /* Perform initial diffusion (and build communication structures) */ errorPrint ("bdgraphBipartDf: cannot propagate diffusion data (1)"); memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ return (1); } ovflval = 0; cdifval = paraptr->cdifval; cremval = paraptr->cremval; edgegsttax = grafptr->s.edgegsttax; for (passnum = 0; ; ) { /* For all passes */ if (ovflval == 0) { /* If no overflow occured */ float * diftgsttax; /* Temporary swap value */ Gnum vertlocnum; float veloval; veloval = 1.0F; /* Assume no vertex loads */ for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) { Gnum edgelocnum; Gnum edgelocnnd; float diffval; diffval = 0.0F; edgelocnum = grafptr->s.vertloctax[vertlocnum]; edgelocnnd = grafptr->s.vendloctax[vertlocnum]; if (grafptr->s.edloloctax != NULL) for ( ; edgelocnum < edgelocnnd; edgelocnum ++) diffval += difogsttax[edgegsttax[edgelocnum]] * (float) grafptr->s.edloloctax[edgelocnum]; else for ( ; edgelocnum < edgelocnnd; edgelocnum ++) diffval += difogsttax[edgegsttax[edgelocnum]]; diffval *= cdifval; diffval += (difogsttax[vertlocnum] * cremval) / ielsloctax[vertlocnum]; if (grafptr->s.veloloctax != NULL) veloval = (float) grafptr->s.veloloctax[vertlocnum]; if (diffval >= 0.0F) { diffval = (diffval - veloval) * ielsloctax[vertlocnum]; if (diffval <= 0.0F) diffval = +BDGRAPHBIPARTDFEPSILON; } else { diffval = (diffval + veloval) * ielsloctax[vertlocnum]; if (diffval >= 0.0F) diffval = -BDGRAPHBIPARTDFEPSILON; } if (isnan (diffval)) { /* If overflow occured */ ovflval = 1; /* We are in state of overflow */ goto abort; /* Exit this loop without swapping arrays */ } difngsttax[vertlocnum] = diffval; } for ( ; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { /* For the two local anchor vertices */ Gnum edgelocnum; Gnum edgelocnnd; float diffval; diffval = 0.0F; edgelocnum = grafptr->s.vertloctax[vertlocnum] + grafptr->s.procglbnbr - 1; /* Skip links to other anchors */ edgelocnnd = grafptr->s.vendloctax[vertlocnum]; if (edgelocnum == edgelocnnd) /* If isolated anchor */ continue; /* Barrel is empty */ for ( ; edgelocnum < edgelocnnd; edgelocnum ++) /* Anchor edges have load 1 even for weighted graphs */ diffval += difogsttax[edgegsttax[edgelocnum]]; diffval *= cdifval; diffval += vanclocval[vertlocnum - vanclocnnd] + (difogsttax[vertlocnum] * cremval) / ielsloctax[vertlocnum]; if (diffval >= 0.0F) { diffval = (diffval - valolocval[vertlocnum - vanclocnnd]) * ielsloctax[vertlocnum]; if (diffval <= 0.0F) diffval = +BDGRAPHBIPARTDFEPSILON; } else { diffval = (diffval + valolocval[vertlocnum - vanclocnnd]) * ielsloctax[vertlocnum]; if (diffval >= 0.0F) diffval = -BDGRAPHBIPARTDFEPSILON; } if (isnan (diffval)) { /* If overflow occured */ ovflval = 1; /* We are in state of overflow */ goto abort; /* Exit this loop without swapping arrays */ } difngsttax[vertlocnum] = diffval; } diftgsttax = (float *) difngsttax; /* Swap old and new diffusion arrays */ difngsttax = (float *) difogsttax; /* Casts to prevent IBM compiler from yelling */ difogsttax = (float *) diftgsttax; } abort : /* If overflow occured, resume here */ if (++ passnum >= paraptr->passnbr) /* If maximum number of passes reached */ break; /* Exit main loop */ if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (difogsttax + grafptr->s.baseval), MPI_FLOAT) != 0) { errorPrint ("bdgraphBipartDf: cannot propagate diffusion data (2)"); memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ return (1); } } for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) /* Set new part distribution */ grafptr->partgsttax[vertlocnum] = (difogsttax[vertlocnum] <= 0.0F) ? 0 : 1; grafptr->partgsttax[vanclocnnd] = 0; /* Set up parts in case anchors are isolated */ grafptr->partgsttax[vanclocnnd + 1] = 1; if (grafptr->s.veloloctax != NULL) { velolocbax = grafptr->s.veloloctax; velolocmsk = ~((Gnum) 0); } else { velolocbax = &bdgraphbipartdfloadone; velolocmsk = 0; } if (grafptr->s.edloloctax != NULL) { edlolocbax = grafptr->s.edloloctax; edlolocmsk = ~((Gnum) 0); } else { edlolocbax = &bdgraphbipartdfloadone; edlolocmsk = 0; } memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (grafptr->partgsttax + grafptr->s.baseval), GRAPHPART_MPI) != 0) { errorPrint ("bdgraphBipartDf: cannot propagate part data (2)"); return (1); } commlocloadintn = commlocloadextn = commlocgainextn = 0; for (vertlocnum = grafptr->s.baseval, fronlocnum = complocsize1 = complocload1 = 0; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { Gnum edgelocnum; Gnum edgelocnnd; Gnum veloval; Gnum partval; Gnum flagval; #ifdef SCOTCH_DEBUG_BDGRAPH2 if (grafptr->partgsttax[vertlocnum] > 1) { errorPrint ("bdgraphBipartDf: internal error (3)"); break; /* Do not break upcoming collective communications */ } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ partval = (Gnum) grafptr->partgsttax[vertlocnum]; veloval = velolocbax[vertlocnum & velolocmsk]; if (grafptr->veexloctax != NULL) { commlocloadextn += grafptr->veexloctax[vertlocnum] * partval; commlocgainextn += grafptr->veexloctax[vertlocnum] * (1 - partval * 2); } complocsize1 += partval; complocload1 += partval * veloval; flagval = 0; for (edgelocnum = grafptr->s.vertloctax[vertlocnum], edgelocnnd = grafptr->s.vendloctax[vertlocnum]; edgelocnum < edgelocnnd; edgelocnum ++) { Gnum edloval; Gnum partend; partend = (Gnum) grafptr->partgsttax[edgegsttax[edgelocnum]]; #ifdef SCOTCH_DEBUG_BDGRAPH2 if (partend > 1) { errorPrint ("bdgraphBipartDf: internal error (4)"); vertlocnum = grafptr->s.vertlocnnd; break; /* Do not break upcoming collective communications */ } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ edloval = edlolocbax[edgelocnum & edlolocmsk]; flagval |= partval ^ partend; commlocloadintn += (partval ^ partend) * edloval; /* Internal load is accounted for twice */ } if (flagval != 0) /* If vertex has neighbors in other part */ grafptr->fronloctab[fronlocnum ++] = vertlocnum; /* Record it as member of separator */ } grafptr->complocload0 = grafptr->s.velolocsum - complocload1; grafptr->complocsize0 = grafptr->s.vertlocnbr - complocsize1; grafptr->fronlocnbr = fronlocnum; reduloctab[0] = fronlocnum; reduloctab[1] = grafptr->complocload0; reduloctab[2] = grafptr->complocsize0; reduloctab[3] = commlocloadintn; /* Twice the internal load; sum globally before dividing by two */ reduloctab[4] = commlocloadextn; reduloctab[5] = commlocgainextn; if (MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 6, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartDf: communication error (2)"); return (1); } grafptr->fronglbnbr = reduglbtab[0]; grafptr->compglbload0 = reduglbtab[1]; grafptr->compglbload0dlt = grafptr->compglbload0 - grafptr->compglbload0avg; grafptr->compglbsize0 = reduglbtab[2]; grafptr->commglbload = (reduglbtab[3] / 2) * grafptr->domdist + reduglbtab[4]; grafptr->commglbgainextn = reduglbtab[5]; #ifdef SCOTCH_DEBUG_BDGRAPH2 if (bdgraphCheck (grafptr) != 0) { errorPrint ("bdgraphBipartDf: internal error (5)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_version.c0000644000175300017530000000642411631334325022516 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_version.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains miscellaneous **/ /** routines for handling API- and **/ /** version-related routines in the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 5.1 : from : 16 nov 2010 **/ /** to 16 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* miscellaneous routines. */ /* */ /************************************/ /*+ This routine returns the version, *** release and patchlevel numbers of *** the library being used (useful for *** dynamic libraries). *** It returns: *** - void : in all cases. +*/ void SCOTCH_version ( int * const versptr, int * const relaptr, int * const patcptr) { *versptr = SCOTCH_VERSION; *relaptr = SCOTCH_RELEASE; *patcptr = SCOTCH_PATCHLEVEL; } scotch-5.1.12b.dfsg/src/libscotch/bdgraph_bipart_ex.h0000644000175300017530000000751711631334325022762 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_bipart_ex.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the parallel load imbalance **/ /** minimization bipartitioning routine **/ /** for distributed graphs. **/ /** **/ /** DATES : # Version 5.1 : from : 14 jul 2010 **/ /** to : 14 aug 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct BdgraphBipartExParam_ { INT sbbtnbr; /*+ Number of sub-bits in the distributed gain structure +*/ double deltval; /*+ Maximum weight imbalance ratio +*/ } BdgraphBipartExParam; /* Sort structure for local vertices. First element used for intSort2asc1. */ typedef struct BdgraphBipartExSort_ { Gnum veloval; /* Load per process; TRICK: FIRST */ Gnum prioval; /* Priority value, not to sort by process rank */ Gnum procnum; /* Process number; TRICK: (Gnum) for sorting */ } BdgraphBipartExSort; /* Sort structure for individual moves. */ typedef struct BdgraphBipartExMove_ { Gnum veloval; /* Load per process; TRICK: FIRST */ Gnum vertnum; /* Vertex number */ } BdgraphBipartExMove; /* ** The function prototypes. */ #ifndef BDGRAPH_BIPART_EX #define static #endif int bdgraphBipartEx (Bdgraph * restrict const, const BdgraphBipartExParam * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/vmesh_store.c0000644000175300017530000001414311631334325021640 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh_store.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the save data **/ /** structure handling routines for node **/ /** separation meshes. **/ /** **/ /** DATES : # Version 4.0 : from : 10 sep 2002 **/ /** to : 10 sep 2002 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VMESH_STORE #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" #include "vmesh.h" /*********************************/ /* */ /* Store mesh handling routines. */ /* */ /*********************************/ /* This routine builds a save structure ** for the given node separation mesh. ** It returns: ** - 0 : if allocation succeeded. ** - !0 : on error. */ int vmeshStoreInit ( const Vmesh * const meshptr, VmeshStore * const storptr) { Gnum savsize; savsize = (meshptr->m.velmnbr + meshptr->m.vnodnbr) * (sizeof (GraphPart) + sizeof (Gnum)); /* Compute size for frontier and part arrays */ if ((storptr->datatab = (byte *) memAlloc (savsize)) == NULL) { /* Allocate save structure */ errorPrint ("vmeshStoreInit: out of memory"); return (1); } return (0); } /* This routine frees a mesh node ** separation save structure. ** It returns: ** - VOID : in all cases. */ void vmeshStoreExit ( VmeshStore * const storptr) { memFree (storptr->datatab); #ifdef SCOTCH_DEBUG_VMESH2 storptr->datatab = NULL; #endif /* SCOTCH_DEBUG_VMESH2 */ } /* This routine saves partition data from the ** given node separation mesh to the given ** save structure. ** It returns: ** - VOID : in all cases. */ void vmeshStoreSave ( const Vmesh * const meshptr, VmeshStore * const storptr) { byte * parttab; /* Pointer to part data save area */ byte * frontab; /* Pointer to frontier data save area */ storptr->ecmpsize[0] = meshptr->ecmpsize[0]; /* Save partition parameters */ storptr->ecmpsize[1] = meshptr->ecmpsize[1]; storptr->ncmpload[0] = meshptr->ncmpload[0]; storptr->ncmpload[1] = meshptr->ncmpload[1]; storptr->ncmpload[2] = meshptr->ncmpload[2]; storptr->ncmploaddlt = meshptr->ncmploaddlt; storptr->ncmpsize[0] = meshptr->ncmpsize[0]; storptr->ncmpsize[1] = meshptr->ncmpsize[1]; storptr->fronnbr = meshptr->fronnbr; frontab = storptr->datatab; /* Compute data offsets within save structure */ parttab = frontab + meshptr->fronnbr * sizeof (Gnum); memCpy (frontab, meshptr->frontab, meshptr->fronnbr * sizeof (Gnum)); memCpy (parttab, meshptr->parttax + meshptr->m.baseval, (meshptr->m.velmnbr + meshptr->m.vnodnbr) * sizeof (GraphPart)); } /* This routine updates partition data of the ** given active graph, using the given save graph. ** It returns: ** - VOID : in all cases. */ void vmeshStoreUpdt ( Vmesh * const meshptr, const VmeshStore * const storptr) { byte * frontab; /* Pointer to frontier data save area */ byte * parttab; /* Pointer to part data save area */ meshptr->ecmpsize[0] = storptr->ecmpsize[0]; /* Load partition parameters */ meshptr->ecmpsize[1] = storptr->ecmpsize[1]; meshptr->ncmpload[0] = storptr->ncmpload[0]; meshptr->ncmpload[1] = storptr->ncmpload[1]; meshptr->ncmpload[2] = storptr->ncmpload[2]; meshptr->ncmploaddlt = storptr->ncmploaddlt; meshptr->ncmpsize[0] = storptr->ncmpsize[0]; meshptr->ncmpsize[1] = storptr->ncmpsize[1]; meshptr->fronnbr = storptr->fronnbr; frontab = storptr->datatab; /* Compute data offsets within save structure */ parttab = frontab + storptr->fronnbr * sizeof (Gnum); memCpy (meshptr->frontab, frontab, storptr->fronnbr * sizeof (Gnum)); memCpy (meshptr->parttax + meshptr->m.baseval, parttab, (meshptr->m.velmnbr + meshptr->m.vnodnbr) * sizeof (GraphPart)); } scotch-5.1.12b.dfsg/src/libscotch/kdgraph_map_rb_map.h0000644000175300017530000000543611631334325023111 0ustar hazelscthazelsct/* Copyright 2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kdgraph_map_rb_map.h **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the Parallel Dual Recursive **/ /** Bipartitioning mapping algorithm. **/ /** **/ /** DATES : # Version 5.1 : from : 24 jun 2008 **/ /** to 24 jun 2008 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /* ** The function prototypes. */ #ifndef KDGRAPH_MAP_RB #define static #endif int kdgraphMapRbMap (Kdgraph * const, Kdmapping * const, const KdgraphMapRbParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_hf.h0000644000175300017530000000666011631334325022270 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_hf.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the block-oriented Halo **/ /** Approximate (Multiple) Minimum Fill **/ /** mesh ordering routine. **/ /** **/ /** DATES : # Version 4.0 : from : 09 dec 2003 **/ /** to 10 dec 2003 **/ /** # Version 5.1 : from : 01 oct 2009 **/ /** to : 01 oct 2009 **/ /** **/ /************************************************************/ /* ** The defines. */ #define HMESHORDERHFCOMPRAT 1.2L /*+ Compression ratio +*/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HmeshOrderHfParam_ { INT colmin; /*+ Minimum number of columns +*/ INT colmax; /*+ Maximum number of columns +*/ double fillrat; /*+ Fill-in ratio +*/ } HmeshOrderHfParam; /* ** The function prototypes. */ #ifndef HMESH_ORDER_HF #define static #endif int hmeshOrderHf (const Hmesh * restrict const, Order * restrict const, const Gnum, OrderCblk * restrict const, const HmeshOrderHfParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/mesh_io.h0000644000175300017530000000532711631334325020736 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mesh_io.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the source graph input/output **/ /** functions. **/ /** **/ /** DATES : # Version 4.0 : from : 14 nov 2002 **/ /** to 14 nov 2002 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef MESH_IO #define static #endif int meshLoad2 (const Gnum, const Gnum, const Gnum * const, const Gnum * const, Gnum * const, const Gnum, const Gnum * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_io_save.c0000644000175300017530000000632611631334325024004 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_io_save.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted source graph saving routine of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 16 may 2007 **/ /** to 16 may 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "graph.h" #include "dgraph.h" #include "scotch.h" /****************************************/ /* */ /* These routines are the C API for the */ /* distributed graph handling routines. */ /* */ /****************************************/ /*+ This routine saves the contents of the given *** opaque distributed graph structure to the *** given streams. *** It returns: *** - 0 : if the saving succeeded. *** - !0 : on error. +*/ int SCOTCH_dgraphSave ( SCOTCH_Dgraph * const grafptr, FILE * const stream) { return (dgraphSave ((Dgraph * const) grafptr, stream)); } scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_ex.c0000644000175300017530000001176211631334325022606 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_ex.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module tries to balance the **/ /** subgraphs of the partition as best as **/ /** it can. **/ /** **/ /** DATES : # Version 2.0 : from : 25 oct 1994 **/ /** to 03 nov 1994 **/ /** # Version 3.0 : from : 18 nov 1995 **/ /** to 18 nov 1995 **/ /** # Version 3.1 : from : 20 nov 1995 **/ /** to 29 nov 1995 **/ /** # Version 3.2 : from : 15 sep 1996 **/ /** to 13 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 3.4 : from : 01 jun 2001 **/ /** to 01 jun 2001 **/ /** # Version 4.0 : from : 11 dec 2003 **/ /** to 11 dec 2003 **/ /** # Version 5.1 : from : 30 nov 2007 **/ /** to 30 nov 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes */ #define BGRAPH_BIPART_EX #include "module.h" #include "common.h" #include "gain.h" #include "graph.h" #include "arch.h" #include "bgraph.h" #include "bgraph_bipart_ex.h" #include "bgraph_bipart_fm.h" #include "bgraph_bipart_gg.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the bipartitioning. ** It returns: ** - 0 : if bipartitioning could be computed. ** - 1 : on error. */ int bgraphBipartEx ( Bgraph * restrict const grafptr) { BgraphBipartFmParam parafmdat; /* Parameter area for the Fiduccia-Mattheyses algorithm */ if (grafptr->compload0dlt == 0) /* Return if nothing to do */ return (0); parafmdat.movenbr = grafptr->s.vertnbr; parafmdat.passnbr = ~0; parafmdat.deltval = 0.0L; /* Exact balance required */ if (bgraphBipartFm (grafptr, ¶fmdat) != 0) /* Return if error */ return (1); if ((grafptr->s.vertnbr > 1) && /* If graph has several vertices but is completely imbalanced */ ((grafptr->compload0 == 0) || (grafptr->compload0 == grafptr->s.velosum))) { BgraphBipartGgParam paraggdat; /* Parameter area for the Greedy Graph Growing algorithm */ paraggdat.passnbr = 4; if (bgraphBipartGg (grafptr, ¶ggdat) != 0) /* Return if error */ return (1); } #ifdef SCOTCH_DEBUG_BGRAPH2 if (bgraphCheck (grafptr) != 0) { errorPrint ("bgraphBipartEx: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/hall_order_hf.h0000644000175300017530000000602111631334325022073 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hall_order_hf.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the block-oriented Halo **/ /** Approximate (Multiple) Minimum Fill **/ /** ordering routine. **/ /** **/ /** DATES : # Version 3.4 : from : 15 may 2001 **/ /** to : 15 may 2001 **/ /** # Version 4.0 : from : 10 jan 2003 **/ /** to : 08 dec 2003 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef HALL_ORDER_HF #define static #endif void hallOrderHfR2hamdf4 (const Gnum n, const Gnum nbelts, const Gnum nbbuck, const Gnum iwlen, Gnum pe[], Gnum pfree, Gnum len[], Gnum iw[], Gnum nv[], Gnum elen[], Gnum last[], Gnum * ncmpa, Gnum degree[], Gnum wf[], Gnum next[], Gnum w[], Gnum head[]); #undef static scotch-5.1.12b.dfsg/src/libscotch/arch_deco.c0000644000175300017530000005205711631334325021217 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_deco.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the decomposition- **/ /** defined target architecture. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 23 dec 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 29 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 14 sep 1995 **/ /** # Version 3.1 : from : 20 jul 1996 **/ /** to 23 jul 1996 **/ /** # Version 3.2 : from : 11 sep 1996 **/ /** to 28 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 17 may 1999 **/ /** # Version 4.0 : from : 29 nov 2003 **/ /** to 10 mar 2005 **/ /** # Version 5.0 : from : 10 sep 2007 **/ /** to 28 feb 2008 **/ /** # Version 5.1 : from : 21 jan 2008 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ARCH_DECO #include "module.h" #include "common.h" #include "arch.h" #include "arch_deco.h" /***************************************/ /* */ /* These are the decomposition-defined */ /* architecture routines. */ /* */ /***************************************/ /* This routine builds a compiled ** decomposition-defined architecture ** from the raw terminal tables that are ** passed to it. ** It returns: ** - 0 : if the decomposition has been successfully computed. ** - !0 : on error. */ int archDecoArchBuild ( ArchDeco * restrict const archptr, /*+ Architecture to build +*/ const Anum termdomnbr, /*+ Number of terminal domains (ie processors) +*/ const Anum termdommax, /*+ Maximum domain number given to a terminal domain +*/ const ArchDecoTermVert * const termverttab, /*+ Terminal vertex array +*/ const Anum * const termdisttab) /*+ Terminal distance map +*/ { Anum i, j, k; #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchDeco) > sizeof (ArchDummy)) || (sizeof (ArchDecoDom) > sizeof (ArchDomDummy))) { errorPrint ("archDecoArchBuild: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if (memAllocGroup ((void **) (void *) &archptr->domverttab, (size_t) (termdommax * sizeof (ArchDecoVert)), &archptr->domdisttab, (size_t) ((((termdommax * (termdommax - 1)) / 2) + 1) * sizeof (Anum)), NULL) == NULL) { errorPrint ("archDecoArchBuild: out of memory"); return (1); } archptr->flagval = ARCHDECOFREE; archptr->domtermnbr = termdomnbr; archptr->domvertnbr = termdommax; for (i = 0; i < termdommax; i ++) { archptr->domverttab[i].labl = ARCHDOMNOTTERM; /* Assume domain is not a terminal */ archptr->domverttab[i].size = 0; /* Assume domain is not used (yet) */ archptr->domverttab[i].wght = 0; /* Assume domain is not used (yet) */ } for (i = 0; i < termdomnbr; i ++) { /* Set terminal data of all declared terminals */ #ifdef SCOTCH_DEBUG_ARCH1 if (termverttab[i].num > termdommax) { /* If incorrect maximum terminal number */ errorPrint ("archDecoArchBuild: bad maximum terminal"); archDecoArchFree (archptr); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ archptr->domverttab[termverttab[i].num - 1].labl = termverttab[i].labl; archptr->domverttab[termverttab[i].num - 1].size = 1; archptr->domverttab[termverttab[i].num - 1].wght = termverttab[i].wght; } for (i = termdommax - 1; i > 0; i --) { /* Accumulate data from terminals to root */ j = ((i - 1) >> 1); if (archptr->domverttab[i].labl != ARCHDOMNOTTERM) { if ((archptr->domverttab[j].labl == ARCHDOMNOTTERM) || /* Get smallest label */ (archptr->domverttab[j].labl > archptr->domverttab[i].labl)) archptr->domverttab[j].labl = archptr->domverttab[i].labl; archptr->domverttab[j].size += archptr->domverttab[i].size; archptr->domverttab[j].wght += archptr->domverttab[i].wght; } } #ifdef SCOTCH_DEBUG_ARCH1 if (archptr->domverttab[0].size != termdomnbr) { /* If incorrect accumulation */ errorPrint ("archDecoArchBuild: bad terminal count"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ memSet (archptr->domdisttab, 0, termdommax * (termdommax - 1) * sizeof (Anum) / 2); /* Assume distance is not known */ for (i = 1, k = 0; i < termdomnbr; i ++) { /* Read the terminal distance map */ for (j = 0; j < i; j ++, k ++) archDecoArchDist (archptr, termverttab[i].num, termverttab[j].num) = termdisttab[k]; } for (j = termdommax; j > 0; j --) { /* Loop on domains */ if (archDecoArchSize (archptr, j) == 0) /* If domain is unused, skip it */ continue; for (i = termdommax; i > j; i --) { /* Double loop on distance array values */ if (archDecoArchSize (archptr, i) == 0) /* If domain is unused, skip it */ continue; if (archDecoArchSize (archptr, i) > 1) { /* If domain i has subdomains */ if (archDecoArchSize (archptr, j) > 1) /* If domain j has subdomains */ archDecoArchDist (archptr, i, j) = (archDecoArchDistE (archptr, 2 * i, 2 * j) + archDecoArchDistE (archptr, 2 * i, 2 * j + 1) + archDecoArchDistE (archptr, 2 * i + 1, 2 * j) + archDecoArchDistE (archptr, 2 * i + 1, 2 * j + 1) + 2) / 4; else /* If domain j is a terminal */ archDecoArchDist (archptr, i, j) = (archDecoArchDistE (archptr, 2 * i, j) + archDecoArchDistE (archptr, 2 * i + 1, j) + 1) / 2; } else { /* If domain i is a terminal */ if (archDecoArchSize (archptr, j) > 1) /* If domain j has subdomains */ archDecoArchDist (archptr, i, j) = (archDecoArchDistE (archptr, i, 2 * j) + archDecoArchDistE (archptr, i, 2 * j + 1) + 1) / 2; #ifdef SCOTCH_DEBUG_ARCH1 else { /* If both domain are terminals */ if (archDecoArchDist (archptr, i, j) == 0) { /* Distance value must be greater than zero */ errorPrint ("archDecoArchBuild: invalid null distance"); archDecoArchFree (archptr); return (1); } } #endif /* SCOTCH_DEBUG_ARCH1 */ } } } return (0); } /* This routine loads and computes the ** decomposition-defined architecture ** tables. ** It returns: ** - 0 : if the decomposition has been successfully read. ** - !0 : on error. */ int archDecoArchLoad ( ArchDeco * restrict const archptr, FILE * restrict const stream) { INT decotype; /* Type of decomposition */ INT termdomnbr; /* Number of terminal domains (ie processors) */ INT termdommax; /* Maximum domain number given to a terminal domain */ ArchDecoTermVert * restrict termverttab; /* Table of terminal vertex data */ Anum * restrict termdisttab; /* Table of terminal-to-terminal distances */ INT i, j; #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchDeco) > sizeof (ArchDummy)) || (sizeof (ArchDecoDom) > sizeof (ArchDomDummy))) { errorPrint ("archDecoArchLoad: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if ((intLoad (stream, &decotype) != 1) || /* Read header */ (intLoad (stream, &termdomnbr) != 1) || (intLoad (stream, &termdommax) != 1) || (decotype < 0) || (decotype > 1) || (termdommax < termdomnbr) || (termdomnbr < 1)) { errorPrint ("archDecoArchLoad: bad input (1)"); return (1); } if (decotype == 0) { /* If raw decomposition */ if (memAllocGroup ((void **) (void *) &termverttab, (size_t) (termdomnbr * sizeof (ArchDecoTermVert)), &termdisttab, (size_t) ((((termdommax * (termdommax - 1)) / 2) + 1) * sizeof (Anum)), NULL) == NULL) { errorPrint ("archDecoArchLoad: out of memory (1)"); return (1); } for (i = 0; i < termdomnbr; i ++) { /* For all declared terminals */ INT termvertlabl; INT termvertwght; INT termvertnum; if ((intLoad (stream, &termvertlabl) != 1) || /* Read terminal data */ (intLoad (stream, &termvertwght) != 1) || (intLoad (stream, &termvertnum) != 1) || (termvertnum < 1) || (termvertnum > termdommax)) { errorPrint ("archDecoArchLoad: bad input (2)"); memFree (termverttab); /* Free group leader */ return (1); } termverttab[i].labl = (ArchDomNum) termvertlabl; termverttab[i].wght = (Anum) termvertwght; termverttab[i].num = (Anum) termvertnum; } for (i = 0, j = (termdomnbr * (termdomnbr - 1)) / 2; i < j; i ++) { /* Read terminal distance map */ INT termdistval; if ((intLoad (stream, &termdistval) != 1) || (termdistval < 1)) { errorPrint ("archDecoArchLoad: bad input (3)"); memFree (termverttab); /* Free group leader */ return (1); } termdisttab[i] = (Anum) termdistval; } archDecoArchBuild (archptr, termdomnbr, termdommax, termverttab, termdisttab); memFree (termverttab); /* Free group leader */ } else { /* If it is a compiled decomposition */ if (memAllocGroup ((void **) (void *) &archptr->domverttab, (size_t) (termdommax * sizeof (ArchDecoVert)), &archptr->domdisttab, (size_t) ((((termdommax * (termdommax - 1)) / 2) + 1) * sizeof (Anum)), NULL) == NULL) { errorPrint ("archDecoArchLoad: out of memory (2)"); return (1); } archptr->flagval = ARCHDECOFREE; archptr->domtermnbr = (Anum) termdomnbr; archptr->domvertnbr = (Anum) termdommax; for (i = 0; i < termdommax; i ++) { /* Read domain array */ INT domvertlabl; INT domvertsize; INT domvertwght; if ((intLoad (stream, &domvertlabl) != 1) || (intLoad (stream, &domvertsize) != 1) || (intLoad (stream, &domvertwght) != 1)) { errorPrint ("archDecoArchLoad: bad input (4)"); archDecoArchFree (archptr); return (1); } archptr->domverttab[i].labl = (ArchDomNum) domvertlabl; archptr->domverttab[i].size = (Anum) domvertsize; archptr->domverttab[i].wght = (Anum) domvertwght; } for (i = 0; i < (termdommax * (termdommax - 1)) / 2; i ++) { /* Read distance array */ INT domdistval; if (intLoad (stream, &domdistval) != 1) { errorPrint ("archDecoArchLoad: bad input (5)"); archDecoArchFree (archptr); return (1); } archptr->domdisttab[i] = domdistval; } } return (0); } /* This routine frees the decomposition ** architecture structures. ** It returns: ** - 0 : if the decomposition has been successfully freed. ** - !0 : on error. */ int archDecoArchFree ( ArchDeco * const archptr) { #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchDeco) > sizeof (ArchDummy)) || (sizeof (ArchDecoDom) > sizeof (ArchDomDummy))) { errorPrint ("archDecoArchFree: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if (((archptr->flagval & ARCHDECOFREE) != 0) && (archptr->domverttab != NULL)) memFree (archptr->domverttab); /* Free group leader */ archptr->domtermnbr = archptr->domvertnbr = 0; archptr->domverttab = NULL; archptr->domdisttab = NULL; return (0); } /* This routine saves the given target architecture ** as compiled decomposition tables. ** It returns: ** - 0 : if the decomposition has been successfully written. ** - !0 : on error. */ int archDecoArchSave ( const ArchDeco * const archptr, FILE * restrict const stream) { Anum i, j; #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchDeco) > sizeof (ArchDummy)) || (sizeof (ArchDecoDom) > sizeof (ArchDomDummy))) { errorPrint ("archDecoArchSave: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if (fprintf (stream, "1\n" ANUMSTRING "\t" ANUMSTRING "\n", /* Write number of domains */ (Anum) archptr->domtermnbr, (Anum) archptr->domvertnbr) == EOF) { errorPrint ("archDecoArchSave: bad output (1)"); return (1); } for (i = 0; i < archptr->domvertnbr; i ++) { /* Write domain array */ if (fprintf (stream, ANUMSTRING "\t" ANUMSTRING "\t" ANUMSTRING "\n", (Anum) archptr->domverttab[i].labl, (Anum) archptr->domverttab[i].size, (Anum) archptr->domverttab[i].wght) == EOF) { errorPrint ("archDecoArchSave: bad output (2)"); return (1); } } j = (archptr->domvertnbr * (archptr->domvertnbr - 1)) / 2; for (i = 0; i < j; i ++) { /* Write distance array */ if (fprintf (stream, ANUMSTRING "%c", (Anum) archptr->domdisttab[i], (((i % 8) == 7) && (i != (j - 1))) ? '\n' : '\t') == EOF) { errorPrint ("archDecoArchSave: bad output (3)"); return (1); } } return (0); } /* This function returns the smallest number ** of terminal domain included in the given ** domain. */ ArchDomNum archDecoDomNum ( const ArchDeco * const archptr, const ArchDecoDom * const domptr) { return (archptr->domverttab[domptr->num - 1].labl); } /* This function returns the terminal domain associated ** with the given terminal number in the architecture. ** It returns: ** - 0 : if label is valid and domain has been updated. ** - 1 : if label is invalid. ** - 2 : on error. */ int archDecoDomTerm ( const ArchDeco * const archptr, ArchDecoDom * const domptr, const ArchDomNum domnum) { Anum i, j; for (i = archptr->domtermnbr, j = archptr->domvertnbr - 1; (i > 0) && (j != (Anum) (-1)); j --) { if (archptr->domverttab[j].size == 1) { /* If terminal vertex */ i --; /* One more terminal scanned */ if (archptr->domverttab[j].labl == domnum) { /* If terminal domain number found */ domptr->num = j; /* Set domain number */ return (0); } } } return (1); /* Cannot set domain */ } /* This function returns the number of ** elements in the given domain. */ Anum archDecoDomSize ( const ArchDeco * const archptr, const ArchDecoDom * const domptr) { return (archptr->domverttab[domptr->num - 1].size); } /* This function returns the weight of ** the given domain. */ Anum archDecoDomWght ( const ArchDeco * const archptr, const ArchDecoDom * const domptr) { return (archptr->domverttab[domptr->num - 1].wght); } /* This function returns the average distance ** between two domains, which is extracted ** from the table. */ Anum archDecoDomDist ( const ArchDeco * const archptr, const ArchDecoDom * const dom0ptr, const ArchDecoDom * const dom1ptr) { return (archDecoArchDistE (archptr, dom0ptr->num, dom1ptr->num)); } /* This function sets the biggest ** domain available for this ** architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archDecoDomFrst ( const ArchDeco * const archptr, ArchDecoDom * restrict const domptr) { domptr->num = 1; return (0); } /* This routine reads domain information ** from the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archDecoDomLoad ( const ArchDeco * const archptr, ArchDecoDom * restrict const domptr, FILE * restrict const stream) { if ((intLoad (stream, &domptr->num) != 1) || (domptr->num < 1) || (domptr->num > archptr->domvertnbr)) { errorPrint ("archDecoDomLoad: bad input"); return (1); } return (0); } /* This routine saves domain information ** to the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archDecoDomSave ( const ArchDeco * const archptr, const ArchDecoDom * const domptr, FILE * restrict const stream) { if (fprintf (stream, ANUMSTRING " ", (Anum) domptr->num) == EOF) { errorPrint ("archDecoDomSave: bad output"); return (1); } return (0); } /* This function tries to split a ** decomposition domain into two ** subdomains. ** It returns: ** - 0 : if bipartitioning succeeded. ** - 1 : if bipartitioning could not be performed. ** - 2 : on error. */ int archDecoDomBipart ( const ArchDeco * const archptr, const ArchDecoDom * const domptr, ArchDecoDom * restrict const dom0ptr, ArchDecoDom * restrict const dom1ptr) { if (archptr->domverttab[domptr->num - 1].size <= 1) /* Return if cannot bipartition more */ return (1); dom0ptr->num = domptr->num * 2; /* Compute subdomain numbers from domain number */ dom1ptr->num = dom0ptr->num + 1; return (0); } /* This function creates the MPI_Datatype for ** decomposition-described domains. ** It returns: ** - 0 : if type could be created. ** - 1 : on error. */ #ifdef SCOTCH_PTSCOTCH int archDecoDomMpiType ( const ArchDeco * const archptr, MPI_Datatype * const typeptr) { *typeptr = ANUM_MPI; return (0); } #endif /* SCOTCH_PTSCOTCH */ scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_vw.c0000644000175300017530000001033611631334325023171 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_vw.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module outputs the state of the **/ /** current partition on the form of a **/ /** Scotch mapping file. **/ /** **/ /** DATES : # Version 4.0 : from : 18 may 2004 **/ /** to 18 may 2004 **/ /** # Version 5.1 : from : 11 aug 2010 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VGRAPH_SEPARATE_VW #include "module.h" #include "common.h" #include "gain.h" #include "graph.h" #include "vgraph.h" #include "vgraph_separate_vw.h" /* ** The static variables. */ static int vgraphseparatevwfilenum = 0; /* Number of file to output */ /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine outputs the mapping file. ** It returns: ** - 0 : if the file could be produced. ** - !0 : on error. */ int vgraphSeparateVw ( Vgraph * restrict const grafptr) /*+ Separation graph +*/ { char nametab[64]; /* File name */ FILE * restrict fileptr; Gnum vertnum; /* Vertex number */ sprintf (nametab, "vgraphseparatevw_output_%08d.map", vgraphseparatevwfilenum ++); if ((fileptr = fopen (nametab, "w+")) == NULL) { errorPrint ("vgraphSeparateVw: cannot open partition file"); return (1); } fprintf (fileptr, GNUMSTRING "\n", /* Output size of mapping; test if failure later, in main loop */ (Gnum) grafptr->s.vertnbr); for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { if (fprintf (fileptr, GNUMSTRING "\t%d\n", (Gnum) ((grafptr->s.vnumtax != NULL) ? grafptr->s.vnumtax[vertnum] : vertnum), (int) grafptr->parttax[vertnum]) <= 0) { errorPrint ("vgraphSeparateVw: bad output"); fclose (fileptr); return (1); } } return (0); } scotch-5.1.12b.dfsg/src/libscotch/mesh_check.c0000644000175300017530000002167311631334325021401 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mesh_check.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the source mesh **/ /** functions. **/ /** **/ /** DATES : # Version 4.0 : from : 29 dec 2001 **/ /** to 11 may 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MESH #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" /****************************************/ /* */ /* These routines handle source meshes. */ /* */ /****************************************/ /* This routine checks the consistency ** of the given mesh. ** It returns: ** - 0 : if mesh data are consistent. ** - !0 : on error. */ int meshCheck ( const Mesh * const meshptr) { Gnum vertnnd; /* Maximum vertex index */ Gnum vertnum; /* Number of current vertex */ Gnum veisnbr; /* Number of isolated element vertices */ Gnum velosum; /* Vertex element load sum */ Gnum vnlosum; /* Vertex node load sum */ Gnum degrmax; /* Maximum degree */ if ((meshptr->velmbas > meshptr->velmnnd) || (meshptr->vnodbas > meshptr->vnodnnd) || ((meshptr->velmnnd != meshptr->vnodbas) && (meshptr->vnodnnd != meshptr->velmbas))) { errorPrint ("meshCheck: invalid node and element numbers"); return (1); } vertnnd = meshptr->velmnbr + meshptr->vnodnbr + meshptr->baseval; degrmax = 0; veisnbr = 0; for (vertnum = meshptr->velmbas; vertnum < meshptr->velmnnd; vertnum ++) { /* For all element vertices */ Gnum degrval; Gnum edgenum; if ((meshptr->verttax[vertnum] < meshptr->baseval) || (meshptr->vendtax[vertnum] < meshptr->verttax[vertnum])) { errorPrint ("meshCheck: invalid vertex arrays (1)"); return (1); } degrval = meshptr->vendtax[vertnum] - meshptr->verttax[vertnum]; if (degrval > degrmax) degrmax = degrval; else if (degrval == 0) veisnbr ++; for (edgenum = meshptr->verttax[vertnum]; edgenum < meshptr->vendtax[vertnum]; edgenum ++) { Gnum vertend; /* Number of end vertex */ Gnum edgeend; /* Number of end vertex edge */ vertend = meshptr->edgetax[edgenum]; if ((vertend < meshptr->baseval) || (vertend >= vertnnd)) { /* If invalid edge end */ errorPrint ("meshCheck: invalid edge array (1)"); return (1); } if ((vertend >= meshptr->velmbas) && (vertend < meshptr->velmnnd)) { errorPrint ("meshCheck: element vertices must not be connected together"); return (1); } for (edgeend = meshptr->verttax[vertend]; /* Search for matching arc */ (edgeend < meshptr->vendtax[vertend]) && (meshptr->edgetax[edgeend] != vertnum); edgeend ++) ; if (edgeend >= meshptr->vendtax[vertend]) { errorPrint ("meshCheck: arc data do not match (1)"); return (1); } for (edgeend ++; /* Search for duplicate arcs */ (edgeend < meshptr->vendtax[vertend]) && (meshptr->edgetax[edgeend] != vertnum); edgeend ++) ; if (edgeend < meshptr->vendtax[vertend]) { errorPrint ("meshCheck: duplicate arc (1)"); return (1); } } } if (veisnbr != meshptr->veisnbr) { errorPrint ("meshCheck: invalid number of isolated element vertices (1)"); return (1); } for (vertnum = meshptr->vnodbas; vertnum < meshptr->vnodnnd; vertnum ++) { /* For all node vertices */ Gnum edgenum; if ((meshptr->verttax[vertnum] < meshptr->baseval) || (meshptr->vendtax[vertnum] < meshptr->verttax[vertnum])) { errorPrint ("meshCheck: invalid vertex arrays (2)"); return (1); } if ((meshptr->vendtax[vertnum] - meshptr->verttax[vertnum]) > degrmax) degrmax = meshptr->vendtax[vertnum] - meshptr->verttax[vertnum]; for (edgenum = meshptr->verttax[vertnum]; edgenum < meshptr->vendtax[vertnum]; edgenum ++) { Gnum vertend; /* Number of end vertex */ Gnum edgeend; /* Number of end vertex edge */ vertend = meshptr->edgetax[edgenum]; if ((vertend < meshptr->baseval) || (vertend >= vertnnd)) { /* If invalid edge end */ errorPrint ("meshCheck: invalid edge array (2)"); return (1); } if ((vertend >= meshptr->vnodbas) && (vertend < meshptr->vnodnnd)) { errorPrint ("meshCheck: node vertices must not be connected together"); return (1); } for (edgeend = meshptr->verttax[vertend]; /* Search for matching arc */ (edgeend < meshptr->vendtax[vertend]) && (meshptr->edgetax[edgeend] != vertnum); edgeend ++) ; if (edgeend >= meshptr->vendtax[vertend]) { errorPrint ("meshCheck: arc data do not match (2)"); return (1); } for (edgeend ++; /* Search for duplicate arcs */ (edgeend < meshptr->vendtax[vertend]) && (meshptr->edgetax[edgeend] != vertnum); edgeend ++) ; if (edgeend < meshptr->vendtax[vertend]) { errorPrint ("meshCheck: duplicate arc (2)"); return (1); } } } if (meshptr->velotax == NULL) /* Recompute node vertex load sum */ velosum = meshptr->velmnnd - meshptr->velmbas; else { for (vertnum = meshptr->velmbas, velosum = 0; vertnum < meshptr->velmnnd; vertnum ++) { if (meshptr->velotax[vertnum] < 1) { errorPrint ("meshCheck: invalid element vertex load"); return (1); } velosum += meshptr->velotax[vertnum]; } } if (velosum != meshptr->velosum) { errorPrint ("meshCheck: invalid element vertex load sum"); return (1); } if (meshptr->vnlotax == NULL) /* Recompute node vertex load sum */ vnlosum = meshptr->vnodnnd - meshptr->vnodbas; else { for (vertnum = meshptr->vnodbas, vnlosum = 0; vertnum < meshptr->vnodnnd; vertnum ++) { if (meshptr->vnlotax[vertnum] < 1) { errorPrint ("meshCheck: invalid node vertex load"); return (1); } vnlosum += meshptr->vnlotax[vertnum]; } } if (vnlosum != meshptr->vnlosum) { errorPrint ("meshCheck: invalid node vertex load sum"); return (1); } if (meshptr->degrmax < degrmax) { errorPrint ("meshCheck: invalid maximum degree"); return (1); } return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_random_f.c0000644000175300017530000000572611631334325022622 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_random_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the random generator handling routines **/ /** of the libSCOTCH library. **/ /** **/ /** DATES : # Version 4.0 : from : 21 nov 2005 **/ /** to 23 nov 2005 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the random handling routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFRANDOMRESET, scotchfrandomreset, (), \ ()) { SCOTCH_randomReset (); } scotch-5.1.12b.dfsg/src/libscotch/parser_ll.h0000644000175300017530000000634111631334325021273 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : parser_ll.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a static mapper. **/ /** These lines are the declarations for **/ /** the strategy strings lexical parser. **/ /** **/ /** DATES : # Version 3.1 : from : 07 nov 1995 **/ /** to 13 jun 1996 **/ /** # Version 3.2 : from : 03 oct 1996 **/ /** to 19 oct 1996 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 20 dec 2001 **/ /** to 20 dec 2001 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef PARSER_LL #define static #endif void stratParserInit (const char * const); static int stratParserInput (void); int stratParserLex (void); const char * stratParserRemain (void); void stratParserSelect (unsigned int); #undef static scotch-5.1.12b.dfsg/src/libscotch/arch_cmplt.h0000644000175300017530000001307311631334325021424 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_cmplt.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the complete graph target **/ /** architecture functions. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 12 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 30 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 24 jul 1995 **/ /** # Version 3.1 : from : 11 jun 1996 **/ /** to 11 jun 1996 **/ /** # Version 3.2 : from : 20 sep 1996 **/ /** to 13 may 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 09 jan 2004 **/ /** to 09 jan 2004 **/ /** # Version 5.1 : from : 19 jan 2008 **/ /** to 19 jan 2008 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ The complete graph definitions. +*/ typedef struct ArchCmplt_ { Anum numnbr; /*+ Number of vertices +*/ } ArchCmplt; typedef struct ArchCmpltDom_ { Anum nummin; /*+ Minimum vertex number +*/ Anum numnbr; /*+ Number of vertices +*/ } ArchCmpltDom; /* ** The function prototypes. */ #ifndef ARCH_CMPLT #define static #endif int archCmpltArchLoad (ArchCmplt * restrict const, FILE * restrict const); int archCmpltArchSave (const ArchCmplt * const, FILE * restrict const); #define archCmpltArchFree NULL ArchDomNum archCmpltDomNum (const ArchCmplt * const, const ArchCmpltDom * const); int archCmpltDomTerm (const ArchCmplt * const, ArchCmpltDom * restrict const, const ArchDomNum); Anum archCmpltDomSize (const ArchCmplt * const, const ArchCmpltDom * const); #define archCmpltDomWght archCmpltDomSize Anum archCmpltDomDist (const ArchCmplt * const, const ArchCmpltDom * const, const ArchCmpltDom * const); int archCmpltDomFrst (const ArchCmplt * const, ArchCmpltDom * const); int archCmpltDomLoad (const ArchCmplt * const, ArchCmpltDom * const, FILE * const); int archCmpltDomSave (const ArchCmplt * const, const ArchCmpltDom * const, FILE * const); int archCmpltDomBipart (const ArchCmplt * const, const ArchCmpltDom * const, ArchCmpltDom * restrict const, ArchCmpltDom * restrict const); #ifdef SCOTCH_PTSCOTCH int archCmpltDomMpiType (const ArchCmplt * const, MPI_Datatype * const); #endif /* SCOTCH_PTSCOTCH */ #undef static scotch-5.1.12b.dfsg/src/libscotch/bdgraph.h0000644000175300017530000001704511631334325020722 0ustar hazelscthazelsct/* Copyright 2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph.h **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for distributed edge bipartition- **/ /** ing routines. **/ /** **/ /** DATES : # Version 5.1 : from : 10 sep 2007 **/ /** to : 14 apr 2011 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ Graph option flags. +*/ #define BDGRAPHFREEFRON (DGRAPHBITSNOTUSED) /* Free part array */ #define BDGRAPHFREEPART (DGRAPHBITSNOTUSED << 1) /* Free frontier array */ #define BDGRAPHFREEVEEX (DGRAPHBITSNOTUSED << 2) /* Free external gain array */ /*+ Active graph structure. +*/ typedef struct Bdgraph_ { Dgraph s; /*+ Distributed source graph +*/ Gnum * veexloctax; /*+ Local vertex external gain array if moved to 1 +*/ Gnum veexglbsum; /*+ Global sum of veexloctax array cells +*/ GraphPart * partgsttax; /*+ Based local part array: 0,1: part +*/ Gnum * fronloctab; /*+ Array of local frontier vertex numbers +*/ Gnum fronlocnbr; /*+ Number of local frontier vertices +*/ Gnum fronglbnbr; /*+ Number of global frontier vertices +*/ Gnum complocload0; /*+ Local load of part 0 +*/ Gnum compglbload0; /*+ Global load of part 0 +*/ Gnum compglbload0min; /*+ Minimum allowed load in part 0 (strategy variable) +*/ Gnum compglbload0max; /*+ Maximum allowed load in part 0 (strategy variable) +*/ Gnum compglbload0avg; /*+ Global average load of part 0 +*/ Gnum compglbload0dlt; /*+ Load difference from the average +*/ Gnum complocsize0; /*+ Number of local vertices in part 0 +*/ Gnum compglbsize0; /*+ Number of global vertices in part 0 +*/ Gnum commglbload; /*+ Global communication load +*/ Gnum commglbgainextn; /*+ Global external gain if all swapped +*/ Gnum commglbloadextn0; /*+ Global communication load if all moved to part 0 +*/ Gnum commglbgainextn0; /*+ Global external gain if all swapped from part 0 +*/ Anum domdist; /*+ Distance between subdomains +*/ Anum domwght[2]; /*+ Weights for each subdomain +*/ INT levlnum; /*+ Graph coarsening level +*/ } Bdgraph; /*+ The distributed save graph structure. +*/ typedef struct BdgraphStore_ { Gnum fronlocnbr; /*+ Number of local frontier vertices +*/ Gnum fronglbnbr; /*+ Number of frontier vertices +*/ Gnum complocload0; /*+ Local load in part 0 +*/ Gnum compglbload0; /*+ Load in part 0 +*/ Gnum compglbload0dlt; /*+ Difference from the average +*/ Gnum complocsize0; /*+ Number of local vertices in part 0 +*/ Gnum compglbsize0; /*+ Number of global vertices in part 0 +*/ Gnum commglbload; Gnum commglbgainextn; byte * datatab; /*+ Variable-sized data array +*/ } BdgraphStore; /* ** The function prototypes. */ #ifndef BDGRAPH #define static #endif #ifdef DMAPPING_H int bdgraphInit (Bdgraph * const, const Dgraph * const, const Dgraph * const, const Arch * const, const ArchDom[]); #endif /* DMAPPING_H */ void bdgraphInit2 (Bdgraph * const, const Anum, const Anum, const Anum); #ifdef DMAPPING_H int bdgraphInit3 (Bdgraph * const, const Dgraph * const, const Dmapping * const, const ArchDom[]); #endif /* DMAPPING_H */ void bdgraphExit (Bdgraph * restrict const); void bdgraphFree (Bdgraph * restrict const); void bdgraphZero (Bdgraph * restrict const); int bdgraphCheck (const Bdgraph * restrict const); #ifdef BGRAPH_H int bdgraphGatherAll (const Bdgraph * restrict const, Bgraph * restrict); #endif /* BGRAPH_H */ int bdgraphStoreInit (const Bdgraph * const, BdgraphStore * const); void bdgraphStoreExit (BdgraphStore * const); void bdgraphStoreSave (const Bdgraph * const , BdgraphStore * const); void bdgraphStoreUpdt (Bdgraph * const, const BdgraphStore * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_bl.c0000644000175300017530000001234511631334325022425 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_bl.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module resizes block data using **/ /** the block splitting post-processing **/ /** algorithm. **/ /** **/ /** DATES : # Version 3.4 : from : 24 jun 2002 **/ /** to 24 jun 2002 **/ /** # Version 4.0 : from : 26 jun 2002 **/ /** to 17 mar 2005 **/ /** # Version 5.0 : from : 25 jul 2007 **/ /** to : 25 jul 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HGRAPH_ORDER_BL #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "order.h" #include "hgraph.h" #include "hgraph_order_bl.h" #include "hgraph_order_st.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hgraphOrderBl ( const Hgraph * restrict const grafptr, Order * restrict const ordeptr, const Gnum ordenum, /*+ Zero-based ordering number +*/ OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ const HgraphOrderBlParam * restrict const paraptr) { Gnum cblknbr; /* Number of old column blocks before splitting */ Gnum cblknum; /* Number of current column block */ if (paraptr->cblkmin <= 0) { errorPrint ("hgraphOrderBl: invalid minimum block size"); return (1); } if (hgraphOrderSt (grafptr, ordeptr, ordenum, cblkptr, paraptr->strat) != 0) /* Perform ordering strategy */ return (1); if (cblkptr->cblktab == NULL) { /* If single column block */ if (cblkptr->vnodnbr < (2 * paraptr->cblkmin)) /* If block cannot be split */ return (0); cblknbr = cblkptr->vnodnbr / paraptr->cblkmin; /* Get new number of blocks */ if ((cblkptr->cblktab = (OrderCblk *) memAlloc (cblknbr * sizeof (OrderCblk))) == NULL) { errorPrint ("hgraphOrderBl: out of memory"); return (1); } ordeptr->treenbr += cblknbr; /* These more number of tree nodes */ ordeptr->cblknbr += cblknbr - 1; /* These more number of column blocks */ cblkptr->cblknbr = cblknbr; for (cblknum = 0; cblknum < cblknbr; cblknum ++) { cblkptr->cblktab[cblknum].typeval = ORDERCBLKOTHR; cblkptr->cblktab[cblknum].vnodnbr = ((cblkptr->vnodnbr + cblknbr - 1) - cblknum) / cblknbr; cblkptr->cblktab[cblknum].cblknbr = 0; cblkptr->cblktab[cblknum].cblktab = NULL; } } else { /* Block already partitioned */ for (cblknum = 0; cblknum < cblkptr->cblknbr; cblknum ++) { if (hgraphOrderBl (grafptr, ordeptr, ordenum, cblkptr->cblktab + cblknum, paraptr) != 0) return (1); } } return (0); } scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_ex.h0000644000175300017530000000723611631334325022614 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_ex.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the exact-balance post-processing **/ /** module. **/ /** **/ /** DATES : # Version 2.0 : from : 25 oct 1994 **/ /** to 26 oct 1994 **/ /** # Version 3.0 : from : 18 nov 1995 **/ /** to 20 nov 1995 **/ /** # Version 3.1 : from : 20 nov 1995 **/ /** to 20 nov 1995 **/ /** # Version 3.2 : from : 15 sep 1996 **/ /** to 13 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 11 dec 2003 **/ /** to 11 dec 2003 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ System-defined constants. +*/ #define BGRAPHBIPARTEXGAINTABLSUBBITS 1 #define BGRAPHBIPARTEXSTATEFREE ((GainLink *) 0) /*+ Vertex in initial state (TRICK: must be 0) +*/ #define BGRAPHBIPARTEXSTATEUSED ((GainLink *) 1) /*+ Swapped vertex +*/ #define BGRAPHBIPARTEXSTATELINK ((GainLink *) 2) /*+ Currently in gain table if higher +*/ /* ** The function prototypes. */ #ifndef BGRAPH_BIPART_EX #define static #endif int bgraphBipartEx (Bgraph * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/bdgraph_bipart_zr.c0000644000175300017530000000663211631334325022771 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_bipart_zr.c **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** **/ /** FUNCTION : This module moves all of the vertices **/ /** to the first subdomain of the **/ /** bipartition. **/ /** **/ /** DATES : # Version 5.1 : from : 10 sep 2007 **/ /** to 26 oct 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BDGRAPH_BIPART_ZR #include "module.h" #include "common.h" #include "arch.h" #include "dgraph.h" #include "bdgraph.h" #include "bdgraph_bipart_zr.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine moves all of the graph vertices ** to the first part of the partition. ** It returns: ** - 0 : if the bipartitioning could be computed. ** - !0 : on error. */ int bdgraphBipartZr ( Bdgraph * const grafptr) /*+ Active graph +*/ { if (grafptr->compglbload0 != grafptr->s.veloglbsum) /* If not all vertices already in part zero */ bdgraphZero (grafptr); #ifdef SCOTCH_DEBUG_BDGRAPH2 if (bdgraphCheck (grafptr) != 0) { errorPrint ("bdgraphBipartZr: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/mapping_io.h0000644000175300017530000001120111631334325021421 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mapping_io.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the declarations for **/ /** the mapping handling routines. **/ /** **/ /** DATES : # Version 0.0 : from : 15 dec 1992 **/ /** to 01 apr 1993 **/ /** # Version 1.0 : from : 04 oct 1993 **/ /** to 06 oct 1993 **/ /** # Version 1.1 : from : 15 oct 1993 **/ /** to 15 oct 1993 **/ /** # Version 1.3 : from : 09 apr 1994 **/ /** to 11 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 02 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to 18 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 04 jul 1995 **/ /** # Version 3.1 : from : 30 oct 1995 **/ /** to 06 jun 1996 **/ /** # Version 3.2 : from : 23 aug 1996 **/ /** to 26 may 1998 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to 30 mar 1999 **/ /** # Version 4.0 : from : 11 dec 2001 **/ /** to 13 nov 2005 **/ /** # Version 5.0 : from : 13 sep 2006 **/ /** to 13 sep 2006 **/ /** **/ /************************************************************/ #define MAPPING_H /* ** The defines. */ /*+ Ordering option flags. +*/ #define MAPNONE 0x0000 /* No options set */ #define MAPFREEPART 0x0001 /* Free partition array */ /* ** The type definitions. */ /*+ This structure defines a source label to target label mapping element. +*/ typedef struct MappingLoadMap_ { Gnum slblnum; /*+ Source graph vertex label: FIRST +*/ Gnum tlblnum; /*+ Target architecture vertex label +*/ } MappingLoadMap; /*+ The source graph sort structure, used to sort vertices by increasing label value. +*/ typedef struct MappingLoadPerm { Gnum vlblnum; /*+ Vertex label: FIRST +*/ Gnum vertnum; /*+ Vertex number +*/ } MappingLoadPerm; scotch-5.1.12b.dfsg/src/libscotch/hdgraph_fold.c0000644000175300017530000012345711631334325021734 0ustar hazelscthazelsct/* Copyright 2007-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph_fold.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the halo distribu- **/ /** ted graph folding function. **/ /** **/ /** DATES : # Version 5.0 : from : 23 apr 2006 **/ /** to : 10 sep 2007 **/ /** # Version 5.1 : from : 27 jun 2008 **/ /** to : 04 jan 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HDGRAPH #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_fold_comm.h" #include "hdgraph.h" #include "hdgraph_fold.h" /******************************/ /* */ /* These routines handle halo */ /* distributed source graphs. */ /* */ /******************************/ /* This routine builds a folded graph by ** merging graph data to the processes of ** the first half or to the second half ** of the communicator. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int hdgraphFold ( const Hdgraph * restrict const orggrafptr, const int partval, /* 0 for first half, 1 for second half */ Hdgraph * restrict const fldgrafptr) { int fldprocglbnbr; int fldproclocnum; /* Index of local process in folded communicator */ int fldproccol; /* Color of receiver or not wanted in communicator */ MPI_Comm fldproccomm; /* Communicator of folded part */ fldprocglbnbr = (orggrafptr->s.procglbnbr + 1) / 2; if (partval == 1) { fldproclocnum = orggrafptr->s.proclocnum - fldprocglbnbr; fldprocglbnbr = orggrafptr->s.procglbnbr - fldprocglbnbr; } else fldproclocnum = orggrafptr->s.proclocnum; fldproccol = ((fldproclocnum >= 0) && (fldproclocnum < fldprocglbnbr)) ? 0 : MPI_UNDEFINED; if (MPI_Comm_split (orggrafptr->s.proccomm, fldproccol, fldproclocnum, &fldproccomm) != MPI_SUCCESS) { errorPrint ("hdgraphFold: communication error"); return (1); } return (hdgraphFold2 (orggrafptr, partval, fldgrafptr, fldproccomm)); } int hdgraphFold2 ( const Hdgraph * restrict const orggrafptr, const int partval, /* 0 for first half, 1 for second half */ Hdgraph * restrict const fldgrafptr, MPI_Comm fldproccomm) /* Pre-computed communicator */ { int fldcommtypval; /* Type of communication for this process */ DgraphFoldCommData * restrict fldcommdattab; /* Array of two communication data */ Gnum * restrict fldcommvrttab; /* Starting global send indices of communications */ Gnum * restrict fldvertidxtab; /* Start indices of vertex arrays */ Gnum * restrict fldvendidxtab; /* Adjustment value for end vertex arrays */ Gnum * restrict fldedgeidxtab; /* Start indices of edge arrays */ Gnum * restrict fldedgecnttab; /* Number of edges exchanged during each communication */ Gnum fldvertlocnbr; /* Number of vertices in local folded part */ Gnum fldedgelocsiz; /* (Upper bound of) number of edges in folded graph */ int fldprocglbnbr; int fldproclocnum; /* Index of local process in folded communicator */ int fldvertadjnbr; Gnum * restrict fldvertadjtab; /* Array of index adjustments for original vertices */ Gnum * restrict fldvertdlttab; /* Array of index adjustments for original vertices */ Gnum * restrict fldvhalloctax; /* Index array for remote halo vertex renumbering */ int cheklocval; int chekglbval; int commmax; int commnbr; int requnbr; MPI_Request * restrict requtab; #ifdef SCOTCH_DEBUG_HDGRAPH2 if (orggrafptr->vhndloctax != (orggrafptr->s.vertloctax + 1)) { errorPrint ("hdgraphFold2: halo graph must be compact"); return (1); } if (orggrafptr->s.vendloctax < (orggrafptr->s.vertloctax + orggrafptr->s.vertlocnbr)) { /* MPI_Isend calls should not overlap */ errorPrint ("hdgraphFold2: halo graph must have distinct arrays"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ fldprocglbnbr = (orggrafptr->s.procglbnbr + 1) / 2; if (partval == 1) { fldproclocnum = orggrafptr->s.proclocnum - fldprocglbnbr; fldprocglbnbr = orggrafptr->s.procglbnbr - fldprocglbnbr; } else fldproclocnum = orggrafptr->s.proclocnum; fldcommtypval = ((fldproclocnum >= 0) && (fldproclocnum < fldprocglbnbr)) ? DGRAPHFOLDCOMMRECV : DGRAPHFOLDCOMMSEND; cheklocval = 0; fldvertidxtab = NULL; fldcommdattab = NULL; if (fldcommtypval == DGRAPHFOLDCOMMRECV) { /* If we are going to receive */ #ifdef SCOTCH_DEBUG_HDGRAPH2 if (fldgrafptr == NULL) { errorPrint ("hdgraphFold2: invalid parameters (1)"); return (1); } if (fldproccomm == MPI_COMM_NULL) { errorPrint ("hdgraphFold2: invalid parameters (2)"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ memSet (fldgrafptr, 0, sizeof (Hdgraph)); /* Pre-initialize graph fields */ fldgrafptr->s.proccomm = fldproccomm; fldgrafptr->s.procglbnbr = fldprocglbnbr; fldgrafptr->s.proclocnum = fldproclocnum; fldgrafptr->s.flagval = DGRAPHFREEALL | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; /* For premature freeing on error; do not free vhndloctab as it is grouped with vertloctab */ if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ &fldgrafptr->s.procdsptab, (size_t) ((fldprocglbnbr + 1) * sizeof (Gnum)), &fldgrafptr->s.proccnttab, (size_t) (fldprocglbnbr * sizeof (Gnum)), &fldgrafptr->s.procngbtab, (size_t) (fldprocglbnbr * sizeof (int)), &fldgrafptr->s.procrcvtab, (size_t) (fldprocglbnbr * sizeof (int)), &fldgrafptr->s.procsndtab, (size_t) (fldprocglbnbr * sizeof (int)), NULL) == NULL) { errorPrint ("hdgraphFold2: out of memory (1)"); cheklocval = 1; } else if (dgraphFoldComm (&orggrafptr->s, partval, &commmax, &fldcommtypval, &fldcommdattab, &fldcommvrttab, /* Process can become a sender receiver */ fldgrafptr->s.proccnttab, &fldvertadjnbr, &fldvertadjtab, &fldvertdlttab) != 0) { errorPrint ("hdgraphFold2: cannot compute folding communications (1)"); cheklocval = 1; } else { Gnum fldvelolocnbr; if ((fldcommtypval & DGRAPHFOLDCOMMSEND) == 0) { /* If process is a normal receiver */ int i; for (i = 0, fldvertlocnbr = orggrafptr->s.vertlocnbr; (i < commmax) && (fldcommdattab[i].procnum != -1); i ++) fldvertlocnbr += fldcommdattab[i].vertnbr; commnbr = i; fldedgelocsiz = orggrafptr->s.edgelocsiz + orggrafptr->s.edgeglbsmx * i; /* Upper bound on local edges (degree useless since only for non-halo vertices) */ } else { /* Process is a sender receiver */ fldvertlocnbr = fldcommvrttab[0] - orggrafptr->s.procvrttab[orggrafptr->s.proclocnum]; /* Communications will remove vertices */ fldedgelocsiz = orggrafptr->s.vertloctax[fldvertlocnbr + orggrafptr->s.baseval] - orggrafptr->s.baseval; /* Exact number of edges */ fldgrafptr->s.edgelocsiz = fldedgelocsiz; } fldvelolocnbr = (orggrafptr->s.veloloctax != NULL) ? fldvertlocnbr : 0; if (memAllocGroup ((void **) (void *) /* Allocate distributed graph public data */ &fldgrafptr->s.vertloctax, (size_t) ((fldvertlocnbr + 1) * sizeof (Gnum)), &fldgrafptr->s.vendloctax, (size_t) ( fldvertlocnbr * sizeof (Gnum)), /* Vertex end array for non-halo vertices */ &fldgrafptr->s.vnumloctax, (size_t) ( fldvertlocnbr * sizeof (Gnum)), &fldgrafptr->s.veloloctax, (size_t) ( fldvelolocnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("hdgraphFold2: out of memory (2)"); cheklocval = 1; } else if (fldgrafptr->s.vertloctax -= orggrafptr->s.baseval, fldgrafptr->s.vendloctax -= orggrafptr->s.baseval, fldgrafptr->s.vnumloctax -= orggrafptr->s.baseval, fldgrafptr->s.veloloctax = ((orggrafptr->s.veloloctax != NULL) ? fldgrafptr->s.veloloctax - orggrafptr->s.baseval : NULL), memAllocGroup ((void **) (void *) &fldgrafptr->s.edgeloctax, (size_t) (fldedgelocsiz * sizeof (Gnum)), &fldvhalloctax, (size_t) (orggrafptr->s.edgeglbsmx * sizeof (Gnum)), NULL) == NULL) { errorPrint ("hdgraphFold2: out of memory (3)"); cheklocval = 1; } else { fldgrafptr->s.edgeloctax -= orggrafptr->s.baseval; fldvhalloctax -= orggrafptr->s.baseval; } } } else { /* Process is a sender */ #ifdef SCOTCH_DEBUG_HDGRAPH2 if (fldproccomm != MPI_COMM_NULL) { errorPrint ("hdgraphFold2: invalid parameters (3)"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ if (dgraphFoldComm (&orggrafptr->s, partval, &commmax, &fldcommtypval, &fldcommdattab, &fldcommvrttab, NULL, NULL, NULL, NULL) != 0) { errorPrint ("hdgraphFold2: cannot compute folding communications (2)"); cheklocval = 1; } } if ((cheklocval == 0) && (memAllocGroup ((void **) (void *) /* Allocate folding data */ &fldvertidxtab, (size_t) (commmax * sizeof (Gnum)), &fldvendidxtab, (size_t) (commmax * sizeof (Gnum)), &fldedgeidxtab, (size_t) (commmax * sizeof (Gnum)), &fldedgecnttab, (size_t) (commmax * sizeof (Gnum)), &requtab, (size_t) (commmax * HDGRAPHFOLDTAGNBR * sizeof (MPI_Request)), NULL) == NULL)) { errorPrint ("hdgraphFold2: out of memory (4)"); cheklocval = 1; } #ifdef SCOTCH_DEBUG_HDGRAPH1 /* Communication cannot be merged with a useful one */ if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, orggrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (1)"); chekglbval = 1; } #else /* SCOTCH_DEBUG_HDGRAPH1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_HDGRAPH1 */ if (chekglbval != 0) { if ((fldcommtypval & DGRAPHFOLDCOMMRECV) != 0) { hdgraphExit (fldgrafptr); if (fldvertidxtab != NULL) memFree (fldvertidxtab); /* Free group leaders */ if (fldcommdattab != NULL) memFree (fldcommdattab); } return (1); } requnbr = 0; /* Communications without further processing are placed at beginning of array */ if ((fldcommtypval & DGRAPHFOLDCOMMSEND) != 0) { /* If process is (also) a sender */ Gnum vertsndbas; Gnum vertsndnbr; int i; vertsndnbr = ((fldcommtypval & DGRAPHFOLDCOMMRECV) != 0) ? (fldcommvrttab[0] - orggrafptr->s.procvrttab[orggrafptr->s.proclocnum]) : 0; /* If process is also a receiver, start sending after kept vertices */ for (i = 0, requnbr = 0, vertsndbas = orggrafptr->s.baseval; /* For all send communications to perform */ (i < commmax) && (fldcommdattab[i].procnum != -1); i ++) { Gnum edgelocsiz; vertsndbas += vertsndnbr; vertsndnbr = fldcommdattab[i].vertnbr; edgelocsiz = orggrafptr->s.vertloctax[vertsndbas + vertsndnbr] - orggrafptr->s.vertloctax[vertsndbas]; /* Graph is compact */ fldvertidxtab[i] = vertsndbas; fldedgeidxtab[i] = orggrafptr->s.vertloctax[vertsndbas]; fldedgecnttab[i] = edgelocsiz; if (MPI_Isend (&edgelocsiz, 1, GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGVLBLLOCTAB, orggrafptr->s.proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (2)"); cheklocval = 1; } } commnbr = i; for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { if (MPI_Isend (orggrafptr->s.vertloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGVERTLOCTAB, orggrafptr->s.proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (3)"); cheklocval = 1; } } for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { if (MPI_Isend (orggrafptr->s.vendloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGVENDLOCTAB, orggrafptr->s.proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (4)"); cheklocval = 1; } } for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { if (MPI_Isend (orggrafptr->s.edgeloctax + fldedgeidxtab[i], fldedgecnttab[i], GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGEDGELOCTAB, orggrafptr->s.proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (5)"); cheklocval = 1; } } for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { Gnum vertsndbas; int vertsndnbr; int procsndnum; /* Rank of process to send to */ vertsndbas = fldvertidxtab[i]; vertsndnbr = (int) fldcommdattab[i].vertnbr; procsndnum = (int) fldcommdattab[i].procnum; if ((orggrafptr->s.veloloctax != NULL) && (MPI_Isend (orggrafptr->s.veloloctax + vertsndbas, vertsndnbr, GNUM_MPI, procsndnum, TAGFOLD + TAGVELOLOCTAB, orggrafptr->s.proccomm, &requtab[requnbr ++]) != MPI_SUCCESS)) { errorPrint ("hdgraphFold2: communication error (6)"); cheklocval = 1; } else if ((orggrafptr->s.vnumloctax != NULL) && (MPI_Isend (orggrafptr->s.vnumloctax + vertsndbas, vertsndnbr, GNUM_MPI, procsndnum, TAGFOLD + TAGVNUMLOCTAB, orggrafptr->s.proccomm, &requtab[requnbr ++]) != MPI_SUCCESS)) { errorPrint ("hdgraphFold2: communication error (7)"); cheklocval = 1; } } /* Communications of sender-receivers will be completed in the receiving phase */ } if ((fldcommtypval & DGRAPHFOLDCOMMRECV) != 0) { /* If process is (also) a receiver */ Gnum orgvertlocnbr; Gnum orgvertlocnnd; Gnum fldvertlocadj; Gnum fldvelolocsum; Gnum fldedgelocnum; Gnum fldvhallocnum; Gnum fldehallocnbr; int fldprocnum; int i; const Gnum * restrict const orgvertloctax = orggrafptr->s.vertloctax; const Gnum * restrict const orgvendloctax = orggrafptr->s.vendloctax; const Gnum * restrict const orgedgeloctax = orggrafptr->s.edgeloctax; fldgrafptr->s.procvrttab = fldgrafptr->s.procdsptab; /* Graph does not have holes */ fldgrafptr->s.procdsptab[0] = orggrafptr->s.baseval; /* Build private data of folded graph and array */ for (fldprocnum = 0; fldprocnum < fldprocglbnbr; fldprocnum ++) /* New subdomain indices start from baseval */ fldgrafptr->s.procdsptab[fldprocnum + 1] = fldgrafptr->s.procdsptab[fldprocnum] + fldgrafptr->s.proccnttab[fldprocnum]; if ((fldcommtypval & DGRAPHFOLDCOMMSEND) == 0) { /* If process is a normal receiver */ Gnum orgvertlocmin; Gnum orgvertlocmax; Gnum fldvertlocnum; Gnum fldedgelocbas; Gnum fldvertrcvbas; Gnum fldvertrcvnbr; int procngbmin; int procngbmax; Gnum * restrict const fldedgeloctax = fldgrafptr->s.edgeloctax; for (i = 0, fldvertrcvbas = orggrafptr->s.vertlocnnd, fldvertrcvnbr = 0; /* For all receive communications to perform */ (i < commnbr) && (cheklocval == 0); i ++) { fldvertrcvbas += fldvertrcvnbr; fldvertrcvnbr = fldcommdattab[i].vertnbr; fldvertidxtab[i] = fldvertrcvbas; if (MPI_Irecv (&fldedgecnttab[i], 1, GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGVLBLLOCTAB, orggrafptr->s.proccomm, &requtab[HDGRAPHFOLDTAGENBR * commmax + i]) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (8)"); cheklocval = 1; } } for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { /* Let these communications progress while we process the edge size messages */ if (MPI_Irecv (fldgrafptr->s.vertloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGVERTLOCTAB, orggrafptr->s.proccomm, &requtab[HDGRAPHFOLDTAGVERT * commmax + i]) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (9)"); cheklocval = 1; } } for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { if (MPI_Irecv (fldgrafptr->s.vendloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGVENDLOCTAB, orggrafptr->s.proccomm, &requtab[HDGRAPHFOLDTAGVEND * commmax + i]) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (10)"); cheklocval = 1; } } MPI_Waitall (commnbr, &requtab[HDGRAPHFOLDTAGENBR * commmax], MPI_STATUSES_IGNORE); for (i = 0, fldedgelocbas = orggrafptr->s.vertloctax[orggrafptr->s.vertlocnnd]; (i < commnbr) && (cheklocval == 0); i ++) { fldedgeidxtab[i] = fldedgelocbas; fldedgelocbas += fldedgecnttab[i]; if (MPI_Irecv (fldedgeloctax + fldedgeidxtab[i], fldedgecnttab[i], GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGEDGELOCTAB, orggrafptr->s.proccomm, &requtab[HDGRAPHFOLDTAGEDGE * commmax + i]) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (11)"); cheklocval = 1; } } fldgrafptr->s.edgelocsiz = fldedgelocbas - orggrafptr->s.baseval; /* Get number of local and halo edges */ if (orggrafptr->s.veloloctax != NULL) { for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { if (MPI_Irecv (fldgrafptr->s.veloloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGVELOLOCTAB, orggrafptr->s.proccomm, &requtab[HDGRAPHFOLDTAGVELO * commmax + i]) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (12)"); cheklocval = 1; } } } if (orggrafptr->s.vnumloctax != NULL) { for (i = 0; (i < commnbr) && (cheklocval == 0); i ++) { if (MPI_Irecv (fldgrafptr->s.vnumloctax + fldvertidxtab[i], fldcommdattab[i].vertnbr, GNUM_MPI, fldcommdattab[i].procnum, TAGFOLD + TAGVNUMLOCTAB, orggrafptr->s.proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (13)"); cheklocval = 1; } } } orgvertlocnbr = orggrafptr->s.vertlocnbr; /* Process all local vertices */ orgvertlocnnd = orggrafptr->s.vertlocnnd; if (orggrafptr->s.vnumloctax == NULL) { /* If original graph does not have vertex numbers, create remote parts of vertex number array */ Gnum fldvertlocnum; Gnum fldvertlocadj; int i; Gnum * restrict const fldvnumloctax = fldgrafptr->s.vnumloctax; for (i = 0, fldvertlocnum = orgvertlocnnd; i < commnbr; i ++) { Gnum fldvertlocnnd; for (fldvertlocnnd = fldvertlocnum + fldcommdattab[i].vertnbr, fldvertlocadj = fldcommvrttab[i]; fldvertlocnum < fldvertlocnnd; fldvertlocnum ++) fldvnumloctax[fldvertlocnum] = fldvertlocadj ++; } } for (procngbmin = 0, procngbmax = fldvertadjnbr; /* Initialize search accelerator */ procngbmax - procngbmin > 1; ) { int procngbmed; procngbmed = (procngbmax + procngbmin) / 2; if (fldvertadjtab[procngbmed] <= orggrafptr->s.procvrttab[orggrafptr->s.proclocnum]) procngbmin = procngbmed; else procngbmax = procngbmed; } orgvertlocmin = fldvertadjtab[procngbmin]; orgvertlocmax = fldvertadjtab[procngbmax]; fldvertlocadj = fldvertdlttab[procngbmin]; for (fldvertlocnum = fldedgelocnum = orggrafptr->s.baseval; /* Adjust local part of edge array */ fldvertlocnum < orgvertlocnnd; ) { for ( ; fldedgelocnum < orgvendloctax[fldvertlocnum]; fldedgelocnum ++) { /* Reorder end vertices */ Gnum orgvertlocend; #ifdef SCOTCH_DEBUG_HDGRAPH2 if (fldedgelocnum >= (fldgrafptr->s.edgelocsiz + orggrafptr->s.baseval)) { errorPrint ("hdgraphFold2: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ orgvertlocend = orgedgeloctax[fldedgelocnum]; if ((orgvertlocend >= orgvertlocmin) && /* If end vertex is local */ (orgvertlocend < orgvertlocmax)) fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertlocadj; else { /* End vertex is not local */ int procngbmin; int procngbmax; for (procngbmin = 0, procngbmax = fldvertadjnbr; procngbmax - procngbmin > 1; ) { int procngbnum; procngbnum = (procngbmax + procngbmin) / 2; if (fldvertadjtab[procngbnum] <= orgvertlocend) procngbmin = procngbnum; else procngbmax = procngbnum; } fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertdlttab[procngbmin]; } } fldvertlocnum ++; for ( ; fldedgelocnum < orgvertloctax[fldvertlocnum]; fldedgelocnum ++) { /* Copy halo part as is */ #ifdef SCOTCH_DEBUG_HDGRAPH2 if ((orgedgeloctax[fldedgelocnum] < orggrafptr->s.baseval) || (orgedgeloctax[fldedgelocnum] >= (orggrafptr->vhallocnbr + orggrafptr->s.baseval))) { errorPrint ("hdgraphFold2: internal error (2)"); return (1); } if (fldedgelocnum >= (fldgrafptr->s.edgelocsiz + orggrafptr->s.baseval)) { errorPrint ("hdgraphFold2: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ fldedgeloctax[fldedgelocnum] = orgedgeloctax[fldedgelocnum]; } } fldvelolocsum = orggrafptr->s.velolocsum; /* In case there are vertex loads, we keep all of existing load */ fldehallocnbr = orggrafptr->ehallocnbr; /* Normal receivers have at least all of their local halo vertices */ fldvhallocnum = orggrafptr->vhallocnbr + orggrafptr->s.baseval; /* Index of next halo vertex number to assign */ } else { /* Receiver process is also a sender */ Gnum orgvertlocmin; Gnum orgvertlocmax; Gnum fldvertlocnum; Gnum fldvertlocadj; Gnum fldvhallocmax; /* Maximum current size of halo vertex array */ int procngbmin; int procngbmax; Gnum * restrict const fldedgeloctax = fldgrafptr->s.edgeloctax; orgvertlocnbr = fldvertlocnbr; /* Process only remaining local vertices */ orgvertlocnnd = fldvertlocnbr + orggrafptr->s.baseval; for (procngbmin = 0, procngbmax = fldvertadjnbr; /* Initialize search accelerator */ procngbmax - procngbmin > 1; ) { int procngbmed; procngbmed = (procngbmax + procngbmin) / 2; if (fldvertadjtab[procngbmed] <= orggrafptr->s.procvrttab[orggrafptr->s.proclocnum]) procngbmin = procngbmed; else procngbmax = procngbmed; } orgvertlocmin = fldvertadjtab[procngbmin]; orgvertlocmax = fldvertadjtab[procngbmax]; fldvertlocadj = fldvertdlttab[procngbmin]; fldvhallocmax = orggrafptr->s.baseval - 1; /* Reset halo vertex array for local part as halo vertices may have disappeared */ fldehallocnbr = 0; /* Recount all remaining halo vertices and edges */ fldvhallocnum = orggrafptr->s.baseval; for (fldvertlocnum = fldedgelocnum = orggrafptr->s.baseval; /* Copy remaining local part of edge array */ fldvertlocnum < orgvertlocnnd; ) { for ( ; fldedgelocnum < orgvendloctax[fldvertlocnum]; fldedgelocnum ++) { /* Reorder end vertices */ Gnum orgvertlocend; #ifdef SCOTCH_DEBUG_HDGRAPH2 if (fldedgelocnum >= (fldgrafptr->s.edgelocsiz + orggrafptr->s.baseval)) { errorPrint ("hdgraphFold2: internal error (4)"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ orgvertlocend = orgedgeloctax[fldedgelocnum]; if ((orgvertlocend >= orgvertlocmin) && /* If end vertex is local */ (orgvertlocend < orgvertlocmax)) fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertlocadj; else { /* End vertex is not local */ int procngbnum; int procngbmax; for (procngbnum = 0, procngbmax = fldvertadjnbr; procngbmax - procngbnum > 1; ) { int procngbmed; procngbmed = (procngbmax + procngbnum) / 2; if (fldvertadjtab[procngbmed] <= orgvertlocend) procngbnum = procngbmed; else procngbmax = procngbmed; } fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertdlttab[procngbnum]; } } fldvertlocnum ++; fldehallocnbr += orgvertloctax[fldvertlocnum] - fldedgelocnum; for ( ; fldedgelocnum < orgvertloctax[fldvertlocnum]; fldedgelocnum ++) { /* Renumber halo part */ Gnum orgverthalend; Gnum fldvhallocend; orgverthalend = orgedgeloctax[fldedgelocnum]; #ifdef SCOTCH_DEBUG_HDGRAPH2 if ((orgverthalend < orggrafptr->s.baseval) || (orgverthalend >= (orggrafptr->vhallocnbr + orggrafptr->s.baseval)) || (fldedgelocnum >= (fldgrafptr->s.edgelocsiz + orggrafptr->s.baseval))) { errorPrint ("hdgraphFold2: internal error (5)"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ while (fldvhallocmax < orgverthalend) /* Expand halo vertex index array whenever necessary */ fldvhalloctax[++ fldvhallocmax] = ~0; fldvhallocend = fldvhalloctax[orgverthalend]; /* Get renumbered halo vertex */ if (fldvhallocend < 0) { /* If new halo vertex not yet given */ fldvhallocend = /* Allocate it */ fldvhalloctax[orgverthalend] = fldvhallocnum ++; } fldedgeloctax[fldedgelocnum] = fldvhallocend; } } if (orggrafptr->s.veloloctax != NULL) { /* If original graph has vertex loads */ Gnum fldvertlocnum; for (fldvertlocnum = orggrafptr->s.baseval, fldvelolocsum = 0; /* Accumulate load sum of remaining part */ fldvertlocnum < orgvertlocnnd; fldvertlocnum ++) fldvelolocsum += orggrafptr->s.veloloctax[fldvertlocnum]; } commnbr = 0; /* Turn sender-receiver into normal receiver without any communications to perform */ } if (orggrafptr->s.veloloctax != NULL) /* If original graph has vertex loads */ memCpy (fldgrafptr->s.veloloctax + orggrafptr->s.baseval, /* Copy local part of vertex load array */ orggrafptr->s.veloloctax + orggrafptr->s.baseval, orgvertlocnbr * sizeof (Gnum)); if (orggrafptr->s.vnumloctax != NULL) /* If original graph has vertex numbers */ memCpy (fldgrafptr->s.vnumloctax + orggrafptr->s.baseval, /* Copy local part of vertex number array */ orggrafptr->s.vnumloctax + orggrafptr->s.baseval, orgvertlocnbr * sizeof (Gnum)); else { /* Build local part of vertex number array */ Gnum fldvertlocnum; Gnum fldvertlocadj; for (fldvertlocnum = orggrafptr->s.baseval, fldvertlocadj = orggrafptr->s.procvrttab[orggrafptr->s.proclocnum]; fldvertlocnum < orgvertlocnnd; fldvertlocnum ++) fldgrafptr->s.vnumloctax[fldvertlocnum] = fldvertlocadj ++; } memCpy (fldgrafptr->s.vertloctax + orggrafptr->s.baseval, /* Copy local part of vertex arrays, since they are compact */ orggrafptr->s.vertloctax + orggrafptr->s.baseval, orgvertlocnbr * sizeof (Gnum)); /* Last value not copied */ fldgrafptr->s.vertloctax[fldvertlocnbr + orggrafptr->s.baseval] = fldgrafptr->s.edgelocsiz + orggrafptr->s.baseval; memCpy (fldgrafptr->s.vendloctax + orggrafptr->s.baseval, orggrafptr->s.vendloctax + orggrafptr->s.baseval, orgvertlocnbr * sizeof (Gnum)); for (i = 0; i < commnbr; i ++) { int j; if (MPI_Waitany (commnbr, &requtab[HDGRAPHFOLDTAGVERT * commmax], &j, MPI_STATUS_IGNORE) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (14)"); cheklocval = 1; } else { /* Adjust first remote part of vertex array */ Gnum fldvertlocnum; Gnum fldvertlocnnd; Gnum fldvertlocadj; Gnum * restrict const fldvertloctax = fldgrafptr->s.vertloctax; fldvertlocnum = fldvertidxtab[j]; fldvertlocadj = fldedgeidxtab[j] - fldgrafptr->s.vertloctax[fldvertlocnum]; fldvendidxtab[j] = fldvertlocadj; /* Record updated adjust value for vendloctab pass */ for (fldvertlocnnd = fldvertlocnum + fldcommdattab[j].vertnbr; fldvertlocnum < fldvertlocnnd; fldvertlocnum ++) fldvertloctax[fldvertlocnum] += fldvertlocadj; } } for (i = 0; i < commnbr; i ++) { int j; if (MPI_Waitany (commnbr, &requtab[HDGRAPHFOLDTAGVEND * commmax], &j, MPI_STATUS_IGNORE) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (15)"); cheklocval = 1; } else { /* Adjust first remote part of vertex array */ Gnum fldvendlocnum; Gnum fldvendlocnnd; Gnum fldvendlocadj; Gnum * restrict const fldvendloctax = fldgrafptr->s.vendloctax; fldvendlocnum = fldvertidxtab[j]; fldvendlocadj = fldvendidxtab[j]; /* Get updated adjust from above vertloctab pass */ for (fldvendlocnnd = fldvendlocnum + fldcommdattab[j].vertnbr; fldvendlocnum < fldvendlocnnd; fldvendlocnum ++) fldvendloctax[fldvendlocnum] += fldvendlocadj; } } for (i = 0; i < commnbr; i ++) { MPI_Status statdat; int j; if (MPI_Waitany (commnbr, &requtab[HDGRAPHFOLDTAGEDGE * commmax], &j, &statdat) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (16)"); cheklocval = 1; } else if (cheklocval == 0) { /* Adjust remote part(s) of edge array */ Gnum orgvertlocmin; Gnum orgvertlocmax; Gnum fldvertlocnum; Gnum fldvertlocnnd; Gnum fldvertlocadj; Gnum fldvhallocmax; /* Maximum current size of halo vertex array */ int procngbmin; int procngbmax; Gnum * restrict const fldvertloctax = fldgrafptr->s.vertloctax; Gnum * restrict const fldvendloctax = fldgrafptr->s.vendloctax; Gnum * restrict const fldedgeloctax = fldgrafptr->s.edgeloctax; #ifdef SCOTCH_DEBUG_HDGRAPH2 int fldedgercvnbr; MPI_Get_count (&statdat, GNUM_MPI, &fldedgercvnbr); if (fldedgercvnbr != fldedgecnttab[j]) { errorPrint ("hdgraphFold2: internal error (6)"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ for (procngbmin = 0, procngbmax = fldvertadjnbr; /* Initialize search accelerator */ procngbmax - procngbmin > 1; ) { int procngbmed; procngbmed = (procngbmax + procngbmin) / 2; if (fldvertadjtab[procngbmed] <= fldcommvrttab[j]) procngbmin = procngbmed; else procngbmax = procngbmed; } orgvertlocmin = fldvertadjtab[procngbmin]; orgvertlocmax = fldvertadjtab[procngbmax]; fldvertlocadj = fldvertdlttab[procngbmin]; fldvhallocmax = orggrafptr->s.baseval - 1; /* Reset halo vertex array for each remote part */ for (fldvertlocnum = fldvertidxtab[j], fldedgelocnum = fldedgeidxtab[j], /* Update received part of edge array */ fldvertlocnnd = fldvertlocnum + fldcommdattab[j].vertnbr; fldvertlocnum < fldvertlocnnd; ) { for ( ; fldedgelocnum < fldvendloctax[fldvertlocnum]; fldedgelocnum ++) { /* Reorder end vertices */ Gnum orgvertlocend; #ifdef SCOTCH_DEBUG_HDGRAPH2 if (fldedgelocnum >= (fldgrafptr->s.edgelocsiz + orggrafptr->s.baseval)) { errorPrint ("hdgraphFold2: internal error (7)"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ orgvertlocend = fldedgeloctax[fldedgelocnum]; if ((orgvertlocend >= orgvertlocmin) && /* If end vertex is local */ (orgvertlocend < orgvertlocmax)) fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertlocadj; else { int procngbnum; int procngbmax; for (procngbnum = 0, procngbmax = fldvertadjnbr; procngbmax - procngbnum > 1; ) { int procngbmed; procngbmed = (procngbmax + procngbnum) / 2; if (fldvertadjtab[procngbmed] <= orgvertlocend) procngbnum = procngbmed; else procngbmax = procngbmed; } fldedgeloctax[fldedgelocnum] = orgvertlocend + fldvertdlttab[procngbnum]; } } fldvertlocnum ++; fldehallocnbr += fldvertloctax[fldvertlocnum] - fldedgelocnum; for ( ; fldedgelocnum < fldvertloctax[fldvertlocnum]; fldedgelocnum ++) { /* Renumber halo part */ Gnum orgverthalend; Gnum fldvhallocend; orgverthalend = fldedgeloctax[fldedgelocnum]; #ifdef SCOTCH_DEBUG_HDGRAPH2 if ((orgverthalend < orggrafptr->s.baseval) || (orgverthalend >= (orggrafptr->s.edgeglbsmx + orggrafptr->s.baseval)) || (fldedgelocnum >= (fldgrafptr->s.edgelocsiz + orggrafptr->s.baseval))) { errorPrint ("hdgraphFold2: internal error (8)"); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ while (fldvhallocmax < orgverthalend) /* Expand halo vertex index array whenever necessary */ fldvhalloctax[++ fldvhallocmax] = ~0; fldvhallocend = fldvhalloctax[orgverthalend]; /* Get renumbered halo vertex */ if (fldvhallocend < 0) { /* If new halo vertex not yet given */ fldvhallocend = /* Allocate it */ fldvhalloctax[orgverthalend] = fldvhallocnum ++; } fldedgeloctax[fldedgelocnum] = fldvhallocend; } } } } if ((fldcommtypval & DGRAPHFOLDCOMMSEND) == 0) { /* If process is a normal receiver, edge arrays may have been oversized */ fldgrafptr->s.edgeloctax = memRealloc (fldgrafptr->s.edgeloctax + orggrafptr->s.baseval, fldgrafptr->s.edgelocsiz * sizeof (Gnum)); fldgrafptr->s.edgeloctax -= orggrafptr->s.baseval; } fldgrafptr->vhallocnbr = fldvhallocnum - orggrafptr->s.baseval; fldgrafptr->vhndloctax = fldgrafptr->s.vertloctax + 1; /* Compact edge array with halo vertices */ fldgrafptr->ehallocnbr = fldehallocnbr; fldgrafptr->levlnum = orggrafptr->levlnum; /* Folded graph is of same level */ if (orggrafptr->s.veloloctax == NULL) /* If no vertex loads, reset graph vertex load to number of vertices */ fldvelolocsum = fldvertlocnbr; else { /* Graph has vertex loads and load of local part has already been computed */ for (i = 0; i < commnbr; i ++) { int j; if (MPI_Waitany (commnbr, &requtab[HDGRAPHFOLDTAGVELO * commmax], &j, MPI_STATUS_IGNORE) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (17)"); cheklocval = 1; } else if (cheklocval == 0) { /* Accumulate vertex loads for received vertex load array */ Gnum fldvertlocnum; Gnum fldvertlocnnd; for (fldvertlocnum = fldvertidxtab[j], fldvertlocnnd = fldvertlocnum + fldcommdattab[j].vertnbr; fldvertlocnum < fldvertlocnnd; fldvertlocnum ++) fldvelolocsum += fldgrafptr->s.veloloctax[fldvertlocnum]; } } } fldgrafptr->s.baseval = orggrafptr->s.baseval; fldgrafptr->s.vertlocnbr = fldvertlocnbr; fldgrafptr->s.vertlocnnd = fldvertlocnbr + orggrafptr->s.baseval; fldgrafptr->s.velolocsum = fldvelolocsum; fldgrafptr->s.edgelocnbr = fldgrafptr->s.edgelocsiz - fldehallocnbr; fldgrafptr->s.degrglbmax = orggrafptr->s.degrglbmax; if (dgraphBuild4 (&fldgrafptr->s) != 0) { errorPrint ("hdgraphFold2: cannot build folded graph"); hdgraphExit (fldgrafptr); return (1); } #ifdef SCOTCH_DEBUG_HDGRAPH2 if (hdgraphCheck (fldgrafptr) != 0) { /* Check graph consistency; vnumloctab is not checked so no need to wait for it */ errorPrint ("hdgraphFold2: internal error (9)"); hdgraphExit (fldgrafptr); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ } memFree (fldcommdattab); /* Free group leader */ if (MPI_Waitall (requnbr, requtab, MPI_STATUSES_IGNORE) != MPI_SUCCESS) { /* Wait for all graph data to arrive because graph could be freed afterwards */ errorPrint ("hdgraphFold2: communication error (18)"); cheklocval = 1; } memFree (fldvertidxtab); /* Free group leader including request array */ #ifdef SCOTCH_DEBUG_HDGRAPH1 /* Communication cannot be merged with a useful one */ if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, orggrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphFold2: communication error (19)"); chekglbval = 1; } #else /* SCOTCH_DEBUG_HDGRAPH1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_HDGRAPH1 */ return (chekglbval); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_fold_comm.c0000644000175300017530000005727511632730174022606 0ustar hazelscthazelsct/* Copyright 2007,2009-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_fold_comm.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module computes the communication **/ /** pattern of the distributed graph **/ /** folding process. **/ /** **/ /** DATES : # Version 5.0 : from : 23 may 2006 **/ /** to : 10 sep 2007 **/ /** # Version 5.1 : from : 18 jan 2009 **/ /** to : 10 sep 2011 **/ /** **/ /************************************************************/ #define DGRAPH_FOLD_COMM #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_fold_comm.h" /* This routine computes an optimized communication ** scheme for folding the data of a distributed graph. ** It is currently based on a maximum fixed number of ** communications per process. If this maximum is reached, ** the algorithm will fail. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphFoldComm ( const Dgraph * restrict const grafptr, const int partval, /* 0 for first half, 1 for second half */ int * restrict const commptr, /* Pointer to maximum number of communications per process */ int * restrict const commtypval, /* Process will be sender or receiver */ DgraphFoldCommData *restrict * restrict const commdatptr, /* Slots for communication */ Gnum *restrict * restrict const commvrtptr, /* Slots of starting global vertex send indices */ Gnum * restrict const proccnttab, /* Receive count array, for receivers */ int * restrict const vertadjnbrptr, /* Number of adjustment ranges, for receivers */ Gnum * restrict * restrict const vertadjptr, /* Pointer to global index adjustment array, for receivers */ Gnum * restrict * restrict const vertdltptr) /* Pointer to global delta adjustment array, for receivers */ { int commmax; /* Maximum number of communications per process */ int procnum; Gnum * restrict commvrttab; DgraphFoldCommData * restrict commdattab; DgraphFoldCommData * restrict procsrttab; /* Sort array */ int procsndbas; int procsndmnd; int procsndidx; int procrcvbas; int procrcvnnd; int procrcvidx; int fldprocnbr; Gnum * restrict vertadjtab; Gnum * restrict vertdlttab; int * restrict vertprmtab; /* Permutation array for adjustment range computations */ int i; #ifdef SCOTCH_DEBUG_DGRAPH2 DgraphFoldCommData * restrict procchktab; int chekloctab[2]; int chekglbtab[2]; if (grafptr->procglbnbr < 2) { errorPrint ("dgraphFoldComm: invalid parameters"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if ((procsrttab = memAlloc (grafptr->procglbnbr * sizeof (DgraphFoldCommData))) == NULL) { errorPrint ("dgraphFoldComm: out of memory (1)"); return (1); } for (procnum = 0; procnum < grafptr->procglbnbr; procnum ++) { procsrttab[procnum].procnum = procnum; procsrttab[procnum].vertnbr = grafptr->proccnttab[procnum]; } fldprocnbr = (grafptr->procglbnbr + 1) / 2; /* Get number of processes in part 0 (always more than in part 1) */ intSort2asc1 (procsrttab, fldprocnbr); /* Sort both parts of processor array */ intSort2asc1 (procsrttab + fldprocnbr, grafptr->procglbnbr - fldprocnbr); if (partval == 0) { /* If part 0 will receive the data */ procrcvbas = 0; /* Receive by ascending weight order in first part */ procrcvnnd = fldprocnbr; procsndbas = grafptr->procglbnbr; /* Send by descending weight order in other part */ procsndmnd = fldprocnbr; } else { /* Part 1 will receive the data */ procrcvbas = fldprocnbr; /* Receive by ascending weight order in first part */ procrcvnnd = grafptr->procglbnbr; procsndbas = fldprocnbr; /* Send by descending weight order in other part */ procsndmnd = 0; fldprocnbr = grafptr->procglbnbr - fldprocnbr; } *commtypval = ((grafptr->proclocnum >= procrcvbas) && (grafptr->proclocnum < procrcvnnd)) ? DGRAPHFOLDCOMMRECV : DGRAPHFOLDCOMMSEND; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((*commtypval == DGRAPHFOLDCOMMRECV) && ((proccnttab == NULL) || (vertadjptr == NULL) || (vertdltptr == NULL))) { errorPrint ("dgraphFoldComm: internal error (1)"); memFree (procsrttab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ for (commmax = DGRAPHFOLDCOMMNBR, commdattab = NULL; ; commmax ++) { /* Start with small number of communications per process */ int procrcvnum; int procsndnum; int procsndnxt; /* Index of next sender to process after current sender */ Gnum vertglbsum; /* Global number of vertices already sent from all previous senders */ Gnum vertglbavg; /* Global average value of sent vertices to reach during current round */ Gnum vertsndrmn; /* Remaining number of vertices to send from current sending process */ int flagrcvval; /* Number of messages already sent by receiver and sender */ int flagsndval; int commtmp; if (commdattab != NULL) memFree (commdattab); commtmp = (proccnttab == NULL) ? 0 : commmax; if (memAllocGroup ((void **) (void *) &commdattab, (size_t) (commmax * sizeof (DgraphFoldCommData)), &commvrttab, (size_t) (commmax * sizeof (Gnum)), &vertadjtab, (size_t) (commtmp * grafptr->procglbnbr * sizeof (Gnum)), &vertdlttab, (size_t) (commtmp * grafptr->procglbnbr * sizeof (Gnum)), #ifdef SCOTCH_DEBUG_DGRAPH2 &procchktab, (size_t) (commmax * grafptr->procglbnbr * sizeof (DgraphFoldCommData)), #endif /* SCOTCH_DEBUG_DGRAPH2 */ &vertprmtab, (size_t) ((commmax + 1) * fldprocnbr * sizeof (int)), NULL) == NULL) { errorPrint ("dgraphFoldComm: out of memory (2)"); memFree (procsrttab); return (1); } for (i = 0; i < commmax; i ++) { /* Assume we will perform no communication at all */ commdattab[i].procnum = -1; commdattab[i].vertnbr = 0; } if (proccnttab != NULL) { /* If we are a receiver process, start filling count and adjustment arrays */ int procrcvtmp; memSet (vertprmtab, ~0, (commmax + 1) * fldprocnbr * sizeof (int)); /* Reset adjustment index arrays */ memSet (vertadjtab, ~0, commmax * grafptr->procglbnbr * sizeof (Gnum)); for (procrcvtmp = procrcvbas; procrcvtmp < procrcvnnd; procrcvtmp ++) { /* Fill count and adjustment arrays for receiver processes slots */ vertadjtab[procrcvtmp * commmax] = grafptr->procvrttab[procrcvtmp]; vertdlttab[procrcvtmp * commmax] = proccnttab[procrcvtmp - procrcvbas] = grafptr->proccnttab[procrcvtmp]; vertprmtab[(procrcvtmp - procrcvbas) * (commmax + 1)] = procrcvtmp * commmax; } } for (procrcvidx = procrcvbas; procrcvidx < (procrcvnnd - 1); procrcvidx ++, procrcvnnd --) { /* Overloaded receiver vertices will re-send some of their load */ Gnum vertsndnbr; /* Potential overload of receiver process */ procsndidx = procrcvnnd - 1; vertsndnbr = procsrttab[procsndidx].vertnbr - DATASIZE (grafptr->vertglbnbr, fldprocnbr, procsndidx - procrcvbas); if (vertsndnbr <= 0) /* If no further overload to improve, exit loop */ break; procrcvnum = procsrttab[procrcvidx].procnum; procsndnum = procsrttab[procsndidx].procnum; procsrttab[procrcvidx].vertnbr = - (procsrttab[procrcvidx].vertnbr + vertsndnbr); /* Flag as having had a communication */ if (proccnttab != NULL) { /* If we are a receiver process, fill count and adjustment arrays */ proccnttab[procrcvnum - procrcvbas] += vertsndnbr; proccnttab[procsndnum - procrcvbas] -= vertsndnbr; /* Vertices are transferred between receiver processes */ vertadjtab[procsndnum * commmax + 1] = grafptr->procvrttab[procsndnum] + grafptr->proccnttab[procsndnum] - vertsndnbr; vertdlttab[procsndnum * commmax + 1] = vertsndnbr; vertdlttab[procsndnum * commmax] -= vertsndnbr; vertprmtab[(procrcvnum - procrcvbas) * (commmax + 1) + 1] = procsndnum * commmax + 1; if (procsndnum == grafptr->proclocnum) { /* If we are the sender receiver process */ *commtypval = DGRAPHFOLDCOMMSEND | DGRAPHFOLDCOMMRECV; /* Indicate it */ commdattab[0].procnum = procrcvnum; /* Record communication */ commdattab[0].vertnbr = vertsndnbr; commvrttab[0] = grafptr->procvrttab[procsndnum] + grafptr->proccnttab[procsndnum] - vertsndnbr; /* Set starting global index of vertices to be sent */ } else if (procrcvnum == grafptr->proclocnum) { /* If we are the receiver receiver process */ commdattab[0].procnum = procsndnum; /* Record communication */ commdattab[0].vertnbr = vertsndnbr; commvrttab[0] = grafptr->procvrttab[procsndnum] + grafptr->proccnttab[procsndnum] - vertsndnbr; /* Set starting global index of vertices to be sent */ } } } while ((procsndmnd < procsndbas) && (procsrttab[procsndmnd].vertnbr == 0)) /* Do not account for empty sender processes */ procsndmnd ++; if (procsndmnd >= procsndbas) /* If there are no more sender processes */ break; /* We have completed communication computation */ procsndidx = procsndbas - 1; procsndnxt = procsndidx - 1; vertsndrmn = procsrttab[procsndidx].vertnbr; flagsndval = 0; procrcvidx = procrcvbas; procrcvnum = procsrttab[procrcvidx].procnum; flagrcvval = 0; vertglbavg = DATASIZE (grafptr->vertglbnbr, fldprocnbr, 0); vertglbsum = procsrttab[procrcvidx].vertnbr; /* Account for vertices already present in receiver process */ if (vertglbsum < 0) { /* If first receiver has already received a communication */ flagrcvval = 1; vertglbsum = - vertglbsum; procsrttab[procrcvidx].vertnbr = vertglbsum; /* Un-flag */ } while (1) { Gnum vertrcvrmn; /* Remaining number of vertices to receive */ Gnum vertsndnbr; /* Number of vertices actually sent and received */ Gnum vertsndnxt; /* Adjustment to add to vertex count of next sender */ int mesgrcvrmn; /* Number of message slots to receive small messages */ int flagsndnxt; #ifdef SCOTCH_DEBUG_DGRAPH2 if (flagrcvval + flagsndval >= (commmax * 2)) { errorPrint ("dgraphFoldComm: internal error (2)"); memFree (commdattab); /* Free group leader */ memFree (procsrttab); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ vertrcvrmn = (vertglbavg > vertglbsum) ? (vertglbavg - vertglbsum) : 0; /* Remaining space on receiver */ mesgrcvrmn = (vertsndrmn >= vertrcvrmn) ? (commmax - 1) : (commmax - 2); if ((procsndidx > procsndmnd) && /* If there remains small messages to be considered */ (((flagsndval == 0) && /* If sender has not sent anything yet or just started */ (flagrcvval < mesgrcvrmn)) || /* And receiver has space for larger messages to come */ ((flagrcvval == 0) && /* Or if receiver has not received anything yet */ (flagsndval < (commmax - 2)))) && /* And sender has enough slots to send */ (vertrcvrmn >= procsrttab[procsndmnd].vertnbr)) { /* And if receiver can hold small message entirely */ procsndnxt = procsndidx; /* Current large message will be processed next time */ procsndidx = procsndmnd; /* Process smallest message available to date */ flagsndnxt = flagsndval; /* Record location of next message to send */ flagsndval = 0; vertsndnxt = procsrttab[procsndnxt].vertnbr - vertsndrmn; /* Record vertices already sent */ vertsndnbr = /* All of its contents will be sent in one piece */ vertsndrmn = procsrttab[procsndmnd].vertnbr; procsndmnd ++; /* Small message has been processed */ } else { flagsndnxt = 0; vertsndnxt = 0; /* Next sender will not have been interrupted by a small message */ vertsndnbr = ((flagsndval >= (commmax - 1)) || /* If last chance to send for this process */ (((procrcvnnd - procrcvidx) * (commmax - 1) - flagrcvval) <= (procsndidx - procsndmnd))) /* Or if too few communications remain with sender receivers accounted for */ ? vertsndrmn /* Send all of the vertices to be sent */ : MIN (vertsndrmn, vertrcvrmn); /* Else just send what the receiver needs */ } procsndnum = procsrttab[procsndidx].procnum; if (vertsndnbr > 0) { /* If useful communication can take place */ if (proccnttab != NULL) { /* If we are a receiver process, fill count and adjustment arrays */ proccnttab[procrcvnum - procrcvbas] += vertsndnbr; vertadjtab[procsndnum * commmax + flagsndval] = grafptr->procvrttab[procsndnum] + grafptr->proccnttab[procsndnum] - vertsndrmn; vertdlttab[procsndnum * commmax + flagsndval] = vertsndnbr; vertprmtab[(procrcvnum - procrcvbas) * (commmax + 1) + 1 + flagrcvval] = procsndnum * commmax + flagsndval; if (procrcvnum == grafptr->proclocnum) { /* If we are the receiver process */ commdattab[flagrcvval].procnum = procsndnum; /* Record communication */ commdattab[flagrcvval].vertnbr = vertsndnbr; commvrttab[flagrcvval] = grafptr->procvrttab[procsndnum] + grafptr->proccnttab[procsndnum] - vertsndrmn; /* Set starting global index of vertices to be sent */ } } else if (procsndnum == grafptr->proclocnum) { /* If we are the sending process */ commdattab[flagsndval].procnum = procrcvnum; /* Record communication */ commdattab[flagsndval].vertnbr = vertsndnbr; commvrttab[flagsndval] = grafptr->procvrttab[procsndnum] + grafptr->proccnttab[procsndnum] - vertsndrmn; /* Set starting global index of vertices to be sent */ } vertglbsum += vertsndnbr; /* Account for vertices sent and received */ vertsndrmn -= vertsndnbr; flagsndval ++; flagrcvval ++; } if (vertsndrmn <= 0) { /* If sending process has sent everything */ procsndidx = procsndnxt; /* Process next vertex to send */ if (procsndidx < procsndmnd) /* If was last sending process, end loop */ break; procsndnxt = procsndidx - 1; /* Prepare next sender process */ flagsndval = flagsndnxt; /* Skip to next sending process */ vertsndrmn = procsrttab[procsndidx].vertnbr - vertsndnxt; } if ((flagrcvval >= commmax) || /* If receiver cannot receive more */ ((vertglbsum >= vertglbavg) && /* Or has received what it needed and is not forced to accept more */ (((procrcvnnd - procrcvidx) * (commmax - 1) - flagrcvval) > (procsndidx - procsndmnd)))) { if (++ procrcvidx >= procrcvnnd) /* If was last receiver, exit loop and go finalizing communication arrays */ break; procrcvnum = procsrttab[procrcvidx].procnum; /* Skip to next receiver process */ vertglbavg += DATASIZE (grafptr->vertglbnbr, fldprocnbr, procrcvidx - procrcvbas); if (procsrttab[procrcvidx].vertnbr >= 0) { /* If receiver did not receive from a sender receiver */ flagrcvval = 0; vertglbsum += procsrttab[procrcvidx].vertnbr; /* Account for vertices already present in receiver process */ } else { /* Receiver already received from a sender receiver */ flagrcvval = 1; /* Already a communication performed */ vertglbsum -= procsrttab[procrcvidx].vertnbr; /* Use negative value */ } } } if ((procsndidx <= procsndmnd) && (vertsndrmn <= 0)) /* If no sender vertex which has something to send remains */ break; /* Exit the loop on increasing number of communications */ } #ifdef SCOTCH_DEBUG_DGRAPH2 chekloctab[0] = - commmax; chekloctab[1] = commmax; if (MPI_Allreduce (chekloctab, chekglbtab, 2, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphFoldComm: communication error"); memFree (commdattab); /* Free group leader */ return (1); } if ((chekglbtab[0] != chekloctab[0]) || (chekglbtab[1] != chekloctab[1])) { errorPrint ("dgraphFoldComm: internal error (3)"); memFree (commdattab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (proccnttab != NULL) { /* If we are a receiver process */ int vertadjnbr; /* Number of adjustment slots */ Gnum vertadjsum; /* Current new starting position of current slot */ for (procnum = 0, vertadjsum = grafptr->baseval; procnum < ((commmax + 1) * fldprocnbr); procnum ++) { int vertprmnum; Gnum vertadjtmp; vertprmnum = vertprmtab[procnum]; if (vertprmnum == ~0) /* Skip empty slots */ continue; vertadjtmp = vertdlttab[vertprmnum]; /* Accumulate new slot indices and compute adjustments */ vertdlttab[vertprmnum] = vertadjsum - vertadjtab[vertprmnum]; vertadjsum += vertadjtmp; } for (procnum = vertadjnbr = 0; procnum < (commmax * grafptr->procglbnbr); procnum ++) { /* Compact vertex adjustment arrays */ if (vertadjtab[procnum] != -1) { vertadjtab[vertadjnbr] = vertadjtab[procnum]; vertdlttab[vertadjnbr] = vertdlttab[procnum]; vertadjnbr ++; } } vertadjtab[vertadjnbr] = grafptr->procvrttab[grafptr->procglbnbr]; /* Set upper bound on global vertex indices */ *vertadjnbrptr = vertadjnbr; *vertadjptr = vertadjtab; *vertdltptr = vertdlttab; } *commdatptr = commdattab; /* Set group leader */ *commvrtptr = commvrttab; *commptr = commmax; memFree (procsrttab); #ifdef SCOTCH_DEBUG_DGRAPH2 if (proccnttab == NULL) { /* If we are a sender process */ Gnum vertsndnbr; /* Number of vertices actually sent */ int i; for (i = 0, vertsndnbr = 0; (i < commmax) && (commdattab[i].procnum >= 0); i ++) vertsndnbr += commdattab[i].vertnbr; if (vertsndnbr != grafptr->vertlocnbr) { errorPrint ("dgraphFoldComm: internal error (4)"); memFree (commdattab); /* Free group leader */ return (1); } } if (MPI_Allgather (commdattab, 2 * commmax, GNUM_MPI, procchktab, 2 * commmax, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphFoldComm: communication error"); memFree (commdattab); /* Free group leader */ return (1); } for (procnum = 0; procnum < grafptr->procglbnbr; procnum ++) { int commnum; for (commnum = 0; (commnum < commmax) && (procchktab[commmax * procnum + commnum].procnum != -1); commnum ++) { Gnum procend; Gnum vertnbr; int commend; procend = procchktab[commmax * procnum + commnum].procnum; vertnbr = procchktab[commmax * procnum + commnum].vertnbr; for (commend = 0; commend < commmax; commend ++) { if ((procchktab[commmax * procend + commend].procnum == procnum) && (procchktab[commmax * procend + commend].vertnbr == vertnbr)) break; } if (commend >= commmax) { errorPrint ("dgraphFoldComm: internal error (5)"); memFree (commdattab); /* Free group leader */ return (1); } } } #endif /* SCOTCH_DEBUG_DGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/vmesh.h0000644000175300017530000001177111631334325020435 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for mesh vertex separation **/ /** routines. **/ /** **/ /** DATES : # Version 4.0 : from : 10 sep 2002 **/ /** to : 10 sep 2002 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to : 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ Active graph structure. +*/ typedef struct Vmesh_ { Mesh m; /*+ Source mesh +*/ GraphPart * parttax; /*+ Based part array: 0,1: part; 2: separator +*/ Gnum ecmpsize[2]; /*+ Number of elements in each part (not in separator) +*/ Gnum ncmpload[3]; /*+ Loads of nodes in both parts and separator +*/ Gnum ncmploaddlt; /*+ Node load difference between both parts +*/ Gnum ncmpsize[2]; /*+ Number of nodes in parts (separator is fronnbr) +*/ Gnum fronnbr; /*+ Number of frontier nodes; TRICK: ncmpsize[2] +*/ Gnum * frontab; /*+ Array of frontier node numbers +*/ Gnum levlnum; /*+ Nested dissection or coarsening level +*/ } Vmesh; /*+ The graph separator storing structure. +*/ typedef struct VmeshStore_ { Gnum ecmpsize[2]; /*+ Number of elements in each part +*/ Gnum ncmpload[3]; /*+ Loads of nodes in both parts and separator +*/ Gnum ncmploaddlt; /*+ Node load difference between both parts +*/ Gnum ncmpsize[2]; /*+ Number of nodes in parts (separator is fronnbr) +*/ Gnum fronnbr; /*+ Number of frontier nodes; TRICK: ncmpsize[2] +*/ byte * datatab; /*+ Variable-sized data array +*/ } VmeshStore; /* ** The function prototypes. */ #ifndef VMESH #define static #endif void vmeshExit (Vmesh * const); void vmeshZero (Vmesh * const); int vmeshCheck (const Vmesh * const); int vmeshStoreInit (const Vmesh * const, VmeshStore * const); void vmeshStoreExit (VmeshStore * const); void vmeshStoreSave (const Vmesh * const , VmeshStore * const); void vmeshStoreUpdt (Vmesh * const, const VmeshStore * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/kgraph_map_rb_part.c0000644000175300017530000003073211631334325023126 0ustar hazelscthazelsct/* Copyright 2008,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kgraph_map_rb_part.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module performs the Dual Recursive **/ /** Bipartitioning mapping algorithm for **/ /** (eventually weighted) complete graph **/ /** target architectures. **/ /** **/ /** DATES : # Version 5.1 : from : 16 sep 2008 **/ /** to 31 aug 2011 **/ /** **/ /** NOTES : # This is a rewrite of kgraphMapRb() **/ /** for complete-graph target topologies. **/ /** Its advantage over kgraphMapRbMap() **/ /** is that no job arrays are allocated, **/ /** which can save space for instance for **/ /** using the variable-sized complete **/ /** graph architecture. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define KGRAPH_MAP_RB_PART #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "arch.h" #include "mapping.h" #include "bgraph.h" #include "bgraph_bipart_st.h" #include "kgraph.h" #include "kgraph_map_rb.h" #include "kgraph_map_rb_part.h" /********************************************/ /* */ /* This is the entry point for the Dual */ /* Recursive Bipartitioning mapping method. */ /* */ /********************************************/ /* This routine runs the Dual Recursive ** Bipartitioning algorithm. ** It returns: ** - 0 : on success. ** - !0 : on error. */ static int kgraphMapRbPart3 ( const Graph * restrict const orggrafptr, /* Graph to induce and bipartition */ const GraphPart * restrict const orgparttax, /* Part array of original graph */ const GraphPart indpartval, /* Part of graph to consider */ const int domnnum, /* Index of domain onto which map the part */ Mapping * restrict const mappptr) /* Final mapping */ { Gnum vertnum; if (orgparttax == NULL) { /* If graph is full graph */ #ifdef SCOTCH_DEBUG_KGRAPH2 if ((orggrafptr->vnumtax != NULL) || (domnnum != 0)) { errorPrint ("kgraphMapRbPart3: internal error"); return (1); } #endif /* SCOTCH_DEBUG_KGRAPH2 */ memSet (mappptr->parttax + mappptr->baseval, 0, orggrafptr->vertnbr * sizeof (ArchDomNum)); } else { /* Graph to consider is a subgraph of the original graph */ if (orggrafptr->vnumtax == NULL) { /* If original graph is not itself a subgraph */ for (vertnum = orggrafptr->baseval; vertnum < orggrafptr->vertnnd; vertnum ++) { /* For all graph vertices */ if (orgparttax[vertnum] == indpartval) /* If vertex belongs to the right part */ mappptr->parttax[vertnum] = domnnum; } } else { for (vertnum = orggrafptr->baseval; vertnum < orggrafptr->vertnnd; vertnum ++) { /* For all graph vertices */ if (orgparttax[vertnum] == indpartval) /* If vertex belongs to the right part */ mappptr->parttax[orggrafptr->vnumtax[vertnum]] = domnnum; } } } return (0); } static int kgraphMapRbPart2 ( KgraphMapRbPartData * restrict const topdataptr, /* Top-level graph and partition data */ Graph * restrict const orggrafptr, /* Graph to induce and bipartition */ const GraphPart * restrict const orgparttax, /* Part array of original graph to consider */ const GraphPart indpartval, /* Part of graph to consider */ const Gnum indvertnbr, /* Number of vertices in part or in graph */ const Anum domnnum) /* Index of domain onto which map the part */ { Graph indgrafdat; Graph * indgrafptr; Bgraph actgrafdat; Anum domnsubidx; Anum domnsubdlt; ArchDom domnsubtab[2]; /* Target subdomains */ Anum domnsubnum[2]; /* Index of subdomains in mapping */ Gnum grafsubsiz[2]; Mapping * restrict mappptr; int avarval; /* Flag set if variable-sized */ int i; int o; mappptr = topdataptr->mappptr; avarval = archVar (&mappptr->archdat); o = (avarval && /* If architecture is variable-sized */ (indvertnbr <= 1)) /* And source subgraph of minimal size */ ? 1 /* Then do not bipartition target more */ : archDomBipart (&mappptr->archdat, &mappptr->domntab[domnnum], &domnsubtab[0], &domnsubtab[1]); switch (o) { case 1 : /* If target domain is terminal */ return (kgraphMapRbPart3 (orggrafptr, orgparttax, indpartval, domnnum, mappptr)); /* Update mapping and return */ case 2 : /* On error */ errorPrint ("kgraphMapRbPart2: cannot bipartition domain"); return (1); } indgrafptr = orggrafptr; /* Assume we will work on the original graph */ if (orgparttax != NULL) { /* If not the case, build induced subgraph */ indgrafptr = &indgrafdat; if (graphInducePart (orggrafptr, orgparttax, indvertnbr, indpartval, &indgrafdat) != 0) { errorPrint ("kgraphMapRbPart2: cannot induce graph"); return (1); } } if (bgraphInit (&actgrafdat, indgrafptr, NULL, mappptr, domnsubtab) != 0) { /* Create active graph */ errorPrint ("kgraphMapRbPart2: cannot create bipartition graph"); return (1); } if (! avarval) { /* If not variable-sized, impose constraints on bipartition */ double comploadavg; comploadavg = (double) actgrafdat.s.velosum / (double) archDomWght (&mappptr->archdat, &mappptr->domntab[domnnum]); actgrafdat.compload0min = actgrafdat.compload0avg - (Gnum) MIN ((topdataptr->comploadmax - comploadavg) * (double) actgrafdat.domwght[0], (comploadavg - topdataptr->comploadmin) * (double) actgrafdat.domwght[1]); actgrafdat.compload0max = actgrafdat.compload0avg + (Gnum) MIN ((comploadavg - topdataptr->comploadmin) * (double) actgrafdat.domwght[0], (topdataptr->comploadmax - comploadavg) * (double) actgrafdat.domwght[1]); } if (bgraphBipartSt (&actgrafdat, topdataptr->paraptr->strat) != 0) { /* Perform bipartitioning */ errorPrint ("kgraphMapRbPart2: cannot bipartition graph"); bgraphExit (&actgrafdat); return (1); } memFree (actgrafdat.frontab); /* Frontier array of bipartitioning graph is no longer necessary */ actgrafdat.s.flagval &= ~BGRAPHFREEFRON; if (archVar (&mappptr->archdat)) { /* If architecture is variable-sized */ if ((actgrafdat.compload0 == 0) || /* If bipartition failed */ (actgrafdat.compload0 == actgrafdat.s.velosum)) return (kgraphMapRbPart3 (orggrafptr, orgparttax, indpartval, domnnum, mappptr)); /* Update mapping with original domain and return */ } domnsubdlt = mappptr->domnnbr - domnnum; /* Increment in domain number */ domnsubidx = domnnum - domnsubdlt; /* Place where to insert subdomain */ mappptr->domnnbr --; /* One less subdomain as for now */ grafsubsiz[0] = actgrafdat.compsize0; grafsubsiz[1] = actgrafdat.s.vertnbr - actgrafdat.compsize0; o = 0; for (i = 1; i >= 0; i --) { /* For all subparts */ if (grafsubsiz[i] <= 0) /* If subpart is empty, skip it */ continue; mappptr->domnnbr ++; /* One more subdomain to account for */ if (mappptr->domnnbr > mappptr->domnmax) { Anum domnmax; ArchDom * restrict domntmp; domnmax = mappptr->domnmax + (mappptr->domnmax >> 2) + 8; /* Increase size by 25% */ if ((domntmp = memRealloc (mappptr->domntab, domnmax * sizeof (ArchDom))) == NULL) { errorPrint ("kgraphMapRbPart: cannot resize structures"); o = 1; break; } mappptr->domnmax = domnmax; mappptr->domntab = domntmp; } domnsubidx += domnsubdlt; /* Compute location of subdomain */ domnsubnum[i] = domnsubidx; /* Record it before recursion */ mappptr->domntab[domnsubidx] = domnsubtab[i]; /* Write it at this place */ } if (o == 0) { for (i = 1; i >= 0; i --) { /* For all subparts */ if (grafsubsiz[i] <= 0) /* If subpart is empty, skip it */ continue; if ((o = kgraphMapRbPart2 (topdataptr, indgrafptr, actgrafdat.parttax, (GraphPart) i, grafsubsiz[i], domnsubnum[i])) != 0) return (1); /* If problem in recursion, stop */ } } bgraphExit (&actgrafdat); /* Free bipartition graph (that is, parttax) */ if (indgrafptr == &indgrafdat) /* If an induced subgraph had been created */ graphExit (indgrafptr); /* Free it */ return (o); } int kgraphMapRbPart ( Kgraph * restrict const grafptr, const KgraphMapRbParam * restrict const paraptr) { KgraphMapRbPartData topdatadat; topdatadat.topgrafptr = &grafptr->s; topdatadat.topfrontab = NULL; topdatadat.topfronnbr = 0; topdatadat.mappptr = &grafptr->m; topdatadat.paraptr = paraptr; topdatadat.comploadmin = (1.0 - paraptr->kbalval) * grafptr->comploadrat; /* Ratio can have been tilted when working on subgraph */ topdatadat.comploadmax = (1.0 + paraptr->kbalval) * grafptr->comploadrat; grafptr->m.domnnbr = 1; /* Reset mapping to original (sub)domain */ grafptr->m.domntab[0] = grafptr->m.domnorg; return (kgraphMapRbPart2 (&topdatadat, &grafptr->s, NULL, 0, grafptr->s.vertnbr, 0)); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_halo.h0000644000175300017530000001021611631334325021554 0ustar hazelscthazelsct/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_halo.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the data declara- **/ /** tions for the asynchronous halo **/ /** exchange routine. **/ /** **/ /** DATES : # Version 5.0 : from : 28 dec 2007 **/ /** to : 05 feb 2008 **/ /** # Version 5.1 : from : 28 aug 2008 **/ /** to : 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines. */ /* procsidtab-related values. */ #define DGRAPHGHSTSIDMAX ((int) ((unsigned int) (1 << (sizeof (int) * 8 - 1)) - 2U)) /* Maximum leap value for procsidtab entries */ /* ** The type and structure definitions. */ /* Sort structure for ghost edges. */ typedef struct DgraphHaloRequest_ { int flagval; #ifdef SCOTCH_PTHREAD Dgraph * grafptr; /* Pointer to graph data */ void * attrgsttab; /* Attribute array to share */ MPI_Datatype attrglbtype; /* Attribute datatype */ pthread_t thrdval; /* Data of asynchronous thread */ #else /* SCOTCH_PTHREAD */ #ifdef SCOTCH_MPI_ASYNC_COLL byte * attrsndtab; /* Group leader for memory freeing */ MPI_Request requval; /* MPI asynchronous communication request */ #endif /* SCOTCH_MPI_ASYNC_COLL */ #endif /* SCOTCH_PTHREAD */ } DgraphHaloRequest; /* ** The function prototypes. */ #ifndef DGRAPH_HALO #define static #endif #ifdef SCOTCH_PTHREAD static void * dgraphHaloAsync2 (DgraphHaloRequest * restrict); #endif /* SCOTCH_PTHREAD */ void dgraphHaloAsync (Dgraph * restrict const, void * restrict const, const MPI_Datatype, DgraphHaloRequest * restrict); int dgraphHaloWait (DgraphHaloRequest * restrict); int dgraphHaloCheck (const Dgraph * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/kdgraph_map_st.h0000644000175300017530000000627511631334325022301 0ustar hazelscthazelsct/* Copyright 2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kdgraph_map_st.h **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the strategy and method **/ /** tables and the generic entry point for **/ /** the parallel multi-way static mapping **/ /** routines. **/ /** **/ /** DATES : # Version 5.1 : from : 16 jun 2008 **/ /** to 16 jun 2008 **/ /** **/ /************************************************************/ /* ** The type definitions. */ /*+ Method types. +*/ typedef enum KdgraphMapStMethodType_ { KDGRAPHMAPSTMETHRB = 0, /*+ Dual Recursive Bipartitioning +*/ KDGRAPHMAPSTMETHNBR /*+ Number of methods +*/ } KdgraphMapStMethodType; /* ** The external declarations. */ extern StratTab kdgraphmapststratab; /* ** The function prototypes. */ #ifndef KDGRAPH_MAP_ST #define static #endif int kdgraphMapSt (Kdgraph * restrict const, Kdmapping * restrict const, const Strat * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/vmesh_separate_fm.h0000644000175300017530000001613611631334325023003 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh_separate_fm.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the improved Fiduccia-Mattheyses **/ /** mesh element separation routine. **/ /** **/ /** DATES : # Version 4.0 : from : 26 feb 2003 **/ /** to 06 may 2004 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Gain table subbits. +*/ #define VMESHSEPAFMGAINBITS 4 /*+ Prime number for hashing vertex numbers. +*/ #define VMESHSEPAFMHASHPRIME 11 /*+ Prime number for hashing +*/ /*+ Gain table vertex status. +*/ #define VMESHSEPAFMSTATEFREE ((GainLink *) 0) /*+ Element is free or separator-chained +*/ #define VMESHSEPAFMSTATEUSED ((GainLink *) 1) /*+ Element already swapped +*/ #define VMESHSEPAFMSTATELINK ((GainLink *) 2) /*+ Currently in gain table if higher +*/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct VmeshSeparateFmParam_ { INT movenbr; /*+ Maximum number of uneffective moves that can be done +*/ INT passnbr; /*+ Number of passes to be performed (-1 : infinite) +*/ double deltrat; /*+ Maximum weight imbalance ratio +*/ } VmeshSeparateFmParam; /*+ The hash element structure. The goal of both hash arrays is to record partition data that supercedes the one contained in the calling Vmesh structure, until the newly computed partition is written back to the Vmesh. +*/ typedef struct VmeshSeparateFmElement_ { GainLink gainlink; /*+ Gain link if moved to other part; FIRST +*/ Gnum velmnum; /*+ Number of vertex in hash table +*/ int vertpart; /*+ Vertex part +*/ Gnum ncmpcut2; /*+ Number of neighbor nodes in separator +*/ Gnum ncmpgain2; /*+ Separator gain if moved to given part +*/ Gnum ncmpgaindlt; /*+ Node load imbalance if element swapped +*/ Gnum mswpnum; /*+ Number of move sweep when data recorded +*/ } VmeshSeparateFmElement; /*+ The hash node structure. +*/ typedef struct VmeshSeparateFmNode_ { Gnum vnodnum; /*+ Number of vertex in hash table +*/ Gnum vnloval; /*+ Vertex load +*/ int vertpart; /*+ Vertex part +*/ Gnum ecmpsize0; /*+ Number of element neighbors in part 0 +*/ Gnum mswpnum; /*+ Number of move sweep when data recorded +*/ } VmeshSeparateFmNode; /*+ The move recording structure. +*/ typedef struct VmeshSeparateFmSave_ { Gnum hertnum; /*+ Hash index of vertex, (helmnum) or (-1 - hnodnum) +*/ union { /*+ Stored data to recover +*/ struct { /*+ Recovery data for element +*/ int vertpart; /*+ Vertex part +*/ Gnum ncmpcut2; /*+ Number of neighbor nodes in separator +*/ Gnum ncmpgain2; /*+ Separator gain if moved to given part +*/ Gnum ncmpgaindlt; /*+ Node load imbalance if element swapped +*/ } elem; struct { /*+ Recovery data for node +*/ int vertpart; /*+ Vertex part +*/ Gnum ecmpsize0; /*+ Number of element neighbors in part 0 +*/ } node; } data; } VmeshSeparateFmSave; /* ** The function prototypes. */ #ifndef VMESH_SEPARATE_FM #define static #endif int vmeshSeparateFm (Vmesh * restrict const, const VmeshSeparateFmParam * restrict const); static VmeshSeparateFmElement * vmeshSeparateFmTablGet (GainTabl * const, const Gnum, const Gnum); static int vmeshSeparateFmResize (GainTabl * restrict const, VmeshSeparateFmElement * restrict * const, VmeshSeparateFmNode * restrict * const, VmeshSeparateFmSave * restrict * const, const Gnum, VmeshSeparateFmElement **, VmeshSeparateFmElement **, const Gnum); #ifdef SCOTCH_DEBUG_VMESH3 static int vmeshSeparateFmCheck (const Vmesh * const, const VmeshSeparateFmElement * restrict, const VmeshSeparateFmNode * restrict, const Gnum, const Gnum, const Gnum); #endif /* SCOTCH_DEBUG_VMESH3 */ #undef static scotch-5.1.12b.dfsg/src/libscotch/common_file_compress.h0000644000175300017530000001124411631334325023510 0ustar hazelscthazelsct/* Copyright 2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : common_file_compress.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the file (de)compression routines. **/ /** **/ /** DATES : # Version 5.0 : from : 12 mar 2008 **/ /** to 17 mar 2008 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /* Buffer size. */ #define FILECOMPRESSDATASIZE (128 * 1024) /* Size of (un)compressing buffers */ /* Available types of (un)compression. */ typedef enum FileCompressType_ { FILECOMPRESSTYPENOTIMPL = -1, /* Error code */ FILECOMPRESSTYPENONE, /* No compression */ FILECOMPRESSTYPEBZ2, FILECOMPRESSTYPEGZ, FILECOMPRESSTYPELZMA } FileCompressType; /* (Un)compression type slot. */ typedef struct FileCompressTab_ { char * name; /* File extension name */ FileCompressType type; /* (Un)compression type */ } FileCompressTab; /* ** The type and structure definitions. */ typedef struct FileCompressData_ { int typeval; /*+ Type of (un)compression +*/ int innerfd; /*+ Inner file handle (pipe end) +*/ FILE * outerstream; /*+ Outer stream +*/ double datatab; /*+ Start of data buffer +*/ } FileCompressData; /* ** The function prototypes. */ #ifdef COMMON_FILE_COMPRESS_BZ2 #ifdef COMMON_FILE_COMPRESS static void fileCompressBz2 (FileCompressData * const dataptr); #endif /* COMMON_FILE_COMPRESS */ #ifdef COMMON_FILE_UNCOMPRESS static void fileUncompressBz2 (FileCompressData * const dataptr); #endif /* COMMON_FILE_UNCOMPRESS */ #endif /* COMMON_FILE_COMPRESS_Bz2 */ #ifdef COMMON_FILE_COMPRESS_GZ #ifdef COMMON_FILE_COMPRESS static void fileCompressGz (FileCompressData * const dataptr); #endif /* COMMON_FILE_COMPRESS */ #ifdef COMMON_FILE_UNCOMPRESS static void fileUncompressGz (FileCompressData * const dataptr); #endif /* COMMON_FILE_UNCOMPRESS */ #endif /* COMMON_FILE_COMPRESS_GZ */ #ifdef COMMON_FILE_COMPRESS_LZMA /* #ifdef COMMON_FILE_COMPRESS */ /* static void fileCompressLzma (FileCompressData * const dataptr); */ /* #endif /\* COMMON_FILE_COMPRESS *\/ */ #ifdef COMMON_FILE_UNCOMPRESS static void fileUncompressLzma (FileCompressData * const dataptr); #endif /* COMMON_FILE_UNCOMPRESS */ #endif /* COMMON_FILE_COMPRESS_LZMA */ scotch-5.1.12b.dfsg/src/libscotch/order.h0000644000175300017530000001530111631334325020417 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : order.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data **/ /** declarations for the generic ordering **/ /** structure. **/ /** **/ /** DATES : # Version 3.2 : from : 19 oct 1996 **/ /** to : 21 aug 1998 **/ /** # Version 4.0 : from : 19 dec 2001 **/ /** to 28 dec 2004 **/ /** # Version 5.0 : from : 25 jul 2007 **/ /** to 25 jul 2007 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ #define ORDER_H /* ** The defines. */ /*+ Ordering option flags. +*/ #define ORDERNONE 0x0000 /* No options set */ #define ORDERFREEPERI 0x0001 /* Free inverse permutation array */ /*+ Column block separation tree cell flags. The ORDERCBLKNEDI value must correspond to a single bit and be equal to the DORDERCBLKNEDI value. +*/ #define ORDERCBLKOTHR 0x0000 /*+ Other ordering node +*/ #define ORDERCBLKNEDI 0x0001 /*+ Nested dissection separator node +*/ /* ** The type and structure definitions. */ /*+ Column-block tree node. Each node defines a column block, which is either a separator or a leaf built by nested dissection, or a super-variable built by minimum-degree algorithms. Column blocks are given in ascending order within sub-arrays, for proper infix traversal. +*/ typedef struct OrderCblk_ { int typeval; /*+ Type of tree node +*/ Gnum vnodnbr; /*+ Number of node vertices in subtree +*/ Gnum cblknbr; /*+ Number of descendent column blocks +*/ struct OrderCblk_ * cblktab; /*+ Sub-array of column-blocks +*/ } OrderCblk; /*+ Ordering structure. A block ordering is defined by its inverse permutation peritab and by the tree of permuted ordering blocks, which, once flattened, defines the blocks of the ordering. For the sake of consistency between orderings that have been produced either from graphs or meshes, all ordering values are based from baseval. +*/ typedef struct Order_ { int flagval; /*+ Flag value +*/ Gnum baseval; /*+ Base value for structures +*/ Gnum vnodnbr; /*+ Number of node vertices +*/ Gnum treenbr; /*+ Number of column block tree nodes +*/ Gnum cblknbr; /*+ Number of column blocks +*/ OrderCblk cblktre; /*+ Root of column block tree +*/ Gnum * peritab; /*+ Inverse permutation array [vnodnbr] +*/ } Order; /* ** The function prototypes. */ #ifndef ORDER #define static #endif int orderInit (Order * const, const Gnum, const Gnum, Gnum * const); void orderExit (Order * const); static void orderExit2 (OrderCblk * const, const Gnum); int orderLoad (Order * restrict const, const Gnum * restrict const, FILE * restrict const); int orderSave (const Order * restrict const, const Gnum * restrict const, FILE * restrict const); int orderSaveMap (const Order * const, const Gnum * restrict const, FILE * restrict const); int orderSaveTree (const Order * const, const Gnum * restrict const, FILE * restrict const); void orderPeri (const Gnum * const, const Gnum, const Gnum, Gnum * const, const Gnum); void orderRang (const Order * const, Gnum * const); static void orderRang2 (Gnum ** const, Gnum * const, const OrderCblk * const); void orderTree (const Order * restrict const, Gnum * restrict const); static void orderTree2 (Gnum * restrict const, Gnum * restrict const, const OrderCblk * restrict const, Gnum); int orderCheck (const Order * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/dmapping_io.c0000644000175300017530000002625611631334325021600 0ustar hazelscthazelsct/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dmapping_io.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles distributed **/ /** mappings. **/ /** **/ /** DATES : # Version 5.1 : from : 13 jun 2008 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DORDER #include "module.h" #include "common.h" #include "comm.h" #include "dgraph.h" #include "dgraph_allreduce.h" #include "arch.h" #include "dmapping.h" /************************************/ /* */ /* These routines handle orderings. */ /* */ /************************************/ DGRAPHALLREDUCEMAXSUMOP (1, 5) /* This routine saves a distributed mapping. ** The distributed graph structure is provided ** to access the distribution of vertex labels, ** whenever present. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dmapSave ( const Dmapping * restrict const dmapptr, const Dgraph * restrict const grafptr, FILE * restrict const stream) { const DmappingFrag * restrict fragptr; Gnum fragglbnbr; Gnum * restrict termloctab; Gnum * restrict termrcvtab; Gnum vertrcvmax; Gnum vertglbnbr; Gnum * restrict vlbltax; Gnum reduloctab[6]; Gnum reduglbtab[6]; int protnum; reduloctab[0] = dmapptr->vertlocmax; reduloctab[1] = dmapptr->vertlocnbr; reduloctab[2] = dmapptr->fragnbr; if (stream != NULL) { /* If file provided */ reduloctab[3] = 1; /* This process is the root */ reduloctab[4] = grafptr->proclocnum; /* Get its rank */ } else { reduloctab[3] = /* This process is not the root */ reduloctab[4] = 0; } reduloctab[5] = (grafptr->vlblloctax != NULL) ? 1 : 0; /* See if vertex labels provided */ if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 1, 5, grafptr->proccomm) != 0) { errorPrint ("dmapSave: communication error (1)"); return (1); } if (reduglbtab[3] != 1) { errorPrint ("dmapSave: should have only one root"); return (1); } if ((reduglbtab[5] != 0) && (reduglbtab[5] != grafptr->procglbnbr)) { errorPrint ("dmapSave: inconsistent parameters"); return (1); } if ((reduglbtab[1] < 0) && (reduglbtab[1] > grafptr->procglbnbr)) { errorPrint ("dmapSave: invalid mapping (1)"); return (1); } vertrcvmax = reduglbtab[0]; /* Size of largest fragment to receive */ vertglbnbr = reduglbtab[1]; fragglbnbr = reduglbtab[2]; protnum = (int) reduglbtab[4]; /* Get rank of root process */ reduloctab[0] = 0; if (protnum == grafptr->proclocnum) { Gnum vlblnbr; vlblnbr = (grafptr->vlblloctax != NULL) ? grafptr->vertglbnbr : 0; if ((termloctab = memAllocGroup ((void **) (void *) /* termloctab not used on root processor, but used only for freeing the block */ &termrcvtab, (size_t) (vertrcvmax * 2 * sizeof (Gnum)), /* TRICK: "*2" as vnumrcvtab is sent after termrcvtab */ &vlbltax, (size_t) (vlblnbr * sizeof (Gnum)), NULL)) == NULL) { errorPrint ("dmapSave: out of memory (1)"); reduloctab[0] = 1; } else if (fprintf (stream, GNUMSTRING "\n", (Gnum) vertglbnbr) == EOF) { errorPrint ("dmapSave: bad output (1)"); reduloctab[0] = 1; } } else { vlbltax = NULL; /* Prevent Valgrind from yelling */ if ((termloctab = memAlloc (dmapptr->vertlocmax * sizeof (Gnum))) == NULL) { errorPrint ("dmapSave: out of memory (2)"); reduloctab[0] = 1; } } #ifdef SCOTCH_DEBUG_DMAP1 /* This communication cannot be covered by a useful one */ if (MPI_Allreduce (reduloctab, reduglbtab, 1, GNUM_MPI, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dmapSave: communication error (2)"); reduglbtab[0] = 1; } #else /* SCOTCH_DEBUG_DMAP1 */ reduglbtab[0] = reduloctab[0]; #endif /* SCOTCH_DEBUG_DMAP1 */ if (reduglbtab[0] != 0) { if (termloctab != NULL) memFree (termloctab); /* Free group leader */ return (1); } if (grafptr->vlblloctax != NULL) { if (commGatherv (grafptr->vlblloctax + grafptr->baseval, grafptr->vertlocnbr, GNUM_MPI, vlbltax, grafptr->proccnttab, grafptr->procdsptab, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dmapSave: communication error (3)"); return (1); } vlbltax -= grafptr->baseval; /* Base label array */ } if (protnum == grafptr->proclocnum) { Gnum vertrcvnbr; Gnum * restrict vnumrcvptr; Gnum * restrict termrcvptr; for (fragptr = dmapptr->fragptr; fragptr != NULL; fragptr = fragptr->nextptr) { /* Output local fragments */ Gnum fraglocnum; for (fraglocnum = 0; fraglocnum < fragptr->vertnbr; fraglocnum ++) { Gnum vnumnum; Gnum termnum; vnumnum = fragptr->vnumtab[fraglocnum]; #ifdef SCOTCH_DEBUG_DMAP2 if ((vnumnum < 0) || (vnumnum >= (grafptr->vertglbnbr + grafptr->baseval))) { errorPrint ("dmapSave: invalid mapping (2)"); return (1); } #endif /* SCOTCH_DEBUG_DMAP2 */ termnum = archDomNum (&dmapptr->archdat, &fragptr->domntab[fragptr->parttab[fraglocnum]]); if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", (Gnum) ((grafptr->vlblloctax != NULL) ? vlbltax[vnumnum] : vnumnum), (Gnum) termnum) == EOF) { errorPrint ("dmapSave: bad output (2)"); reduloctab[0] = 1; break; } } } for (fragglbnbr -= dmapptr->fragnbr; fragglbnbr > 0; fragglbnbr --) { /* For all non-local fragments */ Gnum * restrict termrcvnnd; MPI_Status statdat; int recvnbr; if (MPI_Recv (termrcvtab, (int) (vertrcvmax * 2), GNUM_MPI, MPI_ANY_SOURCE, MPI_ANY_TAG, grafptr->proccomm, &statdat) != MPI_SUCCESS) { errorPrint ("dmapSave: communication error (4)"); /* TRICK: "*2" as vnumrcvtab is sent after termrcvtab */ return (1); } if (reduloctab[0] != 0) continue; MPI_Get_count (&statdat, GNUM_MPI, &recvnbr); vertrcvnbr = (Gnum) (recvnbr / 2); /* We received a composite message made of both vectors */ vnumrcvptr = termrcvtab + vertrcvnbr; /* Vertex index array is just after terminal number array */ for (termrcvptr = termrcvtab, termrcvnnd = termrcvtab + vertrcvnbr; termrcvptr < termrcvnnd; termrcvptr ++, vnumrcvptr ++) { if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", (Gnum) ((grafptr->vlblloctax != NULL) ? vlbltax[*vnumrcvptr] : *vnumrcvptr), (Gnum) *termrcvptr) == EOF) { errorPrint ("dmapSave: bad output (3)"); reduloctab[0] = 1; break; } } } } else { int typecnttab[2]; MPI_Aint typedsptab[2]; MPI_Datatype typedat; for (fragptr = dmapptr->fragptr; fragptr != NULL; fragptr = fragptr->nextptr) { /* Output local fragments */ Gnum fraglocnum; for (fraglocnum = 0; fraglocnum < fragptr->vertnbr; fraglocnum ++) { #ifdef SCOTCH_DEBUG_DMAP2 Gnum vnumnum; vnumnum = fragptr->vnumtab[fraglocnum]; if ((vnumnum < 0) || (vnumnum >= (grafptr->vertglbnbr + grafptr->baseval))) { errorPrint ("dmapSave: invalid mapping (3)"); return (1); } #endif /* SCOTCH_DEBUG_DMAP2 */ termloctab[fraglocnum] = archDomNum (&dmapptr->archdat, &fragptr->domntab[fragptr->parttab[fraglocnum]]); } MPI_Address (termloctab, &typedsptab[0]); MPI_Address (fragptr->vnumtab, &typedsptab[1]); typedsptab[1] -= typedsptab[0]; typedsptab[0] = 0; typecnttab[0] = typecnttab[1] = (int) fragptr->vertnbr; MPI_Type_hindexed (2, typecnttab, typedsptab, GNUM_MPI, &typedat); MPI_Type_commit (&typedat); if (MPI_Send (termloctab, 1, typedat, protnum, 0, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dmapSave: communication error (5)"); return (1); } MPI_Type_free (&typedat); } } memFree (termloctab); /* Free group leader */ #ifdef SCOTCH_DEBUG_DMAP1 /* This communication cannot be covered by a useful one */ if (MPI_Allreduce (reduloctab, reduglbtab, 1, GNUM_MPI, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dmapSave: communication error (6)"); reduglbtab[0] = 1; } #else /* SCOTCH_DEBUG_DMAP1 */ reduglbtab[0] = reduloctab[0]; #endif /* SCOTCH_DEBUG_DMAP1 */ return ((int) reduglbtab[0]); } scotch-5.1.12b.dfsg/src/libscotch/dorder.c0000644000175300017530000003036511631334325020565 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dorder.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles distributed **/ /** orderings. **/ /** **/ /** DATES : # Version 5.0 : from : 18 apr 2006 **/ /** to 28 jul 2006 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DORDER #include "module.h" #include "common.h" #include "dgraph.h" #include "dorder.h" /************************************/ /* */ /* These routines handle orderings. */ /* */ /************************************/ /* This routine initializes a distributed ** ordering with respect to the given parameters. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dorderInit ( Dorder * restrict const ordeptr, const Gnum baseval, const Gnum vnodglbnbr, MPI_Comm proccomm) { ordeptr->baseval = baseval; ordeptr->vnodglbnbr = vnodglbnbr; ordeptr->cblklocnbr = 0; ordeptr->linkdat.nextptr = &ordeptr->linkdat; /* Loop double-chained list */ ordeptr->linkdat.prevptr = &ordeptr->linkdat; MPI_Comm_dup (proccomm, &ordeptr->proccomm); /* Duplicate communicator to avoid lifespan problems */ MPI_Comm_rank (ordeptr->proccomm, &ordeptr->proclocnum); #ifdef SCOTCH_PTHREAD pthread_mutex_init (&ordeptr->mutelocdat, NULL); /* Initialize local mutex */ #endif /* SCOTCH_PTHREAD */ return (0); } /* This routine frees the column blocks ** of the given distributed ordering. ** It returns: ** - void : in all cases. */ static void dorderFreeCblk ( DorderCblk * restrict const cblkptr) { #ifdef SCOTCH_DEBUG_DORDER2 if ((cblkptr->typeval < DORDERCBLKNEDI) || (cblkptr->typeval > (DORDERCBLKNEDI | DORDERCBLKLEAF))) errorPrint ("dorderFreeCblk: invalid column block type"); #endif /* SCOTCH_DEBUG_DORDER2 */ if ((cblkptr->typeval & DORDERCBLKLEAF) != 0) { memFree (cblkptr->data.leaf.periloctab); if (cblkptr->data.leaf.nodeloctab != NULL) memFree (cblkptr->data.leaf.nodeloctab); } memFree (cblkptr); /* Free column block structure */ } void dorderFree ( Dorder * restrict const ordeptr) { DorderCblk * cblkptr; DorderLink * linkptr; for (linkptr = ordeptr->linkdat.nextptr; linkptr != &ordeptr->linkdat; ) { cblkptr = (DorderCblk *) linkptr; /* TRICK: FIRST */ linkptr = linkptr->nextptr; dorderFreeCblk (cblkptr); } ordeptr->linkdat.nextptr = /* Loop double-chained list */ ordeptr->linkdat.prevptr = &ordeptr->linkdat; } /* This routine frees the contents ** of the given ordering. ** It returns: ** - void : in all cases. */ void dorderExit ( Dorder * restrict const ordeptr) { dorderFree (ordeptr); MPI_Comm_free (&ordeptr->proccomm); /* Free duplicated communicator */ #ifdef SCOTCH_PTHREAD pthread_mutex_destroy (&ordeptr->mutelocdat); /* Destroy local mutex */ #endif /* SCOTCH_PTHREAD */ #ifdef SCOTCH_DEBUG_DORDER2 memSet (ordeptr, ~0, sizeof (Dorder)); #endif /* SCOTCH_DEBUG_DORDER2 */ } /* This routine creates the root column ** block slot in the given distributed ** ordering structure. ** It returns: ** - !NULL : root column block. ** - NULL : on error. */ DorderCblk * dorderFrst ( Dorder * const ordeptr) { DorderCblk cblkdat; DorderCblk * cblkptr; cblkdat.ordelocptr = ordeptr; /* Fake father node */ cblkdat.cblknum.proclocnum = 0; /* Belongs to process 0 to ease displacement computations */ cblkdat.cblknum.cblklocnum = -1; if ((cblkptr = dorderNew (&cblkdat, ordeptr->proccomm)) == NULL) return (NULL); cblkptr->ordeglbval = 0; /* Un-based inverse permutation index */ cblkptr->vnodglbnbr = ordeptr->vnodglbnbr; cblkptr->cblkfthnum = 0; return (cblkptr); } /* This routine gives back a new distributed ** column block slot in the same ordering ** structure as the given column block. ** It returns: ** - !NULL : new column block. ** - NULL : on error. */ DorderCblk * dorderNew ( DorderCblk * const cblkptr, /* One of the column blocks */ MPI_Comm proccomm) /* Communicator sharing the block */ { Dorder * restrict ordeptr; DorderCblk * restrict cblknewptr; Gnum reduloctab[3]; Gnum reduglbtab[3]; int proclocnum; MPI_Comm_rank (proccomm, &proclocnum); ordeptr = cblkptr->ordelocptr; reduloctab[1] = /* Assume process is not root for this column block */ reduloctab[2] = 0; if ((cblknewptr = (DorderCblk *) memAlloc (sizeof (DorderCblk))) == NULL) { errorPrint ("dorderNew: out of memory"); reduloctab[0] = 2; /* Indicate error without doubt */ } else { reduloctab[0] = 0; if (proclocnum == 0) { /* If root of sub-tree */ reduloctab[0] = 1; /* Indicate it is the root */ reduloctab[1] = ordeptr->proclocnum; /* Broadcast global rank of block root */ #ifdef SCOTCH_PTHREAD pthread_mutex_lock (&ordeptr->mutelocdat); /* Lock local mutex */ #endif /* SCOTCH_PTHREAD */ reduloctab[2] = ordeptr->cblklocnbr ++; /* One more root block in local ordering */ #ifdef SCOTCH_PTHREAD pthread_mutex_unlock (&ordeptr->mutelocdat); /* Unlock local mutex */ #endif /* SCOTCH_PTHREAD */ } } if (MPI_Allreduce (&reduloctab, &reduglbtab, 3, GNUM_MPI, MPI_SUM, proccomm) != MPI_SUCCESS) { errorPrint ("dorderNew: communication error"); return (NULL); } if (reduglbtab[0] != 1) { errorPrint ("dorderNew: cannot create new node"); if (cblknewptr != NULL) memFree (cblknewptr); return (NULL); } cblknewptr->ordelocptr = ordeptr; cblknewptr->typeval = DORDERCBLKNONE; cblknewptr->fathnum = cblkptr->cblknum; cblknewptr->cblknum.proclocnum = (int) reduglbtab[1]; cblknewptr->cblknum.cblklocnum = reduglbtab[2]; #ifdef SCOTCH_PTHREAD pthread_mutex_lock (&ordeptr->mutelocdat); /* Lock local mutex */ #endif /* SCOTCH_PTHREAD */ cblknewptr->linkdat.nextptr = &ordeptr->linkdat; /* Link new block at end of local ordering node list */ cblknewptr->linkdat.prevptr = ordeptr->linkdat.prevptr; ordeptr->linkdat.prevptr->nextptr = &cblknewptr->linkdat; ordeptr->linkdat.prevptr = &cblknewptr->linkdat; #ifdef SCOTCH_PTHREAD pthread_mutex_unlock (&ordeptr->mutelocdat); /* Unlock local mutex */ #endif /* SCOTCH_PTHREAD */ return (cblknewptr); } /* This routine gives back a new centralized ** column block slot in the same ordering ** structure as the given column block. ** It returns: ** - !NULL : new column block. ** - NULL : on error. */ DorderCblk * dorderNewSequ ( DorderCblk * const cblkptr) /* One of the column blocks */ { Dorder * restrict ordeptr; DorderCblk * restrict cblknewptr; if ((cblknewptr = (DorderCblk *) memAlloc (sizeof (DorderCblk))) == NULL) { errorPrint ("dorderNewSequ: out of memory"); return (NULL); } ordeptr = cblkptr->ordelocptr; cblknewptr->ordelocptr = ordeptr; cblknewptr->typeval = DORDERCBLKNONE; cblknewptr->fathnum = cblkptr->cblknum; cblknewptr->cblknum.proclocnum = ordeptr->proclocnum; /* Node belongs to this process */ #ifdef SCOTCH_PTHREAD pthread_mutex_lock (&ordeptr->mutelocdat); /* Lock local mutex */ #endif /* SCOTCH_PTHREAD */ cblknewptr->cblknum.cblklocnum = ordeptr->cblklocnbr ++; /* One more locally-rooted block in ordering */ cblknewptr->linkdat.nextptr = &ordeptr->linkdat; /* Link new block at end of local ordering node list */ cblknewptr->linkdat.prevptr = ordeptr->linkdat.prevptr; ordeptr->linkdat.prevptr->nextptr = &cblknewptr->linkdat; ordeptr->linkdat.prevptr = &cblknewptr->linkdat; #ifdef SCOTCH_PTHREAD pthread_mutex_unlock (&ordeptr->mutelocdat); /* Unlock local mutex */ #endif /* SCOTCH_PTHREAD */ return (cblknewptr); } /* This routine gives back a new centralized ** index range in the same ordering structure ** as the given column block. ** It returns: ** - !NULL : new column block. ** - NULL : on error. */ Gnum dorderNewSequIndex ( DorderCblk * const cblkptr, /* One of the column blocks */ const Gnum cblknbr) /* Number of indices to reserve */ { Dorder * restrict ordeptr; Gnum cblklocnum; ordeptr = cblkptr->ordelocptr; #ifdef SCOTCH_PTHREAD pthread_mutex_lock (&ordeptr->mutelocdat); /* Lock local mutex */ #endif /* SCOTCH_PTHREAD */ cblklocnum = ordeptr->cblklocnbr; /* Get current local index number */ ordeptr->cblklocnbr += cblknbr; /* These more root blocks in local ordering */ #ifdef SCOTCH_PTHREAD pthread_mutex_unlock (&ordeptr->mutelocdat); /* Unlock local mutex */ #endif /* SCOTCH_PTHREAD */ return (cblklocnum); } /* This routine removes a no longer used ** column block from the given distributed ** ordering. Leaves or locally-rooted column ** blocks are kept, others are removed. ** It returns: ** - void : in all cases. */ void dorderDispose ( DorderCblk * const cblkptr) /* Column block to consider */ { Dorder * restrict ordeptr; ordeptr = cblkptr->ordelocptr; if (cblkptr->cblknum.proclocnum == ordeptr->proclocnum) /* If node is local root of column block, keep it */ return; if ((cblkptr->typeval & DORDERCBLKLEAF) == 0) { /* If node is not non-rooted leaf of distributed ordering */ #ifdef SCOTCH_PTHREAD pthread_mutex_lock (&ordeptr->mutelocdat); /* Lock local mutex */ #endif /* SCOTCH_PTHREAD */ cblkptr->linkdat.nextptr->prevptr = cblkptr->linkdat.prevptr; /* Unchain node from double-chained list */ cblkptr->linkdat.prevptr->nextptr = cblkptr->linkdat.nextptr; #ifdef SCOTCH_PTHREAD pthread_mutex_unlock (&ordeptr->mutelocdat); /* Unlock local mutex */ #endif /* SCOTCH_PTHREAD */ memFree (cblkptr); } } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_th.c0000644000175300017530000001130111631334325023141 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : separate_th.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module thins a vertex separator. **/ /** **/ /** DATES : # Version 3.3 : from : 17 oct 1998 **/ /** to 17 oct 1998 **/ /** # Version 4.0 : from : 12 dec 2001 **/ /** to 06 jan 2002 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VGRAPH_SEPARATE_TH #include "module.h" #include "common.h" #include "graph.h" #include "vgraph.h" #include "vgraph_separate_th.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the bipartitioning. ** It returns: ** - 0 : if the bipartitioning could be computed. ** - !0 : on error. */ int vgraphSeparateTh ( Vgraph * const grafptr) { Gnum fronnbr; /* Current number of frontier vertices */ Gnum fronnum; /* Number of current frontier vertex */ Gnum commcut[3]; /* Cut count array ([3] for halo) */ fronnbr = grafptr->fronnbr; /* Get current number of frontier vertices */ for (fronnum = 0; fronnum < fronnbr; ) { Gnum vertnum; Gnum edgenum; vertnum = grafptr->frontab[fronnum]; /* Get vertex number */ commcut[0] = commcut[1] = commcut[2] = 0; for (edgenum = grafptr->s.verttax[vertnum]; edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) commcut[grafptr->parttax[grafptr->s.edgetax[edgenum]]] ++; if (commcut[0] == 0) { grafptr->parttax[vertnum] = 1; grafptr->compload[1] += (grafptr->s.velotax == NULL) ? 1 : grafptr->s.velotax[vertnum]; grafptr->compsize[1] ++; grafptr->frontab[fronnum] = grafptr->frontab[-- fronnbr]; /* Replace frontier vertex by another */ } else if (commcut[1] == 0) { grafptr->parttax[vertnum] = 0; grafptr->compload[0] += (grafptr->s.velotax == NULL) ? 1 : grafptr->s.velotax[vertnum]; grafptr->compsize[0] ++; grafptr->frontab[fronnum] = grafptr->frontab[-- fronnbr]; /* Replace frontier vertex by another */ } else fronnum ++; /* Keep vertex in separator */ } grafptr->fronnbr = fronnbr; /* Set new frontier parameters */ grafptr->compload[2] = grafptr->s.velosum - (grafptr->compload[0] + grafptr->compload[1]); grafptr->comploaddlt = grafptr->compload[0] - grafptr->compload[1]; return (0); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_allreduce.h0000644000175300017530000001070111631334325022570 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /**********************************************************/ /* */ /* NAME : dgraph_allreduce.h */ /* */ /* AUTHOR : Francois PELLEGRINI */ /* */ /* FUNCTION : These lines are the data declarations */ /* for the communication routines */ /* */ /* # Version 5.0 : from : 28 aug 2006 */ /* to 29 aug 2006 */ /* */ /**********************************************************/ /* ** The defines. */ /*+ Combined maximum-sum reduction operator +*/ #define DGRAPHALLREDUCEMAXSUMOP(m,s) \ static \ void \ dgraphAllreduceMaxSumOp##m##_##s ( \ const Gnum * const in, /* First operand */ \ Gnum * const inout, /* Second and output operand */ \ const int * const len, /* Number of instances ; should be 1, not used */ \ const MPI_Datatype * const typedat) /* MPI datatype ; not used */ \ { \ int i; \ \ for (i = 0; i < (m); i ++) /* Perform maximum on first part of data array */ \ if (in[i] > inout[i]) \ inout[i] = in[i]; \ \ for ( ; i < ((m) + (s)); i ++) /* Perform sum on second part of data array */ \ inout[i] += in[i]; \ } #define dgraphAllreduceMaxSum(rlt,rgt,m,s,comm) dgraphAllreduceMaxSum2 ((rlt), (rgt), (m) + (s), (MPI_User_function *) (dgraphAllreduceMaxSumOp##m##_##s), (comm)) /* ** The function prototypes. */ int dgraphAllreduceMaxSum2 (Gnum *, Gnum *, int, MPI_User_function *, MPI_Comm); scotch-5.1.12b.dfsg/src/libscotch/hdgraph_gather.c0000644000175300017530000005241511631334325022255 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph_gather.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the routine which **/ /** builds a centralized halo graph by **/ /** gathering the pieces of a distributed **/ /** halo graph. **/ /** **/ /** DATES : # Version 5.0 : from : 19 apr 2006 **/ /** to : 10 sep 2007 **/ /** # Version 5.1 : from : 30 jul 2010 **/ /** to : 30 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HDGRAPH_GATHER #include "module.h" #include "common.h" #include "comm.h" #include "graph.h" #include "hgraph.h" #include "dgraph.h" #include "hdgraph.h" /******************************/ /* */ /* These routines handle halo */ /* distributed source graphs. */ /* */ /******************************/ /* This function gathers the pieces of ** a distributed halo graph to build a ** centralized halo graph. ** There is no gathered vnumtab array if ** the original graph did not have one, as ** vertices are gathered in global order, or ** else the original vnumloctab is gathered. ** It returns: ** - 0 : if graph data are consistent. ** - !0 : on error. */ int hdgraphGather ( Hdgraph * restrict const dgrfptr, /* Distributed halo graph */ Hgraph * restrict const cgrfptr) /* Centralized halo graph */ { Gnum vertlocnum; Gnum vertlocadj; /* Local vertex array adjust */ Gnum vhallocnnd; int vhallocnbr; /* Local copy for sending as a MPI_INT */ Gnum * restrict verthaltax; Gnum * restrict edgehaltax; Gnum edgehalnum; int ehallocnbr; /* Local copy for sending as a MPI_INT */ int rootnum; /* Index of root process */ Gnum reduloctab[4]; /* Arrays for reductions */ Gnum reduglbtab[4]; int * restrict recvcnttab; /* Arrays for parametrizing gather operations */ int * restrict recvdsptab; int cheklocval; int chekglbval; Gnum degrmax; if (cgrfptr != NULL) { /* If centralized graph provided */ reduloctab[0] = 1; /* This process is the root */ reduloctab[1] = (Gnum) dgrfptr->s.proclocnum; /* Get its rank */ } else { reduloctab[0] = /* This process is not the root */ reduloctab[1] = 0; } reduloctab[2] = dgrfptr->vhallocnbr; reduloctab[3] = dgrfptr->ehallocnbr; if (MPI_Allreduce (reduloctab, reduglbtab, 4, GNUM_MPI, MPI_SUM, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (1)"); return (1); } if (reduglbtab[0] != 1) { errorPrint ("hdgraphGather: should have only one root"); return (1); } rootnum = (int) reduglbtab[1]; /* Get rank of root process */ degrmax = dgrfptr->s.degrglbmax; /* Distributed degree does not account for halo edges */ cheklocval = 0; if (cgrfptr != NULL) { /* If process is root */ Gnum vnohnbr; Gnum vertnbr; Gnum velonbr; Gnum vnumnbr; Gnum * restrict velotax; Gnum * restrict vnumtax; Gnum edgenbr; vnohnbr = dgrfptr->s.vertglbnbr; vertnbr = vnohnbr + reduglbtab[2]; velonbr = (dgrfptr->s.veloloctax != NULL) ? vertnbr : 0; vnumnbr = (dgrfptr->s.vnumloctax != NULL) ? vnohnbr : 0; /* Vertex numbers only serve for non-halo vertices */ edgenbr = dgrfptr->s.edgeglbnbr + 2 * reduglbtab[3]; /* Twice since halo vertices will be created for real */ cgrfptr->s.flagval = GRAPHFREEEDGE | GRAPHEDGEGROUP | GRAPHFREEVERT | GRAPHVERTGROUP; /* In case of premature freeing on error */ recvcnttab = NULL; if (memAllocGroup ((void **) (void *) &cgrfptr->s.verttax, (size_t) ((vertnbr + 1) * sizeof (Gnum)), /* Compact vertex array */ &velotax, (size_t) (velonbr * sizeof (Gnum)), &vnumtax, (size_t) (vnumnbr * sizeof (Gnum)), &cgrfptr->vnhdtax, (size_t) (vnohnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("hdgraphGather: out of memory (1)"); cheklocval = 1; } else if (cgrfptr->s.verttax -= dgrfptr->s.baseval, cgrfptr->s.velotax = (dgrfptr->s.veloloctax != NULL) ? velotax - dgrfptr->s.baseval : NULL, cgrfptr->s.vnumtax = (dgrfptr->s.vnumloctax != NULL) ? vnumtax - dgrfptr->s.baseval : NULL, cgrfptr->vnhdtax -= dgrfptr->s.baseval, ((cgrfptr->s.edgetax = (Gnum *) memAlloc (edgenbr * sizeof (Gnum))) == NULL)) { errorPrint ("hdgraphGather: out of memory (2)"); cheklocval = 1; } else if (cgrfptr->s.edgetax -= dgrfptr->s.baseval, memAllocGroup ((void **) (void *) &recvcnttab, (size_t) (dgrfptr->s.procglbnbr * sizeof (int)), &recvdsptab, (size_t) (dgrfptr->s.procglbnbr * sizeof (int)), NULL) == NULL) { errorPrint ("hdgraphGather: out of memory (3)"); cheklocval = 1; } else { cgrfptr->s.baseval = dgrfptr->s.baseval; cgrfptr->s.vertnbr = vertnbr; cgrfptr->s.vertnnd = vertnbr + dgrfptr->s.baseval; cgrfptr->s.vendtax = cgrfptr->s.verttax + 1; /* Compact edge array */ cgrfptr->s.velosum = dgrfptr->s.veloglbsum + reduglbtab[2]; /* Halo vertices have unity vertex loads */ cgrfptr->s.vlbltax = NULL; cgrfptr->s.edgenbr = edgenbr; cgrfptr->s.edlotax = NULL; cgrfptr->s.edlosum = edgenbr; cgrfptr->s.proccomm = MPI_COMM_NULL; /* Not a multi-sequential gather: no communication possible */ cgrfptr->s.procglbnbr = cgrfptr->s.proclocnum = 0; cgrfptr->vnohnbr = vnohnbr; cgrfptr->vnohnnd = vnohnbr + dgrfptr->s.baseval; cgrfptr->vnlosum = dgrfptr->s.veloglbsum; cgrfptr->enohnbr = cgrfptr->enohsum = dgrfptr->s.edgeglbnbr; cgrfptr->levlnum = dgrfptr->levlnum; } } if ((cheklocval == 0) && (memAllocGroup ((void **) (void *) &verthaltax, (size_t) (dgrfptr->vhallocnbr * sizeof (Gnum)), &edgehaltax, (size_t) (dgrfptr->ehallocnbr * sizeof (Gnum)), NULL) == NULL)) { errorPrint ("hdgraphGather: out of memory (4)"); cheklocval = 1; } else { verthaltax -= dgrfptr->s.baseval; edgehaltax -= dgrfptr->s.baseval; } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_SUM, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (2)"); return (1); } if (chekglbval != 0) { if (verthaltax != NULL) memFree (verthaltax + dgrfptr->s.baseval); if (cgrfptr != NULL) { /* If data were previously allocated */ if (recvcnttab != NULL) memFree (recvcnttab); hgraphExit (cgrfptr); } return (1); } if (dgrfptr->vhndloctax == dgrfptr->s.vertloctax + 1) { /* If distributed halo graph is compact */ Gnum procglbnum; Gnum edgenum; if (cgrfptr != NULL) { Gnum vertnum; cgrfptr->s.verttax[dgrfptr->s.baseval] = dgrfptr->s.baseval; if (commGatherv (dgrfptr->s.vertloctax + 1 + dgrfptr->s.baseval, /* Do not send first index, it is always equal to baseval */ dgrfptr->s.vertlocnbr, GNUM_MPI, cgrfptr->s.verttax + 1, /* First index will always be equal to baseval too, and procdsptab holds based values */ dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (3)"); return (1); } if (commGatherv (dgrfptr->s.vendloctax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GNUM_MPI, cgrfptr->vnhdtax, /* procdsptab holds based values */ dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (4)"); return (1); } for (procglbnum = 1, vertnum = dgrfptr->s.procdsptab[1] + 1; /* Adjust index sub-arrays for all processors except the first one */ procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) { Gnum vertnnd; Gnum edgeadj; for (vertnnd = dgrfptr->s.procdsptab[procglbnum + 1] + 1, edgeadj = cgrfptr->s.verttax[vertnum - 1] - dgrfptr->s.baseval; vertnum < vertnnd; vertnum ++) { cgrfptr->s.verttax[vertnum] += edgeadj; cgrfptr->vnhdtax[vertnum - 1] += edgeadj; } } for (procglbnum = 0, edgenum = dgrfptr->s.baseval; /* Build arrays for MPI_Gatherv on edge arrays */ procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) { recvcnttab[procglbnum] = cgrfptr->s.verttax[dgrfptr->s.procdsptab[procglbnum + 1]] - cgrfptr->s.verttax[dgrfptr->s.procdsptab[procglbnum]]; /* verttax used twice since centralized graph is compact */ recvdsptab[procglbnum] = edgenum; edgenum += recvcnttab[procglbnum]; } if (MPI_Gatherv (dgrfptr->s.edgeloctax + dgrfptr->s.baseval, /* Gather edge arrays with global vertex indices */ (int) (dgrfptr->s.edgelocnbr + dgrfptr->ehallocnbr), GNUM_MPI, cgrfptr->s.edgetax, recvcnttab, recvdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (5)"); return (1); } } else { if (MPI_Gatherv (dgrfptr->s.vertloctax + 1 + dgrfptr->s.baseval, /* Do not send first index, it is always equal to baseval */ (int) dgrfptr->s.vertlocnbr, GNUM_MPI, NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (6)"); return (1); } if (MPI_Gatherv (dgrfptr->s.vendloctax + dgrfptr->s.baseval, (int) dgrfptr->s.vertlocnbr, GNUM_MPI, NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (7)"); return (1); } if (MPI_Gatherv (dgrfptr->s.edgeloctax + dgrfptr->s.baseval, /* Gather edge arrays with global vertex indices */ (int) (dgrfptr->s.edgelocnbr + dgrfptr->ehallocnbr), GNUM_MPI, NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (8)"); return (1); } } } else { errorPrint ("hdgraphGather: Not implemented"); /* Not really necessary as all Hdgraph structures created by Scotch itself are compact */ return (1); } memSet (verthaltax + dgrfptr->s.baseval, 0, dgrfptr->vhallocnbr * sizeof (Gnum)); /* Initialize halo end vertex count array */ for (vertlocnum = dgrfptr->s.baseval; vertlocnum < dgrfptr->s.vertlocnnd; vertlocnum ++) { Gnum edgelocnum; for (edgelocnum = dgrfptr->s.vendloctax[vertlocnum]; edgelocnum < dgrfptr->vhndloctax[vertlocnum]; edgelocnum ++) verthaltax[dgrfptr->s.edgeloctax[edgelocnum]] ++; /* One more edge to this halo vertex */ } vhallocnbr = (int) dgrfptr->vhallocnbr; if (MPI_Gather (&vhallocnbr, 1, MPI_INT, recvcnttab, 1, MPI_INT, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (9)"); return (1); } if (cgrfptr != NULL) { /* Build gather parameter array to receive halo edge counts */ Gnum procglbnum; Gnum vertnum; for (procglbnum = 0, vertnum = 0; procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) { /* Displacements start from zero because adjusted later */ recvdsptab[procglbnum] = vertnum; vertnum += recvcnttab[procglbnum]; } if (MPI_Gatherv (verthaltax + dgrfptr->s.baseval, (int) dgrfptr->vhallocnbr, GNUM_MPI, /* Gather count arrays of halo vertices */ cgrfptr->s.verttax + cgrfptr->vnohnnd + 1, recvcnttab, recvdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (10)"); return (1); } for (procglbnum = 0, vertnum = dgrfptr->s.baseval; /* Adjust end vertex indices for halo edges */ procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) { Gnum vertnnd; Gnum vertadj; for (vertnnd = dgrfptr->s.procdsptab[procglbnum + 1], vertadj = cgrfptr->vnohnbr + recvdsptab[procglbnum]; vertnum < vertnnd; vertnum ++) { Gnum edgenum; if (degrmax < (cgrfptr->s.vendtax[vertnum] - cgrfptr->s.verttax[vertnum])) /* Account for halo edges in maximum degree */ degrmax = (cgrfptr->s.vendtax[vertnum] - cgrfptr->s.verttax[vertnum]); for (edgenum = cgrfptr->vnhdtax[vertnum]; edgenum < cgrfptr->s.vendtax[vertnum]; edgenum ++) cgrfptr->s.edgetax[edgenum] += vertadj; } } } else { if (MPI_Gatherv (verthaltax + dgrfptr->s.baseval, (int) dgrfptr->vhallocnbr, GNUM_MPI, /* Gather count arrays of halo vertices */ NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (11)"); return (1); } } for (vertlocnum = edgehalnum = dgrfptr->s.baseval, vhallocnnd = dgrfptr->vhallocnbr + dgrfptr->s.baseval; vertlocnum < vhallocnnd; vertlocnum ++) { /* Prepare index array for edge collection */ Gnum degrlocval; degrlocval = verthaltax[vertlocnum]; verthaltax[vertlocnum] = edgehalnum; edgehalnum += degrlocval; } vertlocadj = dgrfptr->s.procdsptab[dgrfptr->s.proclocnum] - dgrfptr->s.baseval; for (vertlocnum = dgrfptr->s.baseval; vertlocnum < dgrfptr->s.vertlocnnd; vertlocnum ++) { /* Collect halo edge ends */ Gnum edgelocnum; for (edgelocnum = dgrfptr->s.vendloctax[vertlocnum]; edgelocnum < dgrfptr->vhndloctax[vertlocnum]; edgelocnum ++) edgehaltax[verthaltax[dgrfptr->s.edgeloctax[edgelocnum]] ++] = vertlocnum + vertlocadj; } ehallocnbr = (int) dgrfptr->ehallocnbr; if (MPI_Gather (&ehallocnbr, 1, MPI_INT, recvcnttab, 1, MPI_INT, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { /* Gather halo edge counts */ errorPrint ("hdgraphGather: communication error (12)"); return (1); } if (cgrfptr != NULL) { /* Compute receive arrays for edge sub-arrays of halo vertices */ Gnum procglbnum; Gnum edgeadj; for (procglbnum = 0, edgeadj = 0; procglbnum < dgrfptr->s.procglbnbr; procglbnum ++) { recvdsptab[procglbnum] = edgeadj; edgeadj += recvcnttab[procglbnum]; } if (MPI_Gatherv (edgehaltax + dgrfptr->s.baseval, (int) dgrfptr->ehallocnbr, GNUM_MPI, /* Gather edge arrays of halo vertices */ cgrfptr->s.edgetax + cgrfptr->enohnbr + reduglbtab[3] + dgrfptr->s.baseval, recvcnttab, recvdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (13)"); return (1); } } else { if (MPI_Gatherv (edgehaltax + dgrfptr->s.baseval, (int) dgrfptr->ehallocnbr, GNUM_MPI, /* Gather edge arrays of halo vertices */ NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (14)"); return (1); } } memFree (verthaltax + dgrfptr->s.baseval); /* Free group leader */ if (cgrfptr != NULL) { /* Finalize vertex and edge arrays of centralized graph */ Gnum vertnum; Gnum edgeadj; if (dgrfptr->s.veloloctax != NULL) { /* Get vertex loads if any */ if (commGatherv (dgrfptr->s.veloloctax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GNUM_MPI, cgrfptr->s.velotax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (15)"); return (1); } for (vertnum = cgrfptr->vnohnnd; vertnum < cgrfptr->s.vertnnd; vertnum ++) /* complete filling of vertex load array */ cgrfptr->s.velotax[vertnum] = 1; } if (dgrfptr->s.vnumloctax != NULL) { /* Get vertex numbers if any */ if (commGatherv (dgrfptr->s.vnumloctax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GNUM_MPI, cgrfptr->s.vnumtax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (16)"); return (1); } } memFree (recvcnttab); /* Free group leader */ for (vertnum = cgrfptr->vnohnnd + 1, edgeadj = cgrfptr->s.verttax[cgrfptr->vnohnnd]; /* Adjust vertex array for halo vertices */ vertnum <= cgrfptr->s.vertnnd; vertnum ++) { Gnum degrval; degrval = cgrfptr->s.verttax[vertnum]; if (degrmax < degrval) /* Account for halo edges in maximum degree */ degrmax = degrval; edgeadj += degrval; cgrfptr->s.verttax[vertnum] = edgeadj; } cgrfptr->s.degrmax = degrmax; } else { if (dgrfptr->s.veloloctax != NULL) { /* Get vertex loads if any */ if (MPI_Gatherv (dgrfptr->s.veloloctax + dgrfptr->s.baseval, (int) dgrfptr->s.vertlocnbr, GNUM_MPI, NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (17)"); return (1); } } if (dgrfptr->s.vnumloctax != NULL) { /* Get vertex numbers if any */ if (MPI_Gatherv (dgrfptr->s.vnumloctax + dgrfptr->s.baseval, (int) dgrfptr->s.vertlocnbr, GNUM_MPI, NULL, NULL, NULL, GNUM_MPI, rootnum, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (18)"); return (1); } } } #ifdef SCOTCH_DEBUG_HDGRAPH2 cheklocval = (cgrfptr != NULL) ? hgraphCheck (cgrfptr) : 0; if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphGather: communication error (19)"); return (1); } if (chekglbval != 0) { errorPrint ("hdgraphGather: internal error"); if (cgrfptr != NULL) hgraphExit (cgrfptr); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_bl.h0000644000175300017530000000633411631334325022433 0ustar hazelscthazelsct/* Copyright 2004,2007,2009,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_bl.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the block splitting algorithm. **/ /** **/ /** DATES : # Version 3.4 : from : 24 jun 2002 **/ /** to 24 jun 2002 **/ /** # Version 4.0 : from : 26 jun 2002 **/ /** to 29 dec 2004 **/ /** # Version 5.1 : from : 01 oct 2009 **/ /** to : 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HgraphOrderBlParam_ { Strat * strat; /*+ Ordering strategy +*/ INT cblkmin; /*+ Block splitting size +*/ } HgraphOrderBlParam; /* ** The function prototypes. */ #ifndef HGRAPH_ORDER_BL #define static #endif int hgraphOrderBl (const Hgraph * const, Order * const, const Gnum, OrderCblk * const, const HgraphOrderBlParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_hx.c0000644000175300017530000001664011631334325022304 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_hx.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains service routines **/ /** for the hmeshOrderH{d|f} ordering **/ /** routines. **/ /** **/ /** DATES : # Version 4.0 : from : 09 dec 2003 **/ /** to : 24 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH_ORDER_HX #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" #include "hmesh.h" #include "hmesh_order_hx.h" /***********************************/ /* */ /* These are the service routines. */ /* */ /***********************************/ /* This routine fills the input arrays for ** the mesh ordering routines. ** It returns: ** - void : in all cases. */ int hmeshOrderHxFill ( const Hmesh * restrict const meshptr, Gnum * restrict const petab, Gnum * restrict const lentab, Gnum * restrict const iwtab, Gnum * restrict const elentab, Gnum * restrict const pfreptr) { Gnum * restrict petax; Gnum * restrict iwtax; Gnum * restrict lentax; Gnum * restrict elentax; HmeshOrderHxHash * restrict hashtab; /* Neighbor hash table */ Gnum hashsiz; Gnum hashmsk; Gnum n; /* Number of nodes to order */ Gnum velmadj; /* Index adjustment for element indices */ Gnum vnodadj; /* Index adjustment for node indices */ Gnum velmnum; Gnum vnodnum; Gnum degrval; Gnum vertnum; Gnum edgenum; n = meshptr->m.velmnbr + meshptr->m.vnodnbr; for (hashsiz = 16, degrval = meshptr->m.degrmax * (meshptr->m.degrmax - 1); /* Compute hash table size */ hashsiz < degrval; hashsiz <<= 1) ; hashsiz <<= 1; hashmsk = hashsiz - 1; if ((hashtab = memAlloc (hashsiz * sizeof (HmeshOrderHxHash))) == NULL) { errorPrint ("hmeshOrderHxFill: out of memory"); return (1); } memSet (hashtab, ~0, hashsiz * sizeof (HmeshOrderHxHash)); petax = petab - 1; /* Base HAMF arrays at base 1 */ iwtax = iwtab - 1; lentax = lentab - 1; elentax = elentab - 1; velmadj = 1 + meshptr->m.vnodnbr - meshptr->m.velmbas; for (vnodnum = meshptr->m.vnodbas, vertnum = edgenum = 1; /* Copy non-halo node data with base 1 */ vnodnum < meshptr->vnohnnd; vertnum ++, vnodnum ++) { Gnum enodnum; Gnum nghbnbr; petax[vertnum] = edgenum; lentax[vertnum] = meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]; for (enodnum = meshptr->m.verttax[vnodnum], nghbnbr = -1; /* -1 since loop edge will be processed in the main loop */ enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { Gnum velmnum; Gnum eelmnum; velmnum = meshptr->m.edgetax[enodnum]; iwtax[edgenum ++] = velmnum + velmadj; /* Adjust end element index */ for (eelmnum = meshptr->m.verttax[velmnum]; eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { Gnum vnodend; Gnum hnodend; vnodend = meshptr->m.edgetax[eelmnum]; for (hnodend = (vnodend * HMESHORDERHXHASHPRIME) & hashmsk; ; hnodend = (hnodend + 1) & hashmsk) { if (hashtab[hnodend].vertnum != vnodnum) { hashtab[hnodend].vertnum = vnodnum; hashtab[hnodend].vertend = vnodend; nghbnbr ++; } if (hashtab[hnodend].vertend == vnodend) /* If end vertex already present */ break; /* Skip to next end vertex */ } } elentax[vertnum] = nghbnbr; } } for ( ; vnodnum < meshptr->m.vnodnnd; vnodnum ++, vertnum ++) { /* Copy halo vertices with base 1 */ Gnum degrval; Gnum enodnum; degrval = meshptr->m.verttax[vnodnum] - meshptr->m.vendtax[vnodnum]; petax[vertnum] = edgenum; lentax[vertnum] = (degrval != 0) ? degrval : - (n + 1); elentax[vertnum] = 0; for (enodnum = meshptr->m.verttax[vnodnum]; enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) iwtax[edgenum ++] = meshptr->m.edgetax[enodnum] + velmadj; /* Adjust end element index */ } vnodadj = 1 - meshptr->m.vnodbas; /* Base nodes at 1 */ for (velmnum = meshptr->m.velmbas; velmnum < meshptr->m.velmnnd; velmnum ++, vertnum ++) { Gnum eelmnum; petax[vertnum] = edgenum; lentax[vertnum] = meshptr->m.vendtax[velmnum] - meshptr->m.verttax[velmnum]; elentax[vertnum] = - (n + 1); for (eelmnum = meshptr->m.verttax[velmnum]; eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) iwtax[edgenum ++] = meshptr->m.edgetax[eelmnum] + vnodadj; /* Adjust end node index */ } *pfreptr = edgenum; /* Set index to first free area */ memFree (hashtab); return (0); } scotch-5.1.12b.dfsg/src/libscotch/hall_order_hx.c0000644000175300017530000003635511631334325022125 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hall_order_hx.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains service routines **/ /** for interfacing the halo ordering **/ /** routines provided by Patrick Amestoy **/ /** with the ones of libScotch. **/ /** **/ /** DATES : # Version 4.0 : from : 13 jan 2003 **/ /** to : 28 dec 2004 **/ /** # Version 5.0 : from : 25 jul 2007 **/ /** to : 29 may 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HALL_ORDER_HX #include "module.h" #include "common.h" #include "graph.h" #include "order.h" #include "hgraph.h" #include "hall_order_hx.h" /*********************/ /* */ /* Service routines. */ /* */ /*********************/ /* This routine post-processes the elimination tree ** produced by Amestoy's halo ordering routines. ** On input, the elimination tree is described by ** nvtab and petab. ** On output, we build an un-based elimination tree ** (that is, based to 0), structured as follows: ** - cblknbr : number of column blocks (that is, ** principal variables). ** - sizetab : sizetab[i] holds the total number of ** variables (principal and secondary) if i is ** a principal variable, or ~0 if i is a secondary ** variable or in halo. (sizetab = lentab) ** - petab : petab[i] holds the father of principal ** variable i, or ~0 if i is a root. ** - frsttab : when i is a principal variable, ** frsttab[i] holds the number of the first principal ** son variable of principal variable i, or ~0 if none. ** If i is a secondary variable or in halo, frsttab[i] ** holds ~0 too. ** - nexttab : linked list of principal son variables. ** When i is a principal variable, j=frsttab[i] is ** its first son (if any), and k=nexttab[j] is the ** second son, and l=nexttab[k] is its third son, and ** so on, or ~0 if none. ** - secntab : linked list of secondary variables. ** When i is a principal variable, secntab[i] holds ** the number of the first secondary variable of ** principal variable i, or ~0 if none. When i is ** a secondary variable, secntab[i] holds the next ** secondary variable in linked list, or ~0 if none. ** It returns: ** - 0 : if data structures have been initialized. ** - !0 : on error. */ int hallOrderHxBuild ( const Gnum baseval, /*+ Base value of graph and permutation +*/ const Gnum vertnbr, /*+ Number of vertices in considered graph +*/ const Gnum vnohnbr, /*+ Number of non-halo vertices in considered graph +*/ const Gnum * restrict const vnumtax, /*+ Vertex number array of subgraph, if subgraph +*/ Order * restrict const ordeptr, /*+ Ordering to update +*/ OrderCblk * restrict const cblkptr, /*+ Multiple column-block of ordering +*/ Gnum * restrict const nvartax, Gnum * restrict const sizetax, Gnum * restrict const fathtax, /*+ Was petab +*/ Gnum * restrict const frsttax, Gnum * restrict const nexttax, Gnum * restrict const secntax, Gnum * restrict const desctax, /*+ Was iwtab +*/ Gnum * restrict const permtax, /*+ Based direct permutation array +*/ Gnum * restrict const peritab, /*+ Un-based inverse permutation array +*/ Gnum * restrict const leaftab, /*+ Un-based array for storage of leaves +*/ const Gnum colmin, const Gnum colmax, const float fillrat) { Gnum vnohnnd; Gnum cblknbr; Gnum cblknum; Gnum leafnbr; Gnum leafnum; Gnum rootnum; Gnum ordetmp; Gnum i, j, k; memSet (desctax + baseval, 0, vertnbr * sizeof (Gnum)); memSet (sizetax + baseval, 0, vertnbr * sizeof (Gnum)); memSet (frsttax + baseval, ~0, vertnbr * sizeof (Gnum)); memSet (secntax + baseval, ~0, vertnbr * sizeof (Gnum)); vnohnnd = vnohnbr + baseval; #ifdef SCOTCH_DEBUG_ORDER2 for (i = baseval; i < vnohnnd; i ++) { if ((fathtax[i] > 0) || (fathtax[i] < - vertnbr)) { errorPrint ("hallOrderHxBuild: elimination tree out of bounds"); return (1); } } #endif /* SCOTCH_DEBUG_ORDER2 */ for (i = baseval, cblknbr = 0, rootnum = ~0; /* Assume no root found yet */ i < vnohnnd; i ++) { if (nvartax[i] != 0) { /* If principal variable */ cblknbr ++; /* One more column block */ sizetax[i] ++; /* One more column */ if ((fathtax[i] < 0) && /* If not root of tree */ (fathtax[i] > - (vnohnbr + 1))) { /* And father not in halo */ fathtax[i] = baseval - (fathtax[i] + 1); /* Re-base father number */ nexttax[i] = frsttax[fathtax[i]]; /* Link vertex to tree */ frsttax[fathtax[i]] = i; /* Variable is first son */ desctax[fathtax[i]] ++; /* Father has one more son */ } else { fathtax[i] = ~0; /* Father is (pseudo-)root */ rootnum = i; /* Record (last) root */ } } else { /* If secondary variable */ fathtax[i] = baseval - (fathtax[i] + 1); /* Re-base father number */ if (fathtax[i] >= vnohnnd) { /* If father in halo */ if (frsttax[fathtax[i]] == ~0) { /* If first such vertex */ cblknbr ++; /* One more column block */ sizetax[i] = 1; /* One more column */ nvartax[i] = 1; /* Make it principal */ frsttax[fathtax[i]] = i; /* Record it as root */ fathtax[i] = ~0; /* Make it (pseudo-)root */ rootnum = i; /* Record (last) root */ continue; /* Skip to next vertex */ } else { fathtax[i] = frsttax[fathtax[i]]; /* Get first such vertex as root */ nvartax[fathtax[i]] ++; /* Record us as secondary variable */ } } sizetax[fathtax[i]] ++; /* One more column */ secntax[i] = secntax[fathtax[i]]; /* Link secondary variable */ secntax[fathtax[i]] = i; } } for (i = baseval, leafnbr = 0; /* Build leaf list for amalgamation */ i < vnohnnd; i ++) { if ((fathtax[i] != ~0) && /* If node has a father */ (nvartax[i] != 0) && /* And is a principal variable */ (frsttax[i] == ~0)) /* And is a leaf */ leaftab[leafnbr ++] = i; /* Add it to leaf list */ } for (leafnum = 0; leafnum < leafnbr; leafnum ++) { /* As long as candidate leaves exist */ i = leaftab[leafnum]; j = fathtax[i]; if ((sizetax[i] + sizetax[j]) <= colmax) { /* If will not be too large */ if ((sizetax[i] < colmin) || /* If column block too small */ (((float) (2 * sizetax[i]) * (float) (nvartax[j] - nvartax[i] + sizetax[i])) < (float) nvartax[j] * (float) nvartax[j] * fillrat)) { nvartax[j] += sizetax[i]; sizetax[j] += sizetax[i]; nvartax[i] = 0; if (secntax[i] == ~0) /* If node had no secondary variables */ secntax[i] = secntax[j]; /* Make it take the ones of its father */ else if (secntax[j] != ~0) { /* Else if there is something to append */ for (k = secntax[i]; secntax[k] != ~0; k = secntax[k]) ; /* Find last node */ secntax[k] = secntax[j]; /* Append father list to node list */ } secntax[j] = i; /* Now he is a secondary variable of it */ if (frsttax[j] == i) { /* If node is first son of father */ if (frsttax[i] == ~0) /* If node has no sons */ frsttax[j] = nexttax[i]; /* First son is now next node */ else { frsttax[j] = frsttax[i]; for (k = frsttax[i]; nexttax[k] != ~0; k = nexttax[k]) fathtax[k] = j; fathtax[k] = j; nexttax[k] = nexttax[i]; } } else { /* Else unlink node from son chain */ for (k = frsttax[j]; nexttax[k] != i; k = nexttax[k]) ; if (frsttax[i] == ~0) /* If node has no sons */ nexttax[k] = nexttax[i]; else { nexttax[k] = frsttax[i]; for (k = frsttax[i]; nexttax[k] != ~0; k = nexttax[k]) fathtax[k] = j; fathtax[k] = j; nexttax[k] = nexttax[i]; } } cblknbr --; /* One less column block */ } } if (((-- desctax[j]) <= 0) && /* If all descendents processed */ (fathtax[j] != ~0)) /* And node has a father */ leaftab[leafnbr ++] = j; /* Enqueue father */ } #ifdef SCOTCH_DEBUG_ORDER2 memSet (peritab, ~0, vnohnbr * sizeof (Gnum)); #endif /* SCOTCH_DEBUG_ORDER2 */ ordetmp = hallOrderHxTree (frsttax, nexttax, secntax, peritab, 0, rootnum); if (ordetmp < vnohnbr) { /* If not all nodes ordered */ for (i = baseval; i < rootnum; i ++) { /* For all potential remaining roots */ if (fathtax[i] == ~0) /* If node is a pseudo-root */ ordetmp = hallOrderHxTree (frsttax, nexttax, secntax, peritab, ordetmp, i); } } #ifdef SCOTCH_DEBUG_ORDER2 if (ordetmp != vnohnbr) { errorPrint ("hallOrderHxBuild: incomplete elimination tree"); return (1); } memSet (permtax + baseval, ~0, vnohnbr * sizeof (Gnum)); for (i = 0; i < vnohnbr; i ++) { if ((peritab[i] < baseval) || (peritab[i] >= vnohnnd)) { errorPrint ("hallOrderHxBuild: permutation out of bounds"); return (1); } if (permtax[peritab[i]] != ~0) { errorPrint ("hallOrderHxBuild: duplicate permutation index"); return (1); } permtax[peritab[i]] = i; } for (i = baseval; i < vnohnnd; i ++) { if (permtax[i] == ~0) { errorPrint ("hallOrderHxBuild: unused permutation index"); return (1); } } #endif /* SCOTCH_DEBUG_ORDER2 */ if (cblknbr != 1) { /* If more than one column block in the end, create subtree */ if ((cblkptr->cblktab = (OrderCblk *) memAlloc (cblknbr * sizeof (OrderCblk))) == NULL) { errorPrint ("hallOrderHxBuild: out of memory"); return (1); } cblkptr->cblknbr = cblknbr; ordeptr->cblknbr += cblknbr - 1; /* These more column blocks created */ ordeptr->treenbr += cblknbr; /* These more tree nodes created */ for (i = 0, cblknum = 0; i < vnohnbr; i ++) { if (nvartax[peritab[i]] == 0) /* If secondary variable */ continue; /* Skip to next vertex */ cblkptr->cblktab[cblknum].typeval = ORDERCBLKOTHR; /* Build column blocks */ cblkptr->cblktab[cblknum].vnodnbr = sizetax[peritab[i]]; cblkptr->cblktab[cblknum].cblknbr = 0; cblkptr->cblktab[cblknum].cblktab = NULL; cblknum ++; /* One more column block created */ } } if (vnumtax != NULL) { /* If graph is not original graph */ for (i = 0; i < vnohnbr; i ++) /* Finalize inverse permutation */ peritab[i] = vnumtax[peritab[i]]; } return (0); } /*+ This routine computes the inverse *** permutation according to the *** elimination tree. *** It returns: *** - >0 : next index to be used to order, in all cases. +*/ Gnum hallOrderHxTree ( const Gnum * restrict const frsttax, const Gnum * restrict const nexttax, const Gnum * restrict const secntax, Gnum * restrict const peritab, const Gnum ordenum, const Gnum nodenum) { Gnum ordetmp; Gnum nodetmp; ordetmp = ordenum; for (nodetmp = frsttax[nodenum]; nodetmp != ~0; nodetmp = nexttax[nodetmp]) ordetmp = hallOrderHxTree (frsttax, nexttax, secntax, peritab, ordetmp, nodetmp); peritab[ordetmp ++] = nodenum; /* Order principal variable */ for (nodetmp = secntax[nodenum]; nodetmp != ~0; nodetmp = secntax[nodetmp]) { peritab[ordetmp ++] = nodetmp; /* Order secondary variables */ } return (ordetmp); } scotch-5.1.12b.dfsg/src/libscotch/parser.c0000644000175300017530000006133011631334325020576 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : parser.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a static mapper. **/ /** This module is the strategy lexical and **/ /** syntactic analyzer. **/ /** **/ /** DATES : # Version 3.1 : from : 07 nov 1995 **/ /** to 02 may 1996 **/ /** # Version 3.2 : from : 07 oct 1996 **/ /** to 19 oct 1996 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 10 sep 2001 **/ /** # Version 4.0 : from : 20 dec 2001 **/ /** to 02 feb 2004 **/ /** # Version 5.0 : from : 20 feb 2008 **/ /** to 20 feb 2008 **/ /** # Version 5.1 : from : 22 oct 2008 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define PARSER #include "module.h" #include "common.h" #undef INTEGER /* In case someone defined them */ #undef DOUBLE #include "parser.h" #include "parser_yy.h" /* ** The static and global variables. */ static StratTab stratdummytab = { NULL, NULL, NULL }; /* Dummy strategy table for the dummy empty object */ Strat stratdummy = { &stratdummytab, STRATNODEEMPTY }; /* Dummy empty object for offset computations */ /**************************/ /* */ /* The strategy routines. */ /* */ /**************************/ /* This routine parses the given strategy ** string and builds the corresponding ** strategy tree. ** It returns: ** - !NULL : pointer to the strategy. ** - NULL : on error. */ Strat * stratInit ( const StratTab * const strattab, /*+ Pointer to strategy parsing table +*/ const char * const string) /*+ Strategy string to parse +*/ { #ifdef SCOTCH_DEBUG_PARSER1 if ((strattab == NULL) || (string == NULL)) { errorPrint ("stratInit: invalid parameter"); return (NULL); } #endif /* SCOTCH_DEBUG_PARSER1 */ return (stratParserParse (strattab, string)); /* Parse strategy string */ } /* This routine frees a strategy structure. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int stratExit ( Strat * const strat) { StratParamTab * paratab; /* Table of method parameters */ byte * paraofft; /* Offset of parameter within method structure */ unsigned int i; int o; if (strat == NULL) /* If node does not exist, abort */ return (0); o = 0; /* Assume everything will be all right */ switch (strat->type) { /* Recursively free sub-strategies */ case STRATNODECONCAT : o = stratExit (strat->data.concat.strat[0]); o |= stratExit (strat->data.concat.strat[1]); break; case STRATNODECOND : o = stratTestExit (strat->data.cond.test); o |= stratExit (strat->data.cond.strat[0]); if (strat->data.cond.strat[1] != NULL) o |= stratExit (strat->data.cond.strat[1]); break; case STRATNODESELECT : o = stratExit (strat->data.select.strat[0]); o |= stratExit (strat->data.select.strat[1]); break; case STRATNODEEMPTY : /* Empty strategy node */ if (strat == &stratdummy) /* If node is empty dummy node */ return (0); /* Return without freeing it */ break; case STRATNODEMETHOD : /* Method strategy node */ paratab = strat->tabl->paratab; /* Free the method parameters */ for (i = 0; paratab[i].name != NULL; i ++) { if ((paratab[i].meth == strat->data.method.meth) && /* For all parameters of that method */ (paratab[i].type == STRATPARAMSTRAT)) { /* Which are strategy parameters */ paraofft = (byte *) &strat->data.method.data + /* Compute parameter offset within method */ (paratab[i].dataofft - paratab[i].database); o |= stratExit (*((Strat **) paraofft)); /* Perform recursion */ } } break; #ifdef SCOTCH_DEBUG_PARSER2 default : errorPrint ("stratExit: invalid strategy node"); o = 1; break; #endif /* SCOTCH_DEBUG_PARSER2 */ } memFree (strat); /* Free strategy structure itself */ return (o); /* Return output code */ } /* This routine displays the given ** strategy structure. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int stratSave ( const Strat * const strat, FILE * const stream) { unsigned int paraflag; /* Flag set if method has parameters */ StratParamTab * paratab; /* Pointer to method parameter table */ byte * paraofft; /* Offset of parameter within method structure */ unsigned int i; int o; o = 0; switch (strat->type) { /* Recursively view sub-strategies */ case STRATNODECOND : if ((fprintf (stream, "(/(") == EOF) || (stratTestSave (strat->data.cond.test, stream) != 0) || (fprintf (stream, ")?(") == EOF) || (stratSave (strat->data.cond.strat[0], stream) != 0)) o = 1; if ((o == 0) && (strat->data.cond.strat[1] != NULL)) { if ((fprintf (stream, "):(") == EOF) || (stratSave (strat->data.cond.strat[1], stream) != 0)) o = 1; } if (o == 0) o = (fprintf (stream, ");)") == EOF); break; case STRATNODECONCAT : if ((stratSave (strat->data.concat.strat[0], stream) != 0) || (stratSave (strat->data.concat.strat[1], stream) != 0)) o = 1; break; case STRATNODESELECT : if ((fprintf (stream, "(") == EOF) || (stratSave (strat->data.select.strat[0], stream) != 0) || (fprintf (stream, "|") == EOF) || (stratSave (strat->data.select.strat[1], stream) != 0) || (fprintf (stream, ")") == EOF)) o = 1; case STRATNODEEMPTY : break; case STRATNODEMETHOD : if (fprintf (stream, "%s", strat->tabl->methtab[strat->data.method.meth].name) == EOF) { /* Print method name */ o = 1; break; } paraflag = 0; /* No method parameters seen yet */ paratab = strat->tabl->paratab; for (i = 0; paratab[i].name != NULL; i ++) { if (paratab[i].meth == strat->data.method.meth) { /* For all parameters of that method */ paraofft = (byte*) &strat->data.method.data + /* Compute parameter offset within method */ (paratab[i].dataofft - paratab[i].database); if (fprintf (stream, "%c%s=", /* Open or continue parameter list */ ((paraflag ++ == 0) ? '{' : ','), paratab[i].name) == EOF) { o = 1; break; } switch (paratab[i].type) { /* Print parameter value */ case STRATPARAMCASE : /* Case value */ o = (fprintf (stream, "%c", /* Print corresponding character */ ((char *) paratab[i].datasltr)[*((unsigned int *) paraofft)]) == EOF); break; case STRATPARAMINT : /* Integer value */ o = (fprintf (stream, INTSTRING, *((INT *) paraofft)) == EOF); break; case STRATPARAMDOUBLE : /* Double value */ o = (fprintf (stream, "%g", *((double *) paraofft)) == EOF); break; case STRATPARAMSTRAT : /* Strategy */ o = stratSave (*((Strat **) paraofft), stream); /* Perform recursion */ break; case STRATPARAMSTRING : /* String value */ o = (fprintf (stream, "%s", (char *) paraofft) == EOF); break; #ifdef SCOTCH_DEBUG_PARSER2 default : errorPrint ("stratSave: invalid parameter type"); return (1); #endif /* SCOTCH_DEBUG_PARSER2 */ } } if (o != 0) /* If an error has occured */ break; /* Abort the loop */ } if ((o == 0) && (paraflag != 0)) /* If there is a parameter list */ o |= (fprintf (stream, "}") == EOF); /* Close it */ break; #ifdef SCOTCH_DEBUG_PARSER2 default : errorPrint ("stratSave: invalid strategy node"); return (1); #endif /* SCOTCH_DEBUG_PARSER2 */ } if (o != 0) { errorPrint ("stratSave: bad output"); } return (o); } /*****************************************/ /* */ /* These routines handle strategy tests. */ /* */ /*****************************************/ /* This routine evaluates the ** given condition. ** It returns: ** - 0 : on success; eval updated. ** - !0 : on error. */ int stratTestEval ( const StratTest * restrict const test, StratTest * restrict const eval, /*+ Place where to return final value +*/ const void * restrict const data) /*+ Pointer to data structure where to read variables from +*/ { StratTest val[2]; /* Temporary evaluation variables */ StratTestType sign; /* Sign of comparison */ int o; #ifdef SCOTCH_DEBUG_PARSER1 if ((test == NULL) || (eval == NULL) || (data == NULL)) { errorPrint ("stratTestEval: invalid parameter"); return (1); } #endif /* SCOTCH_DEBUG_PARSER1 */ o = 0; /* Assume no error */ switch (test->typetest) { case STRATTESTNOT : /* Not operator */ o = stratTestEval (test->data.test[0], eval, data); #ifdef SCOTCH_DEBUG_PARSER2 if ((o == 0) && (eval->typenode != STRATPARAMLOG)) { errorPrint ("stratTestEval: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_PARSER2 */ eval->data.val.vallog = 1 - eval->data.val.vallog; break; case STRATTESTAND : /* And operator */ o = stratTestEval (test->data.test[0], eval, data); #ifdef SCOTCH_DEBUG_PARSER2 if ((o == 0) && (eval->typenode != STRATPARAMLOG)) { errorPrint ("stratTestEval: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_PARSER2 */ if ((o == 0) && (eval->data.val.vallog == 1)) { o = stratTestEval (test->data.test[1], eval, data); #ifdef SCOTCH_DEBUG_PARSER2 if (eval->typenode != STRATPARAMLOG) { errorPrint ("stratTestEval: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_PARSER2 */ } break; case STRATTESTOR : /* Or operator */ o = stratTestEval (test->data.test[0], eval, data); #ifdef SCOTCH_DEBUG_PARSER2 if ((o == 0) && (eval->typenode != STRATPARAMLOG)) { errorPrint ("stratTestEval: internal error (4)"); return (1); } #endif /* SCOTCH_DEBUG_PARSER2 */ if ((o == 0) && (eval->data.val.vallog == 0)) { o = stratTestEval (test->data.test[1], eval, data); #ifdef SCOTCH_DEBUG_PARSER2 if (eval->typenode != STRATPARAMLOG) { errorPrint ("stratTestEval: internal error (5)"); return (1); } #endif /* SCOTCH_DEBUG_PARSER2 */ } break; case STRATTESTLT : /* Less-than operator */ case STRATTESTEQ : /* Equal-to operator */ case STRATTESTGT : /* Greater-than operator */ o = stratTestEval (test->data.test[0], &val[0], data); o |= stratTestEval (test->data.test[1], &val[1], data); o |= stratTestEvalCast (&val[0], &val[1]); if (o != 0) break; sign = STRATTESTNBR; /* In case of error */ switch (val[0].typenode) { case STRATPARAMDOUBLE : sign = (val[0].data.val.valdbl < val[1].data.val.valdbl) ? STRATTESTLT : ((val[0].data.val.valdbl > val[1].data.val.valdbl) ? STRATTESTGT : STRATTESTEQ); break; case STRATPARAMINT : sign = (val[0].data.val.valint < val[1].data.val.valint) ? STRATTESTLT : ((val[0].data.val.valint > val[1].data.val.valint) ? STRATTESTGT : STRATTESTEQ); break; #ifdef SCOTCH_DEBUG_PARSER2 default : errorPrint ("stratTestEval: internal error (6)"); o = 1; break; #endif /* SCOTCH_DEBUG_PARSER2 */ } eval->typenode = STRATPARAMLOG; /* Build test result */ eval->data.val.vallog = (sign == test->typetest); break; case STRATTESTADD : /* Addition operator */ o = stratTestEval (test->data.test[0], &val[0], data); o |= stratTestEval (test->data.test[1], &val[1], data); o |= stratTestEvalCast (&val[0], &val[1]); if (o != 0) break; if (val[0].typenode == STRATPARAMDOUBLE) eval->data.val.valdbl = val[0].data.val.valdbl + val[1].data.val.valdbl; else eval->data.val.valint = val[0].data.val.valint + val[1].data.val.valint; eval->typenode = val[0].typenode; break; case STRATTESTSUB : /* Subtraction operator */ o = stratTestEval (test->data.test[0], &val[0], data); o |= stratTestEval (test->data.test[1], &val[1], data); o |= stratTestEvalCast (&val[0], &val[1]); if (o != 0) break; if (val[0].typenode == STRATPARAMDOUBLE) eval->data.val.valdbl = val[0].data.val.valdbl - val[1].data.val.valdbl; else eval->data.val.valint = val[0].data.val.valint - val[1].data.val.valint; eval->typenode = val[0].typenode; break; case STRATTESTMUL : /* Multiplication operator */ o = stratTestEval (test->data.test[0], &val[0], data); o |= stratTestEval (test->data.test[1], &val[1], data); o |= stratTestEvalCast (&val[0], &val[1]); if (o != 0) break; if (val[0].typenode == STRATPARAMDOUBLE) eval->data.val.valdbl = val[0].data.val.valdbl * val[1].data.val.valdbl; else eval->data.val.valint = val[0].data.val.valint * val[1].data.val.valint; eval->typenode = val[0].typenode; break; case STRATTESTMOD : /* Modulus operator */ o = stratTestEval (test->data.test[0], &val[0], data); o |= stratTestEval (test->data.test[1], &val[1], data); o |= stratTestEvalCast (&val[0], &val[1]); if (o != 0) break; if (val[0].typenode == STRATPARAMDOUBLE) eval->data.val.valdbl = fmod (val[0].data.val.valdbl, val[1].data.val.valdbl); else eval->data.val.valint = val[0].data.val.valint % val[1].data.val.valint; eval->typenode = val[0].typenode; break; case STRATTESTVAL : /* Constant value */ *eval = *test; /* Copy value */ break; case STRATTESTVAR : /* Variable */ switch (test->typenode) { case STRATPARAMDOUBLE : eval->data.val.valdbl = *((double *) ((byte *) data + test->data.var.datadisp)); break; case STRATPARAMINT : eval->data.val.valint = *((INT *) ((byte *) data + test->data.var.datadisp)); break; #ifdef SCOTCH_DEBUG_PARSER1 default : errorPrint ("stratTestEval: internal error (7)"); o = 1; break; #endif /* SCOTCH_DEBUG_PARSER1 */ } eval->typenode = test->typenode; break; #ifdef SCOTCH_DEBUG_PARSER1 default : errorPrint ("stratTestEval: invalid condition type (%u)", test->typetest); o = 1; break; #endif /* SCOTCH_DEBUG_PARSER1 */ } eval->typetest = STRATTESTVAL; return (o); } /* This routine casts the type of one ** of the two input values so as to ** get the same type for both values. ** It returns: ** - VOID : in all cases; */ static int stratTestEvalCast ( StratTest * const test0, StratTest * const test1) { #ifdef SCOTCH_DEBUG_PARSER2 if (((test0->typenode != STRATPARAMINT) && (test0->typenode != STRATPARAMDOUBLE)) || ((test1->typenode != STRATPARAMINT) && (test1->typenode != STRATPARAMDOUBLE))) { errorPrint ("stratTestEvalCast: internal error"); return (1); } #endif /* SCOTCH_DEBUG_PARSER2 */ if (test0->typenode != test1->typenode) { /* If value types differ */ if (test0->typenode == STRATPARAMDOUBLE) { test1->typenode = STRATPARAMDOUBLE; test1->data.val.valdbl = (double) test1->data.val.valint; } else { test0->typenode = STRATPARAMDOUBLE; test0->data.val.valdbl = (double) test0->data.val.valint; } } return (0); } /* This routine fres the given ** strategy condition. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int stratTestExit ( StratTest * const test) { int o; /* Output condition flag */ #ifdef SCOTCH_DEBUG_PARSER1 if (test == NULL) { errorPrint ("stratTestExit: invalid parameter"); return (1); } #endif /* SCOTCH_DEBUG_PARSER1 */ o = 0; switch (test->typetest) { case STRATTESTNOT : /* Not operator */ o = stratTestExit (test->data.test[0]); /* Free the son */ break; case STRATTESTAND : /* And operator */ case STRATTESTOR : /* Or operator */ case STRATTESTLT : /* Less-than operator */ case STRATTESTEQ : /* Equal-to operator */ case STRATTESTGT : /* Greater-than operator */ case STRATTESTMOD : /* Modulus operator */ case STRATTESTMUL : /* Multiplication operator */ case STRATTESTADD : /* Addition operator */ case STRATTESTSUB : /* Subtraction operator */ o = stratTestExit (test->data.test[0]); /* Free the sons */ o |= stratTestExit (test->data.test[1]); break; case STRATTESTVAL : /* Constant value */ case STRATTESTVAR : /* Variable */ break; #ifdef SCOTCH_DEBUG_PARSER1 default : errorPrint ("stratTestExit: invalid condition type (%u)", test->typetest); o = 1; break; #endif /* SCOTCH_DEBUG_PARSER1 */ } memFree (test); /* Free the structure */ return (o); } /* This routine displays the ** given strategy condition. ** It returns: ** - 0 : on success. ** - !0 : on error. */ static char strattestsaveop[STRATTESTNBR] = "|&!=><+-*%##"; static char * strattestsavepa[2][2] = { { "(", ")" }, { "", "" } }; int stratTestSave ( const StratTest * const test, FILE * const stream) { int i; int o; #ifdef SCOTCH_DEBUG_PARSER1 if ((test == NULL) || (stream == NULL)) { errorPrint ("stratTestSave: invalid parameter"); return (1); } #endif /* SCOTCH_DEBUG_PARSER1 */ o = 0; /* Assume no error */ switch (test->typetest) { case STRATTESTNOT : /* Not operator */ if ((fprintf (stream, "!(") == EOF) || (stratTestSave (test->data.test[0], stream) != 0) || (fprintf (stream, ")") == EOF)) o = 1; break; case STRATTESTAND : /* And operator */ case STRATTESTOR : /* Or operator */ case STRATTESTEQ : /* Equal-to operator */ case STRATTESTGT : /* Greater-than operator */ case STRATTESTLT : /* Less-than operator */ case STRATTESTADD : /* Addition operator */ case STRATTESTSUB : /* Subtraction operator */ case STRATTESTMUL : /* Multiplication operator */ case STRATTESTMOD : /* Modulus operator */ i = (test->data.test[0]->typetest < test->typetest) ? 1 : 0; fprintf (stream, strattestsavepa[i][0]); o = stratTestSave (test->data.test[0], stream); fprintf (stream, strattestsavepa[i][1]); if (o == 0) { fprintf (stream, "%c", strattestsaveop[test->typetest]); i = (test->data.test[1]->typetest < test->typetest) ? 1 : 0; fprintf (stream, strattestsavepa[i][0]); stratTestSave (test->data.test[1], stream); fprintf (stream, strattestsavepa[i][1]); } break; case STRATTESTVAL : /* Constant value */ switch (test->typenode) { case STRATPARAMDOUBLE : o = (fprintf (stream, "%lf", test->data.val.valdbl) == EOF); break; case STRATPARAMINT : o = (fprintf (stream, INTSTRING, (INT) test->data.val.valint) == EOF); break; #ifdef SCOTCH_DEBUG_PARSER2 default : errorPrint ("stratTestSave: invalid value type"); o = 1; #endif /* SCOTCH_DEBUG_PARSER2 */ } break; case STRATTESTVAR : /* Variable */ for (i = 0; test->data.var.datatab->condtab[i].name != NULL; i ++) { if ((test->data.var.datatab->condtab[i].dataofft - test->data.var.datatab->condtab[i].database) == test->data.var.datadisp) break; } if (test->data.var.datatab->condtab[i].name == NULL) { errorPrint ("stratTestSave: invalid variable displacement"); return (1); } o = (fprintf (stream, "%s", test->data.var.datatab->condtab[i].name) == EOF); break; #ifdef SCOTCH_DEBUG_PARSER2 default : errorPrint ("stratTestSave: invalid condition type (%u)", test->typetest); o = 1; #endif /* SCOTCH_DEBUG_PARSER2 */ } return (o); } scotch-5.1.12b.dfsg/src/libscotch/vdgraph.c0000644000175300017530000001215211631334325020733 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the distributed **/ /** separator handling routines. **/ /** **/ /** DATES : # Version 5.0 : from : 07 feb 2006 **/ /** to 13 mar 2006 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VDGRAPH #include "module.h" #include "common.h" #include "dgraph.h" #include "vdgraph.h" /*************************************/ /* */ /* These routines handle distributed */ /* separator graphs. */ /* */ /*************************************/ /* This routine initializes a distributed ** separator graph structure. As for the Dgraph ** structure, in order to avoid collective ** communication whenever possible, the allocation ** of send and receive index arrays is not performed ** in the routine itself, but rather delegated to ** subsequent routines such as dgraphBuild. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int vdgraphInit ( Vdgraph * restrict const grafptr, /* Distributed separator graph structure */ MPI_Comm proccomm) /* Communicator to be used for all communications */ { memSet (grafptr, 0, sizeof (Vdgraph)); /* Clear public and private graph fields */ grafptr->s.proccomm = proccomm; /* Set private fields */ MPI_Comm_size (proccomm, &grafptr->s.procglbnbr); /* Get communicator data */ MPI_Comm_rank (proccomm, &grafptr->s.proclocnum); return (0); } /* This routine frees the contents ** of the given distributed active graph. ** It returns: ** - VOID : in all cases. */ void vdgraphExit ( Vdgraph * const grafptr) { if (grafptr->partgsttax != NULL) memFree (grafptr->partgsttax + grafptr->s.baseval); if (grafptr->fronloctab != NULL) memFree (grafptr->fronloctab); dgraphExit (&grafptr->s); /* Free distributed source graph and its private data (flagval may be corrupted afterwards) */ #ifdef SCOTCH_DEBUG_VDGRAPH2 memSet (grafptr, ~0, sizeof (Vdgraph)); #endif /* SCOTCH_DEBUG_VDGRAPH2 */ } /* This routine moves all of the graph ** vertices to the first part. ** It returns: ** - VOID : in all cases. */ void vdgraphZero ( Vdgraph * const grafptr) { memSet (grafptr->partgsttax + grafptr->s.baseval, 0, grafptr->s.vertgstnbr * sizeof (GraphPart)); /* Set all local and ghost vertices to part 0 */ grafptr->compglbloaddlt = grafptr->s.veloglbsum; grafptr->compglbload[0] = grafptr->s.veloglbsum; /* No frontier vertices */ grafptr->compglbload[1] = grafptr->compglbload[2] = 0; grafptr->compglbsize[0] = grafptr->s.vertglbnbr; grafptr->compglbsize[1] = grafptr->compglbsize[2] = 0; grafptr->complocload[0] = grafptr->s.velolocsum; grafptr->complocload[1] = grafptr->complocload[2] = 0; grafptr->complocsize[0] = grafptr->s.vertlocnbr; grafptr->complocsize[1] = grafptr->complocsize[2] = 0; } scotch-5.1.12b.dfsg/src/libscotch/arch_hcub.h0000644000175300017530000001273711631334325021234 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_hcub.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the hypercube graph target **/ /** architecture functions. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 12 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 30 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 09 aug 1995 **/ /** # Version 3.1 : from : 11 jun 1996 **/ /** to 11 jun 1996 **/ /** # Version 3.2 : from : 21 sep 1996 **/ /** to 13 may 1998 **/ /** # Version 4.0 : from : 11 nov 2003 **/ /** to 11 nov 2003 **/ /** # Version 5.1 : from : 21 jan 2008 **/ /** to 21 jan 2008 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ The binary hypercube definitions. +*/ typedef struct ArchHcub_ { Anum dimmax; /*+ Number of hypercube dimensions +*/ } ArchHcub; typedef struct ArchHcubDom_ { Anum dimcur; /*+ Current dimension to be set +*/ Anum bitset; /*+ Bit set of set dimensions +*/ } ArchHcubDom; /* ** The function prototypes. */ #ifndef ARCH_HCUB #define static #endif int archHcubArchLoad (ArchHcub * restrict const, FILE * restrict const); int archHcubArchSave (const ArchHcub * const, FILE * restrict const); #define archHcubArchFree NULL ArchDomNum archHcubDomNum (const ArchHcub * const, const ArchHcubDom * const); int archHcubDomTerm (const ArchHcub * const, ArchHcubDom * restrict const, const ArchDomNum); Anum archHcubDomSize (const ArchHcub * const, const ArchHcubDom * const); #define archHcubDomWght archHcubDomSize Anum archHcubDomDist (const ArchHcub * const, const ArchHcubDom * const, const ArchHcubDom * const); int archHcubDomFrst (const ArchHcub * const, ArchHcubDom * restrict const); int archHcubDomLoad (const ArchHcub * const, ArchHcubDom * restrict const, FILE * restrict const); int archHcubDomSave (const ArchHcub * const, const ArchHcubDom * const, FILE * restrict const); int archHcubDomBipart (const ArchHcub * const, const ArchHcubDom * const, ArchHcubDom * restrict const, ArchHcubDom * restrict const); #ifdef SCOTCH_PTSCOTCH int archHcubDomMpiType (const ArchHcub * const, MPI_Datatype * const); #endif /* SCOTCH_PTSCOTCH */ #undef static scotch-5.1.12b.dfsg/src/libscotch/mesh_graph.c0000644000175300017530000002232711631334325021422 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mesh_graph.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the source mesh **/ /** to graph conversion function. **/ /** **/ /** DATES : # Version 4.0 : from : 11 oct 2003 **/ /** to 05 may 2004 **/ /** # Version 5.1 : from : 19 nov 2009 **/ /** to 19 nov 2009 **/ /** **/ /** NOTES : # From a given mesh is created a graph, **/ /** such that all vertices of the graph **/ /** represent the nodes of the mesh, and **/ /** there exists an edge between two **/ /** vertices if there exists at least one **/ /** element to which the two associated **/ /** nodes belong. **/ /** In order to extract mesh vertex **/ /** partitions from graph vertex **/ /** partitions easily, the vertices of **/ /** the graph are numbered in the same **/ /** order as the nodes of the mesh. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MESH_GRAPH #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" #include "mesh_graph.h" /*******************************/ /* */ /* The graph building routine. */ /* */ /*******************************/ /* This routine builds a graph from the ** given mesh. ** It returns: ** - 0 : if the graph has been successfully built. ** - 1 : on error. */ int meshGraph ( const Mesh * restrict const meshptr, /*+ Original mesh +*/ Graph * restrict const grafptr) /*+ Graph to build +*/ { Gnum hashnbr; /* Number of vertices in hash table */ Gnum hashsiz; /* Size of hash table */ Gnum hashmsk; /* Mask for access to hash table */ MeshGraphHash * restrict hashtab; /* Table of edges to other node vertices */ Gnum edgemax; /* Upper bound of number of edges in mesh */ Gnum edgennd; /* Based upper bound on number of edges */ Gnum edgenum; /* Number of current graph edge */ Gnum vertnum; /* Number of current graph vertex */ Gnum degrmax; grafptr->flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; grafptr->baseval = meshptr->baseval; grafptr->vertnbr = meshptr->vnodnbr; grafptr->vertnnd = meshptr->vnodnbr + meshptr->baseval; for (hashsiz = 32, hashnbr = meshptr->degrmax * meshptr->degrmax * 2; /* Compute size of hash table */ hashsiz < hashnbr; hashsiz <<= 1) ; hashmsk = hashsiz - 1; if (((grafptr->verttax = memAlloc ((meshptr->vnodnbr + 1) * sizeof (Gnum))) == NULL) || ((hashtab = memAlloc (hashsiz * sizeof (MeshGraphHash))) == NULL)) { errorPrint ("meshGraph: out of memory (1)"); if (grafptr->verttax != NULL) memFree (grafptr->verttax); return (1); } grafptr->verttax -= grafptr->baseval; grafptr->vendtax = grafptr->verttax + 1; if (meshptr->vnlotax != NULL) /* Keep node part of mesh vertex load array as graph vertex load array */ grafptr->velotax = meshptr->vnlotax + meshptr->vnodbas - grafptr->baseval; /* Since GRAPHVERTGROUP, no problem on graphFree */ grafptr->velosum = meshptr->vnlosum; edgemax = 2 * meshptr->edgenbr; /* Compute lower bound on number of edges in graph */ #ifdef SCOTCH_DEBUG_MESH2 edgemax = meshptr->degrmax + 1; /* Allow testing dynamic reallocation of edge array */ #endif /* SCOTCH_DEBUG_MESH2 */ if ((grafptr->edgetax = memAlloc (edgemax * sizeof (Gnum))) == NULL) { errorPrint ("meshGraph: out of memory (2)"); graphFree (grafptr); return (1); } grafptr->edgetax -= grafptr->baseval; memSet (hashtab, ~0, hashsiz * sizeof (MeshGraphHash)); /* Initialize hash table */ for (vertnum = edgenum = grafptr->baseval, edgennd = edgemax + grafptr->baseval, degrmax = 0; /* Build graph edges */ vertnum < grafptr->vertnnd; vertnum ++) { Gnum vnodnum; Gnum hnodnum; Gnum enodnum; grafptr->verttax[vertnum] = edgenum; vnodnum = vertnum + (meshptr->vnodbas - meshptr->baseval); hnodnum = (vnodnum * MESHGRAPHHASHPRIME) & hashmsk; /* Prevent adding loop edge */ hashtab[hnodnum].vertnum = vnodnum; hashtab[hnodnum].vertend = vnodnum; for (enodnum = meshptr->verttax[vnodnum]; enodnum < meshptr->vendtax[vnodnum]; enodnum ++) { Gnum velmnum; Gnum eelmnum; velmnum = meshptr->edgetax[enodnum]; for (eelmnum = meshptr->verttax[velmnum]; eelmnum < meshptr->vendtax[velmnum]; eelmnum ++) { Gnum vnodend; Gnum hnodend; vnodend = meshptr->edgetax[eelmnum]; for (hnodend = (vnodend * MESHGRAPHHASHPRIME) & hashmsk; ; hnodend = (hnodend + 1) & hashmsk) { if (hashtab[hnodend].vertnum != vnodnum) { /* If edge not yet created */ if (edgenum == edgennd) { /* If edge array already full */ Gnum edgemax; Gnum * restrict edgetmp; edgemax = edgennd - grafptr->baseval; /* Increase size by 25 % */ edgemax = edgemax + (edgemax >> 2); if ((edgetmp = memRealloc (grafptr->edgetax + grafptr->baseval, edgemax * sizeof (Gnum))) == NULL) { errorPrint ("meshGraph: out of memory (3)"); graphFree (grafptr); memFree (hashtab); return (1); } grafptr->edgetax = edgetmp - grafptr->baseval; edgennd = edgemax + grafptr->baseval; } hashtab[hnodend].vertnum = vnodnum; /* Record new edge */ hashtab[hnodend].vertend = vnodend; grafptr->edgetax[edgenum ++] = vnodend - (meshptr->vnodbas - grafptr->baseval); /* Build new edge */ break; } if (hashtab[hnodend].vertend == vnodend) /* If edge already exists */ break; /* Skip to next neighbor */ } } } if ((edgenum - grafptr->verttax[vertnum]) > degrmax) /* Compute maximum degree */ degrmax = (edgenum - grafptr->verttax[vertnum]); } grafptr->verttax[vertnum] = edgenum; /* Set end of vertex array */ grafptr->edgenbr = edgenum - grafptr->baseval; grafptr->degrmax = degrmax; #ifdef SCOTCH_DEBUG_MESH2 if (graphCheck (grafptr) != 0) { errorPrint ("meshGraph: internal error"); return (1); } #endif /* SCOTCH_DEBUG_MESH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_build.h0000644000175300017530000000671311631334325021737 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /**********************************************************/ /* */ /* NAME : dgraph_build.h */ /* */ /* AUTHOR : Francois PELLEGRINI */ /* Francois CHATENET (P0.0) */ /* Sebastien FOUCAULT (P0.0) */ /* Nicolas GICQUEL (P0.1) */ /* Jerome LACOSTE (P0.1) */ /* */ /* FUNCTION : Part of a parallel static mapper. */ /* These lines are the data declarations */ /* for the distributed source graph */ /* building routines. */ /* */ /* # Version P0.1 : from : 01 apr 1997 */ /* to 13 sep 2006 */ /* # Version 5.0 : from : 22 dec 2006 */ /* to 22 dec 2006 */ /* */ /**********************************************************/ /* ** The type and structure definitions. */ /* Sort structure for local vertices. First element used for intSort2asc1. */ typedef struct DgraphLablSortVert_ { Gnum vlblglbnum; /* Global vertex label: FIRST */ Gnum vertlocnum; /* Index in local vertex array */ } DgraphLablSortVert; /* Sort structure for local edges. */ typedef struct DgraphLablSortEdge_ { Gnum vlblglbnum; /* Global vertex label */ Gnum edgelocnum; /* Index of local edge */ } DgraphLablSortEdge; scotch-5.1.12b.dfsg/src/libscotch/arch.c0000644000175300017530000003640111631334325020220 0ustar hazelscthazelsct/* Copyright 2004,2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the generic target **/ /** architecture functions. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 23 dec 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 29 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 16 aug 1995 **/ /** # Version 3.1 : from : 02 may 1996 **/ /** to 17 jul 1996 **/ /** # Version 3.2 : from : 07 sep 1996 **/ /** to 28 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 3.4 : from : 08 nov 2001 **/ /** to 08 nov 2001 **/ /** # Version 4.0 : from : 04 nov 2003 **/ /** to 09 jan 2004 **/ /** # Version 5.1 : from : 11 dec 2007 **/ /** to 25 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ARCH #include "module.h" #include "common.h" #include "arch.h" #include "arch_cmplt.h" #include "arch_cmpltw.h" #include "arch_deco.h" #include "arch_hcub.h" #include "arch_mesh.h" #include "arch_tleaf.h" #include "arch_torus.h" #include "arch_vcmplt.h" #include "arch_vhcub.h" /* ** The static definitions. */ static const ArchClass archClassTab[] = { ARCHCLASSBLOCK ("cmplt", Cmplt, ARCHPART), ARCHCLASSBLOCK ("cmpltw", Cmpltw, ARCHPART), ARCHCLASSBLOCK ("deco", Deco, ARCHNONE), ARCHCLASSBLOCK ("hcub", Hcub, ARCHNONE), ARCHCLASSBLOCK ("tleaf", Tleaf, ARCHNONE), ARCHCLASSBLOCK ("mesh2D", Mesh2, ARCHNONE), #ifdef SCOTCH_DEBUG_ARCH3 ARCHCLASSBLOCK ("mesh2O", Mesh2o, ARCHNONE), ARCHCLASSBLOCK ("mesh2U", Mesh2u, ARCHNONE), #endif /* SCOTCH_DEBUG_ARCH3 */ ARCHCLASSBLOCK ("mesh3D", Mesh3, ARCHNONE), ARCHCLASSBLOCK ("torus2D", Torus2, ARCHNONE), ARCHCLASSBLOCK ("torus3D", Torus3, ARCHNONE), ARCHCLASSBLOCK ("varcmplt", Vcmplt, ARCHPART | ARCHVAR), ARCHCLASSBLOCK ("varhcub", Vhcub, ARCHVAR), ARCHCLASSBLOCKNULL }; /**************************************/ /* */ /* These are the entry points for the */ /* generic architecture routines. */ /* */ /**************************************/ /* This routine initializes an architecture structure. ** It zeroes the architecture body so that architecture ** specific routines can check if their pointers have ** been initialized or not. ** It returns: ** - !NULL : pointer to the target architecture. ** - NULL : on error. */ int archInit ( Arch * restrict const archptr) { memset (archptr, 0, sizeof (Arch)); /* Initialize architecture body (arch->class = NULL) */ return (0); } /* This routine deletes an architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archExit ( Arch * restrict const archptr) { return (archFree (archptr)); /* Free architecture data */ } /* This routine frees the architecture data. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archFree ( Arch * restrict const archptr) { int o; o = 0; /* Assume everything will be all right */ if ((archptr->class != NULL) && (archptr->class->archFree != NULL)) /* If there is a specific freeing routing */ o = archptr->class->archFree (&archptr->data); /* Call it */ memset (archptr, 0, sizeof (Arch)); /* Initialize the architecture body (arch->class = NULL) */ return (o); } /* This routine loads an architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archLoad ( Arch * restrict const archptr, FILE * const stream) { const ArchClass * restrict class; /* Pointer to architecture class */ char name[256]; /* Architecture name string */ if (fscanf (stream, "%255s", name) != 1) { /* Read architecture name */ errorPrint ("archLoad: cannot load architecture type"); return (1); } name[255] = '\0'; /* Set end of string */ if ((class = archClass (name)) == NULL) { /* Get class from its name */ errorPrint ("archLoad: invalid architecture type"); return (1); } if (class->archLoad != NULL) { /* If class has loading function */ if (class->archLoad (&archptr->data, stream) != 0) { /* Load class data */ errorPrint ("archLoad: cannot load architecture data"); memset (archptr, 0, sizeof (Arch)); /* Initialize architecture body */ return (1); } } archptr->class = class; /* Set architecture class */ return (0); } /* This routine saves an architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archSave ( const Arch * restrict const archptr, FILE * restrict const stream) { int o; if (archptr->class == NULL) /* If no architecture type defined */ return (0); /* Nothing to do */ o = (fprintf (stream, "%s\n", /* Write architecture class */ archptr->class->archname) == EOF); if (archptr->class->archSave != NULL) /* If class has saving function */ o |= archptr->class->archSave (&archptr->data, stream); /* Write architecture data */ o |= (fprintf (stream, "\n") == EOF); if (o != 0) errorPrint ("archSave: bad output"); return (o); } /* This routine returns the pointer to ** the class of a given architecture ** name. ** It returns: ** - !NULL : class pointer. ** - NULL : on error. */ const ArchClass * archClass ( const char * const name) { const ArchClass * restrict class; /* Pointer to architecture class */ for (class = archClassTab; /* For all classes */ (class->archname != NULL) && /* Search if class names match */ (strcasecmp (name, class->archname) != 0); class ++) ; return ((class->archname != NULL) ? class : NULL); } /**************************************/ /* */ /* These are the entry points for the */ /* generic domain routines. They are */ /* used only in debugging mode, to */ /* provide breakpoints for routines */ /* which are else implemented as */ /* macros for the sake of efficiency. */ /* */ /**************************************/ /* This function returns the smallest number ** of terminal domain included within the ** given domain. */ #ifdef SCOTCH_DEBUG_ARCH2 ArchDomNum archDomNum ( const Arch * const archptr, const ArchDom * const domptr) { return (archDomNum2 (archptr, domptr)); /* Call proper routine */ } #endif /* SCOTCH_DEBUG_ARCH2 */ /* This function computes the terminal domain ** associated with the given terminal number. ** It returns: ** - 0 : if label is valid and domain has been updated. ** - 1 : if label is invalid. ** - 2 : on error. */ #ifdef SCOTCH_DEBUG_ARCH2 int archDomTerm ( const Arch * const archptr, ArchDom * restrict const domptr, const ArchDomNum domnum) { return (archDomTerm2 (archptr, domptr, domnum)); /* Call proper routine */ } #endif /* SCOTCH_DEBUG_ARCH2 */ /* This function returns the number ** of elements in the given domain. ** It returns: ** - >0 : size of the domain. ** - 0 : on error. */ #ifdef SCOTCH_DEBUG_ARCH2 Anum archDomSize ( const Arch * const archptr, const ArchDom * const domptr) { return (archDomSize2 (archptr, domptr)); /* Call proper routine */ } #endif /* SCOTCH_DEBUG_ARCH2 */ /* This function returns the weight ** of the given domain. ** It returns: ** - >0 : weight of the domain. ** - 0 : on error. */ #ifdef SCOTCH_DEBUG_ARCH2 Anum archDomWght ( const Arch * const archptr, const ArchDom * const domptr) { return (archDomWght2 (archptr, domptr)); /* Call proper routine */ } #endif /* SCOTCH_DEBUG_ARCH2 */ /* This function gives the average ** distance between two domains. ** It returns: ** - !-1 : distance between subdomains. ** - -1 : on error. */ #ifdef SCOTCH_DEBUG_ARCH2 Anum archDomDist ( const Arch * const archptr, const ArchDom * const dom0ptr, const ArchDom * const dom1ptr) { return (archDomDist2 (archptr, dom0ptr, dom1ptr)); /* Call proper routine */ } #endif /* SCOTCH_DEBUG_ARCH2 */ /* This function sets the biggest ** available domain for the given ** architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ #ifdef SCOTCH_DEBUG_ARCH2 int archDomFrst ( const Arch * const archptr, ArchDom * const domptr) { return (archDomFrst2 (archptr, domptr)); /* Call proper routine */ } #endif /* SCOTCH_DEBUG_ARCH2 */ /* This routine reads domain information ** from the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archDomLoad ( const Arch * const archptr, ArchDom * const domptr, FILE * const stream) { return (archptr->class->domLoad (&archptr->data, /* Call proper routine */ &domptr->data, stream)); } /* This routine saves domain information ** to the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archDomSave ( const Arch * const archptr, const ArchDom * const domptr, FILE * const stream) { return (archptr->class->domSave (&archptr->data, /* Call proper routine */ &domptr->data, stream)); } /* This function tries to split a domain into ** two subdomains. The two subdomains are created ** so that subdomain 0 has same T_domNum as ** original domain. ** It returns: ** - 0 : if bipartitioning succeeded. ** - 1 : if bipartitioning could not be performed. ** - 2 : on error. */ #ifdef SCOTCH_DEBUG_ARCH2 int archDomBipart ( const Arch * const archptr, const ArchDom * const domptr, ArchDom * const dom0ptr, ArchDom * const dom1ptr) { int o; o = archDomBipart2 (archptr, domptr, dom0ptr, dom1ptr); /* Call proper routine */ if ((o == 0) && /* Check domain number coherence for fixed-sized architectures */ (strncmp (archName (archptr), "var", 3) != 0) && (archDomNum (archptr, dom0ptr) != archDomNum (archptr, domptr))) { errorPrint ("archDomBipart: domain number mismatch"); return (2); } return (o); } #endif /* SCOTCH_DEBUG_ARCH2 */ /* This function creates the MPI_Datatype for ** complete graph domains. ** It returns: ** - 0 : if type could be created. ** - 1 : on error. */ #ifdef SCOTCH_PTSCOTCH int archDomMpiType ( const Arch * const archptr, MPI_Datatype * const typeptr) { int bloktab[2]; MPI_Aint disptab[2]; MPI_Datatype typetab[2]; int o; bloktab[0] = /* Build structured type to set up upper bound of domain datatype */ bloktab[1] = 1; disptab[0] = 0; /* Displacement of real datatype is base of array */ disptab[1] = sizeof (ArchDom); /* Displacement of upper bound is size of ArchDom */ typetab[1] = MPI_UB; o = ((int (*) (const void * const, const void * const)) archptr->class->domMpiType) ((const void * const) &archptr->data, &typetab[0]); if (o == 0) o = (MPI_Type_struct (2, bloktab, disptab, typetab, typeptr) != MPI_SUCCESS); if (o == 0) o = (MPI_Type_commit (typeptr) != MPI_SUCCESS); /* Created MPI types have to be committed */ return (o); } #endif /* SCOTCH_PTSCOTCH */ scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_hd.h0000644000175300017530000000727211631334325022433 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_hd.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the block-oriented Halo **/ /** Approximate (Multiple) Minimum Degree **/ /** ordering routine. **/ /** **/ /** DATES : # Version 3.2 : from : 09 aug 1998 **/ /** to : 18 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 19 oct 1998 **/ /** # Version 4.0 : from : 14 jan 2003 **/ /** to : 24 jan 2004 **/ /** # Version 5.1 : from : 01 oct 2009 **/ /** to : 01 oct 2009 **/ /** **/ /************************************************************/ /* ** The defines. */ #define HGRAPHORDERHDCOMPRAT 1.2L /*+ Compression ratio +*/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HgraphOrderHdParam_ { INT colmin; /*+ Minimum number of columns +*/ INT colmax; /*+ Maximum number of columns +*/ double fillrat; /*+ Fill-in ratio +*/ } HgraphOrderHdParam; /* ** The function prototypes. */ #ifndef HGRAPH_ORDER_HD #define static #endif int hgraphOrderHd (const Hgraph * restrict const, Order * restrict const, const Gnum, OrderCblk * restrict const, const HgraphOrderHdParam * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_bd.h0000644000175300017530000000751111631334325022561 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_bd.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the bipartition graph banding **/ /** module. **/ /** **/ /** DATES : Version 5.0 : from : 27 nov 2006 **/ /** to : 29 may 2007 **/ /** Version 5.1 : from : 04 nov 2010 **/ /** to : 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct BgraphBipartBdParam_ { Gnum distmax; /*+ Maximum distance to separator +*/ Strat * stratbnd; /*+ Strategy for band graph +*/ Strat * stratorg; /*+ Strategy for original graph +*/ } BgraphBipartBdParam; /*+ Neighbor queue. +*/ typedef struct BgraphBipartBdQueue_ { Gnum * head; /*+ Head of distance queue +*/ Gnum * tail; /*+ Tail of distance queue +*/ Gnum * qtab; /*+ Array of queue elements +*/ } BgraphBipartBdQueue; /* ** The function prototypes. */ int bgraphBipartBd (Bgraph * restrict const, const BgraphBipartBdParam * restrict const); /* ** The macro definitions. */ #define bgraphBipartBdQueueFlush(queue) ((queue)->head = (queue)->tail = (queue)->qtab) #define bgraphBipartBdQueueEmpty(queue) ((queue)->head <= (queue)->tail) #define bgraphBipartBdQueuePut(queue,vnum) (* ((queue)->head ++) = (vnum)) #define bgraphBipartBdQueueGet(queue) (* ((queue)->tail ++)) scotch-5.1.12b.dfsg/src/libscotch/arch_cmpltw.c0000644000175300017530000003753211631334325021614 0ustar hazelscthazelsct/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_cmpltw.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the weighted **/ /** complete graph target architecture. **/ /** **/ /** DATES : # Version 5.1 : from : 11 dec 2007 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ARCH_CMPLTW #include "module.h" #include "common.h" #include "graph.h" #include "arch.h" #include "arch_cmpltw.h" /******************************************/ /* */ /* These are the complete graph routines. */ /* */ /******************************************/ /* This routine builds a complete weighted ** graph architecture from the given load array. ** It returns: ** - 0 : if the architecture has been successfully built. ** - !0 : on error. */ static void archCmpltwArchBuild3 ( ArchCmpltwLoad * restrict const velotab, ArchCmpltwLoad * restrict const vesotab, Anum vertnbr, Anum velosum) { Gnum velosum0; Gnum velosum1; Anum vertnbr0; Anum vertnbr1; Anum vertnum0; Anum vertnum1; Anum vertnum; vertnum0 = vertnum1 = vertnbr - 1; velosum0 = velotab[vertnum0 --].veloval; velosum1 = 0; for (vertnum = vertnum0; vertnum >= 0; vertnum --) { if (velosum1 < velosum0) { velosum1 += velotab[vertnum].veloval; vesotab[vertnum1 --] = velotab[vertnum]; } else { velosum0 += velotab[vertnum].veloval; velotab[vertnum0 --] = velotab[vertnum]; } } if (velosum0 >= velosum1) { vertnbr0 = vertnbr - vertnum0 - 1; vertnbr1 = vertnbr - vertnbr0; memMov (velotab, velotab + vertnbr1, vertnbr0 * sizeof (ArchCmpltwLoad)); memCpy (velotab + vertnbr0, vesotab + vertnbr0, vertnbr1 * sizeof (ArchCmpltwLoad)); } else { Anum velotmp; vertnbr0 = vertnbr - vertnum1 - 1; vertnbr1 = vertnbr - vertnbr0; memCpy (velotab, vesotab + vertnbr1, vertnbr0 * sizeof (ArchCmpltwLoad)); velotmp = velosum0; velosum0 = velosum1; velosum1 = velotmp; } if (vertnbr0 > 2) archCmpltwArchBuild3 (velotab, vesotab, vertnbr0, velosum0); if (vertnbr1 > 2) archCmpltwArchBuild3 (velotab + vertnbr0, vesotab + vertnbr0, vertnbr1, velosum1); } static int archCmpltwArchBuild2 ( ArchCmpltw * restrict const archptr) { ArchCmpltwLoad * restrict vesotab; /* Auxiliary sort array for weighted vertices */ if (archptr->vertnbr < 3) /* No need to sort if less than 3 vertices */ return (0); if ((vesotab = (ArchCmpltwLoad *) memAlloc (archptr->vertnbr * sizeof (ArchCmpltwLoad))) == NULL) { errorPrint ("archCmpltwArchBuild2: out of memory"); memFree (archptr->velotab); archptr->velotab = NULL; return (1); } intSort2asc2 (archptr->velotab, archptr->vertnbr); /* Sort load array by both keys to be portable across sorting implementations */ archCmpltwArchBuild3 (archptr->velotab, vesotab, archptr->vertnbr, archptr->velosum); memFree (vesotab); return (0); } int archCmpltwArchBuild ( ArchCmpltw * restrict const archptr, const Gnum vertnbr, /* Gnum since to be called from the library */ const Gnum * restrict const velotab) /* Gnum since to be called from the library */ { Anum vertnum; Gnum velosum; #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchCmpltw) > sizeof (ArchDummy)) || (sizeof (ArchCmpltwDom) > sizeof (ArchDomDummy))) { errorPrint ("archCmpltwArchBuild: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if (vertnbr <= 0) { errorPrint ("archCmpltwArchBuild: invalid parameters"); return (1); } archptr->vertnbr = (Anum) vertnbr; if ((archptr->velotab = (ArchCmpltwLoad *) memAlloc (archptr->vertnbr * sizeof (ArchCmpltwLoad))) == NULL) { errorPrint ("archCmpltwArchBuild: out of memory"); return (1); } for (vertnum = 0, velosum = 0; vertnum < archptr->vertnbr; vertnum ++) { /* Fill vertex load array */ Gnum veloval; veloval = velotab[vertnum]; velosum += veloval; archptr->velotab[vertnum].veloval = veloval; archptr->velotab[vertnum].vertnum = vertnum; } archptr->velosum = (Anum) velosum; return (archCmpltwArchBuild2 (archptr)); } /* This routine loads the weighted complete ** graph architecture. ** It returns: ** - 0 : if the architecture has been successfully read. ** - !0 : on error. */ int archCmpltwArchLoad ( ArchCmpltw * restrict const archptr, FILE * restrict const stream) { long vertnbr; Gnum velosum; Anum vertnum; #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchCmpltw) > sizeof (ArchDummy)) || (sizeof (ArchCmpltwDom) > sizeof (ArchDomDummy))) { errorPrint ("archCmpltwArchLoad: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if ((fscanf (stream, "%ld", &vertnbr) != 1) || (vertnbr < 1)) { errorPrint ("archCmpltwArchLoad: bad input (1)"); return (1); } archptr->vertnbr = (Anum) vertnbr; if ((archptr->velotab = (ArchCmpltwLoad *) memAlloc (archptr->vertnbr * sizeof (ArchCmpltwLoad))) == NULL) { errorPrint ("archCmpltwArchLoad: out of memory"); return (1); } for (vertnum = 0, velosum = 0; vertnum < archptr->vertnbr; vertnum ++) { long veloval; Gnum velotmp; if ((fscanf (stream, "%ld", &veloval) != 1) || (veloval < 1)) { errorPrint ("archCmpltwArchLoad: bad input (2)"); return (1); } velotmp = (Gnum) veloval; velosum += velotmp; archptr->velotab[vertnum].veloval = velotmp; archptr->velotab[vertnum].vertnum = vertnum; } archptr->velosum = (Anum) velosum; return (archCmpltwArchBuild2 (archptr)); } /* This routine saves the weighted ** complete graph architecture. ** It returns: ** - 0 : if the architecture has been successfully written. ** - !0 : on error. */ int archCmpltwArchSave ( const ArchCmpltw * const archptr, FILE * restrict const stream) { Anum vertnum; #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchCmpltw) > sizeof (ArchDummy)) || (sizeof (ArchCmpltwDom) > sizeof (ArchDomDummy))) { errorPrint ("archCmpltwArchSave: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if (fprintf (stream, ANUMSTRING, (Anum) archptr->vertnbr) == EOF) { errorPrint ("archCmpltwArchSave: bad output (1)"); return (1); } for (vertnum = 0; vertnum < archptr->vertnbr; vertnum ++) { /* For all weights to output */ Anum verttmp; for (verttmp = 0; verttmp < archptr->vertnbr; verttmp ++) { /* For all vertex indices: O(n^2) loop but we don't really care */ if (archptr->velotab[verttmp].vertnum == vertnum) { if (fprintf (stream, " " ANUMSTRING, (Anum) archptr->velotab[verttmp].veloval) == EOF) { errorPrint ("archCmpltwArchSave: bad output (2)"); return (1); } break; } if (verttmp == archptr->vertnbr) { errorPrint ("archCmpltwArchSave: internal error"); return (1); } } } return (0); } /* This routine frees the weighted complete ** graph architecture data structures. ** It returns: ** - 0 : if the architecture has been successfully freed. ** - !0 : on error. */ int archCmpltwArchFree ( ArchCmpltw * const archptr) { #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchCmpltw) > sizeof (ArchDummy)) || (sizeof (ArchCmpltwDom) > sizeof (ArchDomDummy))) { errorPrint ("archCmpltwArchFree: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if (archptr->velotab != NULL) { memFree (archptr->velotab); archptr->velotab = NULL; } return (0); } /* This function returns the smallest number ** of terminal domain included in the given ** domain. */ ArchDomNum archCmpltwDomNum ( const ArchCmpltw * const archptr, const ArchCmpltwDom * const domptr) { return (archptr->velotab[domptr->vertmin].vertnum); /* Return vertex number */ } /* This function returns the terminal domain associated ** with the given terminal number in the architecture. ** ** It returns: ** - 0 : if label is valid and domain has been updated. ** - 1 : if label is invalid. ** - 2 : on error. */ int archCmpltwDomTerm ( const ArchCmpltw * const archptr, ArchCmpltwDom * const domptr, const ArchDomNum domnum) { if (domnum < archptr->vertnbr) { /* If valid label */ Anum vertnum; for (vertnum = 0; vertnum < archptr->vertnbr; vertnum ++) { /* Search for terminal domain index matching vertex label */ if (archptr->velotab[vertnum].vertnum == domnum) break; } #ifdef SCOTCH_DEBUG_ARCH2 if (vertnum == archptr->vertnbr) { /* If index not found */ errorPrint ("archCmpltwDomTerm: internal error"); return (2); } #endif /* SCOTCH_DEBUG_ARCH2 */ domptr->vertmin = vertnum; /* Set the domain */ domptr->vertnbr = 1; domptr->veloval = archptr->velotab[vertnum].veloval; return (0); } return (1); /* Cannot set domain */ } /* This function returns the number of ** elements in the complete domain. */ Anum archCmpltwDomSize ( const ArchCmpltw * const archptr, const ArchCmpltwDom * const domptr) { return (domptr->vertnbr); } /* This function returns the weight of ** the complete domain. */ Anum archCmpltwDomWght ( const ArchCmpltw * const archptr, const ArchCmpltwDom * const domptr) { return (domptr->veloval); } /* This function returns the average ** distance between two complete ** subdomains. */ Anum archCmpltwDomDist ( const ArchCmpltw * const archptr, const ArchCmpltwDom * const dom0ptr, const ArchCmpltwDom * const dom1ptr) { return (((dom0ptr->vertmin == dom1ptr->vertmin) && /* All domains are at distance 1 */ (dom0ptr->vertnbr == dom1ptr->vertnbr)) ? 0 : 1); /* If they are different */ } /* This function sets the biggest ** domain available for this ** architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archCmpltwDomFrst ( const ArchCmpltw * const archptr, ArchCmpltwDom * restrict const domptr) { domptr->vertmin = 0; domptr->vertnbr = archptr->vertnbr; domptr->veloval = archptr->velosum; return (0); } /* This routine reads domain information ** from the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archCmpltwDomLoad ( const ArchCmpltw * const archptr, ArchCmpltwDom * restrict const domptr, FILE * const stream) { long vertmin; long vertnbr; Anum vertnum; Anum vertnnd; Anum velosum; if ((fscanf (stream, "%ld%ld", &vertmin, &vertnbr) != 2) || (vertnbr < 1) || (vertnbr + vertmin > (long) archptr->vertnbr)) { errorPrint ("archCmpltwDomLoad: bad input"); return (1); } domptr->vertmin = (Anum) vertmin; domptr->vertnbr = (Anum) vertnbr; for (vertnum = domptr->vertmin, vertnnd = vertnum + domptr->vertnbr, velosum = 0; vertnum < vertnnd; vertnum ++) velosum += archptr->velotab[vertnum].veloval; domptr->veloval += velosum; return (0); } /* This routine saves domain information ** to the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archCmpltwDomSave ( const ArchCmpltw * const archptr, const ArchCmpltwDom * const domptr, FILE * const stream) { if (fprintf (stream, ANUMSTRING " " ANUMSTRING " ", (Anum) domptr->vertmin, (Anum) domptr->vertnbr) == EOF) { errorPrint ("archCmpltwDomSave: bad output"); return (1); } return (0); } /* This function tries to split a complete ** graph domain into two subdomains. ** It returns: ** - 0 : if bipartitioning succeeded. ** - 1 : if bipartitioning could not be performed. ** - 2 : on error. */ int archCmpltwDomBipart ( const ArchCmpltw * const archptr, const ArchCmpltwDom * const domptr, ArchCmpltwDom * restrict const dom0ptr, ArchCmpltwDom * restrict const dom1ptr) { Anum vertnum; Anum velosum1; Anum velosum2; /* Half of overall load sum */ if (domptr->vertnbr <= 1) /* Return if cannot bipartition more */ return (1); vertnum = domptr->vertmin + domptr->vertnbr - 1; velosum1 = (Anum) archptr->velotab[vertnum].veloval; velosum2 = domptr->veloval / 2; for (vertnum --; vertnum > domptr->vertmin; vertnum --) { Anum velotmp; velotmp = velosum1 + (Anum) archptr->velotab[vertnum].veloval; if (velotmp > velosum2) /* Domain 1 is always the least loaded */ break; velosum1 = velotmp; } dom0ptr->vertmin = domptr->vertmin; /* Bipartition vertices */ dom1ptr->vertmin = vertnum + 1; dom0ptr->vertnbr = dom1ptr->vertmin - domptr->vertmin; dom1ptr->vertnbr = domptr->vertnbr - dom0ptr->vertnbr; dom0ptr->veloval = domptr->veloval - velosum1; dom1ptr->veloval = velosum1; return (0); } /* This function creates the MPI_Datatype for ** weighted complete graph domains. ** It returns: ** - 0 : if type could be created. ** - 1 : on error. */ #ifdef SCOTCH_PTSCOTCH int archCmpltwDomMpiType ( const ArchCmpltw * const archptr, MPI_Datatype * const typeptr) { MPI_Type_contiguous (3, ANUM_MPI, typeptr); return (0); } #endif /* SCOTCH_PTSCOTCH */ scotch-5.1.12b.dfsg/src/libscotch/hmesh_induce.c0000644000175300017530000004505611631334325021744 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_induce.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the halo source **/ /** mesh subgraph-making functions. **/ /** **/ /** DATES : # Version 4.0 : from : 07 jan 2002 **/ /** to 11 may 2004 **/ /** # Version 5.0 : from : 22 dec 2006 **/ /** to 11 jun 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH #define HMESH_INDUCE #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" #include "hmesh.h" /*********************************************/ /* */ /* These routines handle halo source meshes. */ /* */ /*********************************************/ /* This routine builds the halo mesh induced ** by the original halo mesh and the array of ** selected node vertices. Elements which are ** adjacent to the selected nodes are themselves ** selected, as well as their adjacent node ** vertices, which comprise the new halo. ** In the induced halo mesh, elements are ** placed first, then non-halo nodes, then ** halo nodes. This order is quite important ** as it eases the building of vertex separation ** meshes from halo meshes, just by ignoring ** halo nodes. ** The induced vnumtab array is a baseval-based ** list of the selected node vertices if the ** original halo mesh does not have a vnumtab, or ** the proper subset of the original vnumtab else. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int hmeshInducePart ( const Hmesh * restrict const orgmeshptr, /* Pointer to original graph */ const GraphPart * restrict const orgparttax, /* Array of vertex partition flags */ const GraphPart orgpartval, /* Partition value of vertices to keep (0 or 1) */ const Gnum orgvelmnbr, /* Number of (maybe isolated) element vertices in selected part */ const Gnum orgvnodnbr, /* Number of node vertices in selected part */ const Gnum orgvnspnbr, /* Number of node vertices in separator */ Hmesh * restrict const indmeshptr) /* Pointer to induced halo submesh */ { Gnum orgvelmnum; /* Number of current element vertex in original halo mesh */ Gnum orgvnodnum; /* Number of current node vertex in original halo mesh */ Gnum * restrict orgindxtax; /* Original to induced vertex number translation array */ Gnum indvertnbr; /* Upper bound on the number of vertices in induced halo mesh */ Gnum indvertnum; /* Number of current vertex in induced mesh graph */ Gnum indvelmnbr; /* Number of element vertices in induced halo mesh */ Gnum indveihnbr; /* Number of newly created halo-isolated elements */ Gnum indvnodnbr; /* Upper bound on the number of node vertices in induced halo mesh */ Gnum indvnodnum; /* Number of current node vertex in induced halo mesh */ Gnum * restrict indedgetax; /* Based access to induced mesh graph edge arrays */ Gnum indedgenbr; /* (Approximate) number of edges in induced halo mesh */ Gnum indedgenum; /* Number of current edge in induced halo mesh */ Gnum * restrict indvnuhtax; /* Array of vertex numbers for halo nodes (aka vnumtab) */ Gnum indvelonbr; Gnum indvelosum; Gnum indvnlonbr; Gnum indvnlosum; Gnum indvnhlsum; indvelmnbr = orgvelmnbr - orgmeshptr->veihnbr; /* Remove known halo-isolated elements */ if (orgpartval == 0) /* If submesh is part zero */ indvelmnbr -= orgmeshptr->m.veisnbr; /* Also remove isolated elements, which belong to it */ indvnodnbr = orgvnodnbr + orgvnspnbr + orgmeshptr->m.vnodnnd - orgmeshptr->vnohnnd; /* Compute upper bound on number of node vertices */ indvertnbr = indvnodnbr + indvelmnbr; indedgenbr = ((orgmeshptr->m.degrmax > 0) && (indvertnbr < (orgmeshptr->m.edgenbr / orgmeshptr->m.degrmax))) /* Choose best upper bound on number of edges (avoid multiply overflow) */ ? (indvertnbr * orgmeshptr->m.degrmax) : orgmeshptr->m.edgenbr; memSet (indmeshptr, 0, sizeof (Hmesh)); /* Initialize halo mesh fields */ indmeshptr->m.baseval = orgmeshptr->m.baseval; /* Inherit mesh properties */ indmeshptr->m.flagval = MESHFREETABS | MESHVERTGROUP; indmeshptr->m.velmnbr = indvelmnbr; indmeshptr->m.velmbas = indmeshptr->m.baseval; /* Elements are placed first */ indmeshptr->m.velmnnd = indmeshptr->m.vnodbas = orgvelmnbr + indmeshptr->m.baseval; /* Node vertices are placed after elements */ indmeshptr->m.veisnbr = 0; /* All isolated elements will be removed in submesh */ indvelonbr = (orgmeshptr->m.velotax != NULL) ? indmeshptr->m.velmnbr : 0; indvnlonbr = (orgmeshptr->m.vnlotax != NULL) ? indvnodnbr : 0; if (memAllocGroup ((void **) (void *) &indmeshptr->m.verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)), &indmeshptr->vehdtax, (size_t) ( orgvelmnbr * sizeof (Gnum)), /* vehdtab is limited to elements */ &indmeshptr->m.velotax, (size_t) ( indvelonbr * sizeof (Gnum)), &indmeshptr->m.vnlotax, (size_t) ( indvnlonbr * sizeof (Gnum)), &indmeshptr->m.vnumtax, (size_t) ( orgvnodnbr * sizeof (Gnum)), NULL) == NULL) { /* vnumtab is of size vnohnbr */ errorPrint ("hmeshInducePart: out of memory (1)"); /* Allocate induced mesh graph structure */ return (1); } indmeshptr->m.verttax -= indmeshptr->m.baseval; indmeshptr->m.vendtax = indmeshptr->m.verttax + 1; /* Compact array */ indmeshptr->m.velotax = (indvelonbr != 0) ? (indmeshptr->m.velotax - indmeshptr->m.velmbas) : NULL; indmeshptr->m.vnlotax = (indvnlonbr != 0) ? (indmeshptr->m.vnlotax - indmeshptr->m.vnodbas) : NULL; indmeshptr->m.vnumtax -= indmeshptr->m.vnodbas; /* Only for non-halo nodes */ indmeshptr->m.degrmax = orgmeshptr->m.degrmax; indmeshptr->vnohnbr = orgvnodnbr; indmeshptr->vnohnnd = indmeshptr->m.vnodbas + orgvnodnbr; indmeshptr->vehdtax -= indmeshptr->m.velmbas; indmeshptr->vnhlsum = orgvnodnbr; /* Assume no vertex loads */ if (memAllocGroup ((void **) (void *) &indedgetax, (size_t) (indedgenbr * sizeof (Gnum)), &orgindxtax, (size_t) ((orgmeshptr->m.velmnbr + orgmeshptr->m.vnodnbr) * sizeof (Gnum)), &indvnuhtax, (size_t) ((orgvnspnbr + orgmeshptr->m.vnodnnd - orgmeshptr->vnohnnd) * sizeof (Gnum)), NULL) == NULL) { errorPrint ("hmeshInducePart: out of memory (2)"); /* Allocate induced mesh graph structure */ hmeshExit (indmeshptr); return (1); } indedgetax -= indmeshptr->m.baseval; orgindxtax -= orgmeshptr->m.baseval; indvnuhtax -= indmeshptr->vnohnnd; /* Base array so as to catch halo nodes only */ indvnhlsum = 0; for (orgvnodnum = orgmeshptr->m.vnodbas, /* For all original non-halo node vertices */ indvnodnum = indmeshptr->m.vnodbas; /* And assuming all elements will be kept */ orgvnodnum < orgmeshptr->vnohnnd; orgvnodnum ++) { if (orgparttax[orgvnodnum] == orgpartval) { /* If in right part */ orgindxtax[orgvnodnum] = indvnodnum; /* Set new index of node */ indmeshptr->m.vnumtax[indvnodnum] = orgvnodnum - (orgmeshptr->m.vnodbas - orgmeshptr->m.baseval); if (orgmeshptr->m.vnlotax != NULL) indvnhlsum += (indmeshptr->m.vnlotax[indvnodnum] = orgmeshptr->m.vnlotax[orgvnodnum]); indvnodnum ++; } else if (orgparttax[orgvnodnum] == 2) /* If node belongs to separator */ orgindxtax[orgvnodnum] = ~0; /* Pre-set array for separator nodes */ } #ifdef SCOTCH_DEBUG_HMESH2 if ((indvnodnum - indmeshptr->m.vnodbas) != orgvnodnbr) { errorPrint ("hmeshInducePart: internal error (1)"); memFree (indedgetax + indmeshptr->m.baseval); hmeshExit (indmeshptr); return (1); } #endif /* SCOTCH_DEBUG_HMESH2 */ memSet (orgindxtax + orgmeshptr->vnohnnd, ~0, (orgmeshptr->m.vnodnnd - orgmeshptr->vnohnnd) * sizeof (Gnum)); /* Pre-set halo node vertices */ indveihnbr = 0; indvelosum = 0; indvnlosum = 0; for (orgvelmnum = orgmeshptr->m.velmbas, /* For all elements of original graph */ indvertnum = indedgenum = indmeshptr->m.baseval; /* Elements are placed first in vertex array */ orgvelmnum < orgmeshptr->m.velmnnd; orgvelmnum ++) { if (orgparttax[orgvelmnum] == orgpartval) { /* If element belongs to right part */ Gnum orgedgenum; Gnum indedgennd; /* Index of after-last edge position in edge array */ Gnum indedhdnum; /* Index of after-last edge linking to non-halo vertices */ orgedgenum = orgmeshptr->m.verttax[orgvelmnum]; if (orgedgenum == orgmeshptr->vehdtax[orgvelmnum]) /* If (halo-)isolated element vertex */ continue; /* Discard element in induced submesh */ #ifdef SCOTCH_DEBUG_HMESH2 if (indvertnum >= indmeshptr->m.velmnnd) { /* If too many element vertices kept */ errorPrint ("hmeshInducePart: internal error (2)"); /* Maybe a problem with veisnbr or veihnbr */ memFree (indedgetax + indmeshptr->m.baseval); hmeshExit (indmeshptr); return (1); } #endif /* SCOTCH_DEBUG_HMESH2 */ indmeshptr->m.verttax[indvertnum] = indedgenum; indedhdnum = orgmeshptr->m.vendtax[orgvelmnum] - orgmeshptr->m.verttax[orgvelmnum] + indedgenum; indedgennd = indedhdnum; if (orgmeshptr->m.velotax != NULL) { Gnum orgveloval; orgveloval = orgmeshptr->m.velotax[orgvelmnum]; indmeshptr->m.velotax[indvertnum] = orgveloval; indvelosum += orgveloval; } for ( ; orgedgenum < orgmeshptr->m.vendtax[orgvelmnum]; orgedgenum ++) { Gnum orgvertend; orgvertend = orgmeshptr->m.edgetax[orgedgenum]; if (orgindxtax[orgvertend] == ~0) { /* If found yet un-numbered halo node */ #ifdef SCOTCH_DEBUG_HMESH2 if ((orgvertend < orgmeshptr->vnohnnd) && (orgparttax[orgvertend] != 2)) { errorPrint ("hmeshInducePart: internal error (3)"); memFree (indedgetax + indmeshptr->m.baseval); hmeshExit (indmeshptr); return (1); } #endif /* SCOTCH_DEBUG_HMESH2 */ if (orgmeshptr->m.vnlotax != NULL) { Gnum orgvnloval; orgvnloval = orgmeshptr->m.vnlotax[orgvertend]; indmeshptr->m.vnlotax[indvnodnum] = orgvnloval; indvnlosum += orgvnloval; } orgindxtax[orgvertend] = indvnodnum; /* Set number of halo node */ indvnuhtax[indvnodnum] = orgvertend; /* Keep number of halo node */ indvnodnum ++; indedgetax[-- indedhdnum] = orgindxtax[orgvertend]; continue; } if (orgindxtax[orgvertend] < indmeshptr->vnohnnd) /* If non-halo vertex */ indedgetax[indedgenum ++] = orgindxtax[orgvertend]; else /* Else if halo vertex */ indedgetax[-- indedhdnum] = orgindxtax[orgvertend]; } #ifdef SCOTCH_DEBUG_HMESH2 if (indedgenum != indedhdnum) { errorPrint ("hmeshInducePart: internal error (4)"); memFree (indedgetax + indmeshptr->m.baseval); hmeshExit (indmeshptr); return (1); } #endif /* SCOTCH_DEBUG_HMESH2 */ if (indedhdnum == indmeshptr->m.verttax[indvertnum]) /* If element has halo nodes only */ indveihnbr ++; /* One more halo-isolated element created */ indmeshptr->vehdtax[indvertnum] = indedhdnum; indedgenum = indedgennd; orgindxtax[orgvelmnum] = indvertnum; indvertnum ++; /* One more element created */ } else orgindxtax[orgvelmnum] = ~0; } #ifdef SCOTCH_DEBUG_HMESH2 if (indvertnum != indmeshptr->m.velmnnd) { errorPrint ("hmeshInducePart: internal error (5)"); /* Maybe a problem with veisnbr or veihnbr */ memFree (indedgetax + indmeshptr->m.baseval); hmeshExit (indmeshptr); return (1); } #endif /* SCOTCH_DEBUG_HMESH2 */ indmeshptr->veihnbr = indveihnbr; indmeshptr->m.vnodnbr = indvnodnum - indmeshptr->m.vnodbas; indmeshptr->m.vnodnnd = indvertnum + indmeshptr->m.vnodnbr; indmeshptr->m.velosum = (indmeshptr->m.velotax != NULL) ? indvelosum : indmeshptr->m.velmnbr; if (indmeshptr->m.vnlotax != NULL) { /* If vertex loads wanted */ indmeshptr->m.vnlosum = indvnhlsum + indvnlosum; indmeshptr->vnhlsum = indvnhlsum; } else { indmeshptr->m.vnlosum = indmeshptr->m.vnodnbr; indmeshptr->vnhlsum = indmeshptr->vnohnbr; } indedgenbr = 2 * (indedgenum - indmeshptr->m.baseval); /* Twice as many arcs as element arcs */ for ( ; indvertnum < indmeshptr->vnohnnd; indvertnum ++) { /* For all non-halo induced node vertices */ Gnum orgvnodnum; Gnum orgedgenum; orgvnodnum = indmeshptr->m.vnumtax[indvertnum] + (orgmeshptr->m.vnodbas - orgmeshptr->m.baseval); /* Get number of original node */ indmeshptr->m.verttax[indvertnum] = indedgenum; for (orgedgenum = orgmeshptr->m.verttax[orgvnodnum]; orgedgenum < orgmeshptr->m.vendtax[orgvnodnum]; orgedgenum ++) { Gnum orgvertend; orgvertend = orgmeshptr->m.edgetax[orgedgenum]; #ifdef SCOTCH_DEBUG_HMESH2 if (orgindxtax[orgvertend] == ~0) { errorPrint ("hmeshInducePart: internal error (6)"); memFree (indedgetax + indmeshptr->m.baseval); hmeshExit (indmeshptr); return (1); } #endif /* SCOTCH_DEBUG_HMESH2 */ indedgetax[indedgenum ++] = orgindxtax[orgvertend]; } } indmeshptr->enohnbr = indedgenum - indmeshptr->m.baseval; for ( ; indvertnum < indmeshptr->m.vnodnnd; indvertnum ++) { /* For all halo induced node vertices */ Gnum orgvnodnum; Gnum orgedgenum; orgvnodnum = indvnuhtax[indvertnum]; /* Get number of original node */ indmeshptr->m.verttax[indvertnum] = indedgenum; for (orgedgenum = orgmeshptr->m.verttax[orgvnodnum]; orgedgenum < orgmeshptr->m.vendtax[orgvnodnum]; orgedgenum ++) { Gnum orgvertend; orgvertend = orgmeshptr->m.edgetax[orgedgenum]; if (orgindxtax[orgvertend] != ~0) { /* If end element belongs to right part */ indedgetax[indedgenum ++] = orgindxtax[orgvertend]; } } } indmeshptr->m.verttax[indvertnum] = indedgenum; /* Set end of edge array */ indmeshptr->m.edgenbr = indedgenum - indmeshptr->m.baseval; indmeshptr->m.vnodnnd = indvertnum; /* Record number of induced non-element vertices */ indmeshptr->m.vnodnbr = indvertnum - indmeshptr->m.vnodbas; if (orgmeshptr->m.vnumtax != NULL) { /* If source mesh is not original mesh */ for (indvnodnum = indmeshptr->m.vnodbas; indvnodnum < indmeshptr->vnohnnd; indvnodnum ++) indmeshptr->m.vnumtax[indvnodnum] = orgmeshptr->m.vnumtax[indmeshptr->m.vnumtax[indvnodnum] + (orgmeshptr->m.vnodbas - orgmeshptr->m.baseval)]; } indmeshptr->m.edgetax = memRealloc (indedgetax + indmeshptr->m.baseval, indedgenbr * sizeof (Gnum)); indmeshptr->m.edgetax -= indmeshptr->m.baseval; #ifdef SCOTCH_DEBUG_HMESH2 if (hmeshCheck (indmeshptr) != 0) { /* Check halo mesh consistency */ errorPrint ("hmeshInducePart: inconsistent halo mesh data"); hmeshExit (indmeshptr); return (1); } #endif /* SCOTCH_DEBUG_HMESH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_bd.h0000644000175300017530000000763211631334325023134 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_bd.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** : Cedric CHEVALIER **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the separation graph banding **/ /** module. **/ /** **/ /** DATES : Version 5.0 : from : 18 oct 2004 **/ /** to : 16 sep 2006 **/ /** Version 5.1 : from : 30 oct 2007 **/ /** to : 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct VgraphSeparateBdParam_ { Gnum distmax; /*+ Maximum distance to separator +*/ Strat * stratbnd; /*+ Strategy for band graph +*/ Strat * stratorg; /*+ Strategy for original graph +*/ } VgraphSeparateBdParam; /*+ Neighbor queue. +*/ typedef struct VgraphSeparateBdQueue_ { Gnum * head; /*+ Head of distance queue +*/ Gnum * tail; /*+ Tail of distance queue +*/ Gnum * qtab; /*+ Array of queue elements +*/ } VgraphSeparateBdQueue; /* ** The function prototypes. */ int vgraphSeparateBd (Vgraph * restrict const, const VgraphSeparateBdParam * restrict const); /* ** The macro definitions. */ #define vgraphSeparateBdQueueFlush(queue) ((queue)->head = (queue)->tail = (queue)->qtab) #define vgraphSeparateBdQueueEmpty(queue) ((queue)->head <= (queue)->tail) #define vgraphSeparateBdQueuePut(queue,vnum) (* ((queue)->head ++) = (vnum)) #define vgraphSeparateBdQueueGet(queue) (* ((queue)->tail ++)) scotch-5.1.12b.dfsg/src/libscotch/dummysizes.c0000644000175300017530000002702611631334325021517 0ustar hazelscthazelsct/* Copyright 2004,2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dummysizes.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of the libScotch compilation job. **/ /** This small program processes files that **/ /** are in fact pattern header files for **/ /** the libScotch library, and replaces **/ /** symbolic sizes of the opaque libScotch **/ /** by the proper integer values according **/ /** to the machine on which it is run. **/ /** **/ /** DATES : # Version 3.4 : from : 22 oct 2001 **/ /** to : 22 nov 2001 **/ /** # Version 4.0 : from : 25 nov 2001 **/ /** to : 06 jan 2006 **/ /** # Version 5.0 : from : 26 apr 2006 **/ /** to : 03 apr 2008 **/ /** # Version 5.1 : from : 16 jun 2008 **/ /** to : 15 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DUMMYSIZES #define CHARMAX 2048 /* Maximum line size */ #define SUBSMAX 48 /* Maximum number of substitutions */ #define C_FILENBR 2 /* Number of files in list */ #define C_FILEARGNBR 2 /* Number of files which can be arguments */ #define C_filenamehedinp C_fileTab[0].name /* Source graph input file name */ #define C_filenamehedout C_fileTab[1].name /* Statistics output file name */ #define C_filepntrhedinp C_fileTab[0].pntr /* Source graph input file */ #define C_filepntrhedout C_fileTab[1].pntr /* Statistics output file */ #define EXPAND(s) EXPANDTWO(s) #define EXPANDTWO(s) #s #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "geom.h" #include "mesh.h" #include "arch.h" #include "mapping.h" #include "order.h" #ifdef SCOTCH_PTSCOTCH #include "dgraph.h" #include "dgraph_halo.h" #include "dmapping.h" #include "dorder.h" #include "library_dmapping.h" #endif /* SCOTCH_PTSCOTCH */ #include "library_mapping.h" #include "library_order.h" /* ** The static definitions. */ static int C_fileNum = 0; /* Number of file in arg list */ static File C_fileTab[C_FILENBR] = { /* The file array */ { "-", NULL, "r" }, { "-", NULL, "w" } }; /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ void subsFill ( char * substab[2], char * origptr, int subsval) { char * subsptr; subsptr = malloc (32 * sizeof (char)); sprintf (subsptr, "%d", (int) ((subsval + sizeof (double) - 1) / sizeof (double))); substab[0] = origptr; substab[1] = subsptr; } /******************************/ /* */ /* This is the main function. */ /* */ /******************************/ int main ( int argc, char * argv[]) { char chartab[CHARMAX]; char chartmp[CHARMAX]; char * substab[SUBSMAX][2]; /* Substitution array */ int subsnbr; int i; if ((argc >= 2) && (argv[1][0] == '?')) { /* If need for help */ printf ("Usage is:\ndummysizes [ []]\n"); return (((argv[1][0] == '?') && argv[1][1] == '\0') ? 0 : 1); } for (i = 0; i < C_FILENBR; i ++) /* Set default stream pointers */ C_fileTab[i].pntr = (C_fileTab[i].mode[0] == 'r') ? stdin : stdout; for (i = 1; i < argc; i ++) { /* Loop for all option codes */ if ((argv[i][0] != '+') && /* If found a file name */ ((argv[i][0] != '-') || (argv[i][1] == '\0'))) { if (C_fileNum < C_FILEARGNBR) /* A file name has been given */ C_fileTab[C_fileNum ++].name = argv[i]; else { fprintf (stderr, "dummysizes: ERROR: main: too many file names given"); exit (1); } } else { /* If found an option name */ switch (argv[i][1]) { case 'H' : /* Give the usage message */ case 'h' : printf ("Usage is:\ndummysizes [ []]\n"); exit (0); case 'V' : fprintf (stderr, "dummysizes, version " SCOTCH_VERSION_STRING "\n"); fprintf (stderr, "Copyright 2004,2007-2010 ENSEIRB, INRIA & CNRS, France\n"); fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n"); return (0); default : fprintf (stderr, "dummysizes: ERROR: main: unprocessed option (\"%s\")", argv[i]); exit (1); } } } for (i = 0; i < C_FILENBR; i ++) { /* For all file names */ if ((C_fileTab[i].name[0] != '-') || /* If not standard stream */ (C_fileTab[i].name[1] != '\0')) { if ((C_fileTab[i].pntr = fopen (C_fileTab[i].name, C_fileTab[i].mode)) == NULL) { /* Open the file */ fprintf (stderr, "dummysizes: ERROR: main: cannot open file (%d)", i); exit (1); } } } substab[0][0] = "library.h "; #ifdef SCOTCH_PTSCOTCH substab[0][1] = "scotch.h "; #else /* SCOTCH_PTSCOTCH */ substab[0][1] = "ptscotch.h"; #endif /* SCOTCH_PTSCOTCH */ substab[1][0] = "libraryf.h "; #ifdef SCOTCH_PTSCOTCH substab[1][1] = "scotchf.h "; #else /* SCOTCH_PTSCOTCH */ substab[1][1] = "ptscotchf.h"; #endif /* SCOTCH_PTSCOTCH */ substab[2][0] = "DUMMYIDX"; substab[2][1] = EXPAND (IDX); substab[3][0] = "DUMMYINT"; substab[3][1] = EXPAND (INT); substab[4][0] = "DUMMYMAXINT"; substab[4][1] = EXPAND (INTVALMAX); substab[5][0] = "DUMMYNUMSTRING"; substab[5][1] = "\"" GNUMSTRING "\""; substab[6][0] = "DUMMYPTFLAG"; #ifdef SCOTCH_PTSCOTCH substab[6][1] = "PTSCOTCH"; #else /* SCOTCH_PTSCOTCH */ substab[6][1] = "SEQSCOTCH"; #endif /* SCOTCH_PTSCOTCH */ substab[7][0] = "DUMMYVERSION"; substab[7][1] = EXPAND (SCOTCH_VERSION); substab[8][0] = "DUMMYRELEASE"; substab[8][1] = EXPAND (SCOTCH_RELEASE); substab[9][0] = "DUMMYPATCHLEVEL"; substab[9][1] = EXPAND (SCOTCH_PATCHLEVEL); subsnbr = 10; subsFill (substab[subsnbr ++], "DUMMYSIZEARCH", sizeof (Arch)); subsFill (substab[subsnbr ++], "DUMMYSIZEGEOM", sizeof (Geom)); subsFill (substab[subsnbr ++], "DUMMYSIZEGRAPH", sizeof (Graph)); subsFill (substab[subsnbr ++], "DUMMYSIZEMESH", sizeof (Mesh)); subsFill (substab[subsnbr ++], "DUMMYSIZEMAP", sizeof (LibMapping)); subsFill (substab[subsnbr ++], "DUMMYSIZEORDER", sizeof (LibOrder)); subsFill (substab[subsnbr ++], "DUMMYSIZESTRAT", sizeof (Strat *)); #ifdef SCOTCH_PTSCOTCH subsFill (substab[subsnbr ++], "DUMMYSIZEDGRAPHHALOREQ", sizeof (DgraphHaloRequest)); /* TRICK: before DUMMYSIZEDGRAPH */ subsFill (substab[subsnbr ++], "DUMMYSIZEDGRAPH", sizeof (Dgraph)); subsFill (substab[subsnbr ++], "DUMMYSIZEDMAP", sizeof (LibDmapping)); subsFill (substab[subsnbr ++], "DUMMYSIZEDORDER", sizeof (Dorder)); #else /* SCOTCH_PTSCOTCH */ subsFill (substab[subsnbr ++], "DUMMYSIZEDGRAPHHALOREQ", 1); /* TRICK: before DUMMYSIZEDGRAPH */ subsFill (substab[subsnbr ++], "DUMMYSIZEDGRAPH", 1); subsFill (substab[subsnbr ++], "DUMMYSIZEDMAP", 1); subsFill (substab[subsnbr ++], "DUMMYSIZEDORDER", 1); #endif /* SCOTCH_PTSCOTCH */ while (fgets (chartab, CHARMAX, C_filepntrhedinp) != NULL) { /* Infinite loop on file lines */ int charnbr; int subsnum; if (((charnbr = strlen (chartab)) >= (CHARMAX - 1)) && /* If line read is at least as long as maximum size */ (chartab[CHARMAX - 1] != '\n')) { /* And last character is not a newline, that is, some is missing */ fprintf (stderr, "dummysizes: ERROR: line too long\n"); exit (1); } for (subsnum = 0; subsnum < subsnbr; subsnum ++) { /* Perform substitutions */ char * charptr; /* Place where token found */ while ((charptr = strstr (chartab, substab[subsnum][0])) != NULL) { /* As long as substitution can be performed */ int charnbr; int charnum; charnum = charptr - chartab; /* Position where token found */ charnbr = strlen (substab[subsnum][0]); /* Length of token */ strcpy (chartmp, charptr + charnbr); /* Save end of line */ sprintf (charptr, "%s%s", substab[subsnum][1], chartmp); /* Replace end of line with substituted token */ } } fputs (chartab, C_filepntrhedout); /* Output possibly updated line */ } #ifdef SCOTCH_DEBUG_MAIN1 for (i = 0; i < C_FILENBR; i ++) { /* For all file names */ if ((C_fileTab[i].name[0] != '-') || /* If not standard stream */ (C_fileTab[i].name[1] != '\0')) { fclose (C_fileTab[i].pntr); /* Close the stream */ } } #endif /* SCOTCH_DEBUG_MAIN1 */ exit (0); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_gr.h0000644000175300017530000000572611631334325022305 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_gr.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the graph-based node ordering **/ /** routine. **/ /** **/ /** DATES : # Version 4.0 : from : 30 nov 2003 **/ /** to : 30 nov 2003 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HmeshOrderGrParam_ { Strat * stratptr; /*+ Graph ordering strategy +*/ } HmeshOrderGrParam; /* ** The function prototypes. */ #ifndef HMESH_ORDER_GR #define static #endif int hmeshOrderGr (const Hmesh * const, Order * restrict const, const Gnum, OrderCblk * restrict const, const HmeshOrderGrParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/mesh_io_habo.c0000644000175300017530000003065511631334325021724 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mesh_io_habo.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the I/O routines **/ /** for handling the Harwell-Boeing **/ /** elemental matrix format. **/ /** **/ /** DATES : # Version 4.0 : from : 19 jan 2004 **/ /** to 20 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MESH_IO_HABO #include "module.h" #include "common.h" #include "geom.h" #include "graph.h" #include "mesh.h" /* This routine loads the geometrical mesh ** in the Harwell-Boeing matrix format, and ** allocates the proper structures. ** - 0 : on success. ** - !0 : on error. */ int meshGeomLoadHabo ( Mesh * restrict const meshptr, /* Mesh to load */ Geom * restrict const geomptr, /* Geometry to load */ FILE * const filesrcptr, /* Topological data */ FILE * const filegeoptr, /* No use */ const char * const dataptr) /* No use */ { long habmattag; /* Matrix tag number in file */ long habmatnum; /* Current matrix number */ char habmatbuf[4][84]; /* Matrix header line buffers */ char habmattype[4]; /* Matrix type */ long habcrdnbr; /* Total number of data lines */ long habrhsnbr; /* Number of right hand side lines */ int habcolsiz; /* Size of column type */ int habnzrsiz; /* Size of non-zero type */ Gnum habevlnbr; /* Number of element matrix values (not uesd) */ Gnum habvixnbr; /* Number of element matrix variable indices */ Gnum habeltnbr; /* Number of elements */ Gnum habvarnbr; /* Number of variables, that is, nodes */ Gnum velmnum; /* Number of current element vertex */ Gnum vnodnum; /* Number of current node vertex */ Gnum edgenum; /* Number of current edge (arc) */ Gnum edgesum; /* Accumulated number of edges in node part */ Gnum degrmax; /* Maximum degree */ int c; if (((habmattag = atol (dataptr)) == 0) && /* Get tag value */ (dataptr[0] != '0') && (dataptr[0] != '\0')) { errorPrint ("meshGeomLoadHabo: bad input (1)"); return (1); } for (habmatnum = 0; habmatnum <= habmattag; habmatnum ++) { /* Read headers and skip if necessary */ memSet (habmatbuf[0], ' ', &habmatbuf[3][83] - &habmatbuf[0][0]); /* Initialize header buffers */ if ((fgets (habmatbuf[0], 83, filesrcptr) == NULL) || /* Read mesh header */ (fgets (habmatbuf[1], 83, filesrcptr) == NULL) || (fgets (habmatbuf[2], 83, filesrcptr) == NULL) || (fgets (habmatbuf[3], 83, filesrcptr) == NULL)) { errorPrint ("meshGeomLoadHabo: bad input (2)"); return (1); } habmatbuf[1][70] = '\0'; /* Extract header values */ habrhsnbr = atol (&habmatbuf[1][56]); habmatbuf[1][14] = '\0'; habcrdnbr = atol (&habmatbuf[1][00]); habmattype[0] = toupper (habmatbuf[2][0]); habmattype[1] = toupper (habmatbuf[2][1]); habmattype[2] = toupper (habmatbuf[2][2]); habmatbuf[2][70] = '\0'; habevlnbr = (Gnum) atol (&habmatbuf[2][57]); /* NELTVL */ habmatbuf[2][56] = '\0'; habvixnbr = (Gnum) atol (&habmatbuf[2][43]); /* VARIX */ habmatbuf[2][42] = '\0'; habeltnbr = (Gnum) atol (&habmatbuf[2][29]); /* NELT */ habmatbuf[2][28] = '\0'; habvarnbr = (Gnum) atol (&habmatbuf[2][14]); /* NVAR */ habmatbuf[2][14] = '\0'; if ((c = sscanf (habmatbuf[3], "(%*d%*[Ii]%d) (%*d%*[Ii]%d)", &habcolsiz, &habnzrsiz)) != 2) { errorPrint ("meshGeomLoadHabo: bad input (3, %d)", c); return (1); } if (habrhsnbr != 0) { while ((c = getc (filesrcptr)) != '\n'){ /* Skip RHS format line */ if (c == EOF) { errorPrint ("meshGeomLoadHabo: bad input (4)"); return (1); } } } if (habmatnum < habmattag) { /* If we have to skip file */ while (habcrdnbr -- > 0) { /* Skip all of file lines */ while ((c = getc (filesrcptr)) != '\n') { /* Skip line */ if (c == EOF) { errorPrint ("meshGeomLoadHabo: bad input (5)"); return (1); } } } } } if (habmattype[2] != 'E') { errorPrint ("meshGeomLoadHabo: only elemental matrices supported"); return (1); } if (habmattype[1] == 'R') { errorPrint ("meshGeomLoadHabo: rectangular matrices not supported"); return (1); } if (((meshptr->verttax = (Gnum *) memAlloc ((habeltnbr + habvarnbr + 1) * sizeof (Gnum))) == NULL) || ((meshptr->edgetax = (Gnum *) memAlloc (habvixnbr * 2 * sizeof (Gnum))) == NULL)) { errorPrint ("meshGeomLoadHabo: out of memory (1)"); if (meshptr->verttax != NULL) { memFree (meshptr->verttax); meshptr->verttax = NULL; } return (1); } meshptr->flagval = MESHFREETABS; /* Totally new mesh structure */ meshptr->baseval = 1; /* Harwell-Boeing meshs have base 1 */ meshptr->vendtax = meshptr->verttax; meshptr->verttax --; meshptr->edgenbr = habvixnbr * 2; meshptr->edgetax --; meshptr->velmnbr = habeltnbr; meshptr->velmbas = habvarnbr + 1; meshptr->velmnnd = habeltnbr + habvarnbr + 1; meshptr->vnodnbr = habvarnbr; meshptr->vnodbas = 1; meshptr->vnodnnd = meshptr->velmbas; meshptr->vnlosum = habvarnbr; for (velmnum = meshptr->velmbas; velmnum <= meshptr->velmnnd; velmnum ++) { /* Read ELTPTR as second part of vertex array */ Gnum habcolval; /* Current column value */ int habcolidx; /* Current index in column value */ while (((c = getc (filesrcptr)) == '\n') || (c == '\r')) ; habcolval = (c == ' ') ? 0 : (c - '0'); for (habcolidx = 1; habcolidx < habcolsiz; habcolidx ++) { if ((c = getc (filesrcptr)) != ' ') habcolval = habcolval * 10 + c - '0'; } if (c == EOF) { errorPrint ("meshGeomLoadHabo: bad input (6)"); meshFree (meshptr); return (1); } #ifdef SCOTCH_DEBUG_MESH2 if ((habcolval < 1) || (habcolval > (habvixnbr + 1))) { errorPrint ("meshGeomLoadHabo: bad input (7)"); return (1); } #endif /* SCOTCH_DEBUG_MESH2 */ meshptr->verttax[velmnum] = habcolval + habvixnbr; } if (meshptr->verttax[velmnum - 1] != (habvixnbr + habvixnbr + 1)) { errorPrint ("meshGeomLoadHabo: bad input (8)"); meshFree (meshptr); return (1); } memSet (meshptr->verttax + 1, 0, habvarnbr * sizeof (Gnum)); /* Pre-set node adjacency array */ for (edgenum = habvixnbr + 1; edgenum <= meshptr->edgenbr; edgenum ++) { /* Read VARIND as second part of edge array */ Gnum habnodval; /* Current non-zero value */ int habnzridx; /* Current index in non-zero value */ while (((c = getc (filesrcptr)) == '\n') || (c == '\r')) ; habnodval = (c == ' ') ? 0 : (c - '0'); for (habnzridx = 1; habnzridx < habnzrsiz; habnzridx ++) { if ((c = getc (filesrcptr)) != ' ') habnodval = habnodval * 10 + c - '0'; } if (c == EOF) { errorPrint ("meshGeomLoadHabo: bad input (9)"); meshFree (meshptr); return (1); } #ifdef SCOTCH_DEBUG_MESH2 if ((habnodval < 1) || (habnodval > habvarnbr)) { errorPrint ("meshGeomLoadHabo: bad input (10)"); return (1); } #endif /* SCOTCH_DEBUG_MESH2 */ meshptr->edgetax[edgenum] = habnodval; meshptr->verttax[habnodval] ++; } degrmax = 1; for (vnodnum = edgesum = 1; vnodnum < meshptr->vnodnnd; vnodnum ++) { /* Accumulate start indices for node part of vertex array */ Gnum degrval; degrval = meshptr->verttax[vnodnum]; if (degrval > degrmax) degrmax = degrval; meshptr->verttax[vnodnum] = edgesum; edgesum += degrval; } #ifdef SCOTCH_DEBUG_MESH2 if (edgesum != meshptr->verttax[meshptr->velmbas]) { errorPrint ("meshGeomLoadHabo: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_MESH2 */ for (velmnum = meshptr->velmbas, edgenum = habvixnbr + 1; /* Re-scan element part of edge array to build node part of edge array */ velmnum < meshptr->velmnnd; velmnum ++) { if ((meshptr->vendtax[velmnum] - edgenum) > degrmax) degrmax = (meshptr->vendtax[velmnum] - edgenum); for ( ; edgenum < meshptr->vendtax[velmnum]; edgenum ++) { Gnum vnodnum; vnodnum = meshptr->edgetax[edgenum]; #ifdef SCOTCH_DEBUG_MESH2 if ((vnodnum < 1) || (vnodnum > habvarnbr)) { errorPrint ("meshGeomLoadHabo: internal error (2)"); return (1); } if (meshptr->verttax[vnodnum] > habvixnbr) { errorPrint ("meshGeomLoadHabo: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_MESH2 */ meshptr->edgetax[meshptr->verttax[vnodnum] ++] = velmnum; } } meshptr->degrmax = degrmax; for (vnodnum = edgesum = 1; vnodnum < meshptr->vnodnnd; vnodnum ++) { /* Restore start indices for node part of vertex array */ Gnum edgenum; edgenum = meshptr->verttax[vnodnum]; meshptr->verttax[vnodnum] = edgesum; edgesum = edgenum; } #ifdef SCOTCH_DEBUG_MESH2 if (meshCheck (meshptr) != 0) { errorPrint ("meshGeomLoadHabo: inconsistent mesh data"); return (1); } #endif /* SCOTCH_DEBUG_MESH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_graph_map_view.h0000644000175300017530000000714311631334325024025 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_map_view.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the declarations for **/ /** the mapping viewing routines. **/ /** **/ /** DATES : # Version 5.0 : from : 04 feb 2007 **/ /** to 04 feb 2007 **/ /** **/ /************************************************************/ #define LIBRARY_GRAPH_MAP_VIEW_H /* ** The type definitions. */ /*+ Complementary vertex structure. +*/ typedef struct GraphMapViewVertex_ { Gnum passnum; /*+ Number of pass when vertex selected +*/ Gnum vertdist; /*+ Current distance from diameter vertex +*/ } GraphMapViewVertex; /*+ Neighbor queue. +*/ typedef struct GraphMapViewQueue_ { Gnum * head; /*+ Head of distance queue +*/ Gnum * tail; /*+ Tail of distance queue +*/ Gnum * qtab; /*+ Array of queue elements +*/ } GraphMapViewQueue; /* ** The function prototypes. */ #ifndef LIBRARY_GRAPH_MAP_VIEW #define static #endif static Gnum graphMapView2 (const Graph * const, const Anum * const, const Anum); #undef static /* ** The macro definitions. */ #define graphMapViewQueueFlush(queue) ((queue)->head = (queue)->tail = (queue)->qtab) #define graphMapViewQueueEmpty(queue) ((queue)->head <= (queue)->tail) #define graphMapViewQueuePut(queue,vnum) (* ((queue)->head ++) = (vnum)) #define graphMapViewQueueGet(queue) (* ((queue)->tail ++)) scotch-5.1.12b.dfsg/src/libscotch/vmesh_separate_zr.c0000644000175300017530000000620611631334325023024 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_zr.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module moves all of the vertices **/ /** to the first subdomain. **/ /** **/ /** DATES : # Version 4.0 : from : 10 sep 2002 **/ /** to 29 may 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VMESH_SEPARATE_ZR #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" #include "vmesh.h" #include "vmesh_separate_zr.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine moves all of the mesh nodes ** and elements to the first part of the ** partition. ** It returns: ** - 0 : if the bipartitioning could be computed. ** - !0 : on error. */ int vmeshSeparateZr ( Vmesh * restrict const meshptr) { if (meshptr->ncmpload[0] != meshptr->m.vnlosum) /* If not all vertices already in part zero */ vmeshZero (meshptr); return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_geom.c0000644000175300017530000001163711631334325021762 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_geom.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the geom **/ /** graph handling routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 3.4 : from : 10 oct 1999 **/ /** to 01 nov 2001 **/ /** # Version 4.0 : from : 18 dec 2001 **/ /** to 19 jan 2004 **/ /** # Version 5.1 : from : 17 nov 2010 **/ /** to 17 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "geom.h" #include "graph.h" #include "scotch.h" /****************************************/ /* */ /* These routines are the C API for the */ /* graph geometry handling routines. */ /* */ /****************************************/ /*+ This routine reserves a memory area *** of a size sufficient to store a *** geometry structure. *** It returns: *** - !NULL : if the initialization succeeded. *** - NULL : on error. +*/ SCOTCH_Geom * SCOTCH_geomAlloc () { return ((SCOTCH_Geom *) memAlloc (sizeof (SCOTCH_Geom))); } /*+ This routine initializes the opaque *** geom structure used to handle graph *** geometry in the Scotch library. *** It returns: *** - 0 : if the initialization succeeded. *** - !0 : on error. +*/ int SCOTCH_geomInit ( SCOTCH_Geom * const geomptr) { if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { errorPrint ("SCOTCH_geomInit: internal error (1)"); return (1); } if (sizeof (SCOTCH_Geom) < sizeof (Geom)) { errorPrint ("SCOTCH_geomInit: internal error (2)"); return (1); } return (geomInit ((Geom *) geomptr)); } /*+ This routine frees the contents of the *** given opaque geometry structure. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_geomExit ( SCOTCH_Geom * const geomptr) { geomExit ((Geom *) geomptr); } /*+ This routine accesses all of the geometry data. *** NULL pointers on input indicate unwanted *** data. NULL pointers on output indicate *** unexisting arrays. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_geomData ( const SCOTCH_Geom * const geomptr, /* Geometry structure to read */ SCOTCH_Num * const dimnptr, /* Number of dimensions */ double ** const geomtab) /* Geometry array [vertnbr] */ { const Geom * srcgeomptr; /* Pointer to source geometry structure */ srcgeomptr = (const Geom *) geomptr; if (dimnptr != NULL) *dimnptr = srcgeomptr->dimnnbr; if (geomtab != NULL) *geomtab = (double *) srcgeomptr->geomtab; } scotch-5.1.12b.dfsg/src/libscotch/hdgraph_order_si.c0000644000175300017530000001223011631334325022600 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph_order_si.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders halo distributed **/ /** graph vertices using a simple method. **/ /** **/ /** DATES : # Version 5.0 : from : 15 apr 2006 **/ /** to 25 jul 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HDGRAPH_ORDER_SI #include "module.h" #include "common.h" #include "dgraph.h" #include "dorder.h" #include "hdgraph.h" #include "hdgraph_order_si.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hdgraphOrderSi ( const Hdgraph * restrict const grafptr, DorderCblk * restrict const cblkptr) /*+ Single column-block +*/ { Gnum * restrict periloctab; Gnum * restrict periloctax; Gnum vnohlocnbr; Gnum vertlocnum; #ifdef SCOTCH_DEBUG_HDGRAPH1 int cheklocval; int chekglbval; cheklocval = 0; #endif /* SCOTCH_DEBUG_HDGRAPH1 */ vnohlocnbr = grafptr->s.vertlocnbr; /* Get number of local non-halo vertices */ if ((periloctab = (Gnum *) memAlloc (vnohlocnbr * sizeof (Gnum))) == NULL) { /* Allocate local fragment */ errorPrint ("hdgraphOrderSi: out of memory"); #ifndef SCOTCH_DEBUG_HDGRAPH1 return (1); } #else /* SCOTCH_DEBUG_HDGRAPH1 */ } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->s.proccomm) != MPI_SUCCESS) { /* Communication cannot be merged with a useful one */ errorPrint ("hdgraphOrderSi: communication error (1)"); return (1); } if (chekglbval != 0) { if (periloctab != NULL) memFree (periloctab); return (1); } #endif /* SCOTCH_DEBUG_HDGRAPH1 */ cblkptr->typeval = DORDERCBLKLEAF; /* Fill node as leaf */ cblkptr->data.leaf.ordelocval = cblkptr->ordeglbval + grafptr->s.procdsptab[grafptr->s.proclocnum] - grafptr->s.baseval;; cblkptr->data.leaf.vnodlocnbr = vnohlocnbr; cblkptr->data.leaf.periloctab = periloctab; cblkptr->data.leaf.nodelocnbr = 0; cblkptr->data.leaf.nodeloctab = NULL; #ifdef SCOTCH_DEBUG_HDGRAPH2 cblkptr->data.leaf.cblklocnum = -1; #endif /* SCOTCH_DEBUG_HDGRAPH2 */ periloctax = periloctab - grafptr->s.baseval; if (grafptr->s.vnumloctax == NULL) { /* If graph is original graph */ Gnum vertglbadj; vertglbadj = grafptr->s.procdsptab[grafptr->s.proclocnum] - grafptr->s.baseval; /* Set adjustement for global ordering */ for (vertlocnum = grafptr->s.baseval; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) periloctax[vertlocnum] = vertlocnum + vertglbadj; } else { /* Graph is not original graph */ for (vertlocnum = grafptr->s.baseval; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) periloctax[vertlocnum] = grafptr->s.vnumloctax[vertlocnum]; } return (0); } scotch-5.1.12b.dfsg/src/libscotch/graph.c0000644000175300017530000001552111631334325020404 0ustar hazelscthazelsct/* Copyright 2004,2007,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the source graph **/ /** functions. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to 18 may 1993 **/ /** # Version 1.3 : from : 30 apr 1994 **/ /** to 18 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 31 oct 1994 **/ /** # Version 3.0 : from : 07 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 28 nov 1995 **/ /** to 08 jun 1996 **/ /** # Version 3.2 : from : 07 sep 1996 **/ /** to 15 sep 1998 **/ /** # Version 3.3 : from : 22 sep 1998 **/ /** to 31 dec 1998 **/ /** # Version 4.0 : from : 24 nov 2001 **/ /** to 22 apr 2004 **/ /** # Version 5.1 : from : 08 mar 2011 **/ /** to 08 mar 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GRAPH #include "module.h" #include "common.h" #include "graph.h" /****************************************/ /* */ /* These routines handle source graphs. */ /* */ /****************************************/ /* This routine initializes a source graph ** structure. ** It returns: ** - 0 : in all cases. */ int graphInit ( Graph * const grafptr) { memSet (grafptr, 0, sizeof (Graph)); /* Initialize graph fields */ grafptr->flagval = GRAPHFREETABS; /* By default, free all arrays */ return (0); } /* This routine frees a source graph structure. ** It returns: ** - VOID : in all cases. */ void graphExit ( Graph * const grafptr) { graphFree (grafptr); /* Free graph data */ #ifdef SCOTCH_DEBUG_GRAPH2 memSet (grafptr, ~0, sizeof (Graph)); /* Purge graph fields */ #endif /* SCOTCH_DEBUG_GRAPH2 */ } /* This routine frees the graph data. ** It returns: ** - VOID : in all cases. */ void graphFree ( Graph * const grafptr) { if (((grafptr->flagval & GRAPHFREEEDGE) != 0) && /* If edgetab must be freed */ (grafptr->edgetax != NULL)) /* And if it exists */ memFree (grafptr->edgetax + grafptr->baseval); /* Free it */ if ((grafptr->flagval & GRAPHFREEVERT) != 0) { /* If verttab/vendtab must be freed */ if ((grafptr->vendtax != NULL) && /* If vendtax is distinct from verttab */ (grafptr->vendtax != grafptr->verttax + 1) && /* (if vertex arrays grouped, vendtab not distinct anyway) */ ((grafptr->flagval & GRAPHVERTGROUP) == 0)) memFree (grafptr->vendtax + grafptr->baseval); /* Then free vendtax */ if (grafptr->verttax != NULL) /* Free verttab anyway, as it is the array group leader */ memFree (grafptr->verttax + grafptr->baseval); } if ((grafptr->flagval & GRAPHFREEVNUM) != 0) { /* If vnumtab must be freed */ if ((grafptr->vnumtax != NULL) && /* And is not in vertex array group */ ((grafptr->flagval & GRAPHVERTGROUP) == 0)) memFree (grafptr->vnumtax + grafptr->baseval); } if ((grafptr->flagval & GRAPHFREEOTHR) != 0) { /* If other arrays must be freed */ if ((grafptr->velotax != NULL) && /* Free graph tables */ ((grafptr->flagval & GRAPHVERTGROUP) == 0)) memFree (grafptr->velotax + grafptr->baseval); if ((grafptr->vlbltax != NULL) && ((grafptr->flagval & GRAPHVERTGROUP) == 0)) memFree (grafptr->vlbltax + grafptr->baseval); if ((grafptr->edlotax != NULL) && ((grafptr->flagval & GRAPHEDGEGROUP) == 0)) memFree (grafptr->edlotax + grafptr->baseval); } #ifdef SCOTCH_DEBUG_GRAPH2 memSet (grafptr, ~0, sizeof (Graph)); /* Purge graph fields */ #endif /* SCOTCH_DEBUG_GRAPH2 */ } /* This routine returns the SCOTCH_PTSCOTCH ** flag. It is used to detect discrepancies ** resulting from a mixed use of the libscotch ** and libptscotch libraries. ** It returns: ** - 0 : if not compiled as part of the PT-Scotch library. ** - 1 : if compiled as part of the PT-Scotch library. */ int graphPtscotch () { #ifdef SCOTCH_PTSCOTCH return (1); #else /* SCOTCH_PTSCOTCH */ return (0); #endif /* SCOTCH_PTSCOTCH */ } scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_si.h0000644000175300017530000000526311631334325022304 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_si.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the simple halo mesh ordering **/ /** routine. **/ /** **/ /** DATES : # Version 4.0 : from : 01 jan 2002 **/ /** to 28 sep 2002 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef HMESH_ORDER_SI #define static #endif int hmeshOrderSi (const Hmesh * const, Order * const, const Gnum, OrderCblk * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_fm.h0000644000175300017530000001534211631334325022577 0ustar hazelscthazelsct/* Copyright 2004,2007,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_fm.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for our Improved Fiduccia-Mattheyses **/ /** bipartitioning algorithm. **/ /** **/ /** DATES : # Version 1.0 : from : 30 sep 1993 **/ /** to 09 oct 1993 **/ /** # Version 1.1 : from : 15 oct 1993 **/ /** to 15 oct 1993 **/ /** # Version 1.3 : from : 06 apr 1994 **/ /** to 13 apr 1994 **/ /** # Version 2.0 : from : 04 jul 1994 **/ /** to 25 nov 1994 **/ /** # Version 3.0 : from : 06 jul 1995 **/ /** to 06 jul 1995 **/ /** # Version 3.1 : from : 06 nov 1995 **/ /** to 07 jun 1996 **/ /** # Version 3.2 : from : 21 sep 1996 **/ /** to 13 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 12 mar 1999 **/ /** # Version 4.0 : from : 27 aug 2004 **/ /** to 27 aug 2004 **/ /** # Version 5.1 : from : 27 mar 2011 **/ /** to 27 mar 2011 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Gain table subbits. +*/ #define BGRAPHBIPARTFMSUBBITS 4 /*+ Prime number for hashing vertex numbers. +*/ #define BGRAPHBIPARTFMHASHPRIME 17 /*+ Prime number for hashing +*/ /** Gain table vertex status. **/ #define BGRAPHBIPARTFMSTATEFREE ((GainLink *) 0) /*+ Vertex in initial state +*/ #define BGRAPHBIPARTFMSTATEUSED ((GainLink *) 1) /*+ Swapped vertex +*/ #define BGRAPHBIPARTFMSTATELINK ((GainLink *) 2) /*+ Currently in gain table if higher +*/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct BgraphBipartFmParam_ { INT movenbr; /*+ Maximum number of uneffective moves that can be done +*/ INT passnbr; /*+ Number of passes to be performed (-1 : infinite) +*/ double deltval; /*+ Maximum weight imbalance ratio +*/ } BgraphBipartFmParam; /*+ The hash vertex structure. For trick reasons, the gain table data structure must be the first field of the structure. +*/ typedef struct BgraphBipartFmVertex_ { GainLink gainlink; /*+ Gain link: FIRST +*/ Gnum vertnum; /*+ Number of vertex +*/ int partval; /*+ Vertex part +*/ Gnum compgain; /*+ Computation gain +*/ Gnum commgain; /*+ Communication gain +*/ Gnum commcut; /*+ Cut edges +*/ Gnum mswpnum; /*+ Number of move sweep when data recorded +*/ } BgraphBipartFmVertex; /*+ The move recording structure. +*/ typedef struct BgraphBipartFmSave_ { Gnum hashnum; /*+ Number of vertex slot +*/ int partval; /*+ Vertex part +*/ Gnum compgain; /*+ Computation gain +*/ Gnum commgain; /*+ Communication gain +*/ Gnum commcut; /*+ Cut edges +*/ } BgraphBipartFmSave; /* ** The function prototypes. */ #ifndef BGRAPH_BIPART_FM #define static #endif static BgraphBipartFmVertex * bgraphBipartFmTablGet (GainTabl * restrict const, const Gnum, const Gnum, const Gnum); int bgraphBipartFm (Bgraph * restrict const, const BgraphBipartFmParam * const); static int bgraphBipartFmResize (BgraphBipartFmVertex * restrict *, Gnum * restrict const, Gnum * const, BgraphBipartFmSave * restrict *, const Gnum, GainTabl * const, BgraphBipartFmVertex ** const); #ifdef SCOTCH_DEBUG_BGRAPH3 static int bgraphBipartFmCheck (const Bgraph * restrict const, const BgraphBipartFmVertex * restrict const, const Gnum, const int, const Gnum, const Gnum, const Gnum); #endif /* SCOTCH_DEBUG_BGRAPH3 */ #undef static scotch-5.1.12b.dfsg/src/libscotch/hmesh_check.c0000644000175300017530000001124211631334325021540 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_check.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the halo source **/ /** mesh functions. **/ /** **/ /** DATES : # Version 4.0 : from : 12 sep 2002 **/ /** to 11 may 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" #include "hmesh.h" /****************************************/ /* */ /* These routines handle source meshes. */ /* */ /****************************************/ /* This routine checks the consistency ** of the given halo mesh. ** It returns: ** - 0 : if halo mesh data are consistent. ** - !0 : on error. */ int hmeshCheck ( const Hmesh * const meshptr) { Gnum vnhlsum; if ((meshptr->vnohnnd < meshptr->m.vnodbas) || (meshptr->vnohnnd > meshptr->m.vnodnnd)) { errorPrint ("hmeshCheck: invalid halo node numbers"); return (1); } if (meshCheck (&meshptr->m) != 0) { errorPrint ("hmeshCheck: invalid non-halo mesh structure"); return (1); } if (meshptr->vehdtax != meshptr->m.vendtax) { Gnum veihnbr; Gnum velmnum; for (velmnum = meshptr->m.velmbas, veihnbr = 0; /* For all element vertices */ velmnum < meshptr->m.velmnnd; velmnum ++) { if ((meshptr->vehdtax[velmnum] < meshptr->m.verttax[velmnum]) || (meshptr->vehdtax[velmnum] > meshptr->m.vendtax[velmnum])) { errorPrint ("hmeshCheck: invalid non-halo end vertex array"); return (1); } if (meshptr->vehdtax[velmnum] == meshptr->m.verttax[velmnum]) veihnbr ++; } if (veihnbr != meshptr->veihnbr) { errorPrint ("hmeshCheck: invalid number of halo-isolated element vertices (1)"); return (1); } } else { if (meshptr->veihnbr != 0) { errorPrint ("hmeshCheck: invalid number of halo-isolated element vertices (2)"); return (1); } } if (meshptr->m.vnlotax == NULL) /* Recompute non-halo node vertex load sum */ vnhlsum = meshptr->vnohnnd - meshptr->m.vnodbas; else { Gnum vnodnum; for (vnodnum = meshptr->m.vnodbas, vnhlsum = 0; vnodnum < meshptr->vnohnnd; vnodnum ++) vnhlsum += meshptr->m.vnlotax[vnodnum]; } if (vnhlsum != meshptr->vnhlsum) { errorPrint ("hmeshCheck: invalid non-halo vertex load sum"); return (1); } return (0); } scotch-5.1.12b.dfsg/src/libscotch/vmesh_separate_fm.c0000644000175300017530000016225411631334325023001 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh_separate_fm.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module separates an active **/ /** mesh using an element-oriented version **/ /** of our improved Fiduccia-Mattheyses **/ /** heuristics. **/ /** **/ /** DATES : # Version 4.0 : from : 26 feb 2003 **/ /** to 06 may 2004 **/ /** # Version 5.0 : from : 12 sep 2007 **/ /** to 22 may 2008 **/ /** # Version 5.1 : from : 12 nov 2008 **/ /** to 12 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VMESH_SEPARATE_FM /* #define SCOTCH_DEBUG_VMESH3 */ /* For intensive debugging */ #include "module.h" #include "common.h" #include "gain.h" #include "graph.h" #include "mesh.h" #include "vmesh.h" #include "vmesh_separate_gg.h" #include "vmesh_separate_fm.h" /* This routine resizes the hash arrays ** as well as the associated structures. ** In the group of allocated arrays, ** the element array must be put before ** the node array, because the element ** structure is larger than the node ** structure, such that the old and new ** node arrays can never overlap after ** the doubling in size of the element ** array. The same for the move array. ** It returns: ** - 0 : if resize succeeded. ** - !0 : in case of error. */ static int vmeshSeparateFmResize ( GainTabl * restrict const tablptr, /*+ Pointer to gain table +*/ VmeshSeparateFmElement * restrict * const helmptr, /*+ Pointer to pointer to element hash table +*/ VmeshSeparateFmNode * restrict * const hnodptr, /*+ Pointer to pointer to node hash table +*/ VmeshSeparateFmSave * restrict * const saveptr, /*+ Pointer to pointer to move array +*/ const Gnum savenbr, /*+ Current number of items in save array +*/ VmeshSeparateFmElement ** lockptr, /*+ Pointer to list of locked elements +*/ VmeshSeparateFmElement ** sepaptr, /*+ Pointer to list of separator elements, if any +*/ const Gnum hashold) /*+ Maximum number of vertices in hash structures +*/ { Gnum hashsiz; /* Size of hash table */ Gnum hashmsk; /* Mask for access to hash table */ Gnum hashmax; /* Maximum number of objects in tables */ VmeshSeparateFmSave * restrict movetab; /* Pointer to move array */ VmeshSeparateFmElement * restrict helmtab; /* Element hash table */ VmeshSeparateFmNode * hnodtab; /* Node hash table */ size_t addradj; /* Address adjustment */ Gnum helmold; VmeshSeparateFmNode * hnodtld; Gnum hnodold; VmeshSeparateFmSave * restrict savetab; Gnum savenum; hashmax = 2 * hashold; /* Set new number */ hashsiz = 4 * hashmax; /* Set new size */ hashmsk = hashsiz - 1; savetab = *saveptr; /* Point to old move array */ for (savenum = 0; savenum < savenbr; savenum ++) { /* Turn hash indices into vertex indices */ Gnum hertnum; hertnum = savetab[savenum].hertnum; savetab[savenum].hertnum = (hertnum >= 0) ? (*helmptr)[hertnum].velmnum : (-1 - (*hnodptr)[-1 - hertnum].vnodnum); } if (memReallocGroup ((void *) *helmptr, /* Get old group leader */ &helmtab, (size_t) (hashsiz * sizeof (VmeshSeparateFmElement)), &hnodtab, (size_t) (hashsiz * sizeof (VmeshSeparateFmNode)), &movetab, (size_t) (hashmax * sizeof (VmeshSeparateFmSave)), NULL) == NULL) { errorPrint ("vmeshSeparateFmResize: cannot resize arrays"); return (1); /* If cannot reallocate */ } #ifdef SCOTCH_DEBUG_VMESH2 if (((byte *) hnodtab - (byte *) helmtab) < ((byte *) (*saveptr) - (byte *) (*helmptr))) { /* If cannot simply copy node hash array */ errorPrint ("vmeshSeparateFmResize: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ memMov (movetab, ((byte *) helmtab) + ((byte *) *saveptr - (byte *) *helmptr), savenbr * sizeof (VmeshSeparateFmSave)); /* Old array may have moved but arrays cannot overlap */ memSet (hnodtab, ~0, hashsiz * sizeof (VmeshSeparateFmNode)); /* Cannot overlap */ hnodtld = (VmeshSeparateFmNode *) ((byte *) helmtab) + ((byte *) *hnodptr - (byte *) *helmptr); /* Point to old node array */ for (hnodold = 0; hnodold < (hashold * 4); hnodold ++) { /* For all old allocated nodes */ Gnum hnodnew; if (hnodtld[hnodold].vnodnum == ~0) /* If unallocated slot */ continue; /* Skip to next slot */ for (hnodnew = (hnodtld[hnodold].vnodnum * VMESHSEPAFMHASHPRIME) & hashmsk; hnodtab[hnodnew].vnodnum != ~0; hnodnew = (hnodnew + 1) & hashmsk) ; hnodtab[hnodnew] = hnodtld[hnodold]; /* Move node data to new position */ } /* TODO */ fprintf (stderr, "hertnum no longer valid !\n"); exit (1); addradj = (byte *) helmtab - (byte *) (*helmptr); /* Compute address difference */ gainTablFree (tablptr); /* Reset gain table */ memSet (helmtab + hashold, ~0, hashold * 2 * sizeof (VmeshSeparateFmElement)); for (helmold = 0; helmold < (hashold * 4); helmold ++) { /* For all old allocated elements */ Gnum helmnew; if (helmtab[helmold].velmnum == ~0) /* If unallocated slot */ continue; /* Skip to next slot */ for (helmnew = (helmtab[helmold].velmnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; helmnew = (helmnew + 1) & hashmsk) { if (helmtab[helmnew].velmnum == ~0) { helmtab[helmnew].velmnum = helmtab[helmold].velmnum; helmtab[helmnew].vertpart = helmtab[helmold].vertpart; helmtab[helmnew].ncmpcut2 = helmtab[helmold].ncmpcut2; helmtab[helmnew].ncmpgain2 = helmtab[helmold].ncmpgain2; helmtab[helmnew].ncmpgaindlt = helmtab[helmold].ncmpgaindlt; helmtab[helmnew].mswpnum = helmtab[helmold].mswpnum; helmtab[helmold].velmnum = ~0; /* Free old slot */ helmtab[helmold].mswpnum = ~0; /* Reset sweep number */ break; } if (helmtab[helmnew].velmnum != helmtab[helmold].velmnum) /* If element not found */ continue; /* Go on searching */ } if (helmtab[helmold].gainlink.next >= VMESHSEPAFMSTATELINK) /* If element was linked */ gainTablAdd (tablptr, (GainLink *) &helmtab[helmnew], helmtab[helmnew].ncmpgain2); /* Re-link it */ else { /* Element may be chained in some list */ helmtab[helmnew].gainlink.next = helmtab[helmold].gainlink.next; /* Save it */ helmtab[helmnew].gainlink.prev = (GainLink *) ((byte *) helmtab[helmold].gainlink.prev + addradj); } } if (*lockptr != NULL) *lockptr = (VmeshSeparateFmElement *) ((byte *) (*lockptr) + addradj); if (sepaptr != NULL) { if (*sepaptr != NULL) *sepaptr = (VmeshSeparateFmElement *) ((byte *) (*sepaptr) + addradj); } for (savenum = 0; savenum < savenbr; savenum ++) { /* Turn vertex indices back into hash indices */ Gnum vertnum; vertnum = movetab[savenum].hertnum; /* Read vertex index */ if (vertnum >= 0) { /* If element vertex */ Gnum helmnum; for (helmnum = (vertnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; helmnum = (helmnum + 1) & hashmsk) { #ifdef SCOTCH_DEBUG_VMESH2 if (helmtab[helmnum].velmnum == ~0) { /* We should always find the elements */ errorPrint ("vmeshSeparateFmResize: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ if (helmtab[helmnum].velmnum == vertnum) /* If element found */ break; } movetab[savenum].hertnum = helmnum; /* Save element hash index */ } else { /* If node vertex */ Gnum hnodnum; vertnum = -1 - vertnum; for (hnodnum = (vertnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; hnodnum = (hnodnum + 1) & hashmsk) { #ifdef SCOTCH_DEBUG_VMESH2 if (hnodtab[hnodnum].vnodnum == ~0) { /* We should always find the nodes */ errorPrint ("vmeshSeparateFmResize: internal error (3)"); return (1); } if (hnodtab[hnodnum].vnodnum == vertnum) /* If element found */ break; #endif /* SCOTCH_DEBUG_VMESH2 */ } movetab[savenum].hertnum = -1 - hnodnum; /* Save node hash index */ } } fprintf (stderr, "########### vmeshSeparateFmResize (%ld) !!!\n", (long) hashold); return (0); } /* This routine returns the vertex of best gain ** whose swap will keep the balance correct. ** It returns: ** - !NULL : pointer to the vertex. ** - NULL : if no more vertices available. */ static VmeshSeparateFmElement * vmeshSeparateFmTablGet ( GainTabl * const tablptr, /*+ Gain table +*/ const Gnum deltcur, /*+ Current imbalance +*/ const Gnum deltmax) /*+ Maximum imbalance +*/ { const VmeshSeparateFmElement * velmptr; VmeshSeparateFmElement * vertbest; Gnum gainbest; const GainEntr * tablbest; Gnum deltbest; Gnum deltnew; tablbest = tablptr->tend; /* Assume no candidate vertex found yet */ gainbest = GAINMAX; vertbest = NULL; deltbest = deltmax; for (velmptr = (VmeshSeparateFmElement *) gainTablFrst (tablptr); /* Select candidate vertices */ (velmptr != NULL) && (velmptr->gainlink.tabl < tablbest); velmptr = (VmeshSeparateFmElement *) gainTablNext (tablptr, &velmptr->gainlink)) { deltnew = abs (deltcur + velmptr->ncmpgaindlt); if (deltnew <= deltmax) { /* If vertex enforces balance */ if ((velmptr->ncmpgain2 < gainbest) || /* And if it gives better gain */ ((velmptr->ncmpgain2 == gainbest) && /* Or if it gives better load */ (deltnew < deltbest))) { tablbest = velmptr->gainlink.tabl; /* Select it */ gainbest = velmptr->ncmpgain2; vertbest = (VmeshSeparateFmElement *) velmptr; deltbest = deltnew; } } } return (vertbest); } /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine computes the ** separation of the given mesh. ** It returns: ** - 0 : if bipartitioning could be computed. ** - !0 : on error. */ int vmeshSeparateFm ( Vmesh * restrict const meshptr, /*+ Node separation mesh +*/ const VmeshSeparateFmParam * restrict const paraptr) /*+ Method parameters +*/ { GainTabl * restrict tablptr; /* Pointer to gain table */ long passnbr; /* Maximum number of passes to go */ VmeshSeparateFmSave * restrict movetab; /* Pointer to move array */ Gnum movenbr; /* Number of uneffective moves done */ Gnum savenbr; /* Number of recorded backtrack moves */ Gnum mswpnum; /* Current number of recording sweep */ int moveflag; /* Flag set if useful moves made */ Gnum fronnum; /* Current index in frontier array */ Gnum vertnbr; Gnum hashsiz; /* Size of hash table */ Gnum hashmsk; /* Mask for access to hash table */ Gnum hashmax; /* Maximum number of objects in tables */ Gnum hashnbr; /* Estimated number of onjects in hash */ Gnum helmnbr; /* Number of elements in hash table */ Gnum helmnum; Gnum hnodnum; Gnum hnodnbr; /* Number of nodes in hash table */ VmeshSeparateFmElement * restrict helmtab; /* Element hash table */ VmeshSeparateFmNode * restrict hnodtab; /* Node hash table */ VmeshSeparateFmElement * lockptr; /* Linked list of locked elements */ VmeshSeparateFmElement * velmptr; /* Pointer to current element */ Gnum ncmploaddltmat; /* Theoretical latgest imbalance allowed */ Gnum ncmploaddltmax; /* Largest imbalance allowed */ Gnum ncmploaddlt; /* Current imbalance */ Gnum ncmpload2; /* Current size of separator */ Gnum ncmpload2bst; Gnum ncmploaddltbst; Gnum ecmpload1; Gnum ncmpload1; Gnum ncmpsize1; Gnum ncmpsize2; if (paraptr->deltrat > 0.0L) { Gnum ncmploaddlttmp; ncmploaddltmat = (Gnum) (paraptr->deltrat * meshptr->m.vnlosum) + 1; ncmploaddlttmp = (Gnum) (((float) meshptr->m.edgenbr * (float) meshptr->m.vnlosum) / ((float) meshptr->m.velmnbr * (float) meshptr->m.vnodnbr)); if (ncmploaddltmat < ncmploaddlttmp) ncmploaddltmat = ncmploaddlttmp; } else ncmploaddltmat = 0; ncmploaddltmat = (paraptr->deltrat > 0.0L) ? ((Gnum) (paraptr->deltrat * meshptr->m.vnlosum) + 1) : 0; /* printf ("FM Mbal=%ld\n", (long) ncmploaddltmat); */ if ((meshptr->fronnbr == 0) && /* If imbalance in graph with no frontier */ (abs (meshptr->ncmploaddlt) > ncmploaddltmat)) { VmeshSeparateGgParam paramdat; paramdat.passnbr = 3; vmeshSeparateGg (meshptr, ¶mdat); /* Compute a balanced initial partition */ } vertnbr = meshptr->m.velmnbr + meshptr->m.vnodnbr; hashnbr = 2 * ((meshptr->fronnbr + paraptr->movenbr) * (1 + (Gnum) ((float) meshptr->m.edgenbr / (float) vertnbr))); if (hashnbr > vertnbr) /* Set bound on hash table */ hashnbr = vertnbr; for (hashmax = 256; hashmax < hashnbr; hashmax <<= 1) ; /* Get upper power of two */ /* TODO */ hashmax *= 4; hashsiz = 4 * hashmax; hashmsk = hashsiz - 1; if (((tablptr = gainTablInit (meshptr->m.vnlosum, VMESHSEPAFMGAINBITS)) == NULL) || (memAllocGroup ((void **) (void *) &helmtab, (size_t) (hashsiz * sizeof (VmeshSeparateFmElement)), &hnodtab, (size_t) (hashsiz * sizeof (VmeshSeparateFmNode)), &movetab, (size_t) (hashmax * sizeof (VmeshSeparateFmSave)), NULL) == NULL)) { if (tablptr != NULL) { errorPrint ("vmeshSeparateFm: out of memory (1)"); gainTablExit (tablptr); } return (1); } passnbr = paraptr->passnbr; /* Set remaining number of passes */ ncmpload2 = meshptr->ncmpload[2]; /* Set current partition loads */ ncmploaddlt = meshptr->ncmploaddlt; memset (helmtab, ~0, (byte *) &hnodtab[hashsiz] - (byte *) helmtab); /* Set all vertex numbers to ~0 */ helmnbr = hnodnbr = 0; savenbr = 0; /* No recorded moves yet */ lockptr = NULL; /* Set locked list as empty */ for (fronnum = 0; fronnum < meshptr->fronnbr; fronnum ++) { /* Set initial gains */ Gnum vnloval; Gnum vnodnum; Gnum enodnum; Gnum hnodnum; Gnum ecmpsize1; vnodnum = meshptr->frontab[fronnum]; #ifdef SCOTCH_DEBUG_VMESH2 if (meshptr->parttax[vnodnum] != 2) { errorPrint ("vmeshSeparateFm: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ vnloval = (meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum]; for (hnodnum = (vnodnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; hnodnum = (hnodnum + 1) & hashmsk) { if (hnodtab[hnodnum].vnodnum == ~0) /* If node slot found */ break; /* No need to go on */ #ifdef SCOTCH_DEBUG_VMESH2 if (hnodtab[hnodnum].vnodnum == vnodnum) { /* If node already present in frontier array */ errorPrint ("vmeshSeparateFm: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ } hnodnbr ++; /* One more node in hash table */ hnodtab[hnodnum].vnodnum = vnodnum; /* Insert node in hash table */ hnodtab[hnodnum].vnloval = vnloval; if ((meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]) == 0) { /* If single node */ int vnodpart; vnodpart = (ncmploaddlt > 0) ? 1 : 0; ncmpload2 -= vnloval; /* Node cannot belong to the separator */ ncmploaddlt += (1 - 2 * vnodpart) * vnloval; hnodtab[hnodnum].vertpart = vnodpart; hnodtab[hnodnum].ecmpsize0 = 0; continue; /* No need to process elements of node vertex */ } for (enodnum = meshptr->m.verttax[vnodnum], ecmpsize1 = 0; /* For all (at least one) element neighbors of node */ enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { Gnum velmnum; Gnum helmnum; velmnum = meshptr->m.edgetax[enodnum]; for (helmnum = (velmnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; helmnum = (helmnum + 1) & hashmsk) { if (helmtab[helmnum].velmnum == ~0) { /* If element not yet inserted */ if (helmnbr >= hashmax) { /* If element hash table is full */ if (vmeshSeparateFmResize (tablptr, &helmtab, &hnodtab, &movetab, savenbr, &lockptr, NULL, hashmax) != 0) { errorPrint ("vmeshSeparateFm: cannot resize arrays (1)"); memFree (helmtab); /* Free group leader */ gainTablExit (tablptr); return (1); } hashmax <<= 1; hashsiz <<= 1; hashmsk = (hashmsk << 1) | 1; #ifdef SCOTCH_DEBUG_VMESH3 if (vmeshSeparateFmCheck (meshptr, helmtab, hnodtab, hashmsk, ncmpload2, ncmploaddlt) != 0) { errorPrint ("vmeshSeparateFm: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH3 */ for (helmnum = (velmnum * VMESHSEPAFMHASHPRIME) & hashmsk; /* Re-compute position in table */ helmtab[helmnum].velmnum != ~0; helmnum = (helmnum + 1) & hashmsk) ; } helmtab[helmnum].gainlink.prev = (GainLink *) lockptr; /* Link it */ lockptr = &helmtab[helmnum]; helmtab[helmnum].velmnum = velmnum; /* Insert it */ helmtab[helmnum].vertpart = meshptr->parttax[velmnum] & 1; /* Separator elements to part 0 */ helmnbr ++; break; } if (helmtab[helmnum].velmnum == velmnum) /* If element already or newly inserted */ break; /* It will already be processed later */ } ecmpsize1 += helmtab[helmnum].vertpart; /* Account for its (possibly modified) part */ } hnodtab[hnodnum].vertpart = 2; /* Assume node is in separator */ hnodtab[hnodnum].ecmpsize0 = meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum] - ecmpsize1; if (hnodtab[hnodnum].ecmpsize0 == 0) { /* If all neighboring elements are in part 1 */ ncmpload2 -= vnloval; /* Node moves from separator to part 1 too */ ncmploaddlt -= vnloval; hnodtab[hnodnum].vertpart = 1; } else if (ecmpsize1 == 0) { /* If all neighboring elements are in part 0 */ ncmpload2 -= vnloval; /* Node moves from separator to part 0 too */ ncmploaddlt += vnloval; hnodtab[hnodnum].vertpart = 0; } } for (velmptr = lockptr; velmptr != NULL; /* Process all frontier elements */ velmptr = (VmeshSeparateFmElement *) velmptr->gainlink.prev) { Gnum velmnum; Gnum eelmnum; Gnum ncmpcut2; Gnum ncmpgain2; Gnum ncmpgaindlt; velmnum = velmptr->velmnum; ncmpcut2 = ncmpgain2 = ncmpgaindlt = 0; for (eelmnum = meshptr->m.verttax[velmnum]; /* For all neighbors of element */ eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { Gnum vnodnum; Gnum hnodnum; Gnum vnoddeg; vnodnum = meshptr->m.edgetax[eelmnum]; vnoddeg = meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]; for (hnodnum = (vnodnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; hnodnum = (hnodnum + 1) & hashmsk) { if (hnodtab[hnodnum].vnodnum == vnodnum) { /* If node exists (can be in same part or separator) */ int vnodpart; Gnum vnloval; vnodpart = hnodtab[hnodnum].vertpart; vnloval = hnodtab[hnodnum].vnloval; if (vnodpart == 2) { /* If vertex is in separator */ ncmpcut2 ++; /* One more node in separator */ if ((hnodtab[hnodnum].ecmpsize0 - 1) == ((vnoddeg - 2) * velmptr->vertpart)) { /* If element is only neighbor in its part */ ncmpgain2 -= vnloval; ncmpgaindlt += vnloval * (2 * velmptr->vertpart - 1); } } else { /* Vertex not in separator */ #ifdef SCOTCH_DEBUG_VMESH2 if (vnodpart != velmptr->vertpart) { /* Node should be in same part as element */ errorPrint ("vmeshSeparateFm: internal error (4)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ if (vnoddeg <= 1) /* If element is node's sole neighbor */ ncmpgaindlt += (vnloval * (2 * vnodpart - 1)) * 2; else { ncmpgain2 += vnloval; ncmpgaindlt += (vnloval * (2 * vnodpart - 1)); } } break; } if (hnodtab[hnodnum].vnodnum == ~0) { /* If node does not exist */ int vnodpart; Gnum vnloval; vnodpart = velmptr->vertpart; /* Get its part */ vnloval = (meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum]; #ifdef SCOTCH_DEBUG_VMESH2 if (vnodpart != meshptr->parttax[vnodnum]) { /* Node should be in same part as element */ errorPrint ("vmeshSeparateFm: internal error (5)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ if (vnoddeg > 1) { /* If node will move to separator */ ncmpgain2 += vnloval; /* Increase size of separator */ ncmpgaindlt += (2 * vnodpart - 1) * vnloval; /* Account for imbalance */ } else /* Node will move with element */ ncmpgaindlt += (2 * vnodpart - 1) * 2 * vnloval; /* Double imbalance */ break; } } } velmptr->ncmpcut2 = ncmpcut2; velmptr->ncmpgain2 = ncmpgain2; velmptr->ncmpgaindlt = ncmpgaindlt; } ncmploaddltmax = MAX (ncmploaddltmat, abs (ncmploaddlt)); /* Set current maximum imbalance after cleaning */ #ifdef SCOTCH_DEBUG_VMESH3 if (vmeshSeparateFmCheck (meshptr, helmtab, hnodtab, hashmsk, ncmpload2, ncmploaddlt) != 0) { errorPrint ("vmeshSeparateFm: internal error (6)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH3 */ mswpnum = 0; /* First sweep */ ncmpload2bst = ncmpload2; /* Record best state */ ncmploaddltbst = ncmploaddlt; do { /* As long as there are improvements */ VmeshSeparateFmElement * velmptr; Gnum velmgain2; Gnum velmgaindlt; while (lockptr != NULL) { /* For all elements in locked list */ VmeshSeparateFmElement * velmptr; velmptr = lockptr; /* Unlink element from list */ lockptr = (VmeshSeparateFmElement *) velmptr->gainlink.prev; velmptr->gainlink.next = VMESHSEPAFMSTATEFREE;/* Set it free anyway */ if (velmptr->ncmpcut2 > 0) /* If element has nodes in separator */ gainTablAdd (tablptr, (GainLink *) velmptr, velmptr->ncmpgain2); /* Put it in table */ } /* fprintf (stderr, "LOOP %ld\t(%ld,\t%ld)\n", (long) passnbr, (long) ncmpload2bst, (long) ncmploaddltbst); */ moveflag = 0; /* No moves to date */ movenbr = 0; /* No uneffective moves yet */ while ((movenbr < paraptr->movenbr) && /* As long as we can find effective elements */ ((velmptr = vmeshSeparateFmTablGet (tablptr, ncmploaddlt, ncmploaddltmax)) != NULL)) { VmeshSeparateFmElement * sepaptr; /* Linked list of separator frontier elements */ Gnum velmnum; /* Number of current element */ Gnum velmpart; /* Old part of current element */ Gnum eelmnum; gainTablDel (tablptr, &velmptr->gainlink); /* Remove it from table */ velmptr->gainlink.next = VMESHSEPAFMSTATEUSED; /* Mark it as used */ velmptr->gainlink.prev = (GainLink *) lockptr; /* Lock it */ lockptr = velmptr; if (velmptr->mswpnum != mswpnum) { /* If element data not yet recorded */ movetab[savenbr].hertnum = velmptr - helmtab; /* Record them */ movetab[savenbr].data.elem.vertpart = velmptr->vertpart; movetab[savenbr].data.elem.ncmpcut2 = velmptr->ncmpcut2; movetab[savenbr].data.elem.ncmpgain2 = velmptr->ncmpgain2; movetab[savenbr].data.elem.ncmpgaindlt = velmptr->ncmpgaindlt; velmptr->mswpnum = mswpnum; savenbr ++; /* One more move recorded */ } movenbr ++; /* One more assumed uneffective move performed */ velmgain2 = velmptr->ncmpgain2; /* Save old gains for this vertex */ velmgaindlt = velmptr->ncmpgaindlt; ncmpload2 += velmgain2; /* Account for gains */ ncmploaddlt += velmgaindlt; velmnum = velmptr->velmnum; /* Move element to other part */ velmpart = velmptr->vertpart; velmptr->vertpart = velmpart ^ 1; sepaptr = NULL; /* No frontier elements to relink yet */ for (eelmnum = meshptr->m.verttax[velmnum]; /* (Re-)link neighbors */ eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { Gnum vnoddeg; Gnum vnodnum; Gnum hnodnum; Gnum enodnum; Gnum vnloval; /* Load of current node */ int vnodpartold; /* Old part of current node */ int vnodpartnew; /* New part of current node */ Gnum ecmpsize0old; Gnum ecmpsize0new; vnodnum = meshptr->m.edgetax[eelmnum]; vnoddeg = meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]; for (hnodnum = (vnodnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; hnodnum = (hnodnum + 1) & hashmsk) { if (hnodtab[hnodnum].vnodnum == vnodnum) /* If node found */ break; if (hnodtab[hnodnum].vnodnum == ~0) { /* If node not yet inserted */ #ifdef SCOTCH_DEBUG_VMESH2 if (meshptr->parttax[vnodnum] != velmpart) { errorPrint ("vmeshSeparateFm: internal error (7)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ if (hnodnbr >= hashmax) { /* If node hash table is full */ if (vmeshSeparateFmResize (tablptr, &helmtab, &hnodtab, &movetab, savenbr, &lockptr, &sepaptr, hashmax) != 0) { errorPrint ("vmeshSeparateFm: cannot resize arrays (2)"); memFree (helmtab); /* Free group leader */ gainTablExit (tablptr); return (1); } hashmax <<= 1; hashsiz <<= 1; hashmsk = (hashmsk << 1) | 1; #ifdef SCOTCH_DEBUG_VMESH3 if (vmeshSeparateFmCheck (meshptr, helmtab, hnodtab, hashmsk, ncmpload2, ncmploaddlt) != 0) { errorPrint ("vmeshSeparateFm: internal error (8)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH3 */ for (helmnum = (velmnum * VMESHSEPAFMHASHPRIME) & hashmsk; /* Re-compute positions in tables */ helmtab[helmnum].velmnum != velmnum; helmnum = (helmnum + 1) & hashmsk) ; velmptr = helmtab + helmnum; for (hnodnum = (vnodnum * VMESHSEPAFMHASHPRIME) & hashmsk; hnodtab[hnodnum].vnodnum != ~0; hnodnum = (hnodnum + 1) & hashmsk) ; } hnodtab[hnodnum].vnodnum = vnodnum; /* Insert node in hash table */ hnodtab[hnodnum].vnloval = (meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum]; hnodtab[hnodnum].ecmpsize0 = vnoddeg * (1 - velmpart); hnodtab[hnodnum].vertpart = velmpart; /* Node belongs to old part */ hnodnbr ++; /* One more node created */ break; } } if (hnodtab[hnodnum].mswpnum != mswpnum) { /* If node data not yet recorded */ movetab[savenbr].hertnum = -1 - hnodnum; movetab[savenbr].data.node.vertpart = hnodtab[hnodnum].vertpart; movetab[savenbr].data.node.ecmpsize0 = hnodtab[hnodnum].ecmpsize0; hnodtab[hnodnum].mswpnum = mswpnum; savenbr ++; /* One more move recorded */ } vnloval = hnodtab[hnodnum].vnloval; if (vnoddeg <= 1) { /* If node only has one neighbor */ #ifdef SCOTCH_DEBUG_VMESH2 if (hnodtab[hnodnum].vertpart != velmpart) { errorPrint ("vmeshSeparateFm: internal error (9)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ hnodtab[hnodnum].vertpart = 1 - velmpart; /* Directly move node to other part */ hnodtab[hnodnum].ecmpsize0 = velmpart; continue; /* Skip to next node */ } ecmpsize0old = hnodtab[hnodnum].ecmpsize0; ecmpsize0new = hnodtab[hnodnum].ecmpsize0 += (2 * velmpart - 1); /* One less neighbor element for this node */ #ifdef SCOTCH_DEBUG_VMESH2 if ((hnodtab[hnodnum].ecmpsize0 < 0) || (hnodtab[hnodnum].ecmpsize0 > vnoddeg)) { errorPrint ("vmeshSeparateFm: internal error (10)"); return (1); } if (hnodtab[hnodnum].vertpart == (1 - velmpart)) { errorPrint ("vmeshSeparateFm: internal error (11)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ vnodpartold = hnodtab[hnodnum].vertpart; /* Get old node part value */ vnodpartnew = 2; /* Assume new node part */ if (vnodpartold != vnodpartnew) /* If belonged to old part */ hnodtab[hnodnum].vertpart = vnodpartnew; /* Move to separator */ else if ((ecmpsize0old - 1) == (vnoddeg - 2) * velmpart) { vnodpartnew = /* Belonged to separator and last element in this part */ hnodtab[hnodnum].vertpart = 1 - velmpart; } for (enodnum = meshptr->m.verttax[vnodnum]; /* For all element neighbors of node */ enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { Gnum velmend; Gnum helmend; int vendpart; Gnum ncmpcut2; Gnum ncmpgain2; Gnum ncmpgaindlt; velmend = meshptr->m.edgetax[enodnum]; for (helmend = (velmend * VMESHSEPAFMHASHPRIME) & hashmsk; ; helmend = (helmend + 1) & hashmsk) { if (helmtab[helmend].velmnum == velmend) /* If element found */ break; if (helmtab[helmend].velmnum == ~0) { /* If element not yet inserted */ Gnum ncmpgain2; Gnum ncmpgaindlt; #ifdef SCOTCH_DEBUG_VMESH2 if (vnodpartold == 2) { /* Elements neighboring the frontier should exist */ errorPrint ("vmeshSeparateFm: internal error (12)"); return (1); } if (vnodpartold != meshptr->parttax[velmend]) { /* Unexisting elements should be in same part as their neighboring nodes */ errorPrint ("vmeshSeparateFm: internal error (13)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ if (helmnbr >= hashmax) { /* If element hash table is full */ if (vmeshSeparateFmResize (tablptr, &helmtab, &hnodtab, &movetab, savenbr, &lockptr, &sepaptr, hashmax) != 0) { errorPrint ("vmeshSeparateFm: cannot resize arrays (3)"); memFree (helmtab); /* Free group leader */ gainTablExit (tablptr); return (1); } hashmax <<= 1; hashsiz <<= 1; hashmsk = (hashmsk << 1) | 1; #ifdef SCOTCH_DEBUG_VMESH3 if (vmeshSeparateFmCheck (meshptr, helmtab, hnodtab, hashmsk, ncmpload2, ncmploaddlt) != 0) { errorPrint ("vmeshSeparateFm: internal error (14)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH3 */ for (helmnum = (velmnum * VMESHSEPAFMHASHPRIME) & hashmsk; /* Re-compute positions in tables */ helmtab[helmnum].velmnum != velmnum; helmnum = (helmnum + 1) & hashmsk) ; velmptr = helmtab + helmnum; for (hnodnum = (vnodnum * VMESHSEPAFMHASHPRIME) & hashmsk; hnodtab[hnodnum].vnodnum != vnodnum; hnodnum = (hnodnum + 1) & hashmsk) ; for (helmend = (velmend * VMESHSEPAFMHASHPRIME) & hashmsk; helmtab[helmend].velmnum != ~0; helmend = (helmend + 1) & hashmsk) ; } helmtab[helmend].gainlink.next = VMESHSEPAFMSTATEFREE; helmtab[helmend].velmnum = velmend; helmtab[helmend].vertpart = vnodpartold; helmtab[helmend].ncmpcut2 = 0; if (meshptr->m.vnlotax == NULL) { Gnum eelmend; ncmpgain2 = meshptr->m.vendtax[velmend] - meshptr->m.verttax[velmend]; ncmpgaindlt = (2 * vnodpartold - 1) * ncmpgain2; for (eelmend = meshptr->m.verttax[velmend]; /* For all neighboring nodes */ eelmend < meshptr->m.vendtax[velmend]; eelmend ++) { Gnum vnodend; vnodend = meshptr->m.edgetax[eelmend]; if ((meshptr->m.vendtax[vnodend] - meshptr->m.verttax[vnodend]) <= 1) { /* If node linked to element only */ ncmpgain2 --; /* Node will directly move to other part */ ncmpgaindlt += (2 * velmpart - 1); } } } else { Gnum eelmend; Gnum veloend; for (eelmend = meshptr->m.verttax[velmend], ncmpgain2 = ncmpgaindlt = veloend = 0; /* For all neighboring nodes */ eelmend < meshptr->m.vendtax[velmend]; eelmend ++) { Gnum vnodend; Gnum vnloend; vnodend = meshptr->m.edgetax[eelmend]; vnloend = meshptr->m.vnlotax[vnodend]; veloend += vnloend; if ((meshptr->m.vendtax[vnodend] - meshptr->m.verttax[vnodend]) <= 1) { /* If node linked to element only */ ncmpgain2 -= vnloend; ncmpgaindlt += vnloend * (2 * velmpart - 1); } } ncmpgain2 += veloend; ncmpgaindlt += (2 * vnodpartold - 1) * veloend; } helmtab[helmend].ncmpgain2 = ncmpgain2; helmtab[helmend].ncmpgaindlt = ncmpgaindlt; helmnbr ++; break; } } if (helmtab[helmend].mswpnum != mswpnum) { /* If element data not yet recorded */ movetab[savenbr].hertnum = helmend; movetab[savenbr].data.elem.vertpart = helmtab[helmend].vertpart; movetab[savenbr].data.elem.ncmpcut2 = helmtab[helmend].ncmpcut2; movetab[savenbr].data.elem.ncmpgain2 = helmtab[helmend].ncmpgain2; movetab[savenbr].data.elem.ncmpgaindlt = helmtab[helmend].ncmpgaindlt; helmtab[helmend].mswpnum = mswpnum; savenbr ++; /* One more move recorded */ } if (helmtab[helmend].gainlink.next != VMESHSEPAFMSTATEUSED) { /* If element available */ if (helmtab[helmend].gainlink.next >= VMESHSEPAFMSTATELINK) /* If element linked */ gainTablDel (tablptr, &helmtab[helmend].gainlink); /* Unlink element */ helmtab[helmend].gainlink.next = VMESHSEPAFMSTATEUSED; /* Chain neighbor elements */ helmtab[helmend].gainlink.prev = (GainLink *) sepaptr; sepaptr = &helmtab[helmend]; } vendpart = helmtab[helmend].vertpart; ncmpcut2 = helmtab[helmend].ncmpcut2; /* Get element values */ ncmpgain2 = helmtab[helmend].ncmpgain2; ncmpgaindlt = helmtab[helmend].ncmpgaindlt; if (vnodpartold != 2) { /* If node was in same part as the element */ ncmpgain2 -= vnloval; ncmpgaindlt -= (2 * vendpart - 1) * vnloval; } else { /* If node was in separator */ ncmpcut2 --; if ((ecmpsize0old - 1) == ((vnoddeg - 2) * vendpart)) { /* If element was the only one in its part */ ncmpgain2 += vnloval; ncmpgaindlt -= (2 * vendpart - 1) * vnloval; } } if (vnodpartnew != 2) { /* If node is now in same part as the element */ ncmpgain2 += vnloval; ncmpgaindlt += (2 * vendpart - 1) * vnloval; } else { /* If node is now in separator */ ncmpcut2 ++; if ((ecmpsize0new - 1) == ((vnoddeg - 2) * vendpart)) { /* If element is the only one in its part */ ncmpgain2 -= vnloval; ncmpgaindlt += (2 * vendpart - 1) * vnloval; } } helmtab[helmend].ncmpcut2 = ncmpcut2; /* Adjust element values */ helmtab[helmend].ncmpgain2 = ncmpgain2; helmtab[helmend].ncmpgaindlt = ncmpgaindlt; } } velmptr->ncmpgain2 = - velmgain2; /* Set new gains of element */ velmptr->ncmpgaindlt = - velmgaindlt; while (sepaptr != NULL) { /* As long as there are element to re-link */ VmeshSeparateFmElement * velmptr; velmptr = sepaptr; /* Get element to re-link */ sepaptr = (VmeshSeparateFmElement *) velmptr->gainlink.prev; velmptr->gainlink.next = VMESHSEPAFMSTATEFREE; if (velmptr->ncmpcut2 != 0) /* If element belongs to frontier */ gainTablAdd (tablptr, (GainLink *) velmptr, velmptr->ncmpgain2); /* Re-link it */ } #ifdef SCOTCH_DEBUG_VMESH3 if (vmeshSeparateFmCheck (meshptr, helmtab, hnodtab, hashmsk, ncmpload2, ncmploaddlt) != 0) { errorPrint ("vmeshSeparateFm: internal error (15)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH3 */ if (ncmpload2 < ncmpload2bst) { /* If move improves separator size */ ncmpload2bst = ncmpload2; /* This move was effective */ ncmploaddltbst = ncmploaddlt; movenbr = savenbr = 0; moveflag = 1; mswpnum ++; } else if (ncmpload2 == ncmpload2bst) { if (abs (ncmploaddlt) < abs (ncmploaddltbst)) { ncmploaddltbst = ncmploaddlt; /* This move was effective */ movenbr = savenbr = 0; moveflag = 1; mswpnum ++; } else if (abs (ncmploaddlt) == abs (ncmploaddltbst)) { ncmploaddltbst = ncmploaddlt; /* Might be the opposite, so record */ savenbr = 0; /* Forget backtracking */ mswpnum ++; } } if (ncmploaddltmax > ncmploaddltmat) { /* If must restrict distance bounds */ Gnum ncmploaddlttmp; ncmploaddlttmp = ncmploaddltmax; /* Save old working ncmpdltmax value */ ncmploaddltmax = MAX (ncmploaddltmat, /* Restrict at most to maximum */ abs (ncmploaddlt)); if (ncmploaddltmax < ncmploaddlttmp) { /* If we have done something useful */ ncmpload2bst = ncmpload2; /* Then record best move done */ ncmploaddltbst = ncmploaddlt; movenbr = savenbr = 0; mswpnum ++; } } } while (savenbr > 0) { /* Delete exceeding moves */ Gnum hertnum; hertnum = movetab[-- savenbr].hertnum; /* Get vertex hash number */ if (hertnum >= 0) { /* If vertex is element */ helmtab[hertnum].vertpart = movetab[savenbr].data.elem.vertpart; helmtab[hertnum].ncmpcut2 = movetab[savenbr].data.elem.ncmpcut2; helmtab[hertnum].ncmpgain2 = movetab[savenbr].data.elem.ncmpgain2; helmtab[hertnum].ncmpgaindlt = movetab[savenbr].data.elem.ncmpgaindlt; if (helmtab[hertnum].gainlink.next != VMESHSEPAFMSTATEUSED) { /* If element not already removed */ if (helmtab[hertnum].gainlink.next >= VMESHSEPAFMSTATELINK) /* If vertex is still linked */ gainTablDel (tablptr, &helmtab[hertnum].gainlink); /* Remove it from table */ helmtab[hertnum].gainlink.next = VMESHSEPAFMSTATEUSED; helmtab[hertnum].gainlink.prev = (GainLink *) lockptr; /* Lock it */ lockptr = &helmtab[hertnum]; } } else { /* Vertex is node */ hertnum = -1 - hertnum; /* Get hash index */ hnodtab[hertnum].vertpart = movetab[savenbr].data.node.vertpart; hnodtab[hertnum].ecmpsize0 = movetab[savenbr].data.node.ecmpsize0; } } ncmpload2 = ncmpload2bst; /* Restore best separator parameters */ ncmploaddlt = ncmploaddltbst; mswpnum ++; /* Forget all recorded moves */ #ifdef SCOTCH_DEBUG_VMESH3 if (vmeshSeparateFmCheck (meshptr, helmtab, hnodtab, hashmsk, ncmpload2, ncmploaddlt) != 0) { errorPrint ("vmeshSeparateFm: internal error (16)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH3 */ } while ((moveflag != 0) && /* As long as vertices are moved */ (-- passnbr != 0)); /* And we are allowed to loop (TRICK for negative values) */ ecmpload1 = 0; /* Assume no change in elements */ for (helmnum = 0; helmnum < hashsiz; helmnum ++) { Gnum velmnum; velmnum = helmtab[helmnum].velmnum; if ((velmnum != ~0) && (helmtab[helmnum].vertpart != meshptr->parttax[velmnum])) { #ifdef SCOTCH_DEBUG_VMESH2 if ((helmtab[helmnum].vertpart < 0) || /* Separator elements should have been removed */ (helmtab[helmnum].vertpart > 1)) { errorPrint ("vmeshSeparateFm: internal error (17)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ ecmpload1 += helmtab[helmnum].vertpart - (meshptr->parttax[velmnum] & 1); meshptr->parttax[velmnum] = helmtab[helmnum].vertpart; } } meshptr->ecmpsize[1] += ecmpload1; /* No longer elements in separator */ meshptr->ecmpsize[0] = meshptr->m.velmnbr - meshptr->ecmpsize[1]; #ifdef SCOTCH_DEBUG_VMESH2 if ((meshptr->ecmpsize[0] + meshptr->ecmpsize[1]) != meshptr->m.velmnbr) { /* Separator elements should have been removed */ errorPrint ("vmeshSeparateFm: internal error (18)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ ncmpsize1 = ncmpsize2 = 0; ncmpload1 = ncmpload2 = 0; for (hnodnum = 0, fronnum = 0; hnodnum < hashsiz; hnodnum ++) { Gnum vnodnum; vnodnum = hnodtab[hnodnum].vnodnum; if (vnodnum != ~0) { #ifdef SCOTCH_DEBUG_VMESH2 if ((hnodtab[hnodnum].vertpart < 0) || (hnodtab[hnodnum].vertpart > 2)) { errorPrint ("vmeshSeparateFm: internal error (19)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ if (hnodtab[hnodnum].vertpart == 2) /* If node belongs to separator */ meshptr->frontab[fronnum ++] = vnodnum; /* Add it to separator array */ if (hnodtab[hnodnum].vertpart != meshptr->parttax[vnodnum]) { Gnum diffpart1; Gnum diffpart2; diffpart1 = (hnodtab[hnodnum].vertpart & 1) - (meshptr->parttax[vnodnum] & 1); diffpart2 = (hnodtab[hnodnum].vertpart >> 1) - (meshptr->parttax[vnodnum] >> 1); ncmpsize1 += diffpart1; ncmpsize2 += diffpart2; ncmpload1 += hnodtab[hnodnum].vnloval * diffpart1; ncmpload2 += hnodtab[hnodnum].vnloval * diffpart2; meshptr->parttax[vnodnum] = hnodtab[hnodnum].vertpart; } } } #ifdef SCOTCH_DEBUG_VMESH2 if ((meshptr->fronnbr + ncmpsize2) != fronnum) { errorPrint ("vmeshSeparateFm: internal error (20)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ meshptr->ncmpload[1] += ncmpload1; meshptr->ncmpload[2] += ncmpload2; meshptr->ncmpload[0] = meshptr->m.vnlosum - meshptr->ncmpload[1] - meshptr->ncmpload[2]; meshptr->ncmploaddlt = meshptr->ncmpload[0] - meshptr->ncmpload[1]; meshptr->fronnbr = fronnum; meshptr->ncmpsize[1] += ncmpsize1; meshptr->ncmpsize[0] = meshptr->m.vnodnbr - fronnum - meshptr->ncmpsize[1]; memFree (helmtab); /* Free group leader */ gainTablExit (tablptr); #ifdef SCOTCH_DEBUG_VMESH2 if (vmeshCheck (meshptr) != 0) { errorPrint ("vmeshSeparateFm: internal error (21)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ /* printf ("FM Sepa\tsize=%ld\tload=%ld\tbal=%ld\n", (long) meshptr->fronnbr, (long) meshptr->ncmpload[2], (long) meshptr->ncmploaddlt); */ return (0); } /* This routine checks the consistency of ** the hash structures. ** It returns: ** - 0 : in case of success. ** - !0 : in case of error. */ #ifdef SCOTCH_DEBUG_VMESH3 static int vmeshSeparateFmCheck ( const Vmesh * const meshptr, const VmeshSeparateFmElement * restrict helmtab, const VmeshSeparateFmNode * restrict hnodtab, const Gnum hashmsk, const Gnum ncmpload2, const Gnum ncmploaddlt) { Gnum vertnbr; Gnum helmnum; Gnum hnodnum; Gnum ncmploadtmp[3]; GraphPart * restrict parttax; vertnbr = meshptr->m.velmnbr + meshptr->m.vnodnbr; if ((parttax = (GraphPart *) memAlloc (vertnbr * sizeof (GraphPart))) == NULL) { errorPrint ("vmeshSeparateFmCheck: out of memory"); return (1); } memCpy (parttax, meshptr->parttax + meshptr->m.baseval, vertnbr * sizeof (GraphPart)); parttax -= meshptr->m.baseval; ncmploadtmp[0] = meshptr->ncmpload[0]; ncmploadtmp[1] = meshptr->ncmpload[1]; ncmploadtmp[2] = meshptr->ncmpload[2]; for (hnodnum = 0; hnodnum <= hashmsk; hnodnum ++) { /* For all node slots */ Gnum vnodnum; Gnum enodnum; Gnum ecmpsize0; int vnodpart; vnodnum = hnodtab[hnodnum].vnodnum; if (vnodnum == ~0) /* If unallocated slot */ continue; /* Skip to next slot */ if (hnodtab[hnodnum].vnloval != ((meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum])) { errorPrint ("vmeshSeparateFmCheck: invalid node load"); return (1); } if ((hnodtab[hnodnum].ecmpsize0 < 0) || (hnodtab[hnodnum].ecmpsize0 > (meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]))) { errorPrint ("vmeshSeparateFmCheck: invalid node neighbors in part 0"); return (1); } vnodpart = hnodtab[hnodnum].vertpart; if (vnodpart != meshptr->parttax[vnodnum]) { ncmploadtmp[meshptr->parttax[vnodnum]] -= hnodtab[hnodnum].vnloval; ncmploadtmp[vnodpart] += hnodtab[hnodnum].vnloval; parttax[vnodnum] = vnodpart; } ecmpsize0 = 0; for (enodnum = meshptr->m.verttax[vnodnum]; /* For all element neighbors */ enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { Gnum velmnum; Gnum helmnum; int velmpart; velmnum = meshptr->m.edgetax[enodnum]; for (helmnum = (velmnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; helmnum = (helmnum + 1) & hashmsk) { if (helmtab[helmnum].velmnum == velmnum) { /* If element found */ velmpart = helmtab[helmnum].vertpart; parttax[velmnum] = velmpart; break; } if (helmtab[helmnum].velmnum == ~0) { /* If element not present */ velmpart = meshptr->parttax[velmnum]; break; } } if (velmpart == 0) ecmpsize0 ++; } if (ecmpsize0 != hnodtab[hnodnum].ecmpsize0) { errorPrint ("vmeshSeparateFmCheck: invalid node neighbor count"); return (1); } } if (ncmpload2 != ncmploadtmp[2]) { errorPrint ("vmeshSeparateFmCheck: invalid frontier load"); return (1); } if (ncmploaddlt != (ncmploadtmp[0] - ncmploadtmp[1])) { errorPrint ("vmeshSeparateFmCheck: invalid separator balance"); return (1); } for (helmnum = 0; helmnum <= hashmsk; helmnum ++) { /* For all element slots */ Gnum velmnum; Gnum eelmnum; Gnum ncmpcut2; Gnum ncmpgain2; Gnum ncmpgaindlt; Gnum ncmpsize[3]; int velmpart; velmnum = helmtab[helmnum].velmnum; if (velmnum == ~0) /* If unallocated slot */ continue; /* Skip to next slot */ ncmpcut2 = ncmpgain2 = ncmpgaindlt = 0; ncmpsize[0] = ncmpsize[1] = ncmpsize[2] = 0; velmpart = helmtab[helmnum].vertpart; for (eelmnum = meshptr->m.verttax[velmnum]; /* For all node neighbors */ eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { Gnum vnodnum; Gnum hnodnum; int vnodpart; Gnum vnloval; vnodnum = meshptr->m.edgetax[eelmnum]; vnloval = (meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum]; for (hnodnum = (vnodnum * VMESHSEPAFMHASHPRIME) & hashmsk; ; hnodnum = (hnodnum + 1) & hashmsk) { if (hnodtab[hnodnum].vnodnum == vnodnum) { /* If element found */ vnodpart = hnodtab[hnodnum].vertpart; if (vnodpart != 2) { if (vnodpart != velmpart) { errorPrint ("vmeshSeparateFmCheck: invalid separator node (1)"); return (1); } if ((meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum] - 1) == 0) ncmpgaindlt += (2 * vnodpart - 1) * 2 * vnloval; else { ncmpgain2 += vnloval; ncmpgaindlt += (2 * vnodpart - 1) * vnloval; } } else if (((hnodtab[hnodnum].ecmpsize0 == 1) && (velmpart == 0)) || ((hnodtab[hnodnum].ecmpsize0 == (meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum] - 1)) && (velmpart == 1))) { ncmpgain2 -= vnloval; ncmpgaindlt += (2 * velmpart - 1) * vnloval; } break; } if (hnodtab[hnodnum].vnodnum == ~0) { /* If element not present */ vnodpart = meshptr->parttax[vnodnum]; if (vnodpart != velmpart) { errorPrint ("vmeshSeparateFmCheck: invalid separator node (2)"); return (1); } if ((meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]) == 1) { if (vnodpart == 2) { errorPrint ("vmeshSeparateFmCheck: invalid separator node (3)"); return (1); } ncmpgaindlt += (2 * vnodpart - 1) * 2 * vnloval; } else { ncmpgain2 += vnloval; ncmpgaindlt += (2 * vnodpart - 1) * vnloval; } break; } } ncmpsize[vnodpart] ++; } if ((ncmpsize[0] != 0) && (ncmpsize[1] != 0)) { errorPrint ("vmeshSeparateFmCheck: invalid element nodes"); return (1); } if (ncmpsize[2] != helmtab[helmnum].ncmpcut2) { errorPrint ("vmeshSeparateFmCheck: invalid element separator count"); return (1); } if ((ncmpgain2 != helmtab[helmnum].ncmpgain2) || (ncmpgaindlt != helmtab[helmnum].ncmpgaindlt)) { errorPrint ("vmeshSeparateFmCheck: invalid element gains"); return (1); } } memFree (parttax + meshptr->m.baseval); return (0); } #endif /* SCOTCH_DEBUG_VMESH3 */ scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_hd.c0000644000175300017530000001545011631334325022256 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_hd.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders a submesh using **/ /** the block-oriented Halo Approximate **/ /** (Multiple) Minimum Degree algorithm, **/ /** with super-variable accounting **/ /** R2HAMDf4 v2.0). **/ /** **/ /** DATES : # Version 4.0 : from : 10 dec 2003 **/ /** to : 24 jan 2004 **/ /** # Version 5.0 : from : 12 sep 2007 **/ /** to : 12 sep 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH_ORDER_HD #include "module.h" #include "common.h" #include "graph.h" #include "order.h" #include "mesh.h" #include "hmesh.h" #include "hall_order_hd.h" #include "hall_order_hx.h" #include "hmesh_order_hd.h" #include "hmesh_order_hx.h" #include "hmesh_order_si.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hmeshOrderHd ( const Hmesh * restrict const meshptr, Order * restrict const ordeptr, const Gnum ordenum, OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ const HmeshOrderHdParam * restrict const paraptr) { Gnum * restrict petab; Gnum pfree; Gnum iwlen; Gnum * restrict iwtab; Gnum * restrict lentab; Gnum * restrict nvartab; Gnum * restrict elentab; Gnum * restrict lasttab; Gnum * restrict leaftab; Gnum * restrict secntab; /* Array of index to first secondary variable */ Gnum * restrict nexttab; /* Array of index of next principal variable */ Gnum * restrict frsttab; Gnum ncmpa; Gnum n; /* Number of nodes to order */ int o; n = meshptr->m.velmnbr + meshptr->m.vnodnbr; if (n < paraptr->colmin) /* If graph is too small, order simply */ return (hmeshOrderSi (meshptr, ordeptr, ordenum, cblkptr)); iwlen = (Gnum) ((double) meshptr->m.edgenbr * HMESHORDERHDCOMPRAT) + 32; if (iwlen < n) /* Prepare to re-use array */ iwlen = n; if (memAllocGroup ((void **) (void *) &petab, (size_t) (n * sizeof (Gnum)), &iwtab, (size_t) (iwlen * sizeof (Gnum)), &lentab, (size_t) (n * sizeof (Gnum)), &nvartab, (size_t) (n * sizeof (Gnum)), &elentab, (size_t) (n * sizeof (Gnum)), &lasttab, (size_t) (n * sizeof (Gnum)), &leaftab, (size_t) (n * sizeof (Gnum)), &frsttab, (size_t) (n * sizeof (Gnum)), &secntab, (size_t) (n * sizeof (Gnum)), &nexttab, (size_t) (n * sizeof (Gnum)), NULL) == NULL) { errorPrint ("hmeshOrderHd: out of memory"); return (1); } hmeshOrderHxFill (meshptr, petab, lentab, iwtab, elentab, &pfree); hallOrderHdHalmd (n, meshptr->m.velmnbr, iwlen, petab, pfree, lentab, iwtab, nvartab, elentab, lasttab, &ncmpa, leaftab, secntab, nexttab, frsttab); if (ncmpa < 0) { errorPrint ("hmeshOrderHd: internal error"); memFree (petab); /* Free group leader */ return (1); } o = hallOrderHxBuild (meshptr->m.baseval, n, meshptr->vnohnbr, (meshptr->m.vnumtax == NULL) ? NULL : meshptr->m.vnumtax + (meshptr->m.vnodbas - meshptr->m.baseval), /* Point to node part of vnumtab array */ ordeptr, cblkptr, nvartab - meshptr->m.baseval, lentab - meshptr->m.baseval, petab - meshptr->m.baseval, frsttab - meshptr->m.baseval, nexttab - meshptr->m.baseval, secntab - meshptr->m.baseval, iwtab - meshptr->m.baseval, elentab - meshptr->m.baseval, ordeptr->peritab + ordenum, /* Use given inverse permutation as inverse permutation space, never based */ leaftab, paraptr->colmin, paraptr->colmax, (float) paraptr->fillrat); memFree (petab); /* Free group leader */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/bdgraph_store.c0000644000175300017530000001664511631334325022136 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_store.c **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the save data **/ /** structure handling routines for dis- **/ /** tributed bipartition graphs. **/ /** **/ /** DATES : # Version 5.1 : from : 10 sep 2007 **/ /** to 22 oct 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BDGRAPH_STORE #include "module.h" #include "common.h" #include "arch.h" #include "dgraph.h" #include "bdgraph.h" /**********************************/ /* */ /* Store graph handling routines. */ /* */ /**********************************/ /* This routine builds a save structure ** for the given active graph. ** It returns: ** - 0 : if allocation succeeded. ** - !0 : on error. */ int bdgraphStoreInit ( const Bdgraph * restrict const grafptr, BdgraphStore * restrict const storptr) { Gnum savsize; savsize = grafptr->s.vertlocnbr * (sizeof (GraphPart) + sizeof (Gnum)); /* Compute size for frontier and part arrays */ if ((storptr->datatab = (byte *) memAlloc (savsize)) == NULL) { /* Allocate save structure */ errorPrint ("bdgraphStoreInit: out of memory"); return (1); } return (0); } /* This routine frees a save structure. ** It returns: ** - VOID : in all cases. */ void bdgraphStoreExit ( BdgraphStore * const storptr) { memFree (storptr->datatab); #ifdef SCOTCH_DEBUG_BDGRAPH2 storptr->datatab = NULL; #endif /* SCOTCH_DEBUG_BDGRAPH2 */ } /* This routine saves partition data from the ** given active graph to the given save structure. ** It returns: ** - VOID : in all cases. */ void bdgraphStoreSave ( const Bdgraph * const grafptr, BdgraphStore * const storptr) { byte * partloctab; /* Pointer to part data save area */ byte * fronloctab; /* Pointer to frontier data save area */ storptr->fronlocnbr = grafptr->fronlocnbr; /* Save partition parameters */ storptr->fronglbnbr = grafptr->fronglbnbr; storptr->complocload0 = grafptr->complocload0; storptr->compglbload0 = grafptr->compglbload0; storptr->compglbload0dlt = grafptr->compglbload0dlt; storptr->complocsize0 = grafptr->complocsize0; storptr->compglbsize0 = grafptr->compglbsize0; storptr->commglbload = grafptr->commglbload; storptr->commglbgainextn = grafptr->commglbgainextn; fronloctab = storptr->datatab; /* Compute data offsets within save structure */ partloctab = fronloctab + grafptr->fronlocnbr * sizeof (Gnum); if (grafptr->fronloctab != NULL) /* If frontier array allocated */ memCpy (fronloctab, grafptr->fronloctab, grafptr->fronlocnbr * sizeof (Gnum)); #ifdef SCOTCH_DEBUG_BDGRAPH2 else if (grafptr->fronglbnbr != 0) errorPrint ("bdgraphStoreSave: inconsistent graph data (1)"); #endif /* SCOTCH_DEBUG_BDGRAPH2 */ if (grafptr->partgsttax != NULL) memCpy (partloctab, grafptr->partgsttax + grafptr->s.baseval, grafptr->s.vertlocnbr * sizeof (GraphPart)); else { #ifdef SCOTCH_DEBUG_BDGRAPH2 if (grafptr->compglbload0 != grafptr->s.veloglbsum) errorPrint ("bdgraphStoreSave: inconsistent graph data (2)"); #endif /* SCOTCH_DEBUG_BDGRAPH2 */ memSet (partloctab, 0, grafptr->s.vertlocnbr * sizeof (GraphPart)); /* In case part array is allocated before update */ } } /* This routine updates partition data of the ** given active graph, using the given save graph. ** It returns: ** - VOID : in all cases. */ void bdgraphStoreUpdt ( Bdgraph * const grafptr, const BdgraphStore * const storptr) { byte * fronloctab; /* Pointer to frontier data save area */ byte * partloctab; /* Pointer to part data save area */ grafptr->fronlocnbr = storptr->fronlocnbr; /* Save partition parameters */ grafptr->fronglbnbr = storptr->fronglbnbr; grafptr->complocload0 = storptr->complocload0; grafptr->compglbload0 = storptr->compglbload0; grafptr->compglbload0dlt = storptr->compglbload0dlt; grafptr->complocsize0 = storptr->complocsize0; grafptr->compglbsize0 = storptr->compglbsize0; grafptr->commglbload = storptr->commglbload; grafptr->commglbgainextn = storptr->commglbgainextn; fronloctab = storptr->datatab; /* Compute data offsets within save structure */ partloctab = fronloctab + grafptr->fronlocnbr * sizeof (Gnum); if (grafptr->fronloctab != NULL) memCpy (grafptr->fronloctab, fronloctab, grafptr->fronlocnbr * sizeof (Gnum)); #ifdef SCOTCH_DEBUG_BDGRAPH2 else if (grafptr->fronglbnbr != 0) errorPrint ("bdgraphStoreUpdt: inconsistent graph data (1)"); #endif /* SCOTCH_DEBUG_BDGRAPH2 */ if (grafptr->partgsttax != NULL) memCpy (grafptr->partgsttax + grafptr->s.baseval, partloctab, grafptr->s.vertlocnbr * sizeof (GraphPart)); #ifdef SCOTCH_DEBUG_BDGRAPH2 else if (grafptr->compglbload0 != grafptr->s.veloglbsum) errorPrint ("bdgraphStoreUpdt: inconsistent graph data (2)"); #endif /* SCOTCH_DEBUG_BDGRAPH2 */ #ifdef SCOTCH_DEBUG_BDGRAPH2 if (bdgraphCheck (grafptr) != 0) errorPrint ("bdgraphStoreUpdt: inconsistent graph data (3)"); #endif /* SCOTCH_DEBUG_BDGRAPH2 */ } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_gp.c0000644000175300017530000002546311631334325023152 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_gp.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module separates an active **/ /** graph using a vertex-oriented version **/ /** of the Gibbs-Poole-Stockmeyer **/ /** algorithm. **/ /** **/ /** DATES : # Version 4.0 : from : 15 may 2004 **/ /** to 17 may 2004 **/ /** # Version 5.0 : from : 12 sep 2007 **/ /** to 12 sep 2007 **/ /** # Version 5.1 : from : 09 nov 2008 **/ /** to 09 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VGRAPH_SEPARATE_GP #include "module.h" #include "common.h" #include "graph.h" #include "vgraph.h" #include "vgraph_separate_gp.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the bipartitioning. ** It returns: ** - 0 : if the bipartitioning could be computed. ** - !0 : on error. */ int vgraphSeparateGp ( Vgraph * restrict const grafptr, /*+ Separation graph +*/ const VgraphSeparateGpParam * const paraptr) /*+ Method parameters +*/ { VgraphSeparateGpQueue queudat; /* Vertex queue */ VgraphSeparateGpVertex * restrict vexxtax; /* Complementary vertex array */ const Gnum * restrict verttax; const Gnum * restrict vendtax; const Gnum * restrict velotax; const Gnum * restrict edgetax; Gnum rootnum; Gnum vertnum; Gnum fronnum; Gnum compsize1; Gnum compsize2; Gnum compload2; Gnum comploaddlt; if (grafptr->compload[0] != grafptr->s.velosum) /* If not all vertices already in part 0 */ vgraphZero (grafptr); /* Move all graph vertices to part 0 */ if (memAllocGroup ((void **) (void *) &queudat.queutab, (size_t) (grafptr->s.vertnbr * sizeof (Gnum)), &vexxtax, (size_t) (grafptr->s.vertnbr * sizeof (VgraphSeparateGpVertex)), NULL) == NULL) { errorPrint ("vgraphSeparateGp: out of memory"); return (1); } memSet (vexxtax, 0, grafptr->s.vertnbr * sizeof (VgraphSeparateGpVertex)); /* Initialize pass numbers */ vexxtax -= grafptr->s.baseval; verttax = grafptr->s.verttax; vendtax = grafptr->s.vendtax; velotax = grafptr->s.velotax; edgetax = grafptr->s.edgetax; compload2 = 0; /* All vertices to part 0 */ comploaddlt = grafptr->s.velosum; for (rootnum = grafptr->s.baseval; /* Loop on connected components */ (rootnum < grafptr->s.vertnnd) && (comploaddlt > 0); rootnum ++) { Gnum passnum; /* Pass number */ Gnum diamnum; /* Number of current diameter vertex */ Gnum diamval; /* Current diameter value */ Gnum diamdeg; /* Degree of current diameter vertex */ int diamflag; /* Flag set if improvement in diameter between passes */ Gnum veloval; while (vexxtax[rootnum].passnum != 0) /* Find first unallocated vertex */ rootnum ++; for (diamnum = rootnum, diamval = diamdeg = 0, diamflag = 1, passnum = 1; /* Start from root */ (passnum < paraptr->passnbr) && (diamflag -- != 0); passnum ++) { /* Loop if improvements */ vgraphSeparateGpQueueFlush (&queudat); /* Flush vertex queue */ vgraphSeparateGpQueuePut (&queudat, diamnum); /* Start from diameter vertex */ vexxtax[diamnum].passnum = passnum; /* It has been enqueued */ vexxtax[diamnum].distval = 0; do { /* Loop on vertices in queue */ Gnum vertnum; Gnum distval; Gnum edgenum; vertnum = vgraphSeparateGpQueueGet (&queudat); /* Get vertex from queue */ distval = vexxtax[vertnum].distval; /* Get vertex distance */ if ((distval > diamval) || /* If vertex increases diameter */ ((distval == diamval) && /* Or is at diameter distance */ ((vendtax[vertnum] - verttax[vertnum]) < diamdeg))) { /* With smaller degree */ diamnum = vertnum; /* Set it as new diameter vertex */ diamval = distval; diamdeg = vendtax[vertnum] - verttax[vertnum]; diamflag = 1; } distval ++; /* Set neighbor distance */ for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { Gnum vertend; /* End vertex number */ vertend = edgetax[edgenum]; if (vexxtax[vertend].passnum < passnum) { /* If vertex not yet queued */ vgraphSeparateGpQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ vexxtax[vertend].passnum = passnum; vexxtax[vertend].distval = distval; } } } while (! vgraphSeparateGpQueueEmpty (&queudat)); /* As long as queue is not empty */ } vgraphSeparateGpQueueFlush (&queudat); /* Flush vertex queue */ vgraphSeparateGpQueuePut (&queudat, diamnum); /* Start from diameter vertex */ vexxtax[diamnum].passnum = passnum; /* It has been enqueued */ vexxtax[diamnum].distval = 0; veloval = (velotax != NULL) ? velotax[diamnum] : 1; grafptr->parttax[diamnum] = 2; /* Move diameter vertex to separator */ comploaddlt -= veloval; compload2 += veloval; do { /* Loop on vertices in queue */ Gnum vertnum; Gnum veloval; Gnum distval; Gnum edgenum; vertnum = vgraphSeparateGpQueueGet (&queudat); /* Get vertex from queue */ veloval = (velotax != NULL) ? velotax[vertnum] : 1; distval = vexxtax[vertnum].distval + 1; grafptr->parttax[vertnum] = 1; /* Move selected vertex from separator to part 1 */ comploaddlt -= veloval; compload2 -= veloval; for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { Gnum vertend; /* End vertex number */ Gnum veloval; vertend = edgetax[edgenum]; veloval = (velotax != NULL) ? velotax[vertend] : 1; if (vexxtax[vertend].passnum < passnum) { /* If vertex not yet queued */ vgraphSeparateGpQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ vexxtax[vertend].passnum = passnum; vexxtax[vertend].distval = distval; grafptr->parttax[vertend] = 2; /* Move neighbor vertex to separator */ comploaddlt -= veloval; compload2 += veloval; } } } while ((comploaddlt > 0) && (! vgraphSeparateGpQueueEmpty (&queudat))); /* As long as balance not achieved and queue is not empty */ } grafptr->compload[0] = (grafptr->s.velosum + comploaddlt - compload2) / 2; grafptr->compload[1] = grafptr->s.velosum - compload2 - grafptr->compload[0]; grafptr->compload[2] = compload2; grafptr->comploaddlt = comploaddlt; memFree (queudat.queutab); /* Free group leader */ compsize1 = compsize2 = 0; for (vertnum = grafptr->s.baseval, fronnum = 0; vertnum < grafptr->s.vertnnd; vertnum ++) { Gnum partval; partval = (Gnum) grafptr->parttax[vertnum]; compsize1 += (partval & 1); /* Superscalar update */ compsize2 += (partval >> 1); if (partval == 2) /* If vertex belongs to frontier */ grafptr->frontab[fronnum ++] = vertnum; /* Record it in frontier array */ } grafptr->compsize[0] = grafptr->s.vertnbr - compsize1 - compsize2; grafptr->compsize[1] = compsize1; grafptr->fronnbr = compsize2; #ifdef SCOTCH_DEBUG_VGRAPH2 if (vgraphCheck (grafptr) != 0) { errorPrint ("vgraphSeparateGp: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_build.c0000644000175300017530000001370711631334325023457 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_build.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted source graph handling routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 23 feb 2007 **/ /** to 18 jul 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "dgraph.h" #include "scotch.h" /****************************************/ /* */ /* These routines are the C API for the */ /* distributed graph handling routines. */ /* */ /****************************************/ /*+ This routine fills the contents of the given *** opaque distributed graph structure with the *** data provided by the user. The base value *** allows the user to set the graph base to 0 or 1. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphBuild ( SCOTCH_Dgraph * const grafptr, /* Distributed graph structure to fill */ const Gnum baseval, /* Base for indexing */ const Gnum vertlocnbr, /* Number of local vertices */ const Gnum vertlocmax, /* Maximum number of local vertices */ Gnum * const vertloctab, /* Local vertex begin array */ Gnum * const vendloctab, /* Local vertex end array */ Gnum * const veloloctab, /* Local vertex load array (if any) */ Gnum * const vlblloctab, /* Local vertex label array (if any) */ const Gnum edgelocnbr, /* Number of local edges */ const Gnum edgelocsiz, /* Size of local edge array */ Gnum * const edgeloctab, /* Local edge array */ Gnum * const edgegsttab, /* Ghost edge array (if any); not const */ Gnum * const edloloctab) /* Local edge load array (if any) */ { Dgraph * srcgrafptr; /* Pointer to source graph structure */ Gnum * vertloctax; Gnum * vendloctax; Gnum * veloloctax; Gnum * vlblloctax; Gnum * edgeloctax; Gnum * edgegsttax; Gnum * edloloctax; #ifdef SCOTCH_DEBUG_LIBRARY1 if (sizeof (SCOTCH_Dgraph) < sizeof (Dgraph)) { errorPrint ("SCOTCH_dgraphBuild: internal error"); return (1); } #endif /* SCOTCH_DEBUG_LIBRARY1 */ if ((baseval < 0) || (baseval > 1)) { errorPrint ("SCOTCH_dgraphBuild: invalid base parameter"); return (1); } srcgrafptr = (Dgraph *) grafptr; /* Use structure as source graph */ vertloctax = (Gnum *) vertloctab - baseval; vendloctax = ((vendloctab == NULL) || (vendloctab == vertloctab + 1)) ? vertloctax + 1 : (Gnum *) vendloctab - baseval; veloloctax = ((veloloctab == NULL) || (veloloctab == vertloctab)) ? NULL : (Gnum *) veloloctab - baseval; vlblloctax = ((vlblloctab == NULL) || (vlblloctab == vertloctab)) ? NULL : (Gnum *) vlblloctab - baseval; edgeloctax = (Gnum *) edgeloctab - baseval; edgegsttax = ((edgegsttab == NULL) || (edgegsttab == edgeloctab)) ? NULL : (Gnum *) edgegsttab - baseval; edloloctax = ((edloloctab == NULL) || (edloloctab == edgeloctab)) ? NULL : (Gnum *) edloloctab - baseval; return (dgraphBuild (srcgrafptr, baseval, vertlocnbr, vertlocmax, vertloctax, vendloctax, veloloctax, NULL, vlblloctax, edgelocnbr, edgelocsiz, edgeloctax, edgegsttax, edloloctax)); } scotch-5.1.12b.dfsg/src/libscotch/library_arch.c0000644000175300017530000003126711631334325021751 0ustar hazelscthazelsct/* Copyright 2004,2007,2009-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_arch.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the target **/ /** architecture handling routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 3.2 : from : 18 aug 1998 **/ /** to : 18 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 29 mar 1999 **/ /** # Version 3.4 : from : 01 nov 2001 **/ /** to : 01 nov 2001 **/ /** # Version 4.0 : from : 13 jan 2004 **/ /** to : 13 jan 2004 **/ /** # Version 5.0 : from : 12 sep 2007 **/ /** to : 12 sep 2007 **/ /** # Version 5.1 : from : 05 jun 2009 **/ /** to : 13 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "graph.h" #include "arch.h" #include "arch_cmplt.h" #include "arch_cmpltw.h" #include "arch_hcub.h" #include "arch_mesh.h" #include "arch_tleaf.h" #include "arch_torus.h" #include "arch_vcmplt.h" #include "arch_vhcub.h" #include "scotch.h" /***************************************/ /* */ /* These routines are the C API for */ /* the architecture handling routines. */ /* */ /***************************************/ /*+ This routine reserves a memory area *** of a size sufficient to store a *** target architecture. *** It returns: *** - !NULL : if the initialization succeeded. *** - NULL : on error. +*/ SCOTCH_Arch * SCOTCH_archAlloc () { return ((SCOTCH_Arch *) memAlloc (sizeof (SCOTCH_Arch))); } /*+ This routine initializes the opaque *** architecture structure used to handle *** target architectures in the Scotch library. *** It returns: *** - 0 : if the initialization succeeded. *** - !0 : on error. +*/ int SCOTCH_archInit ( SCOTCH_Arch * const archptr) { if (sizeof (SCOTCH_Num) != sizeof (Anum)) { errorPrint ("SCOTCH_archInit: internal error (1)"); return (1); } if (sizeof (SCOTCH_Arch) < sizeof (Arch)) { errorPrint ("SCOTCH_archInit: internal error (2)"); return (1); } return (archInit ((Arch *) archptr)); } /*+ This routine frees the contents of the *** given opaque architecture structure. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_archExit ( SCOTCH_Arch * const archptr) { archExit ((Arch *) archptr); } /*+ This routine loads the given opaque *** architecture structure with the data of *** the given stream. *** It returns: *** - 0 : if the loading succeeded. *** - !0 : on error. +*/ int SCOTCH_archLoad ( SCOTCH_Arch * const archptr, FILE * const stream) { return (archLoad ((Arch *) archptr, stream)); } /*+ This routine saves the given opaque *** architecture structure to the given *** stream. *** It returns: *** - 0 : if the saving succeeded. *** - !0 : on error. +*/ int SCOTCH_archSave ( const SCOTCH_Arch * const archptr, FILE * const stream) { return (archSave ((Arch *) archptr, stream)); } /*+ This routine returns the name of the *** given target architecture. *** It returns: *** - !NULL : pointer to the name of the *** target architecture. +*/ char * SCOTCH_archName ( const SCOTCH_Arch * const archptr) { return (archName ((const Arch * const) archptr)); } /*+ This routine returns the size of the *** given target architecture. *** It returns: *** - !0 : size of the target architecture. +*/ SCOTCH_Num SCOTCH_archSize ( const SCOTCH_Arch * const archptr) { ArchDom domdat; archDomFrst ((Arch *) archptr, &domdat); /* Get first domain */ return (archDomSize ((Arch *) archptr, &domdat)); /* Return domain size */ } /*+ This routine tells if the given architecture *** is a variable-sized architecture or not. *** It returns: *** - 0 : if the architecture is not variable-sized. *** - 1 : if the architecture is variable-sized. +*/ int SCOTCH_archVar ( const SCOTCH_Arch * const archptr) { return ((archVar ((Arch *) archptr) != 0) ? 1 : 0); } /*+ These routines fill the contents of the given *** opaque target structure so as to yield target *** architectures of the given types. *** It returns: *** - 0 : if the computation succeeded. *** - !0 : on error. +*/ int SCOTCH_archCmplt ( SCOTCH_Arch * const archptr, const SCOTCH_Num numnbr) { Arch * tgtarchptr; ArchCmplt * tgtarchdatptr; if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { errorPrint ("SCOTCH_archCmplt: internal error"); return (1); } tgtarchptr = (Arch *) archptr; tgtarchdatptr = (ArchCmplt *) (void *) (&tgtarchptr->data); tgtarchptr->class = archClass ("cmplt"); tgtarchdatptr->numnbr = (Anum) numnbr; return (0); } /* ** */ int SCOTCH_archCmpltw ( SCOTCH_Arch * const archptr, const SCOTCH_Num vertnbr, const SCOTCH_Num * const velotab) { Arch * tgtarchptr; if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { errorPrint ("SCOTCH_archCmpltw: internal error"); return (1); } tgtarchptr = (Arch *) archptr; tgtarchptr->class = archClass ("cmpltw"); return (archCmpltwArchBuild ((ArchCmpltw *) (void *) (&tgtarchptr->data), vertnbr, velotab)); } /* ** */ int SCOTCH_archHcub ( SCOTCH_Arch * const archptr, const SCOTCH_Num dimmax) /*+ Number of dimensions +*/ { Arch * tgtarchptr; ArchHcub * tgtarchdatptr; if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { errorPrint ("SCOTCH_archHcub: internal error"); return (1); } tgtarchptr = (Arch *) archptr; tgtarchdatptr = (ArchHcub *) (void *) (&tgtarchptr->data); tgtarchptr->class = archClass ("hcub"); tgtarchdatptr->dimmax = (Anum) dimmax; return (0); } /* ** */ int SCOTCH_archMesh2 ( SCOTCH_Arch * const archptr, const SCOTCH_Num dimxval, const SCOTCH_Num dimyval) { Arch * tgtarchptr; ArchMesh2 * tgtarchdatptr; if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { errorPrint ("SCOTCH_archMesh2: internal error"); return (1); } tgtarchptr = (Arch *) archptr; tgtarchdatptr = (ArchMesh2 *) (void *) (&tgtarchptr->data); tgtarchptr->class = archClass ("mesh2D"); tgtarchdatptr->c[0] = (Anum) dimxval; tgtarchdatptr->c[1] = (Anum) dimyval; return (0); } /* ** */ int SCOTCH_archMesh3 ( SCOTCH_Arch * const archptr, const SCOTCH_Num dimxval, const SCOTCH_Num dimyval, const SCOTCH_Num dimzval) { Arch * tgtarchptr; ArchMesh3 * tgtarchdatptr; if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { errorPrint ("SCOTCH_archMesh3: internal error"); return (1); } tgtarchptr = (Arch *) archptr; tgtarchdatptr = (ArchMesh3 *) (void *) (&tgtarchptr->data); tgtarchptr->class = archClass ("mesh3D"); tgtarchdatptr->c[0] = (Anum) dimxval; tgtarchdatptr->c[1] = (Anum) dimyval; tgtarchdatptr->c[2] = (Anum) dimzval; return (0); } /* ** */ int SCOTCH_archTleaf ( SCOTCH_Arch * const archptr, const SCOTCH_Num levlnbr, /*+ Number of levels in architecture +*/ const SCOTCH_Num * const sizetab, /*+ Size array, by increasing level number +*/ const SCOTCH_Num * const linktab) /*+ Link cost array, by increasing level number +*/ { Anum levlnum; Anum sizeval; Arch * tgtarchptr; ArchTleaf * tgtarchdatptr; if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { errorPrint ("SCOTCH_archTleaf: internal error"); return (1); } tgtarchptr = (Arch *) archptr; tgtarchdatptr = (ArchTleaf *) (void *) (&tgtarchptr->data); tgtarchptr->class = archClass ("tleaf"); if ((tgtarchdatptr->sizetab = memAlloc ((levlnbr * 2 + 1) * sizeof (Anum))) == NULL) { /* TRICK: One more slot for linktab[-1] */ errorPrint ("SCOTCH_archTleaf: out of memory"); return (1); } tgtarchdatptr->levlnbr = (Anum) levlnbr; tgtarchdatptr->linktab = tgtarchdatptr->sizetab + tgtarchdatptr->levlnbr + 1; tgtarchdatptr->linktab[-1] = 0; /* TRICK: Dummy slot for for level-0 communication */ for (levlnum = 0, sizeval = 1; levlnum < tgtarchdatptr->levlnbr; levlnum ++) { tgtarchdatptr->sizetab[levlnum] = sizetab[levlnum]; tgtarchdatptr->linktab[levlnum] = linktab[levlnum]; sizeval *= tgtarchdatptr->sizetab[levlnum]; } tgtarchdatptr->sizeval = sizeval; return (0); } /* ** */ int SCOTCH_archTorus2 ( SCOTCH_Arch * const archptr, const SCOTCH_Num dimxval, const SCOTCH_Num dimyval) { Arch * tgtarchptr; ArchTorus2 * tgtarchdatptr; if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { errorPrint ("SCOTCH_archTorus2: internal error"); return (1); } tgtarchptr = (Arch *) archptr; tgtarchdatptr = (ArchTorus2 *) (void *) (&tgtarchptr->data); tgtarchptr->class = archClass ("torus2D"); tgtarchdatptr->c[0] = (Anum) dimxval; tgtarchdatptr->c[1] = (Anum) dimyval; return (0); } /* ** */ int SCOTCH_archTorus3 ( SCOTCH_Arch * const archptr, const SCOTCH_Num dimxval, const SCOTCH_Num dimyval, const SCOTCH_Num dimzval) { Arch * tgtarchptr; ArchTorus3 * tgtarchdatptr; if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { errorPrint ("SCOTCH_archTorus3: internal error"); return (1); } tgtarchptr = (Arch *) archptr; tgtarchdatptr = (ArchTorus3 *) (void *) (&tgtarchptr->data); tgtarchptr->class = archClass ("torus3D"); tgtarchdatptr->c[0] = (Anum) dimxval; tgtarchdatptr->c[1] = (Anum) dimyval; tgtarchdatptr->c[2] = (Anum) dimzval; return (0); } /* ** */ int SCOTCH_archVcmplt ( SCOTCH_Arch * const archptr) { Arch * tgtarchptr; if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { errorPrint ("SCOTCH_archVcmplt: internal error"); return (1); } tgtarchptr = (Arch *) archptr; tgtarchptr->class = archClass ("varcmplt"); return (0); } /* ** */ int SCOTCH_archVhcub ( SCOTCH_Arch * const archptr) { Arch * tgtarchptr; if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { errorPrint ("SCOTCH_archVhcub: internal error"); return (1); } tgtarchptr = (Arch *) archptr; tgtarchptr->class = archClass ("vhcub"); return (0); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_induce.h0000644000175300017530000000317011631334325021740 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ #undef static scotch-5.1.12b.dfsg/src/libscotch/hmesh.h0000644000175300017530000001317511631334325020417 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data **/ /** declarations for the halo mesh **/ /** structure. **/ /** **/ /** DATES : # Version 4.0 : from : 31 dec 2001 **/ /** to 29 apr 2004 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ Halo mesh structure. Only node vertices can be halo vertices, not element vertices. Halo node vertices are numbered with the highest available node numbers. Since un-haloing of a mesh should be costless, and since the vertex array must be continuous, when a halo mesh indeed bears halo nodes, it is preferrable that elements be numbered first, then non-halo node vertices, then halo vertices, so that the removal of the halo does not create holes in the vertex array. Else, the indices of the halo nodes must be reassigned to empty elements, which results in a larger structure until it is coarsened or induced. If no halo is present, the order of nodes and elements is not relevant. As for the halo graph structure, in the adjacency list of elements, halo node neighbors must all be put after non-halo node neighbors, so that the edge sub-array comprised between verttab[i] and vnhdtab[i] refer only to non-halo node neighbors, such that edgetab can be re-used by the un-halo-ed mesh. Since Hmesh halo meshes are used only for node ordering, the velotab and vnumtab arrays that are created by hmesh*() routines can be restricted to their node part. It must be guaranteed that this does not create problems at freeing time, for instance by grouping these arrays with verttab. +*/ typedef struct Hmesh_ { Mesh m; /*+ Source mesh +*/ Gnum * restrict vehdtax; /*+ End vertex array for elements [based] (non-halo nodes look at m.vendtax) +*/ Gnum veihnbr; /*+ Number of halo isolated element vertices, which have halo nodes only +*/ Gnum vnohnbr; /*+ Number of non-halo node vertices +*/ Gnum vnohnnd; /*+ Based number of first halo node vertex in mesh graph (m.vnodnnd if none) +*/ Gnum vnhlsum; /*+ Sum of non-halo node vertex weights +*/ Gnum enohnbr; /*+ Number of non-halo edges +*/ Gnum levlnum; /*+ Nested dissection level +*/ } Hmesh; /* ** The function prototypes. */ #ifndef HMESH #define static #endif void hmeshExit (Hmesh * const); Gnum hmeshBase (Hmesh * const, const Gnum); #ifdef HGRAPH_H int hmeshHgraph (const Hmesh * restrict const, Hgraph * restrict const); #endif /* HGRAPH_H */ int hmeshInducePart (const Hmesh * const, const GraphPart * const, const GraphPart, const Gnum, const Gnum, const Gnum, Hmesh * const); int hmeshMesh (const Hmesh * restrict const, Mesh * restrict const); int hmeshCheck (const Hmesh *); #undef static scotch-5.1.12b.dfsg/src/libscotch/kdgraph.c0000644000175300017530000001303411631334325020720 0ustar hazelscthazelsct/* Copyright 2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kdgraph.c **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a parallel bipartitioning **/ /** mapper. **/ /** This module handles the k-way active **/ /** distributed graph and save data struct- **/ /** ure handling routines. **/ /** **/ /** DATES : # Version 5.1 : from : 31 mar 2008 **/ /** to 01 jul 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define KDGRAPH #include "module.h" #include "common.h" #include "arch.h" #include "dgraph.h" #include "dmapping.h" #include "kdgraph.h" /************************************/ /* */ /* Active dgraph handling routines. */ /* */ /************************************/ /* This routine builds the active dgraph ** corresponding to the given k-way ** partition parameters. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int kdgraphInit ( Kdgraph * restrict const actgrafptr, /* Active graph */ const Dgraph * restrict const srcgrafptr, /* Source graph */ Dmapping * restrict const dmapptr) /* Mapping */ { /* const Arch * restrict archptr; /\* Pointer to mapping architecture *\/ */ /* ArchDom domfrst; /\* First, largest domain *\/ */ /* Gnum domfrstload; /\* Load of first domain *\/ */ /* Anum termnum; */ actgrafptr->s = *srcgrafptr; /* Clone source graph */ actgrafptr->s.flagval &= ~DGRAPHFREEALL; actgrafptr->levlnum = 0; actgrafptr->m.mappptr = dmapptr; archDomFrst (&dmapptr->archdat, &actgrafptr->m.domnorg); /* if ((actgrafptr->comploadavg = (Gnum *) memAlloc (actgrafptr->m.domnnbr * sizeof (Gnum) * 2)) == NULL) { */ /* errorPrint ("kdgraphInit: out of memory"); */ /* return (1); */ /* } */ /* actgrafptr->comploaddlt = actgrafptr->comploadavg + actgrafptr->m.domnnbr; */ /* archptr = &dmapptr->archdat; */ /* archDomFrst (archptr, &domfrst); /\* Get first, largest domain *\/ */ /* domfrstload = archDomWght (archptr, &domfrst); /\* Get its load *\/ */ /* actgrafptr->comploadavg[0] = (archDomWght (archptr, &actgrafptr->m.domntab[0]) * actgrafptr->s.velolocsum) / domfrstload; */ /* actgrafptr->comploaddlt[0] = actgrafptr->s.velolocsum - actgrafptr->comploadavg[0]; */ /* for (termnum = 1; termnum < actgrafptr->m.domnnbr; termnum ++) { */ /* actgrafptr->comploadavg[termnum] = (archDomWght (archptr, &actgrafptr->m.domntab[termnum]) * actgrafptr->s.velolocsum) / domfrstload; */ /* actgrafptr->comploaddlt[termnum] = - actgrafptr->comploadavg[termnum]; */ /* } */ /* actgrafptr->fronlocnbr = 0; /\* No frontier yet *\/ */ /* actgrafptr->fronloctab = NULL; */ /* actgrafptr->commload = 0; */ /* actgrafptr->levlnum = 0; */ /* actgrafptr->leafnum = 0; */ return (0); } /* This routine frees the contents ** of the given active graph ** It returns: ** - VOID : in all cases. */ void kdgraphExit ( Kdgraph * restrict const actgrafptr) /* Active graph */ { dgraphExit (&actgrafptr->s); #ifdef SCOTCH_DEBUG_KDGRAPH1 memSet (actgrafptr, 0, sizeof (Kdgraph)); #endif /* SCOTCH_DEBUG_KDGRAPH1 */ } scotch-5.1.12b.dfsg/src/libscotch/hall_order_hf.c0000644000175300017530000013003511631334325022071 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hall_order_hf.c **/ /** **/ /** AUTHOR : Patrick AMESTOY **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders a halo graph or mesh **/ /** structure using the block-oriented Halo **/ /** Approximate (Multiple) Minimum Fill **/ /** algorithm, with super-variable **/ /** accounting R2HAMDf4 (v2.0). **/ /** **/ /** DATES : # Version 3.4 : from : 15 may 2001 **/ /** to : 23 nov 2001 **/ /** # Version 4.0 : from : 10 jan 2003 **/ /** to : 29 aug 2007 **/ /** # Version 5.1 : from : 08 dec 2010 **/ /** to : 08 dec 2010 **/ /** **/ /** NOTES : # This module contains pieces of code **/ /** that belong to other people; see **/ /** below. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HALL_ORDER_HF #include "module.h" #include "common.h" #include "graph.h" #include "hall_order_hf.h" /* -- translated by f2c (version 19970219). */ /** -------------------------------------------------------------------- **/ /** December 8th 2003 **/ /** Unique version for both graph of variables and graphs of elements **/ /** Let us refer to as **/ /** Gv a graph with only variables **/ /** Ge a graph with both variables and elements **/ /** **/ /** Notations used: **/ /** **/ /** Let V be the set of nodes **/ /** V = Ve + V0 + V1 **/ /** V0 = Set of variable nodes (not in halo) **/ /** V1 = Set of variable nodes (in halo) **/ /** Ve = Set of element nodes **/ /** **/ /** All 3 sets are disjoint, Ve and V1 can be empty **/ /** **/ /** Modifications w.r.t. previous version : **/ /** **/ /** New Input: **/ /** --------- **/ /** nbelts : integer holding size of Ve **/ /** =0 if Gv (graph of variables) **/ /** >0 if Ge **/ /** **/ /** Extension of the meaning of input entry len for nodes in Ve **/ /** --------- **/ /** len(i) = | Adj(i) | if i \in V0 U Ve **/ /** ( Note that in the case of a GE graph **/ /** if v\in V0 then len(v) = nb of elements adjacent to v ) **/ /** len(i) = - | Adj(i) | if i \in V1 **/ /** or -N -1 if | Adj(i) | = 0 and i \in V1 **/ /** **/ /** Modified the meaning of input entry elen **/ /** --------- **/ /** if e \in Ve then elen (e) = -N-1 **/ /** if v \in V0 then elen (v) = External degree of v **/ /** Gv : elen (v) = len(v) **/ /** Ge : elen (v) **/ /** should be computed in SCOTCH **/ /** if v \in V1 then elen (v) = 0 **/ /** **/ /** **/ /** Output is unchanged **/ /** --------- **/ /** **/ /** **/ /** End remarks done on December 8th 2003 **/ /** ---------------------------------------------------------------------**/ /** **/ /** **/ /** AMF4 (version used on newton for uns tests) **/ /** given to Francois on Nov 31 2000 **/ /** Approximation of level4 of the minimum fill heuristic **/ /** (best approx of Min fill currently available based on collaborative **/ /** work between P. Amestoy, T. Davis and I. Duff) **/ /** **/ /** Remarks: **/ /** ------- **/ /** 1/ !!!!!!!! WARNING !!!!!!!!!! **/ /** TWO additionnal parameters w.r.t HALOAMD **/ /** -------------------------- **/ /** NBBUCK : integer greater than 1 (advised value is 2*N) **/ /** HEAD : HEAD(0:NBBUCK+1) integer array of size NBBUCK+2 **/ /** NOTE that it start at index 0 !! **/ /** **/ /** 2/ Interface for MA41 or SCOTCH **/ /** **/ /** 3/ Nodes of V1 are amalgamated in one root supervariable **/ /** the complete tree (of V0+V1) is correct in the sense of **/ /** MC47B output interface (NV for V1 nodes is ok). **/ /** Output data (PE,NV) can then be exploited by MA41LD. **/ /** Variable in V1 cannot be characterized on output. **/ /** -------------------------------------------------------------------- **/ void hallOrderHfR2hamdf4 ( Gnum n, /* Matrix order */ Gnum nbelts, /* Number of elements */ Gnum nbbuck, /* Number of buckets */ Gnum iwlen, /* Length of array iw */ Gnum * restrict pe /* [] */, /* Array of indexes in iw of start of row i */ Gnum pfree, /* Useful size in iw */ Gnum * restrict len /* [] */, /* Array of lengths of adjacency lists */ Gnum * restrict iw /* [] */, /* Adjacency list array */ Gnum * restrict nv /* [] */, /* Array of element degrees */ Gnum * restrict elen /* [] */, /* Array that holds the inverse permutation */ Gnum * restrict last /* [] */, /* Array that holds the permutation */ Gnum * restrict ncmpa, /* Number of times array iw was compressed */ Gnum * restrict degree /* [] */, /* Array that holds degree data */ Gnum * restrict wf /* [] */, /* Flag array */ Gnum * restrict next /* [] */, /* Linked list structure */ Gnum * restrict w /* [] */, /* Flag array */ Gnum * restrict head /* [] */) /* Linked list structure */ { Gnum hash, pend, hmod, lenj, dmax, wflg, dext, psrc, pdst, wnvi, e, i, j, k, p, degme, x, nelme, nreal, lastd, nleft, ilast, jlast, inext, jnext, n2, p1, nvpiv, p2, p3, me = 0, nbflag, ln, we, pj, pn, mindeg, elenme, slenme, maxmem, newmem, wf3, wf4, deg, eln, mem, nel, pme, pas, nvi, nvj, pme1, pme2, knt1, knt2, knt3; float rmf, rmf1; /** Min fill approximation one extra array of size NBBUCK+2 is needed **/ /** INTEGER HEAD(0:NBBUCK+1) **/ /** -------------------------------------------------------------------- **/ /** HALOAMD_V6: (January 1999, P. Amestoy) **/ /** *********** **/ /** 1/ ERROR 2 detection followed by stop statement suppressed. **/ /** 2/ Pb 1 identified in V5 was not correctly solved. **/ /** **/ /** HALOAMD_V5: (December 1998, P. Amestoy) **/ /** *********** **/ /** 1/ Solved problem with matrix psmigr 1, because upper bound degree **/ /** DEG>N was considered as a node of V1. **/ /** **/ /** HALOAMD_V4: (October 1998, P. Amestoy) **/ /** *********** **/ /** Only MA41 interface (ok for both scotch and MA41) is included in **/ /** this file. **/ /** **/ /** HALOAMD_V3: (August 1998, P. Amestoy) **/ /** ********** **/ /** Solved problem in version 2: variables of V1 with len(i)=0 were not **/ /** well processed. See modification of the input to characterize those **/ /** variables. **/ /** Problem detected by Jacko Koster while experimenting with C version **/ /** 2 of haloAMD in the context of multiple front method based on **/ /** MA27: "if for an interface variable i, row i in the matrix has only **/ /** a nonzero entry on the diagonal, we first remove this entry and **/ /** len(i) is set to zero on input to HALOAMD. However, this means that **/ /** HALOAMD will treat variable i as an interior variable (in V0) **/ /** instead as an interface variable (in V1). It is indeed a bit **/ /** strange to have such interface variables but we encountered some **/ /** in our debugging experiments with some random partitionings. **/ /** Solution: **/ /** IF on input i \in V1 and len(i)=0 (that is adjlist(i)={}) THEN **/ /** len(i) must be set on input to -N-1. **/ /** ENDIF **/ /** Therefore, all variables i / len(i) < 0 and only those are in V1. **/ /** Variables with len(i) = -N-1 are then processed differently at the **/ /** beginning of the code. **/ /** **/ /** HALOAMD_V2: (April 1998) **/ /** ********** **/ /** The end of the tree (including links to block of flagged indices **/ /** is built) . The list of flagged indices is considered as a dense **/ /** amalgamated node. **/ /** Tested on rosanna: ~amestoy/MA41_NEW/SUN_RISC_dbl/SOFT **/ /** **/ /** Comments on the OUTPUT: **/ /** ---------------------- **/ /** **/ /** Let V= V0 U V1 the nodes of the initial graph (|V|=n). **/ /** The assembly tree corresponds to the tree of the supernodes (or **/ /** supervariables). Each node of the assembly tree is then composed of **/ /** one principal variable and a list of secondary variables. The list **/ /** of variable of a node (principal + secondary variables) then **/ /** describes the structure of the diagonal bloc of the supernode. **/ /** The elimination tree denotes the tree of all the variables(=nodes) **/ /** and is therefore of order n. The arrays NV(N) and PE(N) give a **/ /** description of the assembly tree. **/ /** **/ /** 1/ Description of array nv(N) (on OUPUT) **/ /** nv(i)=0 i is a secondary variable. **/ /** N+1> nv(i) >0 i is a principal variable, nv(i) holds the number **/ /** of elements in column i of L (true degree of i) **/ /** nv(i) = N+1 then i is a flagged variable (belonging to V1) **/ /** **/ /** 2/ Description of array PE(N) (on OUPUT) **/ /** pe(i) = -(father of variable/node i) in the elimination tree. **/ /** If nv (i) .gt. 0, then i represents a node in the assembly tree, **/ /** and the parent of i is -pe (i), or zero if i is a root. **/ /** If nv (i) = 0, then (i,-pe (i)) represents an edge in a **/ /** subtree, the root of which is a node in the assembly tree. **/ /** **/ /** 3/ Example: **/ /** Let If be a root node father of Is in the assembly tree. **/ /** If is the principal variable of the node If and let If1, If2, If3 **/ /** be the secondary variables of node If. Is is the principal **/ /** variable of the node Is and let Is1, Is2 be the secondary **/ /** variables of node Is. **/ /** Then: **/ /** NV(If1)=NV(If2)=NV(If3) = 0 (secondary variables) **/ /** NV(Is1)=NV(Is2) = 0 (secondary variables) **/ /** NV(If) > 0 (principal variable) **/ /** NV(Is) > 0 (principal variable) **/ /** PE(If) = 0 (root node) **/ /** PE(Is) = -If (If is the father of Is in the assembly tree) **/ /** PE(If1)=PE(If2)=PE(If3)= -If (If is the principal variable) **/ /** PE(Is1)=PE(Is2)= -Is (Is is the principal variable) **/ /** **/ /** HALOAMD_V1: (September 1997) **/ /** ********** **/ /** Initial version designed to experiment the numerical (fill-in) **/ /** impact of taking into account the halo. This code should be able to **/ /** experiment no-halo, partial halo, complete halo. **/ /** -------------------------------------------------------------------- **/ /** HALOAMD is designed to process a graph composed of two types **/ /** of nodes, V0 and V1, extracted from a larger gragh. **/ /** V0^V1 = {}, **/ /** We used Min. degree heuristic to order only **/ /** nodes in V0, but the adjacency to nodes **/ /** in V1 is taken into account during ordering. **/ /** Nodes in V1 are odered at last. **/ /** Adjacency between nodes of V1 need not be provided, **/ /** however |len(i)| must always corresponds to the number of **/ /** edges effectively provided in the adjacency list of i. **/ /** On input : **/ /** ******** **/ /** Nodes INODE in V1 are flagged with len(INODE) = -degree **/ /** Update version HALO V3 (August 1998): **/ /** if len(i)=0 and i \in V1 then len(i) must be set **/ /** on input to -N-1. **/ /** ERROR return : **/ /** ************ **/ /** Negative value in ncmpa indicates an error detected **/ /** by HALOAMD. **/ /** **/ /** The graph provided MUST follow the rule: **/ /** if (i,j) is an edge in the gragh then **/ /** j must be in the adjacency list of i AND **/ /** i must be in the adjacency list of j. **/ /** **/ /** REMARKS : **/ /** ------- **/ /** 1/ Providing edges between nodes of V1 should not **/ /** affect the final ordering, only the amount of edges **/ /** of the halo should effectively affect the solution. **/ /** This code should work in the following cases: **/ /** 1/ halo not provided **/ /** 2/ halo partially provided **/ /** 3/ complete halo **/ /** 4/ complete halo+interconnection between nodes of V1. **/ /** **/ /** 1/ should run and provide identical results (w.r.t to **/ /** current implementation of AMD in SCOTCH). **/ /** 3/ and 4/ should provide identical results. **/ /** **/ /** 2/ All modifications of the MC47 initial code are indicated **/ /** with begin HALO .. end HALO **/ /** **/ /** Ordering of nodes in V0 is based on Approximate Minimum Degree **/ /** ordering algorithm, with aggressive absorption: **/ /** Given a representation of the nonzero pattern of a symmetric matrix, **/ /** A, (excluding the diagonal) perform an approximate minimum **/ /** (UMFPACK/MA38-style) degree ordering to compute a pivot order **/ /** such that fill-in in the Cholesky **/ /** factors A = LL^T is kept low. At each step, the pivot **/ /** selected is the one with the minimum UMFPACK/MA38-style **/ /** upper-bound on the external degree. Aggresive absorption is **/ /** used to tighten the bound on the degree. This can result an **/ /** significant improvement in the quality of the ordering for **/ /** some matrices. **/ /** The approximate degree algorithm implemented here is the **/ /** symmetric analogue of the degree update algorithm in MA38, by **/ /** Davis and Duff, also in the Harwell Subroutine Library. **/ /** **/ /** **** CAUTION: ARGUMENTS ARE NOT CHECKED FOR ERRORS ON INPUT. ***** **/ /** ** If you want error checking, a more versatile input format, and ** **/ /** ** a simpler user interface, then use MC47A/AD in the Harwell ** **/ /** ** Subroutine Library, which checks for errors, transforms the ** **/ /** ** input, and calls MC47B/BD. ** **/ /** ******************************************************************** **/ /** References: (UF Tech Reports are available via anonymous ftp **/ /** to ftp.cis.ufl.edu:cis/tech-reports). **/ /** [1] Timothy A. Davis and Iain Duff, "An unsymmetric-pattern **/ /** multifrontal method for sparse LU factorization", **/ /** SIAM J. Matrix Analysis and Applications, to appear. **/ /** also Univ. of Florida Technical Report TR-94-038. **/ /** Discuss UMFPACK / MA38. **/ /** [2] Patrick Amestoy, Timothy A. Davis, and Iain S. Duff, **/ /** "An approximate minimum degree ordering algorithm," **/ /** SIAM J. Matrix Analysis and Applications (to appear), **/ /** also Univ. of Florida Technical Report TR-94-039. **/ /** Discusses this routine. **/ /** [3] Alan George and Joseph Liu, "The evolution of the **/ /** minimum degree ordering algorithm," SIAM Review, vol. **/ /** 31, no. 1, pp. 1-19, March 1989. We list below the **/ /** features mentioned in that paper that this code **/ /** includes: **/ /** mass elimination: **/ /** Yes. MA27 relied on supervariable detection for mass **/ /** elimination. **/ /** indistinguishable nodes: **/ /** Yes (we call these "supervariables"). This was also **/ /** in the MA27 code - although we modified the method of **/ /** detecting them (the previous hash was the true degree, **/ /** which we no longer keep track of). A supervariable is **/ /** a set of rows with identical nonzero pattern. All **/ /** variables in a supervariable are eliminated together. **/ /** Each supervariable has as its numerical name that of **/ /** one of its variables (its principal variable). **/ /** quotient graph representation: **/ /** Yes. We use the term "element" for the cliques formed **/ /** during elimination. This was also in the MA27 code. **/ /** The algorithm can operate in place, but it will work **/ /** more efficiently if given some "elbow room." **/ /** element absorption: **/ /** Yes. This was also in the MA27 code. **/ /** external degree: **/ /** Yes. The MA27 code was based on the true degree. **/ /** incomplete degree update and multiple elimination: **/ /** No. This was not in MA27, either. Our method of **/ /** degree update within MC47B/BD is element-based, not **/ /** variable-based. It is thus not well-suited for use **/ /** with incomplete degree update or multiple elimination. **/ /** -------------------------------------------------------------------- **/ /** Authors, and Copyright (C) 1995 by: **/ /** Timothy A. Davis, Patrick Amestoy, Iain S. Duff, & **/ /** John K. Reid. **/ /** Modified (V1) by P.R. Amestoy ENSEEIHT (1997) **/ /** Modified (V2) by P.R. Amestoy ENSEEIHT (1998) **/ /** Modified (V3) by P.R. Amestoy ENSEEIHT (1998) **/ /** Modified (V4) by P.R. Amestoy ENSEEIHT (1998) **/ /** Modified (V5) by P.R. Amestoy ENSEEIHT (1998) **/ /** Modified (V6) by P.R. Amestoy ENSEEIHT (1999) **/ /** **/ /** Dates: September, 1995 **/ /** September, 1997 (halo AMD V1) **/ /** April, 1998 (halo AMD V2) **/ /** August, 1998 (halo AMD V3) **/ -- w; /* Parameter adjustments */ -- next; -- wf; -- degree; -- last; -- elen; -- nv; -- len; -- pe; -- iw; /* -- head; Array head not updated since starts from 0 */ n2 = - (nbbuck + 1); /* pas = n / 8; [Update F.P. 20020715 selon hamf_20020220] Distance betweeen elements of the N, ..., NBBUCK entries of HEAD */ pas = MAX ((n / 8), 1); /* Distance betweeen elements of the N, ..., NBBUCK entries of HEAD */ wflg = 2; *ncmpa = 0; nel = 0; hmod = MAX (1, nbbuck - 1); dmax = 0; mem = pfree - 1; maxmem = mem; mindeg = 0; rmf = (float) (n) * (float) (n - 1); /* Average sparsity of matrix; diagonal entry is not in mem */ nbflag = 0; lastd = 0; memSet (head, 0, (nbbuck + 2) * sizeof (Gnum)); memSet (last + 1, 0, n * sizeof (Gnum)); if (nbelts == 0) { /* Patch 8/12/03 */ memSet (elen + 1, 0, n * sizeof (Gnum)); for (i = 1; i <= n; i ++) { nv[i] = 1; w[i] = 1; if (len[i] < 0) { degree[i] = n2; nbflag ++; if (len[i] == - (n + 1)) { /* Patch 09/08/98 */ len[i] = 0; pe[i] = 0; /* Patch 12/12/03 : Because of compress, we force skipping those entries (which are anyway empty) */ } else len[i] = - len[i]; } else degree[i] = len[i]; } } else { /* Patch 08/12/03 : Duplicate part of previous loop to avoid sytematic testing for elements */ for (i = 1; i <= n; i ++) { nv[i] = 1; w[i] = 1; if (len[i] < 0) { /* i \in V1 */ degree[i] = n2; nbflag ++; if (len[i] == - (n + 1)) { /* Patch 09/08/98 */ len[i] = 0; pe[i] = 0; /* Patch 12/12/03 : because of compress, we force skipping those entries (which are anyway empty) */ elen[i] = 0; /* Patch 16/12/03 */ } else { len[i] = - len[i]; elen[i] = len[i]; /* Patch 16/12/03 : only elements are adjacent to a variable */ } } else { /* i \in Ve or V0 */ if (elen[i] < 0) { /* i \in Ve */ nel ++; degree[i] = len[i]; elen[i] = - nel; dmax = MAX (dmax, degree[i]); /* Patch 11/03/04 */ } else { degree[i] = elen[i]; elen[i] = len[i]; /* Patch 16/12/03 : only elements are adjacent to a variable */ } } } } /* Temporary Patch 8/12/03 TODO REMOVE */ if (nbelts != nel) printf ("error 8Dec2003\n"); nreal = n - nbflag; for (i = 1; i <= n; i ++) { if (elen[i] < 0 ) /* Patch 16/12/03 : Skip elements */ continue; deg = degree[i]; if (deg == n2) { deg = nbbuck + 1; if (lastd == 0) { lastd = i; head[deg] = i; next[i] = 0; last[i] = 0; } else { next[lastd] = i; last[i] = lastd; lastd = i; next[i] = 0; } } else if (deg > 0) { if (nbelts != 0) { /* Patch 04/01/04 */ Gnum l; /* Size of largest adjacent element */ Gnum m; /* Current edge being visited */ for (m = pe[i], l = 0; m < pe[i] + elen[i]; m ++) { Gnum o; /* Current element being visited */ o = iw[m]; if (len[o] > l) l = len[o]; } deg = (Gnum) ((float) deg * (float) (deg - 1) - (float) l * (float) (l - 1)) / 2; if (deg < 0) /* Patch 04/01/04 */ deg = 0; } wf[i] = deg; /* Patch 14/01/04 */ if (deg > n) deg = MIN ((deg - n) / pas + n, nbbuck); inext = head[deg]; if (inext != 0) last[inext] = i; next[i] = inext; head[deg] = i; } else { nel ++; elen[i] = - nel; pe[i] = 0; w[i] = 0; } } /* L20: */ nleft = n - nel; /* Patch v5 12/12/98 */ while (nel < nreal) { /* WHILE (selecting pivots) DO */ for (deg = mindeg; deg <= nbbuck; deg ++) { me = head[deg]; if (me > 0) break; /* GO to 50 */ } /* L40: */ mindeg = deg; if (me <= 0) { /* Error 1 */ *ncmpa = -n; return; } if (deg > n) { j = next[me]; k = wf[me]; while (j > 0) { if (wf[j] < k) { me = j; k = wf[me]; } j = next[j]; } ilast = last[me]; inext = next[me]; if (inext != 0) last[inext] = ilast; if (ilast != 0) next[ilast] = inext; else head[deg] = inext; /* me is at the head of the degree list */ } else { inext = next[me]; if (inext != 0) last[inext] = 0; head[deg] = inext; } elenme = elen[me]; elen[me] = - (nel + 1); nvpiv = nv[me]; nel += nvpiv; nv[me] = - nvpiv; degme = 0; if (elenme == 0) { pme1 = pe[me]; pme2 = pme1 - 1; for (p = pme1; p <= pme1 + len[me] - 1; p ++) { i = iw[p]; nvi = nv[i]; if (nvi > 0) { degme += nvi; nv[i] = - nvi; pme2 ++; iw[pme2] = i; if (degree[i] != n2) { ilast = last[i]; inext = next[i]; if (inext != 0) last[inext] = ilast; if (ilast != 0) next[ilast] = inext; else { if (wf[i] > n) deg = MIN ((wf[i] - n) / pas + n, nbbuck); else deg = wf[i]; head[deg] = inext; } } } } /* L60: */ newmem = 0; } else { p = pe[me]; pme1 = pfree; slenme = len[me] - elenme; for (knt1 = 1; knt1 <= elenme + 1; knt1 ++) { if (knt1 > elenme) { e = me; pj = p; ln = slenme; } else { e = iw[p ++]; pj = pe[e]; ln = len[e]; } for (knt2 = 1; knt2 <= ln; knt2 ++) { i = iw[pj ++]; nvi = nv[i]; if (nvi > 0) { if (pfree > iwlen) { pe[me] = p; len[me] -= knt1; if (len[me] == 0) pe[me] = 0; pe[e] = pj; len[e] = ln - knt2; if (len[e] == 0) pe[e] = 0; (*ncmpa) ++; for (j = 1; j <= n; j ++) { pn = pe[j]; if (pn > 0) { pe[j] = iw[pn]; iw[pn] = - j; } } /* L70: */ pdst = 1; psrc = 1; pend = pme1 - 1; while (psrc <= pend) { /* L80: */ j = - iw[psrc ++]; if (j > 0) { iw[pdst] = pe[j]; pe[j] = pdst ++; lenj = len[j]; for (knt3 = 0; knt3 <= lenj - 2; knt3 ++) iw[pdst + knt3] = iw[psrc + knt3]; pdst = pdst + (lenj - 1); psrc = psrc + (lenj - 1); } } p1 = pdst; for (psrc = pme1; psrc <= pfree - 1; psrc ++, pdst ++) /* L100: */ iw[pdst] = iw[psrc]; pme1 = p1; pfree = pdst; pj = pe[e]; p = pe[me]; } degme += nvi; nv[i] = - nvi; iw[pfree] = i; (pfree) ++; if (degree[i] != n2) { ilast = last[i]; inext = next[i]; if (inext != 0) last[inext] = ilast; if (ilast != 0) next[ilast] = inext; else { if (wf[i] > n) deg = MIN ((wf[i] - n) / pas + n, nbbuck); else deg = wf[i]; head[deg] = inext; } } } } /* L110: */ if (e != me) { pe[e] = -me; w[e] = 0; } } /* L120: */ pme2 = pfree - 1; newmem = pfree - pme1; mem += newmem; maxmem = MAX (maxmem, mem); } degree[me] = degme; pe[me] = pme1; len[me] = pme2 - pme1 + 1; if (wflg + n <= wflg) { for (x = 1; x <= n; x ++) { if (w[x] != 0) w[x] = 1; } /* L130: */ wflg = 2; } for (pme = pme1; pme <= pme2; pme ++) { i = iw[pme]; eln = elen[i]; if (eln > 0) { nvi = - nv[i]; wnvi = wflg - nvi; for (p = pe[i]; p < pe[i] + eln; p ++) { e = iw[p]; we = w[e]; if (we >= wflg) we -= nvi; else if (we != 0) { we = degree[e] + wnvi; wf[e] = 0; } w[e] = we; } /* L140: */ } } /* L150: */ for (pme = pme1; pme <= pme2; pme ++) { i = iw[pme]; p1 = pe[i]; p2 = p1 + elen[i] - 1; pn = p1; hash = 0; deg = 0; wf3 = 0; wf4 = 0; nvi = - nv[i]; for (p = p1; p <= p2; p ++) { e = iw[p]; dext = w[e] - wflg; if (dext > 0) { if (wf[e] == 0) wf[e] = dext * ((2 * degree[e]) - dext - 1); wf4 += wf[e]; deg += dext; iw[pn ++] = e; hash += e; } else if (dext == 0) { pe[e] = -me; w[e] = 0; } } /* L160: */ elen[i] = pn - p1 + 1; p3 = pn; for (p = p2 + 1; p < p1 + len[i]; p ++) { j = iw[p]; nvj = nv[j]; if (nvj > 0) { deg += nvj; wf3 += nvj; iw[pn ++] = j; hash += j; } } /* L170: */ if (degree[i] == n2) deg = n2; if (deg == 0) { pe[i] = - me; nvi = - nv[i]; degme -= nvi; nvpiv += nvi; nel += nvi; nv[i] = 0; elen[i] = 0; } else { if (degree[i] != n2) { if (degree[i] < deg) { wf4 = 0; wf3 = 0; } else degree[i] = deg; } wf[i] = wf4 + 2 * nvi * wf3; iw[pn] = iw[p3]; iw[p3] = iw[p1]; iw[p1] = me; len[i] = pn - p1 + 1; if (deg != n2) { hash = (hash % hmod) + 1; j = head[hash]; if (j <= 0) { next[i] = - j; head[hash] = - i; } else { next[i] = last[j]; last[j] = i; } last[i] = hash; } } } /* L180: */ degree[me] = degme; dmax = MAX (dmax, degme); wflg += dmax; if (wflg + n <= wflg) { for (x = 1; x <= n; x ++) { if (w[x] != 0) w[x] = 1; } wflg = 2; } for (pme = pme1; pme <= pme2; pme ++) { i = iw[pme]; if ((nv[i] < 0) && (degree[i] != n2)) { hash = last[i]; j = head[hash]; if (j == 0) continue; if (j < 0) { i = - j; head[hash] = 0; } else { i = last[j]; last[j] = 0; } if (i == 0) continue; L200: /* WHILE LOOP: */ if (next[i] != 0) { ln = len[i]; eln = elen[i]; for (p = pe[i] + 1; p < pe[i] + ln; p ++) w[iw[p]] = wflg; jlast = i; j = next[i]; L220: /* WHILE LOOP: */ if (j != 0) { if (len[j] != ln) goto L240; if (elen[j] != eln) goto L240; for (p = pe[j] + 1; p < pe[j] + ln; p ++) { if (w[iw[p]] != wflg) goto L240; } /* L230: */ pe[j] = -i; if (wf[j] > wf[i]) wf[i] = wf[j]; nv[i] += nv[j]; nv[j] = 0; elen[j] = 0; j = next[j]; next[jlast] = j; goto L220; L240: jlast = j; j = next[j]; goto L220; } wflg ++; i = next[i]; if (i != 0) goto L200; } } } p = pme1; nleft = n - nel; for (pme = pme1; pme <= pme2; pme ++) { i = iw[pme]; nvi = - nv[i]; if (nvi > 0) { nv[i] = nvi; if (degree[i] != n2) { deg = MIN (degree[i] + degme, nleft) - nvi; if (degree[i] + degme > nleft) { deg = degree[i]; rmf1 = (float) deg * (float) (deg - 1 + (2 * degme)) - (float) wf[i]; degree[i] = nleft - nvi; deg = degree[i]; rmf = (float) deg * (float) (deg - 1) - (float) (degme - nvi) * (float) (degme - nvi - 1); rmf = MIN (rmf, rmf1); } else { deg = degree[i]; degree[i] = degree[i] + degme - nvi; rmf = (float) deg * (float) (deg - 1 + (2 * degme)) - (float) wf[i]; } wf[i] = (Gnum) (rmf / (float) (nvi + 1) + 0.5F); /* Patch 08/12/2010 */ wf[i] = MAX (0, wf[i]); deg = wf[i]; if (deg > n) deg = MIN ((deg - n) / pas + n, nbbuck); inext = head[deg]; if (inext != 0) last[inext] = i; next[i] = inext; last[i] = 0; head[deg] = i; mindeg = MIN (mindeg, deg); } iw[p ++] = i; } } /* L260: */ nv[me] = nvpiv + degme; len[me] = p - pme1; if (len[me] == 0) { pe[me] = 0; w[me] = 0; } if (newmem != 0) { pfree = p; mem = mem - newmem + len[me]; } } /* END WHILE (selecting pivots) */ if (nel < n) { /* Patch 12/12/98 (old: nreal < n) */ for (deg = mindeg; deg <= (nbbuck + 1); deg ++) { me = head[deg]; if (me > 0) break; } mindeg = deg; nelme = - (nel + 1); for (x = 1; x <= n; x ++) { if ((pe[x] > 0) && (elen[x] < 0)) pe[x] = - me; else if (degree[x] == n2) { nel += nv[x]; pe[x] = - me; elen[x] = 0; nv[x] = 0; /* Patch 12/12/98 (old: n + 1) */ } } elen[me] = nelme; nv[me] = n - nreal; /* Patch 12/12/98 (old: n + 1) */ pe[me] = 0; if (nel != n) { /* Error 2 */ *ncmpa = - (n + 1); return; } } for (i = 1; i <= n; i ++) { if (elen[i] == 0) { j = - pe[i]; while (elen[j] >= 0) /* L270: */ j = - pe[j]; e = j; k = - elen[e]; j = i; while (elen[j] >= 0) { /* L280: */ jnext = - pe[j]; pe[j] = - e; if (elen[j] == 0) elen[j] = k ++; j = jnext; } elen[e] = - k; } } /* L290: */ #ifdef DEAD_CODE for (i = 1; i <= n; i ++) { /* Patch 19/10/98 */ k = abs (elen[i]); last[k] = i; elen[i] = k; } /* L300: */ #endif /* DEAD_CODE */ pfree = maxmem; } scotch-5.1.12b.dfsg/src/libscotch/kgraph.c0000644000175300017530000001501711631334325020557 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kgraph.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a bipartitioning mapper. **/ /** This module handles the k-way active **/ /** graph and save data structure handling **/ /** routines. **/ /** **/ /** DATES : # Version 3.2 : from : 03 oct 1997 **/ /** to 26 may 1998 **/ /** # Version 3.4 : from : 30 oct 2001 **/ /** to 30 oct 2001 **/ /** # Version 4.0 : from : 24 jun 2004 **/ /** to 16 feb 2005 **/ /** # Version 5.1 : from : 28 sep 2008 **/ /** to 31 aug 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define KGRAPH #include "module.h" #include "common.h" #include "graph.h" #include "arch.h" #include "mapping.h" #include "kgraph.h" /***********************************/ /* */ /* Active graph handling routines. */ /* */ /***********************************/ /* This routine builds the active graph ** corresponding to the given k-way ** partition parameters. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int kgraphInit ( Kgraph * restrict const actgrafptr, /* Active graph */ const Graph * restrict const srcgrafptr, /* Source graph */ const Mapping * restrict const mappptr) /* Mapping */ { const Arch * restrict archptr; /* Pointer to mapping architecture */ ArchDom domfrst; /* First, largest domain */ Gnum domfrstload; /* Load of first domain */ Anum termnum; actgrafptr->s = *srcgrafptr; /* Clone source graph */ actgrafptr->s.flagval &= ~GRAPHFREETABS; /* Do not allow freeing */ if (mappptr != &actgrafptr->m) actgrafptr->m = *mappptr; /* Clone mapping */ if ((actgrafptr->comploadavg = (Gnum *) memAlloc (actgrafptr->m.domnmax * sizeof (Gnum) * 2)) == NULL) { errorPrint ("kgraphInit: out of memory"); return (1); } actgrafptr->comploaddlt = actgrafptr->comploadavg + actgrafptr->m.domnnbr; /* TRICK: can send both arrays in one piece */ archptr = &mappptr->archdat; archDomFrst (archptr, &domfrst); /* Get first, largest domain */ domfrstload = archDomWght (archptr, &domfrst); /* Get its load */ actgrafptr->comploadavg[0] = (archDomWght (archptr, &actgrafptr->m.domntab[0]) * actgrafptr->s.velosum) / domfrstload; actgrafptr->comploaddlt[0] = actgrafptr->s.velosum - actgrafptr->comploadavg[0]; for (termnum = 1; termnum < actgrafptr->m.domnnbr; termnum ++) { actgrafptr->comploadavg[termnum] = (archDomWght (archptr, &actgrafptr->m.domntab[termnum]) * actgrafptr->s.velosum) / domfrstload; actgrafptr->comploaddlt[termnum] = - actgrafptr->comploadavg[termnum]; } actgrafptr->fronnbr = 0; /* No frontier yet */ actgrafptr->frontab = NULL; actgrafptr->comploadrat = (double) actgrafptr->s.velosum / (double) domfrstload; actgrafptr->commload = 0; actgrafptr->levlnum = 0; return (0); } /* This routine frees the contents ** of the given active graph and ** updates the mapping data accordingly. ** It returns: ** - VOID : in all cases. */ void kgraphExit ( Kgraph * restrict const grafptr) { if ((grafptr->m.parttax != NULL) && ((grafptr->s.flagval & KGRAPHFREEPART) != 0)) memFree (grafptr->m.parttax + grafptr->m.baseval); if (grafptr->frontab != NULL) /* Free frontier if it exists */ memFree (grafptr->frontab); if (grafptr->comploadavg != NULL) /* Free load array if it exists */ memFree (grafptr->comploadavg); graphExit (&grafptr->s); } /* This routine moves all of the graph ** vertices to the first subdomain, and ** computes the resulting gains. ** It returns: ** - VOID : in all cases. */ void kgraphFrst ( Kgraph * restrict const grafptr) { memSet (grafptr->m.parttax + grafptr->m.baseval, 0, grafptr->m.vertnbr * sizeof (Anum)); /* Set all vertices to subdomain 0 */ grafptr->m.domntab[0] = grafptr->m.domnorg; /* Point to first domain */ grafptr->fronnbr = 0; /* No frontier vertices */ } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_fm.c0000644000175300017530000013204511631334325023141 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_fm.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module separates an active **/ /** graph using a vertex-oriented version **/ /** of our improved Fiduccia-Mattheyses **/ /** heuristics, similar in principle to **/ /** the algorithm of Ashcraft and Liu 1994. **/ /** **/ /** DATES : # Version 3.2 : from : 02 nov 1997 **/ /** to 17 jul 1997 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 31 dec 1998 **/ /** # Version 4.0 : from : 07 jan 2002 **/ /** to 18 aug 2004 **/ /** # Version 5.0 : from : 12 sep 2007 **/ /** to 22 may 2008 **/ /** # Version 5.1 : from : 10 nov 2008 **/ /** to 01 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VGRAPH_SEPARATE_FM #include "module.h" #include "common.h" #include "gain.h" #include "graph.h" #include "vgraph.h" #include "vgraph_separate_gg.h" #include "vgraph_separate_fm.h" /* ** The static definitions. */ static VgraphSeparateFmVertex vexxdat; /* Dummy structure for computing offsets */ /*********************************/ /* */ /* Gain table handling routines. */ /* */ /*********************************/ /* This routine returns the vertex of best gain ** whose swap will keep the balance correct. ** It returns: ** - !NULL : pointer to the vertex gainlink. ** - NULL : if no more vertices available. */ static GainLink * vgraphSeparateFmTablGet ( GainTabl * const tablptr, /* Gain table */ const Gnum deltcur, /* Current imbalance */ const Gnum deltmax, /* Maximum imbalance */ const int partval) /* Current preferred */ { const VgraphSeparateFmVertex * vexxptr; /* Pointer to vertex of current link */ const GainLink * linkptr; /* Pointer to current gain link */ const GainLink * linkbest; /* Pointer to best link found */ const GainEntr * tablbest; /* Gain table entry of best link */ Gnum gaincur; /* Separator gain of current link */ Gnum gainbest; /* Separator gain of best link */ linkbest = NULL; /* Assume no candidate vertex found yet */ tablbest = tablptr->tend; gainbest = GAINMAX; for (linkptr = gainTablFrst (tablptr); /* Select candidate vertices */ (linkptr != NULL) && (linkptr->tabl <= tablbest); linkptr = gainTablNext (tablptr, linkptr)) { int vertpart; /* Part of current vertex */ vertpart = 0; /* Assume we point to gainlink0 */ vexxptr = (VgraphSeparateFmVertex *) linkptr; /* TRICK: gainlink0 is at beginning */ if (vexxptr->veloval >= 0) { /* If in fact we point to gainlink1 */ vertpart = 1; /* Then point to vertex structure */ vexxptr = (VgraphSeparateFmVertex *) ((byte *) vexxptr - ((byte *) &vexxdat.gainlink1 - (byte *) &vexxdat)); } gaincur = vexxptr->compgain[vertpart]; /* Get separator gain and vertex balance */ if (gaincur == vexxptr->veloval) /* If vertex is isolated separator vertex */ return ((GainLink *) linkptr); /* Select it immediatly */ if (abs (deltcur + (1 - 2 * vertpart) * (gaincur - 2 * vexxptr->veloval)) <= deltmax) { /* If vertex enforces balance */ if ((gaincur < gainbest) || /* And if it gives better gain */ ((gaincur == gainbest) && /* Or is in preferred part */ (partval == vertpart))) { linkbest = linkptr; /* Select it */ tablbest = linkptr->tabl; gainbest = gaincur; } } } return ((GainLink *) linkbest); /* Return best link found */ } /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ int vgraphSeparateFm ( Vgraph * restrict const grafptr, /*+ Active graph +*/ const VgraphSeparateFmParam * const paraptr) /*+ Method parameters +*/ { GainTabl * restrict tablptr; /* Pointer to gain tables */ INT passnbr; /* Maximum number of passes to go */ Gnum movenbr; /* Number of uneffective moves done */ int moveflag; /* Flag set if useful moves made */ Gnum savenbr; /* Position of current move */ VgraphSeparateFmSave * restrict savetab; /* Pointer to move array */ Gnum hashmax; /* Maximum number of elements in table */ Gnum hashsiz; /* Size of hash and save tables */ Gnum hashmsk; /* Mask for access to hash table */ Gnum hashnbr; /* Number of elements in hash table */ VgraphSeparateFmVertex * hashtab; /* Hash vertex table */ GainLink lockdat; /* Double linked list of locked vertices */ VgraphSeparateFmVertex * vexxptr; /* Pointer to current vertex */ VgraphSeparateFmVertex * sepaptr; /* Pointer to current vertex in table */ Gnum fronnum; /* Current index of frontier vertex */ Gnum comploaddlt; /* Current load imbalance */ Gnum comploaddltmat; /* Theoretical maximum unbalance */ Gnum comploaddltmax; /* Largest unbalance allowed */ Gnum comploaddltbst; /* Unbalance of best solution to date */ Gnum compload2; /* Current load of separator */ Gnum compload2bst; /* Separator load of best solution to date */ Gnum mswpnum; /* Number of current move sweep */ Gnum compsize1add; /* Number of vertices to add to counters */ Gnum compsize1sub; const Gnum * restrict const verttax = grafptr->s.verttax; /* Fast accesses */ const Gnum * restrict const vendtax = grafptr->s.vendtax; const Gnum * restrict const velotax = grafptr->s.velotax; const Gnum * restrict const edgetax = grafptr->s.edgetax; GraphPart * restrict const parttax = grafptr->parttax; comploaddltmat = (paraptr->deltrat > 0.0L) ? MAX ((Gnum) ((grafptr->compload[0] + grafptr->compload[1]) * paraptr->deltrat), ((2 * grafptr->s.velosum) / grafptr->s.vertnbr)) : 0; if (grafptr->fronnbr == 0) { /* If no frontier defined */ if (abs (grafptr->comploaddlt) <= comploaddltmat) /* If balance is achieved */ return (0); /* This algorithm is useless */ else { /* Imbalance must be fought */ VgraphSeparateGgParam paradat; paradat.passnbr = 4; /* Use a standard algorithm */ vgraphSeparateGg (grafptr, ¶dat); if (grafptr->fronnbr == 0) /* If new partition has no frontier */ return (0); /* This algorithm is still useless */ } } hashnbr = 16 * (grafptr->fronnbr + paraptr->movenbr + grafptr->s.degrmax) + 1; #ifdef SCOTCH_DEBUG_VGRAPH2 hashnbr /= 8; /* Ensure resizing routine will be called */ #endif /* SCOTCH_DEBUG_VGRAPH2 */ if (hashnbr > grafptr->s.vertnbr) hashnbr = grafptr->s.vertnbr; for (hashsiz = 512; hashsiz < hashnbr; hashsiz <<= 1) ; /* Get upper power of two */ hashmsk = hashsiz - 1; hashmax = hashsiz >> 2; /* Use hash table at 1/4 of its capacity */ if (((tablptr = gainTablInit (GAINMAX, VGRAPHSEPAFMGAINBITS)) == NULL) || /* Use logarithmic array only */ (memAllocGroup ((void **) (void *) &hashtab, (size_t) (hashsiz * sizeof (VgraphSeparateFmVertex)), &savetab, (size_t) (hashsiz * sizeof (VgraphSeparateFmSave)), NULL) == NULL)) { errorPrint ("vgraphSeparateFm: out of memory (1)"); if (tablptr != NULL) gainTablExit (tablptr); return (1); } memSet (hashtab, ~0, hashsiz * sizeof (VgraphSeparateFmVertex)); /* Set all vertex numbers to ~0 */ for (fronnum = 0, hashnbr = grafptr->fronnbr; /* Set initial gains */ fronnum < hashnbr; fronnum ++) { Gnum vertnum; Gnum hashnum; vertnum = grafptr->frontab[fronnum]; #ifdef SCOTCH_DEBUG_VGRAPH2 if (parttax[vertnum] != 2) { errorPrint ("vgraphSeparateFm: vertex not in separator"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ for (hashnum = (vertnum * VGRAPHSEPAFMHASHPRIME) & hashmsk; hashtab[hashnum].vertnum != ~0; hashnum = (hashnum + 1) & hashmsk) ; if (velotax != NULL) { /* If vertex loads present */ Gnum edgenum; Gnum veloval; Gnum compgain0; Gnum compgain01; for (edgenum = verttax[vertnum], compgain0 = compgain01 = 0; edgenum < vendtax[vertnum]; edgenum ++) { Gnum vertend; Gnum partend; Gnum veloend; vertend = edgetax[edgenum]; partend = (Gnum) parttax[vertend]; veloend = velotax[vertend]; compgain0 += (partend & 1) * veloend; compgain01 += (2 - (partend & 2)) * veloend; } veloval = velotax[vertnum]; hashtab[hashnum].veloval = - veloval; /* TRICK: -veloval: stored value is opposite of load */ hashtab[hashnum].compgain[0] = compgain0 - veloval; hashtab[hashnum].compgain[1] = (compgain01 >> 1) - compgain0 - veloval; } else { /* No vertex loads */ Gnum edgenum; Gnum compgain0; Gnum compgain2; for (edgenum = verttax[vertnum], compgain0 = compgain2 = 0; edgenum < vendtax[vertnum]; edgenum ++) { Gnum vertend; Gnum partend; vertend = edgetax[edgenum]; partend = (Gnum) parttax[vertend]; compgain0 += (partend & 1); compgain2 += (partend & 2); } hashtab[hashnum].veloval = -1; /* TRICK: -veloval */ hashtab[hashnum].compgain[0] = compgain0 - 1; hashtab[hashnum].compgain[1] = vendtax[vertnum] - verttax[vertnum] - (compgain2 >> 1) - compgain0 - 1; } hashtab[hashnum].partval = 2; hashtab[hashnum].vertnum = vertnum; gainTablAdd (tablptr, &hashtab[hashnum].gainlink0, hashtab[hashnum].compgain[0]); /* Link both directions of separator vertex */ gainTablAdd (tablptr, &hashtab[hashnum].gainlink1, hashtab[hashnum].compgain[1]); } comploaddltmax = MAX (comploaddltmat, abs (grafptr->comploaddlt)); /* Set current maximum distance */ comploaddltbst = grafptr->comploaddlt; compload2bst = grafptr->compload[2]; #ifdef SCOTCH_DEBUG_VGRAPH2 #ifdef SCOTCH_DEBUG_VGRAPH3 if (vgraphSeparateFmCheck (grafptr, hashtab, hashmsk, compload2bst, comploaddltbst) != 0) { errorPrint ("vgraphSeparateFm: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH3 */ #endif /* SCOTCH_DEBUG_VGRAPH2 */ passnbr = paraptr->passnbr; /* Set remaining number of passes */ savenbr = 0; /* For empty backtrack of first pass */ mswpnum = -1; /* Will be incremented afterwards */ lockdat.next = /* List of locked vertices is empty */ lockdat.prev = &lockdat; do { /* As long as there is improvement */ while (savenbr -- > 0) { /* Delete exceeding moves */ Gnum hashnum; int partval; hashnum = savetab[savenbr].hashnum; partval = savetab[savenbr].partval; hashtab[hashnum].partval = partval; /* Restore vertex data */ hashtab[hashnum].compgain[0] = savetab[savenbr].compgain[0]; hashtab[hashnum].compgain[1] = savetab[savenbr].compgain[1]; if (hashtab[hashnum].gainlink0.next >= VGRAPHSEPAFMSTATELINK) { /* If vertex is linked */ gainTablDel (tablptr, &hashtab[hashnum].gainlink0); /* Unlink it */ gainTablDel (tablptr, &hashtab[hashnum].gainlink1); hashtab[hashnum].gainlink0.next = VGRAPHSEPAFMSTATEFREE; /* Set it as free */ } if ((hashtab[hashnum].gainlink0.next == VGRAPHSEPAFMSTATEFREE) && (partval == 2)) { /* If vertex not locked and in separator */ gainTablAdd (tablptr, &hashtab[hashnum].gainlink0, hashtab[hashnum].compgain[0]); /* Re-link it */ gainTablAdd (tablptr, &hashtab[hashnum].gainlink1, hashtab[hashnum].compgain[1]); } } compload2 = compload2bst; /* Restore best separator parameters */ comploaddlt = comploaddltbst; mswpnum ++; /* Forget all recorded moves */ #ifdef SCOTCH_DEBUG_VGRAPH2 #ifdef SCOTCH_DEBUG_VGRAPH3 if (vgraphSeparateFmCheck (grafptr, hashtab, hashmsk, compload2, comploaddlt) != 0) { errorPrint ("vgraphSeparateFm: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH3 */ #endif /* SCOTCH_DEBUG_VGRAPH2 */ while (lockdat.next != &lockdat) { /* For all vertices in locked list */ VgraphSeparateFmVertex * vexxptr; vexxptr = (VgraphSeparateFmVertex *) ((byte *) lockdat.next - ((byte *) &vexxdat.gainlink1 - (byte *) &vexxdat)); lockdat.next = (GainLink *) vexxptr->gainlink1.next; /* Unlink vertex from list */ if (vexxptr->partval == 2) { /* If vertex belongs to separator */ #ifdef SCOTCH_DEBUG_VGRAPH2 if (vexxptr->gainlink0.next != VGRAPHSEPAFMSTATEUSED) { errorPrint ("vgraphSeparateFm: linked non-used vertex"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ gainTablAdd (tablptr, &vexxptr->gainlink0, vexxptr->compgain[0]); /* Link it */ gainTablAdd (tablptr, &vexxptr->gainlink1, vexxptr->compgain[1]); } else /* Vertex does not belong to separator */ vexxptr->gainlink0.next = VGRAPHSEPAFMSTATEFREE; /* Set it as free for this run */ } lockdat.prev = &lockdat; /* Restore backward chaining */ moveflag = 0; /* No moves to date */ movenbr = /* No uneffective moves yet */ savenbr = 0; /* No recorded moves yet */ while ((movenbr < paraptr->movenbr) && /* As long as we can find effective vertices */ ((vexxptr = (VgraphSeparateFmVertex *) vgraphSeparateFmTablGet (tablptr, comploaddlt, comploaddltmax, (passnbr & 1))) != NULL)) { int partval; /* Part of current vertex */ Gnum vertnum; Gnum edgenum; partval = 0; /* Assume we point to gainlink0 */ if (vexxptr->veloval >= 0) { /* If in fact we point to gainlink1 */ partval = 1; /* Then point to vertex structure */ vexxptr = (VgraphSeparateFmVertex *) ((byte *) vexxptr - ((byte *) &vexxptr->gainlink1 - (byte *) vexxptr)); } #ifdef SCOTCH_DEBUG_VGRAPH2 if (vexxptr->partval != 2) { errorPrint ("vgraphSeparateFm: linked non-separator vertex (1)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ gainTablDel (tablptr, &vexxptr->gainlink0); /* Remove it from table */ gainTablDel (tablptr, &vexxptr->gainlink1); vexxptr->gainlink0.next = VGRAPHSEPAFMSTATESUCH; /* Mark it as used and avoid chaining */ vexxptr->gainlink1.prev = &lockdat; /* Lock it */ vexxptr->gainlink1.next = lockdat.next; lockdat.next->prev = &vexxptr->gainlink1; lockdat.next = &vexxptr->gainlink1; vertnum = vexxptr->vertnum; /* Get vertex number */ compload2 += vexxptr->compgain[partval]; comploaddlt -= (2 * partval - 1) * (vexxptr->compgain[partval] - 2 * vexxptr->veloval); /* TRICK: -veloval */ if (vexxptr->mswpnum != mswpnum) { /* If vertex data not yet recorded */ vexxptr->mswpnum = mswpnum; savetab[savenbr].hashnum = vexxptr - hashtab; savetab[savenbr].partval = 2; savetab[savenbr].compgain[0] = vexxptr->compgain[0]; savetab[savenbr].compgain[1] = vexxptr->compgain[1]; savenbr ++; /* One more move recorded */ } movenbr ++; /* One more move done */ sepaptr = NULL; /* No separator vertices to relink yet */ for (edgenum = verttax[vertnum]; /* Update neighbors */ edgenum < vendtax[vertnum]; edgenum ++) { Gnum vertend; Gnum hashnum; vertend = edgetax[edgenum]; for (hashnum = (vertend * VGRAPHSEPAFMHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { VgraphSeparateFmVertex * vexxend; /* Pointer to neighbor of current vertex */ vexxend = hashtab + hashnum; /* Point to neighbor */ if (vexxend->vertnum == ~0) { /* If neighbor does not exist yet */ if (parttax[vertend] == partval) /* If no use to create it */ break; /* Skip to next vertex */ #ifdef SCOTCH_DEBUG_VGRAPH2 if (parttax[vertend] != (1 - partval)) { errorPrint ("vgraphSeparateFm: undeclared separator vertex"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ vexxend->vertnum = vertend; /* Set its number (TRICK: mswpnum assumed to be always -1) */ vexxend->partval = 1 - partval; /* Vertex will be in separator */ vexxend->veloval = - ((velotax != NULL) ? velotax[vertend] : 1); vexxend->gainlink0.next = VGRAPHSEPAFMSTATEFREE; /* Vertex will be linked */ hashnbr ++; /* One more vertex in hash table */ #ifdef SCOTCH_DEBUG_VGRAPH2 if (hashnbr > hashmsk) { errorPrint ("vgraphSeparateFm: hash table overflow"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ } if (vexxend->vertnum == vertend) { /* If end vertex has been found */ if (vexxend->partval == 2) { /* If already in separator or chained */ if (vexxend->mswpnum != mswpnum) { /* If vertex data not yet recorded */ vexxend->mswpnum = mswpnum; savetab[savenbr].hashnum = hashnum; savetab[savenbr].partval = 2; savetab[savenbr].compgain[0] = vexxend->compgain[0]; savetab[savenbr].compgain[1] = vexxend->compgain[1]; savenbr ++; /* One more move recorded */ } vexxend->compgain[1 - partval] -= vexxptr->veloval; /* TRICK: -veloval */ if (vexxend->gainlink0.next >= VGRAPHSEPAFMSTATELINK) { /* If vertex is linked */ gainTablDel (tablptr, &vexxend->gainlink0); /* Unlink it temporarily */ gainTablDel (tablptr, &vexxend->gainlink1); /* TRICK: gainlink1.next != NULL */ vexxend->gainlink0.next = VGRAPHSEPAFMSTATEFREE; /* Mark separator vertex as temporarily unlinked */ vexxend->gainlink0.prev = (GainLink *) sepaptr; /* Chain it for relinking */ sepaptr = vexxend; } else if (vexxend->gainlink0.next == VGRAPHSEPAFMSTATEUSED) { vexxend->gainlink0.next = VGRAPHSEPAFMSTATESUCH; /* Mark separator vertex as chained-used */ vexxend->gainlink0.prev = (GainLink *) sepaptr; /* Chain it for relinking */ sepaptr = vexxend; } } else if (vexxend->partval == (1 - partval)) { /* Vertex is in other part */ Gnum edgeend; Gnum compgainp; /* Gain to be added to gain of part partval */ if (vexxend->mswpnum != mswpnum) { /* If vertex data not yet recorded */ vexxend->mswpnum = mswpnum; savetab[savenbr].hashnum = hashnum; savetab[savenbr].partval = 1 - partval; savetab[savenbr].compgain[0] = /* Vertex not in separator so gains are not relevant */ savetab[savenbr].compgain[1] = 0; savenbr ++; /* One more move recorded */ } vexxend->partval = 2; /* Vertex will be in separator */ vexxend->compgain[partval] = vexxend->veloval; /* Moved vertex still in separator */ vexxend->compgain[1 - partval] = vexxend->veloval - vexxptr->veloval; /* TRICK: -veloval */ for (edgeend = verttax[vertend], compgainp = 0; edgeend < vendtax[vertend]; edgeend ++) { Gnum vertent; Gnum hashnum; vertent = edgetax[edgeend]; for (hashnum = (vertent * VGRAPHSEPAFMHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { VgraphSeparateFmVertex * vexxent; /* Pointer to neighbor of neighbor of current vertex */ vexxent = hashtab + hashnum; if (vexxent->vertnum == ~0) { /* If neighbor does not exist */ #ifdef SCOTCH_DEBUG_VGRAPH2 if (parttax[vertent] != (1 - partval)) { errorPrint ("vgraphSeparateFm: broken separator (1)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ compgainp += (velotax != NULL) ? velotax[vertent] : 1; break; /* Skip to next vertex */ } if (vexxent->vertnum == vertent) { /* If end vertex found */ #ifdef SCOTCH_DEBUG_VGRAPH2 if (vexxent->partval == partval) { errorPrint ("vgraphSeparateFm: broken separator (2)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ if (vexxent->partval == 2) { /* If vertex is in separator (or is vexxptr) */ if (vexxent->mswpnum != mswpnum) { /* If vertex data not yet recorded */ vexxent->mswpnum = mswpnum; savetab[savenbr].hashnum = hashnum; savetab[savenbr].partval = 2; savetab[savenbr].compgain[0] = vexxent->compgain[0]; savetab[savenbr].compgain[1] = vexxent->compgain[1]; savenbr ++; /* One more move recorded */ } vexxent->compgain[partval] += vexxend->veloval; /* TRICK: -veloval */ if (vexxent->gainlink0.next >= VGRAPHSEPAFMSTATELINK) { /* If not already chained */ gainTablDel (tablptr, &vexxent->gainlink0); /* Unlink it temporarily */ gainTablDel (tablptr, &vexxent->gainlink1); /* TRICK: gainlink1.next != NULL */ vexxent->gainlink0.next = VGRAPHSEPAFMSTATEFREE; /* Mark separator vertex as temporarily unlinked */ vexxent->gainlink0.prev = (GainLink *) sepaptr; /* Chain it */ sepaptr = vexxent; } else if (vexxent->gainlink0.next == VGRAPHSEPAFMSTATEUSED) { vexxent->gainlink0.next = VGRAPHSEPAFMSTATESUCH; /* Mark separator vertex as chained-used */ vexxent->gainlink0.prev = (GainLink *) sepaptr; /* Chain it for relinking */ sepaptr = vexxent; } } else /* Vertex is in same part as vexxend */ compgainp -= vexxent->veloval; /* TRICK: -veloval */ break; } } } vexxend->compgain[partval] += compgainp; if (vexxend->gainlink0.next == VGRAPHSEPAFMSTATEUSED) /* If vertex was already used */ vexxend->gainlink0.next = VGRAPHSEPAFMSTATESUCH; /* Set it as separator-used-chained */ vexxend->gainlink0.prev = (GainLink *) sepaptr; /* Chain it for relinking */ sepaptr = vexxend; } break; /* If in same part, ignore */ } } } vexxptr->gainlink0.next = VGRAPHSEPAFMSTATEUSED; /* Mark it as used and not chained */ vexxptr->partval = partval; /* Set vertex part last */ while (sepaptr != NULL) { /* For all vertices in chain list */ vexxptr = sepaptr; /* Unlink vertex from list */ sepaptr = (VgraphSeparateFmVertex *) vexxptr->gainlink0.prev; #ifdef SCOTCH_DEBUG_VGRAPH2 if (vexxptr->partval != 2) { errorPrint ("vgraphSeparateFm: linked non-separator vertex (2)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ if (vexxptr->gainlink0.next == VGRAPHSEPAFMSTATEFREE) { /* If vertex is not used */ gainTablAdd (tablptr, &vexxptr->gainlink0, vexxptr->compgain[0]); /* Link it */ gainTablAdd (tablptr, &vexxptr->gainlink1, vexxptr->compgain[1]); } else { vexxptr->gainlink0.next = VGRAPHSEPAFMSTATEUSED; if (vexxptr->compgain[partval] == vexxptr->veloval) { /* If immediate gain */ vexxptr->gainlink1.next->prev = vexxptr->gainlink1.prev; /* Remove vertex from lock list */ vexxptr->gainlink1.prev->next = vexxptr->gainlink1.next; gainTablAdd (tablptr, &vexxptr->gainlink0, vexxptr->compgain[0]); /* Link it */ gainTablAdd (tablptr, &vexxptr->gainlink1, vexxptr->compgain[1]); } } } #ifdef SCOTCH_DEBUG_VGRAPH2 #ifdef SCOTCH_DEBUG_VGRAPH3 if (vgraphSeparateFmCheck (grafptr, hashtab, hashmsk, compload2, comploaddlt) != 0) { errorPrint ("vgraphSeparateFm: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH3 */ #endif /* SCOTCH_DEBUG_VGRAPH2 */ if (hashnbr >= hashmax) { if (vgraphSeparateFmResize (&hashtab, &hashmax, &hashmsk, &savetab, savenbr, tablptr, &lockdat) != 0) { errorPrint ("vgraphSeparateFm: out of memory (2)"); return (1); } } if (compload2 < compload2bst) { /* If move improves the cost */ compload2bst = compload2; /* This move was effective */ comploaddltbst = comploaddlt; movenbr = savenbr = 0; moveflag = 1; mswpnum ++; } else if (compload2 == compload2bst) { if (abs (comploaddlt) < abs (comploaddltbst)) { comploaddltbst = comploaddlt; /* This move was effective */ movenbr = savenbr = 0; moveflag = 1; mswpnum ++; } else if (abs (comploaddlt) == abs (comploaddltbst)) { comploaddltbst = comploaddlt; /* Might be the opposite, so record */ savenbr = 0; /* Forget backtracking */ mswpnum ++; } } if (comploaddltmax > comploaddltmat) { /* If must restrict distance bounds */ Gnum comploaddlttmp; comploaddlttmp = comploaddltmax; /* Save old working compdeltmax value */ comploaddltmax = MAX (comploaddltmat, abs (comploaddlt)); /* Restrict at most to the maximum */ if (comploaddltmax < comploaddlttmp) { /* If we have done something useful */ compload2bst = compload2; /* Then record best move done */ comploaddltbst = comploaddlt; movenbr = savenbr = 0; mswpnum ++; } } } } while ((moveflag != 0) && /* As long as vertices are moved */ (-- passnbr != 0)); /* And we are allowed to loop (TRICK for negative values) */ while (savenbr -- > 0) { /* Delete exceeding moves */ Gnum hashnum; int partval; hashnum = savetab[savenbr].hashnum; partval = savetab[savenbr].partval; hashtab[hashnum].partval = partval; /* Restore vertex part only for update computation */ } compload2 = compload2bst; /* Restore best separator parameters */ comploaddlt = comploaddltbst; compsize1add = /* Variables for superscalar update */ compsize1sub = 0; for (vexxptr = hashtab, fronnum = 0; /* Build new frontier */ vexxptr < hashtab + (hashmax << 2); vexxptr ++) { /* From all vertices in table */ Gnum vertnum; vertnum = vexxptr->vertnum; if (vertnum != ~0) { /* If vertex slot is used */ int partval; /* New part of current vertex */ int partold; /* Old part of current vertex */ partval = vexxptr->partval; partold = parttax[vexxptr->vertnum]; /* Get old part value from array */ if (partval != partold) { /* If vertex part changed */ parttax[vertnum] = partval; /* Set new part value */ compsize1add += (partval & 1); /* Superscalar update */ compsize1sub += (partold & 1); } if (partval == 2) /* If vertex belongs to cut */ grafptr->frontab[fronnum ++] = vertnum; /* Add vertex to frontier */ } } grafptr->compload[0] = ((grafptr->s.velosum - compload2) + comploaddlt) / 2; grafptr->compload[1] = ((grafptr->s.velosum - compload2) - comploaddlt) / 2; grafptr->compload[2] = compload2; grafptr->comploaddlt = comploaddlt; grafptr->compsize[1] = grafptr->compsize[1] + compsize1add - compsize1sub; grafptr->compsize[0] = grafptr->s.vertnbr - grafptr->compsize[1] - fronnum; grafptr->fronnbr = fronnum; #ifdef SCOTCH_DEBUG_VGRAPH2 if (vgraphCheck (grafptr) != 0) { errorPrint ("vgraphSeparateFm: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ memFree (hashtab); /* Free group leader */ gainTablExit (tablptr); return (0); } /* This routine doubles the size all of the arrays ** involved in handling the hash table and hash ** vertex arrays. ** It returns: ** - 0 : if resizing succeeded. ** - !0 : if out of memory. */ static int vgraphSeparateFmResize ( VgraphSeparateFmVertex * restrict * hashtabptr, /*+ Pointer to hash vertex table +*/ Gnum * const hashmaxptr, /*+ Pointer to maximum number of elements in table +*/ Gnum * const hashmskptr, /*+ Pointer to hash table mask +*/ VgraphSeparateFmSave * restrict * savetabptr, /*+ Pointer to move array +*/ const Gnum savenbr, /*+ Current number of active slots in move array +*/ GainTabl * const tablptr, /*+ Gain table +*/ GainLink * const lockptr) { VgraphSeparateFmVertex * restrict hashtab; /* Pointer to new hash table */ VgraphSeparateFmSave * savetab; /* Pointer to new save array */ VgraphSeparateFmSave * saveold; /* Pointer to translated old save array */ Gnum savenum; Gnum hashold; /* Size of old hash table (half of new) */ Gnum hashsiz; Gnum hashmax; Gnum hashmsk; Gnum hashsta; /* Start index of range of hash indices to move */ Gnum hashend; /* End index of range of hash indices to move */ Gnum hashnum; hashmax = *hashmaxptr << 1; /* Compute new sizes */ hashold = *hashmaxptr << 2; hashsiz = *hashmaxptr << 3; hashmsk = hashsiz - 1; if (memReallocGroup ((void *) *hashtabptr, &hashtab, (size_t) (hashsiz * sizeof (VgraphSeparateFmVertex)), &savetab, (size_t) (hashsiz * sizeof (VgraphSeparateFmSave)), NULL) == NULL) { errorPrint ("vgraphSeparateFmResize: out of memory"); return (1); } saveold = (VgraphSeparateFmSave *) ((byte *) hashtab + ((byte *) *savetabptr - (byte *) *hashtabptr)); for (savenum = savenbr - 1; savenum >= 0; savenum --) { /* Move save array, in reverse order */ savetab[savenum].compgain[1] = saveold[savenum].compgain[1]; savetab[savenum].compgain[0] = saveold[savenum].compgain[0]; savetab[savenum].partval = saveold[savenum].partval; savetab[savenum].hashnum = hashtab[saveold[savenum].hashnum].vertnum; /* Temporarily translate from hash index to number */ } *hashtabptr = hashtab; *hashmaxptr = hashmax; *hashmskptr = hashmsk; *savetabptr = savetab; memSet (hashtab + hashold, ~0, hashold * sizeof (VgraphSeparateFmVertex)); gainTablFree (tablptr); /* Reset gain table */ lockptr->next = /* Rebuild lock list */ lockptr->prev = lockptr; for (hashsta = hashold - 1; hashtab[hashsta].vertnum != ~0; hashsta --) ; /* Start index of first segment to reconsider is last empty slot */ hashend = hashold; /* First segment to reconsider ends at the end of the old array */ while (hashend != hashsta) { /* For each of the two segments to consider */ for (hashnum = hashsta; hashnum < hashend; hashnum ++) { /* Re-compute position of vertices in new table */ Gnum vertnum; vertnum = hashtab[hashnum].vertnum; if (vertnum != ~0) { /* If hash slot used */ Gnum hashnew; for (hashnew = (vertnum * VGRAPHSEPAFMHASHPRIME) & hashmsk; ; hashnew = (hashnew + 1) & hashmsk) { if (hashnew == hashnum) /* If hash slot is the same */ break; /* There is nothing to do */ if (hashtab[hashnew].vertnum == ~0) { /* If new slot is empty */ #ifdef SCOTCH_DEBUG_VGRAPH2 if ((hashnew > hashnum) && (hashnew < hashend)) { /* If vertex is not moved either before its old position or after the end of the segment */ errorPrint ("vgraphSeparateFmResize: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ hashtab[hashnew] = hashtab[hashnum]; /* Copy data to new slot */ hashtab[hashnum].mswpnum = ~0; /* TRICK: not tested at creation */ hashtab[hashnum].vertnum = ~0; /* Make old slot empty */ break; } } if (hashtab[hashnew].gainlink0.next >= VGRAPHSEPAFMSTATELINK) { /* If vertex was linked, re-link it */ gainTablAdd (tablptr, &hashtab[hashnew].gainlink0, hashtab[hashnew].compgain[0]); gainTablAdd (tablptr, &hashtab[hashnew].gainlink1, hashtab[hashnew].compgain[1]); } else if (hashtab[hashnew].gainlink0.next == VGRAPHSEPAFMSTATEUSED) { /* Re-lock used vertices */ hashtab[hashnew].gainlink1.prev = lockptr; /* Lock it */ hashtab[hashnew].gainlink1.next = lockptr->next; lockptr->next->prev = &hashtab[hashnew].gainlink1; lockptr->next = &hashtab[hashnew].gainlink1; } } } hashend = hashsta; /* End of second segment to consider is start of first one */ hashsta = 0; /* Start of second segment is beginning of array */ } /* After second segment, hashsta = hashend = 0 and loop stops */ for (savenum = 0; savenum < savenbr; savenum ++) { Gnum vertnum; Gnum hashnum; vertnum = savetab[savenum].hashnum; /* Get vertex number temporarily saved */ for (hashnum = (vertnum * VGRAPHSEPAFMHASHPRIME) & hashmsk; hashtab[hashnum].vertnum != vertnum; hashnum = (hashnum + 1) & hashmsk) { #ifdef SCOTCH_DEBUG_VGRAPH2 if (hashtab[hashnum].vertnum == ~0) { errorPrint ("vgraphSeparateFmResize: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ } savetab[savenum].hashnum = hashnum; /* Set new hash table index */ } return (0); } /* This routine checks the consistency of ** the hash structures. ** It returns: ** - 0 : in case of success. ** - !0 : in case of error. */ #ifdef SCOTCH_DEBUG_VGRAPH3 static int vgraphSeparateFmCheck ( const Vgraph * restrict const grafptr, const VgraphSeparateFmVertex * restrict const hashtab, const Gnum hashmsk, const Gnum compload2, const Gnum comploaddlt) { Gnum hashnum; Gnum comploadtmp[3]; const Gnum * restrict const verttax = grafptr->s.verttax; /* Fast accesses */ const Gnum * restrict const vendtax = grafptr->s.vendtax; const Gnum * restrict const velotax = grafptr->s.velotax; const Gnum * restrict const edgetax = grafptr->s.edgetax; const GraphPart * restrict const parttax = grafptr->parttax; comploadtmp[0] = grafptr->compload[0]; comploadtmp[1] = grafptr->compload[1]; comploadtmp[2] = grafptr->compload[2]; for (hashnum = 0; hashnum <= hashmsk; hashnum ++) { /* For all vertex slots */ Gnum vertnum; int partval; vertnum = hashtab[hashnum].vertnum; if (vertnum == ~0) /* If unallocated slot */ continue; /* Skip to next slot */ if (hashtab[hashnum].veloval != - ((velotax == NULL) ? 1 : velotax[vertnum])) { errorPrint ("vgraphSeparateFmCheck: invalid vertex load (1)"); return (1); } partval = hashtab[hashnum].partval; if ((partval < 0) || (partval > 2)) { errorPrint ("vgraphSeparateFmCheck: invalid part value"); return (1); } if (partval != parttax[vertnum]) { comploadtmp[parttax[vertnum]] += hashtab[hashnum].veloval; /* TRICK: -veloval */ comploadtmp[partval] -= hashtab[hashnum].veloval; } if (partval < 2) { /* If not separator vertex */ if (hashtab[hashnum].gainlink0.next >= VGRAPHSEPAFMSTATELINK) { errorPrint ("vgraphSeparateFmCheck: linked non-separator vertex"); return (1); } } else { /* Separator vertex */ Gnum compload[3]; Gnum edgenum; if (hashtab[hashnum].gainlink0.next == VGRAPHSEPAFMSTATEFREE) { errorPrint ("vgraphSeparateFmCheck: free separator vertex"); return (1); } compload[0] = compload[1] = compload[2] = 0; for (edgenum = verttax[vertnum]; /* For all element neighbors */ edgenum < vendtax[vertnum]; edgenum ++) { Gnum vertend; Gnum hashnum; int partend; Gnum veloend; vertend = edgetax[edgenum]; for (hashnum = (vertend * VGRAPHSEPAFMHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { if (hashtab[hashnum].vertnum == vertend) { /* If end vertex found */ partend = hashtab[hashnum].partval; veloend = hashtab[hashnum].veloval; if (veloend != - ((velotax == NULL) ? 1 : velotax[vertend])) { errorPrint ("vgraphSeparateFmCheck: invalid vertex load (2)"); return (1); } break; } if (hashtab[hashnum].vertnum == ~0) { /* If element not present */ partend = parttax[vertend]; veloend = - ((velotax == NULL) ? 1 : velotax[vertend]); break; } } compload[partend] += veloend; } if ((hashtab[hashnum].compgain[0] != (hashtab[hashnum].veloval - compload[1])) || (hashtab[hashnum].compgain[1] != (hashtab[hashnum].veloval - compload[0]))) { errorPrint ("vgraphSeparateFmCheck: invalid vertex gains"); return (1); } } } if (compload2 != comploadtmp[2]) { errorPrint ("vgraphSeparateFmCheck: invalid frontier load"); return (1); } if (comploaddlt != (comploadtmp[0] - comploadtmp[1])) { errorPrint ("vgraphSeparateFmCheck: invalid separator balance"); return (1); } return (0); } #endif /* SCOTCH_DEBUG_VGRAPH3 */ scotch-5.1.12b.dfsg/src/libscotch/vdgraph_store.c0000644000175300017530000001465111631334325022155 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_store.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the save data **/ /** structure handling routines for **/ /** distributed separation graphs. **/ /** **/ /** DATES : # Version 4.0 : from : 08 mar 2006 **/ /** to : 01 mar 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VDGRAPH_STORE #include "module.h" #include "common.h" #include "dgraph.h" #include "vdgraph.h" /**********************************/ /* */ /* Store graph handling routines. */ /* */ /**********************************/ /* This routine builds a save structure ** for the given active graph. ** It returns: ** - 0 : if allocation succeeded. ** - !0 : on error. */ int vdgraphStoreInit ( const Vdgraph * restrict const grafptr, VdgraphStore * restrict const storptr) { Gnum savsize; savsize = grafptr->s.vertlocnbr * (sizeof (GraphPart) + sizeof (Gnum)); /* Compute size for frontier and part arrays */ if ((storptr->datatab = (byte *) memAlloc (savsize)) == NULL) { /* Allocate save structure */ errorPrint ("vdgraphStoreInit: out of memory"); return (1); } return (0); } /* This routine frees a save structure. ** It returns: ** - VOID : in all cases. */ void vdgraphStoreExit ( VdgraphStore * const storptr) { memFree (storptr->datatab); #ifdef SCOTCH_DEBUG_VDGRAPH2 storptr->datatab = NULL; #endif /* SCOTCH_DEBUG_VDGRAPH2 */ } /* This routine saves partition data from the ** given active graph to the given save structure. ** It returns: ** - VOID : in all cases. */ void vdgraphStoreSave ( const Vdgraph * const grafptr, VdgraphStore * const storptr) { byte * partloctab; /* Pointer to part data save area */ byte * fronloctab; /* Pointer to frontier data save area */ storptr->fronglbnbr = grafptr->compglbsize[2]; /* Save partition parameters */ storptr->compglbloaddlt = grafptr->compglbloaddlt; storptr->compglbload[0] = grafptr->compglbload[0]; storptr->compglbload[1] = grafptr->compglbload[1]; storptr->compglbsize0 = grafptr->compglbsize[0]; storptr->complocsize0 = grafptr->complocsize[0]; storptr->fronlocnbr = grafptr->complocsize[2]; fronloctab = storptr->datatab; /* Compute data offsets within save structure */ partloctab = fronloctab + grafptr->complocsize[2] * sizeof (Gnum); memCpy (fronloctab, grafptr->fronloctab, grafptr->complocsize[2] * sizeof (Gnum)); memCpy (partloctab, grafptr->partgsttax + grafptr->s.baseval, grafptr->s.vertlocnbr * sizeof (GraphPart)); } /* This routine updates partition data of the ** given active graph, using the given save graph. ** It returns: ** - VOID : in all cases. */ void vdgraphStoreUpdt ( Vdgraph * const grafptr, const VdgraphStore * const storptr) { byte * fronloctab; /* Pointer to frontier data save area */ byte * partloctab; /* Pointer to part data save area */ grafptr->compglbload[0] = storptr->compglbload[0]; /* Load partition parameters */ grafptr->compglbload[1] = storptr->compglbload[1]; grafptr->compglbload[2] = grafptr->s.veloglbsum - (storptr->compglbload[0] + storptr->compglbload[1]); grafptr->compglbloaddlt = storptr->compglbloaddlt; grafptr->compglbsize[0] = storptr->compglbsize0; grafptr->compglbsize[1] = grafptr->s.vertglbnbr - (storptr->compglbsize0 + storptr->fronglbnbr); grafptr->compglbsize[2] = storptr->fronglbnbr; grafptr->complocsize[0] = storptr->complocsize0; grafptr->complocsize[1] = grafptr->s.vertlocnbr - (storptr->complocsize0 + storptr->fronlocnbr); grafptr->complocsize[2] = storptr->fronlocnbr; fronloctab = storptr->datatab; /* Compute data offsets within save structure */ partloctab = fronloctab + grafptr->complocsize[2] * sizeof (Gnum); memCpy (grafptr->fronloctab, fronloctab, grafptr->complocsize[2] * sizeof (Gnum)); memCpy (grafptr->partgsttax + grafptr->s.baseval, partloctab, grafptr->s.vertlocnbr * sizeof (GraphPart)); #ifdef SCOTCH_DEBUG_VDGRAPH2 if (vdgraphCheck (grafptr) != 0) errorPrint ("vdgraphStoreUpdt: inconsistent graph data"); #endif /* SCOTCH_DEBUG_VDGRAPH2 */ } scotch-5.1.12b.dfsg/src/libscotch/graph_coarsen.c0000644000175300017530000012212711631334325022117 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_coarsen.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the source graph **/ /** coarsening functions. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to 18 may 1993 **/ /** # Version 1.3 : from : 30 apr 1994 **/ /** to 18 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 31 oct 1994 **/ /** # Version 3.0 : from : 07 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 28 nov 1995 **/ /** to 08 jun 1996 **/ /** # Version 3.2 : from : 07 sep 1996 **/ /** to 17 sep 1998 **/ /** # Version 4.0 : from : 13 dec 2001 **/ /** to 31 aug 2005 **/ /** # Version 5.0 : from : 13 dec 2006 **/ /** to 24 mar 2008 **/ /** # Version 5.1 : from : 30 oct 2009 **/ /** to 30 oct 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GRAPH_COARSEN #include "module.h" #include "common.h" #include "graph.h" #include "graph_coarsen.h" /* ** The static variables. */ static Gnum (* graphCoarsenFuncTab[GRAPHCOARNBR]) (const Graph * const, Gnum *, const Gnum, const Gnum) = { /* Tables of edge-matching routines */ graphCoarsenMatchHy, graphCoarsenMatchSc, graphCoarsenMatchCs, graphCoarsenMatchCh }; /***************************/ /* */ /* The coarsening routine. */ /* */ /***************************/ /* This routine coarsens the given "finegraph" into ** "coargraph", as long as the coarsening ratio remains ** below some threshold value and the coarsened graph ** is not too small. ** It returns: ** - 0 : if the graph has been coarsened. ** - 1 : if the graph could not be coarsened. ** - 2 : on error. */ int graphCoarsen ( const Graph * restrict const finegrafptr, /*+ Graph to coarsen +*/ Graph * restrict const coargrafptr, /*+ Coarse graph to build +*/ GraphCoarsenMulti * restrict * const coarmultptr, /*+ Pointer to multinode table to build +*/ const Gnum coarnbr, /*+ Minimum number of coarse vertices +*/ const double coarrat, /*+ Maximum contraction ratio +*/ const GraphCoarsenType coartype) /*+ Edge matching type +*/ { Gnum coarhashnbr; /* Size of the hash table */ Gnum coarhashmsk; /* Mask for access to hash table */ GraphCoarsenHash * restrict coarhashtab; /* Table of edges to other multinodes */ Gnum coarvertnbr; /* Number of coarse vertices */ Gnum coarvertnum; /* Number of current multinode vertex */ Gnum coarvertmax; /* Maximum number of multinode vertices */ Gnum coarvelomax; /* Maximum vertex weight allowed */ GraphCoarsenMulti * restrict coarmulttax; /* Multinode array */ Gnum * restrict finecoartax; /* Based access to finecoartab */ Gnum finevertnum; /* Number of currently selected fine vertex */ size_t coarmultoftval; size_t coarvelooftval; size_t coaredgeoftval; size_t coaredlooftval; #ifdef SCOTCH_DEBUG_GRAPH2 if (coartype >= GRAPHCOARNBR) { errorPrint ("graphCoarsen: invalid parameter"); return (2); } #endif /* SCOTCH_DEBUG_GRAPH2 */ #ifdef SCOTCH_DEBUG_GRAPH1 if (coarrat < 0.5L) /* If impossible coarsening ratio wanted */ return (1); /* We will never succeed */ #endif /* SCOTCH_DEBUG_GRAPH1 */ coarvertmax = (Gnum) ((double) finegrafptr->vertnbr * coarrat); /* Maximum number of coarse vertices */ if (coarvertmax < coarnbr) /* If there will be too few vertices in graph */ return (1); /* It is useless to go any further */ if ((finecoartax = (Gnum *) memAlloc (finegrafptr->vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("graphCoarsen: out of memory (1)"); /* Allocate coarse graph uncoarsening array */ return (2); } memSet (finecoartax, ~0, finegrafptr->vertnbr * sizeof (Gnum)); finecoartax -= finegrafptr->baseval; /* Set based access to finecoartab */ coarvelomax = (3 * finegrafptr->velosum) / (2 * coarnbr) + 1; coarvertnbr = graphCoarsenFuncTab[coartype] (finegrafptr, finecoartax, coarvertmax, coarvelomax); /* Call proper matching function */ if (coarvertnbr >= coarvertmax) { /* If coarsened graph too large */ memFree (finecoartax + finegrafptr->baseval); /* Do not proceed any further */ return (1); } #ifdef SCOTCH_DEBUG_GRAPH2 for (finevertnum = finegrafptr->baseval; finevertnum < finegrafptr->vertnnd; finevertnum ++) { if (finecoartax[finevertnum] <= ~0) { /* If coarsening not aborted, this should not happen */ errorPrint ("graphCoarsen: internal error (1)"); memFree (finecoartax + finegrafptr->baseval); return (2); } } #endif /* SCOTCH_DEBUG_GRAPH2 */ memSet (coargrafptr, 0, sizeof (Graph)); /* Initialize coarse graph */ coargrafptr->flagval = GRAPHFREEVERT | GRAPHVERTGROUP | GRAPHEDGEGROUP; coargrafptr->baseval = finegrafptr->baseval; coargrafptr->vertnbr = coarvertnbr; coargrafptr->vertnnd = coarvertnbr + coargrafptr->baseval; coargrafptr->velosum = finegrafptr->velosum; /* Keep load of finer graph */ for (coarhashmsk = 31; coarhashmsk < finegrafptr->degrmax; coarhashmsk = coarhashmsk * 2 + 1) ; coarhashmsk = coarhashmsk * 4 + 3; coarhashnbr = coarhashmsk + 1; if (memAllocGroup ((void **) (void *) &coargrafptr->verttax, (size_t) ((coarvertnbr + 1) * sizeof (Gnum)), &coargrafptr->velotax, (size_t) (coarvertnbr * sizeof (Gnum)), &coarmulttax, (size_t) (coarvertnbr * sizeof (GraphCoarsenMulti)), &coargrafptr->edgetax, (size_t) (finegrafptr->edgenbr * sizeof (Gnum)), /* Pre-allocate space for edge arrays */ &coargrafptr->edlotax, (size_t) (finegrafptr->edgenbr * sizeof (Gnum)), &coarhashtab, (size_t) (coarhashnbr * sizeof (GraphCoarsenHash)), NULL) == NULL) { errorPrint ("graphCoarsen: out of memory (2)"); /* Allocate coarser graph structure */ memFree (finecoartax + finegrafptr->baseval); return (2); } coargrafptr->verttax -= coargrafptr->baseval; /* Base coarse graph arrays */ coargrafptr->velotax -= coargrafptr->baseval; coargrafptr->edgetax -= coargrafptr->baseval; coargrafptr->edlotax -= coargrafptr->baseval; coarmulttax -= coargrafptr->baseval; for (finevertnum = finegrafptr->baseval, coarvertnum = coargrafptr->baseval; /* Finalize finecoartab array */ finevertnum < finegrafptr->vertnnd; finevertnum ++) { Gnum finematenum; /* Number of current mate vertex */ finematenum = finecoartax[finevertnum]; /* Get mate number */ if (finematenum >= finevertnum) { /* If mate has larger number */ coarmulttax[coarvertnum].vertnum[0] = finevertnum; /* Build new multinode */ coarmulttax[coarvertnum].vertnum[1] = finematenum; /* Second index always biggest */ finecoartax[finematenum] = /* Point to coarse vertex */ finecoartax[finevertnum] = coarvertnum; /* Always valid since coarvertnum <= finevertnum */ coarvertnum ++; /* One more multinode created */ } } #ifdef SCOTCH_DEBUG_GRAPH2 if ((coarvertnum - coargrafptr->baseval) != coarvertnbr) { errorPrint ("graphCoarsen: internal error (2)"); graphFree (coargrafptr); memFree (finecoartax + finegrafptr->baseval); return (2); } #endif /* SCOTCH_DEBUG_GRAPH2 */ if (finegrafptr->velotax != NULL) { /* If fine graph is weighted */ for (coarvertnum = coargrafptr->baseval; coarvertnum < coargrafptr->vertnnd; coarvertnum ++) { Gnum coarveloval; coarveloval = finegrafptr->velotax[coarmulttax[coarvertnum].vertnum[0]]; if (coarmulttax[coarvertnum].vertnum[0] != coarmulttax[coarvertnum].vertnum[1]) coarveloval += finegrafptr->velotax[coarmulttax[coarvertnum].vertnum[1]]; coargrafptr->velotax[coarvertnum] = coarveloval; } } else { /* Fine graph is not weighted */ for (coarvertnum = coargrafptr->baseval; coarvertnum < coargrafptr->vertnnd; coarvertnum ++) coargrafptr->velotax[coarvertnum] = (coarmulttax[coarvertnum].vertnum[0] != coarmulttax[coarvertnum].vertnum[1]) ? 2 : 1; } memSet (coarhashtab, ~0, coarhashnbr * sizeof (GraphCoarsenHash)); if (finegrafptr->edlotax != NULL) /* If edge loads available */ graphCoarsenEdgeLl (finegrafptr, finecoartax, coarmulttax, coargrafptr, coarhashtab, coarhashmsk); else /* Fine edges not weighted */ graphCoarsenEdgeLu (finegrafptr, finecoartax, coarmulttax, coargrafptr, coarhashtab, coarhashmsk); coargrafptr->edgenbr = coargrafptr->verttax[coargrafptr->vertnnd] - coargrafptr->baseval; /* Set exact number of edges */ memFree (finecoartax + finegrafptr->baseval); coarvelooftval = coargrafptr->velotax - coargrafptr->verttax; coarmultoftval = (Gnum *) coarmulttax - coargrafptr->verttax; coaredgeoftval = coargrafptr->edgetax - coargrafptr->verttax; coaredlooftval = coargrafptr->edlotax - coargrafptr->verttax; memReallocGroup ((void *) (coargrafptr->verttax + coargrafptr->baseval), /* Re-allocate data, wiping temporary arrays */ &coargrafptr->verttax, (size_t) ((coarvertnbr + 1) * sizeof (Gnum)), &coargrafptr->velotax, (size_t) (coarvertnbr * sizeof (Gnum)), &coarmulttax, (size_t) (coarvertnbr * sizeof (GraphCoarsenMulti)), &coargrafptr->edgetax, (size_t) (finegrafptr->edgenbr * sizeof (Gnum)), &coargrafptr->edlotax, (size_t) (coargrafptr->edgenbr * sizeof (Gnum)), NULL); coargrafptr->verttax -= coargrafptr->baseval; coargrafptr->vendtax = coargrafptr->verttax + 1; /* Use compact representation of arrays */ coargrafptr->velotax = coargrafptr->verttax + coarvelooftval; coargrafptr->edgetax = coargrafptr->verttax + coaredgeoftval; coargrafptr->edlotax = coargrafptr->verttax + coaredlooftval; coarmulttax = (GraphCoarsenMulti *) (coargrafptr->verttax + coarmultoftval); *coarmultptr = coarmulttax; /* Return pointer to multinode array */ #ifdef SCOTCH_DEBUG_GRAPH2 if (graphCheck (coargrafptr) != 0) { /* Check graph consistency */ errorPrint ("graphCoarsen: inconsistent graph data"); graphFree (coargrafptr); return (2); } #endif /* SCOTCH_DEBUG_GRAPH2 */ return (0); } /****************************************/ /* */ /* The edge array building subroutines. */ /* */ /****************************************/ #define GRAPHCOARSENEDGENAME graphCoarsenEdgeLl #define GRAPHCOARSENEDGEINIT const Gnum * restrict const fineedlotax = finegrafptr->edlotax #define GRAPHCOARSENEDGEEDLOINIT coaredlotax[coaredgenum] = fineedlotax[fineedgenum] #define GRAPHCOARSENEDGEEDLOADD coaredlotax[coarhashtab[h].edgenum] += fineedlotax[fineedgenum] #define GRAPHCOARSENEDGEEDLOSUB coaredlosum -= finegrafptr->edlotax[fineedgenum] #include "graph_coarsen_edge.c" #undef GRAPHCOARSENEDGENAME #undef GRAPHCOARSENEDGEINIT #undef GRAPHCOARSENEDGEEDLOINIT #undef GRAPHCOARSENEDGEEDLOADD #undef GRAPHCOARSENEDGEEDLOSUB #define GRAPHCOARSENEDGENAME graphCoarsenEdgeLu #define GRAPHCOARSENEDGEINIT #define GRAPHCOARSENEDGEEDLOINIT coaredlotax[coaredgenum] = 1 #define GRAPHCOARSENEDGEEDLOADD coaredlotax[coarhashtab[h].edgenum] ++ #define GRAPHCOARSENEDGEEDLOSUB coaredlosum -- #include "graph_coarsen_edge.c" #undef GRAPHCOARSENEDGENAME #undef GRAPHCOARSENEDGEINIT #undef GRAPHCOARSENEDGEEDLOINIT #undef GRAPHCOARSENEDGEEDLOADD #undef GRAPHCOARSENEDGEEDLOSUB /*****************************/ /* */ /* The matching subroutines. */ /* */ /*****************************/ static Gnum graphCoarsenMatchHy ( const Graph * restrict const finegrafptr, /* Fine graph to perform matching on */ Gnum * restrict finecoartax, /* Fine to coarse vertex index array */ const Gnum coarvertmax, /* Maximum number of vertices to get */ const Gnum coarvelomax) /* Maximum vertex weight allowed */ { Gnum coarvertnum; /* Number of current multinode vertex */ Gnum finepertbas; /* Index of base of perturbation area */ Gnum finepertnbr; /* Size of perturbation area */ const Gnum * restrict fineverttax; /* Based access to vertex array */ const Gnum * restrict finevendtax; /* Based access to end vertex array */ const Gnum * restrict finevelotax; /* Based access to end vertex array */ const Gnum * restrict fineedgetax; /* Based access to end vertex array */ const Gnum * restrict fineedlotax; /* Based access to end vertex array */ Gnum finevertnnd; /* Current end of vertex array */ Gnum finevertnum; /* Number of currently selected fine vertex */ if (finegrafptr->edlotax == NULL) /* If no edge loads, perform scan matching instead */ return (graphCoarsenMatchSc (finegrafptr, finecoartax, coarvertmax, coarvelomax)); fineverttax = finegrafptr->verttax; finevendtax = finegrafptr->vendtax; finevelotax = finegrafptr->velotax; fineedgetax = finegrafptr->edgetax; fineedlotax = finegrafptr->edlotax; finevertnnd = finegrafptr->vertnnd; coarvertnum = 0; if (finegrafptr->velotax != NULL) { Gnum finevelodlt; /* Minimum load of neighbor */ finevelodlt = (3 * finegrafptr->velosum) / (5 * (finevertnnd - finegrafptr->baseval)); for (finevertnum = finegrafptr->baseval; /* Pre-selection loop for isolated and lightest vertices */ finevertnum < finevertnnd; finevertnum ++) { if (fineverttax[finevertnum] == finevendtax[finevertnum]) { /* If isolated vertex */ while (finecoartax[-- finevertnnd] != ~0) ; /* Search for first matchable "neighbor" */ finecoartax[finevertnum] = finevertnnd; /* At worst we will stop at finevertnum */ finecoartax[finevertnnd] = finevertnum; coarvertnum ++; /* One more coarse vertex created */ } else { /* Vertex has neighbors */ if ((finevelotax[finevertnum] < finevelodlt) && (finecoartax[finevertnum] == ~0)) { /* If vertex is too light on average */ Gnum finevertbst; /* Number of current best neighbor */ Gnum fineedlobst; /* Edge load of current best neighbor */ Gnum fineedgenum; if (coarvertnum >= coarvertmax) /* If coarse graph is too large */ return (coarvertmax); /* Return that we cannot coarsen more */ finevertbst = finevertnum; /* No matching neighbor found yet */ fineedlobst = 0; for (fineedgenum = fineverttax[finevertnum]; /* For all adjacent vertices */ fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { if ((finecoartax[fineedgetax[fineedgenum]] == ~0) && /* If unmatched vertex */ (fineedlotax[fineedgenum] > fineedlobst)) { /* And is better candidate */ fineedlobst = fineedlotax[fineedgenum]; finevertbst = fineedgetax[fineedgenum]; } } finecoartax[finevertnum] = finevertbst; finecoartax[finevertbst] = finevertnum; coarvertnum ++; /* One more coarse vertex created */ } } } } finepertnbr = 2 + intRandVal (GRAPHCOARPERTPRIME - 2); /* Compute perturbation area size (avoid DIV0 in random) */ for (finepertbas = finegrafptr->baseval; finepertbas < finevertnnd; /* Run cache-friendly perturbation */ finepertbas += finepertnbr) { Gnum finepertval; /* Current index in perturbation area */ if (finepertbas + finepertnbr > finevertnnd) finepertnbr = finevertnnd - finepertbas; finepertval = 0; /* Start from first perturbation vertex */ do { /* Loop on perturbation vertices */ finevertnum = finepertbas + finepertval; /* Compute corresponding vertex number */ if (finecoartax[finevertnum] == ~0) { /* If vertex has not been picked already */ Gnum finevertbst; /* Number of current best neighbor */ Gnum fineedlobst; /* Edge load of current best neighbor */ Gnum finevelodlt; /* Maximum load of neighbor */ Gnum fineedgenum; if (coarvertnum >= coarvertmax) /* If coarse graph too large */ return (coarvertmax); /* Return that cannot coarsen more */ finevertbst = finevertnum; /* No matching vertex found yet */ fineedlobst = 0; finevelodlt = coarvelomax - ((finevelotax != NULL) ? finevelotax[finevertnum] : 1); for (fineedgenum = fineverttax[finevertnum]; /* For all adjacent vertices */ fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { if ((finecoartax[fineedgetax[fineedgenum]] == ~0) && /* If unmatched vertex */ (fineedlotax[fineedgenum] > fineedlobst) && /* And better candidate */ ((finevelotax == NULL) || /* And does not create overloads */ (finevelodlt >= finevelotax[fineedgetax[fineedgenum]]))) { fineedlobst = fineedlotax[fineedgenum]; finevertbst = fineedgetax[fineedgenum]; } } finecoartax[finevertnum] = finevertbst; finecoartax[finevertbst] = finevertnum; coarvertnum ++; /* One more coarse vertex created */ } finepertval = (finepertval + GRAPHCOARPERTPRIME) % finepertnbr; /* Compute next perturbation index */ } while (finepertval != 0); } return (coarvertnum); /* Return number of coarse vertices */ } static Gnum graphCoarsenMatchSc ( const Graph * restrict const finegrafptr, /* Fine graph to perform matching on */ Gnum * restrict finecoartax, /* Fine to coarse vertex index array */ const Gnum coarvertmax, /* Maximum number of vertices to get */ const Gnum coarvelomax) /* Maximum vertex weight allowed */ { Gnum coarvertnum; /* Number of current multinode vertex */ Gnum finepertbas; /* Index of base of perturbation area */ const Gnum * restrict fineverttax; /* Based access to vertex array */ Gnum finepertnbr; /* Size of perturbation area */ Gnum finevertnnd; /* Current end of vertex array */ Gnum finevertnum; /* Number of currently selected fine vertex */ fineverttax = finegrafptr->verttax; coarvertnum = 0; for (finepertbas = finegrafptr->baseval, finevertnnd = finegrafptr->vertnnd; finepertbas < finevertnnd; finepertbas += finepertnbr) { /* Run cache-friendly perturbation */ Gnum finepertval; /* Current index in perturbation area */ finepertnbr = finegrafptr->degrmax * 2 + intRandVal (finegrafptr->degrmax + 1) + 1; /* Compute perturbation area size (avoid DIV0 in random) */ if (finepertnbr >= GRAPHCOARPERTPRIME) finepertnbr = 32 + intRandVal (GRAPHCOARPERTPRIME - 34); if (finepertbas + finepertnbr > finevertnnd) finepertnbr = finevertnnd - finepertbas; finepertval = 0; /* Start from first perturbation vertex */ do { /* Loop on perturbation vertices */ finevertnum = finepertbas + finepertval; /* Compute corresponding vertex number */ if (finecoartax[finevertnum] == ~0) { /* If vertex has not been picked already */ Gnum finevertbst; /* Number of current best matching vertex */ if (coarvertnum >= coarvertmax) /* If coarse graph is too large */ return (coarvertmax); /* Return that we cannot coarsen more */ if (fineverttax[finevertnum] == finegrafptr->vendtax[finevertnum]) { /* If isolated vertex */ while (finecoartax[-- finevertnnd] != ~0) ; /* Search for first matchable "neighbor" */ finevertbst = finevertnnd; /* Unmatched vertex will act as neighbor */ } else { /* Vertex has neighbors */ Gnum finevelodlt; /* Overload limit */ Gnum fineedgenum; /* Current edge number */ finevertbst = finevertnum; /* No matching vertex found yet */ finevelodlt = coarvelomax - ((finegrafptr->velotax != NULL) ? finegrafptr->velotax[finevertnum] : 1); for (fineedgenum = fineverttax[finevertnum]; /* For all adjacent vertices */ fineedgenum < finegrafptr->vendtax[finevertnum]; fineedgenum ++) { if ((finecoartax[finegrafptr->edgetax[fineedgenum]] == ~0) && /* If unmatched vertex */ ((finegrafptr->velotax == NULL) || /* And does not create overloads */ (finevelodlt >= finegrafptr->velotax[finegrafptr->edgetax[fineedgenum]]))) { finevertbst = finegrafptr->edgetax[fineedgenum]; break; } } } finecoartax[finevertnum] = finevertbst; finecoartax[finevertbst] = finevertnum; coarvertnum ++; /* One more coarse vertex created */ } finepertval = (finepertval + GRAPHCOARPERTPRIME) % finepertnbr; /* Compute next perturbation index */ } while (finepertval != 0); } return (coarvertnum); /* Return number of coarse vertices */ } static Gnum graphCoarsenMatchCs ( /* Crystallographic scan */ const Graph * restrict const finegrafptr, /* Fine graph to perform matching on */ Gnum * restrict finecoartax, /* Fine to coarse vertex index array */ const Gnum coarvertmax, /* Maximum number of vertices to get */ const Gnum coarvelomax) /* Maximum vertex weight allowed */ { Gnum coarvertnum; /* Number of current multinode vertex */ const Gnum * restrict fineverttax; /* Based access to vertex array */ const Gnum * restrict finevendtax; /* Based access to end vertex array */ const Gnum * restrict finevelotax; /* Based access to vertex load array */ const Gnum * restrict fineedgetax; /* Based access to edge array */ Gnum finevertnum; /* Number of currently selected fine vertex */ Gnum * restrict finequeutab; Gnum finequeuheadval; Gnum finequeutailval; Gnum finepermnum; /* Permutation number for finding connected components */ fineverttax = finegrafptr->verttax; finevendtax = finegrafptr->vendtax; finevelotax = finegrafptr->velotax; fineedgetax = finegrafptr->edgetax; if ((finequeutab = memAlloc (finegrafptr->vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("graphCoarsenMatchCs: out of memory"); return (graphCoarsenMatchSc (finegrafptr, finecoartax, coarvertmax, coarvelomax)); /* Fallback strategy */ } coarvertnum = 0; finequeuheadval = 1; finequeutailval = 0; finequeutab[0] = finegrafptr->baseval + intRandVal (finegrafptr->vertnbr); /* Start from random vertex */ finecoartax[finequeutab[0]] = -2; /* Set vertex as enqueued */ for (finepermnum = finegrafptr->baseval; finequeutailval < finegrafptr->vertnbr; ) { if (finequeutailval < finequeuheadval) { /* If vertices remain in queue */ Gnum finevertbst; /* Best vertex found till now */ Gnum finevelodlt; /* Overload limit */ Gnum fineedgenum; /* Current edge number */ finevertnum = finequeutab[finequeutailval ++]; /* Select a vertex from the queue */ if (finecoartax[finevertnum] >= 0) { /* If selected vertex already matched */ for (fineedgenum = fineverttax[finevertnum]; /* For all adjacent vertices */ fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { Gnum finevertend; finevertend = fineedgetax[fineedgenum]; if (finecoartax[finevertend] == ~0) { finequeutab[finequeuheadval ++] = finevertend; finecoartax[finevertend] = -2; } } continue; /* Skip to next vertex */ } if (coarvertnum >= coarvertmax) /* If coarse graph is too large */ break; /* Return that we cannot coarsen more */ finevertbst = finevertnum; /* No matching vertex found yet */ finevelodlt = coarvelomax - ((finegrafptr->velotax != NULL) ? finegrafptr->velotax[finevertnum] : 1); for (fineedgenum = fineverttax[finevertnum]; /* For all adjacent vertices */ fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { Gnum finevertend; Gnum finecoarval; finevertend = fineedgetax[fineedgenum]; finecoarval = finecoartax[finevertend]; if (finecoarval < 0) { /* If vertex not matched */ if (finecoartax[finevertend] == ~0) { /* If vertex not enqueued */ finequeutab[finequeuheadval ++] = finevertend; /* Enqueue it */ finecoartax[finevertend] = -2; } if ((finevelotax == NULL) || /* And does not create overloads */ (finevelodlt >= finevelotax[finevertend])) { finevertbst = finevertend; /* Get matching vertex */ while (++ fineedgenum < finevendtax[finevertnum]) { /* Scan and enqueue remaining neighbors */ finevertend = fineedgetax[fineedgenum]; if (finecoartax[finevertend] == ~0) { finequeutab[finequeuheadval ++] = finevertend; finecoartax[finevertend] = -2; } } } } } finecoartax[finevertnum] = finevertbst; /* Match both vertices */ finecoartax[finevertbst] = finevertnum; coarvertnum ++; /* One more coarse vertex created */ } else { /* Search for other connected component */ Gnum finevertbst; for ( ; finecoartax[finepermnum] >= 0; finepermnum ++) { /* Scan vertices in ascending order */ #ifdef SCOTCH_DEBUG_GRAPH2 if (finepermnum >= finegrafptr->vertnnd) { errorPrint ("graphCoarsenMatchCs: internal error (1)"); memFree (finequeutab); return (finegrafptr->vertnbr); /* Coarsening aborted */ } #endif /* SCOTCH_DEBUG_GRAPH2 */ } #ifdef SCOTCH_DEBUG_GRAPH2 if (finecoartax[finepermnum] != ~0) { errorPrint ("graphCoarsenMatchCs: internal error (2)"); memFree (finequeutab); return (finegrafptr->vertnbr); /* Coarsening aborted */ } #endif /* SCOTCH_DEBUG_GRAPH2 */ finevertnum = finepermnum ++; /* Start from found vertex */ if (fineverttax[finevertnum] != finevendtax[finevertnum]) { /* If vertex not isolated */ finequeutab[finequeuheadval ++] = finevertnum; /* Enqueue it for normal processing */ continue; /* Skip to main loop to process it */ } finequeuheadval = ++ finequeutailval; /* One more vertex enqueued-edqueued */ if (coarvertnum >= coarvertmax) /* If coarse graph is too large */ break; /* Return that we cannot coarsen more */ if (finequeutailval >= finegrafptr->vertnbr) /* If isolated vertex is last available vertex */ finevertbst = finevertnum; else { for ( ; finecoartax[finepermnum] >= 0; finepermnum ++) { #ifdef SCOTCH_DEBUG_GRAPH2 if (finepermnum >= finegrafptr->vertnnd) { errorPrint ("graphCoarsenMatchCs: internal error (3)"); memFree (finequeutab); return (finegrafptr->vertnbr); /* Coarsening aborted */ } #endif /* SCOTCH_DEBUG_GRAPH2 */ } #ifdef SCOTCH_DEBUG_GRAPH2 if (finecoartax[finepermnum] != ~0) { errorPrint ("graphCoarsenMatchCs: internal error (4)"); memFree (finequeutab); return (finegrafptr->vertnbr); /* Coarsening aborted */ } #endif /* SCOTCH_DEBUG_GRAPH2 */ finevertbst = finepermnum ++; /* Get found vertex */ finequeuheadval = ++ finequeutailval; /* One more vertex enqueued-edqueued */ } finecoartax[finevertnum] = finevertbst; /* Match both vertices */ finecoartax[finevertbst] = finevertnum; coarvertnum ++; /* One more coarse vertex created */ } } memFree (finequeutab); return (coarvertnum); /* Return number of coarse vertices */ } static Gnum graphCoarsenMatchCh ( /* Crystallographic heavy edge */ const Graph * restrict const finegrafptr, /* Fine graph to perform matching on */ Gnum * restrict finecoartax, /* Fine to coarse vertex index array */ const Gnum coarvertmax, /* Maximum number of vertices to get */ const Gnum coarvelomax) /* Maximum vertex weight allowed */ { Gnum coarvertnum; /* Number of current multinode vertex */ const Gnum * restrict fineverttax; /* Based access to vertex array */ const Gnum * restrict finevendtax; /* Based access to end vertex array */ const Gnum * restrict finevelotax; /* Based access to vertex load array */ const Gnum * restrict fineedgetax; /* Based access to edge array */ const Gnum * restrict fineedlotax; /* Based access to edge load array */ Gnum finevertnum; /* Number of currently selected fine vertex */ Gnum * restrict finequeutab; Gnum finequeuheadval; Gnum finequeutailval; Gnum finepermnum; /* Permutation number for finding connected components */ if (finegrafptr->edlotax == NULL) /* If no edge loads, perform scan matching instead */ return (graphCoarsenMatchCs (finegrafptr, finecoartax, coarvertmax, coarvelomax)); fineverttax = finegrafptr->verttax; finevendtax = finegrafptr->vendtax; finevelotax = finegrafptr->velotax; fineedgetax = finegrafptr->edgetax; fineedlotax = finegrafptr->edlotax; if ((finequeutab = memAlloc (finegrafptr->vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("graphCoarsenMatchCh: out of memory"); return (graphCoarsenMatchSc (finegrafptr, finecoartax, coarvertmax, coarvelomax)); /* Fallback strategy */ } coarvertnum = 0; finequeuheadval = 1; finequeutailval = 0; finequeutab[0] = finegrafptr->baseval + intRandVal (finegrafptr->vertnbr); /* Start from random vertex */ finecoartax[finequeutab[0]] = -2; /* Set vertex as enqueued */ for (finepermnum = finegrafptr->baseval; finequeutailval < finegrafptr->vertnbr; ) { if (finequeutailval < finequeuheadval) { /* If vertices remain in queue */ Gnum finevertbst; /* Best vertex found till now */ Gnum fineedlobst; /* Edge load of current best neighbor */ Gnum finevelodlt; /* Overload limit */ Gnum fineedgenum; /* Current edge number */ finevertnum = finequeutab[finequeutailval ++]; /* Select a vertex from the queue */ if (finecoartax[finevertnum] >= 0) { /* If selected vertex already matched */ for (fineedgenum = fineverttax[finevertnum]; /* For all adjacent vertices */ fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { Gnum finevertend; finevertend = fineedgetax[fineedgenum]; if (finecoartax[finevertend] == ~0) { finequeutab[finequeuheadval ++] = finevertend; finecoartax[finevertend] = -2; } } continue; /* Skip to next vertex */ } if (coarvertnum >= coarvertmax) /* If coarse graph is too large */ break; /* Return that we cannot coarsen more */ finevertbst = finevertnum; /* No matching vertex found yet */ fineedlobst = 0; finevelodlt = coarvelomax - ((finegrafptr->velotax != NULL) ? finegrafptr->velotax[finevertnum] : 1); for (fineedgenum = fineverttax[finevertnum]; /* For all adjacent vertices */ fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { Gnum finevertend; Gnum finecoarval; finevertend = fineedgetax[fineedgenum]; finecoarval = finecoartax[finevertend]; if (finecoarval < 0) { /* If vertex not matched */ Gnum fineedloval; fineedloval = fineedlotax[fineedgenum]; if (finecoartax[finevertend] == ~0) { /* If vertex not enqueued */ finequeutab[finequeuheadval ++] = finevertend; /* Enqueue it */ finecoartax[finevertend] = -2; } if (((finevelotax == NULL) || /* And does not create overloads */ (finevelodlt >= finevelotax[finevertend])) && (fineedloval > fineedlobst)) { finevertbst = finevertend; /* Get matching vertex */ fineedlobst = fineedloval; } } } finecoartax[finevertnum] = finevertbst; /* Match both vertices */ finecoartax[finevertbst] = finevertnum; coarvertnum ++; /* One more coarse vertex created */ } else { /* Search for other connected component */ Gnum finevertbst; for ( ; finecoartax[finepermnum] >= 0; finepermnum ++) { /* Scan vertices in ascending order */ #ifdef SCOTCH_DEBUG_GRAPH2 if (finepermnum >= finegrafptr->vertnnd) { errorPrint ("graphCoarsenMatchCh: internal error (1)"); memFree (finequeutab); return (finegrafptr->vertnbr); /* Coarsening aborted */ } #endif /* SCOTCH_DEBUG_GRAPH2 */ } #ifdef SCOTCH_DEBUG_GRAPH2 if (finecoartax[finepermnum] != ~0) { errorPrint ("graphCoarsenMatchCh: internal error (2)"); memFree (finequeutab); return (finegrafptr->vertnbr); /* Coarsening aborted */ } #endif /* SCOTCH_DEBUG_GRAPH2 */ finevertnum = finepermnum ++; /* Start from found vertex */ if (fineverttax[finevertnum] != finevendtax[finevertnum]) { /* If vertex not isolated */ finequeutab[finequeuheadval ++] = finevertnum; /* Enqueue it for normal processing */ continue; /* Skip to main loop to process it */ } finequeuheadval = ++ finequeutailval; /* One more vertex enqueued-edqueued */ if (coarvertnum >= coarvertmax) /* If coarse graph is too large */ break; /* Return that we cannot coarsen more */ if (finequeutailval >= finegrafptr->vertnbr) /* If isolated vertex is last available vertex */ finevertbst = finevertnum; else { for ( ; finecoartax[finepermnum] >= 0; finepermnum ++) { #ifdef SCOTCH_DEBUG_GRAPH2 if (finepermnum >= finegrafptr->vertnnd) { errorPrint ("graphCoarsenMatchCh: internal error (3)"); memFree (finequeutab); return (finegrafptr->vertnbr); /* Coarsening aborted */ } #endif /* SCOTCH_DEBUG_GRAPH2 */ } #ifdef SCOTCH_DEBUG_GRAPH2 if (finecoartax[finepermnum] != ~0) { errorPrint ("graphCoarsenMatchCh: internal error (4)"); memFree (finequeutab); return (finegrafptr->vertnbr); /* Coarsening aborted */ } #endif /* SCOTCH_DEBUG_GRAPH2 */ finevertbst = finepermnum ++; /* Get found vertex */ finequeuheadval = ++ finequeutailval; /* One more vertex enqueued-edqueued */ } finecoartax[finevertnum] = finevertbst; /* Match both vertices */ finecoartax[finevertbst] = finevertnum; coarvertnum ++; /* One more coarse vertex created */ } } memFree (finequeutab); return (coarvertnum); /* Return number of coarse vertices */ } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_stat.c0000644000175300017530000002637011631334325023333 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_stat.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the source **/ /** graph handling routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 23 jun 2007 **/ /** to 03 apr 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "dgraph.h" #include "library_dgraph_stat.h" #include "scotch.h" /* ** The static variables. */ static int dgraphstatblentab[2] = { 7, 3 }; static MPI_Datatype dgraphstattypetab[2] = { GNUM_MPI, MPI_DOUBLE }; /************************************/ /* */ /* These routines are the C API for */ /* the graph handling routines. */ /* */ /************************************/ /* This routine is the reduction-loc operator which ** returns in inout[2] the rank of the process which ** holds the best partition. ** It returns: ** - void : in all cases. */ static void dgraphStatReduceAll ( const DgraphStatData * const in, /* First operand */ DgraphStatData * const inout, /* Second and output operand */ const int * const len, /* Number of instances; should be 1, not used */ const MPI_Datatype * const typedat) /* MPI datatype; not used */ { if (inout->velomin > in->velomin) inout->velomin = in->velomin; if (inout->velomax < in->velomax) inout->velomax = in->velomax; if (inout->degrmin > in->degrmin) inout->degrmin = in->degrmin; if (inout->degrmax < in->degrmax) inout->degrmax = in->degrmax; if (inout->edlomin > in->edlomin) inout->edlomin = in->edlomin; if (inout->edlomax < in->edlomax) inout->edlomax = in->edlomax; inout->edlosum += in->edlosum; inout->velodlt += in->velodlt; inout->degrdlt += in->degrdlt; inout->edlodlt += in->edlodlt; } /*+ This routine computes statistics *** on the given distributed graph. *** It returns: *** - VOID : in all cases. +*/ int SCOTCH_dgraphStat ( const SCOTCH_Dgraph * const grafptr, SCOTCH_Num * const velominptr, SCOTCH_Num * const velomaxptr, SCOTCH_Num * const velosumptr, double * veloavgptr, double * velodltptr, SCOTCH_Num * const degrminptr, SCOTCH_Num * const degrmaxptr, double * degravgptr, double * degrdltptr, SCOTCH_Num * const edlominptr, SCOTCH_Num * const edlomaxptr, SCOTCH_Num * const edlosumptr, double * edloavgptr, double * edlodltptr) { const Dgraph * srcgrafptr; DgraphStatData srcgstadat; DgraphStatData srclstadat; MPI_Datatype srctypedat; MPI_Aint srcdisptab[2]; MPI_Op srcoperdat; Gnum vertlocnum; double veloglbavg; double velolocdlt; Gnum degrlocmin; Gnum degrlocmax; double degrglbavg; double degrlocdlt; Gnum edloglbsum; double edloglbavg; double edlolocdlt; int o; srcgrafptr = (Dgraph *) grafptr; velolocdlt = 0.0L; if (srcgrafptr->vertglbnbr > 0) { if (srcgrafptr->veloloctax != NULL) { /* If graph has vertex loads */ const Gnum * restrict veloloctax; Gnum velolocmin; Gnum velolocmax; veloloctax = srcgrafptr->veloloctax; velolocmin = GNUMMAX; velolocmax = 0; veloglbavg = (double) srcgrafptr->veloglbsum / (double) srcgrafptr->vertglbnbr; for (vertlocnum = srcgrafptr->baseval; vertlocnum < srcgrafptr->vertlocnnd; vertlocnum ++) { Gnum velolocval; velolocval = veloloctax[vertlocnum]; if (velolocval < velolocmin) velolocmin = velolocval; if (velolocval > velolocmax) velolocmax = velolocval; velolocdlt += fabs ((double) velolocval - veloglbavg); } srclstadat.velomin = velolocmin; srclstadat.velomax = velolocmax; } else { srclstadat.velomin = srclstadat.velomax = 1; veloglbavg = 1.0L; } } else { srclstadat.velomin = srclstadat.velomax = 0; veloglbavg = 0.0L; } srclstadat.velodlt = velolocdlt; degrlocmax = 0; degrlocdlt = 0.0L; if (srcgrafptr->vertglbnbr > 0) { degrlocmin = GNUMMAX; degrglbavg = (double) srcgrafptr->edgeglbnbr / (double) srcgrafptr->vertglbnbr; for (vertlocnum = srcgrafptr->baseval; vertlocnum < srcgrafptr->vertlocnnd; vertlocnum ++) { Gnum degrlocval; degrlocval = srcgrafptr->vendloctax[vertlocnum] - srcgrafptr->vertloctax[vertlocnum]; /* Get vertex degree */ if (degrlocval < degrlocmin) degrlocmin = degrlocval; if (degrlocval > degrlocmax) degrlocmax = degrlocval; degrlocdlt += fabs ((double) degrlocval - degrglbavg); } } else { degrlocmin = 0; degrglbavg = 0.0L; } srclstadat.degrmin = degrlocmin; srclstadat.degrmax = degrlocmax; srclstadat.degrdlt = degrlocdlt; edlolocdlt = 0.0L; if (srcgrafptr->edgeglbnbr > 0) { if (srcgrafptr->edloloctax != NULL) { /* If graph has edge loads */ Gnum edlolocmin; Gnum edlolocmax; Gnum edlolocsum; edlolocmin = GNUMMAX; edlolocmax = 0; edlolocsum = 0; for (vertlocnum = srcgrafptr->baseval; vertlocnum < srcgrafptr->vertlocnnd; vertlocnum ++) { Gnum edgelocnum; for (edgelocnum = srcgrafptr->vertloctax[vertlocnum]; edgelocnum < srcgrafptr->vendloctax[vertlocnum]; edgelocnum ++) { Gnum edlolocval; edlolocval = srcgrafptr->edloloctax[edgelocnum]; edlolocsum += edlolocval; if (edlolocval < edlolocmin) /* Account for edge load */ edlolocmin = edlolocval; if (edlolocval > edlolocmax) edlolocmax = edlolocval; } } if (MPI_Allreduce (&edlolocsum, &edloglbsum, 1, GNUM_MPI, MPI_SUM, srcgrafptr->proccomm) != MPI_SUCCESS) { errorPrint ("SCOTCH_dgraphStat: communication error (1)"); return (1); } edloglbavg = (double) edloglbsum / (double) (2 * srcgrafptr->edgeglbnbr); for (vertlocnum = srcgrafptr->baseval; vertlocnum < srcgrafptr->vertlocnnd; vertlocnum ++) { Gnum edgelocnum; for (edgelocnum = srcgrafptr->vertloctax[vertlocnum]; edgelocnum < srcgrafptr->vendloctax[vertlocnum]; edgelocnum ++) edlolocdlt += fabs ((double) srcgrafptr->edloloctax[edgelocnum] - edloglbavg); } } else { srclstadat.edlomin = srclstadat.edlomax = 1; edloglbsum = srcgrafptr->edgeglbnbr / 2; edloglbavg = 1.0L; } } else { srclstadat.edlomin = srclstadat.edlomax = 0; edloglbsum = 0; edloglbavg = 0.0L; } srclstadat.edlodlt = edlolocdlt; MPI_Address (&srclstadat.velomin, &srcdisptab[0]); MPI_Address (&srclstadat.velodlt, &srcdisptab[1]); srcdisptab[1] -= srcdisptab[0]; srcdisptab[0] -= srcdisptab[0]; o = 1; /* Assume something will go wrong */ if ((MPI_Type_struct (2, dgraphstatblentab, srcdisptab, dgraphstattypetab, &srctypedat) == MPI_SUCCESS) && (MPI_Type_commit (&srctypedat) == MPI_SUCCESS)) { if (MPI_Op_create ((MPI_User_function *) dgraphStatReduceAll, 0, &srcoperdat) == MPI_SUCCESS) { if (MPI_Allreduce (&srclstadat, &srcgstadat, 1, srctypedat, srcoperdat, srcgrafptr->proccomm) == MPI_SUCCESS) o = 0; MPI_Op_free (&srcoperdat); } MPI_Type_free (&srctypedat); } if (o != 0) { errorPrint ("SCOTCH_dgraphStat: communication error (2)"); return (1); } if (velominptr != NULL) *velominptr = (SCOTCH_Num) srcgstadat.velomin; if (velomaxptr != NULL) *velomaxptr = (SCOTCH_Num) srcgstadat.velomax; if (velosumptr != NULL) *velosumptr = (SCOTCH_Num) srcgrafptr->veloglbsum; if (veloavgptr != NULL) *veloavgptr = (double) veloglbavg; if (velodltptr != NULL) *velodltptr = srcgstadat.velodlt / (double) srcgrafptr->vertglbnbr; if (degrminptr != NULL) *degrminptr = (SCOTCH_Num) srcgstadat.degrmin; if (degrmaxptr != NULL) *degrmaxptr = (SCOTCH_Num) srcgstadat.degrmax; if (degravgptr != NULL) *degravgptr = (double) degrglbavg; if (degrdltptr != NULL) *degrdltptr = srcgstadat.degrdlt / (double) srcgrafptr->vertglbnbr; if (edlominptr != NULL) *edlominptr = (SCOTCH_Num) srcgstadat.edlomin; if (edlomaxptr != NULL) *edlomaxptr = (SCOTCH_Num) srcgstadat.edlomax; if (edlosumptr != NULL) *edlosumptr = (SCOTCH_Num) edloglbsum; if (edloavgptr != NULL) *edloavgptr = (double) edloglbavg; if (edlodltptr != NULL) *edlodltptr = srcgstadat.edlodlt / (double) srcgrafptr->edgeglbnbr; return (0); } scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_gg.h0000644000175300017530000001032411631334325022565 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_gg.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Luca SCARANO (v3.1) **/ /** **/ /** FUNCTION : This module contains the function **/ /** declarations for the greedy graph **/ /** growing bipartitioning method. **/ /** **/ /** DATES : # Version 3.1 : from : 07 jan 1996 **/ /** to 29 apr 1996 **/ /** # Version 3.2 : from : 20 sep 1996 **/ /** to 13 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 09 jan 2004 **/ /** to 09 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ System-defined constants. +*/ #define BGRAPHBIPARTGGGAINTABLSUBBITS 1 #define BGRAPHBIPARTGGSTATEFREE ((GainLink *) 0) /*+ Vertex in initial state (TRICK: must be 0) +*/ #define BGRAPHBIPARTGGSTATEUSED ((GainLink *) 1) /*+ Swapped vertex +*/ #define BGRAPHBIPARTGGSTATELINK ((GainLink *) 2) /*+ Currently in gain table if higher +*/ /* ** The type and structure definitions. */ /** Method parameters. **/ typedef struct BgraphBipartGgParam_ { INT passnbr; /*+ Number of passes to do +*/ } BgraphBipartGgParam; /*+ The complementary vertex structure. For trick reasons, the gain table data structure must be the first field of the structure. +*/ typedef struct BgraphBipartGgVertex_ { GainLink gainlink; /*+ Gain link: FIRST +*/ Gnum commgain0; /*+ Gain if vertex and neighbors in part 0 +*/ Gnum commgain; /*+ Gain value +*/ } BgraphBipartGgVertex; /* ** The function prototypes. */ #ifndef BGRAPH_BIPART_GG #define static #endif int bgraphBipartGg (Bgraph * restrict const, const BgraphBipartGgParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library.h0000644000175300017530000006101111631334325020747 0ustar hazelscthazelsct/* Copyright 2004,2007-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Declaration file for the LibScotch **/ /** static mapping and sparse matrix block **/ /** ordering library. **/ /** **/ /** DATES : # Version 3.2 : from : 07 sep 1996 **/ /** to 22 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to 31 may 1999 **/ /** # Version 3.4 : from : 10 oct 1999 **/ /** to 15 nov 2001 **/ /** # Version 4.0 : from : 11 dec 2001 **/ /** to 20 dec 2005 **/ /** # Version 5.0 : from : 26 apr 2006 **/ /** to : 20 feb 2008 **/ /** # Version 5.1 : from : 30 nov 2007 **/ /** to : 06 sep 2011 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ Version flags. +*/ #define SCOTCH_VERSION DUMMYVERSION #define SCOTCH_RELEASE DUMMYRELEASE #define SCOTCH_PATCHLEVEL DUMMYPATCHLEVEL /*+ Parallel processing flag. +*/ #ifndef SCOTCH_PTSCOTCH #define SCOTCH_DUMMYPTFLAG #endif /* SCOTCH_PTSCOTCH */ /*+ Integer type. +*/ typedef DUMMYIDX SCOTCH_Idx; typedef DUMMYINT SCOTCH_Num; #define SCOTCH_NUMMAX DUMMYMAXINT #define SCOTCH_NUMSTRING DUMMYNUMSTRING /*+ Strategy string parametrization values +*/ #define SCOTCH_STRATQUALITY 1 #define SCOTCH_STRATSPEED 2 #define SCOTCH_STRATBALANCE 4 #define SCOTCH_STRATSAFETY 8 #define SCOTCH_STRATSCALABILITY 16 /*+ Opaque objects. The dummy sizes of these objects, computed at compile-time by program "dummysizes", are given as double values for proper padding +*/ typedef struct { double dummy[DUMMYSIZEARCH]; } SCOTCH_Arch; #ifdef SCOTCH_PTSCOTCH typedef struct { double dummy[DUMMYSIZEDGRAPH]; } SCOTCH_Dgraph; typedef struct { double dummy[DUMMYSIZEDGRAPHHALOREQ]; } SCOTCH_DgraphHaloReq; typedef struct { double dummy[DUMMYSIZEDMAP]; } SCOTCH_Dmapping; typedef struct { double dummy[DUMMYSIZEDORDER]; } SCOTCH_Dordering; #endif /* SCOTCH_PTSCOTCH */ typedef struct { double dummy[DUMMYSIZEGEOM]; } SCOTCH_Geom; typedef struct { double dummy[DUMMYSIZEGRAPH]; } SCOTCH_Graph; typedef struct { double dummy[DUMMYSIZEMESH]; } SCOTCH_Mesh; typedef struct { double dummy[DUMMYSIZEMAP]; } SCOTCH_Mapping; typedef struct { double dummy[DUMMYSIZEORDER]; } SCOTCH_Ordering; typedef struct { double dummy[DUMMYSIZESTRAT]; } SCOTCH_Strat; /* ** The function prototypes. */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ SCOTCH_Arch * SCOTCH_archAlloc (void); int SCOTCH_archInit (SCOTCH_Arch * const); void SCOTCH_archExit (SCOTCH_Arch * const); int SCOTCH_archLoad (SCOTCH_Arch * const, FILE * const); int SCOTCH_archSave (const SCOTCH_Arch * const, FILE * const); int SCOTCH_archBuild (SCOTCH_Arch * const, const SCOTCH_Graph * const, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Strat * const); char * SCOTCH_archName (const SCOTCH_Arch * const); SCOTCH_Num SCOTCH_archSize (const SCOTCH_Arch * const); int SCOTCH_archVar (const SCOTCH_Arch * const); int SCOTCH_archCmplt (SCOTCH_Arch * const, const SCOTCH_Num); int SCOTCH_archCmpltw (SCOTCH_Arch * const, const SCOTCH_Num, const SCOTCH_Num * const); int SCOTCH_archHcub (SCOTCH_Arch * const, const SCOTCH_Num); int SCOTCH_archMesh2 (SCOTCH_Arch * const, const SCOTCH_Num, const SCOTCH_Num); int SCOTCH_archMesh3 (SCOTCH_Arch * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num); int SCOTCH_archTleaf (SCOTCH_Arch * const, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Num * const); int SCOTCH_archTorus2 (SCOTCH_Arch * const, const SCOTCH_Num, const SCOTCH_Num); int SCOTCH_archTorus3 (SCOTCH_Arch * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num); int SCOTCH_archVcmplt (SCOTCH_Arch * const); int SCOTCH_archVhcub (SCOTCH_Arch * const); #ifdef SCOTCH_PTSCOTCH SCOTCH_Dgraph * SCOTCH_dgraphAlloc (void); int SCOTCH_dgraphInit (SCOTCH_Dgraph * const, MPI_Comm); void SCOTCH_dgraphExit (SCOTCH_Dgraph * const); void SCOTCH_dgraphFree (SCOTCH_Dgraph * const); int SCOTCH_dgraphLoad (SCOTCH_Dgraph * const, FILE * const, const SCOTCH_Num, const SCOTCH_Num); int SCOTCH_dgraphSave (SCOTCH_Dgraph * const, FILE * const); int SCOTCH_dgraphCheck (const SCOTCH_Dgraph * const); int SCOTCH_dgraphBuild (SCOTCH_Dgraph * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, const SCOTCH_Num, const SCOTCH_Num, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); int SCOTCH_dgraphBuildGrid3D (SCOTCH_Dgraph * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const int); int SCOTCH_dgraphCoarsen (SCOTCH_Dgraph * const, SCOTCH_Dgraph * const, SCOTCH_Num * const, const SCOTCH_Num, const double); int SCOTCH_dgraphGather (const SCOTCH_Dgraph * const, SCOTCH_Graph * const); int SCOTCH_dgraphScatter (SCOTCH_Dgraph * const, const SCOTCH_Graph * const); void SCOTCH_dgraphSize (const SCOTCH_Dgraph * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); void SCOTCH_dgraphData (const SCOTCH_Dgraph * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, MPI_Comm * const); int SCOTCH_dgraphStat (const SCOTCH_Dgraph * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const); int SCOTCH_dgraphGhst (SCOTCH_Dgraph * const); int SCOTCH_dgraphHalo (SCOTCH_Dgraph * const, void * const, const MPI_Datatype); int SCOTCH_dgraphHaloAsync (SCOTCH_Dgraph * const, void * const, const MPI_Datatype, SCOTCH_DgraphHaloReq * const); SCOTCH_DgraphHaloReq * SCOTCH_dgraphHaloReqAlloc (void); int SCOTCH_dgraphHaloWait (SCOTCH_DgraphHaloReq * const); int SCOTCH_dgraphMapInit (const SCOTCH_Dgraph * const, SCOTCH_Dmapping * const, const SCOTCH_Arch * const, SCOTCH_Num * const); void SCOTCH_dgraphMapExit (const SCOTCH_Dgraph * const, SCOTCH_Dmapping * const); int SCOTCH_dgraphMapSave (const SCOTCH_Dgraph * const, const SCOTCH_Dmapping * const, FILE * const); int SCOTCH_dgraphMapView (SCOTCH_Dgraph * const, const SCOTCH_Dmapping * const, FILE * const); int SCOTCH_dgraphMapCompute (SCOTCH_Dgraph * const, SCOTCH_Dmapping * const, SCOTCH_Strat * const); int SCOTCH_dgraphMap (SCOTCH_Dgraph * const, const SCOTCH_Arch * const, SCOTCH_Strat * const, SCOTCH_Num * const); int SCOTCH_dgraphPart (SCOTCH_Dgraph * const, const SCOTCH_Num, SCOTCH_Strat * const, SCOTCH_Num * const); int SCOTCH_dgraphCorderInit (const SCOTCH_Dgraph * const, SCOTCH_Ordering * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); void SCOTCH_dgraphCorderExit (const SCOTCH_Dgraph * const, SCOTCH_Ordering * const); int SCOTCH_dgraphOrderInit (const SCOTCH_Dgraph * const, SCOTCH_Dordering * const); void SCOTCH_dgraphOrderExit (const SCOTCH_Dgraph * const, SCOTCH_Dordering * const); int SCOTCH_dgraphOrderSave (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const, FILE * const); int SCOTCH_dgraphOrderSaveBlock (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const, FILE * const); int SCOTCH_dgraphOrderSaveMap (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const, FILE * const); int SCOTCH_dgraphOrderSaveTree (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const, FILE * const); int SCOTCH_dgraphOrderPerm (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const, SCOTCH_Num * const); SCOTCH_Num SCOTCH_dgraphOrderCblkDist (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const); int SCOTCH_dgraphOrderTreeDist (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const, SCOTCH_Num * const, SCOTCH_Num * const); int SCOTCH_dgraphOrderCompute (SCOTCH_Dgraph * const, SCOTCH_Dordering * const, SCOTCH_Strat * const); int SCOTCH_dgraphOrderComputeList (SCOTCH_Dgraph * const, SCOTCH_Dordering * const, const SCOTCH_Num, const SCOTCH_Num * const, SCOTCH_Strat * const); int SCOTCH_dgraphOrderGather (const SCOTCH_Dgraph * const, const SCOTCH_Dordering * const, SCOTCH_Ordering * const); SCOTCH_Dmapping * SCOTCH_dmapAlloc (void); SCOTCH_Dordering * SCOTCH_dorderAlloc (void); #endif /* SCOTCH_PTSCOTCH */ void SCOTCH_errorProg (const char * const); void SCOTCH_errorPrint (const char * const, ...); void SCOTCH_errorPrintW (const char * const, ...); SCOTCH_Geom * SCOTCH_geomAlloc (void); int SCOTCH_geomInit (SCOTCH_Geom * const); void SCOTCH_geomExit (SCOTCH_Geom * const); void SCOTCH_geomData (const SCOTCH_Geom * const, SCOTCH_Num * const, double ** const); SCOTCH_Graph * SCOTCH_graphAlloc (void); int SCOTCH_graphInit (SCOTCH_Graph * const); void SCOTCH_graphExit (SCOTCH_Graph * const); void SCOTCH_graphFree (SCOTCH_Graph * const); int SCOTCH_graphLoad (SCOTCH_Graph * const, FILE * const, const SCOTCH_Num, const SCOTCH_Num); int SCOTCH_graphSave (const SCOTCH_Graph * const, FILE * const); int SCOTCH_graphBuild (SCOTCH_Graph * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Num * const); int SCOTCH_graphCoarsen (const SCOTCH_Graph * const, SCOTCH_Graph * const, SCOTCH_Num * const, const SCOTCH_Num, const double); SCOTCH_Num SCOTCH_graphBase (SCOTCH_Graph * const, const SCOTCH_Num baseval); int SCOTCH_graphCheck (const SCOTCH_Graph * const); void SCOTCH_graphSize (const SCOTCH_Graph * const, SCOTCH_Num * const, SCOTCH_Num * const); void SCOTCH_graphData (const SCOTCH_Graph * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num * const, SCOTCH_Num ** const, SCOTCH_Num ** const); void SCOTCH_graphStat (const SCOTCH_Graph * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const); int SCOTCH_graphGeomLoadChac (SCOTCH_Graph * const, SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); int SCOTCH_graphGeomLoadHabo (SCOTCH_Graph * const, SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); int SCOTCH_graphGeomLoadMmkt (SCOTCH_Graph * const, SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); int SCOTCH_graphGeomLoadScot (SCOTCH_Graph * const, SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); int SCOTCH_graphGeomSaveChac (const SCOTCH_Graph * const, const SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); int SCOTCH_graphGeomSaveMmkt (const SCOTCH_Graph * const, const SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); int SCOTCH_graphGeomSaveScot (const SCOTCH_Graph * const, const SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); int SCOTCH_graphMapInit (const SCOTCH_Graph * const, SCOTCH_Mapping * const, const SCOTCH_Arch * const, SCOTCH_Num * const); void SCOTCH_graphMapExit (const SCOTCH_Graph * const, SCOTCH_Mapping * const); int SCOTCH_graphMapLoad (const SCOTCH_Graph * const, const SCOTCH_Mapping * const, FILE * const); int SCOTCH_graphMapSave (const SCOTCH_Graph * const, const SCOTCH_Mapping * const, FILE * const); int SCOTCH_graphMapView (const SCOTCH_Graph * const, const SCOTCH_Mapping * const, FILE * const); int SCOTCH_graphMapCompute (SCOTCH_Graph * const, SCOTCH_Mapping * const, SCOTCH_Strat * const); int SCOTCH_graphMap (SCOTCH_Graph * const, const SCOTCH_Arch * const, SCOTCH_Strat * const, SCOTCH_Num * const); int SCOTCH_graphPart (SCOTCH_Graph * const, const SCOTCH_Num, SCOTCH_Strat * const, SCOTCH_Num * const); int SCOTCH_graphOrderInit (const SCOTCH_Graph * const, SCOTCH_Ordering * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); void SCOTCH_graphOrderExit (const SCOTCH_Graph * const, SCOTCH_Ordering * const); int SCOTCH_graphOrderLoad (const SCOTCH_Graph * const, SCOTCH_Ordering * const, FILE * const); int SCOTCH_graphOrderSave (const SCOTCH_Graph * const, const SCOTCH_Ordering * const, FILE * const); int SCOTCH_graphOrderSaveMap (const SCOTCH_Graph * const, const SCOTCH_Ordering * const, FILE * const); int SCOTCH_graphOrderSaveTree (const SCOTCH_Graph * const, const SCOTCH_Ordering * const, FILE * const); int SCOTCH_graphOrderCompute (SCOTCH_Graph * const, SCOTCH_Ordering * const, SCOTCH_Strat * const); int SCOTCH_graphOrderComputeList (SCOTCH_Graph * const, SCOTCH_Ordering * const, const SCOTCH_Num, const SCOTCH_Num * const, SCOTCH_Strat * const); int SCOTCH_graphOrderFactor (const SCOTCH_Graph * const, const SCOTCH_Ordering * const, SCOTCH_Graph * const); int SCOTCH_graphOrderView (const SCOTCH_Graph * const, const SCOTCH_Ordering * const, FILE * const); int SCOTCH_graphOrder (SCOTCH_Graph * const, SCOTCH_Strat * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); int SCOTCH_graphOrderList (SCOTCH_Graph * const, const SCOTCH_Num, const SCOTCH_Num * const, SCOTCH_Strat * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); int SCOTCH_graphOrderCheck (const SCOTCH_Graph * const, const SCOTCH_Ordering * const); SCOTCH_Mapping * SCOTCH_mapAlloc (void); void SCOTCH_memoryTrace (void); void SCOTCH_memoryUntrace (void); void SCOTCH_memoryTraceReset (void); unsigned long SCOTCH_memoryTraceGet (void); int SCOTCH_meshInit (SCOTCH_Mesh * const); void SCOTCH_meshExit (SCOTCH_Mesh * const); int SCOTCH_meshLoad (SCOTCH_Mesh * const, FILE * const, const SCOTCH_Num); int SCOTCH_meshSave (const SCOTCH_Mesh * const, FILE * const); int SCOTCH_meshBuild (SCOTCH_Mesh * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num * const, const SCOTCH_Num, const SCOTCH_Num * const); int SCOTCH_meshCheck (const SCOTCH_Mesh * const); void SCOTCH_meshSize (const SCOTCH_Mesh * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); void SCOTCH_meshData (const SCOTCH_Mesh * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num ** const, SCOTCH_Num * const, SCOTCH_Num ** const, SCOTCH_Num * const); void SCOTCH_meshStat (const SCOTCH_Mesh * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const, SCOTCH_Num * const, SCOTCH_Num * const, double * const, double * const); int SCOTCH_meshGraph (const SCOTCH_Mesh * const, SCOTCH_Graph * const); int SCOTCH_meshGeomLoadHabo (SCOTCH_Mesh * const, SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); int SCOTCH_meshGeomLoadScot (SCOTCH_Mesh * const, SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); int SCOTCH_meshGeomSaveScot (const SCOTCH_Mesh * const, const SCOTCH_Geom * const, FILE * const, FILE * const, const char * const); int SCOTCH_meshOrderInit (const SCOTCH_Mesh * const, SCOTCH_Ordering * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); void SCOTCH_meshOrderExit (const SCOTCH_Mesh * const, SCOTCH_Ordering * const); int SCOTCH_meshOrderSave (const SCOTCH_Mesh * const, const SCOTCH_Ordering * const, FILE * const); int SCOTCH_meshOrderSaveMap (const SCOTCH_Mesh * const, const SCOTCH_Ordering * const, FILE * const); int SCOTCH_meshOrderSaveTree (const SCOTCH_Mesh * const, const SCOTCH_Ordering * const, FILE * const); int SCOTCH_meshOrderCompute (SCOTCH_Mesh * const, SCOTCH_Ordering * const, SCOTCH_Strat * const); int SCOTCH_meshOrderComputeList (SCOTCH_Mesh * const, SCOTCH_Ordering * const, const SCOTCH_Num, const SCOTCH_Num * const, SCOTCH_Strat * const); int SCOTCH_meshOrder (SCOTCH_Mesh * const, SCOTCH_Strat * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); int SCOTCH_meshOrderList (SCOTCH_Mesh * const, const SCOTCH_Num, const SCOTCH_Num * const, SCOTCH_Strat * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const, SCOTCH_Num * const); int SCOTCH_meshOrderCheck (const SCOTCH_Mesh * const, const SCOTCH_Ordering * const); SCOTCH_Ordering * SCOTCH_orderAlloc (void); void SCOTCH_randomReset (void); SCOTCH_Strat * SCOTCH_stratAlloc (void); int SCOTCH_stratInit (SCOTCH_Strat * const); void SCOTCH_stratExit (SCOTCH_Strat * const); void SCOTCH_stratFree (SCOTCH_Strat * const); int SCOTCH_stratSave (const SCOTCH_Strat * const, FILE * const); #ifdef SCOTCH_PTSCOTCH int SCOTCH_stratDgraphMap (SCOTCH_Strat * const, const char * const); int SCOTCH_stratDgraphMapBuild (SCOTCH_Strat * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const double); int SCOTCH_stratDgraphClusterBuild (SCOTCH_Strat * const, const SCOTCH_Num, const SCOTCH_Num, const SCOTCH_Num, const double, const double); int SCOTCH_stratDgraphOrder (SCOTCH_Strat * const, const char * const); int SCOTCH_stratDgraphOrderBuild (SCOTCH_Strat * const, const SCOTCH_Num, const SCOTCH_Num, const double); #endif /* SCOTCH_PTSCOTCH */ int SCOTCH_stratGraphBipart (SCOTCH_Strat * const, const char * const); int SCOTCH_stratGraphMap (SCOTCH_Strat * const, const char * const); int SCOTCH_stratGraphMapBuild (SCOTCH_Strat * const, const SCOTCH_Num, const SCOTCH_Num, const double); int SCOTCH_stratGraphClusterBuild (SCOTCH_Strat * const, const SCOTCH_Num, const SCOTCH_Num, const double, const double); int SCOTCH_stratGraphOrder (SCOTCH_Strat * const, const char * const); int SCOTCH_stratGraphOrderBuild (SCOTCH_Strat * const, const SCOTCH_Num, const double); int SCOTCH_stratMeshOrder (SCOTCH_Strat * const, const char * const); int SCOTCH_stratMeshOrderBuild (SCOTCH_Strat * const, const SCOTCH_Num, const double); void SCOTCH_version (int * const, int * const, int * const); #ifdef __cplusplus } #endif /* __cplusplus */ scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_order_gather.c0000644000175300017530000001523311631334325025021 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_order_gather.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted ordering gathering routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 21 jul 2007 **/ /** to 04 aug 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "dgraph.h" #include "order.h" #include "dorder.h" #include "library_order.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the distributed ordering */ /* handling routines. */ /* */ /************************************/ /*+ This routine initializes an API centralized *** ordering with respect to the given distributed *** source graph and the locations of output parameters. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphCorderInit ( const SCOTCH_Dgraph * const grafptr, /*+ Distributed graph to order +*/ SCOTCH_Ordering * const cordptr, /*+ Ordering structure to initialize +*/ SCOTCH_Num * const permtab, /*+ Direct permutation array +*/ SCOTCH_Num * const peritab, /*+ Inverse permutation array +*/ SCOTCH_Num * const cblkptr, /*+ Pointer to number of column blocks +*/ SCOTCH_Num * const rangtab, /*+ Column block range array +*/ SCOTCH_Num * const treetab) /*+ Separator tree array +*/ { Dgraph * srcgrafptr; LibOrder * libcordptr; #ifdef SCOTCH_DEBUG_LIBRARY1 if (sizeof (SCOTCH_Ordering) < sizeof (LibOrder)) { errorPrint ("SCOTCH_dgraphCorderInit: internal error"); return (1); } #endif /* SCOTCH_DEBUG_LIBRARY1 */ srcgrafptr = (Dgraph *) grafptr; /* Use structure as distributed source graph */ libcordptr = (LibOrder *) cordptr; libcordptr->permtab = ((permtab == NULL) || ((void *) permtab == (void *) grafptr)) ? NULL : (Gnum *) permtab; libcordptr->peritab = ((peritab == NULL) || ((void *) peritab == (void *) grafptr)) ? NULL : (Gnum *) peritab; libcordptr->cblkptr = ((cblkptr == NULL) || ((void *) cblkptr == (void *) grafptr)) ? NULL : (Gnum *) cblkptr; libcordptr->rangtab = ((rangtab == NULL) || ((void *) rangtab == (void *) grafptr)) ? NULL : (Gnum *) rangtab; libcordptr->treetab = ((treetab == NULL) || ((void *) treetab == (void *) grafptr)) ? NULL : (Gnum *) treetab; return (orderInit (&libcordptr->o, srcgrafptr->baseval, srcgrafptr->vertglbnbr, libcordptr->peritab)); } /*+ This routine frees an API centralized ordering. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_dgraphCorderExit ( const SCOTCH_Dgraph * const grafptr, SCOTCH_Ordering * const cordptr) { orderExit (&((LibOrder *) cordptr)->o); } /*+ This routine gathers the contents of *** the given distributed ordering into the *** given centralized ordering. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphOrderGather ( const SCOTCH_Dgraph * const grafptr, /*+ Not used +*/ const SCOTCH_Dordering * const dordptr, /*+ Distributed ordering +*/ SCOTCH_Ordering * const cordptr) /*+ Centralized ordering +*/ { LibOrder * libcordptr; /* Pointer to ordering */ if ((cordptr != NULL) && ((void *) cordptr != (void *) dordptr)) { /* If potential root process */ libcordptr = (LibOrder *) cordptr; /* Get centralized ordering */ if (dorderGather ((Dorder *) dordptr, &libcordptr->o) != 0) return (1); if (libcordptr->permtab != NULL) /* Build direct permutation if wanted */ orderPeri (libcordptr->o.peritab, libcordptr->o.baseval, libcordptr->o.vnodnbr, libcordptr->permtab, libcordptr->o.baseval); if (libcordptr->rangtab != NULL) /* Build range array if column block data wanted */ orderRang (&libcordptr->o, libcordptr->rangtab); if (libcordptr->treetab != NULL) /* Build separator tree array if wanted */ orderTree (&libcordptr->o, libcordptr->treetab); if (libcordptr->cblkptr != NULL) /* Set number of column blocks if wanted */ *(libcordptr->cblkptr) = libcordptr->o.cblknbr; return (0); } else return (dorderGather ((Dorder *) dordptr, NULL)); } scotch-5.1.12b.dfsg/src/libscotch/vmesh.c0000644000175300017530000000765211631334325020433 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the separator **/ /** handling routines. **/ /** **/ /** DATES : # Version 4.0 : from : 06 feb 2003 **/ /** to 05 mar 2003 **/ /** # Version 5.1 : from : 09 nov 2008 **/ /** to 09 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VMESH #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" #include "vmesh.h" /*************************/ /* */ /* These routines handle */ /* separator meshes. */ /* */ /*************************/ /* This routine frees the contents ** of the given active mesh. ** It returns: ** - VOID : in all cases. */ void vmeshExit ( Vmesh * const meshptr) { if (meshptr->parttax != NULL) /* Free leader of group (parttab + frontab) */ memFree (meshptr->parttax + meshptr->m.baseval); meshFree (&meshptr->m); /* Free source mesh */ #ifdef SCOTCH_DEBUG_VMESH2 memSet (meshptr, ~0, sizeof (Vmesh)); #endif /* SCOTCH_DEBUG_VMESH2 */ } /* This routine moves all of the mesh ** elements to the first part. ** It returns: ** - VOID : in all cases. */ void vmeshZero ( Vmesh * const meshptr) { memSet (meshptr->parttax + meshptr->m.baseval, 0, (meshptr->m.velmnbr + meshptr->m.vnodnbr) * sizeof (GraphPart)); meshptr->ecmpsize[0] = meshptr->m.velmnbr; meshptr->ecmpsize[1] = 0; meshptr->ncmpload[0] = meshptr->m.vnlosum; meshptr->ncmpload[1] = meshptr->ncmpload[2] = 0; meshptr->ncmploaddlt = meshptr->m.vnlosum; meshptr->ncmpsize[0] = meshptr->m.vnodnbr; meshptr->ncmpsize[1] = meshptr->fronnbr = 0; } scotch-5.1.12b.dfsg/src/libscotch/arch_vcmplt.c0000644000175300017530000001726111631334325021610 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_vcmplt.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the variable-sized **/ /** complete graph target architecture. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 23 dec 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 29 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 16 aug 1995 **/ /** # Version 3.1 : from : 20 jul 1996 **/ /** to 20 jul 1996 **/ /** # Version 3.2 : from : 15 oct 1996 **/ /** to 14 may 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 3.4 : from : 14 sep 2001 **/ /** to 08 nov 2001 **/ /** # Version 4.0 : from : 05 nov 2003 **/ /** to 05 nov 2003 **/ /** # Version 5.1 : from : 21 jan 2008 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ARCH_VCMPLT #include "module.h" #include "common.h" #include "arch.h" #include "arch_vcmplt.h" /*****************************************/ /* */ /* These are the variable-sized complete */ /* graph handling routines. */ /* */ /*****************************************/ /* This function returns the smallest number ** of terminal domain included in the given ** domain. */ ArchDomNum archVcmpltDomNum ( const ArchVcmplt * const archptr, const ArchVcmpltDom * const domptr) { return (domptr->termnum); /* Return terminal number */ } /* This function returns the terminal domain associated ** with the given terminal number in the architecture. ** It returns: ** - 0 : if label is valid and domain has been updated. ** - 1 : if label is invalid. ** - 2 : on error. */ int archVcmpltDomTerm ( const ArchVcmplt * const archptr, ArchVcmpltDom * const domptr, const ArchDomNum domnum) { if (domnum != ARCHDOMNOTTERM) { /* If valid label */ domptr->termnum = domnum; /* Set the domain */ return (0); } return (1); /* Cannot set domain */ } /* This function returns the number of ** elements in the domain. */ Anum archVcmpltDomSize ( const ArchVcmplt * const archptr, const ArchVcmpltDom * const domptr) { return (1); /* All domains have same size for bipartitioning */ } /* This function returns the average ** distance between two subdomains. */ Anum archVcmpltDomDist ( const ArchVcmplt * const archptr, const ArchVcmpltDom * const dom0ptr, const ArchVcmpltDom * const dom1ptr) { return ((dom0ptr->termnum == dom1ptr->termnum) ? 0 : 1); /* All distinct terminals are at distance 1 */ } /* This function sets the biggest ** domain available for this ** architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archVcmpltDomFrst ( const ArchVcmplt * const archptr, ArchVcmpltDom * restrict const domptr) { domptr->termnum = 1; /* First terminal number */ return (0); } /* This routine reads domain information ** from the given stream. ** It returns: ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archVcmpltDomLoad ( const ArchVcmplt * const archptr, ArchVcmpltDom * restrict const domptr, FILE * const stream) { if (intLoad (stream, &domptr->termnum) != 1) { errorPrint ("archVcmpltDomLoad: bad input"); return (1); } return (0); } /* This routine saves domain information ** to the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archVcmpltDomSave ( const ArchVcmplt * const archptr, const ArchVcmpltDom * const domptr, FILE * const stream) { if (fprintf (stream, ANUMSTRING " ", (Anum) domptr->termnum) == EOF) { errorPrint ("archVcmpltDomSave: bad output"); return (1); } return (0); } /* This function splits a domain ** into two subdomains. ** It returns: ** - 0 : if bipartitioning succeeded. ** - 2 : on error. */ int archVcmpltDomBipart ( const ArchVcmplt * const archptr, const ArchVcmpltDom * const domptr, ArchVcmpltDom * restrict const dom0ptr, ArchVcmpltDom * restrict const dom1ptr) { dom0ptr->termnum = domptr->termnum << 1; dom1ptr->termnum = dom0ptr->termnum + 1; return ((dom1ptr->termnum < domptr->termnum) ? 2 : 0); /* Return error on overflow */ } /* This function creates the MPI_Datatype for ** variable-sized complete graph domains. ** It returns: ** - 0 : if type could be created. ** - 1 : on error. */ #ifdef SCOTCH_PTSCOTCH int archVcmpltDomMpiType ( const ArchVcmplt * const archptr, MPI_Datatype * const typeptr) { *typeptr = ANUM_MPI; return (0); } #endif /* SCOTCH_PTSCOTCH */ scotch-5.1.12b.dfsg/src/libscotch/vmesh_separate_gg.h0000644000175300017530000001137211631334325022773 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh_separate_gg.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the the greedy mesh growing node **/ /** separation method. **/ /** **/ /** DATES : # Version 4.0 : from : 16 sep 2002 **/ /** to 07 apr 2004 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ System-defined constants. +*/ #define VMESHSEPAGGSUBBITS 4 #define VMESHSEPAGGSTATEPART0 ((GainLink *) 0) /*+ Element vertex in part 0 (initial state) +*/ #define VMESHSEPAGGSTATEPART1 ((GainLink *) 1) /*+ Element vertex in part 1 +*/ #define VMESHSEPAGGSTATEPART2 ((GainLink *) 2) /*+ Element vertex in part 2, chained +*/ #define VMESHSEPAGGSTATELINK ((GainLink *) 3) /*+ Currently in gain table if higher +*/ /* ** The type and structure definitions. */ /*+ Method parameters. +*/ typedef struct VmeshSeparateGgParam_ { INT passnbr; /*+ Number of passes to perform +*/ } VmeshSeparateGgParam; /*+ The complementary element vertex structure. For trick reasons, the gain table data structure must be the first field of the structure. +*/ typedef struct VmeshSeparateGgElem_ { GainLink gainlink; /*+ Gain link: FIRST +*/ Gnum ncmpgain2; /*+ Computation gain in separator: (0->2) - (2->1) +*/ Gnum ncmpgaindlt; /*+ Overall computation delta: - (0->2) - (2->1) +*/ } VmeshSeparateGgElem; /*+ The complementary vertex structure. Only partval is always valid. Other fields are valid only when vertex belongs to separator. +*/ typedef struct VmeshSeparateGgNode_ { int partval; /*+ Part to which node vertex belongs +*/ Gnum commsize0; /*+ Number of neighbors in part 0 +*/ Gnum velmisum0; /*+ Sum of all element indices in part 0; the last one is the right one +*/ } VmeshSeparateGgNode; /* ** The function prototypes. */ #ifndef VMESH_SEPARATE_GG #define static #endif int vmeshSeparateGg (Vmesh * restrict const, const VmeshSeparateGgParam * restrict const); #ifdef SCOTCH_DEBUG_VMESH3 static int vmeshSeparateGgCheck (Vmesh * restrict const, const Gnum, const Gnum, const VmeshSeparateGgElem * restrict const, const VmeshSeparateGgNode * restrict const vnoxtax); #endif /* SCOTCH_DEBUG_VMESH3 */ #undef static scotch-5.1.12b.dfsg/src/libscotch/library_geom_f.c0000644000175300017530000000772111631334325022266 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_geom_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the graph geometry handling routines **/ /** of the libSCOTCH library. **/ /** **/ /** DATES : # Version 4.0 : from : 15 jun 2005 **/ /** to 22 dec 2005 **/ /** # Version 5.1 : from : 15 apr 2010 **/ /** to 15 apr 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /******************************************/ /* */ /* These routines are the Fortran API for */ /* the graph geometry handling routines. */ /* */ /******************************************/ /* ** */ FORTRAN ( \ SCOTCHFGEOMINIT, scotchfgeominit, ( \ SCOTCH_Geom * const geomptr, \ int * const revaptr), \ (geomptr, revaptr)) { *revaptr = SCOTCH_geomInit (geomptr); } /* ** */ FORTRAN ( \ SCOTCHFGEOMEXIT, scotchfgeomexit, ( \ SCOTCH_Geom * const geomptr), \ (geomptr)) { SCOTCH_geomExit (geomptr); } /* ** */ FORTRAN ( \ SCOTCHFGEOMDATA, scotchfgeomdata, ( \ const SCOTCH_Geom * const geomptr, \ const double * const indxptr, \ SCOTCH_Num * const dimnptr, \ SCOTCH_Idx * const geomidx), \ (geomptr, indxptr, dimnptr, geomidx)) { double * geomtab; SCOTCH_geomData (geomptr, dimnptr, &geomtab); *geomidx = (geomtab - indxptr) + 1; /* Add 1 since Fortran indices start at 1 */ } scotch-5.1.12b.dfsg/src/libscotch/hmesh.c0000644000175300017530000001067511631334325020414 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the halo source **/ /** mesh functions. **/ /** **/ /** DATES : # Version 4.0 : from : 12 sep 2002 **/ /** to 10 feb 2003 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" #include "hmesh.h" /****************************************/ /* */ /* These routines handle source meshes. */ /* */ /****************************************/ /* This routine frees a source halo mesh structure. ** It returns: ** - VOID : in all cases. */ void hmeshExit ( Hmesh * const meshptr) { if ((meshptr->vehdtax != NULL) && /* Exit halo mesh data */ (meshptr->vehdtax != (meshptr->m.vendtax + (meshptr->m.baseval - meshptr->m.velmbas))) && ((meshptr->m.flagval & MESHVERTGROUP) == 0)) memFree (meshptr->vehdtax + meshptr->m.velmbas); meshExit (&meshptr->m); /* Exit mesh data */ #ifdef SCOTCH_DEBUG_HMESH2 memSet (meshptr, ~0, sizeof (Hmesh)); /* Purge halo mesh fields */ #endif /* SCOTCH_DEBUG_HMESH2 */ } /* This routine sets the base of the given ** halo mesh to the given base value, and ** returns the old base value. ** It returns: ** - old base value : in all cases. */ Gnum hmeshBase ( Hmesh * const meshptr, const Gnum baseval) { Gnum baseold; /* Old base value */ Gnum baseadj; /* Base adjustment */ Gnum velmnum; if (meshptr->m.baseval == baseval) /* If nothing to do */ return (baseval); baseold = meshptr->m.baseval; /* Record old base value */ baseadj = baseval - baseold; /* Compute adjustment */ meshBase (&meshptr->m, baseval); /* Change base of mesh */ for (velmnum = meshptr->m.velmbas; velmnum < meshptr->m.velmnnd; velmnum ++) meshptr->vehdtax[velmnum] += baseadj; /* Change base of array */ meshptr->vnohnnd += baseadj; meshptr->vehdtax -= baseadj; return (baseold); /* Return old base value */ } scotch-5.1.12b.dfsg/src/libscotch/vdgraph_gather_all.c0000644000175300017530000002311711631334325023120 0ustar hazelscthazelsct/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_gather_all.c **/ /** **/ /** AUTHORS : Cedric CHEVALIER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the routine which **/ /** builds a centralized Vgraph on all **/ /** processes by gathering the pieces of a **/ /** distributed Vdgraph. **/ /** **/ /** DATES : # Version 5.0 : from : 29 apr 2006 **/ /** to 01 mar 2008 **/ /** # Version 5.1 : from : 18 apr 2009 **/ /** to 30 jul 2010 **/ /** **/ /** NOTES : # The definitions of MPI_Gather and **/ /** MPI_Gatherv indicate that elements in **/ /** the receive array should not be **/ /** written more than once. Great care **/ /** should be taken to enforce this rule, **/ /** especially when the number of **/ /** vertices in the centralized graph is **/ /** smaller than the number of **/ /** processes. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VDGRAPH #include "module.h" #include "common.h" #include "comm.h" #include "graph.h" #include "vgraph.h" #include "dgraph.h" #include "vdgraph.h" /* This function gathers on all processes ** the pieces of a distributed Vdgraph to ** build a centralized Vgraph. ** It returns: ** - 0 : if graph data are consistent. ** - !0 : on error. */ int vdgraphGatherAll ( const Vdgraph * restrict const dgrfptr, /* Distributed graph */ Vgraph * restrict cgrfptr) /* Centralized graph */ { int * restrict froncnttab; /* Count array for gather operations */ int * restrict frondsptab; /* Displacement array for gather operations */ int fronlocnbr; /* Also int to enforce MPI standard */ int cheklocval; #ifdef SCOTCH_DEBUG_VDGRAPH1 int chekglbval; #endif /* SCOTCH_DEBUG_VDGRAPH1 */ int procnum; cheklocval = 0; #ifdef SCOTCH_DEBUG_VDGRAPH1 if (cgrfptr == NULL) /* Centralized graphs should be provided by all */ cheklocval = 1; if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphGatherAll: communication error (1)"); return (1); } if (chekglbval != 0) { errorPrint ("vdgraphGatherAll: centralized graphs should be provided on every process"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH1 */ if (dgraphGatherAll (&dgrfptr->s, &cgrfptr->s) != 0) { errorPrint ("vdgraphGatherAll: cannot build centralized graph"); return (1); } cgrfptr->parttax = NULL; /* In case of error */ cgrfptr->frontab = NULL; if (((cgrfptr->parttax = (GraphPart *) memAlloc (cgrfptr->s.vertnbr * sizeof (GraphPart))) == NULL) || ((cgrfptr->parttax -= cgrfptr->s.baseval, cgrfptr->frontab = (Gnum *) memAlloc (cgrfptr->s.vertnbr * sizeof (Gnum))) == NULL)) { errorPrint ("vdgraphGatherAll: out of memory (1)"); #ifndef SCOTCH_DEBUG_VDGRAPH1 vgraphExit (cgrfptr); return (1); } #else /* SCOTCH_DEBUG_VDGRAPH1 */ cheklocval = 1; } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphGatherAll: communication error (2)"); return (1); } if (chekglbval != 0) { vgraphExit (cgrfptr); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH1 */ cgrfptr->levlnum = dgrfptr->levlnum; /* Set level of separation graph as level of halo graph */ if (dgrfptr->partgsttax == NULL) { /* If distributed graph does not have a part array yet */ vgraphZero (cgrfptr); return (0); } if (memAllocGroup ((void **) (void *) /* Allocate tempory arrays to gather separator vertices */ &froncnttab, (size_t) (dgrfptr->s.procglbnbr * sizeof (int)), &frondsptab, (size_t) (dgrfptr->s.procglbnbr * sizeof (int)), NULL) == NULL) { errorPrint ("vdgraphGatherAll: out of memory (2)"); #ifndef SCOTCH_DEBUG_VDGRAPH1 vgraphExit (cgrfptr); return (1); } #else /* SCOTCH_DEBUG_VDGRAPH1 */ cheklocval = 1; } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphGatherAll: communication error (3)"); return (1); } if (chekglbval != 0) { if (froncnttab != NULL) memFree (froncnttab); vgraphExit (cgrfptr); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH1 */ if (commAllgatherv (dgrfptr->partgsttax + dgrfptr->s.baseval, dgrfptr->s.vertlocnbr, GRAPHPART_MPI, /* Get parttax of distributed graph */ cgrfptr->parttax, dgrfptr->s.proccnttab, dgrfptr->s.procdsptab, GRAPHPART_MPI, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphGatherAll: communication error (4)"); return (1); } fronlocnbr = (int) dgrfptr->complocsize[2]; if (MPI_Allgather (&fronlocnbr, 1, MPI_INT, /* Compute how separator vertices are distributed */ froncnttab, 1, MPI_INT, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphGatherAll: communication error (5)"); return (1); } frondsptab[0] = 0; /* Offset 0 for first process */ for (procnum = 1; procnum < dgrfptr->s.procglbnbr; procnum ++) /* Adjust index sub-arrays for all processes except the first one */ frondsptab[procnum] = frondsptab[procnum - 1] + froncnttab[procnum - 1]; if (MPI_Allgatherv (dgrfptr->fronloctab, fronlocnbr, GNUM_MPI, /* Gather separator vertices */ cgrfptr->frontab, froncnttab, frondsptab, GNUM_MPI, dgrfptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphGatherAll: communication error (6)"); return (1); } for (procnum = 1; procnum < dgrfptr->s.procglbnbr; procnum ++) { /* Adjust index sub-arrays for all processes except the first one */ Gnum vertnum; Gnum vertnnd; for (vertnum = (Gnum) frondsptab[procnum], vertnnd = vertnum + (Gnum) froncnttab[procnum]; vertnum < vertnnd; vertnum ++) cgrfptr->frontab[vertnum] += (Gnum) dgrfptr->s.procdsptab[procnum] - dgrfptr->s.baseval; } memFree (froncnttab); /* Free group leader */ for (procnum = 0; procnum < dgrfptr->s.proclocnum; procnum ++) /* Desynchronize random generators across processes */ cheklocval = intRandVal (2); intPerm (cgrfptr->frontab, dgrfptr->compglbsize[2]); /* Compute permutation of frontier array to have different solutions on every process */ cgrfptr->compload[0] = dgrfptr->compglbload[0]; /* Update other fields */ cgrfptr->compload[1] = dgrfptr->compglbload[1]; cgrfptr->compload[2] = dgrfptr->compglbload[2]; cgrfptr->comploaddlt = dgrfptr->compglbloaddlt; cgrfptr->compsize[0] = dgrfptr->compglbsize[0]; cgrfptr->compsize[1] = dgrfptr->compglbsize[1]; cgrfptr->fronnbr = dgrfptr->compglbsize[2]; #ifdef SCOTCH_DEBUG_VDGRAPH2 if (vgraphCheck (cgrfptr) != 0) { errorPrint ("vdgraphGatherAll: internal error"); vgraphExit (cgrfptr); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_gg.h0000644000175300017530000000777311631334325023152 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_gg.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the greedy graph growing vertex **/ /** separation method. **/ /** **/ /** DATES : # Version 3.2 : from : 14 nov 1997 **/ /** to 15 jul 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 19 dec 2001 **/ /** to 09 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ System-defined constants. +*/ #define VGRAPHSEPAGGSUBBITS 4 #define VGRAPHSEPAGGSTATEPART0 ((GainLink *) 0) /*+ Vertex in part 0 (initial state) +*/ #define VGRAPHSEPAGGSTATEPART1 ((GainLink *) 1) /*+ Vertex in part 1 +*/ #define VGRAPHSEPAGGSTATEPART2 ((GainLink *) 2) /*+ Vertex in part 2, chained +*/ #define VGRAPHSEPAGGSTATELINK ((GainLink *) 3) /*+ Currently in gain table if higher +*/ /* ** The type and structure definitions. */ /*+ Method parameters. +*/ typedef struct VgraphSeparateGgParam_ { INT passnbr; /*+ Number of passes to do +*/ } VgraphSeparateGgParam; /*+ The complementary vertex structure. For trick reasons, the gain table data structure must be the first field of the structure. +*/ typedef struct VgraphSeparateGgVertex_ { GainLink gainlink; /*+ Gain link: FIRST +*/ Gnum compgain2; /*+ Computation gain in separator +*/ } VgraphSeparateGgVertex; /* ** The function prototypes. */ #ifndef VGRAPH_SEPARATE_GG #define static #endif int vgraphSeparateGg (Vgraph * restrict const, const VgraphSeparateGgParam * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_graph_io_scot.c0000644000175300017530000001023511631334325023644 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_io_scot.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the Scotch **/ /** geometry and graph handling routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 3.4 : from : 10 oct 1999 **/ /** to 01 nov 2001 **/ /** # Version 4.0 : from : 18 dec 2001 **/ /** to 19 jan 2004 **/ /** # Version 5.1 : from : 27 apr 2010 **/ /** to 27 apr 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "geom.h" #include "graph.h" #include "scotch.h" /*************************************/ /* */ /* These routines are the C API for */ /* the Scotch graph and geometry */ /* handling routines. */ /* */ /*************************************/ /*+ This routine loads the given opaque graph *** structure with the data of the given stream. *** - 0 : if loading succeeded. *** - !0 : on error. +*/ int SCOTCH_graphGeomLoadScot ( SCOTCH_Graph * restrict const grafptr, SCOTCH_Geom * restrict const geomptr, FILE * const filegrfptr, FILE * const filegeoptr, const char * const dataptr) { return (graphGeomLoadScot ((Graph *) grafptr, (Geom *) geomptr, filegrfptr, filegeoptr, dataptr)); } /*+ This routine saves the contents of the given *** opaque graph structure to the given stream. *** It returns: *** - 0 : if the saving succeeded. *** - !0 : on error. +*/ int SCOTCH_graphGeomSaveScot ( const SCOTCH_Graph * restrict const grafptr, const SCOTCH_Geom * restrict const geomptr, FILE * const filegrfptr, FILE * const filegeoptr, const char * const dataptr) { return (graphGeomSaveScot ((Graph *) grafptr, (Geom *) geomptr, filegrfptr, filegeoptr, dataptr)); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_cp.c0000644000175300017530000006010711631334325022264 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_cp.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module performs compession of mesh **/ /** nodes, by merging nodes having the same **/ /** adjacency structure. **/ /** **/ /** DATES : # Version 4.0 : from : 08 feb 2004 **/ /** to 05 jan 2005 **/ /** # Version 5.0 : from : 25 jul 2007 **/ /** to : 12 sep 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH_ORDER_CP #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "order.h" #include "mesh.h" #include "hmesh.h" #include "hmesh_order_cp.h" #include "hmesh_order_st.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hmeshOrderCp ( const Hmesh * restrict const finemeshptr, Order * restrict const fineordeptr, const Gnum ordenum, /*+ Zero-based ordering number +*/ OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ const HmeshOrderCpParam * restrict const paraptr) { Hmesh coarmeshdat; /* Compressed halo submesh */ Order coarordedat; /* Ordering of compressed halo submesh */ Gnum * restrict coarperitab; /* Coarse permutation array */ const Gnum * restrict coarperitax; /* Temporary based access to coarperitab */ Gnum coarvertnum; /* Number of current compressed vertex */ Gnum * restrict coarvsiztax; /* Array of coarse vertex sizes (as number of merged fine vertices) */ Gnum coaredgenum; /* Number of current compressed edge */ Gnum * restrict coarvpostax; /* Position in fine permutation of fine vertices merged into same vertex */ Gnum coarvnodmax; Gnum coarvertmax; Gnum * restrict finecoartax; /* Original to compressed vertex number array */ HmeshOrderCpHash * restrict finehashtab; /* Neighbor hash table */ Gnum finehashmsk; /* Mask for access to hash table */ int * restrict finehasptab; /* Pre-hashing table */ Gnum finehaspmsk; /* Mask for access to pre-hashing table */ Gnum * restrict finehsumtax; /* Array of hash values for each original vertex */ Gnum finevertnbr; /* Number of fine vertices in compressed elimination tree */ Gnum finevsizsum; /* Sum of compressed vertex sizes to build fine inverse permutation */ Gnum coarvsizsiz; /* Size of array of sizes of coarse nodes */ Gnum coarvelmnbr; /* Number of coarse element vertices */ Gnum * restrict coarverttax; Gnum * restrict coarvnlotax; Gnum * restrict coaredgetax; Gnum * restrict coarfinetax; Gnum finevnodnum; Gnum coarvnodnbr; Gnum finevelmnum; Gnum coarvnodnnd; Gnum coardegrmax; Gnum coarvnodnum; if (finemeshptr->vnohnbr != finemeshptr->m.vnodnbr) { errorPrint ("hmeshOrderCp: halo meshes not supported yet"); return (1); } coarvelmnbr = finemeshptr->m.velmnbr; /* To date, keep isolated elements */ coarvnodmax = (Gnum) ((double) finemeshptr->vnohnbr * paraptr->comprat) + (finemeshptr->m.vnodnbr - finemeshptr->vnohnbr); coarvertmax = coarvnodmax + coarvelmnbr; coarvsizsiz = (finemeshptr->m.vnlotax == NULL) ? 0 : coarvnodmax; for (finehashmsk = 15; /* Set neighbor hash table size */ finehashmsk < finemeshptr->m.degrmax; finehashmsk = finehashmsk * 2 + 1) ; finehashmsk = finehashmsk * 4 + 3; /* Fill hash table at 1/4 of capacity */ if (memAllocGroup ((void **) (void *) &coarverttax, (size_t) ((coarvertmax + 1) * sizeof (Gnum)), &coarvsiztax, (size_t) (coarvsizsiz * sizeof (Gnum)), /* TRICK: if no vertex loads, coarvsiztax points to coarvnodtax */ &coarvnlotax, (size_t) (coarvnodmax * sizeof (Gnum)), /* Only change node weights */ &finecoartax, (size_t) (finemeshptr->m.vnodnbr * sizeof (Gnum)), &coaredgetax, (size_t) (finemeshptr->m.edgenbr * sizeof (Gnum)), &finehsumtax, (size_t) (finemeshptr->m.vnodnbr * sizeof (Gnum)), &finehashtab, (size_t) ((finehashmsk + 1) * sizeof (HmeshOrderCpHash)), &coarperitab, (size_t) (coarvnodmax * sizeof (Gnum)), /* TODO: move after resize */ &coarfinetax, (size_t) (coarvnodmax * sizeof (Gnum)), NULL) == NULL) { errorPrint ("hmeshOrderCp: out of memory (1)"); return (1); } /* TODO : resize after success */ finehsumtax -= finemeshptr->m.vnodbas; /* TRICK: do not base finecoartax yet (see later) */ finehasptab = (int *) finecoartax; /* Use finecoartab as temporary pre-hash table */ for (finehaspmsk = 1; /* Get pre-hash mask that fits in finecoartab */ finehaspmsk <= finemeshptr->m.vnodnbr; /* Smallest (2^i)-1 value > vertnbr */ finehaspmsk = finehaspmsk * 2 + 1) ; finehaspmsk >>= 1; /* Ensure masked data will always fit into finecoartab array */ finehaspmsk = (finehaspmsk * (sizeof (Gnum) / sizeof (int))) + ((sizeof (Gnum) / sizeof (int)) - 1); if (finehaspmsk >= ((sizeof (int) << (3 + 1)) - 1)) /* Only use 1/8 of array for pre-hashing, for increased cache locality */ finehaspmsk >>= 3; memSet (finehasptab, 0, (finehaspmsk + 1) * sizeof (int)); /* Initialize pre-hash table */ for (finevnodnum = finemeshptr->m.vnodbas, coarvnodnbr = finemeshptr->m.vnodnbr; /* For all non-halo node vertices */ finevnodnum < finemeshptr->vnohnnd; finevnodnum ++) { Gnum fineenodnum; /* Current edge number */ Gnum finehsumval; /* Hash sum value */ Gnum finehsumbit; for (fineenodnum = finemeshptr->m.verttax[finevnodnum], finehsumval = 0; fineenodnum < finemeshptr->m.vendtax[finevnodnum]; fineenodnum ++) finehsumval += finemeshptr->m.edgetax[fineenodnum]; finehsumtax[finevnodnum] = finehsumval; finehsumbit = finehsumval & ((sizeof (int) << 3) - 1); /* Get bit mask and byte position (division should be optimized into a shift) */ finehsumval /= (sizeof (int) << 3); finehsumval &= finehaspmsk; /* Make hash sum value fit into finehasptab */ coarvnodnbr -= (finehasptab[finehsumval] >> finehsumbit) & 1; /* If hash value already in pre-hash table, maybe one more vertex compressed */ finehasptab[finehsumval] |= (1 << finehsumbit); /* Put value into pre-hash table anyway */ } if (coarvnodnbr > coarvnodmax) { /* If mesh needs not be compressed */ memFree (coarverttax); /* Group leader not yet based */ return (hmeshOrderSt (finemeshptr, fineordeptr, ordenum, cblkptr, paraptr->stratunc)); } memSet (finecoartax, ~0, finemeshptr->m.vnodnbr * sizeof (Gnum)); memSet (&coarmeshdat, 0, sizeof (Hmesh)); /* Initialize compressed halo mesh structure */ coarmeshdat.m.flagval = MESHFREEVERT | MESHVERTGROUP; /* Free only coarverttab as group leader */ coarmeshdat.m.baseval = finemeshptr->m.baseval; coarmeshdat.m.velmbas = coarmeshdat.m.baseval; coarmeshdat.m.velmnbr = coarvelmnbr; /* Mesh compression does not touch elements, apart from isolated elements */ coarmeshdat.m.velmnnd = coarmeshdat.m.vnodbas = coarvelmnbr + coarmeshdat.m.baseval; coarmeshdat.m.veisnbr = finemeshptr->m.veisnbr; /* To date, keep all isolated element vertices, if any */ coarmeshdat.m.velosum = finemeshptr->m.velosum; coarmeshdat.m.vnlosum = finemeshptr->m.vnlosum; coarverttax -= coarmeshdat.m.baseval; coarvsiztax -= coarmeshdat.m.vnodbas; /* TRICK: if no vertex loads, coarvsiztax points to coarvnodtax */ coarvnlotax -= coarmeshdat.m.vnodbas; coaredgetax -= coarmeshdat.m.baseval; finecoartax -= finemeshptr->m.vnodbas; coarmeshdat.m.verttax = coarverttax; coarmeshdat.m.vendtax = coarverttax + 1; /* Use compact representation of arrays */ coarmeshdat.m.velotax = finemeshptr->m.velotax; /* Re-use element vertex load array, if any */ coarmeshdat.m.vnlotax = coarvnlotax; coarmeshdat.m.edgetax = coaredgetax; coarfinetax -= coarmeshdat.m.vnodbas; memSet (finehashtab, ~0, (finehashmsk + 1) * sizeof (HmeshOrderCpHash)); for (finevelmnum = finemeshptr->m.velmbas, coarvertnum = coaredgenum = coarmeshdat.m.baseval, /* Build element arrays */ coarvnodnnd = coarmeshdat.m.baseval + finemeshptr->m.velmnbr, coardegrmax = 0; finevelmnum < finemeshptr->m.velmnnd; finevelmnum ++) { Gnum fineeelmnum; Gnum coardegrval; fineeelmnum = finemeshptr->m.verttax[finevelmnum]; #ifdef DEAD_CODE if (fineeelmnum == finemeshptr->m.vendtax[finevelmnum]) /* Skip isolated elements */ continue; #endif #ifdef SCOTCH_DEBUG_ORDER2 if (coarvertnum >= coarmeshdat.m.velmnnd) { /* If too many elements declared */ errorPrint ("hmeshOrderCp: internal error (1)"); /* Maybe problem with veisnbr */ return (1); } #endif /* SCOTCH_DEBUG_ORDER2 */ coarverttax[coarvertnum] = coaredgenum; for ( ; fineeelmnum < finemeshptr->m.vendtax[finevelmnum]; fineeelmnum ++) { Gnum finevnodnum; Gnum coarvnodnum; finevnodnum = finemeshptr->m.edgetax[fineeelmnum]; coarvnodnum = finecoartax[finevnodnum]; if (coarvnodnum != ~0) { /* If fine node already considered */ if (coarvnodnum >= 0) /* If node is leader of cluster */ coaredgetax[coaredgenum ++] = coarvnodnum; /* Add it to coarse mesh */ } else { /* Fine node not yet considered */ Gnum finehsumval; Gnum finedegrval; Gnum fineeelmngb; Gnum coarvsizval; /* Number of fine node vertices in coarse node vertex */ if (coarvnodnnd >= (coarvnodmax + coarmeshdat.m.vnodbas)) { /* If mesh needs not be compressed */ memFree (coarverttax + coarmeshdat.m.baseval); return (hmeshOrderSt (finemeshptr, fineordeptr, ordenum, cblkptr, paraptr->stratunc)); } coarvsizval = 1; /* Cluster leader it at least alone */ coarvnodnum = coarvnodnnd ++; /* Node is leader of future cluster */ finecoartax[finevnodnum] = coarvnodnum; /* Record node as cluster leader */ coaredgetax[coaredgenum ++] = coarvnodnum; /* Add leader to coarse mesh */ coarfinetax[coarvnodnum] = finevnodnum; /* Record node to build edge sub-array */ finehsumval = finehsumtax[finevnodnum]; /* Get hash sum of cluster leader */ finedegrval = finemeshptr->m.vendtax[finevnodnum] - finemeshptr->m.verttax[finevnodnum]; for (fineeelmngb = fineeelmnum + 1; /* For all remaining edges of current element */ fineeelmngb < finemeshptr->m.vendtax[finevelmnum]; fineeelmngb ++) { Gnum finevnodngb; Gnum fineenodngb; finevnodngb = finemeshptr->m.edgetax[fineeelmngb]; /* Get index of neighboring node */ if ((finecoartax[finevnodngb] != ~0) || /* If node has already been processed or */ (finehsumval != finehsumtax[finevnodngb]) || /* If hash sum does not match, skip node */ (finedegrval != (finemeshptr->m.vendtax[finevnodngb] - finemeshptr->m.verttax[finevnodngb]))) continue; if (finehashtab[(finevelmnum * HMESHORDERCPHASHPRIME) & finehashmsk].vnodnum != finevnodnum) { /* If hash table not yet filled */ Gnum fineenodnum; for (fineenodnum = finemeshptr->m.verttax[finevnodnum]; fineenodnum < finemeshptr->m.vendtax[finevnodnum]; fineenodnum ++) { Gnum finevelmend; Gnum finehelmend; finevelmend = finemeshptr->m.edgetax[fineenodnum]; for (finehelmend = (finevelmend * HMESHORDERCPHASHPRIME) & finehashmsk; finehashtab[finehelmend].vnodnum == finevnodnum; finehelmend = (finehelmend + 1) & finehashmsk) ; finehashtab[finehelmend].vnodnum = finevnodnum; /* Fill hash table with node adjacency */ finehashtab[finehelmend].velmnum = finevelmend; } } for (fineenodngb = finemeshptr->m.verttax[finevnodngb]; fineenodngb < finemeshptr->m.vendtax[finevnodngb]; fineenodngb ++) { Gnum finevelmngb; Gnum finehelmngb; finevelmngb = finemeshptr->m.edgetax[fineenodngb]; for (finehelmngb = (finevelmngb * HMESHORDERCPHASHPRIME) & finehashmsk; ; finehelmngb = (finehelmngb + 1) & finehashmsk) { if (finehashtab[finehelmngb].vnodnum != finevnodnum) /* If adjacencies differ, break */ goto loop_failed; if (finehashtab[finehelmngb].velmnum == finevelmngb) /* If neighbor found, process next neighbor */ break; } } finecoartax[finevnodngb] = -2 - coarvnodnum; /* Set index of cluster non-leader */ coarvsizval ++; /* One more non-leader in cluster */ loop_failed: ; } coarvsiztax[coarvnodnum] = coarvsizval; } } coardegrval = coaredgenum - coarverttax[coarvertnum]; if (coardegrval > coardegrmax) coardegrmax = coardegrval; coarvertnum ++; /* One more coarse element created */ } #ifdef SCOTCH_DEBUG_ORDER2 if (coarvertnum != coarmeshdat.m.velmnnd) { /* If too many elements declared */ errorPrint ("hmeshOrderCp: internal error (2)"); /* Maybe problem with veisnbr */ return (1); } #endif /* SCOTCH_DEBUG_ORDER2 */ coarmeshdat.m.vnodnnd = coarvnodnnd; coarmeshdat.m.vnodnbr = coarvnodnnd - coarmeshdat.m.vnodbas; #ifdef SCOTCH_DEBUG_ORDER2 for (finevnodnum = finemeshptr->m.vnodbas; finevnodnum < finemeshptr->m.vnodnnd; finevnodnum ++) { if (finecoartax[finevnodnum] == ~0) { errorPrint ("hmeshOrderCp: internal error (3)"); return (1); } } #endif /* SCOTCH_DEBUG_ORDER2 */ for ( ; coarvertnum < coarmeshdat.m.vnodnnd; coarvertnum ++) { /* Build node arrays */ Gnum finevnodnum; Gnum fineenodnum; Gnum coardegrval; coarverttax[coarvertnum] = coaredgenum; finevnodnum = coarfinetax[coarvertnum]; coardegrval = finemeshptr->m.vendtax[finevnodnum] - finemeshptr->m.verttax[finevnodnum]; for (fineenodnum = finemeshptr->m.verttax[finevnodnum]; fineenodnum < finemeshptr->m.vendtax[finevnodnum]; fineenodnum ++) coaredgetax[coaredgenum ++] = finemeshptr->m.edgetax[fineenodnum] - (finemeshptr->m.velmbas - coarmeshdat.m.velmbas); if (coardegrval > coardegrmax) coardegrmax = coardegrval; } coarverttax[coarvertnum] = coaredgenum; /* Set end of vertex array */ coarmeshdat.m.edgenbr = coaredgenum - coarmeshdat.m.baseval; coarmeshdat.m.degrmax = coardegrmax; coarmeshdat.vnohnbr = coarmeshdat.m.vnodnbr; /* Halo meshes not yet supported */ coarmeshdat.vnohnnd = coarmeshdat.m.vnodnnd; coarmeshdat.vehdtax = coarmeshdat.m.vendtax; /* Only element part of vendtab will be accessed through vehdtab */ coarmeshdat.vnhlsum = coarmeshdat.m.vnlosum; coarmeshdat.enohnbr = coarmeshdat.m.edgenbr; if (finemeshptr->m.vnlotax != NULL) { /* If fine mesh has node vertex loads */ memSet (coarmeshdat.m.vnlotax + coarmeshdat.m.vnodbas, 0, coarmeshdat.m.vnodnbr * sizeof (Gnum)); for (finevnodnum = finemeshptr->m.vnodbas; finevnodnum < finemeshptr->m.vnodnnd; finevnodnum ++) { /* Compute vertex loads for compressed mesh */ coarmeshdat.m.vnlotax[finecoartax[finevnodnum]] += finemeshptr->m.vnlotax[finevnodnum]; } } #ifdef SCOTCH_DEBUG_ORDER2 if (hmeshCheck (&coarmeshdat) != 0) { errorPrint ("hmeshOrderCp: internal error (4)"); hmeshExit (&coarmeshdat); return (1); } #endif /* SCOTCH_DEBUG_ORDER2 */ orderInit (&coarordedat, coarmeshdat.m.baseval, coarmeshdat.m.vnodnbr, coarperitab); /* Build ordering of compressed submesh */ if (hmeshOrderSt (&coarmeshdat, &coarordedat, 0, &coarordedat.cblktre, paraptr->stratcpr) != 0) { hmeshExit (&coarmeshdat); return (1); } coarvsiztax += (coarmeshdat.m.vnodbas - coarmeshdat.m.baseval); /* Adjust array to match permutation bounds */ *cblkptr = coarordedat.cblktre; /* Link sub-tree to ordering */ coarordedat.cblktre.cblktab = NULL; /* Unlink sub-tree from sub-ordering */ finevertnbr = hmeshOrderCpTree (coarordedat.peritab, /* Expand sub-tree */ coarvsiztax, cblkptr, 0); #ifdef SCOTCH_DEBUG_ORDER2 if (finevertnbr != finemeshptr->m.vnodnbr) { errorPrint ("hmeshOrderCp: internal error (5)"); hmeshExit (&coarmeshdat); return (1); } #endif /* SCOTCH_DEBUG_ORDER2 */ fineordeptr->treenbr += coarordedat.cblknbr; /* Adjust number of tree nodes */ fineordeptr->cblknbr += coarordedat.cblknbr - 1; /* Adjust number of column blocks */ coarvpostax = coarmeshdat.m.verttax; /* Recycle verttab (not velotab as may be merged with coarvsiztab) */ coarperitax = coarperitab - coarmeshdat.m.vnodbas; for (coarvnodnum = coarmeshdat.m.vnodbas, finevsizsum = 0; /* Compute initial indices for inverse permutation expansion */ coarvnodnum < coarmeshdat.m.vnodnnd; coarvnodnum ++) { coarvpostax[coarperitax[coarvnodnum]] = finevsizsum; finevsizsum += coarvsiztax[coarperitax[coarvnodnum]]; } coarvpostax = coarmeshdat.m.verttax + (coarmeshdat.m.baseval - coarmeshdat.m.vnodbas); for (finevnodnum = finemeshptr->m.vnodbas; finevnodnum < finemeshptr->m.vnodnnd; finevnodnum ++) { /* Compute fine permutation */ Gnum coarvnodnum; coarvnodnum = finecoartax[finevnodnum]; /* Get index of corresponding coarse node */ if (coarvnodnum < 0) /* If node is not cluster leader */ coarvnodnum = -2 - coarvnodnum; /* Get index of cluster leader */ fineordeptr->peritab[coarvpostax[coarvnodnum] ++] = finevnodnum + (finemeshptr->m.baseval - finemeshptr->m.vnodbas); } orderExit (&coarordedat); hmeshExit (&coarmeshdat); return (0); } /* This routine turns the coarse elimination ** tree produced by the ordering of the coarse ** mesh into a fine elimination tree, according ** to the cardinality of the coarse vertices. ** It returns: ** - !0 : overall number of fine vertices, in all cases. */ static Gnum hmeshOrderCpTree ( const Gnum * restrict const coarperitab, /* Coarse inverse permutation */ const Gnum * restrict const coarvsiztax, /* Array of fine sizes of coarse vertices */ OrderCblk * restrict const coficblkptr, /* Current coarse/fine column block cell */ Gnum coarordenum) /* Compressed vertex to start expansion at */ { Gnum finevertnbr; /* Number of fine vertices in subtree */ finevertnbr = 0; /* No fine vertices yet */ if (coficblkptr->cblktab == NULL) { /* If leaf of column block tree */ Gnum coarvnumnum; for (coarvnumnum = coarordenum; coarvnumnum < coarordenum + coficblkptr->vnodnbr; coarvnumnum ++) finevertnbr += coarvsiztax[coarperitab[coarvnumnum]]; /* Sum-up fine vertices */ } else { Gnum coarvertnbr; /* Number of coarse vertices in cell */ Gnum coarvertsum; /* Number of coarse vertices in subtree */ Gnum coficblknum; /* Index in column block array */ for (coficblknum = 0, coarvertsum = coarordenum; /* Start at current coarse index */ coficblknum < coficblkptr->cblknbr; coficblknum ++) { coarvertnbr = coficblkptr->cblktab[coficblknum].vnodnbr; /* Save number of coarse vertices */ finevertnbr += hmeshOrderCpTree (coarperitab, coarvsiztax, &coficblkptr->cblktab[coficblknum], coarvertsum); coarvertsum += coarvertnbr; /* Sum-up coarse vertices */ } } coficblkptr->vnodnbr = finevertnbr; /* Set number of fine vertices */ return (finevertnbr); /* Return accumulated number */ } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_order_io_f.c0000644000175300017530000000735211631334325024466 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_order_io_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** distributed ordering I/O routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 26 jul 2007 **/ /** to 18 oct 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the ordering routines. */ /* */ /**************************************/ FORTRAN ( \ SCOTCHFDGRAPHORDERSAVEMAP, scotchfdgraphordersavemap, ( \ const SCOTCH_Dgraph * const grafptr, \ const SCOTCH_Dordering * const ordeptr, \ FILE * const stream, \ int * const revaptr), \ (grafptr, ordeptr, stream, revaptr)) { *revaptr = SCOTCH_dgraphOrderSaveMap (grafptr, ordeptr, stream); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHORDERSAVETREE, scotchfdgraphordersavetree, ( \ const SCOTCH_Dgraph * const grafptr, \ const SCOTCH_Dordering * const ordeptr, \ FILE * const stream, \ int * const revaptr), \ (grafptr, ordeptr, stream, revaptr)) { *revaptr = SCOTCH_dgraphOrderSaveTree (grafptr, ordeptr, stream); } scotch-5.1.12b.dfsg/src/libscotch/mesh_io.c0000644000175300017530000004125011631334325020724 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mesh_io.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the source graph **/ /** input/output functions. **/ /** **/ /** DATES : # Version 4.0 : from : 05 nov 2002 **/ /** to 06 may 2004 **/ /** # Version 5.0 : from : 12 sep 2007 **/ /** to 27 feb 2008 **/ /** # Version 5.1 : from : 11 aug 2010 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MESH_IO #include "module.h" #include "common.h" #include "graph.h" #include "graph_io.h" #include "mesh.h" #include "mesh_io.h" /******************************************/ /* */ /* These routines handle source mesh I/O. */ /* */ /******************************************/ /* This routine loads a source mesh from ** the given stream. ** Edge loads, whenever present, are ** always discarded. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int meshLoad ( Mesh * restrict const meshptr, /* Mesh structure to fill */ FILE * restrict const stream, /* Stream from which to read graph data */ const Gnum baseval) /* Base value (-1 means keep file base) */ { Gnum edgenum; /* Number of edges really allocated */ Gnum edgennd; Gnum vertnbr; Gnum velmnbr; /* Number of elements in mesh */ Gnum velmbas; /* Base index for element vertices */ Gnum vnodnbr; /* Number of nodes in mesh */ Gnum vnodbas; /* Base index for node vertices */ Gnum vlblmax; /* Maximum vertex label number */ Gnum vlblval; /* Value where to read vertex label */ Gnum velonbr; /* Size of vertex load array */ Gnum veloval; /* Value where to read vertex load */ Gnum vlblnbr; /* Size of vertex label array */ Gnum edloval; /* Value where to read edge load */ Gnum edgeval; /* Value where to read edge end */ Gnum baseadj; Gnum versval; Gnum degrmax; Gnum propval; char proptab[4]; Gnum vertbastab[2]; Gnum vertnndtab[2]; Gnum edgeadjtab[2]; int i; memSet (meshptr, 0, sizeof (Mesh)); if ((intLoad (stream, &versval) != 1) || /* Read version number */ (versval != 1)) { errorPrint ("meshLoad: bad input (1)"); return (1); } if ((intLoad (stream, &velmnbr) != 1) || /* Read rest of header */ (intLoad (stream, &vnodnbr) != 1) || (intLoad (stream, &meshptr->edgenbr) != 1) || (intLoad (stream, &velmbas) != 1) || (intLoad (stream, &vnodbas) != 1) || (intLoad (stream, &propval) != 1) || (velmnbr < 0) || (vnodnbr < 0) || (velmbas < 0) || (vnodbas < 0) || (propval < 0) || (propval > 111) || (((velmbas + velmnbr) != vnodbas) && ((vnodbas + vnodnbr) != velmbas))) { errorPrint ("meshLoad: bad input (2)"); return (1); } sprintf (proptab, "%3.3d", (int) propval); /* Compute file properties */ proptab[0] -= '0'; /* Vertex labels flag */ proptab[1] -= '0'; /* Edge weights flag */ proptab[2] -= '0'; /* Vertex loads flag */ baseadj = MIN (velmbas, vnodbas); /* Get file graph base value */ if (baseval == -1) { /* If keep file graph base */ meshptr->baseval = baseadj; /* Set graph base as file base */ baseadj = 0; /* No base adjustment needed */ } else { /* If set graph base */ meshptr->baseval = baseval; /* Set wanted graph base */ baseadj = baseval - baseadj; /* Update base adjust */ } meshptr->flagval = MESHFREEVERT | MESHVERTGROUP; /* Edge array grouped with vertex array */ meshptr->velmnbr = velmnbr; meshptr->velmbas = velmbas + baseadj; meshptr->velmnnd = velmnbr + (velmbas + baseadj); meshptr->vnodnbr = vnodnbr; meshptr->vnodbas = vnodbas + baseadj; meshptr->vnodnnd = vnodnbr + (vnodbas + baseadj); vertnbr = velmnbr + vnodnbr; velonbr = (proptab[2] != 0) ? vertnbr : 0; vlblnbr = (proptab[0] != 0) ? vertnbr : 0; if (memAllocGroup ((void **) (void *) &meshptr->verttax, (size_t) ((vertnbr + 1) * sizeof (Gnum)), &meshptr->vlbltax, (size_t) ( vlblnbr * sizeof (Gnum)), &meshptr->velotax, (size_t) ( velonbr * sizeof (Gnum)), /* Allocate single array for both element and node vertices */ &meshptr->edgetax, (size_t) ( meshptr->edgenbr * sizeof (Gnum)), NULL) == NULL) { /* Edge array grouped with vertex arrays */ errorPrint ("meshLoad: out of memory (1)"); meshFree (meshptr); return (1); } meshptr->verttax -= meshptr->baseval; meshptr->vendtax = meshptr->verttax + 1; /* Use compact vertex array */ meshptr->velotax = (velonbr != 0) ? (meshptr->velotax - meshptr->baseval) : NULL; /* Store based load array access in velotax */ meshptr->vnlotax = meshptr->velotax; meshptr->vlbltax = (vlblnbr != 0) ? (meshptr->vlbltax - meshptr->baseval) : NULL; meshptr->velosum = meshptr->velmnbr; /* Assume element and node vertices not weighted */ meshptr->vnlosum = meshptr->vnodnbr; meshptr->edgetax -= meshptr->baseval; degrmax = 0; edgennd = meshptr->edgenbr + meshptr->baseval; edgenum = meshptr->baseval; /* No edges allocated yet */ vlblmax = vertnbr + meshptr->baseval - 1; /* No vertex labels known */ if (meshptr->velmbas <= meshptr->vnodbas) { /* If elements first */ vertbastab[0] = meshptr->velmbas; vertnndtab[0] = meshptr->velmnnd; edgeadjtab[0] = meshptr->vnodbas - meshptr->baseval; vertbastab[1] = meshptr->vnodbas; vertnndtab[1] = meshptr->vnodnnd; edgeadjtab[1] = meshptr->velmbas - meshptr->baseval; } else { vertbastab[0] = meshptr->vnodbas; vertnndtab[0] = meshptr->vnodnnd; edgeadjtab[0] = meshptr->velmbas - meshptr->baseval; vertbastab[1] = meshptr->velmbas; vertnndtab[1] = meshptr->velmnnd; edgeadjtab[1] = meshptr->vnodbas - meshptr->baseval; } for (i = 0; i < 2; i ++) { /* For both kinds of vertices */ Gnum vertbas; Gnum vertnnd; Gnum edgeadj; Gnum vertnum; Gnum velosum; Gnum velomax; vertbas = vertbastab[i]; vertnnd = vertnndtab[i]; edgeadj = edgeadjtab[i]; velosum = 0; velomax = 1; /* Assume vertex loads all equal to 1 */ for (vertnum = vertbas; vertnum < vertnnd; vertnum ++) { /* For all vertices of same kind */ Gnum degrval; if (meshptr->vlbltax != NULL) { /* If must read label */ if (intLoad (stream, &vlblval) != 1) { /* Read label data */ errorPrint ("meshLoad: bad input (3)"); meshFree (meshptr); return (1); } meshptr->vlbltax[vertnum] = vlblval + vertbas + baseadj; /* Adjust vertex label */ if (meshptr->vlbltax[vertnum] > vlblmax) /* Get maximum vertex label */ vlblmax = meshptr->vlbltax[vertnum]; } if (proptab[2] != 0) { /* If must read vertex load */ if ((intLoad (stream, &veloval) != 1) || /* Read vertex load data */ (veloval < 1)) { errorPrint ("meshLoad: bad input (4)"); meshFree (meshptr); return (1); } if (veloval > velomax) velomax = veloval; meshptr->velotax[vertnum] = veloval; velosum += veloval; } if (intLoad (stream, °rval) != 1) { /* Read vertex degree */ errorPrint ("meshLoad: bad input (5)"); meshFree (meshptr); return (1); } if (degrmax < degrval) /* Set maximum degree */ degrmax = degrval; meshptr->verttax[vertnum] = edgenum; /* Set index in edge array */ degrval += edgenum; if (degrval > edgennd) { /* Check if edge array overflows */ errorPrint ("meshLoad: invalid arc count (1)"); meshFree (meshptr); return (1); } for ( ; edgenum < degrval; edgenum ++) { if (proptab[1] != 0) { /* If must read edge load */ if (intLoad (stream, &edloval) != 1) { /* Read edge load data (useless) */ errorPrint ("meshLoad: bad input (6)"); meshFree (meshptr); return (1); } } if (intLoad (stream, &edgeval) != 1) { /* Read edge data */ errorPrint ("meshLoad: bad input (7)"); meshFree (meshptr); return (1); } meshptr->edgetax[edgenum] = edgeval + edgeadj; } } if (vertbastab[i] == meshptr->velmbas) { /* If elements are processed */ if (velomax == 1) /* If element loads not significant */ meshptr->velotax = NULL; else meshptr->velosum = velosum; } else { if (velomax == 1) /* If node loads not significant */ meshptr->vnlotax = NULL; else meshptr->vnlosum = velosum; } } meshptr->verttax[vertnbr + meshptr->baseval] = meshptr->edgenbr + meshptr->baseval; /* Set end of edge array */ if (edgenum != edgennd) { /* Check if number of edges is valid */ errorPrint ("meshLoad: invalid arc count (2)"); meshFree (meshptr); return (1); } meshptr->degrmax = degrmax; if (meshptr->vlbltax != NULL) { /* If vertex label renaming necessary */ if (graphLoad2 (meshptr->baseval, vertnbr + meshptr->baseval, meshptr->verttax, /* Rename edge ends */ meshptr->vendtax, meshptr->edgetax, vlblmax, meshptr->vlbltax) != 0) { errorPrint ("meshLoad: cannot relabel vertices"); meshFree (meshptr); return (1); } } #ifdef SCOTCH_DEBUG_MESH2 if (meshCheck (meshptr) != 0) { /* Check mesh consistency */ errorPrint ("meshLoad: inconsistent mesh data"); meshFree (meshptr); return (1); } #endif /* SCOTCH_DEBUG_MESH2 */ return (0); } /* This routine saves a source mesh to ** the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int meshSave ( const Mesh * restrict const meshptr, FILE * restrict const stream) { char propstr[4]; /* Property string */ Gnum vertbastab[2]; Gnum vertnndtab[2]; Gnum * velotabtab[2]; Gnum edgeadjtab[2]; int i; int o; propstr[0] = (meshptr->vlbltax != NULL) ? '1' : '0'; /* Set property string */ propstr[1] = '0'; /* No edge loads written */ propstr[2] = ((meshptr->velotax != NULL) || (meshptr->vnlotax != NULL)) ? '1' : '0'; propstr[3] = '\0'; if (fprintf (stream, "1\n" GNUMSTRING "\t" GNUMSTRING "\t" GNUMSTRING "\n" GNUMSTRING "\t" GNUMSTRING "\t%3s\n", /* Write file header */ (Gnum) meshptr->velmnbr, (Gnum) meshptr->vnodnbr, (Gnum) meshptr->edgenbr, (Gnum) meshptr->velmbas, (Gnum) meshptr->vnodbas, propstr) == EOF) { errorPrint ("meshSave: bad output (1)"); return (1); } vertbastab[0] = meshptr->baseval; vertnndtab[1] = meshptr->velmnbr + meshptr->vnodnbr + meshptr->baseval; if (meshptr->velmbas <= meshptr->vnodbas) { /* If elements first */ vertnndtab[0] = meshptr->velmnnd; velotabtab[0] = meshptr->velotax; edgeadjtab[0] = meshptr->vnodbas - meshptr->baseval; vertbastab[1] = meshptr->vnodbas; velotabtab[0] = meshptr->vnlotax; edgeadjtab[1] = meshptr->velmbas - meshptr->baseval; } else { vertnndtab[0] = meshptr->vnodnnd; velotabtab[0] = meshptr->vnlotax; edgeadjtab[0] = meshptr->velmbas - meshptr->baseval; vertbastab[1] = meshptr->velmbas; velotabtab[1] = meshptr->velotax; edgeadjtab[1] = meshptr->vnodbas - meshptr->baseval; } for (i = 0; i < 2; i ++) { /* For both kinds of vertices */ Gnum vertbas; Gnum vertnnd; Gnum * restrict velotax; Gnum edgeadj; Gnum vertnum; vertbas = vertbastab[i]; vertnnd = vertnndtab[i]; velotax = velotabtab[i]; edgeadj = edgeadjtab[i]; for (vertnum = vertbas, o = 0; (vertnum < vertnnd) && (o == 0); vertnum ++) { Gnum edgenum; if (meshptr->vlbltax != NULL) /* Write vertex label if necessary */ o = (fprintf (stream, GNUMSTRING "\t", (Gnum) meshptr->vlbltax[vertnum]) == EOF); if (propstr[2] != '0') /* Write vertex load if necessary */ o |= (fprintf (stream, GNUMSTRING "\t", (Gnum) ((velotax != NULL) ? velotax[vertnum] : 1)) == EOF); o |= (fprintf (stream, GNUMSTRING, (Gnum) (meshptr->vendtax[vertnum] - meshptr->verttax[vertnum])) == EOF); /* Write vertex degree */ for (edgenum = meshptr->verttax[vertnum]; (edgenum < meshptr->vendtax[vertnum]) && (o == 0); edgenum ++) { o |= (putc ('\t', stream) == EOF); o |= (intSave (stream, /* Write edge end */ (meshptr->vlbltax != NULL) ? meshptr->vlbltax[meshptr->edgetax[edgenum]] : meshptr->edgetax[edgenum] - edgeadj) != 1); } o |= (putc ('\n', stream) == EOF); } } if (o != 0) errorPrint ("meshSave: bad output (2)"); return (o); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_nd.h0000644000175300017530000000621711631334325022272 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_nd.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the halo mesh nested dissection **/ /** ordering algorithm. **/ /** **/ /** DATES : # Version 4.0 : from : 06 jan 2002 **/ /** to 23 jan 2004 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HmeshOrderNdParam_ { Strat * sepstrat; /*+ Separation strategy +*/ Strat * ordstratlea; /*+ Leaf ordering strategy +*/ Strat * ordstratsep; /*+ Separator ordering strategy +*/ } HmeshOrderNdParam; /* ** The function prototypes. */ #ifndef HMESH_ORDER_ND #define static #endif int hmeshOrderNd (const Hmesh * restrict const, Order * restrict const, const Gnum, OrderCblk * restrict const, const HmeshOrderNdParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_zr.c0000644000175300017530000000741711631334325022627 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_zr.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module moves all of the vertices **/ /** to the first subdomain of the **/ /** bipartition. **/ /** **/ /** DATES : # Version 3.2 : from : 23 aug 1996 **/ /** to 13 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 3.4 : from : 01 jun 2001 **/ /** to 01 jun 2001 **/ /** # Version 4.0 : from : 01 nov 2003 **/ /** to 29 may 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BGRAPH_BIPART_ZR #include "module.h" #include "common.h" #include "graph.h" #include "arch.h" #include "bgraph.h" #include "bgraph_bipart_zr.h" /********************************/ /* */ /* Zero bipartitioning routine. */ /* */ /********************************/ /* This routine moves all the vertices ** of the given graph to the first part. ** It returns: ** - 0 : if bipartitioning could be computed. ** - 1 : on error. */ int bgraphBipartZr ( Bgraph * restrict const grafptr) /*+ Active graph +*/ { if (grafptr->compload0 != grafptr->s.velosum) /* If not all vertices already in part zero */ bgraphZero (grafptr); #ifdef SCOTCH_DEBUG_BGRAPH2 if (bgraphCheck (grafptr) != 0) { errorPrint ("bgraphBipartZr: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_build_grid3d.h0000644000175300017530000001215411631334325023167 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_build_grid3d.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the data **/ /** declarations for the distributed 3D **/ /** grid graph building routine. **/ /** **/ /** DATES : # Version 5.1 : from : 06 jun 2010 **/ /** to : 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ The multinode table element, which contains pairs of based indices of collapsed vertices. Both values are equal for uncollapsed vertices. +*/ typedef struct DgraphBuildGrid3DData_ { Gnum baseval; Gnum dimxval; Gnum dimyval; Gnum dimzval; Gnum * edgeloctax; Gnum * edloloctax; Gnum (* funcvrtptr) (const struct DgraphBuildGrid3DData_ * restrict const, const Gnum, Gnum, const Gnum, const Gnum, const Gnum); struct { /* Pre-computed data for 26-neighbor torus */ Gnum ngbxmin; Gnum ngbxmax; Gnum ngbymin; Gnum ngbymax; Gnum ngbzmin; Gnum ngbzmax; } t26; } DgraphBuildGrid3DData; /* ** The function prototypes. */ #ifndef DGRAPH_BUILD_GRID3D #define static #endif static Gnum dgraphBuildGrid3Dvertex26M (const DgraphBuildGrid3DData * restrict const, const Gnum, Gnum, const Gnum, const Gnum, const Gnum); static Gnum dgraphBuildGrid3Dvertex26T (const DgraphBuildGrid3DData * restrict const, const Gnum, Gnum, const Gnum, const Gnum, const Gnum); static Gnum dgraphBuildGrid3Dvertex6M (const DgraphBuildGrid3DData * restrict const, const Gnum, Gnum, const Gnum, const Gnum, const Gnum); static Gnum dgraphBuildGrid3Dvertex6T (const DgraphBuildGrid3DData * restrict const, const Gnum, Gnum, const Gnum, const Gnum, const Gnum); #undef static /* ** The macro definitions. */ #define DGRAPHBUILDGRID3DNGB(d,v,e,x,y,z) { \ Gnum edgeloctmp; \ Gnum vertglbend; \ edgeloctmp = (e); \ vertglbend = ((z) * (d)->dimyval + (y)) * (d)->dimxval + (x) + (d)->baseval; \ (d)->edgeloctax[edgeloctmp] = vertglbend; \ if ((d)->edloloctax != NULL) \ (d)->edloloctax[edgeloctmp] = ((vertglbend + (v)) % 16) + 1; \ } scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_nd.h0000644000175300017530000000677011631334325022443 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_nd.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the halo graph nested dissection **/ /** ordering algorithm. **/ /** **/ /** DATES : # Version 3.2 : from : 17 oct 1996 **/ /** to : 18 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to 13 mar 1999 **/ /** # Version 4.0 : from : 03 jan 2002 **/ /** to 24 apr 2004 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HgraphOrderNdParam_ { Strat * sepstrat; /*+ Separation strategy +*/ Strat * ordstratlea; /*+ Leaf ordering strategy +*/ Strat * ordstratsep; /*+ Separator ordering strategy +*/ } HgraphOrderNdParam; /* ** The function prototypes. */ #ifndef HGRAPH_ORDER_ND #define static #endif int hgraphOrderNd (const Hgraph * const, Order * const, const Gnum, OrderCblk * const, const HgraphOrderNdParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_graph_map_view.c0000644000175300017530000004576511631334325024034 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_map_view.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the mapping **/ /** routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 3.2 : from : 19 aug 1998 **/ /** to 20 aug 1998 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to 30 mar 1999 **/ /** # Version 3.4 : from : 01 nov 2001 **/ /** to 01 nov 2001 **/ /** # Version 4.0 : from : 13 jan 2004 **/ /** to 30 nov 2006 **/ /** # Version 5.0 : from : 04 feb 2007 **/ /** to 03 apr 2008 **/ /** # Version 5.1 : from : 27 jul 2008 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #define LIBRARY_GRAPH_MAP_VIEW #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "arch.h" #include "mapping.h" #include "kgraph.h" #include "library_mapping.h" #include "library_graph_map_view.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the mapping routines. */ /* */ /************************************/ /*+ This routine writes mapping statistics *** to the given stream. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphMapView ( const SCOTCH_Graph * const libgrafptr, const SCOTCH_Mapping * const libmappptr, FILE * const stream) { const Graph * restrict grafptr; const Mapping * restrict mappptr; Anum * restrict parttax; /* Part array */ MappingSort * restrict domntab; /* Pointer to domain sort array */ ArchDom domnfrst; /* Largest domain in architecture */ Anum tgtnbr; /* Number of processors in target topology */ Anum mapnbr; /* Number of processors effectively used */ Anum mapnum; double mapavg; /* Average mapping weight */ Gnum mapmin; Gnum mapmax; Gnum mapsum; /* (Partial) sum of vertex loads */ double mapdlt; double mapmmy; /* Maximum / average ratio */ Anum * restrict nghbtab; /* Table storing neighbors of current subdomain */ Anum nghbnbr; Anum nghbmin; Anum nghbmax; Anum nghbsum; Gnum vertnum; Gnum veloval; Gnum edloval; Gnum commdist[256]; /* Array of load distribution */ Gnum commload; /* Total edge load (edge sum) */ Gnum commdilat; /* Total edge dilation */ Gnum commexpan; /* Total edge expansion */ Anum distmax; Anum distval; Gnum diammin; Gnum diammax; Gnum diamsum; const Gnum * restrict const verttax = ((Graph *) libgrafptr)->verttax; const Gnum * restrict const vendtax = ((Graph *) libgrafptr)->vendtax; const Gnum * restrict const velotax = ((Graph *) libgrafptr)->velotax; const Gnum * restrict const edgetax = ((Graph *) libgrafptr)->edgetax; const Gnum * restrict const edlotax = ((Graph *) libgrafptr)->edlotax; grafptr = (Graph *) libgrafptr; mappptr = &((LibMapping *) libmappptr)->m; if ((grafptr->vertnbr == 0) || /* Return if nothing to do */ (grafptr->edgenbr == 0)) return (0); if (memAllocGroup ((void **) (void *) &domntab, (size_t) ((grafptr->vertnbr + 1) * sizeof (MappingSort)), &parttax, (size_t) (grafptr->vertnbr * sizeof (Anum)), &nghbtab, (size_t) ((grafptr->vertnbr + 2) * sizeof (Anum)), NULL) == NULL) { errorPrint ("SCOTCH_graphMapView: out of memory"); return (1); } memSet (parttax, ~0, grafptr->vertnbr * sizeof (Anum)); for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { parttax[vertnum] = domntab[vertnum].labl = archDomNum (&mappptr->archdat, mapDomain (mappptr, vertnum + grafptr->baseval)); domntab[vertnum].peri = vertnum + grafptr->baseval; /* Build inverse permutation */ } domntab[grafptr->vertnbr].labl = ARCHDOMNOTTERM; /* TRICK: avoid testing (i+1) */ domntab[grafptr->vertnbr].peri = ~0; /* Prevent Valgrind from yelling */ parttax -= grafptr->baseval; /* From now on, base part array */ intSort2asc2 (domntab, grafptr->vertnbr); /* Sort domain label array by increasing target labels */ archDomFrst (&mappptr->archdat, &domnfrst); /* Get architecture domain */ tgtnbr = archDomSize (&mappptr->archdat, &domnfrst); /* Get architecture size */ mapsum = 0; mapnbr = 0; veloval = 1; /* Assume unweighted vertices */ for (vertnum = 0; domntab[vertnum].labl != ARCHDOMNOTTERM; vertnum ++) { parttax[domntab[vertnum].peri] = mapnbr; /* Build map of partition parts starting from 0 */ if (domntab[vertnum].labl != domntab[vertnum + 1].labl) /* TRICK: if new (or end) domain label */ mapnbr ++; if (velotax != NULL) veloval = velotax[domntab[vertnum].peri]; mapsum += veloval; } mapavg = (mapnbr == 0) ? 0.0L : (double) mapsum / (double) mapnbr; mapsum = 0; mapmin = GNUMMAX; mapmax = 0; mapdlt = 0.0L; for (vertnum = 0; domntab[vertnum].labl != ARCHDOMNOTTERM; vertnum ++) { if (velotax != NULL) veloval = velotax[domntab[vertnum].peri]; mapsum += veloval; if (domntab[vertnum].labl != domntab[vertnum + 1].labl) { /* TRICK: if new (or end) domain label */ if (mapsum < mapmin) mapmin = mapsum; if (mapsum > mapmax) mapmax = mapsum; mapdlt += fabs ((double) mapsum - mapavg); mapsum = 0; /* Reset domain load sum */ } } mapdlt = (mapnbr != 0) ? mapdlt / ((double) mapnbr * mapavg) : 0.0L; mapmmy = (mapnbr != 0) ? (double) mapmax / (double) mapavg : 0.0L; if (mapnbr > tgtnbr) { /* If more subdomains than architecture size */ #ifdef SCOTCH_DEBUG_MAP2 if (! archVar (&mappptr->archdat)) { /* If not a variable-sized architecture */ errorPrint ("SCOTCH_graphMapView: invalid mapping"); memFree (domntab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_MAP2 */ tgtnbr = mapnbr; /* Assume it is a variable-sized architecture */ } fprintf (stream, "M\tProcessors " GNUMSTRING "/" GNUMSTRING " (%g)\n", (Gnum) mapnbr, (Gnum) tgtnbr, (double) mapnbr / (double) tgtnbr); fprintf (stream, "M\tTarget min=" GNUMSTRING "\tmax=" GNUMSTRING "\tavg=%g\tdlt=%g\tmaxavg=%g\n", (Gnum) mapmin, (Gnum) mapmax, mapavg, mapdlt, mapmmy); nghbnbr = 0; nghbmin = ANUMMAX; nghbmax = 0; nghbsum = 0; nghbnbr = 0; nghbtab[0] = -2; for (vertnum = 0; domntab[vertnum].labl != ARCHDOMNOTTERM; vertnum ++) { Gnum edgenum; Gnum edgennd; Anum partnum; partnum = parttax[domntab[vertnum].peri]; for (edgenum = verttax[domntab[vertnum].peri], edgennd = vendtax[domntab[vertnum].peri]; edgenum < edgennd; edgenum ++) { Anum partend; partend = parttax[edgetax[edgenum]]; if ((partend != partnum) && /* If edge is not internal */ (partend != nghbtab[nghbnbr])) { /* And neighbor is not sole neighbor or has not just been found */ Anum partmin; Anum partmax; partmin = 0; partmax = nghbnbr; while ((partmax - partmin) > 1) { Anum partmed; partmed = (partmax + partmin) >> 1; if (nghbtab[partmed] > partend) partmax = partmed; else partmin = partmed; } if (nghbtab[partmin] == partend) /* If neighboring part found, skip to next neighbor */ continue; #ifdef SCOTCH_DEBUG_MAP2 if (nghbnbr >= (grafptr->vertnbr + 1)) { errorPrint ("SCOTCH_graphMapView: internal error"); return (1); } #endif /* SCOTCH_DEBUG_MAP2 */ nghbnbr ++; for (partmax = nghbnbr; partmax > (partmin + 1); partmax --) nghbtab[partmax] = nghbtab[partmax - 1]; nghbtab[partmin + 1] = partend; /* Add new neighbor part in the right place */ } } if (domntab[vertnum].labl != domntab[vertnum + 1].labl) { /* TRICK: if new (or end) domain label */ if (nghbnbr < nghbmin) nghbmin = nghbnbr; if (nghbnbr > nghbmax) nghbmax = nghbnbr; nghbsum += nghbnbr; nghbnbr = 0; } } fprintf (stream, "M\tNeighbors min=" GNUMSTRING "\tmax=" GNUMSTRING "\tsum=" GNUMSTRING "\n", (Gnum) nghbmin, (Gnum) nghbmax, (Gnum) nghbsum); memset (commdist, 0, 256 * sizeof (Gnum)); /* Initialize the data */ commload = commdilat = commexpan = 0; edloval = 1; for (vertnum = grafptr->baseval; vertnum < grafptr->vertnnd; vertnum ++) { Gnum edgenum; if (parttax[vertnum] == ~0) /* Skip unmapped vertices */ continue; for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { if (parttax[edgetax[edgenum]] == ~0) continue; distval = archDomDist (&mappptr->archdat, mapDomain (mappptr, vertnum), mapDomain (mappptr, edgetax[edgenum])); if (edlotax != NULL) /* Get edge weight if any */ edloval = edlotax[edgenum]; commdist[(distval > 255) ? 255 : distval] += edloval; commload += edloval; commdilat += distval; commexpan += distval * edloval; } } fprintf (stream, "M\tCommDilat=%f\t(" GNUMSTRING ")\n", /* Print expansion parameters */ (double) commdilat / grafptr->edgenbr, (Gnum) (commdilat / 2)); fprintf (stream, "M\tCommExpan=%f\t(" GNUMSTRING ")\n", ((commload == 0) ? (double) 0.0L : (double) commexpan / (double) commload), (Gnum) (commexpan / 2)); fprintf (stream, "M\tCommCutSz=%f\t(" GNUMSTRING ")\n", ((commload == 0) ? (double) 0.0L : (double) (commload - commdist[0]) / (double) commload), (Gnum) ((commload - commdist[0]) / 2)); fprintf (stream, "M\tCommDelta=%f\n", (((double) commload * (double) commdilat) == 0.0L) ? (double) 0.0L : ((double) commexpan * (double) grafptr->edgenbr) / ((double) commload * (double) commdilat)); for (distmax = 255; distmax != -1; distmax --) /* Find longest distance */ if (commdist[distmax] != 0) break; for (distval = 0; distval <= distmax; distval ++) /* Print distance histogram */ fprintf (stream, "M\tCommLoad[" ANUMSTRING "]=%f\n", (Anum) distval, (double) commdist[distval] / (double) commload); diammin = GNUMMAX; diammax = 0; diamsum = 0; for (mapnum = 0; mapnum < mapnbr; mapnum ++) { Gnum diamval; diamval = graphMapView2 (grafptr, parttax, mapnum); diamsum += diamval; if (diamval < diammin) diammin = diamval; if (diamval > diammax) diammax = diamval; } fprintf (stream, "M\tPartDiam\tmin=" GNUMSTRING "\tmax=" GNUMSTRING "\tavg=%lf\n", (Gnum) diammin, (Gnum) diammax, (double) diamsum / (double) mapnbr); memFree (domntab); /* Free group leader */ return (0); } /*+ This routine computes the pseudo-diameter of *** the given part. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ static Gnum graphMapView2 ( const Graph * const grafptr, /*+ Graph +*/ const Anum * const parttax, /*+ Part array +*/ const Anum partval) /*+ Part value +*/ { GraphMapViewQueue queudat; /* Neighbor queue */ GraphMapViewVertex * restrict vexxtax; /* Based access to vexxtab */ Gnum rootnum; /* Number of current root vertex */ Gnum vertdist; /* Vertex distance */ int diamflag; /* Flag set if diameter changed */ Gnum diambase; /* Base distance for connected components */ Gnum diamdist; /* Current diameter distance */ Gnum diamnum; /* Vertex which achieves diameter */ Gnum passnum; /* Pass number */ const Gnum * restrict verttax; /* Based access to vertex array */ const Gnum * restrict vendtax; /* Based access to vertex end array */ const Gnum * restrict edgetax; if (memAllocGroup ((void **) (void *) &queudat.qtab, (size_t) (grafptr->vertnbr * sizeof (Gnum)), &vexxtax, (size_t) (grafptr->vertnbr * sizeof (GraphMapViewVertex)), NULL) == NULL) { errorPrint ("graphMapView2: out of memory"); return (-1); } memSet (vexxtax, 0, grafptr->vertnbr * sizeof (GraphMapViewVertex)); /* Initialize pass numbers */ edgetax = grafptr->edgetax; verttax = grafptr->verttax; vendtax = grafptr->vendtax; vexxtax -= grafptr->baseval; diamnum = 0; /* Start distances from zero */ diamdist = 0; for (passnum = 1, rootnum = grafptr->baseval; ; passnum ++) { /* For all connected components */ while ((rootnum < grafptr->vertnbr) && ((vexxtax[rootnum].passnum != 0) || /* Find first unallocated vertex */ (parttax[rootnum] != partval))) rootnum ++; if (rootnum >= grafptr->vertnbr) /* Exit if all of graph processed */ break; diambase = ++ diamdist; /* Start from previous distance */ diamnum = rootnum; /* Start from found root */ for (diamflag = 1; diamflag -- != 0; passnum ++) { /* Loop if modifications */ graphMapViewQueueFlush (&queudat); /* Flush vertex queue */ graphMapViewQueuePut (&queudat, diamnum); /* Start from diameter vertex */ vexxtax[diamnum].passnum = passnum; /* It has been enqueued */ vexxtax[diamnum].vertdist = diambase; /* It is at base distance */ do { /* Loop on vertices in queue */ Gnum vertnum; Gnum edgenum; vertnum = graphMapViewQueueGet (&queudat); /* Get vertex from queue */ vertdist = vexxtax[vertnum].vertdist; /* Get vertex distance */ if ((vertdist > diamdist) || /* If vertex increases diameter */ ((vertdist == diamdist) && /* Or is at diameter distance */ ((vendtax[vertnum] - verttax[vertnum]) < /* With smaller degree */ (vendtax[diamnum] - verttax[diamnum])))) { diamnum = vertnum; /* Set it as new diameter vertex */ diamdist = vertdist; diamflag = 1; } vertdist ++; /* Set neighbor distance */ for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { Gnum vertend; vertend = edgetax[edgenum]; if ((vexxtax[vertend].passnum < passnum) && /* If vertex not queued yet */ (parttax[vertend] == partval)) { /* And of proper part */ graphMapViewQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ vexxtax[vertend].passnum = passnum; vexxtax[vertend].vertdist = vertdist; } } } while (! graphMapViewQueueEmpty (&queudat)); /* As long as queue is not empty */ } } memFree (queudat.qtab); /* Free group leader */ return (diamdist); } scotch-5.1.12b.dfsg/src/libscotch/hdgraph_check.c0000644000175300017530000001462011631334325022054 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph_check.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a parallel static mapper. **/ /** This module contains the distributed **/ /** graph consistency checking routine. **/ /** **/ /** # Version 5.0 : from : 21 apr 2006 **/ /** to : 29 apr 2006 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HDGRAPH_CHECK #include "module.h" #include "common.h" #include "dgraph.h" #include "hdgraph.h" /******************************/ /* */ /* These routines handle halo */ /* distributed source graphs. */ /* */ /******************************/ /* This function checks the consistency ** of the given halo distributed graph. ** It returns: ** - 0 : if graph data are consistent. ** - !0 : on error. */ int hdgraphCheck ( const Hdgraph * restrict const grafptr) { Gnum vertlocnum; int * restrict vhalloctax; /* Flag array for halo vertices */ Gnum vhallocnnd; Gnum vhallocnum; Gnum ehallocnbr; int cheklocval; /* Local consistency flag */ int chekglbval; /* Global consistency flag */ cheklocval = 0; for (vertlocnum = grafptr->s.baseval, ehallocnbr = 0; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { if ((grafptr->vhndloctax[vertlocnum] < grafptr->s.vendloctax[vertlocnum]) || (grafptr->vhndloctax[vertlocnum] > (grafptr->s.edgelocsiz + grafptr->s.baseval))) { errorPrint ("hdgraphCheck: inconsistent local vertex arrays"); cheklocval = 1; } ehallocnbr += grafptr->vhndloctax[vertlocnum] - grafptr->s.vendloctax[vertlocnum]; } if (ehallocnbr != grafptr->ehallocnbr) { errorPrint ("hdgraphCheck: invalid local number of halo edges"); cheklocval = 1; } if ((grafptr->vhallocnbr < 0) || (grafptr->vhallocnbr > grafptr->s.edgelocsiz)) { errorPrint ("hdgraphCheck: invalid local number of halo vertices"); cheklocval = 1; } vhalloctax = NULL; if ((cheklocval == 0) && ((vhalloctax = (int *) memAlloc (grafptr->vhallocnbr * sizeof (int))) == NULL)) { errorPrint ("hdgraphCheck: out of memory"); cheklocval = 1; } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphCheck: communication error (1)"); return (1); } if (chekglbval != 0) { if (vhalloctax != NULL) memFree (vhalloctax); return (1); } memSet (vhalloctax, ~0, grafptr->vhallocnbr * sizeof (int)); vhalloctax -= grafptr->s.baseval; vhallocnnd = grafptr->vhallocnbr + grafptr->s.baseval; for (vertlocnum = grafptr->s.baseval; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { Gnum edgelocnum; for (edgelocnum = grafptr->s.vendloctax[vertlocnum]; edgelocnum < grafptr->vhndloctax[vertlocnum]; edgelocnum ++) { Gnum vhallocend; vhallocend = grafptr->s.edgeloctax[edgelocnum]; if ((vhallocend < grafptr->s.baseval) || (vhallocend >= vhallocnnd)) { errorPrint ("hdgraphCheck: invalid halo vertex number"); vertlocnum = grafptr->s.vertlocnnd; /* Avoid unwanted cascaded error messages */ cheklocval = 1; break; } vhalloctax[vhallocend] = 0; /* Flag halo vertex as used */ } } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphCheck: communication error (2)"); return (1); } if (chekglbval != 0) { memFree (vhalloctax + grafptr->s.baseval); return (1); } for (vhallocnum = grafptr->s.baseval; vhallocnum < vhallocnnd; vhallocnum ++) { if (vhalloctax[vhallocnum] != 0) { /* If halo vertex index not used in graph */ errorPrint ("hdgraphCheck: unused halo vertex number"); cheklocval = 1; break; } } memFree (vhalloctax + grafptr->s.baseval); if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("hdgraphCheck: communication error (3)"); return (1); } if (chekglbval != 0) return (1); return (dgraphCheck (&grafptr->s)); } scotch-5.1.12b.dfsg/src/libscotch/library_dmapping.c0000644000175300017530000000620311631334325022623 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dmapping.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains miscellaneous **/ /** routines for handling distributed **/ /** graph mappings. **/ /** **/ /** DATES : # Version 5.1 : from : 17 nov 2010 **/ /** to 17 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /****************************************/ /* */ /* These routines are the C API for */ /* mapping structure handling routines. */ /* */ /****************************************/ /*+ This routine reserves a memory area *** of a size sufficient to store a *** graph mapping structure. *** It returns: *** - !NULL : if the initialization succeeded. *** - NULL : on error. +*/ SCOTCH_Dmapping * SCOTCH_dmapAlloc () { return ((SCOTCH_Dmapping *) memAlloc (sizeof (SCOTCH_Dmapping))); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_hgraph.h0000644000175300017530000000606711631334325021752 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_hgraph.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the source halo mesh to source halo **/ /** graph building routine. **/ /** **/ /** DATES : # Version 4.0 : from : 30 nov 2003 **/ /** to 30 nov 2003 **/ /** **/ /************************************************************/ /* ** The defines. */ /** Prime number for cache-friendly perturbations. **/ #define HMESHHGRAPHHASHPRIME 37 /* Prime number */ /* ** The type and structure definitions. */ /*+ A table made of such elements is used during graph building to build the edge array of the graph from the one of the mesh. +*/ typedef struct HmeshHgraphHash_ { Gnum vertnum; /*+ Origin vertex (i.e. pass) number in mesh +*/ Gnum vertend; /*+ End vertex number in mesh +*/ } HmeshHgraphHash; scotch-5.1.12b.dfsg/src/libscotch/kgraph_check.c0000644000175300017530000001235711631334325021720 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kgraph_check.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the mapping graph **/ /** consistency checking routine. **/ /** **/ /** DATES : # Version 5.1 : from : 13 jul 2010 **/ /** to 13 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define KGRAPH #include "module.h" #include "common.h" #include "graph.h" #include "arch.h" #include "mapping.h" #include "kgraph.h" /*************************/ /* */ /* These routines handle */ /* mapping graphs. */ /* */ /*************************/ /* This routine checks the consistency ** of the given mapping graph. ** It returns: ** - 0 : if graph data are consistent. ** - !0 : on error. */ int kgraphCheck ( const Kgraph * restrict const grafptr) { int * restrict flagtax; /* Frontier flag array */ Gnum vertnum; /* Number of current vertex */ Gnum fronnum; /* Number of frontier vertex */ const Gnum * restrict const verttax = grafptr->s.verttax; const Gnum * restrict const vendtax = grafptr->s.vendtax; const Gnum * restrict const edgetax = grafptr->s.edgetax; const Anum * restrict const parttax = grafptr->m.parttax; if ((flagtax = memAlloc (grafptr->s.vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("kgraphCheck: out of memory"); return (1); } memSet (flagtax, ~0, grafptr->s.vertnbr * sizeof (Gnum)); flagtax -= grafptr->s.baseval; if ((grafptr->m.domnmax <= 0) || (grafptr->m.domnnbr <= 0) || (grafptr->m.domnnbr > grafptr->m.domnmax)) { errorPrint ("kgraphCheck: invalid number of domains"); return (1); } for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { if ((parttax[vertnum] < 0) || (parttax[vertnum] >= grafptr->m.domnnbr)) { errorPrint ("kgraphCheck: invalid part array"); return (1); } } if ((grafptr->fronnbr < 0) || (grafptr->fronnbr > grafptr->s.vertnbr)) { errorPrint ("kgraphCheck: invalid number of frontier vertices"); return (1); } for (fronnum = 0; fronnum < grafptr->fronnbr; fronnum ++) { Gnum vertnum; Gnum edgenum; Anum partval; Anum flagval; vertnum = grafptr->frontab[fronnum]; if ((vertnum < grafptr->s.baseval) || (vertnum >= grafptr->s.vertnnd)) { errorPrint ("kgraphCheck: invalid vertex index in frontier array"); return (1); } if (flagtax[vertnum] != ~0) { errorPrint ("kgraphCheck: duplicate vertex in frontier array"); return (1); } flagtax[vertnum] = 0; partval = parttax[vertnum]; for (edgenum = verttax[vertnum], flagval = 0; edgenum < vendtax[vertnum]; edgenum ++) flagval |= parttax[edgetax[edgenum]] ^ partval; /* Flag set if neighbor part differs from vertex part */ if (flagval == 0) { errorPrint ("kgraphCheck: invalid vertex in frontier array"); return (1); } } memFree (flagtax + grafptr->s.baseval); return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_arch_build_f.c0000644000175300017530000001045311631334325023427 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_arch_build_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the target architecture building **/ /** routine of the libSCOTCH library. **/ /** **/ /** DATES : # Version 4.0 : from : 17 mar 2005 **/ /** to 17 mar 2005 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /****************************************/ /* */ /* These routines are the Fortran API */ /* for the target architecture building */ /* routines. */ /* */ /****************************************/ /* ** */ FORTRAN ( \ SCOTCHFSTRATGRAPHBIPART, scotchfstratgraphbipart, ( \ SCOTCH_Strat * const stratptr, \ const char * const string, \ int * const revaptr, \ const int strnbr), \ (stratptr, string, revaptr, strnbr)) { char * restrict strtab; /* Pointer to null-terminated string */ if ((strtab = (char *) memAlloc (strnbr + 1)) == NULL) { /* Allocate temporary space */ errorPrint ("SCOTCHFSTRATGRAPHBIPART: out of memory (1)"); *revaptr = 1; } memCpy (strtab, string, strnbr); /* Copy string contents */ strtab[strnbr] = '\0'; /* Terminate string */ *revaptr = SCOTCH_stratGraphBipart (stratptr, strtab); /* Call original routine */ memFree (strtab); } /* ** */ FORTRAN ( \ SCOTCHFARCHBUILD, scotchfarchbuild, ( \ SCOTCH_Arch * const archptr, \ SCOTCH_Graph * const grafptr, \ const SCOTCH_Num * const listnbr, \ const SCOTCH_Num * const listptr, \ SCOTCH_Strat * const stratptr, \ int * const revaptr), \ (archptr, grafptr, listnbr, listptr, stratptr, revaptr)) { *revaptr = SCOTCH_archBuild (archptr, grafptr, *listnbr, listptr, stratptr); } scotch-5.1.12b.dfsg/src/libscotch/library_graph_order_f.c0000644000175300017530000003004011631334325023621 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_order_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** graph ordering routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 3.4 : from : 02 feb 2000 **/ /** to 15 nov 2001 **/ /** # Version 4.0 : from : 02 feb 2002 **/ /** to 13 dec 2005 **/ /** # Version 5.0 : from : 04 aug 2007 **/ /** to 31 may 2008 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 25 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the ordering routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFGRAPHORDERINIT, scotchfgraphorderinit, ( \ const SCOTCH_Graph * const grafptr, \ SCOTCH_Ordering * const ordeptr, \ SCOTCH_Num * const permtab, \ SCOTCH_Num * const peritab, \ SCOTCH_Num * const cblkptr, \ SCOTCH_Num * const rangtab, \ SCOTCH_Num * const treetab, \ int * const revaptr), \ (grafptr, ordeptr, permtab, peritab, \ cblkptr, rangtab, treetab, revaptr)) { *revaptr = SCOTCH_graphOrderInit (grafptr, ordeptr, permtab, peritab, cblkptr, rangtab, treetab); } /* ** */ FORTRAN ( \ SCOTCHFGRAPHORDEREXIT, scotchfgraphorderexit, ( \ const SCOTCH_Graph * const grafptr, \ SCOTCH_Ordering * const ordeptr), \ (grafptr, ordeptr)) { SCOTCH_graphOrderExit (grafptr, ordeptr); } /* ** */ FORTRAN ( \ SCOTCHFGRAPHORDERSAVE, scotchfgraphordersave, ( \ const SCOTCH_Graph * const grafptr, \ const SCOTCH_Ordering * const ordeptr, \ int * const fileptr, \ int * const revaptr), \ (grafptr, ordeptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHORDERSAVE: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHORDERSAVE: cannot open output stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_graphOrderSave (grafptr, ordeptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFGRAPHORDERSAVEMAP, scotchfgraphordersavemap, ( \ const SCOTCH_Graph * const grafptr, \ const SCOTCH_Ordering * const ordeptr, \ int * const fileptr, \ int * const revaptr), \ (grafptr, ordeptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHORDERSAVEMAP: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHORDERSAVEMAP: cannot open output stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_graphOrderSaveMap (grafptr, ordeptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFGRAPHORDERSAVETREE, scotchfgraphordersavetree, ( \ const SCOTCH_Graph * const grafptr, \ const SCOTCH_Ordering * const ordeptr, \ int * const fileptr, \ int * const revaptr), \ (grafptr, ordeptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHORDERSAVETREE: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHORDERSAVETREE: cannot open output stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_graphOrderSaveTree (grafptr, ordeptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFGRAPHORDERCOMPUTE, scotchfgraphordercompute, ( \ SCOTCH_Graph * const grafptr, \ SCOTCH_Ordering * const ordeptr, \ SCOTCH_Strat * const stratptr, \ int * const revaptr), \ (grafptr, ordeptr, stratptr, revaptr)) { *revaptr = SCOTCH_graphOrderCompute (grafptr, ordeptr, stratptr); } /* ** */ FORTRAN ( \ SCOTCHFGRAPHORDERCOMPUTELIST, scotchfgraphordercomputelist, ( \ SCOTCH_Graph * const grafptr, \ SCOTCH_Ordering * const ordeptr, \ const SCOTCH_Num * listptr, \ const SCOTCH_Num * const listtab, \ SCOTCH_Strat * const stratptr, \ int * const revaptr), \ (grafptr, ordeptr, listptr, listtab, stratptr, revaptr)) { *revaptr = SCOTCH_graphOrderComputeList (grafptr, ordeptr, *listptr, listtab, stratptr); } /* ** */ FORTRAN ( \ SCOTCHFGRAPHORDER, scotchfgraphorder, ( \ SCOTCH_Graph * const grafptr, \ SCOTCH_Strat * const stratptr, \ SCOTCH_Num * const permtab, \ SCOTCH_Num * const peritab, \ SCOTCH_Num * const cblkptr, \ SCOTCH_Num * const rangtab, \ SCOTCH_Num * const treetab, \ int * const revaptr), \ (grafptr, stratptr, permtab, peritab, \ cblkptr, rangtab, treetab, revaptr)) { *revaptr = SCOTCH_graphOrder (grafptr, stratptr, permtab, peritab, cblkptr, rangtab, treetab); } /* ** */ FORTRAN ( \ SCOTCHFGRAPHORDERLIST, scotchfgraphorderlist, ( \ SCOTCH_Graph * const grafptr, \ const SCOTCH_Num * const listptr, \ const SCOTCH_Num * const listtab, \ SCOTCH_Strat * const stratptr, \ SCOTCH_Num * const permtab, \ SCOTCH_Num * const peritab, \ SCOTCH_Num * const cblkptr, \ SCOTCH_Num * const rangtab, \ SCOTCH_Num * const treetab, \ int * const revaptr), \ (grafptr, listptr, listtab, stratptr, \ permtab, peritab, cblkptr, rangtab, treetab, revaptr)) { *revaptr = SCOTCH_graphOrderList (grafptr, *listptr, listtab, stratptr, permtab, peritab, cblkptr, rangtab, treetab); } /* ** */ FORTRAN ( \ SCOTCHFGRAPHORDERCHECK, scotchfgraphordercheck, ( \ const SCOTCH_Graph * const grafptr, \ const SCOTCH_Ordering * const ordeptr, \ int * const revaptr), \ (grafptr, ordeptr, revaptr)) { *revaptr = SCOTCH_graphOrderCheck (grafptr, ordeptr); } /* ** */ FORTRAN ( \ SCOTCHFSTRATGRAPHORDER, scotchfstratgraphorder, ( \ SCOTCH_Strat * const stratptr, \ const char * const string, \ int * const revaptr, \ const int strnbr), \ (stratptr, string, revaptr, strnbr)) { char * restrict strtab; /* Pointer to null-terminated string */ if ((strtab = (char *) memAlloc (strnbr + 1)) == NULL) { /* Allocate temporary space */ errorPrint ("SCOTCHFSTRATGRAPHORDER: out of memory (1)"); *revaptr = 1; } memCpy (strtab, string, strnbr); /* Copy string contents */ strtab[strnbr] = '\0'; /* Terminate string */ *revaptr = SCOTCH_stratGraphOrder (stratptr, strtab); /* Call original routine */ memFree (strtab); /* Prevent compiler warnings */ } /* ** */ FORTRAN ( \ SCOTCHFSTRATGRAPHORDERBUILD, scotchfstratgraphorderbuild, ( \ SCOTCH_Strat * const stratptr, \ const SCOTCH_Num * const flagval, \ const double * const balrat, \ int * const revaptr), \ (stratptr, flagval, balrat, revaptr)) { *revaptr = SCOTCH_stratGraphOrderBuild (stratptr, *flagval, *balrat); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_fold_comm.h0000644000175300017530000000760411631334325022577 0ustar hazelscthazelsct/* Copyright 2007,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_fold_comm.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the distributed source graph **/ /** building routines. **/ /** **/ /** # Version 5.0 : from : 23 may 2006 **/ /** to 19 aug 2006 **/ /** # Version 5.1 : from : 30 jul 2010 **/ /** to 03 jan 2011 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Starting maximum number of communications per process +*/ #define DGRAPHFOLDCOMMNBR 4 /* Starting maximum number of communications per process */ /* ** The type and structure definitions. */ /*+ Process communication type. Receivers that have more local vertices than needed can also be senders, hence the " = 1" to allow for or-ing both values. +*/ typedef enum DgraphFoldCommType_ { DGRAPHFOLDCOMMRECV = 1, /*+ Process is a receiver +*/ DGRAPHFOLDCOMMSEND /*+ Process is a sender +*/ } DgraphFoldCommType; /* Sort structure for processors. */ typedef struct DgraphFoldCommData_ { Gnum vertnbr; /* Number of vertices; TRICK: FIRST */ Gnum procnum; /* Processor index (Gnum for sorting) */ } DgraphFoldCommData; /* ** The function prototypes. */ int dgraphFoldComm (const Dgraph * restrict const, const int, int * restrict const, int * restrict const, DgraphFoldCommData * restrict * restrict const, Gnum * restrict * restrict const, Gnum * restrict const, int * restrict const, Gnum * restrict * restrict const, Gnum * restrict * restrict const); scotch-5.1.12b.dfsg/src/libscotch/common_file_uncompress.c0000644000175300017530000003116111631334325024046 0ustar hazelscthazelsct/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : common_file_uncompress.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles compressed streams **/ /** for uncompression. **/ /** **/ /** DATES : # Version 5.0 : from : 11 mar 2008 **/ /** to : 15 may 2008 **/ /** # Version 5.1 : from : 27 jun 2010 **/ /** to 27 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define COMMON_FILE #define COMMON_FILE_UNCOMPRESS #ifndef COMMON_NOMODULE #include "module.h" #endif /* COMMON_NOMODULE */ #include "common.h" #include "common_file.h" #include "common_file_compress.h" #ifdef COMMON_FILE_COMPRESS_BZ2 #include "bzlib.h" #endif /* COMMON_FILE_COMPRESS_BZ2 */ #ifdef COMMON_FILE_COMPRESS_GZ #include "zlib.h" #endif /* COMMON_FILE_COMPRESS_GZ */ #ifdef COMMON_FILE_COMPRESS_LZMA #include "lzmadec.h" /* TODO: Temporary interface */ #endif /* COMMON_FILE_COMPRESS_LZMA */ /* ** The static definitions. */ static FileCompressTab filetab[] = { #ifdef COMMON_FILE_COMPRESS_BZ2 { ".bz2", FILECOMPRESSTYPEBZ2, }, #else /* COMMON_FILE_COMPRESS_BZ2 */ { ".bz2", FILECOMPRESSTYPENOTIMPL }, #endif /* COMMON_FILE_COMPRESS_BZ */ #ifdef COMMON_FILE_COMPRESS_GZ { ".gz", FILECOMPRESSTYPEGZ, }, #else /* COMMON_FILE_COMPRESS_GZ */ { ".gz", FILECOMPRESSTYPENOTIMPL }, #endif /* COMMON_FILE_COMPRESS_GZ */ #ifdef COMMON_FILE_COMPRESS_LZMA { ".lzma", FILECOMPRESSTYPELZMA }, #else /* COMMON_FILE_COMPRESS_LZMA */ { ".lzma", FILECOMPRESSTYPENOTIMPL }, #endif /* COMMON_FILE_COMPRESS_LZMA */ { NULL, FILECOMPRESSTYPENOTIMPL } }; /*********************************/ /* */ /* Basic routines for filenames. */ /* */ /*********************************/ /* This routine searches the given file name ** for relevant extensions and returns the ** corresponding code if it is the case. ** It returns: ** - FILECOMPRESSTYPENONE : no recognized file extension. ** - FILECOMPRESSTYPENOTIMPL : compression algorithm not implemented. ** - FILECOMPRESSTYPExxxx : implemented compression algorithm. */ int fileUncompressType ( const char * const nameptr) /*+ Name string +*/ { int namelen; int i; namelen = strlen (nameptr); for (i = 0; filetab[i].name != NULL; i ++) { int extnlen; /* Name of extension string */ extnlen = strlen (filetab[i].name); if ((namelen >= extnlen) && (strncmp (filetab[i].name, nameptr + (namelen - extnlen), extnlen) == 0)) return (filetab[i].type); } return (FILECOMPRESSTYPENONE); } /* This routine creates a thread to uncompress the ** given stream according to the given (un)compression ** algorithm. ** If threads are available, uncompression will be ** performed by an auxiliary thread. Else, a child process ** will be fork()'ed, and after completion this process ** will remain a zombie until the main process terminates. ** It returns: ** - !NULL : stream holding uncompressed data. ** - NULL : on error. */ static void * /* (void *) to comply to the Posix pthread API */ fileUncompress2 ( FileCompressData * const dataptr) { switch (dataptr->typeval) { #ifdef COMMON_FILE_COMPRESS_BZ2 case FILECOMPRESSTYPEBZ2 : fileUncompressBz2 (dataptr); break; #endif /* COMMON_FILE_COMPRESS_BZ2 */ #ifdef COMMON_FILE_COMPRESS_GZ case FILECOMPRESSTYPEGZ : fileUncompressGz (dataptr); break; #endif /* COMMON_FILE_COMPRESS_GZ */ #ifdef COMMON_FILE_COMPRESS_LZMA case FILECOMPRESSTYPELZMA : fileUncompressLzma (dataptr); break; #endif /* COMMON_FILE_COMPRESS_LZMA */ default : errorPrint ("fileUncompress2: method not implemented"); } close (dataptr->innerfd); /* Close writer's end */ memFree (dataptr); /* Free buffers */ return ((void *) 0); /* Don't care anyway */ } FILE * fileUncompress ( FILE * const stream, /*+ Compressed stream +*/ const int typeval) /*+ (Un)compression algorithm +*/ { int filetab[2]; FILE * readptr; FileCompressData * dataptr; #ifdef COMMON_PTHREAD pthread_t thrdval; #endif /* COMMON_PTHREAD */ if (typeval <= FILECOMPRESSTYPENONE) /* If uncompressed stream, return original stream pointer */ return (stream); if (pipe (filetab) != 0) { errorPrint ("fileUncompress: cannot create pipe"); return (NULL); } if ((readptr = fdopen (filetab[0], "r")) == NULL) { errorPrint ("fileUncompress: cannot create stream"); close (filetab[0]); close (filetab[1]); return (NULL); } if ((dataptr = memAlloc (sizeof (FileCompressData) + FILECOMPRESSDATASIZE)) == NULL) { errorPrint ("fileUncompress: out of memory"); fclose (readptr); close (filetab[1]); return (NULL); } dataptr->typeval = typeval; /* Fill structure to be passed to uncompression thread/process */ dataptr->innerfd = filetab[1]; dataptr->outerstream = stream; #ifdef COMMON_PTHREAD if (pthread_create (&thrdval, NULL, (void * (*) (void *)) fileUncompress2, (void *) dataptr) != 0) { /* If could not create thread */ errorPrint ("fileUncompress: cannot create thread"); memFree (dataptr); fclose (readptr); close (filetab[1]); return (NULL); } pthread_detach (thrdval); /* Detach thread so that it will end up gracefully by itself */ #else /* COMMON_PTHREAD */ switch (fork ()) { case -1 : /* Error */ errorPrint ("fileUncompress: cannot create child process"); memFree (dataptr); fclose (readptr); close (filetab[1]); return (NULL); case 0 : /* We are the son process */ fclose (readptr); /* Close reader pipe stream */ fileUncompress2 (dataptr); /* Perform uncompression */ exit (0); /* Exit gracefully */ default : /* We are the father process */ close (filetab[1]); /* Close the writer pipe end */ } #endif /* COMMON_PTHREAD */ return (readptr); } /* This routine uncompresses a stream compressed in the ** bzip2 format. ** It returns: ** - void : in all cases. Uncompression stops immediately ** in case of error. */ #ifdef COMMON_FILE_COMPRESS_BZ2 static void fileUncompressBz2 ( FileCompressData * const dataptr) { BZFILE * bzfile; int bzsize; int bzerror; if (FILECOMPRESSDATASIZE < (BZ_MAX_UNUSED)) { errorPrint ("fileUncompressBz2: cannot start decompression (1)"); return; } if ((bzfile = BZ2_bzReadOpen (&bzerror, dataptr->outerstream, 0, 0, NULL, 0)) == NULL) { errorPrint ("fileUncompressBz2: cannot start decompression (2)"); BZ2_bzReadClose (&bzerror, bzfile); return; } while ((bzsize = BZ2_bzRead (&bzerror, bzfile, &dataptr->datatab, FILECOMPRESSDATASIZE), bzerror) >= BZ_OK) { /* If BZ_OK or BZ_STREAM_END */ if (write (dataptr->innerfd, &dataptr->datatab, bzsize) != bzsize) { errorPrint ("fileUncompressBz2: cannot write"); bzerror = BZ_STREAM_END; /* Avoid other error message */ break; } if (bzerror == BZ_STREAM_END) { /* If end of compressed stream */ void * bzunusptr; int bzunusnbr; BZ2_bzReadGetUnused (&bzerror, bzfile, &bzunusptr, &bzunusnbr); /* Get remaining chars in stream */ if ((bzunusnbr == 0) && (feof (dataptr->outerstream) != 0)) { /* If end of uncompressed stream too */ bzerror = BZ_STREAM_END; break; } memMov (&dataptr->datatab, bzunusptr, bzunusnbr); BZ2_bzReadClose (&bzerror, bzfile); if ((bzfile = BZ2_bzReadOpen (&bzerror, dataptr->outerstream, 0, 0, &dataptr->datatab, bzunusnbr)) == NULL) { errorPrint ("fileUncompressBz2: cannot start decompression (3)"); bzerror = BZ_STREAM_END; break; } } } if (bzerror != BZ_STREAM_END) errorPrint ("fileUncompressBz2: cannot read"); BZ2_bzReadClose (&bzerror, bzfile); fclose (dataptr->outerstream); /* Do as zlib does */ } #endif /* COMMON_FILE_COMPRESS_BZ2 */ /* This routine uncompresses a stream compressed in the ** gzip format. ** It returns: ** - void : in all cases. Uncompression stops immediately ** in case of error. */ #ifdef COMMON_FILE_COMPRESS_GZ static void fileUncompressGz ( FileCompressData * const dataptr) { gzFile gzfile; int gzsize; if ((gzfile = gzdopen (fileno (dataptr->outerstream), "rb")) == NULL) { errorPrint ("fileUncompressGz: cannot start decompression"); return; } while ((gzsize = gzread (gzfile, &dataptr->datatab, FILECOMPRESSDATASIZE)) > 0) { if (write (dataptr->innerfd, &dataptr->datatab, gzsize) != gzsize) { errorPrint ("fileUncompressGz: cannot write"); break; } } if (gzsize < 0) errorPrint ("fileUncompressGz: cannot read"); gzclose (gzfile); } #endif /* COMMON_FILE_COMPRESS_GZ */ /* This routine uncompresses a stream compressed in the ** lzma format. ** It returns: ** - void : in all cases. Uncompression stops immediately ** in case of error. */ #ifdef COMMON_FILE_COMPRESS_LZMA static void fileUncompressLzma ( FileCompressData * const dataptr) { lzmadec_FILE * lzmafile; ssize_t lzmasize; if ((lzmafile = lzmadec_dopen (fileno (dataptr->outerstream))) == NULL) { errorPrint ("fileUncompressLzma: cannot start decompression"); return; } while ((lzmasize = lzmadec_read (lzmafile, (void *) &dataptr->datatab, FILECOMPRESSDATASIZE)) > 0) { if (write (dataptr->innerfd, &dataptr->datatab, lzmasize) != lzmasize) { errorPrint ("fileUncompressLzma: cannot write"); break; } } if (lzmasize < 0) errorPrint ("fileUncompressLzma: cannot read"); lzmadec_close (lzmafile); } #endif /* COMMON_FILE_COMPRESS_LZMA */ scotch-5.1.12b.dfsg/src/libscotch/parser_yy.h0000644000175300017530000001013011631334325021314 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : parser_yy.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a static mapper. **/ /** These lines are the declarations for **/ /** the strategy strings syntactic parser. **/ /** **/ /** DATES : # Version 3.1 : from : 07 nov 1995 **/ /** to 30 may 1996 **/ /** # Version 3.2 : from : 03 oct 1996 **/ /** to 19 oct 1996 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 20 dec 2001 **/ /** to 21 dec 2001 **/ /** # Version 5.1 : from : 09 jun 2009 **/ /** to 07 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines. */ /* Change some function names. */ #if ((defined SCOTCH_RENAME_PARSER) || (defined yylex)) /* If prefix renaming */ #define scotchyyparse stratParserParse2 /* Parser function name */ #define scotchyyerror stratParserError /* Error processing routine */ #ifndef yylval #define yylval scotchyylval /* It should be Yacc/Bison's job to redefine it! */ #endif /* yylval */ #else /* SCOTCH_RENAME_PARSER */ #define yylex stratParserLex /* Lexical analyzer */ #define yyparse stratParserParse2 /* Parser function name */ #define yyerror stratParserError /* Error processing routine */ #endif /* SCOTCH_RENAME_PARSER */ /* ** The function prototypes. */ #ifndef PARSER_YY #define static #endif int yylex (void); Strat * stratParserParse (const StratTab * const, const char * const); int stratParserParse2 (void); static int stratParserError (const char * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_io_load_f.c0000644000175300017530000001136011631334325024264 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_io_load_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the distributed source graph handling **/ /** routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 13 may 2007 **/ /** to 13 may 2007 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 27 mar 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the graph handling routines. */ /* */ /**************************************/ /* When an input stream is built from the given ** file handle, it is set as unbuffered, so as to ** allow for multiple stream reads from the same ** file handle. If it were buffered, too many ** input characters would be read on the first ** block read. */ FORTRAN ( \ SCOTCHFDGRAPHLOAD, scotchfdgraphload, ( \ SCOTCH_Dgraph * const grafptr, \ int * const fileptr, \ const SCOTCH_Num * const baseptr, \ const SCOTCH_Num * const flagptr, \ int * const revaptr), \ (grafptr, fileptr, baseptr, flagptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if (*fileptr == -1) /* If process does not want to open a stream */ stream = NULL; else { if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFDGRAPHLOAD: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFDGRAPHLOAD: cannot open input stream"); close (filenum); *revaptr = 1; return; } setbuf (stream, NULL); /* Do not buffer on input */ } errorPrint ("SCOTCHFDGRAPHLOAD: not implemented"); o = SCOTCH_dgraphLoad (grafptr, stream, *baseptr, *flagptr); if (stream != NULL) /* If process has an open stream */ fclose (stream); /* This closes filenum too */ *revaptr = o; } scotch-5.1.12b.dfsg/src/libscotch/mapping.c0000644000175300017530000001613011631334325020733 0ustar hazelscthazelsct/* Copyright 2004,2007-2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mapping.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles (partial) mappings. **/ /** **/ /** DATES : # Version 0.0 : from : 31 mar 1993 **/ /** to 31 mar 1993 **/ /** # Version 1.0 : from : 04 oct 1993 **/ /** to 06 oct 1993 **/ /** # Version 1.1 : from : 15 oct 1993 **/ /** to 15 oct 1993 **/ /** # Version 1.3 : from : 09 apr 1994 **/ /** to 11 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 17 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to 18 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 19 oct 1995 **/ /** # Version 3.1 : from : 30 oct 1995 **/ /** to 14 jun 1996 **/ /** # Version 3.2 : from : 23 aug 1996 **/ /** to 07 sep 1998 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to 30 mar 1999 **/ /** # Version 3.4 : from : 11 sep 2001 **/ /** to 08 nov 2001 **/ /** # Version 4.0 : from : 16 jan 2004 **/ /** to 05 jan 2005 **/ /** # Version 5.1 : from : 25 jun 2008 **/ /** to 28 apr 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MAPPING #include "module.h" #include "common.h" #include "graph.h" #include "arch.h" #include "mapping.h" /***********************************/ /* */ /* These routines handle mappings. */ /* */ /***********************************/ /* This routine builds a mapping. ** It returns: ** - 0 : if mapping successfully initialized. ** - !0 : on error. */ int mapInit2 ( Mapping * restrict const mappptr, /*+ Mapping structure to fill +*/ const Gnum baseval, /*+ Base value +*/ const Gnum vertnbr, const Arch * restrict const archptr, const ArchDom * restrict const domnptr) /*+ Pointer to initial (sub)domain +*/ { Anum domnmax; /* Maximum number of domains */ Anum * restrict parttab; /* Temporary pointer to part array */ if (archVar (archptr)) /* If target architecture is variable-sized */ domnmax = (vertnbr > 1024) ? 1024 : vertnbr; /* Pre-set number of domains */ else /* Else if fixed architecture */ domnmax = archDomSize (archptr, domnptr); /* Get architecture size */ #ifdef SCOTCH_DEBUG_MAP2 if (domnmax <= 0) { errorPrint ("mapInit2: target architecture must have at least one domain"); return (1); } #endif /* SCOTCH_DEBUG_MAP2 */ mappptr->baseval = baseval; mappptr->vertnbr = vertnbr; mappptr->domnmax = domnmax + 1; /* +1 for empty domain in mapLoad */ mappptr->domnnbr = 1; /* One domain in mapping to date */ mappptr->archdat = *archptr; mappptr->domnorg = *domnptr; if ((parttab = (Anum *) memAlloc (vertnbr * sizeof (Anum))) == NULL) { /* Allocate part array first as it will never move */ errorPrint ("mapInit: out of memory (1)"); return (1); } mappptr->parttax = parttab - baseval; memSet (parttab, 0, vertnbr * sizeof (Anum)); /* All vertices mapped to first domain */ if ((mappptr->domntab = (ArchDom *) memAlloc ((domnmax + 1) * sizeof (ArchDom))) == NULL) { /* Allocate possibly variable-sized domain array */ errorPrint ("mapInit: out of memory (2)"); return (1); } mappptr->domntab[0] = *domnptr; /* Set first domain */ return (0); } int mapInit ( Mapping * restrict const mappptr, const Gnum baseval, const Gnum vertnbr, const Arch * restrict const archptr) { ArchDom domnorg; /* First, largest, domain */ archDomFrst (archptr, &domnorg); /* Get first domain of target architecture */ return (mapInit2 (mappptr, baseval, vertnbr, archptr, &domnorg)); } /* This routine frees the contents ** of the given mapping. ** It returns: ** - VOID : in all cases. */ void mapExit ( Mapping * const mappptr) { if (mappptr->domntab != NULL) memFree (mappptr->domntab); if (mappptr->parttax != NULL) memFree (mappptr->parttax + mappptr->baseval); #ifdef SCOTCH_DEBUG_MAP2 memSet (mappptr, ~0, sizeof (Mapping)); #endif /* SCOTCH_DEBUG_MAP2 */ } scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_fm.c0000644000175300017530000012770711631334325022603 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_fm.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module bipartitions an active **/ /** graph using our improvements of the **/ /** Fiduccia-Mattheyses heuristics. **/ /** **/ /** DATES : # Version 1.0 : from : 30 sep 1993 **/ /** to 09 oct 1993 **/ /** # Version 1.1 : from : 15 oct 1993 **/ /** to 15 oct 1993 **/ /** # Version 1.2 : from : 07 feb 1994 **/ /** to 15 feb 1994 **/ /** # Version 1.3 : from : 06 apr 1994 **/ /** to 30 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 03 nov 1994 **/ /** # Version 3.1 : from : 06 nov 1995 **/ /** to 07 jun 1996 **/ /** # Version 3.2 : from : 21 sep 1996 **/ /** to 13 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 12 mar 1999 **/ /** # Version 3.4 : from : 01 jun 2001 **/ /** to 01 jun 2001 **/ /** # Version 4.0 : from : 20 dec 2003 **/ /** to 05 may 2006 **/ /** # Version 5.0 : from : 24 mar 2008 **/ /** to : 22 may 2008 **/ /** # Version 5.1 : from : 30 oct 2008 **/ /** to : 14 apr 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BGRAPH_BIPART_FM #include "module.h" #include "common.h" #include "gain.h" #include "graph.h" #include "arch.h" #include "bgraph.h" #include "bgraph_bipart_fm.h" #include "bgraph_bipart_gg.h" /*********************************/ /* */ /* Gain table handling routines. */ /* */ /*********************************/ /* This routine returns the vertex of best gain ** whose swap will keep the balance correct. ** It returns: ** - !NULL : pointer to the vertex. ** - NULL : if no more vertices available. */ static BgraphBipartFmVertex * bgraphBipartFmTablGet ( GainTabl * restrict const tablptr, /*+ Gain table +*/ const Gnum deltcur, /*+ Current imbalance +*/ const Gnum deltmin, /*+ Minimum imbalance +*/ const Gnum deltmax) /*+ Maximum imbalance +*/ { BgraphBipartFmVertex * vexxptr; BgraphBipartFmVertex * vertbest; Gnum gainbest; const GainEntr * tablbest; Gnum deltbest; tablbest = tablptr->tend; /* Assume no candidate vertex found yet */ gainbest = GAINMAX; vertbest = NULL; deltbest = deltmax; for (vexxptr = (BgraphBipartFmVertex *) gainTablFrst (tablptr); /* Select candidate vertices */ (vexxptr != NULL) && (vexxptr->gainlink.tabl < tablbest); vexxptr = (BgraphBipartFmVertex *) gainTablNext (tablptr, &vexxptr->gainlink)) { Gnum deltnew; deltnew = deltcur + vexxptr->compgain; if ((deltnew >= deltmin) && /* If vertex enforces balance */ (deltnew <= deltmax)) { deltnew = abs (deltnew); if ((vexxptr->commgain < gainbest) || /* And if it gives better gain */ ((vexxptr->commgain == gainbest) && /* Or if it gives better load */ (deltnew < deltbest))) { tablbest = vexxptr->gainlink.tabl; /* Select it */ gainbest = vexxptr->commgain; vertbest = vexxptr; deltbest = deltnew; } } } return (vertbest); } /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the bipartitioning. ** It returns: ** - 0 : if bipartitioning could be computed. ** - 1 : on error. */ int bgraphBipartFm ( Bgraph * restrict const grafptr, /*+ Active graph +*/ const BgraphBipartFmParam * const paraptr) /*+ Method parameters +*/ { GainTabl * restrict tablptr; /* Pointer to gain table */ INT passnbr; /* Maximum number of passes to go */ BgraphBipartFmSave * restrict savetab; /* Pointer to move array */ Gnum movenbr; /* Number of uneffective moves done */ Gnum savenbr; /* Number of recorded backtrack moves */ Gnum mswpnum; /* Current number of recording sweep */ int moveflag; /* Flag set if useful moves made */ int swapval; /* Flag set if global swap performed */ int swapvalbst; /* Recorded swap value for best position */ Gnum hashsiz; /* Size of hash table */ Gnum hashmsk; /* Mask for access to hash table */ Gnum hashnum; /* Hash value */ BgraphBipartFmVertex * lockptr; /* Linked list of locked vertices */ BgraphBipartFmVertex * restrict hashtab; /* Extended vertex array */ Gnum hashmax; Gnum hashnbr; Gnum compload0dltmit; /* Theoretical smallest imbalance allowed */ Gnum compload0dltmat; /* Theoretical largest imbalance allowed */ Gnum compload0dltmin; /* Smallest imbalance allowed */ Gnum compload0dltmax; /* Largest imbalance allowed */ Gnum compload0dltbst; /* Best imbalance value found to date */ Gnum compload0dlt; /* Current imbalance */ Gnum compsize0dlt; /* Update of size of part 0 */ Gnum commgainextn; /* Current external communication gain */ Gnum commgainextnbst; /* External gain of best recorded position */ Gnum commload; /* Communication load of current position */ Gnum commloadbst; /* Best communication load to date */ Gnum domdist; /* Distance between the two subdomains */ Gnum fronnbr; Gnum fronnum; const Gnum * restrict const verttax = grafptr->s.verttax; /* Fast accesses */ const Gnum * restrict const vendtax = grafptr->s.vendtax; const Gnum * restrict const velotax = grafptr->s.velotax; const Gnum * restrict const edgetax = grafptr->s.edgetax; const Gnum * restrict const edlotax = grafptr->s.edlotax; compload0dltmat = (paraptr->deltval <= 0.0L) ? 0 : ((Gnum) ((double) grafptr->s.velosum * paraptr->deltval / (double) MAX (grafptr->domwght[0], grafptr->domwght[1])) + 1); compload0dltmit = MAX ((grafptr->compload0min - grafptr->compload0avg), - compload0dltmat); compload0dltmat = MIN ((grafptr->compload0max - grafptr->compload0avg), compload0dltmat); compload0dltmin = MIN (grafptr->compload0dlt, compload0dltmit); /* Set current maximum distance */ compload0dltmax = MAX (grafptr->compload0dlt, compload0dltmat); if (grafptr->fronnbr == 0) { /* If no current frontier */ if ((grafptr->compload0dlt >= compload0dltmit) && /* If balance is correct */ (grafptr->compload0dlt <= compload0dltmat)) return (0); /* Nothing to do */ else { /* Imbalance must be fought */ BgraphBipartGgParam paradat; paradat.passnbr = 4; /* Use a standard algorithm */ if (bgraphBipartGg (grafptr, ¶dat) != 0) /* Return if error */ return (1); if (grafptr->fronnbr == 0) /* If new partition has no frontier */ return (0); /* This algorithm is still useless */ compload0dltmin = MIN (compload0dltmit, grafptr->compload0dlt); compload0dltmax = MAX (compload0dltmat, grafptr->compload0dlt); } } #ifdef SCOTCH_DEBUG_BGRAPH2 hashnbr = 2 * grafptr->fronnbr + 1; /* Ensure resizing will be performed, for maximum code coverage */ #else /* SCOTCH_DEBUG_BGRAPH2 */ hashnbr = 4 * (grafptr->fronnbr + paraptr->movenbr + grafptr->s.degrmax); #endif /* SCOTCH_DEBUG_BGRAPH2 */ if (hashnbr > grafptr->s.vertnbr) hashnbr = grafptr->s.vertnbr; for (hashsiz = 256; hashsiz < hashnbr; hashsiz <<= 1) ; /* Get upper power of two */ hashmsk = hashsiz - 1; hashmax = hashsiz >> 2; if ((tablptr = gainTablInit (GAIN_LINMAX, BGRAPHBIPARTFMSUBBITS)) != NULL) { void * hashtmp; /* Temporary variable for vertex array to avoid problems with "restrict" */ if (memAllocGroup ((void **) &hashtmp, (size_t) (hashsiz * sizeof (BgraphBipartFmVertex)), &savetab, (size_t) (hashsiz * sizeof (BgraphBipartFmSave)), NULL) == NULL) { errorPrint ("bgraphBipartFm: out of memory (1)"); gainTablExit (tablptr); return (1); } hashtab = hashtmp; } else return (1); memset (hashtab, ~0, hashsiz * sizeof (BgraphBipartFmVertex)); /* Set all vertex numbers to ~0 */ domdist = grafptr->domdist; for (fronnum = 0, hashnbr = grafptr->fronnbr; /* Set initial gains */ fronnum < hashnbr; fronnum ++) { Gnum vertnum; Gnum veloval; Gnum hashnum; Gnum edgenum; Gnum edloval; Gnum commcut; Gnum commgain; int partval; int partdlt; vertnum = grafptr->frontab[fronnum]; partval = grafptr->parttax[vertnum]; for (edgenum = verttax[vertnum], commcut = commgain = 0, edloval = 1; edgenum < vendtax[vertnum]; edgenum ++) { Gnum vertend; int partend; int partdlt; vertend = edgetax[edgenum]; partend = grafptr->parttax[vertend]; if (edlotax != NULL) edloval = edlotax[edgenum]; partdlt = partval ^ partend; commcut += partdlt; commgain += (1 - 2 * partdlt) * edloval; } commgain *= domdist; /* Adjust internal gains with respect to external gains */ partdlt = 2 * partval - 1; veloval = (velotax != NULL) ? velotax[vertnum] : 1; for (hashnum = (vertnum * BGRAPHBIPARTFMHASHPRIME) & hashmsk; hashtab[hashnum].vertnum != ~0; hashnum = (hashnum + 1) & hashmsk) ; hashtab[hashnum].vertnum = vertnum; /* Implicitely set slot as used */ hashtab[hashnum].partval = partval; hashtab[hashnum].compgain = partdlt * veloval; hashtab[hashnum].commgain = (grafptr->veextax == NULL) ? commgain : (commgain - partdlt * grafptr->veextax[vertnum]); hashtab[hashnum].commcut = commcut; hashtab[hashnum].mswpnum = 0; /* Implicitely set slot as used */ gainTablAdd (tablptr, (GainLink *) &hashtab[hashnum], hashtab[hashnum].commgain); } compload0dltbst = grafptr->compload0dlt; commloadbst = grafptr->commload; commgainextnbst = grafptr->commgainextn; swapvalbst = 0; /* No global swap performed yet */ #ifdef SCOTCH_DEBUG_BGRAPH2 #ifdef SCOTCH_DEBUG_BGRAPH3 if (bgraphBipartFmCheck (grafptr, hashtab, hashmsk, 0, compload0dltbst, commloadbst, commgainextnbst) != 0) { errorPrint ("bgraphBipartFm: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH3 */ #endif /* SCOTCH_DEBUG_BGRAPH2 */ passnbr = paraptr->passnbr; /* Set remaining number of passes */ savenbr = 0; /* For empty backtrack of first pass */ mswpnum = 0; /* Will be incremented afterwards */ lockptr = NULL; /* Locked list is empty */ do { /* As long as there are improvements */ BgraphBipartFmVertex * vexxptr; while (savenbr -- > 0) { /* Delete exceeding moves */ Gnum hashnum; int partval; hashnum = savetab[savenbr].hashnum; partval = savetab[savenbr].partval; hashtab[hashnum].partval = partval; /* Restore vertex data */ hashtab[hashnum].compgain = savetab[savenbr].compgain; hashtab[hashnum].commgain = savetab[savenbr].commgain; hashtab[hashnum].commcut = savetab[savenbr].commcut; if (hashtab[hashnum].gainlink.next >= BGRAPHBIPARTFMSTATELINK) { /* If vertex is linked */ gainTablDel (tablptr, &hashtab[hashnum].gainlink); /* Unlink it */ hashtab[hashnum].gainlink.next = BGRAPHBIPARTFMSTATEFREE; /* Set it as free */ } if ((hashtab[hashnum].gainlink.next == BGRAPHBIPARTFMSTATEFREE) && (partval == 2)) /* If vertex not locked and in separator */ gainTablAdd (tablptr, &hashtab[hashnum].gainlink, hashtab[hashnum].commgain); /* Re-link it */ } compload0dlt = compload0dltbst; /* Restore best separator parameters */ commload = commloadbst; commgainextn = commgainextnbst; swapval = swapvalbst; mswpnum ++; /* Forget all recorded moves */ #ifdef SCOTCH_DEBUG_BGRAPH2 #ifdef SCOTCH_DEBUG_BGRAPH3 if (bgraphBipartFmCheck (grafptr, hashtab, hashmsk, swapval, compload0dlt, commload, commgainextn) != 0) { errorPrint ("bgraphBipartFm: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH3 */ #endif /* SCOTCH_DEBUG_BGRAPH2 */ while (lockptr != NULL) { /* For all vertices in locked list */ BgraphBipartFmVertex * vexxptr; vexxptr = lockptr; /* Unlink vertex from list */ lockptr = (BgraphBipartFmVertex *) vexxptr->gainlink.prev; if (vexxptr->commcut > 0) /* If vertex has cut edges */ gainTablAdd (tablptr, (GainLink *) vexxptr, vexxptr->commgain); /* Put it in table */ else vexxptr->gainlink.next = BGRAPHBIPARTFMSTATEFREE; /* Set it free anyway */ } moveflag = 0; /* No useful moves made */ movenbr = 0; /* No uneffective moves recorded yet */ savenbr = 0; /* Back up to beginning of table */ while ((movenbr < paraptr->movenbr) && /* As long as we can find effective vertices */ ((vexxptr = (BgraphBipartFmVertex *) bgraphBipartFmTablGet (tablptr, compload0dlt, compload0dltmin, compload0dltmax)) != NULL)) { Gnum vertnum; /* Number of current vertex */ int partval; /* Part of current vertex */ Gnum edgenum; Gnum edloval; gainTablDel (tablptr, &vexxptr->gainlink); /* Remove it from table */ vexxptr->gainlink.next = BGRAPHBIPARTFMSTATEUSED; /* Mark it as used */ vexxptr->gainlink.prev = (GainLink *) lockptr; /* Lock it */ lockptr = vexxptr; vertnum = vexxptr->vertnum; partval = vexxptr->partval; if (vexxptr->mswpnum != mswpnum) { /* If vertex data not yet recorded */ vexxptr->mswpnum = mswpnum; savetab[savenbr].hashnum = vexxptr - hashtab; savetab[savenbr].partval = partval; savetab[savenbr].compgain = vexxptr->compgain; savetab[savenbr].commgain = vexxptr->commgain; savetab[savenbr].commcut = vexxptr->commcut; savenbr ++; /* One more move recorded */ } movenbr ++; /* One more move done */ commload += vexxptr->commgain; compload0dlt += vexxptr->compgain; if (grafptr->veextax != NULL) commgainextn += 2 * (2 * partval - 1) * grafptr->veextax[vertnum]; vexxptr->partval = partval ^ 1; /* Swap vertex first in case neighbors are added */ vexxptr->compgain = - vexxptr->compgain; vexxptr->commgain = - vexxptr->commgain; vexxptr->commcut = vendtax[vertnum] - verttax[vertnum] - vexxptr->commcut; edloval = 1; for (edgenum = verttax[vertnum]; /* (Re-)link neighbors */ edgenum < vendtax[vertnum]; edgenum ++) { Gnum vertend; /* Number of current end neighbor vertex */ Gnum hashnum; vertend = edgetax[edgenum]; if (edlotax != NULL) edloval = edlotax[edgenum]; for (hashnum = (vertend * BGRAPHBIPARTFMHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { if (hashtab[hashnum].vertnum == vertend) { /* If hash slot found */ int partdlt; if (hashtab[hashnum].mswpnum != mswpnum) { /* If vertex data not yet recorded */ savetab[savenbr].hashnum = hashnum; /* Record them */ savetab[savenbr].partval = hashtab[hashnum].partval; savetab[savenbr].compgain = hashtab[hashnum].compgain; savetab[savenbr].commgain = hashtab[hashnum].commgain; savetab[savenbr].commcut = hashtab[hashnum].commcut; hashtab[hashnum].mswpnum = mswpnum; savenbr ++; } partdlt = 2 * (partval ^ hashtab[hashnum].partval) - 1; hashtab[hashnum].commgain += (domdist * 2) * edloval * partdlt; hashtab[hashnum].commcut -= partdlt; if (hashtab[hashnum].gainlink.next != BGRAPHBIPARTFMSTATEUSED) { /* If vertex is of use */ if (hashtab[hashnum].gainlink.next >= BGRAPHBIPARTFMSTATELINK) { /* If vertex is linked */ gainTablDel (tablptr, &hashtab[hashnum].gainlink); /* Remove it from table */ hashtab[hashnum].gainlink.next = BGRAPHBIPARTFMSTATEFREE; /* Mark it as free anyway */ } if (hashtab[hashnum].commcut > 0) /* If vertex belongs to the frontier */ gainTablAdd (tablptr, &hashtab[hashnum].gainlink, hashtab[hashnum].commgain); /* Re-link it */ } break; } if (hashtab[hashnum].vertnum == ~0) { /* If hash slot empty */ Gnum commgain; /* Communication gain of current vertex */ Gnum commgainold; /* Old communication gain of current vertex */ Gnum veloval; Gnum veexval; int partold; int partdlt; if (hashnbr >= hashmax) { /* If extended vertex table is already full */ if (bgraphBipartFmResize (&hashtab, &hashmax, &hashmsk, &savetab, savenbr, tablptr, &lockptr) != 0) { errorPrint ("bgraphBipartFm: out of memory (2)"); memFree (hashtab); /* Free group leader */ gainTablExit (tablptr); } for (hashnum = (vertend * BGRAPHBIPARTFMHASHPRIME) & hashmsk; hashtab[hashnum].vertnum != ~0; hashnum = (hashnum + 1) & hashmsk) ; /* Search for new first free slot */ } if (edlotax != NULL) { /* If graph edges are weighted */ Gnum edgeend; for (edgeend = verttax[vertend], commgainold = 0; /* Compute neighbor edge load sum */ edgeend < vendtax[vertend]; edgeend ++) commgainold += edlotax[edgeend]; commgain = commgainold - 2 * edloval; } else { /* Graph edges are not weighted */ commgainold = vendtax[vertend] - verttax[vertend]; commgain = commgainold - 2; } veloval = 1; if (velotax != NULL) veloval = velotax[vertend]; veexval = 0; if (grafptr->veextax != NULL) veexval = grafptr->veextax[vertend]; #ifdef SCOTCH_DEBUG_BGRAPH2 if (grafptr->parttax[vertend] != (partval ^ swapval)) { errorPrint ("bgraphBipartFm: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ partold = partval ^ swapval ^ swapvalbst; /* Get part of vertex as in latest accepted configuration */ partdlt = 2 * partold - 1; /* Compute values to fill save table according to last stable configuration */ savetab[savenbr].hashnum = hashnum; /* Record initial state of new vertex */ savetab[savenbr].partval = partold; savetab[savenbr].compgain = partdlt * veloval; savetab[savenbr].commgain = commgainold * domdist - (partdlt * veexval); savetab[savenbr].commcut = 0; savenbr ++; partdlt = 2 * partval - 1; /* Compute values to fill hash table according to current configuration */ hashtab[hashnum].vertnum = vertend; hashtab[hashnum].partval = partval; /* It was a neighbor of the moved vertex, in current global swap state */ hashtab[hashnum].compgain = partdlt * veloval; hashtab[hashnum].commgain = commgain * domdist - (partdlt * veexval); hashtab[hashnum].commcut = 1; hashtab[hashnum].mswpnum = mswpnum; /* Vertex has just been saved */ hashnbr ++; /* One more vertex in hash table */ gainTablAdd (tablptr, (GainLink *) &hashtab[hashnum], hashtab[hashnum].commgain); break; } } } if (commload < commloadbst) { /* If move improves the cost */ compload0dltbst = compload0dlt; /* This move was effective */ commloadbst = commload; commgainextnbst = commgainextn; swapvalbst = swapval; moveflag = 1; movenbr = savenbr = 0; mswpnum ++; } else if (commload == commloadbst) { if (abs (compload0dlt) < abs (compload0dltbst)) { compload0dltbst = compload0dlt; /* This move was effective */ commgainextnbst = commgainextn; swapvalbst = swapval; moveflag = 1; movenbr = savenbr = 0; mswpnum ++; } else if (abs (compload0dlt) == abs (compload0dltbst)) { compload0dltbst = compload0dlt; /* Forget backtracking */ commgainextnbst = commgainextn; swapvalbst = swapval; savenbr = 0; mswpnum ++; } } if ((compload0dltmin < compload0dltmit) || /* If must restrict distance bounds */ (compload0dltmax > compload0dltmat)) { if ((compload0dlt > compload0dltmin) && /* If we have done something useful */ (compload0dlt < compload0dltmax)) { compload0dltmin = MIN (compload0dltmit, compload0dlt); /* Update bounds */ compload0dltmax = MAX (compload0dltmat, compload0dlt); compload0dltbst = compload0dlt; /* Record best move done */ commloadbst = commload; commgainextnbst = commgainextn; swapvalbst = swapval; moveflag = 1; movenbr = savenbr = 0; mswpnum ++; } } #ifdef SCOTCH_DEBUG_BGRAPH2 #ifdef SCOTCH_DEBUG_BGRAPH3 if (bgraphBipartFmCheck (grafptr, hashtab, hashmsk, swapval, compload0dlt, commload, commgainextn) != 0) { errorPrint ("bgraphBipartFm: internal error (4)"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH3 */ #endif /* SCOTCH_DEBUG_BGRAPH2 */ if (commgainextn < 0) { /* If global swap improves gain */ Gnum compload0dlttmp; #ifdef SCOTCH_DEBUG_BGRAPH2 if (grafptr->veextax == NULL) { /* commgainextn should always be 0 if (veextab == NULL) */ errorPrint ("bgraphBipartFm: internal error (5)"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ compload0dlttmp = grafptr->s.velosum - compload0dlt - 2 * grafptr->compload0avg; if (abs (compload0dlttmp) <= compload0dltmax) { /* If still within bounds, perform actual swapping */ Gnum hashnum; commload += commgainextn; /* Perform global swap */ commgainextn = - commgainextn; compload0dlt = compload0dlttmp; swapval ^= 1; for (hashnum = 0; hashnum <= hashmsk; hashnum ++) { /* hashsiz no longer valid after resizing, so use hashmsk */ Gnum commgain; if (hashtab[hashnum].mswpnum == ~0) /* If hash slot not used, skip it */ continue; if (hashtab[hashnum].mswpnum != mswpnum) { /* And vertex data not yet recorded */ hashtab[hashnum].mswpnum = mswpnum; /* Record them */ savetab[savenbr].hashnum = hashnum; savetab[savenbr].partval = hashtab[hashnum].partval; savetab[savenbr].compgain = hashtab[hashnum].compgain; savetab[savenbr].commgain = hashtab[hashnum].commgain; savetab[savenbr].commcut = hashtab[hashnum].commcut; savenbr ++; } hashtab[hashnum].partval ^= 1; /* Swap the vertex */ hashtab[hashnum].compgain = - hashtab[hashnum].compgain; commgain = grafptr->veextax[hashtab[hashnum].vertnum]; if (commgain != 0) { /* If vertex has external cocycle edges */ hashtab[hashnum].commgain += 2 * (1 - 2 * hashtab[hashnum].partval) * commgain; /* Compute new gain */ if (hashtab[hashnum].gainlink.next >= BGRAPHBIPARTFMSTATELINK) { /* If vertex is linked */ gainTablDel (tablptr, &hashtab[hashnum].gainlink); /* Remove it from table */ gainTablAdd (tablptr, &hashtab[hashnum].gainlink, hashtab[hashnum].commgain); /* Re-link it */ } } } if ((commload < commloadbst) || /* If move improves cost */ ((commload == commloadbst) && (abs (compload0dlt) < abs (compload0dltbst)))) { compload0dltbst = compload0dlt; /* Then record best move done */ commloadbst = commload; commgainextnbst = commgainextn; swapvalbst = swapval; moveflag = 1; movenbr = savenbr = 0; mswpnum ++; } #ifdef SCOTCH_DEBUG_BGRAPH2 #ifdef SCOTCH_DEBUG_BGRAPH3 if (bgraphBipartFmCheck (grafptr, hashtab, hashmsk, swapval, compload0dlt, commload, commgainextn) != 0) { errorPrint ("bgraphBipartFm: internal error (6)"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH3 */ #endif /* SCOTCH_DEBUG_BGRAPH2 */ } } } } while ((moveflag != 0) && /* As long as vertices are moved */ (-- passnbr != 0)); /* And we are allowed to loop (TRICK for negative values) */ #ifdef SCOTCH_DEBUG_BGRAPH2 #ifdef SCOTCH_DEBUG_BGRAPH3 if (bgraphBipartFmCheck (grafptr, hashtab, hashmsk, swapval, compload0dlt, commload, commgainextn) != 0) { errorPrint ("bgraphBipartFm: internal error (7)"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH3 */ #endif /* SCOTCH_DEBUG_BGRAPH2 */ compsize0dlt = 0; /* No difference to number of vertices yet */ if (swapvalbst != 0) { /* If global swap needed */ Gnum vertnum; compsize0dlt = grafptr->s.vertnbr - 2 * grafptr->compsize0; /* Set difference so as to swap all vertices */ for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) /* Swap all vertices in part array */ grafptr->parttax[vertnum] ^= 1; } while (savenbr -- > 0) { /* Delete exceeding moves */ Gnum hashnum; hashnum = savetab[savenbr].hashnum; hashtab[hashnum].partval = savetab[savenbr].partval; /* Restore vertex data */ hashtab[hashnum].commcut = savetab[savenbr].commcut; } compload0dlt = compload0dltbst; /* Restore best separator parameters */ commload = commloadbst; commgainextn = commgainextnbst; for (hashnum = fronnbr = 0; /* Build new frontier */ hashnum <= hashmsk; hashnum ++) { /* hashsiz no longer valid after resizing, so use hashmsk */ Gnum vertnum; int partval; vertnum = hashtab[hashnum].vertnum; /* Get vertex data from slot */ if (vertnum == ~0) continue; partval = hashtab[hashnum].partval; if (grafptr->parttax[vertnum] != partval) { /* If vertex part changed */ grafptr->parttax[vertnum] = partval; /* Set new part value */ compsize0dlt += (1 - 2 * partval); /* Adjust size of part 0 accordingly */ } if (hashtab[hashnum].commcut > 0) /* If vertex belongs to cut */ grafptr->frontab[fronnbr ++] = vertnum; /* Add vertex to frontier */ } grafptr->fronnbr = fronnbr; grafptr->compload0 = compload0dlt + grafptr->compload0avg; grafptr->compload0dlt = compload0dlt; grafptr->compsize0 += compsize0dlt; grafptr->commload = commload; grafptr->commgainextn = commgainextn; grafptr->bbalval = (double) ((grafptr->compload0dlt < 0) ? (- grafptr->compload0dlt) : grafptr->compload0dlt) / (double) grafptr->compload0avg; #ifdef SCOTCH_DEBUG_BGRAPH2 if (bgraphCheck (grafptr) != 0) { errorPrint ("bgraphBipartFm: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ memFree (hashtab); /* Free group leader */ gainTablExit (tablptr); return (0); } /* This routine doubles the size all of the arrays ** involved in handling the hash table and hash ** vertex arrays. ** It returns: ** - 0 : if resizing succeeded. ** - !0 : if out of memory. */ static int bgraphBipartFmResize ( BgraphBipartFmVertex * restrict * hashtabptr, /*+ Extended vertex array +*/ Gnum * restrict const hashmaxptr, /*+ Size of vertex array +*/ Gnum * const hashmskptr, /*+ Pointer to hash table mask +*/ BgraphBipartFmSave * restrict * savetabptr, /*+ Move array +*/ const Gnum savenbr, /*+ Number of moves recorded +*/ GainTabl * const tablptr, /*+ Gain table +*/ BgraphBipartFmVertex ** const lockptr) /*+ Pointer to locked list +*/ { BgraphBipartFmVertex * restrict hashtab; /* Extended vertex array */ BgraphBipartFmSave * savetab; /* Move backtracking array */ BgraphBipartFmSave * saveold; /* Pointer to translated old save array */ Gnum savenum; Gnum hashold; /* Size of old hash table (half of new) */ Gnum hashsiz; Gnum hashmax; Gnum hashmsk; Gnum hashsta; /* Start index of range of hash indices to move */ Gnum hashend; /* End index of range of hash indices to move */ Gnum hashnum; hashmax = *hashmaxptr << 1; /* Compute new sizes */ hashold = *hashmaxptr << 2; hashsiz = *hashmaxptr << 3; hashmsk = hashsiz - 1; #ifdef SCOTCH_DEBUG_BGRAPH2 if (sizeof (BgraphBipartFmVertex) < sizeof (BgraphBipartFmSave)) { /* Should always be true */ errorPrint ("bgraphBipartFmResize: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ if (memReallocGroup ((void *) *hashtabptr, &hashtab, (size_t) (hashsiz * sizeof (BgraphBipartFmVertex)), &savetab, (size_t) (hashsiz * sizeof (BgraphBipartFmSave)), NULL) == NULL) { errorPrint ("bgraphBipartFmResize: out of memory"); return (1); } saveold = (BgraphBipartFmSave *) ((byte *) hashtab + ((byte *) *savetabptr - (byte *) *hashtabptr)); for (savenum = savenbr - 1; savenum >= 0; savenum --) { /* Move save array, in reverse order */ savetab[savenum].commcut = saveold[savenum].commcut; savetab[savenum].commgain = saveold[savenum].commgain; savetab[savenum].compgain = saveold[savenum].compgain; savetab[savenum].partval = saveold[savenum].partval; savetab[savenum].hashnum = hashtab[saveold[savenum].hashnum].vertnum; /* Temporarily translate from hash index to number */ } *hashtabptr = hashtab; *hashmaxptr = hashmax; *hashmskptr = hashmsk; *savetabptr = savetab; memSet (hashtab + hashold, ~0, hashold * sizeof (BgraphBipartFmVertex)); gainTablFree (tablptr); /* Reset gain table */ *lockptr = NULL; /* Rebuild lock list */ for (hashsta = hashold - 1; hashtab[hashsta].vertnum != ~0; hashsta --) ; /* Start index of first segment to reconsider is last empty slot */ hashend = hashold; /* First segment to reconsider ends at the end of the old array */ while (hashend != hashsta) { /* For each of the two segments to consider */ for (hashnum = hashsta; hashnum < hashend; hashnum ++) { /* Re-compute position of vertices in new table */ Gnum vertnum; vertnum = hashtab[hashnum].vertnum; if (vertnum != ~0) { /* If hash slot used */ Gnum hashnew; for (hashnew = (vertnum * BGRAPHBIPARTFMHASHPRIME) & hashmsk; ; hashnew = (hashnew + 1) & hashmsk) { if (hashnew == hashnum) /* If hash slot is the same */ break; /* There is nothing to do */ if (hashtab[hashnew].vertnum == ~0) { /* If new slot is empty */ #ifdef SCOTCH_DEBUG_BGRAPH2 if ((hashnew > hashnum) && (hashnew < hashend)) { /* If vertex is not moved either before its old position or after the end of the segment */ errorPrint ("bgraphBipartFmResize: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ hashtab[hashnew] = hashtab[hashnum]; /* Copy data to new slot */ hashtab[hashnum].mswpnum = ~0; /* TRICK: not tested at creation */ hashtab[hashnum].vertnum = ~0; /* Make old slot empty */ break; } } if (hashtab[hashnew].gainlink.next >= BGRAPHBIPARTFMSTATELINK) /* If vertex was linked, re-link it */ gainTablAdd (tablptr, &hashtab[hashnew].gainlink, hashtab[hashnew].compgain); else if (hashtab[hashnew].gainlink.next == BGRAPHBIPARTFMSTATEUSED) { /* Re-lock used vertices */ hashtab[hashnew].gainlink.prev = (GainLink *) *lockptr; /* Lock it */ *lockptr = &hashtab[hashnew]; } } } hashend = hashsta; /* End of second segment to consider is start of first one */ hashsta = 0; /* Start of second segment is beginning of array */ } /* After second segment, hashsta = hashend = 0 and loop stops */ for (savenum = 0; savenum < savenbr; savenum ++) { Gnum vertnum; Gnum hashnum; vertnum = savetab[savenum].hashnum; /* Get vertex number temporarily saved */ for (hashnum = (vertnum * BGRAPHBIPARTFMHASHPRIME) & hashmsk; hashtab[hashnum].vertnum != vertnum; hashnum = (hashnum + 1) & hashmsk) { #ifdef SCOTCH_DEBUG_BGRAPH2 if (hashtab[hashnum].vertnum == ~0) { errorPrint ("bgraphBipartFmResize: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ } savetab[savenum].hashnum = hashnum; /* Set new hash table index */ } return (0); } /* This routine checks the consistency of ** the hash structures. ** It returns: ** - 0 : in case of success. ** - !0 : in case of error. */ #ifdef SCOTCH_DEBUG_BGRAPH2 #ifdef SCOTCH_DEBUG_BGRAPH3 static int bgraphBipartFmCheck ( const Bgraph * restrict const grafptr, const BgraphBipartFmVertex * restrict const hashtab, const Gnum hashmsk, const int swapval, const Gnum compload0dlt, const Gnum commload, const Gnum commgainextn) { Gnum domdist; Gnum hashnum; Gnum compload0tmp; Gnum commloaddlttmp; /* Difference between old and current communication load */ Gnum commloadextndlttmp; Gnum commgainextntmp; domdist = grafptr->domdist; compload0tmp = (swapval == 0) ? grafptr->compload0 : (grafptr->s.velosum - grafptr->compload0); commloaddlttmp = 0; /* No difference yet */ commloadextndlttmp = swapval * grafptr->commgainextn; commgainextntmp = (1 - 2 * swapval) * grafptr->commgainextn; for (hashnum = 0; hashnum <= hashmsk; hashnum ++) { /* For all vertex slots */ Gnum vertnum; Gnum veloval; Gnum veexval; Gnum edgenum; int partval; int partold; Gnum commcut; Gnum commgain; Gnum commgainextn; vertnum = hashtab[hashnum].vertnum; if (vertnum == ~0) /* If unallocated slot */ continue; /* Skip to next slot */ veloval = (velotax != NULL) ? velotax[vertnum] : 1; partval = hashtab[hashnum].partval; if ((partval < 0) || (partval > 1)) { errorPrint ("bgraphBipartFmCheck: invalid vertex part value"); return (1); } if (hashtab[hashnum].compgain != (2 * partval - 1) * veloval) { errorPrint ("bgraphBipartFmCheck: invalid vertex computation gain"); return (1); } partold = grafptr->parttax[vertnum] ^ swapval; veexval = (grafptr->veextax != NULL) ? grafptr->veextax[vertnum] : 0; compload0tmp += (partval ^ partold) * (1 - 2 * partval) * veloval; commgainextn = (1 - 2 * partval) * veexval; commgainextntmp += (partval ^ partold) * commgainextn * 2; commloadextndlttmp -= (partval ^ partold) * commgainextn; commcut = commgain = 0; for (edgenum = verttax[vertnum]; /* For all neighbors */ edgenum < vendtax[vertnum]; edgenum ++) { Gnum edloval; Gnum vertend; Gnum hashend; int partend; int partond; int partdlt; vertend = edgetax[edgenum]; partond = grafptr->parttax[vertend] ^ swapval; edloval = (edlotax != NULL) ? edlotax[edgenum] : 1; for (hashend = (vertend * BGRAPHBIPARTFMHASHPRIME) & hashmsk; ; hashend = (hashend + 1) & hashmsk) { if (hashtab[hashend].vertnum == vertend) { /* If end vertex found */ partend = hashtab[hashend].partval; break; } if (hashtab[hashend].vertnum == ~0) { /* If end vertex not present */ partend = partond; /* Keep old end part */ break; } } partdlt = partval ^ partend; commcut += partdlt; commgain += (1 - 2 * partdlt) * edloval; commloaddlttmp += (partdlt - (partold ^ partond)) * edloval; /* Will account twice for difference of edge loads */ } if (commcut != hashtab[hashnum].commcut) { errorPrint ("bgraphBipartFmCheck: invalid vertex cut value"); return (1); } if ((commgain * domdist + commgainextn) != hashtab[hashnum].commgain) { errorPrint ("bgraphBipartFmCheck: invalid vertex communication gain value"); return (1); } } if ((compload0tmp - grafptr->compload0avg) != compload0dlt) { errorPrint ("bgraphBipartFmCheck: invalid computation load"); return (1); } if ((grafptr->commload + (commloaddlttmp / 2) * domdist) != (commload - commloadextndlttmp)) { errorPrint ("bgraphBipartFmCheck: invalid communication load"); return (1); } if (commgainextntmp != commgainextn) { errorPrint ("bgraphBipartFmCheck: invalid external communication gain"); return (1); } return (0); } #endif /* SCOTCH_DEBUG_BGRAPH3 */ #endif /* SCOTCH_DEBUG_BGRAPH2 */ scotch-5.1.12b.dfsg/src/libscotch/dorder_io.c0000644000175300017530000002507411631334325021255 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dorder_io.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles distributed **/ /** orderings. **/ /** **/ /** DATES : # Version 5.0 : from : 27 apr 2006 **/ /** to 13 jun 2008 **/ /** # Version 5.1 : from : 30 jul 2010 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DORDER #include "module.h" #include "common.h" #include "comm.h" #include "dgraph.h" #include "dorder.h" #include "order.h" /************************************/ /* */ /* These routines handle orderings. */ /* */ /************************************/ /* This routine saves a distributed ordering. ** The distributed graph structure is provided ** to access the distribution of vertex labels, ** whenever present. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dorderSave ( const Dorder * restrict const ordeptr, const Dgraph * restrict const grafptr, FILE * restrict const stream) { Gnum * restrict peritab; Gnum * restrict permtab; Gnum * restrict vlbltax; int procglbnbr; int reduloctab[3]; int reduglbtab[3]; int protnum; if (stream != NULL) { /* If file provided */ reduloctab[0] = 1; /* This process is the root */ reduloctab[1] = ordeptr->proclocnum; /* Get its rank */ } else { reduloctab[0] = /* This process is not the root */ reduloctab[1] = 0; } reduloctab[2] = (grafptr->vlblloctax != NULL) ? 1 : 0; /* See if vertex labels provided */ if (MPI_Allreduce (reduloctab, reduglbtab, 3, MPI_INT, MPI_SUM, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderSave: communication error (1)"); return (1); } if (reduglbtab[0] != 1) { errorPrint ("dorderSave: should have only one root"); return (1); } MPI_Comm_size (ordeptr->proccomm, &procglbnbr); if ((reduglbtab[2] != 0) && (reduglbtab[2] != procglbnbr)) { errorPrint ("dorderSave: inconsistent parameters"); return (1); } protnum = (int) reduglbtab[1]; /* Get rank of root process */ reduloctab[0] = 0; permtab = NULL; if (protnum == ordeptr->proclocnum) { Gnum vlblnbr; vlblnbr = (grafptr->vlblloctax != NULL) ? ordeptr->vnodglbnbr : 0; if (memAllocGroup ((void **) (void *) &permtab, (size_t) (ordeptr->vnodglbnbr * sizeof (Gnum)), &peritab, (size_t) (ordeptr->vnodglbnbr * sizeof (Gnum)), &vlbltax, (size_t) (vlblnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dorderSave: out of memory"); #ifdef SCOTCH_DEBUG_DORDER1 reduloctab[0] = 1; #else /* SCOTCH_DEBUG_DORDER1 */ return (1); #endif /* SCOTCH_DEBUG_DORDER1 */ } } #ifdef SCOTCH_DEBUG_DORDER1 /* This communication cannot be covered by a useful one */ if (MPI_Bcast (&reduloctab[0], 1, MPI_INT, protnum, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderSave: communication error (2)"); if (permtab != NULL); memFree (permtab); /* Free group leader */ return (1); } if (reduloctab[0] != 0) return (1); #endif /* SCOTCH_DEBUG_DORDER1 */ if (grafptr->vlblloctax != NULL) { if (commGatherv (grafptr->vlblloctax + grafptr->baseval, grafptr->vertlocnbr, GNUM_MPI, vlbltax, grafptr->proccnttab, grafptr->procdsptab, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderSave: communication error (3)"); return (1); } } if (protnum == ordeptr->proclocnum) { Gnum vertnum; for (vertnum = 0; vertnum < ordeptr->vnodglbnbr; ) { /* Till all inverse permutation indices collected */ const DorderLink * linkptr; for (linkptr = ordeptr->linkdat.nextptr; linkptr != &ordeptr->linkdat; linkptr = linkptr->nextptr) { const DorderCblk * cblkptr; cblkptr = (DorderCblk *) linkptr; /* TRICK: FIRST */ if (((cblkptr->typeval & DORDERCBLKLEAF) != 0) && (cblkptr->data.leaf.ordelocval == vertnum) && /* If column block fragment starts at proper index */ (cblkptr->data.leaf.vnodlocnbr > 0)) { /* And is not an empty local block with relevent data elsewhere */ memCpy (peritab + vertnum, cblkptr->data.leaf.periloctab, cblkptr->data.leaf.vnodlocnbr * sizeof (Gnum)); vertnum += cblkptr->data.leaf.vnodlocnbr; break; } } if (linkptr == &ordeptr->linkdat) { /* If fragment not found locally */ MPI_Status statdat; int recvnbr; if (MPI_Bcast (&vertnum, 1, GNUM_MPI, protnum, ordeptr->proccomm) != MPI_SUCCESS) { /* Broadcast missing fragment */ errorPrint ("dorderSave: communication error (4)"); memFree (permtab); /* Free group leader */ return (1); } if (MPI_Recv (peritab + vertnum, ordeptr->vnodglbnbr - vertnum, GNUM_MPI, MPI_ANY_SOURCE, DORDERTAGPERI, ordeptr->proccomm, &statdat) != MPI_SUCCESS) { errorPrint ("dorderSave: communication error (5)"); return (1); } MPI_Get_count (&statdat, GNUM_MPI, &recvnbr); vertnum += recvnbr; } } vertnum = -1; /* Indicate termination */ if (MPI_Bcast (&vertnum, 1, GNUM_MPI, protnum, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderSave: communication error (6)"); memFree (permtab); /* Free group leader */ return (1); } if (fprintf (stream, GNUMSTRING "\n", (Gnum) ordeptr->vnodglbnbr) == EOF) { errorPrint ("dorderSave: bad output (1)"); memFree (permtab); return (1); } orderPeri (peritab, ordeptr->baseval, ordeptr->vnodglbnbr, permtab, ordeptr->baseval); /* Compute direct permutation */ if (grafptr->vlblloctax != NULL) { /* If ordering has label array */ vlbltax -= ordeptr->baseval; /* Base label array */ for (vertnum = 0; vertnum < ordeptr->vnodglbnbr; vertnum ++) { if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", (Gnum) vlbltax[vertnum + ordeptr->baseval], (Gnum) vlbltax[permtab[vertnum]]) == EOF) { errorPrint ("dorderSave: bad output (2)"); memFree (permtab); return (1); } } } else { for (vertnum = 0; vertnum < ordeptr->vnodglbnbr; vertnum ++) { if (fprintf (stream, GNUMSTRING "\t" GNUMSTRING "\n", (Gnum) (vertnum + ordeptr->baseval), (Gnum) permtab[vertnum]) == EOF) { errorPrint ("dorderSave: bad output (3)"); memFree (permtab); return (1); } } } memFree (permtab); /* Free group leader */ } else { while (1) { const DorderLink * linkptr; Gnum vertnum; if (MPI_Bcast (&vertnum, 1, GNUM_MPI, protnum, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderSave: communication error (7)"); return (1); } if (vertnum == -1) /* If asked to quit */ break; /* Finish */ for (linkptr = ordeptr->linkdat.nextptr; linkptr != &ordeptr->linkdat; linkptr = linkptr->nextptr) { const DorderCblk * cblkptr; cblkptr = (DorderCblk *) linkptr; /* TRICK: FIRST */ if (((cblkptr->typeval & DORDERCBLKLEAF) != 0) && /* If matching column block fragment found */ (cblkptr->data.leaf.ordelocval == vertnum) && (cblkptr->data.leaf.vnodlocnbr > 0)) { /* And is not an empty local block with relevent data elsewhere */ if (MPI_Send (cblkptr->data.leaf.periloctab, cblkptr->data.leaf.vnodlocnbr, GNUM_MPI, protnum, DORDERTAGPERI, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderSave: communication error (8)"); return (1); } break; } } } } return (0); } scotch-5.1.12b.dfsg/src/libscotch/graph.h0000644000175300017530000002457511631334325020422 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the source graph functions. **/ /** **/ /** DATES : # Version 0.0 : from : 02 dec 1992 **/ /** to 18 may 1993 **/ /** # Version 1.3 : from : 30 apr 1994 **/ /** to 18 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 18 aug 1994 **/ /** # Version 3.0 : from : 07 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 28 nov 1995 **/ /** to 28 nov 1995 **/ /** # Version 3.2 : from : 07 sep 1996 **/ /** to 15 sep 1998 **/ /** # Version 3.3 : from : 28 sep 1998 **/ /** to 23 mar 1999 **/ /** # Version 3.4 : from : 20 mar 2000 **/ /** to 20 mar 2000 **/ /** # Version 4.0 : from : 24 nov 2001 **/ /** to 03 mar 2006 **/ /** # Version 5.0 : from : 03 mar 2006 **/ /** to 01 jun 2008 **/ /** # Version 5.1 : from : 11 aug 2010 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ #define GRAPH_H /* ** The defines. */ /*+ Graph option flags. +*/ #define GRAPHNONE 0x0000 /* No options set */ #define GRAPHFREEEDGE 0x0001 /* Free edgetab array */ #define GRAPHFREEVERT 0x0002 /* Free verttab array */ #define GRAPHFREEVNUM 0x0004 /* Free vnumtab array */ #define GRAPHFREEOTHR 0x0008 /* Free all other arrays */ #define GRAPHFREETABS 0x000F /* Free all graph arrays */ #define GRAPHVERTGROUP 0x0010 /* All vertex arrays grouped */ #define GRAPHEDGEGROUP 0x0020 /* All edge arrays grouped */ #define GRAPHBITSUSED 0x003F /* Significant bits for plain graph routines */ #define GRAPHBITSNOTUSED 0x0040 /* Value above which bits not used by plain graph routines */ #define GRAPHIONOLOADVERT 1 /* Remove vertex loads on loading */ #define GRAPHIONOLOADEDGE 2 /* Remove edge loads on loading */ /* ** The type and structure definitions. */ #ifndef GNUMMAX /* If dgraph.h not included */ typedef INT Gnum; /* Vertex and edge numbers */ typedef UINT Gunum; /* Unsigned type of same width */ #define GNUMMAX (INTVALMAX) /* Maximum signed Gnum value */ #define GNUMSTRING INTSTRING /* String to printf a Gnum */ #endif /* GNUMMAX */ /*+ The vertex part type, in compressed form. +*/ typedef byte GraphPart; /*+ The vertex list structure. Since a vertex list always refers to a given graph, vertex indices contained in the vertex list array are based with respect to the base value of the associated graph. However, the array itself is not based. +*/ typedef struct VertList_ { Gnum vnumnbr; /*+ Number of vertices in list +*/ Gnum * vnumtab; /*+ Pointer to vertex array +*/ } VertList; /*+ The graph flag type. +*/ typedef int GraphFlag; /*+ Graph property flags +*/ /*+ The graph structure. +*/ typedef struct Graph_ { GraphFlag flagval; /*+ Graph properties +*/ Gnum baseval; /*+ Base index for edge/vertex arrays +*/ Gnum vertnbr; /*+ Nmber of vertices in graph +*/ Gnum vertnnd; /*+ Number of vertices in graph, plus baseval +*/ Gnum * verttax; /*+ Vertex array [based] +*/ Gnum * vendtax; /*+ End vertex array [based] +*/ Gnum * velotax; /*+ Vertex load array (if present) +*/ Gnum velosum; /*+ Overall graph vertex load +*/ Gnum * vnumtax; /*+ Vertex number in ancestor graph +*/ Gnum * vlbltax; /*+ Vertex label (from file) +*/ Gnum edgenbr; /*+ Number of edges (arcs) in graph +*/ Gnum * edgetax; /*+ Edge array [based] +*/ Gnum * edlotax; /*+ Edge load array (if present) +*/ Gnum edlosum; /*+ Sum of edge (in fact arc) loads +*/ Gnum degrmax; /*+ Maximum degree +*/ #ifdef SCOTCH_PTSCOTCH MPI_Comm proccomm; /*+ Communicator used for parallel algorithm +*/ int procglbnbr; /*+ Number of processes in communictor +*/ int proclocnum; /*+ Rank of process in current communicator +*/ #endif /* SCOTCH_PTSCOTCH */ } Graph; /* ** The function prototypes. */ #ifndef GRAPH #define static #endif int listInit (VertList *); void listExit (VertList *); int listAlloc (VertList *, Gnum); int listFree (VertList *); int listLoad (VertList *, FILE *); int listSave (VertList *, FILE *); void listSort (VertList *); int listCopy (VertList *, VertList *); int graphInit (Graph * const); void graphExit (Graph * const); void graphFree (Graph * const); int graphLoad (Graph * const, FILE * const, const Gnum, const GraphFlag); int graphLoad2 (const Gnum, const Gnum, const Gnum * const, const Gnum * const, Gnum * restrict const, const Gnum, const Gnum * const); int graphSave (const Graph * const, FILE * const); Gnum graphBase (Graph * const, const Gnum); int graphInduceList (const Graph * const, const VertList * const, Graph * const); int graphInducePart (const Graph * const, const GraphPart *, const Gnum, const GraphPart, Graph * const); int graphCheck (const Graph *); int graphPtscotch (); #ifdef GEOM_H int graphGeomLoadChac (Graph * restrict const, Geom * restrict const, FILE * const, FILE * const, const char * const); int graphGeomSaveChac (const Graph * restrict const, const Geom * restrict const, FILE * const, FILE * const, const char * const); int graphGeomLoadHabo (Graph * restrict const, Geom * restrict const, FILE * const, FILE * const, const char * const); int graphGeomLoadMmkt (Graph * restrict const, Geom * restrict const, FILE * const, FILE * const, const char * const); int graphGeomSaveMmkt (const Graph * restrict const, const Geom * restrict const, FILE * const, FILE * const, const char * const); int graphGeomLoadScot (Graph * restrict const, Geom * restrict const, FILE * const, FILE * const, const char * const); int graphGeomSaveScot (const Graph * restrict const, const Geom * restrict const, FILE * const, FILE * const, const char * const); #endif /* GEOM_H */ #undef static scotch-5.1.12b.dfsg/src/libscotch/dgraph_band.c0000644000175300017530000013716111631334325021541 0ustar hazelscthazelsct/* Copyright 2007-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_band.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module computes a distributed band **/ /** graph from the given frontier array. **/ /** **/ /** DATES : # Version 5.1 : from : 11 nov 2007 **/ /** to : 20 feb 2011 **/ /** **/ /** NOTES : # This code derives from the code of **/ /** vdgraph_separate_bd.c in version 5.0. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH_BAND #include "module.h" #include "common.h" #include "dgraph.h" /**********************************/ /* */ /* Distance computation routines. */ /* */ /**********************************/ /* This routine computes a distributed index array ** of given width around the current separator, ** using collective communication. ** It returns: ** - 0 : if the index array could be computed. ** - !0 : on error. */ int dgraphBandColl ( Dgraph * restrict const grafptr, /*+ Distributed graph +*/ const Gnum queulocnbr, /*+ Number of frontier vertices, start size for vertex queue +*/ Gnum * restrict const queuloctab, /*+ Array of frontier vertices, re-used as queue array +*/ const Gnum distmax, /*+ Maximum distance from separator vertices +*/ Gnum * restrict * restrict const vnumgstptr, /*+ Pointer to vnumgsttax +*/ Gnum * restrict const bandvertlvlptr, /*+ Pointer to based start index of last level +*/ Gnum * restrict const bandvertlocptr, /*+ Pointer to bandvertlocnnd +*/ Gnum * restrict const bandedgelocptr) /*+ Pointer to bandedgelocnbr +*/ { Gnum queulocnum; Gnum vertlocnnd; Gnum * restrict vnumgsttax; /* Index array for vertices kept in band graph */ Gnum vnumgstsiz; /* Size of vnumgsttax; TRICK: re-use */ Gnum * vrcvdattab; /* Data arrays [norestrict:async] */ Gnum * restrict vsnddattab; Gnum * restrict procvgbtab; /* Array of neighbor bounds [+1] */ int procngbnbr; int procngbnum; int * restrict vrcvcnttab; int * restrict vsndcnttab; int * restrict vrcvdsptab; int * restrict vsnddsptab; int * restrict nsndidxtab; int vrcvdspnum; int vsnddspnum; Gnum queuheadidx; /* Index of head of queue */ Gnum queutailidx; /* Index of tail of queue */ Gnum bandvertlvlnum; Gnum bandvertlocnnd; Gnum bandedgelocnbr; Gnum distval; #ifdef SCOTCH_DEBUG_DGRAPH1 Gnum reduloctab[3]; Gnum reduglbtab[3]; #else /* SCOTCH_DEBUG_DGRAPH1 */ Gnum reduglbtab[1]; #endif /* SCOTCH_DEBUG_DGRAPH1 */ const Gnum * restrict const vertloctax = grafptr->vertloctax; const Gnum * restrict const vendloctax = grafptr->vendloctax; const Gnum * restrict const edgegsttax = grafptr->edgegsttax; const Gnum * restrict const edgeloctax = grafptr->edgeloctax; procngbnbr = grafptr->procngbnbr; reduglbtab[0] = 0; /* Assume everything is all right */ vnumgstsiz = MAX ((grafptr->vertgstnbr * sizeof (Gnum)), (grafptr->procglbnbr * sizeof (int))); /* TRICK: re-use array for further error collective communications */ if (((vnumgsttax = memAlloc (vnumgstsiz)) == NULL) || (memAllocGroup ((void **) (void *) &procvgbtab, (size_t) ((procngbnbr + 1) * sizeof (Gnum)), &nsndidxtab, (size_t) (procngbnbr * sizeof (int)), &vrcvcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), &vsndcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), /* TRICK: vsndcnttab, vrcvdsptab, vrcvdattab, vrcvdattab joined */ &vrcvdsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), &vsnddsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), &vrcvdattab, (size_t) (grafptr->procsndnbr * sizeof (Gnum)), /* Senders and receivers inverted because we send local, not halo vertices */ &vsnddattab, (size_t) ((grafptr->vertgstnbr - grafptr->vertlocnbr) * sizeof (Gnum)), NULL) == NULL)) { errorPrint ("dgraphBandColl: out of memory (1)"); reduglbtab[0] = 1; } #ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication not needed and not absorbable by the algorithm */ reduloctab[0] = reduglbtab[0]; reduloctab[1] = distmax; reduloctab[2] = - distmax; if (MPI_Allreduce (reduloctab, reduglbtab, 3, GNUM_MPI, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphBandColl: communication error (1)"); return (1); } if (reduglbtab[1] != - reduglbtab[2]) { errorPrint ("dgraphBandColl: invalid parameters"); reduglbtab[0] = 1; } #endif /* SCOTCH_DEBUG_DGRAPH1 */ if (reduglbtab[0] != 0) { if (vnumgsttax != NULL) { if (procvgbtab != NULL) memFree (procvgbtab); /* Free group leader */ memFree (vnumgsttax); } return (1); } memSet (vsndcnttab, 0, (((int *) vrcvdattab) - vsndcnttab) * sizeof (int)); /* TRICK: vsndcnttab, vrcvdsptab, vrcvdattab, vrcvdattab joined */ for (procngbnum = 0, vrcvdspnum = vsnddspnum = 0; /* Build communication index arrays */ procngbnum < procngbnbr; procngbnum ++) { int procglbnum; procglbnum = grafptr->procngbtab[procngbnum]; procvgbtab[procngbnum] = grafptr->procvrttab[procglbnum]; vrcvdsptab[procglbnum] = vrcvdspnum; vsnddsptab[procglbnum] = vsnddspnum; vrcvdspnum += grafptr->procsndtab[procglbnum]; /* Senders and receivers are reversed */ vsnddspnum += grafptr->procrcvtab[procglbnum]; } procvgbtab[procngbnum] = grafptr->procvrttab[grafptr->procglbnbr]; bandvertlvlnum = /* Start index of last level is start index */ bandvertlocnnd = grafptr->baseval; /* Reset number of band vertices, plus base */ bandedgelocnbr = 0; memSet (vnumgsttax, ~0, grafptr->vertgstnbr * sizeof (Gnum)); /* Reset part array */ vnumgsttax -= grafptr->baseval; vertlocnnd = grafptr->vertlocnnd; for (queulocnum = 0; queulocnum < queulocnbr; queulocnum ++) { /* All frontier vertices will be first vertices of band graph */ Gnum vertlocnum; vertlocnum = queuloctab[queulocnum]; vnumgsttax[vertlocnum] = bandvertlocnnd ++; /* Keep frontier vertex in band */ bandedgelocnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; /* Account for its edges */ } queuheadidx = 0; /* No queued vertex read yet */ queutailidx = queulocnbr; /* All frontier vertices are already in queue */ for (distval = 0; ++ distval <= distmax; ) { Gnum queunextidx; /* Tail index for enqueuing vertices of next band */ int procngbnum; bandvertlvlnum = bandvertlocnnd; /* Save start index of current level, based */ *bandvertlvlptr = bandvertlvlnum; for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) /* Build communication index arrays */ nsndidxtab[procngbnum] = vsnddsptab[grafptr->procngbtab[procngbnum]]; for (queunextidx = queutailidx; queuheadidx < queutailidx; ) { /* For all vertices in queue */ Gnum vertlocnum; Gnum edgelocnum; vertlocnum = queuloctab[queuheadidx ++]; /* Dequeue vertex */ for (edgelocnum = vertloctax[vertlocnum]; edgelocnum < vendloctax[vertlocnum]; edgelocnum ++) { Gnum vertlocend; vertlocend = edgegsttax[edgelocnum]; if (vnumgsttax[vertlocend] != ~0) /* If end vertex has already been processed */ continue; /* Skip to next vertex */ if (vertlocend < vertlocnnd) { /* If end vertex is local */ vnumgsttax[vertlocend] = bandvertlocnnd ++; /* Label vertex as enqueued */ queuloctab[queunextidx ++] = vertlocend; /* Enqueue vertex for next pass */ bandedgelocnbr += vendloctax[vertlocend] - vertloctax[vertlocend]; /* Account for its edges */ } else { /* End vertex is a ghost */ Gnum vertglbend; int procngbnum; int procngbmax; vnumgsttax[vertlocend] = 0; /* Label ghost vertex as enqueued */ vertglbend = edgeloctax[edgelocnum]; /* Get global number of end vertex */ procngbnum = 0; procngbmax = procngbnbr; while ((procngbmax - procngbnum) > 1) { /* Find owner process by dichotomy on procvgbtab */ int procngbmed; procngbmed = (procngbmax + procngbnum) / 2; if (procvgbtab[procngbmed] > vertglbend) procngbmax = procngbmed; else procngbnum = procngbmed; } #ifdef SCOTCH_DEBUG_DGRAPH2 if ((grafptr->procvrttab[grafptr->procngbtab[procngbnum]] > vertglbend) || (grafptr->procvrttab[grafptr->procngbtab[procngbnum] + 1] <= vertglbend) || (nsndidxtab[procngbnum] >= (vsnddsptab[grafptr->procngbtab[procngbnum]] + grafptr->procrcvtab[grafptr->procngbtab[procngbnum]]))) { errorPrint ("dgraphBandColl: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ vsnddattab[nsndidxtab[procngbnum] ++] = vertglbend - procvgbtab[procngbnum] + grafptr->baseval; /* Buffer local value on neighbor processor */ } } } for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) { int procglbnum; procglbnum = grafptr->procngbtab[procngbnum]; vsndcnttab[procglbnum] = nsndidxtab[procngbnum] - vsnddsptab[procglbnum]; } if (MPI_Alltoall (vsndcnttab, 1, MPI_INT, vrcvcnttab, 1, MPI_INT, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphBandColl: communication error (2)"); return (1); } if (MPI_Alltoallv (vsnddattab, vsndcnttab, vsnddsptab, GNUM_MPI, vrcvdattab, vrcvcnttab, vrcvdsptab, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphBandColl: communication error (3)"); return (1); } for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) { /* For all receive buffers */ Gnum * restrict vrcvdatptr; int vertrcvnum; int procglbnum; int statsiz; procglbnum = grafptr->procngbtab[procngbnum]; vrcvdatptr = vrcvdattab + vrcvdsptab[procglbnum]; statsiz = vrcvcnttab[procglbnum]; for (vertrcvnum = 0; vertrcvnum < statsiz; vertrcvnum ++) { Gnum vertlocend; vertlocend = vrcvdatptr[vertrcvnum]; /* Get local vertex from message */ #ifdef SCOTCH_DEBUG_DGRAPH2 if ((vertlocend < grafptr->baseval) || (vertlocend >= vertlocnnd)) { errorPrint ("dgraphBandColl: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (vnumgsttax[vertlocend] != ~0) /* If end vertex has already been processed */ continue; /* Skip to next vertex */ vnumgsttax[vertlocend] = bandvertlocnnd ++; /* Label vertex as enqueued */ queuloctab[queunextidx ++] = vertlocend; /* Enqueue vertex for next pass */ bandedgelocnbr += vendloctax[vertlocend] - vertloctax[vertlocend]; /* Account for its edges */ } } queutailidx = queunextidx; /* Prepare queue for next sweep */ } memFree (procvgbtab); /* Free group leader */ *vnumgstptr = vnumgsttax; *bandvertlocptr = bandvertlocnnd - grafptr->baseval; *bandedgelocptr = bandedgelocnbr; return (0); } /* This routine computes a distributed index array ** of given width around the current separator, ** using point-to-point communication. ** It returns: ** - 0 : if the index array could be computed. ** - !0 : on error. */ int dgraphBandPtop ( Dgraph * restrict const grafptr, /*+ Distributed graph +*/ const Gnum queulocnbr, /*+ Number of frontier vertices, start size for vertex queue +*/ Gnum * restrict const queuloctab, /*+ Array of frontier vertices, re-used as queue array +*/ const Gnum distmax, /*+ Maximum distance from separator vertices +*/ Gnum * restrict * restrict const vnumgstptr, /*+ Pointer to vnumgsttax +*/ Gnum * restrict const bandvertlvlptr, /*+ Pointer to based start index of last level +*/ Gnum * restrict const bandvertlocptr, /*+ Pointer to bandvertlocnnd +*/ Gnum * restrict const bandedgelocptr) /*+ Pointer to bandedgelocnbr +*/ { Gnum queulocnum; Gnum vertlocnnd; Gnum * restrict vnumgsttax; /* Index array for vertices kept in band graph */ Gnum vnumgstsiz; /* Size of vnumgsttax; TRICK: re-use */ Gnum * vrcvdattab; /* Data arrays [norestrict:async] */ Gnum * vsnddattab; Gnum * restrict procvgbtab; /* Array of neighbor bounds [+1] */ int procngbnbr; int procngbnum; int procngbnxt; Gnum * restrict nrcvdsptab; Gnum * restrict nsnddsptab; Gnum nrcvdspnum; Gnum nsnddspnum; Gnum * restrict nsndidxtab; Gnum queuheadidx; /* Index of head of queue */ Gnum queutailidx; /* Index of tail of queue */ MPI_Request * nrcvreqtab; /* Array of receive requests */ MPI_Request * nsndreqtab; /* Array of receive requests */ Gnum bandvertlvlnum; Gnum bandvertlocnnd; Gnum bandedgelocnbr; Gnum distval; #ifdef SCOTCH_DEBUG_DGRAPH1 Gnum reduloctab[3]; Gnum reduglbtab[3]; #else /* SCOTCH_DEBUG_DGRAPH1 */ Gnum reduglbtab[1]; #endif /* SCOTCH_DEBUG_DGRAPH1 */ const Gnum * restrict const vertloctax = grafptr->vertloctax; const Gnum * restrict const vendloctax = grafptr->vendloctax; const Gnum * restrict const edgegsttax = grafptr->edgegsttax; const Gnum * restrict const edgeloctax = grafptr->edgeloctax; procngbnbr = grafptr->procngbnbr; reduglbtab[0] = 0; /* Assume everything is all right */ vnumgstsiz = MAX ((grafptr->vertgstnbr * sizeof (Gnum)), (grafptr->procglbnbr * sizeof (int))); /* TRICK: re-use array for further error collective communications */ if (((vnumgsttax = memAlloc (vnumgstsiz)) == NULL) || (memAllocGroup ((void **) (void *) &procvgbtab, (size_t) ((procngbnbr + 1) * sizeof (Gnum)), &nrcvdsptab, (size_t) ((procngbnbr + 1) * sizeof (Gnum)), /* +1 to check against end of array */ &nsnddsptab, (size_t) ((procngbnbr + 1) * sizeof (Gnum)), /* +1 to check against end of array */ &nsndidxtab, (size_t) (procngbnbr * sizeof (Gnum)), /* Here Gnum's since point-to-point */ &nrcvreqtab, (size_t) (procngbnbr * sizeof (MPI_Request)), &nsndreqtab, (size_t) (procngbnbr * sizeof (MPI_Request)), &vrcvdattab, (size_t) (grafptr->procsndnbr * sizeof (Gnum)), /* Senders and receivers inverted because we send local, not halo vertices */ &vsnddattab, (size_t) ((grafptr->vertgstnbr - grafptr->vertlocnbr) * sizeof (Gnum)), NULL) == NULL)) { errorPrint ("dgraphBandPtop: out of memory (1)"); reduglbtab[0] = 1; } #ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication not needed and not absorbable by the algorithm */ reduloctab[0] = reduglbtab[0]; reduloctab[1] = distmax; reduloctab[2] = - distmax; if (MPI_Allreduce (reduloctab, reduglbtab, 3, GNUM_MPI, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphBandPtop: communication error (1)"); return (1); } if (reduglbtab[1] != - reduglbtab[2]) { errorPrint ("dgraphBandPtop: invalid parameters"); reduglbtab[0] = 1; } #endif /* SCOTCH_DEBUG_DGRAPH1 */ if (reduglbtab[0] != 0) { if (vnumgsttax != NULL) { if (procvgbtab != NULL) memFree (procvgbtab); /* Free group leader */ memFree (vnumgsttax); } return (1); } for (procngbnum = 0, nrcvdspnum = nsnddspnum = procngbnxt = 0; /* Build communication index arrays */ procngbnum < procngbnbr; procngbnum ++) { int procglbnum; procglbnum = grafptr->procngbtab[procngbnum]; if ((procngbnxt == 0) && (procglbnum > grafptr->proclocnum)) /* Find index of first neighbor of higher rank */ procngbnxt = procngbnum; procvgbtab[procngbnum] = grafptr->procvrttab[procglbnum]; nrcvdsptab[procngbnum] = nrcvdspnum; /* Arrays are indexed per neighbor since we are doing point-to-point communication */ nsnddsptab[procngbnum] = nsnddspnum; nrcvdspnum += grafptr->procsndtab[procglbnum]; /* Senders and receivers are reversed */ nsnddspnum += grafptr->procrcvtab[procglbnum]; } procvgbtab[procngbnum] = grafptr->procvrttab[grafptr->procglbnbr]; nrcvdsptab[procngbnum] = nrcvdspnum; /* Mark end of communication index arrays */ nsnddsptab[procngbnum] = nsnddspnum; procngbnum = procngbnxt; /* Create receive requests in descending order */ do { procngbnum = (procngbnum + (procngbnbr - 1)) % procngbnbr; /* Pre-decrement neighbor rank */ if (MPI_Recv_init (vrcvdattab + nrcvdsptab[procngbnum], (int) (nrcvdsptab[procngbnum + 1] - nrcvdsptab[procngbnum]), GNUM_MPI, grafptr->procngbtab[procngbnum], TAGBAND, grafptr->proccomm, nrcvreqtab + procngbnum) != MPI_SUCCESS) { errorPrint ("dgraphBandPtop: communication error (2)"); return (1); } } while (procngbnum != procngbnxt); bandvertlvlnum = /* Start index of last level is start index */ bandvertlocnnd = grafptr->baseval; /* Reset number of band vertices, plus base */ bandedgelocnbr = 0; memSet (vnumgsttax, ~0, grafptr->vertgstnbr * sizeof (Gnum)); /* Reset part array */ vnumgsttax -= grafptr->baseval; vertlocnnd = grafptr->vertlocnnd; for (queulocnum = 0; queulocnum < queulocnbr; queulocnum ++) { /* All frontier vertices will be first vertices of band graph */ Gnum vertlocnum; vertlocnum = queuloctab[queulocnum]; vnumgsttax[vertlocnum] = bandvertlocnnd ++; /* Keep frontier vertex in band */ bandedgelocnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; /* Account for its edges */ } queuheadidx = 0; /* No queued vertex read yet */ queutailidx = queulocnbr; /* All frontier vertices are already in queue */ for (distval = 0; ++ distval <= distmax; ) { Gnum queunextidx; /* Tail index for enqueuing vertices of next band */ int vrcvreqnbr; if (MPI_Startall (procngbnbr, nrcvreqtab) != MPI_SUCCESS) { /* Start all receive operations from neighbors */ errorPrint ("dgraphBandPtop: communication error (3)"); return (1); } bandvertlvlnum = bandvertlocnnd; /* Save start index of current level, based */ *bandvertlvlptr = bandvertlvlnum; memCpy (nsndidxtab, nsnddsptab, procngbnbr * sizeof (Gnum)); /* Reset send buffer indices */ for (queunextidx = queutailidx; queuheadidx < queutailidx; ) { /* For all vertices in queue */ Gnum vertlocnum; Gnum edgelocnum; vertlocnum = queuloctab[queuheadidx ++]; /* Dequeue vertex */ for (edgelocnum = vertloctax[vertlocnum]; edgelocnum < vendloctax[vertlocnum]; edgelocnum ++) { Gnum vertlocend; vertlocend = edgegsttax[edgelocnum]; if (vnumgsttax[vertlocend] != ~0) /* If end vertex has already been processed */ continue; /* Skip to next vertex */ if (vertlocend < vertlocnnd) { /* If end vertex is local */ vnumgsttax[vertlocend] = bandvertlocnnd ++; /* Label vertex as enqueued */ queuloctab[queunextidx ++] = vertlocend; /* Enqueue vertex for next pass */ bandedgelocnbr += vendloctax[vertlocend] - vertloctax[vertlocend]; /* Account for its edges */ } else { /* End vertex is a ghost */ Gnum vertglbend; int procngbnum; int procngbmax; vnumgsttax[vertlocend] = 0; /* Label ghost vertex as enqueued */ vertglbend = edgeloctax[edgelocnum]; /* Get global number of end vertex */ procngbnum = 0; procngbmax = procngbnbr; while ((procngbmax - procngbnum) > 1) { /* Find owner process by dichotomy on procvgbtab */ int procngbmed; procngbmed = (procngbmax + procngbnum) / 2; if (procvgbtab[procngbmed] > vertglbend) procngbmax = procngbmed; else procngbnum = procngbmed; } #ifdef SCOTCH_DEBUG_DGRAPH2 if ((grafptr->procvrttab[grafptr->procngbtab[procngbnum]] > vertglbend) || (grafptr->procvrttab[grafptr->procngbtab[procngbnum] + 1] <= vertglbend) || (nsndidxtab[procngbnum] >= nsnddsptab[procngbnum + 1])) { errorPrint ("dgraphBandPtop: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ vsnddattab[nsndidxtab[procngbnum] ++] = vertglbend - procvgbtab[procngbnum] + grafptr->baseval; /* Buffer local value on neighbor processor */ } } } procngbnum = procngbnxt; /* Send all buffers to neighbors */ do { int procglbnum; procglbnum = grafptr->procngbtab[procngbnum]; if (MPI_Isend (vsnddattab + nsnddsptab[procngbnum], nsndidxtab[procngbnum] - nsnddsptab[procngbnum], GNUM_MPI, grafptr->procngbtab[procngbnum], TAGBAND, grafptr->proccomm, nsndreqtab + procngbnum) != MPI_SUCCESS) { errorPrint ("dgraphBandPtop: communication error (4)"); return (1); } procngbnum = (procngbnum + 1) % procngbnbr; /* Post-increment neighbor rank */ } while (procngbnum != procngbnxt); for (vrcvreqnbr = procngbnbr; vrcvreqnbr > 0; vrcvreqnbr --) { /* For all pending receive requests */ Gnum * restrict vrcvdatptr; int vertrcvnum; MPI_Status statdat; int statsiz; int o; #ifdef SCOTCH_DETERMINISTIC procngbnum = vrcvreqnbr - 1; o = MPI_Wait (&nrcvreqtab[procngbnum], &statdat); #else /* SCOTCH_DETERMINISTIC */ o = MPI_Waitany (procngbnbr, nrcvreqtab, &procngbnum, &statdat); #endif /* SCOTCH_DETERMINISTIC */ if ((o != MPI_SUCCESS) || (MPI_Get_count (&statdat, GNUM_MPI, &statsiz) != MPI_SUCCESS)) { errorPrint ("dgraphBandPtop: communication error (5)"); return (1); } #ifdef SCOTCH_DEBUG_DGRAPH2 if (statdat.MPI_SOURCE != grafptr->procngbtab[procngbnum]) { errorPrint ("dgraphBandPtop: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ vrcvdatptr = vrcvdattab + nrcvdsptab[procngbnum]; for (vertrcvnum = 0; vertrcvnum < statsiz; vertrcvnum ++) { Gnum vertlocend; vertlocend = vrcvdatptr[vertrcvnum]; /* Get local vertex from message */ #ifdef SCOTCH_DEBUG_DGRAPH2 if ((vertlocend < grafptr->baseval) || (vertlocend >= vertlocnnd)) { errorPrint ("dgraphBandPtop: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (vnumgsttax[vertlocend] != ~0) /* If end vertex has already been processed */ continue; /* Skip to next vertex */ vnumgsttax[vertlocend] = bandvertlocnnd ++; /* Label vertex as enqueued */ queuloctab[queunextidx ++] = vertlocend; /* Enqueue vertex for next pass */ bandedgelocnbr += vendloctax[vertlocend] - vertloctax[vertlocend]; /* Account for its edges */ } } queutailidx = queunextidx; /* Prepare queue for next sweep */ if (MPI_Waitall (procngbnbr, nsndreqtab, MPI_STATUSES_IGNORE) != MPI_SUCCESS) { /* Wait until all send operations completed */ errorPrint ("dgraphBandPtop: communication error (6)"); return (1); } } for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) { /* Free persistent receive requests */ if (MPI_Request_free (nrcvreqtab + procngbnum) != MPI_SUCCESS) { errorPrint ("dgraphBandPtop: communication error (7)"); return (1); } } memFree (procvgbtab); /* Free group leader */ *vnumgstptr = vnumgsttax; *bandvertlocptr = bandvertlocnnd - grafptr->baseval; *bandedgelocptr = bandedgelocnbr; return (0); } /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine computes a distributed index array ** of given width around the current separator. ** It returns: ** - 0 : if the index array could be computed. ** - !0 : on error. */ int dgraphBand ( Dgraph * restrict const grafptr, /*+ Distributed graph +*/ const Gnum fronlocnbr, /*+ Number of frontier vertices +*/ Gnum * restrict const fronloctab, /*+ Array of frontier vertices, re-used as queue array +*/ const GraphPart * restrict const partgsttax, /*+ Part array for original graph ({0,1} or {0,1,2}) +*/ const Gnum complocload0, /*+ Load in part 0 or {0,2} +*/ const Gnum complocload1, /*+ Load in part 1 +*/ Gnum distmax, /*+ Maximum distance from separator vertices +*/ Dgraph * restrict const bandgrafptr, /*+ Pointer to band graph structure to fill +*/ Gnum * restrict * const bandfronlocptr, /*+ Pointer to bandfronloctab +*/ GraphPart * restrict * const bandpartgstptr, /*+ Pointer to bandpartgsttax +*/ Gnum * const bandvertlvlptr, /*+ Pointer to based start index of last level +*/ Gnum * const bandvertlocptr1, /*+ Pointer to number of band vertices in part 1 +*/ Gnum * const bandvertlocancptr) /*+ Pointer to flag set if anchor vertices overloaded +*/ { Gnum bandvertlocnnd; /* End of local band vertex array, (without anchor vertices) */ Gnum bandvertlocnbr; /* Number of local band vertices (including anchor vertices) */ Gnum bandvertlocnbr1; /* Number of band graph vertices in part 1 except anchor 1 */ Gnum bandvertlvlnum; /* Index of first band vertex belonging to last level */ Gnum * restrict bandvertloctax; Gnum bandvertlocadj; /* Ajust value for local-to-global band vertex indices */ Gnum bandvertlocancadj; /* Flag set when anchor(s) represent unexistent vertices */ Gnum bandvertlocnum; Gnum bandvelolocsum; Gnum bandvelolocsum1; Gnum * restrict bandedgeloctax; Gnum bandedgelocnum; Gnum bandedgeloctmp; Gnum bandedgelocnbr; /* Number of local edges in band graph */ Gnum * restrict bandedloloctax; Gnum bandedlolocnbr; /* Size of local band edge load array */ Gnum * restrict bandfronloctab; GraphPart * restrict bandpartgsttax; Gnum * restrict bandvnumgsttax; /* Indices of selected band vertices in band graph */ Gnum banddegrlocmax; Gnum degrval; Gnum veloval; const Gnum * restrict edgegsttax; Gnum fronlocnum; int cheklocval; int procngbnum; if (dgraphGhst (grafptr) != 0) { /* Compute ghost edge array if not already present */ errorPrint ("dgraphBand: cannot compute ghost edge array"); return (1); } if ((((grafptr->flagval & DGRAPHCOMMPTOP) != 0) ? dgraphBandPtop : dgraphBandColl) (grafptr, fronlocnbr, fronloctab, distmax, &bandvnumgsttax, &bandvertlvlnum, &bandvertlocnbr, &bandedgelocnbr) != 0) return (1); if (bandvertlvlptr != NULL) *bandvertlvlptr = bandvertlvlnum; bandedgelocnbr += 2 * ((bandvertlocnbr + grafptr->baseval - bandvertlvlnum) + (grafptr->procglbnbr - 1)); /* Add edges to and from anchors */ bandvertlocnbr += 2; /* Add anchor vertices */ bandedlolocnbr = (grafptr->edloloctax != NULL) ? bandedgelocnbr : 0; dgraphInit (bandgrafptr, grafptr->proccomm); bandgrafptr->flagval = (DGRAPHFREEALL ^ DGRAPHFREECOMM) | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; /* Arrays created by the routine itself */ bandgrafptr->baseval = grafptr->baseval; cheklocval = 0; if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ &bandgrafptr->procdsptab, (size_t) ((grafptr->procglbnbr + 1) * sizeof (Gnum)), &bandgrafptr->proccnttab, (size_t) (grafptr->procglbnbr * sizeof (Gnum)), &bandgrafptr->procngbtab, (size_t) (grafptr->procglbnbr * sizeof (int)), &bandgrafptr->procrcvtab, (size_t) (grafptr->procglbnbr * sizeof (int)), &bandgrafptr->procsndtab, (size_t) (grafptr->procglbnbr * sizeof (int)), NULL) == NULL) { errorPrint ("dgraphBand: out of memory (1)"); cheklocval = 1; } else if (memAllocGroup ((void **) (void *) /* Allocate distributed graph public data */ &bandgrafptr->vertloctax, (size_t) ((bandvertlocnbr + 1) * sizeof (Gnum)), /* Compact vertex array */ &bandgrafptr->vnumloctax, (size_t) (bandvertlocnbr * sizeof (Gnum)), &bandgrafptr->veloloctax, (size_t) (bandvertlocnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphBand: out of memory (2)"); cheklocval = 1; } else if (bandgrafptr->vertloctax -= bandgrafptr->baseval, bandgrafptr->veloloctax -= bandgrafptr->baseval, bandgrafptr->vnumloctax -= bandgrafptr->baseval, (memAllocGroup ((void **) (void *) &bandedgeloctax, (size_t) (bandedgelocnbr * sizeof (Gnum)), &bandedloloctax, (size_t) (bandedlolocnbr * sizeof (Gnum)), NULL) == NULL)) { errorPrint ("dgraphBand: out of memory (3)"); cheklocval = 1; } else { bandedgeloctax -= bandgrafptr->baseval; bandedloloctax = (grafptr->edloloctax != NULL) ? (bandedloloctax - bandgrafptr->baseval) : NULL; if ((bandfronloctab = memAlloc (bandvertlocnbr * sizeof (Gnum))) == NULL) { errorPrint ("dgraphBand: out of memory (4)"); cheklocval = 1; } else if ((bandpartgsttax = memAlloc ((bandvertlocnbr + bandedgelocnbr) * sizeof (GraphPart))) == NULL) { /* Upper bound on number of ghost vertices */ errorPrint ("dgraphBand: out of memory (5)"); cheklocval = 1; } else bandpartgsttax -= bandgrafptr->baseval; } if (cheklocval != 0) { /* In case of memory error */ bandgrafptr->procdsptab[0] = -1; if (MPI_Allgather (&bandgrafptr->procdsptab[0], 1, GNUM_MPI, /* Send received data to dummy array */ bandvnumgsttax + bandgrafptr->baseval, 1, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphBand: communication error (1)"); return (1); } if (bandfronloctab != NULL) memFree (bandfronloctab); dgraphExit (bandgrafptr); memFree (bandvnumgsttax + bandgrafptr->baseval); return (1); } else { bandgrafptr->procdsptab[0] = bandvertlocnbr; if (MPI_Allgather (&bandgrafptr->procdsptab[0], 1, GNUM_MPI, &bandgrafptr->procdsptab[1], 1, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphBand: communication error (2)"); return (1); } } bandgrafptr->procdsptab[0] = bandgrafptr->baseval; /* Build vertex-to-process array */ #ifdef SCOTCH_DEBUG_DGRAPH2 memSet (bandgrafptr->vnumloctax + bandgrafptr->baseval, ~0, (bandvertlocnbr * sizeof (Gnum))); #endif /* SCOTCH_DEBUG_DGRAPH2 */ for (procngbnum = 1; procngbnum <= grafptr->procglbnbr; procngbnum ++) { /* Process potential error flags from other processes */ if (bandgrafptr->procdsptab[procngbnum] < 0) { /* If error notified by another process */ if (bandpartgsttax != NULL) memFree (bandpartgsttax + bandgrafptr->baseval); if (bandfronloctab != NULL) memFree (bandfronloctab); dgraphExit (bandgrafptr); memFree (bandvnumgsttax + bandgrafptr->baseval); return (1); } bandgrafptr->procdsptab[procngbnum] += bandgrafptr->procdsptab[procngbnum - 1]; bandgrafptr->proccnttab[procngbnum - 1] = bandgrafptr->procdsptab[procngbnum] - bandgrafptr->procdsptab[procngbnum - 1]; } for (fronlocnum = 0, bandvertlocnum = bandgrafptr->baseval, bandvertlocadj = bandgrafptr->procdsptab[grafptr->proclocnum] - bandgrafptr->baseval; fronlocnum < fronlocnbr; fronlocnum ++, bandvertlocnum ++) { /* Turn all graph frontier vertices into band frontier vertices */ Gnum vertlocnum; bandfronloctab[fronlocnum] = bandvertlocnum; /* All frontier vertices are first vertices of band graph */ vertlocnum = fronloctab[fronlocnum]; bandgrafptr->vnumloctax[bandvertlocnum] = vertlocnum; bandvnumgsttax[vertlocnum] += bandvertlocadj; /* Turn local indices in band graph into global indices */ } for (bandvertlocnnd = bandvertlocnbr + bandgrafptr->baseval - 2; /* Pick selected band vertices from rest of frontier array without anchors */ bandvertlocnum < bandvertlocnnd; fronlocnum ++, bandvertlocnum ++) { Gnum vertlocnum; vertlocnum = fronloctab[fronlocnum]; bandgrafptr->vnumloctax[bandvertlocnum] = vertlocnum; bandvnumgsttax[vertlocnum] += bandvertlocadj; /* Turn local indices in band graph into global indices */ } bandgrafptr->vnumloctax[bandvertlocnnd] = /* Prevent Valgrind from yelling when centralizing band graphs */ bandgrafptr->vnumloctax[bandvertlocnnd + 1] = -1; if (dgraphHaloSync (grafptr, (byte *) (bandvnumgsttax + bandgrafptr->baseval), GNUM_MPI) != 0) { /* Share global indexing of halo vertices */ errorPrint ("dgraphBand: cannot perform halo exchange"); return (1); } edgegsttax = grafptr->edgegsttax; veloval = 1; bandvertloctax = bandgrafptr->vertloctax; bandvertlocnbr1 = 0; bandvelolocsum = 0; bandvelolocsum1 = 0; banddegrlocmax = 0; for (bandvertlocnum = bandedgelocnum = bandgrafptr->baseval; /* Build global vertex array of band graph */ bandvertlocnum < bandvertlvlnum; bandvertlocnum ++) { /* For all vertices that do not belong to the last level */ Gnum vertlocnum; Gnum edgelocnum; Gnum degrval; GraphPart partval; Gnum partval1; vertlocnum = bandgrafptr->vnumloctax[bandvertlocnum]; partval = partgsttax[vertlocnum]; #ifdef SCOTCH_DEBUG_DGRAPH2 if (partval > 2) { errorPrint ("dgraphBand: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ partval1 = partval & 1; bandvertlocnbr1 += partval1; /* Count vertices in part 1 */ bandpartgsttax[bandvertlocnum] = partval; bandvertloctax[bandvertlocnum] = bandedgelocnum; if (grafptr->veloloctax != NULL) { veloval = grafptr->veloloctax[vertlocnum]; bandvelolocsum += veloval; bandvelolocsum1 += veloval & (- partval1); /* Sum vertex load if (partval == 1) */ } bandgrafptr->veloloctax[bandvertlocnum] = veloval; degrval = grafptr->vendloctax[vertlocnum] - grafptr->vertloctax[vertlocnum]; if (banddegrlocmax < degrval) banddegrlocmax = degrval; for (edgelocnum = grafptr->vertloctax[vertlocnum]; /* For all original edges */ edgelocnum < grafptr->vendloctax[vertlocnum]; edgelocnum ++) { #ifdef SCOTCH_DEBUG_DGRAPH2 if (bandvnumgsttax[edgegsttax[edgelocnum]] == ~0) { /* All ends should belong to the band graph too */ errorPrint ("dgraphBand: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ bandedgeloctax[bandedgelocnum ++] = bandvnumgsttax[edgegsttax[edgelocnum]]; } } for ( ; bandvertlocnum < bandvertlocnnd; bandvertlocnum ++) { /* For all vertices that belong to the last level except anchors */ Gnum vertlocnum; Gnum edgelocnum; Gnum degrval; GraphPart partval; Gnum partval1; vertlocnum = bandgrafptr->vnumloctax[bandvertlocnum]; partval = partgsttax[vertlocnum]; #ifdef SCOTCH_DEBUG_DGRAPH2 if (partval > 2) { errorPrint ("dgraphBand: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ partval1 = partval & 1; bandvertlocnbr1 += partval1; /* Count vertices in part 1 */ bandpartgsttax[bandvertlocnum] = partval; bandvertloctax[bandvertlocnum] = bandedgelocnum; if (grafptr->veloloctax != NULL) { veloval = grafptr->veloloctax[vertlocnum]; bandvelolocsum += veloval; bandvelolocsum1 += veloval & (- partval1); /* Sum vertex load if (partval == 1) */ } bandgrafptr->veloloctax[bandvertlocnum] = veloval; for (edgelocnum = grafptr->vertloctax[vertlocnum]; /* For all original edges */ edgelocnum < grafptr->vendloctax[vertlocnum]; edgelocnum ++) { Gnum bandvertlocend; bandvertlocend = bandvnumgsttax[edgegsttax[edgelocnum]]; if (bandvertlocend != ~0) { /* If end vertex belongs to band graph */ if (bandedloloctax != NULL) /* If graph has edge weights, copy load */ bandedloloctax[bandedgelocnum] = grafptr->edloloctax[edgelocnum]; bandedgeloctax[bandedgelocnum ++] = bandvertlocend; } } if (bandedloloctax != NULL) /* If graph has edge weights */ bandedloloctax[bandedgelocnum] = 1; /* Edge to anchor has load 1 */ bandedgeloctax[bandedgelocnum ++] = bandvertlocnnd + bandvertlocadj + partval1; /* Add edge to anchor of proper part */ degrval = bandedgelocnum - bandvertloctax[bandvertlocnum]; if (banddegrlocmax < degrval) banddegrlocmax = degrval; } memFree (bandvnumgsttax + bandgrafptr->baseval); /* Free useless space */ bandpartgsttax[bandvertlocnnd] = 0; /* Set parts of anchor vertices */ bandpartgsttax[bandvertlocnnd + 1] = 1; bandvertloctax[bandvertlocnum] = bandedgelocnum; /* Process anchor vertex in part 0 */ for (procngbnum = 0; procngbnum < grafptr->proclocnum; procngbnum ++) /* Build clique with anchors of part 0 */ bandedgeloctax[bandedgelocnum ++] = bandgrafptr->procdsptab[procngbnum + 1] - 2; for (procngbnum ++; procngbnum < grafptr->procglbnbr; procngbnum ++) /* Build clique with anchors of part 0 */ bandedgeloctax[bandedgelocnum ++] = bandgrafptr->procdsptab[procngbnum + 1] - 2; bandedgeloctmp = bandedgelocnum + (bandvertlocnnd - bandvertlvlnum); for (procngbnum = 0; procngbnum < grafptr->proclocnum; procngbnum ++) /* Build clique with anchors of part 1 */ bandedgeloctax[bandedgeloctmp ++] = bandgrafptr->procdsptab[procngbnum + 1] - 1; for (procngbnum ++; procngbnum < grafptr->procglbnbr; procngbnum ++) /* Build clique with anchors of part 1 */ bandedgeloctax[bandedgeloctmp ++] = bandgrafptr->procdsptab[procngbnum + 1] - 1; bandvertloctax[bandvertlocnnd + 2] = bandedgeloctmp; bandedgelocnbr = bandedgeloctmp - bandgrafptr->baseval; /* Set real number of edges */ for (bandvertlocnum = bandvertlvlnum, bandedgeloctmp = bandedgelocnum + (bandvertlocnnd - bandvertlvlnum); /* Link vertices of last level to anchors */ bandvertlocnum < bandvertlocnnd; bandvertlocnum ++) { if (bandpartgsttax[bandvertlocnum] == 0) bandedgeloctax[bandedgelocnum ++] = bandvertlocnum + bandvertlocadj; else bandedgeloctax[-- bandedgeloctmp] = bandvertlocnum + bandvertlocadj; } bandvertloctax[bandvertlocnnd + 1] = bandedgeloctmp; degrval = bandvertloctax[bandvertlocnnd + 1] - bandvertloctax[bandvertlocnnd]; if (banddegrlocmax < degrval) banddegrlocmax = degrval; degrval = bandvertloctax[bandvertlocnnd + 2] - bandvertloctax[bandvertlocnnd + 1]; if (banddegrlocmax < degrval) banddegrlocmax = degrval; if (bandedloloctax != NULL) { /* If graph has edge weights */ Gnum edgelocnum; Gnum edgelocnnd; for (bandvertlocnum = bandgrafptr->baseval; /* For all vertices that do not belong to the last level */ bandvertlocnum < bandvertlvlnum; bandvertlocnum ++) { Gnum vertlocnum; Gnum bandedgelocnum; vertlocnum = bandgrafptr->vnumloctax[bandvertlocnum]; bandedgelocnum = bandvertloctax[bandvertlocnum]; memCpy (bandedloloctax + bandedgelocnum, /* Copy edge load array */ &grafptr->edloloctax[grafptr->vertloctax[vertlocnum]], (bandvertloctax[bandvertlocnum + 1] - bandedgelocnum) * sizeof (Gnum)); } /* Vertices of last level have been processed before */ for (edgelocnum = bandvertloctax[bandvertlocnnd], /* Loads of anchor edges are all 1's too */ edgelocnnd = bandvertloctax[bandvertlocnnd + 2]; edgelocnum < edgelocnnd; edgelocnum ++) bandedloloctax[edgelocnum] = 1; } if (grafptr->veloloctax == NULL) { /* If original graph is not weighted */ bandgrafptr->veloloctax[bandvertlocnnd] = complocload0 + bandvertlocnbr1 - bandvertlocnbr + 2; /* Plus 2 for anchors */ bandgrafptr->veloloctax[bandvertlocnnd + 1] = complocload1 - bandvertlocnbr1; } else { bandgrafptr->veloloctax[bandvertlocnnd] = complocload0 + bandvelolocsum1 - bandvelolocsum; bandgrafptr->veloloctax[bandvertlocnnd + 1] = complocload1 - bandvelolocsum1; } bandvertlocancadj = 0; if ((bandgrafptr->veloloctax[bandvertlocnnd] == 0) || /* If at least one anchor is empty */ (bandgrafptr->veloloctax[bandvertlocnnd + 1] == 0)) { bandvertlocancadj = 1; bandgrafptr->veloloctax[bandvertlocnnd] ++; /* Increase weight of both anchors to keep balance */ bandgrafptr->veloloctax[bandvertlocnnd + 1] ++; } bandgrafptr->procvrttab = bandgrafptr->procdsptab; /* Graph does not have holes */ bandgrafptr->vertlocnbr = bandvertlocnbr; bandgrafptr->vertlocnnd = bandvertlocnbr + bandgrafptr->baseval; bandgrafptr->vendloctax = bandvertloctax + 1; /* Band graph is compact */ bandgrafptr->velolocsum = grafptr->velolocsum + 2 * bandvertlocancadj; bandgrafptr->edgeloctax = bandedgeloctax; bandgrafptr->edloloctax = bandedloloctax; bandgrafptr->edgelocnbr = bandedgelocnbr; bandgrafptr->edgelocsiz = bandedgelocnbr; bandgrafptr->degrglbmax = banddegrlocmax; /* Local maximum degree will be turned into global maximum degree */ if (dgraphBuild4 (bandgrafptr) != 0) { errorPrint ("dgraphBand: cannot build band graph"); return (1); } #ifdef SCOTCH_DEBUG_DGRAPH2 if (dgraphCheck (bandgrafptr) != 0) { errorPrint ("dgraphBand: internal error (4)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ *bandfronlocptr = bandfronloctab; *bandpartgstptr = bandpartgsttax; *bandvertlocptr1 = bandvertlocnbr1; *bandvertlocancptr = bandvertlocancadj; return (0); } scotch-5.1.12b.dfsg/src/libscotch/graph_list.c0000644000175300017530000002003111631334325021427 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_list.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the source graph **/ /** vertex lists functions. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to 18 may 1993 **/ /** # Version 1.3 : from : 30 apr 1994 **/ /** to 18 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 31 oct 1994 **/ /** # Version 3.0 : from : 07 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 28 nov 1995 **/ /** to 08 jun 1996 **/ /** # Version 3.2 : from : 07 sep 1996 **/ /** to 15 sep 1998 **/ /** # Version 4.0 : from : 10 dec 2001 **/ /** to 10 dec 2001 **/ /** # Version 5.1 : from : 11 aug 2010 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GRAPH_LIST #include "module.h" #include "common.h" #include "graph.h" /********************************/ /* */ /* These routines handle vertex */ /* number lists. */ /* */ /********************************/ /* This routine creates a vertex number list. ** It returns: ** - 0 : in all cases. */ int listInit ( VertList * listptr) { listptr->vnumnbr = 0; /* Initialize list fields */ listptr->vnumtab = NULL; return (0); } /* This routine deletes the given vertex number list. ** It returns: ** - VOID : in all cases. */ void listExit ( VertList * listptr) { if (listptr->vnumtab != NULL) memFree (listptr->vnumtab); /* Free vertex list array */ #ifdef SCOTCH_DEBUG_GRAPH2 memSet (listptr, 0, sizeof (VertList)); /* Purge list fields */ #endif /* SCOTCH_DEBUG_GRAPH2 */ } /* This routine allocates a vertex ** number list array. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int listAlloc ( VertList * listptr, Gnum vnumnbr) { if (vnumnbr == listptr->vnumnbr) /* If array is already dimensioned */ return (0); /* Keep it as it is */ listFree (listptr); /* Free vertex array */ if (vnumnbr > 0) { /* Reallocate vertex space */ if ((listptr->vnumtab = (Gnum *) memAlloc (vnumnbr * sizeof (Gnum))) == NULL) { errorPrint ("listAlloc: out of memory"); return (1); } listptr->vnumnbr = vnumnbr; } return (0); } /* This routine frees a vertex ** number list array. ** It returns: ** - 0 : in all cases. */ int listFree ( VertList * listptr) { if (listptr->vnumtab != NULL) /* Free vertex list array */ memFree (listptr->vnumtab); listptr->vnumnbr = 0; /* Reset list values */ listptr->vnumtab = NULL; return (0); } /* These routines load a vertex number list ** from the given stream. Because of the search ** for duplicates, the list read is always ** sorted by ascending order. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int listLoad ( VertList * listptr, FILE * stream) { Gnum vnumnbr; Gnum vnumnum; if (intLoad (stream, &vnumnbr) != 1) { /* Read number of vertices */ errorPrint ("listLoad: bad input (1)"); return (1); } if (listAlloc (listptr, vnumnbr) != 0) { /* Allocate vertex space */ errorPrint ("listLoad: out of memory"); return (1); } for (vnumnum = 0; vnumnum < vnumnbr; vnumnum ++) { /* Read vertex list contents */ if (intLoad (stream, &listptr->vnumtab[vnumnum]) != 1) { errorPrint ("listLoad: bad input (2)"); return (1); } } listSort (listptr); /* Sort vertex list by ascending order */ for (vnumnum = 1; vnumnum < vnumnbr; vnumnum ++) { /* Search list for duplicates */ if (listptr->vnumtab[vnumnum] == listptr->vnumtab[vnumnum - 1]) { errorPrint ("listLoad: duplicate vertex numbers"); return (1); } } return (0); } /* This routine sorts a vertex list ** by ascending order. ** It returns: ** - VOID : in all cases. */ void listSort ( VertList * listptr) { intSort1asc1 (listptr->vnumtab, listptr->vnumnbr); } /* This routine saves a vertex number list ** to the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int listSave ( VertList * listptr, FILE * stream) { Gnum vnumnum; int o; o = (intSave (stream, listptr->vnumnbr) == 0); /* Write number of vertices */ for (vnumnum = 0; (o == 0) && (vnumnum < listptr->vnumnbr); vnumnum ++) { o = (fprintf (stream, "%c" GNUMSTRING, ((vnumnum % 8) == 0) ? '\n' : '\t', (Gnum) listptr->vnumtab[vnumnum]) == EOF); } o |= (fprintf (stream, "\n") == EOF); if (o != 0) errorPrint ("listSave: bad output"); return (o); } /* This routine copies the contents ** of a vertex list into another. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int listCopy ( VertList * dstlistptr, /* Destination list */ VertList * srclistptr) /* Source list */ { if (listAlloc (dstlistptr, dstlistptr->vnumnbr) != 0) { /* Allocate vertex space */ errorPrint ("listCopy: out of memory"); return (1); } memCpy (dstlistptr->vnumtab, /* Copy list data */ srclistptr->vnumtab, srclistptr->vnumnbr * sizeof (Gnum)); return (0); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_scatter.c0000644000175300017530000004332011631334325022273 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_scatter.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** Francois CHATENET (P0.0) **/ /** Sebastien FOUCAULT (P0.0) **/ /** **/ /** FUNCTION : This module contains the routine that **/ /** builds a distributed graph by evenly **/ /** distributing the pieces of a central- **/ /** ized graph across processors. **/ /** **/ /** # Version P0.0 : from : 01 apr 1997 **/ /** to 20 jun 1997 **/ /** # Version P0.1 : from : 14 apr 1998 **/ /** to 20 jun 1998 **/ /** # Version P0.2 : from : 19 may 1999 **/ /** to 19 may 1999 **/ /** # Version 5.0 : from : 27 apr 2006 **/ /** to : 10 sep 2007 **/ /** **/ /** NOTES : # The definitions of MPI_Scatter and **/ /** MPI_Scatterv indicate that elements **/ /** in the send array should not be read **/ /** more than once. Great care should be **/ /** taken to enforce this rule, especial- **/ /** ly when the number of vertices in the **/ /** centralized graph is smaller than the **/ /** number of processors. **/ /** **/ /** # When the source graph is not compact, **/ /** compacted arrays are created prior to **/ /** sending parts of them. In a really **/ /** efficient implementation, these **/ /** should be created by pieces and sent **/ /** in a one-to-one way so as to save as **/ /** much memory as possible. This is yet **/ /** to be done. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH_SCATTER #include "module.h" #include "common.h" #include "graph.h" #include "dgraph.h" /* Service function which creates compact ** arrays from non-compact ones. */ static void dgraphScatter2 ( const Graph * restrict const cgrfptr, Gnum * restrict verttax, Gnum * restrict edgetax, Gnum * restrict edlotax) { Gnum vertnum; /* Current vertex number in compacted arrays */ Gnum edgenum; /* Current edge number in compacted arrays */ for (vertnum = edgenum = cgrfptr->baseval; vertnum < cgrfptr->vertnnd; vertnum ++) { Gnum edgetmp; Gnum edgetnd; verttax[vertnum] = edgenum; edgetmp = cgrfptr->verttax[vertnum]; edgetnd = cgrfptr->vendtax[vertnum]; for ( ; edgetmp < edgetnd; edgetmp ++, edgenum ++) edgetax[edgenum] = cgrfptr->edgetax[edgetmp]; if (edlotax != NULL) { for (edgetmp = cgrfptr->verttax[vertnum], edgenum = verttax[vertnum]; edgetmp < edgetnd; edgetmp ++, edgenum ++) edlotax[edgenum] = cgrfptr->edlotax[edgetmp]; } } verttax[vertnum] = edgenum; } /* This function evenly distributes the pieces ** of a centralized graph across processors. ** It returns: ** - 0 : if scattering has succeeded. ** - !0 : on error. */ int dgraphScatter ( Dgraph * restrict const grafptr, /* Distributed graph */ const Graph * restrict const cgrfptr) /* Centralized graph to scatter */ { Gnum baseval; /* Base value */ Gnum * restrict verttax; /* Array of vertices when edge array is not compact */ Gnum * restrict edgetax; /* Compact array of edges when edge aray is not compact */ Gnum * restrict edlotax; /* Compact array of edges weights */ Gnum vertlocnum; /* Current local vertex number */ Gnum vertlocnbr; /* Number of local vertices */ Gnum vertlocnnd; Gnum * restrict vertloctax; /* Array of local vertices */ Gnum * restrict veloloctax; /* Array of local vertex weights */ Gnum velolocnbr; Gnum vlbllocnbr; Gnum * restrict vlblloctax; /* Array of local vertex labels */ Gnum edgelocnbr; /* Number of local edges */ Gnum edlolocnbr; Gnum * restrict edgeloctax; /* Array of local edges */ Gnum * restrict edloloctax; /* Array of local edge weights */ int * restrict attrdsptab; /* Displacement array for scatter operations */ int * restrict attrcnttab; /* Count array for scatter operations */ Gnum * restrict attrdattab; /* Temporary array to avoid multiple scatter reads */ Gnum reduloctab[9]; /* Arrays for reductions */ Gnum reduglbtab[9]; Gnum vertlocadj; /* Local vertex array adjust */ int protnum; /* Root process */ if (cgrfptr != NULL) { /* If centralized graph provided */ if (cgrfptr->vendtax != (cgrfptr->verttax + 1)) { /* If edge array is not compact */ Gnum edlonbr; edlonbr = (cgrfptr->edlotax != NULL) ? cgrfptr->edgenbr : 0; if (memAllocGroup ((void **) (void *) &verttax, (size_t) ((cgrfptr->vertnbr + 1) * sizeof (Gnum)), &edgetax, (size_t) (cgrfptr->edgenbr * sizeof (Gnum)), &edlotax, (size_t) (edlonbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphScatter: out of memory (1)"); return (1); } verttax -= cgrfptr->baseval; edgetax -= cgrfptr->baseval; edlotax = (cgrfptr->edlotax != NULL) ? (edlotax - cgrfptr->baseval) : NULL; dgraphScatter2 (cgrfptr, verttax, edgetax, edlotax); } else { verttax = cgrfptr->verttax; edgetax = cgrfptr->edgetax; edlotax = cgrfptr->edlotax; } reduloctab[0] = 1; /* This process is the root */ reduloctab[1] = (Gnum) grafptr->proclocnum; /* Get its number */ reduloctab[2] = cgrfptr->baseval; reduloctab[3] = cgrfptr->vertnbr; reduloctab[4] = cgrfptr->edgenbr; reduloctab[5] = cgrfptr->velosum; reduloctab[6] = (cgrfptr->velotax != NULL) ? 1 : 0; reduloctab[7] = (cgrfptr->vlbltax != NULL) ? 1 : 0; reduloctab[8] = (cgrfptr->edlotax != NULL) ? 1 : 0; } else { reduloctab[0] = /* This process is not the root */ reduloctab[1] = reduloctab[2] = reduloctab[3] = reduloctab[4] = reduloctab[5] = reduloctab[6] = reduloctab[7] = reduloctab[8] = 0; } if (MPI_Allreduce (reduloctab, reduglbtab, 9, GNUM_MPI, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphScatter: communication error (1)"); return (1); } if (reduglbtab[0] != 1) { errorPrint ("dgraphScatter: should have only one root"); return (1); } baseval = reduglbtab[2]; vertlocnbr = DATASIZE (reduglbtab[3], grafptr->procglbnbr, grafptr->proclocnum); velolocnbr = (reduglbtab[6] != 0) ? vertlocnbr : 0; vlbllocnbr = (reduglbtab[7] != 0) ? vertlocnbr : 0; if (memAllocGroup ((void **) (void *) &vertloctax, (size_t) ((vertlocnbr + 1) * sizeof (Gnum)), &veloloctax, (size_t) (velolocnbr * sizeof (Gnum)), &vlblloctax, (size_t) (vlbllocnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphScatter: out of memory (2)"); if ((cgrfptr != NULL) && (cgrfptr->verttax != verttax)) memFree (verttax + baseval); /* Free group leader */ return (1); } vertloctax -= baseval; veloloctax = (reduglbtab[6] != 0) ? (veloloctax - baseval) : NULL; vlblloctax = (reduglbtab[7] != 0) ? (vlblloctax - baseval) : NULL; protnum = (int) reduglbtab[1]; if (cgrfptr != NULL) { /* If root process */ Gnum procnum; if (memAllocGroup ((void **) (void *) &attrdattab, (size_t) (grafptr->procglbnbr * sizeof (Gnum)), &attrdsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), &attrcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), NULL) == NULL) { errorPrint ("dgraphScatter: out of memory (3)"); memFree (vertloctax + baseval); if (cgrfptr->verttax != verttax) memFree (verttax + baseval); /* Free group leader */ return (1); } attrdsptab[0] = 0; /* Build arrays for MPI_Scatterv */ attrcnttab[0] = DATASIZE (reduglbtab[3], grafptr->procglbnbr, 0); attrdattab[0] = verttax[attrdsptab[0] + attrcnttab[0] + baseval]; for (procnum = 1; procnum < grafptr->procglbnbr; procnum ++) { attrdsptab[procnum] = attrdsptab[procnum - 1] + attrcnttab[procnum - 1]; attrcnttab[procnum] = DATASIZE (reduglbtab[3], grafptr->procglbnbr, procnum); attrdattab[procnum] = verttax[attrdsptab[procnum] + attrcnttab[procnum] + baseval]; } if (MPI_Scatterv (verttax + baseval, attrcnttab, attrdsptab, GNUM_MPI, /* Perform two scatters since cannot avoid multiple reads with only one scatter */ vertloctax + baseval, vertlocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphScatter: communication error (2)"); return (1); } if (MPI_Scatter (attrdattab, 1, GNUM_MPI, vertloctax + baseval + vertlocnbr, 1, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphScatter: communication error (3)"); return (1); } if (reduglbtab[6] != 0) { /* Scatter vertex loads */ if (MPI_Scatterv (cgrfptr->velotax + baseval, attrcnttab, attrdsptab, GNUM_MPI, veloloctax + baseval, vertlocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphScatter: communication error (4)"); return (1); } } if (reduglbtab[7] != 0) { /* Scatter labels */ if (MPI_Scatterv (cgrfptr->vlbltax + baseval, attrcnttab, attrdsptab, GNUM_MPI, vlblloctax + baseval, vertlocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphScatter: communication error (5)"); return (1); } } } else { /* Process is not root */ if (MPI_Scatterv (NULL, NULL, NULL, GNUM_MPI, vertloctax + baseval, vertlocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphScatter: communication error (6)"); return (1); } if (MPI_Scatter (NULL, 1, GNUM_MPI, vertloctax + baseval + vertlocnbr, 1, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphScatter: communication error (7)"); return (1); } if (reduglbtab[6] != 0) { /* Scatter vertex loads */ if (MPI_Scatterv (NULL, NULL, NULL, GNUM_MPI, veloloctax + baseval, vertlocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphScatter: communication error (8)"); return (1); } } if (reduglbtab[7] != 0) { /* Scatter labels */ if (MPI_Scatterv (NULL, NULL, NULL, GNUM_MPI, vlblloctax + baseval, vertlocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphScatter: communication error (9)"); return (1); } } } vertlocadj = vertloctax[baseval] - baseval; /* Compute local indices */ for (vertlocnum = baseval, vertlocnnd = vertlocnbr + baseval; vertlocnum <= vertlocnnd; vertlocnum ++) vertloctax[vertlocnum] -= vertlocadj; edgelocnbr = vertloctax[vertlocnnd] - vertloctax[baseval]; edlolocnbr = (reduglbtab[8] != 0) ? edgelocnbr : 0; if (memAllocGroup ((void **) (void *) &edgeloctax, (size_t) (edgelocnbr * sizeof (Gnum)), &edloloctax, (size_t) (edlolocnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphScatter: out of memory (4)"); if (cgrfptr != NULL) { memFree (attrdattab); /* Free group leader */ if (cgrfptr->verttax != verttax) memFree (verttax + baseval); /* Free group leader */ } memFree (vertloctax + baseval); return (1); } edgeloctax -= baseval; edloloctax = (reduglbtab[8] != 0) ? edloloctax - baseval : NULL; if (cgrfptr != NULL) { /* If root process */ Gnum procnum; for (procnum = 0; procnum < grafptr->procglbnbr; procnum ++) { /* Build arrays for MPI_Scatterv */ attrcnttab[procnum] = verttax[attrdsptab[procnum] + attrcnttab[procnum]+baseval] - verttax[attrdsptab[procnum] + baseval]; attrdsptab[procnum] = verttax[attrdsptab[procnum] + baseval] - baseval; } if (MPI_Scatterv (edgetax + baseval, attrcnttab, attrdsptab, GNUM_MPI, edgeloctax + baseval, edgelocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphScatter: communication error (10)"); return (1); } if (reduglbtab[8] != 0) { if (MPI_Scatterv (edlotax + baseval, attrcnttab, attrdsptab, GNUM_MPI, edloloctax + baseval, edgelocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphScatter: communication error (11)"); return (1); } } memFree (attrdattab); /* Free group leader */ if (cgrfptr->verttax != verttax) memFree (verttax + baseval); } else { /* Process is not root */ if (MPI_Scatterv (NULL, NULL, NULL, GNUM_MPI, edgeloctax + baseval , edgelocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphScatter: communication error (12)"); return (1); } if (reduglbtab[8] != 0) { if (MPI_Scatterv (NULL, NULL, NULL, GNUM_MPI, edloloctax + baseval , edgelocnbr, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphScatter: communication error (13)"); return (1); } } } if (dgraphBuild (grafptr, baseval, vertlocnbr, vertlocnbr, vertloctax, vertloctax + 1, veloloctax, NULL, NULL, edgelocnbr, edgelocnbr, edgeloctax, NULL, edloloctax) != 0) { memFree (edgeloctax + baseval); memFree (vertloctax + baseval); return (1); } grafptr->flagval |= DGRAPHFREETABS | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; /* Give ownership of arrays to graph */ grafptr->vlblloctax = vlblloctax; /* Add labels afterwards, since relabeling already done */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/arch_mesh.h0000644000175300017530000001675211631334325021250 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_mesh.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the mesh graph target architecture **/ /** functions. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 12 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 30 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 17 aug 1995 **/ /** # Version 3.1 : from : 22 jul 1996 **/ /** to 23 jul 1996 **/ /** # Version 3.2 : from : 16 oct 1996 **/ /** to 14 may 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 09 jan 2004 **/ /** to 09 jan 2004 **/ /** # Version 5.1 : from : 21 jan 2008 **/ /** to 21 jan 2008 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ The 2D-mesh definitions. +*/ typedef struct ArchMesh2_ { Anum c[2]; /*+ Mesh dimensions +*/ } ArchMesh2; typedef struct ArchMesh2Dom_ { Anum c[2][2]; /*+ Inclusive X and Y coordinates +*/ } ArchMesh2Dom; /*+ The 3D-mesh definitions. +*/ typedef struct ArchMesh3_ { Anum c[3]; /*+ Mesh dimensions +*/ } ArchMesh3; typedef struct ArchMesh3Dom_ { Anum c[3][2]; /*+ Inclusive X, Y, and Z coordinates +*/ } ArchMesh3Dom; /* ** The function prototypes. */ #ifndef ARCH_MESH #define static #endif int archMesh2ArchLoad (ArchMesh2 * restrict const, FILE * restrict const); int archMesh2ArchSave (const ArchMesh2 * const, FILE * restrict const); #define archMesh2ArchFree NULL ArchDomNum archMesh2DomNum (const ArchMesh2 * const, const ArchMesh2Dom * const); int archMesh2DomTerm (const ArchMesh2 * const, ArchMesh2Dom * restrict const, const ArchDomNum); Anum archMesh2DomSize (const ArchMesh2 * const, const ArchMesh2Dom * const); #define archMesh2DomWght archMesh2DomSize Anum archMesh2DomDist (const ArchMesh2 * const, const ArchMesh2Dom * const, const ArchMesh2Dom * const); int archMesh2DomFrst (const ArchMesh2 * const, ArchMesh2Dom * const); int archMesh2DomLoad (const ArchMesh2 * const, ArchMesh2Dom * const, FILE * restrict const); int archMesh2DomSave (const ArchMesh2 * const, const ArchMesh2Dom * const, FILE * restrict const); int archMesh2DomBipart (const ArchMesh2 * const, const ArchMesh2Dom * const, ArchMesh2Dom * restrict const, ArchMesh2Dom * restrict const); int archMesh2DomBipartO (const ArchMesh2 * const, const ArchMesh2Dom * const, ArchMesh2Dom * restrict const, ArchMesh2Dom * restrict const); int archMesh2DomBipartU (const ArchMesh2 * const, const ArchMesh2Dom * const, ArchMesh2Dom * restrict const, ArchMesh2Dom * restrict const); #ifdef SCOTCH_PTSCOTCH int archMesh2DomMpiType (const ArchMesh2 * const, MPI_Datatype * const); #endif /* SCOTCH_PTSCOTCH */ int archMesh3ArchLoad (ArchMesh3 * restrict const, FILE * restrict const); int archMesh3ArchSave (const ArchMesh3 * const, FILE * restrict const); #define archMesh3ArchFree NULL ArchDomNum archMesh3DomNum (const ArchMesh3 * const, const ArchMesh3Dom * const); int archMesh3DomTerm (const ArchMesh3 * const, ArchMesh3Dom * restrict const, const ArchDomNum); Anum archMesh3DomSize (const ArchMesh3 * const, const ArchMesh3Dom * const); #define archMesh3DomWght archMesh3DomSize Anum archMesh3DomDist (const ArchMesh3 * const, const ArchMesh3Dom * const, const ArchMesh3Dom * const); int archMesh3DomFrst (const ArchMesh3 * const, ArchMesh3Dom * const); int archMesh3DomLoad (const ArchMesh3 * const, ArchMesh3Dom * const, FILE * restrict const); int archMesh3DomSave (const ArchMesh3 * const, const ArchMesh3Dom * const, FILE * restrict const); int archMesh3DomBipart (const ArchMesh3 * const, const ArchMesh3Dom * const, ArchMesh3Dom * restrict const, ArchMesh3Dom * restrict const); #ifdef SCOTCH_PTSCOTCH int archMesh3DomMpiType (const ArchMesh3 * const, MPI_Datatype * const); #endif /* SCOTCH_PTSCOTCH */ #undef static scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_gp.h0000644000175300017530000001041411631334325022271 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_gp.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the Gibbs-Poole-Stockmeyer **/ /** node ordering routine. **/ /** **/ /** DATES : # Version 3.2 : from : 31 oct 1996 **/ /** to : 27 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 02 oct 1998 **/ /** # Version 4.0 : from : 04 nov 2002 **/ /** to : 01 dec 2003 **/ /** # Version 5.1 : from : 01 oct 2009 **/ /** to : 01 oct 2009 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HmeshOrderGpParam_ { INT passnbr; /*+ Number of passes to do +*/ } HmeshOrderGpParam; /*+ Complementary vertex structure. +*/ typedef struct HmeshOrderGpVertex_ { Gnum passnum; /*+ Number of pass when vertex selected +*/ Gnum vertdist; /*+ Current distance from diameter vertex +*/ } HmeshOrderGpVertex; /*+ Neighbor queue. +*/ typedef struct HmeshOrderGpQueue_ { Gnum * head; /*+ Head of distance queue +*/ Gnum * tail; /*+ Tail of distance queue +*/ Gnum * qtab; /*+ Array of queue elements +*/ } HmeshOrderGpQueue; /* ** The function prototypes. */ #ifndef HMESH_ORDER_GP #define static #endif int hmeshOrderGp (const Hmesh * const, Order * const, const Gnum, OrderCblk * const, const HmeshOrderGpParam * restrict const); #undef static /* ** The macro definitions. */ #define hmeshOrderGpQueueFlush(queue) ((queue)->head = (queue)->tail = (queue)->qtab) #define hmeshOrderGpQueueEmpty(queue) ((queue)->head <= (queue)->tail) #define hmeshOrderGpQueuePut(queue,vnum) (* ((queue)->head ++) = (vnum)) #define hmeshOrderGpQueueGet(queue) (* ((queue)->tail ++)) scotch-5.1.12b.dfsg/src/libscotch/library_graph_io_habo_f.c0000644000175300017530000001212311631334325024110 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_io_habo_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** graph i/o routines of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 4.0 : from : 23 nov 2005 **/ /** to 23 nov 2005 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 27 mar 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the mapping routines. */ /* */ /**************************************/ /* String lengths are passed at the very ** end of the argument list. */ FORTRAN ( \ SCOTCHFGRAPHGEOMLOADHABO, scotchfgraphgeomloadhabo, ( \ SCOTCH_Graph * const grafptr, \ SCOTCH_Geom * const geomptr, \ const int * const filegrfptr, \ const int * const filegeoptr, \ const char * const dataptr, /* No use */ \ int * const revaptr, \ const int datanbr), \ (grafptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) { FILE * filegrfstream; /* Streams to build from handles */ FILE * filegeostream; int filegrfnum; /* Duplicated handle */ int filegeonum; int o; if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHGEOMLOADHABO: cannot duplicate handle (1)"); *revaptr = 1; /* Indicate error */ return; } if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHGEOMLOADHABO: cannot duplicate handle (2)"); close (filegrfnum); *revaptr = 1; /* Indicate error */ return; } if ((filegrfstream = fdopen (filegrfnum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHGEOMLOADHABO: cannot open input stream (1)"); close (filegrfnum); close (filegeonum); *revaptr = 1; return; } if ((filegeostream = fdopen (filegeonum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHGEOMLOADHABO: cannot open input stream (2)"); fclose (filegrfstream); close (filegeonum); *revaptr = 1; return; } o = SCOTCH_graphGeomLoadHabo (grafptr, geomptr, filegrfstream, filegeostream, NULL); fclose (filegrfstream); /* This closes file descriptors too */ fclose (filegeostream); *revaptr = o; } scotch-5.1.12b.dfsg/src/libscotch/dgraph_ghst.c0000644000175300017530000003701411631334325021576 0ustar hazelscthazelsct/* Copyright 2007-2009,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_ghst.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Francois CHATENET (P0.0) **/ /** Sebastien FOUCAULT (P0.0) **/ /** Nicolas GICQUEL (P0.1) **/ /** Jerome LACOSTE (P0.1) **/ /** **/ /** FUNCTION : Part of a parallel static mapper. **/ /** This module contains the halo building **/ /** routine. **/ /** **/ /** # Version P0.0 : from : 01 apr 1997 **/ /** to 20 jun 1997 **/ /** # Version P0.1 : from : 14 apr 1998 **/ /** to 20 jun 1998 **/ /** # Version 5.0 : from : 28 feb 2006 **/ /** to 10 sep 2007 **/ /** # Version 5.1 : from : 02 jul 2008 **/ /** to 20 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH_GHST #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_allreduce.h" #include "dgraph_ghst.h" #include "dgraph_halo.h" /* This routine builds the ghost structures ** required by the halo routines. If flagval ** is set to 0, the ghost edge array is built ** in addition to the local edge array, while ** if flagval is set to 1, the ghost edge array ** replaces the local edge array. This latter ** option is useful to save memory when processing ** intermediate graphs that are not visible to ** the user. ** It returns: ** - 0 : on success. ** - !0 : on error. */ DGRAPHALLREDUCEMAXSUMOP (2, 1) int dgraphGhst2 ( Dgraph * restrict const grafptr, /* Graph structure */ const int flagval) /* Replacement flag */ { int procngbnbr; /* Number of neighboring processes */ Gnum procsndnbr; int * restrict procsidtab; /* Send index array */ int procsidnbr; /* Number of entries in send index array */ Gnum vertsidnum; /* Last vertex index in send index array */ Gnum vertlocmin; /* Smallest index of local vertices */ Gnum vertlocmax; /* Largest index of local vertices, + 1 */ Gnum vertlocbas; /* Base index for ghost edge array */ Gnum vertlocnum; /* Current vertex number (based) */ Gnum * restrict vertsidtab; /* Flag array for building procs(i|n)dtab */ Gnum vertgstnum; /* Number of current ghost vertex */ DgraphGhstSort * restrict sortloctab; /* Array for sorting ghost vertices */ Gnum sortlocnbr; /* Number of ghost edges in sort array */ Gnum sortlocnum; Gnum * edgeloctax; /* Pointer to original edgeloctax array */ Gnum * edgegsttax; /* Pointer to ghost edge array, maybe the same */ Gnum reduloctab[3]; /* Gnum to perform a maxsum operator */ Gnum reduglbtab[3]; int cheklocval; if ((grafptr->flagval & DGRAPHHASEDGEGST) != 0) /* If ghost edge array already computed, do nothing */ return (0); edgeloctax = grafptr->edgeloctax; cheklocval = 0; if (grafptr->edgegsttax == NULL) { /* If ghost edge array not allocated yet */ if ((flagval == 0) || ((grafptr->flagval & DGRAPHFREETABS) == 0)) { /* If no replacement or cannot modify array */ if ((grafptr->edgegsttax = (Gnum *) memAlloc (grafptr->edgelocsiz * sizeof (Gnum))) == NULL) { errorPrint ("dgraphGhst: out of memory (1)"); cheklocval = 1; } else { grafptr->edgegsttax -= grafptr->baseval; grafptr->flagval |= DGRAPHFREEEDGEGST; /* Free array on exit */ } } else { /* Replace edgeloctab by edgegsttab */ grafptr->edgegsttax = grafptr->edgeloctax; grafptr->edgeloctax = NULL; if ((grafptr->flagval & DGRAPHFREETABS) != 0) grafptr->flagval |= DGRAPHFREEEDGEGST; /* It is edgegsttax which will free edloloctax if edge arrays are grouped */ } } if ((cheklocval == 0) && (memAllocGroup ((void **) (void *) &procsidtab, (size_t) ((grafptr->edgelocnbr + grafptr->vertlocnbr) * sizeof (int)), &vertsidtab, (size_t) (grafptr->procglbnbr * sizeof (Gnum)), &sortloctab, (size_t) ((grafptr->edgelocnbr + 1) * sizeof (DgraphGhstSort)), NULL) == NULL)) { errorPrint ("dgraphGhst: out of memory (2)"); cheklocval = 1; } reduloctab[0] = 1; /* Assume memory error and prepare data for aborting */ reduloctab[1] = reduloctab[2] = 0; if (cheklocval != 0) { /* TRICK: Processes not on error will perform collective communication at end of routine */ if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 2, 1, grafptr->proccomm) != 0) { errorPrint ("dgraphGhst: communication error (1)"); return (1); } } vertlocmin = grafptr->procvrttab[grafptr->proclocnum]; vertlocmax = grafptr->procvrttab[grafptr->proclocnum + 1]; vertlocbas = vertlocmin - grafptr->baseval; memSet (grafptr->procrcvtab, 0, grafptr->procglbnbr * sizeof (int)); memSet (grafptr->procsndtab, 0, grafptr->procglbnbr * sizeof (int)); memSet (vertsidtab, ~0, grafptr->procglbnbr * sizeof (Gnum)); edgegsttax = grafptr->edgegsttax; for (vertlocnum = vertsidnum = grafptr->baseval, sortlocnbr = 0, procsidnbr = 0; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { Gnum edgelocnum; for (edgelocnum = grafptr->vertloctax[vertlocnum]; edgelocnum < grafptr->vendloctax[vertlocnum]; edgelocnum ++) { Gnum vertlocend; vertlocend = edgeloctax[edgelocnum]; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((vertlocend < grafptr->baseval) || (vertlocend >= (grafptr->procvrttab[grafptr->procglbnbr]))) { errorPrint ("dgraphGhst: invalid edge array"); if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 2, 1, grafptr->proccomm) != 0) errorPrint ("dgraphGhst: communication error (2)"); memFree (procsidtab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if ((vertlocend >= vertlocmin) && (vertlocend < vertlocmax)) /* If edge is local */ edgegsttax[edgelocnum] = vertlocend - vertlocbas; /* Adjust its index */ else { /* End vertex is not local */ int procngbnum; int procngbmax; sortloctab[sortlocnbr].vertglbnum = vertlocend; /* Add it to sort array */ sortloctab[sortlocnbr].edgegstnum = edgelocnum; sortlocnbr ++; for (procngbnum = 0, procngbmax = grafptr->procglbnbr; procngbmax - procngbnum > 1; ) { int procngbmed; procngbmed = (procngbmax + procngbnum) / 2; if (grafptr->procvrttab[procngbmed] <= vertlocend) procngbnum = procngbmed; else procngbmax = procngbmed; } if (vertsidtab[procngbnum] != vertlocnum) { /* If vertex not already sent to process */ vertsidtab[procngbnum] = vertlocnum; /* Neighbor process will receive vertex */ grafptr->procsndtab[procngbnum] ++; /* One more vertex to send to this neighbor */ while ((vertlocnum - vertsidnum) >= DGRAPHGHSTSIDMAX) { /* If Gnum range too long for int */ procsidtab[procsidnbr ++] = -DGRAPHGHSTSIDMAX; /* Decrease by maximum int distance */ vertsidnum += DGRAPHGHSTSIDMAX; } if (vertsidnum != vertlocnum) { /* If communication concerns new local vertex */ procsidtab[procsidnbr ++] = - (vertlocnum - vertsidnum); /* Encode jump in procsidtab */ vertsidnum = vertlocnum; /* Current local vertex is last send vertex */ } procsidtab[procsidnbr ++] = procngbnum; /* Send this vertex data to this processor */ } } } } vertgstnum = grafptr->vertlocnnd; /* No ghost vertices yet */ procngbnbr = 0; /* No neighbor processes yet */ procsndnbr = 0; /* No vertex to send yet */ if (sortlocnbr > 0) { /* If there are ghost vertices */ Gnum vertgstbas; /* Number of current ghost vertex */ int procngbnum; intSort2asc1 (sortloctab, sortlocnbr); /* Sort them by ascending end vertex */ sortlocnum = 0; /* Start adjacency search from beginning */ procngbnum = -1; /* Start neighbor search from begnning */ do { /* For each distinct neighbor process */ vertgstbas = vertgstnum; /* Record first ghost number used for it */ edgegsttax[sortloctab[sortlocnum].edgegstnum] = vertgstnum; /* First ghost is always allocated */ while (grafptr->procvrttab[++ procngbnum + 1] <= sortloctab[sortlocnum].vertglbnum) { /* Find owner process */ #ifdef SCOTCH_DEBUG_DGRAPH2 if ((procngbnum > grafptr->procglbnbr) || /* If we have skipped a neighbor to which we have to send something */ (grafptr->procsndtab[procngbnum] != 0)) { errorPrint ("dgraphGhst: internal error (1)"); if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 2, 1, grafptr->proccomm) != 0) errorPrint ("dgraphGhst: communication error (3)"); memFree (procsidtab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ } #ifdef SCOTCH_DEBUG_DGRAPH2 if (grafptr->procsndtab[procngbnum] == 0) { /* If we had in fact no edges to send to this neighbor */ errorPrint ("dgraphGhst: internal error (2)"); if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 2, 1, grafptr->proccomm) != 0) errorPrint ("dgraphGhst: communication error (4)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ procsndnbr += grafptr->procsndtab[procngbnum]; /* Sum-up vertices to send */ grafptr->procngbtab[procngbnbr ++] = procngbnum; /* Add it to neighbor process array */ while (++ sortlocnum < sortlocnbr) { /* For all following ghost edges */ if (sortloctab[sortlocnum].vertglbnum != /* If new ghost vertex */ sortloctab[sortlocnum - 1].vertglbnum) { vertgstnum ++; /* Allocate new ghost vertex number */ if (grafptr->procvrttab[procngbnum + 1] <= sortloctab[sortlocnum].vertglbnum) { /* If new neighbor */ grafptr->procrcvtab[procngbnum] = vertgstnum - vertgstbas; /* Sum-up data for old neighbor */ break; /* Process new neighbor */ } } edgegsttax[sortloctab[sortlocnum].edgegstnum] = vertgstnum; /* Allocate ghost */ } } while (sortlocnum < sortlocnbr); vertgstnum ++; /* Size is one above last number */ grafptr->procrcvtab[procngbnum] = vertgstnum - vertgstbas; /* Sum-up data for last neighbor */ } grafptr->vertgstnbr = vertgstnum - grafptr->baseval; grafptr->vertgstnnd = grafptr->vertgstnbr + grafptr->baseval; grafptr->procngbnbr = procngbnbr; grafptr->procsndnbr = procsndnbr; grafptr->procsidtab = memRealloc (procsidtab, procsidnbr * sizeof (int)); /* Reallocate send index array */ grafptr->procsidnbr = procsidnbr; reduloctab[0] = 0; /* No memory error */ reduloctab[1] = /* Set maximum number of neighbors */ reduloctab[2] = grafptr->procngbnbr; if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 2, 1, grafptr->proccomm) != 0) { errorPrint ("dgraphGhst: communication error (5)"); return (1); } if (reduglbtab[0] != 0) /* If error, propagated by some previous reduction operator */ return (1); grafptr->procngbmax = reduglbtab[1]; grafptr->flagval |= DGRAPHFREEPSID | DGRAPHHASEDGEGST; /* Graph now has a valid ghost edge array */ #ifndef SCOTCH_COMM_COLL #ifndef SCOTCH_COMM_PTOP if (((float) reduglbtab[2]) <= ((float) grafptr->procglbnbr * (float) (grafptr->procglbnbr - 1) * (float) SCOTCH_COMM_PTOP_RAT)) #endif /* SCOTCH_COMM_PTOP */ grafptr->flagval |= DGRAPHCOMMPTOP; /* If too few communications, use point-to-point instead */ #endif /* SCOTCH_COMM_COLL */ #ifdef SCOTCH_DEBUG_DGRAPH2 if (dgraphHaloCheck (grafptr) != 0) { errorPrint ("dgraphGhst: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/hall_order_hx.h0000644000175300017530000000624711631334325022127 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hall_order_hx.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the halo ordering service **/ /** routines. **/ /** **/ /** DATES : # Version 4.0 : from : 14 jan 2003 **/ /** to : 08 dec 2003 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef HALL_ORDER_HX #define static #endif int hallOrderHxBuild (const Gnum, const Gnum, const Gnum, const Gnum * restrict const, Order * restrict const, OrderCblk * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, const Gnum, const Gnum, const float); Gnum hallOrderHxTree (const Gnum * restrict const, const Gnum * restrict const, const Gnum * restrict const, Gnum * restrict const, const Gnum, const Gnum); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_mapping.c0000644000175300017530000000617711631334325022471 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_mapping.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains miscellaneous **/ /** routines for handling centralized **/ /** graph mappings. **/ /** **/ /** DATES : # Version 5.1 : from : 17 nov 2010 **/ /** to 17 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /****************************************/ /* */ /* These routines are the C API for */ /* mapping structure handling routines. */ /* */ /****************************************/ /*+ This routine reserves a memory area *** of a size sufficient to store a *** graph mapping structure. *** It returns: *** - !NULL : if the initialization succeeded. *** - NULL : on error. +*/ SCOTCH_Mapping * SCOTCH_mapAlloc () { return ((SCOTCH_Mapping *) memAlloc (sizeof (SCOTCH_Mapping))); } scotch-5.1.12b.dfsg/src/libscotch/last_resort/0000755000175300017530000000000011145123146021471 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/src/libscotch/last_resort/parser_ly.h0000644000175300017530000000641411430776710023657 0ustar hazelscthazelsct/* A Bison parser, made by GNU Bison 2.4.2. */ /* Skeleton interface for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { METHODNAME = 258, PARAMNAME = 259, VALCASE = 260, VALDOUBLE = 261, VALINT = 262, VALSTRING = 263, VALSTRAT = 264, VALPARAM = 265, VALTEST = 266 }; #endif /* Tokens. */ #define METHODNAME 258 #define PARAMNAME 259 #define VALCASE 260 #define VALDOUBLE 261 #define VALINT 262 #define VALSTRING 263 #define VALSTRAT 264 #define VALPARAM 265 #define VALTEST 266 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { /* Line 1685 of yacc.c */ #line 90 "parser_yy.y" char CASEVAL; /* Case value */ StratTest * TEST; /* Test type */ StratTestType TESTOP; /* Relational type */ double DOUBLE; /* Double-precision */ INT INTEGER; /* Integer */ char STRING[PARSERSTRINGLEN]; /* Character string */ struct { const StratTab * tabl; /* Current tables */ Strat * strat; /* Current method */ StratParamTab * param; /* Current parameter */ } SAVE; /* Parameter type */ Strat * STRAT; /* Strategy tree */ /* Line 1685 of yacc.c */ #line 90 "y.tab.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif extern YYSTYPE scotchyylval; scotch-5.1.12b.dfsg/src/libscotch/last_resort/parser_ll.c0000644000175300017530000016011511430776707023642 0ustar hazelscthazelsct#line 2 "lex.yy.c" #line 4 "lex.yy.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define yy_create_buffer scotchyy_create_buffer #define yy_delete_buffer scotchyy_delete_buffer #define yy_flex_debug scotchyy_flex_debug #define yy_init_buffer scotchyy_init_buffer #define yy_flush_buffer scotchyy_flush_buffer #define yy_load_buffer_state scotchyy_load_buffer_state #define yy_switch_to_buffer scotchyy_switch_to_buffer #define yyin scotchyyin #define yyleng scotchyyleng #define yylex scotchyylex #define yylineno scotchyylineno #define yyout scotchyyout #define yyrestart scotchyyrestart #define yytext scotchyytext #define yywrap scotchyywrap #define yyalloc scotchyyalloc #define yyrealloc scotchyyrealloc #define yyfree scotchyyfree #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; #endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE scotchyyrestart(scotchyyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif extern int scotchyyleng; extern FILE *scotchyyin, *scotchyyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up scotchyytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up scotchyytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via scotchyyrestart()), so that the user can continue scanning by * just pointing scotchyyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when scotchyytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int scotchyyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow scotchyywrap()'s to do buffer switches * instead of setting up a fresh scotchyyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void scotchyyrestart (FILE *input_file ); void scotchyy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE scotchyy_create_buffer (FILE *file,int size ); void scotchyy_delete_buffer (YY_BUFFER_STATE b ); void scotchyy_flush_buffer (YY_BUFFER_STATE b ); void scotchyypush_buffer_state (YY_BUFFER_STATE new_buffer ); void scotchyypop_buffer_state (void ); static void scotchyyensure_buffer_stack (void ); static void scotchyy_load_buffer_state (void ); static void scotchyy_init_buffer (YY_BUFFER_STATE b,FILE *file ); #define YY_FLUSH_BUFFER scotchyy_flush_buffer(YY_CURRENT_BUFFER ) YY_BUFFER_STATE scotchyy_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE scotchyy_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE scotchyy_scan_bytes (yyconst char *bytes,int len ); void *scotchyyalloc (yy_size_t ); void *scotchyyrealloc (void *,yy_size_t ); void scotchyyfree (void * ); #define yy_new_buffer scotchyy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ scotchyyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ scotchyy_create_buffer(scotchyyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ scotchyyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ scotchyy_create_buffer(scotchyyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ typedef unsigned char YY_CHAR; FILE *scotchyyin = (FILE *) 0, *scotchyyout = (FILE *) 0; typedef int yy_state_type; extern int scotchyylineno; int scotchyylineno = 1; extern char *scotchyytext; #define yytext_ptr scotchyytext static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up scotchyytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ scotchyyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 13 #define YY_END_OF_BUFFER 14 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[56] = { 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 14, 12, 11, 11, 1, 2, 3, 12, 4, 12, 5, 12, 12, 8, 10, 11, 2, 4, 0, 0, 5, 0, 0, 0, 7, 8, 0, 0, 10, 4, 0, 4, 6, 0, 6, 9, 0, 9, 0 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 5, 6, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1, 1, 1, 8, 8, 8, 8, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 8, 8, 8, 8, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int32_t yy_meta[10] = { 0, 1, 2, 2, 1, 1, 1, 3, 3, 3 } ; static yyconst flex_int16_t yy_base[61] = { 0, 0, 2, 0, 0, 2, 0, 5, 0, 10, 0, 13, 0, 64, 63, 16, 0, 66, 69, 0, 0, 69, 0, 69, 58, 20, 57, 24, 59, 55, 28, 0, 0, 0, 0, 47, 33, 0, 44, 36, 44, 69, 0, 38, 39, 0, 40, 35, 32, 43, 29, 25, 46, 21, 15, 69, 55, 17, 13, 58, 3 } ; static yyconst flex_int16_t yy_def[61] = { 0, 56, 56, 2, 3, 2, 5, 5, 7, 2, 9, 9, 11, 2, 2, 2, 15, 55, 55, 57, 57, 55, 58, 55, 55, 55, 55, 55, 59, 55, 55, 60, 57, 58, 25, 55, 55, 27, 55, 55, 59, 55, 30, 55, 55, 60, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55 } ; static yyconst flex_int16_t yy_nxt[79] = { 0, 55, 19, 20, 19, 20, 45, 21, 21, 21, 22, 22, 23, 23, 23, 24, 33, 25, 26, 32, 27, 29, 54, 30, 31, 31, 35, 34, 54, 36, 38, 37, 51, 39, 43, 42, 51, 44, 47, 48, 48, 50, 48, 51, 53, 52, 54, 46, 41, 36, 49, 49, 39, 52, 46, 44, 18, 18, 18, 40, 40, 40, 42, 41, 37, 34, 55, 28, 28, 17, 55, 55, 55, 55, 55, 55, 55, 55, 55 } ; static yyconst flex_int16_t yy_chk[79] = { 0, 0, 1, 1, 2, 2, 60, 3, 3, 3, 5, 5, 7, 7, 7, 9, 58, 9, 11, 57, 11, 15, 54, 15, 15, 15, 25, 25, 53, 25, 27, 27, 51, 27, 30, 30, 50, 30, 36, 48, 36, 39, 47, 39, 44, 43, 44, 46, 40, 46, 49, 38, 49, 52, 35, 52, 56, 56, 56, 59, 59, 59, 29, 28, 26, 24, 17, 14, 13, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; extern int scotchyy_flex_debug; int scotchyy_flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *scotchyytext; #line 1 "parser_ll.l" #line 2 "parser_ll.l" /* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : parser_ll.l **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the lexical parser **/ /** which processes strategy strings. **/ /** **/ /** DATES : # Version 3.1 : from : 07 nov 1995 **/ /** to 23 aug 1996 **/ /** # Version 3.2 : from : 24 sep 1996 **/ /** to 05 jun 1997 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 11 sep 2001 **/ /** # Version 4.0 : from : 20 dec 2001 **/ /** to 23 dec 2001 **/ /** # Version 5.1 : from : 09 jun 2009 **/ /** to 09 jun 2009 **/ /** **/ /** NOTES : # In order for flex to read its input **/ /** with getc() instead of fread, we set **/ /** YY_ALWAYS_INTERACTIVE to 1. This may **/ /** not always work with future releases. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define PARSER_LL #include "module.h" #include "common.h" #undef INTEGER /* In case someone defined them */ #undef DOUBLE #include "parser.h" #include "parser_ll.h" #include "parser_yy.h" #include "parser_ly.h" /*+ Definitions produced by yacc +*/ /* Assume no interactive parsing. */ #ifdef X_OSDOS /* Available only with MKS LEX */ #ifdef YY_INTERACTIVE #undef YY_INTERACTIVE #endif /* YY_INTERACTIVE */ #define YY_INTERACTIVE 0 #endif /* X_OSDOS */ #ifdef FLEX_SCANNER #define YY_ALWAYS_INTERACTIVE 1 /* Set the parser as interactive and read one char at a time */ #define YY_INPUT(buf,result,max_size) { int c = stratParserInput (); result = (c == 0) ? YY_NULL : ((buf)[0] = c, 1); } #else /* FLEX_SCANNER */ #undef getc /* Redirect I/O functions */ #define getc yygetc #undef yygetc #define yygetc(stream) stratParserInput () #endif /* FLEX_SCANNER */ #define YY_NO_UNPUT /* No prototype for yyunput as not defined */ #define YY_SKIP_YYWRAP /* No prototype for scotchyywrap as defined as macro */ #define scotchyywrap() (1) /* Always return end-of-file on end-of-string */ /* ** The static variables. */ static const char * stratparserstringptr; /* Pointer to the string to parse */ #line 610 "lex.yy.c" #define INITIAL 0 #define lstrat 1 #define lparam 2 #define lparamcase 3 #define lparamdouble 4 #define lparamint 5 #define lparamstring 6 #define ltest 7 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals (void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int scotchyylex_destroy (void ); int scotchyyget_debug (void ); void scotchyyset_debug (int debug_flag ); YY_EXTRA_TYPE scotchyyget_extra (void ); void scotchyyset_extra (YY_EXTRA_TYPE user_defined ); FILE *scotchyyget_in (void ); void scotchyyset_in (FILE * in_str ); FILE *scotchyyget_out (void ); void scotchyyset_out (FILE * out_str ); int scotchyyget_leng (void ); char *scotchyyget_text (void ); int scotchyyget_lineno (void ); void scotchyyset_lineno (int line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int scotchyywrap (void ); #else extern int scotchyywrap (void ); #endif #endif static void yyunput (int c,char *buf_ptr ); #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void ); #else static int input (void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( scotchyytext, scotchyyleng, 1, scotchyyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ unsigned n; \ for ( n = 0; n < max_size && \ (c = getc( scotchyyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( scotchyyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, scotchyyin))==0 && ferror(scotchyyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(scotchyyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int scotchyylex (void); #define YY_DECL int scotchyylex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after scotchyytext and scotchyyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; #line 121 "parser_ll.l" #line 801 "lex.yy.c" if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! scotchyyin ) scotchyyin = stdin; if ( ! scotchyyout ) scotchyyout = stdout; if ( ! YY_CURRENT_BUFFER ) { scotchyyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = scotchyy_create_buffer(scotchyyin,YY_BUF_SIZE ); } scotchyy_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); /* Support of scotchyytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 56 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 69 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: YY_RULE_SETUP #line 122 "parser_ll.l" { strncpy (yylval.STRING, scotchyytext, PARSERSTRINGLEN); yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; return (METHODNAME); } YY_BREAK case 2: YY_RULE_SETUP #line 128 "parser_ll.l" { strncpy (yylval.STRING, scotchyytext, PARSERSTRINGLEN); yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; return (PARAMNAME); } YY_BREAK case 3: YY_RULE_SETUP #line 134 "parser_ll.l" { yylval.CASEVAL = scotchyytext[0]; return (VALCASE); } YY_BREAK case 4: YY_RULE_SETUP #line 139 "parser_ll.l" { yylval.DOUBLE = atof (scotchyytext); return (VALDOUBLE); } YY_BREAK case 5: YY_RULE_SETUP #line 144 "parser_ll.l" { yylval.INTEGER = (INT) atol (scotchyytext); return (VALINT); } YY_BREAK case 6: YY_RULE_SETUP #line 148 "parser_ll.l" { yylval.INTEGER = (INT) atof (scotchyytext); /* FLOAT is put after so that INTEGER can be matched */ return (VALINT); } YY_BREAK case 7: /* rule 7 can match eol */ YY_RULE_SETUP #line 153 "parser_ll.l" { scotchyytext[scotchyyleng - 1] = '\0'; /* Remove the heading and trailing \" */ strncpy (yylval.STRING, scotchyytext + 1, PARSERSTRINGLEN); yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; return (VALSTRING); } YY_BREAK case 8: YY_RULE_SETUP #line 160 "parser_ll.l" { yylval.INTEGER = (INT) atol (scotchyytext); return (VALINT); } YY_BREAK case 9: YY_RULE_SETUP #line 164 "parser_ll.l" { yylval.DOUBLE = atof (scotchyytext); return (VALDOUBLE); } YY_BREAK case 10: YY_RULE_SETUP #line 168 "parser_ll.l" { strncpy (yylval.STRING, scotchyytext, PARSERSTRINGLEN); yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; return (PARAMNAME); } YY_BREAK case 11: /* rule 11 can match eol */ YY_RULE_SETUP #line 174 "parser_ll.l" ; YY_BREAK case 12: YY_RULE_SETUP #line 175 "parser_ll.l" return (scotchyytext[0]); YY_BREAK case 13: YY_RULE_SETUP #line 177 "parser_ll.l" ECHO; YY_BREAK #line 986 "lex.yy.c" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(lstrat): case YY_STATE_EOF(lparam): case YY_STATE_EOF(lparamcase): case YY_STATE_EOF(lparamdouble): case YY_STATE_EOF(lparamint): case YY_STATE_EOF(lparamstring): case YY_STATE_EOF(ltest): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed scotchyyin at a new source and called * scotchyylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = scotchyyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_c_buf_p); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( scotchyywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * scotchyytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of scotchyylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ scotchyyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; scotchyyrestart(scotchyyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) scotchyyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 56 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { register int yy_is_jam; register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 56 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 55); return yy_is_jam ? 0 : yy_current_state; } static void yyunput (int c, register char * yy_bp ) { register char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up scotchyytext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = (yy_n_chars) + 2; register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; register char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ scotchyyrestart(scotchyyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( scotchyywrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve scotchyytext */ (yy_hold_char) = *++(yy_c_buf_p); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void scotchyyrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ scotchyyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = scotchyy_create_buffer(scotchyyin,YY_BUF_SIZE ); } scotchyy_init_buffer(YY_CURRENT_BUFFER,input_file ); scotchyy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void scotchyy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * scotchyypop_buffer_state(); * scotchyypush_buffer_state(new_buffer); */ scotchyyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; scotchyy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (scotchyywrap()) processing, but the only time this flag * is looked at is after scotchyywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void scotchyy_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; scotchyyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE scotchyy_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) scotchyyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in scotchyy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) scotchyyalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in scotchyy_create_buffer()" ); b->yy_is_our_buffer = 1; scotchyy_init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with scotchyy_create_buffer() * */ void scotchyy_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) scotchyyfree((void *) b->yy_ch_buf ); scotchyyfree((void *) b ); } #ifndef __cplusplus extern int isatty (int ); #endif /* __cplusplus */ /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a scotchyyrestart() or at EOF. */ static void scotchyy_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; scotchyy_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then scotchyy_init_buffer was _probably_ * called from scotchyyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void scotchyy_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) scotchyy_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void scotchyypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; scotchyyensure_buffer_stack(); /* This block is copied from scotchyy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from scotchyy_switch_to_buffer. */ scotchyy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void scotchyypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; scotchyy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { scotchyy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void scotchyyensure_buffer_stack (void) { int num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (yy_buffer_stack) = (struct yy_buffer_state**)scotchyyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in scotchyyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)scotchyyrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in scotchyyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE scotchyy_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) scotchyyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in scotchyy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; scotchyy_switch_to_buffer(b ); return b; } /** Setup the input buffer state to scan a string. The next call to scotchyylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * scotchyy_scan_bytes() instead. */ YY_BUFFER_STATE scotchyy_scan_string (yyconst char * yystr ) { return scotchyy_scan_bytes(yystr,strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to scotchyylex() will * scan from a @e copy of @a bytes. * @param bytes the byte buffer to scan * @param len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE scotchyy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) scotchyyalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in scotchyy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = scotchyy_scan_buffer(buf,n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in scotchyy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up scotchyytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ scotchyytext[scotchyyleng] = (yy_hold_char); \ (yy_c_buf_p) = scotchyytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ scotchyyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int scotchyyget_lineno (void) { return scotchyylineno; } /** Get the input stream. * */ FILE *scotchyyget_in (void) { return scotchyyin; } /** Get the output stream. * */ FILE *scotchyyget_out (void) { return scotchyyout; } /** Get the length of the current token. * */ int scotchyyget_leng (void) { return scotchyyleng; } /** Get the current token. * */ char *scotchyyget_text (void) { return scotchyytext; } /** Set the current line number. * @param line_number * */ void scotchyyset_lineno (int line_number ) { scotchyylineno = line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * * @see scotchyy_switch_to_buffer */ void scotchyyset_in (FILE * in_str ) { scotchyyin = in_str ; } void scotchyyset_out (FILE * out_str ) { scotchyyout = out_str ; } int scotchyyget_debug (void) { return scotchyy_flex_debug; } void scotchyyset_debug (int bdebug ) { scotchyy_flex_debug = bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from scotchyylex_destroy(), so don't allocate here. */ (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = (char *) 0; (yy_init) = 0; (yy_start) = 0; /* Defined in main.c */ #ifdef YY_STDINIT scotchyyin = stdin; scotchyyout = stdout; #else scotchyyin = (FILE *) 0; scotchyyout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * scotchyylex_init() */ return 0; } /* scotchyylex_destroy is for both reentrant and non-reentrant scanners. */ int scotchyylex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ scotchyy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; scotchyypop_buffer_state(); } /* Destroy the stack itself. */ scotchyyfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * scotchyylex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *scotchyyalloc (yy_size_t size ) { return (void *) malloc( size ); } void *scotchyyrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void scotchyyfree (void * ptr ) { free( (char *) ptr ); /* see scotchyyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 177 "parser_ll.l" /*******************************************/ /* */ /* These routines handle data input to the */ /* lexical analyzer. */ /* */ /*******************************************/ /* This routine initializes the ** lexical analyzer. ** It returns: ** - VOID : in all cases. */ void stratParserInit ( const char * const string) /*+ Strategy string to parse +*/ { #ifdef FLEX_SCANNER scotchyyrestart (scotchyyin); /* (Re-)initialize the parser */ #endif /* FLEX_SCANNER */ stratParserSelect (VALSTRAT); /* Begin with a strategy */ stratparserstringptr = string; /* Point to beginning of string */ } /* This routine reads a single character ** from the input string. ** It returns: ** - 0 : if end of string reached. ** - !0 : character from string. */ static int stratParserInput () { if (*stratparserstringptr == '\0') /* If end-of-string reached */ return (0); /* Return end-of-file token */ else /* Else return the character */ return ((int) (unsigned char) *stratparserstringptr ++); } /* This routine returns the pointer to the ** remaining part of the string. */ const char * stratParserRemain () { return (stratparserstringptr); } /* This routine selects the sub-parser ** to parse the input. ** It returns: ** - VOID : in all cases. */ void stratParserSelect ( unsigned int type) { switch (type) { case VALCASE : BEGIN lparamcase; break; case VALDOUBLE : BEGIN lparamdouble; break; case VALINT : BEGIN lparamint; break; case VALSTRING : BEGIN lparamstring; break; case VALPARAM : BEGIN lparam; break; case VALSTRAT : BEGIN lstrat; break; case VALTEST : BEGIN ltest; break; } } scotch-5.1.12b.dfsg/src/libscotch/last_resort/parser_yy.c0000644000175300017530000023201711430776710023667 0ustar hazelscthazelsct/* A Bison parser, made by GNU Bison 2.4.2. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.4.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Using locations. */ #define YYLSP_NEEDED 0 /* Substitute the variable and function names. */ #define yyparse scotchyyparse #define yylex scotchyylex #define yyerror scotchyyerror #define yylval scotchyylval #define yychar scotchyychar #define yydebug scotchyydebug #define yynerrs scotchyynerrs /* Copy the first part of user declarations. */ /* Line 189 of yacc.c */ #line 1 "parser_yy.y" /* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : parser_yy.y **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the syntactic parser **/ /** which processes strategy strings. **/ /** **/ /** DATES : # Version 3.1 : from : 07 nov 1995 **/ /** to 13 jun 1996 **/ /** # Version 3.2 : from : 24 sep 1996 **/ /** to 27 feb 1997 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 20 dec 2001 **/ /** to 11 jun 2004 **/ /** # Version 5.1 : from : 30 oct 2007 **/ /** to 09 jun 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define PARSER_YY #include "module.h" #include "common.h" #undef INTEGER /* In case someone defined them */ #undef DOUBLE #include "parser.h" #include "parser_ll.h" #include "parser_yy.h" /* #define SCOTCH_DEBUG_PARSER3 */ #ifdef SCOTCH_DEBUG_PARSER3 extern int yydebug; #define YYDEBUG 1 #endif /* SCOTCH_DEBUG_PARSER3 */ /* ** The static and global definitions. ** See also at the end of this file. */ static const StratTab * parserstrattab; /* Pointer to parsing tables */ static Strat * parserstratcurr = NULL; /* Pointer to current strategy node */ static StratParamTab * parserparamcurr = NULL; /* Pointer to current parameter */ extern unsigned int parsermethtokentab[]; /* Pre-definition for stupid compilers */ /* Line 189 of yacc.c */ #line 170 "y.tab.c" /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { METHODNAME = 258, PARAMNAME = 259, VALCASE = 260, VALDOUBLE = 261, VALINT = 262, VALSTRING = 263, VALSTRAT = 264, VALPARAM = 265, VALTEST = 266 }; #endif /* Tokens. */ #define METHODNAME 258 #define PARAMNAME 259 #define VALCASE 260 #define VALDOUBLE 261 #define VALINT 262 #define VALSTRING 263 #define VALSTRAT 264 #define VALPARAM 265 #define VALTEST 266 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { /* Line 214 of yacc.c */ #line 90 "parser_yy.y" char CASEVAL; /* Case value */ StratTest * TEST; /* Test type */ StratTestType TESTOP; /* Relational type */ double DOUBLE; /* Double-precision */ INT INTEGER; /* Integer */ char STRING[PARSERSTRINGLEN]; /* Character string */ struct { const StratTab * tabl; /* Current tables */ Strat * strat; /* Current method */ StratParamTab * param; /* Current parameter */ } SAVE; /* Parameter type */ Strat * STRAT; /* Strategy tree */ /* Line 214 of yacc.c */ #line 245 "y.tab.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif /* Copy the second part of user declarations. */ /* Line 264 of yacc.c */ #line 257 "y.tab.c" #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int yyi) #else static int YYID (yyi) int yyi; #endif { return yyi; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 13 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 82 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 31 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 35 /* YYNRULES -- Number of rules. */ #define YYNRULES 61 /* YYNRULES -- Number of states. */ #define YYNSTATES 88 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 266 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 24, 2, 2, 2, 30, 23, 2, 17, 18, 29, 27, 21, 28, 2, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 15, 25, 22, 26, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 19, 12, 20, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint8 yyprhs[] = { 0, 0, 3, 5, 9, 11, 13, 14, 17, 19, 20, 21, 30, 32, 35, 36, 40, 42, 43, 47, 48, 49, 55, 56, 60, 62, 63, 68, 70, 72, 74, 76, 77, 80, 82, 84, 88, 90, 94, 96, 99, 103, 105, 109, 111, 113, 115, 119, 121, 123, 125, 129, 131, 133, 137, 139, 141, 145, 147, 149, 151, 153 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { 32, 0, -1, 33, -1, 33, 12, 34, -1, 34, -1, 35, -1, -1, 35, 36, -1, 36, -1, -1, -1, 37, 13, 51, 38, 14, 33, 39, 15, -1, 40, -1, 16, 33, -1, -1, 17, 33, 18, -1, 41, -1, -1, 3, 42, 43, -1, -1, -1, 44, 19, 46, 45, 20, -1, -1, 46, 21, 47, -1, 47, -1, -1, 4, 48, 22, 49, -1, 5, -1, 6, -1, 7, -1, 8, -1, -1, 50, 33, -1, 1, -1, 52, -1, 52, 12, 53, -1, 53, -1, 53, 23, 54, -1, 54, -1, 24, 54, -1, 17, 52, 18, -1, 55, -1, 57, 56, 57, -1, 25, -1, 22, -1, 26, -1, 57, 58, 59, -1, 59, -1, 27, -1, 28, -1, 59, 60, 61, -1, 61, -1, 29, -1, 61, 62, 63, -1, 63, -1, 30, -1, 17, 57, 18, -1, 64, -1, 65, -1, 6, -1, 7, -1, 4, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 130, 130, 136, 154, 157, 159, 174, 192, 196, 200, 196, 224, 227, 232, 237, 241, 245, 244, 306, 310, 306, 314, 317, 318, 322, 321, 360, 393, 406, 419, 434, 434, 456, 464, 467, 485, 488, 506, 509, 525, 529, 532, 551, 555, 559, 565, 581, 584, 588, 594, 610, 613, 619, 635, 638, 644, 648, 649, 652, 667, 684 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "METHODNAME", "PARAMNAME", "VALCASE", "VALDOUBLE", "VALINT", "VALSTRING", "VALSTRAT", "VALPARAM", "VALTEST", "'|'", "'/'", "'?'", "';'", "':'", "'('", "')'", "'{'", "'}'", "','", "'='", "'&'", "'!'", "'<'", "'>'", "'+'", "'-'", "'*'", "'%'", "$accept", "STRAT", "STRATSELECT", "STRATEMPTY", "STRATCONCAT", "STRATTEST", "$@1", "$@2", "STRATTESTELSE", "STRATGROUP", "STRATMETHOD", "$@3", "METHODPARAM", "$@4", "$@5", "PARAMLIST", "PARAMPARAM", "@6", "PARAMVAL", "@7", "TEST", "TESTOR", "TESTAND", "TESTNOT", "TESTREL", "TESTRELOP", "TESTEXPR1", "TESTEXPR1OP", "TESTEXPR2", "TESTEXPR2OP", "TESTEXPR3", "TESTEXPR3OP", "TESTEXPR4", "TESTVAL", "TESTVAR", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 124, 47, 63, 59, 58, 40, 41, 123, 125, 44, 61, 38, 33, 60, 62, 43, 45, 42, 37 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 31, 32, 33, 33, 34, 34, 35, 35, 37, 38, 36, 36, 39, 39, 40, 40, 42, 41, 44, 45, 43, 43, 46, 46, 48, 47, 49, 49, 49, 49, 50, 49, 49, 51, 52, 52, 53, 53, 54, 54, 54, 55, 56, 56, 56, 57, 57, 58, 58, 59, 59, 60, 61, 61, 62, 63, 63, 63, 64, 64, 65 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 1, 3, 1, 1, 0, 2, 1, 0, 0, 8, 1, 2, 0, 3, 1, 0, 3, 0, 0, 5, 0, 3, 1, 0, 4, 1, 1, 1, 1, 0, 2, 1, 1, 3, 1, 3, 1, 2, 3, 1, 3, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 3, 1, 1, 3, 1, 1, 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 6, 17, 6, 0, 2, 4, 5, 8, 0, 12, 16, 22, 0, 1, 6, 7, 0, 18, 0, 15, 3, 61, 59, 60, 0, 0, 10, 34, 36, 38, 41, 0, 47, 51, 54, 57, 58, 0, 0, 0, 39, 0, 0, 0, 44, 43, 45, 48, 49, 0, 0, 52, 0, 55, 0, 25, 20, 24, 40, 56, 6, 35, 37, 0, 42, 46, 50, 53, 0, 0, 0, 14, 0, 0, 23, 21, 6, 0, 33, 27, 28, 29, 30, 26, 6, 13, 11, 32 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { -1, 3, 4, 5, 6, 7, 8, 41, 77, 9, 10, 11, 17, 18, 70, 56, 57, 68, 83, 84, 26, 27, 28, 29, 30, 49, 31, 50, 32, 52, 33, 54, 34, 35, 36 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -24 static const yytype_int8 yypact[] = { 12, -24, 12, 3, 15, -24, 12, -24, 11, -24, -24, 9, 31, -24, 12, -24, 13, -24, 16, -24, -24, -24, -24, -24, 13, 13, -24, 24, 29, -24, -24, 34, 10, 2, -24, -24, -24, 49, 45, 20, -24, 40, 13, 13, -24, -24, -24, -24, -24, 27, 27, -24, 27, -24, 27, -24, 43, -24, -24, -24, 12, 29, -24, 27, -17, 10, 2, -24, 33, 49, 46, 0, 23, 1, -24, -24, 12, 50, -24, -24, -24, -24, -24, -24, 12, 15, -24, 15 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -24, -24, -2, 53, -24, 62, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, 4, -24, -24, -24, -24, 47, 28, -20, -24, -24, -23, -24, 19, -24, 25, -24, 18, -24, -24 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -32 static const yytype_int8 yytable[] = { 12, 39, 78, 13, -31, 40, 79, 80, 81, 82, 47, 48, 14, -31, -31, 1, 76, 21, -31, 22, 23, -31, -31, 62, 16, -9, 64, 14, -19, 2, 24, 21, 53, 22, 23, 37, 42, 25, 59, 51, 72, 59, 44, 14, 63, 45, 46, 47, 48, 19, 47, 48, 43, 55, 60, 73, 44, 42, 71, 45, 46, 47, 48, 58, 69, 86, 75, 20, 15, 65, 61, 38, 67, 74, 85, 0, 0, 66, 0, 0, 0, 0, 87 }; static const yytype_int8 yycheck[] = { 2, 24, 1, 0, 3, 25, 5, 6, 7, 8, 27, 28, 12, 12, 13, 3, 16, 4, 17, 6, 7, 20, 21, 43, 13, 13, 49, 12, 19, 17, 17, 4, 30, 6, 7, 19, 12, 24, 18, 29, 63, 18, 22, 12, 17, 25, 26, 27, 28, 18, 27, 28, 23, 4, 14, 22, 22, 12, 60, 25, 26, 27, 28, 18, 21, 15, 20, 14, 6, 50, 42, 24, 54, 69, 76, -1, -1, 52, -1, -1, -1, -1, 84 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 3, 17, 32, 33, 34, 35, 36, 37, 40, 41, 42, 33, 0, 12, 36, 13, 43, 44, 18, 34, 4, 6, 7, 17, 24, 51, 52, 53, 54, 55, 57, 59, 61, 63, 64, 65, 19, 52, 57, 54, 38, 12, 23, 22, 25, 26, 27, 28, 56, 58, 29, 60, 30, 62, 4, 46, 47, 18, 18, 14, 53, 54, 17, 57, 59, 61, 63, 48, 21, 45, 33, 57, 22, 47, 20, 16, 39, 1, 5, 6, 7, 8, 49, 50, 33, 15, 33 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. However, YYFAIL appears to be in use. Nevertheless, it is formally deprecated in Bison 2.4.2's NEWS entry, where a plan to phase it out is discussed. */ #define YYFAIL goto yyerrlab #if defined YYFAIL /* This is here to suppress warnings from the GCC cpp's -Wunused-macros. Normally we don't worry about that warning, but some users do, and we want to make it easy for users to remove YYFAIL uses, which will produce warnings from Bison 2.5. */ #endif #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else # define YYLEX yylex () #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) #else static void yy_stack_print (yybottom, yytop) yytype_int16 *yybottom; yytype_int16 *yytop; #endif { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) { int yybot = *yybottom; YYFPRINTF (stderr, " %d", yybot); } YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, int yyrule) #else static void yy_reduce_print (yyvsp, yyrule) YYSTYPE *yyvsp; int yyrule; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, Rule); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into YYRESULT an error message about the unexpected token YYCHAR while in state YYSTATE. Return the number of bytes copied, including the terminating null byte. If YYRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return YYSIZE_MAXIMUM if overflow occurs during size calculation. */ static YYSIZE_T yysyntax_error (char *yyresult, int yystate, int yychar) { int yyn = yypact[yystate]; if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) return 0; else { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; if (yysize_overflow) return YYSIZE_MAXIMUM; if (yyresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yyresult; int yyi = 0; while ((*yyp = *yyf) != '\0') { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } } return yysize; } } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yymsg, yytype, yyvaluep) const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*-------------------------. | yyparse or yypush_parse. | `-------------------------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else int yyparse () #endif #endif { int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* The stacks and their tools: `yyss': related to states. `yyvs': related to semantic values. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs; YYSTYPE *yyvsp; YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ int yytoken; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; yytoken = 0; yyss = yyssa; yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: /* Line 1464 of yacc.c */ #line 131 "parser_yy.y" { parserstratcurr = ((yyvsp[(1) - (1)].STRAT)); /* Save pointer to root of tree */ } break; case 3: /* Line 1464 of yacc.c */ #line 137 "parser_yy.y" { Strat * strat; if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { errorPrint ("stratParserParse: out of memory (2)"); stratExit ((yyvsp[(1) - (3)].STRAT)); stratExit ((yyvsp[(3) - (3)].STRAT)); YYABORT; } strat->tabl = parserstrattab; strat->type = STRATNODESELECT; strat->data.select.strat[0] = ((yyvsp[(1) - (3)].STRAT)); strat->data.select.strat[1] = ((yyvsp[(3) - (3)].STRAT)); ((yyval.STRAT)) = strat; } break; case 6: /* Line 1464 of yacc.c */ #line 159 "parser_yy.y" { Strat * strat; if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { errorPrint ("stratParserParse: out of memory (3)"); YYABORT; } strat->tabl = parserstrattab; strat->type = STRATNODEEMPTY; ((yyval.STRAT)) = strat; } break; case 7: /* Line 1464 of yacc.c */ #line 175 "parser_yy.y" { Strat * strat; if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { errorPrint ("stratParserParse: out of memory (4)"); stratExit ((yyvsp[(1) - (2)].STRAT)); stratExit ((yyvsp[(2) - (2)].STRAT)); YYABORT; } strat->tabl = parserstrattab; strat->type = STRATNODECONCAT; strat->data.concat.strat[0] = ((yyvsp[(1) - (2)].STRAT)); strat->data.concat.strat[1] = ((yyvsp[(2) - (2)].STRAT)); ((yyval.STRAT)) = strat; } break; case 9: /* Line 1464 of yacc.c */ #line 196 "parser_yy.y" { stratParserSelect (VALTEST); /* Parse parameter tokens */ } break; case 10: /* Line 1464 of yacc.c */ #line 200 "parser_yy.y" { stratParserSelect (VALSTRAT); /* Parse strategy tokens */ } break; case 11: /* Line 1464 of yacc.c */ #line 204 "parser_yy.y" { Strat * strat; if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { errorPrint ("stratParserParse: out of memory (1)"); stratExit ((yyvsp[(6) - (8)].STRAT)); if (((yyvsp[(7) - (8)].STRAT)) != NULL) stratExit ((yyvsp[(7) - (8)].STRAT)); stratTestExit ((yyvsp[(3) - (8)].TEST)); YYABORT; } strat->tabl = parserstrattab; strat->type = STRATNODECOND; strat->data.cond.test = ((yyvsp[(3) - (8)].TEST)); strat->data.cond.strat[0] = ((yyvsp[(6) - (8)].STRAT)); strat->data.cond.strat[1] = ((yyvsp[(7) - (8)].STRAT)); ((yyval.STRAT)) = strat; } break; case 13: /* Line 1464 of yacc.c */ #line 228 "parser_yy.y" { ((yyval.STRAT)) = ((yyvsp[(2) - (2)].STRAT)); } break; case 14: /* Line 1464 of yacc.c */ #line 232 "parser_yy.y" { ((yyval.STRAT)) = NULL; } break; case 15: /* Line 1464 of yacc.c */ #line 238 "parser_yy.y" { ((yyval.STRAT)) = ((yyvsp[(2) - (3)].STRAT)); } break; case 17: /* Line 1464 of yacc.c */ #line 245 "parser_yy.y" { Strat * strat; int meth; int methlen; StratMethodTab * methtab; int i, j; meth = methlen = 0; /* No method recognized yet */ methtab = parserstrattab->methtab; /* Point to the method table */ for (i = 0; methtab[i].name != NULL; i ++) { if ((strncasecmp (((yyvsp[(1) - (1)].STRING)), /* Find longest matching code name */ methtab[i].name, j = strlen (methtab[i].name)) == 0) && (j > methlen)) { meth = methtab[i].meth; methlen = j; } } if (methlen == 0) { /* If method name not known */ errorPrint ("stratParserParse: invalid method name \"%s\", before \"%s\"", ((yyvsp[(1) - (1)].STRING)), stratParserRemain ()); YYABORT; } if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { errorPrint ("stratParserParse: out of memory (5)"); YYABORT; } strat->tabl = parserstrattab; strat->type = STRATNODEMETHOD; strat->data.method.meth = meth; /* Set method type */ if (methtab[meth].data != NULL) /* If default values exist */ memcpy (&strat->data.method.data, /* Set values to default */ methtab[meth].data, sizeof (StratNodeMethodData)); parserstratcurr = strat; /* Structure available for parameter processing */ } break; case 18: /* Line 1464 of yacc.c */ #line 285 "parser_yy.y" { StratParamTab * paratab; int i; paratab = parserstrattab->paratab; /* Point to the parameter table */ for (i = 0; paratab[i].name != NULL; i ++) { if ((paratab[i].meth == parserstratcurr->data.method.meth) && /* If a strategy parameter found for this method */ (paratab[i].type == STRATPARAMSTRAT)) { if (*((Strat **) ((byte *) &parserstratcurr->data.method.data + /* And this parameter has not been set */ (paratab[i].dataofft - paratab[i].database))) == NULL) errorPrintW ("stratParserParse: strategy parameter \"%s\" of method \"%s\" not set, before \"%s\"", paratab[i].name, parserstrattab->methtab[parserstratcurr->data.method.meth].name, stratParserRemain ()); } } ((yyval.STRAT)) = parserstratcurr; /* Return current structure */ parserstratcurr = NULL; /* No current structure */ } break; case 19: /* Line 1464 of yacc.c */ #line 306 "parser_yy.y" { stratParserSelect (VALPARAM); /* Parse parameter tokens */ } break; case 20: /* Line 1464 of yacc.c */ #line 310 "parser_yy.y" { stratParserSelect (VALSTRAT); /* Parse strategy tokens */ } break; case 25: /* Line 1464 of yacc.c */ #line 322 "parser_yy.y" { int para; int paralen; StratParamTab * paratab; int i, j; para = paralen = 0; /* No parameter recognized yet */ paratab = parserstrattab->paratab; /* Point to the parameter table */ for (i = 0; paratab[i].name != NULL; i ++) { if ((paratab[i].meth == parserstratcurr->data.method.meth) && (strncasecmp (((yyvsp[(1) - (1)].STRING)), /* Find longest matching parameter name */ paratab[i].name, j = strlen (paratab[i].name)) == 0) && (j > paralen)) { para = i; paralen = j; } } if (paralen == 0) { errorPrint ("stratParserParse: invalid method parameter name \"%s\", before \"%s\"", ((yyvsp[(1) - (1)].STRING)), stratParserRemain ()); YYABORT; } ((yyval.SAVE)).tabl = parserstrattab; /* Save current strategy tables */ parserparamcurr = ¶tab[para]; /* Save current parameter value */ stratParserSelect (parsermethtokentab[parserparamcurr->type]); if (parserparamcurr->type == STRATPARAMSTRAT) /* If parameter is a strategy */ parserstrattab = (StratTab *) parserparamcurr->datasltr; /* Use new strategy tables */ } break; case 26: /* Line 1464 of yacc.c */ #line 354 "parser_yy.y" { stratParserSelect (VALPARAM); /* Go-on reading parameters */ parserstrattab = ((yyvsp[(2) - (4)].SAVE)).tabl; /* Restore current strategy tables */ } break; case 27: /* Line 1464 of yacc.c */ #line 361 "parser_yy.y" { char c; /* Character read */ char * p; /* Pointer to selector string */ int i; /* Index in selector string */ c = ((yyvsp[(1) - (1)].CASEVAL)); /* First, use char as is */ for (p = (char *) parserparamcurr->datasltr, i = 0; (*p != '\0') && (*p != c); p ++, i ++) ; if (*p == '\0') { /* Char was not found */ c = tolower (c); /* Convert char to lower case */ for (p = (char *) parserparamcurr->datasltr, i = 0; (*p != '\0') && (*p != c); p ++, i ++) ; if (*p == '\0') { errorPrint ("stratParserParse: invalid method parameter switch \"%s=%c\", before \"%s\"", parserparamcurr->name, ((yyvsp[(1) - (1)].CASEVAL)), stratParserRemain ()); YYABORT; } } #ifdef SCOTCH_DEBUG_PARSER2 if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (int)) > sizeof (StratNodeMethodData)) { errorPrint ("stratParserParse: internal error (1)"); YYABORT; } #endif /* SCOTCH_DEBUG_PARSER2 */ *((int *) ((byte *) &parserstratcurr->data.method.data + (parserparamcurr->dataofft - parserparamcurr->database))) = i; } break; case 28: /* Line 1464 of yacc.c */ #line 394 "parser_yy.y" { #ifdef SCOTCH_DEBUG_PARSER2 if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (double)) > sizeof (StratNodeMethodData)) { errorPrint ("stratParserParse: internal error (2)"); YYABORT; } #endif /* SCOTCH_DEBUG_PARSER2 */ *((double *) ((byte *) &parserstratcurr->data.method.data + (parserparamcurr->dataofft - parserparamcurr->database))) = ((yyvsp[(1) - (1)].DOUBLE)); } break; case 29: /* Line 1464 of yacc.c */ #line 407 "parser_yy.y" { #ifdef SCOTCH_DEBUG_PARSER2 if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (INT)) > sizeof (StratNodeMethodData)) { errorPrint ("stratParserParse: internal error (3)"); YYABORT; } #endif /* SCOTCH_DEBUG_PARSER2 */ *((INT *) ((byte *) &parserstratcurr->data.method.data + (parserparamcurr->dataofft - parserparamcurr->database))) = (INT) ((yyvsp[(1) - (1)].INTEGER)); } break; case 30: /* Line 1464 of yacc.c */ #line 420 "parser_yy.y" { #ifdef SCOTCH_DEBUG_PARSER2 if ((parserparamcurr->dataofft - parserparamcurr->database + strlen ((yyvsp[(1) - (1)].STRING)) + 1) > sizeof (StratNodeMethodData)) { errorPrint ("stratParserParse: internal error (4)"); YYABORT; } #endif /* SCOTCH_DEBUG_PARSER2 */ strcpy ((char *) ((byte *) &parserstratcurr->data.method.data + (parserparamcurr->dataofft - parserparamcurr->database)), ((yyvsp[(1) - (1)].STRING))); } break; case 31: /* Line 1464 of yacc.c */ #line 434 "parser_yy.y" { ((yyval.SAVE)).strat = parserstratcurr; ((yyval.SAVE)).param = parserparamcurr; parserstratcurr = NULL; parserparamcurr = NULL; } break; case 32: /* Line 1464 of yacc.c */ #line 441 "parser_yy.y" { parserstratcurr = ((yyvsp[(1) - (2)].SAVE)).strat; /* Restore current method */ parserparamcurr = ((yyvsp[(1) - (2)].SAVE)).param; /* Restore current parameter */ #ifdef SCOTCH_DEBUG_PARSER2 if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (Strat *)) > sizeof (StratNodeMethodData)) { errorPrint ("stratParserParse: internal error (5)"); YYABORT; } #endif /* SCOTCH_DEBUG_PARSER2 */ *((Strat **) ((byte *) &parserstratcurr->data.method.data + (parserparamcurr->dataofft - parserparamcurr->database))) = ((yyvsp[(2) - (2)].STRAT)); } break; case 33: /* Line 1464 of yacc.c */ #line 457 "parser_yy.y" { errorPrint ("stratParserParse: invalid value for parameter \"%s\" of method \"%s\", before \"%s\"", parserparamcurr->name, parserstratcurr->tabl->methtab[parserstratcurr->data.method.meth].name, stratParserRemain ()); YYABORT; } break; case 35: /* Line 1464 of yacc.c */ #line 468 "parser_yy.y" { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (6)"); stratTestExit ((yyvsp[(1) - (3)].TEST)); stratTestExit ((yyvsp[(3) - (3)].TEST)); YYABORT; } test->typetest = STRATTESTOR; test->typenode = STRATPARAMLOG; test->data.test[0] = ((yyvsp[(1) - (3)].TEST)); test->data.test[1] = ((yyvsp[(3) - (3)].TEST)); ((yyval.TEST)) = test; } break; case 37: /* Line 1464 of yacc.c */ #line 489 "parser_yy.y" { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (7)"); stratTestExit ((yyvsp[(1) - (3)].TEST)); stratTestExit ((yyvsp[(3) - (3)].TEST)); YYABORT; } test->typetest = STRATTESTAND; test->typenode = STRATPARAMLOG; test->data.test[0] = ((yyvsp[(1) - (3)].TEST)); test->data.test[1] = ((yyvsp[(3) - (3)].TEST)); ((yyval.TEST)) = test; } break; case 39: /* Line 1464 of yacc.c */ #line 510 "parser_yy.y" { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (8)"); stratTestExit ((yyvsp[(2) - (2)].TEST)); YYABORT; } test->typetest = STRATTESTNOT; test->typenode = STRATPARAMLOG; test->data.test[0] = ((yyvsp[(2) - (2)].TEST)); ((yyval.TEST)) = test; } break; case 40: /* Line 1464 of yacc.c */ #line 526 "parser_yy.y" { ((yyval.TEST)) = ((yyvsp[(2) - (3)].TEST)); } break; case 42: /* Line 1464 of yacc.c */ #line 533 "parser_yy.y" { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (9)"); stratTestExit ((yyvsp[(1) - (3)].TEST)); stratTestExit ((yyvsp[(3) - (3)].TEST)); YYABORT; } test->typetest = ((yyvsp[(2) - (3)].TESTOP)); test->typenode = STRATPARAMLOG; test->data.test[0] = ((yyvsp[(1) - (3)].TEST)); test->data.test[1] = ((yyvsp[(3) - (3)].TEST)); ((yyval.TEST)) = test; } break; case 43: /* Line 1464 of yacc.c */ #line 552 "parser_yy.y" { ((yyval.TESTOP)) = STRATTESTLT; } break; case 44: /* Line 1464 of yacc.c */ #line 556 "parser_yy.y" { ((yyval.TESTOP)) = STRATTESTEQ; } break; case 45: /* Line 1464 of yacc.c */ #line 560 "parser_yy.y" { ((yyval.TESTOP)) = STRATTESTGT; } break; case 46: /* Line 1464 of yacc.c */ #line 566 "parser_yy.y" { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (10)"); stratTestExit ((yyvsp[(1) - (3)].TEST)); stratTestExit ((yyvsp[(3) - (3)].TEST)); YYABORT; } test->typetest = ((yyvsp[(2) - (3)].TESTOP)); test->data.test[0] = ((yyvsp[(1) - (3)].TEST)); test->data.test[1] = ((yyvsp[(3) - (3)].TEST)); ((yyval.TEST)) = test; } break; case 48: /* Line 1464 of yacc.c */ #line 585 "parser_yy.y" { ((yyval.TESTOP)) = STRATTESTADD; } break; case 49: /* Line 1464 of yacc.c */ #line 589 "parser_yy.y" { ((yyval.TESTOP)) = STRATTESTSUB; } break; case 50: /* Line 1464 of yacc.c */ #line 595 "parser_yy.y" { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { stratTestExit ((yyvsp[(1) - (3)].TEST)); stratTestExit ((yyvsp[(3) - (3)].TEST)); errorPrint ("stratParserParse: out of memory (11)"); YYABORT; } test->typetest = ((yyvsp[(2) - (3)].TESTOP)); test->data.test[0] = ((yyvsp[(1) - (3)].TEST)); test->data.test[1] = ((yyvsp[(3) - (3)].TEST)); ((yyval.TEST)) = test; } break; case 52: /* Line 1464 of yacc.c */ #line 614 "parser_yy.y" { ((yyval.TESTOP)) = STRATTESTMUL; } break; case 53: /* Line 1464 of yacc.c */ #line 620 "parser_yy.y" { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (12)"); stratTestExit ((yyvsp[(1) - (3)].TEST)); stratTestExit ((yyvsp[(3) - (3)].TEST)); YYABORT; } test->typetest = ((yyvsp[(2) - (3)].TESTOP)); test->data.test[0] = ((yyvsp[(1) - (3)].TEST)); test->data.test[1] = ((yyvsp[(3) - (3)].TEST)); ((yyval.TEST)) = test; } break; case 55: /* Line 1464 of yacc.c */ #line 639 "parser_yy.y" { ((yyval.TESTOP)) = STRATTESTMOD; } break; case 56: /* Line 1464 of yacc.c */ #line 645 "parser_yy.y" { ((yyval.TEST)) = ((yyvsp[(2) - (3)].TEST)); } break; case 59: /* Line 1464 of yacc.c */ #line 653 "parser_yy.y" { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (13)"); YYABORT; } test->typetest = STRATTESTVAL; test->typenode = STRATPARAMDOUBLE; test->data.val.valdbl = ((yyvsp[(1) - (1)].DOUBLE)); ((yyval.TEST)) = test; } break; case 60: /* Line 1464 of yacc.c */ #line 668 "parser_yy.y" { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (14)"); YYABORT; } test->typetest = STRATTESTVAL; test->typenode = STRATPARAMINT; test->data.val.valint = ((yyvsp[(1) - (1)].INTEGER)); ((yyval.TEST)) = test; } break; case 61: /* Line 1464 of yacc.c */ #line 685 "parser_yy.y" { StratTest * test; StratParamTab * condtab; int para; int paralen; int i, j; para = paralen = 0; /* No parameter recognized yet */ condtab = parserstrattab->condtab; /* Point to parameter table */ for (i = 0; condtab[i].name != NULL; i ++) { if ((strncasecmp (((yyvsp[(1) - (1)].STRING)), /* Find longest matching parameter name */ condtab[i].name, j = strlen (condtab[i].name)) == 0) && (j > paralen)) { para = i; paralen = j; } } if (paralen == 0) { errorPrint ("stratParserParse: invalid graph parameter name \"%s\", before \"%s\"", ((yyvsp[(1) - (1)].STRING)), stratParserRemain ()); YYABORT; } if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (15)"); YYABORT; } test->typetest = STRATTESTVAR; test->typenode = condtab[para].type; test->data.var.datatab = parserstrattab; test->data.var.datadisp = condtab[para].dataofft - condtab[para].database; ((yyval.TEST)) = test; } break; /* Line 1464 of yacc.c */ #line 2273 "y.tab.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) { YYSIZE_T yyalloc = 2 * yysize; if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yyalloc); if (yymsg) yymsg_alloc = yyalloc; else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; } } if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); yyerror (yymsg); } else { yyerror (YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } } #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } *++yyvsp = yylval; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #if !defined(yyoverflow) || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif /* Make sure YYID is used. */ return YYID (yyresult); } /* Line 1684 of yacc.c */ #line 725 "parser_yy.y" /* ** The static and global definitions (bis). ** These are put at the end of the file because ** the token values that they use are not yet ** defined in the first section of the file. */ unsigned int parsermethtokentab[] = { /* Table for parameter/token type conversion */ VALCASE, VALDOUBLE, VALINT, -1, /* No logical parameters */ VALSTRAT, VALSTRING, -1 /* One more value to detect array overflow */ }; /************************************/ /* */ /* These routines drive the parser. */ /* */ /************************************/ /* This routine is the entry point for ** the strategy parser. ** It returns: ** - !NULL : pointer to the strategy. ** - NULL : on error. */ Strat * stratParserParse ( const StratTab * const strattab, /*+ Pointer to parsing tables +*/ const char * const string) /*+ Strategy string to parse +*/ { yyclearin; /* Reset the parser state */ #ifdef SCOTCH_DEBUG_PARSER3 yydebug = 1; /* Set debugging if needed */ #endif /* SCOTCH_DEBUG_PARSER3 */ stratParserInit (string); /* Initialize the lexical parser */ parserstrattab = strattab; /* Point to the parsing tables */ parserstratcurr = NULL; /* Clear up the temporary strategy pointer */ if (stratParserParse2 () != 0) { /* Parse the strategy string */ if (parserstratcurr != NULL) stratExit (parserstratcurr); return (NULL); } return (parserstratcurr); /* Return strategy pointer */ } /* This routine displays the parser error message. ** It returns: ** - 1 : in all cases. */ static int stratParserError ( const char * const errstr) { errorPrint ("stratParserParse: invalid strategy string, before \"%s\"", stratParserRemain ()); return (1); } scotch-5.1.12b.dfsg/src/libscotch/common_file.c0000644000175300017530000002774411631334325021604 0ustar hazelscthazelsct/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : common_file.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles files and file **/ /** names. **/ /** **/ /** DATES : # Version 5.0 : from : 21 may 2007 **/ /** to : 16 mar 2008 **/ /** # Version 5.1 : from : 27 jun 2010 **/ /** to 27 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define COMMON_FILE #ifndef COMMON_NOMODULE #include "module.h" #endif /* COMMON_NOMODULE */ #include "common.h" #include "common_file.h" /*********************************/ /* */ /* Basic routines for filenames. */ /* */ /*********************************/ /* This routine expands distributed filenames ** according to process numbers and the root ** process number. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int fileNameDistExpand ( char ** const nameptr, /*+ Pointer to name string pointer +*/ const int procnbr, /*+ Number of processes +*/ const int procnum, /*+ Number of current process +*/ const int protnum) /*+ Root process number +*/ { int namemax; int namenum; char * naexptr; int naexmax; int naexnum; int flagval; /* Flag set if expansion took place */ namemax = strlen (*nameptr); naexmax = namemax + FILENAMEDISTEXPANDNBR * 2; if ((naexptr = memAlloc ((naexmax + 1) * sizeof (char))) == NULL) /* "+ 1" for terminating character */ return (1); #ifdef COMMON_DEBUG sprintf (naexptr, FILENAMEDISTEXPANDSTR, procnbr); /* TRICK: Test if FILENAMEDISTEXPANDNBR is a size large enough */ if (atoi (naexptr) != procnbr) { errorPrint ("fileNameDistExpand: undersized integer string size"); return (1); } #endif /* COMMON_DEBUG */ for (namenum = naexnum = flagval = 0; namenum < namemax; ) { char charval; int dataval = 0; int datasiz; charval = (*nameptr)[namenum ++]; /* Get current characted */ datasiz = 1; /* Assume individual expanded character */ if (charval == '%') { char chnxval; /* Value of next char */ switch (chnxval = (*nameptr)[namenum ++]) { case 'p' : /* "%p" translates into number of processes */ flagval = 1; datasiz = FILENAMEDISTEXPANDNBR; dataval = procnbr; break; case 'r' : /* "%r" translates into process rank */ flagval = 1; datasiz = FILENAMEDISTEXPANDNBR; dataval = procnum; break; case '-' : /* "%-" translates into nothing but indicates distributed file */ datasiz = 0; flagval = 1; break; case '%' : /* "%%" translates into '%' */ break; default : charval = chnxval; /* Unrecognized character */ } } if (datasiz > 0) { if ((naexnum + datasiz) > naexmax) { char * nanwptr; naexmax += datasiz + FILENAMEDISTEXPANDNBR; if ((nanwptr = memRealloc (naexptr, (naexmax + 1) * sizeof (char))) == NULL) { /* "+ 1" for terminating character */ memFree (naexptr); return (1); } naexptr = nanwptr; } if (datasiz == 1) naexptr[naexnum ++] = charval; else { sprintf (&naexptr[naexnum], FILENAMEDISTEXPANDSTR, dataval); /* TRICK: Change format string if FILENAMEDISTEXPANDNBR changes */ naexptr[naexnum + FILENAMEDISTEXPANDNBR] = ' '; naexnum = strchr (&naexptr[naexnum], ' ') - naexptr; } } } naexptr[naexnum] = '\0'; /* Set terminating character as there is always room for it */ if ((flagval != 0) || (procnum == protnum)) /* If file name is a distributed one or we are the root process */ *nameptr = naexptr; /* Replace new string by old one */ else { memFree (naexptr); /* No need for the expanded string */ *nameptr = NULL; } return (0); } /* This routine opens a block of file ** descriptor structures. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int fileBlockOpen ( File * const filetab, const int filenbr) { int i, j; for (i = 0; i < filenbr; i ++) { /* For all file names */ if (filetab[i].pntr == NULL) /* If unwanted stream, do nothing */ continue; for (j = 0; j < i; j ++) { if ((filetab[i].mode[0] == filetab[j].mode[0]) && /* If very same name with same opening mode */ (filetab[j].name != NULL) && (strcmp (filetab[i].name, filetab[j].name) == 0)) { filetab[i].pntr = filetab[j].pntr; /* Share pointer to already processed stream */ filetab[i].name = NULL; /* Do not close this stream multiple times */ break; } } if (j == i) { /* If original stream */ int compval; /* Compression type */ FILE * compptr; /* Processed ((un)compressed) stream */ if (filetab[i].name[0] != '-') { /* If not standard stream, open it */ if ((filetab[i].pntr = fopen (filetab[i].name, filetab[i].mode)) == NULL) { /* Open the file */ errorPrint ("fileBlockOpen: cannot open file (%d)", i); return (1); } } compval = (filetab[i].mode[0] == 'r') ? fileUncompressType (filetab[i].name) : fileCompressType (filetab[i].name); if (compval < 0) { errorPrint ("fileBlockOpen: (un)compression type not implemented"); return (1); } compptr = (filetab[i].mode[0] == 'r') ? fileUncompress (filetab[i].pntr, compval) : fileCompress (filetab[i].pntr, compval); if (compptr == NULL) { errorPrint ("fileBlockOpen: cannot create (un)compression subprocess"); return (1); } filetab[i].pntr = compptr; /* Use processed stream instead of original stream */ } } return (0); } /* This routine opens a block of eventually ** distributed file descriptor structures. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int fileBlockOpenDist ( File * const filetab, const int filenbr, const int procglbnbr, const int proclocnum, const int protglbnum) { int i, j; for (i = 0; i < filenbr; i ++) { /* For all file names */ if (fileNameDistExpand (&filetab[i].name, procglbnbr, proclocnum, protglbnum) != 0) { /* If cannot allocate new name */ errorPrint ("fileBlockOpenDist: cannot create file name (%d)", i); return (1); } if (filetab[i].name == NULL) /* If inexisting stream because not root process and centralized stream */ filetab[i].pntr = NULL; if (filetab[i].pntr == NULL) /* If unwanted stream, do nothing */ continue; for (j = 0; j < i; j ++) { if ((filetab[i].mode[0] == filetab[j].mode[0]) && /* If very same name with same opening mode */ (filetab[j].name != NULL) && (strcmp (filetab[i].name, filetab[j].name) == 0)) { filetab[i].pntr = filetab[j].pntr; /* Share pointer to already processed stream */ filetab[i].name = NULL; /* Do not close this stream multiple times */ break; } } if (j == i) { /* If original stream */ int compval; /* Compression type */ FILE * compptr; /* Processed ((un)compressed) stream */ if (filetab[i].name[0] != '-') { /* If not standard stream, open it */ if ((filetab[i].pntr = fopen (filetab[i].name, filetab[i].mode)) == NULL) { /* Open the file */ errorPrint ("fileBlockOpenDist: cannot open file (%d)", i); return (1); } } compval = (filetab[i].mode[0] == 'r') ? fileUncompressType (filetab[i].name) : fileCompressType (filetab[i].name); if (compval < 0) { errorPrint ("fileBlockOpenDist: (un)compression type not implemented"); return (1); } compptr = (filetab[i].mode[0] == 'r') ? fileUncompress (filetab[i].pntr, compval) : fileCompress (filetab[i].pntr, compval); if (compptr == NULL) { errorPrint ("fileBlockOpenDist: cannot create (un)compression subprocess"); return (1); } filetab[i].pntr = compptr; /* Use processed stream instead of original stream */ } } return (0); } /* This routine opens a block of file ** descriptor structures. ** It returns: ** - 0 : on success. ** - !0 : on error. */ void fileBlockClose ( File * const filetab, const int filenbr) { int i; for (i = 0; i < filenbr; i ++) { /* For all file names */ if (filetab[i].pntr == NULL) /* If unwanted stream, do nothing */ continue; if ((filetab[i].name != NULL) && /* If existing stream */ (filetab[i].name[0] != '-')) { fclose (filetab[i].pntr); /* Close the stream */ } } } scotch-5.1.12b.dfsg/src/libscotch/arch_tleaf.c0000644000175300017530000003336311631334325021377 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_tleaf.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the tree-leaf **/ /** target architecture. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 23 dec 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 29 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 08 sep 1995 **/ /** # Version 3.1 : from : 20 jul 1996 **/ /** to 20 jul 1996 **/ /** # Version 3.2 : from : 10 oct 1996 **/ /** to 14 may 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 3.4 : from : 07 jun 2001 **/ /** to 07 jun 2001 **/ /** # Version 4.0 : from : 10 dec 2003 **/ /** to 10 mar 2005 **/ /** # Version 5.1 : from : 21 jan 2008 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ARCH_TLEAF #include "module.h" #include "common.h" #include "arch.h" #include "arch_tleaf.h" /*******************************************/ /* */ /* These are the tree-leaf graph routines. */ /* */ /*******************************************/ /* This routine loads the ** tree leaf architecture. ** It returns: ** - 0 : if the architecture has been successfully read. ** - !0 : on error. */ int archTleafArchLoad ( ArchTleaf * restrict const archptr, FILE * restrict const stream) { Anum sizeval; Anum levlnum; #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchTleaf) > sizeof (ArchDummy)) || (sizeof (ArchTleafDom) > sizeof (ArchDomDummy))) { errorPrint ("archTleafArchLoad: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if (intLoad (stream, &archptr->levlnbr) != 1) { errorPrint ("archTleafArchLoad: bad input (1)"); return (1); } if ((archptr->sizetab = memAlloc ((archptr->levlnbr * 2 + 1) * sizeof (Anum))) == NULL) { /* TRICK: One more slot for linktab[-1] */ errorPrint ("archTleafArchLoad: out of memory"); return (1); } archptr->linktab = archptr->sizetab + archptr->levlnbr + 1; /* TRICK: One more slot */ archptr->linktab[-1] = 0; /* Dummy slot for for level-0 communication */ for (levlnum = 0, sizeval = 1; levlnum < archptr->levlnbr; levlnum ++) { if ((intLoad (stream, &archptr->sizetab[levlnum]) != 1) || (intLoad (stream, &archptr->linktab[levlnum]) != 1) || (archptr->sizetab[levlnum] < 2) || (archptr->linktab[levlnum] < 1)) { errorPrint ("archTleafArchLoad: bad input (2)"); return (1); } sizeval *= archptr->sizetab[levlnum]; } archptr->sizeval = sizeval; return (0); } /* This routine frees the tree ** leaf architecture structures. ** It returns: ** - 0 : if the architecture has been successfully freed. ** - !0 : on error. */ int archTleafArchFree ( ArchTleaf * const archptr) { #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchTleaf) > sizeof (ArchDummy)) || (sizeof (ArchTleafDom) > sizeof (ArchDomDummy))) { errorPrint ("archTleafArchFree: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ memFree (archptr->sizetab); /* Free group leader */ #ifdef SCOTCH_DEBUG_ARCH2 archptr->sizetab = archptr->linktab = NULL; #endif /* SCOTCH_DEBUG_ARCH2 */ return (0); } /* This routine saves the ** tree leaf architecture. ** It returns: ** - 0 : if the architecture has been successfully written. ** - !0 : on error. */ int archTleafArchSave ( const ArchTleaf * const archptr, FILE * restrict const stream) { Anum levlnum; #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchTleaf) > sizeof (ArchDummy)) || (sizeof (ArchTleafDom) > sizeof (ArchDomDummy))) { errorPrint ("archTleafArchSave: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if (fprintf (stream, ANUMSTRING, (Anum) archptr->levlnbr) == EOF) { errorPrint ("archTleafSave: bad output (1)"); return (1); } for (levlnum = 0; levlnum < archptr->levlnbr; levlnum ++) { if (fprintf (stream, " " ANUMSTRING " " ANUMSTRING, (Anum) archptr->sizetab[levlnum], (Anum) archptr->linktab[levlnum]) == EOF) { errorPrint ("archTleafSave: bad output (2)"); return (1); } } return (0); } /* This function returns the smallest number ** of terminal domain included in the given ** domain. */ ArchDomNum archTleafDomNum ( const ArchTleaf * const archptr, const ArchTleafDom * const domnptr) { Anum levlnum; Anum sizeval; sizeval = 1; /* Compute size of blocks below */ for (levlnum = domnptr->levlnum; levlnum < archptr->levlnbr; levlnum ++) sizeval *= archptr->sizetab[levlnum]; return (domnptr->indxmin * sizeval); } /* This function returns the terminal domain associated ** with the given terminal number in the architecture. ** It returns: ** - 0 : if label is valid and domain has been updated. ** - 1 : if label is invalid. ** - 2 : on error. */ int archTleafDomTerm ( const ArchTleaf * const archptr, ArchTleafDom * const domnptr, const ArchDomNum domnnum) { #ifdef SCOTCH_DEBUG_ARCH2 if (domnnum < 0) { errorPrint ("archTleafDomTerm: invalid parameter"); return (1); } #endif /* SCOTCH_DEBUG_ARCH2 */ if (domnnum < archptr->sizeval) { /* If valid label */ domnptr->levlnum = archptr->levlnbr; /* Set the domain */ domnptr->indxmin = domnnum; domnptr->indxnbr = 1; return (0); } return (1); /* Cannot set domain */ } /* This function returns the number of ** elements in the subtree domain. */ Anum archTleafDomSize ( const ArchTleaf * const archptr, const ArchTleafDom * const domnptr) { Anum levlnum; Anum sizeval; sizeval = 1; /* Compute size of blocks below */ for (levlnum = domnptr->levlnum; levlnum < archptr->levlnbr; levlnum ++) sizeval *= archptr->sizetab[levlnum]; return (sizeval * domnptr->indxnbr); } /* This function returns the average ** distance between two tree leaf ** subdomains. */ Anum archTleafDomDist ( const ArchTleaf * const archptr, const ArchTleafDom * const dom0ptr, const ArchTleafDom * const dom1ptr) { Anum lev0num; Anum lev1num; Anum idx0min; Anum idx1min; Anum idx0nbr; Anum idx1nbr; Anum distval; const Anum * const sizetab = archptr->sizetab; lev0num = dom0ptr->levlnum; lev1num = dom1ptr->levlnum; idx0min = dom0ptr->indxmin; idx1min = dom1ptr->indxmin; idx0nbr = dom0ptr->indxnbr; idx1nbr = dom1ptr->indxnbr; if (lev0num != lev1num) { if (lev0num > lev1num) { idx0nbr = 1; do { lev0num --; idx0min /= sizetab[lev0num]; } while (lev0num > lev1num); } else { idx1nbr = 1; do { lev1num --; idx1min /= sizetab[lev1num]; } while (lev1num > lev0num); } } distval = archptr->linktab[lev0num - 1]; /* Get cost at this level */ return (((idx0min >= (idx1min + idx1nbr)) || /* If inclusion, only half of the distance */ (idx1min >= (idx0min + idx0nbr))) ? distval : ((idx0nbr == idx1nbr) ? 0 : (distval >> 1))); } /* This function sets the biggest ** domain available for this ** architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archTleafDomFrst ( const ArchTleaf * const archptr, ArchTleafDom * restrict const domnptr) { domnptr->levlnum = 0; domnptr->indxmin = 0; domnptr->indxnbr = 1; /* The root vertex is unique */ return (0); } /* This routine reads domain information ** from the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archTleafDomLoad ( const ArchTleaf * const archptr, ArchTleafDom * restrict const domnptr, FILE * const stream) { if ((intLoad (stream, &domnptr->levlnum) != 1) || (intLoad (stream, &domnptr->indxmin) != 1) || (intLoad (stream, &domnptr->indxnbr) != 1) || (domnptr->levlnum < 0) || (domnptr->levlnum > archptr->levlnbr)) { errorPrint ("archTleafDomLoad: bad input"); return (1); } return (0); } /* This routine saves domain information ** to the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archTleafDomSave ( const ArchTleaf * const archptr, const ArchTleafDom * const domnptr, FILE * const stream) { if (fprintf (stream, ANUMSTRING " " ANUMSTRING " " ANUMSTRING " ", (Anum) domnptr->levlnum, (Anum) domnptr->indxmin, (Anum) domnptr->indxnbr) == EOF) { errorPrint ("archTleafDomSave: bad output"); return (1); } return (0); } /* This function tries to split a tree leaf ** domain into two subdomains. ** It returns: ** - 0 : if bipartitioning succeeded. ** - 1 : if bipartitioning could not be performed. ** - 2 : on error. */ int archTleafDomBipart ( const ArchTleaf * const archptr, const ArchTleafDom * const domnptr, ArchTleafDom * restrict const dom0ptr, ArchTleafDom * restrict const dom1ptr) { Anum sizeval; if (domnptr->indxnbr <= 1) { /* If dubdomain has only one node at this level */ if (domnptr->levlnum >= archptr->levlnbr) /* Return if cannot bipartition more */ return (1); sizeval = archptr->sizetab[domnptr->levlnum]; /* Partition all the vertices of a new level */ dom0ptr->levlnum = dom1ptr->levlnum = domnptr->levlnum + 1; dom0ptr->indxmin = domnptr->indxmin * sizeval; } else { /* Subdomain has several indices */ sizeval = domnptr->indxnbr; /* Base on existing block size */ dom0ptr->levlnum = /* Stay at same level */ dom1ptr->levlnum = domnptr->levlnum; dom0ptr->indxmin = domnptr->indxmin; /* Start from the existing start index */ } dom0ptr->indxnbr = (sizeval + 1) >> 1; /* Subdomain 0 is always the largest one */ dom1ptr->indxmin = dom0ptr->indxmin + dom0ptr->indxnbr; dom1ptr->indxnbr = sizeval - dom0ptr->indxnbr; return (0); } /* This function creates the MPI_Datatype for ** tree-leaf domains. ** It returns: ** - 0 : if type could be created. ** - 1 : on error. */ #ifdef SCOTCH_PTSCOTCH int archTleafDomMpiType ( const ArchTleaf * const archptr, MPI_Datatype * const typeptr) { MPI_Type_contiguous (3, ANUM_MPI, typeptr); return (0); } #endif /* SCOTCH_PTSCOTCH */ scotch-5.1.12b.dfsg/src/libscotch/library_graph_io_scot_f.c0000644000175300017530000001633711631334325024162 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_io_scot_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** graph i/o routines of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 4.0 : from : 23 nov 2005 **/ /** to 23 nov 2005 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 27 mar 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the mapping routines. */ /* */ /**************************************/ /* String lengths are passed at the very ** end of the argument list. */ FORTRAN ( \ SCOTCHFGRAPHGEOMLOADSCOT, scotchfgraphgeomloadscot, ( \ SCOTCH_Graph * const grafptr, \ SCOTCH_Geom * const geomptr, \ const int * const filegrfptr, \ const int * const filegeoptr, \ const char * const dataptr, /* No use */ \ int * const revaptr, \ const int datanbr), \ (grafptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) { FILE * filegrfstream; /* Streams to build from handles */ FILE * filegeostream; int filegrfnum; /* Duplicated handle */ int filegeonum; int o; if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHGEOMLOADSCOT: cannot duplicate handle (1)"); *revaptr = 1; /* Indicate error */ return; } if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHGEOMLOADSCOT: cannot duplicate handle (2)"); close (filegrfnum); *revaptr = 1; /* Indicate error */ return; } if ((filegrfstream = fdopen (filegrfnum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHGEOMLOADSCOT: cannot open input stream (1)"); close (filegrfnum); close (filegeonum); *revaptr = 1; return; } if ((filegeostream = fdopen (filegeonum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHGEOMLOADSCOT: cannot open input stream (2)"); fclose (filegrfstream); close (filegeonum); *revaptr = 1; return; } o = SCOTCH_graphGeomLoadScot (grafptr, geomptr, filegrfstream, filegeostream, NULL); fclose (filegrfstream); /* This closes file descriptors too */ fclose (filegeostream); *revaptr = o; } /* String lengths are passed at the very ** end of the argument list. */ FORTRAN ( \ SCOTCHFGRAPHGEOMSAVESCOT, scotchfgraphgeomsavescot, ( \ const SCOTCH_Graph * const grafptr, \ const SCOTCH_Geom * const geomptr, \ const int * const filegrfptr, \ const int * const filegeoptr, \ const char * const dataptr, /* No use */ \ int * const revaptr, \ const int datanbr), \ (grafptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) { FILE * filegrfstream; /* Streams to build from handles */ FILE * filegeostream; int filegrfnum; /* Duplicated handle */ int filegeonum; int o; if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHGEOMSAVESCOT: cannot duplicate handle (1)"); *revaptr = 1; /* Indicate error */ return; } if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHGEOMSAVESCOT: cannot duplicate handle (2)"); close (filegrfnum); *revaptr = 1; /* Indicate error */ return; } if ((filegrfstream = fdopen (filegrfnum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHGEOMSAVESCOT: cannot open output stream (1)"); close (filegrfnum); close (filegeonum); *revaptr = 1; return; } if ((filegeostream = fdopen (filegeonum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHGEOMSAVESCOT: cannot open output stream (2)"); fclose (filegrfstream); close (filegeonum); *revaptr = 1; return; } o = SCOTCH_graphGeomSaveScot (grafptr, geomptr, filegrfstream, filegeostream, NULL); fclose (filegrfstream); /* This closes file descriptors too */ fclose (filegeostream); *revaptr = o; } scotch-5.1.12b.dfsg/src/libscotch/library_mesh_io_scot.c0000644000175300017530000000771211631334325023505 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_mesh_io_scot.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the Scotch **/ /** geometry and mesh handling routines o f **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 4.0 : from : 19 jan 2004 **/ /** to 19 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "geom.h" #include "graph.h" #include "mesh.h" #include "scotch.h" /*************************************/ /* */ /* These routines are the C API for */ /* the Scotch mesh and geometry */ /* handling routines. */ /* */ /*************************************/ /*+ This routine loads the given opaque mesh *** structure with the data of the given stream. *** - 0 : if loading succeeded. *** - !0 : on error. +*/ int SCOTCH_meshGeomLoadScot ( SCOTCH_Mesh * restrict const meshptr, SCOTCH_Geom * restrict const geomptr, FILE * const filesrcptr, FILE * const filegeoptr, const char * const dataptr) /* No use */ { return (meshGeomLoadScot ((Mesh *) meshptr, (Geom *) geomptr, filesrcptr, filegeoptr, NULL)); } /*+ This routine saves the contents of the given *** opaque mesh structure to the given stream. *** It returns: *** - 0 : if the saving succeeded. *** - !0 : on error. +*/ int SCOTCH_meshGeomSaveScot ( const SCOTCH_Mesh * restrict const meshptr, const SCOTCH_Geom * restrict const geomptr, FILE * const filesrcptr, FILE * const filegeoptr, const char * const dataptr) /* No use */ { return (meshGeomSaveScot ((Mesh *) meshptr, (Geom *) geomptr, filesrcptr, filegeoptr, NULL)); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_si.c0000644000175300017530000001032411631334325022271 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_si.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders halo mesh vertices **/ /** using the natural order. **/ /** **/ /** DATES : # Version 4.0 : from : 01 jan 2002 **/ /** to 27 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH_ORDER_SI #include "module.h" #include "common.h" #include "graph.h" #include "order.h" #include "mesh.h" #include "hmesh.h" #include "hmesh_order_si.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hmeshOrderSi ( const Hmesh * restrict const meshptr, Order * restrict const ordeptr, const Gnum ordenum, OrderCblk * restrict const cblkptr) /*+ Single column-block +*/ { Gnum vnodnum; Gnum ordeval; if (meshptr->m.vnumtax == NULL) { /* If mesh is original mesh (no halo) */ #ifdef SCOTCH_DEBUG_ORDER2 if (meshptr->m.vnodnbr != ordeptr->vnodnbr) { errorPrint ("hmeshOrderSi: invalid permutation bounds"); return (1); } #endif /* SCOTCH_DEBUG_ORDER2 */ for (vnodnum = ordeptr->baseval, ordeval = ordenum; vnodnum < ordeptr->baseval + ordeptr->vnodnbr; vnodnum ++, ordeval ++) { ordeptr->peritab[ordeval] = vnodnum; } } else { /* Mesh is not original mesh */ for (vnodnum = meshptr->m.vnodbas, ordeval = ordenum; vnodnum < meshptr->vnohnnd; vnodnum ++, ordeval ++) { ordeptr->peritab[ordeval] = meshptr->m.vnumtax[vnodnum]; #ifdef SCOTCH_DEBUG_ORDER2 if ((ordeptr->peritab[ordeval] < ordeptr->baseval) || (ordeptr->peritab[ordeval] >= (ordeptr->baseval + ordeptr->vnodnbr))) { errorPrint ("hmeshOrderSi: invalid permutation index"); return (1); } #endif /* SCOTCH_DEBUG_ORDER2 */ } } return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_order_io.c0000644000175300017530000000763511631334325024165 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_order_io.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted ordering I/O routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 26 jul 2007 **/ /** to 18 oct 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "dgraph.h" #include "dorder.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the distributed ordering */ /* handling routines. */ /* */ /************************************/ /*+ This routine saves to the given stream *** the mapping data associated with the *** given distributed ordering. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphOrderSaveMap ( const SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ const SCOTCH_Dordering * const ordeptr, /*+ Ordering to save +*/ FILE * const stream) /*+ Output stream +*/ { return (dorderSaveMap ((Dorder *) ordeptr, (Dgraph *) grafptr, stream)); } /*+ This routine saves to the given stream *** the separator tree data associated with *** the given distributed ordering. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphOrderSaveTree ( const SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ const SCOTCH_Dordering * const ordeptr, /*+ Ordering to save +*/ FILE * const stream) /*+ Output stream +*/ { return (dorderSaveTree ((Dorder *) ordeptr, (Dgraph *) grafptr, stream)); } scotch-5.1.12b.dfsg/src/libscotch/kgraph_map_ml.c0000644000175300017530000003176011631334325022107 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kgraph_map_ml.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module performs the Dual Recursive **/ /** Bipartitioning mapping algorithm. **/ /** It is now a branching routine. **/ /** **/ /** DATES : # Version 5.1 : from : 13 jul 2010 **/ /** to 14 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define KGRAPH_MAP_ML #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "graph_coarsen.h" #include "arch.h" #include "mapping.h" #include "kgraph.h" #include "kgraph_map_ml.h" #include "kgraph_map_st.h" /*********************************************/ /* */ /* The coarsening and uncoarsening routines. */ /* */ /*********************************************/ /* This routine builds a coarser graph from the ** graph that is given on input. The coarser ** graphs differ at this stage from classical ** active graphs as their internal gains are not ** yet computed. ** It returns: ** - 0 : if the coarse graph has been built. ** - 1 : if threshold reached or on error. */ static int kgraphMapMlCoarsen ( const Kgraph * restrict const finegrafptr, /*+ Finer graph +*/ Kgraph * restrict const coargrafptr, /*+ Coarser graph to build +*/ GraphCoarsenMulti * restrict * const coarmultptr, /*+ Pointer to multinode table to build +*/ const KgraphMapMlParam * const paraptr) /*+ Method parameters +*/ { Gnum vertmax; vertmax = (archVar (&finegrafptr->m.archdat) ? 1 : finegrafptr->m.domnnbr) * paraptr->coarnbr; if (graphCoarsen (&finegrafptr->s, &coargrafptr->s, coarmultptr, vertmax, paraptr->coarrat, paraptr->coartype) != 0) return (1); /* Return if coarsening failed */ coargrafptr->m.baseval = finegrafptr->m.baseval; coargrafptr->m.vertnbr = coargrafptr->s.vertnbr; coargrafptr->m.parttax = NULL; /* Do not allocate part array yet */ coargrafptr->m.domntab = finegrafptr->m.domntab; /* Re-use domain array */ coargrafptr->m.domnnbr = finegrafptr->m.domnnbr; coargrafptr->m.domnmax = finegrafptr->m.domnmax; coargrafptr->m.archdat = finegrafptr->m.archdat; coargrafptr->m.domnorg = finegrafptr->m.domnorg; coargrafptr->frontab = finegrafptr->frontab; /* Re-use frontier array if it exists */ coargrafptr->comploadavg = finegrafptr->comploadavg; /* Re-use existing load arrays */ coargrafptr->comploaddlt = finegrafptr->comploaddlt; coargrafptr->levlnum = finegrafptr->levlnum + 1; /* Graph level is coarsening level */ return (0); } /* This routine propagates the separation of the ** coarser graph back to the finer graph, according ** to the multinode table of collapsed vertices. ** After the separation is propagated, it finishes ** to compute the parameters of the finer graph that ** were not computed at the coarsening stage. ** It returns: ** - 0 : if coarse graph data has been propagated to fine graph. ** - !0 : on error. */ static int kgraphMapMlUncoarsen ( Kgraph * restrict const finegrafptr, /*+ Finer graph +*/ Kgraph * restrict const coargrafptr, /*+ Coarser graph +*/ const GraphCoarsenMulti * restrict const coarmulttax) /*+ Multinode array +*/ { Gnum coarvertnum; const Anum * restrict coarparttax; Gnum * coarfrontab; /* [norestrict] */ Gnum coarfronnum; Anum * restrict fineparttax; Gnum * finefrontab; /* [norestrict] */ Gnum finefronnbr; const Gnum * restrict const fineverttax = finegrafptr->s.verttax; const Gnum * restrict const finevendtax = finegrafptr->s.vendtax; const Gnum * restrict const fineedgetax = finegrafptr->s.edgetax; if (finegrafptr->m.parttax == NULL) { /* If partition array not yet allocated */ if ((finegrafptr->m.parttax = (Anum *) memAlloc (finegrafptr->s.vertnbr * sizeof (Anum))) == NULL) { errorPrint ("kgraphMapMlUncoarsen: out of memory (1)"); return (1); } finegrafptr->s.flagval |= KGRAPHFREEPART; /* Allocated data will be freed along with graph structure */ finegrafptr->m.parttax -= finegrafptr->s.baseval; } if (finegrafptr->frontab == NULL) { /* If frontier array not yet allocated */ if ((finegrafptr->frontab = (Gnum *) memAlloc (finegrafptr->s.vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("kgraphMapMlUncoarsen: out of memory (2)"); return (1); } } if (coargrafptr == NULL) { /* If no coarse graph provided */ kgraphFrst (finegrafptr); /* Assign all vertices to first subdomain */ return (0); } finegrafptr->m.domntab = coargrafptr->m.domntab; /* Get pointer to domain array again in case it was reallocated */ finegrafptr->m.domnnbr = coargrafptr->m.domnnbr; finegrafptr->m.domnmax = coargrafptr->m.domnmax; coargrafptr->m.domntab = NULL; /* Do not doubly free array */ finegrafptr->comploadavg = coargrafptr->comploadavg; /* Get pointer to load array again in case it was reallocated */ finegrafptr->comploaddlt = coargrafptr->comploaddlt; coargrafptr->comploadavg = NULL; /* Do not doubly free array */ coarparttax = coargrafptr->m.parttax; fineparttax = finegrafptr->m.parttax; for (coarvertnum = coargrafptr->s.baseval; coarvertnum < coargrafptr->s.vertnnd; coarvertnum ++) { Gnum finevertnum0; /* First multinode vertex */ Gnum finevertnum1; /* Second multinode vertex */ Anum partval; finevertnum0 = coarmulttax[coarvertnum].vertnum[0]; finevertnum1 = coarmulttax[coarvertnum].vertnum[1]; partval = coarparttax[coarvertnum]; fineparttax[finevertnum0] = partval; if (finevertnum0 != finevertnum1) fineparttax[finevertnum1] = partval; } coarfrontab = coargrafptr->frontab; /* TRICK: may also be equal to finefrontab */ finefrontab = finegrafptr->frontab; for (coarfronnum = 0, finefronnbr = coargrafptr->fronnbr; /* Re-cycle frontier array from coarse to fine graph */ coarfronnum < coargrafptr->fronnbr; coarfronnum ++) { Gnum coarvertnum; Gnum finevertnum0; /* First multinode vertex */ Gnum finevertnum1; /* Second multinode vertex */ coarvertnum = coarfrontab[coarfronnum]; finevertnum0 = coarmulttax[coarvertnum].vertnum[0]; finevertnum1 = coarmulttax[coarvertnum].vertnum[1]; if (finevertnum0 != finevertnum1) { /* If multinode si made of two distinct vertices */ Anum coarpartval; Gnum fineedgenum; coarpartval = coarparttax[coarvertnum]; #ifdef SCOTCH_DEBUG_KGRAPH2 finefrontab[coarfronnum] = ~0; #endif /* SCOTCH_DEBUG_KGRAPH2 */ for (fineedgenum = fineverttax[finevertnum0]; fineedgenum < finevendtax[finevertnum0]; fineedgenum ++) { if (fineparttax[fineedgetax[fineedgenum]] != coarpartval) { /* If first vertex belongs to frontier */ finefrontab[coarfronnum] = finevertnum0; /* Record it in lieu of the coarse frontier vertex */ break; } } if (fineedgenum >= finegrafptr->s.vendtax[finevertnum0]) { /* If first vertex not in frontier */ finefrontab[coarfronnum] = finevertnum1; /* Then second vertex must be in frontier */ continue; /* Skip to next multinode */ } for (fineedgenum = fineverttax[finevertnum1]; /* Check if second vertex belong to frontier too */ fineedgenum < finevendtax[finevertnum1]; fineedgenum ++) { if (fineparttax[fineedgetax[fineedgenum]] != coarpartval) { /* If second vertex belongs to frontier */ finefrontab[finefronnbr ++] = finevertnum1; /* Record it at the end of the (recycled ?) frontier array */ break; } } #ifdef SCOTCH_DEBUG_KGRAPH2 if (finefrontab[coarfronnum] == ~0) { errorPrint ("kgraphMapMlUncoarsen: internal error"); return (1); } #endif /* SCOTCH_DEBUG_KGRAPH2 */ } else /* If coarse vertex is single node */ finefrontab[coarfronnum] = finevertnum0; /* Then it belongs to the frontier */ } finegrafptr->fronnbr = finefronnbr; #ifdef SCOTCH_DEBUG_KGRAPH2 if (kgraphCheck (finegrafptr) != 0) { errorPrint ("kgraphMapMlUncoarsen: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_KGRAPH2 */ return (0); } /* This routine recursively performs the partitioning. ** It returns: ** - 0 : if mapping could be computed. ** - !0 : on error. */ static int kgraphMapMl2 ( Kgraph * restrict const grafptr, const KgraphMapMlParam * const paraptr) { Kgraph coargrafdat; GraphCoarsenMulti * restrict coarmulttax; int o; if (kgraphMapMlCoarsen (grafptr, &coargrafdat, &coarmulttax, paraptr) == 0) { if (((o = kgraphMapMl2 (&coargrafdat, paraptr)) == 0) && ((o = kgraphMapMlUncoarsen (grafptr, &coargrafdat, coarmulttax)) == 0) && ((o = kgraphMapSt (grafptr, paraptr->stratasc)) != 0)) /* Apply ascending strategy */ errorPrint ("kgraphMapMl2: cannot apply ascending strategy"); kgraphExit (&coargrafdat); } else { /* Cannot coarsen due to lack of memory or error */ if (((o = kgraphMapMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ ((o = kgraphMapSt (grafptr, paraptr->stratlow)) != 0)) /* Apply low strategy */ errorPrint ("kgraphMapMl2: cannot apply low strategy"); } return (o); } /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the muti-level mapping. ** It returns: ** - 0 : if separator could be computed. ** - 1 : on error. */ int kgraphMapMl ( Kgraph * const grafptr, /*+ Graph to map +*/ const KgraphMapMlParam * const paraptr) /*+ Method parameters +*/ { Gnum levlnum; /* Save value for graph level */ int o; levlnum = grafptr->levlnum; /* Save graph level */ grafptr->levlnum = 0; /* Initialize coarsening level */ o = kgraphMapMl2 (grafptr, paraptr); /* Perform multi-level mapping */ grafptr->levlnum = levlnum; /* Restore graph level */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_nd.c0000644000175300017530000002125611631334325022265 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_nd.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders mesh nodes using the **/ /** nested dissection algorithm. **/ /** **/ /** DATES : # Version 4.0 : from : 06 jan 2002 **/ /** to 05 jan 2005 **/ /** # Version 5.0 : from : 25 jul 2007 **/ /** to : 12 sep 2007 **/ /** # Version 5.1 : from : 09 nov 2008 **/ /** to : 09 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH_ORDER_ND #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "order.h" #include "mesh.h" #include "hmesh.h" #include "hmesh_order_nd.h" #include "hmesh_order_st.h" #include "vmesh.h" #include "vmesh_separate_st.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hmeshOrderNd ( const Hmesh * restrict const meshptr, Order * restrict const ordeptr, const Gnum ordenum, OrderCblk * restrict const cblkptr, const HmeshOrderNdParam * const paraptr) { Hmesh indmeshdat; /* Induced halo mesh data */ Vmesh nspmeshdat; /* Node separation mesh */ Gnum vertnbr; int o; if (hmeshMesh (meshptr, &nspmeshdat.m) != 0) { errorPrint ("hmeshOrderNd: cannot create node separation mesh"); return (1); } nspmeshdat.ecmpsize[0] = nspmeshdat.m.velmnbr; nspmeshdat.ecmpsize[1] = 0; nspmeshdat.ncmpload[0] = nspmeshdat.m.vnlosum; nspmeshdat.ncmpload[1] = 0; nspmeshdat.ncmpload[2] = 0; nspmeshdat.ncmploaddlt = nspmeshdat.m.vnlosum; nspmeshdat.ncmpsize[0] = nspmeshdat.m.vnodnbr; nspmeshdat.ncmpsize[1] = 0; nspmeshdat.fronnbr = 0; nspmeshdat.levlnum = meshptr->levlnum; vertnbr = nspmeshdat.m.velmnbr + nspmeshdat.m.vnodnbr; if (memAllocGroup ((void **) (void *) &nspmeshdat.parttax, (size_t) (vertnbr * sizeof (GraphPart)), &nspmeshdat.frontab, (size_t) (vertnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("hmeshOrderNd: out of memory (1)"); return (1); } memSet (nspmeshdat.parttax, 0, vertnbr * sizeof (GraphPart)); /* Set all vertices to part 0 */ nspmeshdat.parttax -= nspmeshdat.m.baseval; if (vmeshSeparateSt (&nspmeshdat, paraptr->sepstrat) != 0) { /* Separate mesh */ vmeshExit (&nspmeshdat); return (1); } if ((nspmeshdat.ncmpsize[0] == 0) || /* If could not separate more */ (nspmeshdat.ncmpsize[1] == 0)) { vmeshExit (&nspmeshdat); return (hmeshOrderSt (meshptr, ordeptr, ordenum, cblkptr, paraptr->ordstratlea)); /* Order this leaf */ } cblkptr->typeval = ORDERCBLKNEDI; /* Node becomes a nested dissection node */ if ((cblkptr->cblktab = (OrderCblk *) memAlloc (3 * sizeof (OrderCblk))) == NULL) { errorPrint ("hmeshOrderNd: out of memory (2)"); vmeshExit (&nspmeshdat); return (1); } cblkptr->cblktab[0].typeval = ORDERCBLKOTHR; /* Build column blocks */ cblkptr->cblktab[0].vnodnbr = nspmeshdat.ncmpsize[0]; cblkptr->cblktab[0].cblknbr = 0; cblkptr->cblktab[0].cblktab = NULL; cblkptr->cblktab[1].typeval = ORDERCBLKOTHR; cblkptr->cblktab[1].vnodnbr = nspmeshdat.ncmpsize[1]; cblkptr->cblktab[1].cblknbr = 0; cblkptr->cblktab[1].cblktab = NULL; cblkptr->cblktab[2].vnodnbr = nspmeshdat.fronnbr; cblkptr->cblktab[2].cblknbr = 0; cblkptr->cblktab[2].cblktab = NULL; if (nspmeshdat.fronnbr != 0) { /* If separator not empty */ cblkptr->cblknbr = 3; /* It is a three-cell tree node */ ordeptr->cblknbr += 2; /* Two more column blocks created */ ordeptr->treenbr += 3; /* Three more tree nodes created */ cblkptr->cblktab[2].typeval = ORDERCBLKOTHR; cblkptr->cblktab[2].vnodnbr = nspmeshdat.fronnbr; cblkptr->cblktab[2].cblknbr = 0; cblkptr->cblktab[2].cblktab = NULL; if (meshInduceSepa (&nspmeshdat.m, nspmeshdat.parttax, nspmeshdat.fronnbr, nspmeshdat.frontab, &indmeshdat.m) != 0) { errorPrint ("hmeshOrderNd: cannot build induced subgraph (1)"); memFree (nspmeshdat.frontab); /* Free remaining space */ return (1); } indmeshdat.vnohnbr = indmeshdat.m.vnodnbr; /* Fill halo mesh structure of non-halo mesh */ indmeshdat.vnohnnd = indmeshdat.m.vnodnnd; indmeshdat.vehdtax = indmeshdat.m.vendtax; indmeshdat.vnhlsum = indmeshdat.m.vnlosum; indmeshdat.enohnbr = indmeshdat.m.edgenbr; indmeshdat.levlnum = meshptr->levlnum; /* Separator mesh is at level of original mesh */ o = hmeshOrderSt (&indmeshdat, ordeptr, ordenum + nspmeshdat.ncmpsize[0] + nspmeshdat.ncmpsize[1], cblkptr->cblktab + 2, paraptr->ordstratsep); hmeshExit (&indmeshdat); } else { /* Separator is empty */ cblkptr->cblknbr = 2; /* It is a two-cell tree node */ ordeptr->cblknbr ++; /* One more column block created */ ordeptr->treenbr += 2; /* Two more tree nodes created */ o = 0; /* No separator ordering computed */ } if (o == 0) { if (hmeshInducePart (meshptr, nspmeshdat.parttax, 0, nspmeshdat.ecmpsize[0], nspmeshdat.ncmpsize[0], nspmeshdat.fronnbr, &indmeshdat) != 0) { errorPrint ("hmeshOrderNd: cannot build induced subgraph (2)"); memFree (nspmeshdat.frontab); /* Free remaining space */ return (1); } o = hmeshOrderNd (&indmeshdat, ordeptr, ordenum, cblkptr->cblktab, paraptr); hmeshExit (&indmeshdat); } if (o == 0) { if (hmeshInducePart (meshptr, nspmeshdat.parttax, 1, nspmeshdat.ecmpsize[1], nspmeshdat.ncmpsize[1], nspmeshdat.fronnbr, &indmeshdat) != 0) { errorPrint ("hmeshOrderNd: cannot build induced subgraph (3)"); memFree (nspmeshdat.frontab); /* Free remaining space */ return (1); } o = hmeshOrderNd (&indmeshdat, ordeptr, ordenum + nspmeshdat.ncmpsize[0], cblkptr->cblktab + 1, paraptr); hmeshExit (&indmeshdat); } vmeshExit (&nspmeshdat); return (0); } scotch-5.1.12b.dfsg/src/libscotch/dorder_io_block.c0000644000175300017530000001143011631334325022416 0ustar hazelscthazelsct/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dorder_io_block.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles distributed **/ /** orderings. **/ /** **/ /** DATES : # Version 5.0 : from : 26 may 2008 **/ /** to 26 may 2008 **/ /** # Version 5.1 : from : 11 aug 2010 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DORDER #include "module.h" #include "common.h" #include "dgraph.h" #include "order.h" #include "dorder.h" /************************************/ /* */ /* These routines handle orderings. */ /* */ /************************************/ /* This routine saves a distributed ordering on ** a combined block ordering format. ** The distributed graph structure is provided ** to access the distribution of vertex labels, ** whenever present. ** It returns: ** - 0 : on success. ** - !0 : on error. */ static int dorderSaveBlock2 ( const Order * const cordptr, const Gnum * const vlbltab, FILE * const stream) { Gnum vertnum; Gnum * restrict rangtab; Gnum cblknum; int o; if ((rangtab = memAlloc ((cordptr->vnodnbr + 1) * sizeof (Gnum))) == NULL) { errorPrint ("dorderSaveBlock2: out of memory"); return (1); } orderRang (cordptr, rangtab); if (fprintf (stream, "0\n" GNUMSTRING "\t" GNUMSTRING "\n", (Gnum) cordptr->cblknbr, (Gnum) cordptr->vnodnbr) < 0) { errorPrint ("dorderSaveBlock2: bad output (1)"); return (1); } for (cblknum = 0, o = 1; (o == 1) && (cblknum < cordptr->cblknbr); cblknum ++) { /* Save column-block range array */ o = intSave (stream, rangtab[cblknum]); putc (((cblknum & 7) == 7) ? '\n' : '\t', stream); } o = intSave (stream, rangtab[cblknum]); putc ('\n', stream); orderPeri (cordptr->peritab, cordptr->baseval, cordptr->vnodnbr, rangtab, cordptr->baseval); /* TRICK: re-use rangtab as permtab */ for (vertnum = 0; (o == 1) && (vertnum < (cordptr->vnodnbr - 1)); vertnum ++) { /* Save direct permutation */ o = intSave (stream, rangtab[vertnum]); putc (((vertnum & 7) == 7) ? '\n' : '\t', stream); } o = intSave (stream, rangtab[vertnum]); putc ('\n', stream); if (o != 1) errorPrint ("dorderSaveBlock2: bad output (2)"); return (1 - o); } int dorderSaveBlock ( const Dorder * restrict const ordeptr, const Dgraph * restrict const grafptr, FILE * restrict const stream) { return (dorderSaveTree2 (ordeptr, grafptr, stream, dorderSaveBlock2)); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_halo_fill.c0000644000175300017530000000740111631334325022557 0ustar hazelscthazelsct/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_halo_fill.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a parallel static mapper. **/ /** This module contains the halo update **/ /** routines. **/ /** **/ /** # Version 5.0 : from : 31 dec 2006 **/ /** to 05 feb 2008 **/ /** # Version 5.1 : from : 28 aug 2008 **/ /** to 29 aug 2010 **/ /** **/ /************************************************************/ /* This function fills the send array used by ** all of the halo routines. ** It returns: ** - void : in all cases. */ static void DGRAPHHALOFILLNAME ( const Dgraph * restrict const grafptr, const void * restrict const attrgsttab, /* Attribute array to diffuse */ const int attrglbsiz, /* Type extent of attribute */ byte ** restrict const attrdsptab) /* Temporary address displacement array */ { byte * restrict attrgstptr; const int * restrict procsidptr; const int * restrict procsidnnd; for (procsidptr = grafptr->procsidtab, procsidnnd = procsidptr + grafptr->procsidnbr, attrgstptr = (byte *) attrgsttab; procsidptr < procsidnnd; procsidptr ++) { int procsidval; procsidval = *procsidptr; if (procsidval < 0) attrgstptr -= ((Gnum) procsidval) * DGRAPHHALOFILLSIZE; else { byte * attrdspptr; attrdspptr = attrdsptab[procsidval]; attrdsptab[procsidval] = attrdspptr + DGRAPHHALOFILLSIZE; /* Skip to next position in send buffer */ DGRAPHHALOFILLCOPY (attrdspptr, attrgstptr, DGRAPHHALOFILLSIZE); } } } scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_df.c0000644000175300017530000003441111631334325022557 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_df.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module computes a bipartition of **/ /** a bipartition graph by using a **/ /** diffusion scheme. **/ /** **/ /** NOTES : # This algorithm has been designed to **/ /** work on band graphs only, for which **/ /** the two anchor vertices are the two **/ /** last vertices, the before-last as **/ /** anchor of part 0, and the last as **/ /** anchor of part 1. **/ /** **/ /** DATES : # Version 5.0 : from : 09 jan 2007 **/ /** to 10 sep 2007 **/ /** # Version 5.1 : from : 29 oct 2007 **/ /** to 27 mar 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BGRAPH_BIPART_DF #include "module.h" #include "common.h" #include "graph.h" #include "arch.h" #include "bgraph.h" #include "bgraph_bipart_df.h" /* ** The static variables. */ static const Gnum bgraphbipartdfloadzero = 0; static const Gnum bgraphbipartdfloadone = 1; /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the bipartitioning. ** It returns: ** - 0 : if bipartitioning could be computed. ** - 1 : on error. */ int bgraphBipartDf ( Bgraph * restrict const grafptr, /*+ Active graph +*/ const BgraphBipartDfParam * const paraptr) /*+ Method parameters +*/ { float * restrict edlstax; /* Edge load sum array */ float * restrict veextax; /* External leaks array */ float * restrict difotax; /* Old diffusion value array */ float * restrict difntax; /* New diffusion value array */ float cdifval; float cremval; Gnum fronnum; Gnum compload0; Gnum compload1; Gnum compsize1; Gnum commloadintn; Gnum commloadextn; Gnum commgainextn; Gnum veexnbr; float veexval; const Gnum * restrict veexbax; Gnum veexmsk; float veloval; const Gnum * restrict velobax; Gnum velomsk; Gnum vancval0; /* Initial values for both anchors */ Gnum vancval1; float vanctab[2]; /* Value to add to each anchor */ Gnum vertnum; INT passnum; veexnbr = (grafptr->veextax != NULL) ? grafptr->s.vertnbr : 0; if (memAllocGroup ((void **) (void *) &edlstax, (size_t) (grafptr->s.vertnbr * sizeof (float)), &veextax, (size_t) (veexnbr * sizeof (float)), &difotax, (size_t) (grafptr->s.vertnbr * sizeof (float)), &difntax, (size_t) (grafptr->s.vertnbr * sizeof (float)), NULL) == NULL) { errorPrint ("bgraphBipartDf: out of memory (1)"); return (1); } edlstax -= grafptr->s.baseval; /* Base access to veextax and diffusion arrays */ difotax -= grafptr->s.baseval; difntax -= grafptr->s.baseval; veextax = (grafptr->veextax != NULL) ? veextax - grafptr->s.baseval : NULL; compload0 = (paraptr->typeval == BGRAPHBIPARTDFTYPEBAL) /* If balanced parts wanted */ ? grafptr->compload0avg /* Target is average */ : ( (grafptr->compload0 < grafptr->compload0min) ? grafptr->compload0min : /* Else keep load if not off balance */ ((grafptr->compload0 > grafptr->compload0max) ? grafptr->compload0max : grafptr->compload0)); vancval0 = (float) - compload0; /* Values to be injected to anchor vertices at every iteration */ vancval1 = (float) (grafptr->s.velosum - compload0); if (grafptr->s.edlotax == NULL) { /* If graph doesn't have edge weights */ Gnum vertnum; for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { difotax[vertnum] = 0.0; edlstax[vertnum] = (float) (grafptr->s.vendtax[vertnum] - grafptr->s.verttax[vertnum]); } } else { /* If graph has edge weights */ Gnum vertnum; for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { Gnum edgenum; Gnum edgennd; Gnum edlosum; for (edgenum = grafptr->s.verttax[vertnum], edgennd = grafptr->s.vendtax[vertnum], edlosum = 0; edgenum < edgennd; edgenum ++) edlosum += grafptr->s.edlotax[edgenum]; difotax[vertnum] = 0.0; edlstax[vertnum] = (float) edlosum; } } if (veextax != NULL) { Gnum vertnum; Gnum veexsum; Gnum veexsum0; float idodist; /* Inverse of domdist */ idodist = 1.0 / (float) grafptr->domdist; for (vertnum = grafptr->s.baseval, veexsum = veexsum0 = 0; vertnum < grafptr->s.vertnnd; vertnum ++) { Gnum veexval; veexval = grafptr->veextax[vertnum]; veexsum += veexval; /* Sum all external gains, positive and negative */ veexsum0 += BGRAPHBIPARTDFGNUMSGNMSK (veexval); /* Sum all negative external gains; superscalar update */ veextax[vertnum] = (float) veexval / idodist; } vancval0 += (float) veexsum0; vancval1 += (float) (veexsum - veexsum0); } vancval1 -= BGRAPHBIPARTDFEPSILON; /* Slightly tilt value to add to part 1 */ difotax[grafptr->s.vertnnd - 2] = vancval0 / edlstax[grafptr->s.vertnnd - 2]; /* Load anchor vertices for first pass */ difotax[grafptr->s.vertnnd - 1] = vancval1 / edlstax[grafptr->s.vertnnd - 1]; veexval = 0.0F; /* Assume no external gains */ veloval = 1.0F; /* Assume no vertex loads */ cdifval = paraptr->cdifval; cremval = paraptr->cremval; for (passnum = 0; passnum < paraptr->passnbr; passnum ++) { /* For all passes */ Gnum vertnum; Gnum vertnnd; float vancval; /* Value to load vertex with if anchor */ float * difttax; /* Temporary swap value */ vanctab[0] = vancval0; /* Copy anchor values to injection variables */ vanctab[1] = vancval1; vancval = 0.0F; /* At first vertices are not anchors */ vertnum = grafptr->s.baseval; vertnnd = grafptr->s.vertnnd - 2; while (1) { for ( ; vertnum < vertnnd; vertnum ++) { Gnum edgenum; Gnum edgennd; float diffval; edgenum = grafptr->s.verttax[vertnum]; edgennd = grafptr->s.vendtax[vertnum]; diffval = 0.0F; if (grafptr->s.edlotax != NULL) for ( ; edgenum < edgennd; edgenum ++) diffval += difotax[grafptr->s.edgetax[edgenum]] * (float) grafptr->s.edlotax[edgenum]; else for ( ; edgenum < edgennd; edgenum ++) diffval += difotax[grafptr->s.edgetax[edgenum]]; diffval *= cdifval; diffval += difotax[vertnum] * cremval * edlstax[vertnum] + vancval; if (grafptr->s.velotax != NULL) veloval = (float) grafptr->s.velotax[vertnum]; if (veextax != NULL) { veexval = veextax[vertnum] * diffval; if (veexval >= 0.0F) /* If vertex is already in right part */ veexval = 0.0F; /* Then it will not be impacted */ else { int partval; partval = (diffval < 0.0F) ? 0 : 1; /* Load anchor with load removed from vertex */ vanctab[partval] += (float) (2 * partval - 1) * veexval; } } if (diffval >= 0.0F) { diffval -= veloval + veexval; if (diffval <= 0.0F) diffval = +BGRAPHBIPARTDFEPSILON; } else { diffval += veloval + veexval; if (diffval >= 0.0F) diffval = -BGRAPHBIPARTDFEPSILON; } if (isnan (diffval)) /* If overflow occured (because of avalanche process) */ goto abort; /* Exit main loop without swapping arrays so as to keep last valid iteration */ difntax[vertnum] = diffval / edlstax[vertnum]; } if (vertnum == grafptr->s.vertnnd) /* If all vertices processed, exit intermediate infinite loop */ break; vertnnd ++; /* Prepare to go only for one more run */ vancval = vanctab[vertnum - grafptr->s.vertnnd + 2]; /* Load variable with anchor value */ } difttax = (float *) difntax; /* Swap old and new diffusion arrays */ difntax = (float *) difotax; /* Casts to prevent IBM compiler from yelling */ difotax = (float *) difttax; } abort : /* If overflow occured, resume here */ for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) /* Update part according to diffusion state */ grafptr->parttax[vertnum] = (difotax[vertnum] <= 0.0F) ? 0 : 1; if (grafptr->veextax != NULL) { veexbax = grafptr->veextax; veexmsk = ~((Gnum) 0); } else { veexbax = &bgraphbipartdfloadzero; veexmsk = 0; } if (grafptr->s.velotax != NULL) { velobax = grafptr->s.velotax; velomsk = ~((Gnum) 0); } else { velobax = &bgraphbipartdfloadone; velomsk = 0; } for (vertnum = grafptr->s.baseval, fronnum = 0, commloadextn = grafptr->commloadextn0, commgainextn = commloadintn = compload1 = compsize1 = 0; vertnum < grafptr->s.vertnnd; vertnum ++) { Gnum edgenum; Gnum partval; Gnum commload; /* Vertex internal communication load */ partval = (Gnum) grafptr->parttax[vertnum]; compsize1 += partval; compload1 += partval * velobax[vertnum & velomsk]; commloadextn += partval * veexbax[vertnum & veexmsk]; commgainextn += (1 - 2 * partval) * veexbax[vertnum & veexmsk]; commload = 0; if (grafptr->s.edlotax != NULL) { for (edgenum = grafptr->s.verttax[vertnum]; edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) { Gnum partend; partend = (Gnum) grafptr->parttax[grafptr->s.edgetax[edgenum]]; commload += (partval ^ partend) * grafptr->s.edlotax[edgenum]; } } else { for (edgenum = grafptr->s.verttax[vertnum]; edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) commload += partval ^ (Gnum) grafptr->parttax[grafptr->s.edgetax[edgenum]]; } commloadintn += commload; /* Internal loads will be added twice */ if (commload != 0) /* If end vertex is in the other part */ grafptr->frontab[fronnum ++] = vertnum; /* Then it belongs to the frontier */ } grafptr->fronnbr = fronnum; grafptr->compload0 = grafptr->s.velosum - compload1; grafptr->compload0dlt = grafptr->compload0 - grafptr->compload0avg; grafptr->compsize0 = grafptr->s.vertnbr - compsize1; grafptr->commload = commloadextn + (commloadintn / 2) * grafptr->domdist; grafptr->commgainextn = commgainextn; grafptr->bbalval = (double) ((grafptr->compload0dlt < 0) ? (- grafptr->compload0dlt) : grafptr->compload0dlt) / (double) grafptr->compload0avg; memFree (edlstax + grafptr->s.baseval); #ifdef SCOTCH_DEBUG_BGRAPH2 if (bgraphCheck (grafptr) != 0) { errorPrint ("bgraphBipartDf: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_order_perm_f.c0000644000175300017530000000645211631334325025022 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_order_perm_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** distributed ordering permutation **/ /** building routine of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 5.0 : from : 18 oct 2007 **/ /** to 18 oct 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the ordering routines. */ /* */ /**************************************/ FORTRAN ( \ SCOTCHFDGRAPHORDERPERM, scotchfdgraphorderperm, ( \ const SCOTCH_Dgraph * const grafptr, \ const SCOTCH_Dordering * const ordeptr, \ SCOTCH_Num * const permloctab, \ int * const revaptr), \ (grafptr, ordeptr, permloctab, revaptr)) { *revaptr = SCOTCH_dgraphOrderPerm (grafptr, ordeptr, permloctab); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_ghst.h0000644000175300017530000000663011631334325021603 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /**********************************************************/ /* */ /* NAME : dgraph_ghst.h */ /* */ /* AUTHOR : Francois PELLEGRINI */ /* Francois CHATENET (P0.0) */ /* Sebastien FOUCAULT (P0.0) */ /* Nicolas GICQUEL (P0.1) */ /* Jerome LACOSTE (P0.1) */ /* */ /* FUNCTION : Part of a parallel static mapper. */ /* These lines are the data declarations */ /* for the halo building routine. */ /* */ /* # Version P0.0 : from : 01 apr 1997 */ /* to 20 jun 1997 */ /* # Version P0.1 : from : 12 apr 1998 */ /* to 20 jun 1998 */ /* # Version 5.0 : from : 28 feb 2006 */ /* to 31 dec 2006 */ /* */ /**********************************************************/ /* ** The defines. */ /* procsidtab-related values. */ #define DGRAPHGHSTSIDMAX ((int) ((unsigned int) (1 << (sizeof (int) * 8 - 1)) - 2U)) /* Maximum leap value for procsidtab entries */ /* ** The type and structure definitions. */ /* Sort structure for ghost edges. */ typedef struct DgraphGhstSort_ { Gnum vertglbnum; /* Global end vertex number */ Gnum edgegstnum; /* Number of ghost edge */ } DgraphGhstSort; scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_order_io_block.c0000644000175300017530000000672711631334325025340 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_order_io_block.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted ordering distributed tree **/ /** building routine of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 5.1 : from : 28 may 2008 **/ /** to 28 may 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "dgraph.h" #include "dorder.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the distributed ordering */ /* handling routines. */ /* */ /************************************/ /*+ This routine saves the contents of *** the given ordering to the given stream *** on the form of a block ordering. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphOrderSaveBlock ( const SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ const SCOTCH_Dordering * const ordeptr, /*+ Ordering to save +*/ FILE * const stream) /*+ Output stream +*/ { return (dorderSaveBlock ((Dorder *) ordeptr, (Dgraph *) grafptr, stream)); } scotch-5.1.12b.dfsg/src/libscotch/vgraph_store.c0000644000175300017530000001431311631334325022004 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_store.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the save data **/ /** structure handling routines for separa- **/ /** tion graphs. **/ /** **/ /** DATES : # Version 3.3 : from : 17 oct 1998 **/ /** to 17 oct 1998 **/ /** # Version 3.4 : from : 11 dec 2001 **/ /** to : 11 dec 2001 **/ /** # Version 4.0 : from : 01 jan 2002 **/ /** to : 06 jan 2002 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VGRAPH_STORE #include "module.h" #include "common.h" #include "graph.h" #include "vgraph.h" /**********************************/ /* */ /* Store graph handling routines. */ /* */ /**********************************/ /* This routine builds a save structure ** for the given active graph. ** It returns: ** - 0 : if allocation succeeded. ** - !0 : on error. */ int vgraphStoreInit ( const Vgraph * restrict const grafptr, VgraphStore * restrict const storptr) { Gnum savsize; savsize = grafptr->s.vertnbr * (sizeof (GraphPart) + sizeof (Gnum)); /* Compute size for frontier and part arrays */ if ((storptr->datatab = (byte *) memAlloc (savsize)) == NULL) { /* Allocate save structure */ errorPrint ("vgraphStoreInit: out of memory"); return (1); } return (0); } /* This routine frees a save structure. ** It returns: ** - VOID : in all cases. */ void vgraphStoreExit ( VgraphStore * const storptr) { memFree (storptr->datatab); #ifdef SCOTCH_DEBUG_VGRAPH2 storptr->datatab = NULL; #endif /* SCOTCH_DEBUG_VGRAPH2 */ } /* This routine saves partition data from the ** given active graph to the given save structure. ** It returns: ** - VOID : in all cases. */ void vgraphStoreSave ( const Vgraph * const grafptr, VgraphStore * const storptr) { byte * parttab; /* Pointer to part data save area */ byte * frontab; /* Pointer to frontier data save area */ storptr->fronnbr = grafptr->fronnbr; /* Save partition parameters */ storptr->comploaddlt = grafptr->comploaddlt; storptr->compload[0] = grafptr->compload[0]; storptr->compload[1] = grafptr->compload[1]; storptr->compsize0 = grafptr->compsize[0]; frontab = storptr->datatab; /* Compute data offsets within save structure */ parttab = frontab + grafptr->fronnbr * sizeof (Gnum); memCpy (frontab, grafptr->frontab, grafptr->fronnbr * sizeof (Gnum)); memCpy (parttab, grafptr->parttax + grafptr->s.baseval, grafptr->s.vertnbr * sizeof (GraphPart)); } /* This routine updates partition data of the ** given active graph, using the given save graph. ** It returns: ** - VOID : in all cases. */ void vgraphStoreUpdt ( Vgraph * const grafptr, const VgraphStore * const storptr) { byte * frontab; /* Pointer to frontier data save area */ byte * parttab; /* Pointer to part data save area */ grafptr->compload[0] = storptr->compload[0]; /* Load partition parameters */ grafptr->compload[1] = storptr->compload[1]; grafptr->compload[2] = grafptr->s.velosum - (storptr->compload[0] + storptr->compload[1]); grafptr->comploaddlt = storptr->comploaddlt; grafptr->compsize[0] = storptr->compsize0; grafptr->compsize[1] = grafptr->s.vertnbr - (storptr->compsize0 + storptr->fronnbr); grafptr->fronnbr = storptr->fronnbr; frontab = storptr->datatab; /* Compute data offsets within save structure */ parttab = frontab + grafptr->fronnbr * sizeof (Gnum); memCpy (grafptr->frontab, frontab, grafptr->fronnbr * sizeof (Gnum)); memCpy (grafptr->parttax + grafptr->s.baseval, parttab, grafptr->s.vertnbr * sizeof (GraphPart)); #ifdef SCOTCH_DEBUG_VGRAPH2 if (vgraphCheck (grafptr) != 0) errorPrint ("vgraphStoreUpdt: inconsistent graph data"); #endif /* SCOTCH_DEBUG_VGRAPH2 */ } scotch-5.1.12b.dfsg/src/libscotch/vmesh_check.c0000644000175300017530000002034011631334325021555 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh_check.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the consistency **/ /** checker for separation meshes. **/ /** **/ /** DATES : # Version 4.0 : from : 21 mar 2003 **/ /** to 11 may 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VMESH #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" #include "vmesh.h" /*************************/ /* */ /* These routines handle */ /* separator meshes. */ /* */ /*************************/ /* This routine checks the consistency ** of the given separator mesh. ** It returns: ** - 0 : if mesh data are consistent. ** - !0 : on error. */ int vmeshCheck ( const Vmesh * const meshptr) { Gnum velmnum; /* Number of current element vertex */ Gnum vnodnum; /* Number of current node vertex */ Gnum fronnum; /* Number of current frontier vertex */ int * restrict frontax; /* Frontier flag array */ Gnum ecmpsize[2]; /* Elements never in separator */ Gnum ncmpsize[3]; Gnum ncmpload[3]; if ((meshptr->ecmpsize[0] + meshptr->ecmpsize[1]) > meshptr->m.velmnbr) { errorPrint ("vmeshCheck: invalid element balance"); return (1); } if (meshptr->ncmploaddlt != (meshptr->ncmpload[0] - meshptr->ncmpload[1])) { errorPrint ("vmeshCheck: invalid node balance"); return (1); } ecmpsize[0] = ecmpsize[1] = 0; for (velmnum = meshptr->m.velmbas; velmnum < meshptr->m.velmnnd; velmnum ++) { Gnum edgecut[3]; /* Array of cut edges */ Gnum partnum; /* Part of current vertex */ Gnum eelmnum; /* Number of current edge */ partnum = meshptr->parttax[velmnum]; if ((partnum < 0) || (partnum > 1)) { errorPrint ("vmeshCheck: invalid part array (1)"); return (1); } ecmpsize[partnum] ++; if ((partnum != 0) && (meshptr->m.verttax[velmnum] == meshptr->m.vendtax[velmnum])) { errorPrint ("vmeshCheck: isolated element not in part 0"); return (1); } edgecut[0] = edgecut[1] = edgecut[2] = 0; for (eelmnum = meshptr->m.verttax[velmnum]; eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) edgecut[meshptr->parttax[meshptr->m.edgetax[eelmnum]]] ++; if (partnum == 2) { if ((edgecut[0] != 0) || (edgecut[1] != 0)) { errorPrint ("vmeshCheck: separator element not surrounded by separator nodes"); return (1); } } else { if (edgecut[1 - partnum] != 0) { errorPrint ("vmeshCheck: element should be in separator (%ld)", (long) velmnum); return (1); } } } if ((meshptr->ecmpsize[0] != ecmpsize[0]) || (meshptr->ecmpsize[1] != ecmpsize[1])) { errorPrint ("vmeshCheck: invalid element parameters"); return (1); } ncmpload[0] = ncmpload[1] = ncmpload[2] = 0; ncmpsize[0] = ncmpsize[1] = ncmpsize[2] = 0; for (vnodnum = meshptr->m.vnodbas; vnodnum < meshptr->m.vnodnnd; vnodnum ++) { Gnum edgecut[3]; /* Array of cut edges */ Gnum partnum; /* Part of current vertex */ Gnum enodnum; /* Number of current edge */ partnum = meshptr->parttax[vnodnum]; if ((partnum < 0) || (partnum > 2)) { errorPrint ("vmeshCheck: invalid part array (2)"); return (1); } ncmpsize[partnum] ++; ncmpload[partnum] += (meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum]; edgecut[0] = edgecut[1] = edgecut[2] = 0; for (enodnum = meshptr->m.verttax[vnodnum]; enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) edgecut[meshptr->parttax[meshptr->m.edgetax[enodnum]]] ++; #ifdef SCOTCH_DEBUG_VMESH3 if (partnum == 2) { if ((edgecut[0] == 0) || (edgecut[1] == 0)) errorPrint ("vmeshCheck: no-use separator vertex%s (%ld)", /* Warning only */ ((meshptr->levlnum == 0) ? " at level 0" : ""), (long) vnodnum); } else { #else if (partnum != 2) { #endif /* SCOTCH_DEBUG_VMESH3 */ if (edgecut[1 - partnum] != 0) { errorPrint ("vmeshCheck: node should be in separator (%ld)", (long) vnodnum); return (1); } } } if ((meshptr->ncmpload[0] != ncmpload[0]) || (meshptr->ncmpload[1] != ncmpload[1]) || (meshptr->ncmpload[2] != ncmpload[2]) || (meshptr->ncmpsize[0] != ncmpsize[0]) || (meshptr->ncmpsize[1] != ncmpsize[1]) || (meshptr->fronnbr != ncmpsize[2])) { errorPrint ("vmeshCheck: invalid node parameters"); return (1); } if ((meshptr->fronnbr < 0) || (meshptr->fronnbr > meshptr->m.vnodnbr)) { errorPrint ("vmeshCheck: invalid number of frontier vertices"); return (1); } if ((frontax = memAlloc (meshptr->m.vnodnbr * sizeof (int))) == NULL) { errorPrint ("vmeshCheck: out of memory"); return (1); } memSet (frontax, 0, meshptr->m.vnodnbr * sizeof (int)); frontax -= meshptr->m.vnodbas; for (fronnum = 0; fronnum < meshptr->fronnbr; fronnum ++) { Gnum vnodnum; vnodnum = meshptr->frontab[fronnum]; if ((vnodnum < meshptr->m.vnodbas) || (vnodnum >= meshptr->m.vnodnnd)) { errorPrint ("vmeshCheck: invalid vertex in frontier array"); memFree (frontax + meshptr->m.vnodbas); return (1); } if (meshptr->parttax[vnodnum] != 2) { errorPrint ("vmeshCheck: invalid frontier array"); memFree (frontax + meshptr->m.vnodbas); return (1); } if (frontax[vnodnum] != 0) { errorPrint ("vmeshCheck: duplicate node in frontier array"); memFree (frontax + meshptr->m.vnodbas); return (1); } frontax[vnodnum] = 1; } memFree (frontax + meshptr->m.vnodbas); return (0); } scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_si.h0000644000175300017530000000566111631334325022453 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_si.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the simple halo graph **/ /** ordering routine. **/ /** **/ /** DATES : # Version 3.2 : from : 01 nov 1996 **/ /** to : 18 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to 02 oct 1998 **/ /** # Version 4.0 : from : 19 dec 2001 **/ /** to 11 dec 2002 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef HGRAPH_ORDER_SI #define static #endif int hgraphOrderSi (const Hgraph * const, Order * const, const Gnum, OrderCblk * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/kdgraph_map_st.c0000644000175300017530000002021211631334325022257 0ustar hazelscthazelsct/* Copyright 2008-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kdgraph_map_st.c **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the strategy and **/ /** method tables for the parallel **/ /** multi-way static mapping routines. **/ /** **/ /** DATES : # Version 5.1 : from : 16 jun 2008 **/ /** to 14 apr 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define KDGRAPH_MAP_ST #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "dgraph.h" #include "dgraph_coarsen.h" #include "arch.h" #include "mapping.h" #include "dmapping.h" #include "bdgraph.h" #include "bdgraph_bipart_st.h" #include "kgraph.h" #include "kgraph_map_st.h" #include "kdgraph.h" #include "kdgraph_map_rb.h" #include "kdgraph_map_st.h" /* ** The static and global variables. */ static union { KdgraphMapRbParam param; StratNodeMethodData padding; } kdgraphmapstdefaultrb = { { &stratdummy, &stratdummy, 0.05 } }; static StratMethodTab kdgraphmapstmethtab[] = { /* Mapping methods array */ { KDGRAPHMAPSTMETHRB, "r", kdgraphMapRb, &kdgraphmapstdefaultrb }, { -1, NULL, NULL, NULL } }; static StratParamTab kdgraphmapstparatab[] = { /* Method parameter list */ { KDGRAPHMAPSTMETHRB, STRATPARAMSTRAT, "sep", (byte *) &kdgraphmapstdefaultrb.param, (byte *) &kdgraphmapstdefaultrb.param.stratsep, (void *) &bdgraphbipartststratab }, { KDGRAPHMAPSTMETHRB, STRATPARAMSTRAT, "seq", (byte *) &kdgraphmapstdefaultrb.param, (byte *) &kdgraphmapstdefaultrb.param.stratseq, (void *) &kgraphmapststratab }, { KDGRAPHMAPSTMETHRB, STRATPARAMDOUBLE, "bal", (byte *) &kdgraphmapstdefaultrb.param, (byte *) &kdgraphmapstdefaultrb.param.kbalval, NULL }, { KDGRAPHMAPSTMETHNBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; static StratParamTab kdgraphmapstcondtab[] = { /* Graph condition parameter table */ { STRATNODENBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; StratTab kdgraphmapststratab = { /* Strategy tables for graph mapping methods */ kdgraphmapstmethtab, kdgraphmapstparatab, kdgraphmapstcondtab }; /****************************************/ /* */ /* This is the generic mapping routine. */ /* */ /****************************************/ /* This routine computes the given ** mapping according to the given ** strategy. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int kdgraphMapSt ( Kdgraph * restrict const grafptr, /*+ Mapping graph +*/ Kdmapping * restrict const mappptr, /*+ Dynamic mapping +*/ const Strat * restrict const strat) /*+ Mapping strategy +*/ { StratTest val; int o; #ifdef SCOTCH_DEBUG_KDGRAPH2 if (sizeof (Gnum) != sizeof (INT)) { errorPrint ("kdgraphMapSt: invalid type specification for parser variables"); return (1); } if ((sizeof (KdgraphMapRbParam) > sizeof (StratNodeMethodData))) { errorPrint ("kdgraphMapSt: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_KDGRAPH2 */ #ifdef SCOTCH_DEBUG_KDGRAPH1 if ((strat->tabl != &kdgraphmapststratab) && (strat != &stratdummy)) { errorPrint ("kdgraphMapSt: invalid parameter (1)"); return (1); } #endif /* SCOTCH_DEBUG_KDGRAPH1 */ o = 0; switch (strat->type) { case STRATNODECONCAT : o = kdgraphMapSt (grafptr, mappptr, strat->data.concat.strat[0]); /* Apply first strategy */ if (o == 0) /* If it worked all right */ o |= kdgraphMapSt (grafptr, mappptr, strat->data.concat.strat[1]); /* Then apply second strategy */ break; case STRATNODECOND : o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ if (o == 0) { /* If evaluation was correct */ #ifdef SCOTCH_DEBUG_KDGRAPH2 if ((val.typetest != STRATTESTVAL) || (val.typenode != STRATPARAMLOG)) { errorPrint ("kdgraphMapSt: invalid test result"); o = 1; break; } #endif /* SCOTCH_DEBUG_KDGRAPH2 */ if (val.data.val.vallog == 1) /* If expression is true */ o = kdgraphMapSt (grafptr, mappptr, strat->data.cond.strat[0]); /* Apply first strategy */ else { /* Else if expression is false */ if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ o = kdgraphMapSt (grafptr, mappptr, strat->data.cond.strat[1]); /* Apply second strategy */ } } break; case STRATNODEEMPTY : break; case STRATNODESELECT : errorPrint ("kdgraphMapSt: selection operator not implemented for k-way strategies"); return (1); #ifdef SCOTCH_DEBUG_KDGRAPH1 case STRATNODEMETHOD : #else /* SCOTCH_DEBUG_KDGRAPH1 */ default : #endif /* SCOTCH_DEBUG_KDGRAPH1 */ return (strat->tabl->methtab[strat->data.method.meth].func (grafptr, mappptr, (void *) &strat->data.method.data)); #ifdef SCOTCH_DEBUG_KDGRAPH1 default : errorPrint ("kdgraphMapSt: invalid parameter (2)"); return (1); #endif /* SCOTCH_DEBUG_KDGRAPH1 */ } return (o); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_gr.c0000644000175300017530000000737411631334325022301 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_gr.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders a halo mesh by **/ /** turning it into a graph and using a **/ /** graph separation strategy. **/ /** **/ /** DATES : # Version 4.0 : from : 30 nov 2003 **/ /** to 27 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH_ORDER_GR #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "order.h" #include "hgraph.h" #include "hgraph_order_st.h" #include "mesh.h" #include "hmesh.h" #include "hmesh_order_gr.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hmeshOrderGr ( const Hmesh * restrict const meshptr, Order * restrict const ordeptr, const Gnum ordenum, OrderCblk * restrict const cblkptr, const HmeshOrderGrParam * const paraptr) { Hgraph grafdat; int o; hgraphInit (&grafdat); if (hmeshHgraph (meshptr, &grafdat) != 0) { /* Build halo graph with improper vnumtab */ errorPrint ("hmeshOrderGr: cannot build halo graph"); return (1); } if ((o = hgraphOrderSt (&grafdat, ordeptr, ordenum, cblkptr, paraptr->stratptr)) != 0) errorPrint ("hmeshOrderGr: cannot order graph"); hgraphFree (&grafdat); /* Free graph structure */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/graph_io_mmkt.c0000644000175300017530000003050611631334325022123 0ustar hazelscthazelsct/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_io_mmkt.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** Cedric CHEVALIER (v5.0) **/ /** **/ /** FUNCTION : This module contains the input/output **/ /** routines for handling the Matrix Market **/ /** format. **/ /** **/ /** DATES : # Version 5.0 : from : 17 jan 2008 **/ /** to : 21 mar 2008 **/ /** # Version 5.1 : from : 27 apr 2010 **/ /** to : 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GRAPH_IO_MMKT #include "module.h" #include "common.h" #include "geom.h" #include "graph.h" #include "graph_io_mmkt.h" /********************************************************/ /* */ /* These routines handle source Matrix Market matrices. */ /* */ /********************************************************/ /* This routine loads a source graph from ** the given stream, corresponding to a MatrixMarket file. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int graphGeomLoadMmkt ( Graph * restrict const grafptr, /* Graph to load */ Geom * restrict const geomptr, /* Geometry to load */ FILE * const filesrcptr, /* Topological data */ FILE * const filegeoptr, /* No use */ const char * const dataptr) /* Fake base value */ { Gnum baseval; Gnum mrownbr; Gnum mcolnbr; Gnum linenbr; Gnum linenum; Gnum vertnum; Gnum verttmp; GraphGeomMmktEdge * sorttab; Gnum sortnbr; Gnum sortnum; Gnum * edgetax; Gnum edgenum; Gnum edgetmp; Gnum degrmax; char linetab[1025]; char * lineptr; char c; baseval = 1; /* Regular MatrixMarket indices start from 1 */ if ((dataptr != NULL) && /* If base value provided */ (dataptr[0] != '\0') && ((baseval = (Gnum) atol (dataptr)) == 0) && /* Get base value */ (dataptr[0] != '0')) { errorPrint ("graphGeomLoadMmkt: invalid parameter"); return (1); } if (fgets (linetab, 1025, filesrcptr) == NULL) { /* Read header lines */ errorPrint ("graphGeomLoadMmkt: bad input (1)"); return (1); } if (strncmp (linetab, "%%MatrixMarket", 14) != 0) { errorPrint ("graphGeomLoadMmkt: invalid header"); return (1); } for (lineptr = linetab + 14; *lineptr != '\0'; lineptr ++) *lineptr = tolower (*lineptr); if (strstr (linetab + 14, "matrix") == NULL) { errorPrint ("graphGeomLoadMmkt: only matrix types supported"); return (1); } while ((c = fgetc (filesrcptr)) == '%') { /* Skip additional comment lines */ if (fgets (linetab, 1025, filesrcptr) == NULL) { errorPrint ("graphGeomLoadMmkt: bad input (2)"); return (1); } } ungetc (c, filesrcptr); if ((intLoad (filesrcptr, &mrownbr) != 1) || /* Read number of rows */ (intLoad (filesrcptr, &mcolnbr) != 1) || /* Read number of columns */ (intLoad (filesrcptr, &linenbr) != 1)) { /* Read number of lines */ errorPrint ("graphGeomLoadMmkt: bad input (3)"); return (1); } if (mrownbr != mcolnbr) { /* If not a square matrix */ errorPrint ("graphGeomLoadMmkt: not a square matrix"); return (1); } memSet (grafptr, 0, sizeof (Graph)); grafptr->flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; grafptr->baseval = baseval; grafptr->vertnbr = mrownbr; grafptr->vertnnd = grafptr->vertnbr + baseval; if ((grafptr->verttax = memAlloc ((grafptr->vertnbr + 1) * sizeof (Gnum))) == NULL) { errorPrint ("graphGeomLoadMmkt: out of memory (1)"); graphExit (grafptr); return (1); } grafptr->verttax -= baseval; grafptr->vendtax = grafptr->verttax + 1; grafptr->velosum = grafptr->vertnbr; if ((sorttab = (GraphGeomMmktEdge *) memAlloc (2 * linenbr * sizeof (GraphGeomMmktEdge))) == NULL) { /* Twice the space for symmetric edges */ errorPrint ("graphGeomLoadMmkt: out of memory (2)"); graphExit (grafptr); return (1); } grafptr->edgetax = ((Gnum *) sorttab) - baseval; /* TRICK: will be freed if graph is freed */ for (linenum = sortnbr = 0; linenum < linenbr; linenum ++) { if ((intLoad (filesrcptr, &sorttab[sortnbr].vertnum[0]) != 1) || /* Read edge ends */ (intLoad (filesrcptr, &sorttab[sortnbr].vertnum[1]) != 1) || (fgets (linetab, 1025, filesrcptr) == NULL)) { /* Skip end of line */ errorPrint ("graphGeomLoadMmkt: bad input (4)"); graphExit (grafptr); return (1); } if ((sorttab[sortnbr].vertnum[0] < baseval) || (sorttab[sortnbr].vertnum[0] >= (mrownbr + baseval)) || (sorttab[sortnbr].vertnum[1] < baseval) || (sorttab[sortnbr].vertnum[1] >= (mrownbr + baseval))) { errorPrint ("graphGeomLoadMmkt: bad input (5)"); graphExit (grafptr); return (1); } if (sorttab[sortnbr].vertnum[0] != sorttab[sortnbr].vertnum[1]) { /* If not loop edge */ sorttab[sortnbr + 1].vertnum[0] = sorttab[sortnbr].vertnum[1]; /* Add symmetric edge */ sorttab[sortnbr + 1].vertnum[1] = sorttab[sortnbr].vertnum[0]; sortnbr += 2; } } intSort2asc2 (sorttab, sortnbr); /* Sort edges by increasing indices */ edgetax = grafptr->edgetax; /* TRICK: point to beginning of sorted edge array for re-use */ for (sortnum = degrmax = 0, vertnum = baseval - 1, edgetmp = edgenum = baseval; sortnum < sortnbr; sortnum ++) { Gnum vertend; if (vertnum < sorttab[sortnum].vertnum[0]) { /* If change of vertex index, that is, first edge end */ edgetmp = edgenum - edgetmp; /* Compute degree and see if it is maximum degree */ if (edgetmp > degrmax) degrmax = edgetmp; edgetmp = edgenum; grafptr->verttax[++ vertnum] = edgenum; /* Set beginning of new edge sub-array */ while (vertnum < sorttab[sortnum].vertnum[0]) /* Fill gaps with isolated vertices */ grafptr->verttax[++ vertnum] = edgenum; verttmp = baseval - 1; /* Make sure next edge will be considered as never seen before */ } vertend = sorttab[sortnum].vertnum[1]; /* Get end of current edge */ if (vertend != verttmp) /* If edge differs from previous one */ edgetax[edgenum ++] = verttmp = vertend; /* Add it to array and prevent duplicates */ } edgetmp = edgenum - edgetmp; /* Compute degree and see if it is maximum degree */ if (edgetmp > degrmax) degrmax = edgetmp; while (vertnum < mrownbr) /* Fill gaps with isolated vertices and mark beginning of new one */ grafptr->verttax[++ vertnum] = edgenum; grafptr->verttax[++ vertnum] = edgenum; /* Mark end of array */ #ifdef SCOTCH_DEBUG_GRAPH2 if (vertnum != grafptr->vertnnd) { errorPrint ("graphGeomLoadMmkt: internal error (1)"); graphExit (grafptr); return (1); } #endif /* SCOTCH_DEBUG_GRAPH2 */ grafptr->edgenbr = edgenum - baseval; grafptr->edgetax = ((Gnum *) memRealloc (edgetax + baseval, grafptr->edgenbr * sizeof (Gnum))) - baseval; /* TRICK: keep only useful space in re-used array */ grafptr->edlotax = NULL; grafptr->edlosum = grafptr->edgenbr; grafptr->degrmax = degrmax; #ifdef SCOTCH_DEBUG_GRAPH2 if (graphCheck (grafptr) != 0) { /* Check graph consistency */ errorPrint ("graphGeomLoadMmkt: internal error (2)"); graphExit (grafptr); return (1); } #endif /* SCOTCH_DEBUG_GRAPH2 */ return (0); } /* This routine saves the geometrical graph ** in the Matrix Market symmetric graph format. ** It returns: ** - 0 : on succes ** - !0 : on error. */ int graphGeomSaveMmkt ( const Graph * restrict const grafptr, /* Graph to save */ const Geom * restrict const geomptr, /* Geometry to save */ FILE * const filesrcptr, /* Topological data */ FILE * const filegeoptr, /* No use */ const char * const dataptr) /* No use */ { Gnum baseadj; /* Base adjustment */ Gnum vertnum; /* Current vertex */ Gnum edgenum; /* Current edge */ int o; baseadj = 1 - grafptr->baseval; /* Output base is always 1 */ o = (fprintf (filesrcptr, "%%%%MatrixMarket matrix coordinate pattern symmetric\n%% Produced by Scotch graphGeomSaveMmkt\n" GNUMSTRING " " GNUMSTRING " " GNUMSTRING "\n", /* Write graph header */ (Gnum) grafptr->vertnbr, (Gnum) grafptr->vertnbr, (Gnum) ((grafptr->edgenbr / 2) + grafptr->vertnbr)) == EOF); for (vertnum = grafptr->baseval; (o == 0) && (vertnum < grafptr->vertnnd); vertnum ++) { Gnum vlblnum; /* Vertex label to output */ vlblnum = ((grafptr->vlbltax != NULL) ? grafptr->vlbltax[vertnum] : vertnum) + baseadj; if (fprintf (filesrcptr, GNUMSTRING " " GNUMSTRING "\n", /* Write diagonal term */ (Gnum) vlblnum, (Gnum) vlblnum) < 0) { o = 1; break; } for (edgenum = grafptr->verttax[vertnum]; edgenum < grafptr->vendtax[vertnum]; edgenum ++) { Gnum vlblend; /* End vertex label to output */ vlblend = grafptr->edgetax[edgenum]; if (grafptr->vlbltax != NULL) vlblend = grafptr->vlbltax[vlblend]; vlblend += baseadj; if (vlblend < vlblnum) { if (fprintf (filesrcptr, GNUMSTRING " " GNUMSTRING "\n", (Gnum) vlblnum, (Gnum) vlblend) < 0) { o = 1; break; } } } } if (o != 0) errorPrint ("graphGeomSaveMmkt: bad output"); return (o); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_gather_f.c0000644000175300017530000000627311631334325024137 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_gather_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the distributed source graph handling **/ /** routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 12 jul 2007 **/ /** to 12 jul 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the distributed graph handling */ /* routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFDGRAPHGATHER, scotchfdgraphgather, ( \ SCOTCH_Dgraph * const dgrfptr, \ SCOTCH_Graph * const cgrfptr, \ int * const revaptr), \ (dgrfptr, cgrfptr, revaptr)) { *revaptr = SCOTCH_dgraphGather (dgrfptr, cgrfptr); } scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_ml.h0000644000175300017530000001035111631334325022600 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_ml.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Luca SCARANO (v3.1) **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the multi-level graph bipartitio- **/ /** ning routines. **/ /** **/ /** DATES : # Version 3.1 : from : 24 oct 1995 **/ /** to 03 jul 1996 **/ /** # Version 3.2 : from : 20 sep 1996 **/ /** to 13 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 12 dec 2003 **/ /** to 20 mar 2005 **/ /** # Version 5.1 : from : 13 jul 2010 **/ /** to 13 jul 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct BgraphBipartMlParam_ { INT coarnbr; /*+ Minimum number of vertices +*/ double coarrat; /*+ Coarsening ratio +*/ GraphCoarsenType coartype; /*+ Edge matching function type +*/ Strat * stratlow; /*+ Strategy at lowest level +*/ Strat * stratasc; /*+ Strategy at ascending levels +*/ } BgraphBipartMlParam; /* ** The function prototypes. */ #ifndef BGRAPH_BIPART_ML #define static #endif static int bgraphBipartMlCoarsen (const Bgraph * const, Bgraph * restrict const, GraphCoarsenMulti * restrict * const, const BgraphBipartMlParam * const); static int bgraphBipartMlUncoarsen (Bgraph * restrict const, const Bgraph * restrict const, const GraphCoarsenMulti * const); int bgraphBipartMl (Bgraph * restrict const, const BgraphBipartMlParam * const); static int bgraphBipartMl2 (Bgraph * restrict const, const BgraphBipartMlParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/dorder_gather.h0000644000175300017530000001000011631334325022104 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dorder_gather.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the distributed ordering gathering **/ /** function. **/ /** **/ /** DATES : # Version 5.0 : from : 20 jul 2007 **/ /** to : 27 jul 2007 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to : 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Tag for MPI communications. +*/ #define DORDERGATHERNODESIZE (sizeof (DorderGatherNode) / sizeof (Gnum)) /* ** The type and structure definitions. */ /*+ This structure holds the tree definition. +*/ typedef struct DorderGatherLeaf_ { Gnum ordelocval; /*+ Starting index of inverse permutation +*/ Gnum vnodlocnbr; /*+ Number of node vertices in fragment +*/ } DorderGatherLeaf; /*+ This structure holds the separator tree structure. Because arrays of this structure is to be sent as a single contiguous array, all its fields must be of the same type. +*/ typedef struct DorderGatherNode_ { Gnum fathnum; /*+ Global number of father node +*/ Gnum typeval; /*+ Node type +*/ Gnum vnodnbr; /*+ Number of node vertices +*/ Gnum cblknum; /*+ Rank of node in father column block array +*/ } DorderGatherNode; /*+ This structure holds the separator tree structure. +*/ typedef struct DorderGatherCblk_ { Gnum cblknbr; /*+ Number of sons +*/ OrderCblk * cblktab; /*+ Pointer to sub-array +*/ } DorderGatherCblk; scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_order_tree_dist.c0000644000175300017530000000775611631334325025544 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_order_tree_dist.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted ordering distributed tree **/ /** building routine of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 5.1 : from : 30 nov 2007 **/ /** to 30 nov 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "dgraph.h" #include "dorder.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the distributed ordering */ /* handling routines. */ /* */ /************************************/ /*+ This routine returns the number of *** distributed column blocks contained *** in the given distributed ordering. *** It returns: *** - >=0 : on success. *** - <0 : on error. +*/ SCOTCH_Num SCOTCH_dgraphOrderCblkDist ( const SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ const SCOTCH_Dordering * const ordeptr) /*+ Computed ordering +*/ { return (dorderCblkDist ((Dorder *) ordeptr)); } /*+ This routine fills the given distributed *** permutation array with the permutation *** stored in the given distributed ordering. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphOrderTreeDist ( const SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ const SCOTCH_Dordering * const ordeptr, /*+ Computed ordering +*/ SCOTCH_Num * const treeglbtab, /*+ Father array +*/ SCOTCH_Num * const sizeglbtab) /*+ Size array +*/ { return (dorderTreeDist ((Dorder *) ordeptr, (Dgraph *) grafptr, treeglbtab, sizeglbtab)); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_hx.h0000644000175300017530000000645211631334325022311 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_hx.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the halo mesh block Approxi- **/ /** mate (Multiple) Minimum Degree and Fill **/ /** ordering routines. **/ /** **/ /** DATES : # Version 4.0 : from : 09 dec 2003 **/ /** to 09 dec 2003 **/ /** **/ /************************************************************/ /* ** The defines. */ #define HMESHORDERHXHASHPRIME 17 /* Prime number */ /* ** The type and structure definitions. */ /*+ A table made of such elements is used to compute the external degree of non-halo vertices. +*/ typedef struct HmeshOrderHxHash_ { Gnum vertnum; /*+ Origin vertex (i.e. pass) number +*/ Gnum vertend; /*+ End vertex number in mesh +*/ } HmeshOrderHxHash; /* ** The function prototypes. */ #ifndef HMESH_ORDER_HX #define static #endif int hmeshOrderHxFill (const Hmesh * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/graph_io_habo.h0000644000175300017530000001005311631334325022064 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_io_habo.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the Harwell-Boeing matrix **/ /** format I/O module. **/ /** **/ /** DATES : # Version 3.2 : from : 06 nov 1997 **/ /** to 06 nov 1997 **/ /** # Version 3.3 : from : 13 dec 1998 **/ /** to 15 dec 1998 **/ /** # Version 4.0 : from : 18 dec 2001 **/ /** to 19 jan 2004 **/ /** # Version 5.0 : from : 06 jun 2007 **/ /** to 06 jun 2007 **/ /** # Version 5.1 : from : 09 nov 2008 **/ /** to 09 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Prime number for hashing vertex numbers. +*/ #define GRAPHGEOMHABOHASHPRIME 7 /*+ Prime number +*/ /* ** The type and structure definitions. */ /*+ This structure holds neighbor vertex hashing data. +*/ typedef struct GraphGeomHaboHash_ { Gnum vertnum; /*+ Origin vertex (i.e. pass) number +*/ Gnum vertend; /*+ Adjacent end vertex number +*/ } GraphGeomHaboHash; /*+ This structure holds line formats for reading input data +*/ typedef struct GraphGeomHaboLine_ { int strtnbr; /*+ Number of starting blank characters +*/ int datanbr; /*+ Number of integers par line +*/ int datalen; /*+ Number of characters per integer +*/ } GraphGeomHaboLine; /* ** The function prototypes. */ #ifndef GRAPH_IO_HABO #define static #endif static int graphGeomLoadHaboFormat (GraphGeomHaboLine * restrict const, const char * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_zr.c0000644000175300017530000000641511631334325023173 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_zr.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module moves all of the vertices **/ /** to the first subdomain. **/ /** **/ /** DATES : # Version 3.3 : from : 31 may 1999 **/ /** to 31 may 1999 **/ /** # Version 4.0 : from : 19 dec 2001 **/ /** to 29 may 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VGRAPH_SEPARATE_ZR #include "module.h" #include "common.h" #include "graph.h" #include "vgraph.h" #include "vgraph_separate_zr.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine moves all of the graph vertices ** to the first part of the partition. ** It returns: ** - 0 : if the bipartitioning could be computed. ** - !0 : on error. */ int vgraphSeparateZr ( Vgraph * const grafptr) /*+ Active graph +*/ { if (grafptr->compload[0] != grafptr->s.velosum) /* If not all vertices already in part zero */ vgraphZero (grafptr); return (0); } scotch-5.1.12b.dfsg/src/libscotch/hgraph_induce.c0000644000175300017530000003554211631334325022110 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_induce.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the halo source **/ /** graph subgraph-making functions. **/ /** **/ /** DATES : # Version 4.0 : from : 02 jan 2002 **/ /** to 25 feb 2004 **/ /** # Version 5.0 : from : 19 dec 2006 **/ /** to 11 jun 2008 **/ /** # Version 5.1 : from : 24 oct 2010 **/ /** to 24 oct 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HGRAPH #define HGRAPH_INDUCE #include "module.h" #include "common.h" #include "graph.h" #include "hgraph.h" #include "hgraph_induce.h" /*********************************************/ /* */ /* These routines handle halo source graphs. */ /* */ /*********************************************/ /* This routine builds the graph induced ** by the original graph and the list of ** selected vertices. ** The induced vnumtab array is the list ** array if the original graph does not have ** a vnumtab, or the proper subset of the ** original vnumtab else. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int hgraphInduceList ( const Hgraph * restrict const orggrafptr, /* Pointer to original graph */ const VertList * restrict const orglistptr, /* Pointer to vertex list */ const Gnum orghalonbr, /* Upper bound of number of vertices in halo */ Hgraph * restrict const indgrafptr) /* Pointer to induced subgraph */ { Gnum * restrict orgindxtax; /* Original to induced vertex number translation */ Gnum * restrict indedgetab; /* Origin of induced graph edge arrays */ Gnum indvertnbr; /* Number of vertices in induced graph */ Gnum indvertnum; /* Number of current vertex in induced graph */ Gnum indvelosiz; Gnum indedgenbr; /* (Approximate) number of edges in induced graph */ Gnum indedgesiz; /* (Approximate) size of edge and edge load arrays */ memSet (indgrafptr, 0, sizeof (Hgraph)); /* Pre-initialize graph fields */ indgrafptr->s.flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; indgrafptr->s.baseval = orggrafptr->s.baseval; indvertnbr = orglistptr->vnumnbr + orghalonbr; /* Compute upper bound on number of vertices */ indvelosiz = (orggrafptr->s.velotax != NULL) ? indvertnbr : 0; if (memAllocGroup ((void **) (void *) &indgrafptr->s.verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)), &indgrafptr->vnhdtax, (size_t) ( orglistptr->vnumnbr * sizeof (Gnum)), /* Put closest to beginning of array because no padding after */ &indgrafptr->s.velotax, (size_t) ( indvertnbr * sizeof (Gnum)), &indgrafptr->s.vnumtax, (size_t) ( indvertnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("hgraphInduceList: out of memory (1)"); /* Allocate induced graph structure */ return (1); } memCpy (indgrafptr->s.vnumtax, orglistptr->vnumtab, orglistptr->vnumnbr * sizeof (Gnum)); /* Copy vertex number array from list */ indgrafptr->s.velotax = (orggrafptr->s.velotax != NULL) ? (indgrafptr->s.velotax - indgrafptr->s.baseval) : NULL; indgrafptr->s.verttax -= indgrafptr->s.baseval; indgrafptr->s.vnumtax -= indgrafptr->s.baseval; indgrafptr->vnhdtax -= indgrafptr->s.baseval; indgrafptr->vnohnbr = orglistptr->vnumnbr; indgrafptr->vnohnnd = orglistptr->vnumnbr + indgrafptr->s.baseval; indedgenbr = ((orggrafptr->s.degrmax > 0) && (indvertnbr < (orggrafptr->s.edgenbr / orggrafptr->s.degrmax))) /* Choose best upper bound on number of edges (avoid multiply overflow) */ ? (indvertnbr * orggrafptr->s.degrmax) : orggrafptr->s.edgenbr; indedgesiz = (orggrafptr->s.edlotax != NULL) ? indedgenbr * 2 : indedgenbr; /* Account for edge load array size if graph has edge weights */ if (memAllocGroup ((void **) (void *) /* If cannot allocate edge arrays with approximation */ &indedgetab, (size_t) (indedgesiz * sizeof (Gnum)), &orgindxtax, (size_t) (orggrafptr->s.vertnbr * sizeof (Gnum)), NULL) == NULL) { indedgenbr = hgraphInduce3 (orggrafptr, orglistptr); /* Count real number of edges */ indedgesiz = (orggrafptr->s.edlotax != NULL) ? indedgenbr * 2 : indedgenbr; /* Account for edge load array size if graph has edge weights */ if ((indedgenbr < 0) || /* If cannot compute real number of edges */ (memAllocGroup ((void **) (void *) /* Or cannot allocate edge arrays with real values */ &indedgetab, (size_t) (indedgesiz * sizeof (Gnum)), &orgindxtax, (size_t) (orggrafptr->s.vertnbr * sizeof (Gnum)), NULL) == NULL)) { errorPrint ("hgraphInduceList: out of memory (2)"); hgraphExit (indgrafptr); return (1); } } memSet (orgindxtax, ~0, orggrafptr->s.vertnbr * sizeof (Gnum)); /* Preset index array */ orgindxtax -= orggrafptr->s.baseval; /* Base access to orgindxtab */ for (indvertnum = indgrafptr->s.baseval; indvertnum < indgrafptr->vnohnnd; indvertnum ++) /* For all non-halo vertices */ orgindxtax[indgrafptr->s.vnumtax[indvertnum]] = indvertnum; /* Mark selected vertices */ return (hgraphInduce2 (orggrafptr, orgindxtax, indgrafptr, indedgenbr, indedgetab)); } /* This routine finalizes the building of the ** halo graph induced by the original halo graph. ** Vertices belonging to the old halo remain to ** be numbered. ** It returns: ** - 0 : on success. ** - !0 : on error. */ static int hgraphInduce2 ( const Hgraph * restrict const orggrafptr, /* Pointer to original graph */ Gnum * restrict const orgindxtax, /* Array of numbers of selected vertices */ Hgraph * restrict const indgrafptr, /* Pointer to induced graph */ const Gnum indedgenbr, /* (Approximate) number of edges in induced graph */ Gnum * restrict const indedgetab) /* Pointer to pre-allocated space for edge arrays */ { void * restrict indedgetnd; /* End of compacted edge array */ Gnum indvertnum; /* Current vertex number in induced halo graph */ indedgetnd = memOffset (indedgetab, &indgrafptr->s.edgetax, (size_t) (indedgenbr * sizeof (Gnum)), NULL); indgrafptr->s.edgetax = indedgetab - indgrafptr->s.baseval; #ifdef SCOTCH_DEBUG_HGRAPH2 if (indedgetnd > (void *) (orgindxtax + orggrafptr->s.baseval)) { errorPrint ("hgraphInduce2: invalid edge array size (1)"); hgraphExit (indgrafptr); return (1); } #endif /* SCOTCH_DEBUG_HGRAPH2 */ if (orggrafptr->s.edlotax != NULL) { size_t indedlooftval; /* Offset of edge load array with respect to edge array */ indedgetnd = memOffset (indedgetnd, &indgrafptr->s.edlotax, (size_t) (indedgenbr * sizeof (Gnum)), NULL); indgrafptr->s.edlotax -= indgrafptr->s.baseval; #ifdef SCOTCH_DEBUG_HGRAPH2 if (indedgetnd > (void *) (orgindxtax + orggrafptr->s.baseval)) { errorPrint ("hgraphInduce2: invalid edge array size (2)"); hgraphExit (indgrafptr); /* Indedgetab is now freed as part of indgrafptr */ return (1); } #endif /* SCOTCH_DEBUG_HGRAPH2 */ hgraphInduce2L (orggrafptr, orgindxtax, indgrafptr); indedlooftval = indgrafptr->s.edlotax - indgrafptr->s.edgetax; memReallocGroup ((void *) indedgetab, /* Implicitely free orgindxtab */ &indgrafptr->s.edgetax, (size_t) (indedgenbr * sizeof (Gnum)), /* Keep first offset as estimated number of edges */ &indgrafptr->s.edlotax, (size_t) (indgrafptr->s.edgenbr * sizeof (Gnum)), /* Use real number of edges for second array */ NULL); indgrafptr->s.edgetax -= indgrafptr->s.baseval; indgrafptr->s.edlotax = indgrafptr->s.edgetax + indedlooftval; /* Use old index into old array as new index */ } else { hgraphInduce2U (orggrafptr, orgindxtax, indgrafptr); indgrafptr->s.edgetax = memRealloc ((void *) indedgetab, indgrafptr->s.edgenbr * sizeof (Gnum)); /* Use real number of edges, implicitely free orgindxtab */ indgrafptr->s.edgetax -= indgrafptr->s.baseval; } indgrafptr->s.vendtax = indgrafptr->s.verttax + 1; /* Use compact representation of arrays */ indgrafptr->levlnum = orggrafptr->levlnum + 1; /* Induced subgraph is one level below */ if (orggrafptr->s.vnumtax != NULL) { /* Adjust vnumtax */ for (indvertnum = indgrafptr->s.baseval; indvertnum < indgrafptr->s.vertnnd; indvertnum ++) indgrafptr->s.vnumtax[indvertnum] = orggrafptr->s.vnumtax[indgrafptr->s.vnumtax[indvertnum]]; } #ifdef SCOTCH_DEBUG_HGRAPH2 if (hgraphCheck (indgrafptr) != 0) { /* Check graph consistency */ errorPrint ("hgraphInduce2: inconsistent graph data"); hgraphExit (indgrafptr); return (1); } #endif /* SCOTCH_DEBUG_HGRAPH2 */ return (0); } #define HGRAPHINDUCE2U #define HGRAPHINDUCE2NAME hgraphInduce2U #define HGRAPHINDUCE2EDLOINIT(e) #define HGRAPHINDUCE2EDLOSUM indgrafptr->s.edgenbr #define HGRAPHINDUCE2ENOHINIT #define HGRAPHINDUCE2ENOHSUM indgrafptr->enohnbr #include "hgraph_induce_edge.c" #undef HGRAPHINDUCE2NAME #undef HGRAPHINDUCE2EDLOINIT #undef HGRAPHINDUCE2EDLOSUM #undef HGRAPHINDUCE2ENOHINIT #undef HGRAPHINDUCE2ENOHSUM #undef HGRAPHINDUCE2U #define HGRAPHINDUCE2L #define HGRAPHINDUCE2NAME hgraphInduce2L #define HGRAPHINDUCE2EDLOINIT(e) indedlosum += indgrafptr->s.edlotax[e] = orggrafptr->s.edlotax[orgvertend] #define HGRAPHINDUCE2EDLOSUM indedlosum #define HGRAPHINDUCE2ENOHINIT indenohsum += orggrafptr->s.edlotax[orgvertend] #define HGRAPHINDUCE2ENOHSUM indenohsum #include "hgraph_induce_edge.c" #undef HGRAPHINDUCE2NAME #undef HGRAPHINDUCE2EDLOINIT #undef HGRAPHINDUCE2EDLOSUM #undef HGRAPHINDUCE2ENOHINIT #undef HGRAPHINDUCE2ENOHSUM #undef HGRAPHINDUCE2L /* This routine computes the exact number of edges ** required to build the induced halo subgraph. It ** is used when larger approximations lead to an ** out-of-memory error message. As a side effect, ** yet unnumbered halo vertices of the induced ** subgraph are numbered and the induced halo graph ** data are updated accordingly. ** It returns: ** - >=0 : number of edges in induced halo graph. ** - -1 : if out of memory (this is helpless). */ static Gnum hgraphInduce3 ( const Hgraph * restrict const orggrafptr, /* Pointer to original graph */ const VertList * restrict const orglistptr) /* Pointer to vertex list */ { Gnum indedgenbr; /* Revised number of edges in induced halo graph */ Gnum indvertnum; /* Current vertex number in induced halo graph */ Gnum * restrict orgindxtax; /* Array of numbers of selected vertices */ if ((orgindxtax = memAlloc (orggrafptr->s.vertnbr * sizeof (Gnum))) == NULL) return (-1); memSet (orgindxtax, ~0, orggrafptr->s.vertnbr * sizeof (Gnum)); /* Preset index array */ orgindxtax -= orggrafptr->s.baseval; /* Base access to orgindxtab */ for (indvertnum = 0; indvertnum < orglistptr->vnumnbr; indvertnum ++) /* For all vertices in list */ orgindxtax[orglistptr->vnumtab[indvertnum]] = indvertnum; /* Mark selected vertices */ for (indvertnum = 0, indedgenbr = 0; /* For all vertices in list */ indvertnum < orglistptr->vnumnbr; indvertnum ++) { Gnum orgvertnum; /* Current vertex number in original halo graph */ Gnum orgedgenum; /* Current edge number in original halo graph */ orgvertnum = orglistptr->vnumtab[indvertnum]; /* Get number of original vertex */ indedgenbr += orggrafptr->s.vendtax[orgvertnum] - orggrafptr->s.verttax[orgvertnum]; /* Add degree of original vertex */ for (orgedgenum = orggrafptr->s.verttax[orgvertnum]; /* For all neighbors of original halo vertex */ orgedgenum < orggrafptr->s.vendtax[orgvertnum]; orgedgenum ++) { if (orgindxtax[orggrafptr->s.edgetax[orgedgenum]] == ~0) /* If neighbor is halo vertex */ indedgenbr ++; /* Account for the arc once more */ } } memFree (orgindxtax + orggrafptr->s.baseval); return (indedgenbr); } scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_hx.h0000644000175300017530000000550211631334325022451 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_hx.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the halo graph block Approxi- **/ /** mate (Multiple) Minimum Degree and Fill **/ /** ordering routines. **/ /** **/ /** DATES : # Version 4.0 : from : 24 jan 2004 **/ /** to 24 jan 2004 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef HGRAPH_ORDER_HX #define static #endif void hgraphOrderHxFill (const Hgraph * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/dmapping.c0000644000175300017530000002536311631334325021107 0ustar hazelscthazelsct/* Copyright 2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dmapping.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Jun-Ho HER **/ /** **/ /** FUNCTION : This module handles (partial) mappings. **/ /** **/ /** DATES : # Version 5.1 : from : 31 mar 2008 **/ /** to 09 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DMAPPING #include "module.h" #include "common.h" #include "dgraph.h" #include "arch.h" #include "dmapping.h" /***********************************/ /* */ /* These routines handle mappings. */ /* */ /***********************************/ /* This routine builds a mapping. ** It returns: ** - 0 : if mapping successfully initialized. ** - !0 : on error. */ int dmapInit ( Dmapping * restrict const dmapptr, const Arch * restrict const archptr) { dmapptr->fragptr = NULL; dmapptr->fragnbr = dmapptr->vertlocmax = dmapptr->vertlocnbr = 0; dmapptr->archdat = *archptr; #ifdef SCOTCH_PTHREAD pthread_mutex_init (&dmapptr->mutelocdat, NULL); /* Initialize local mutex */ #endif /* SCOTCH_PTHREAD */ return (0); } /* This routine frees the contents of the given ** mapping. The architecture data is never freed ** as it is usually a copy of an existing Arch ** structure. ** It returns: ** - VOID : in all cases. */ void dmapExit ( Dmapping * const dmapptr) { DmappingFrag * fragptr; DmappingFrag * fragtmp; for (fragptr = dmapptr->fragptr; fragptr != NULL; fragptr = fragtmp) { memFree (fragptr->vnumtab); memFree (fragptr->parttab); memFree (fragptr->domntab); fragtmp = fragptr->nextptr; memFree (fragptr); } #ifdef SCOTCH_PTHREAD pthread_mutex_destroy (&dmapptr->mutelocdat); /* Destroy local mutex */ #endif /* SCOTCH_PTHREAD */ #ifdef SCOTCH_DEBUG_DMAP2 memSet (dmapptr, ~0, sizeof (Dmapping)); #endif /* SCOTCH_DEBUG_DMAP2 */ } /* This routine adds a fragment to the given ** distributed mapping. ** It returns: ** - void : in all cases. */ void dmapAdd ( Dmapping * restrict const dmapptr, DmappingFrag * restrict const fragptr) { #ifdef SCOTCH_PTHREAD pthread_mutex_lock (&dmapptr->mutelocdat); /* Lock local mutex */ #endif /* SCOTCH_PTHREAD */ if (dmapptr->vertlocmax < fragptr->vertnbr) dmapptr->vertlocmax = fragptr->vertnbr; dmapptr->vertlocnbr += fragptr->vertnbr; dmapptr->fragnbr ++; fragptr->nextptr = dmapptr->fragptr; /* Link fragment to mapping */ dmapptr->fragptr = fragptr; #ifdef SCOTCH_PTHREAD pthread_mutex_unlock (&dmapptr->mutelocdat); /* Unlock local mutex */ #endif /* SCOTCH_PTHREAD */ } /* This routine propagates back distributed mapping ** information to a part array associated with a ** distributed graph structure. ** It returns: ** - 0 : if partition data successfully obtained. ** - !0 : on error. */ int dmapTerm ( const Dmapping * restrict const dmapptr, const Dgraph * restrict const grafptr, Gnum * restrict const termloctab) { Gnum * restrict termloctax; int * restrict sendcnttab; int * restrict senddsptab; int * restrict recvcnttab; int * restrict recvdsptab; DmappingTermSort * restrict sortsndtab; DmappingTermSort * restrict sortrcvtab; Gnum vertlocnum; int vertrcvnbr; int vertsndnbr; int procnum; DmappingFrag * restrict fragptr; Gnum reduloctab[2]; Gnum reduglbtab[2]; reduloctab[0] = dmapptr->vertlocnbr; reduloctab[1] = 0; if (memAllocGroup ((void **) (void *) &senddsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), &sendcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), &recvdsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), &recvcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), &sortsndtab, (size_t) ((dmapptr->vertlocnbr + 1) * sizeof (DmappingTermSort)), /* "+1" for end marker */ &sortrcvtab, (size_t) (grafptr->vertlocnbr * sizeof (DmappingTermSort)), NULL) == NULL) { errorPrint ("dmapTerm: out of memory"); reduloctab[1] = 1; } if (MPI_Allreduce (reduloctab, reduglbtab, 2, GNUM_MPI, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dmapTerm: communication error (1)"); reduglbtab[1] = 1; } if (reduglbtab[1] != 0) { if (senddsptab != NULL) memFree (senddsptab); /* Free group leader */ return (1); } if (reduglbtab[0] == 0) { /* If mapping structure is empty, create an empty mapping */ memSet (termloctab, 0, grafptr->vertlocnbr * sizeof (Gnum)); memFree (senddsptab); /* Free group leader */ return (0); } if (reduglbtab[0] != grafptr->vertglbnbr) { errorPrint ("dmapTerm: invalid mapping (1)"); memFree (senddsptab); /* Free group leader */ return (1); } for (fragptr = dmapptr->fragptr, vertlocnum = 0; fragptr != NULL; fragptr = fragptr->nextptr) { Gnum fraglocnum; for (fraglocnum = 0; fraglocnum < fragptr->vertnbr; fraglocnum ++, vertlocnum ++) { #ifdef SCOTCH_DEBUG_DMAP2 if ((vertlocnum >= dmapptr->vertlocnbr) || (fragptr->parttab[fraglocnum] < 0) || (fragptr->parttab[fraglocnum] >= fragptr->domnnbr)) { errorPrint ("dmapTerm: invalid mapping (2)"); return (1); } #endif /* SCOTCH_DEBUG_DMAP2 */ sortsndtab[vertlocnum].vertnum = fragptr->vnumtab[fraglocnum]; sortsndtab[vertlocnum].termnum = (Gnum) archDomNum (&dmapptr->archdat, &fragptr->domntab[fragptr->parttab[fraglocnum]]); } } #ifdef SCOTCH_DEBUG_DMAP2 if (vertlocnum != dmapptr->vertlocnbr) { errorPrint ("dmapTerm: invalid mapping (3)"); return (1); } #endif /* SCOTCH_DEBUG_DMAP2 */ sortsndtab[vertlocnum].vertnum = /* Set end marker */ sortsndtab[vertlocnum].termnum = GNUMMAX; intSort2asc1 (sortsndtab, dmapptr->vertlocnbr); /* Sort mapping array by original vertex numbers, without marker */ for (vertlocnum = 0, procnum = 0; procnum < grafptr->procglbnbr; ) { Gnum vertsndnbr; Gnum procdspval; vertsndnbr = 0; procdspval = grafptr->procdsptab[procnum + 1]; while (sortsndtab[vertlocnum].vertnum < procdspval) { vertsndnbr ++; vertlocnum ++; #ifdef SCOTCH_DEBUG_DMAP2 if (vertlocnum > dmapptr->vertlocnbr) { /* If beyond regular indices plus end marker */ errorPrint ("dmapTerm: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DMAP2 */ } sendcnttab[procnum ++] = (int) (vertsndnbr * 2); /* Communication array for MPI, so (int), and "*2" because a Sort is 2 Gnums */ } #ifdef SCOTCH_DEBUG_DMAP2 if (vertlocnum != dmapptr->vertlocnbr) { errorPrint ("dmapTerm: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DMAP2 */ if (MPI_Alltoall (sendcnttab, 1, MPI_INT, recvcnttab, 1, MPI_INT, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dmapTerm: communication error (2)"); return (1); } for (procnum = 0, vertrcvnbr = vertsndnbr = 0; procnum < grafptr->procglbnbr; procnum ++) { /* Accumulate send and receive indices */ recvdsptab[procnum] = vertrcvnbr; vertrcvnbr += recvcnttab[procnum]; /* Accumulate "*2" values as counts */ senddsptab[procnum] = vertsndnbr; vertsndnbr += sendcnttab[procnum]; } if (MPI_Alltoallv (sortsndtab, sendcnttab, senddsptab, GNUM_MPI, sortrcvtab, recvcnttab, recvdsptab, GNUM_MPI, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dmapTerm: communication error (3)"); return (1); } memSet (termloctab, ~0, grafptr->vertlocnbr * sizeof (Gnum)); termloctax = termloctab - grafptr->procdsptab[grafptr->proclocnum]; /* Base local array through global indices */ for (vertlocnum = 0; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) { #ifdef SCOTCH_DEBUG_DMAP2 if (termloctax[sortrcvtab[vertlocnum].vertnum] != ~0) { errorPrint ("dmapTerm: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_DMAP2 */ termloctax[sortrcvtab[vertlocnum].vertnum] = sortrcvtab[vertlocnum].termnum; } #ifdef SCOTCH_DEBUG_DMAP2 for (vertlocnum = 0; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) { if (termloctab[vertlocnum] == ~0) { errorPrint ("dmapTerm: internal error (4)"); return (1); } } #endif /* SCOTCH_DEBUG_DMAP2 */ memFree (senddsptab); /* Free group leader */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_error.c0000644000175300017530000001423411631334325022160 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_error.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module provides error handling **/ /** routines to process errors generated by **/ /** the routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 3.3 : from : 02 oct 1998 **/ /** to 02 oct 1998 **/ /** # Version 3.4 : from : 01 nov 2001 **/ /** to 01 nov 2001 **/ /** # Version 5.0 : from : 06 mar 2008 **/ /** to 24 may 2008 **/ /** # Version 5.1 : from : 27 sep 2008 **/ /** to 17 jul 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY_ERROR #include "module.h" #include "common.h" #include "scotch.h" /********************************/ /* */ /* The error handling routines. */ /* */ /********************************/ static char _SCOTCHerrorProgName[32] = ""; /* This routine sets the program name for ** error reporting. ** It returns: ** - VOID : in all cases. */ void SCOTCH_errorProg ( const char * const progstr) /*+ Program name +*/ { int charnbr; const char * nsrcptr; char * ndstptr; nsrcptr = progstr; ndstptr = _SCOTCHerrorProgName; charnbr = strlen (progstr); if (charnbr > 31) { _SCOTCHerrorProgName[0] = _SCOTCHerrorProgName[1] = _SCOTCHerrorProgName[2] = '.'; ndstptr += 3; nsrcptr += charnbr - 28; charnbr = 28; } strncpy (ndstptr, nsrcptr, charnbr); _SCOTCHerrorProgName[31] = '\0'; } /* This routine prints an error message with ** a variable number of arguments, as printf () ** does, and exits. ** It returns: ** - void : in all cases. */ void SCOTCH_errorPrint ( const char * const errstr, /*+ printf-like variable argument list */ ...) { va_list errlist; /* The argument list of the call */ #ifdef SCOTCH_PTSCOTCH int proclocnum; #endif /* SCOTCH_PTSCOTCH */ fprintf (stderr, "%s", _SCOTCHerrorProgName); #ifdef SCOTCH_PTSCOTCH if ((MPI_Initialized (&proclocnum) == MPI_SUCCESS) && (proclocnum != 0) && (MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum) == MPI_SUCCESS)) fprintf (stderr, "(%d): ", proclocnum); else fprintf (stderr, ": "); #else /* SCOTCH_PTSCOTCH */ if (_SCOTCHerrorProgName[0] != '\0') fprintf (stderr, ": "); #endif /* SCOTCH_PTSCOTCH */ fprintf (stderr, "ERROR: "); va_start (errlist, errstr); vfprintf (stderr, errstr, errlist); /* Print arguments */ va_end (errlist); fprintf (stderr, "\n"); fflush (stderr); /* In case it has been set to buffered mode */ } /* This routine prints a warning message with ** a variable number of arguments, as printf () ** does. ** It returns: ** - VOID : in all cases. */ void SCOTCH_errorPrintW ( const char * const errstr, /*+ printf-like variable argument list */ ...) { va_list errlist; /* The argument list of the call */ #ifdef SCOTCH_PTSCOTCH int proclocnum; #endif /* SCOTCH_PTSCOTCH */ fprintf (stderr, "%s", _SCOTCHerrorProgName); #ifdef SCOTCH_PTSCOTCH if ((MPI_Initialized (&proclocnum) == MPI_SUCCESS) && (proclocnum != 0) && (MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum) == MPI_SUCCESS)) fprintf (stderr, "(%d): ", proclocnum); else fprintf (stderr, ": "); #else /* SCOTCH_PTSCOTCH */ if (_SCOTCHerrorProgName[0] != '\0') fprintf (stderr, ": "); #endif /* SCOTCH_PTSCOTCH */ fprintf (stderr, "WARNING: "); va_start (errlist, errstr); vfprintf (stderr, errstr, errlist); /* Print arguments */ va_end (errlist); fprintf (stderr, "\n"); fflush (stderr); /* In case it has been set to buffered mode */ } scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_st.c0000644000175300017530000004474211631334325022624 0ustar hazelscthazelsct/* Copyright 2004,2007,2009-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_st.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the strategy and **/ /** method tables for graph bipartitioning **/ /** methods. **/ /** **/ /** DATES : # Version 3.2 : from : 08 oct 1996 **/ /** to 13 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 12 mar 1999 **/ /** # Version 3.4 : from : 01 jun 2001 **/ /** to 01 jun 2001 **/ /** # Version 4.0 : from : 12 jan 2004 **/ /** to 20 aug 2004 **/ /** # Version 5.0 : from : 27 nov 2006 **/ /** to 29 may 2007 **/ /** # Version 5.1 : from : 26 oct 2009 **/ /** to 15 apr 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BGRAPH_BIPART_ST #include "module.h" #include "common.h" #include "gain.h" #include "parser.h" #include "graph.h" #include "graph_coarsen.h" #include "arch.h" #include "bgraph.h" #include "bgraph_bipart_bd.h" #include "bgraph_bipart_df.h" #include "bgraph_bipart_ex.h" #include "bgraph_bipart_fm.h" #include "bgraph_bipart_gg.h" #include "bgraph_bipart_gp.h" #include "bgraph_bipart_ml.h" #include "bgraph_bipart_zr.h" #include "bgraph_bipart_st.h" /* ** The static and global variables. */ static Bgraph bgraphdummy; /*+ Dummy active graph for offset computations +*/ static union { BgraphBipartBdParam param; StratNodeMethodData padding; } bgraphbipartstdefaultbd = { { 3, &stratdummy } }; static union { BgraphBipartDfParam param; StratNodeMethodData padding; } bgraphbipartstdefaultdf = { { 40, 1.0, 0.0, BGRAPHBIPARTDFTYPEBAL } }; static union { /* Default parameters for bipartitioning methods */ BgraphBipartFmParam param; /* Parameter zone */ StratNodeMethodData padding; /* To avoid reading out of structure */ } bgraphbipartstdefaultfm = { { 80, ~0, 0.01L } }; static union { BgraphBipartGgParam param; StratNodeMethodData padding; } bgraphbipartstdefaultgg = { { 5 } }; static union { BgraphBipartGpParam param; StratNodeMethodData padding; } bgraphbipartstdefaultgp = { { 5 } }; static union { BgraphBipartMlParam param; StratNodeMethodData padding; } bgraphbipartstdefaultml = { { 100, 0.8L, GRAPHCOARHEM, &stratdummy, &stratdummy } }; static StratMethodTab bgraphbipartstmethtab[] = { /* Bipartitioning methods array */ { BGRAPHBIPARTSTMETHBD, "b", bgraphBipartBd, &bgraphbipartstdefaultbd }, { BGRAPHBIPARTSTMETHDF, "d", bgraphBipartDf, &bgraphbipartstdefaultdf }, { BGRAPHBIPARTSTMETHEX, "x", bgraphBipartEx, NULL }, { BGRAPHBIPARTSTMETHFM, "f", bgraphBipartFm, &bgraphbipartstdefaultfm }, { BGRAPHBIPARTSTMETHGG, "h", bgraphBipartGg, &bgraphbipartstdefaultgg }, { BGRAPHBIPARTSTMETHGP, "g", bgraphBipartGp, &bgraphbipartstdefaultgp }, { BGRAPHBIPARTSTMETHML, "m", bgraphBipartMl, &bgraphbipartstdefaultml }, { BGRAPHBIPARTSTMETHZR, "z", bgraphBipartZr, NULL }, { -1, NULL, NULL, NULL } }; static StratParamTab bgraphbipartstparatab[] = { /* Method parameter list */ { BGRAPHBIPARTSTMETHBD, STRATPARAMSTRAT, "bnd", (byte *) &bgraphbipartstdefaultbd.param, (byte *) &bgraphbipartstdefaultbd.param.stratbnd, (void *) &bgraphbipartststratab }, { BGRAPHBIPARTSTMETHBD, STRATPARAMSTRAT, "org", (byte *) &bgraphbipartstdefaultbd.param, (byte *) &bgraphbipartstdefaultbd.param.stratorg, (void *) &bgraphbipartststratab }, { BGRAPHBIPARTSTMETHBD, STRATPARAMINT, "width", (byte *) &bgraphbipartstdefaultbd.param, (byte *) &bgraphbipartstdefaultbd.param.distmax, NULL }, { BGRAPHBIPARTSTMETHDF, STRATPARAMINT, "pass", (byte *) &bgraphbipartstdefaultdf.param, (byte *) &bgraphbipartstdefaultdf.param.passnbr, NULL }, { BGRAPHBIPARTSTMETHDF, STRATPARAMDOUBLE, "dif", (byte *) &bgraphbipartstdefaultdf.param, (byte *) &bgraphbipartstdefaultdf.param.cdifval, NULL }, { BGRAPHBIPARTSTMETHDF, STRATPARAMDOUBLE, "rem", (byte *) &bgraphbipartstdefaultdf.param, (byte *) &bgraphbipartstdefaultdf.param.cremval, NULL }, { BGRAPHBIPARTSTMETHDF, STRATPARAMCASE, "type", (byte *) &bgraphbipartstdefaultdf.param, (byte *) &bgraphbipartstdefaultdf.param.typeval, (void *) "bk" }, { BGRAPHBIPARTSTMETHFM, STRATPARAMINT, "move", (byte *) &bgraphbipartstdefaultfm.param, (byte *) &bgraphbipartstdefaultfm.param.movenbr, NULL }, { BGRAPHBIPARTSTMETHFM, STRATPARAMINT, "pass", (byte *) &bgraphbipartstdefaultfm.param, (byte *) &bgraphbipartstdefaultfm.param.passnbr, NULL }, { BGRAPHBIPARTSTMETHFM, STRATPARAMDOUBLE, "bal", (byte *) &bgraphbipartstdefaultfm.param, (byte *) &bgraphbipartstdefaultfm.param.deltval, NULL }, { BGRAPHBIPARTSTMETHGG, STRATPARAMINT, "pass", (byte *) &bgraphbipartstdefaultgg.param, (byte *) &bgraphbipartstdefaultgg.param.passnbr, NULL }, { BGRAPHBIPARTSTMETHML, STRATPARAMSTRAT, "asc", (byte *) &bgraphbipartstdefaultml.param, (byte *) &bgraphbipartstdefaultml.param.stratasc, (void *) &bgraphbipartststratab }, { BGRAPHBIPARTSTMETHML, STRATPARAMSTRAT, "low", (byte *) &bgraphbipartstdefaultml.param, (byte *) &bgraphbipartstdefaultml.param.stratlow, (void *) &bgraphbipartststratab }, { BGRAPHBIPARTSTMETHML, STRATPARAMCASE, "type", (byte *) &bgraphbipartstdefaultml.param, (byte *) &bgraphbipartstdefaultml.param.coartype, (void *) "hscd" }, { BGRAPHBIPARTSTMETHML, STRATPARAMINT, "vert", (byte *) &bgraphbipartstdefaultml.param, (byte *) &bgraphbipartstdefaultml.param.coarnbr, NULL }, { BGRAPHBIPARTSTMETHML, STRATPARAMDOUBLE, "rat", (byte *) &bgraphbipartstdefaultml.param, (byte *) &bgraphbipartstdefaultml.param.coarrat, NULL }, { BGRAPHBIPARTSTMETHNBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; static StratParamTab bgraphbipartstcondtab[] = { /* Active graph condition parameter table */ { STRATNODECOND, STRATPARAMINT, "load", (byte *) &bgraphdummy, (byte *) &bgraphdummy.s.velosum, NULL }, { STRATNODECOND, STRATPARAMINT, "load0", (byte *) &bgraphdummy, (byte *) &bgraphdummy.compload0, NULL }, { STRATNODECOND, STRATPARAMINT, "lmin0", (byte *) &bgraphdummy, (byte *) &bgraphdummy.compload0min, NULL }, { STRATNODECOND, STRATPARAMINT, "lmax0", (byte *) &bgraphdummy, (byte *) &bgraphdummy.compload0max, NULL }, { STRATNODECOND, STRATPARAMINT, "edge", (byte *) &bgraphdummy, (byte *) &bgraphdummy.s.edgenbr, NULL }, { STRATNODECOND, STRATPARAMINT, "vert", (byte *) &bgraphdummy, (byte *) &bgraphdummy.s.vertnbr, NULL }, { STRATNODECOND, STRATPARAMINT, "levl", (byte *) &bgraphdummy, (byte *) &bgraphdummy.levlnum, NULL }, { STRATNODENBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; StratTab bgraphbipartststratab = { /* Strategy tables for graph bipartitioning methods */ bgraphbipartstmethtab, bgraphbipartstparatab, bgraphbipartstcondtab }; /***********************************************/ /* */ /* This is the generic bipartitioning routine. */ /* */ /***********************************************/ /* This routine performs the bipartitioning of ** the given active graph according to the ** given strategy. ** It returns: ** - 0 : if bipartitioning could be computed. ** - 1 : on error. */ int bgraphBipartSt ( Bgraph * restrict const grafptr, /*+ Active graph to bipartition +*/ const Strat * restrict const strat) /*+ Bipartitioning strategy +*/ { StratTest val; /* Result of condition evaluation */ BgraphStore savetab[2]; /* Results of the two strategies */ int o; int o2; #ifdef SCOTCH_DEBUG_BGRAPH2 if (sizeof (Gnum) != sizeof (INT)) { errorPrint ("bgraphBipartSt: invalid type specification for parser variables"); return (1); } if ((sizeof (BgraphBipartFmParam) > sizeof (StratNodeMethodData)) || (sizeof (BgraphBipartGgParam) > sizeof (StratNodeMethodData)) || (sizeof (BgraphBipartMlParam) > sizeof (StratNodeMethodData))) { errorPrint ("bgraphBipartSt: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ #ifdef SCOTCH_DEBUG_BGRAPH1 if (strat->tabl != &bgraphbipartststratab) { errorPrint ("bgraphBipartSt: invalid parameter (1)"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH1 */ o = 0; switch (strat->type) { case STRATNODECONCAT : o = bgraphBipartSt (grafptr, strat->data.concat.strat[0]); /* Apply the first strategy */ if (o == 0) /* If it worked all right */ o |= bgraphBipartSt (grafptr, strat->data.concat.strat[1]); /* Then apply second strategy */ break; case STRATNODECOND : o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ if (o == 0) { /* If evaluation was correct */ #ifdef SCOTCH_DEBUG_VGRAPH2 if ((val.typetest != STRATTESTVAL) || (val.typenode != STRATPARAMLOG)) { errorPrint ("bgraphBipartSt: invalid test result"); o = 1; break; } #endif /* SCOTCH_DEBUG_VGRAPH2 */ if (val.data.val.vallog == 1) /* If expression is true */ o = bgraphBipartSt (grafptr, strat->data.cond.strat[0]); /* Apply first strategy */ else { /* Else if expression is false */ if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ o = bgraphBipartSt (grafptr, strat->data.cond.strat[1]); /* Apply second strategy */ } } break; case STRATNODEEMPTY : break; case STRATNODESELECT : if (((bgraphStoreInit (grafptr, &savetab[0])) != 0) || /* Allocate save areas */ ((bgraphStoreInit (grafptr, &savetab[1])) != 0)) { errorPrint ("bgraphBipartSt: out of memory"); bgraphStoreExit (&savetab[0]); return (1); } bgraphStoreSave (grafptr, &savetab[1]); /* Save initial bipartition */ o = bgraphBipartSt (grafptr, strat->data.select.strat[0]); /* Apply first strategy */ bgraphStoreSave (grafptr, &savetab[0]); /* Save its result */ bgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition */ o2 = bgraphBipartSt (grafptr, strat->data.select.strat[1]); /* Apply second strategy */ if ((o == 0) || (o2 == 0)) { /* If at least one method did bipartition */ Gnum compload0; int b0; int b1; compload0 = grafptr->compload0avg + savetab[0].compload0dlt; b0 = ((compload0 < grafptr->compload0min) || (compload0 > grafptr->compload0max)) ? 1 : o; compload0 = grafptr->compload0avg + savetab[1].compload0dlt; b1 = ((compload0 < grafptr->compload0min) || (compload0 > grafptr->compload0max)) ? 1 : o2; do { /* Do we want to restore partition 0 ? */ if (b0 > b1) break; if (b0 == b1) { /* If both are valid or invalid */ if (b0 == 0) { /* If both are valid */ if ( (savetab[0].commload > grafptr->commload) || /* Compare on cut */ ((savetab[0].commload == grafptr->commload) && (abs (savetab[0].compload0dlt) > abs (grafptr->compload0dlt)))) break; } else { /* If both are invalid */ if ( (abs (savetab[0].compload0dlt) > abs (grafptr->compload0dlt)) || /* Compare on imbalance */ ((abs (savetab[0].compload0dlt) == abs (grafptr->compload0dlt)) && (savetab[0].commload > grafptr->commload))) break; } } bgraphStoreUpdt (grafptr, &savetab[0]); /* Restore its result */ } while (0); } if (o2 < o) /* o = min(o,o2): if one biparts, then bipart */ o = o2; /* Else if one stops, then stop, else error */ bgraphStoreExit (&savetab[0]); /* Free both save areas */ bgraphStoreExit (&savetab[1]); break; #ifdef SCOTCH_DEBUG_BGRAPH2 case STRATNODEMETHOD : #else /* SCOTCH_DEBUG_BGRAPH2 */ default : #endif /* SCOTCH_DEBUG_BGRAPH2 */ return (strat->tabl->methtab[strat->data.method.meth].func (grafptr, (void *) &strat->data.method.data)); #ifdef SCOTCH_DEBUG_BGRAPH2 default : errorPrint ("bgraphBipartSt: invalid parameter (2)"); return (1); #endif /* SCOTCH_DEBUG_BGRAPH2 */ } return (o); } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_zr.h0000644000175300017530000000540211631334325023173 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_zr.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the move-all-to-first-subdomain **/ /** separation method. **/ /** **/ /** DATES : # Version 3.3 : from : 31 may 1999 **/ /** to 31 may 1999 **/ /** # Version 4.0 : from : 19 dec 2001 **/ /** to 01 jan 2002 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef VGRAPH_SEPARATE_ZR #define static #endif int vgraphSeparateZr (Vgraph * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_cp.h0000644000175300017530000001007211631334325022265 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_cp.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the mesh compression algorithm. **/ /** **/ /** DATES : # Version 4.0 : from : 08 feb 2004 **/ /** to 08 feb 2004 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines. */ /** Prime number for hashing vertex numbers. **/ #define HMESHORDERCPHASHPRIME 17 /* Prime number */ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HmeshOrderCpParam_ { double comprat; /*+ Compression ratio threshold +*/ Strat * stratcpr; /*+ Compressed submesh ordering strategy +*/ Strat * stratunc; /*+ Uncompressed submesh ordering strategy +*/ } HmeshOrderCpParam; /*+ This structure holds fine neighbor hashing data. +*/ typedef struct HmeshOrderCpHash_ { Gnum vnodnum; /*+ Origin node vertex (i.e. pass) number +*/ Gnum velmnum; /*+ Adjacent end element vertex number +*/ } HmeshOrderCpHash; /*+ This structure holds coarse neighbor mate data. +*/ typedef struct HgraphOrderCpMate_ { Gnum coarvertend; /*+ Adjacent coarse end vertex number +*/ Gnum finevertend; /*+ Adjacent end vertex number +*/ } HgraphOrderCpMate; /* ** The function prototypes. */ #ifndef HMESH_ORDER_CP #define static #endif int hmeshOrderCp (const Hmesh * const, Order * const, const Gnum, OrderCblk * const, const HmeshOrderCpParam * const); static Gnum hmeshOrderCpTree (const Gnum * const, const Gnum * const, OrderCblk * const, Gnum); #undef static scotch-5.1.12b.dfsg/src/libscotch/hall_order_hd.h0000644000175300017530000000574111631334325022101 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hall_order_hd.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the block-oriented Halo **/ /** Approximate (Multiple) Minimum Degree **/ /** ordering routine. **/ /** **/ /** DATES : # Version 3.4 : from : 15 may 2001 **/ /** to : 15 may 2001 **/ /** # Version 4.0 : from : 10 jan 2003 **/ /** to : 10 dec 2003 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef HALL_ORDER_HD #define static #endif void hallOrderHdHalmd (Gnum n, Gnum nbelts, Gnum iwlen, Gnum pe[], Gnum pfree, Gnum len[], Gnum iw[], Gnum nv[], Gnum elen[], Gnum last[], Gnum * ncmpa, Gnum degree[], Gnum head[], Gnum next[], Gnum w[]); #undef static scotch-5.1.12b.dfsg/src/libscotch/arch_hcub.c0000644000175300017530000002275111631334325021224 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_hcub.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the hypercube **/ /** target architecture. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 23 dec 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 29 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 08 sep 1995 **/ /** # Version 3.1 : from : 11 jun 1996 **/ /** to 11 jun 1996 **/ /** # Version 3.2 : from : 21 sep 1996 **/ /** to 14 may 1998 **/ /** # Version 4.0 : from : 11 nov 2003 **/ /** to 10 mar 2005 **/ /** # Version 5.1 : from : 21 jan 2008 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ARCH_HCUB #include "module.h" #include "common.h" #include "arch.h" #include "arch_hcub.h" /********************************************/ /* */ /* These are the binary hypercube routines. */ /* */ /********************************************/ /* This routine loads the binary ** hypercube architecture. ** It returns: ** - 0 : if the architecture has been successfully read. ** - !0 : on error. */ int archHcubArchLoad ( ArchHcub * restrict const archptr, FILE * restrict const stream) { #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchHcub) > sizeof (ArchDummy)) || (sizeof (ArchHcubDom) > sizeof (ArchDomDummy))) { errorPrint ("archHcubArchLoad: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if ((intLoad (stream, &archptr->dimmax) != 1) || (archptr->dimmax < 1) || (archptr->dimmax > (sizeof (archptr->dimmax) << 3))) { errorPrint ("archHcubArchLoad: bad input"); return (1); } return (0); } /* This routine saves the ** binary hypercube architecture. ** It returns: ** - 0 : if the architecture has been successfully written. ** - !0 : on error. */ int archHcubArchSave ( const ArchHcub * const archptr, FILE * restrict const stream) { #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchHcub) > sizeof (ArchDummy)) || (sizeof (ArchHcubDom) > sizeof (ArchDomDummy))) { errorPrint ("archHcubArchSave: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if (fprintf (stream, ANUMSTRING " ", (Anum) archptr->dimmax) == EOF) { errorPrint ("archHcubArchSave: bad output"); return (1); } return (0); } /* This function returns the smallest number ** of terminal domain included in the given ** domain. */ ArchDomNum archHcubDomNum ( const ArchHcub * const archptr, const ArchHcubDom * const domptr) { return (domptr->bitset); /* Return vertex number */ } /* This function returns the terminal domain associated ** with the given terminal number in the architecture. ** It returns: ** - 0 : if label is valid and domain has been updated. ** - 1 : if label is invalid. ** - 2 : on error. */ int archHcubDomTerm ( const ArchHcub * const archptr, ArchHcubDom * const domptr, const ArchDomNum domnum) { if (domnum < (1 << archptr->dimmax)) { /* If valid label */ domptr->dimcur = 0; /* Set the domain */ domptr->bitset = domnum; return (0); } return (1); /* Cannot set domain */ } /* This function returns the number of ** elements in the hypercube domain. */ Anum archHcubDomSize ( const ArchHcub * const archptr, const ArchHcubDom * const domptr) { return (1 << domptr->dimcur); } /* This function returns the average distance ** between two sub-hypercubes. */ Anum archHcubDomDist ( const ArchHcub * const archptr, const ArchHcubDom * const dom0ptr, const ArchHcubDom * const dom1ptr) { Anum i, j, k; if (dom0ptr->dimcur > dom1ptr->dimcur) { /* Get smallest set dimension value */ i = dom0ptr->dimcur; j = i - dom1ptr->dimcur; } else { i = dom1ptr->dimcur; j = i - dom0ptr->dimcur; } j /= 2; /* For set/unset bits, assume 1/2 difference */ for (k = (dom0ptr->bitset ^ dom1ptr->bitset) >> i, i = archptr->dimmax - i; i > 0; k >>= 1, i --) j += (k & 1); /* Add Hamming difference on set dimensions */ return (j); } /* This function sets the biggest ** domain available for this ** architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archHcubDomFrst ( const ArchHcub * const archptr, ArchHcubDom * restrict const domptr) { domptr->dimcur = archptr->dimmax; domptr->bitset = 0; return (0); } /* This routine reads domain information ** from the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archHcubDomLoad ( const ArchHcub * const archptr, ArchHcubDom * restrict const domptr, FILE * restrict const stream) { if ((intLoad (stream, &domptr->dimcur) != 1) || (intLoad (stream, &domptr->bitset) != 1) || (domptr->dimcur > archptr->dimmax)) { errorPrint ("archHcubDomLoad: bad input"); return (1); } return (0); } /* This routine saves domain information ** to the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archHcubDomSave ( const ArchHcub * const archptr, const ArchHcubDom * const domptr, FILE * restrict const stream) { if (fprintf (stream, ANUMSTRING " " ANUMSTRING " ", (Anum) domptr->dimcur, (Anum) domptr->bitset) == EOF) { errorPrint ("archHcubDomSave: bad output"); return (1); } return (0); } /* This function tries to split a hypercube ** domain into two subdomains. ** It returns: ** - 0 : if bipartitioning succeeded. ** - 1 : if bipartitioning could not be performed. ** - 2 : on error. */ int archHcubDomBipart ( const ArchHcub * const archptr, const ArchHcubDom * const domptr, ArchHcubDom * restrict const dom0ptr, ArchHcubDom * restrict const dom1ptr) { if (domptr->dimcur <= 0) /* Return if cannot bipartition more */ return (1); dom0ptr->dimcur = dom1ptr->dimcur = domptr->dimcur - 1; dom0ptr->bitset = domptr->bitset; dom1ptr->bitset = domptr->bitset | (1 << dom1ptr->dimcur); return (0); } /* This function creates the MPI_Datatype for ** hypercube domains. ** It returns: ** - 0 : if type could be created. ** - 1 : on error. */ #ifdef SCOTCH_PTSCOTCH int archHcubDomMpiType ( const ArchHcub * const archptr, MPI_Datatype * const typeptr) { MPI_Type_contiguous (2, ANUM_MPI, typeptr); return (0); } #endif /* SCOTCH_PTSCOTCH */ scotch-5.1.12b.dfsg/src/libscotch/library_graph_map.c0000644000175300017530000003447311631334325022774 0ustar hazelscthazelsct/* Copyright 2004,2007-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_map.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the mapping **/ /** routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 3.2 : from : 19 aug 1998 **/ /** to 20 aug 1998 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to 30 mar 1999 **/ /** # Version 3.4 : from : 01 nov 2001 **/ /** to 01 nov 2001 **/ /** # Version 4.0 : from : 13 jan 2004 **/ /** to 13 nov 2005 **/ /** # Version 5.1 : from : 29 oct 2007 **/ /** to 24 jul 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "arch.h" #include "mapping.h" #include "kgraph.h" #include "kgraph_map_st.h" #include "library_mapping.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the mapping routines. */ /* */ /************************************/ /*+ This routine initializes an API opaque *** mapping with respect to the given source *** graph and the locations of output parameters. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphMapInit ( const SCOTCH_Graph * const grafptr, /*+ Graph to map +*/ SCOTCH_Mapping * const mappptr, /*+ Mapping structure to initialize +*/ const SCOTCH_Arch * const archptr, /*+ Target architecture used to map +*/ SCOTCH_Num * const parttab) /*+ Mapping array +*/ { LibMapping * restrict srcmappptr; #ifdef SCOTCH_DEBUG_LIBRARY1 if (sizeof (SCOTCH_Mapping) < sizeof (LibMapping)) { errorPrint ("SCOTCH_graphMapInit: internal error"); return (1); } #endif /* SCOTCH_DEBUG_LIBRARY1 */ srcmappptr = (LibMapping *) mappptr; srcmappptr->parttax = (parttab != NULL) ? (parttab - ((Graph *) grafptr)->baseval) : parttab; return (mapInit (&srcmappptr->m, ((Graph *) grafptr)->baseval, ((Graph *) grafptr)->vertnbr, (Arch *) archptr)); } /*+ This routine frees an API mapping. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_graphMapExit ( const SCOTCH_Graph * const grafptr, SCOTCH_Mapping * const mappptr) { mapExit (&((LibMapping *) mappptr)->m); } /*+ This routine saves the contents of *** the given mapping to the given stream. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphMapLoad ( const SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ const SCOTCH_Mapping * const mappptr, /*+ Mapping to save +*/ FILE * const stream) /*+ Output stream +*/ { LibMapping * restrict lmapptr; int o; lmapptr = (LibMapping *) mappptr; if ((o = mapLoad (&lmapptr->m, ((Graph *) grafptr)->vlbltax, stream)) != 0) return (o); if (lmapptr->parttax != NULL) { /* Propagate mapping data to user partition array */ Gnum vertnum; Gnum vertnnd; for (vertnum = lmapptr->m.baseval, vertnnd = vertnum + lmapptr->m.vertnbr; vertnum < vertnnd; vertnum ++) lmapptr->parttax[vertnum] = archDomNum (&lmapptr->m.archdat, &lmapptr->m.domntab[lmapptr->m.parttax[vertnum]]); } return (0); } /*+ This routine saves the contents of *** the given mapping to the given stream. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphMapSave ( const SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ const SCOTCH_Mapping * const mappptr, /*+ Mapping to save +*/ FILE * const stream) /*+ Output stream +*/ { return (mapSave (&((LibMapping *) mappptr)->m, ((Graph *) grafptr)->vlbltax, stream)); } /*+ This routine computes a mapping *** of the API mapping structure with *** respect to the given strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphMapCompute ( SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ SCOTCH_Mapping * const mappptr, /*+ Mapping to compute +*/ SCOTCH_Strat * const stratptr) /*+ Mapping strategy +*/ { Kgraph mapgrafdat; /* Effective mapping graph */ const Strat * mapstratptr; /* Pointer to mapping strategy */ LibMapping * restrict lmapptr; int o; #ifdef SCOTCH_DEBUG_GRAPH2 if (graphCheck ((Graph *) grafptr) != 0) { errorPrint ("SCOTCH_graphMapCompute: invalid input graph"); return (1); } #endif /* SCOTCH_DEBUG_GRAPH2 */ lmapptr = (LibMapping *) mappptr; if (*((Strat **) stratptr) == NULL) { /* Set default mapping strategy if necessary */ ArchDom archdomnorg; archDomFrst (&lmapptr->m.archdat, &archdomnorg); if (archVar (&lmapptr->m.archdat)) SCOTCH_stratGraphClusterBuild (stratptr, 0, 1, 0.0, 0.05); else SCOTCH_stratGraphMapBuild (stratptr, 0, archDomSize (&lmapptr->m.archdat, &archdomnorg), 0.05); } mapstratptr = *((Strat **) stratptr); if (mapstratptr->tabl != &kgraphmapststratab) { errorPrint ("SCOTCH_graphMapCompute: not a graph mapping strategy"); return (1); } if (kgraphInit (&mapgrafdat, (Graph *) grafptr, &lmapptr->m) != 0) return (1); o = kgraphMapSt (&mapgrafdat, mapstratptr); /* Perform mapping */ lmapptr->m.domnmax = mapgrafdat.m.domnmax; /* Do not free the mapping, as it has been cloned */ lmapptr->m.domnnbr = mapgrafdat.m.domnnbr; lmapptr->m.domntab = mapgrafdat.m.domntab; /* Update pointer to domntab in case it has changed */ mapgrafdat.m.parttax = NULL; /* Prevent mapping arrays from being freed by graph */ mapgrafdat.m.domntab = NULL; kgraphExit (&mapgrafdat); if (lmapptr->parttax != NULL) { /* Propagate mapping data to user partition array */ Gnum vertnum; Gnum vertnnd; for (vertnum = lmapptr->m.baseval, vertnnd = vertnum + lmapptr->m.vertnbr; vertnum < vertnnd; vertnum ++) lmapptr->parttax[vertnum] = archDomNum (&lmapptr->m.archdat, &lmapptr->m.domntab[lmapptr->m.parttax[vertnum]]); } return (o); } /*+ This routine computes a mapping of the *** given graph structure onto the given *** target architecture with respect to the *** given strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphMap ( SCOTCH_Graph * const grafptr, /*+ Graph to map +*/ const SCOTCH_Arch * const archptr, /*+ Target architecture +*/ SCOTCH_Strat * const stratptr, /*+ Mapping strategy +*/ SCOTCH_Num * const maptab) /*+ Mapping array +*/ { SCOTCH_Mapping mapdat; int o; SCOTCH_graphMapInit (grafptr, &mapdat, archptr, maptab); o = SCOTCH_graphMapCompute (grafptr, &mapdat, stratptr); SCOTCH_graphMapExit (grafptr, &mapdat); return (o); } /*+ This routine computes a partition of *** the given graph structure with respect *** to the given strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphPart ( SCOTCH_Graph * const grafptr, /*+ Graph to map +*/ const SCOTCH_Num partnbr, /*+ Number of parts +*/ SCOTCH_Strat * const stratptr, /*+ Mapping strategy +*/ SCOTCH_Num * const maptab) /*+ Mapping array +*/ { SCOTCH_Arch archdat; int o; SCOTCH_archInit (&archdat); SCOTCH_archCmplt (&archdat, partnbr); o = SCOTCH_graphMap (grafptr, &archdat, stratptr, maptab); SCOTCH_archExit (&archdat); return (o); } /*+ This routine parses the given *** mapping strategy. *** It returns: *** - 0 : if string successfully scanned. *** - !0 : on error. +*/ int SCOTCH_stratGraphMap ( SCOTCH_Strat * const stratptr, const char * const string) { if (*((Strat **) stratptr) != NULL) stratExit (*((Strat **) stratptr)); if ((*((Strat **) stratptr) = stratInit (&kgraphmapststratab, string)) == NULL) { errorPrint ("SCOTCH_stratGraphMap: error in mapping strategy"); return (1); } return (0); } /*+ This routine provides predefined static *** mapping strategies. *** It returns: *** - 0 : if string successfully initialized. *** - !0 : on error. +*/ int SCOTCH_stratGraphMapBuild ( SCOTCH_Strat * const stratptr, /*+ Strategy to create +*/ const SCOTCH_Num flagval, /*+ Desired characteristics +*/ const SCOTCH_Num partnbr, /*+ Number of expected parts +*/ const double kbalval) /*+ Desired imbalance ratio +*/ { char bufftab[8192]; /* Should be enough */ char kbaltab[32]; char bbaltab[32]; char * difsptr; char * exasptr; sprintf (kbaltab, "%lf", kbalval); sprintf (bbaltab, "%lf", kbalval); strcpy (bufftab, "r{job=t,map=t,poli=S,bal=,sep=(m{type=h,vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}})}"); stringSubst (bufftab, "", ((flagval & SCOTCH_STRATSPEED) != 0) ? "" : "m{type=h,vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}}|"); if ((flagval & SCOTCH_STRATBALANCE) != 0) exasptr = "f{bal=0}"; else exasptr = ""; if ((flagval & SCOTCH_STRATSAFETY) != 0) difsptr = ""; else difsptr = "(d{dif=1,rem=0,pass=40}|)"; stringSubst (bufftab, "", exasptr); stringSubst (bufftab, "", difsptr); stringSubst (bufftab, "", kbaltab); stringSubst (bufftab, "", kbaltab); if (SCOTCH_stratGraphMap (stratptr, bufftab) != 0) { errorPrint ("SCOTCH_stratGraphMapBuild: error in sequential mapping strategy"); return (1); } return (0); } /*+ This routine provides predefined *** clustering strategies. *** It returns: *** - 0 : if string successfully initialized. *** - !0 : on error. +*/ SCOTCH_stratGraphClusterBuild ( SCOTCH_Strat * const stratptr, /*+ Strategy to create +*/ const SCOTCH_Num flagval, /*+ Desired characteristics +*/ const SCOTCH_Num pwgtval, /*+ Threshold part weight +*/ const double densval, /*+ Threshold density value +*/ const double bbalval) /*+ Maximum imbalance ratio +*/ { char bufftab[8192]; /* Should be enough */ char bbaltab[32]; char pwgttab[32]; char denstab[32]; char * difsptr; char * exasptr; sprintf (bbaltab, "%lf", bbalval); sprintf (denstab, "%lf", densval); sprintf (pwgttab, GNUMSTRING, pwgtval); strcpy (bufftab, "r{job=u,map=t,poli=L,sep=/((load>)&!(edge>vert**(vert-1)))?(m{type=h,vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}});}"); stringSubst (bufftab, "", ((flagval & SCOTCH_STRATSPEED) != 0) ? "" : "m{type=h,vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}}|"); if ((flagval & SCOTCH_STRATBALANCE) != 0) exasptr = "f{bal=0}"; else exasptr = ""; if ((flagval & SCOTCH_STRATSAFETY) != 0) difsptr = ""; else difsptr = "(d{dif=1,rem=0,pass=40}|)"; stringSubst (bufftab, "", exasptr); stringSubst (bufftab, "", difsptr); stringSubst (bufftab, "", bbaltab); stringSubst (bufftab, "", denstab); stringSubst (bufftab, "", pwgttab); if (SCOTCH_stratGraphMap (stratptr, bufftab) != 0) { errorPrint ("SCOTCH_stratGraphClusterBuild: error in sequential mapping strategy"); return (1); } return (0); } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_ml.h0000644000175300017530000000762011631334325023154 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_ml.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the multi-level vertex separation **/ /** routines. **/ /** **/ /** DATES : # Version 3.2 : from : 28 oct 1997 **/ /** to 13 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 13 dec 2001 **/ /** to 02 feb 2004 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct VgraphSeparateMlParam_ { INT coarnbr; /*+ Minimum number of vertices +*/ double coarrat; /*+ Coarsening ratio +*/ GraphCoarsenType coartype; /*+ Edge matching function type +*/ Strat * stratlow; /*+ Strategy at lowest level +*/ Strat * stratasc; /*+ Strategy at ascending levels +*/ } VgraphSeparateMlParam; /* ** The function prototypes. */ #ifndef VGRAPH_SEPARATE_ML #define static #endif static int vgraphSeparateMlCoarsen (const Vgraph * const, Vgraph * const, GraphCoarsenMulti * restrict * const, const VgraphSeparateMlParam * const); static int vgraphSeparateMlUncoarsen (Vgraph * const, const Vgraph * const, const GraphCoarsenMulti * restrict const); int vgraphSeparateMl (Vgraph * const, const VgraphSeparateMlParam * const); static int vgraphSeparateMl2 (Vgraph * const, const VgraphSeparateMlParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_map_f.c0000644000175300017530000002064411631334325023440 0ustar hazelscthazelsct/* Copyright 2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_map_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** parallel mapping routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 5.1 : from : 28 jun 2008 **/ /** to 31 aug 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the parallel mapping routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFDGRAPHMAPINIT, scotchfdgraphmapinit, ( \ const SCOTCH_Dgraph * const grafptr, \ SCOTCH_Dmapping * const mapptr, \ const SCOTCH_Arch * const archptr, \ SCOTCH_Num * const termloctab, \ int * const revaptr), \ (grafptr, mapptr, archptr, termloctab, revaptr)) { *revaptr = SCOTCH_dgraphMapInit (grafptr, mapptr, archptr, termloctab); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHMAPEXIT, scotchfdgraphmapexit, ( \ const SCOTCH_Dgraph * const grafptr, \ SCOTCH_Dmapping * const mapptr), \ (grafptr, mapptr)) { SCOTCH_dgraphMapExit (grafptr, mapptr); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHMAPSAVE, scotchfdgraphmapsave, ( \ const SCOTCH_Dgraph * const grafptr, \ SCOTCH_Dmapping * const mapptr, \ int * const fileptr, \ int * const revaptr), \ (grafptr, mapptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFDGRAPHMAPSAVE: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFDGRAPHMAPSAVE: cannot open output stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_dgraphMapSave (grafptr, mapptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHMAPCOMPUTE, scotchfdgraphmapcompute, ( \ SCOTCH_Dgraph * const grafptr, \ SCOTCH_Dmapping * const mapptr, \ SCOTCH_Strat * const stratptr, \ int * const revaptr), \ (grafptr, mapptr, stratptr, revaptr)) { *revaptr = SCOTCH_dgraphMapCompute (grafptr, mapptr, stratptr); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHMAP, scotchfdgraphmap, ( \ SCOTCH_Dgraph * const grafptr, \ const SCOTCH_Arch * const archptr, \ SCOTCH_Strat * const stratptr, \ SCOTCH_Num * const termloctab, \ int * const revaptr), \ (grafptr, archptr, stratptr, termloctab, revaptr)) { *revaptr = SCOTCH_dgraphMap (grafptr, archptr, stratptr, termloctab); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHPART, scotchfdgraphpart, ( \ SCOTCH_Dgraph * const grafptr, \ const SCOTCH_Num * const partptr, \ SCOTCH_Strat * const stratptr, \ SCOTCH_Num * const termloctab, \ int * const revaptr), \ (grafptr, partptr, stratptr, termloctab, revaptr)) { *revaptr = SCOTCH_dgraphPart (grafptr, *partptr, stratptr, termloctab); } /* String lengths are passed at the very ** end of the argument list. */ FORTRAN ( \ SCOTCHFSTRATDGRAPHMAP, scotchfstratdgraphmap, ( \ SCOTCH_Strat * const stratptr, \ const char * const string, \ int * const revaptr, \ const int strnbr), \ (stratptr, string, revaptr, strnbr)) { char * restrict strtab; /* Pointer to null-terminated string */ if ((strtab = (char *) memAlloc (strnbr + 1)) == NULL) { /* Allocate temporary space */ errorPrint ("SCOTCHFSTRATDGRAPHMAP: out of memory (1)"); *revaptr = 1; } memCpy (strtab, string, strnbr); /* Copy string contents */ strtab[strnbr] = '\0'; /* Terminate string */ *revaptr = SCOTCH_stratDgraphMap (stratptr, strtab); /* Call original routine */ memFree (strtab); } /* ** */ FORTRAN ( \ SCOTCHFSTRATDGRAPHMAPBUILD, scotchfstratdgraphmapbuild, ( \ SCOTCH_Strat * const stratptr, \ const SCOTCH_Num * const flagval, \ const SCOTCH_Num * const procnbr, \ const SCOTCH_Num * const partnbr, \ const double * const kbalval, \ int * const revaptr), \ (stratptr, flagval, procnbr, partnbr, kbalval, revaptr)) { *revaptr = SCOTCH_stratDgraphMapBuild (stratptr, *flagval, *procnbr, *partnbr, *kbalval); } /* ** */ FORTRAN ( \ SCOTCHFSTRATDGRAPHCLUSTERBUILD, scotchfstratdgraphclusterbuild, ( \ SCOTCH_Strat * const stratptr, \ const SCOTCH_Num * const flagval, \ const SCOTCH_Num * const procnbr, \ const SCOTCH_Num * const pwgtval, \ const double * const densval, \ const double * const bbalval, \ int * const revaptr), \ (stratptr, flagval, procnbr, pwgtval, densval, bbalval, revaptr)) { *revaptr = SCOTCH_stratDgraphClusterBuild (stratptr, *flagval, *procnbr, *pwgtval, *densval, *bbalval); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_map_view.c0000644000175300017530000003754711631334325024177 0ustar hazelscthazelsct/* Copyright 2008-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_map_view.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted mapping routines of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 5.1 : from : 26 jul 2008 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #define LIBRARY_DGRAPH_MAP_VIEW #include "module.h" #include "common.h" #include "parser.h" #include "dgraph.h" #include "dgraph_halo.h" #include "arch.h" #include "dmapping.h" #include "kdgraph.h" #include "library_dmapping.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the mapping routines. */ /* */ /************************************/ /*+ This routine writes distributed mapping *** statistics to the given stream. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphMapView ( SCOTCH_Dgraph * const libgrafptr, const SCOTCH_Dmapping * const libmappptr, FILE * const stream) { Dgraph * restrict grafptr; const LibDmapping * restrict mappptr; ArchDom domnfrst; /* Largest domain in architecture */ unsigned int * restrict nmskloctab; /* Local neighbor bitfield */ unsigned int * restrict nmskglbtab; /* Local neighbor bitfield */ int nmskidxnbr; /* Size of bitfield; int since sent by MPI */ Gnum * restrict tgloloctab; /* Local array of terminal domain loads */ Gnum * restrict tgloglbtab; /* Global array of terminal domain loads */ Gnum * restrict termgsttax; /* Terminal domain ghost mapping array */ Anum tgtnbr; /* Number of processors in target topology */ Anum tgtnum; Anum mapnbr; /* Number of processors effectively used */ double mapavg; /* Average mapping weight */ Gnum mapmin; Gnum mapmax; Gnum mapsum; /* (Partial) sum of vertex loads */ double mapdlt; double mapmmy; /* Maximum / average ratio */ Anum ngbsum; Anum ngbmin; Anum ngbmax; Gnum vertlocnum; Gnum veloval; Gnum edloval; Gnum commlocdist[256 + 3]; /* Array of local load distribution */ Gnum commglbdist[256 + 3]; Gnum commlocload; /* Total local edge load (edge sum) */ Gnum commlocdilat; /* Total edge dilation */ Gnum commlocexpan; /* Total edge expansion */ Anum distmax; Anum distval; int cheklocval; int chekglbval; DgraphHaloRequest requdat; grafptr = (Dgraph *) libgrafptr; mappptr = (LibDmapping *) libmappptr; if ((grafptr->vertglbnbr == 0) || /* Return if nothing to do */ (grafptr->edgeglbnbr == 0)) return (0); archDomFrst (&mappptr->m.archdat, &domnfrst); /* Get architecture domain */ tgtnbr = archDomSize (&mappptr->m.archdat, &domnfrst); /* Get architecture size */ if (archVar (&mappptr->m.archdat)) { errorPrint ("SCOTCH_dgraphMapView: not implemented"); return (1); } if (dgraphGhst (grafptr) != 0) { /* Compute ghost edge array if not already present */ errorPrint ("SCOTCH_dgraphMapView: cannot compute ghost edge array"); return (1); } nmskidxnbr = (tgtnbr + 1 + ((sizeof (int) << 3) - 1)) / (sizeof (int) << 3); /* Size of neighbor subdomain bitfield; TRICK: "+1" to have a "-1" cell for unmapped vertices */ cheklocval = 0; if (memAllocGroup ((void **) (void *) &nmskloctab, (size_t) (nmskidxnbr * sizeof (unsigned int)), &nmskglbtab, (size_t) (nmskidxnbr * sizeof (unsigned int)), &tgloloctab, (size_t) ((tgtnbr + 1) * sizeof (Gnum)), /* TRICK: "+1" to have a "-1" cell for unmapped vertices */ &tgloglbtab, (size_t) (tgtnbr * sizeof (Gnum)), &termgsttax, (size_t) (grafptr->vertgstnbr * sizeof (Gnum)), NULL) == NULL) { cheklocval = 1; } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("SCOTCH_dgraphMapView: communication error (1)"); return (1); } if (chekglbval != 0) { if (nmskloctab != NULL) memFree (nmskloctab); errorPrint ("SCOTCH_dgraphMapView: out of memory"); return (1); } if (dmapTerm (&mappptr->m, grafptr, termgsttax) != 0) { errorPrint ("SCOTCH_dgraphMapView: cannot build local terminal array"); memFree (nmskloctab); return (1); } dgraphHaloAsync (grafptr, termgsttax, GNUM_MPI, &requdat); termgsttax -= grafptr->baseval; memSet (tgloloctab, 0, (tgtnbr + 1) * sizeof (Gnum)); tgloloctab ++; /* TRICK: trim array for "-1" cell */ veloval = 1; for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { #ifdef SCOTCH_DEBUG_DMAP2 if ((termgsttax[vertlocnum] < -1) || (termgsttax[vertlocnum] >= tgtnbr)) { errorPrint ("SCOTCH_dgraphMapView: invalid local terminal array"); memFree (nmskloctab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_DMAP2 */ if (grafptr->veloloctax != NULL) veloval = grafptr->veloloctax[vertlocnum]; tgloloctab[termgsttax[vertlocnum]] += veloval; /* One more vertex of given weight assigned to this target */ } if (MPI_Allreduce (tgloloctab, tgloglbtab, tgtnbr, GNUM_MPI, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("SCOTCH_dgraphMapView: communication error (2)"); memFree (nmskloctab); /* Free group leader */ return (1); } mapmin = GNUMMAX; mapmax = 0; mapsum = 0; mapnbr = 0; for (tgtnum = 0; tgtnum < tgtnbr; tgtnum ++) { Gnum tgtsum; tgtsum = tgloglbtab[tgtnum]; if (tgtsum != 0) { mapnbr ++; mapsum += tgtsum; if (tgtsum < mapmin) mapmin = tgtsum; if (tgtsum > mapmax) mapmax = tgtsum; } } mapavg = (mapnbr == 0) ? 0.0L : ((double) mapsum / (double) mapnbr); mapdlt = 0.0L; for (tgtnum = 0; tgtnum < tgtnbr; tgtnum ++) mapdlt += fabs ((double) tgloglbtab[tgtnum] - mapavg); mapdlt = (mapnbr != 0) ? mapdlt / ((double) mapnbr * mapavg) : 0.0L; mapmmy = (mapnbr != 0) ? (double) mapmax / (double) mapavg : 0.0L; if (stream != NULL) { fprintf (stream, "M\tProcessors " GNUMSTRING "/" GNUMSTRING "(%g)\n", (Gnum) mapnbr, (Gnum) tgtnbr, (double) mapnbr / (double) tgtnbr); fprintf (stream, "M\tTarget min=" GNUMSTRING "\tmax=" GNUMSTRING "\tavg=%g\tdlt=%g\tmaxavg=%g\n", (Gnum) mapmin, (Gnum) mapmax, mapavg, mapdlt, mapmmy); } if (dgraphHaloWait (&requdat) != 0) { /* Wait for ghost terminal data to be exchanged */ errorPrint ("SCOTCH_dgraphMapView: cannot complete asynchronous halo exchange"); memFree (nmskloctab); /* Free group leader */ return (1); } ngbmin = ANUMMAX; ngbmax = 0; ngbsum = 0; for (tgtnum = 0; tgtnum < tgtnbr; tgtnum ++) { /* For all subdomain indices */ int nmskidxnum; Gnum vertlocnum; Anum ngbnbr; if (tgloglbtab[tgtnum] <= 0) /* If empty subdomain, skip it */ continue; memSet (nmskloctab, 0, nmskidxnbr * sizeof (int)); /* Reset neighbor bit mask */ for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { /* For all local vertices */ Gnum termnum; Gnum edgelocnum; Gnum edgelocnnd; termnum = termgsttax[vertlocnum]; if (termnum != tgtnum) /* If vertex does not belong to current part or is not mapped, skip it */ continue; for (edgelocnum = grafptr->vertloctax[vertlocnum], edgelocnnd = grafptr->vendloctax[vertlocnum]; edgelocnum < edgelocnnd; edgelocnum ++) { Gnum termend; termend = termgsttax[grafptr->edgegsttax[edgelocnum]]; if (termend != tgtnum) { /* If edge is not internal */ termend ++; /* TRICK: turn unmapped to 0 and so on */ nmskloctab[termend / (sizeof (int) << 3)] |= 1 << (termend & ((sizeof (int) << 3) - 1)); /* Flag neighbor in bit array */ } } } nmskloctab[0] &= ~1; /* Do not account for unmapped vertices (terminal domain 0 because of "+1") */ if (MPI_Allreduce (nmskloctab, nmskglbtab, nmskidxnbr, MPI_INT, MPI_BOR, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("SCOTCH_dgraphMapView: communication error (3)"); memFree (nmskloctab); /* Free group leader */ return (1); } for (nmskidxnum = 0, ngbnbr = 0; nmskidxnum < nmskidxnbr; nmskidxnum ++) { unsigned int nmskbitval; for (nmskbitval = nmskglbtab[nmskidxnum]; nmskbitval != 0; nmskbitval >>= 1) ngbnbr += nmskbitval & 1; } ngbsum += ngbnbr; if (ngbnbr < ngbmin) ngbmin = ngbnbr; if (ngbnbr > ngbmax) ngbmax = ngbnbr; } if (stream != NULL) { fprintf (stream, "M\tNeighbors min=" GNUMSTRING "\tmax=" GNUMSTRING "\tsum=" GNUMSTRING "\n", (Gnum) ngbmin, (Gnum) ngbmax, (Gnum) ngbsum); } memSet (commlocdist, 0, 256 * sizeof (Gnum)); /* Initialize the data */ commlocload = commlocdilat = commlocexpan = 0; edloval = 1; for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { /* For all local vertices */ Gnum termlocnum; ArchDom termdomdat; Gnum edgelocnum; Gnum edgelocnnd; termlocnum = termgsttax[vertlocnum]; if (termlocnum == ~0) /* Skip unmapped vertices */ continue; archDomTerm (&mappptr->m.archdat, &termdomdat, termlocnum); for (edgelocnum = grafptr->vertloctax[vertlocnum], edgelocnnd = grafptr->vendloctax[vertlocnum]; edgelocnum < edgelocnnd; edgelocnum ++) { ArchDom termdomend; Gnum termgstend; Anum distval; termgstend = termgsttax[grafptr->edgegsttax[edgelocnum]]; if (termgstend == ~0) /* Skip unmapped end vertices */ continue; distval = 0; if (grafptr->edloloctax != NULL) /* Get edge weight if any */ edloval = grafptr->edloloctax[edgelocnum]; if (termgstend != termlocnum) { /* If not same domain, compute distance */ archDomTerm (&mappptr->m.archdat, &termdomend, termgstend); distval = archDomDist (&mappptr->m.archdat, &termdomdat, &termdomend); } commlocdist[(distval > 255) ? 255 : distval] += edloval; commlocload += edloval; commlocdilat += distval; commlocexpan += distval * edloval; } } commlocdist[256] = commlocload; commlocdist[256 + 1] = commlocdilat; commlocdist[256 + 2] = commlocexpan; if (MPI_Allreduce (commlocdist, commglbdist, 256 + 3, GNUM_MPI, MPI_SUM, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("SCOTCH_dgraphMapView: communication error (4)"); memFree (nmskloctab); /* Free group leader */ return (1); } if (stream != NULL) { Gnum commglbload; commglbload = commglbdist[256]; fprintf (stream, "M\tCommDilat=%f\t(" GNUMSTRING ")\n", /* Print expansion parameters */ (double) commglbdist[256 + 1] / grafptr->edgeglbnbr, (Gnum) (commglbdist[256 + 1] / 2)); fprintf (stream, "M\tCommExpan=%f\t(" GNUMSTRING ")\n", ((commglbload == 0) ? (double) 0.0L : (double) commglbdist[256 + 2] / (double) commglbload), (Gnum) (commglbdist[256 + 2] / 2)); fprintf (stream, "M\tCommCutSz=%f\t(" GNUMSTRING ")\n", ((commglbload == 0) ? (double) 0.0L : (double) (commglbload - commglbdist[0]) / (double) commglbload), (Gnum) ((commglbload - commglbdist[0]) / 2)); fprintf (stream, "M\tCommDelta=%f\n", (((double) commglbload * (double) commglbdist[256 + 1]) == 0.0L) ? (double) 0.0L : ((double) commglbdist[256 + 2] * (double) grafptr->edgeglbnbr) / ((double) commglbload * (double) commglbdist[256 + 2])); for (distmax = 255; distmax != -1; distmax --) /* Find longest distance */ if (commglbdist[distmax] != 0) break; for (distval = 0; distval <= distmax; distval ++) /* Print distance histogram */ fprintf (stream, "M\tCommLoad[" ANUMSTRING "]=%f\n", (Anum) distval, (double) commglbdist[distval] / (double) commglbload); } memFree (nmskloctab); /* Free group leader */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/kdgraph.h0000644000175300017530000000752011631334325020730 0ustar hazelscthazelsct/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kdgraph.h **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a static mapper. **/ /** These lines are the data declarations **/ /** for the parallel k-way graph partiton- **/ /** ing structures and routines. **/ /** **/ /** DATES : # Version 5.1 : from : 31 mar 2008 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ The dynamic mapping structure. +*/ typedef struct Kdmapping_ { Dmapping * mappptr; /*+ Resulting mapping +*/ ArchDom domnorg; /*+ Initial domain +*/ } Kdmapping; /*+ The graph structure. +*/ typedef struct Kdgraph_ { Dgraph s; /*+ Source graph +*/ Kdmapping m; /*+ Mapping +*/ INT levlnum; } Kdgraph; /* ** The function prototypes. */ #ifndef KDGRAPH #define static #endif int kdgraphInit (Kdgraph * const, const Dgraph * restrict const, Dmapping * restrict const); void kdgraphExit (Kdgraph * const); int kdgraphFold (const Kdgraph *, const int, Kdgraph * const); int kdgraphFold2 (const Kdgraph *, const int, Kdgraph * const, MPI_Comm); #ifdef KGRAPH_H int kdgraphGather (Kdgraph *, Kgraph *); #endif /* KGRAPH_H */ int kdgraphInducePart (Kdgraph * restrict const, GraphPart * const, const Gnum, const GraphPart, Kdgraph * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_order.h0000644000175300017530000000656511631334325022157 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_order.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the library ordering **/ /** structure. **/ /** **/ /** DATES : # Version 3.3 : from : 08 oct 1998 **/ /** to : 08 oct 1998 **/ /** # Version 4.0 : from : 11 dec 2001 **/ /** to 25 dec 2004 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ Ordering. +*/ typedef struct LibOrder_ { Order o; /*+ Ordering data +*/ Gnum * permtab; /*+ Direct permutation array +*/ Gnum * peritab; /*+ Inverse permutation array +*/ Gnum * cblkptr; /*+ Pointer to number of column blocks +*/ Gnum * rangtab; /*+ Column block range array +*/ Gnum * treetab; /*+ Separator tree array +*/ } LibOrder; scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_coarsen_f.c0000644000175300017530000000657511631334325024324 0ustar hazelscthazelsct/* Copyright 2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_coarsen_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** distributed graph coarsening routine of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.1 : from : 07 aug 2011 **/ /** to 07 aug 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the mapping routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFDGRAPHCOARSEN, scotchfdgraphcoarsen, ( \ SCOTCH_Dgraph * const finegrafptr, \ SCOTCH_Dgraph * const coargrafptr, \ SCOTCH_Num * const multloctab, \ SCOTCH_Num * const coarnbrptr, \ double * const coarratptr, \ int * const revaptr), \ (finegrafptr, coargrafptr, multloctab, coarnbrptr, coarratptr, revaptr)) { *revaptr = SCOTCH_dgraphCoarsen (finegrafptr, coargrafptr, multloctab, *coarnbrptr, *coarratptr); } scotch-5.1.12b.dfsg/src/libscotch/mapping_io.c0000644000175300017530000002400111631334325021416 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mapping_io.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles (partial) mappings. **/ /** **/ /** DATES : # Version 0.0 : from : 31 mar 1993 **/ /** to 31 mar 1993 **/ /** # Version 1.0 : from : 04 oct 1993 **/ /** to 06 oct 1993 **/ /** # Version 1.1 : from : 15 oct 1993 **/ /** to 15 oct 1993 **/ /** # Version 1.3 : from : 09 apr 1994 **/ /** to 11 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 17 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to 18 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 19 oct 1995 **/ /** # Version 3.1 : from : 30 oct 1995 **/ /** to 14 jun 1996 **/ /** # Version 3.2 : from : 23 aug 1996 **/ /** to 07 sep 1998 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to 30 mar 1999 **/ /** # Version 3.4 : from : 11 sep 2001 **/ /** to 08 nov 2001 **/ /** # Version 4.0 : from : 16 jan 2004 **/ /** to 14 nov 2005 **/ /** # Version 5.0 : from : 13 sep 2006 **/ /** to 27 feb 2008 **/ /** # Version 5.1 : from : 11 aug 2010 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MAPPING_IO #include "module.h" #include "common.h" #include "graph.h" #include "arch.h" #include "mapping.h" #include "mapping_io.h" /***********************************/ /* */ /* These routines handle mappings. */ /* */ /***********************************/ /* This routine reads the contents of the given mapping ** file to the given mapping, reordering vertices ** according to the given vertex label table if necessary. ** It returns: ** - 0 : if mapping successfully written. ** - 1 : on error. ** - 2 : variable-sized architectures cannot be loaded. */ int mapLoad ( Mapping * restrict const mappptr, const Gnum * restrict const vlbltab, FILE * restrict const stream) { Gnum vertnum; Gnum mappnum; Gnum mappnbr; MappingLoadMap * mapptab; /* Mapping array */ MappingLoadPerm * permtab; /* Array of sorted label/index pairs */ Anum archnbr; /* Size of the target architecture */ ArchDom fdomdat; /* First domain of architecture */ if (strcmp (archName (&mappptr->archdat), "term") == 0) /* If target architecture is variable-sized */ return (2); archDomFrst (&mappptr->archdat, &fdomdat); /* Get architecture size */ archnbr = archDomSize (&mappptr->archdat, &fdomdat); if (mappptr->domnmax < (archnbr + 1)) { /* If mapping array too small to store mapping data */ ArchDom * restrict domntab; if ((domntab = (ArchDom *) memRealloc (mappptr->domntab, (archnbr + 1) * sizeof (ArchDom))) == NULL) { /* If cannot resize domain array */ errorPrint ("mapLoad: out of memory (1)"); return (1); } mappptr->domnmax = archnbr + 1; /* Point to new array */ mappptr->domntab = domntab; } mappptr->domnnbr = archnbr + 1; /* One more for first domain, for unmapped vertices */ archDomFrst (&mappptr->archdat, &mappptr->domntab[0]); /* Set first domain with root domain data */ for (mappnum = 0; mappnum < archnbr; mappnum ++) /* For all terminal domain numbers */ archDomTerm (&mappptr->archdat, &mappptr->domntab[mappnum + 1], mappnum); /* Set domain with terminal domain data */ if ((intLoad (stream, &mappnbr) != 1) || /* Read number of mapping entries */ (mappnbr < 1)) { errorPrint ("mapLoad: bad input (1)"); return (1); } if (memAllocGroup ((void **) (void *) &mapptab, (size_t) (mappnbr * sizeof (MappingLoadMap)), &permtab, (size_t) (mappptr->vertnbr * sizeof (MappingLoadPerm)), NULL) == NULL) { errorPrint ("mapLoad: out of memory (2)"); return (1); } for (mappnum = 0; mappnum < mappnbr; mappnum ++) { /* Load mapping array */ if ((intLoad (stream, &mapptab[mappnum].slblnum) != 1) || (intLoad (stream, &mapptab[mappnum].tlblnum) != 1)) { errorPrint ("mapLoad: bad input (2)"); return (1); } } intSort2asc1 (mapptab, mappnbr); /* Sort mapping array by increasing source labels */ if (vlbltab != NULL) { /* If graph has vertex labels */ Gnum vertnum; for (vertnum = 0; vertnum < mappptr->vertnbr; vertnum ++) { /* Build inverse permutation */ permtab[vertnum].vertnum = vertnum + mappptr->baseval; permtab[vertnum].vlblnum = vlbltab[vertnum]; } intSort2asc1 (permtab, mappptr->vertnbr); /* Sort vertex array by increasing labels */ } else { Gnum vertnum; for (vertnum = 0; vertnum < mappptr->vertnbr; vertnum ++) { /* Build identity permutation */ permtab[vertnum].vertnum = vertnum + mappptr->baseval; permtab[vertnum].vlblnum = vertnum + mappptr->baseval; } } for (vertnum = 0, mappnum = 0; /* For all graph vertices */ vertnum < mappptr->vertnbr; vertnum ++) { while ((mappnum < mappnbr) && /* Skip useless mapping data (if graph is subgraph of originally mapped graph) */ (permtab[vertnum].vlblnum > mapptab[mappnum].slblnum)) mappnum ++; if (mappnum >= mappnbr) /* If all mapping data exhausted */ break; /* Exit the matching loop */ if (permtab[vertnum].vlblnum == mapptab[mappnum].slblnum) { /* If matching mapping data found */ if ((mapptab[mappnum].tlblnum >= 0) && /* If mapping valid */ (mapptab[mappnum].tlblnum < archnbr)) mappptr->parttax[permtab[vertnum].vertnum] = mapptab[mappnum].tlblnum + 1; /* Set mapping to terminal domain */ mappnum ++; /* Mapping pair has been used */ } } memFree (mapptab); /* Free group leader */ return (0); } /* This routine writes the contents of the ** given mapping to the given string. ** It returns: ** - 0 : if mapping successfully written. ** - !0 : on error. */ int mapSave ( const Mapping * restrict const mappptr, const Gnum * restrict const vlbltab, FILE * restrict const stream) { const Gnum * restrict vlbltax; Gnum vertnum; vlbltax = (vlbltab != NULL) ? (vlbltab - mappptr->baseval) : NULL; if (fprintf (stream, GNUMSTRING "\n", (Gnum) mappptr->vertnbr) == EOF) { errorPrint ("mapSave: bad output (1)"); return (1); } for (vertnum = mappptr->baseval; vertnum < (mappptr->vertnbr + mappptr->baseval); vertnum ++) { if (fprintf (stream, GNUMSTRING "\t" ANUMSTRING "\n", (Gnum) ((vlbltax != NULL) ? vlbltax[vertnum] : vertnum), (Anum) archDomNum (&mappptr->archdat, &mappptr->domntab[mappptr->parttax[vertnum]])) == EOF) { errorPrint ("mapSave: bad output (2)"); return (1); } } return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_strat.c0000644000175300017530000000621011631334325022157 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_strat.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains miscellaneous **/ /** routines for handling strategy **/ /** strings. **/ /** **/ /** DATES : # Version 5.1 : from : 17 nov 2010 **/ /** to 17 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /*****************************************/ /* */ /* These routines are the C API for */ /* ordering structure handling routines. */ /* */ /*****************************************/ /*+ This routine reserves a memory area *** of a size sufficient to store a *** distributed ordering structure. *** It returns: *** - !NULL : if the initialization succeeded. *** - NULL : on error. +*/ SCOTCH_Strat * SCOTCH_stratAlloc () { return ((SCOTCH_Strat *) memAlloc (sizeof (SCOTCH_Strat))); } scotch-5.1.12b.dfsg/src/libscotch/library_mesh_order_f.c0000644000175300017530000002745011631334325023467 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_mesh_order_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** mesh ordering routines of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 4.0 : from : 14 jan 2004 **/ /** to 20 dec 2005 **/ /** # Version 5.0 : from : 04 aug 2007 **/ /** to 04 aug 2007 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 25 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the ordering routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFMESHORDERINIT, scotchfmeshorderinit, ( \ const SCOTCH_Mesh * const meshptr, \ SCOTCH_Ordering * const ordeptr, \ SCOTCH_Num * const permtab, \ SCOTCH_Num * const peritab, \ SCOTCH_Num * const cblkptr, \ SCOTCH_Num * const rangtab, \ SCOTCH_Num * const treetab, \ int * const revaptr), \ (meshptr, ordeptr, permtab, peritab, \ cblkptr, rangtab, treetab, revaptr)) { *revaptr = SCOTCH_meshOrderInit (meshptr, ordeptr, permtab, peritab, cblkptr, rangtab, treetab); } /* ** */ FORTRAN ( \ SCOTCHFMESHORDEREXIT, scotchfmeshorderexit, ( \ const SCOTCH_Mesh * const meshptr, \ SCOTCH_Ordering * const ordeptr), \ (meshptr, ordeptr)) { SCOTCH_meshOrderExit (meshptr, ordeptr); } /* ** */ FORTRAN ( \ SCOTCHFMESHORDERSAVE, scotchfmeshordersave, ( \ const SCOTCH_Mesh * const meshptr, \ const SCOTCH_Ordering * const ordeptr, \ int * const fileptr, \ int * const revaptr), \ (meshptr, ordeptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFMESHORDERSAVE: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFMESHORDERSAVE: cannot open output stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_meshOrderSave (meshptr, ordeptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFMESHORDERSAVEMAP, scotchfmeshordersavemap, ( \ const SCOTCH_Mesh * const meshptr, \ const SCOTCH_Ordering * const ordeptr, \ int * const fileptr, \ int * const revaptr), \ (meshptr, ordeptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFMESHORDERSAVEMAP: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFMESHORDERSAVEMAP: cannot open output stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_meshOrderSaveMap (meshptr, ordeptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFMESHORDERSAVETREE, scotchfmeshordersavetree, ( \ const SCOTCH_Mesh * const meshptr, \ const SCOTCH_Ordering * const ordeptr, \ int * const fileptr, \ int * const revaptr), \ (meshptr, ordeptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFMESHORDERSAVETREE: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFMESHORDERSAVETREE: cannot open output stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_meshOrderSaveTree (meshptr, ordeptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFMESHORDERCOMPUTE, scotchfmeshordercompute, ( \ SCOTCH_Mesh * const meshptr, \ SCOTCH_Ordering * const ordeptr, \ SCOTCH_Strat * const stratptr, \ int * const revaptr), \ (meshptr, ordeptr, stratptr, revaptr)) { *revaptr = SCOTCH_meshOrderCompute (meshptr, ordeptr, stratptr); } /* ** */ FORTRAN ( \ SCOTCHFMESHORDERCOMPUTELIST, scotchfmeshordercomputelist, ( \ SCOTCH_Mesh * const meshptr, \ SCOTCH_Ordering * const ordeptr, \ const SCOTCH_Num * listptr, \ const SCOTCH_Num * const listtab, \ SCOTCH_Strat * const stratptr, \ int * const revaptr), \ (meshptr, ordeptr, listptr, listtab, stratptr, revaptr)) { *revaptr = SCOTCH_meshOrderComputeList (meshptr, ordeptr, *listptr, listtab, stratptr); } /* ** */ FORTRAN ( \ SCOTCHFMESHORDER, scotchfmeshorder, ( \ SCOTCH_Mesh * const meshptr, \ SCOTCH_Strat * const stratptr, \ SCOTCH_Num * const permtab, \ SCOTCH_Num * const peritab, \ SCOTCH_Num * const cblkptr, \ SCOTCH_Num * const rangtab, \ SCOTCH_Num * const treetab, \ int * const revaptr), \ (meshptr, stratptr, permtab, peritab, \ cblkptr, rangtab, treetab, revaptr)) { *revaptr = SCOTCH_meshOrder (meshptr, stratptr, permtab, peritab, cblkptr, rangtab, treetab); } /* ** */ FORTRAN ( \ SCOTCHFMESHORDERLIST, scotchfmeshorderlist, ( \ SCOTCH_Mesh * const meshptr, \ const SCOTCH_Num * const listptr, \ const SCOTCH_Num * const listtab, \ SCOTCH_Strat * const stratptr, \ SCOTCH_Num * const permtab, \ SCOTCH_Num * const peritab, \ SCOTCH_Num * const cblkptr, \ SCOTCH_Num * const rangtab, \ SCOTCH_Num * const treetab, \ int * const revaptr), \ (meshptr, listptr, listtab, stratptr, \ permtab, peritab, cblkptr, rangtab, treetab, revaptr)) { *revaptr = SCOTCH_meshOrderList (meshptr, *listptr, listtab, stratptr, permtab, peritab, cblkptr, rangtab, treetab); } /* ** */ FORTRAN ( \ SCOTCHFMESHORDERCHECK, scotchfmeshordercheck, ( \ const SCOTCH_Mesh * const meshptr, \ SCOTCH_Ordering * const ordeptr, \ int * const revaptr), \ (meshptr, ordeptr, revaptr)) { *revaptr = SCOTCH_meshOrderCheck (meshptr, ordeptr); } /* ** */ FORTRAN ( \ SCOTCHFSTRATMESHORDER, scotchfstratmeshorder, ( \ SCOTCH_Strat * const stratptr, \ const char * const string, \ int * const revaptr, \ const int strnbr), \ (stratptr, string, revaptr, strnbr)) { char * restrict strtab; /* Pointer to null-terminated string */ if ((strtab = (char *) memAlloc (strnbr + 1)) == NULL) { /* Allocate temporary space */ errorPrint ("SCOTCHFSTRATMESHORDER: out of memory (1)"); *revaptr = 1; } memCpy (strtab, string, strnbr); /* Copy string contents */ strtab[strnbr] = '\0'; /* Terminate string */ *revaptr = SCOTCH_stratMeshOrder (stratptr, strtab); /* Call original routine */ memFree (strtab); /* Prevent compiler warnings */ } /* ** */ FORTRAN ( \ SCOTCHFSTRATMESHORDERBUILD, scotchfstratmeshorderbuild, ( \ SCOTCH_Strat * const stratptr, \ const SCOTCH_Num * const flagval, \ const double * const balrat, \ int * const revaptr), \ (stratptr, flagval, balrat, revaptr)) { *revaptr = SCOTCH_stratMeshOrderBuild (stratptr, *flagval, *balrat); } scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_st.h0000644000175300017530000000763211631334325022626 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_st.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the strategy and method **/ /** tables and the generic entry point for **/ /** the graph bipartitioning methods. **/ /** **/ /** DATES : # Version 3.2 : from : 08 oct 1996 **/ /** to 13 sep 1998 **/ /** # Version 4.0 : from : 15 jan 2002 **/ /** to 15 jan 2002 **/ /** # Version 5.0 : from : 27 nov 2006 **/ /** to 13 jan 2007 **/ /** **/ /************************************************************/ /* ** The type definitions. */ /** Method types. **/ typedef enum BgraphBipartStMethodType_ { BGRAPHBIPARTSTMETHBD = 0, /*+ Band +*/ BGRAPHBIPARTSTMETHDF, /*+ Diffusion +*/ BGRAPHBIPARTSTMETHEX, /*+ Exactifying +*/ BGRAPHBIPARTSTMETHFM, /*+ Fiduccia-Mattheyses +*/ BGRAPHBIPARTSTMETHGG, /*+ Greedy Graph Growing +*/ BGRAPHBIPARTSTMETHGP, /*+ Gibbs-Poole-Stockmeyer +*/ BGRAPHBIPARTSTMETHML, /*+ Multi-level (strategy) +*/ BGRAPHBIPARTSTMETHZR, /*+ Move all to part zero +*/ BGRAPHBIPARTSTMETHNBR /*+ Number of methods +*/ } BgraphBipartStMethodType; /* ** The external declarations. */ extern StratTab bgraphbipartststratab; /* ** The function prototypes. */ #ifndef BGRAPH_BIPART_ST #define static #endif int bgraphBipartSt (Bgraph * restrict const, const Strat * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/vdgraph_separate_st.h0000644000175300017530000000671111631334325023336 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_separate_st.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the global distributed sepa- **/ /** ration strategy and method tables. **/ /** **/ /** DATES : # Version 5.0 : from : 16 feb 2006 **/ /** to 08 mar 2006 **/ /** # Version 5.1 : from : 05 nov 2007 **/ /** to 05 nov 2007 **/ /** **/ /************************************************************/ /* ** The type definitions. */ /*+ Method types. +*/ typedef enum VdgraphSeparateStMethodType_ { VDGRAPHSEPASTMETHBD = 0, /*+ Band strategy +*/ VDGRAPHSEPASTMETHDF, /*+ Diffusion method +*/ VDGRAPHSEPASTMETHML, /*+ Multilevel strategy +*/ VDGRAPHSEPASTMETHSQ, /*+ Sequential strategy +*/ VDGRAPHSEPASTMETHZR, /*+ Zero method +*/ VDGRAPHSEPASTMETHNBR /*+ Number of methods +*/ } VdgraphSeparateStMethodType; /* ** The external declarations. */ extern StratTab vdgraphseparateststratab; /* ** The function prototypes. */ #ifndef VDGRAPH_SEPARATE_ST #define static #endif int vdgraphSeparateSt (Vdgraph * const, const Strat * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/common_string.c0000644000175300017530000001076411631334325022165 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : common_string.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** These lines are common routines used **/ /** by all modules. **/ /** **/ /** DATES : # Version 5.1 : from : 23 jul 2010 **/ /** to 23 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define COMMON #ifndef COMMON_NOMODULE #include "module.h" #endif /* COMMON_NOMODULE */ #include #include "common.h" /********************************/ /* */ /* String substitution routine. */ /* */ /********************************/ static void stringSubst2 ( char * const bsrcptr, char * const bdstptr, const char * const pattstr, const char * const replstr, const int pattsiz, const int replsiz) { char * pattptr; int pattidx; pattptr = strstr (bsrcptr, pattstr); /* Search for the pattern in the remaining source string */ pattidx = (pattptr == NULL) ? (strlen (bsrcptr) + 1): (pattptr - bsrcptr); /* Get length of unchanged part */ if (replsiz < pattsiz) /* If replacement is smaller, pre-move unchanged part */ memMov (bdstptr, bsrcptr, pattidx * sizeof (char)); if (pattptr != NULL) /* If remaining part of string has to be processed */ stringSubst2 (pattptr + pattsiz, bdstptr + pattidx + replsiz, pattstr, replstr, pattsiz, replsiz); if (replsiz > pattsiz) /* If replacement is longer, post-move unchanged part */ memMov (bdstptr, bsrcptr, pattidx * sizeof (char)); if (pattptr != NULL) /* If there is something to replace */ memCpy (bdstptr + pattidx, replstr, replsiz * sizeof (char)); /* Write replacement string */ return; } void stringSubst ( char * const buffptr, /* String to search into */ const char * const pattstr, /* Pattern to search for */ const char * const replstr) /* Replacement string */ { int pattsiz; int replsiz; pattsiz = strlen (pattstr); replsiz = strlen (replstr); stringSubst2 (buffptr, buffptr, pattstr, replstr, pattsiz, replsiz); } scotch-5.1.12b.dfsg/src/libscotch/vdgraph_separate_zr.c0000644000175300017530000000632511631334325023337 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_separate_zr.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module moves all of the vertices **/ /** of the distributed separator graph to **/ /** the first subdomain. **/ /** **/ /** DATES : # Version 5.0 : from : 07 feb 2006 **/ /** to 07 feb 2006 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VDGRAPH_SEPARATE_ZR #include "module.h" #include "common.h" #include "dgraph.h" #include "vdgraph.h" #include "vdgraph_separate_zr.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine moves all of the graph vertices ** to the first part of the partition. ** It returns: ** - 0 : if the bipartitioning could be computed. ** - !0 : on error. */ int vdgraphSeparateZr ( Vdgraph * const grafptr) /*+ Active graph +*/ { if (grafptr->compglbload[0] != grafptr->s.veloglbsum) /* If not all vertices already in part zero */ vdgraphZero (grafptr); return (0); } scotch-5.1.12b.dfsg/src/libscotch/arch_build.h0000644000175300017530000001014211631334325021376 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_build.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the architecture building routine. **/ /** **/ /** DATES : # Version 3.2 : from : 29 may 1997 **/ /** to 01 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 29 nov 2003 **/ /** to 29 nov 2003 **/ /** **/ /** NOTES : # This file contains pieces of code **/ /** extracted from release 3.1 of **/ /** "amk_src.c". **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ Job to process. +*/ typedef struct ArchBuildJob_ { struct ArchBuildJob_ * joblink; /*+ Link to job pool +*/ ArchDomNum domnum; /*+ Mapping domain to which vertices belong +*/ Graph grafdat; /*+ Job graph data +*/ } ArchBuildJob; /*+ Vertex distance information. +*/ typedef struct ArchBuildDistElem_ { int queued; /*+ Flag set if vertex queued +*/ Anum distval; /*+ Distance to initial vertex +*/ } ArchBuildDistElem; /*+ Queue element. +*/ typedef struct ArchBuildQueuElem_ { Gnum vertnum; /*+ Vertex number in source graph +*/ Anum distval; /*+ Distance reached +*/ } ArchBuildQueuElem; /* ** The function prototypes. */ #ifndef ARCH_BUILD #define static #endif static void archBuildJobExit (ArchBuildJob *); int archBuild (Arch * const, const Graph * const, const VertList * const, const Strat * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/hdgraph_order_nd.h0000644000175300017530000001222111631334325022573 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph_order_nd.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the halo distributed graph nested **/ /** dissection ordering algorithm. **/ /** **/ /** DATES : # Version 5.0 : from : 16 apr 2006 **/ /** to 16 jun 2007 **/ /** # Version 5.1 : from : 11 nov 2008 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HdgraphOrderNdParam_ { Strat * sepstrat; /*+ Separation strategy +*/ Strat * ordstratlea; /*+ Leaf ordering strategy +*/ Strat * ordstratsep; /*+ Separator ordering strategy +*/ Strat * ordstratseq; /*+ Sequential ordering strategy +*/ } HdgraphOrderNdParam; /*+ Method types. +*/ typedef enum HdgraphOrderNdType_ { HDGRAPHORDERNDTYPECENT = 0, /*+ Centralized folded graph +*/ HDGRAPHORDERNDTYPEDIST /*+ Distributed folded graph +*/ } HdgraphOrderNdType; /*+ This structure holds folded graph data, whether centralized or distributed. +*/ typedef struct HdgraphOrderNdGraph_ { HdgraphOrderNdType typeval; /*+ Halo graph type +*/ union { Hgraph cgrfdat; /*+ Centralized halo graph +*/ Hdgraph dgrfdat; /*+ Distributed halo graph +*/ } data; } HdgraphOrderNdGraph; /*+ This structure holds the data passed to the subgraph building threads. +*/ typedef struct HdgraphOrderNdData_ { Hdgraph * orggrafptr; /*+ Pointer to original graph +*/ Gnum indlistnbr; /*+ Local number of vertices in subgraph +*/ const Gnum * indlisttab; /*+ Local list of vertices in subgraph +*/ HdgraphOrderNdGraph * fldgrafptr; /*+ Pointer to folded graph union area +*/ int fldpartval; /*+ Part of processor array to which to fold to +*/ int fldprocnbr; /*+ Number of processes in folded communicator +*/ int fldprocnum; /*+ Rank of process in folded communicator, or -1 +*/ MPI_Comm fldproccomm; /*+ Communicator for the folded graph, if any +*/ } HdgraphOrderNdData; /* ** The function prototypes. */ #ifndef HDGRAPH_ORDER_ND #define static #endif static void * hdgraphOrderNdFold2 (void * const); static int hdgraphOrderNdFold (Hdgraph * restrict const, const Gnum, const Gnum * restrict const, const Gnum, const Gnum * restrict const, HdgraphOrderNdGraph * restrict const); int hdgraphOrderNd (Hdgraph * const, DorderCblk * const, const HdgraphOrderNdParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_dgraph.c0000644000175300017530000002216211631334325022273 0ustar hazelscthazelsct/* Copyright 2007,2009,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted source graph handling routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 26 apr 2006 **/ /** to 14 apr 2008 **/ /** # Version 5.1 : from : 26 mar 2009 **/ /** to 17 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "graph.h" /* For graphPtscotch() */ #include "dgraph.h" #include "scotch.h" /****************************************/ /* */ /* These routines are the C API for the */ /* distributed graph handling routines. */ /* */ /****************************************/ /*+ This routine reserves a memory area *** of a size sufficient to store a *** distributed graph structure. *** It returns: *** - !NULL : if the initialization succeeded. *** - NULL : on error. +*/ SCOTCH_Dgraph * SCOTCH_dgraphAlloc () { return ((SCOTCH_Dgraph *) memAlloc (sizeof (SCOTCH_Dgraph))); } /*+ This routine initializes the opaque *** distributed graph structure used to *** handle distributed graphs in the *** Scotch library. *** It returns: *** - 0 : if the initialization succeeded. *** - !0 : on error. +*/ int SCOTCH_dgraphInit ( SCOTCH_Dgraph * const grafptr, MPI_Comm proccomm) /* Communicator to be used for all communications */ { #ifdef SCOTCH_PTHREAD int thrdlvlval; #endif /* SCOTCH_PTHREAD */ if (graphPtscotch () != 1) { errorPrint ("SCOTCH_dgraphInit: linking with both libScotch and libPTScotch is not allowed"); return (1); } #ifdef SCOTCH_PTHREAD MPI_Query_thread (&thrdlvlval); if (thrdlvlval < MPI_THREAD_MULTIPLE) { errorPrint ("SCOTCH_dgraphInit: Scotch compiled with SCOTCH_PTHREAD and program not launched with MPI_THREAD_MULTIPLE"); return (1); } #endif /* SCOTCH_PTHREAD */ if (sizeof (SCOTCH_Num) != sizeof (Gnum)) { errorPrint ("SCOTCH_dgraphInit: internal error (1)"); return (1); } if (sizeof (SCOTCH_Dgraph) < sizeof (Dgraph)) { errorPrint ("SCOTCH_dgraphInit: internal error (2)"); return (1); } return (dgraphInit ((Dgraph *) grafptr, proccomm)); } /*+ This routine frees the contents of the *** given opaque graph structure. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_dgraphExit ( SCOTCH_Dgraph * const grafptr) { dgraphExit ((Dgraph *) grafptr); } /*+ This routine frees the contents of the *** given opaque graph structure but does *** not free its private data. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_dgraphFree ( SCOTCH_Dgraph * const grafptr) { dgraphFree ((Dgraph *) grafptr); } /*+ This routine accesses graph size data. *** NULL pointers on input indicate unwanted *** data. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_dgraphSize ( const SCOTCH_Dgraph * const grafptr, SCOTCH_Num * const vertglbnbr, SCOTCH_Num * const vertlocnbr, SCOTCH_Num * const edgeglbnbr, SCOTCH_Num * const edgelocnbr) { const Dgraph * srcgrafptr; srcgrafptr = (Dgraph *) grafptr; if (vertglbnbr != NULL) *vertglbnbr = (SCOTCH_Num) (srcgrafptr->vertglbnbr); if (vertlocnbr != NULL) *vertlocnbr = (SCOTCH_Num) (srcgrafptr->vertlocnbr); if (edgeglbnbr != NULL) *edgeglbnbr = (SCOTCH_Num) srcgrafptr->edgeglbnbr; if (edgelocnbr != NULL) *edgelocnbr = (SCOTCH_Num) srcgrafptr->edgelocnbr; } /*+ This routine accesses all of the graph data. *** NULL pointers on input indicate unwanted *** data. NULL pointers on output indicate *** unexisting arrays. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_dgraphData ( const SCOTCH_Dgraph * const grafptr, /* Graph structure to read */ SCOTCH_Num * const baseptr, /* Base value */ SCOTCH_Num * const vertglbptr, /* Number of global vertices */ SCOTCH_Num * const vertlocptr, /* Number of local vertices */ SCOTCH_Num * const vertlocptz, /* Maximum number of local vertices */ SCOTCH_Num * const vertgstptr, /* Number of local + ghost vertices */ SCOTCH_Num ** const vertloctab, /* Vertex array [vertnbr+1] */ SCOTCH_Num ** const vendloctab, /* Vertex array [vertnbr] */ SCOTCH_Num ** const veloloctab, /* Vertex load array */ SCOTCH_Num ** const vlblloctab, /* Vertex label array */ SCOTCH_Num * const edgeglbptr, /* Number of global edges (arcs) */ SCOTCH_Num * const edgelocptr, /* Number of local edges (arcs) */ SCOTCH_Num * const edgelocptz, /* Size of local edge array */ SCOTCH_Num ** const edgeloctab, /* Local edge array [edgelocsiz] */ SCOTCH_Num ** const edgegsttab, /* Ghost edge array [edgelocsiz] */ SCOTCH_Num ** const edloloctab, /* Edge load array [edgelocsiz] */ MPI_Comm * const comm) /* MPI Communicator */ { const Dgraph * srcgrafptr; /* Pointer to source graph structure */ srcgrafptr = (const Dgraph *) grafptr; if (baseptr != NULL) *baseptr = srcgrafptr->baseval; if (vertglbptr != NULL) *vertglbptr = srcgrafptr->vertglbnbr; if (vertlocptr != NULL) *vertlocptr = srcgrafptr->vertlocnbr; if (vertlocptz != NULL) *vertlocptz = srcgrafptr->procvrttab[srcgrafptr->proclocnum + 1] - srcgrafptr->procvrttab[srcgrafptr->proclocnum]; if (vertgstptr != NULL) *vertgstptr = ((srcgrafptr->flagval & DGRAPHHASEDGEGST) != 0) ? srcgrafptr->vertgstnbr : -1; if (vertloctab != NULL) *vertloctab = srcgrafptr->vertloctax + srcgrafptr->baseval; if (vendloctab != NULL) *vendloctab = srcgrafptr->vendloctax + srcgrafptr->baseval; if (veloloctab != NULL) *veloloctab = (srcgrafptr->veloloctax != NULL) ? srcgrafptr->veloloctax + srcgrafptr->baseval : NULL; if (vlblloctab != NULL) *vlblloctab = (srcgrafptr->vlblloctax != NULL) ? srcgrafptr->vlblloctax + srcgrafptr->baseval : NULL; if (edgeglbptr != NULL) *edgeglbptr = srcgrafptr->edgeglbnbr; if (edgelocptr != NULL) *edgelocptr = srcgrafptr->edgelocnbr; if (edgelocptz != NULL) *edgelocptz = srcgrafptr->edgelocsiz; if (edgeloctab != NULL) *edgeloctab = srcgrafptr->edgeloctax + srcgrafptr->baseval; if (edgegsttab != NULL) *edgegsttab = (srcgrafptr->edgegsttax != NULL) ? srcgrafptr->edgegsttax + srcgrafptr->baseval : NULL; if (edloloctab != NULL) *edloloctab = (srcgrafptr->edloloctax != NULL) ? srcgrafptr->edloloctax + srcgrafptr->baseval : NULL; if (comm != NULL) *comm = srcgrafptr->proccomm; } scotch-5.1.12b.dfsg/src/libscotch/library_mapping.h0000644000175300017530000000554111631334325022470 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_mapping.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the library ordering **/ /** structure. **/ /** **/ /** DATES : # Version 4.0 : from : 28 jun 2004 **/ /** to 28 jun 2004 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ Ordering. +*/ typedef struct LibMapping_ { Mapping m; /*+ Mapping data +*/ Gnum * parttax; /*+ Partition array +*/ } LibMapping; scotch-5.1.12b.dfsg/src/libscotch/library_graph_check_f.c0000644000175300017530000000633111631334325023571 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_check_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the source graph handling routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 3.4 : from : 02 dec 1999 **/ /** to 15 nov 2001 **/ /** # Version 4.0 : from : 11 dec 2001 **/ /** to 22 apr 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the graph handling routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFGRAPHCHECK, scotchfgraphcheck, ( \ const SCOTCH_Graph * const grafptr, \ int * const revaptr), \ (grafptr, revaptr)) { *revaptr = SCOTCH_graphCheck (grafptr); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_gather_all.c0000644000175300017530000005540511631334325022737 0ustar hazelscthazelsct/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_gather_all.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the routine which **/ /** builds a centralized graph on all **/ /** processes by gathering the pieces of **/ /** a distributed graph. **/ /** **/ /** DATES : # Version 5.0 : from : 07 feb 2006 **/ /** to 17 jun 2008 **/ /** # Version 5.1 : from : 30 jul 2010 **/ /** to 30 jul 2010 **/ /** **/ /** NOTES : # The definitions of MPI_Gather and **/ /** MPI_Gatherv indicate that elements in **/ /** the receive array should not be **/ /** written more than once. Great care **/ /** should be taken to enforce this rule, **/ /** especially when the number of **/ /** vertices in the centralized graph is **/ /** smaller than the number of **/ /** processes. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH #include "module.h" #include "common.h" #include "comm.h" #include "graph.h" #include "dgraph.h" /* This function gathers on all processes ** the pieces of a distributed graph to ** build a centralized graph. This function ** does not compute edlosum on the centralized ** graphs when it is already given in the passed ** value, as a non-negative number. ** It returns: ** - 0 : if graph data are consistent. ** - !0 : on error. */ static int dgraphGatherAll3 ( Gnum * const senddattab, const Gnum sendcntnbr, Gnum * const recvdattab, Gnum * const recvcnttab, Gnum * const recvdsptab, const int rootnum, MPI_Comm comm) { if (rootnum == -1) /* If collective communication wanted */ return (commAllgatherv (senddattab, sendcntnbr, GNUM_MPI, recvdattab, recvcnttab, recvdsptab, GNUM_MPI, comm)); else return (commGatherv (senddattab, sendcntnbr, GNUM_MPI, recvdattab, recvcnttab, recvdsptab, GNUM_MPI, rootnum, comm)); } int dgraphGatherAll2 ( const Dgraph * restrict const dgrfptr, /* Distributed graph */ Graph * restrict cgrfptr, /* Centralized graph */ const Gnum edlosum, /* -1 means recompute */ const int protnum) /* -1 means allgather */ { Gnum baseval; Gnum * restrict verttax; /* Target vertex array for root, dummy for non-roots */ Gnum * restrict velotax; /* Target vertex load array for root, dummy for non-roots */ Gnum * restrict vnumtax; /* Target vertex index array for root, dummy for non-roots */ Gnum * restrict vlbltax; /* Target vertex label array for root, dummy for non-roots */ Gnum * restrict edgetax; /* Target edge array for root, dummy for non-roots */ Gnum * restrict edlotax; /* Target edge load array for root, dummy for non-roots */ Gnum vertlocnbr; /* Size of temporary distributed vertex array */ Gnum * restrict vertloctax; /* Temporary vertex array if graph is not compact */ Gnum edgelocnbr; /* Size of temporary distributed edge array */ Gnum * restrict edgeloctab; /* Temporary edge array if distributed graph is not compact */ Gnum * restrict recvcnttab; /* Count array for gather operations */ Gnum * restrict recvdsptab; /* Displacement array for gather operations */ int cheklocval; int chekglbval; const Gnum * restrict const edgeloctax = dgrfptr->edgeloctax; #ifdef SCOTCH_DEBUG_DGRAPH1 cheklocval = 0; if (cgrfptr != NULL) /* Centralized graphs should be provided by all */ cheklocval = 1; if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_SUM, dgrfptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphGatherAll2: communication error (1)"); return (1); } if (protnum == -1) { /* If collective gathering wanted */ if (chekglbval != dgrfptr->procglbnbr) { errorPrint ("dgraphGatherAll2: centralized graphs should be provided on every process"); return (1); } } else { /* Single gathering wanted */ if (chekglbval != 1) { errorPrint ("dgraphGatherAll2: should have only one root"); return (1); } } #endif /* SCOTCH_DEBUG_DGRAPH1 */ baseval = dgrfptr->baseval; cheklocval = 0; if (cgrfptr != NULL) { /* If root process */ Gnum velonbr; Gnum vnumnbr; Gnum vlblnbr; Gnum edlonbr; velonbr = (dgrfptr->veloloctax != NULL) ? dgrfptr->vertglbnbr : 0; vnumnbr = (dgrfptr->vnumloctax != NULL) ? dgrfptr->vertglbnbr : 0; vlblnbr = (dgrfptr->vlblloctax != NULL) ? dgrfptr->vertglbnbr : 0; edlonbr = (dgrfptr->edloloctax != NULL) ? dgrfptr->edgeglbnbr : 0; if (memAllocGroup ((void **) (void *) &cgrfptr->verttax, (size_t) ((dgrfptr->vertglbnbr + 1) * sizeof (Gnum)), &cgrfptr->velotax, (size_t) (velonbr * sizeof (Gnum)), &cgrfptr->vnumtax, (size_t) (vnumnbr * sizeof (Gnum)), &cgrfptr->vlbltax, (size_t) (vlblnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphGatherAll2: out of memory (1)"); cheklocval = 1; } else if (memAllocGroup ((void **) (void *) &cgrfptr->edgetax, (size_t) (dgrfptr->edgeglbnbr * sizeof (Gnum)), &cgrfptr->edlotax, (size_t) (edlonbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphGatherAll2: out of memory (2)"); cheklocval = 1; } } if (dgrfptr->vendloctax == (dgrfptr->vertloctax + 1)) { /* If distributed graph is compact */ vertlocnbr = /* No need to recompact arrays */ edgelocnbr = 0; } else { /* Need extra space to compact vertex and edge arrays before sending */ vertlocnbr = dgrfptr->vertlocnbr; edgelocnbr = dgrfptr->edgelocnbr; } if (cheklocval == 0) { if (memAllocGroup ((void **) (void *) &recvcnttab, (size_t) (dgrfptr->procglbnbr * sizeof (Gnum)), /* Allocated for non-roots too but don't care as these are very small */ &recvdsptab, (size_t) (dgrfptr->procglbnbr * sizeof (Gnum)), &vertloctax, (size_t) (vertlocnbr * sizeof (Gnum)), &edgeloctab, (size_t) (edgelocnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphGatherAll2: out of memory (3)"); cheklocval = 1; } } #ifdef SCOTCH_DEBUG_DGRAPH1 /* Communication cannot be merged with a useful one */ if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphGatherAll2: communication error (2)"); return (1); } #else /* SCOTCH_DEBUG_DGRAPH1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_DGRAPH1 */ if (chekglbval != 0) { if (recvcnttab != NULL) memFree (recvcnttab); if (cgrfptr->verttax != NULL) { if (cgrfptr->edgetax != NULL) memFree (cgrfptr->edgetax); /* Arrays are not based yet */ memFree (cgrfptr->verttax); } return (1); } if (cgrfptr != NULL) { verttax = cgrfptr->verttax - baseval; velotax = (dgrfptr->veloloctax != NULL) ? (cgrfptr->velotax - baseval) : NULL; vnumtax = (dgrfptr->vnumloctax != NULL) ? (cgrfptr->vnumtax - baseval) : NULL; vlbltax = (dgrfptr->vlblloctax != NULL) ? (cgrfptr->vlbltax - baseval) : NULL; edgetax = cgrfptr->edgetax - baseval; edlotax = (dgrfptr->edloloctax != NULL) ? (cgrfptr->edlotax - baseval) : NULL; cgrfptr->flagval = GRAPHFREEVERT | GRAPHVERTGROUP | GRAPHFREEEDGE | GRAPHEDGEGROUP; /* Other arrays are grouped, too */ cgrfptr->baseval = baseval; cgrfptr->vertnbr = dgrfptr->vertglbnbr; cgrfptr->vertnnd = dgrfptr->vertglbnbr + baseval; cgrfptr->verttax = verttax; cgrfptr->vendtax = verttax + 1; /* Compact edge array */ cgrfptr->velotax = velotax; cgrfptr->velosum = dgrfptr->veloglbsum; cgrfptr->vnumtax = vnumtax; cgrfptr->vlbltax = vlbltax; cgrfptr->edgenbr = dgrfptr->edgeglbnbr; cgrfptr->edgetax = edgetax; cgrfptr->edlotax = edlotax; cgrfptr->edlosum = edlosum; cgrfptr->degrmax = dgrfptr->degrglbmax; cgrfptr->proccomm = MPI_COMM_NULL; /* These fields exist only when compiled with SCOTCH_PTSCOTCH */ cgrfptr->procglbnbr = 1; /* Graph gathered on one single processor so no communicator */ cgrfptr->proclocnum = 0; } #ifdef SCOTCH_DEBUG_DGRAPH2 /* Prevent Valgrind from yelling */ else { /* Process is not root */ verttax = velotax = vlbltax = edgetax = edlotax = NULL; } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (dgrfptr->vendloctax == (dgrfptr->vertloctax + 1)) { /* If distributed graph is compact */ if (dgraphGatherAll3 (dgrfptr->vertloctax + baseval + 1, dgrfptr->vertlocnbr, /* Do not send first index, it is always equal to baseval */ verttax + 1, /* First index will always be equal to baseval too, and procdsptab holds based values */ dgrfptr->proccnttab, dgrfptr->procdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphGatherAll2: communication error (3)"); return (1); } if (cgrfptr != NULL) { Gnum procnum; verttax[baseval] = baseval; for (procnum = 1; procnum < dgrfptr->procglbnbr; procnum ++) { /* Adjust index sub-arrays for all processes except the first one */ Gnum vertnum; Gnum vertnnd; Gnum edgedlt; for (vertnum = dgrfptr->procdsptab[procnum] + 1, vertnnd = dgrfptr->proccnttab[procnum] + vertnum, edgedlt = verttax[vertnum - 1] - baseval; vertnum < vertnnd; vertnum ++) verttax[vertnum] += edgedlt; } } } else { /* Distributed graph is not compact */ Gnum vertlocnum; Gnum * restrict edgelocptr; vertloctax -= baseval; /* Base temporary vertex array */ for (vertlocnum = baseval, edgelocptr = edgeloctab; /* Build vertex send array */ vertlocnum < dgrfptr->vertlocnnd; vertlocnum ++) { Gnum edgelocnum; vertloctax[vertlocnum] = dgrfptr->vendloctax[vertlocnum] - dgrfptr->vertloctax[vertlocnum]; /* Get edge counts */ for (edgelocnum = dgrfptr->vertloctax[vertlocnum]; edgelocnum < dgrfptr->vendloctax[vertlocnum]; edgelocnum ++) *edgelocptr ++ = edgeloctax[edgelocnum]; } if (dgraphGatherAll3 (vertloctax + baseval, dgrfptr->vertlocnbr, verttax + 1, /* First index will always be equal to baseval, and procdsptab holds based values */ dgrfptr->proccnttab, dgrfptr->procdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphGatherAll2: communication error (4)"); return (1); } if (cgrfptr != NULL) { Gnum vertnum; Gnum edgenum; verttax[baseval] = baseval; for (vertnum = baseval + 1, edgenum = baseval; /* Create compact centralized vertex array */ vertnum <= cgrfptr->vertnnd; vertnum ++) { edgenum += verttax[vertnum]; verttax[vertnum] = edgenum; } #ifdef SCOTCH_DEBUG_DGRAPH2 if (verttax[cgrfptr->vertnnd] != (cgrfptr->edgenbr + baseval)) { errorPrint ("dgraphGatherAll2: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ } } if (dgrfptr->veloloctax != NULL) { if (dgraphGatherAll3 (dgrfptr->veloloctax + baseval, dgrfptr->vertlocnbr, velotax, /* Based array since procdsptab holds based values */ dgrfptr->proccnttab, dgrfptr->procdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphGatherAll2: communication error (6)"); return (1); } } if (dgrfptr->vnumloctax != NULL) { if (dgraphGatherAll3 (dgrfptr->vnumloctax + baseval, dgrfptr->vertlocnbr, vnumtax, /* Based array since procdsptab holds based values */ dgrfptr->proccnttab, dgrfptr->procdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphGatherAll2: communication error (5)"); return (1); } } if (dgrfptr->vlblloctax != NULL) { if (dgraphGatherAll3 (dgrfptr->vlblloctax + baseval, dgrfptr->vertlocnbr, vlbltax, /* Based array since procdsptab holds based values */ dgrfptr->proccnttab, dgrfptr->procdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphGatherAll2: communication error (7)"); return (1); } } if (cgrfptr != NULL) { Gnum procnum; Gnum edgenum; for (procnum = 0, edgenum = baseval; /* Build arrays for MPI_Gatherv on edge arrays */ procnum < dgrfptr->procglbnbr; procnum ++) { recvcnttab[procnum] = verttax[dgrfptr->procdsptab[procnum] + dgrfptr->proccnttab[procnum]] - verttax[dgrfptr->procdsptab[procnum]]; /* verttax used twice since centralized graph is compact */ recvdsptab[procnum] = edgenum; edgenum += recvcnttab[procnum]; } #ifdef SCOTCH_DEBUG_DGRAPH2 if ((recvdsptab[dgrfptr->procglbnbr - 1] + recvcnttab[dgrfptr->procglbnbr - 1]) != (cgrfptr->edgenbr + baseval)) { errorPrint ("dgraphGatherAll2: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ } if (dgrfptr->vendloctax == (dgrfptr->vertloctax + 1)) { /* If distributed graph is compact */ if (dgraphGatherAll3 (dgrfptr->edgeloctax + baseval, dgrfptr->edgelocnbr, /* Send global indices */ edgetax, /* Based array as recvdsptab holds based values */ recvcnttab, recvdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphGatherAll2: communication error (8)"); return (1); } if (dgrfptr->edloloctax != NULL) { if (dgraphGatherAll3 (dgrfptr->edloloctax + baseval, dgrfptr->edgelocnbr, edlotax, /* Based array as recvdsptab holds based values */ recvcnttab, recvdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphGatherAll2: communication error (9)"); return (1); } } } else { /* Distributed graph is not compact */ if (dgraphGatherAll3 (edgeloctab, dgrfptr->edgelocnbr, edgetax, /* Based array as recvdsptab holds based values */ recvcnttab, recvdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphGatherAll2: communication error (10)"); return (1); } if (dgrfptr->edloloctax != NULL) { Gnum vertlocnum; Gnum * restrict edlolocptr; for (vertlocnum = baseval, edlolocptr = edgeloctab; /* Recycle edge send array to build edge load send array */ vertlocnum < dgrfptr->vertlocnnd; vertlocnum ++) { Gnum edgelocnum; for (edgelocnum = dgrfptr->vertloctax[vertlocnum]; edgelocnum < dgrfptr->vendloctax[vertlocnum]; edgelocnum ++) *edlolocptr ++ = dgrfptr->edloloctax[edgelocnum]; } if (dgraphGatherAll3 (edgeloctab, dgrfptr->edgelocnbr, /* Send compacted edge load array */ edlotax, /* Based array as recvdsptab holds based values */ recvcnttab, recvdsptab, protnum, dgrfptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphGatherAll2: communication error (11)"); return (1); } } } if (cgrfptr != NULL) { if ((dgrfptr->procdsptab[dgrfptr->procglbnbr] != /* If graph has holes, relabel end vertices */ dgrfptr->procvrttab[dgrfptr->procglbnbr])) { Gnum procnum; for (procnum = 0; procnum < dgrfptr->procglbnbr; procnum ++) { /* Accelerate search per sender process */ Gnum vertlocmin; Gnum vertlocmax; Gnum vertlocadj; Gnum edgelocnum; Gnum edgelocnnd; vertlocmin = dgrfptr->procvrttab[procnum]; /* Initialize search accelerator */ vertlocmax = dgrfptr->procvrttab[procnum + 1]; vertlocadj = dgrfptr->procdsptab[procnum] - vertlocmin; for (edgelocnum = recvdsptab[procnum], edgelocnnd = edgelocnum + recvcnttab[procnum]; edgelocnum < edgelocnnd; edgelocnum ++) { Gnum vertlocend; vertlocend = cgrfptr->edgetax[edgelocnum]; if ((vertlocend >= vertlocmin) && /* If end vertex is local with respect to current process */ (vertlocend < vertlocmax)) cgrfptr->edgetax[edgelocnum] = vertlocend + vertlocadj; else { /* End vertex is not local */ int procngbmin; int procngbmax; for (procngbmin = 0, procngbmax = dgrfptr->procglbnbr; procngbmax - procngbmin > 1; ) { int procngbnum; procngbnum = (procngbmax + procngbmin) / 2; if (dgrfptr->procvrttab[procngbnum] <= vertlocend) procngbmin = procngbnum; else procngbmax = procngbnum; } cgrfptr->edgetax[edgelocnum] = vertlocend + dgrfptr->procdsptab[procngbmin] - dgrfptr->procvrttab[procngbmin]; } } } } if (cgrfptr->edlotax == NULL) /* If no edge loads */ cgrfptr->edlosum = cgrfptr->edgenbr; /* Edge load sum is trivial */ else { if (edlosum >= 0) /* If edge load sum already computed by library call */ cgrfptr->edlosum = edlosum; else { /* Compute it from scratch on every root process (small graph assumed) */ Gnum edgenum; Gnum edgennd; Gnum edlotmp; for (edgenum = cgrfptr->baseval, edgennd = edgenum + cgrfptr->edgenbr, edlotmp = 0; /* Edge load array is always compact */ edgenum < edgennd; edgenum ++) edlotmp += cgrfptr->edlotax[edgenum]; cgrfptr->edlosum = edlotmp; } } } memFree (recvcnttab); #ifdef SCOTCH_DEBUG_DGRAPH2 cheklocval = (cgrfptr != NULL) ? graphCheck (cgrfptr) : 0; if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dgrfptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphGatherAll2: communication error (12)"); return (1); } if (chekglbval != 0) { errorPrint ("dgraphGatherAll2: inconsistent centralized graph data"); if (cgrfptr != NULL) graphFree (cgrfptr); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ return (0); } /* This function gathers on all processes ** the pieces of a distributed graph to ** build a centralized graph. ** Since the resulting centralized graphs are ** supposed to be small in the general case, ** edlosum is computed without communication ** on each of the processors. ** It returns: ** - 0 : if graph data are consistent. ** - !0 : on error. */ int dgraphGatherAll ( const Dgraph * restrict const dgrfptr, /* Distributed graph */ Graph * restrict cgrfptr) /* Centralized graph */ { return (dgraphGatherAll2 (dgrfptr, cgrfptr, -1, -1)); } scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_ml.c0000644000175300017530000003545711631334325022611 0ustar hazelscthazelsct/* Copyright 2004,2007-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_ml.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Luca SCARANO (v3.1) **/ /** **/ /** FUNCTION : This module bipartitions an active **/ /** graph using a multi-level scheme. **/ /** **/ /** DATES : # Version 3.1 : from : 24 oct 1995 **/ /** to 19 sep 1996 **/ /** # Version 3.2 : from : 20 sep 1996 **/ /** to 13 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 12 mar 1999 **/ /** # Version 3.4 : from : 01 jun 2001 **/ /** to 01 jun 2001 **/ /** # Version 4.0 : from : 12 dec 2003 **/ /** to 20 mar 2005 **/ /** # Version 5.1 : from : 28 sep 2008 **/ /** to 27 mar 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BGRAPH_BIPART_ML #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "graph_coarsen.h" #include "arch.h" #include "bgraph.h" #include "bgraph_bipart_ml.h" #include "bgraph_bipart_st.h" /*********************************************/ /* */ /* The coarsening and uncoarsening routines. */ /* */ /*********************************************/ /* This routine builds a coarser graph from the ** graph that is given on input. The coarser ** graphs differ at this stage from classical ** active graphs as their internal gains are not ** yet computed. ** It returns: ** - 0 : if the coarse graph has been built. ** - 1 : if threshold reached or on error. */ static int bgraphBipartMlCoarsen ( const Bgraph * const finegrafptr, /*+ Finer graph +*/ Bgraph * restrict const coargrafptr, /*+ Coarser graph to build +*/ GraphCoarsenMulti * restrict * const coarmultptr, /*+ Pointer to multinode table to build +*/ const BgraphBipartMlParam * const paraptr) /*+ Method parameters +*/ { if (graphCoarsen (&finegrafptr->s, &coargrafptr->s, coarmultptr, paraptr->coarnbr, paraptr->coarrat, paraptr->coartype) != 0) return (1); /* Return if coarsening failed */ if (finegrafptr->veextax != NULL) { /* Merge external gains for coarsened vertices */ GraphCoarsenMulti * restrict coarmulttax; Gnum * restrict coarveextax; Gnum coarvertnum; const Gnum * restrict const fineveextax = finegrafptr->veextax; if ((coarveextax = (Gnum *) memAlloc (coargrafptr->s.vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("bgraphBipartMlCoarsen: out of memory"); graphExit (&coargrafptr->s); /* Only free Graph since veextab not allocated */ return (1); } coarveextax -= coargrafptr->s.baseval; coarmulttax = *coarmultptr; coargrafptr->s.flagval |= BGRAPHFREEVEEX; coargrafptr->veextax = coarveextax; for (coarvertnum = coargrafptr->s.baseval; coarvertnum < coargrafptr->s.vertnnd; coarvertnum ++) { Gnum finevertnum0; /* First multinode vertex */ Gnum finevertnum1; /* Second multinode vertex */ finevertnum0 = coarmulttax[coarvertnum].vertnum[0]; finevertnum1 = coarmulttax[coarvertnum].vertnum[1]; coarveextax[coarvertnum] = (finevertnum0 != finevertnum1) ? fineveextax[finevertnum0] + fineveextax[finevertnum1] : fineveextax[finevertnum0]; } } else /* If fine graph does not have external gains */ coargrafptr->veextax = NULL; /* Coarse graph does not have external gains */ coargrafptr->s.flagval |= BGRAPHFREEPART; /* Only part array will have to be freed, as frontier is shared */ coargrafptr->parttax = NULL; /* Do not allocate partition data yet */ coargrafptr->frontab = finegrafptr->frontab; /* Use frontier array of finer graph as coarse frontier array */ coargrafptr->compload0min = finegrafptr->compload0min; /* Only set constant partition parameters as others will be set on uncoarsening */ coargrafptr->compload0max = finegrafptr->compload0max; coargrafptr->compload0avg = finegrafptr->compload0avg; coargrafptr->commloadextn0 = finegrafptr->commloadextn0; coargrafptr->commgainextn0 = finegrafptr->commgainextn0; coargrafptr->domdist = finegrafptr->domdist; coargrafptr->domwght[0] = finegrafptr->domwght[0]; coargrafptr->domwght[1] = finegrafptr->domwght[1]; coargrafptr->levlnum = finegrafptr->levlnum + 1; return (0); } /* This routine propagates the bipartition of the ** coarser graph back to the finer graph, according ** to the multinode table of collapsed vertices. ** After the bipartition is propagated, it finishes ** to compute the parameters of the finer graph that ** were not computed at the coarsening stage. ** It returns: ** - 0 : if coarse graph data has been propagated to fine graph. ** - !0 : on error. */ static int bgraphBipartMlUncoarsen ( Bgraph * restrict const finegrafptr, /*+ Finer graph +*/ const Bgraph * const coargrafptr, /*+ Coarser graph +*/ const GraphCoarsenMulti * const coarmulttax) /*+ Pointer to multinode array +*/ { GraphPart * restrict fineparttax; Gnum finefronnbr; Gnum finecompsize1; const GraphPart * restrict coarparttax; Gnum coarvertnum; Gnum coarfronnum; Gnum * restrict coarfrontab; const Gnum * restrict const fineverttax = finegrafptr->s.verttax; /* Fast accesses */ const Gnum * restrict const finevendtax = finegrafptr->s.vendtax; const Gnum * restrict const fineedgetax = finegrafptr->s.edgetax; if (finegrafptr->parttax == NULL) { /* If partition array not yet allocated */ if ((finegrafptr->parttax = (GraphPart *) memAlloc (finegrafptr->s.vertnbr * sizeof (GraphPart))) == NULL) { errorPrint ("bgraphBipartMlUncoarsen: out of memory"); return (1); /* Allocated data will be freed along with graph structure */ } finegrafptr->parttax -= finegrafptr->s.baseval; } if (coargrafptr == NULL) { /* If no coarse graph provided */ bgraphZero (finegrafptr); /* Assign all vertices to part 0 */ return (0); } coarparttax = coargrafptr->parttax; coarfrontab = coargrafptr->frontab; /* TRICK: also equal to finefrontab */ fineparttax = finegrafptr->parttax; finecompsize1 = coargrafptr->s.vertnbr - coargrafptr->compsize0; /* Pre-allocate sizes */ for (coarvertnum = coargrafptr->s.baseval; coarvertnum < coargrafptr->s.vertnnd; coarvertnum ++) { Gnum finevertnum0; /* First multinode vertex */ Gnum finevertnum1; /* Second multinode vertex */ GraphPart partval; finevertnum0 = coarmulttax[coarvertnum].vertnum[0]; finevertnum1 = coarmulttax[coarvertnum].vertnum[1]; partval = coarparttax[coarvertnum]; fineparttax[finevertnum0] = partval; if (finevertnum0 != finevertnum1) { fineparttax[finevertnum1] = partval; finecompsize1 += partval; /* Account for extra vertices created in part 1 */ } } finegrafptr->compload0 = coargrafptr->compload0; finegrafptr->compload0dlt = coargrafptr->compload0dlt; finegrafptr->compsize0 = finegrafptr->s.vertnbr - finecompsize1; finegrafptr->commload = coargrafptr->commload; finegrafptr->commgainextn = coargrafptr->commgainextn; finegrafptr->bbalval = coargrafptr->bbalval; for (coarfronnum = 0, finefronnbr = coargrafptr->fronnbr; /* Re-cycle frontier array from coarse to fine graph */ coarfronnum < coargrafptr->fronnbr; coarfronnum ++) { Gnum coarvertnum; Gnum finevertnum0; /* First multinode vertex */ Gnum finevertnum1; /* Second multinode vertex */ coarvertnum = coarfrontab[coarfronnum]; finevertnum0 = coarmulttax[coarvertnum].vertnum[0]; finevertnum1 = coarmulttax[coarvertnum].vertnum[1]; if (finevertnum0 != finevertnum1) { /* If multinode si made of two distinct vertices */ GraphPart coarpartval; Gnum fineedgenum; coarpartval = coarparttax[coarvertnum]; #ifdef SCOTCH_DEBUG_BGRAPH2 coarfrontab[coarfronnum] = ~0; #endif /* SCOTCH_DEBUG_BGRAPH2 */ for (fineedgenum = fineverttax[finevertnum0]; fineedgenum < finevendtax[finevertnum0]; fineedgenum ++) { if (fineparttax[fineedgetax[fineedgenum]] != coarpartval) { /* If first vertex belongs to frontier */ coarfrontab[coarfronnum] = finevertnum0; /* Record it in lieu of the coarse frontier vertex */ break; } } if (fineedgenum >= finegrafptr->s.vendtax[finevertnum0]) { /* If first vertex not in frontier */ coarfrontab[coarfronnum] = finevertnum1; /* Then second vertex must be in frontier */ continue; /* Skip to next multinode */ } for (fineedgenum = fineverttax[finevertnum1]; /* Check if second vertex belong to frontier too */ fineedgenum < finevendtax[finevertnum1]; fineedgenum ++) { if (fineparttax[fineedgetax[fineedgenum]] != coarpartval) { /* If second vertex belongs to frontier */ coarfrontab[finefronnbr ++] = finevertnum1; /* Record it at the end of the recycled frontier array */ break; } } #ifdef SCOTCH_DEBUG_BGRAPH2 if (coarfrontab[coarfronnum] == ~0) { errorPrint ("bgraphBipartMlUncoarsen: internal error"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ } else /* If coarse vertex is single node */ coarfrontab[coarfronnum] = finevertnum0; /* Then it belongs to the frontier */ } finegrafptr->fronnbr = finefronnbr; #ifdef SCOTCH_DEBUG_BGRAPH2 if (bgraphCheck (finegrafptr) != 0) { errorPrint ("bgraphBipartMlUncoarsen: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ return (0); } /* This routine recursively performs the ** bipartitioning recursion. ** It returns: ** - 0 : if bipartitioning could be computed. ** - 1 : on error. */ static int bgraphBipartMl2 ( Bgraph * restrict const grafptr, /*+ Active graph +*/ const BgraphBipartMlParam * const paraptr) /*+ Method parameters +*/ { Bgraph coargrafdat; GraphCoarsenMulti * coarmultptr; int o; if (bgraphBipartMlCoarsen (grafptr, &coargrafdat, &coarmultptr, paraptr) == 0) { if (((o = bgraphBipartMl2 (&coargrafdat, paraptr)) == 0) && ((o = bgraphBipartMlUncoarsen (grafptr, &coargrafdat, coarmultptr)) == 0) && ((o = bgraphBipartSt (grafptr, paraptr->stratasc)) != 0)) /* Apply ascending strategy */ errorPrint ("bgraphBipartMl2: cannot apply ascending strategy"); bgraphExit (&coargrafdat); } else { if (((o = bgraphBipartMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ ((o = bgraphBipartSt (grafptr, paraptr->stratlow)) != 0)) /* Apply low strategy */ errorPrint ("bgraphBipartMl2: cannot apply low strategy"); } return (o); } /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the multi-level bipartitioning. ** It returns: ** - 0 : if bipartitioning could be computed. ** - 1 : on error. */ int bgraphBipartMl ( Bgraph * restrict const grafptr, /*+ Active graph +*/ const BgraphBipartMlParam * const paraptr) /*+ Method parameters +*/ { Gnum levlnum; /* Save value for graph level */ int o; levlnum = grafptr->levlnum; /* Save graph level */ grafptr->levlnum = 0; /* Initialize coarsening level */ o = bgraphBipartMl2 (grafptr, paraptr); /* Perform multi-level bipartitioning */ grafptr->levlnum = levlnum; /* Restore graph level */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_order.c0000644000175300017530000002505311631334325023470 0ustar hazelscthazelsct/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_order.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted graph ordering routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 25 apr 2006 **/ /** to 11 nov 2008 **/ /** # Version 5.1 : from : 29 mar 2010 **/ /** to 14 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "parser.h" #include "dgraph.h" #include "dorder.h" #include "hdgraph.h" #include "hdgraph_order_st.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the distributed graph ordering */ /* routines. */ /* */ /************************************/ /*+ This routine initializes an API ordering *** with respect to the given source graph *** and the locations of output parameters. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphOrderInit ( const SCOTCH_Dgraph * const grafptr, /*+ Distributed graph to order +*/ SCOTCH_Dordering * const ordeptr) /*+ Ordering structure to initialize +*/ { Dgraph * srcgrafptr; Dorder * srcordeptr; #ifdef SCOTCH_DEBUG_LIBRARY1 if (sizeof (SCOTCH_Dordering) < sizeof (Dorder)) { errorPrint ("SCOTCH_graphDorderInit: internal error"); return (1); } #endif /* SCOTCH_DEBUG_LIBRARY1 */ srcgrafptr = (Dgraph *) grafptr; /* Use structure as source graph */ srcordeptr = (Dorder *) ordeptr; return (dorderInit (srcordeptr, srcgrafptr->baseval, srcgrafptr->vertglbnbr, srcgrafptr->proccomm)); } /*+ This routine frees an API ordering. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_dgraphOrderExit ( const SCOTCH_Dgraph * const grafptr, SCOTCH_Dordering * const ordeptr) { dorderExit ((Dorder *) ordeptr); } /*+ This routine saves the contents of *** the given ordering to the given stream. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphOrderSave ( const SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ const SCOTCH_Dordering * const ordeptr, /*+ Ordering to save +*/ FILE * const stream) /*+ Output stream +*/ { return (dorderSave ((Dorder *) ordeptr, (Dgraph *) grafptr, stream)); } /*+ This routine computes an ordering *** of the API ordering structure with *** respect to the given strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphOrderCompute ( SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ SCOTCH_Dordering * const ordeptr, /*+ Ordering to compute +*/ SCOTCH_Strat * const stratptr) /*+ Ordering strategy +*/ { return (SCOTCH_dgraphOrderComputeList (grafptr, ordeptr, 0, NULL, stratptr)); } /*+ This routine computes a partial ordering *** of the listed vertices of the API ordering *** structure graph with respect to the given *** strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphOrderComputeList ( SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ SCOTCH_Dordering * const ordeptr, /*+ Ordering to compute +*/ const SCOTCH_Num listnbr, /*+ Number of vertices in list +*/ const SCOTCH_Num * const listtab, /*+ List of vertex indices to order +*/ SCOTCH_Strat * const stratptr) /*+ Ordering strategy +*/ { Dorder * srcordeptr; /* Pointer to ordering */ DorderCblk * srccblkptr; /* Initial column block */ Dgraph * restrict srcgrafptr; /* Pointer to scotch graph */ Hdgraph srcgrafdat; /* Halo source graph structure */ Gnum srclistnbr; /* Number of items in list */ Gnum * restrict srclisttab; /* Subgraph vertex list */ const Strat * ordstratptr; /* Pointer to ordering strategy */ srcgrafptr = (Dgraph *) grafptr; #ifdef SCOTCH_DEBUG_DGRAPH2 if (dgraphCheck (srcgrafptr) != 0) { errorPrint ("SCOTCH_dgraphOrderComputeList: invalid input graph"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (*((Strat **) stratptr) == NULL) /* Set default ordering strategy if necessary */ SCOTCH_stratDgraphOrderBuild (stratptr, SCOTCH_STRATQUALITY, srcgrafptr->procglbnbr, 0.2); ordstratptr = *((Strat **) stratptr); if (ordstratptr->tabl != &hdgraphorderststratab) { errorPrint ("SCOTCH_dgraphOrderComputeList: not a distributed ordering strategy"); return (1); } srcgrafdat.s = *srcgrafptr; /* Copy non-halo graph data */ srcgrafdat.s.edloloctax = NULL; /* Never mind about edge loads */ srcgrafdat.vhallocnbr = 0; /* No halo on graph */ srcgrafdat.vhndloctax = srcgrafdat.s.vendloctax; srcgrafdat.ehallocnbr = 0; srcgrafdat.levlnum = 0; srcordeptr = (Dorder *) ordeptr; /* Get ordering */ srclistnbr = (Gnum) listnbr; /* Build vertex list */ srclisttab = (Gnum *) listtab; /* TODO: Take list into account */ dorderFree (srcordeptr); /* Clean all existing ordering data */ if ((srccblkptr = dorderFrst (srcordeptr)) == NULL) { errorPrint ("SCOTCH_dgraphOrderComputeList: cannot create root column block"); return (1); } hdgraphOrderSt (&srcgrafdat, srccblkptr, ordstratptr); dorderDispose (srccblkptr); srcgrafptr->flagval |= srcgrafdat.s.flagval & (DGRAPHFREEEDGEGST | DGRAPHHASEDGEGST); srcgrafptr->edgegsttax = srcgrafdat.s.edgegsttax; /* Get edge ghost array from working graph if it gained one */ *srcgrafptr = srcgrafdat.s; /* Get back Dgraph structure, possibly updated (additional ghost data arrays) */ return (0); } /*+ This routine parses the given *** distributed graph ordering strategy. *** It returns: *** - 0 : if string successfully scanned. *** - !0 : on error. +*/ int SCOTCH_stratDgraphOrder ( SCOTCH_Strat * const stratptr, const char * const string) { if (*((Strat **) stratptr) != NULL) stratExit (*((Strat **) stratptr)); if ((*((Strat **) stratptr) = stratInit (&hdgraphorderststratab, string)) == NULL) { errorPrint ("SCOTCH_stratDgraphOrder: error in ordering strategy"); return (1); } return (0); } /*+ This routine provides predefined *** ordering strategies. *** It returns: *** - 0 : if string successfully initialized. *** - !0 : on error. +*/ int SCOTCH_stratDgraphOrderBuild ( SCOTCH_Strat * const stratptr, /*+ Strategy to create +*/ const SCOTCH_Num flagval, /*+ Desired characteristics +*/ const SCOTCH_Num procnbr, /*+ Number of processes for running +*/ const double balrat) /*+ Desired imbalance ratio +*/ { char bufftab[8192]; /* Should be enough */ char bbaltab[32]; char verttab[32]; Gnum vertnbr; vertnbr = MAX (2000 * procnbr, 10000); vertnbr = MIN (vertnbr, 1000000); sprintf (verttab, GNUMSTRING, vertnbr); strcpy (bufftab, "n{sep=m{vert=,asc=b{width=3,strat=q{strat=f}},low=q{strat=h},vert=100,dvert=10,dlevl=0,proc=1,seq=q{strat=m{type=h,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=h{pass=10}f{bal=}}}}},ole=q{strat=n{sep=/(vert>120)?m{type=h,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=h{pass=10}f{bal=}}};,ole=f{cmin=15,cmax=100000,frat=0.0},ose=g}},ose=s,osq=n{sep=/(vert>120)?m{type=h,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=h{pass=10}f{bal=}}};,ole=f{cmin=15,cmax=100000,frat=0.0},ose=g}}"); sprintf (bbaltab, "%lf", balrat); stringSubst (bufftab, "", bbaltab); stringSubst (bufftab, "", verttab); if (SCOTCH_stratDgraphOrder (stratptr, bufftab) != 0) { errorPrint ("SCOTCH_stratDgraphOrderBuild: error in parallel ordering strategy"); return (1); } return (0); } scotch-5.1.12b.dfsg/src/libscotch/order.c0000644000175300017530000002404511631334325020417 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : order.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles generic orderings. **/ /** **/ /** DATES : # Version 3.2 : from : 19 oct 1996 **/ /** to 27 aug 1998 **/ /** # Version 4.0 : from : 19 dec 2001 **/ /** to 26 dec 2004 **/ /** # Version 5.0 : from : 25 jul 2007 **/ /** to 25 jul 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ORDER #include "module.h" #include "common.h" #include "graph.h" #include "order.h" /************************************/ /* */ /* These routines handle orderings. */ /* */ /************************************/ /* This routine initializes an ordering ** with respect to a given source graph. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int orderInit ( Order * restrict const ordeptr, const Gnum baseval, const Gnum vnodnbr, Gnum * restrict const peritab) { ordeptr->flagval = ORDERNONE; ordeptr->baseval = baseval; ordeptr->vnodnbr = vnodnbr; ordeptr->treenbr = /* Initialize a simple blocking */ ordeptr->cblknbr = 1; ordeptr->cblktre.typeval = ORDERCBLKOTHR; ordeptr->cblktre.vnodnbr = vnodnbr; ordeptr->cblktre.cblknbr = 0; ordeptr->cblktre.cblktab = NULL; ordeptr->peritab = peritab; if (ordeptr->peritab == NULL) { /* Inverse permutation must be allocated */ ordeptr->flagval |= ORDERFREEPERI; /* Flag it so it will be freed */ if ((ordeptr->peritab = (Gnum *) memAlloc (vnodnbr * sizeof (Gnum))) == NULL) { errorPrint ("orderInit: out of memory"); return (1); } } #ifdef SCOTCH_DEBUG_ORDER2 memSet (ordeptr->peritab, ~0, vnodnbr * sizeof (Gnum)); #endif /* SCOTCH_DEBUG_ORDER2 */ return (0); } /* This routine frees the contents ** of the given ordering. ** It returns: ** - 0 : on success. ** - !0 : on error. */ void orderExit ( Order * restrict const ordeptr) { if (ordeptr->cblktre.cblktab != NULL) /* Free column block tree */ orderExit2 (ordeptr->cblktre.cblktab, ordeptr->cblktre.cblknbr); if ((ordeptr->peritab != NULL) && ((ordeptr->flagval & ORDERFREEPERI) != 0)) /* If peritab is group leader */ memFree (ordeptr->peritab); /* Free group leader */ #ifdef SCOTCH_DEBUG_ORDER2 memSet (ordeptr, ~0, sizeof (Order)); #endif /* SCOTCH_DEBUG_ORDER2 */ } static void orderExit2 ( OrderCblk * restrict const cblktab, const Gnum cblknbr) { Gnum cblknum; for (cblknum = 0; cblknum < cblknbr; cblknum ++) { if (cblktab[cblknum].cblktab != NULL) orderExit2 (cblktab[cblknum].cblktab, cblktab[cblknum].cblknbr); } memFree (cblktab); } /* This routine computes the inverse permutation ** of the given permutation, according to the ** direct and inverse base values. ** It returns: ** - VOID : in all cases. */ void orderPeri ( const Gnum * restrict const permtab, /* Permutation to invert */ const Gnum permbas, /* Permutation base value */ const Gnum permnbr, /* Number of permutation indices */ Gnum * restrict const peritab, /* Array of inverse permutation */ const Gnum peribas) /* Base value of inverse permutation */ { Gnum permnum; for (permnum = 0; permnum < permnbr; permnum ++) peritab[permtab[permnum] - permbas] = permnum + peribas; } /* This routine computes the column block ** range array of the given ordering. ** It returns: ** - VOID : in all cases. */ void orderRang ( const Order * restrict const ordeptr, /* Ordering */ Gnum * restrict const rangtab) /* Column block range array [+1] */ { Gnum * rangptr; Gnum ordenum; rangptr = rangtab; /* Set beginning of range array */ ordenum = ordeptr->baseval; /* Set initial number */ orderRang2 (&rangptr, &ordenum, &ordeptr->cblktre); *rangptr = ordenum; /* Set end of range array */ } static void orderRang2 ( Gnum ** restrict const rangppt, Gnum * restrict const ordeppt, const OrderCblk * restrict const cblkptr) { Gnum cblknum; #ifdef SCOTCH_DEBUG_ORDER2 Gnum * restrict rangtmp; if (cblkptr->vnodnbr < 1) errorPrint ("orderRang2: internal error (1)"); #endif /* SCOTCH_DEBUG_ORDER2 */ if (cblkptr->cblktab == NULL) { /* If leaf of column block tree */ *(*rangppt) ++ = *ordeppt; /* Set beginning of column block */ *ordeppt += cblkptr->vnodnbr; /* Advance by column block size */ } else { #ifdef SCOTCH_DEBUG_ORDER2 rangtmp = *rangppt; #endif /* SCOTCH_DEBUG_ORDER2 */ for (cblknum = 0; cblknum < cblkptr->cblknbr; cblknum ++) orderRang2 (rangppt, ordeppt, &cblkptr->cblktab[cblknum]); #ifdef SCOTCH_DEBUG_ORDER2 if ((*ordeppt - *rangtmp) != cblkptr->vnodnbr) errorPrint ("orderRang2: internal error (2)"); #endif /* SCOTCH_DEBUG_ORDER2 */ } } /* This routine computes the separator tree ** array of the given ordering. ** It returns: ** - VOID : in all cases. */ void orderTree ( const Order * restrict const ordeptr, /* Ordering */ Gnum * restrict const treetab) /* Column block separator tree array */ { Gnum cblanum; cblanum = ordeptr->cblknbr + ordeptr->baseval - 1; /* Set number of last column block */ orderTree2 (treetab - ordeptr->baseval, &cblanum, &ordeptr->cblktre, -1); #ifdef SCOTCH_DEBUG_ORDER2 if (cblanum != ordeptr->baseval - 1) errorPrint ("orderTree: internal error"); #endif /* SCOTCH_DEBUG_ORDER2 */ } static void orderTree2 ( Gnum * restrict const treetax, /* Based access to tree table */ Gnum * restrict const cblaptr, /* Pointer to current number of last column block, in descending order */ const OrderCblk * restrict const cblkptr, /* Current column block tree node */ Gnum cbfanum) /* Current number of ancestor separator column block */ { #ifdef SCOTCH_DEBUG_ORDER2 if (cblkptr->vnodnbr < 1) errorPrint ("orderTree2: internal error (1)"); #endif /* SCOTCH_DEBUG_ORDER2 */ if (cblkptr->cblktab == NULL) /* If leaf of column block tree */ treetax[(*cblaptr) --] = cbfanum; /* Set its ancestor */ else { /* Node has sub-nodes */ Gnum cblknum; cblknum = cblkptr->cblknbr - 1; /* Assume all column blocks will be scanned */ if ((cblkptr->cblknbr == 3) && /* If node is a nested dissection node */ (cblkptr->typeval == ORDERCBLKNEDI)) { /* With a non-empty separator */ Gnum cblanum; cblanum = *cblaptr; /* Save number of last column block of separator */ orderTree2 (treetax, cblaptr, &cblkptr->cblktab[cblknum], cbfanum); /* Scan separator apart */ cbfanum = cblanum; /* Separator becomes most recent ancestor of parts */ cblknum = 1; /* Only scan the two parts, not the separator */ } for ( ; cblknum >= 0; cblknum --) { orderTree2 (treetax, cblaptr, &cblkptr->cblktab[cblknum], cbfanum); #ifdef SCOTCH_DEBUG_ORDER2 if (*cblaptr < -1) errorPrint ("orderTree2: internal error (2)"); #endif /* SCOTCH_DEBUG_ORDER2 */ } } } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_coarsen.c0000644000175300017530000001073411631334325024007 0ustar hazelscthazelsct/* Copyright 2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_coarsen.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the **/ /** distributed graph coarsening routine of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.1 : from : 07 aug 2011 **/ /** to 07 aug 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_coarsen.h" #include "scotch.h" /************************************/ /* */ /* This routine is the C API for */ /* the distributed graph coarsening */ /* routine. */ /* */ /************************************/ /*+ This routine creates a distributed coarse graph *** from the given fine graph, unless the coarse graph *** is smaller than some threshold size or the *** coarsening ratio is above some other threshold. *** If the coarse graph is created, a coarse-to-fine *** vertex array is created, that contains a pair of *** fine indices for each coarse index. It is the *** user's responsibility to free this array when it *** is no longer needed. *** It returns: *** - 0 : if the graph has been coarsened. *** - 1 : if the graph could not be coarsened. *** - 2 : on error. +*/ int SCOTCH_dgraphCoarsen ( SCOTCH_Dgraph * restrict const finegrafptr, /* Fine graph structure to fill */ SCOTCH_Dgraph * restrict const coargrafptr, /* Coarse graph */ SCOTCH_Num * restrict const multloctab, /* Pointer to multinode array */ const SCOTCH_Num coarnbr, /* Minimum number of coarse vertices */ const double coarrat) /* Maximum contraction ratio */ { DgraphCoarsenMulti * restrict multlocptr; int o; o = dgraphCoarsen ((Dgraph * restrict const) finegrafptr, (Dgraph * restrict const) coargrafptr, &multlocptr, 5, coarnbr, 0, 0, coarrat); if (o == 0) { /* If coarsening succeeded */ SCOTCH_Num coarvertnbr; SCOTCH_dgraphSize (coargrafptr, NULL, &coarvertnbr, NULL, NULL); /* Get number of local coarse vertices */ memCpy (multloctab, multlocptr, coarvertnbr * 2 * sizeof (Gnum)); } return (o); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_stat_f.c0000644000175300017530000001036111631334325023631 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_stat_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the distributed source graph analyzing **/ /** routine of the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 24 jun 2007 **/ /** to 24 jun 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the graph handling routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFDGRAPHSTAT, scotchfdgraphstat, ( \ const SCOTCH_Dgraph * const grafptr, \ SCOTCH_Num * const velominptr, \ SCOTCH_Num * const velomaxptr, \ SCOTCH_Num * const velosumptr, \ double * veloavgptr, \ double * velodltptr, \ SCOTCH_Num * const degrminptr, \ SCOTCH_Num * const degrmaxptr, \ double * degravgptr, \ double * degrdltptr, \ SCOTCH_Num * const edlominptr, \ SCOTCH_Num * const edlomaxptr, \ SCOTCH_Num * const edlosumptr, \ double * edloavgptr, \ double * edlodltptr, \ int * const revaptr), \ (grafptr, velominptr, velomaxptr, velosumptr, \ veloavgptr, velodltptr, degrminptr, \ degrmaxptr, degravgptr, degrdltptr, \ edlominptr, edlomaxptr, edlosumptr, \ edloavgptr, edlodltptr, revaptr)) { *revaptr = SCOTCH_dgraphStat (grafptr, velominptr, velomaxptr, velosumptr, veloavgptr, velodltptr, degrminptr, degrmaxptr, degravgptr, degrdltptr, edlominptr, edlomaxptr, edlosumptr, edloavgptr, edlodltptr); } scotch-5.1.12b.dfsg/src/libscotch/bdgraph.c0000644000175300017530000001741011631334325020711 0ustar hazelscthazelsct/* Copyright 2007,2008,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph.c **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the distributed **/ /** bipartitioning graph data structure **/ /** handling routines. **/ /** **/ /** DATES : # Version 5.1 : from : 10 sep 2007 **/ /** to 14 apr 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BDGRAPH #include "module.h" #include "common.h" #include "arch.h" #include "dgraph.h" #include "dmapping.h" #include "bdgraph.h" /*************************************/ /* */ /* These routines handle distributed */ /* bipartition graphs. */ /* */ /*************************************/ /* This routine builds the active graph ** corresponding to the given bipartitioning ** job parameters. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int bdgraphInit ( Bdgraph * restrict const actgrafptr, /* Active graph */ const Dgraph * restrict const indgrafptr, /* Induced source subdgraph */ const Dgraph * restrict const srcgrafptr, /* Original source graph */ const Arch * restrict const archptr, /* Current mapping of halo vertices */ const ArchDom domsubtab[]) /* Subdomains */ { Anum domdist; /* Distance between both subdomains */ Anum domwght0; /* Processor workforce in each domain */ Anum domwght1; domdist = archDomDist (archptr, &domsubtab[0], &domsubtab[1]); /* Get distance between subdomains */ domwght0 = archDomWght (archptr, &domsubtab[0]); /* Get weights of subdomains */ domwght1 = archDomWght (archptr, &domsubtab[1]); actgrafptr->s = *indgrafptr; /* Get source graph data */ actgrafptr->s.flagval &= ~DGRAPHFREEALL; /* Do not free contents of separation graph */ actgrafptr->s.vlblloctax = NULL; /* Never mind about vertex labels in the future */ actgrafptr->veexloctax = NULL; /* No external gain (yet) */ actgrafptr->veexglbsum = 0; actgrafptr->partgsttax = NULL; /* Do not allocate frontier arrays yet */ actgrafptr->fronloctab = NULL; bdgraphInit2 (actgrafptr, domdist, domwght0, domwght1); /* TODO: Compute external gains */ #ifdef SCOTCH_DEBUG_BDGRAPH2 if (bdgraphCheck (actgrafptr) != 0) { errorPrint ("bdgraphInit: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ return (0); } void bdgraphInit2 ( Bdgraph * restrict const actgrafptr, /* Active graph */ const Anum domdist, /* Distance between both subdomains */ const Anum domwght0, /* Processor workforce in each domain */ const Anum domwght1) { actgrafptr->fronlocnbr = /* No frontier vertices */ actgrafptr->fronglbnbr = 0; actgrafptr->complocload0 = actgrafptr->s.velolocsum; actgrafptr->compglbload0 = actgrafptr->s.veloglbsum; actgrafptr->compglbload0min = 0; /* No external constraints on bipartition (yet) */ actgrafptr->compglbload0max = actgrafptr->s.veloglbsum; actgrafptr->compglbload0avg = (Gnum) (((double) actgrafptr->s.veloglbsum * (double) domwght0) / (double) (domwght0 + domwght1)); actgrafptr->compglbload0dlt = actgrafptr->s.veloglbsum - actgrafptr->compglbload0avg; actgrafptr->complocsize0 = actgrafptr->s.vertlocnbr; actgrafptr->compglbsize0 = actgrafptr->s.vertglbnbr; actgrafptr->commglbload = 0; actgrafptr->commglbloadextn0 = 0; actgrafptr->commglbgainextn = 0; actgrafptr->commglbgainextn0 = 0; actgrafptr->domdist = domdist; actgrafptr->domwght[0] = domwght0; actgrafptr->domwght[1] = domwght1; actgrafptr->levlnum = 0; } /* This routine frees the contents ** of the given distributed active graph. ** It returns: ** - VOID : in all cases. */ void bdgraphExit ( Bdgraph * const grafptr) { if (grafptr->partgsttax != NULL) memFree (grafptr->partgsttax + grafptr->s.baseval); if (grafptr->fronloctab != NULL) memFree (grafptr->fronloctab); if (grafptr->veexloctax != NULL) memFree (grafptr->veexloctax + grafptr->s.baseval); dgraphExit (&grafptr->s); /* Free distributed source graph and its private data (flagval may be corrupted afterwards) */ #ifdef SCOTCH_DEBUG_BDGRAPH2 memSet (grafptr, ~0, sizeof (Bdgraph)); #endif /* SCOTCH_DEBUG_BDGRAPH2 */ } /* This routine moves all of the graph ** vertices to the first part. ** It returns: ** - VOID : in all cases. */ void bdgraphZero ( Bdgraph * const grafptr) { if (grafptr->partgsttax != NULL) memSet (grafptr->partgsttax + grafptr->s.baseval, 0, grafptr->s.vertgstnbr * sizeof (GraphPart)); /* Set all local and ghost vertices to part 0 */ grafptr->fronlocnbr = /* No frontier vertices */ grafptr->fronglbnbr = 0; grafptr->complocload0 = grafptr->s.velolocsum; grafptr->compglbload0 = grafptr->s.veloglbsum; grafptr->compglbload0dlt = grafptr->s.veloglbsum - grafptr->compglbload0avg; grafptr->complocsize0 = grafptr->s.vertlocnbr; grafptr->compglbsize0 = grafptr->s.vertglbnbr; grafptr->commglbload = grafptr->commglbloadextn0; grafptr->commglbgainextn = grafptr->commglbgainextn0; } scotch-5.1.12b.dfsg/src/libscotch/mapping.h0000644000175300017530000001504511631334325020744 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mapping.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the declarations for **/ /** the mapping handling routines. **/ /** **/ /** DATES : # Version 0.0 : from : 15 dec 1992 **/ /** to 01 apr 1993 **/ /** # Version 1.0 : from : 04 oct 1993 **/ /** to 06 oct 1993 **/ /** # Version 1.1 : from : 15 oct 1993 **/ /** to 15 oct 1993 **/ /** # Version 1.3 : from : 09 apr 1994 **/ /** to 11 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 02 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to 18 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 04 jul 1995 **/ /** # Version 3.1 : from : 30 oct 1995 **/ /** to 06 jun 1996 **/ /** # Version 3.2 : from : 23 aug 1996 **/ /** to 26 may 1998 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to 30 mar 1999 **/ /** # Version 4.0 : from : 11 dec 2001 **/ /** to 13 nov 2005 **/ /** # Version 5.1 : from : 25 jun 2008 **/ /** to 04 nov 2010 **/ /** **/ /** NOTES : # While Anum and Gnum are different **/ /** types, because architectures are **/ /** most often much smaller than **/ /** than graphs and require smaller **/ /** integer ranges, for interface **/ /** consistency reasons as well as for **/ /** variable-sized architecture handling, **/ /** they will always amount to the same **/ /** type. **/ /** **/ /************************************************************/ #define MAPPING_H /* ** The type definitions. */ /*+ This structure defines an (eventually partial) mapping of a source graph to a target architecture. +*/ typedef struct Mapping_ { Gnum baseval; /*+ Base value for structures +*/ Gnum vertnbr; /*+ Number of vertices in mapping +*/ Anum * parttax; /*+ Mapping array [vertnbr] +*/ ArchDom * domntab; /*+ Array of domains [termmax] +*/ Anum domnnbr; /*+ Current number of domains +*/ Anum domnmax; /*+ Maximum number of domains +*/ Arch archdat; /*+ Architecture data +*/ ArchDom domnorg; /*+ Initial (sub)domain +*/ } Mapping; /*+ The target architecture sort structure, used to sort vertices by increasing label value. +*/ typedef struct MappingSort_ { Anum labl; /*+ Target architecture vertex label +*/ Anum peri; /*+ Inverse permutation +*/ } MappingSort; /* ** The function prototypes. */ #ifndef MAPPING #define static #endif int mapInit (Mapping * restrict const, const Gnum, const Gnum, const Arch * restrict const); int mapInit2 (Mapping * restrict const, const Gnum, const Gnum, const Arch * restrict const, const ArchDom * restrict const); void mapExit (Mapping * const); int mapLoad (Mapping * restrict const, const Gnum * restrict const, FILE * restrict const); int mapSave (const Mapping * restrict const, const Gnum * restrict const, FILE * restrict const); int mapView (const Mapping * restrict const, const Graph * restrict const, FILE * const); #undef static /* ** The macro definitions. */ #define mapDomain(map,idx) (&((map)->domntab[(map)->parttax[(idx)]])) scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_scatter_f.c0000644000175300017530000000630611631334325024327 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_scatter_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the distributed source graph handling **/ /** routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 16 feb 2007 **/ /** to 12 jul 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the distributed graph handling */ /* routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFDGRAPHSCATTER, scotchfdgraphscatter, ( \ SCOTCH_Dgraph * const dgrfptr, \ SCOTCH_Graph * const cgrfptr, \ int * const revaptr), \ (dgrfptr, cgrfptr, revaptr)) { *revaptr = SCOTCH_dgraphScatter (dgrfptr, cgrfptr); } scotch-5.1.12b.dfsg/src/libscotch/mesh_coarsen.h0000644000175300017530000001251411631334325021755 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mesh_coarsen.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the source mesh coarsening **/ /** functions. **/ /** **/ /** DATES : # Version 4.0 : from : 19 oct 2003 **/ /** to 04 feb 2004 **/ /** **/ /************************************************************/ /* ** The defines. */ /** Prime number for cache-friendly perturbations. **/ #define MESHCOARSENPERTPRIME 31 /* Prime number */ /** Prime number for hashing vertex numbers. **/ #define MESHCOARSENHASHPRIME 17 /* Prime number */ /* ** The type and structure definitions. */ /*+ Here are the edge matching function types for coarsening. +*/ typedef enum MeshCoarsenType_ { MESHCOARSENNGB, /*+ Most neighbors matching +*/ MESHCOARSENNBR /*+ Number of matching types +*/ } MeshCoarsenType; /*+ A table made of such elements is used during coarsening to build the edge array of the new mesh, after the labeling of the vertices. +*/ typedef struct MeshCoarsenMult_ { Gnum finevelmnum[2]; } MeshCoarsenMult; /*+ A table made of such cells is used during coarsening to build the edge array of the elements of the new mesh. +*/ typedef struct MeshCoarsenHngb_ { Gnum coarvelmnum; /*+ Coarse origin element vertex (i.e. pass) number +*/ Gnum coarvnodnum; /*+ Neighbor fine node vertex number +*/ } MeshCoarsenHngb; /*+ A table made of such cells is used during coarsening to detect and merge bridge nodes, that is, nodes that connect only two coarse nodes together. +*/ typedef struct MeshCoarsenHbdg_ { Gnum coarvelmnum; /*+ Coarse origin element vertex (i.e. pass) number +*/ Gnum coarvelmend; /*+ Coarse end element vertex number +*/ Gnum coarvnodnum; /*+ Number of connecting coarse node +*/ } MeshCoarsenHbdg; /*+ A table made of such elements is used during coarsening to build the edge array of the new mesh, after the labeling of the vertices. +*/ typedef struct MeshCoarsenNgHash_ { Gnum velmnum; /*+ Origin element vertex (i.e. pass) number +*/ Gnum velmend; /*+ End element vertex number in fine mesh +*/ Gnum vnngnbr; /*+ Number of shared neighboring node vertices +*/ Gnum vnbgnbr; /*+ Number of bridge neighboring node vertices +*/ } MeshCoarsenNgHash; /* ** The function prototypes. */ #ifndef MESH_COARSEN #define static #endif int meshCoarsen (const Mesh * restrict const, Mesh * restrict const, Gnum * restrict * const, const Gnum, const double, const MeshCoarsenType); static void meshCoarsenMatchNg (const Mesh * restrict const, MeshCoarsenMult * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_dorder.c0000644000175300017530000000622511631334325022307 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dorder.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains miscellaneous **/ /** routines for handling distributed **/ /** graph orderings. **/ /** **/ /** DATES : # Version 5.1 : from : 17 nov 2010 **/ /** to 17 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /*****************************************/ /* */ /* These routines are the C API for */ /* ordering structure handling routines. */ /* */ /*****************************************/ /*+ This routine reserves a memory area *** of a size sufficient to store a *** distributed ordering structure. *** It returns: *** - !NULL : if the initialization succeeded. *** - NULL : on error. +*/ SCOTCH_Dordering * SCOTCH_dorderAlloc () { return ((SCOTCH_Dordering *) memAlloc (sizeof (SCOTCH_Dordering))); } scotch-5.1.12b.dfsg/src/libscotch/mesh_graph.h0000644000175300017530000000606311631334325021426 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mesh_graph.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the source mesh to source graph **/ /** building routine. **/ /** **/ /** DATES : # Version 4.0 : from : 13 oct 2003 **/ /** to 13 oct 2003 **/ /** **/ /************************************************************/ /* ** The defines. */ /** Prime number for cache-friendly perturbations. **/ #define MESHGRAPHHASHPRIME 37 /* Prime number */ /* ** The type and structure definitions. */ /*+ A table made of such elements is used during graph building to build the edge array of the graph from the one of the mesh. +*/ typedef struct MeshGraphHash_ { Gnum vertnum; /*+ Origin vertex (i.e. pass) number in mesh +*/ Gnum vertend; /*+ End vertex number in mesh +*/ } MeshGraphHash; scotch-5.1.12b.dfsg/src/libscotch/graph_induce.c0000644000175300017530000004313311631334325021733 0ustar hazelscthazelsct/* Copyright 2004,2007-2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_induce.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the source graph **/ /** subgraph-making functions. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to 18 may 1993 **/ /** # Version 1.3 : from : 30 apr 1994 **/ /** to 18 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 31 oct 1994 **/ /** # Version 3.0 : from : 07 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 28 nov 1995 **/ /** to 08 jun 1996 **/ /** # Version 3.2 : from : 07 sep 1996 **/ /** to 17 sep 1998 **/ /** # Version 4.0 : from : 28 nov 2001 **/ /** to 17 apr 2006 **/ /** # Version 5.0 : from : 14 dec 2006 **/ /** to 11 jun 2008 **/ /** # Version 5.1 : from : 01 jan 2009 **/ /** to 01 jan 2009 **/ /** **/ /** NOTES : # Several algorithms, such as the **/ /** active graph building routine of **/ /** bgraphInit2, assume that, for every **/ /** vertex, remaining edges will be kept **/ /** in the same order as in the original **/ /** graph. This must be enforced. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GRAPH #define GRAPH_INDUCE #include "module.h" #include "common.h" #include "graph.h" #include "graph_induce.h" /****************************************/ /* */ /* These routines handle source graphs. */ /* */ /****************************************/ /* This routine builds the graph induced ** by the original graph and the list of ** selected vertices. ** The induced vnumtab array is the list ** array if the original graph does not have ** a vnumtab, or the proper subset of the ** original vnumtab else. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int graphInduceList ( const Graph * restrict const orggrafptr, const VertList * restrict const indlistptr, Graph * restrict const indgrafptr) { Gnum * restrict orgindxtax; /* Based access to vertex translation array */ Gnum indvertnbr; /* Number of vertices in induced graph */ Gnum indvertnum; /* Number of current vertex in induced graph */ Gnum * restrict indedgetab; /* Pointer to pre-allocated edge array */ Gnum indedgenbr; /* (Approximate) number of edges in induced graph */ memSet (indgrafptr, 0, sizeof (Graph)); /* Initialize graph fields */ indgrafptr->flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; indgrafptr->baseval = orggrafptr->baseval; indvertnbr = indlistptr->vnumnbr; if (orggrafptr->velotax != NULL) { if (memAllocGroup ((void **) (void *) &indgrafptr->verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)), &indgrafptr->vnumtax, (size_t) ( indvertnbr * sizeof (Gnum)), &indgrafptr->velotax, (size_t) ( indvertnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("graphInduceList: out of memory (1)"); return (1); /* Nothing to free because group allocation failed */ } indgrafptr->velotax -= indgrafptr->baseval; } else { if (memAllocGroup ((void **) (void *) &indgrafptr->verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)), &indgrafptr->vnumtax, (size_t) ( indvertnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("graphInduceList: out of memory (2)"); return (1); } } indgrafptr->verttax -= indgrafptr->baseval; /* Adjust base of arrays */ indgrafptr->vnumtax -= indgrafptr->baseval; indgrafptr->vertnbr = indvertnbr; indgrafptr->vertnnd = indvertnbr + indgrafptr->baseval; indedgenbr = orggrafptr->edgenbr; /* Choose best upper bound on number of edges (avoid multiply overflow) */ if ((orggrafptr->degrmax > 0) && (indvertnbr < (indedgenbr / orggrafptr->degrmax))) indedgenbr = indvertnbr * orggrafptr->degrmax; if (orggrafptr->edlotax != NULL) /* If graph has edge weights */ indedgenbr *= 2; /* Account for edge weights */ if (memAllocGroup ((void *) &indedgetab, (size_t) (indedgenbr * sizeof (Gnum)), /* Pre-allocate space for edgetab (and edlotab) */ &orgindxtax, (size_t) (orggrafptr->vertnbr * sizeof (Gnum)), NULL) == NULL) { /* orgindxtab is at the end of the heap */ errorPrint ("graphInduceList: out of memory (3)"); graphExit (indgrafptr); return (1); } /* TODO: Vertex list can be kept as it is the one of *graphOrderNd */ memCpy (indgrafptr->vnumtax + indgrafptr->baseval, /* Copy vertex number array from list */ indlistptr->vnumtab, indvertnbr * sizeof (Gnum)); memSet (orgindxtax, ~0, orggrafptr->vertnbr * sizeof (Gnum)); /* Preset index array */ orgindxtax -= orggrafptr->baseval; for (indvertnum = indgrafptr->baseval, indedgenbr = 0; /* Fill index array */ indvertnum < indgrafptr->baseval + indvertnbr; indvertnum ++) { Gnum orgvertnum; orgvertnum = indgrafptr->vnumtax[indvertnum]; orgindxtax[orgvertnum] = indvertnum; /* Mark selected vertices */ indedgenbr += orggrafptr->vendtax[orgvertnum] - orggrafptr->verttax[orgvertnum]; } return (graphInduce2 (orggrafptr, indgrafptr, indvertnbr, indedgenbr, indedgetab, orgindxtax)); } /* This routine builds the graph induced ** by the original graph and the vector ** of selected vertices. ** The induced vnumtab array is the list of ** selected vertices if the original graph ** does not have a vnumtab, or the proper ** subset of the original vnumtab else. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int graphInducePart ( const Graph * restrict const orggrafptr, /* Pointer to original graph */ const GraphPart * const orgparttax, /* Based array of vertex partition flags */ const Gnum indvertnbr, /* Number of vertices in selected part */ const GraphPart indpartval, /* Partition value of vertices to keep */ Graph * restrict const indgrafptr) /* Pointer to induced subgraph */ { Gnum * restrict orgindxtab; /* Original to induced vertex translation array */ Gnum * restrict orgindxtax; /* Based access to vertex translation array */ Gnum indvertnum; /* Number of current vertex in induced graph */ Gnum * restrict indedgetab; /* Pointer to pre-allocated edge array */ Gnum indedgenbr; /* (Approximate) number of edges in induced graph */ Gnum orgvertnum; memSet (indgrafptr, 0, sizeof (Graph)); /* Initialize graph fields */ indgrafptr->flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; indgrafptr->baseval = orggrafptr->baseval; indedgenbr = ((orggrafptr->degrmax > 0) && (indvertnbr < (orggrafptr->edgenbr / orggrafptr->degrmax))) /* Choose best upper bound on number of edges (avoid multiply overflow) */ ? (indvertnbr * orggrafptr->degrmax) : orggrafptr->edgenbr; if (orggrafptr->edlotax != NULL) /* If graph has edge weights */ indedgenbr *= 2; /* Account for edge weights */ if (orggrafptr->velotax != NULL) { if (memAllocGroup ((void **) (void *) &indgrafptr->verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)), &indgrafptr->vnumtax, (size_t) ( indvertnbr * sizeof (Gnum)), &indgrafptr->velotax, (size_t) ( indvertnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("graphInducePart: out of memory (1)"); return (1); /* Nothing to free because group allocation failed */ } indgrafptr->velotax -= indgrafptr->baseval; } else { if (memAllocGroup ((void **) (void *) &indgrafptr->verttax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)), &indgrafptr->vnumtax, (size_t) ( indvertnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("graphInducePart: out of memory (2)"); return (1); } } indgrafptr->verttax -= indgrafptr->baseval; /* Adjust base of arrays */ indgrafptr->vnumtax -= indgrafptr->baseval; indgrafptr->vertnbr = indvertnbr; indgrafptr->vertnnd = indvertnbr + indgrafptr->baseval; if (memAllocGroup ((void *) &indedgetab, (size_t) (indedgenbr * sizeof (Gnum)), /* Pre-allocate space for edgetab (and edlotab) */ &orgindxtab, (size_t) (orggrafptr->vertnbr * sizeof (Gnum)), NULL) == NULL) { /* orgindxtab is at the end of the heap */ errorPrint ("graphInducePart: out of memory (3)"); graphExit (indgrafptr); return (1); } orgindxtax = orgindxtab - orggrafptr->baseval; for (indvertnum = indgrafptr->baseval, indedgenbr = 0, orgvertnum = orggrafptr->baseval; /* Fill index array */ orgvertnum < orggrafptr->vertnnd; orgvertnum ++) { if (orgparttax[orgvertnum] == indpartval) { /* If vertex should be kept */ orgindxtax[orgvertnum] = indvertnum; /* Mark selected vertex */ indgrafptr->vnumtax[indvertnum] = orgvertnum; indedgenbr += orggrafptr->vendtax[orgvertnum] - orggrafptr->verttax[orgvertnum]; indvertnum ++; /* One more induced vertex created */ } else orgindxtax[orgvertnum] = ~0; } #ifdef SCOTCH_DEBUG_GRAPH2 if ((indvertnum - indgrafptr->baseval) != indvertnbr) { errorPrint ("graphInducePart: inconsistent data"); memFree (indedgetab); graphExit (indgrafptr); return (1); } #endif /* SCOTCH_DEBUG_GRAPH2 */ return (graphInduce2 (orggrafptr, indgrafptr, indvertnbr, indedgenbr, indedgetab, orgindxtax)); } /* This routine finalizes the building ** of the induced subgraph. ** It returns: ** - 0 : on success. ** - !0 : on error. */ static int graphInduce2 ( const Graph * restrict const orggrafptr, /* Pointer to original graph */ Graph * restrict const indgrafptr, /* Pointer to induced graph */ const Gnum indvertnbr, /* Number of vertices in induced graph */ const Gnum indedgenbr, /* (Upper bound of) number of edges in induced graph */ Gnum * restrict const indedgetab, /* Pointer to pre-allocated edge and edge load arrays */ const Gnum * restrict const orgindxtax) /* Array of numbers of selected vertices */ { Gnum indvertnum; /* Current induced vertex number */ Gnum indvelosum; /* Overall induced vertex load */ Gnum indedlosum; /* Overall induced edge load */ Gnum indedgenum; /* Number of current induced edge */ Gnum orgvertnum; /* Number of current vertex in original graph */ Gnum orgedgenum; /* Number of current edge in original graph */ if (orggrafptr->edlotax != NULL) { memOffset ((void *) indedgetab, &indgrafptr->edgetax, (size_t) (indedgenbr * sizeof (Gnum)), &indgrafptr->edlotax, (size_t) (indedgenbr * sizeof (Gnum)), NULL); indgrafptr->edgetax -= indgrafptr->baseval; indgrafptr->edlotax -= indgrafptr->baseval; } else indgrafptr->edgetax = indedgetab - indgrafptr->baseval; indvelosum = (indgrafptr->velotax == NULL) ? indgrafptr->vertnbr : 0; indedlosum = 0; for (indvertnum = indedgenum = indgrafptr->baseval; indvertnum < indgrafptr->vertnnd; indvertnum ++) { orgvertnum = indgrafptr->vnumtax[indvertnum]; indgrafptr->verttax[indvertnum] = indedgenum; if (indgrafptr->velotax != NULL) { /* If graph has vertex weights */ indvelosum += /* Accumulate vertex loads */ indgrafptr->velotax[indvertnum] = orggrafptr->velotax[orgvertnum]; } if (indgrafptr->edlotax != NULL) { /* If graph has edge weights */ for (orgedgenum = orggrafptr->verttax[orgvertnum]; orgedgenum < orggrafptr->vendtax[orgvertnum]; orgedgenum ++) { if (orgindxtax[orggrafptr->edgetax[orgedgenum]] != ~0) { /* If edge should be kept */ indedlosum += indgrafptr->edlotax[indedgenum] = orggrafptr->edlotax[orgedgenum]; indgrafptr->edgetax[indedgenum] = orgindxtax[orggrafptr->edgetax[orgedgenum]]; indedgenum ++; } } } else { for (orgedgenum = orggrafptr->verttax[orgvertnum]; orgedgenum < orggrafptr->vendtax[orgvertnum]; orgedgenum ++) { if (orgindxtax[orggrafptr->edgetax[orgedgenum]] != ~0) { /* If edge should be kept */ indgrafptr->edgetax[indedgenum] = orgindxtax[orggrafptr->edgetax[orgedgenum]]; indedgenum ++; } } } } indgrafptr->verttax[indvertnum] = indedgenum; /* Mark end of edge array */ indgrafptr->vendtax = indgrafptr->verttax + 1; /* Use compact representation of vertex arrays */ indgrafptr->vertnbr = indvertnum - indgrafptr->baseval; indgrafptr->vertnnd = indvertnum; indgrafptr->velosum = indvelosum; indgrafptr->edgenbr = indedgenum - indgrafptr->baseval; /* Set actual number of edges */ indgrafptr->edlosum = (indgrafptr->edlotax != NULL) ? indedlosum : indgrafptr->edgenbr; indgrafptr->degrmax = orggrafptr->degrmax; /* Induced maximum degree is likely to be the one of the original graph */ if (indgrafptr->edlotax != NULL) { /* Re-allocate arrays and delete orgindxtab */ size_t indedlooftval; /* Offset of edge load array with respect to edge array */ indedlooftval = indgrafptr->edlotax - indgrafptr->edgetax; indgrafptr->edgetax = memRealloc (indgrafptr->edgetax + indgrafptr->baseval, (indedlooftval + indgrafptr->edgenbr) * sizeof (Gnum)); indgrafptr->edgetax -= indgrafptr->baseval; indgrafptr->edlotax = indgrafptr->edgetax + indedlooftval; /* Use old index into old array as new index */ } else { indgrafptr->edgetax = memRealloc (indgrafptr->edgetax + indgrafptr->baseval, indgrafptr->edgenbr * sizeof (Gnum)); indgrafptr->edgetax -= indgrafptr->baseval; } if (orggrafptr->vnumtax != NULL) { /* Adjust vnumtax */ for (indvertnum = indgrafptr->baseval; indvertnum < indgrafptr->vertnnd; indvertnum ++) indgrafptr->vnumtax[indvertnum] = orggrafptr->vnumtax[indgrafptr->vnumtax[indvertnum]]; } #ifdef SCOTCH_DEBUG_GRAPH2 if (graphCheck (indgrafptr) != 0) { /* Check graph consistency */ errorPrint ("graphInduce2: inconsistent graph data"); graphExit (indgrafptr); return (1); } #endif /* SCOTCH_DEBUG_GRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_graph_map_f.c0000644000175300017530000002305511631334325023273 0ustar hazelscthazelsct/* Copyright 2004,2007,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_map_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** mapping routines of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 3.4 : from : 02 dec 1999 **/ /** to 15 nov 2001 **/ /** # Version 4.0 : from : 12 jan 2004 **/ /** to 12 dec 2005 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 31 aug 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the mapping routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFGRAPHMAPINIT, scotchfgraphmapinit, ( \ const SCOTCH_Graph * const grafptr, \ SCOTCH_Mapping * const mapptr, \ const SCOTCH_Arch * const archptr, \ SCOTCH_Num * const maptab, \ int * const revaptr), \ (grafptr, mapptr, archptr, maptab, revaptr)) { *revaptr = SCOTCH_graphMapInit (grafptr, mapptr, archptr, maptab); } /* ** */ FORTRAN ( \ SCOTCHFGRAPHMAPEXIT, scotchfgraphmapexit, ( \ const SCOTCH_Graph * const grafptr, \ SCOTCH_Mapping * const mapptr), \ (grafptr, mapptr)) { SCOTCH_graphMapExit (grafptr, mapptr); } /* ** */ FORTRAN ( \ SCOTCHFGRAPHMAPLOAD, scotchfgraphmapload, ( \ const SCOTCH_Graph * const grafptr, \ SCOTCH_Mapping * const mapptr, \ int * const fileptr, \ int * const revaptr), \ (grafptr, mapptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHMAPLOAD: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHMAPLOAD: cannot open input stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_graphMapLoad (grafptr, mapptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFGRAPHMAPSAVE, scotchfgraphmapsave, ( \ const SCOTCH_Graph * const grafptr, \ SCOTCH_Mapping * const mapptr, \ int * const fileptr, \ int * const revaptr), \ (grafptr, mapptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHMAPSAVE: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHMAPSAVE: cannot open output stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_graphMapSave (grafptr, mapptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFGRAPHMAPCOMPUTE, scotchfgraphmapcompute, ( \ SCOTCH_Graph * const grafptr, \ SCOTCH_Mapping * const mapptr, \ SCOTCH_Strat * const stratptr, \ int * const revaptr), \ (grafptr, mapptr, stratptr, revaptr)) { *revaptr = SCOTCH_graphMapCompute (grafptr, mapptr, stratptr); } /* ** */ FORTRAN ( \ SCOTCHFGRAPHMAP, scotchfgraphmap, ( \ SCOTCH_Graph * const grafptr, \ const SCOTCH_Arch * const archptr, \ SCOTCH_Strat * const stratptr, \ SCOTCH_Num * const maptab, \ int * const revaptr), \ (grafptr, archptr, stratptr, maptab, revaptr)) { *revaptr = SCOTCH_graphMap (grafptr, archptr, stratptr, maptab); } /* ** */ FORTRAN ( \ SCOTCHFGRAPHPART, scotchfgraphpart, ( \ SCOTCH_Graph * const grafptr, \ const SCOTCH_Num * const partptr, \ SCOTCH_Strat * const stratptr, \ SCOTCH_Num * const maptab, \ int * const revaptr), \ (grafptr, partptr, stratptr, maptab, revaptr)) { *revaptr = SCOTCH_graphPart (grafptr, *partptr, stratptr, maptab); } /* String lengths are passed at the very ** end of the argument list. */ FORTRAN ( \ SCOTCHFSTRATGRAPHMAP, scotchfstratgraphmap, ( \ SCOTCH_Strat * const stratptr, \ const char * const string, \ int * const revaptr, \ const int strnbr), \ (stratptr, string, revaptr, strnbr)) { char * restrict strtab; /* Pointer to null-terminated string */ if ((strtab = (char *) memAlloc (strnbr + 1)) == NULL) { /* Allocate temporary space */ errorPrint ("SCOTCHFSTRATGRAPHMAP: out of memory (1)"); *revaptr = 1; } memCpy (strtab, string, strnbr); /* Copy string contents */ strtab[strnbr] = '\0'; /* Terminate string */ *revaptr = SCOTCH_stratGraphMap (stratptr, strtab); /* Call original routine */ memFree (strtab); } /* ** */ FORTRAN ( \ SCOTCHFSTRATGRAPHMAPBUILD, scotchfstratgraphmapbuild, ( \ SCOTCH_Strat * const stratptr, \ const SCOTCH_Num * const flagval, \ const SCOTCH_Num * const partnbr, \ const double * const balrat, \ int * const revaptr), \ (stratptr, flagval, partnbr, balrat, revaptr)) { *revaptr = SCOTCH_stratGraphMapBuild (stratptr, *flagval, *partnbr, *balrat); } /* ** */ FORTRAN ( \ SCOTCHFSTRATGRAPHCLUSTERBUILD, scotchfstratgraphclusterbuild, ( \ SCOTCH_Strat * const stratptr, \ const SCOTCH_Num * const flagval, \ const SCOTCH_Num * const pwgtval, \ const double * const densval, \ const double * const bbalval, \ int * const revaptr), \ (stratptr, flagval, pwgtval, densval, bbalval, revaptr)) { *revaptr = SCOTCH_stratGraphClusterBuild (stratptr, *flagval, *pwgtval, *densval, *bbalval); } scotch-5.1.12b.dfsg/src/libscotch/bdgraph_bipart_ml.c0000644000175300017530000010423111631334325022740 0ustar hazelscthazelsct/* Copyright 2007-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_bipart_ml.c **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module bipartitions a distributed **/ /** graph using a multi-level scheme. **/ /** **/ /** DATES : # Version 5.1 : from : 30 oct 2007 **/ /** to : 14 apr 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BDGRAPH_BIPART_ML #include "module.h" #include "common.h" #include "parser.h" #include "arch.h" #include "dgraph.h" #include "dgraph_coarsen.h" #include "bdgraph.h" #include "bdgraph_bipart_ml.h" #include "bdgraph_bipart_st.h" /*********************************************/ /* */ /* The coarsening and uncoarsening routines. */ /* */ /*********************************************/ /* This routine builds a coarser graph from the ** Dgraph that is given on input. The coarser ** Dgraphs differ at this stage from classical ** active Dgraphs as their internal gains are not ** yet computed. ** It returns: ** - 0 : if the coarse Dgraph has been built. ** - 1 : if threshold reached or on error. */ static int bdgraphBipartMlCoarsen ( Bdgraph * restrict const finegrafptr, /*+ Finer graph +*/ Bdgraph * restrict const coargrafptr, /*+ Coarser graph to build +*/ DgraphCoarsenMulti * restrict * const coarmultptr, /*+ Pointer to multinode table to build +*/ const BdgraphBipartMlParam * const paraptr) /*+ Method parameters +*/ { int foldval; foldval = 1; if ((paraptr->duplvlmax > -1) && /* duplvlmax can allow fold dup */ (paraptr->duplvlmax < finegrafptr->levlnum + 1)) foldval = 0; else if (paraptr->duplvlmax < -1) /* duplvlmax can allow only fold */ foldval = (-(paraptr->duplvlmax + 1) < (finegrafptr->levlnum + 1)) ? 0 : -1; if (dgraphCoarsen (&finegrafptr->s, &coargrafptr->s, coarmultptr, paraptr->passnbr, paraptr->coarnbr, foldval, paraptr->dupmax, paraptr->coarrat) != 0) return (1); /* Return if coarsening failed */ coargrafptr->partgsttax = NULL; /* Do not allocate partition data yet */ coargrafptr->fronloctab = NULL; coargrafptr->fronglbnbr = 0; if (coargrafptr->s.procglbnbr == 0) { /* Not owner of graph */ coargrafptr->veexloctax = NULL; return (0); } if (finegrafptr->veexloctax != NULL) { /* Merge external gains for coarsened vertices */ DgraphCoarsenMulti * restrict coarmulttax; Gnum * restrict coarveexloctax; Gnum coarvertlocnum; if ((coarveexloctax = (Gnum *) memAlloc (coargrafptr->s.vertlocnbr * sizeof (Gnum))) == NULL) { errorPrint ("bdgraphBipartMlCoarsen: out of memory"); dgraphExit (&coargrafptr->s); /* Only free Dgraph since veexloctax not allocated */ return (1); } coarveexloctax -= coargrafptr->s.baseval; coargrafptr->veexloctax = coarveexloctax; coarmulttax = *coarmultptr; for (coarvertlocnum = coargrafptr->s.baseval; coarvertlocnum < coargrafptr->s.vertlocnnd; coarvertlocnum++) { Gnum finevertnum0; /* First multinode vertex */ Gnum finevertnum1; /* Second multinode vertex */ finevertnum0 = coarmulttax[coarvertlocnum].vertglbnum[0]; finevertnum1 = coarmulttax[coarvertlocnum].vertglbnum[1]; coarveexloctax[coarvertlocnum] = (finevertnum0 != finevertnum1) ? finegrafptr->veexloctax[finevertnum0] + finegrafptr->veexloctax[finevertnum1] : finegrafptr->veexloctax[finevertnum0]; } } else /* If fine graph does not have external gains */ coargrafptr->veexloctax = NULL; /* Coarse graph does not have external gains */ coargrafptr->veexglbsum = finegrafptr->veexglbsum; coargrafptr->compglbload0min = finegrafptr->compglbload0min; /* Only set constant partition parameters as others will be set on uncoarsening */ coargrafptr->compglbload0max = finegrafptr->compglbload0max; coargrafptr->compglbload0avg = finegrafptr->compglbload0avg; coargrafptr->commglbloadextn0 = finegrafptr->commglbloadextn0; coargrafptr->commglbgainextn0 = finegrafptr->commglbgainextn0; coargrafptr->domdist = finegrafptr->domdist; coargrafptr->domwght[0] = finegrafptr->domwght[0]; coargrafptr->domwght[1] = finegrafptr->domwght[1]; coargrafptr->levlnum = finegrafptr->levlnum + 1; return (0); } /* This routine is the reduction-loc operator which ** returns in inout[2] the rank of the process which ** holds the best partition. ** It returns: ** - void : in all cases. */ static void bdgraphBipartMlOpBest ( const Gnum * const in, /* First operand */ Gnum * const inout, /* Second and output operand */ const int * const len, /* Number of instances ; should be 1, not used */ const MPI_Datatype * const typedat) /* MPI datatype ; not used */ { inout[5] |= in[5]; /* Memory error flag */ if (inout[0] == 1) { /* Handle cases when at least one of them is erroneous */ if (in[0] == 1) { if (inout[1] > in[1]) /* To enforce commutativity, always keep smallest process number */ inout[1] = in[1]; inout[2] = in[2]; return; } inout[0] = in[0]; /* Validity flag */ inout[1] = in[1]; /* Lead process rank */ inout[2] = in[2]; /* Lead process color */ inout[3] = in[3]; /* Communication load */ inout[4] = in[4]; /* Load imbalance */ return; } else if (in[0] == 1) return; if ((in[3] < inout[3]) || /* Select best partition */ ((in[3] == inout[3]) && ((in[4] < inout[4]) || ((in[4] == inout[4]) && (in[1] < inout[1]))))) { inout[1] = in[1]; inout[2] = in[2]; inout[3] = in[3]; inout[4] = in[4]; } } /* This routine propagates the bipartitioning of the ** coarser graph back to the finer graph, according ** to the multinode table of collapsed vertices. ** After the bipartitioning is propagated, it finishes ** to compute the parameters of the finer graph that ** were not computed at the coarsening stage. ** It returns: ** - 0 : if coarse graph data has been propagated to fine graph. ** - !0 : on error. */ static int bdgraphBipartMlUncoarsen ( Bdgraph * restrict finegrafptr, /*+ Finer graph +*/ const Bdgraph * restrict const coargrafptr, /*+ Coarser graph +*/ const DgraphCoarsenMulti * restrict const coarmulttax) /*+ Multinode array +*/ { Gnum baseval; Gnum finefronlocnbr; Gnum finefronlocnum; Gnum fineedlolocval; Gnum finevertlocadj; /* Global vertex adjustment */ Gnum finevertlocnum; Gnum finevertlocnnd; /* Index for frontier array fronloctab */ Gnum finecomplocsize1; Gnum finecomplocload1; Gnum finecommlocloadintn; Gnum finecommlocloadextn; Gnum finecommlocgainextn; int vrcvdspnbr; int vsnddspnbr; int * restrict vrcvcnttab; int * restrict vsndcnttab; int * restrict vrcvdsptab; int * restrict vsnddsptab; Gnum * restrict vrcvdattab; Gnum * restrict vsnddattab; Gnum * restrict vsndidxtab; BdgraphBipartMlSort * restrict sortloctab; /* Array of vertices to send to their owner */ Gnum sortlocnbr; Gnum sortlocnum; int procnum; MPI_Datatype besttypedat; /* Data type for finding best bipartition */ MPI_Op bestoperdat; /* Handle of MPI operator for finding best bipartition */ Gnum reduloctab[6]; /* "6": both for selecting best and propagating data */ Gnum reduglbtab[6]; const Gnum * restrict coarfronloctab; GraphPart * restrict coarpartgsttax; GraphPart * restrict finepartgsttax; Gnum * restrict finefronloctab; const int fineprocglbnbr = finegrafptr->s.procglbnbr; const Gnum * restrict const fineprocvrttab = finegrafptr->s.procvrttab; const Gnum * restrict const fineedgegsttax = finegrafptr->s.edgegsttax; const Gnum * restrict const finevertloctax = finegrafptr->s.vertloctax; const Gnum * restrict const finevendloctax = finegrafptr->s.vendloctax; const Gnum * restrict const fineveloloctax = finegrafptr->s.veloloctax; const Gnum * restrict const fineveexloctax = finegrafptr->veexloctax; const Gnum * restrict const fineedloloctax = finegrafptr->s.edloloctax; reduloctab[5] = 0; /* Assume everything is fine */ if (finegrafptr->partgsttax == NULL) { /* If partition array not yet allocated */ if (dgraphGhst (&finegrafptr->s) != 0) { /* Create ghost edge array and compute vertgstnbr */ errorPrint ("bdgraphBipartMlUncoarsen: cannot compute ghost edge array"); reduloctab[5] = 1; /* Allocated data will be freed along with graph structure */ } else if ((finegrafptr->partgsttax = (GraphPart *) memAlloc (finegrafptr->s.vertgstnbr * sizeof (GraphPart))) == NULL) { errorPrint ("bdgraphBipartMlUncoarsen: out of memory (1)"); reduloctab[5] = 1; /* Allocated data will be freed along with graph structure */ } else if (finegrafptr->partgsttax -= finegrafptr->s.baseval, (finegrafptr->fronloctab = (Gnum *) memAlloc (finegrafptr->s.vertlocnbr * sizeof (Gnum))) == NULL) { errorPrint ("bdgraphBipartMlUncoarsen: out of memory (2)"); reduloctab[5] = 1; /* Allocated data will be freed along with graph structure */ } } if (coargrafptr == NULL) { /* If coarser graph not provided */ #ifdef SCOTCH_DEBUG_BDGRAPH1 /* Communication cannot be overlapped by a useful one */ if (MPI_Allreduce (&reduloctab[5], &reduglbtab[5], 1, GNUM_MPI, MPI_SUM, finegrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartMlUncoarsen: communication error (1)"); return (1); } #else /* SCOTCH_DEBUG_BDGRAPH1 */ reduglbtab[5] = reduloctab[5]; #endif /* SCOTCH_DEBUG_BDGRAPH1 */ if (reduglbtab[5] != 0) return (1); bdgraphZero (finegrafptr); /* Assign all vertices to part 0 */ return (0); } if (coargrafptr->s.procglbnbr <= 0) { /* If unused folded coargrafptr */ reduloctab[0] = 1; /* Set it as invalid */ reduloctab[1] = 0; /* Useless rank */ reduloctab[2] = 1; /* Color is not the one of folded */ reduloctab[3] = /* Prevent Valgrind from yelling */ reduloctab[4] = 0; } else { reduloctab[0] = ((coargrafptr->compglbload0 == 0) || /* Empty subdomains are deemed invalid */ (coargrafptr->compglbload0 == coargrafptr->s.veloglbsum)) ? 1 : 0; reduloctab[1] = finegrafptr->s.proclocnum; /* Set rank and color key according to coarse graph (sub)communicator */ reduloctab[2] = finegrafptr->s.prockeyval; reduloctab[3] = coargrafptr->commglbload; reduloctab[4] = coargrafptr->compglbload0dlt; } if ((MPI_Type_contiguous (6, GNUM_MPI, &besttypedat) != MPI_SUCCESS) || (MPI_Type_commit (&besttypedat) != MPI_SUCCESS) || (MPI_Op_create ((MPI_User_function *) bdgraphBipartMlOpBest, 1, &bestoperdat) != MPI_SUCCESS)) { errorPrint ("bdgraphBipartMlUncoarsen: communication error (2)"); return (1); } if (MPI_Allreduce (reduloctab, reduglbtab, 1, besttypedat, bestoperdat, finegrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartMlUncoarsen: communication error (3)"); return (1); } if ((MPI_Op_free (&bestoperdat) != MPI_SUCCESS) || (MPI_Type_free (&besttypedat) != MPI_SUCCESS)) { errorPrint ("bdgraphBipartMlUncoarsen: communication error (4)"); return (1); } if (reduglbtab[5] != 0) /* If memory error, return */ return (1); if (reduglbtab[0] == 1) { /* If all possible partitions are invalid */ #ifdef SCOTCH_DEBUG_BDGRAPH2 errorPrintW ("bdgraphBipartMlUncoarsen: no valid partition"); #endif /* SCOTCH_DEBUG_BDGRAPH2 */ return (1); /* All invalid partitions will lead to low method be applied at upper level */ } if (memAllocGroup ((void **) (void *) &vrcvcnttab, (size_t) (fineprocglbnbr * sizeof (int)), &vrcvdsptab, (size_t) (fineprocglbnbr * sizeof (int)), &vsnddsptab, (size_t) (fineprocglbnbr * sizeof (int)), &vsndcnttab, (size_t) (fineprocglbnbr * sizeof (int)), &vsndidxtab, (size_t) (fineprocglbnbr * sizeof (Gnum) * 4), /* TRICK: sortloctab after vsndidxtab after vsndcnttab */ &sortloctab, (size_t) (2 * coargrafptr->s.vertlocnbr * sizeof (BdgraphBipartMlSort)), NULL) == NULL) { errorPrint ("bdgraphBipartMlUncoarsen: out of memory (3)"); reduloctab[5] = 1; } #ifdef SCOTCH_DEBUG_BDGRAPH1 /* Communication cannot be overlapped by a useful one */ if (MPI_Allreduce (&reduloctab[5], &reduglbtab[5], 1, GNUM_MPI, MPI_SUM, finegrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartMlUncoarsen: communication error (5)"); return (1); } #else /* SCOTCH_DEBUG_BDGRAPH1 */ reduglbtab[5] = reduloctab[5]; #endif /* SCOTCH_DEBUG_BDGRAPH1 */ if (reduglbtab[5] != 0) { if (vrcvcnttab != NULL) memFree (vrcvcnttab); return (1); } memSet (vsndcnttab, 0, ((byte *) sortloctab) - ((byte *) vsndcnttab)); /* TRICK: sortloctab after vsndidxtab after vsndcnttab */ baseval = finegrafptr->s.baseval; coarfronloctab = coargrafptr->fronloctab; coarpartgsttax = coargrafptr->partgsttax; finepartgsttax = finegrafptr->partgsttax; finevertlocnnd = finegrafptr->s.vertlocnnd; finevertlocadj = finegrafptr->s.procvrttab[finegrafptr->s.proclocnum] - baseval; finefronloctab = finegrafptr->fronloctab; finecomplocsize1 = 0; finecomplocload1 = 0; finecommlocloadextn = 0; finecommlocgainextn = 0; #ifdef SCOTCH_DEBUG_BDGRAPH2 memSet (finepartgsttax + baseval, ~0, finegrafptr->s.vertgstnbr * sizeof (GraphPart)); /* All vertices are unvisited */ #endif /* SCOTCH_DEBUG_BDGRAPH2 */ finefronlocnbr = 0; sortlocnbr = 0; if (reduglbtab[2] == (Gnum) coargrafptr->s.prockeyval) { /* If we belong to the group of the lead process, we must browse and send local data */ Gnum coarfronlocnum; Gnum coarvertlocnum; for (coarfronlocnum = 0; coarfronlocnum < coargrafptr->fronlocnbr; coarfronlocnum ++) coarpartgsttax[coarfronloctab[coarfronlocnum]] |= 2; /* Flag vertex as belonging to frontier */ for (coarvertlocnum = baseval; coarvertlocnum < coargrafptr->s.vertlocnnd; coarvertlocnum ++) { GraphPart coarpartval; Gnum coarpartmsk; Gnum finevertglbnum; Gnum finevertlocnum; int i; coarpartval = coarpartgsttax[coarvertlocnum]; coarpartmsk = (Gnum) (coarpartval & 1); i = 0; do { finevertglbnum = coarmulttax[coarvertlocnum].vertglbnum[i]; finevertlocnum = finevertglbnum - finevertlocadj; if ((finevertlocnum >= baseval) && /* If vertex is local */ (finevertlocnum < finevertlocnnd)) { #ifdef SCOTCH_DEBUG_BDGRAPH2 if (finepartgsttax[finevertlocnum] != ((GraphPart) ~0)) { errorPrint ("bdgraphBipartMlUncoarsen: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ finepartgsttax[finevertlocnum] = (coarpartval & 1); finecomplocsize1 += coarpartmsk; /* One extra vertex created in part 1 if (coarpartval == 1) */ if ((coarpartval & 2) != 0) /* If coarse frontier vertex, add fine vertex to fine frontier */ finefronloctab[finefronlocnbr ++] = finevertlocnum; if (fineveloloctax != NULL) { Gnum veloval; veloval = fineveloloctax[finevertlocnum]; finecomplocload1 += veloval & (- coarpartmsk); } if (fineveexloctax != NULL) { Gnum veexval; veexval = fineveexloctax[finevertlocnum]; finecommlocloadextn += veexval * coarpartmsk; finecommlocgainextn += veexval * (1 - 2 * coarpartmsk); } } else { int procngbnum; int procngbmax; procngbnum = 0; procngbmax = fineprocglbnbr; while ((procngbmax - procngbnum) > 1) { /* Find owner process by dichotomy on procvgbtab */ int procngbmed; procngbmed = (procngbmax + procngbnum) / 2; if (fineprocvrttab[procngbmed] > finevertglbnum) procngbmax = procngbmed; else procngbnum = procngbmed; } vsndidxtab[4 * procngbnum + coarpartval] ++; /* One of four counters per process number will be incremented */ sortloctab[sortlocnbr].vertnum = finevertglbnum; sortloctab[sortlocnbr].procnum = ((procngbnum + (fineprocglbnbr * coarpartmsk)) ^ (- (Gnum) (coarpartval >> 1))); /* Embed part and frontier information */ sortlocnbr ++; } i ++; /* Process next multinode vertex */ } while (finevertglbnum != coarmulttax[coarvertlocnum].vertglbnum[1]); /* If not single node */ } for (procnum = 0; procnum < fineprocglbnbr; procnum ++) { /* Aggregate data to be sent */ vsndcnttab[procnum] = vsndidxtab[4 * procnum] + vsndidxtab[4 * procnum + 1] + vsndidxtab[4 * procnum + 2] + vsndidxtab[4 * procnum + 3]; if (vsndcnttab[procnum] != 0) /* If we will send data to neighbor */ vsndcnttab[procnum] += 3; /* Add control data to message size */ } } if (MPI_Alltoall (vsndcnttab, 1, MPI_INT, vrcvcnttab, 1, MPI_INT, finegrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartMlUncoarsen: communication error (3)"); return (1); } for (procnum = 0, vrcvdspnbr = vsnddspnbr = 0; /* Build communication index arrays */ procnum < fineprocglbnbr; procnum ++) { vrcvdsptab[procnum] = vrcvdspnbr; vsnddsptab[procnum] = vsnddspnbr; vrcvdspnbr += vrcvcnttab[procnum]; vsnddspnbr += vsndcnttab[procnum]; } if (memAllocGroup ((void **) (void *) &vrcvdattab, (size_t) (vrcvdspnbr * sizeof (Gnum)), &vsnddattab, (size_t) (vsnddspnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("bdgraphBipartMlUncoarsen: out of memory (4)"); reduloctab[5] = 1; } #ifdef SCOTCH_DEBUG_BDGRAPH1 /* Communication cannot be overlapped by a useful one */ if (MPI_Allreduce (&reduloctab[5], &reduglbtab[5], 1, GNUM_MPI, MPI_SUM, finegrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartMlUncoarsen: communication error (4)"); return (1); } #else /* SCOTCH_DEBUG_BDGRAPH1 */ reduglbtab[5] = reduloctab[5]; #endif /* SCOTCH_DEBUG_BDGRAPH1 */ if (reduglbtab[5] != 0) { if (vrcvdattab != NULL) memFree (vrcvdattab); if (vrcvcnttab != NULL) memFree (vrcvcnttab); return (1); } for (procnum = 0; procnum < fineprocglbnbr; procnum ++) { Gnum vsnddspval; vsnddspval = vsnddsptab[procnum]; if (vsndcnttab[procnum] != 0) { Gnum vsndidxnum; vsnddattab[vsnddspval] = vsndidxtab[4 * procnum]; vsnddattab[vsnddspval + 1] = vsndidxtab[4 * procnum + 1]; vsnddattab[vsnddspval + 2] = vsndidxtab[4 * procnum + 2]; vsnddspval += 3; /* Compute sub-array indices to pack vertices to be sent */ vsndidxnum = vsndidxtab[4 * procnum]; vsndidxtab[4 * procnum] = vsnddspval; vsnddspval += vsndidxnum; vsndidxnum = vsndidxtab[4 * procnum + 1]; vsndidxtab[4 * procnum + 1] = vsnddspval; vsnddspval += vsndidxnum; vsndidxnum = vsndidxtab[4 * procnum + 2]; vsndidxtab[4 * procnum + 2] = vsnddspval; vsnddspval += vsndidxnum; vsndidxtab[4 * procnum + 3] = vsnddspval; } } for (sortlocnum = 0; sortlocnum < sortlocnbr; sortlocnum ++) { /* For all vertices to send */ Gnum vertglbend; Gnum procngbnum; int partval; vertglbend = sortloctab[sortlocnum].vertnum; procngbnum = sortloctab[sortlocnum].procnum; partval = 0; /* Extract frontier and part data from process number */ if (procngbnum < 0) { partval = 2; procngbnum ^= (Gnum) -1; } if (procngbnum >= fineprocglbnbr) { partval |= 1; procngbnum -= fineprocglbnbr; } #ifdef SCOTCH_DEBUG_BDGRAPH2 if (((partval < 3) && (vsndidxtab[4 * procngbnum + partval] >= vsndidxtab[4 * procngbnum + partval + 1])) || (vsndidxtab[4 * procngbnum + partval] >= (vsnddsptab[procngbnum] + vsndcnttab[procngbnum]))) { errorPrint ("bdgraphBipartMlUncoarsen: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ vsnddattab[vsndidxtab[4 * procngbnum + partval] ++] = vertglbend; /* Pack vertex in proper sub-array */ } if (MPI_Alltoallv (vsnddattab, vsndcnttab, vsnddsptab, GNUM_MPI, vrcvdattab, vrcvcnttab, vrcvdsptab, GNUM_MPI, finegrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartMlUncoarsen: communication error (5)"); return (1); } for (procnum = 0; procnum < fineprocglbnbr; ++ procnum) { /* Update local ones from the buffer for receiving data */ Gnum vrcvidxnum; Gnum vrcvidxnnd; if (vrcvcnttab[procnum] == 0) /* If nothing received from this process, skip it */ continue; finecomplocsize1 += (vrcvcnttab[procnum] - 3) - vrcvdattab[vrcvdsptab[procnum]] - vrcvdattab[vrcvdsptab[procnum] + 2]; for (vrcvidxnum = vrcvdsptab[procnum] + 3, vrcvidxnnd = vrcvidxnum + vrcvdattab[vrcvdsptab[procnum]]; /* Vertices in sub-array 0 */ vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { Gnum finevertlocnum; finevertlocnum = vrcvdattab[vrcvidxnum] - finevertlocadj; #ifdef SCOTCH_DEBUG_BDGRAPH2 if ((finevertlocnum < baseval) || (finevertlocnum >= finevertlocnnd)) { errorPrint ("bdgraphBipartMlUncoarsen: internal error (4)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ finepartgsttax[finevertlocnum] = 0; } for (vrcvidxnnd = vrcvidxnum + vrcvdattab[vrcvdsptab[procnum] + 1]; /* Vertices in sub-array 1 */ vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { Gnum finevertlocnum; finevertlocnum = vrcvdattab[vrcvidxnum] - finevertlocadj; #ifdef SCOTCH_DEBUG_BDGRAPH2 if ((finevertlocnum < baseval) || (finevertlocnum >= finevertlocnnd)) { errorPrint ("bdgraphBipartMlUncoarsen: internal error (5)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ finepartgsttax[finevertlocnum] = 1; if (fineveloloctax != NULL) finecomplocload1 += fineveloloctax[finevertlocnum]; if (fineveexloctax != NULL) { Gnum veexval; veexval = fineveexloctax[finevertlocnum]; finecommlocloadextn += veexval; finecommlocgainextn -= veexval; } } for (vrcvidxnnd = vrcvidxnum + vrcvdattab[vrcvdsptab[procnum] + 2]; /* Vertices in sub-array 2 */ vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { Gnum finevertlocnum; finevertlocnum = vrcvdattab[vrcvidxnum] - finevertlocadj; #ifdef SCOTCH_DEBUG_BDGRAPH2 if ((finevertlocnum < baseval) || (finevertlocnum >= finevertlocnnd)) { errorPrint ("bdgraphBipartMlUncoarsen: internal error (6)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ finepartgsttax[finevertlocnum] = 0; finefronloctab[finefronlocnbr ++] = finevertlocnum; } for (vrcvidxnnd = vrcvdsptab[procnum] + vrcvcnttab[procnum]; /* Vertices in sub-array 3 */ vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { Gnum finevertlocnum; finevertlocnum = vrcvdattab[vrcvidxnum] - finevertlocadj; #ifdef SCOTCH_DEBUG_BDGRAPH2 if ((finevertlocnum < baseval) || (finevertlocnum >= finevertlocnnd)) { errorPrint ("bdgraphBipartMlUncoarsen: internal error (7)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ finepartgsttax[finevertlocnum] = 1; finefronloctab[finefronlocnbr ++] = finevertlocnum; if (fineveloloctax != NULL) finecomplocload1 += fineveloloctax[finevertlocnum]; if (fineveexloctax != NULL) { Gnum veexval; veexval = fineveexloctax[finevertlocnum]; finecommlocloadextn += veexval; finecommlocgainextn -= veexval; } } } #ifdef SCOTCH_DEBUG_BDGRAPH2 for (finevertlocnum = baseval; finevertlocnum < finevertlocnnd; finevertlocnum ++) { if (finepartgsttax[finevertlocnum] == ((GraphPart) ~0)) { errorPrint ("bdgraphBipartMlUncoarsen: internal error (8)"); return (1); } } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ if (dgraphHaloSync (&finegrafptr->s, (byte *) (finepartgsttax + baseval), GRAPHPART_MPI) != 0) { errorPrint ("bdgraphBipartMlUncoarsen: cannot perform halo exchange"); return (1); } finecommlocloadintn = 0; fineedlolocval = 1; /* Assume edges are not weighted */ for (finefronlocnum = 0; finefronlocnum < finefronlocnbr; finefronlocnum ++) { Gnum finevertlocnum; Gnum fineedgelocnum; Gnum partval; Gnum commcut; finevertlocnum = finefronloctab[finefronlocnum]; partval = finepartgsttax[finevertlocnum]; for (fineedgelocnum = finevertloctax[finevertlocnum], commcut = 0; fineedgelocnum < finevendloctax[finevertlocnum]; fineedgelocnum ++) { Gnum partdlt; partdlt = partval ^ finepartgsttax[fineedgegsttax[fineedgelocnum]]; commcut += partdlt; if (fineedloloctax != NULL) fineedlolocval = fineedloloctax[fineedgelocnum]; finecommlocloadintn += partdlt * fineedlolocval; /* Counted in both part, should be divided by 2 in summing up phase */ } if (commcut == 0) /* If vertex does not really belong to frontier */ finefronloctab[finefronlocnum --] = finefronloctab[-- finefronlocnbr]; /* Replace vertex and redo */ } memFree (vrcvdattab); /* Free group leaders */ memFree (vrcvcnttab); finegrafptr->fronlocnbr = finefronlocnbr; finegrafptr->complocsize0 = finegrafptr->s.vertlocnbr - finecomplocsize1; finegrafptr->complocload0 = (fineveloloctax == NULL) ? finegrafptr->complocsize0 : (finegrafptr->s.velolocsum - finecomplocload1); reduloctab[0] = finegrafptr->complocload0; reduloctab[1] = finegrafptr->complocsize0; reduloctab[2] = finegrafptr->fronlocnbr; reduloctab[3] = finecommlocloadintn; reduloctab[4] = finecommlocloadextn; reduloctab[5] = finecommlocgainextn; MPI_Allreduce (reduloctab, reduglbtab, 6, GNUM_MPI, MPI_SUM, finegrafptr->s.proccomm); finegrafptr->compglbload0 = reduglbtab[0]; finegrafptr->compglbload0dlt = finegrafptr->compglbload0 - finegrafptr->compglbload0avg; finegrafptr->compglbsize0 = reduglbtab[1]; finegrafptr->fronglbnbr = reduglbtab[2]; finegrafptr->commglbload = ((reduglbtab[3] / 2) * finegrafptr->domdist + reduglbtab[4] + finegrafptr->commglbloadextn0); finegrafptr->commglbgainextn = reduglbtab[5]; if (coargrafptr->s.procglbnbr != 0) memFree ((void *) (coarmulttax + coargrafptr->s.baseval)); #ifdef SCOTCH_DEBUG_BDGRAPH2 if (bdgraphCheck (finegrafptr) != 0) { errorPrint ("bdgraphBipartMlUncoarsen: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ return (0); } /* This routine performs the ** bipartitioning recursion. ** It returns: ** - 0 : if bipartitioning could be computed. ** - !0 : on error. */ static int bdgraphBipartMl2 ( Bdgraph * restrict const grafptr, /* Active graph */ const BdgraphBipartMlParam * const paraptr) /* Method parameters */ { Bdgraph coargrafdat; DgraphCoarsenMulti * restrict coarmulttax; int o; if (grafptr->s.procglbnbr <= 1) { /* Enter into sequential mode */ if (((o = bdgraphBipartMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ ((o = bdgraphBipartSt (grafptr, paraptr->stratseq)) != 0)) { #ifdef SCOTCH_DEBUG_BDGRAPH2 errorPrintW ("bdgraphBipartMl2: cannot apply sequential strategy"); #endif /* SCOTCH_DEBUG_BDGRAPH2 */ } return (o); } if (bdgraphBipartMlCoarsen (grafptr, &coargrafdat, &coarmulttax, paraptr) == 0) { o = (coargrafdat.s.procglbnbr == 0) ? 0 : bdgraphBipartMl2 (&coargrafdat, paraptr); /* Apply recursion on coarsened graph if it exists */ if ((o == 0) && ((o = bdgraphBipartMlUncoarsen (grafptr, &coargrafdat, coarmulttax)) == 0) && ((o = bdgraphBipartSt (grafptr, paraptr->stratasc)) != 0)) { /* Apply ascending strategy if uncoarsening worked */ #ifdef SCOTCH_DEBUG_BDGRAPH2 errorPrintW ("bdgraphBipartMl2: cannot apply ascending strategy"); #endif /* SCOTCH_DEBUG_BDGRAPH2 */ } bdgraphExit (&coargrafdat); if (o == 0) /* If multi-level failed, apply low strategy as fallback */ return (o); } if (((o = bdgraphBipartMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ ((o = bdgraphBipartSt (grafptr, paraptr->stratlow)) != 0)) { /* Apply low strategy */ #ifdef SCOTCH_DEBUG_BDGRAPH2 errorPrintW ("bdgraphBipartMl2: cannot apply low strategy"); #endif /* SCOTCH_DEBUG_BDGRAPH2 */ } return (o); } /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the muti-level bipartitioning. ** It returns: ** - 0 : if bipartitioning could be computed. ** - 1 : on error. */ int bdgraphBipartMl ( Bdgraph * const grafptr, /*+ Active graph +*/ const BdgraphBipartMlParam * const paraptr) /*+ Method parameters +*/ { Gnum levlnum; /* Save value for graph level */ int o; levlnum = grafptr->levlnum; /* Save graph level */ grafptr->levlnum = 0; /* Initialize coarsening level */ o = bdgraphBipartMl2 (grafptr, paraptr); /* Perform multi-level bipartitioning */ grafptr->levlnum = levlnum; /* Restore graph level */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/hdgraph_fold.h0000644000175300017530000000654111631334325021733 0ustar hazelscthazelsct/* Copyright 2007-2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph_fold.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the distributed source graph **/ /** folding routines. **/ /** **/ /** # Version 5.0 : from : 06 sep 2006 **/ /** to 06 sep 2006 **/ /** # Version 5.1 : from : 03 jan 2009 **/ /** to 03 jan 2009 **/ /** **/ /************************************************************/ /* ** The defines. */ /* Slot indices used for point-to-point folding communications. First indices are used for communications without further processing. At the moment, there is one anonymous slot: vnumloctab. */ typedef enum HdgraphFoldTag_ { HDGRAPHFOLDTAGENBR = 1, /*+ Edge size message +*/ HDGRAPHFOLDTAGVERT, /*+ vertloctab message +*/ HDGRAPHFOLDTAGVEND, /*+ vendloctab message +*/ HDGRAPHFOLDTAGVELO, /*+ veloloctab message +*/ HDGRAPHFOLDTAGEDGE, /*+ edgeloctab message +*/ HDGRAPHFOLDTAGNBR /*+ Number of tags +*/ } HdgraphFoldTag; scotch-5.1.12b.dfsg/src/libscotch/common_memory.c0000644000175300017530000003127211631334325022164 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : common_memory.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** This module handles errors. **/ /** **/ /** DATES : # Version 0.0 : from : 07 sep 2001 **/ /** to 07 sep 2001 **/ /** # Version 0.1 : from : 14 apr 2001 **/ /** to 24 mar 2003 **/ /** # Version 2.0 : from : 01 jul 2008 **/ /** to : 01 jul 2008 **/ /** # Version 5.1 : from : 22 nov 2008 **/ /** to : 27 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define COMMON_MEMORY #ifndef COMMON_NOMODULE #include "module.h" #endif /* COMMON_NOMODULE */ #include "common.h" /*********************************/ /* */ /* The memory handling routines. */ /* */ /*********************************/ /* This routine keeps track of the amount of ** allocated memory, and keeps track of the ** maximum allowed. */ #ifdef COMMON_MEMORY_TRACE #define COMMON_MEMORY_SKEW (MAX ((sizeof (size_t)), (sizeof (double)))) /* For proper alignment */ static size_t memorysiz = 0; /*+ Number of allocated bytes +*/ static size_t memorymax = 0; /*+ Maximum amount of allocated data +*/ #if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) static int muteflag = 1; /*+ Flag for mutex initialization +*/ static pthread_mutex_t mutelocdat; /*+ Local mutex for updates +*/ #endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ void * memAllocRecord ( size_t newsiz) { size_t newadd; byte * newptr; #if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) if (muteflag != 0) { /* Unsafe code with respect to race conditions but should work as first allocs are sequential */ muteflag = 0; pthread_mutex_init (&mutelocdat, NULL); /* Initialize local mutex */ } pthread_mutex_lock (&mutelocdat); /* Lock local mutex */ #endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ if ((newptr = malloc (newsiz + COMMON_MEMORY_SKEW)) == NULL) /* Non-zero sizes will guarantee non-NULL pointers */ newadd = (size_t) 0; else { newadd = newsiz; *((size_t *) newptr) = newsiz; /* Record size for freeing */ newptr += COMMON_MEMORY_SKEW; /* Skew pointer while enforcing alignment */ } memorysiz += newadd; if (memorymax < memorysiz) memorymax = memorysiz; #if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) pthread_mutex_unlock (&mutelocdat); /* Unlock local mutex */ #endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ return ((void *) newptr); /* Return skewed pointer or NULL */ } void * memReallocRecord ( void * oldptr, size_t newsiz) { byte * tmpptr; byte * newptr; size_t oldsiz; size_t newadd; tmpptr = ((byte *) oldptr) - COMMON_MEMORY_SKEW; oldsiz = *((size_t *) tmpptr); #if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) pthread_mutex_lock (&mutelocdat); /* Lock local mutex */ #endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ if ((newptr = realloc (tmpptr, newsiz + COMMON_MEMORY_SKEW)) == NULL) newadd = (size_t) 0; else { newadd = newsiz - oldsiz; /* Add difference between the two sizes */ *((size_t *) newptr) = newsiz; /* Record size for freeing */ newptr += COMMON_MEMORY_SKEW; /* Skew pointer while enforcing alignment */ } memorysiz += newadd; if (memorymax < memorysiz) memorymax = memorysiz; #if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) pthread_mutex_unlock (&mutelocdat); /* Unlock local mutex */ #endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ return ((void *) newptr); /* Return skewed pointer or NULL */ } void memFreeRecord ( void * oldptr) { byte * tmpptr; size_t oldsiz; tmpptr = ((byte *) oldptr) - COMMON_MEMORY_SKEW; oldsiz = *((size_t *) tmpptr); #if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) pthread_mutex_lock (&mutelocdat); /* Lock local mutex */ #endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ free (tmpptr); memorysiz -= oldsiz; #if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) pthread_mutex_unlock (&mutelocdat); /* Unlock local mutex */ #endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ } size_t memMax () { size_t curmax; #if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) pthread_mutex_lock (&mutelocdat); /* Lock local mutex */ #endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ curmax = memorymax; #if (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) pthread_mutex_unlock (&mutelocdat); /* Unlock local mutex */ #endif /* (defined (COMMON_PTHREAD) || defined (SCOTCH_PTHREAD)) */ return (curmax); } #endif /* COMMON_MEMORY_TRACE */ /* This routine allocates a set of arrays in ** a single memAlloc()'ed array, the address ** of which is placed in the first argument. ** Arrays to be allocated are described as ** a duplet of ..., &ptr, size, ..., ** terminated by a NULL pointer. ** It returns: ** - !NULL : pointer to block, all arrays allocated. ** - NULL : no array allocated. */ void * memAllocGroup ( void ** memptr, /*+ Pointer to first argument to allocate +*/ ...) { va_list memlist; /* Argument list of the call */ byte ** memloc; /* Pointer to pointer of current argument */ size_t memoff; /* Offset value of argument */ byte * blkptr; /* Pointer to memory chunk */ memoff = 0; memloc = (byte **) memptr; /* Point to first memory argument */ va_start (memlist, memptr); /* Start argument parsing */ while (memloc != NULL) { /* As long as not NULL pointer */ memoff = (memoff + (sizeof (double) - 1)) & (~ (sizeof (double) - 1)); memoff += va_arg (memlist, size_t); memloc = va_arg (memlist, byte **); } if ((blkptr = (byte *) memAlloc (memoff)) == NULL) { /* If cannot allocate */ *memptr = NULL; /* Set first pointer to NULL */ return (NULL); } memoff = 0; memloc = (byte **) memptr; /* Point to first memory argument */ va_start (memlist, memptr); /* Restart argument parsing */ while (memloc != NULL) { /* As long as not NULL pointer */ memoff = (memoff + (sizeof (double) - 1)) & (~ (sizeof (double) - 1)); /* Pad */ *memloc = blkptr + memoff; /* Set argument address */ memoff += va_arg (memlist, size_t); /* Accumulate padded sizes */ memloc = va_arg (memlist, void *); /* Get next argument pointer */ } return ((void *) blkptr); } /* This routine reallocates a set of arrays in ** a single memRealloc()'ed array passed as ** first argument, and the address of which ** is placed in the second argument. ** Arrays to be allocated are described as ** a duplet of ..., &ptr, size, ..., ** terminated by a NULL pointer. ** It returns: ** - !NULL : pointer to block, all arrays allocated. ** - NULL : no array allocated. */ void * memReallocGroup ( void * oldptr, /*+ Pointer to block to reallocate +*/ ...) { va_list memlist; /* Argument list of the call */ byte ** memloc; /* Pointer to pointer of current argument */ size_t memoff; /* Offset value of argument */ byte * blkptr; /* Pointer to memory chunk */ memoff = 0; va_start (memlist, oldptr); /* Start argument parsing */ while ((memloc = va_arg (memlist, byte **)) != NULL) { /* As long as not NULL pointer */ memoff = (memoff + (sizeof (double) - 1)) & (~ (sizeof (double) - 1)); /* Pad */ memoff += va_arg (memlist, size_t); /* Accumulate padded sizes */ } if ((blkptr = (byte *) memRealloc (oldptr, memoff)) == NULL) /* If cannot allocate block */ return (NULL); memoff = 0; va_start (memlist, oldptr); /* Restart argument parsing */ while ((memloc = va_arg (memlist, byte **)) != NULL) { /* As long as not NULL pointer */ memoff = (memoff + (sizeof (double) - 1)) & (~ (sizeof (double) - 1)); /* Pad */ *memloc = blkptr + memoff; /* Set argument address */ memoff += va_arg (memlist, size_t); /* Accumulate padded sizes */ } return ((void *) blkptr); } /* This routine computes the offsets of arrays ** of given sizes and types with respect to a ** given base address passed as first argument. ** Arrays the offsets of which are to be computed ** are described as a duplet of ..., &ptr, size, ..., ** terminated by a NULL pointer. ** It returns: ** - !NULL : in all cases, pointer to the end of ** the memory area. */ void * memOffset ( void * memptr, /*+ Pointer to base address of memory area +*/ ...) { va_list memlist; /* Argument list of the call */ byte ** memloc; /* Pointer to pointer of current argument */ size_t memoff; /* Offset value of argument */ memoff = 0; va_start (memlist, memptr); /* Start argument parsing */ while ((memloc = va_arg (memlist, byte **)) != NULL) { /* As long as not NULL pointer */ memoff = (memoff + (sizeof (double) - 1)) & (~ (sizeof (double) - 1)); *memloc = (byte *) memptr + memoff; /* Set argument address */ memoff += va_arg (memlist, size_t); /* Accumulate padded sizes */ } return ((void *) ((byte *) memptr + memoff)); } scotch-5.1.12b.dfsg/src/libscotch/library_graph_f.c0000644000175300017530000002476711631334325022451 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the source graph handling routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 3.4 : from : 02 dec 1999 **/ /** to 15 nov 2001 **/ /** # Version 4.0 : from : 11 dec 2001 **/ /** to 17 mar 2005 **/ /** # Version 5.0 : from : 11 jul 2007 **/ /** to 11 jul 2007 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 15 apr 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the graph handling routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFGRAPHINIT, scotchfgraphinit, ( \ SCOTCH_Graph * const grafptr, \ int * const revaptr), \ (grafptr, revaptr)) { *revaptr = SCOTCH_graphInit (grafptr); } /* ** */ FORTRAN ( \ SCOTCHFGRAPHEXIT, scotchfgraphexit, ( \ SCOTCH_Graph * const grafptr), \ (grafptr)) { SCOTCH_graphExit (grafptr); } /* ** */ FORTRAN ( \ SCOTCHFGRAPHFREE, scotchfgraphfree, ( \ SCOTCH_Graph * const grafptr), \ (grafptr)) { SCOTCH_graphFree (grafptr); } /* When an input stream is built from the given ** file handle, it is set as unbuffered, so as to ** allow for multiple stream reads from the same ** file handle. If it were buffered, too many ** input characters would be read on the first ** block read. */ FORTRAN ( \ SCOTCHFGRAPHLOAD, scotchfgraphload, ( \ SCOTCH_Graph * const grafptr, \ int * const fileptr, \ const SCOTCH_Num * const baseptr, \ const SCOTCH_Num * const flagptr, \ int * const revaptr), \ (grafptr, fileptr, baseptr, flagptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHLOAD: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHLOAD: cannot open input stream"); close (filenum); *revaptr = 1; return; } setbuf (stream, NULL); /* Do not buffer on input */ o = SCOTCH_graphLoad (grafptr, stream, *baseptr, *flagptr); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFGRAPHSAVE, scotchfgraphsave, ( \ const SCOTCH_Graph * const grafptr, \ int * const fileptr, \ int * const revaptr), \ (grafptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHSAVE: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHSAVE: cannot open output stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_graphSave (grafptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFGRAPHBUILD, scotchfgraphbuild, ( \ SCOTCH_Graph * const grafptr, \ const SCOTCH_Num * const baseptr, \ const SCOTCH_Num * const vertptr, \ const SCOTCH_Num * const verttab, \ const SCOTCH_Num * const vendtab, \ const SCOTCH_Num * const velotab, \ const SCOTCH_Num * const vlbltab, \ const SCOTCH_Num * const edgeptr, \ const SCOTCH_Num * const edgetab, \ const SCOTCH_Num * const edlotab, \ int * const revaptr), \ (grafptr, baseptr, vertptr, verttab, vendtab, \ velotab, vlbltab, edgeptr, edgetab, edlotab, \ revaptr)) { *revaptr = SCOTCH_graphBuild (grafptr, *baseptr, *vertptr, verttab, vendtab, velotab, vlbltab, *edgeptr, edgetab, edlotab); } /* ** */ FORTRAN ( \ SCOTCHFGRAPHSIZE, scotchfgraphsize, ( \ const SCOTCH_Graph * const grafptr, \ SCOTCH_Num * const vertptr, \ SCOTCH_Num * const edgeptr), \ (grafptr, vertptr, edgeptr)) { SCOTCH_graphSize (grafptr, vertptr, edgeptr); } /* ** */ FORTRAN ( \ SCOTCHFGRAPHDATA, scotchfgraphdata, ( \ const SCOTCH_Graph * const grafptr, \ const SCOTCH_Num * const indxptr, \ SCOTCH_Num * const baseptr, \ SCOTCH_Num * const vertptr, \ SCOTCH_Idx * const vertidx, \ SCOTCH_Idx * const vendidx, \ SCOTCH_Idx * const veloidx, \ SCOTCH_Idx * const vlblidx, \ SCOTCH_Num * const edgeptr, \ SCOTCH_Idx * const edgeidx, \ SCOTCH_Idx * const edloidx), \ (grafptr, indxptr, baseptr, \ vertptr, vertidx, vendidx, veloidx, vlblidx, \ edgeptr, edgeidx, edloidx)) { SCOTCH_Num * verttab; /* Pointer to graph arrays */ SCOTCH_Num * vendtab; SCOTCH_Num * velotab; SCOTCH_Num * vlbltab; SCOTCH_Num * edgetab; SCOTCH_Num * edlotab; SCOTCH_graphData (grafptr, baseptr, vertptr, &verttab, &vendtab, &velotab, &vlbltab, edgeptr, &edgetab, &edlotab); *vertidx = (verttab - indxptr) + 1; /* Add 1 since Fortran indices start at 1 */ *vendidx = (vendtab - indxptr) + 1; *veloidx = (velotab != NULL) ? (velotab - indxptr) + 1 : *vertidx; *vlblidx = (vlbltab != NULL) ? (vlbltab - indxptr) + 1 : *vertidx; *edgeidx = (edgetab - indxptr) + 1; *edloidx = (edlotab != NULL) ? (edlotab - indxptr) + 1 : *edgeidx; } /* ** */ FORTRAN ( \ SCOTCHFGRAPHSTAT, scotchfgraphstat, ( \ const SCOTCH_Graph * const grafptr, \ SCOTCH_Num * const velominptr, \ SCOTCH_Num * const velomaxptr, \ SCOTCH_Num * const velosumptr, \ double * veloavgptr, \ double * velodltptr, \ SCOTCH_Num * const degrminptr, \ SCOTCH_Num * const degrmaxptr, \ double * degravgptr, \ double * degrdltptr, \ SCOTCH_Num * const edlominptr, \ SCOTCH_Num * const edlomaxptr, \ SCOTCH_Num * const edlosumptr, \ double * edloavgptr, \ double * edlodltptr), \ (grafptr, velominptr, velomaxptr, velosumptr, \ veloavgptr, velodltptr, degrminptr, \ degrmaxptr, degravgptr, degrdltptr, \ edlominptr, edlomaxptr, edlosumptr, \ edloavgptr, edlodltptr)) { SCOTCH_graphStat (grafptr, velominptr, velomaxptr, velosumptr, veloavgptr, velodltptr, degrminptr, degrmaxptr, degravgptr, degrdltptr, edlominptr, edlomaxptr, edlosumptr, edloavgptr, edlodltptr); } scotch-5.1.12b.dfsg/src/libscotch/bgraph.h0000644000175300017530000001767411631334325020566 0ustar hazelscthazelsct/* Copyright 2004,2007,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the job control routines of the **/ /** Dual Recursive Bipartitioning method. **/ /** **/ /** DATES : # Version 0.0 : from : 23 mar 1993 **/ /** to 12 may 1993 **/ /** # Version 1.3 : from : 06 apr 1994 **/ /** to 09 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 04 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to 30 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 15 nov 1995 **/ /** to 15 nov 1995 **/ /** # Version 3.2 : from : 24 aug 1996 **/ /** to 03 nov 1997 **/ /** # Version 3.3 : from : 01 dec 1998 **/ /** to 02 dec 1998 **/ /** # Version 4.0 : from : 18 dec 2001 **/ /** to 05 may 2006 **/ /** # Version 5.0 : from : 30 nov 2006 **/ /** to 30 nov 2006 **/ /** # Version 5.1 : from : 08 jan 2008 **/ /** to 18 mar 2011 **/ /** **/ /************************************************************/ #define BGRAPH_H /* ** The type and structure definitions. */ /*+ Graph option flags. +*/ #define BGRAPHFREEFRON (GRAPHBITSNOTUSED) /* Free frontier array */ #define BGRAPHFREEPART (GRAPHBITSNOTUSED << 1) /* Free part array */ #define BGRAPHFREEVEEX (GRAPHBITSNOTUSED << 2) /* Free external gain array */ /*+ The bipartition graph structure. +*/ typedef struct Bgraph_ { Graph s; /*+ Source graph data +*/ Gnum * veextax; /*+ Vertex external gain array if moved to 1 +*/ GraphPart * parttax; /*+ Array of parts for every vertex +*/ Gnum * frontab; /*+ Array of frontier vertex numbers +*/ Gnum fronnbr; /*+ Number of frontier vertices +*/ Gnum compload0min; /*+ Minimum allowed load in part 0 (strategy variable) +*/ Gnum compload0max; /*+ Maximum allowed load in part 0 (strategy variable) +*/ Gnum compload0avg; /*+ Average load of part 0 +*/ Gnum compload0dlt; /*+ Difference from the average +*/ Gnum compload0; /*+ Load in part 0 (strategy variable) +*/ Gnum compsize0; /*+ Number of vertices in part 0 +*/ Gnum commload; /*+ Communication load +*/ Gnum commloadextn0; /*+ Communication load if all moved to part 0 +*/ Gnum commgainextn0; /*+ External gain if all swapped from part 0 +*/ Gnum commgainextn; /*+ External gain if all swapped +*/ Anum domdist; /*+ Distance between subdomains +*/ Gnum domwght[2]; /*+ Weights of the two subdomains +*/ INT levlnum; /*+ Coarsening level +*/ double bbalval; /*+ Bipartitioning imbalance ratio (strategy variable) +*/ } Bgraph; /*+ The save graph structure. +*/ typedef struct BgraphStore_ { Gnum fronnbr; /*+ Number of frontier nodes +*/ Gnum compload0dlt; /*+ Difference from the average +*/ Gnum compsize0; /*+ Number of vertices in part 0 +*/ Gnum commload; /*+ Communication load +*/ Gnum commgainextn; /*+ External gain if all swapped +*/ byte * datatab; /*+ Variable-sized data array +*/ } BgraphStore; /* ** The function prototypes. */ #ifndef BGRAPH #define static #endif #ifdef MAPPING_H int bgraphInit (Bgraph * const, const Graph * const, const Graph * const, const Mapping * const, const ArchDom[]); #endif /* MAPPING_H */ void bgraphInit2 (Bgraph * const, const Anum, const Anum, const Anum); #ifdef MAPPING_H int bgraphInit3 (Bgraph * const, const Graph * const, const Mapping * const, const ArchDom[]); #endif /* MAPPING_H */ void bgraphExit (Bgraph * restrict const); void bgraphSwal (Bgraph * restrict const); void bgraphZero (Bgraph * restrict const); int bgraphCheck (const Bgraph * restrict const); int bgraphStoreInit (const Bgraph * const, BgraphStore * const); void bgraphStoreExit (BgraphStore * const); void bgraphStoreSave (const Bgraph * const, BgraphStore * const); void bgraphStoreUpdt (Bgraph * const, const BgraphStore * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/graph_io_scot.h0000644000175300017530000000633411631334325022132 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_io_scot.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the Scotch graph format **/ /** module. **/ /** **/ /** DATES : # Version 3.2 : from : 06 nov 1997 **/ /** to 06 nov 1997 **/ /** # Version 3.3 : from : 13 dec 1998 **/ /** to 21 dec 1998 **/ /** # Version 4.0 : from : 18 dec 2001 **/ /** to 19 jan 2004 **/ /** # Version 5.0 : from : 13 sep 2006 **/ /** to 13 sep 2006 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ The sort structure, used to sort graph vertices by label. Field labl is first because of intSort2asc1. +*/ typedef struct GraphGeomScotSort_ { Gnum labl; /*+ Vertex label: FIRST +*/ Gnum num; /*+ Vertex number +*/ } GraphGeomScotSort; scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_gp.h0000644000175300017530000001055111631334325022600 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_gp.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the Gibbs, Poole, and Stockmeyer **/ /** bipartitioning algorithm. **/ /** **/ /** DATES : # Version 2.0 : from : 06 jun 1994 **/ /** to 28 oct 1994 **/ /** # Version 3.2 : from : 21 sep 1996 **/ /** to 13 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 01 nov 2003 **/ /** to 20 aug 2004 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ Method parameters. +*/ typedef struct BgraphBipartGpParam_ { INT passnbr; /*+ Number of passes to do +*/ } BgraphBipartGpParam; /*+ Complementary vertex structure. +*/ typedef struct BgraphBipartGpVertex_ { Gnum passnum; /*+ Number of pass when vertex selected +*/ Gnum distval; /*+ Current distance from diameter vertex +*/ } BgraphBipartGpVertex; /*+ Neighbor queue. +*/ typedef struct BgraphBipartGpQueue_ { Gnum headnum; /*+ Head of distance queue +*/ Gnum tailnum; /*+ Tail of distance queue +*/ Gnum * queutab; /*+ Array of queue elements +*/ } BgraphBipartGpQueue; /* ** The function prototypes. */ #ifndef BGRAPH_BIPART_GP #define static #endif int bgraphBipartGp (Bgraph * restrict const, const BgraphBipartGpParam * const); #undef static /* ** The macro definitions. */ #define bgraphBipartGpQueueFlush(queue) ((queue)->headnum = (queue)->tailnum = 0) #define bgraphBipartGpQueueEmpty(queue) ((queue)->headnum <= (queue)->tailnum) #define bgraphBipartGpQueuePut(queue,vnum) ((queue)->queutab[(queue)->headnum ++] = (vnum)) #define bgraphBipartGpQueueGet(queue) ((queue)->queutab[(queue)->tailnum ++]) scotch-5.1.12b.dfsg/src/libscotch/kgraph_map_st.c0000644000175300017530000002473611631334325022132 0ustar hazelscthazelsct/* Copyright 2004,2007,2009-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kgraph_map_st.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the strategy and **/ /** method tables for the multi-way static **/ /** mapping routines. **/ /** **/ /** DATES : # Version 3.2 : from : 15 oct 1996 **/ /** to 26 may 1998 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to 17 may 1999 **/ /** # Version 3.4 : from : 12 sep 2001 **/ /** to 12 sep 2001 **/ /** # Version 4.0 : from : 12 jan 2004 **/ /** to 05 jan 2005 **/ /** # Version 5.1 : from : 04 oct 2009 **/ /** to 29 mar 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define KGRAPH_MAP_ST #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "graph_coarsen.h" #include "arch.h" #include "mapping.h" #include "bgraph.h" #include "bgraph_bipart_st.h" #include "kgraph.h" #include "kgraph_map_ml.h" #include "kgraph_map_rb.h" #include "kgraph_map_st.h" /* ** The static and global variables. */ static union { KgraphMapMlParam param; StratNodeMethodData padding; } kgraphmapstdefaultml = { { 100, 0.8L, GRAPHCOARHEM, &stratdummy, &stratdummy } }; static union { KgraphMapRbParam param; StratNodeMethodData padding; } kgraphmapstdefaultrb = { { 1, 1, KGRAPHMAPRBPOLINGSIZE, &stratdummy, 0.05 } }; static StratMethodTab kgraphmapstmethtab[] = { /* Mapping methods array */ { KGRAPHMAPSTMETHML, "m", kgraphMapMl, &kgraphmapstdefaultml }, { KGRAPHMAPSTMETHRB, "r", kgraphMapRb, &kgraphmapstdefaultrb }, { -1, NULL, NULL, NULL } }; static StratParamTab kgraphmapstparatab[] = { /* Method parameter list */ { KGRAPHMAPSTMETHML, STRATPARAMSTRAT, "asc", (byte *) &kgraphmapstdefaultml.param, (byte *) &kgraphmapstdefaultml.param.stratasc, (void *) &kgraphmapststratab }, { KGRAPHMAPSTMETHML, STRATPARAMSTRAT, "low", (byte *) &kgraphmapstdefaultml.param, (byte *) &kgraphmapstdefaultml.param.stratlow, (void *) &kgraphmapststratab }, { KGRAPHMAPSTMETHML, STRATPARAMCASE, "type", (byte *) &kgraphmapstdefaultml.param, (byte *) &kgraphmapstdefaultml.param.coartype, (void *) "hscd" }, { KGRAPHMAPSTMETHML, STRATPARAMINT, "vert", (byte *) &kgraphmapstdefaultml.param, (byte *) &kgraphmapstdefaultml.param.coarnbr, NULL }, { KGRAPHMAPSTMETHML, STRATPARAMDOUBLE, "rat", (byte *) &kgraphmapstdefaultml.param, (byte *) &kgraphmapstdefaultml.param.coarrat, NULL }, { KGRAPHMAPSTMETHRB, STRATPARAMCASE, "job", (byte *) &kgraphmapstdefaultrb.param, (byte *) &kgraphmapstdefaultrb.param.flagjobtie, (void *) "ut" }, { KGRAPHMAPSTMETHRB, STRATPARAMDOUBLE, "bal", (byte *) &kgraphmapstdefaultrb.param, (byte *) &kgraphmapstdefaultrb.param.kbalval, NULL }, { KGRAPHMAPSTMETHRB, STRATPARAMCASE, "map", (byte *) &kgraphmapstdefaultrb.param, (byte *) &kgraphmapstdefaultrb.param.flagmaptie, (void *) "ut" }, { KGRAPHMAPSTMETHRB, STRATPARAMCASE, "poli", (byte *) &kgraphmapstdefaultrb.param, (byte *) &kgraphmapstdefaultrb.param.polival, (void *) "rls LS" }, { KGRAPHMAPSTMETHRB, STRATPARAMSTRAT, "sep", (byte *) &kgraphmapstdefaultrb.param, (byte *) &kgraphmapstdefaultrb.param.strat, (void *) &bgraphbipartststratab }, { KGRAPHMAPSTMETHNBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; static StratParamTab kgraphmapstcondtab[] = { /* Graph condition parameter table */ { STRATNODENBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; StratTab kgraphmapststratab = { /* Strategy tables for graph mapping methods */ kgraphmapstmethtab, kgraphmapstparatab, kgraphmapstcondtab }; /****************************************/ /* */ /* This is the generic mapping routine. */ /* */ /****************************************/ /* This routine computes the given ** mapping according to the given ** strategy. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int kgraphMapSt ( Kgraph * restrict const grafptr, /*+ Mapping graph +*/ const Strat * restrict const strat) /*+ Mapping strategy +*/ { StratTest val; int o; #ifdef SCOTCH_DEBUG_KGRAPH2 if (sizeof (Gnum) != sizeof (INT)) { errorPrint ("kgraphMapSt: invalid type specification for parser variables"); return (1); } if ((sizeof (KgraphMapRbParam) > sizeof (StratNodeMethodData))) { errorPrint ("kgraphMapSt: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_KGRAPH2 */ #ifdef SCOTCH_DEBUG_KGRAPH1 if ((strat->tabl != &kgraphmapststratab) && (strat != &stratdummy)) { errorPrint ("kgraphMapSt: invalid parameter (1)"); return (1); } #endif /* SCOTCH_DEBUG_KGRAPH1 */ o = 0; switch (strat->type) { case STRATNODECONCAT : o = kgraphMapSt (grafptr, strat->data.concat.strat[0]); /* Apply first strategy */ if (o == 0) /* If it worked all right */ o |= kgraphMapSt (grafptr, strat->data.concat.strat[1]); /* Then apply second strategy */ break; case STRATNODECOND : o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ if (o == 0) { /* If evaluation was correct */ #ifdef SCOTCH_DEBUG_KGRAPH2 if ((val.typetest != STRATTESTVAL) || (val.typenode != STRATPARAMLOG)) { errorPrint ("kgraphMapSt: invalid test result"); o = 1; break; } #endif /* SCOTCH_DEBUG_KGRAPH2 */ if (val.data.val.vallog == 1) /* If expression is true */ o = kgraphMapSt (grafptr, strat->data.cond.strat[0]); /* Apply first strategy */ else { /* Else if expression is false */ if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ o = kgraphMapSt (grafptr, strat->data.cond.strat[1]); /* Apply second strategy */ } } break; case STRATNODEEMPTY : break; case STRATNODESELECT : errorPrint ("kgraphMapSt: selection operator not implemented for k-way strategies"); return (1); #ifdef SCOTCH_DEBUG_KGRAPH1 case STRATNODEMETHOD : #else /* SCOTCH_DEBUG_KGRAPH1 */ default : #endif /* SCOTCH_DEBUG_KGRAPH1 */ return (strat->tabl->methtab[strat->data.method.meth].func (grafptr, (void *) &strat->data.method.data)); #ifdef SCOTCH_DEBUG_KGRAPH1 default : errorPrint ("kgraphMapSt: invalid parameter (2)"); return (1); #endif /* SCOTCH_DEBUG_KGRAPH1 */ } return (o); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_f.c0000644000175300017530000001467011631334325022605 0ustar hazelscthazelsct/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the distributed source graph handling **/ /** routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 04 sep 2006 **/ /** to 05 aug 2007 **/ /** # Version 5.1 : from : 27 jul 2008 **/ /** to 15 apr 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the graph handling routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFDGRAPHINIT, scotchfdgraphinit, ( \ SCOTCH_Dgraph * const grafptr, \ const MPI_Fint * const commptr, \ int * const revaptr), \ (grafptr, commptr, revaptr)) { MPI_Comm commdat; commdat = MPI_Comm_f2c (*commptr); *revaptr = SCOTCH_dgraphInit (grafptr, commdat); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHEXIT, scotchfdgraphexit, ( \ SCOTCH_Dgraph * const grafptr), \ (grafptr)) { SCOTCH_dgraphExit (grafptr); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHSIZE, scotchfdgraphsize, ( \ const SCOTCH_Dgraph * const grafptr, \ SCOTCH_Num * const vertglbptr, \ SCOTCH_Num * const vertlocptr, \ SCOTCH_Num * const edgeglbptr, \ SCOTCH_Num * const edgelocptr), \ (grafptr, vertglbptr, vertlocptr, edgeglbptr, edgelocptr)) { SCOTCH_dgraphSize (grafptr, vertglbptr, vertlocptr, edgeglbptr, edgelocptr); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHDATA, scotchfdgraphdata, ( \ const SCOTCH_Dgraph * const grafptr, \ const SCOTCH_Num * const indxptr, \ SCOTCH_Num * const baseptr, \ SCOTCH_Num * const vertglbptr, \ SCOTCH_Num * const vertlocptr, \ SCOTCH_Num * const vertlocptz, \ SCOTCH_Num * const vertgstptr, \ SCOTCH_Idx * const vertlocidx, \ SCOTCH_Idx * const vendlocidx, \ SCOTCH_Idx * const velolocidx, \ SCOTCH_Idx * const vlbllocidx, \ SCOTCH_Num * const edgeglbptr, \ SCOTCH_Num * const edgelocptr, \ SCOTCH_Num * const edgelocptz, \ SCOTCH_Idx * const edgelocidx, \ SCOTCH_Idx * const edgegstidx, \ SCOTCH_Idx * const edlolocidx, \ MPI_Fint * const commptr), \ (grafptr, indxptr, baseptr, \ vertglbptr, vertlocptr, vertlocptz, \ vertgstptr, vertlocidx, vendlocidx, \ velolocidx, vlbllocidx, edgeglbptr, \ edgelocptr, edgelocptz, edgelocidx, \ edgegstidx, edlolocidx, commptr)) { SCOTCH_Num * vertloctab; /* Pointer to graph arrays */ SCOTCH_Num * vendloctab; SCOTCH_Num * veloloctab; SCOTCH_Num * vlblloctab; SCOTCH_Num * edgeloctab; SCOTCH_Num * edgegsttab; SCOTCH_Num * edloloctab; MPI_Comm commdat; SCOTCH_dgraphData (grafptr, baseptr, vertglbptr, vertlocptr, vertlocptz, vertgstptr, &vertloctab, &vendloctab, &veloloctab, &vlblloctab, edgeglbptr, edgelocptr, edgelocptz, &edgeloctab, &edgegsttab, &edloloctab, &commdat); *vertlocidx = (vertloctab - indxptr) + 1; /* Add 1 since Fortran indices start at 1 */ *vendlocidx = (vendloctab - indxptr) + 1; *velolocidx = (veloloctab != NULL) ? (veloloctab - indxptr) + 1 : *vertlocidx; *vlbllocidx = (vlblloctab != NULL) ? (vlblloctab - indxptr) + 1 : *vertlocidx; *edgelocidx = (edgeloctab - indxptr) + 1; *edgegstidx = (edgegsttab != NULL) ? (edgegsttab - indxptr) + 1 : *vertlocidx; *edlolocidx = (edloloctab != NULL) ? (edloloctab - indxptr) + 1 : *vertlocidx; *commptr = MPI_Comm_c2f (commdat); } scotch-5.1.12b.dfsg/src/libscotch/common.h0000644000175300017530000003137511631334325020605 0ustar hazelscthazelsct/* Copyright 2004,2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : common.h **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** David GOUDIN **/ /** Pascal HENON **/ /** Pierre RAMET **/ /** Cedric CHEVALIER (v5.0) **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** These lines are the common data **/ /** declarations for all modules. **/ /** **/ /** DATES : # Version 0.0 : from : 08 may 1998 **/ /** to : 08 jan 2001 **/ /** # Version 1.0 : from : 06 jun 2002 **/ /** to : 06 jun 2002 **/ /** # Version 2.0 : from : 13 jun 2005 **/ /** to : 01 jul 2008 **/ /** # Version 5.1 : from : 09 nov 2008 **/ /** to : 23 nov 2010 **/ /** **/ /************************************************************/ #define COMMON_H /* ** The includes. */ #ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE 600 #endif /* _XOPEN_SOURCE */ #include #include #include #include #include #include #if (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) #include #endif /* (((defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || (defined HAVE_STDINT_H)) */ #ifdef HAVE_MALLOC_H #include /* Deprecated, but required on some old systems */ #endif /* HAVE_MALLOC_H */ #include #include #include /* For the effective calls to clock () */ #include #include #include #if ((defined COMMON_TIMING_OLD) || (defined HAVE_SYS_TIME_H)) #include #endif /* ((defined COMMON_TIMING_OLD) || (defined HAVE_SYS_TIME_H)) */ #if ((defined COMMON_TIMING_OLD) || (defined HAVE_SYS_RESOURCE_H)) #include #endif /* ((defined COMMON_TIMING_OLD) || (defined HAVE_SYS_RESOURCE_H)) */ #if ((defined COMMON_WINDOWS) || (defined HAVE_WINDOWS_H)) #include #endif /* ((defined COMMON_WINDOWS) || (defined HAVE_WINDOWS_H)) */ #if ((! defined COMMON_WINDOWS) && (! defined HAVE_NOT_UNISTD_H)) #include #endif /* ((! defined COMMON_WINDOWS) && (! defined HAVE_NOT_UNISTD_H)) */ #ifdef SCOTCH_PTSCOTCH #include #endif /* SCOTCH_PTSCOTCH */ #if ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) #include #endif /* ((defined COMMON_PTHREAD) || (defined SCOTCH_PTHREAD)) */ /* ** Working definitions. */ #ifdef COMMON_MEMORY_TRACE #define memAlloc(size) memAllocRecord ((size) | 8) #define memRealloc(ptr,size) memReallocRecord ((ptr), ((size) | 8)) #define memFree(ptr) (memFreeRecord ((void *) (ptr)), 0) #else /* COMMON_MEMORY_TRACE */ #define memAlloc(size) malloc((size) | 8) /* For platforms which return NULL for malloc(0) */ #define memRealloc(ptr,size) realloc((ptr),((size) | 8)) #define memFree(ptr) (free ((char *) (ptr)), 0) #endif /* COMMON_MEMORY_TRACE */ #define memSet(ptr,val,siz) memset((ptr),(val),(siz)) #define memCpy(dst,src,siz) memcpy((dst),(src),(siz)) #define memMov(dst,src,siz) memmove((dst),(src),(siz)) #define MIN(x,y) (((x) < (y)) ? (x) : (y)) #define MAX(x,y) (((x) < (y)) ? (y) : (x)) #define ABS(x) MAX ((x), -(x)) #define SIGN(x) (((x) < 0) ? -1 : 1) /* ** Handling of generic types. */ #ifndef INT /* If type not externally overriden */ #ifdef INTSIZE32 #define INT int32_t #define UINT u_int32_t #define COMM_INT MPI_INTEGER4 #define INTSTRING "%d" #else /* INTSIZE32 */ #ifdef INTSIZE64 #define INT int64_t #define UINT u_int64_t #define COMM_INT MPI_LONG_LONG #define INTSTRING "%lld" #else /* INTSIZE64 */ #ifdef LONG /* Better not use it */ #define INT long /* Long integer type */ #define UINT unsigned long #define COMM_INT MPI_LONG #define INTSTRING "%ld" #else /* LONG */ #define INT int /* Default integer type */ #define UINT unsigned int #define COMM_INT MPI_INT /* Generic MPI integer type */ #define INTSTRING "%d" #endif /* LONG */ #endif /* INTSIZE64 */ #endif /* INTSIZE32 */ #endif /* INT */ #ifndef IDX /* If type not externally overriden */ #ifdef IDXSIZE32 #define IDX int32_t #else /* IDXSIZE32 */ #ifdef IDXSIZE64 #define IDX int64_t #else /* IDXSIZE64 */ #define IDX INT #endif /* IDXSIZE64 */ #endif /* IDXSIZE32 */ #endif /* IDX */ #ifndef INTSIZEBITS #define INTSIZEBITS (sizeof (INT) << 3) #endif /* INTSIZEBITS */ #define INTVALMAX ((INT) (((UINT) 1 << (INTSIZEBITS - 1)) - 1)) #define byte unsigned char /* Byte type */ #ifndef BYTE #define BYTE byte #endif /* BYTE */ #ifndef COMM_BYTE #define COMM_BYTE MPI_BYTE #endif /* COMM_BYTE */ #define COMM_PART COMM_BYTE /* ** Handling of flag arrays. */ #define flagSize(n) (((n) + (sizeof (int) << 3) - 1) / (sizeof (int) << 3)) #define flagVal(a,n) (((a)[(n) / (sizeof (int) << 3)] >> ((n) & ((sizeof (int) << 3) - 1))) & 1) #define flagSet(a,n) (a)[(n) / (sizeof (int) << 3)] |= (1 << ((n) & ((sizeof (int) << 3) - 1))) /* ** Handling of timers. */ /** The clock type. **/ typedef struct Clock_ { double time[2]; /*+ The start and accumulated times +*/ } Clock; /* ** Handling of files. */ /** The file structure. **/ typedef struct File_ { char * name; /*+ File name +*/ FILE * pntr; /*+ File pointer +*/ char * mode; /*+ Opening mode +*/ } File; /* ** Function prototypes. */ void * memAllocGroup (void **, ...); void * memReallocGroup (void *, ...); void * memOffset (void *, ...); #ifdef COMMON_MEMORY_TRACE void * memAllocRecord (size_t); void * memReallocRecord (void * const, size_t); void memFreeRecord (void * const); size_t memMax (); #endif /* COMMON_MEMORY_TRACE */ void usagePrint (FILE * const, const char (* [])); int fileBlockOpen (File * const, const int); int fileBlockOpenDist (File * const, const int, const int, const int, const int); void fileBlockClose (File * const, const int); FILE * fileCompress (FILE * const, const int); int fileCompressType (const char * const); FILE * fileUncompress (FILE * const, const int); int fileUncompressType (const char * const); int fileNameDistExpand (char ** const, const int, const int, const int); void errorProg (const char * const); void errorPrint (const char * const, ...); void errorPrintW (const char * const, ...); int intLoad (FILE * const, INT * const); int intSave (FILE * const, const INT); void intAscn (INT * const, const INT, const INT); void intPerm (INT * const, const INT); void intRandReset (void); void intRandInit (void); INT intRandVal (INT); void intSort1asc1 (void * const, const INT); void intSort2asc1 (void * const, const INT); void intSort2asc2 (void * const, const INT); void intSort3asc1 (void * const, const INT); void intSort3asc2 (void * const, const INT); INT intSearchDicho (const INT * const, const INT, const INT, const INT); void clockInit (Clock * const); void clockStart (Clock * const); void clockStop (Clock * const); double clockVal (Clock * const); double clockGet (void); void stringSubst (char * const, const char * const, const char * const); /* ** Macro definitions. */ #define clockInit(clk) ((clk)->time[0] = (clk)->time[1] = 0) #define clockStart(clk) ((clk)->time[0] = clockGet ()) #define clockStop(clk) ((clk)->time[1] += (clockGet () - (clk)->time[0])) #define clockVal(clk) ((clk)->time[1]) #ifdef COMMON_RANDOM_RAND #define intRandVal(ival) ((INT) (((UINT) rand ()) % ((UINT) (ival)))) #else /* COMMON_RANDOM_RAND */ #define intRandVal(ival) ((INT) (((UINT) random ()) % ((UINT) (ival)))) #endif /* COMMON_RANDOM_RAND */ #define DATASIZE(n,p,i) ((INT) (((n) + ((p) - 1 - (i))) / (p))) #define FORTRAN(nu,nl,pl,pc) FORTRAN2(FORTRAN3(nu),FORTRAN3(nl),pl,pc) #define FORTRAN2(nu,nl,pl,pc) \ void nu pl; \ void nl pl \ { nu pc; } \ void FORTRAN4(nl,_) pl \ { nu pc; } \ void FORTRAN4(nl,__) pl \ { nu pc; } \ void nu pl #define FORTRAN3(s) s #define FORTRAN4(p,s) p##s #define STRINGIFY2(n) #n #define STRINGIFY(n) STRINGIFY2(n) scotch-5.1.12b.dfsg/src/libscotch/vdgraph_separate_bd.h0000644000175300017530000000603111631334325023270 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_separate_bd.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the band vertex separation **/ /** routine for distributed graphs. **/ /** **/ /** DATES : # Version 5.0 : from : 04 mar 2006 **/ /** to : 04 mar 2006 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct VdgraphSeparateBdParam_ { INT distmax; /*+ Width of band surrounding the separator +*/ Strat * strat; /*+ Separation strategy used on the band garph +*/ } VdgraphSeparateBdParam; /* ** The function prototypes. */ #ifndef VDGRAPH_SEPARATE_BD #define static #endif int vdgraphSeparateBd (Vdgraph * const, const VdgraphSeparateBdParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_bd.c0000644000175300017530000005312211631334325023122 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_bd.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER **/ /** **/ /** FUNCTION : This module builds a band graph around **/ /** the frontier in order to decrease **/ /** problem size for the strategy to be **/ /** applied. **/ /** **/ /** DATES : # Version 5.0 : from : 18 oct 2004 **/ /** to : 12 sep 2007 **/ /** # Version 5.1 : from : 30 oct 2007 **/ /** to : 09 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VGRAPH_SEPARATE_BD #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "vgraph.h" #include "vgraph_separate_bd.h" #include "vgraph_separate_st.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ int vgraphSeparateBd ( Vgraph * restrict const orggrafptr, /*+ Active graph +*/ const VgraphSeparateBdParam * const paraptr) /*+ Method parameters +*/ { VgraphSeparateBdQueue queudat; /* Neighbor queue */ Gnum * restrict orgdisttax; /* Based access to distance array for original graph */ Gnum orgdistmax; /* Maximum distance allowed */ #define orgindxtax orgdisttax /* Recycle distance array as number indexing array */ Vgraph bndgrafdat; /* Band graph structure */ Gnum bndvertnbr; /* Number of regular vertices in band graph (without anchors) */ Gnum bndvertnnd; Gnum * restrict bndvnumtax; /* Band vertex number array, recycling queudat.qtab */ Gnum bndcompsize1; /* Number of regular vertices in part 1 of band graph */ Gnum bndcompload1; /* Load of regular vertices in part 1 */ Gnum bndvlvlnum; /* Index of first band graph vertex to belong to the last layer */ Gnum bndvertnum; Gnum bndvelosum; /* Load of regular vertices in band graph */ Gnum * restrict bndedgetax; Gnum bndedgenbr; /* Upper bound on the number of edges, including anchor edges */ Gnum bndeancnbr; /* Number of anchor edges */ Gnum bndedgenum; Gnum bndedgetmp; Gnum bnddegrmax; Gnum fronnum; const Gnum * restrict const orgverttax = orggrafptr->s.verttax; /* Fast accesses */ const Gnum * restrict const orgvendtax = orggrafptr->s.vendtax; const Gnum * restrict const orgvelotax = orggrafptr->s.velotax; const Gnum * restrict const orgedgetax = orggrafptr->s.edgetax; if (orggrafptr->fronnbr == 0) /* If no separator vertices, apply strategy to full graph */ return (vgraphSeparateSt (orggrafptr, paraptr->stratorg)); orgdistmax = (Gnum) paraptr->distmax; if (orgdistmax < 1) /* To simplify algorithm, always at least one layer of vertices around separator */ orgdistmax = 1; if (memAllocGroup ((void **) (void *) &queudat.qtab, (size_t) (orggrafptr->s.vertnbr * sizeof (Gnum)), /* TRICK: no need of "+ 2" for anchor vertices (see below) */ &orgdisttax, (size_t) (orggrafptr->s.vertnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("vgraphSeparateBd: out of memory (1)"); return (1); } memSet (orgdisttax, ~0, orggrafptr->s.vertnbr * sizeof (Gnum)); /* Initialize distance array */ orgdisttax -= orggrafptr->s.baseval; vgraphSeparateBdQueueFlush (&queudat); /* Flush vertex queue */ bndedgenbr = 0; /* Guess upper bound on the number of edges */ bndvelosum = 0; for (fronnum = 0; fronnum < orggrafptr->fronnbr; fronnum ++) { /* Enqueue separator vertices */ Gnum orgvertnum; orgvertnum = orggrafptr->frontab[fronnum]; #ifdef SCOTCH_DEBUG_VGRAPH2 if ((orgvertnum < orggrafptr->s.baseval) || (orgvertnum >= orggrafptr->s.vertnnd)) { errorPrint ("vgraphSeparateBd: internal error (1)"); memFree (queudat.qtab); /* Free group leader */ return (1); } if (orgdisttax[orgvertnum] != ~0) { errorPrint ("vgraphSeparateBd: internal error (2)"); memFree (queudat.qtab); /* Free group leader */ return (1); } if (orggrafptr->parttax[orgvertnum] != 2) { errorPrint ("vgraphSeparateBd: internal error (3)"); memFree (queudat.qtab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ orgdisttax[orgvertnum] = 0; vgraphSeparateBdQueuePut (&queudat, orgvertnum); if (orgvelotax != NULL) bndvelosum += orgvelotax[orgvertnum]; } bndcompsize1 = 0; bndcompload1 = 0; do { /* Loop on vertices in queue */ Gnum orgvertnum; Gnum orgedgenum; Gnum orgdistval; orgvertnum = vgraphSeparateBdQueueGet (&queudat); #ifdef SCOTCH_DEBUG_VGRAPH2 if ((orgvertnum < orggrafptr->s.baseval) || (orgvertnum >= orggrafptr->s.vertnnd)) { errorPrint ("vgraphSeparateBd: internal error (4)"); memFree (queudat.qtab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ bndedgenbr += orgvendtax[orgvertnum] - orgverttax[orgvertnum]; /* Exact or upper bound on number of edges, including anchor edge(s) */ orgdistval = orgdisttax[orgvertnum]; /* Get vertex distance */ if (orgdistval >= orgdistmax) { /* If we belong to the farthest layer */ bndedgenbr ++; /* One more anchor edge, for the opposite */ continue; } orgdistval ++; /* Distance of neighbors */ for (orgedgenum = orgverttax[orgvertnum]; orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++) { Gnum orgvertend; Gnum orgpartval1; orgvertend = orgedgetax[orgedgenum]; if (orgdisttax[orgvertend] == ~0) { /* If vertex not visited yet */ #ifdef SCOTCH_DEBUG_VGRAPH2 if (orggrafptr->parttax[orgvertend] > 1) { errorPrint ("vgraphSeparateBd: internal error (5)"); memFree (queudat.qtab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ orgpartval1 = orggrafptr->parttax[orgvertend] & 1; orgdisttax[orgvertend] = orgdistval; /* Enqueue vertex */ vgraphSeparateBdQueuePut (&queudat, orgvertend); bndcompsize1 += orgpartval1; /* Count vertices in part 1 */ if (orgvelotax != NULL) { bndvelosum += orgvelotax[orgvertend]; bndcompload1 += orgvelotax[orgvertend] * orgpartval1; } } } } while (! vgraphSeparateBdQueueEmpty (&queudat)); /* As long as queue is not empty */ bndvertnbr = queudat.head - queudat.qtab; /* Number of regular band graph vertices (withour anchors) is number of enqueued vertices */ if (orgvelotax == NULL) { bndvelosum = bndvertnbr; bndcompload1 = bndcompsize1; } if ((bndcompsize1 >= orggrafptr->compsize[1]) || /* If either part has all of its vertices in band, use plain graph instead */ ((bndvertnbr - bndcompsize1 - orggrafptr->fronnbr) >= orggrafptr->compsize[0])) { memFree (queudat.qtab); /* Free group leader */ return (vgraphSeparateSt (orggrafptr, paraptr->stratorg)); } /* TRICK: since always at least one missing vertex per part, there is room for anchor vertices */ bndvertnnd = bndvertnbr + orggrafptr->s.baseval; bndvnumtax = queudat.qtab - orggrafptr->s.baseval; /* TRICK: re-use queue array as vertex number array as vertices taken in queue order */ for (bndvertnum = orggrafptr->s.baseval; bndvertnum < bndvertnnd; bndvertnum ++) { /* For vertices not belonging to last layer */ Gnum orgvertnum; orgvertnum = bndvnumtax[bndvertnum]; /* Get distance index of vertex */ if (orgindxtax[orgvertnum] >= paraptr->distmax) /* If vertex belongs to last layer */ break; orgindxtax[orgvertnum] = bndvertnum; } bndvlvlnum = bndvertnum; /* Get index of first vertex of last layer */ for ( ; bndvertnum < bndvertnnd; bndvertnum ++) /* For vertices belonging to last layer */ orgindxtax[bndvnumtax[bndvertnum]] = bndvertnum; memSet (&bndgrafdat, 0, sizeof (Vgraph)); bndgrafdat.s.flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; bndgrafdat.s.baseval = orggrafptr->s.baseval; bndgrafdat.s.vertnbr = bndvertnbr + 2; /* "+ 2" for anchor vertices */ bndgrafdat.s.vertnnd = bndvertnnd + 2; if (memAllocGroup ((void **) (void *) /* Do not allocate vnumtab but keep queudat.qtab instead */ &bndgrafdat.s.verttax, (size_t) ((bndvertnbr + 3) * sizeof (Gnum)), &bndgrafdat.s.velotax, (size_t) ((bndvertnbr + 2) * sizeof (Gnum)), NULL) == NULL) { errorPrint ("vgraphSeparateBd: out of memory (2)"); memFree (queudat.qtab); return (1); } bndgrafdat.s.verttax -= orggrafptr->s.baseval; /* Adjust base of arrays */ bndgrafdat.s.vendtax = bndgrafdat.s.verttax + 1; /* Band graph is compact */ bndgrafdat.s.velotax -= orggrafptr->s.baseval; bndgrafdat.s.vnumtax = bndvnumtax; bndgrafdat.s.velosum = orggrafptr->s.velosum; bndgrafdat.s.velotax[bndvertnnd] = orggrafptr->compload[0] - (bndvelosum - orggrafptr->compload[2] - bndcompload1); /* Set loads of anchor vertices */ bndgrafdat.s.velotax[bndvertnnd + 1] = orggrafptr->compload[1] - bndcompload1; if (((bndgrafdat.s.edgetax = (Gnum *) memAlloc (bndedgenbr * sizeof (Gnum))) == NULL) || (bndgrafdat.s.edgetax -= orggrafptr->s.baseval, ((bndgrafdat.parttax = (GraphPart *) memAlloc ((bndvertnbr + 2) * sizeof (GraphPart))) == NULL))) { errorPrint ("vgraphSeparateBd: out of memory (3)"); graphExit (&bndgrafdat.s); memFree (queudat.qtab); return (1); } bndgrafdat.parttax -= orggrafptr->s.baseval; /* From now on we should free a Vgraph and not a Graph */ bndedgetax = bndgrafdat.s.edgetax; for (bndvertnum = bndedgenum = orggrafptr->s.baseval, bnddegrmax = 0; /* Fill index array for vertices not belonging to last level */ bndvertnum < bndvlvlnum; bndvertnum ++) { Gnum orgvertnum; Gnum orgedgenum; orgvertnum = bndvnumtax[bndvertnum]; bndgrafdat.s.verttax[bndvertnum] = bndedgenum; bndgrafdat.s.velotax[bndvertnum] = (orgvelotax != NULL) ? orgvelotax[orgvertnum] : 1; for (orgedgenum = orgverttax[orgvertnum]; /* All edges of first levels are kept */ orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++, bndedgenum ++) { #ifdef SCOTCH_DEBUG_VGRAPH2 if ((bndedgenum >= (bndedgenbr + orggrafptr->s.baseval)) || (orgindxtax[orgedgetax[orgedgenum]] < 0)) { errorPrint ("vgraphSeparateBd: internal error (6)"); vgraphExit (&bndgrafdat); memFree (queudat.qtab); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ bndedgetax[bndedgenum] = orgindxtax[orgedgetax[orgedgenum]]; } bndgrafdat.parttax[bndvertnum] = orggrafptr->parttax[orgvertnum]; /* Copy part array */ if (bnddegrmax < (bndedgenum - bndgrafdat.s.verttax[bndvertnum])) bnddegrmax = (bndedgenum - bndgrafdat.s.verttax[bndvertnum]); } bndeancnbr = 0; for ( ; bndvertnum < bndvertnnd; bndvertnum ++) { /* Fill index array for vertices belonging to last level */ Gnum orgvertnum; Gnum orgedgenum; GraphPart orgpartval; Gnum bnddegrval; orgvertnum = bndvnumtax[bndvertnum]; bndgrafdat.s.verttax[bndvertnum] = bndedgenum; bndgrafdat.s.velotax[bndvertnum] = (orgvelotax != NULL) ? orgvelotax[orgvertnum] : 1; for (orgedgenum = orgverttax[orgvertnum]; /* Keep only band edges */ orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++) { Gnum bndvertend; #ifdef SCOTCH_DEBUG_VGRAPH2 if (bndedgenum >= (bndedgenbr + orggrafptr->s.baseval)) { errorPrint ("vgraphSeparateBd: internal error (7)"); vgraphExit (&bndgrafdat); memFree (queudat.qtab); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ bndvertend = orgindxtax[orgedgetax[orgedgenum]]; if (bndvertend != ~0) bndedgetax[bndedgenum ++] = bndvertend; } orgpartval = orggrafptr->parttax[orgvertnum]; bndgrafdat.parttax[bndvertnum] = orgpartval; /* Record part for vertices of last level */ bnddegrval = bndedgenum - bndgrafdat.s.verttax[bndvertnum]; if (bnddegrval < (orgvendtax[orgvertnum] - orgverttax[orgvertnum])) { /* If vertex is connected to rest of part */ bndedgetax[bndedgenum ++] = bndvertnnd + (Gnum) orgpartval; /* Add anchor edge to proper anchor vertex */ bndeancnbr ++; bnddegrval ++; /* One more (anchor) edge added to this vertex */ } if (bnddegrmax < bnddegrval) bnddegrmax = bnddegrval; } bndgrafdat.parttax[bndvertnnd] = 0; /* Set parts of anchor vertices */ bndgrafdat.parttax[bndvertnnd + 1] = 1; bndgrafdat.s.verttax[bndvertnnd] = bndedgenum; /* Mark end of regular edge array and start of first anchor edge array */ bndedgetmp = bndedgenum + bndeancnbr; #ifdef SCOTCH_DEBUG_VGRAPH2 if ((bndedgetmp - 1) >= (bndedgenbr + orggrafptr->s.baseval)) { errorPrint ("vgraphSeparateBd: internal error (8)"); vgraphExit (&bndgrafdat); memFree (queudat.qtab); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ bndgrafdat.s.edgenbr = bndgrafdat.s.edlosum = bndedgetmp - orggrafptr->s.baseval; /* Since edge load array not kept */ bndgrafdat.s.verttax[bndvertnnd + 2] = bndedgetmp; /* Mark end of edge array with anchor vertices */ for (bndvertnum = bndvlvlnum; bndvertnum < bndvertnnd; bndvertnum ++) { /* Fill anchor edge arrays */ Gnum orgvertnum; orgvertnum = bndvnumtax[bndvertnum]; if (bndgrafdat.s.verttax[bndvertnum + 1] > bndgrafdat.s.verttax[bndvertnum]) { /* If vertex is not isolated */ Gnum bndvertend; bndvertend = bndedgetax[bndgrafdat.s.verttax[bndvertnum + 1] - 1]; /* Get last neighbor of its edge sub-array */ if (bndvertend >= bndvertnnd) { /* If it is an anchor */ if (bndvertend == bndvertnnd) /* Add edge from proper anchor */ bndedgetax[bndedgenum ++] = bndvertnum; else bndedgetax[-- bndedgetmp] = bndvertnum; } } } bndgrafdat.s.verttax[bndvertnnd + 1] = bndedgenum; /* Mark end of edge array of first anchor and start of second */ #ifdef SCOTCH_DEBUG_VGRAPH2 if (bndedgenum != bndedgetmp) { errorPrint ("vgraphSeparateBd: internal error (9)"); vgraphExit (&bndgrafdat); memFree (queudat.qtab); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ if (bnddegrmax < (bndgrafdat.s.verttax[bndvertnnd + 1] - bndgrafdat.s.verttax[bndvertnnd])) bnddegrmax = (bndgrafdat.s.verttax[bndvertnnd + 1] - bndgrafdat.s.verttax[bndvertnnd]); if (bnddegrmax < (bndgrafdat.s.verttax[bndvertnnd + 2] - bndgrafdat.s.verttax[bndvertnnd + 1])) bnddegrmax = (bndgrafdat.s.verttax[bndvertnnd + 2] - bndgrafdat.s.verttax[bndvertnnd + 1]); bndgrafdat.s.degrmax = bnddegrmax; bndgrafdat.s.edgetax = (Gnum *) memRealloc ((void *) (bndgrafdat.s.edgetax + orggrafptr->s.baseval), bndgrafdat.s.edgenbr * sizeof (Gnum)) - orggrafptr->s.baseval; bndgrafdat.frontab = queudat.qtab + bndgrafdat.s.vertnbr; /* Recycle end of queue array and part of index array as band frontier array */ for (fronnum = 0, bndvertnum = orggrafptr->s.baseval; /* Fill band frontier array with first vertex indices as they make the separator */ fronnum < orggrafptr->fronnbr; fronnum ++, bndvertnum ++) bndgrafdat.frontab[fronnum] = bndvertnum; bndgrafdat.compload[0] = orggrafptr->compload[0]; bndgrafdat.compload[1] = orggrafptr->compload[1]; bndgrafdat.compload[2] = orggrafptr->compload[2]; bndgrafdat.comploaddlt = orggrafptr->comploaddlt; bndgrafdat.compsize[0] = bndvertnbr - bndcompsize1 - orggrafptr->fronnbr + 1; /* "+ 1" for anchor vertices */ bndgrafdat.compsize[1] = bndcompsize1 + 1; bndgrafdat.fronnbr = orggrafptr->fronnbr; bndgrafdat.levlnum = orggrafptr->levlnum; #ifdef SCOTCH_DEBUG_VGRAPH2 if ((graphCheck (&bndgrafdat.s) != 0) || /* Check band graph consistency */ (vgraphCheck (&bndgrafdat) != 0)) { errorPrint ("vgraphSeparateBd: inconsistent band graph data"); bndgrafdat.frontab = NULL; /* Do not free frontab as it is not allocated */ vgraphExit (&bndgrafdat); memFree (queudat.qtab); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ if (vgraphSeparateSt (&bndgrafdat, paraptr->stratbnd) != 0) { /* Apply strategy to band graph */ errorPrint ("vgraphSeparateBd: cannot separate band graph"); bndgrafdat.frontab = NULL; /* Do not free frontab as it is not allocated */ vgraphExit (&bndgrafdat); memFree (queudat.qtab); return (1); } if ((bndgrafdat.parttax[bndvertnnd] != 0) || /* If band graph was too small and anchors changed parts, apply strategy on full graph */ (bndgrafdat.parttax[bndvertnnd + 1] != 1)) { bndgrafdat.frontab = NULL; /* Do not free frontab as it is not allocated */ vgraphExit (&bndgrafdat); memFree (queudat.qtab); return (vgraphSeparateSt (orggrafptr, paraptr->stratorg)); } orggrafptr->compload[0] = bndgrafdat.compload[0]; orggrafptr->compload[1] = bndgrafdat.compload[1]; orggrafptr->compload[2] = bndgrafdat.compload[2]; orggrafptr->comploaddlt = bndgrafdat.comploaddlt; orggrafptr->compsize[0] = orggrafptr->compsize[0] - (bndvertnbr - bndcompsize1 - orggrafptr->fronnbr) + bndgrafdat.compsize[0] - 1; /* "- 1" for anchors */ orggrafptr->compsize[1] = orggrafptr->compsize[1] - bndcompsize1 + bndgrafdat.compsize[1] - 1; orggrafptr->fronnbr = bndgrafdat.fronnbr; for (bndvertnum = bndgrafdat.s.baseval; bndvertnum < bndvertnnd; bndvertnum ++) /* Update part array of full graph */ orggrafptr->parttax[bndvnumtax[bndvertnum]] = bndgrafdat.parttax[bndvertnum]; for (fronnum = 0; fronnum < bndgrafdat.fronnbr; fronnum ++) /* Update frontier array of full graph */ orggrafptr->frontab[fronnum] = bndgrafdat.s.vnumtax[bndgrafdat.frontab[fronnum]]; bndgrafdat.frontab = NULL; /* Do not free frontab as it is not allocated */ vgraphExit (&bndgrafdat); /* Free band graph structures */ memFree (queudat.qtab); #ifdef SCOTCH_DEBUG_VGRAPH2 if (vgraphCheck (orggrafptr) != 0) { errorPrint ("vgraphSeparateBd: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_parser.c0000644000175300017530000001030011631334325022311 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_parser.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the generic **/ /** strategy handling routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 3.2 : from : 19 aug 1998 **/ /** to 19 aug 1998 **/ /** DATES : # Version 3.3 : from : 01 oct 1998 **/ /** to 31 may 1999 **/ /** # Version 3.4 : from : 01 nov 2001 **/ /** to 01 nov 2001 **/ /** # Version 4.0 : from : 23 dec 2001 **/ /** to : 23 dec 2001 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "parser.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the strategy handling routines. */ /* */ /************************************/ /* This routine initializes a strategy ** structure. ** It returns: ** - 0 : in all cases. */ int SCOTCH_stratInit ( SCOTCH_Strat * const stratptr) { if (sizeof (SCOTCH_Strat) < sizeof (Strat *)) { errorPrint ("SCOTCH_stratInit: internal error (1)"); return (1); } *((Strat **) stratptr) = NULL; /* Initialize pointer to strategy */ return (0); } /* This routine frees a strategy structure. ** It returns: ** - VOID : in all cases. */ void SCOTCH_stratExit ( SCOTCH_Strat * const stratptr) { if (*((Strat **) stratptr) != NULL) /* If strategy is not null */ stratExit (*((Strat **) stratptr)); /* Free strategy structure */ } /* This routine outputs the contents of the ** given strategy to the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int SCOTCH_stratSave ( const SCOTCH_Strat * const stratptr, FILE * const stream) { return (stratSave (*((Strat **) stratptr), stream)); } scotch-5.1.12b.dfsg/src/libscotch/library_error_exit.c0000644000175300017530000001447711631334325023222 0ustar hazelscthazelsct/* Copyright 2004,2007-2009,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_error_exit.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module provides error handling **/ /** routines to process errors generated by **/ /** the routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 3.3 : from : 02 oct 1998 **/ /** to 02 oct 1998 **/ /** # Version 3.4 : from : 01 nov 2001 **/ /** to 01 nov 2001 **/ /** # Version 5.0 : from : 06 mar 2008 **/ /** to 24 may 2008 **/ /** # Version 5.1 : from : 27 sep 2008 **/ /** to 17 jul 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY_ERROR #include "module.h" #include "common.h" #include "scotch.h" /********************************/ /* */ /* The error handling routines. */ /* */ /********************************/ static char _SCOTCHerrorProgName[32] = ""; /* This routine sets the program name for ** error reporting. ** It returns: ** - VOID : in all cases. */ void SCOTCH_errorProg ( const char * const progstr) /*+ Program name +*/ { int charnbr; const char * nsrcptr; char * ndstptr; nsrcptr = progstr; ndstptr = _SCOTCHerrorProgName; charnbr = strlen (progstr); if (charnbr > 31) { _SCOTCHerrorProgName[0] = _SCOTCHerrorProgName[1] = _SCOTCHerrorProgName[2] = '.'; ndstptr += 3; nsrcptr += charnbr - 28; charnbr = 28; } strncpy (ndstptr, nsrcptr, charnbr); _SCOTCHerrorProgName[31] = '\0'; } /* This routine prints an error message with ** a variable number of arguments, as printf () ** does, and exits. ** It returns: ** - EXIT : in all cases. */ void SCOTCH_errorPrint ( const char * const errstr, /*+ printf-like variable argument list */ ...) { va_list errlist; /* The argument list of the call */ #ifdef SCOTCH_PTSCOTCH int proclocnum; #endif /* SCOTCH_PTSCOTCH */ fprintf (stderr, "%s", _SCOTCHerrorProgName); #ifdef SCOTCH_PTSCOTCH if ((MPI_Initialized (&proclocnum) == MPI_SUCCESS) && (proclocnum != 0) && (MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum) == MPI_SUCCESS)) fprintf (stderr, "(%d): ", proclocnum); else fprintf (stderr, ": "); #else /* SCOTCH_PTSCOTCH */ if (_SCOTCHerrorProgName[0] != '\0') fprintf (stderr, ": "); #endif /* SCOTCH_PTSCOTCH */ fprintf (stderr, "ERROR: "); va_start (errlist, errstr); vfprintf (stderr, errstr, errlist); /* Print arguments */ va_end (errlist); fprintf (stderr, "\n"); fflush (stderr); /* In case it has been set to buffered mode */ #ifdef SCOTCH_ERROR_SLEEP sleep (SCOTCH_ERROR_SLEEP); /* Wait for messages to be propagated */ #endif /* SCOTCH_ERROR_SLEEP */ exit (1); } /* This routine prints a warning message with ** a variable number of arguments, as printf () ** does. ** It returns: ** - VOID : in all cases. */ void SCOTCH_errorPrintW ( const char * const errstr, /*+ printf-like variable argument list */ ...) { va_list errlist; /* The argument list of the call */ #ifdef SCOTCH_PTSCOTCH int proclocnum; #endif /* SCOTCH_PTSCOTCH */ fprintf (stderr, "%s", _SCOTCHerrorProgName); #ifdef SCOTCH_PTSCOTCH if ((MPI_Initialized (&proclocnum) == MPI_SUCCESS) && (proclocnum != 0) && (MPI_Comm_rank (MPI_COMM_WORLD, &proclocnum) == MPI_SUCCESS)) fprintf (stderr, "(%d): ", proclocnum); else fprintf (stderr, ": "); #else /* SCOTCH_PTSCOTCH */ if (_SCOTCHerrorProgName[0] != '\0') fprintf (stderr, ": "); #endif /* SCOTCH_PTSCOTCH */ fprintf (stderr, "WARNING: "); va_start (errlist, errstr); vfprintf (stderr, errstr, errlist); /* Print arguments */ va_end (errlist); fprintf (stderr, "\n"); fflush (stderr); /* In case it has been set to buffered mode */ } scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_hf.c0000644000175300017530000001612311631334325022256 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_hf.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders a submesh using **/ /** the block-oriented Halo Approximate **/ /** (Multiple) Minimum Fill algorithm, **/ /** with super-variable accounting **/ /** R2HAMDf4 v2.0). **/ /** **/ /** DATES : # Version 4.0 : from : 08 dec 2003 **/ /** to : 09 dec 2003 **/ /** # Version 5.0 : from : 12 sep 2007 **/ /** to : 12 sep 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH_ORDER_HF #include "module.h" #include "common.h" #include "graph.h" #include "order.h" #include "mesh.h" #include "hmesh.h" #include "hall_order_hf.h" #include "hall_order_hx.h" #include "hmesh_order_hf.h" #include "hmesh_order_hx.h" #include "hmesh_order_si.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hmeshOrderHf ( const Hmesh * restrict const meshptr, Order * restrict const ordeptr, const Gnum ordenum, OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ const HmeshOrderHfParam * restrict const paraptr) { Gnum nbbuck; Gnum * restrict petab; Gnum pfree; Gnum iwlen; Gnum * restrict iwtab; Gnum * restrict lentab; Gnum * restrict nvartab; Gnum * restrict elentab; Gnum * restrict lasttab; Gnum * restrict leaftab; Gnum * restrict secntab; /* Array of index to first secondary variable */ Gnum * restrict nexttab; /* Array of index of next principal variable */ Gnum * restrict frsttab; Gnum * restrict headtab; /* Head array : nbbuck = 2 * n */ Gnum ncmpa; Gnum n; /* Number of nodes to order */ int o; n = meshptr->m.velmnbr + meshptr->m.vnodnbr; if (n < paraptr->colmin) /* If graph is too small, order simply */ return (hmeshOrderSi (meshptr, ordeptr, ordenum, cblkptr)); nbbuck = n * 2; iwlen = (Gnum) ((double) meshptr->m.edgenbr * HMESHORDERHFCOMPRAT) + 32; if (iwlen < n) /* Prepare to re-use array */ iwlen = n; if (memAllocGroup ((void **) (void *) &petab, (size_t) (n * sizeof (Gnum)), &iwtab, (size_t) (iwlen * sizeof (Gnum)), &lentab, (size_t) (n * sizeof (Gnum)), &nvartab, (size_t) (n * sizeof (Gnum)), &elentab, (size_t) (n * sizeof (Gnum)), &lasttab, (size_t) (n * sizeof (Gnum)), &leaftab, (size_t) (n * sizeof (Gnum)), &frsttab, (size_t) (n * sizeof (Gnum)), &secntab, (size_t) (n * sizeof (Gnum)), &nexttab, (size_t) (n * sizeof (Gnum)), &headtab, (size_t) ((nbbuck + 2) * sizeof (Gnum)), NULL) == NULL) { errorPrint ("hmeshOrderHf: out of memory"); return (1); } hmeshOrderHxFill (meshptr, petab, lentab, iwtab, elentab, &pfree); hallOrderHfR2hamdf4 (n, meshptr->m.velmnbr, nbbuck, iwlen, petab, pfree, lentab, iwtab, nvartab, elentab, lasttab, &ncmpa, leaftab, secntab, nexttab, frsttab, headtab); if (ncmpa < 0) { errorPrint ("hmeshOrderHf: internal error"); memFree (petab); /* Free group leader */ return (1); } o = hallOrderHxBuild (meshptr->m.baseval, n, meshptr->vnohnbr, (meshptr->m.vnumtax == NULL) ? NULL : meshptr->m.vnumtax + (meshptr->m.vnodbas - meshptr->m.baseval), /* Point to node part of vnumtab array */ ordeptr, cblkptr, nvartab - meshptr->m.baseval, lentab - meshptr->m.baseval, petab - meshptr->m.baseval, frsttab - meshptr->m.baseval, nexttab - meshptr->m.baseval, secntab - meshptr->m.baseval, iwtab - meshptr->m.baseval, elentab - meshptr->m.baseval, ordeptr->peritab + ordenum, /* Use given inverse permutation as inverse permutation space, never based */ leaftab, paraptr->colmin, paraptr->colmax, (float) paraptr->fillrat); memFree (petab); /* Free group leader */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_gg.c0000644000175300017530000003667311631334325022577 0ustar hazelscthazelsct/* Copyright 2004,2007,2009,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_gg.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Luca SCARANO (v3.1) **/ /** **/ /** FUNCTION : This module computes a bipartition of **/ /** a bipartition graph by multiple runs of **/ /** the greedy graph growing algorithm. **/ /** **/ /** DATES : # Version 3.1 : from : 07 jan 1996 **/ /** to 07 jun 1996 **/ /** # Version 3.2 : from : 20 sep 1996 **/ /** to 13 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 3.4 : from : 01 jun 2001 **/ /** to 01 jun 2001 **/ /** # Version 4.0 : from : 09 jan 2004 **/ /** to 01 sep 2004 **/ /** # Version 5.0 : from : 02 jan 2007 **/ /** to 04 feb 2007 **/ /** # Version 5.1 : from : 21 nov 2007 **/ /** to 22 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BGRAPH_BIPART_GG #include "module.h" #include "common.h" #include "gain.h" #include "graph.h" #include "arch.h" #include "bgraph.h" #include "bgraph_bipart_gg.h" /* ** The static variables. */ static const Gnum bgraphbipartggloadone = 1; static const Gnum bgraphbipartggloadzero = 0; /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the bipartitioning. ** It returns: ** - 0 : if bipartitioning could be computed. ** - 1 : on error. */ int bgraphBipartGg ( Bgraph * restrict const grafptr, /*+ Active graph +*/ const BgraphBipartGgParam * const paraptr) /*+ Method parameters +*/ { GainTabl * restrict tablptr; /* Pointer to gain table */ BgraphBipartGgVertex * restrict vexxtax; /* Extended vertex array */ BgraphBipartGgVertex * vexxptr; /* Pointer to current vertex to swap */ const Gnum * restrict veexptr; /* Pointer to external gain of current vertex */ Gnum * restrict permtab; /* Permutation table for finding new roots */ Gnum permnum; /* Current permutation index */ const Gnum * restrict velobax; /* Data for handling of optional arrays */ Gnum velomsk; const byte * restrict veexbab; /* Un-based array for external gains */ int veexsiz; const Gnum * restrict edlobax; Gnum edlomsk; byte * restrict flagtax; Gnum vertnum; Gnum fronnum; Gnum compsize1; Gnum commgainextn; unsigned int passnum; Anum domdist2; /* Two times domdist */ if (((tablptr = gainTablInit (GAIN_LINMAX, BGRAPHBIPARTGGGAINTABLSUBBITS)) == NULL) || /* Use logarithmic array only */ ((vexxtax = (BgraphBipartGgVertex *) memAlloc (grafptr->s.vertnbr * sizeof (BgraphBipartGgVertex))) == NULL)) { errorPrint ("bgraphBipartGg: out of memory (1)"); if (tablptr != NULL) gainTablExit (tablptr); return (1); } vexxtax -= grafptr->s.baseval; /* Base access to vexxtax */ permtab = NULL; /* Do not allocate permutation array yet */ domdist2 = 2 * grafptr->domdist; if (grafptr->s.edlotax == NULL) { /* If graph has no edge weights */ Gnum vertnum; for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { Gnum commload; commload = (grafptr->s.vendtax[vertnum] - grafptr->s.verttax[vertnum]) * grafptr->domdist; vexxtax[vertnum].commgain0 = (grafptr->veextax == NULL) ? commload : commload + grafptr->veextax[vertnum]; } edlobax = &bgraphbipartggloadone; edlomsk = 0; } else { /* Graph has edge weights */ Gnum vertnum; for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { Gnum commload; Gnum edgenum; for (edgenum = grafptr->s.verttax[vertnum], commload = 0; edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) commload += grafptr->s.edlotax[edgenum]; commload *= grafptr->domdist; vexxtax[vertnum].commgain0 = (grafptr->veextax == NULL) ? commload : commload + grafptr->veextax[vertnum]; } edlobax = grafptr->s.edlotax; edlomsk = ~((Gnum) 0); /* TRICK: will assume that ~0 is -1 */ } if (grafptr->s.velotax == NULL) { /* Set accesses to optional arrays */ velobax = &bgraphbipartggloadone; /* In case vertices not weighted (least often) */ velomsk = 0; } else { velobax = grafptr->s.velotax; velomsk = ~((Gnum) 0); } if (grafptr->veextax == NULL) { veexbab = (byte *) &bgraphbipartggloadzero; veexsiz = 0; } else { veexbab = (byte *) (grafptr->veextax + grafptr->s.baseval); veexsiz = sizeof (Gnum); } for (passnum = 0; passnum < paraptr->passnbr; passnum ++) { /* For all passes */ Gnum vertnum; Gnum commload; Gnum compload0dlt; for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { /* Reset extended vertex array */ vexxtax[vertnum].gainlink.next = BGRAPHBIPARTGGSTATEFREE; vexxtax[vertnum].commgain = vexxtax[vertnum].commgain0; } gainTablFree (tablptr); /* Reset gain table */ permnum = 0; /* No permutation built yet */ compload0dlt = grafptr->s.velosum - grafptr->compload0avg; /* Reset bipartition parameters */ commload = grafptr->commloadextn0; vexxptr = vexxtax + (grafptr->s.baseval + intRandVal (grafptr->s.vertnbr)); /* Randomly select first root vertex */ do { /* For all root vertices, till balance */ vexxptr->gainlink.next = /* TRICK: allow deletion of root vertex */ vexxptr->gainlink.prev = (GainLink *) vexxptr; #ifdef SCOTCH_DEBUG_GAIN2 vexxptr->gainlink.tabl = NULL; #endif /* SCOTCH_DEBUG_GAIN2 */ do { /* As long as vertices can be retrieved */ const Gnum * restrict edgeptr; /* Pointer to current end vertex index */ const Gnum * restrict edgetnd; /* Pointer to end of edge array */ const Gnum * restrict edloptr; /* Pointer to current edge load */ Gnum vertnum; /* Number of current vertex */ Gnum veloval; /* Load of selected vertex */ gainTablDel (tablptr, (GainLink *) vexxptr); /* Remove vertex from the table */ vertnum = vexxptr - vexxtax; /* Get number of selected vertex */ veloval = velobax[vertnum & velomsk]; if (abs (compload0dlt - veloval) >= abs (compload0dlt)) { /* If swapping would cause imbalance */ permnum = grafptr->s.vertnbr; /* Terminate swapping process */ vexxptr = NULL; break; } vexxptr->gainlink.next = BGRAPHBIPARTGGSTATEUSED; /* Mark it as swapped */ compload0dlt -= veloval; /* Update partition parameters */ commload += vexxptr->commgain; for (edgeptr = grafptr->s.edgetax + grafptr->s.verttax[vertnum], /* (Re-)link neighbors */ edgetnd = grafptr->s.edgetax + grafptr->s.vendtax[vertnum], edloptr = edlobax + (grafptr->s.verttax[vertnum] & edlomsk); edgeptr < edgetnd; edgeptr ++, edloptr -= edlomsk) { /* TRICK: assume that ~0 is -1 */ BgraphBipartGgVertex * vexxend; /* Pointer to end vertex of current edge */ vexxend = vexxtax + *edgeptr; /* Point to end vertex */ if (vexxend->gainlink.next != BGRAPHBIPARTGGSTATEUSED) { /* If vertex needs to be updated */ vexxend->commgain -= *edloptr * domdist2; /* Adjust gain value */ if (vexxend->gainlink.next >= BGRAPHBIPARTGGSTATELINK) /* If vertex is linked */ gainTablDel (tablptr, (GainLink *) vexxend); /* Remove it from table */ gainTablAdd (tablptr, (GainLink *) vexxend, vexxend->commgain); /* (Re-)link vertex in table */ } } } while ((vexxptr = (BgraphBipartGgVertex *) gainTablFrst (tablptr)) != NULL); if (permnum == 0) { /* If permutation has not been built yet */ if (permtab == NULL) { /* If permutation array not allocated yet */ if ((permtab = (Gnum *) memAlloc (grafptr->s.vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("bgraphBipartGg: out of memory (2)"); memFree (vexxtax + grafptr->s.baseval); gainTablExit (tablptr); return (1); } intAscn (permtab, grafptr->s.vertnbr, grafptr->s.baseval); /* Initialize based permutation array */ } intPerm (permtab, grafptr->s.vertnbr); /* Build random permutation */ } for ( ; permnum < grafptr->s.vertnbr; permnum ++) { /* Find next root vertex */ if (vexxtax[permtab[permnum]].gainlink.next == BGRAPHBIPARTGGSTATEFREE) { vexxptr = vexxtax + permtab[permnum ++]; break; } } } while (vexxptr != NULL); if ((passnum == 0) || /* If first try */ ( (grafptr->commload > commload) || /* Or if better solution reached */ ((grafptr->commload == commload) && (abs (grafptr->compload0dlt) > abs (compload0dlt))))) { Gnum vertnum; grafptr->compload0dlt = compload0dlt; /* Set graph parameters */ grafptr->commload = commload; for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) /* Copy bipartition state with flag 2 for tabled vertices */ grafptr->parttax[vertnum] = (vexxtax[vertnum].gainlink.next >= BGRAPHBIPARTGGSTATELINK) ? 2 : (GraphPart) ((intptr_t) vexxtax[vertnum].gainlink.next); } } flagtax = (byte *) (vexxtax + grafptr->s.baseval) - grafptr->s.baseval; /* Re-use extended vertex array for flag array */ memSet (flagtax + grafptr->s.baseval, ~0, grafptr->s.vertnbr * sizeof (byte)); for (vertnum = grafptr->s.baseval, veexptr = (Gnum *) veexbab, fronnum = 0, compsize1 = 0, commgainextn = grafptr->commgainextn0; vertnum < grafptr->s.vertnnd; vertnum ++, veexptr = (Gnum *) ((byte *) veexptr + veexsiz)) { int partval; partval = grafptr->parttax[vertnum]; if (partval > 1) { /* If vertex belongs to frontier of part 0 */ Gnum edgenum; Gnum frontmp; /* Temporary count value for frontier */ grafptr->frontab[fronnum ++] = vertnum; /* Then it belongs to the frontier */ grafptr->parttax[vertnum] = 0; /* And it belongs to part 0 */ for (edgenum = grafptr->s.verttax[vertnum], frontmp = 1; edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) { Gnum vertend; vertend = grafptr->s.edgetax[edgenum]; if (grafptr->parttax[vertend] == 1) { /* If vertex belongs to other part */ frontmp = 0; /* Then first frontier vertex was useful */ if (flagtax[vertend] != 0) { /* If vertex has not yet been flagged */ grafptr->frontab[fronnum ++] = vertend; /* Then add it to the frontier */ flagtax[vertend] = 0; /* Flag it */ } } } fronnum -= frontmp; /* Remove vertex from frontier if it was useless */ } partval &= 1; compsize1 += partval; commgainextn -= partval * 2 * *veexptr; } grafptr->fronnbr = fronnum; grafptr->compload0 = grafptr->compload0avg + grafptr->compload0dlt; grafptr->compsize0 = grafptr->s.vertnbr - compsize1; grafptr->commgainextn = commgainextn; grafptr->bbalval = (double) ((grafptr->compload0dlt < 0) ? (- grafptr->compload0dlt) : grafptr->compload0dlt) / (double) grafptr->compload0avg; if (permtab != NULL) /* Free work arrays */ memFree (permtab); memFree (vexxtax + grafptr->s.baseval); gainTablExit (tablptr); #ifdef SCOTCH_DEBUG_BGRAPH2 if (bgraphCheck (grafptr) != 0) { errorPrint ("bgraphBipartGg: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/bgraph.c0000644000175300017530000003761511631334325020556 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the bipartition **/ /** graph data structure handling **/ /** routines. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to 12 may 1993 **/ /** # Version 1.3 : from : 06 apr 1994 **/ /** to 09 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 01 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to 30 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 15 aug 1995 **/ /** # Version 3.1 : from : 15 nov 1995 **/ /** to 16 nov 1995 **/ /** # Version 3.2 : from : 24 aug 1996 **/ /** to : 14 oct 1997 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 19 oct 1998 **/ /** # Version 4.0 : from : 18 dec 2001 **/ /** to 31 aug 2004 **/ /** # Version 5.0 : from : 17 dec 2006 **/ /** to 10 sep 2007 **/ /** # Version 5.1 : from : 08 oct 2008 **/ /** to 18 mar 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BGRAPH #include "module.h" #include "common.h" #include "graph.h" #include "arch.h" #include "mapping.h" #include "bgraph.h" /*************************/ /* */ /* These routines handle */ /* bipartition graphs. */ /* */ /*************************/ /* This routine builds the active graph ** corresponding to the given bipartitioning ** job parameters. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int bgraphInit ( Bgraph * restrict const actgrafptr, /* Active graph */ const Graph * restrict const indgrafptr, /* Induced source subgraph */ const Graph * restrict const srcgrafptr, /* Original source graph */ const Mapping * restrict const mapptr, /* Current mapping of halo vertices */ const ArchDom domsubtab[]) /* Subdomains */ { Anum domdist; /* Distance between both subdomains */ Anum domwght0; /* Processor workforce in each domain */ Anum domwght1; domdist = archDomDist (&mapptr->archdat, &domsubtab[0], &domsubtab[1]); /* Get distance between subdomains */ domwght0 = archDomWght (&mapptr->archdat, &domsubtab[0]); /* Get weights of subdomains */ domwght1 = archDomWght (&mapptr->archdat, &domsubtab[1]); actgrafptr->s = *indgrafptr; /* Get source graph data */ actgrafptr->s.flagval = (indgrafptr->flagval & ~GRAPHFREETABS) | BGRAPHFREEFRON | BGRAPHFREEPART; /* Graph is a clone with own grouped bipartitioning arrays */ actgrafptr->s.vlbltax = NULL; /* Remove vertex labels */ actgrafptr->veextax = NULL; /* No external gains (yet) */ if (((actgrafptr->parttax = memAlloc (actgrafptr->s.vertnbr * sizeof (GraphPart))) == NULL) || ((actgrafptr->frontab = memAlloc (actgrafptr->s.vertnbr * sizeof (Gnum))) == NULL)) { errorPrint ("bgraphInit: out of memory"); if (actgrafptr->parttax != NULL) memFree (actgrafptr->parttax); return (1); } actgrafptr->parttax -= actgrafptr->s.baseval; bgraphInit2 (actgrafptr, domdist, domwght0, domwght1); if ((srcgrafptr != NULL) && /* If target architecture needs external gains and */ (indgrafptr->vertnbr != srcgrafptr->vertnbr)) { /* If induced subgraph is not original graph */ if (bgraphInit3 (actgrafptr, srcgrafptr, mapptr, domsubtab) != 0) { /* Add external loads */ bgraphExit (actgrafptr); return (1); } } #ifdef SCOTCH_DEBUG_BGRAPH2 if (bgraphCheck (actgrafptr) != 0) { errorPrint ("bgraphInit: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ return (0); } void bgraphInit2 ( Bgraph * restrict const actgrafptr, /* Active graph */ const Anum domdist, /* Distance between both subdomains */ const Anum domwght0, /* Processor workforce in each domain */ const Anum domwght1) { actgrafptr->fronnbr = 0; /* No frontier since all vertices set to part 0 */ actgrafptr->compload0min = 0; /* No external constraints on bipartition (yet) */ actgrafptr->compload0max = actgrafptr->s.velosum; actgrafptr->compload0avg = (Gnum) (((double) actgrafptr->s.velosum * (double) domwght0) / (double) (domwght0 + domwght1)); actgrafptr->compload0dlt = actgrafptr->s.velosum - actgrafptr->compload0avg; actgrafptr->compload0 = actgrafptr->s.velosum; actgrafptr->compsize0 = actgrafptr->s.vertnbr; actgrafptr->commload = 0; actgrafptr->commloadextn0 = 0; actgrafptr->commgainextn = 0; actgrafptr->commgainextn0 = 0; actgrafptr->domdist = domdist; actgrafptr->domwght[0] = domwght0; actgrafptr->domwght[1] = domwght1; actgrafptr->levlnum = 0; memSet (actgrafptr->parttax + actgrafptr->s.baseval, 0, actgrafptr->s.vertnbr * sizeof (GraphPart)); /* Set all vertices to part 0 */ } /* This routine adds external gain data to ** the active graph given to it, according ** to the initial source graph, the current ** mapping, and the two subdomains. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int bgraphInit3 ( Bgraph * restrict const actgrafptr, /*+ Active graph being built +*/ const Graph * restrict const srcgrafptr, /*+ Original source graph +*/ const Mapping * restrict const mapptr, /*+ Partial mapping +*/ const ArchDom domsub[]) /*+ Subdomains +*/ { const Arch * restrict tgtarchptr; /* Pointer to the target architecture */ Gnum actvertnum; /* Number of current active vertex */ Gnum commloadextn0; /* External communication load */ Gnum commgainextn0; /* External communication gain */ Gnum * restrict veextax; /* External gain array */ Gnum veexflagval; /* Flag set if external array useful */ tgtarchptr = &mapptr->archdat; /* Get target architecture */ if ((veextax = (Gnum *) memAlloc (actgrafptr->s.vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("bgraphInit3: out of memory"); return (1); } veextax -= actgrafptr->s.baseval; veexflagval = /* No useful array entry yet */ commloadextn0 = /* No external communication yet */ commgainextn0 = 0; for (actvertnum = actgrafptr->s.baseval; /* Compute external loads */ actvertnum < actgrafptr->s.vertnnd; actvertnum ++) { Gnum commgainextn; /* External communication gain for current vertex */ Gnum srcvertnum; /* Number of current original vertex */ commgainextn = 0; /* Initialize external loads */ srcvertnum = actgrafptr->s.vnumtax[actvertnum]; /* Get vertex number in original graph */ if ((srcgrafptr->vendtax[srcvertnum] - srcgrafptr->verttax[srcvertnum]) != /* If vertex has external edges */ (actgrafptr->s.vendtax[actvertnum] - actgrafptr->s.verttax[actvertnum])) { Gnum commloadextn; /* External communication load for current vertex */ Gnum srcedgenum; Gnum srcedloval; commloadextn = 0; srcedgenum = srcgrafptr->verttax[srcvertnum]; srcedloval = 1; /* Assume no edge loads */ if (actgrafptr->s.vendtax[actvertnum] > actgrafptr->s.verttax[actvertnum]) { /* If vertex has active edges */ Gnum actedgenum; Gnum srcvertend; for (actedgenum = actgrafptr->s.verttax[actvertnum], srcvertend = actgrafptr->s.vnumtax[actgrafptr->s.edgetax[actedgenum]]; ; srcedgenum ++) { ArchDom * restrict srcdomnptr; /* Pointer to domain of current source edge vertex */ #ifdef SCOTCH_DEBUG_BGRAPH2 if (srcedgenum >= srcgrafptr->vendtax[srcvertnum]) { errorPrint ("bgraphInit3: internal error"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ if (srcgrafptr->edgetax[srcedgenum] == srcvertend) { /* If source graph edge is current active edge */ if (++ actedgenum >= actgrafptr->s.vendtax[actvertnum]) { /* If all active edges found */ srcedgenum ++; /* Process next edge as external edge in next loop */ break; /* All remaining external edges will be processed in next loop */ } srcvertend = actgrafptr->s.vnumtax[actgrafptr->s.edgetax[actedgenum]]; /* Get new end number to look for */ continue; /* Skip internal edge */ } srcdomnptr = mapDomain (mapptr, srcgrafptr->edgetax[srcedgenum]); if (srcgrafptr->edlotax != NULL) srcedloval = srcgrafptr->edlotax[srcedgenum]; commloadextn += srcedloval * archDomDist (tgtarchptr, domsub, srcdomnptr); commgainextn += srcedloval * archDomDist (tgtarchptr, domsub + 1, srcdomnptr); } } for ( ; srcedgenum < srcgrafptr->vendtax[srcvertnum]; srcedgenum ++) { ArchDom * restrict srcdomnptr; /* Pointer to domain of current source edge vertex */ srcdomnptr = mapDomain (mapptr, srcgrafptr->edgetax[srcedgenum]); if (srcgrafptr->edlotax != NULL) srcedloval = srcgrafptr->edlotax[srcedgenum]; commloadextn += srcedloval * archDomDist (tgtarchptr, domsub, srcdomnptr); commgainextn += srcedloval * archDomDist (tgtarchptr, domsub + 1, srcdomnptr); } commgainextn -= commloadextn; /* Compute vertex gain */ commloadextn0 += commloadextn; /* Account for external edges */ commgainextn0 += commgainextn; } veextax[actvertnum] = commgainextn; /* Record external gain value */ veexflagval |= commgainextn; /* Accumulate non-zero values */ } if (veexflagval == 0) { /* If external gain array is useless */ memFree (veextax + actgrafptr->s.baseval); /* Forget about it */ return (0); } actgrafptr->s.flagval |= BGRAPHFREEVEEX; /* Keep external gain array */ actgrafptr->veextax = veextax; actgrafptr->commload = commloadextn0; actgrafptr->commgainextn = commgainextn0; actgrafptr->commloadextn0 = commloadextn0; actgrafptr->commgainextn0 = commgainextn0; return (0); } /* This routine frees the contents ** of the given active graph. ** It returns: ** - VOID : in all cases. */ void bgraphExit ( Bgraph * restrict const grafptr) { if ((grafptr->veextax != NULL) && /* External gain array is private */ ((grafptr->s.flagval & BGRAPHFREEVEEX) != 0)) memFree (grafptr->veextax + grafptr->s.baseval); if ((grafptr->frontab != NULL) && ((grafptr->s.flagval & BGRAPHFREEFRON) != 0)) memFree (grafptr->frontab); if ((grafptr->parttax != NULL) && ((grafptr->s.flagval & BGRAPHFREEPART) != 0)) memFree (grafptr->parttax + grafptr->s.baseval); graphExit (&grafptr->s); /* Free re-allocated arrays of cloned source graph, if any */ #ifdef SCOTCH_DEBUG_BGRAPH2 memSet (grafptr, ~0, sizeof (Bgraph)); #endif /* SCOTCH_DEBUG_BGRAPH2 */ } /* This routine swaps all of the graph ** vertices from one part to another, and ** recomputes the resulting gains. ** It returns: ** - VOID : in all cases. */ void bgraphSwal ( Bgraph * restrict const grafptr) { Gnum vertnum; for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) grafptr->parttax[vertnum] ^= 1; grafptr->compload0 = grafptr->s.velosum - grafptr->compload0; grafptr->compload0dlt = grafptr->s.velosum - grafptr->compload0dlt - 2 * grafptr->compload0avg; grafptr->compsize0 = grafptr->s.vertnbr - grafptr->compsize0; grafptr->commload += grafptr->commgainextn; grafptr->commgainextn = - grafptr->commgainextn; } /* This routine moves all of the graph ** vertices to the first part, and ** computes the resulting gains. ** It returns: ** - VOID : in all cases. */ void bgraphZero ( Bgraph * restrict const grafptr) { memSet (grafptr->parttax + grafptr->s.baseval, 0, grafptr->s.vertnbr * sizeof (GraphPart)); /* Set all vertices to part 0 */ grafptr->fronnbr = 0; /* No frontier vertices */ grafptr->compload0 = grafptr->s.velosum; grafptr->compload0dlt = grafptr->s.velosum - grafptr->compload0avg; grafptr->compsize0 = grafptr->s.vertnbr; grafptr->commload = grafptr->commloadextn0; /* Initialize communication load */ grafptr->commgainextn = grafptr->commgainextn0; grafptr->bbalval = (double) grafptr->compload0dlt / (double) grafptr->compload0avg; } scotch-5.1.12b.dfsg/src/libscotch/library_graph_io_mmkt.c0000644000175300017530000001003111631334325023636 0ustar hazelscthazelsct/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_io_mmkt.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the Matrix **/ /** Market geometry and graph handling **/ /** routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 13 mar 2008 **/ /** to 13 mar 2008 **/ /** # Version 5.1 : from : 27 apr 2010 **/ /** to 27 apr 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "geom.h" #include "graph.h" #include "scotch.h" /*************************************/ /* */ /* These routines are the C API for */ /* the Matrix Market graph and */ /* geometry handling routines. */ /* */ /*************************************/ /*+ This routine loads the given opaque geom *** structure with the data of the given stream. *** - 0 : if loading succeeded. *** - !0 : on error. +*/ int SCOTCH_graphGeomLoadMmkt ( SCOTCH_Graph * restrict const grafptr, SCOTCH_Geom * restrict const geomptr, FILE * const filegrfptr, FILE * const filegeoptr, const char * const dataptr) { return (graphGeomLoadMmkt ((Graph *) grafptr, (Geom *) geomptr, filegrfptr, filegeoptr, dataptr)); } /*+ This routine saves the contents of the given *** opaque graph structure to the given stream. *** It returns: *** - 0 : if the saving succeeded. *** - !0 : on error. +*/ int SCOTCH_graphGeomSaveMmkt ( const SCOTCH_Graph * restrict const grafptr, const SCOTCH_Geom * restrict const geomptr, FILE * const filegrfptr, FILE * const filegeoptr, const char * const dataptr) { return (graphGeomSaveMmkt ((Graph *) grafptr, (Geom *) geomptr, filegrfptr, filegeoptr, dataptr)); } scotch-5.1.12b.dfsg/src/libscotch/hgraph_check.c0000644000175300017530000001205611631334325021711 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the source graph **/ /** functions. **/ /** **/ /** DATES : # Version 4.0 : from : 17 jan 2002 **/ /** to 01 dec 2003 **/ /** # Version 5.0 : from : 19 dec 2006 **/ /** to 19 dec 2006 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HGRAPH #include "module.h" #include "common.h" #include "graph.h" #include "hgraph.h" /****************************************/ /* */ /* These routines handle source graphs. */ /* */ /****************************************/ /* This routine checks the consistency ** of the given halo graph. ** It returns: ** - 0 : if graph data are consistent. ** - !0 : on error. */ int hgraphCheck ( const Hgraph * restrict const grafptr) { Gnum vertnum; /* Number of current vertex */ Gnum edgenum; /* Number of current edge */ Gnum enohsum; if (graphCheck (&grafptr->s) != 0) { errorPrint ("hgraphCheck: invalid graph structure in halo graph"); return (1); } if ((grafptr->vnohnbr < 0) || (grafptr->vnohnbr > grafptr->s.vertnbr) || (grafptr->vnohnnd != (grafptr->vnohnbr + grafptr->s.baseval)) || (grafptr->vnlosum > grafptr->s.velosum) || (grafptr->enohnbr > grafptr->s.edgenbr) || (grafptr->enohsum < grafptr->enohnbr)) { errorPrint ("hgraphCheck: invalid halo graph parameters"); return (1); } enohsum = (grafptr->s.edlotax == NULL) ? grafptr->enohnbr : 0; for (vertnum = grafptr->s.baseval; vertnum < grafptr->vnohnnd; vertnum ++) { /* For all non-halo vertices */ if ((grafptr->vnhdtax[vertnum] < grafptr->s.verttax[vertnum]) || (grafptr->vnhdtax[vertnum] > grafptr->s.vendtax[vertnum])) { errorPrint ("hgraphCheck: invalid non-halo end vertex array"); return (1); } if (grafptr->s.edlotax != NULL) { Gnum edgenum; for (edgenum = grafptr->s.verttax[vertnum]; edgenum < grafptr->vnhdtax[vertnum]; edgenum ++) enohsum += grafptr->s.edlotax[edgenum]; } } if (grafptr->enohsum != enohsum) { errorPrint ("hgraphCheck: invalid non-halo edge load sum"); return (1); } for ( ; vertnum < grafptr->s.vertnnd; vertnum ++) { /* For all halo vertices */ for (edgenum = grafptr->s.verttax[vertnum]; edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) { if (grafptr->s.edgetax[edgenum] >= grafptr->vnohnnd) { /* If two halo vertices connected together */ errorPrint ("hgraphCheck: halo vertices should not be connected together"); return (1); } } } return (0); } scotch-5.1.12b.dfsg/src/libscotch/arch_torus.c0000644000175300017530000004772011631334325021462 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_torus.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the torus graph **/ /** target architectures. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 23 dec 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 29 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 08 sep 1995 **/ /** # Version 3.1 : from : 07 may 1996 **/ /** to 22 jul 1996 **/ /** # Version 3.2 : from : 16 oct 1996 **/ /** to 14 may 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 05 nov 2003 **/ /** to 10 mar 2005 **/ /** # Version 5.1 : from : 21 jan 2008 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ARCH_TORUS #include "module.h" #include "common.h" #include "arch.h" #include "arch_torus.h" /***********************************************/ /* */ /* These are the 2-dimensional torus routines. */ /* */ /***********************************************/ /* This routine loads the ** bidimensional torus architecture. ** It returns: ** - 0 : if the architecture has been successfully read. ** - !0 : on error. */ int archTorus2ArchLoad ( ArchTorus2 * restrict const archptr, FILE * restrict const stream) { #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchTorus2) > sizeof (ArchDummy)) || (sizeof (ArchTorus2Dom) > sizeof (ArchDomDummy))) { errorPrint ("archTorus2ArchLoad: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if ((intLoad (stream, &archptr->c[0]) != 1) || (intLoad (stream, &archptr->c[1]) != 1) || (archptr->c[0] < 1) || (archptr->c[1] < 1)) { errorPrint ("archTorus2ArchLoad: bad input"); return (1); } return (0); } /* This routine saves the ** bidimensional torus architecture. ** It returns: ** - 0 : if the architecture has been successfully written. ** - !0 : on error. */ int archTorus2ArchSave ( const ArchTorus2 * const archptr, FILE * restrict const stream) { #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchTorus2) > sizeof (ArchDummy)) || (sizeof (ArchTorus2Dom) > sizeof (ArchDomDummy))) { errorPrint ("archTorus2ArchSave: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if (fprintf (stream, ANUMSTRING " " ANUMSTRING " ", (Anum) archptr->c[0], (Anum) archptr->c[1]) == EOF) { errorPrint ("archTorus2ArchSave: bad output"); return (1); } return (0); } /* This function returns the smallest number ** of terminal domain included in the given ** domain. */ ArchDomNum archTorus2DomNum ( const ArchTorus2 * const archptr, const ArchTorus2Dom * const domptr) { return ((domptr->c[1][0] * archptr->c[0]) + domptr->c[0][0]); /* Return vertex number */ } /* This function returns the terminal domain associated ** with the given terminal number in the architecture. ** It returns: ** - 0 : if label is valid and domain has been updated. ** - 1 : if label is invalid. ** - 2 : on error. */ int archTorus2DomTerm ( const ArchTorus2 * const archptr, ArchTorus2Dom * const domptr, const ArchDomNum domnum) { if (domnum < (archptr->c[0] * archptr->c[1])) { /* If valid label */ domptr->c[0][0] = /* Set the domain */ domptr->c[0][1] = domnum % archptr->c[0]; domptr->c[1][0] = domptr->c[1][1] = domnum / archptr->c[0]; return (0); } return (1); /* Cannot set domain */ } /* This function returns the number of ** elements in the rectangular domain. */ Anum archTorus2DomSize ( const ArchTorus2 * const archptr, const ArchTorus2Dom * const domptr) { return ((domptr->c[0][1] - domptr->c[0][0] + 1) * (domptr->c[1][1] - domptr->c[1][0] + 1)); } /* This function returns the average ** distance between two rectangular ** domains (in fact the distance between ** the centers of the domains). */ Anum archTorus2DomDist ( const ArchTorus2 * const archptr, const ArchTorus2Dom * const dom0ptr, const ArchTorus2Dom * const dom1ptr) { Anum dc0, dc1; Anum ds0, ds1; dc0 = abs (dom0ptr->c[0][0] + dom0ptr->c[0][1] - dom1ptr->c[0][0] - dom1ptr->c[0][1]); ds0 = (dc0 > archptr->c[0]) ? (2 * archptr->c[0] - dc0) : dc0; dc1 = abs (dom0ptr->c[1][0] + dom0ptr->c[1][1] - dom1ptr->c[1][0] - dom1ptr->c[1][1]); ds1 = (dc1 > archptr->c[1]) ? (2 * archptr->c[1] - dc1) : dc1; return ((ds0 + ds1) >> 1); } /* This function sets the biggest ** domain available for this ** architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archTorus2DomFrst ( const ArchTorus2 * const archptr, ArchTorus2Dom * restrict const domptr) { domptr->c[0][0] = domptr->c[1][0] = 0; domptr->c[0][1] = archptr->c[0] - 1; domptr->c[1][1] = archptr->c[1] - 1; return (0); } /* This routine reads domain information ** from the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archTorus2DomLoad ( const ArchTorus2 * const archptr, ArchTorus2Dom * restrict const domptr, FILE * restrict const stream) { if ((intLoad (stream, &domptr->c[0][0]) != 1) || (intLoad (stream, &domptr->c[1][0]) != 1) || (intLoad (stream, &domptr->c[0][1]) != 1) || (intLoad (stream, &domptr->c[1][1]) != 1)) { errorPrint ("archTorus2DomLoad: bad input"); return (1); } return (0); } /* This routine saves domain information ** to the given stream. ** - 0 : on success. ** - !0 : on error. */ int archTorus2DomSave ( const ArchTorus2 * const archptr, const ArchTorus2Dom * const domptr, FILE * restrict const stream) { if (fprintf (stream, ANUMSTRING " " ANUMSTRING " " ANUMSTRING " " ANUMSTRING " ", (Anum) domptr->c[0][0], (Anum) domptr->c[1][0], (Anum) domptr->c[0][1], (Anum) domptr->c[1][1]) == EOF) { errorPrint ("archTorus2DomSave: bad output"); return (1); } return (0); } /* This function tries to split a rectangular ** domain into two subdomains. ** It returns: ** - 0 : if bipartitioning succeeded. ** - 1 : if bipartitioning could not be performed. ** - 2 : on error. */ int archTorus2DomBipart ( const ArchTorus2 * const archptr, const ArchTorus2Dom * const domptr, ArchTorus2Dom * restrict const dom0ptr, ArchTorus2Dom * restrict const dom1ptr) { Anum dimsiz[2]; int dimval; /* Dimension along which to split */ dimsiz[0] = domptr->c[0][1] - domptr->c[0][0]; dimsiz[1] = domptr->c[1][1] - domptr->c[1][0]; if ((dimsiz[0] | dimsiz[1]) == 0) /* Return if cannot bipartition more */ return (1); dimval = 1; if ((dimsiz[0] > dimsiz[1]) || /* Split domain in two along largest dimension */ ((dimsiz[0] == dimsiz[1]) && (archptr->c[0] > archptr->c[1]))) dimval = 0; if (dimval == 0) { /* Split across the X dimension */ dom0ptr->c[0][0] = domptr->c[0][0]; dom0ptr->c[0][1] = (domptr->c[0][0] + domptr->c[0][1]) / 2; dom1ptr->c[0][0] = dom0ptr->c[0][1] + 1; dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; } else { /* Split across the Y dimension */ dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = (domptr->c[1][0] + domptr->c[1][1]) / 2; dom1ptr->c[1][0] = dom0ptr->c[1][1] + 1; dom1ptr->c[1][1] = domptr->c[1][1]; } return (0); } /* This function creates the MPI_Datatype for ** 2D torus domains. ** It returns: ** - 0 : if type could be created. ** - 1 : on error. */ #ifdef SCOTCH_PTSCOTCH int archTorus2DomMpiType ( const ArchTorus2 * const archptr, MPI_Datatype * const typeptr) { MPI_Type_contiguous (4, ANUM_MPI, typeptr); return (0); } #endif /* SCOTCH_PTSCOTCH */ /***********************************************/ /* */ /* These are the 3-dimensional torus routines. */ /* */ /***********************************************/ /* This routine loads the ** tridimensional torus architecture. ** It returns: ** - 0 : if the architecture has been successfully read. ** - !0 : on error. */ int archTorus3ArchLoad ( ArchTorus3 * restrict const archptr, FILE * restrict const stream) { #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchTorus3) > sizeof (ArchDummy)) || (sizeof (ArchTorus3Dom) > sizeof (ArchDomDummy))) { errorPrint ("archTorus3ArchLoad: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if ((intLoad (stream, &archptr->c[0]) != 1) || (intLoad (stream, &archptr->c[1]) != 1) || (intLoad (stream, &archptr->c[2]) != 1) || (archptr->c[0] < 1) || (archptr->c[1] < 1) || (archptr->c[2] < 1)) { errorPrint ("archTorus3ArchLoad: bad input"); return (1); } return (0); } /* This routine saves the ** tridimensional torus architecture. ** It returns: ** - 0 : if the architecture has been successfully written. ** - !0 : on error. */ int archTorus3ArchSave ( const ArchTorus3 * const archptr, FILE * restrict const stream) { #ifdef SCOTCH_DEBUG_ARCH1 if ((sizeof (ArchTorus3) > sizeof (ArchDummy)) || (sizeof (ArchTorus3Dom) > sizeof (ArchDomDummy))) { errorPrint ("archTorus3ArchSave: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_ARCH1 */ if (fprintf (stream, ANUMSTRING " " ANUMSTRING " " ANUMSTRING " ", (Anum) archptr->c[0], (Anum) archptr->c[1], (Anum) archptr->c[2]) == EOF) { errorPrint ("archTorus3ArchSave: bad output"); return (1); } return (0); } /* This function returns the smallest number ** of terminal domain included in the given ** domain. */ ArchDomNum archTorus3DomNum ( const ArchTorus3 * const archptr, const ArchTorus3Dom * const domptr) { return ((((domptr->c[2][0] * archptr->c[1]) + /* Return the vertex number */ domptr->c[1][0]) * archptr->c[0]) + domptr->c[0][0]); } /* This function returns the terminal domain associated ** with the given terminal number in the architecture. ** It returns: ** - 0 : if label is valid and domain has been updated. ** - 1 : if label is invalid. ** - 2 : on error. */ int archTorus3DomTerm ( const ArchTorus3 * const archptr, ArchTorus3Dom * const domptr, const ArchDomNum domnum) { if (domnum < (archptr->c[0] * archptr->c[1] * archptr->c[2])) { /* If valid label */ domptr->c[0][0] = /* Set the domain */ domptr->c[0][1] = domnum % archptr->c[0]; domptr->c[1][0] = domptr->c[1][1] = (domnum / archptr->c[0]) % archptr->c[1]; domptr->c[2][0] = domptr->c[2][1] = domnum / (archptr->c[0] * archptr->c[1]); return (0); } return (1); /* Cannot set domain */ } /* This function returns the number of ** elements in the cubic domain. */ Anum archTorus3DomSize ( const ArchTorus3 * const archptr, const ArchTorus3Dom * const domptr) { return ((domptr->c[0][1] - domptr->c[0][0] + 1) * (domptr->c[1][1] - domptr->c[1][0] + 1) * (domptr->c[2][1] - domptr->c[2][0] + 1)); } /* This function returns the average distance ** between two cubic domains (in fact the ** distance between the centers of the domains). */ Anum archTorus3DomDist ( const ArchTorus3 * const archptr, const ArchTorus3Dom * const dom0ptr, const ArchTorus3Dom * const dom1ptr) { Anum dc0, dc1, dc2; Anum ds0, ds1, ds2; dc0 = abs (dom0ptr->c[0][0] + dom0ptr->c[0][1] - dom1ptr->c[0][0] - dom1ptr->c[0][1]); ds0 = (dc0 > archptr->c[0]) ? (2 * archptr->c[0] - dc0) : dc0; dc1 = abs (dom0ptr->c[1][0] + dom0ptr->c[1][1] - dom1ptr->c[1][0] - dom1ptr->c[1][1]); ds1 = (dc1 > archptr->c[1]) ? (2 * archptr->c[1] - dc1) : dc1; dc2 = abs (dom0ptr->c[2][0] + dom0ptr->c[2][1] - dom1ptr->c[2][0] - dom1ptr->c[2][1]); ds2 = (dc2 > archptr->c[2]) ? (2 * archptr->c[2] - dc2) : dc2; return ((ds0 + ds1 + ds2) >> 1); } /* This function sets the biggest ** domain available for this ** architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archTorus3DomFrst ( const ArchTorus3 * const archptr, ArchTorus3Dom * restrict const domptr) { domptr->c[0][0] = domptr->c[1][0] = domptr->c[2][0] = 0; domptr->c[0][1] = archptr->c[0] - 1; domptr->c[1][1] = archptr->c[1] - 1; domptr->c[2][1] = archptr->c[2] - 1; return (0); } /* This routine reads domain information ** from the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archTorus3DomLoad ( const ArchTorus3 * const archptr, ArchTorus3Dom * restrict const domptr, FILE * restrict const stream) { if ((intLoad (stream, &domptr->c[0][0]) != 1) || (intLoad (stream, &domptr->c[1][0]) != 1) || (intLoad (stream, &domptr->c[2][0]) != 1) || (intLoad (stream, &domptr->c[0][1]) != 1) || (intLoad (stream, &domptr->c[1][1]) != 1) || (intLoad (stream, &domptr->c[2][1]) != 1)) { errorPrint ("archTorus3DomLoad: bad input"); return (1); } return (0); } /* This routine saves domain information ** to the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archTorus3DomSave ( const ArchTorus3 * const archptr, const ArchTorus3Dom * const domptr, FILE * restrict const stream) { if (fprintf (stream, ANUMSTRING " " ANUMSTRING " " ANUMSTRING " " ANUMSTRING " " ANUMSTRING " " ANUMSTRING " ", (Anum) domptr->c[0][0], (Anum) domptr->c[1][0], (Anum) domptr->c[2][0], (Anum) domptr->c[0][1], (Anum) domptr->c[1][1], (Anum) domptr->c[2][1]) == EOF) { errorPrint ("archTorus3DomSave: bad output"); return (1); } return (0); } /* This function tries to split a cubic ** domain into two subdomains. ** It returns: ** - 0 : if bipartitioning succeeded. ** - 1 : if bipartitioning could not be performed. ** - 2 : on error. */ int archTorus3DomBipart ( const ArchTorus3 * const archptr, const ArchTorus3Dom * const domptr, ArchTorus3Dom * restrict const dom0ptr, ArchTorus3Dom * restrict const dom1ptr) { Anum dimsiz[3]; int dimtmp; int dimval; dimsiz[0] = domptr->c[0][1] - domptr->c[0][0]; dimsiz[1] = domptr->c[1][1] - domptr->c[1][0]; dimsiz[2] = domptr->c[2][1] - domptr->c[2][0]; if ((dimsiz[0] | dimsiz[1] | dimsiz[2]) == 0) /* Return if cannot bipartition more */ return (1); dimval = (archptr->c[1] > archptr->c[0]) ? 1 : 0; /* Assume all subdomain dimensions are equal */ if (archptr->c[2] > archptr->c[dimval]) /* Find priviledged dimension */ dimval = 2; dimtmp = dimval; /* Find best dimension */ if (dimsiz[(dimtmp + 1) % 3] > dimsiz[dimval]) dimval = (dimtmp + 1) % 3; if (dimsiz[(dimtmp + 2) % 3] > dimsiz[dimval]) dimval = (dimtmp + 2) % 3; if (dimval == 0) { /* Split domain in two along largest dimension */ dom0ptr->c[0][0] = domptr->c[0][0]; dom0ptr->c[0][1] = (domptr->c[0][0] + domptr->c[0][1]) / 2; dom1ptr->c[0][0] = dom0ptr->c[0][1] + 1; dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; dom0ptr->c[2][0] = dom1ptr->c[2][0] = domptr->c[2][0]; dom0ptr->c[2][1] = dom1ptr->c[2][1] = domptr->c[2][1]; } else if (dimval == 1) { dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = (domptr->c[1][0] + domptr->c[1][1]) / 2; dom1ptr->c[1][0] = dom0ptr->c[1][1] + 1; dom1ptr->c[1][1] = domptr->c[1][1]; dom0ptr->c[2][0] = dom1ptr->c[2][0] = domptr->c[2][0]; dom0ptr->c[2][1] = dom1ptr->c[2][1] = domptr->c[2][1]; } else { dom0ptr->c[0][0] = dom1ptr->c[0][0] = domptr->c[0][0]; dom0ptr->c[0][1] = dom1ptr->c[0][1] = domptr->c[0][1]; dom0ptr->c[1][0] = dom1ptr->c[1][0] = domptr->c[1][0]; dom0ptr->c[1][1] = dom1ptr->c[1][1] = domptr->c[1][1]; dom0ptr->c[2][0] = domptr->c[2][0]; dom0ptr->c[2][1] = (domptr->c[2][0] + domptr->c[2][1]) / 2; dom1ptr->c[2][0] = dom0ptr->c[2][1] + 1; dom1ptr->c[2][1] = domptr->c[2][1]; } return (0); } /* This function creates the MPI_Datatype for ** 3D torus domains. ** It returns: ** - 0 : if type could be created. ** - 1 : on error. */ #ifdef SCOTCH_PTSCOTCH int archTorus3DomMpiType ( const ArchTorus3 * const archptr, MPI_Datatype * const typeptr) { MPI_Type_contiguous (6, ANUM_MPI, typeptr); return (0); } #endif /* SCOTCH_PTSCOTCH */ scotch-5.1.12b.dfsg/src/libscotch/comm.c0000644000175300017530000001665511631334325020247 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : comm.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the large size **/ /** communication handling routines. **/ /** **/ /** DATES : # Version 5.1 : from : 30 jul 2010 **/ /** to : 30 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define COMM #include "module.h" #include "common.h" #include "comm.h" /************************************/ /* */ /* These routines handle large size */ /* communications */ /* */ /************************************/ /* ** */ int commAllgatherv ( void * const senddattab, const Gnum sendcntnbr, MPI_Datatype sendtypval, void * const recvdattab, const Gnum * const recvcnttab, const Gnum * const recvdsptab, MPI_Datatype recvtypval, MPI_Comm comm) { int * restrict ircvcnttab; int * restrict ircvdsptab; int procglbnbr; int procnum; int o; MPI_Comm_size (comm, &procglbnbr); if (memAllocGroup ((void **) (void *) &ircvcnttab, (size_t) (procglbnbr * sizeof (int)), &ircvdsptab, (size_t) (procglbnbr * sizeof (int)), NULL) == NULL) { errorPrint ("commAllgatherv: out of memory"); return (MPI_ERR_OTHER); } for (procnum = 0; procnum < procglbnbr; procnum ++) { ircvcnttab[procnum] = (int) recvcnttab[procnum]; ircvdsptab[procnum] = (int) recvdsptab[procnum]; if (((Gnum) ircvcnttab[procnum] != recvcnttab[procnum]) || ((Gnum) ircvdsptab[procnum] != recvdsptab[procnum])) { errorPrint ("commAllgatherv: communication indices out of range"); memFree (ircvcnttab); return (MPI_ERR_ARG); } } o = MPI_Allgatherv (senddattab, sendcntnbr, sendtypval, recvdattab, ircvcnttab, ircvdsptab, recvtypval, comm); memFree (ircvcnttab); return (o); } /* ** */ int commGatherv ( void * const senddattab, const Gnum sendcntnbr, MPI_Datatype sendtypval, void * const recvdattab, const Gnum * const recvcnttab, const Gnum * const recvdsptab, MPI_Datatype recvtypval, const int rootnum, MPI_Comm comm) { int * restrict ircvcnttab; int * restrict ircvdsptab; int proclocnum; int o; MPI_Comm_rank (comm, &proclocnum); ircvcnttab = NULL; if (rootnum == proclocnum) { int procglbnbr; int procnum; MPI_Comm_size (comm, &procglbnbr); if (memAllocGroup ((void **) (void *) &ircvcnttab, (size_t) (procglbnbr * sizeof (int)), &ircvdsptab, (size_t) (procglbnbr * sizeof (int)), NULL) == NULL) { errorPrint ("commGatherv: out of memory"); return (MPI_ERR_OTHER); } for (procnum = 0; procnum < procglbnbr; procnum ++) { ircvcnttab[procnum] = (int) recvcnttab[procnum]; ircvdsptab[procnum] = (int) recvdsptab[procnum]; if (((Gnum) ircvcnttab[procnum] != recvcnttab[procnum]) || ((Gnum) ircvdsptab[procnum] != recvdsptab[procnum])) { errorPrint ("commGatherv: communication indices out of range"); memFree (ircvcnttab); return (MPI_ERR_ARG); } } } o = MPI_Gatherv (senddattab, sendcntnbr, sendtypval, recvdattab, ircvcnttab, ircvdsptab, recvtypval, rootnum, comm); if (ircvcnttab != NULL) memFree (ircvcnttab); return (o); } /* ** */ int commScatterv ( void * const senddattab, const Gnum * const sendcnttab, const Gnum * const senddsptab, MPI_Datatype sendtypval, void * const recvdattab, const Gnum recvcntnbr, MPI_Datatype recvtypval, const int rootnum, MPI_Comm comm) { int * restrict isndcnttab; int * restrict isnddsptab; int proclocnum; int o; MPI_Comm_rank (comm, &proclocnum); isndcnttab = NULL; if (rootnum == proclocnum) { int procglbnbr; int procnum; MPI_Comm_size (comm, &procglbnbr); if (memAllocGroup ((void **) (void *) &isndcnttab, (size_t) (procglbnbr * sizeof (int)), &isnddsptab, (size_t) (procglbnbr * sizeof (int)), NULL) == NULL) { errorPrint ("commScatterv: out of memory"); return (MPI_ERR_OTHER); } for (procnum = 0; procnum < procglbnbr; procnum ++) { isndcnttab[procnum] = (int) sendcnttab[procnum]; isnddsptab[procnum] = (int) senddsptab[procnum]; if (((Gnum) isndcnttab[procnum] != sendcnttab[procnum]) || ((Gnum) isnddsptab[procnum] != senddsptab[procnum])) { errorPrint ("commScatterv: communication indices out of range"); memFree (isndcnttab); return (MPI_ERR_ARG); } } } o = MPI_Scatterv (senddattab, isndcnttab, isnddsptab, sendtypval, recvdattab, (int) recvcntnbr, recvtypval, rootnum, comm); if (isndcnttab != NULL) memFree (isndcnttab); return (o); } scotch-5.1.12b.dfsg/src/libscotch/kdgraph_map_rb_part.h0000644000175300017530000001211211631334325023267 0ustar hazelscthazelsct/* Copyright 2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kdgraph_map_rb_part.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the Parallel Dual Recursive **/ /** Bipartitioning mapping algorithm. **/ /** **/ /** DATES : # Version 5.1 : from : 23 jun 2008 **/ /** to 31 aug 2011 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds folded graph data, whether centralized or distributed +*/ typedef struct KdgraphMapRbPartGraph_ { ArchDom domnorg; /*+ Domain to bipartition at this stage +*/ int procnbr; /*+ Number of processes holding graph +*/ INT levlnum; /*+ Level number +*/ union { Graph cgrfdat; /*+ Centralized graph +*/ Dgraph dgrfdat; /*+ Distributed graph +*/ } data; } KdgraphMapRbPartGraph; /*+ This structure holds the data passed to the subgraph building threads. +*/ typedef struct KdgraphMapRbPartThread_ { Dmapping * mappptr; /*+ Pointer to mapping structure +*/ Dgraph * orggrafptr; /*+ Pointer to original graph +*/ const ArchDom * inddomnptr; /*+ Pointer to subjob domain +*/ Gnum indvertnbr; /*+ Local number of vertices in subgraph +*/ int indpartval; /*+ Graph part from which to extract subgraph +*/ GraphPart * indparttax; /*+ Based local vertex partition flags in subgraph +*/ KdgraphMapRbPartGraph * fldgrafptr; /*+ Pointer to folded graph union area +*/ int fldpartval; /*+ Part of processor array to which to fold to +*/ int fldprocnbr; /*+ Number of processes in folded communicator +*/ int fldprocnum; /*+ Rank of process in folded communicator, or -1 +*/ MPI_Comm fldproccomm; /*+ Communicator for the folded graph, if any +*/ } KdgraphMapRbPartThread; /*+ This structure holds the data passed to each bipartitioning job. +*/ typedef struct KdgraphMapRbPartData_ { Dmapping * mappptr; const KdgraphMapRbParam * paraptr; double comploadrat; /*+ Ideal vertex load per target load +*/ double comploadmin; /*+ Minimum vertex load per target load +*/ double comploadmax; /*+ Maximum vertex load per target load +*/ } KdgraphMapRbPartData; /* ** The function prototypes. */ #ifndef KDGRAPH_MAP_RB #define static #endif int kdgraphMapRbPart (Kdgraph * const, Kdmapping * const, const KdgraphMapRbParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/arch_deco.h0000644000175300017530000001705711631334325021225 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_deco.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the decomposition-defined target **/ /** architecture functions. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 12 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 30 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 24 jul 1995 **/ /** # Version 3.1 : from : 20 jul 1996 **/ /** to 20 jul 1996 **/ /** # Version 3.2 : from : 11 sep 1996 **/ /** to 28 sep 1998 **/ /** # Version 4.0 : from : 29 nov 2003 **/ /** to 14 jun 2004 **/ /** # Version 5.1 : from : 21 jan 2008 **/ /** to 27 sep 2008 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Decomposition architecture flags. +*/ #define ARCHDECONONE 0x0000 /*+ No options set +*/ #define ARCHDECOFREE 0x0001 /*+ Free arrays +*/ /* ** The type and structure definitions. */ /*+ The decomposition-described terminal vertex definition. +*/ typedef struct ArchDecoTermVert_ { ArchDomNum labl; /*+ Number for terminals, or ARCHDOMNOTTERM +*/ Anum wght; /*+ Weight of the domain (processor load) +*/ Anum num; /*+ Number of the terminal +*/ } ArchDecoTermVert; /*+ The decomposition-described architecture definitions. +*/ typedef struct ArchDecoVert_ { ArchDomNum labl; /*+ Smallest number of included terminal +*/ Anum size; /*+ Number of processors in the domain +*/ Anum wght; /*+ Weight of the domain (processor load) +*/ } ArchDecoVert; typedef struct ArchDeco_ { int flagval; /*+ Flag value +*/ Anum domtermnbr; /*+ Number of terminal domains +*/ Anum domvertnbr; /*+ Number of domains +*/ ArchDecoVert * domverttab; /*+ Table of domain "vertices" +*/ Anum * domdisttab; /*+ Table of domain distances +*/ } ArchDeco; typedef struct ArchDecoDom_ { Anum num; /*+ Domain number in the decomposition +*/ } ArchDecoDom; /* ** The function prototypes. */ #ifndef ARCH_DECO #define static #endif int archDecoArchBuild (ArchDeco * const, const Anum, const Anum, const ArchDecoTermVert * const, const Anum * const); int archDecoArchLoad (ArchDeco * const, FILE * restrict const); int archDecoArchSave (const ArchDeco * const, FILE * restrict const); int archDecoArchFree (ArchDeco * const); Anum archDecoArchSize (ArchDeco * const, const Anum); Anum archDecoArchDist (ArchDeco * const, const Anum, const Anum); Anum archDecoArchDistE (ArchDeco * const, const Anum, const Anum); ArchDomNum archDecoDomNum (const ArchDeco * const, const ArchDecoDom * const); int archDecoDomTerm (const ArchDeco * const, ArchDecoDom * restrict const, const ArchDomNum); Anum archDecoDomSize (const ArchDeco * const, const ArchDecoDom * const); Anum archDecoDomWght (const ArchDeco * const, const ArchDecoDom * const); Anum archDecoDomDist (const ArchDeco * const, const ArchDecoDom * const, const ArchDecoDom * const); int archDecoDomFrst (const ArchDeco * const, ArchDecoDom * restrict const); int archDecoDomLoad (const ArchDeco * const, ArchDecoDom * restrict const, FILE * restrict const); int archDecoDomSave (const ArchDeco * const, const ArchDecoDom * const, FILE * restrict const); int archDecoDomBipart (const ArchDeco * const, const ArchDecoDom * const, ArchDecoDom * restrict const, ArchDecoDom * restrict const); #ifdef SCOTCH_PTSCOTCH int archDecoDomMpiType (const ArchDeco * const, MPI_Datatype * const); #endif /* SCOTCH_PTSCOTCH */ #undef static /* ** The macro definitions. */ #define archDecoArchSize(d,i) ((d)->domverttab[(i) - 1].size) #define archDecoArchDist(d,i,j) ((d)->domdisttab[((i) >= (j)) ? (((i) - 1) * ((i) - 2)) / 2 + (j) - 1 \ : (((j) - 1) * ((j) - 2)) / 2 + (i) - 1]) #define archDecoArchDistE(d,i,j) (((i) == (j)) ? 0 : archDecoArchDist ((d), (i), (j))) scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_order_tree_dist_f.c0000644000175300017530000000747511631334325026047 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_order_tree_dist_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** distributed ordering distributed tree **/ /** building routine of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 5.1 : from : 30 nov 2007 **/ /** to 30 nov 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the ordering routines. */ /* */ /**************************************/ FORTRAN ( \ SCOTCHFDGRAPHORDERCBLKDIST, scotchfdgraphordercblkdist, ( \ const SCOTCH_Dgraph * const grafptr, \ const SCOTCH_Dordering * const ordeptr, \ SCOTCH_Num * const cblkglbptr), (grafptr, ordeptr, cblkglbptr)) { *cblkglbptr = SCOTCH_dgraphOrderCblkDist (grafptr, ordeptr); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHORDERTREEDIST, scotchfdgraphordertreedist, ( \ const SCOTCH_Dgraph * const grafptr, \ const SCOTCH_Dordering * const ordeptr, \ SCOTCH_Num * const treeglbtab, \ SCOTCH_Num * const sizeglbtab, \ int * const revaptr), \ (grafptr, ordeptr, treeglbtab, sizeglbtab, revaptr)) { *revaptr = SCOTCH_dgraphOrderTreeDist (grafptr, ordeptr, treeglbtab, sizeglbtab); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_io_load.h0000644000175300017530000000562411631334325022246 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_io_load.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the distributed graph loading **/ /** routines. **/ /** **/ /** DATES : # Version 5.0 : from : 12 may 2007 **/ /** to 13 may 2007 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef DGRAPH_IO_LOAD #define static #endif static int dgraphLoadCent (Dgraph * restrict const, FILE * const, Gnum, const GraphFlag, const int); static int dgraphLoadDist (Dgraph * restrict const, FILE * const, Gnum, const GraphFlag); static int dgraphLoadMulti (Dgraph * restrict const, FILE * const, Gnum, const GraphFlag); #undef static scotch-5.1.12b.dfsg/src/libscotch/comm.h0000644000175300017530000000737311631334325020251 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : comm.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for communication functions. **/ /** **/ /** DATES : # Version 5.1 : from : 30 jul 2010 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ #define COMM_H /* ** The type and structure definitions. */ #ifndef GNUMMAX /* If dgraph.h not included */ typedef INT Gnum; /* Vertex and edge numbers */ typedef UINT Gunum; /* Unsigned type of same width */ #define GNUMMAX (INTVALMAX) /* Maximum signed Gnum value */ #define GNUMSTRING INTSTRING /* String to printf a Gnum */ #endif /* GNUMMAX */ /* ** The function prototypes. */ #ifndef COMM #define static #endif int commAllgatherv (void * const, const Gnum, MPI_Datatype, void * const, const Gnum * const, const Gnum * const, MPI_Datatype, MPI_Comm); int commGatherv (void * const, const Gnum, MPI_Datatype, void * const, const Gnum * const, const Gnum * const, MPI_Datatype, const int, MPI_Comm); int commScatterv (void * const, const Gnum * const, const Gnum * const, MPI_Datatype, void * const, const Gnum, MPI_Datatype, const int, MPI_Comm); #undef static /* ** The macro definitions. */ #ifndef COMM #ifndef INTSIZE64 #define commAllgatherv MPI_Allgatherv #define commGatherv MPI_Gatherv #define commScatterv MPI_Scatterv #endif /* INTSIZE64 */ #endif /* COMM */ scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_st.h0000644000175300017530000000742411631334325022320 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_st.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data **/ /** declarations for the main halo mesh **/ /** ordering routine. **/ /** **/ /** DATES : # Version 4.0 : from : 28 sep 2002 **/ /** to : 08 feb 2004 **/ /** **/ /************************************************************/ /* ** The type definitions. */ /*+ Method types. +*/ typedef enum HmeshOrderStMethodType_ { HMESHORDERSTMETHBL = 0, /*+ Block splitting post-processing +*/ HMESHORDERSTMETHCP, /*+ Mesh compression +*/ HMESHORDERSTMETHGP, /*+ Gibbs-Poole-Stockmeyer +*/ HMESHORDERSTMETHGR, /*+ Graph-based ordering +*/ HMESHORDERSTMETHHD, /*+ Block Halo Approximate Minimum Degree +*/ HMESHORDERSTMETHHF, /*+ Block Halo Approximate Minimum Fill +*/ HMESHORDERSTMETHND, /*+ Nested Dissection +*/ HMESHORDERSTMETHSI, /*+ Simple +*/ HMESHORDERSTMETHNBR /*+ Number of methods +*/ } HmeshOrderStMethodType; /* ** The external declarations. */ extern StratTab hmeshorderststratab; /* ** The function prototypes. */ #ifndef HMESH_ORDER_ST #define static #endif int hmeshOrderSt (const Hmesh * restrict const, Order * restrict const, const Gnum, OrderCblk * restrict const, const Strat * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_mesh_order.c0000644000175300017530000003767311631334325023172 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_mesh_order.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the mesh **/ /** ordering routines of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 3.2 : from : 19 aug 1998 **/ /** to 22 aug 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 27 mar 1999 **/ /** # Version 4.0 : from : 29 jan 2002 **/ /** to 20 dec 2005 **/ /** # Version 5.0 : from : 04 aug 2007 **/ /** to 31 may 2008 **/ /** # Version 5.1 : from : 29 mar 2010 **/ /** to 14 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "mesh.h" #include "order.h" #include "hmesh.h" #include "hmesh_order_st.h" #include "library_order.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the mesh ordering routines. */ /* */ /************************************/ /*+ This routine initializes an API ordering *** with respect to the given source graph *** and the locations of output parameters. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_meshOrderInit ( const SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ SCOTCH_Ordering * const ordeptr, /*+ Ordering structure to initialize +*/ SCOTCH_Num * const permtab, /*+ Direct permutation array +*/ SCOTCH_Num * const peritab, /*+ Inverse permutation array +*/ SCOTCH_Num * const cblkptr, /*+ Pointer to number of column blocks +*/ SCOTCH_Num * const rangtab, /*+ Column block range array +*/ SCOTCH_Num * const treetab) /*+ Separator tree array +*/ { Mesh * srcmeshptr; LibOrder * libordeptr; #ifdef SCOTCH_DEBUG_LIBRARY1 if (sizeof (SCOTCH_Ordering) < sizeof (LibOrder)) { errorPrint ("SCOTCH_meshOrderInit: internal error"); return (1); } #endif /* SCOTCH_DEBUG_LIBRARY1 */ srcmeshptr = (Mesh *) meshptr; /* Use structure as source mesh */ libordeptr = (LibOrder *) ordeptr; libordeptr->permtab = ((permtab == NULL) || ((void *) permtab == (void *) meshptr)) ? NULL : (Gnum *) permtab; libordeptr->peritab = ((peritab == NULL) || ((void *) peritab == (void *) meshptr)) ? NULL : (Gnum *) peritab; libordeptr->cblkptr = ((cblkptr == NULL) || ((void *) cblkptr == (void *) meshptr)) ? NULL : (Gnum *) cblkptr; libordeptr->rangtab = ((rangtab == NULL) || ((void *) rangtab == (void *) meshptr)) ? NULL : (Gnum *) rangtab; libordeptr->treetab = ((treetab == NULL) || ((void *) treetab == (void *) meshptr)) ? NULL : (Gnum *) treetab; return (orderInit (&libordeptr->o, srcmeshptr->baseval, srcmeshptr->vnodnbr, libordeptr->peritab)); } /*+ This routine frees an API ordering. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_meshOrderExit ( const SCOTCH_Mesh * const meshptr, SCOTCH_Ordering * const ordeptr) { orderExit (&((LibOrder *) ordeptr)->o); } /*+ This routine saves the contents of *** the given ordering to the given stream. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_meshOrderSave ( const SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ const SCOTCH_Ordering * const ordeptr, /*+ Ordering to save +*/ FILE * const stream) /*+ Output stream +*/ { return (orderSave (&((LibOrder *) ordeptr)->o, ((Mesh *) meshptr)->vlbltax, stream)); } /*+ This routine saves the mapping data *** associated with the given ordering *** to the given stream. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_meshOrderSaveMap ( const SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ const SCOTCH_Ordering * const ordeptr, /*+ Ordering to save +*/ FILE * const stream) /*+ Output stream +*/ { return (orderSaveMap (&((LibOrder *) ordeptr)->o, ((Mesh *) meshptr)->vlbltax, stream)); } /*+ This routine saves to the given stream *** the separator tree data associated with *** the given ordering. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_meshOrderSaveTree ( const SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ const SCOTCH_Ordering * const ordeptr, /*+ Ordering to save +*/ FILE * const stream) /*+ Output stream +*/ { return (orderSaveTree (&((LibOrder *) ordeptr)->o, ((Mesh *) meshptr)->vlbltax, stream)); } /*+ This routine computes an ordering *** of the API ordering structure with *** respect to the given strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_meshOrderCompute ( SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ SCOTCH_Ordering * const ordeptr, /*+ Ordering to compute +*/ SCOTCH_Strat * const stratptr) /*+ Ordering strategy +*/ { return (SCOTCH_meshOrderComputeList (meshptr, ordeptr, 0, NULL, stratptr)); } /*+ This routine computes a partial ordering *** of the listed nodes of the API ordering *** structure mesh with respect to the given *** strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_meshOrderComputeList ( SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ SCOTCH_Ordering * const ordeptr, /*+ Ordering to compute +*/ const SCOTCH_Num listnbr, /*+ Number of vertices in list +*/ const SCOTCH_Num * const listtab, /*+ List of vertex indices to order +*/ SCOTCH_Strat * const stratptr) /*+ Ordering strategy +*/ { LibOrder * libordeptr; /* Pointer to ordering */ Mesh * srcmeshptr; /* Pointer to source mesh */ Hmesh srcmeshdat; /* Halo source mesh structure */ VertList srclistdat; /* Subgraph vertex list */ VertList * srclistptr; /* Pointer to subgraph vertex list */ const Strat * ordstratptr; /* Pointer to ordering strategy */ srcmeshptr = (Mesh *) meshptr; #ifdef SCOTCH_DEBUG_MESH2 if (meshCheck (srcmeshptr) != 0) { errorPrint ("SCOTCH_meshOrderComputeList: invalid input mesh"); return (1); } #endif /* SCOTCH_DEBUG_MESH2 */ if (*((Strat **) stratptr) == NULL) /* Set default ordering strategy if necessary */ SCOTCH_stratMeshOrderBuild (stratptr, SCOTCH_STRATQUALITY, 0.1); ordstratptr = *((Strat **) stratptr); if (ordstratptr->tabl != &hmeshorderststratab) { errorPrint ("SCOTCH_meshOrderComputeList: not a mesh ordering strategy"); return (1); } memCpy (&srcmeshdat.m, srcmeshptr, sizeof (Mesh)); /* Copy non-halo mesh data */ srcmeshdat.m.flagval &= ~MESHFREETABS; /* Do not allow to free arrays */ srcmeshdat.vehdtax = srcmeshdat.m.vendtax; /* End of non-halo vertices */ srcmeshdat.veihnbr = 0; /* No halo isolated elements */ srcmeshdat.vnohnbr = srcmeshdat.m.vnodnbr; /* All nodes are non-halo */ srcmeshdat.vnohnnd = srcmeshdat.m.vnodnnd; /* No halo present */ srcmeshdat.vnhlsum = srcmeshdat.m.vnlosum; /* Sum of node vertex weights */ srcmeshdat.enohnbr = srcmeshdat.m.edgenbr; /* All edges are non-halo */ srcmeshdat.levlnum = 0; /* Start from level zero */ libordeptr = (LibOrder *) ordeptr; /* Get ordering */ srclistdat.vnumnbr = (Gnum) listnbr; /* Build vertex list */ srclistdat.vnumtab = (Gnum *) listtab; srclistptr = ((srclistdat.vnumnbr == 0) || (srclistdat.vnumnbr == srcmeshdat.m.vnodnbr)) ? NULL : &srclistdat; /* Is the list really necessary */ if (srclistptr != NULL) { errorPrint ("SCOTCH_meshOrderComputeList: node lists not yet implemented"); return (1); } hmeshOrderSt (&srcmeshdat, &libordeptr->o, 0, &libordeptr->o.cblktre, ordstratptr); #ifdef SCOTCH_DEBUG_LIBRARY2 orderCheck (&libordeptr->o); #endif /* SCOTCH_DEBUG_LIBRARY2 */ if (libordeptr->permtab != NULL) /* Build direct permutation if wanted */ orderPeri (libordeptr->o.peritab, libordeptr->o.baseval, libordeptr->o.vnodnbr, libordeptr->permtab, libordeptr->o.baseval); if (libordeptr->rangtab != NULL) /* Build range array if column block data wanted */ orderRang (&libordeptr->o, libordeptr->rangtab); if (libordeptr->treetab != NULL) /* Build separator tree array if wanted */ orderTree (&libordeptr->o, libordeptr->treetab); if (libordeptr->cblkptr != NULL) /* Set number of column blocks if wanted */ *(libordeptr->cblkptr) = libordeptr->o.cblknbr; meshExit (&srcmeshdat.m); /* Free in case mesh had been reordered */ return (0); } /*+ This routine computes an ordering *** of the API ordering structure with *** respect to the given strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_meshOrder ( SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ SCOTCH_Strat * const stratptr, /*+ Ordering strategy +*/ SCOTCH_Num * const permtab, /*+ Ordering permutation +*/ SCOTCH_Num * const peritab, /*+ Inverse permutation array +*/ SCOTCH_Num * const cblkptr, /*+ Pointer to number of column blocks +*/ SCOTCH_Num * const rangtab, /*+ Column block range array +*/ SCOTCH_Num * const treetab) /*+ Separator tree array +*/ { SCOTCH_Ordering ordedat; int o; SCOTCH_meshOrderInit (meshptr, &ordedat, permtab, peritab, cblkptr, rangtab, treetab); o = SCOTCH_meshOrderCompute (meshptr, &ordedat, stratptr); SCOTCH_meshOrderExit (meshptr, &ordedat); return (o); } /*+ This routine computes an ordering *** of the submesh of the API ordering *** structure mesh induced by the given *** vertex list, with respect to the given *** strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_meshOrderList ( SCOTCH_Mesh * const meshptr, /*+ Mesh to order +*/ const SCOTCH_Num listnbr, /*+ Number of vertices in list +*/ const SCOTCH_Num * const listtab, /*+ List of vertex indices to order +*/ SCOTCH_Strat * const stratptr, /*+ Ordering strategy +*/ SCOTCH_Num * const permtab, /*+ Ordering permutation +*/ SCOTCH_Num * const peritab, /*+ Inverse permutation array +*/ SCOTCH_Num * const cblkptr, /*+ Pointer to number of column blocks +*/ SCOTCH_Num * const rangtab, /*+ Column block range array +*/ SCOTCH_Num * const treetab) /*+ Column block range array +*/ { SCOTCH_Ordering ordedat; int o; SCOTCH_meshOrderInit (meshptr, &ordedat, permtab, peritab, cblkptr, rangtab, treetab); o = SCOTCH_meshOrderComputeList (meshptr, &ordedat, listnbr, listtab, stratptr); SCOTCH_meshOrderExit (meshptr, &ordedat); return (o); } /*+ This routine checks the consistency *** of the given mesh ordering. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_meshOrderCheck ( const SCOTCH_Mesh * const meshptr, const SCOTCH_Ordering * const ordeptr) /*+ Ordering to check +*/ { return (orderCheck (&((LibOrder *) ordeptr)->o)); } /*+ This routine parses the given *** mesh ordering strategy. *** It returns: *** - 0 : if string successfully scanned. *** - !0 : on error. +*/ int SCOTCH_stratMeshOrder ( SCOTCH_Strat * const stratptr, const char * const string) { if (*((Strat **) stratptr) != NULL) stratExit (*((Strat **) stratptr)); if ((*((Strat **) stratptr) = stratInit (&hmeshorderststratab, string)) == NULL) { errorPrint ("SCOTCH_stratMeshOrder: error in ordering strategy"); return (1); } return (0); } /*+ This routine provides predefined *** ordering strategies. *** It returns: *** - 0 : if string successfully initialized. *** - !0 : on error. +*/ int SCOTCH_stratMeshOrderBuild ( SCOTCH_Strat * const stratptr, /*+ Strategy to create +*/ const SCOTCH_Num flagval, /*+ Desired characteristics +*/ const double balrat) /*+ Desired imbalance ratio +*/ { char bufftab[8192]; /* Should be enough */ char bbaltab[32]; strcpy (bufftab, "c{rat=0.7,cpr=n{sep=/(vnod>120)?m{vnod=100,low=h{pass=10},asc=f{bal=}}:;,ole=v{strat=d{cmin=0,cmax=10000000,frat=0}},ose=g},unc=n{sep=/(vnod>120)?m{vnod=100,low=h{pass=10},asc=f{bal=}}:;,ole=v{strat=d{cmin=0,cmax=10000000,frat=0}},ose=g}}"); sprintf (bbaltab, "%lf", balrat); stringSubst (bufftab, "", bbaltab); if (SCOTCH_stratMeshOrder (stratptr, bufftab) != 0) { errorPrint ("SCOTCH_stratMeshOrderBuild: error in sequential ordering strategy"); return (1); } return (0); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_io_load.c0000644000175300017530000011210311631334325022230 0ustar hazelscthazelsct/* Copyright 2007-2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_io_load.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the input/output routines for **/ /** distributed graphs. **/ /** **/ /** # Version 5.0 : from : 28 apr 2007 **/ /** to : 24 mar 2008 **/ /** # Version 5.1 : from : 23 jun 2008 **/ /** to : 27 jan 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH_IO_LOAD #include "module.h" #include "common.h" #include "graph.h" #include "dgraph.h" #include "dgraph_allreduce.h" #include "dgraph_io_load.h" /* This routine loads a distributed source ** graph from the given stream(s). Either ** one processor holds a non-NULL stream ** of a centralized graph, or all of them ** hold valid streams to either a centralized ** or a distributed graph. ** It returns: ** - 0 : on success. ** - !0 : on error. */ DGRAPHALLREDUCEMAXSUMOP (6, 3) DGRAPHALLREDUCEMAXSUMOP (10, 2) int dgraphLoad ( Dgraph * restrict const grafptr, /* Not const since halo may update structure */ FILE * const stream, /* One single centralized stream or distributed ones */ const Gnum baseval, /* Base value (-1 means keep file base) */ const DgraphFlag flagval) /* Graph loading flags */ { Gnum reduloctab[12]; Gnum reduglbtab[12]; Gnum versval; #ifdef SCOTCH_DEBUG_DGRAPH2 if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { /* Synchronize for debugging */ errorPrint ("dgraphLoad: communication error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ reduloctab[0] = baseval; /* Exchange baseval to check it is the same for all */ reduloctab[1] = - baseval; reduloctab[2] = flagval; /* Exchange flagval to check it is the same for all */ reduloctab[3] = - flagval; reduloctab[4] = 0; /* Set uneffective values for versval */ reduloctab[5] = -2; reduloctab[6] = /* Assume everything will be fine */ reduloctab[7] = /* Assume does not have a stream */ reduloctab[8] = 0; if (stream != NULL) { if (intLoad (stream, &versval) != 1) { /* Read version number */ errorPrint ("dgraphLoad: bad input (1)"); versval = 0; reduloctab[6] = 1; } else if ((versval != 0) && (versval != 2)) { /* If not a graph format */ errorPrint ("dgraphLoad: not a graph format"); reduloctab[6] = 1; } reduloctab[4] = versval; reduloctab[5] = - versval; reduloctab[7] = 1; /* One more process involved in loading */ reduloctab[8] = grafptr->proclocnum; } if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 6, 3, grafptr->proccomm) != 0) { errorPrint ("dgraphLoad: communication error (2)"); return (1); } if (reduglbtab[6] != 0) /* Return from previous errors */ return (1); if ((reduglbtab[0] != - reduglbtab[1])) { errorPrint ("dgraphLoad: inconsistent base value"); return (1); } if ((reduglbtab[2] != - reduglbtab[3])) { errorPrint ("dgraphLoad: inconsistent flag value"); return (1); } if ((reduglbtab[7] != 0) && (reduglbtab[4] != - reduglbtab[5])) { errorPrint ("dgraphLoad: inconsistent graph file version value"); return (1); } if (reduglbtab[4] == 2) { /* If distributed graph format */ if (reduglbtab[7] == grafptr->procglbnbr) /* If as many input streams as processors */ return (dgraphLoadDist (grafptr, stream, baseval, flagval)); /* Read distributed graph */ } else { /* If centralized graph format */ if (reduglbtab[7] == 1) /* If only one reader stream */ return (dgraphLoadCent (grafptr, stream, baseval, flagval, reduglbtab[8])); /* Distribute centralized graph from known root */ else if (reduglbtab[7] == grafptr->procglbnbr) return (dgraphLoadMulti (grafptr, stream, baseval, flagval)); /* Read multi-centralized graph */ } errorPrint ("dgraphLoad: invalid number of input streams"); return (1); } /* This routine loads a centralized source ** graph from a single stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ static int dgraphLoadCent ( Dgraph * restrict const grafptr, /* Distributed graph to load */ FILE * const stream, /* One single centralized stream */ Gnum baseval, /* Base value (-1 means keep file base) */ const DgraphFlag flagval, /* Graph loading flags */ const int protnum) /* Root process number */ { Gnum vertglbnbr; Gnum vertglbmax; Gnum vertlocnbr; Gnum * vertloctax; /* [norestrict:async] */ Gnum * vertlocptr; Gnum * restrict vertredtax; Gnum velolocnbr; Gnum velolocsum; Gnum * veloloctax; Gnum * restrict veloredtax; Gnum vlbllocnbr; Gnum * vlblloctax; Gnum * restrict vlblredtax; Gnum edgelocnbr; Gnum * edgeloctax; Gnum edgeredmnd; Gnum * restrict edgeredtax; Gnum * edloloctax; Gnum * restrict edloredtax; Gnum degrglbmax; Gnum baseadj; Gnum reduglbtab[5]; char proptab[4]; /* Property string array */ int cheklocval; int chekglbval; int o; #ifdef SCOTCH_DEBUG_DGRAPH2 if (((stream != NULL) && (protnum != grafptr->proclocnum)) || /* Enforce single stream */ ((stream == NULL) && (protnum == grafptr->proclocnum))) { errorPrint ("dgraphLoadCent: invalid parameter (1)"); return (1); } if ((protnum < 0) || (protnum >= grafptr->procglbnbr)) { errorPrint ("dgraphLoadCent: invalid parameter (2)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ reduglbtab[0] = 0; /* Assume everything will be fine */ if (stream != NULL) { if ((intLoad (stream, &reduglbtab[1]) != 1) || /* Read rest of header */ (intLoad (stream, &reduglbtab[2]) != 1) || (intLoad (stream, &reduglbtab[3]) != 1) || (intLoad (stream, &reduglbtab[4]) != 1) || (reduglbtab[4] < 0) || (reduglbtab[4] > 111)) { errorPrint ("dgraphLoadCent: bad input (1)"); cheklocval = 1; } } if (MPI_Bcast (&reduglbtab[0], 5, GNUM_MPI, protnum, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphLoadCent: communication error (1)"); return (1); } if (reduglbtab[0] != 0) return (1); if (baseval == -1) { /* If keep file graph base */ baseval = reduglbtab[3]; /* Set graph base as file base */ baseadj = 0; /* No base adjustment needed */ } else /* If set graph base */ baseadj = baseval - reduglbtab[3]; /* Update base adjust */ vertglbnbr = reduglbtab[1]; vertglbmax = DATASIZE (vertglbnbr, grafptr->procglbnbr, 0); vertlocnbr = DATASIZE (vertglbnbr, grafptr->procglbnbr, grafptr->proclocnum); sprintf (proptab, "%3.3d", (int) reduglbtab[4]); /* Compute file properties */ proptab[0] -= '0'; /* Vertex labels flag */ proptab[1] -= '0'; /* Edge weights flag */ proptab[2] -= '0'; /* Vertex loads flag */ velolocnbr = ((proptab[2] != 0) && ((flagval & GRAPHIONOLOADVERT) == 0)) ? vertglbmax : 0; vlbllocnbr = (proptab[0] != 0) ? vertglbmax : 0; vlblloctax = veloloctax = vertloctax = edgeloctax = /* Send arrays not allocated yet for root process */ edgeredtax = NULL; /* No read edge array yet */ cheklocval = 0; if ((vertlocptr = memAlloc ((vertglbmax + 2 + velolocnbr + vlbllocnbr) * sizeof (Gnum))) == NULL) { /* TRICK: "+2" for space for velolocsum */ errorPrint ("dgraphLoadCent: out of memory (1)"); cheklocval = 1; } else { vertloctax = vertlocptr -= baseval; vertlocptr += vertglbmax + 2; /* TRICK: "+2" for space for velolocsum */ if (proptab[2] != 0) { veloloctax = vertlocptr; vertlocptr += vertglbmax; } if (proptab[0] != 0) { vlblloctax = vertlocptr; baseadj = 0; /* No vertex adjustments if vertex labels */ } if (stream != NULL) { /* Allocate read edge array */ Gnum edgeredmax; Gnum edloredmax; edgeredmax = reduglbtab[2] / grafptr->procglbnbr + 1; edgeredmax += (edgeredmax >> 2) + 4; /* Add 25% more space for edges than average */ edloredmax = ((proptab[1] != 0) && ((flagval & GRAPHIONOLOADEDGE) == 0)) ? edgeredmax : 0; if ((edgeredtax = memAlloc ((edgeredmax + edloredmax) * sizeof (Gnum))) == NULL) { errorPrint ("dgraphLoadCent: out of memory (2)"); cheklocval = 1; } else { edgeredtax -= baseval; edloredtax = (edloredmax != 0) ? (edgeredtax + edgeredmax) : NULL; vertredtax = vertloctax; /* Prepare read vertex arrays, which will never move */ veloredtax = veloloctax; vlblredtax = vlblloctax; } edgeredmnd = edgeredmax + baseval; } } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphLoadCent: communication error (2)"); chekglbval = 1; } if (chekglbval != 0) { if (edgeredtax != NULL) memFree (edgeredtax + baseval); if (vertloctax != NULL) memFree (vertloctax + baseval); return (1); } degrglbmax = 0; /* No maximum degree yet */ if (stream != NULL) { Gnum procnum; for (procnum = 0; procnum < grafptr->procglbnbr; procnum ++) { Gnum vertrednnd; Gnum vertrednum; Gnum edgerednum; Gnum veloredsum; for (vertrednum = edgerednum = baseval, veloredsum = 0, vertrednnd = DATASIZE (vertglbnbr, grafptr->procglbnbr, procnum) + baseval; vertrednum < vertrednnd; vertrednum ++) { Gnum degrredval; if (vlblredtax != NULL) { /* If must read label */ Gnum vlblredval; /* Vertex label value to be read */ if (intLoad (stream, &vlblredval) != 1) { /* Read label data */ errorPrint ("dgraphLoadCent: bad input (2)"); cheklocval = 1; break; } vlblredtax[vertrednum] = vlblredval; } if (proptab[2] != 0) { /* If must read vertex load */ Gnum veloredval; if (intLoad (stream, &veloredval) != 1) { /* Read vertex load data */ errorPrint ("dgraphLoadCent: bad input (3)"); cheklocval = 1; break; } if (veloredtax != NULL) veloredsum += veloredtax[vertrednum] = veloredval; } if (intLoad (stream, °rredval) != 1) { /* Read vertex degree */ errorPrint ("dgraphLoadCent: bad input (4)"); cheklocval = 1; break; } if (degrglbmax < degrredval) /* Set maximum degree */ degrglbmax = degrredval; vertredtax[vertrednum] = edgerednum; /* Set index in edge array */ degrredval += edgerednum; if (degrredval > edgeredmnd) { /* Check if edge array overflows */ Gnum edgeredmax; Gnum edgenewmax; Gnum edgenewsiz; Gnum * restrict edgenewtab; edgenewmax = edgeredmax = edgeredmnd - baseval; do /* Increase edge array size by 25 % */ edgenewmax += (edgenewmax >> 2) + 4; while (edgenewmax < (degrredval - baseval)); edgenewsiz = (edloredtax != NULL) ? (2 * edgenewmax) : edgenewmax; if ((edgenewtab = memRealloc (edgeredtax + baseval, edgenewsiz * sizeof (Gnum))) == NULL) { errorPrint ("dgraphLoadCent: out of memory (3)"); cheklocval = 1; break; } edgeredtax = edgenewtab - baseval; edgeredmnd = edgenewmax + baseval; if (edloredtax != NULL) { /* Move edge load array if present */ memMov (edgenewtab + edgenewmax, edgenewtab + edgeredmax, (edgerednum - baseval) * sizeof (Gnum)); edloredtax = edgeredtax + edgenewmax; } } for ( ; edgerednum < degrredval; edgerednum ++) { Gnum edgeredval; /* Value where to read edge end */ if (proptab[1] != 0) { /* If must read edge load */ Gnum edloredval; /* Value where to read edge load */ if (intLoad (stream, &edloredval) != 1) { /* Read edge load data */ errorPrint ("dgraphLoadCent: bad input (5)"); cheklocval = 1; break; } if (edloredtax != NULL) edloredtax[edgerednum] = edloredval; } if (intLoad (stream, &edgeredval) != 1) { /* Read edge data */ errorPrint ("dgraphLoadCent: bad input (6)"); cheklocval = 1; break; } edgeredtax[edgerednum] = edgeredval + baseadj; } if (cheklocval != 0) break; } vertredtax[vertrednum ++] = edgerednum; /* Set end of edge array */ if (cheklocval == 0) { if (procnum != grafptr->proclocnum) { /* If arrays have to be sent */ MPI_Request requtab[5]; MPI_Status stattab[5]; int requnbr; vertredtax[baseval] = edgerednum - baseval; /* First slot is number of edges */ vertredtax[vertrednum] = (veloredtax != NULL) ? veloredsum : (vertrednnd - baseval); /* Add vertex load sum to send vertex array */ if (MPI_Isend (vertredtax + baseval, vertrednnd - baseval + 2, /* TRICK: "+2" and not "+1" because of space for velolocsum */ GNUM_MPI, procnum, TAGVERTLOCTAB, grafptr->proccomm, &requtab[0]) != MPI_SUCCESS) { errorPrint ("dgraphLoadCent: communication error (5)"); return (1); /* Dirty exit as we can do nothing */ } requnbr = 1; if (veloredtax != NULL) { if (MPI_Isend (veloredtax + baseval, vertlocnbr, GNUM_MPI, procnum, TAGVELOLOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("dgraphLoadCent: communication error (6)"); return (1); } } if (vlblredtax != NULL) { if (MPI_Isend (vlblredtax + baseval, vertlocnbr, GNUM_MPI, procnum, TAGVLBLLOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("dgraphLoadCent: communication error (7)"); return (1); } } if (MPI_Recv (&reduglbtab[0], 0, MPI_INT, procnum, MPI_ANY_TAG, grafptr->proccomm, &stattab[0]) != MPI_SUCCESS) { errorPrint ("dgraphLoadCent: communication error (8)"); return (1); } if (stattab[0].MPI_TAG != TAGOK) /* If receiver could not allocate memory for edge arrays */ cheklocval = 1; else { if (MPI_Isend (edgeredtax + baseval, edgerednum - baseval, GNUM_MPI, procnum, TAGEDGELOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("dgraphLoadCent: communication error (9)"); return (1); } if (edloredtax != NULL) { if (MPI_Isend (edloredtax + baseval, edgerednum - baseval, GNUM_MPI, procnum, TAGEDLOLOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("dgraphLoadCent: communication error (10)"); return (1); } } MPI_Waitall (requnbr, &requtab[0], &stattab[0]); } } else { /* Arrays are local */ velolocsum = (veloredtax != NULL) ? veloredsum : vertlocnbr; /* Save accumulated values as local data */ edgelocnbr = edgerednum - baseval; if (edgeredmnd - edgerednum > 10000) { /* If array can be compacted */ if (edloredtax != NULL) { memMov (edgeredtax + edgerednum, edloredtax + baseval, edgelocnbr * sizeof (Gnum)); edgeredtax = memRealloc (edgeredtax + baseval, edgelocnbr * 2 * sizeof (Gnum)); edgeredtax -= baseval; edloredtax = edgeredtax + edgelocnbr; } else { edgeredtax = memRealloc (edgeredtax + baseval, edgelocnbr * sizeof (Gnum)); edgeredtax -= baseval; } } edgeloctax = edgeredtax; /* Keep read edge array as local edge array */ edloloctax = edloredtax; if (grafptr->proclocnum == (grafptr->procglbnbr - 1)) { /* If root process is last process */ vertredtax = /* No need to reallocate read arrays */ edgeredtax = NULL; break; /* And we can exit now */ } if ((vertlocptr = memAlloc ((vertglbmax + 2 + velolocnbr + vlbllocnbr) * sizeof (Gnum))) == NULL) { /* TRICK: "+2" for space for velolocsum */ errorPrint ("dgraphLoadCent: out of memory (4)"); cheklocval = 1; } else { Gnum edgeredmax; Gnum edloredmax; vertredtax = vertlocptr -= baseval; vertlocptr += vertglbmax + 2; /* TRICK: "+2" for space for velolocsum */ if (veloredtax != NULL) { veloredtax = vertlocptr; vertlocptr += vertglbmax; } if (vlblredtax != NULL) vlblredtax = vertlocptr; edgeredmax = edgeredmnd - baseval; edloredmax = (edloloctax != NULL) ? edgeredmax : 0; if ((edgeredtax = memAlloc ((edgeredmax + edloredmax) * sizeof (Gnum))) == NULL) { errorPrint ("dgraphLoadCent: out of memory (5)"); cheklocval = 1; } else { edgeredtax -= baseval; if (edloredtax != NULL) edloredtax = edgeredtax + edgeredmax; } } } } if (cheklocval != 0) { /* If error encountered */ for ( ; procnum < grafptr->procglbnbr; procnum ++) { /* Send abortion messages */ if (procnum != grafptr->proclocnum) { /* Abortion messages complete vertloctab receives */ if (MPI_Send (vertredtax + baseval, 0, GNUM_MPI, procnum, TAGVERTLOCTAB, grafptr->proccomm) != MPI_SUCCESS) errorPrint ("dgraphLoadCent: communication error (11)"); } } break; } } if (vertredtax != NULL) { /* Free reader arrays if reallocated */ if (vertredtax != vertloctax) /* If equal, vertloctax will be deallocated afterwards */ memFree (vertredtax + baseval); memFree (edgeredtax + baseval); } } else { /* Process is not reader */ MPI_Request requtab[5]; MPI_Status stattab[5]; int requnbr; int vertrcvnbr; /* int because of the MPI API */ if (MPI_Irecv (vertloctax + baseval, vertlocnbr + 2, GNUM_MPI, /* TRICK: "+2" and not "+1" because of velolocsum */ protnum, TAGVERTLOCTAB, grafptr->proccomm, &requtab[2]) != MPI_SUCCESS) { /* requtab[2] is first surely available slot */ errorPrint ("dgraphLoadCent: communication error (10)"); return (1); /* Dirty exit as we can do nothing */ } requnbr = 0; if (veloloctax != NULL) { if (MPI_Irecv (veloloctax + baseval, vertlocnbr, GNUM_MPI, protnum, TAGVELOLOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("dgraphLoadCent: communication error (11)"); return (1); } } if (vlblloctax != NULL) { if (MPI_Irecv (vlblloctax + baseval, vertlocnbr, GNUM_MPI, protnum, TAGVLBLLOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("dgraphLoadCent: communication error (12)"); return (1); } } MPI_Wait (&requtab[2], &stattab[2]); /* Wait until vertloctab received */ MPI_Get_count (&stattab[2], GNUM_MPI, &vertrcvnbr); /* Get size of received array */ #ifdef SCOTCH_DEBUG_DGRAPH2 if (((Gnum) vertrcvnbr != 0) && /* vertrcvnbr == 0 in the case of abortion message */ ((Gnum) vertrcvnbr != (vertlocnbr + 2))) { /* TRICK: "+2" and not "+1" because of velolocsum */ errorPrint ("dgraphLoadCent: invalid vertex array size"); vertrcvnbr = 0; } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (vertrcvnbr == 0) { /* Empty message means abortion wanted */ while (requnbr > 0) { /* Cancel all pending requests */ requnbr --; MPI_Cancel (&requtab[requnbr]); MPI_Request_free (&requtab[requnbr]); } /* No more pending requests */ } else { Gnum edlolocnbr; edgelocnbr = vertloctax[baseval]; /* edgelocnbr is first cell */ vertloctax[baseval] = baseval; /* First cell is always baseval */ velolocsum = vertloctax[vertlocnbr + baseval + 1]; /* TRICK: get velolocsum */ edlolocnbr = ((proptab[1] != 0) && ((flagval & GRAPHIONOLOADEDGE) == 0)) ? edgelocnbr : 0; edloloctax = NULL; /* Assume no edge load array */ if ((edgeloctax = memAlloc ((edgelocnbr + edlolocnbr) * sizeof (Gnum))) == NULL) { errorPrint ("dgraphLoadCent: out of memory (6)"); MPI_Send (&cheklocval, 0, MPI_INT, protnum, TAGBAD, grafptr->proccomm); /* Memory could not be allocated */ cheklocval = 1; } else { if (MPI_Irecv (edgeloctax, edgelocnbr, GNUM_MPI, protnum, TAGEDGELOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("dgraphLoadCent: communication error (13)"); return (1); } if (edlolocnbr != 0) { edloloctax = edgeloctax + edgelocnbr; if (MPI_Irecv (edloloctax, edgelocnbr, GNUM_MPI, protnum, TAGEDLOLOCTAB, grafptr->proccomm, &requtab[requnbr ++]) != MPI_SUCCESS) { errorPrint ("dgraphLoadCent: communication error (14)"); return (1); } edloloctax -= baseval; } edgeloctax -= baseval; MPI_Isend (&cheklocval, 0, MPI_INT, protnum, TAGOK, grafptr->proccomm, &requtab[requnbr ++]); /* Send ready to receive */ } } MPI_Waitall (requnbr, &requtab[0], &stattab[0]); /* Wait until all pending communications completed and all arrays received */ } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphLoadCent: communication error (15)"); chekglbval = 1; } if (chekglbval != 0) { if (edgeloctax != NULL) memFree (edgeloctax + baseval); memFree (vertloctax + baseval); return (1); } o = dgraphBuild2 (grafptr, baseval, /* Build distributed graph */ vertlocnbr, vertlocnbr, vertloctax, vertloctax + 1, veloloctax, velolocsum, NULL, vlblloctax, edgelocnbr, edgelocnbr, edgeloctax, NULL, edloloctax, degrglbmax); /* Non-readers will have degrglbmax set to 0 */ grafptr->flagval |= DGRAPHFREETABS | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; return (o); } /* This routine loads a distributed source ** graph from a distributed source graph ** file spread across all of the streams. ** It returns: ** - 0 : on success. ** - !0 : on error. */ static int dgraphLoadDist ( Dgraph * restrict const grafptr, /* Distributed graph to load */ FILE * const stream, /* One single centralized stream */ Gnum baseval, /* Base value (-1 means keep file base) */ const DgraphFlag flagval) /* Graph loading flags */ { Gnum proclocnum; Gnum vertlocnbr; Gnum vertlocnnd; Gnum vertlocnum; Gnum * restrict vertloctax; Gnum * vertlocptr; Gnum velolocnbr; Gnum velolocsum; Gnum * restrict veloloctax; Gnum vlbllocnbr; Gnum * restrict vlblloctax; Gnum edgelocnbr; Gnum edgelocnnd; Gnum edgelocnum; Gnum * restrict edgeloctax; Gnum * restrict edloloctax; Gnum degrlocmax; Gnum baseadj; Gnum reduloctab[12]; Gnum reduglbtab[12]; char proptab[4]; /* Property string array */ int cheklocval; int chekglbval; int o; #ifdef SCOTCH_DEBUG_DGRAPH2 if (stream == NULL) { errorPrint ("dgraphLoadDist: invalid parameter"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ reduloctab[0] = 0; /* Assume everything will be fine */ o = intLoad (stream, &reduloctab[1]); /* Read rest of header */ o += intLoad (stream, &proclocnum); o += intLoad (stream, &reduloctab[3]); o += intLoad (stream, &reduloctab[5]); o += intLoad (stream, &reduloctab[10]); o += intLoad (stream, &reduloctab[11]); o += intLoad (stream, &reduloctab[7]); o += intLoad (stream, &reduloctab[9]); if ((o != 8) || (reduloctab[9] < 0) || (reduloctab[9] > 111)) { errorPrint ("dgraphLoadDist: bad input (1)"); reduloctab[0] = 2; /* Immediate abort has maximum value so as to be propagated by MAX reduce */ } reduloctab[2] = - reduloctab[1]; reduloctab[4] = - reduloctab[3]; reduloctab[6] = - reduloctab[5]; reduloctab[8] = - reduloctab[7]; if ((int) proclocnum != grafptr->proclocnum) /* If fragment is not read by proper process */ reduloctab[0] |= 1; if ((int) reduloctab[1] != grafptr->procglbnbr) { errorPrint ("dgraphLoadDist: wrong number of processors to read distributed graph"); reduloctab[0] = 2; } if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 10, 2, grafptr->proccomm) != 0) { errorPrint ("dgraphLoadDist: communication error (1)"); reduglbtab[0] = 2; } if (reduglbtab[0] >= 2) /* If has to abort immediately */ return (1); if ((reduglbtab[2] != - reduglbtab[1]) || (reduglbtab[4] != - reduglbtab[3]) || (reduglbtab[6] != - reduglbtab[5]) || (reduglbtab[8] != - reduglbtab[7])) { errorPrint ("dgraphLoadDist: inconsistent distributed graph headers"); return (1); } if (reduloctab[0] == 1) errorPrint ("dgraphLoadDist: distributed graph file not read by proper process"); if (reduglbtab[0] != 0) /* If cannot go on anyway */ return (1); if ((reduglbtab[10] != reduloctab[3]) || (reduglbtab[11] != reduloctab[5])) errorPrint ("dgraphLoadDist: bad input (2)"); if ((reduglbtab[10] != reduglbtab[3]) || (reduglbtab[11] != reduglbtab[5])) return (1); if (baseval == -1) { /* If keep file graph base */ baseval = reduglbtab[7]; /* Set graph base as file base */ baseadj = 0; /* No base adjustment needed */ } else /* If set graph base */ baseadj = baseval - reduglbtab[7]; /* Update base adjust */ vertlocnbr = reduloctab[10]; edgelocnbr = reduloctab[11]; sprintf (proptab, "%3.3d", (int) reduglbtab[9]); /* Compute file properties */ proptab[0] -= '0'; /* Vertex labels flag */ proptab[1] -= '0'; /* Edge weights flag */ proptab[2] -= '0'; /* Vertex loads flag */ velolocnbr = ((proptab[2] != 0) && ((flagval & GRAPHIONOLOADVERT) == 0)) ? vertlocnbr : 0; vlbllocnbr = (proptab[0] != 0) ? vertlocnbr : 0; vlblloctax = veloloctax = vertloctax = edgeloctax = NULL; cheklocval = 0; if ((vertlocptr = memAlloc ((vertlocnbr + 1 + velolocnbr + vlbllocnbr) * sizeof (Gnum))) == NULL) { errorPrint ("dgraphLoadDist: out of memory (1)"); cheklocval = 1; } else { Gnum edlolocnbr; vertloctax = vertlocptr -= baseval; vertlocptr += vertlocnbr + 1; if ((proptab[2] != 0) && ((flagval & GRAPHIONOLOADVERT) == 0)) { veloloctax = vertlocptr; vertlocptr += vertlocnbr; } if (proptab[0] != 0) { vlblloctax = vertlocptr; baseadj = 0; /* No vertex adjustments if vertex labels */ } edlolocnbr = ((proptab[1] != 0) && ((flagval & GRAPHIONOLOADEDGE) == 0)) ? edgelocnbr : 0; if ((edgeloctax = memAlloc ((edgelocnbr + edlolocnbr) * sizeof (Gnum))) == NULL) { errorPrint ("dgraphLoadDist: out of memory (2)"); cheklocval = 1; } else { edgeloctax -= baseval; edloloctax = ((proptab[1] != 0) && ((flagval & GRAPHIONOLOADEDGE) == 0)) ? (edgeloctax + edgelocnbr) : NULL; } } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphLoadDist: communication error (2)"); chekglbval = 1; } if (chekglbval != 0) { if (edgeloctax != NULL) memFree (edgeloctax + baseval); if (vertloctax != NULL) memFree (vertloctax + baseval); return (1); } degrlocmax = 0; /* No maximum degree yet */ velolocsum = (veloloctax != NULL) ? 0 : vertlocnbr; for (vertlocnum = edgelocnum = baseval, vertlocnnd = vertlocnbr + baseval, edgelocnnd = edgelocnbr + baseval; vertlocnum < vertlocnnd; vertlocnum ++) { Gnum degrlocval; if (vlblloctax != NULL) { /* If must read label */ Gnum vlbllocval; /* Vertex label value to be read */ if (intLoad (stream, &vlbllocval) != 1) { /* Read label data */ errorPrint ("dgraphLoadDist: bad input (2)"); cheklocval = 1; break; } vlblloctax[vertlocnum] = vlbllocval; } if (proptab[2] != 0) { /* If must read vertex load */ Gnum velolocval; if (intLoad (stream, &velolocval) != 1) { /* Read vertex load data */ errorPrint ("dgraphLoadDist: bad input (3)"); cheklocval = 1; break; } if (veloloctax != NULL) velolocsum += veloloctax[vertlocnum] = velolocval; } if (intLoad (stream, °rlocval) != 1) { /* Read vertex degree */ errorPrint ("dgraphLoadDist: bad input (4)"); cheklocval = 1; break; } if (degrlocmax < degrlocval) /* Set maximum degree */ degrlocmax = degrlocval; vertloctax[vertlocnum] = edgelocnum; /* Set index in edge array */ degrlocval += edgelocnum; if (degrlocval > edgelocnnd) { /* Check if edge array overflows */ errorPrint ("dgraphLoadDist: invalid arc count (1)"); cheklocval = 1; break; } for ( ; edgelocnum < degrlocval; edgelocnum ++) { Gnum edgelocval; /* Value where to read edge end */ if (proptab[1] != 0) { /* If must read edge load */ Gnum edlolocval; /* Value where to read edge load */ if (intLoad (stream, &edlolocval) != 1) { /* Read edge load data */ errorPrint ("dgraphLoadDist: bad input (5)"); cheklocval = 1; break; } if (edloloctax != NULL) edloloctax[edgelocnum] = edlolocval; } if (intLoad (stream, &edgelocval) != 1) { /* Read edge data */ errorPrint ("dgraphLoadDist: bad input (6)"); cheklocval = 1; break; } edgeloctax[edgelocnum] = edgelocval + baseadj; } if (cheklocval != 0) break; } vertloctax[vertlocnum] = edgelocnum; /* Set end of edge array */ if (edgelocnum != edgelocnnd) { /* Check if number of edges is valid */ errorPrint ("dgraphLoadDist: invalid arc count (2)"); cheklocval = 1; } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphLoadDist: communication error (17)"); chekglbval = 1; } if (chekglbval != 0) { memFree (edgeloctax + baseval); memFree (vertloctax + baseval); return (1); } o = dgraphBuild2 (grafptr, baseval, /* Build distributed graph */ vertlocnbr, vertlocnbr, vertloctax, vertloctax + 1, veloloctax, velolocsum, NULL, vlblloctax, edgelocnbr, edgelocnbr, edgeloctax, NULL, edloloctax, degrlocmax); grafptr->flagval |= DGRAPHFREETABS | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; return (o); } /* This routine loads a distributed source ** graph from a centralized source graph ** file replicated on all of the streams. ** It returns: ** - 0 : on success. ** - !0 : on error. */ static int dgraphLoadMulti ( Dgraph * restrict const grafptr, /* Distributed graph to load */ FILE * const stream, /* One single centralized stream */ Gnum baseval, /* Base value (-1 means keep file base) */ const DgraphFlag flagval) /* Graph loading flags */ { errorPrint ("dgraphLoadMulti: not implemented"); return (1); } scotch-5.1.12b.dfsg/src/libscotch/library_graph_io_habo.c0000644000175300017530000000677511631334325023623 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_io_habo.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the Harwell- **/ /** Boeing geometry and graph handling **/ /** routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 4.0 : from : 18 nov 2003 **/ /** to 19 jan 2004 **/ /** # Version 5.1 : from : 27 apr 2010 **/ /** to 27 apr 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "geom.h" #include "graph.h" #include "scotch.h" /*************************************/ /* */ /* These routines are the C API for */ /* the Harwell-Boeing geometry */ /* handling routines. */ /* */ /*************************************/ /*+ This routine loads the given opaque geom *** structure with the data of the given stream. *** - 0 : if loading succeeded. *** - !0 : on error. +*/ int SCOTCH_graphGeomLoadHabo ( SCOTCH_Graph * restrict const grafptr, SCOTCH_Geom * restrict const geomptr, FILE * const filegrfptr, FILE * const filegeoptr, const char * const dataptr) { return (graphGeomLoadHabo ((Graph *) grafptr, (Geom *) geomptr, filegrfptr, filegeoptr, dataptr)); } scotch-5.1.12b.dfsg/src/libscotch/parser.h0000644000175300017530000002610311631334325020602 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : parser.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the declarations for **/ /** the strategy lexical and syntactic **/ /** analyzer. **/ /** **/ /** DATES : # Version 3.1 : from : 07 nov 1995 **/ /** to 02 may 1996 **/ /** # Version 3.2 : from : 07 oct 1996 **/ /** to 19 oct 1996 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 20 dec 2001 **/ /** to 11 jun 2004 **/ /** # Version 5.1 : from : 20 feb 2008 **/ /** to 20 feb 2008 **/ /** **/ /************************************************************/ /* ** The defines. */ #define PARSERSTRINGLEN 256 /*+ Length of parser strings +*/ /* ** The type definitions. */ /*+ Strategy node types. +*/ typedef enum StratNodeType_ { STRATNODECONCAT, /*+ Concatenation node +*/ STRATNODECOND, /*+ Condition node +*/ STRATNODEEMPTY, /*+ Empty strategy +*/ STRATNODEMETHOD, /*+ Method +*/ STRATNODESELECT, /*+ Selection node +*/ STRATNODENBR /*+ Number of strategy nodes +*/ } StratNodeType; /*+ Method and graph parameter types. +*/ typedef enum StratParamType_ { STRATPARAMCASE = 0, /*+ Character; TRICK: FIRST +*/ STRATPARAMDOUBLE, /*+ Double floating-point +*/ STRATPARAMINT, /*+ Integer +*/ STRATPARAMLOG, /*+ Logical value +*/ STRATPARAMSTRAT, /*+ Strategy +*/ STRATPARAMSTRING /*+ String of characters +*/ } StratParamType; /*+ Test types, ordered by ascending priority, for proper writing of parentheses. Initial value should be zero for proper indexing. +*/ typedef enum StratTestType_ { STRATTESTOR = 0, /*+ Or operator +*/ STRATTESTAND, /*+ And operator +*/ STRATTESTNOT, /*+ Not operator +*/ STRATTESTEQ, /*+ Equal-to operator +*/ STRATTESTGT, /*+ Greater-than operator +*/ STRATTESTLT, /*+ Less-than operator +*/ STRATTESTADD, /*+ Addition operator +*/ STRATTESTSUB, /*+ Subtraction operator +*/ STRATTESTMUL, /*+ Multiplication operator +*/ STRATTESTMOD, /*+ Modulus operator +*/ STRATTESTVAL, /*+ Constant value +*/ STRATTESTVAR, /*+ Variable +*/ STRATTESTNBR /*+ Number of test nodes +*/ } StratTestType; /*+ Method characteristics. +*/ typedef struct StratMethodTab_ { int meth; /*+ Method number in method table +*/ char * name; /*+ Method name +*/ int (* func) (); /*+ Pointer to bipartitioning method +*/ void * data; /*+ Pointer to default parameters +*/ } StratMethodTab; /*+ Method parameter characteristics. +*/ typedef struct StratParamTab_ { int meth; /*+ Method number in method table +*/ StratParamType type; /*+ Parameter type +*/ char * name; /*+ Parameter name +*/ byte * database; /*+ Pointer to data base in method +*/ byte * dataofft; /*+ Pointer to data offset in method +*/ void * datasltr; /*+ Pointer to data selector +*/ } StratParamTab; /*+ Strategy characteristics. +*/ typedef struct StratTab_ { StratMethodTab * methtab; /*+ Pointer to method table +*/ StratParamTab * paratab; /*+ Pointer to parameter table +*/ StratParamTab * condtab; /*+ Pointer to condition table +*/ } StratTab; /*+ Concatenation strategy node. +*/ typedef struct StratNodeConcat_ { /*+ Concatenation node +*/ struct Strat_ * strat[2]; /*+ Pointers to the two strategies to combine +*/ } StratNodeConcat; /*+ Condition and test strategy nodes. +*/ typedef union StratTestVal_ { /*+ Constant value +*/ double valdbl; /*+ Double value +*/ INT valint; /*+ Integer value +*/ int vallog; /*+ Logical value +*/ } StratTestVal; typedef struct StratTestVar_ { /*+ Condition variable +*/ const StratTab * datatab; /*+ Pointer to data parameter table +*/ int datadisp; /*+ Displacement with respect to beginning +*/ } StratTestVar; typedef struct StratTest_ { /*+ Test node +*/ StratTestType typetest; /*+ Test type +*/ StratParamType typenode; /*+ Node type +*/ union { struct StratTest_ * test[2]; /*+ Logical/relational branches +*/ StratTestVal val; /*+ Value +*/ StratTestVar var; /*+ Variable +*/ } data; } StratTest; typedef struct StratNodeCond_ { /*+ Test node +*/ StratTest * test; /*+ Test condition +*/ struct Strat_ * strat[2]; /*+ Then/else strategies +*/ } StratNodeCond; /*+ Data structure of the empty strategy operator node. +*/ typedef struct StratNodeEmpty_ { /*+ Empty node +*/ byte dummy; /*+ Dummy data +*/ } StratNodeEmpty; /*+ Data structure of the empty strategy operator node. +*/ typedef double StratNodeMethodData[10]; /*+ Reserved padded space for method data */ typedef struct StratNodeMethod_ { /*+ Method node +*/ int meth; /*+ Index in method table +*/ StratNodeMethodData data; /*+ Method data +*/ } StratNodeMethod; /*+ Data structure of the selection strategy operator node. +*/ typedef struct StratNodeSelect_ { /*+ Selection node +*/ struct Strat_ * strat[2]; /*+ Pointers to the two strategies to test +*/ } StratNodeSelect; /*+ The strategy node data structure. +*/ typedef struct Strat_ { const StratTab * tabl; /*+ Pointer to parsing strategy table +*/ StratNodeType type; /*+ Method type +*/ union { /*+ Method data +*/ double padding; /*+ Padding for double alignment +*/ StratNodeConcat concat; /*+ Concatenation node data +*/ StratNodeCond cond; /*+ Condition node data +*/ StratNodeEmpty empty; /*+ Empty node data +*/ StratNodeMethod method; /*+ Method node data +*/ StratNodeSelect select; /*+ Selection node data +*/ } data; } Strat; /* ** The external declarations. */ extern Strat stratdummy; /*+ Dummy empty strategy node +*/ /* ** The function prototypes. */ #ifndef PARSER #define static #endif Strat * stratInit (const StratTab * const , const char * const); int stratExit (Strat * const); int stratSave (const Strat * const, FILE * const); int stratTestEval (const StratTest * const, StratTest * const, const void * const); static int stratTestEvalCast (StratTest * const, StratTest * const); int stratTestExit (StratTest * const); int stratTestSave (const StratTest * const, FILE * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/graph_induce.h0000644000175300017530000000670011631334325021737 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_induce.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the source graph sub-graph making **/ /** functions. **/ /** **/ /** DATES : # Version 0.0 : from : 02 dec 1992 **/ /** to 18 may 1993 **/ /** # Version 1.3 : from : 30 apr 1994 **/ /** to 18 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 18 aug 1994 **/ /** # Version 3.0 : from : 07 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 28 nov 1995 **/ /** to 28 nov 1995 **/ /** # Version 3.2 : from : 07 sep 1996 **/ /** to 17 sep 1998 **/ /** # Version 4.0 : from : 28 nov 2001 **/ /** to 28 nov 2001 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef GRAPH_INDUCE #define static #endif static int graphInduce2 (const Graph * const, Graph * const, const Gnum, const Gnum, Gnum * const, const Gnum * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/graph_io_scot.c0000644000175300017530000003043011631334325022117 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_io_scot.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the I/O routines **/ /** for handling the Scotch graph format. **/ /** **/ /** DATES : # Version 3.2 : from : 06 nov 1997 **/ /** to 26 may 1998 **/ /** # Version 3.3 : from : 13 dec 1998 **/ /** to 21 dec 1998 **/ /** # Version 4.0 : from : 18 dec 2001 **/ /** to 22 dec 2005 **/ /** # Version 5.0 : from : 13 sep 2006 **/ /** to 27 feb 2008 **/ /** # Version 5.1 : from : 11 aug 2010 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GRAPH_IO_SCOT #include "module.h" #include "common.h" #include "geom.h" #include "graph.h" #include "graph_io_scot.h" /* This routine loads the geometrical graph ** in the Scotch graph format, and allocates ** the proper structures. ** - 0 : on success. ** - !0 : on error. */ int graphGeomLoadScot ( Graph * restrict const grafptr, /* Graph to load */ Geom * restrict const geomptr, /* Geometry to load */ FILE * const filesrcptr, /* Topological data */ FILE * const filegeoptr, /* No use */ const char * const dataptr) /* No use */ { void * coorfileptr; /* Temporary pointer to comply with C99 rules */ double * restrict coorfiletab; /* Pointer to geometric data read from file */ GraphGeomScotSort * restrict coorsorttab; /* Pointer to geometric data sorting array */ int coorsortflag; /* Flag set if geometric data sorted by label */ Gnum coornbr; /* Number of geometric coordinates in file */ Gnum coornum; /* Number of current coordinate */ GraphGeomScotSort * restrict vertsorttab; /* Pointer to graph sorting array */ int vertsortflag; /* Flag set if graph data sorted by label */ Gnum vertnum; /* Current graph vertex */ Gnum dimnnbr; /* Dimension of geometry file */ int o; if (filesrcptr != NULL) { if (graphLoad (grafptr, filesrcptr, -1, 0) != 0) return (1); } if (filegeoptr == NULL) return (0); if ((intLoad (filegeoptr, &dimnnbr) != 1) || /* Read type and number of geometry items */ (intLoad (filegeoptr, &coornbr) != 1) || (dimnnbr < 1) || (dimnnbr > 3)) { errorPrint ("graphGeomLoadScot: bad input (1)"); return (1); } if ((filesrcptr != NULL) && (grafptr->vertnbr != coornbr)) { errorPrint ("graphGeomLoadScot: inconsistent number of vertices"); return (1); } if (grafptr->vertnbr == 0) return (0); if ((geomptr->geomtab == NULL) && /* Allocate geometry if necessary */ ((geomptr->geomtab = (double *) memAlloc (grafptr->vertnbr * dimnnbr * sizeof (double))) == NULL)) { errorPrint ("graphGeomLoadScot: out of memory (1)"); return (1); } if (memAllocGroup ((void **) &coorfileptr, (size_t) (coornbr * dimnnbr * sizeof (double)), &coorsorttab, (size_t) (coornbr * sizeof (GraphGeomScotSort)), &vertsorttab, (size_t) (grafptr->vertnbr * sizeof (GraphGeomScotSort)), NULL) == NULL) { errorPrint ("graphGeomLoadScot: out of memory (2)"); return (1); } coorfiletab = coorfileptr; o = 0; coorsortflag = 1; /* Assume geometry data sorted */ for (coornum = 0; (o == 0) && (coornum < coornbr); coornum ++) { Gnum vlblnum; o = 1 - intLoad (filegeoptr, &vlblnum); coorsorttab[coornum].labl = vlblnum; coorsorttab[coornum].num = coornum; if ((coornum > 0) && /* Check if geometry data sorted */ (coorsorttab[coornum].labl < coorsorttab[coornum - 1].labl)) coorsortflag = 0; /* Geometry data not sorted */ o |= 1 - fscanf (filegeoptr, "%lf", /* Read X coordinate */ &coorfiletab[coornum * dimnnbr]); if (dimnnbr > 1) { o |= 1 - fscanf (filegeoptr, "%lf", /* Read Y coordinate */ &coorfiletab[(coornum * dimnnbr) + 1]); if (dimnnbr > 2) o |= 1 - fscanf (filegeoptr, "%lf", /* Read Z coordinate */ &coorfiletab[(coornum * dimnnbr) + 2]); } } if (o != 0) { errorPrint ("graphGeomLoadScot: bad input (2)"); memFree (coorfiletab); /* Free group leader */ return (1); } if (coorsortflag != 1) /* If geometry data not sorted */ intSort2asc1 (coorsorttab, coornbr); /* Sort sort area by ascending labels */ for (coornum = 1; coornum < coornbr; coornum ++) { /* Check geometric data integrity */ if (coorsorttab[coornum].labl == coorsorttab[coornum - 1].labl) { errorPrint ("graphGeomLoadScot: duplicate vertex label"); memFree (coorfiletab); /* Free group leader */ return (1); } } if (grafptr->vlbltax != NULL) { /* If graph has vertex labels */ vertsortflag = 1; /* Assume graph data sorted */ for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { vertsorttab[vertnum].labl = grafptr->vlbltax[vertnum + grafptr->baseval]; vertsorttab[vertnum].num = vertnum; if ((vertnum > 0) && /* Check if graph data sorted */ (vertsorttab[vertnum].labl < vertsorttab[vertnum - 1].labl)) vertsortflag = 0; /* Graph data not sorted */ } if (vertsortflag != 1) /* If graph data not sorted */ intSort2asc1 (vertsorttab, grafptr->vertnbr); /* Sort sort area by ascending labels */ } else { /* Graph does not have vertex labels */ for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) vertsorttab[vertnum].labl = vertsorttab[vertnum].num = vertnum; } for (coornum = vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { /* For all vertices in graph */ while ((coornum < coornbr) && (coorsorttab[coornum].labl < vertsorttab[vertnum].labl)) coornum ++; /* Search geometry vertex with same label */ if ((coornum >= coornbr) || (coorsorttab[coornum].labl > vertsorttab[vertnum].labl)) { /* If label does not exist */ errorPrint ("graphGeomLoadScot: vertex geometry data not found (%d)", vertsorttab[vertnum].labl); memFree (coorfiletab); /* Free group leader */ return (1); } memCpy (&geomptr->geomtab[vertsorttab[vertnum].num * dimnnbr], &coorfiletab[coorsorttab[coornum ++].num * dimnnbr], dimnnbr * sizeof (double)); } memFree (coorfiletab); /* Free group leader */ return (0); } /* This routine saves the source process graph ** in the Scotch source and geometry formats. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int graphGeomSaveScot ( const Graph * restrict const grafptr, /* Graph to save */ const Geom * restrict const geomptr, /* Geometry to save */ FILE * const filesrcptr, /* Topological data */ FILE * const filegeoptr, /* No use */ const char * const dataptr) /* No use */ { Gnum vertnum; int dimnnbr; int o; if (filesrcptr != NULL) { if (graphSave (grafptr, filesrcptr) != 0) /* Save graph structural data */ return (1); } dimnnbr = geomptr->dimnnbr; o = 0; if (geomptr->geomtab != NULL) { /* If geometrical data present */ o = (fprintf (filegeoptr, GNUMSTRING "\n" GNUMSTRING "\n", /* Output file header */ (Gnum) geomptr->dimnnbr, (Gnum) grafptr->vertnbr) == EOF); switch (dimnnbr) { /* Output geometry data */ case 1 : for (vertnum = grafptr->baseval; (o == 0) && (vertnum < grafptr->vertnnd); vertnum ++) o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\n", (Gnum) ((grafptr->vlbltax != NULL) ? grafptr->vlbltax[vertnum] : vertnum), (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr]) == EOF); break; case 2 : for (vertnum = grafptr->baseval; (o == 0) && (vertnum < grafptr->vertnnd); vertnum ++) o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\t%lf\n", (Gnum) ((grafptr->vlbltax != NULL) ? grafptr->vlbltax[vertnum] : vertnum), (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr], (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr + 1]) == EOF); break; case 3 : for (vertnum = grafptr->baseval; (o == 0) && (vertnum < grafptr->vertnnd); vertnum ++) o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\t%lf\t%lf\n", (Gnum) ((grafptr->vlbltax != NULL) ? grafptr->vlbltax[vertnum] : vertnum), (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr], (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr + 1], (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr + 2]) == EOF); break; #ifdef SCOTCH_DEBUG_GRAPH2 default : errorPrint ("graphGeomSaveScot: invalid geometry type"); return (1); #endif /* SCOTCH_DEBUG_GRAPH2 */ } if (o != 0) { errorPrint ("graphGeomSaveScot: bad output"); } } return (o); } scotch-5.1.12b.dfsg/src/libscotch/library_parser_f.c0000644000175300017530000001076511631334325022635 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_parser_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** strategy handling routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 4.0 : from : 17 jan 2004 **/ /** to 17 mar 2005 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 27 mar 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "parser.h" #include "scotch.h" /***************************************/ /* */ /* These routines are the Fortran API */ /* for the ordering handling routines. */ /* */ /***************************************/ FORTRAN ( \ SCOTCHFSTRATINIT, scotchfstratinit, ( \ SCOTCH_Strat * const stratptr, \ int * const revaptr), \ (stratptr, revaptr)) { *revaptr = SCOTCH_stratInit (stratptr); } /* ** */ FORTRAN ( \ SCOTCHFSTRATEXIT, scotchfstratexit, ( \ SCOTCH_Strat * const stratptr), \ (stratptr)) { SCOTCH_stratExit (stratptr); } /* ** */ FORTRAN ( \ SCOTCHFSTRATSAVE, scotchfstratsave, ( \ const SCOTCH_Strat * const stratptr, \ int * const fileptr, \ int * const revaptr), \ (stratptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFSTRATSAVE: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFSTRATSAVE: cannot open output stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_stratSave (stratptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } scotch-5.1.12b.dfsg/src/libscotch/graph_coarsen_edge.c0000644000175300017530000001436011631334325023102 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_coarsen_edge.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This commodity file contains the edge **/ /** arrays building subroutine which is **/ /** duplicated, with minor modifications, **/ /** into graph_coarsen.c. **/ /** **/ /** DATES : # Version 4.0 : from : 17 dec 2001 **/ /** to 25 feb 2004 **/ /** # Version 5.0 : from : 13 dec 2006 **/ /** to 14 dec 2006 **/ /** # Version 5.1 : from : 30 oct 2009 **/ /** to 30 oct 2009 **/ /** **/ /************************************************************/ static void GRAPHCOARSENEDGENAME ( const Graph * restrict const finegrafptr, /*+ Graph to coarsen +*/ const Gnum * restrict const finecoartax, /*+ Fine to coarse array +*/ const GraphCoarsenMulti * restrict const coarmulttax, /*+ Multinode array +*/ Graph * restrict const coargrafptr, /*+ Coarse graph to build +*/ GraphCoarsenHash * restrict const coarhashtab, /*+ End vertex hash table +*/ const Gnum coarhashmsk) /*+ Hash table mask +*/ { Gnum coarvertnum; Gnum coaredgenum; Gnum coardegrmax; Gnum coaredlosum; Gnum * restrict const coarverttax = coargrafptr->verttax; Gnum * restrict const coaredgetax = coargrafptr->edgetax; Gnum * restrict const coaredlotax = coargrafptr->edlotax; const Gnum * restrict const fineverttax = finegrafptr->verttax; const Gnum * restrict const finevendtax = finegrafptr->vendtax; const Gnum * restrict const fineedgetax = finegrafptr->edgetax; GRAPHCOARSENEDGEINIT; coaredlosum = 0; for (coarvertnum = coaredgenum = coargrafptr->baseval, coardegrmax = 0; coarvertnum < coargrafptr->vertnnd; coarvertnum ++) { Gnum finevertnum; int i; coarverttax[coarvertnum] = coaredgenum; /* Set vertex edge index */ i = 0; do { /* For all fine edges of multinode vertices */ Gnum fineedgenum; finevertnum = coarmulttax[coarvertnum].vertnum[i]; for (fineedgenum = fineverttax[finevertnum]; fineedgenum < finevendtax[finevertnum]; fineedgenum ++) { Gnum coarvertend; /* Number of coarse vertex which is end of fine edge */ Gnum h; coarvertend = finecoartax[fineedgetax[fineedgenum]]; if (coarvertend != coarvertnum) { /* If not end of collapsed edge */ for (h = (coarvertend * GRAPHCOARHASHPRIME) & coarhashmsk; ; h = (h + 1) & coarhashmsk) { if (coarhashtab[h].vertorgnum != coarvertnum) { /* If old slot */ coarhashtab[h].vertorgnum = coarvertnum; /* Mark it in reference array */ coarhashtab[h].vertendnum = coarvertend; coarhashtab[h].edgenum = coaredgenum; coaredgetax[coaredgenum] = coarvertend; /* One more edge created */ GRAPHCOARSENEDGEEDLOINIT; /* Initialize edge load entry */ coaredgenum ++; break; /* Give up hashing */ } if (coarhashtab[h].vertendnum == coarvertend) { /* If coarse edge already exists */ GRAPHCOARSENEDGEEDLOADD; /* Accumulate edge load */ break; /* Give up hashing */ } } } else GRAPHCOARSENEDGEEDLOSUB; } } while (i ++, finevertnum != coarmulttax[coarvertnum].vertnum[1]); /* Skip to next matched vertex if both vertices not equal */ if (coardegrmax < (coaredgenum - coarverttax[coarvertnum])) coardegrmax = coaredgenum - coarverttax[coarvertnum]; } coarverttax[coarvertnum] = coaredgenum; /* Mark end of edge array */ coargrafptr->edlosum = finegrafptr->edlosum + coaredlosum; /* Subtract all matched edges */ coargrafptr->degrmax = coardegrmax; } scotch-5.1.12b.dfsg/src/libscotch/arch_build.c0000644000175300017530000004712611631334325021405 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_build.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Sebastien FOURESTIER **/ /** **/ /** FUNCTION : This module builds a decomposition- **/ /** based architecture from a source graph. **/ /** **/ /** DATES : # Version 3.2 : from : 29 may 1997 **/ /** to 30 aug 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 3.4 : from : 30 oct 2001 **/ /** to 08 nov 2001 **/ /** # Version 4.0 : from : 29 nov 2003 **/ /** to 10 mar 2005 **/ /** # Version 5.0 : from : 10 sep 2007 **/ /** to 03 apr 2008 **/ /** # Version 5.1 : from : 28 sep 2008 **/ /** to 28 jun 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ARCH_BUILD #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "arch.h" #include "arch_deco.h" #include "arch_vcmplt.h" #include "mapping.h" #include "bgraph.h" #include "bgraph_bipart_st.h" #include "arch_build.h" /************************************/ /* */ /* These routines handle job pools. */ /* */ /************************************/ /* This routine frees the contents of ** the given job pool. ** It returns: ** - VOID : in all cases. */ static void archBuildJobExit ( ArchBuildJob * const jobtab) { ArchBuildJob * jobptr; jobptr = jobtab; do { graphExit (&jobptr->grafdat); jobptr = jobptr->joblink; } while (jobptr != NULL); } /********************************************/ /* */ /* The main routine, which computes the */ /* decomposition-based target architecture. */ /* */ /********************************************/ /* ** This routine builds a target architecture from ** the given source graph and the optional vertex ** list. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archBuild ( Arch * restrict const tgtarchptr, /*+ Decomposition architecture to build +*/ const Graph * const tgtgrafptr, /*+ Source graph modeling the architecture +*/ const VertList * const tgtlistptr, /*+ Subset of source graph vertices +*/ const Strat * const mapstrat) /*+ Bipartitioning strategy +*/ { Gnum * restrict mapparttax; /* Based access to mapping part array */ ArchDom domsub0; /* Temporary space for subdomain 0 */ Gnum termdomnbr; /* Number of terminal domains */ Gnum termdommax; /* Maximum terminal number */ ArchDecoTermVert * restrict termverttab; /* Terminal vertex table */ Anum * restrict termdisttab; /* Vertex distance table */ ArchBuildDistElem * restrict disttax; /* Distance table */ ArchBuildQueuElem * restrict queutab; /* Distance queue table */ Gnum queuhead; /* Head-of-queue index */ Gnum queutail; /* Tail-of-queue index */ Mapping mappdat; /* Partial and final mapping data */ ArchBuildJob * restrict jobtab; /* Job array */ ArchBuildJob * joblink; /* Linked list of jobs to process */ ArchBuildJob * joborgptr; /* Pointer to original job and first subjob */ ArchBuildJob * jobsubptr; /* Pointer to second subjob */ Bgraph actgrafdat; /* Active graph for bipartitioning */ Gnum invedlosiz; /* Size of inversed edge load array */ Gnum * restrict invedlotax; /* Inversed edge load array for cutting */ Gnum * restrict actfrontab; /* Frontier array for all bipartitionings */ GraphPart * restrict actparttax; /* Part array for all bipartitionings */ GraphPart actpartval; /* Part value to put to subjob */ Gnum actpartnbr; /* Size of part value to put to subjob */ Gnum termdomnum; const Gnum * restrict const tgtverttax = tgtgrafptr->verttax; const Gnum * restrict const tgtvendtax = tgtgrafptr->vendtax; const Gnum * restrict const tgtedgetax = tgtgrafptr->edgetax; const Gnum * restrict const tgtedlotax = tgtgrafptr->edlotax; archInit (tgtarchptr); /* Initialize architecture body */ tgtarchptr->class = archClass ("deco"); /* Set architecture class */ termdomnbr = (tgtlistptr != NULL) ? tgtlistptr->vnumnbr : tgtgrafptr->vertnbr; if (termdomnbr == 0) /* If nothing to do */ return (0); intRandInit (); /* Initialize random generator */ invedlosiz = (tgtedlotax != NULL) ? tgtgrafptr->edgenbr : 0; if ((memAllocGroup ((void **) (void *) &jobtab, (size_t) (termdomnbr * sizeof (ArchBuildJob)), &actfrontab, (size_t) (termdomnbr * sizeof (Gnum)), &actparttax, (size_t) (termdomnbr * sizeof (GraphPart)), &invedlotax, (size_t) (invedlosiz * sizeof (Gnum)), NULL) == NULL) || ((mappdat.parttax = memAlloc (tgtgrafptr->vertnbr * sizeof (ArchDomNum))) == NULL) || /* Final mapping array is for all graph vertices */ ((mappdat.domntab = memAlloc (termdomnbr * sizeof (ArchDom))) == NULL)) { errorPrint ("archBuild: out of memory (1)"); if (jobtab != NULL) { memFree (jobtab); if (mappdat.parttax != NULL) memFree (mappdat.parttax); } return (1); } memSet (mappdat.parttax, 0, termdomnbr * sizeof (ArchDomNum)); actparttax -= tgtgrafptr->baseval; mappdat.baseval = tgtgrafptr->baseval; mappdat.vertnbr = termdomnbr; mappdat.parttax -= tgtgrafptr->baseval; mappdat.domnmax = termdomnbr; archInit (&mappdat.archdat); /* Initialize terminal architecture */ mappdat.archdat.class = archClass ("varcmplt"); /* Set architecture class */ archDomFrst (&mappdat.archdat, &mappdat.domntab[0]); /* Get initial domain */ mappdat.domnnbr = 1; jobtab[0].domnum = 0; /* All vertices mapped to first domain */ if ((tgtlistptr != NULL) && (tgtlistptr->vnumtab != NULL)) /* If vertex list given */ graphInduceList (tgtgrafptr, tgtlistptr, &jobtab[0].grafdat); /* Restrict initial job */ else { /* If no vertex list given */ memCpy (&jobtab[0].grafdat, tgtgrafptr, sizeof (Graph)); /* Job takes whole graph */ jobtab[0].grafdat.flagval &= ~GRAPHFREETABS; /* Graph is a clone */ } if (tgtedlotax != NULL) { /* If architecture graph has edge loads */ Gnum vertnum; Gnum vertnnd; Gnum edlomin; Gnum edlomax; float prodval; const Gnum * restrict const indverttax = jobtab[0].grafdat.verttax; const Gnum * restrict const indvendtax = jobtab[0].grafdat.vendtax; const Gnum * restrict const indedlotax = jobtab[0].grafdat.edlotax; /* Point to possibly induced original edge array */ invedlotax -= tgtgrafptr->baseval; /* Base inversed edge load array */ edlomin = GNUMMAX; edlomax = 1; for (vertnum = jobtab[0].grafdat.baseval, vertnnd = jobtab[0].grafdat.vertnnd; /* Handle non-compact graphs as well as compact graphs */ vertnum < vertnnd; vertnum ++) { Gnum edgenum; Gnum edgennd; for (edgenum = indverttax[vertnum], edgennd = indvendtax[vertnum]; edgenum < edgennd; edgenum ++) { Gnum edloval; edloval = indedlotax[edgenum]; if (edloval < edlomin) edlomin = edloval; if (edloval > edlomax) edlomax = edloval; } } prodval = (float) edlomin * (float) edlomax; for (vertnum = jobtab[0].grafdat.baseval; vertnum < vertnnd; vertnum ++) { Gnum edgenum; Gnum edgennd; for (edgenum = indverttax[vertnum], edgennd = indvendtax[vertnum]; edgenum < edgennd; edgenum ++) { Gnum edloval; edloval = indedlotax[edgenum]; if (edloval == edlomin) edloval = edlomax; else if (edloval == edlomax) edloval = edlomin; else edloval = (Gnum) (prodval / (float) edloval + 0.49F); #ifdef SCOTCH_DEBUG_ARCH2 if ((edloval < edlomin) || (edloval > edlomax)) { errorPrint ("archBuild: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_ARCH2 */ invedlotax[edgenum] = edloval; /* Write inversed cost in working array */ } } jobtab[0].grafdat.edlotax = invedlotax; /* Replace potentially induced edge array with inversed one */ } /* Edge array will be freed along with jobtab group leader */ mapparttax = mappdat.parttax; actgrafdat.veextax = NULL; /* No external gain array */ actgrafdat.parttax = actparttax; /* Set global auxiliary arrays */ actgrafdat.frontab = actfrontab; joblink = NULL; /* Initialize job list */ if (jobtab[0].grafdat.vertnbr > 1) { /* If job is worth bipartitioning */ jobtab[0].joblink = joblink; /* Add initial job to list */ joblink = &jobtab[0]; } while (joblink != NULL) { /* For all jobs in list */ joborgptr = joblink; /* Get job */ joblink = joblink->joblink; /* Remove job from list */ joborgptr->joblink = NULL; /* In case of freeing */ memCpy (&actgrafdat.s, &joborgptr->grafdat, sizeof (Graph)); actgrafdat.s.flagval = joborgptr->grafdat.flagval & ~GRAPHFREETABS; bgraphInit2 (&actgrafdat, 1, 1, 1); /* Create active graph */ if (bgraphBipartSt (&actgrafdat, mapstrat) != 0) { /* Perform bipartitioning */ errorPrint ("archBuild: internal error (2)"); archBuildJobExit (joborgptr); archBuildJobExit (joblink); mapExit (&mappdat); memFree (jobtab); return (1); } if ((actgrafdat.compsize0 == 0) || /* If one of the jobs is empty */ (actgrafdat.compsize0 == actgrafdat.s.vertnbr)) { errorPrint ("archBuild: strategy leads to empty domains"); graphExit (&actgrafdat.s); /* Only free graph part, global arrays kept */ archBuildJobExit (joborgptr); archBuildJobExit (joblink); mapExit (&mappdat); memFree (jobtab); return (1); } archVcmpltDomBipart ((const ArchVcmplt * const) (void *) &mappdat.archdat, /* Update mapping domains */ (const ArchVcmpltDom * const) (void *) &mappdat.domntab[joborgptr->domnum], (ArchVcmpltDom * const) (void *) &domsub0, (ArchVcmpltDom * const) (void *) &mappdat.domntab[mappdat.domnnbr]); mappdat.domntab[joborgptr->domnum] = domsub0; actpartval = actgrafdat.parttax[actgrafdat.s.baseval]; /* Always keep first vertex in sub0 */ actpartnbr = (actpartval == 0) ? actgrafdat.compsize0 : (actgrafdat.s.vertnbr - actgrafdat.compsize0); if (actgrafdat.s.vnumtax != NULL) { /* Update mapping fraction */ Gnum actvertnum; for (actvertnum = actgrafdat.s.baseval; actvertnum < actgrafdat.s.vertnnd; actvertnum ++) { if (actgrafdat.parttax[actvertnum] != actpartval) mappdat.parttax[actgrafdat.s.vnumtax[actvertnum]] = mappdat.domnnbr; } } else { Gnum actvertnum; for (actvertnum = actgrafdat.s.baseval; actvertnum < actgrafdat.s.vertnnd; actvertnum ++) { if (actgrafdat.parttax[actvertnum] != actpartval) mappdat.parttax[actvertnum] = mappdat.domnnbr; } } jobsubptr = jobtab + mappdat.domnnbr; /* Point to new subjob */ jobsubptr->domnum = mappdat.domnnbr ++; /* Build subjobs */ actgrafdat.s.flagval = joborgptr->grafdat.flagval; /* Active is now main copy */ if (actpartnbr < (actgrafdat.s.vertnbr - 1)) { /* If part 1 splittable */ graphInducePart (&actgrafdat.s, actgrafdat.parttax, actgrafdat.s.vertnbr - actpartnbr, 1 - actpartval, &jobsubptr->grafdat); jobsubptr->joblink = joblink; /* Link subjobs in list */ joblink = jobsubptr; } if (actpartnbr > 1) { /* If part 0 splittable */ graphInducePart (&actgrafdat.s, actgrafdat.parttax, actpartnbr, actpartval, &joborgptr->grafdat); joborgptr->joblink = joblink; /* Link subjobs in list */ joblink = joborgptr; } graphExit (&actgrafdat.s); /* Only free graph part, global arrays kept */ } memFree (jobtab); /* Free group leader */ if (memAllocGroup ((void **) (void *) &termverttab, (size_t) (termdomnbr * sizeof (ArchDecoTermVert)), &termdisttab, (size_t) (((termdomnbr * (termdomnbr - 1)) / 2) * sizeof (Anum)), &disttax, (size_t) (tgtgrafptr->vertnbr * sizeof (ArchBuildDistElem)), &queutab, (size_t) (tgtgrafptr->vertnbr * sizeof (ArchBuildQueuElem)), NULL) == NULL) { errorPrint ("archBuild: out of memory (2)"); mapExit (&mappdat); return (1); } for (termdomnum = 0, termdommax = 0; termdomnum < termdomnbr; termdomnum ++) { /* Set terminal vertex array */ Gnum tgtvertnum; tgtvertnum = (tgtlistptr != NULL) ? tgtlistptr->vnumtab[termdomnum] : (termdomnum + tgtgrafptr->baseval); termverttab[termdomnum].labl = tgtvertnum; termverttab[termdomnum].wght = (tgtgrafptr->velotax != NULL) ? tgtgrafptr->velotax[tgtvertnum] : 1; termverttab[termdomnum].num = archDomNum (&mappdat.archdat, mapDomain (&mappdat, tgtvertnum - tgtgrafptr->baseval)); if (termverttab[termdomnum].num > termdommax) /* Find maximum terminal number */ termdommax = termverttab[termdomnum].num; } disttax -= tgtgrafptr->baseval; for (termdomnum = 1; termdomnum < termdomnbr; termdomnum ++) { /* For all active terminal vertices except the first */ Gnum termdomend; Gnum tgtvertnum; for (tgtvertnum = tgtgrafptr->baseval; tgtvertnum < (tgtgrafptr->vertnbr + tgtgrafptr->baseval); tgtvertnum ++) { disttax[tgtvertnum].queued = 0; /* Vertex not queued */ disttax[tgtvertnum].distval = INTVALMAX; /* Assume maximum distance */ } queuhead = /* Reset the queue */ queutail = 0; tgtvertnum = termverttab[termdomnum].labl; queutab[queutail].vertnum = tgtvertnum; /* Insert root vertex */ queutab[queutail ++].distval = 0; disttax[tgtvertnum].queued = 1; /* Mark vertex as queued */ disttax[tgtvertnum].distval = 0; while (queuhead < queutail) { /* As long as there are vertices in queue */ Gnum vertnum; /* Number of current vertex */ Gnum vertdist; /* Current distance value */ Gnum edgenum; vertnum = queutab[queuhead].vertnum; /* Retrieve vertex from queue */ vertdist = queutab[queuhead ++].distval; for (edgenum = tgtverttax[vertnum]; /* For all vertex edges */ edgenum < tgtvendtax[vertnum]; edgenum ++) { Gnum vertend; vertend = tgtedgetax[edgenum]; if (disttax[vertend].queued == 0) { /* If end vertex not queued */ queutab[queutail].vertnum = vertend; /* Queue the vertex */ queutab[queutail ++].distval = disttax[vertend].distval = vertdist + ((tgtedlotax != NULL) ? tgtedlotax[edgenum] : 1); disttax[vertend].queued = 1; /* Mark vertex as queued */ } } } for (termdomend = 0; termdomend < termdomnum; termdomend ++) /* For all previous terminal domains */ termdisttab[((termdomnum * (termdomnum - 1)) / 2) + termdomend] = /* Retrieve distance */ disttax[termverttab[termdomend].labl].distval; } archDecoArchBuild ((ArchDeco *) (void *) &tgtarchptr->data, termdomnbr, termdommax, termverttab, termdisttab); memFree (termverttab); /* Free group leader */ mapExit (&mappdat); return (0); } scotch-5.1.12b.dfsg/src/libscotch/arch_cmpltw.h0000644000175300017530000001251411631334325021612 0ustar hazelscthazelsct/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_cmpltw.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the weighted complete graph target **/ /** architecture functions. **/ /** **/ /** DATES : # Version 5.1 : from : 11 dec 2007 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ The weighted target vertex. They are coded as Gnum rather than as Anum because this array needs to be sorted, by means of the intSort2asc1 routine. +*/ #ifndef GRAPH_H #define Gnum Anum /* Prevent data type to be undefined */ #endif /* GRAPH_H */ typedef struct ArchCmpltwLoad_ { Gnum veloval; /*+ Vertex load +*/ Gnum vertnum; /*+ Vertex index +*/ } ArchCmpltwLoad; /*+ The weighted complete graph definitions. +*/ typedef struct ArchCmpltw_ { Anum vertnbr; /*+ Number of vertices +*/ ArchCmpltwLoad * velotab; /*+ Vertex index array +*/ Anum velosum; /*+ Sum of all weights +*/ } ArchCmpltw; /*+ The weighted domain structure. +*/ typedef struct ArchCmpltwDom_ { Anum vertmin; /*+ Minimum vertex number +*/ Anum vertnbr; /*+ Number of vertices +*/ Anum veloval; /*+ Weight of subdomain +*/ } ArchCmpltwDom; /* ** The function prototypes. */ #ifndef ARCH_CMPLTW #define static #endif int archCmpltwArchBuild (ArchCmpltw * restrict const archptr, const Gnum, const Gnum * restrict const); int archCmpltwArchLoad (ArchCmpltw * restrict const, FILE * restrict const); int archCmpltwArchSave (const ArchCmpltw * const, FILE * restrict const); int archCmpltwArchFree (ArchCmpltw * restrict const); ArchDomNum archCmpltwDomNum (const ArchCmpltw * const, const ArchCmpltwDom * const); int archCmpltwDomTerm (const ArchCmpltw * const, ArchCmpltwDom * restrict const, const ArchDomNum); Anum archCmpltwDomSize (const ArchCmpltw * const, const ArchCmpltwDom * const); Anum archCmpltwDomWght (const ArchCmpltw * const, const ArchCmpltwDom * const); Anum archCmpltwDomDist (const ArchCmpltw * const, const ArchCmpltwDom * const, const ArchCmpltwDom * const); int archCmpltwDomFrst (const ArchCmpltw * const, ArchCmpltwDom * const); int archCmpltwDomLoad (const ArchCmpltw * const, ArchCmpltwDom * const, FILE * const); int archCmpltwDomSave (const ArchCmpltw * const, const ArchCmpltwDom * const, FILE * const); int archCmpltwDomBipart (const ArchCmpltw * const, const ArchCmpltwDom * const, ArchCmpltwDom * restrict const, ArchCmpltwDom * restrict const); #ifdef SCOTCH_PTSCOTCH int archCmpltwDomMpiType (const ArchCmpltw * const, MPI_Datatype * const); #endif /* SCOTCH_PTSCOTCH */ #undef static scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_map.c0000644000175300017530000003622611631334325023136 0ustar hazelscthazelsct/* Copyright 2008-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_map.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted graph mapping routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 5.1 : from : 12 jun 2008 **/ /** to 31 aug 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "parser.h" #include "dgraph.h" #include "arch.h" #include "dmapping.h" #include "kdgraph.h" #include "kdgraph_map_st.h" #include "library_dmapping.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the parallel mapping routines. */ /* */ /************************************/ /*+ This routine initializes an API opaque *** mapping with respect to the given source *** graph and the locations of output parameters. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphMapInit ( const SCOTCH_Dgraph * const grafptr, /*+ Graph to map +*/ SCOTCH_Dmapping * const mappptr, /*+ Mapping structure to initialize +*/ const SCOTCH_Arch * const archptr, /*+ Target architecture used to map +*/ SCOTCH_Num * const termloctab) /*+ Mapping array +*/ { LibDmapping * restrict srcmappptr; #ifdef SCOTCH_DEBUG_LIBRARY1 if (sizeof (SCOTCH_Dmapping) < sizeof (LibDmapping)) { errorPrint ("SCOTCH_dgraphMapInit: internal error"); return (1); } #endif /* SCOTCH_DEBUG_LIBRARY1 */ srcmappptr = (LibDmapping *) mappptr; srcmappptr->termloctab = ((termloctab == NULL) || ((void *) termloctab == (void *) grafptr)) ? NULL : termloctab; return (dmapInit (&srcmappptr->m, (Arch *) archptr)); } /*+ This routine frees an API mapping. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_dgraphMapExit ( const SCOTCH_Dgraph * const grafptr, SCOTCH_Dmapping * const mappptr) { dmapExit (&((LibDmapping *) mappptr)->m); } /*+ This routine saves the contents of *** the given mapping to the given stream. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphMapSave ( const SCOTCH_Dgraph * const grafptr, /*+ Graph to map +*/ const SCOTCH_Dmapping * const mappptr, /*+ Mapping to save +*/ FILE * const stream) /*+ Output stream +*/ { return (dmapSave (&((LibDmapping *) mappptr)->m, (Dgraph *) grafptr, stream)); } /*+ This routine computes a mapping *** of the API mapping structure with *** respect to the given strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphMapCompute ( SCOTCH_Dgraph * const grafptr, /*+ Graph to map +*/ SCOTCH_Dmapping * const mappptr, /*+ Mapping to compute +*/ SCOTCH_Strat * const stratptr) /*+ Mapping strategy +*/ { Kdgraph mapgrafdat; /* Effective mapping graph */ Kdmapping mapmappdat; /* Initial mapping domain */ const Strat * mapstratptr; /* Pointer to mapping strategy */ LibDmapping * restrict srcmappptr; Dgraph * srcgrafptr; int o; srcgrafptr = (Dgraph *) grafptr; srcmappptr = (LibDmapping *) mappptr; #ifdef SCOTCH_DEBUG_DGRAPH2 if (dgraphCheck (srcgrafptr) != 0) { errorPrint ("SCOTCH_dgraphMapCompute: invalid input graph"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (*((Strat **) stratptr) == NULL) { /* Set default mapping strategy if necessary */ ArchDom archdomnorg; archDomFrst (&srcmappptr->m.archdat, &archdomnorg); if (archVar (&srcmappptr->m.archdat)) SCOTCH_stratDgraphClusterBuild (stratptr, 0, srcgrafptr->procglbnbr, 1, 1.0, 0.05); else SCOTCH_stratDgraphMapBuild (stratptr, 0, srcgrafptr->procglbnbr, archDomSize (&srcmappptr->m.archdat, &archdomnorg), 0.05); } mapstratptr = *((Strat **) stratptr); if (mapstratptr->tabl != &kdgraphmapststratab) { errorPrint ("SCOTCH_dgraphMapCompute: not a parallel graph mapping strategy"); return (1); } if (kdgraphInit (&mapgrafdat, srcgrafptr, &srcmappptr->m) != 0) return (1); mapmappdat.mappptr = &srcmappptr->m; if (((o = kdgraphMapSt (&mapgrafdat, &mapmappdat, mapstratptr)) == 0) && /* Perform mapping */ (srcmappptr->termloctab != NULL)) o = dmapTerm (&srcmappptr->m, &mapgrafdat.s, srcmappptr->termloctab); /* Use "&mapgrafdat.s" to take advantage of ghost arrays */ kdgraphExit (&mapgrafdat); return (o); } /*+ This routine computes a mapping of the *** given graph structure onto the given *** target architecture with respect to the *** given strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphMap ( SCOTCH_Dgraph * const grafptr, /*+ Graph to map +*/ const SCOTCH_Arch * const archptr, /*+ Target architecture +*/ SCOTCH_Strat * const stratptr, /*+ Mapping strategy +*/ SCOTCH_Num * const termloctab) /*+ Mapping array +*/ { SCOTCH_Dmapping mappdat; int o; SCOTCH_dgraphMapInit (grafptr, &mappdat, archptr, termloctab); o = SCOTCH_dgraphMapCompute (grafptr, &mappdat, stratptr); SCOTCH_dgraphMapExit (grafptr, &mappdat); return (o); } /*+ This routine computes a partition of *** the given graph structure with respect *** to the given strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphPart ( SCOTCH_Dgraph * const grafptr, /*+ Graph to map +*/ const SCOTCH_Num partnbr, /*+ Number of parts +*/ SCOTCH_Strat * const stratptr, /*+ Mapping strategy +*/ SCOTCH_Num * const termloctab) /*+ Mapping array +*/ { SCOTCH_Arch archdat; int o; SCOTCH_archInit (&archdat); SCOTCH_archCmplt (&archdat, partnbr); o = SCOTCH_dgraphMap (grafptr, &archdat, stratptr, termloctab); SCOTCH_archExit (&archdat); return (o); } /*+ This routine parses the given *** mapping strategy. *** It returns: *** - 0 : if string successfully scanned. *** - !0 : on error. +*/ int SCOTCH_stratDgraphMap ( SCOTCH_Strat * const stratptr, const char * const string) { if (*((Strat **) stratptr) != NULL) stratExit (*((Strat **) stratptr)); if ((*((Strat **) stratptr) = stratInit (&kdgraphmapststratab, string)) == NULL) { errorPrint ("SCOTCH_stratDgraphMap: error in parallel mapping strategy"); return (1); } return (0); } /*+ This routine provides predefined *** mapping strategies. *** It returns: *** - 0 : if string successfully initialized. *** - !0 : on error. +*/ int SCOTCH_stratDgraphMapBuild ( SCOTCH_Strat * const stratptr, /*+ Strategy to create +*/ const SCOTCH_Num flagval, /*+ Desired characteristics +*/ const SCOTCH_Num procnbr, /*+ Number of processes for running +*/ const SCOTCH_Num partnbr, /*+ Number of expected parts +*/ const double kbalval) /*+ Desired imbalance ratio +*/ { char bufftab[8192]; /* Should be enough */ char bbaltab[32]; char kbaltab[32]; char verttab[32]; Gnum vertnbr; char * difpptr; char * difsptr; char * exapptr; char * exasptr; char * muceptr; sprintf (kbaltab, "%lf", kbalval); sprintf (bbaltab, "%lf", kbalval); vertnbr = MAX (2000 * procnbr, 10000); vertnbr = MIN (vertnbr, 100000); sprintf (verttab, GNUMSTRING, vertnbr); strcpy (bufftab, "r{bal=,sep=m{vert=,asc=b{bnd=,org=},low=q{strat=(m{type=h,vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}})},seq=q{strat=(m{type=h,vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}})}},seq=r{bal=,poli=S,sep=(m{type=h,vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}})}}"); stringSubst (bufftab, "", ((flagval & SCOTCH_STRATSPEED) != 0) ? "" : "m{type=h,vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}}|"); if ((flagval & SCOTCH_STRATSCALABILITY) != 0) muceptr = "/(edge<10000000)?q{strat=f};"; /* Multi-centralization */ else muceptr = "q{strat=f}"; if ((flagval & SCOTCH_STRATBALANCE) != 0) { exapptr = "x{bal=0}"; exasptr = "f{bal=0}"; } else { exapptr = "x{bal=}"; /* Parallel exactifier */ exasptr = ""; } if ((flagval & SCOTCH_STRATSAFETY) != 0) { difpptr = ""; difsptr = ""; } else { difpptr = "(d{dif=1,rem=0,pass=40}|)"; difsptr = "(d{dif=1,rem=0,pass=40}|)"; } stringSubst (bufftab, "", muceptr); stringSubst (bufftab, "", exapptr); stringSubst (bufftab, "", exasptr); stringSubst (bufftab, "", difpptr); stringSubst (bufftab, "", difsptr); stringSubst (bufftab, "", bbaltab); stringSubst (bufftab, "", kbaltab); stringSubst (bufftab, "", verttab); if (SCOTCH_stratDgraphMap (stratptr, bufftab) != 0) { errorPrint ("SCOTCH_stratDgraphMapBuild: error in parallel mapping strategy"); return (1); } return (0); } /*+ This routine provides predefined *** clustering strategies. *** It returns: *** - 0 : if string successfully initialized. *** - !0 : on error. +*/ int SCOTCH_stratDgraphClusterBuild ( SCOTCH_Strat * const stratptr, /*+ Strategy to create +*/ const SCOTCH_Num flagval, /*+ Desired characteristics +*/ const SCOTCH_Num procnbr, /*+ Number of processes for running +*/ const SCOTCH_Num pwgtval, /*+ Threshold part load +*/ const double densval, /*+ Threshold density value +*/ const double bbalval) /*+ Maximum imbalance ratio +*/ { char bufftab[8192]; /* Should be enough */ char bbaltab[32]; char denstab[32]; char pwgttab[32]; char verttab[32]; Gnum vertnbr; char * difpptr; char * difsptr; char * exapptr; char * exasptr; char * muceptr; sprintf (bbaltab, "%lf", bbalval); sprintf (denstab, "%lf", densval); sprintf (pwgttab, GNUMSTRING, pwgtval); vertnbr = MAX (2000 * procnbr, 10000); vertnbr = MIN (vertnbr, 100000); sprintf (verttab, GNUMSTRING, vertnbr); strcpy (bufftab, "r{sep=/((load>)&!(edge>vert**(vert-1)))?m{vert=,asc=b{bnd=,org=},low=q{strat=(m{type=h,vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}})},seq=q{strat=/((load>)&!(edge>vert**(vert-1)))?(m{type=h,vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}});}};,seq=r{sep=/((load>)&!(edge>vert**(vert-1)))?(m{type=h,vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}});}}"); stringSubst (bufftab, "", ((flagval & SCOTCH_STRATSPEED) != 0) ? "" : "m{type=h,vert=80,low=h{pass=10}f{bal=,move=80},asc=b{bnd=f{bal=,move=80},org=f{bal=,move=80}}}|"); if ((flagval & SCOTCH_STRATSCALABILITY) != 0) muceptr = "/(edge<10000000)?q{strat=f};"; /* Multi-centralization */ else muceptr = "q{strat=f}"; if ((flagval & SCOTCH_STRATBALANCE) != 0) { exapptr = "x{bal=0}"; exasptr = "f{bal=0}"; } else { exapptr = "x{bal=}"; /* Parallel exactifier */ exasptr = ""; } if ((flagval & SCOTCH_STRATSAFETY) != 0) { difpptr = ""; difsptr = ""; } else { difpptr = "(d{dif=1,rem=0,pass=40}|)"; difsptr = "(d{dif=1,rem=0,pass=40}|)"; } stringSubst (bufftab, "", muceptr); stringSubst (bufftab, "", exapptr); stringSubst (bufftab, "", exasptr); stringSubst (bufftab, "", difpptr); stringSubst (bufftab, "", difsptr); stringSubst (bufftab, "", bbaltab); stringSubst (bufftab, "", denstab); stringSubst (bufftab, "", pwgttab); stringSubst (bufftab, "", verttab); if (SCOTCH_stratDgraphMap (stratptr, bufftab) != 0) { errorPrint ("SCOTCH_stratDgraphClusterBuild: error in parallel mapping strategy"); return (1); } return (0); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_coarsen.h0000644000175300017530000001736011631334325022272 0ustar hazelscthazelsct/* Copyright 2007-2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_coarsen.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER (v5.0) **/ /** **/ /** FUNCTION : This file implements the distributed **/ /** graph coarsening method. **/ /** **/ /** DATES : # Version 5.0 : from : 27 Jul 2005 **/ /** to : 24 feb 2007 **/ /** # Version 5.1 : from : 11 nov 2008 **/ /** to : 26 may 2009 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ The multinode table element, which contains pairs of based indices of collapsed vertices. Both values are equal for uncollapsed vertices. +*/ typedef struct DgraphCoarsenMulti_ { Gnum vertglbnum[2]; /*+ Global indices of the collapsed vertices of a multinode +*/ } DgraphCoarsenMulti; /* This structure defines vertex data exchange cell. It can have many uses depending on the type of algorithm. */ typedef struct DgraphCoarsenVert_ { Gnum datatab[2]; /*+ Two values +*/ } DgraphCoarsenVert; /* This structure defines the inter-process vertex and edge count structure. At matching time, it records the amount of data to be sent to each neighbor process. */ typedef struct DgraphCoarsenCount_ { Gnum vertsndnbr; Gnum edgesndnbr; Gnum vertlocnbr; } DgraphCoarsenCount; /*+ A table made of such elements is used during coarsening to build the edge array of the new graph, after the labeling of the vertices. +*/ typedef struct DgraphCoarsenHash_ { Gnum vertorgnum; /*+ Origin vertex (i.e. pass) number +*/ Gnum vertendnum; /*+ Other end vertex number +*/ Gnum edgelocnum; /*+ Number of corresponding edge +*/ } DgraphCoarsenHash; /*+ This structure gathers all data necessary to the proper execution of the coarsening and matching routines. +*/ typedef struct DgraphCoarsenData_ { Dgraph * finegrafptr; /*+ Pointer to fine graph +*/ Dgraph * coargrafptr; /*+ Pointer to coarse graph which is built +*/ int * coarprivptr; /*+ Pointer to coarse private data to free in case of error +*/ DgraphCoarsenVert * vrcvdattab; /*+ Area reserved for receiving vertex messages +*/ DgraphCoarsenVert * vsnddattab; /*+ Area reserved for sending vertex messages +*/ int * vrcvcnttab; /*+ Count data for vertex receive sub-arrays +*/ int * vsndcnttab; /*+ Count data for vertex send sub-arrays +*/ int * vrcvdsptab; /*+ Displacement for vertex receive sub-arrays [+1] +*/ int * vsnddsptab; /*+ Displacement data for vertex send sub-arrays [+1] +*/ int * nrcvidxtab; /*+ Count array for neighbor receive sub-arrays +*/ int * nsndidxtab; /*+ Count array for neighbor send sub-arrays +*/ MPI_Request * nrcvreqtab; /*+ Request array for receive requests +*/ MPI_Request * nsndreqtab; /*+ TRICK: nsndreqtab = (nrcvreqtab + procngbnbr) +*/ int * procgsttax; /*+ Array giving the neighbor process index of each ghost vertex +*/ int procngbnxt; /*+ Index of first neighbor of higher rank than current process +*/ DgraphCoarsenCount * dcntloctab; /*+ Count array for sending vertices and edges +*/ DgraphCoarsenCount * dcntglbtab; /*+ Count array for receiving vertices and edges +*/ Gnum * coargsttax; /*+ Fine-to-coarse vertex index array +*/ DgraphCoarsenMulti * multloctab; /*+ Structure which contains the result of the matching +*/ Gnum multlocnbr; /*+ Index of next multinode to be created +*/ Gnum vertrcvnbr; /*+ Number of fine vertices to be received +*/ Gnum edgercvnbr; /*+ Number of fine edges to be received +*/ Gnum edgekptnbr; /*+ Upper bound on number of edges kept from finer graph +*/ Gnum vertsndnbr; /*+ Number of fine vertices to be sent +*/ Gnum edgesndnbr; /*+ Number of fine edges to be sent +*/ } DgraphCoarsenData; /* ** The function prototypes. */ #ifndef DGRAPH_COARSEN #define static #endif static int dgraphCoarsenInit (DgraphCoarsenData * restrict const, Dgraph * restrict const, Dgraph * restrict const); static void dgraphCoarsenExit (DgraphCoarsenData * restrict const); static int dgraphCoarsenBuild (DgraphCoarsenData * restrict const); int dgraphCoarsen (Dgraph * restrict const, Dgraph * restrict const, DgraphCoarsenMulti * restrict * const, const Gnum, const Gnum, const int, const Gnum, const double); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_graph_coarsen_f.c0000644000175300017530000000655611631334325024157 0ustar hazelscthazelsct/* Copyright 2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_coarsen_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** graph coarsening routine of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 5.1 : from : 07 aug 2011 **/ /** to 07 aug 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the mapping routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFGRAPHCOARSEN, scotchfgraphcoarsen, ( \ SCOTCH_Graph * const finegrafptr, \ SCOTCH_Graph * const coargrafptr, \ SCOTCH_Num * const coarmulttab, \ SCOTCH_Num * const coarnbrptr, \ double * const coarratptr, \ int * const revaptr), \ (finegrafptr, coargrafptr, coarmulttab, coarnbrptr, coarratptr, revaptr)) { *revaptr = SCOTCH_graphCoarsen (finegrafptr, coargrafptr, coarmulttab, *coarnbrptr, *coarratptr); } scotch-5.1.12b.dfsg/src/libscotch/kdgraph_map_rb_map.c0000644000175300017530000000625611631334325023105 0ustar hazelscthazelsct/* Copyright 2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kdgraph_map_rb_map.c **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** **/ /** FUNCTION : This module performs the Dual Recursive **/ /** Bipartitioning mapping algorithm **/ /** in parallel for non-complete graphs. **/ /** **/ /** DATES : # Version 5.1 : from : 24 jun 2008 **/ /** to 24 jun 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define KDGRAPH_MAP_RB_MAP #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "arch.h" #include "dgraph.h" #include "dmapping.h" #include "kdgraph.h" #include "kdgraph_map_rb.h" #include "kdgraph_map_rb_map.h" #include "kdgraph_map_st.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ int kdgraphMapRbMap ( Kdgraph * restrict const grafptr, Kdmapping * restrict const mappptr, const KdgraphMapRbParam * restrict const paraptr) { errorPrint ("kdgraphMapRbMap: not implemented yet"); return (1); } scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_st.h0000644000175300017530000000766611631334325022475 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_st.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data **/ /** declarations for the main graph **/ /** ordering routine. **/ /** **/ /** DATES : # Version 3.2 : from : 31 oct 1996 **/ /** to : 29 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to 07 sep 2001 **/ /** # Version 4.0 : from : 29 dec 2001 **/ /** to : 15 jan 2003 **/ /** **/ /************************************************************/ /* ** The type definitions. */ /*+ Method types. +*/ typedef enum HgraphOrderStMethodType_ { HGRAPHORDERSTMETHBL = 0, /*+ Block splitting post-processing +*/ HGRAPHORDERSTMETHCP, /*+ Graph compression +*/ HGRAPHORDERSTMETHGP, /*+ Gibbs-Poole-Stockmeyer +*/ HGRAPHORDERSTMETHHD, /*+ Block Halo Approximate Minimum Degree +*/ HGRAPHORDERSTMETHHF, /*+ Block Halo Approximate Minimum Fill +*/ HGRAPHORDERSTMETHND, /*+ Nested Dissection +*/ HGRAPHORDERSTMETHSI, /*+ Simple +*/ HGRAPHORDERSTMETHNBR /*+ Number of methods +*/ } HgraphOrderStMethodType; /* ** The external declarations. */ extern StratTab hgraphorderststratab; /* ** The function prototypes. */ #ifndef HGRAPH_ORDER_ST #define static #endif int hgraphOrderSt (const Hgraph * restrict const, Order * restrict const, const Gnum, OrderCblk * restrict const, const Strat * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/vmesh_separate_ml.c0000644000175300017530000002616211631334325023004 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh_separate_ml.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module separates an active **/ /** mesh using a multi-level scheme. **/ /** **/ /** DATES : # Version 4.0 : from : 19 feb 2003 **/ /** to 31 aug 2005 **/ /** # Version 5.0 : from : 30 jan 2008 **/ /** to 30 jan 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VMESH_SEPARATE_ML #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "mesh.h" #include "mesh_coarsen.h" #include "vmesh.h" #include "vmesh_separate_ml.h" #include "vmesh_separate_st.h" /*********************************************/ /* */ /* The coarsening and uncoarsening routines. */ /* */ /*********************************************/ /* This routine builds a coarser mesh from the ** mesh that is given on input. The coarser ** meshes differ at this stage from classical ** active meshes as their internal gains are not ** yet computed. ** It returns: ** - 0 : if the coarse mesh has been built. ** - 1 : if threshold achieved. ** - 2 : on error. */ static int vmeshSeparateMlCoarsen ( const Vmesh * restrict const finemeshptr, /*+ Finer mesh +*/ Vmesh * restrict const coarmeshptr, /*+ Coarser mesh to build +*/ Gnum * restrict * const finecoarptr, /*+ Pointer to multinode table to build +*/ const VmeshSeparateMlParam * const paraptr) /*+ Method parameters +*/ { int o; if (finemeshptr->m.vnodnbr <= (Gnum) paraptr->vnodnbr) return (1); if ((o = meshCoarsen (&finemeshptr->m, &coarmeshptr->m, finecoarptr, (Gnum) paraptr->vnodnbr, paraptr->coarrat, paraptr->coartype)) != 0) return (o); /* Return if coarsening failed */ coarmeshptr->parttax = NULL; /* Do not allocate partition data yet */ coarmeshptr->frontab = finemeshptr->frontab; /* Re-use frontier array for coarser mesh */ coarmeshptr->levlnum = finemeshptr->levlnum + 1; /* Mesh level is coarsening level */ return (0); } /* This routine propagates the separation of the ** coarser mesh back to the finer mesh, according ** to the multinode table of collapsed elements. ** After the separation is propagated, it finishes ** to compute the parameters of the finer mesh that ** were not computed at the coarsening stage. ** It returns: ** - 0 : if coarse mesh data has been propagated to fine mesh. ** - !0 : on error. */ static int vmeshSeparateMlUncoarsen ( Vmesh * restrict const finemeshptr, /*+ Finer mesh +*/ const Vmesh * restrict const coarmeshptr, /*+ Coarser mesh +*/ const Gnum * restrict const finecoartax) /*+ Multinode array +*/ { if (finemeshptr->parttax == NULL) { /* If partition array not yet allocated */ if ((finemeshptr->parttax = (GraphPart *) memAlloc ((finemeshptr->m.velmnbr + finemeshptr->m.vnodnbr) * sizeof (GraphPart))) == NULL) { errorPrint ("vmeshSeparateMlUncoarsen: out of memory"); return (1); /* Allocated data will be freed along with mesh structure */ } finemeshptr->parttax -= finemeshptr->m.baseval; } if (coarmeshptr != NULL) { /* If coarser mesh provided */ Gnum finevelmnum; Gnum fineecmpsize1; /* Number of fine elements */ Gnum fineecmpsize2; Gnum finevnodnum; Gnum finencmpsize1; /* Number of fine nodes */ Gnum finefronnbr; /* Number of frontier vertices in fine mesh */ for (finevelmnum = finemeshptr->m.velmbas, fineecmpsize1 = fineecmpsize2 = 0; finevelmnum < finemeshptr->m.velmnnd; finevelmnum ++) { Gnum partval; #ifdef SCOTCH_DEBUG_VMESH2 if ((finecoartax[finevelmnum] < coarmeshptr->m.baseval) || (finecoartax[finevelmnum] >= (coarmeshptr->m.velmnbr + coarmeshptr->m.vnodnbr + coarmeshptr->m.baseval))) { errorPrint ("vmeshSeparateMlUncoarsen: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ partval = (Gnum) coarmeshptr->parttax[finecoartax[finevelmnum]]; finemeshptr->parttax[finevelmnum] = partval; fineecmpsize1 += (partval & 1); /* Superscalar update of counters */ fineecmpsize2 += (partval & 2); } finemeshptr->ecmpsize[0] = finemeshptr->m.velmnbr - fineecmpsize1 - (fineecmpsize2 >> 1); finemeshptr->ecmpsize[1] = fineecmpsize1; for (finevnodnum = finemeshptr->m.vnodbas, finencmpsize1 = finefronnbr = 0; finevnodnum < finemeshptr->m.vnodnnd; finevnodnum ++) { Gnum partval; #ifdef SCOTCH_DEBUG_VMESH2 if ((finecoartax[finevnodnum] < coarmeshptr->m.vnodbas) || /* Sons of nodes are always nodes */ (finecoartax[finevnodnum] >= coarmeshptr->m.vnodnnd)) { errorPrint ("vmeshSeparateMlUncoarsen: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ partval = coarmeshptr->parttax[finecoartax[finevnodnum]]; finemeshptr->parttax[finevnodnum] = partval; if ((partval & 2) != 0) /* If node is in separator */ finemeshptr->frontab[finefronnbr ++] = finevnodnum; /* Add to frontier */ finencmpsize1 += (partval & 1); } finemeshptr->ncmpload[0] = coarmeshptr->ncmpload[0]; finemeshptr->ncmpload[1] = coarmeshptr->ncmpload[1]; finemeshptr->ncmpload[2] = coarmeshptr->ncmpload[2]; finemeshptr->ncmploaddlt = coarmeshptr->ncmploaddlt; finemeshptr->ncmpsize[0] = finemeshptr->m.vnodnbr - finencmpsize1 - finefronnbr; finemeshptr->ncmpsize[1] = finencmpsize1; finemeshptr->fronnbr = finefronnbr; } else /* No coarse mesh provided */ vmeshZero (finemeshptr); /* Assign all vertices to part 0 */ #ifdef SCOTCH_DEBUG_VMESH2 if (vmeshCheck (finemeshptr) != 0) { errorPrint ("vmeshSeparateMlUncoarsen: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ return (0); } /* This routine recursively performs the ** coarsening recursion. ** It returns: ** - 0 : if recursion proceeded well. ** - !0 : on error. */ static int vmeshSeparateMl2 ( Vmesh * restrict const finemeshptr, /* Vertex-separation mesh */ const VmeshSeparateMlParam * restrict const paraptr) /* Method parameters */ { Vmesh coarmeshdat; Gnum * restrict finecoartax; int o; o = 1; /* Assume an error if "switch...case" returns a strange value in debug mode */ switch (vmeshSeparateMlCoarsen (finemeshptr, &coarmeshdat, &finecoartax, paraptr)) { case 0 : if (((o = vmeshSeparateMl2 (&coarmeshdat, paraptr)) == 0) && ((o = vmeshSeparateMlUncoarsen (finemeshptr, &coarmeshdat, finecoartax)) == 0) && ((o = vmeshSeparateSt (finemeshptr, paraptr->stratasc)) != 0)) /* Apply ascending strategy */ errorPrint ("vmeshSeparateMl2: cannot apply ascending strategy"); coarmeshdat.frontab = NULL; /* Prevent frontab of fine mesh from being freed */ vmeshExit (&coarmeshdat); memFree (finecoartax + finemeshptr->m.baseval); /* Free finecoartab as not part of coarse mesh vertex group (unlike for graphCoarsen) */ break; #ifdef SCOTCH_DEBUG_VMESH2 case 1 : case 2 : /* Cannot coarsen due to lack of memory */ finecoartax = NULL; /* Prevent Valgrind from yelling */ #else /* SCOTCH_DEBUG_VMESH2 */ default : #endif /* SCOTCH_DEBUG_VMESH2 */ if (((o = vmeshSeparateMlUncoarsen (finemeshptr, NULL, finecoartax)) == 0) && /* Finalize mesh */ ((o = vmeshSeparateSt (finemeshptr, paraptr->stratlow)) != 0)) /* Apply low strategy */ errorPrint ("vmeshSeparateMl2: cannot apply low strategy"); break; } return (o); } /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ int vmeshSeparateMl ( Vmesh * restrict const meshptr, /*+ Node-separation mesh +*/ const VmeshSeparateMlParam * const paraptr) /*+ Method parameters +*/ { Gnum levlnum; /* Save value for mesh level */ int o; levlnum = meshptr->levlnum; /* Save mesh level */ meshptr->levlnum = 0; /* Initialize coarsening level */ o = vmeshSeparateMl2 (meshptr, paraptr); /* Perform multi-level separation */ meshptr->levlnum = levlnum; /* Restore mesh level */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_gather.c0000644000175300017530000001300611631334325022076 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_gather.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** Francois CHATENET (0.0) **/ /** Sebastien FOUCAULT (0.0) **/ /** **/ /** FUNCTION : This module contains the routine which **/ /** builds a centralized graph by gathering **/ /** the pieces of a distributed graph. **/ /** **/ /** DATES : # Version 0.0 : from : 01 apr 1997 **/ /** to : 20 jun 1997 **/ /** # Version 0.1 : from : 14 apr 1998 **/ /** to : 20 jun 1998 **/ /** # Version 0.2 : from : 20 may 1999 **/ /** to : 20 may 1999 **/ /** # Version 5.0 : from : 07 feb 2006 **/ /** to : 16 jul 2007 **/ /** **/ /** NOTES : # The definitions of MPI_Gather and **/ /** MPI_Gatherv indicate that elements in **/ /** the receive array should not be **/ /** written more than once. Great care **/ /** should be taken to enforce this rule, **/ /** especially when the number of **/ /** vertices in the centralized graph is **/ /** smaller than the number of **/ /** processors. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH_GATHER #include "module.h" #include "common.h" #include "graph.h" #include "dgraph.h" /* This function gathers the pieces of ** a distributed graph to build a ** centralized graph. ** It returns: ** - 0 : if graph data are consistent. ** - !0 : on error. */ int dgraphGather ( const Dgraph * restrict const dgrfptr, /* Distributed graph */ Graph * restrict cgrfptr) /* Centralized graph */ { Gnum reduloctab[3]; Gnum reduglbtab[3]; if (dgrfptr->edloloctax == NULL) /* Compute sum of edge loads */ reduloctab[2] = dgrfptr->edgelocnbr; else { Gnum vertlocnum; Gnum edlolocsum; for (vertlocnum = dgrfptr->baseval, edlolocsum = 0; vertlocnum < dgrfptr->vertlocnnd; vertlocnum ++) { Gnum edgelocnum; Gnum edgelocnnd; for (edgelocnum = dgrfptr->vertloctax[vertlocnum], edgelocnnd = dgrfptr->vendloctax[vertlocnum]; edgelocnum < edgelocnnd; edgelocnum ++) edlolocsum += dgrfptr->edloloctax[edgelocnum]; } reduloctab[2] = edlolocsum; } if (cgrfptr != NULL) { /* If centralized graph provided */ reduloctab[0] = 1; /* This process is the root */ reduloctab[1] = (Gnum) dgrfptr->proclocnum; /* Get its number */ } else { reduloctab[0] = /* This process is not the root */ reduloctab[1] = 0; } if (MPI_Allreduce (reduloctab, reduglbtab, 3, GNUM_MPI, MPI_SUM, dgrfptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphGather: communication error"); return (1); } if (reduglbtab[0] != 1) { errorPrint ("dgraphGather: should have only one root"); return (1); } return (dgraphGatherAll2 (dgrfptr, cgrfptr, reduglbtab[2], (int) reduglbtab[1])); } scotch-5.1.12b.dfsg/src/libscotch/mesh.c0000644000175300017530000001701511631334325020237 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mesh.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the source mesh **/ /** functions. **/ /** **/ /** DATES : # Version 4.0 : from : 29 dec 2001 **/ /** to 05 may 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MESH #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" /****************************************/ /* */ /* These routines handle source meshes. */ /* */ /****************************************/ /* This routine initializes a source mesh ** structure. ** It returns: ** - 0 : in all cases. */ int meshInit ( Mesh * const meshptr) { memSet (meshptr, 0, sizeof (Mesh)); /* Initialize mesh fields */ meshptr->flagval = MESHFREETABS; /* By default, free all arrays */ return (0); } /* This routine frees a source mesh structure. ** It returns: ** - VOID : in all cases. */ void meshExit ( Mesh * const meshptr) { meshFree (meshptr); /* Exit mesh data */ #ifdef SCOTCH_DEBUG_MESH2 memSet (meshptr, ~0, sizeof (Mesh)); /* Purge mesh fields */ #endif /* SCOTCH_DEBUG_MESH2 */ } /* This routine frees the mesh data. Because ** vertex load arrays are either passed by ** the user, or grouped with other arrays, ** they are not considered for explicit ** freeing. This is also much simpler, as ** load arrays can be grouped or not. ** It returns: ** - VOID : in all cases. */ void meshFree ( Mesh * const meshptr) { if (((meshptr->flagval & MESHFREEEDGE) != 0) && /* If edgetab must be freed */ (meshptr->edgetax != NULL)) /* And if it exists */ memFree (meshptr->edgetax + meshptr->baseval); /* Free it */ if ((meshptr->flagval & MESHFREEVEND) != 0) { /* If vendtab must be freed */ if ((meshptr->vendtax != NULL) && /* If vendtab is distinct from verttab */ (meshptr->vendtax != meshptr->verttax + 1) && /* (if vertex arrays grouped, vendtab not distinct anyway) */ ((meshptr->flagval & MESHVERTGROUP) == 0)) memFree (meshptr->vendtax + meshptr->baseval); /* Then free vendtab */ } if ((meshptr->flagval & MESHFREEVERT) != 0) { /* If verttab must be freed */ if (meshptr->verttax != NULL) /* Free verttab anyway, as it is the array group leader */ memFree (meshptr->verttax + meshptr->baseval); } #ifdef SCOTCH_DEBUG_MESH2 if ((meshptr->flagval & MESHFREEVNUM) != 0) { /* If vnumtab must be freed */ if ((meshptr->vnumtax != NULL) && /* And is not in vertex array group */ ((meshptr->flagval & MESHVERTGROUP) == 0)) errorPrint ("meshFree: vnumtab should never be freed as its base may vary according to creation routines"); } #endif /* SCOTCH_DEBUG_MESH2 */ if ((meshptr->flagval & MESHFREEOTHR) != 0) { /* If other arrays must be freed */ if (meshptr->vlbltax != NULL) memFree (meshptr->vlbltax + meshptr->baseval); } #ifdef SCOTCH_DEBUG_MESH2 memSet (meshptr, ~0, sizeof (Mesh)); /* Purge mesh fields */ #endif /* SCOTCH_DEBUG_MESH2 */ } /* This routine sets the base of the given ** mesh to the given base value, and returns ** the old base value. ** It returns: ** - old base value : in all cases. */ Gnum meshBase ( Mesh * const meshptr, const Gnum baseval) { Gnum baseold; /* Old base value */ Gnum baseadj; /* Base adjustment */ Gnum vertnum; Gnum edgenum; if (meshptr->baseval == baseval) /* If nothing to do */ return (baseval); baseold = meshptr->baseval; /* Record old base value */ baseadj = baseval - baseold; /* Compute adjustment */ for (vertnum = meshptr->baseval; vertnum < (meshptr->velmnbr + meshptr->vnodnbr + meshptr->baseval); vertnum ++) { for (edgenum = meshptr->verttax[vertnum]; edgenum < meshptr->vendtax[vertnum]; edgenum ++) meshptr->edgetax[edgenum] += baseadj; meshptr->verttax[vertnum] += baseadj; } if (meshptr->vendtax != meshptr->verttax + 1) { /* If distinct vertex end array */ for (vertnum = meshptr->baseval; vertnum < (meshptr->velmnbr + meshptr->vnodnbr + meshptr->baseval); vertnum ++) meshptr->vendtax[vertnum] += baseadj; } else /* If same vertex end array (of size +1) */ meshptr->verttax[meshptr->velmnbr + meshptr->vnodnbr + meshptr->baseval] += baseadj; /* Adjust last entry of verttab */ meshptr->verttax -= baseadj; /* Adjust array accesses */ meshptr->vendtax -= baseadj; meshptr->edgetax -= baseadj; if (meshptr->vnumtax != NULL) meshptr->vnumtax -= baseadj; if (meshptr->vlbltax != NULL) meshptr->vlbltax -= baseadj; meshptr->baseval = baseval; /* Set new base value */ meshptr->velmbas += baseadj; /* Adjust mesh parameter */ meshptr->velmnnd += baseadj; meshptr->vnodbas += baseadj; meshptr->vnodnnd += baseadj; return (baseold); /* Return old base value */ } scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_gp.h0000644000175300017530000001043211631334325022436 0ustar hazelscthazelsct/* Copyright 2004,2007,2009,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_gp.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the Gibbs-Poole-Stockmeyer **/ /** node ordering routine. **/ /** **/ /** DATES : # Version 3.2 : from : 31 oct 1996 **/ /** to : 27 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 02 oct 1998 **/ /** # Version 4.0 : from : 03 feb 2002 **/ /** to : 01 dec 2003 **/ /** # Version 5.1 : from : 01 oct 2009 **/ /** to : 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HgraphOrderGpParam_ { INT passnbr; /*+ Number of passes to do +*/ } HgraphOrderGpParam; /*+ Complementary vertex structure. +*/ typedef struct HgraphOrgerGpVertex_ { Gnum passnum; /*+ Number of pass when vertex selected +*/ Gnum vertdist; /*+ Current distance from diameter vertex +*/ } HgraphOrderGpVertex; /*+ Neighbor queue. +*/ typedef struct HgraphOrgerGpQueue_ { Gnum * head; /*+ Head of distance queue +*/ Gnum * tail; /*+ Tail of distance queue +*/ Gnum * qtab; /*+ Array of queue elements +*/ } HgraphOrgerGpQueue; /* ** The function prototypes. */ #ifndef HGRAPH_ORDER_GP #define static #endif int hgraphOrderGp (const Hgraph * const, Order * const, const Gnum, OrderCblk * const, const HgraphOrderGpParam * restrict const); #undef static /* ** The macro definitions. */ #define hgraphOrderGpQueueFlush(queue) ((queue)->head = (queue)->tail = (queue)->qtab) #define hgraphOrderGpQueueEmpty(queue) ((queue)->head <= (queue)->tail) #define hgraphOrderGpQueuePut(queue,vnum) (* ((queue)->head ++) = (vnum)) #define hgraphOrderGpQueueGet(queue) (* ((queue)->tail ++)) scotch-5.1.12b.dfsg/src/libscotch/vdgraph_separate_ml.c0000644000175300017530000010320611631334325023310 0ustar hazelscthazelsct/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_separate_ml.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER (v5.0) **/ /** **/ /** FUNCTION : This module contains the multi-level **/ /** separation strategy. **/ /** **/ /** DATES : # Version 5.0 : from : 07 mar 2006 **/ /** to : 01 mar 2008 **/ /** # Version 5.1 : from : 14 dec 2008 **/ /** to : 26 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VDGRAPH_SEPARATE_ML #include "module.h" #include "common.h" #include "parser.h" #include "dgraph.h" #include "dgraph_coarsen.h" #include "vdgraph.h" #include "vdgraph_separate_ml.h" #include "vdgraph_separate_st.h" /*********************************************/ /* */ /* The coarsening and uncoarsening routines. */ /* */ /*********************************************/ /* This routine builds a coarser graph from the ** Dgraph that is given on input. The coarser ** Dgraphs differ at this stage from classical ** active Dgraphs as their internal gains are not ** yet computed. ** It returns: ** - 0 : if the coarse Dgraph has been built. ** - 1 : if threshold achieved or on error. */ static int vdgraphSeparateMlCoarsen ( Vdgraph * restrict const finegrafptr, /*+ Finer graph +*/ Vdgraph * restrict const coargrafptr, /*+ Coarser graph to build +*/ DgraphCoarsenMulti * restrict * const coarmultptr, /*+ Pointer to multinode table to build +*/ const VdgraphSeparateMlParam * const paraptr) /*+ Method parameters +*/ { int dofolddup; dofolddup = 1; if ((paraptr->duplvlmax > -1) && /* duplvlmax can allow fold dup */ (paraptr->duplvlmax < finegrafptr->levlnum + 1)) { dofolddup = 0; } else if (paraptr->duplvlmax < -1) { /* duplvlmax can allow only fold */ if (- (paraptr->duplvlmax + 1) < finegrafptr->levlnum + 1) dofolddup = 0; else dofolddup = -1; } if (dgraphCoarsen (&finegrafptr->s, &coargrafptr->s, coarmultptr, paraptr->passnbr, paraptr->coarnbr, dofolddup, paraptr->dupmax, paraptr->coarrat) != 0) return (1); /* Return if coarsening failed */ coargrafptr->fronloctab = NULL; coargrafptr->partgsttax = NULL; /* Do not allocate partition data yet */ if (coargrafptr->s.procglbnbr == 0) { /* Not a owner graph */ coargrafptr->s.vertlocnbr = 0; /* Set it to zero for vrcvdattab allocation */ return (0); } coargrafptr->levlnum = finegrafptr->levlnum + 1; /* Graph level is coarsening level */ if (coargrafptr->s.vertlocnbr <= finegrafptr->s.vertlocnbr) /* If (folded) coarser graph is smaller */ coargrafptr->fronloctab = finegrafptr->fronloctab; /* Re-use frontier array for coarser graph */ else { /* Else allocate new private frontier array */ if ((coargrafptr->fronloctab = memAlloc (coargrafptr->s.vertlocnbr * sizeof (Gnum))) == NULL) { errorPrint ("vdgraphSeparateMlCoarsen: out of memory"); dgraphExit (&coargrafptr->s); /* Only free Dgraph since fronloctab not allocated */ return (1); } } return (0); } /* This routine is the reduction-loc operator which ** returns in inout[2] the rank of the process which ** holds the best partition. ** It returns: ** - void : in all cases. */ static void vdgraphSeparateMlOpBest ( const Gnum * const in, /* First operand */ Gnum * const inout, /* Second and output operand */ const int * const len, /* Number of instances ; should be 1, not used */ const MPI_Datatype * const typedat) /* MPI datatype ; not used */ { inout[5] |= in[5]; /* Memory error flag */ if (inout[0] == 1) { /* Handle cases when at least one of them is erroneous */ if (in[0] == 1) { if (inout[1] > in[1]) { /* To enforce commutativity, always keep smallest process number */ inout[1] = in[1]; inout[2] = in[2]; } return; } inout[0] = in[0]; /* Validity flag */ inout[1] = in[1]; /* Lead process rank */ inout[2] = in[2]; /* Lead process color */ inout[3] = in[3]; /* Separator size */ inout[4] = in[4]; /* Parts imbalance */ return; } else if (in[0] == 1) return; if ((in[3] < inout[3]) || /* Select best partition */ ((in[3] == inout[3]) && ((in[4] < inout[4]) || ((in[4] == inout[4]) && (in[1] < inout[1]))))) { inout[1] = in[1]; inout[2] = in[2]; inout[3] = in[3]; inout[4] = in[4]; } } /* This routine packs the neighbor data to be sent ** to one of the neighbors by part number. ** It returns: ** - void : in all cases. */ static void vdgraphSeparateMlPack ( Gnum * restrict const dataloctab, const Gnum datalocidx, Gnum * restrict ssndcnttab) { Gnum finevertsndnbr0; Gnum finevertsndnbr1; Gnum finevertsndnbr2; Gnum datalocnbr; finevertsndnbr0 = ssndcnttab[0]; finevertsndnbr1 = ssndcnttab[1]; finevertsndnbr2 = ssndcnttab[2]; datalocnbr = finevertsndnbr0 + finevertsndnbr1 + finevertsndnbr2; if (datalocnbr <= datalocidx) { /* If arrays do not overlap */ Gnum * restrict datadsttab = dataloctab + datalocidx; const Gnum * restrict const datasrctab = dataloctab + datalocidx * 2; Gnum datasrcnum; Gnum partidxtab[3]; partidxtab[0] = 0; partidxtab[1] = finevertsndnbr0; partidxtab[2] = finevertsndnbr0 + finevertsndnbr1; for (datasrcnum = 0, datalocnbr <<= 1; datasrcnum < datalocnbr; ) { /* Work on pairs of Gnum's */ Gnum finevertglbnum; Gnum finepartval; finevertglbnum = datasrctab[datasrcnum ++]; finepartval = datasrctab[datasrcnum ++]; datadsttab[partidxtab[finepartval] ++] = finevertglbnum; } } else { /* Arrays do overlap */ Gnum datadstnum; Gnum datasrcnum; Gnum datasrcnnd; Gnum datasrcnxt; datadstnum = datalocidx; for (datasrcnum = datalocidx << 1, datasrcnnd = datasrcnum + (finevertsndnbr0 << 1), datasrcnxt = datasrcnnd; /* Work on pairs of Gnum's */ datasrcnum < datasrcnnd; ) { Gnum finevertglbnum; Gnum finepartval; finevertglbnum = dataloctab[datasrcnum ++]; finepartval = dataloctab[datasrcnum ++]; if (finepartval != 0) { Gnum finevertglbtmp; #ifdef SCOTCH_DEBUG_VDGRAPH2 if ((finepartval < 1) || (finepartval > 2)) { errorPrint ("vdgraphSeparateMlPack: internal error (1)"); return; } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ while (dataloctab[datasrcnxt + 1] != 0) { /* Find first vertex of part zero in next block */ datasrcnxt += 2; #ifdef SCOTCH_DEBUG_VDGRAPH2 if (datasrcnxt >= ((datalocidx + datalocnbr) << 1)) { errorPrint ("vdgraphSeparateMlPack: internal error (2)"); return; } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ } finevertglbtmp = dataloctab[datasrcnxt]; dataloctab[datasrcnxt ++] = finevertglbnum; dataloctab[datasrcnxt ++] = finepartval; finevertglbnum = finevertglbtmp; } dataloctab[datadstnum ++] = finevertglbnum; } for (datasrcnnd += finevertsndnbr1 << 1, datasrcnxt = datasrcnnd; /* Work on pairs of Gnum's */ datasrcnum < datasrcnnd; ) { Gnum finevertglbnum; Gnum finepartval; finevertglbnum = dataloctab[datasrcnum ++]; finepartval = dataloctab[datasrcnum ++]; if (finepartval != 1) { Gnum finevertglbtmp; #ifdef SCOTCH_DEBUG_VDGRAPH2 if (finepartval != 2) { errorPrint ("vdgraphSeparateMlPack: internal error (3)"); return; } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ while (dataloctab[datasrcnxt + 1] != 1) { /* Find first vertex of part one in next block */ datasrcnxt += 2; #ifdef SCOTCH_DEBUG_VDGRAPH2 if (datasrcnxt >= ((datalocidx + datalocnbr) << 1)) { errorPrint ("vdgraphSeparateMlPack: internal error (4)"); return; } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ } finevertglbtmp = dataloctab[datasrcnxt]; dataloctab[datasrcnxt ++] = finevertglbnum; dataloctab[datasrcnxt ++] = finepartval; finevertglbnum = finevertglbtmp; } dataloctab[datadstnum ++] = finevertglbnum; } for (datasrcnnd += finevertsndnbr2 << 1; datasrcnum < datasrcnnd; ) { /* Work on pairs of Gnum's */ Gnum finevertglbnum; finevertglbnum = dataloctab[datasrcnum]; #ifdef SCOTCH_DEBUG_VDGRAPH2 if (dataloctab[datasrcnum + 1] != 2) { errorPrint ("vdgraphSeparateMlPack: internal error (5)"); return; } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ datasrcnum += 2; dataloctab[datadstnum ++] = finevertglbnum; } } } /* This routine propagates the separation of the ** coarser graph back to the finer graph, according ** to the multinode table of collapsed vertices. ** After the separation is propagated, it finishes ** to compute the parameters of the finer graph that ** were not computed at the coarsening stage. ** It returns: ** - 0 : if coarse graph data has been propagated to the fine graph. ** - !0 : on error. */ static int vdgraphSeparateMlUncoarsen ( Vdgraph * restrict finegrafptr, /*+ Finer graph +*/ const Vdgraph * restrict const coargrafptr, /*+ Coarser graph +*/ const DgraphCoarsenMulti * restrict const coarmulttax) /*+ Multinode array +*/ { Gnum coarvertnum; Gnum finevertlocadj; Gnum finecomplocload0; Gnum finecomplocload2; Gnum finecomplocsize1; Gnum finecomplocsize2; Gnum * restrict srcvdattab; Gnum * ssnddattab; /* TRICK: holds vrcvcnttab, vsnddsptab, vrcvdsptab */ Gnum * vrcvdattab; /* TRICK: overlaps with vsnddattab before packing [norestrict:async] */ Gnum * vsnddattab; /* [norestrict:async] */ int * vrcvcnttab; int * vsndcnttab; int * vrcvdsptab; int * vsnddsptab; int vrcvdspnum; int vsnddspnum; Gnum vrcvdatnum; MPI_Datatype besttypedat; /* Data type for finding best bipartition */ MPI_Op bestoperdat; /* Handle of MPI operator for finding best bipartition */ Gnum reduloctab[6]; Gnum reduglbtab[6]; int procnum; const Gnum * restrict fineveloglbtax; GraphPart * restrict finepartglbtax; Gnum * restrict const finefronloctab = finegrafptr->fronloctab; reduloctab[5] = 0; /* Assume everything is fine */ if (finegrafptr->partgsttax == NULL) { /* If partition array not yet allocated */ if (dgraphGhst (&finegrafptr->s) != 0) { /* Create ghost edge array and compute vertgstnbr */ errorPrint ("vdgraphSeparateMlUncoarsen: cannot compute ghost edge array"); reduloctab[5] = 1; /* Allocated data will be freed along with graph structure */ } if ((finegrafptr->partgsttax = (GraphPart *) memAlloc (finegrafptr->s.vertgstnbr * sizeof (GraphPart))) == NULL) { errorPrint ("vdgraphSeparateMlUncoarsen: out of memory (1)"); reduloctab[5] = 1; /* Allocated data will be freed along with graph structure */ } else finegrafptr->partgsttax -= finegrafptr->s.baseval; } if (coargrafptr == NULL) { /* If coarser graph not provided */ #ifdef SCOTCH_DEBUG_BDGRAPH1 /* Communication cannot be overlapped by a useful one */ if (MPI_Allreduce (&reduloctab[5], &reduglbtab[5], 1, GNUM_MPI, MPI_SUM, finegrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphSeparateMlUncoarsen: communication error (1)"); return (1); } #else /* SCOTCH_DEBUG_BDGRAPH1 */ reduglbtab[5] = reduloctab[5]; #endif /* SCOTCH_DEBUG_BDGRAPH1 */ if (reduglbtab[5] != 0) return (1); vdgraphZero (finegrafptr); /* Assign all vertices to part 0 */ return (0); } if (memAllocGroup ((void **) (void *) &vsndcnttab, (size_t) (finegrafptr->s.procglbnbr * sizeof (int)), /* TRICK: srcvdattab after ssnddattab, after vsndcnttab */ &ssnddattab, (size_t) (finegrafptr->s.procglbnbr * 3 * sizeof (Gnum)), /* TRICK: ssnddattab is vrcvcnttab, vsnddsptab, vrcvdsptab */ &srcvdattab, (size_t) (finegrafptr->s.procglbnbr * 3 * sizeof (Gnum)), &vsnddattab, (size_t) (coargrafptr->s.vertlocnbr * 2 * sizeof (Gnum)), /* TRICK: vsnddattab overlaps with vrcvdattab */ &vrcvdattab, (size_t) (MAX ((coargrafptr->s.vertlocnbr * 2), finegrafptr->s.vertlocnbr) * sizeof (Gnum)), NULL) == NULL) { errorPrint ("vdgraphSeparateMlUncoarsen: out of memory (2)"); reduloctab[5] = 1; } if (coargrafptr->s.procglbnbr <= 0) { /* If unused folded coargrafptr */ reduloctab[0] = 1; /* Set it as invalid */ reduloctab[1] = 0; /* Useless rank */ reduloctab[2] = 1; /* Color is not the one of folded */ reduloctab[3] = /* Prevent Valgrind from yelling */ reduloctab[4] = 0; } else { reduloctab[0] = ((coargrafptr->compglbsize[0] == 0) || /* Empty separated parts are deemed invalid */ (coargrafptr->compglbsize[1] == 0)) ? 1 : 0; reduloctab[1] = finegrafptr->s.proclocnum; /* Set rank and color key according to coarse graph (sub)communicator */ reduloctab[2] = finegrafptr->s.prockeyval; reduloctab[3] = coargrafptr->compglbsize[2]; reduloctab[4] = coargrafptr->compglbloaddlt; } if ((MPI_Type_contiguous (6, GNUM_MPI, &besttypedat) != MPI_SUCCESS) || (MPI_Type_commit (&besttypedat) != MPI_SUCCESS) || (MPI_Op_create ((MPI_User_function *) vdgraphSeparateMlOpBest, 1, &bestoperdat) != MPI_SUCCESS)) { errorPrint ("vdgraphSeparateMlUncoarsen: communication error (2)"); return (1); } if (MPI_Allreduce (reduloctab, reduglbtab, 1, besttypedat, bestoperdat, finegrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphSeparateMlUncoarsen: communication error (3)"); return (1); } if ((MPI_Op_free (&bestoperdat) != MPI_SUCCESS) || (MPI_Type_free (&besttypedat) != MPI_SUCCESS)) { errorPrint ("vdgraphSeparateMlUncoarsen: communication error (4)"); return (1); } if (reduglbtab[5] != 0) { /* If memory error, return */ if (vsndcnttab != NULL) /* Partgsttax will be freed at the above level */ memFree (vsndcnttab); return (1); } if (reduglbtab[0] == 1) { /* If all possible partitions are invalid */ #ifdef SCOTCH_DEBUG_BDGRAPH2 errorPrintW ("vdgraphSeparateMlUncoarsen: no valid partition"); #endif /* SCOTCH_DEBUG_BDGRAPH2 */ return (1); /* All invalid partitions will lead to low method be applied at upper level */ } finevertlocadj = finegrafptr->s.procvrttab[finegrafptr->s.proclocnum] - finegrafptr->s.baseval; fineveloglbtax = (finegrafptr->s.veloloctax != NULL) ? (finegrafptr->s.veloloctax - finevertlocadj) : NULL; /* Array can be indexed with global vertex numbers */ finepartglbtax = finegrafptr->partgsttax - finevertlocadj; finegrafptr->complocload[0] = finegrafptr->complocload[1] = finegrafptr->complocload[2] = finegrafptr->complocsize[0] = finegrafptr->complocsize[1] = finegrafptr->complocsize[2] = 0; #ifdef SCOTCH_DEBUG_VDGRAPH2 memSet (finegrafptr->partgsttax + finegrafptr->s.baseval, 3, finegrafptr->s.vertgstnbr * sizeof (GraphPart)); /* Mark all vertices as unvisited */ #endif /* SCOTCH_DEBUG_VDGRAPH2 */ memSet (vsndcnttab, 0, ((byte *) srcvdattab) - ((byte *) vsndcnttab)); /* TRICK: Assume process has nothing to send in vsndcnttab and ssnddattab */ if (reduglbtab[2] == (Gnum) coargrafptr->s.prockeyval) { /* If we belong to the group of the lead process, we must browse and send local data */ Gnum fineveloval; Gnum finevertsndnbr1; Gnum finevertsndnbr2; Gnum finevertglbmin; Gnum finevertglbmax; Gnum finevertglbnnd; Gnum vsnddatnbr; Gnum vsnddatnum; Gnum vsnddattmp; const GraphPart * restrict const coarpartgsttax = coargrafptr->partgsttax; fineveloval = 1; /* Assume no vertex loads */ finevertglbmin = finegrafptr->s.procvrttab[finegrafptr->s.proclocnum]; finevertglbmax = finegrafptr->s.procvrttab[finegrafptr->s.proclocnum + 1]; finecomplocload0 = finecomplocload2 = finecomplocsize1 = finecomplocsize2 = 0; for (coarvertnum = coargrafptr->s.baseval, vsnddatnbr = 0; coarvertnum < coargrafptr->s.vertlocnnd; coarvertnum ++) { Gnum finevertglbnum; GraphPart coarpartval; coarpartval = coarpartgsttax[coarvertnum]; #ifdef SCOTCH_DEBUG_VDGRAPH2 if ((coarpartval < 0) || (coarpartval > 2)) { errorPrint ("vdgraphSeparateMlUncoarsen: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ finevertglbnum = coarmulttax[coarvertnum].vertglbnum[0]; while (1) { /* Loop on both fine vertices of multinode */ Gnum finepartval; finepartval = (Gnum) coarpartval; if ((finevertglbnum >= finevertglbmin) && (finevertglbnum < finevertglbmax)) { /* Vertex is a local one */ #ifdef SCOTCH_DEBUG_VDGRAPH2 if (finepartglbtax[finevertglbnum] != 3) { errorPrint ("vdgraphSeparateMlUncoarsen: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ finepartglbtax[finevertglbnum] = coarpartval; finecomplocsize1 += finepartval & 1; /* One extra vertex created in part 1 if (coarpartval == 1) */ if (fineveloglbtax != NULL) fineveloval = fineveloglbtax[finevertglbnum]; if (coarpartval == 2) { finecomplocload2 += fineveloval; finefronloctab[finecomplocsize2 ++] = finevertglbnum - finevertlocadj; } else finecomplocload0 += fineveloval & (finepartval - 1); } else { /* Non local vertex */ vsnddattab[vsnddatnbr ++] = finevertglbnum; /* Store index and part */ vsnddattab[vsnddatnbr ++] = finepartval; } if (finevertglbnum == coarmulttax[coarvertnum].vertglbnum[1]) /* If single-vertex multinode or both vertices processed */ break; finevertglbnum = coarmulttax[coarvertnum].vertglbnum[1]; /* Process second multinode */ } } finegrafptr->complocload[0] = finecomplocload0; /* Account for local vertices already processed */ finegrafptr->complocload[2] = finecomplocload2; finegrafptr->complocsize[1] = finecomplocsize1; finegrafptr->complocsize[2] = finecomplocsize2; intSort2asc1 ((void *) vsnddattab, vsnddatnbr >> 1); /* Sort vertices to send by ascending global numbers */ finevertsndnbr1 = finevertsndnbr2 = 0; for (vsnddatnum = vsnddattmp = 0, procnum = 0, finevertglbnnd = finegrafptr->s.procvrttab[1]; vsnddatnum < vsnddatnbr; ) { Gnum finevertglbnum; Gnum finepartval; finevertglbnum = vsnddattab[vsnddatnum]; finepartval = vsnddattab[vsnddatnum + 1]; if (finevertglbnum >= finevertglbnnd) { Gnum finevertsndnbr; finevertsndnbr = (vsnddatnum - vsnddattmp) >> 1; finevertsndnbr2 >>= 1; vsndcnttab[procnum] = (int) finevertsndnbr; ssnddattab[3 * procnum] = finevertsndnbr - finevertsndnbr1 - finevertsndnbr2; ssnddattab[3 * procnum + 1] = finevertsndnbr1; ssnddattab[3 * procnum + 2] = finevertsndnbr2; vdgraphSeparateMlPack (vsnddattab, vsnddattmp >> 1, ssnddattab + (3 * procnum)); do finevertglbnnd = finegrafptr->s.procvrttab[(++ procnum) + 1]; while (finevertglbnum >= finevertglbnnd); vsnddattmp = vsnddatnum; /* Set startpoint for new neighbor */ finevertsndnbr1 = finevertsndnbr2 = 0; } vsnddatnum += 2; finevertsndnbr1 += finepartval & 1; /* Count number of vertices in part 1 */ finevertsndnbr2 += finepartval & 2; /* Count twice number of vertices in part 2 */ } finevertsndnbr2 >>= 1; /* Complete data for last receiver process */ vsndcnttab[procnum] = (int) ((vsnddatnum - vsnddattmp) >> 1); ssnddattab[3 * procnum] = ((vsnddatnum - vsnddattmp) >> 1) - finevertsndnbr1 - finevertsndnbr2; ssnddattab[3 * procnum + 1] = finevertsndnbr1; ssnddattab[3 * procnum + 2] = finevertsndnbr2; vdgraphSeparateMlPack (vsnddattab, (Gnum) vsnddattmp >> 1, ssnddattab + (3 * procnum)); #ifdef SCOTCH_DEBUG_VDGRAPH2 if ((ssnddattab[3 * finegrafptr->s.proclocnum] != 0) || /* One should never send something to itself */ (ssnddattab[3 * finegrafptr->s.proclocnum + 1] != 0) || (ssnddattab[3 * finegrafptr->s.proclocnum + 2] != 0)) { errorPrint ("vdgraphSeparateMlUncoarsen: internal error (4)"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ } if (MPI_Alltoall (ssnddattab, 3, GNUM_MPI, srcvdattab, 3, GNUM_MPI, finegrafptr->s.proccomm) != MPI_SUCCESS) { /* Exchange sizes */ errorPrint ("vdgraphSeparateMlUncoarsen: communication error (2)"); return (1); } vrcvcnttab = (int *) ssnddattab; /* TRICK: re-use ssnddattab */ vsnddsptab = vrcvcnttab + finegrafptr->s.procglbnbr; vrcvdsptab = vrcvcnttab + finegrafptr->s.procglbnbr * 2; for (procnum = 0, vsnddspnum = vrcvdspnum = 0; procnum < finegrafptr->s.procglbnbr; procnum ++) { /* Compute size of data to exchange */ vrcvcnttab[procnum] = (int) (srcvdattab[3 * procnum] + srcvdattab[3 * procnum + 1] + srcvdattab[3 * procnum + 2]); vrcvdsptab[procnum] = vrcvdspnum; vsnddsptab[procnum] = vsnddspnum; vrcvdspnum += vrcvcnttab[procnum]; vsnddspnum += vsndcnttab[procnum]; } if (MPI_Alltoallv (vsnddattab, vsndcnttab, vsnddsptab, GNUM_MPI, /* Exchange data */ vrcvdattab, vrcvcnttab, vrcvdsptab, GNUM_MPI, finegrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphSeparateMlUncoarsen: communication error (3)"); return (1); } finecomplocload0 = finegrafptr->complocload[0]; finecomplocload2 = finegrafptr->complocload[2]; finecomplocsize1 = finegrafptr->complocsize[1]; finecomplocsize2 = finegrafptr->complocsize[2]; for (procnum = 0, vrcvdatnum = 0; /* Process partition data per process number */ procnum < finegrafptr->s.procglbnbr; procnum ++) { Gnum vrcvdatnnd; vrcvdatnnd = vrcvdatnum + srcvdattab[3 * procnum]; if (fineveloglbtax != NULL) { for ( ; vrcvdatnum < vrcvdatnnd; vrcvdatnum ++) { Gnum finevertglbnum; finevertglbnum = vrcvdattab[vrcvdatnum]; #ifdef SCOTCH_DEBUG_VDGRAPH2 if (finepartglbtax[finevertglbnum] != 3) { errorPrint ("vdgraphSeparateMlUncoarsen: internal error (5)"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ finepartglbtax[finevertglbnum] = 0; finecomplocload0 += fineveloglbtax[finevertglbnum]; } } else { finecomplocload0 += srcvdattab[3 * procnum]; for ( ; vrcvdatnum < vrcvdatnnd; vrcvdatnum ++) { #ifdef SCOTCH_DEBUG_VDGRAPH2 if (finepartglbtax[vrcvdattab[vrcvdatnum]] != 3) { errorPrint ("vdgraphSeparateMlUncoarsen: internal error (6)"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ finepartglbtax[vrcvdattab[vrcvdatnum]] = 0; } } finecomplocsize1 += srcvdattab[3 * procnum + 1]; vrcvdatnnd = vrcvdatnum + srcvdattab[3 * procnum + 1]; for ( ; vrcvdatnum < vrcvdatnnd; vrcvdatnum ++) { #ifdef SCOTCH_DEBUG_VDGRAPH2 if (finepartglbtax[vrcvdattab[vrcvdatnum]] != 3) { errorPrint ("vdgraphSeparateMlUncoarsen: internal error (7)"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ finepartglbtax[vrcvdattab[vrcvdatnum]] = 1; } vrcvdatnnd = vrcvdatnum + srcvdattab[3 * procnum + 2]; if (fineveloglbtax != NULL) { for ( ; vrcvdatnum < vrcvdatnnd; vrcvdatnum ++) { Gnum finevertglbnum; finevertglbnum = vrcvdattab[vrcvdatnum]; #ifdef SCOTCH_DEBUG_VDGRAPH2 if (finepartglbtax[finevertglbnum] != 3) { errorPrint ("vdgraphSeparateMlUncoarsen: internal error (8)"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ finefronloctab[finecomplocsize2 ++] = finevertglbnum - finevertlocadj; finepartglbtax[finevertglbnum] = 2; finecomplocload2 += fineveloglbtax[finevertglbnum]; } } else { finecomplocload2 += srcvdattab[3 * procnum + 2]; for ( ; vrcvdatnum < vrcvdatnnd; vrcvdatnum ++) { Gnum finevertglbnum; finevertglbnum = vrcvdattab[vrcvdatnum]; #ifdef SCOTCH_DEBUG_VDGRAPH2 if (finepartglbtax[finevertglbnum] != 3) { errorPrint ("vdgraphSeparateMlUncoarsen: internal error (9)"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ finefronloctab[finecomplocsize2 ++] = finevertglbnum - finevertlocadj; finepartglbtax[finevertglbnum] = 2; } } } finegrafptr->complocload[0] = finecomplocload0; finegrafptr->complocload[1] = finegrafptr->s.velolocsum - finecomplocload0 - finecomplocload2; finegrafptr->complocload[2] = finecomplocload2; finegrafptr->complocsize[0] = finegrafptr->s.vertlocnbr - finecomplocsize1 - finecomplocsize2; finegrafptr->complocsize[1] = finecomplocsize1; finegrafptr->complocsize[2] = finecomplocsize2; memFree (vsndcnttab); /* Free group leader */ if (coargrafptr->s.procglbnbr != 0) memFree ((void *) (coarmulttax + coargrafptr->s.baseval)); reduloctab[0] = finegrafptr->complocload[0]; reduloctab[1] = finegrafptr->complocload[1]; reduloctab[2] = finegrafptr->complocload[2]; reduloctab[3] = finegrafptr->complocsize[0]; reduloctab[4] = finegrafptr->complocsize[1]; reduloctab[5] = finegrafptr->complocsize[2]; if (MPI_Allreduce (reduloctab, reduglbtab, 6, GNUM_MPI, MPI_SUM, finegrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphSeparateMlUncoarsen: communication error (4)"); return (1); } finegrafptr->compglbload[0] = reduglbtab[0]; finegrafptr->compglbload[1] = reduglbtab[1]; finegrafptr->compglbload[2] = reduglbtab[2]; finegrafptr->compglbsize[0] = reduglbtab[3]; finegrafptr->compglbsize[1] = reduglbtab[4]; finegrafptr->compglbsize[2] = reduglbtab[5]; finegrafptr->compglbloaddlt = reduglbtab[0] - reduglbtab[1]; #ifdef SCOTCH_DEBUG_VDGRAPH2 if (vdgraphCheck (finegrafptr) != 0) { errorPrint ("vdgraphSeparateMlUncoarsen: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ return (0); } /* This routine recursively performs the ** separation recursion. ** It returns: ** - 0 : if separator could be computed. ** - !0 : on error. */ static int vdgraphSeparateMl2 ( Vdgraph * restrict const grafptr, /* Vertex-separation graph */ const VdgraphSeparateMlParam * const paraptr) /* Method parameters */ { Vdgraph coargrafdat; DgraphCoarsenMulti * restrict coarmulttax; int o; if (grafptr->s.procglbnbr <= paraptr->seqnbr) { /* We must enter in another mode */ if (((o = vdgraphSeparateMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ ((o = vdgraphSeparateSt (grafptr, paraptr->stratseq)) != 0)) { #ifdef SCOTCH_DEBUG_VDGRAPH2 errorPrintW ("vdgraphSeparateMl2: cannot apply sequential strategy"); #endif /* SCOTCH_DEBUG_VDGRAPH2 */ } return (o); } if (vdgraphSeparateMlCoarsen (grafptr, &coargrafdat, &coarmulttax, paraptr) == 0) { o = (coargrafdat.s.procglbnbr == 0) ? 0 : vdgraphSeparateMl2 (&coargrafdat, paraptr); /* Apply recursion on coarsened graph if it exists */ if ((o == 0) && ((o = vdgraphSeparateMlUncoarsen (grafptr, &coargrafdat, coarmulttax)) == 0) && ((o = vdgraphSeparateSt (grafptr, paraptr->stratasc)) != 0)) { /* Apply ascending strategy if uncoarsening worked */ #ifdef SCOTCH_DEBUG_VDGRAPH2 errorPrintW ("vdgraphSeparateMl2: cannot apply ascending strategy"); #endif /* SCOTCH_DEBUG_VDGRAPH2 */ } if (coargrafdat.fronloctab == grafptr->fronloctab) /* If coarse graph shares fronloctab with fine graph */ coargrafdat.fronloctab = NULL; /* Prevent fronloctab of fine graph from being freed */ vdgraphExit (&coargrafdat); if (o == 0) /* If multi-level failed, apply low strategy as fallback */ return (o); } if (((o = vdgraphSeparateMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ ((o = vdgraphSeparateSt (grafptr, paraptr->stratlow)) != 0)) { /* Apply low strategy */ #ifdef SCOTCH_DEBUG_VDGRAPH2 errorPrintW ("vdgraphSeparateMl2: cannot apply low strategy"); #endif /* SCOTCH_DEBUG_VDGRAPH2 */ } return (o); } /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the muti-level separation. ** It returns: ** - 0 : if separator could be computed. ** - 1 : on error. */ int vdgraphSeparateMl ( Vdgraph * const grafptr, /*+ Vertex-separation graph +*/ const VdgraphSeparateMlParam * const paraptr) /*+ Method parameters +*/ { Gnum levlnum; /* Save value for graph level */ int o; levlnum = grafptr->levlnum; /* Save graph level */ grafptr->levlnum = 0; /* Initialize coarsening level */ o = vdgraphSeparateMl2 (grafptr, paraptr); /* Perform multi-level separation */ grafptr->levlnum = levlnum; /* Restore graph level */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/parser_ll.l0000644000175300017530000002234311631334325021277 0ustar hazelscthazelsct%{ /* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : parser_ll.l **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the lexical parser **/ /** which processes strategy strings. **/ /** **/ /** DATES : # Version 3.1 : from : 07 nov 1995 **/ /** to 23 aug 1996 **/ /** # Version 3.2 : from : 24 sep 1996 **/ /** to 05 jun 1997 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 11 sep 2001 **/ /** # Version 4.0 : from : 20 dec 2001 **/ /** to 23 dec 2001 **/ /** # Version 5.1 : from : 09 jun 2009 **/ /** to 24 jul 2011 **/ /** **/ /** NOTES : # In order for flex to read its input **/ /** with getc() instead of fread, we set **/ /** YY_ALWAYS_INTERACTIVE to 1. This may **/ /** not always work with future releases. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define PARSER_LL #include "module.h" #include "common.h" #undef INTEGER /* In case someone defined them */ #undef DOUBLE #include "parser.h" #include "parser_ll.h" #include "parser_yy.h" #include "parser_ly.h" /*+ Definitions produced by yacc +*/ /* Assume no interactive parsing. */ #ifdef X_OSDOS /* Available only with MKS LEX */ #ifdef YY_INTERACTIVE #undef YY_INTERACTIVE #endif /* YY_INTERACTIVE */ #define YY_INTERACTIVE 0 #endif /* X_OSDOS */ #ifdef FLEX_SCANNER #define YY_ALWAYS_INTERACTIVE 1 /* Set the parser as interactive and read one char at a time */ #define YY_INPUT(buf,result,max_size) { int c = stratParserInput (); result = (c == 0) ? YY_NULL : ((buf)[0] = c, 1); } #else /* FLEX_SCANNER */ #undef getc /* Redirect I/O functions */ #define getc yygetc #undef yygetc #define yygetc(stream) stratParserInput () #endif /* FLEX_SCANNER */ #define YY_NO_UNPUT /* No prototype for yyunput as not defined */ #define YY_SKIP_YYWRAP /* No prototype for yywrap as defined as macro */ #define yywrap() (1) /* Always return end-of-file on end-of-string */ /* ** The static variables. */ static const char * stratparserstringptr; /* Pointer to the string to parse */ %} IDENT [A-Za-z][0-9A-Za-z]* INTEGER [0-9]+ FLOAT [0-9]+(\.[0-9]+)?([Ee][-+]?[0-9]+)? STRING \"[^\"]*\" %s lstrat %s lparam %s lparamcase %s lparamdouble %s lparamint %s lparamstring %s ltest %% [0-9A-Za-z] { strncpy (yylval.STRING, yytext, PARSERSTRINGLEN); yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; return (METHODNAME); } {IDENT} { strncpy (yylval.STRING, yytext, PARSERSTRINGLEN); yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; return (PARAMNAME); } [0-9A-Za-z] { yylval.CASEVAL = yytext[0]; return (VALCASE); } ({FLOAT}|{INTEGER}) { yylval.DOUBLE = atof (yytext); return (VALDOUBLE); } {INTEGER} { yylval.INTEGER = (INT) atol (yytext); return (VALINT); } {FLOAT} { yylval.INTEGER = (INT) atof (yytext); /* FLOAT is put after so that INTEGER can be matched */ return (VALINT); } {STRING} { yytext[yyleng - 1] = '\0'; /* Remove the heading and trailing \" */ strncpy (yylval.STRING, yytext + 1, PARSERSTRINGLEN); yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; return (VALSTRING); } {INTEGER} { yylval.INTEGER = (INT) atol (yytext); return (VALINT); } {FLOAT} { yylval.DOUBLE = atof (yytext); return (VALDOUBLE); } {IDENT} { strncpy (yylval.STRING, yytext, PARSERSTRINGLEN); yylval.STRING[PARSERSTRINGLEN - 1] = '\0'; return (PARAMNAME); } [ \t\n]* ; . return (yytext[0]); %% /*******************************************/ /* */ /* These routines handle data input to the */ /* lexical analyzer. */ /* */ /*******************************************/ /* This routine initializes the ** lexical analyzer. ** It returns: ** - VOID : in all cases. */ void stratParserInit ( const char * const string) /*+ Strategy string to parse +*/ { #ifdef FLEX_SCANNER yyrestart (yyin); /* (Re-)initialize the parser */ #endif /* FLEX_SCANNER */ stratParserSelect (VALSTRAT); /* Begin with a strategy */ stratparserstringptr = string; /* Point to beginning of string */ } /* This routine reads a single character ** from the input string. ** It returns: ** - 0 : if end of string reached. ** - !0 : character from string. */ static int stratParserInput () { if (*stratparserstringptr == '\0') /* If end-of-string reached */ return (0); /* Return end-of-file token */ else /* Else return the character */ return ((int) (unsigned char) *stratparserstringptr ++); } /* This routine returns the pointer to the ** remaining part of the string. */ const char * stratParserRemain () { return (stratparserstringptr); } /* This routine selects the sub-parser ** to parse the input. ** It returns: ** - VOID : in all cases. */ void stratParserSelect ( unsigned int type) { switch (type) { case VALCASE : BEGIN lparamcase; break; case VALDOUBLE : BEGIN lparamdouble; break; case VALINT : BEGIN lparamint; break; case VALSTRING : BEGIN lparamstring; break; case VALPARAM : BEGIN lparam; break; case VALSTRAT : BEGIN lstrat; break; case VALTEST : BEGIN ltest; break; } } scotch-5.1.12b.dfsg/src/libscotch/library_order.c0000644000175300017530000000621311631334325022140 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_order.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains miscellaneous **/ /** routines for handling centralized **/ /** graph orderings. **/ /** **/ /** DATES : # Version 5.1 : from : 17 nov 2010 **/ /** to 17 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /*****************************************/ /* */ /* These routines are the C API for */ /* ordering structure handling routines. */ /* */ /*****************************************/ /*+ This routine reserves a memory area *** of a size sufficient to store a *** graph ordering structure. *** It returns: *** - !NULL : if the initialization succeeded. *** - NULL : on error. +*/ SCOTCH_Ordering * SCOTCH_orderAlloc () { return ((SCOTCH_Ordering *) memAlloc (sizeof (SCOTCH_Ordering))); } scotch-5.1.12b.dfsg/src/libscotch/vdgraph_check.c0000644000175300017530000002455511631334325022102 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_check.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the distributed **/ /** separator graph consistency checking **/ /** routine. **/ /** **/ /** DATES : # Version 5.0 : from : 07 feb 2006 **/ /** to 01 mar 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VDGRAPH #include "module.h" #include "common.h" #include "dgraph.h" #include "vdgraph.h" /*************************/ /* */ /* These routines handle */ /* separator graphs. */ /* */ /*************************/ /* This routine checks the consistency ** of the given distributed separator graph. ** It returns: ** - 0 : if graph data are consistent. ** - !0 : on error. */ int vdgraphCheck ( const Vdgraph * const grafptr) { Dgraph grafdat; /* Dummy graph for ghost edge array */ MPI_Comm proccomm; /* Graph communicator */ Gnum vertnum; /* Number of current vertex */ Gnum fronnum; /* Number of frontier vertex */ Gnum complocload[3]; Gnum complocsize[3]; Gnum commcut[3]; GraphPart * restrict partgsttax; Gnum reduloctab[11]; /* Arrays for reductions */ Gnum reduglbtab[11]; int cheklocval; /* Local consistency flag */ int chekglbval; /* Global consistency flag */ proccomm = grafptr->s.proccomm; if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize */ errorPrint ("vdgraphCheck: communication error (1)"); return (1); } cheklocval = 0; /* Assume everything is all right */ if ((grafptr->compglbload[0] + grafptr->compglbload[1] + grafptr->compglbload[2]) != grafptr->s.veloglbsum) { errorPrint ("vdgraphCheck: invalid global load sum"); cheklocval = 1; } if (grafptr->compglbloaddlt != (grafptr->compglbload[0] - grafptr->compglbload[1])) { errorPrint ("vdgraphCheck: invalid global balance"); cheklocval |= 2; } if ((grafptr->compglbsize[0] + grafptr->compglbsize[1] + grafptr->compglbsize[2]) != grafptr->s.vertglbnbr) { errorPrint ("vdgraphCheck: invalid global size sum"); cheklocval |= 4; } if ((grafptr->complocsize[0] + grafptr->complocsize[1] + grafptr->complocsize[2]) != grafptr->s.vertlocnbr) { errorPrint ("vdgraphCheck: invalid local size sum"); cheklocval |= 8; } if ((grafptr->complocsize[2] < 0) || (grafptr->complocsize[2] > grafptr->s.vertlocnbr)) { errorPrint ("vdgraphCheck: invalid number of local frontier vertices"); cheklocval |= 16; } for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertlocnnd; vertnum ++) { if (grafptr->partgsttax[vertnum] > 2) { errorPrint ("vdgraphCheck: invalid local part array"); cheklocval |= 32; break; } } for (fronnum = 0; fronnum < grafptr->complocsize[2]; fronnum ++) { Gnum vertnum; vertnum = grafptr->fronloctab[fronnum]; if ((vertnum < grafptr->s.baseval) || (vertnum >= grafptr->s.vertlocnnd)) { errorPrint ("vdgraphCheck: invalid vertex index in frontier array"); cheklocval |= 64; break; } if (grafptr->partgsttax[vertnum] != 2) { errorPrint ("vdgraphCheck: invalid vertex in frontier array"); cheklocval |= 64; break; } } grafdat = grafptr->s; /* Copy minimal distributed graph data */ if (dgraphGhst (&grafdat) != 0) { /* Create ghost edge array if did not exist */ errorPrint ("vdgraphCheck: cannot compute ghost edge array"); cheklocval |= 128; } if ((partgsttax = memAlloc (grafdat.vertgstnbr * sizeof (byte))) == NULL) { errorPrint ("vdgraphCheck: out of memory"); cheklocval |= 256; } reduloctab[0] = grafptr->compglbload[0]; reduloctab[1] = - grafptr->compglbload[0]; reduloctab[2] = grafptr->compglbload[1]; reduloctab[3] = - grafptr->compglbload[1]; reduloctab[4] = grafptr->compglbload[2]; reduloctab[5] = - grafptr->compglbload[2]; reduloctab[6] = grafptr->compglbsize[2]; reduloctab[7] = - grafptr->compglbsize[2]; reduloctab[8] = grafptr->levlnum; reduloctab[9] = - grafptr->levlnum; reduloctab[10] = cheklocval; if (MPI_Allreduce (reduloctab, reduglbtab, 11, GNUM_MPI, MPI_MAX, proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphCheck: communication error (2)"); return (1); } if (reduglbtab[10] != 0) { /* Return from previous errors */ if (partgsttax != NULL) memFree (partgsttax); return (1); } if ((reduglbtab[1] != - reduglbtab[0]) || (reduglbtab[3] != - reduglbtab[2]) || (reduglbtab[5] != - reduglbtab[4]) || (reduglbtab[7] != - reduglbtab[6]) || (reduglbtab[9] != - reduglbtab[8])) { errorPrint ("vdgraphCheck: inconsistent global graph data"); return (1); } memCpy (partgsttax, grafptr->partgsttax + grafptr->s.baseval, grafptr->s.vertlocnbr); /* Copy local part data */ dgraphHaloSync (&grafdat, partgsttax, GRAPHPART_MPI); /* Spread yet unbased halo part data across neighboring processes */ partgsttax -= grafptr->s.baseval; complocload[0] = complocload[1] = complocload[2] = 0; complocsize[0] = complocsize[1] = complocsize[2] = 0; for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertlocnnd; vertnum ++) { int partnum; /* Part of current vertex */ Gnum edgenum; /* Number of current edge */ partnum = (int) partgsttax[vertnum]; complocload[partnum] += (grafptr->s.veloloctax == NULL) ? 1 : grafptr->s.veloloctax[vertnum]; complocsize[partnum] ++; commcut[0] = commcut[1] = commcut[2] = 0; for (edgenum = grafptr->s.vertloctax[vertnum]; edgenum < grafptr->s.vendloctax[vertnum]; edgenum ++) { if (grafdat.edgegsttax[edgenum] < grafptr->s.vertlocnnd) /* Check only for local ends, as ghost part might be inaccurate */ commcut[partgsttax[grafdat.edgegsttax[edgenum]]] ++; } if (partnum != 2) { if (commcut[1 - partnum] != 0) { errorPrint ("vdgraphCheck: vertex should be in separator (%ld)", (long) vertnum); cheklocval = 1; break; } } } if (grafptr->s.edgegsttax != grafdat.edgegsttax) /* If ghost edge array was allocated here, free it manually */ memFree (grafdat.edgegsttax + grafptr->s.baseval); if (grafptr->s.procsidtab != grafdat.procsidtab) /* The same for procsidtab */ memFree (grafdat.procsidtab); memFree (partgsttax + grafptr->s.baseval); if ((cheklocval == 0) && ((complocsize[0] != grafptr->complocsize[0]) || (complocsize[1] != grafptr->complocsize[1]) || (complocsize[2] != grafptr->complocsize[2]))) { errorPrint ("vgraphCheck: invalid local part sizes"); cheklocval = 1; } reduloctab[0] = complocload[0]; reduloctab[1] = complocload[1]; reduloctab[2] = complocload[2]; reduloctab[3] = complocsize[0]; reduloctab[4] = complocsize[1]; reduloctab[5] = complocsize[2]; reduloctab[6] = cheklocval; if (MPI_Allreduce (reduloctab, reduglbtab, 7, GNUM_MPI, MPI_SUM, proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphCheck: communication error (3)"); return (1); } if (reduglbtab[6] != 0) /* Return from previous errors */ return (1); if ((grafptr->compglbload[0] != reduglbtab[0]) || (grafptr->compglbload[1] != reduglbtab[1]) || (grafptr->compglbload[2] != reduglbtab[2])) { errorPrint ("vdgraphCheck: invalid global part loads"); cheklocval = 1; } if ((grafptr->compglbsize[0] != reduglbtab[3]) || (grafptr->compglbsize[1] != reduglbtab[4]) || (grafptr->compglbsize[2] != reduglbtab[5])) { errorPrint ("vgraphCheck: invalid global part sizes"); cheklocval = 1; } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphCheck: communication error (4)"); return (1); } return (chekglbval); } scotch-5.1.12b.dfsg/src/libscotch/arch_vhcub.c0000644000175300017530000001736511631334325021417 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_vhcub.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the variable-sized **/ /** hypercube target architecture. **/ /** **/ /** DATES : # Version 3.4 : from : 08 nov 2001 **/ /** to 08 nov 2001 **/ /** # Version 4.0 : from : 04 nov 2003 **/ /** to 04 nov 2003 **/ /** # Version 5.1 : from : 21 jan 2008 **/ /** to 27 feb 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define ARCH_VHCUB #include "module.h" #include "common.h" #include "arch.h" #include "arch_vhcub.h" /********************************/ /* */ /* These are the variable-sized */ /* hypercube handling routines. */ /* */ /********************************/ /* This function returns the smallest number ** of terminal domain included in the given ** domain. */ ArchDomNum archVhcubDomNum ( const ArchVhcub * const archptr, const ArchVhcubDom * const domptr) { return (domptr->termnum); /* Return terminal number */ } /* This function returns the terminal domain associated ** with the given terminal number in the architecture. ** It returns: ** - 0 : if label is valid and domain has been updated. ** - 1 : if label is invalid. ** - 2 : on error. */ int archVhcubDomTerm ( const ArchVhcub * const archptr, ArchVhcubDom * const domptr, const ArchDomNum domnum) { Anum termnum; Anum termlvl; if (domnum != ARCHDOMNOTTERM) { /* If valid label */ domptr->termnum = domnum; /* Set the domain */ for (termnum = domnum, termlvl = 0; termnum > 1; /* Compute level */ termnum >>= 1, termlvl ++) ; domptr->termlvl = termnum; /* Set level */ return (0); } return (1); /* Cannot set domain */ } /* This function returns the number of ** elements in the domain. */ Anum archVhcubDomSize ( const ArchVhcub * const archptr, const ArchVhcubDom * const domptr) { return (1); /* All domains have same size for bipartitioning */ } /* This function returns the average ** distance between two subdomains. */ Anum archVhcubDomDist ( const ArchVhcub * const archptr, const ArchVhcubDom * const dom0ptr, const ArchVhcubDom * const dom1ptr) { Anum dom0num; Anum dom1num; Anum distval; if (dom0ptr->termlvl > dom1ptr->termlvl) { dom0num = dom0ptr->termnum >> (dom0ptr->termlvl - dom1ptr->termlvl); dom1num = dom1ptr->termnum; distval = (dom0ptr->termlvl - dom1ptr->termlvl) >> 1; /* One half of unknown bits */ } else { dom0num = dom0ptr->termnum; dom1num = dom1ptr->termnum >> (dom1ptr->termlvl - dom0ptr->termlvl); distval = (dom1ptr->termlvl - dom0ptr->termlvl) >> 1; /* One half of unknown bits */ } for (dom0num ^= dom1num; dom0num != 0; /* Compute number of bit differences */ distval += (dom0num & 1), dom0num >>= 1) ; return (distval); } /* This function sets the biggest ** domain available for this ** architecture. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archVhcubDomFrst ( const ArchVhcub * const archptr, ArchVhcubDom * restrict const domptr) { domptr->termlvl = 0; /* First terminal number */ domptr->termnum = 1; return (0); } /* This routine reads domain information ** from the given stream. ** It returns: ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archVhcubDomLoad ( const ArchVhcub * const archptr, ArchVhcubDom * restrict const domptr, FILE * const stream) { if ((intLoad (stream, &domptr->termlvl) != 1) || (intLoad (stream, &domptr->termnum) != 1) || (domptr->termlvl < 0) || (domptr->termnum < (1 << domptr->termlvl)) || (domptr->termnum >= (1 << (domptr->termlvl + 1)))) { errorPrint ("archVhcubDomLoad: bad input"); return (1); } return (0); } /* This routine saves domain information ** to the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int archVhcubDomSave ( const ArchVhcub * const archptr, const ArchVhcubDom * const domptr, FILE * const stream) { if (fprintf (stream, ANUMSTRING " " ANUMSTRING " ", (Anum) domptr->termlvl, (Anum) domptr->termnum) == EOF) { errorPrint ("archVhcubDomSave: bad output"); return (1); } return (0); } /* This function splits a domain ** into two subdomains. ** It returns: ** - 0 : if bipartitioning succeeded. ** - 2 : on error. */ int archVhcubDomBipart ( const ArchVhcub * const archptr, const ArchVhcubDom * const domptr, ArchVhcubDom * restrict const dom0ptr, ArchVhcubDom * restrict const dom1ptr) { dom0ptr->termlvl = /* Bipartition the domain */ dom1ptr->termlvl = domptr->termlvl + 1; dom0ptr->termnum = domptr->termnum << 1; dom1ptr->termnum = dom0ptr->termnum + 1; return ((dom1ptr->termnum < domptr->termnum) ? 2 : 0); /* Return error on overflow */ } /* This function creates the MPI_Datatype for ** variable-sized hypercube domains. ** It returns: ** - 0 : if type could be created. ** - 1 : on error. */ #ifdef SCOTCH_PTSCOTCH int archVhcubDomMpiType ( const ArchVhcub * const archptr, MPI_Datatype * const typeptr) { MPI_Type_contiguous (2, ANUM_MPI, typeptr); return (0); } #endif /* SCOTCH_PTSCOTCH */ scotch-5.1.12b.dfsg/src/libscotch/common.c0000644000175300017530000001131311631334325020566 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : common.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** David GOUDIN **/ /** Pascal HENON **/ /** Pierre RAMET **/ /** Yves SECRETAN (v5.1) **/ /** **/ /** FUNCTION : Part of a parallel direct block solver. **/ /** These lines are common routines used **/ /** by all modules. **/ /** **/ /** DATES : # Version 0.0 : from : 08 may 1998 **/ /** to 14 sep 1998 **/ /** # Version 2.0 : from : 27 sep 2004 **/ /** to 27 sep 2004 **/ /** # Version 5.1 : from : 27 jun 2010 **/ /** to 23 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define COMMON #ifndef COMMON_NOMODULE #include "module.h" #endif /* COMMON_NOMODULE */ #include "common.h" /*******************/ /* */ /* Timing routine. */ /* */ /*******************/ double clockGet (void) { #ifdef MPI_INT return (MPI_Wtime ()); #else /* MPI_INT */ #if defined COMMON_WINDOWS double res = 0.0; LARGE_INTEGER fq; if (QueryPerformanceFrequency (&fq) == 0) { FILETIME ft; ULARGE_INTEGER t; GetSystemTimeAsFileTime (&ft); t.LowPart = ft.dwLowDateTime; t.HighPart = ft.dwHighDateTime; res = (double) t.QuadPart / 10000000.0; } else { LARGE_INTEGER pc; QueryPerformanceCounter (&pc); res = (double) pc.QuadPart / (double) fq.QuadPart; } return (res); #elif defined COMMON_TIMING_OLD /* Old Unix timing routine */ struct rusage data; getrusage (RUSAGE_SELF, &data); return (((double) data.ru_utime.tv_sec + (double) data.ru_stime.tv_sec) + ((double) data.ru_utime.tv_usec + (double) data.ru_stime.tv_usec) * 1.0e-6L); #else /* COMMON_TIMING_OLD */ struct timespec tp; clock_gettime (CLOCK_REALTIME, &tp); /* Elapsed time */ return ((double) tp.tv_sec + (double) tp.tv_nsec * 1.0e-9L); #endif /* COMMON_TIMING_OLD */ #endif /* MPI_INT */ } /***************************/ /* */ /* Usage printing routine. */ /* */ /***************************/ void usagePrint ( FILE * const stream, const char ** const data) { const char ** cptr; fprintf (stream, "Usage is:\n"); for (cptr = data; *cptr != NULL; cptr ++) fprintf (stream, " %s\n", *cptr); } scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_cp.h0000644000175300017530000001056511631334325022441 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_cp.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the graph compression **/ /** ordering routine. **/ /** **/ /** DATES : # Version 3.2 : from : 29 aug 1998 **/ /** to : 09 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to : 03 jan 1999 **/ /** # Version 4.0 : from : 01 jan 2003 **/ /** to : 01 jan 2003 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to : 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Prime number for hashing vertex numbers. +*/ #define HGRAPHORDERCPHASHPRIME 17 /* Prime number */ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HgraphOrderCpParam_ { double comprat; /*+ Compression ratio threshold +*/ Strat * stratcpr; /*+ Compressed subgraph ordering strategy +*/ Strat * stratunc; /*+ Uncompressed subgraph ordering strategy +*/ } HgraphOrderCpParam; /*+ This structure holds fine neighbor hashing data. +*/ typedef struct HgraphOrderCpHash_ { Gnum vertnum; /*+ Origin vertex (i.e. pass) number +*/ Gnum vertend; /*+ Adjacent end vertex number +*/ } HgraphOrderCpHash; /*+ This structure holds coarse neighbor mate data. +*/ typedef struct HgraphOrderCpMate_ { Gnum coarvertend; /*+ Adjacent coarse end vertex number +*/ Gnum finevertend; /*+ Adjacent end vertex number +*/ } HgraphOrderCpMate; /* ** The function prototypes. */ #ifndef HGRAPH_ORDER_CP #define static #endif int hgraphOrderCp (const Hgraph * const, Order * const, const Gnum, OrderCblk * const, const HgraphOrderCpParam * const); static Gnum hgraphOrderCpTree (const Gnum * const, const Gnum * const, OrderCblk * const, Gnum); #undef static scotch-5.1.12b.dfsg/src/libscotch/hgraph.h0000644000175300017530000001073411631334325020562 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the source halo graph structure. **/ /** **/ /** DATES : # Version 4.0 : from : 02 jan 2002 **/ /** to 30 apr 2004 **/ /** # Version 5.0 : from : 19 dec 2006 **/ /** to 19 dec 2006 **/ /** # Version 5.1 : from : 04 nov 2010 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ #define HGRAPH_H /* ** The defines. */ /*+ Graph option flags. +*/ #define HGRAPHFREEVNHD 0x0400 /* Free vnhdtab array */ #define HGRAPHFREETABS (GRAPHFREETABS | HGRAPHFREEVNHD) /* ** The type and structure definitions. */ /*+ Halo graph structure. +*/ typedef struct Hgraph_ { Graph s; /*+ Source graph +*/ Gnum vnohnbr; /*+ Number of non-halo vertices +*/ Gnum vnohnnd; /*+ Based number of first halo vertex in graph (s.vertnnd if none) +*/ Gnum * vnhdtax; /*+ End vertex array for non-halo vertices [vnohnbr, based] +*/ Gnum vnlosum; /*+ Sum of vertex loads for non-halo vertices only (<= s.velosum) +*/ Gnum enohnbr; /*+ Number of non-halo edges +*/ Gnum enohsum; /*+ Sum of non-halo edge loads +*/ Gnum levlnum; /*+ Nested dissection level +*/ } Hgraph; /* ** The function prototypes. */ #ifndef HGRAPH #define static #endif int hgraphInit (Hgraph * const); void hgraphExit (Hgraph * const); void hgraphFree (Hgraph * const); Gnum hgraphBase (Hgraph * const, const Gnum); int hgraphInduceList (const Hgraph * const, const VertList * const, const Gnum, Hgraph * const); int hgraphCheck (const Hgraph *); #undef static scotch-5.1.12b.dfsg/src/libscotch/mesh_io_scot.c0000644000175300017530000002772611631334325021770 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mesh_io_scot.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the I/O routines **/ /** for handling the Scotch mesh format. **/ /** **/ /** DATES : # Version 4.0 : from : 19 jan 2004 **/ /** to 19 jan 2004 **/ /** # Version 5.0 : from : 13 sep 2006 **/ /** to 27 feb 2008 **/ /** # Version 5.1 : from : 11 aug 2010 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MESH_IO_SCOT #include "module.h" #include "common.h" #include "geom.h" #include "graph.h" #include "mesh.h" /* This routine loads the geometrical mesh ** in the Scotch graph format, and allocates ** the proper structures. ** - 0 : on success. ** - !0 : on error. */ int meshGeomLoadScot ( Mesh * restrict const meshptr, /* Graph to load */ Geom * restrict const geomptr, /* Geometry to load */ FILE * const filesrcptr, /* Topological data */ FILE * const filegeoptr, /* No use */ const char * const dataptr) /* No use */ { #ifdef DEAD_CODE /* TODO */ double * restrict coorfiletab; /* Pointer to geometric data read from file */ MeshGeomScotSort * restrict coorsorttab; /* Pointer to geometric data sorting array */ int coorsortflag; /* Flag set if geometric data sorted by label */ Gnum coornbr; /* Number of geometric coordinates in file */ Gnum coornum; /* Number of current coordinate */ MeshGeomScotSort * restrict vertsorttab; /* Pointer to graph sorting array */ int vertsortflag; /* Flag set if graph data sorted by label */ Gnum vertnum; /* Current graph vertex */ Gnum dimnnbr; /* Dimension of geometry file */ int o; if (filesrcptr != NULL) { if (graphLoad (meshptr, filesrcptr, -1, 0) != 0) return (1); } if (filegeoptr == NULL) return (0); if ((intLoad (filegeoptr, &dimnnbr) != 1) || /* Read type and number of geometry items */ (intLoad (filegeoptr, &coornbr) != 1) || (dimnnbr < 1) || (dimnnbr > 3) || (dimnnbr < 1)) { errorPrint ("meshGeomLoadScot: bad input (1)"); return (1); } if ((filesrcptr != NULL) && (meshptr->vertnbr != coornbr)) { errorPrint ("meshGeomLoadScot: inconsistent number of vertices"); return (1); } if (meshptr->vertnbr == 0) return (0); if ((geomptr->geomtab == NULL) && /* Allocate geometry if necessary */ ((geomptr->geomtab = (double *) memAlloc (meshptr->vertnbr * dimnnbr * sizeof (double))) == NULL)) { errorPrint ("meshGeomLoadScot: out of memory (1)"); return (1); } if (memAllocGroup ((void **) &coorfiletab, (size_t) (coornbr * dimnnbr * sizeof (double)), &coorsorttab, (size_t) (coornbr * sizeof (MeshGeomScotSort)), &vertsorttab, (size_t) (meshptr->vertnbr * sizeof (MeshGeomScotSort)), NULL) == NULL) { errorPrint ("meshGeomLoadScot: out of memory (2)"); return (1); } o = 0; coorsortflag = 1; /* Assume geometry data sorted */ for (coornum = 0; (o == 0) && (coornum < coornbr); coornum ++) { Gnum vlblnum; o = 1 - intLoad (filegeoptr, &vlblnum); coorsorttab[coornum].labl = vlblnum; coorsorttab[coornum].num = coornum; if ((coornum > 0) && /* Check if geometry data sorted */ (coorsorttab[coornum].labl < coorsorttab[coornum - 1].labl)) coorsortflag = 0; /* Geometry data not sorted */ o |= 1 - fscanf (filegeoptr, "%lf", /* Read X coordinate */ &coorfiletab[coornum * dimnnbr]); if (dimnnbr > 1) { o |= 1 - fscanf (filegeoptr, "%lf", /* Read Y coordinate */ &coorfiletab[(coornum * dimnnbr) + 1]); if (dimnnbr > 2) o |= 1 - fscanf (filegeoptr, "%lf", /* Read Z coordinate */ &coorfiletab[(coornum * dimnnbr) + 2]); } } if (o != 0) { errorPrint ("meshGeomLoadScot: bad input (2)"); memFree (coorfiletab); /* Free group leader */ return (1); } if (coorsortflag != 1) /* If geometry data not sorted */ intSort2asc1 (coorsorttab, coornbr); /* Sort sort area by ascending labels */ for (coornum = 1; coornum < coornbr; coornum ++) { /* Check geometric data integrity */ if (coorsorttab[coornum].labl == coorsorttab[coornum - 1].labl) { errorPrint ("meshGeomLoadScot: duplicate vertex label"); memFree (coorfiletab); /* Free group leader */ return (1); } } if (meshptr->vlbltax != NULL) { /* If graph has vertex labels */ vertsortflag = 1; /* Assume graph data sorted */ for (vertnum = 0; vertnum < meshptr->vertnbr; vertnum ++) { vertsorttab[vertnum].labl = meshptr->vlbltax[vertnum + meshptr->baseval]; vertsorttab[vertnum].num = vertnum; if ((vertnum > 0) && /* Check if graph data sorted */ (vertsorttab[vertnum].labl < vertsorttab[vertnum - 1].labl)) vertsortflag = 0; /* Graph data not sorted */ } if (vertsortflag != 1) /* If graph data not sorted */ intSort2asc1 (vertsorttab, meshptr->vertnbr); /* Sort sort area by ascending labels */ } else { /* Graph does not have vertex labels */ for (vertnum = 0; vertnum < meshptr->vertnbr; vertnum ++) vertsorttab[vertnum].labl = vertsorttab[vertnum].num = vertnum; } for (coornum = vertnum = 0; vertnum < meshptr->vertnbr; vertnum ++) { /* For all vertices in graph */ while ((coornum < coornbr) && (coorsorttab[coornum].labl < vertsorttab[vertnum].labl)) coornum ++; /* Search geometry vertex with same label */ if ((coornum >= coornbr) || (coorsorttab[coornum].labl > vertsorttab[vertnum].labl)) { /* If label does not exist */ errorPrint ("meshGeomLoadScot: vertex geometry data not found (%d)", vertsorttab[vertnum].labl); memFree (coorfiletab); /* Free group leader */ return (1); } memCpy (&geomptr->geomtab[vertsorttab[vertnum].num * dimnnbr], &coorfiletab[coorsorttab[coornum ++].num * dimnnbr], dimnnbr * sizeof (double)); } memFree (coorfiletab); /* Free group leader */ #endif /* DEAD_CODE */ return (0); } /* This routine saves the source mesh ** in the Scotch mesh and geometry formats. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int meshGeomSaveScot ( const Mesh * restrict const meshptr, /* Mesh to save */ const Geom * restrict const geomptr, /* Geometry to save */ FILE * const filesrcptr, /* Topological data */ FILE * const filegeoptr, /* No use */ const char * const dataptr) /* No use */ { Gnum vnodnum; int dimnnbr; int o; if (filesrcptr != NULL) { if (meshSave (meshptr, filesrcptr) != 0) /* Save mesh structural data */ return (1); } dimnnbr = geomptr->dimnnbr; o = 0; if (geomptr->geomtab != NULL) { /* If geometrical data present */ o = (fprintf (filegeoptr, GNUMSTRING "\n" GNUMSTRING "\n", /* Output file header */ (Gnum) geomptr->dimnnbr, (Gnum) meshptr->vnodnbr) == EOF); switch (dimnnbr) { /* Output geometry data */ case 1 : for (vnodnum = meshptr->vnodbas; (o == 0) && (vnodnum < meshptr->vnodnnd); vnodnum ++) o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\n", (Gnum) ((meshptr->vlbltax != NULL) ? meshptr->vlbltax[vnodnum] : vnodnum), (double) geomptr->geomtab[(vnodnum - meshptr->vnodbas) * dimnnbr]) == EOF); break; case 2 : for (vnodnum = meshptr->vnodbas; (o == 0) && (vnodnum < meshptr->vnodnnd); vnodnum ++) o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\t%lf\n", (Gnum) ((meshptr->vlbltax != NULL) ? meshptr->vlbltax[vnodnum] : vnodnum), (double) geomptr->geomtab[(vnodnum - meshptr->vnodbas) * dimnnbr], (double) geomptr->geomtab[(vnodnum - meshptr->vnodbas) * dimnnbr + 1]) == EOF); break; case 3 : for (vnodnum = meshptr->vnodbas; (o == 0) && (vnodnum < meshptr->vnodnnd); vnodnum ++) o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\t%lf\t%lf\n", (Gnum) ((meshptr->vlbltax != NULL) ? meshptr->vlbltax[vnodnum] : vnodnum), (double) geomptr->geomtab[(vnodnum - meshptr->vnodbas) * dimnnbr], (double) geomptr->geomtab[(vnodnum - meshptr->vnodbas) * dimnnbr + 1], (double) geomptr->geomtab[(vnodnum - meshptr->vnodbas) * dimnnbr + 2]) == EOF); break; #ifdef SCOTCH_DEBUG_MESH2 default : errorPrint ("meshGeomSaveScot: invalid geometry type"); return (1); #endif /* SCOTCH_DEBUG_MESH2 */ } if (o != 0) { errorPrint ("meshGeomSaveScot: bad output"); } } return (o); } scotch-5.1.12b.dfsg/src/libscotch/vgraph_check.c0000644000175300017530000001551411631334325021731 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_check.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the separator **/ /** graph consistency checking routine. **/ /** **/ /** DATES : # Version 3.2 : from : 24 aug 1996 **/ /** to 03 nov 1997 **/ /** # Version 4.0 : from : 12 dec 2001 **/ /** to 08 jan 2004 **/ /** # Version 5.0 : from : 16 sep 2006 **/ /** to : 16 sep 2006 **/ /** # Version 5.1 : from : 09 nov 2008 **/ /** to : 09 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VGRAPH #include "module.h" #include "common.h" #include "graph.h" #include "vgraph.h" /*************************/ /* */ /* These routines handle */ /* separator graphs. */ /* */ /*************************/ /* This routine checks the consistency ** of the given separator graph. ** It returns: ** - 0 : if graph data are consistent. ** - !0 : on error. */ int vgraphCheck ( const Vgraph * const grafptr) { Gnum vertnum; /* Number of current vertex */ Gnum fronnum; /* Number of frontier vertex */ Gnum compload[3]; Gnum compsize[3]; Gnum commcut[3]; if (grafptr->comploaddlt != (grafptr->compload[0] - grafptr->compload[1])) { errorPrint ("vgraphCheck: invalid balance"); return (1); } for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { if (grafptr->parttax[vertnum] > 2) { errorPrint ("vgraphCheck: invalid part array"); return (1); } } if ((grafptr->fronnbr < 0) || (grafptr->fronnbr > grafptr->s.vertnbr)) { errorPrint ("vgraphCheck: invalid number of frontier vertices"); return (1); } for (fronnum = 0; fronnum < grafptr->fronnbr; fronnum ++) { Gnum vertnum; vertnum = grafptr->frontab[fronnum]; if ((vertnum < grafptr->s.baseval) || (vertnum >= grafptr->s.vertnnd)) { errorPrint ("vgraphCheck: invalid vertex index in frontier array"); return (1); } if (grafptr->parttax[vertnum] != 2) { errorPrint ("vgraphCheck: invalid vertex in frontier array"); return (1); } } compload[0] = compload[1] = compload[2] = 0; compsize[0] = compsize[1] = compsize[2] = 0; for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) { int partnum; /* Part of current vertex */ Gnum edgenum; /* Number of current edge */ partnum = (int) grafptr->parttax[vertnum]; compload[partnum] += (grafptr->s.velotax == NULL) ? 1 : grafptr->s.velotax[vertnum]; compsize[partnum] ++; commcut[0] = commcut[1] = commcut[2] = 0; if ((grafptr->s.verttax[vertnum] < grafptr->s.baseval) || (grafptr->s.verttax[vertnum] > grafptr->s.vendtax[vertnum])) { errorPrint ("vgraphCheck: invalid graph structure (1)"); return (1); } for (edgenum = grafptr->s.verttax[vertnum]; edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) { Gnum vertend; vertend = grafptr->s.edgetax[edgenum]; if ((vertend < grafptr->s.baseval) || (vertend >= grafptr->s.vertnnd)) { errorPrint ("vgraphCheck: invalid graph structure (2)"); return (1); } commcut[grafptr->parttax[vertend]] ++; } #ifdef SCOTCH_DEBUG_VGRAPH3 if (partnum == 2) { if ((commcut[0] == 0) || (commcut[1] == 0)) errorPrintW ("vgraphCheck: no-use separator vertex%s (%ld)", /* Warning only */ ((grafptr->levlnum == 0) ? " at level 0" : ""), (long) vertnum); } else { #else if (partnum != 2) { #endif /* SCOTCH_DEBUG_VGRAPH3 */ if (commcut[1 - partnum] != 0) { errorPrint ("vgraphCheck: vertex should be in separator (%ld)", (long) vertnum); return (1); } } } if ((grafptr->compload[0] != compload[0]) || (grafptr->compload[1] != compload[1]) || (grafptr->compload[2] != compload[2])) { errorPrint ("vgraphCheck: invalid part loads"); return (1); } if (grafptr->comploaddlt != (grafptr->compload[0] - grafptr->compload[1])) { errorPrint ("vgraphCheck: invalid balance"); return (1); } if ((grafptr->compsize[0] != compsize[0]) || (grafptr->compsize[1] != compsize[1]) || (grafptr->fronnbr != compsize[2])) { errorPrint ("vgraphCheck: invalid part sizes"); return (1); } return (0); } scotch-5.1.12b.dfsg/src/libscotch/hgraph.c0000644000175300017530000000772711631334325020565 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the source graph **/ /** functions. **/ /** **/ /** DATES : # Version 4.0 : from : 17 jan 2002 **/ /** to 01 dec 2003 **/ /** # Version 5.0 : from : 19 dec 2006 **/ /** to 30 may 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HGRAPH #include "module.h" #include "common.h" #include "graph.h" #include "hgraph.h" /****************************************/ /* */ /* These routines handle source graphs. */ /* */ /****************************************/ /* This routine initializes a source graph ** structure. ** It returns: ** - 0 : in all cases. */ int hgraphInit ( Hgraph * restrict const grafptr) { memSet (grafptr, 0, sizeof (Hgraph)); /* Initialize graph fields */ grafptr->s.flagval = GRAPHFREETABS; /* By default, free all arrays */ return (0); } /* This routine frees a source graph structure. ** It returns: ** - VOID : in all cases. */ void hgraphExit ( Hgraph * restrict const grafptr) { hgraphFree (grafptr); } /* This routine frees a source graph structure. ** It returns: ** - VOID : in all cases. */ void hgraphFree ( Hgraph * restrict const grafptr) { if ((grafptr->vnhdtax != NULL) && /* Free end vertex array for non-halo vertices */ (grafptr->vnhdtax != grafptr->s.vendtax) && ((grafptr->s.flagval & HGRAPHFREEVNHD) != 0)) memFree (grafptr->vnhdtax); graphFree (&grafptr->s); /* Free graph data */ #ifdef SCOTCH_DEBUG_HGRAPH2 memSet (grafptr, ~0, sizeof (Hgraph)); /* Purge graph fields */ #endif /* SCOTCH_DEBUG_HGRAPH2 */ } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_order_perm.c0000644000175300017530000000664211631334325024516 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_order_perm.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted ordering permutation building **/ /** routine of the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 18 oct 2007 **/ /** to 18 oct 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "dgraph.h" #include "dorder.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the distributed ordering */ /* handling routines. */ /* */ /************************************/ /*+ This routine fills the given distributed *** permutation array with the permutation *** stored in the given distributed ordering. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphOrderPerm ( const SCOTCH_Dgraph * const grafptr, /*+ Graph to order +*/ const SCOTCH_Dordering * const ordeptr, /*+ Computed ordering +*/ SCOTCH_Num * const permloctab) /*+ Direct permutation +*/ { return (dorderPerm ((Dorder *) ordeptr, (Dgraph *) grafptr, permloctab)); } scotch-5.1.12b.dfsg/src/libscotch/kgraph.h0000644000175300017530000001102711631334325020561 0ustar hazelscthazelsct/* Copyright 2004,2007,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kgraph.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a static mapper. **/ /** These lines are the data declarations **/ /** for the k-way graph partitoning struc- **/ /** tures and routines. **/ /** **/ /** DATES : # Version 3.2 : from : 12 sep 1997 **/ /** to 26 may 1998 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to 12 mar 1999 **/ /** # Version 4.0 : from : 11 dec 2001 **/ /** to 16 feb 2005 **/ /** # Version 5.0 : from : 17 jun 2008 **/ /** to 17 jun 2008 **/ /** # Version 5.1 : from : 13 jul 2010 **/ /** to 31 aug 2011 **/ /** **/ /************************************************************/ #define KGRAPH_H /* ** The defines. */ /*+ Graph option flags. +*/ #define KGRAPHFREEPART (GRAPHBITSNOTUSED) /* Free part array */ /* ** The type and structure definitions. */ /*+ The graph structure. +*/ typedef struct Kgraph_ { Graph s; /*+ Source graph +*/ Mapping m; /*+ Current mapping of graph vertices +*/ Gnum fronnbr; /*+ Number of frontier vertices +*/ Gnum * frontab; /*+ Array of frontier vertex numbers +*/ Gnum * comploadavg; /*+ Array of target average loads +*/ Gnum * comploaddlt; /*+ Array of target imbalances +*/ double comploadrat; /*+ Ideal load balance per weight unit +*/ Gnum commload; /*+ Communication load +*/ INT levlnum; /*+ Coarsening level +*/ } Kgraph; /* ** The function prototypes. */ #ifndef KGRAPH #define static #endif int kgraphInit (Kgraph * const, const Graph * restrict const, const Mapping * restrict const); void kgraphExit (Kgraph * const); void kgraphFrst (Kgraph * const); int kgraphCheck (const Kgraph * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_graph_io_mmkt_f.c0000644000175300017530000001633211631334325024155 0ustar hazelscthazelsct/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_io_mmkt_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** graph i/o routines of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 5.0 : from : 14 mar 2008 **/ /** to 14 mar 2008 **/ /** # Version 5.1 : from : 11 oct 2008 **/ /** to 27 mar 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the mapping routines. */ /* */ /**************************************/ /* String lengths are passed at the very ** end of the argument list. */ FORTRAN ( \ SCOTCHFGRAPHGEOMLOADMMKT, scotchfgraphgeomloadmmkt, ( \ SCOTCH_Graph * const grafptr, \ SCOTCH_Geom * const geomptr, \ const int * const filegrfptr, \ const int * const filegeoptr, \ const char * const dataptr, /* No use */ \ int * const revaptr, \ const int datanbr), \ (grafptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) { FILE * filegrfstream; /* Streams to build from handles */ FILE * filegeostream; int filegrfnum; /* Duplicated handle */ int filegeonum; int o; if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHGEOMLOADMMKT: cannot duplicate handle (1)"); *revaptr = 1; /* Indicate error */ return; } if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHGEOMLOADMMKT: cannot duplicate handle (2)"); close (filegrfnum); *revaptr = 1; /* Indicate error */ return; } if ((filegrfstream = fdopen (filegrfnum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHGEOMLOADMMKT: cannot open input stream (1)"); close (filegrfnum); close (filegeonum); *revaptr = 1; return; } if ((filegeostream = fdopen (filegeonum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHGEOMLOADMMKT: cannot open input stream (2)"); fclose (filegrfstream); close (filegeonum); *revaptr = 1; return; } o = SCOTCH_graphGeomLoadMmkt (grafptr, geomptr, filegrfstream, filegeostream, NULL); fclose (filegrfstream); /* This closes file descriptors too */ fclose (filegeostream); *revaptr = o; } /* String lengths are passed at the very ** end of the argument list. */ FORTRAN ( \ SCOTCHFGRAPHGEOMSAVEMMKT, scotchfgraphgeomsavemmkt, ( \ const SCOTCH_Graph * const grafptr, \ const SCOTCH_Geom * const geomptr, \ const int * const filegrfptr, \ const int * const filegeoptr, \ const char * const dataptr, /* No use */ \ int * const revaptr, \ const int datanbr), \ (grafptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) { FILE * filegrfstream; /* Streams to build from handles */ FILE * filegeostream; int filegrfnum; /* Duplicated handle */ int filegeonum; int o; if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHGEOMSAVEMMKT: cannot duplicate handle (1)"); *revaptr = 1; /* Indicate error */ return; } if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHGEOMSAVEMMKT: cannot duplicate handle (2)"); close (filegrfnum); *revaptr = 1; /* Indicate error */ return; } if ((filegrfstream = fdopen (filegrfnum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHGEOMSAVEMMKT: cannot open output stream (1)"); close (filegrfnum); close (filegeonum); *revaptr = 1; return; } if ((filegeostream = fdopen (filegeonum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHGEOMSAVEMMKT: cannot open output stream (2)"); fclose (filegrfstream); close (filegeonum); *revaptr = 1; return; } o = SCOTCH_graphGeomSaveMmkt (grafptr, geomptr, filegrfstream, filegeostream, NULL); fclose (filegrfstream); /* This closes file descriptors too */ fclose (filegeostream); *revaptr = o; } scotch-5.1.12b.dfsg/src/libscotch/vdgraph_separate_st.c0000644000175300017530000004224211631334325023330 0ustar hazelscthazelsct/* Copyright 2007-2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_separate_st.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER **/ /** **/ /** FUNCTION : This module contains the global **/ /** distributed separation strategy and **/ /** method tables. **/ /** **/ /** DATES : # Version 5.0 : from : 16 feb 2006 **/ /** to 01 aug 2007 **/ /** # Version 5.1 : from : 05 nov 2007 **/ /** to 26 may 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VDGRAPH_SEPARATE_ST #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "vgraph.h" #include "vgraph_separate_st.h" #include "dgraph.h" #include "dgraph_coarsen.h" #include "vdgraph.h" #include "vdgraph_separate_bd.h" #include "vdgraph_separate_df.h" #include "vdgraph_separate_ml.h" #include "vdgraph_separate_sq.h" #include "vdgraph_separate_st.h" #include "vdgraph_separate_zr.h" /* ** The static and global variables. */ static Vdgraph vdgraphdummy; /* Dummy distributed separator graph for offset computations */ static union { VdgraphSeparateBdParam param; StratNodeMethodData padding; } vdgraphseparatedefaultbd = { { 3, &stratdummy } }; static union { VdgraphSeparateDfParam param; StratNodeMethodData padding; } vdgraphseparatedefaultdf = { { 0, 300, 1.0, 0.0, 0.2 } }; static union { VdgraphSeparateMlParam param; StratNodeMethodData padding; } vdgraphseparatedefaultml = { { 5, 1000, 100, 0, 0.8L, &stratdummy, &stratdummy, &stratdummy, 1 } }; static union { VdgraphSeparateSqParam param; StratNodeMethodData padding; } vdgraphseparatedefaultsq = { { &stratdummy } }; static StratMethodTab vdgraphseparatestmethtab[] = { /* Distributed graph separation methods array */ { VDGRAPHSEPASTMETHBD, "b", vdgraphSeparateBd, &vdgraphseparatedefaultbd }, { VDGRAPHSEPASTMETHDF, "d", vdgraphSeparateDf, &vdgraphseparatedefaultdf }, { VDGRAPHSEPASTMETHML, "m", vdgraphSeparateMl, &vdgraphseparatedefaultml }, { VDGRAPHSEPASTMETHSQ, "q", vdgraphSeparateSq, &vdgraphseparatedefaultsq }, { VDGRAPHSEPASTMETHZR, "z", vdgraphSeparateZr, NULL }, { -1, NULL, NULL, NULL } }; static StratParamTab vdgraphseparatestparatab[] = { /* Distributed graph separation method parameter list */ { VDGRAPHSEPASTMETHBD, STRATPARAMINT, "width", (byte *) &vdgraphseparatedefaultbd.param, (byte *) &vdgraphseparatedefaultbd.param.distmax, NULL }, { VDGRAPHSEPASTMETHBD, STRATPARAMSTRAT, "strat", (byte *) &vdgraphseparatedefaultbd.param, (byte *) &vdgraphseparatedefaultbd.param.strat, (void *) &vdgraphseparateststratab }, { VDGRAPHSEPASTMETHDF, STRATPARAMINT, "part", (byte *) &vdgraphseparatedefaultdf.param, (byte *) &vdgraphseparatedefaultdf.param.partval, NULL }, { VDGRAPHSEPASTMETHDF, STRATPARAMINT, "pass", (byte *) &vdgraphseparatedefaultdf.param, (byte *) &vdgraphseparatedefaultdf.param.passnbr, NULL }, { VDGRAPHSEPASTMETHDF, STRATPARAMDOUBLE, "bal", (byte *) &vdgraphseparatedefaultdf.param, (byte *) &vdgraphseparatedefaultdf.param.deltval, NULL }, { VDGRAPHSEPASTMETHDF, STRATPARAMDOUBLE, "dif", (byte *) &vdgraphseparatedefaultdf.param, (byte *) &vdgraphseparatedefaultdf.param.cdifval, NULL }, { VDGRAPHSEPASTMETHDF, STRATPARAMDOUBLE, "rem", (byte *) &vdgraphseparatedefaultdf.param, (byte *) &vdgraphseparatedefaultdf.param.cremval, NULL }, { VDGRAPHSEPASTMETHML, STRATPARAMSTRAT, "asc", (byte *) &vdgraphseparatedefaultml.param, (byte *) &vdgraphseparatedefaultml.param.stratasc, (void *) &vdgraphseparateststratab }, { VDGRAPHSEPASTMETHML, STRATPARAMSTRAT, "low", (byte *) &vdgraphseparatedefaultml.param, (byte *) &vdgraphseparatedefaultml.param.stratlow, (void *) &vdgraphseparateststratab }, { VDGRAPHSEPASTMETHML, STRATPARAMSTRAT, "seq", (byte *) &vdgraphseparatedefaultml.param, (byte *) &vdgraphseparatedefaultml.param.stratseq, (void *) &vdgraphseparateststratab }, { VDGRAPHSEPASTMETHML, STRATPARAMINT, "pass", (byte *) &vdgraphseparatedefaultml.param, (byte *) &vdgraphseparatedefaultml.param.passnbr, NULL }, { VDGRAPHSEPASTMETHML, STRATPARAMINT, "proc", (byte *) &vdgraphseparatedefaultml.param, (byte *) &vdgraphseparatedefaultml.param.seqnbr, NULL }, { VDGRAPHSEPASTMETHML, STRATPARAMINT, "vert", (byte *) &vdgraphseparatedefaultml.param, (byte *) &vdgraphseparatedefaultml.param.coarnbr, NULL }, { VDGRAPHSEPASTMETHML, STRATPARAMINT, "dvert", (byte *) &vdgraphseparatedefaultml.param, (byte *) &vdgraphseparatedefaultml.param.dupmax, NULL }, { VDGRAPHSEPASTMETHML, STRATPARAMINT, "dlevl", (byte *) &vdgraphseparatedefaultml.param, (byte *) &vdgraphseparatedefaultml.param.duplvlmax, NULL }, { VDGRAPHSEPASTMETHML, STRATPARAMDOUBLE, "rat", (byte *) &vdgraphseparatedefaultml.param, (byte *) &vdgraphseparatedefaultml.param.coarrat, NULL }, { VDGRAPHSEPASTMETHSQ, STRATPARAMSTRAT, "strat", (byte *) &vdgraphseparatedefaultsq.param, (byte *) &vdgraphseparatedefaultsq.param.strat, (void *) &vgraphseparateststratab }, { VDGRAPHSEPASTMETHNBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; static StratParamTab vdgraphseparatestcondtab[] = { /* Distributed graph condition parameter table */ { STRATNODECOND, STRATPARAMINT, "edge", (byte *) &vdgraphdummy, (byte *) &vdgraphdummy.s.edgeglbnbr, NULL }, { STRATNODECOND, STRATPARAMINT, "levl", (byte *) &vdgraphdummy, (byte *) &vdgraphdummy.levlnum, NULL }, { STRATNODECOND, STRATPARAMINT, "load", (byte *) &vdgraphdummy, (byte *) &vdgraphdummy.s.veloglbsum, NULL }, { STRATNODECOND, STRATPARAMINT, "proc", (byte *) &vdgraphdummy, (byte *) &vdgraphdummy.s.procglbnbr, NULL }, { STRATNODECOND, STRATPARAMINT, "rank", (byte *) &vdgraphdummy, (byte *) &vdgraphdummy.s.proclocnum, NULL }, { STRATNODECOND, STRATPARAMINT, "vert", (byte *) &vdgraphdummy, (byte *) &vdgraphdummy.s.vertglbnbr, NULL }, { STRATNODENBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; StratTab vdgraphseparateststratab = { /* Strategy tables for distributed vertex separation methods */ vdgraphseparatestmethtab, vdgraphseparatestparatab, vdgraphseparatestcondtab }; /*******************************************/ /* */ /* This is the generic separation routine. */ /* */ /*******************************************/ /* This routine computes the separation of the ** given distributed graph according to the given ** strategy. ** All distributed vertex separation routines must ** be collective, that is, they must all return ** the same success or failure return value on all ** of the processors onto which they are run. Else, ** the behavior of the software is unpredictable. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int vdgraphSeparateSt ( Vdgraph * restrict const grafptr, /*+ Distributed separation graph +*/ const Strat * restrict const strat) /*+ Separation strategy +*/ { StratTest val; VdgraphStore savetab[2]; /* Results of the two strategies */ int o; #ifdef SCOTCH_DEBUG_VDGRAPH2 MPI_Comm proccommold; /* Save area for old communicator */ #endif /* SCOTCH_DEBUG_VDGRAPH2 */ #ifdef SCOTCH_DEBUG_VDGRAPH2 if (sizeof (Gnum) != sizeof (INT)) { errorPrint ("vdgraphSeparateSt: invalid type specification for parser variables"); return (1); } if (sizeof (VdgraphSeparateSqParam) > sizeof (StratNodeMethodData)) { errorPrint ("vdgraphSeparateSt: invalid type specification"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ #ifdef SCOTCH_DEBUG_VDGRAPH1 if ((strat->tabl != &vdgraphseparateststratab) && (strat != &stratdummy)) { errorPrint ("vdgraphSeparateSt: invalid parameter (1)"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH1 */ o = 0; switch (strat->type) { case STRATNODECONCAT : o = vdgraphSeparateSt (grafptr, strat->data.concat.strat[0]); /* Apply first strategy */ if (o == 0) /* If it worked all right */ o |= vdgraphSeparateSt (grafptr, strat->data.concat.strat[1]); /* Then apply second strategy */ break; case STRATNODECOND : o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ if (o == 0) { /* If evaluation was correct */ #ifdef SCOTCH_DEBUG_VDGRAPH2 if ((val.typetest != STRATTESTVAL) || (val.typenode != STRATPARAMLOG)) { errorPrint ("vdgraphSeparateSt: invalid test result"); o = 1; break; } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ if (val.data.val.vallog == 1) /* If expression is true */ o = vdgraphSeparateSt (grafptr, strat->data.cond.strat[0]); /* Apply first strategy */ else { /* Else if expression is false */ if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ o = vdgraphSeparateSt (grafptr, strat->data.cond.strat[1]); /* Apply second strategy */ } } break; case STRATNODEEMPTY : break; case STRATNODESELECT : /* TODO: Can be multithreaded! */ if (((vdgraphStoreInit (grafptr, &savetab[0])) != 0) || /* Allocate save areas */ ((vdgraphStoreInit (grafptr, &savetab[1])) != 0)) { errorPrint ("vdgraphSeparateSt: out of memory"); vdgraphStoreExit (&savetab[0]); return (1); } vdgraphStoreSave (grafptr, &savetab[1]); /* Save initial bipartition */ if (vdgraphSeparateSt (grafptr, strat->data.select.strat[0]) != 0) { /* If first strategy didn't work */ vdgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition */ vdgraphStoreSave (grafptr, &savetab[0]); /* Save it as result */ } else { /* First strategy worked */ vdgraphStoreSave (grafptr, &savetab[0]); /* Save its result */ vdgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition */ } if (vdgraphSeparateSt (grafptr, strat->data.select.strat[1]) != 0) /* If second strategy didn't work */ vdgraphStoreUpdt (grafptr, &savetab[1]); /* Restore initial bipartition as its result */ if ( (savetab[0].fronglbnbr < grafptr->compglbsize[2]) || /* If first strategy is better */ ((savetab[0].fronglbnbr == grafptr->compglbsize[2]) && (abs (savetab[0].compglbloaddlt) < abs (grafptr->compglbloaddlt)))) vdgraphStoreUpdt (grafptr, &savetab[0]); /* Restore its result */ vdgraphStoreExit (&savetab[0]); /* Free both save areas */ vdgraphStoreExit (&savetab[1]); break; #ifdef SCOTCH_DEBUG_VDGRAPH1 case STRATNODEMETHOD : #else /* SCOTCH_DEBUG_VDGRAPH1 */ default : #endif /* SCOTCH_DEBUG_VDGRAPH1 */ #ifdef SCOTCH_DEBUG_VDGRAPH2 proccommold = grafptr->s.proccomm; /* Create new communicator to isolate method communications */ MPI_Comm_dup (proccommold, &grafptr->s.proccomm); #endif /* SCOTCH_DEBUG_VDGRAPH2 */ o = strat->tabl->methtab[strat->data.method.meth].func (grafptr, (void *) &strat->data.method.data); #ifdef SCOTCH_DEBUG_VDGRAPH2 MPI_Comm_free (&grafptr->s.proccomm); /* Restore old communicator */ grafptr->s.proccomm = proccommold; #endif /* SCOTCH_DEBUG_VDGRAPH2 */ #ifdef SCOTCH_DEBUG_VDGRAPH1 break; default : errorPrint ("vdgraphSeparateSt: invalid parameter (2)"); return (1); #endif /* SCOTCH_DEBUG_VDGRAPH1 */ } return (o); } scotch-5.1.12b.dfsg/src/libscotch/dorder_tree_dist.c0000644000175300017530000003316411631334325022627 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dorder_tree_dist.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles distributed **/ /** orderings. **/ /** **/ /** DATES : # Version 5.1 : from : 28 nov 2007 **/ /** to 09 may 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DORDER #include "module.h" #include "common.h" #include "dgraph.h" #include "dorder.h" /************************************/ /* */ /* These routines handle orderings. */ /* */ /************************************/ /* This function returns to all processes the ** number of distributed leaf column blocks ** possessed by the ordering. ** It returns: ** - >=0 : number of distributed column blocks. ** - <0 : on error. */ Gnum dorderCblkDist ( const Dorder * restrict const ordeptr) { const DorderLink * restrict linklocptr; Gnum dblklocnbr; /* Local number of locally-rooted distributed column blocks */ Gnum dblkglbnbr; for (linklocptr = ordeptr->linkdat.nextptr, dblklocnbr = 0; /* For all nodes in local ordering structure */ linklocptr != &ordeptr->linkdat; linklocptr = linklocptr->nextptr) { const DorderCblk * restrict cblklocptr; cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ if (cblklocptr->cblknum.proclocnum == ordeptr->proclocnum) dblklocnbr ++; } if (MPI_Allreduce (&dblklocnbr, &dblkglbnbr, 1, GNUM_MPI, MPI_SUM, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderCblkDist: communication error"); return ((Gnum) -1); } return (dblkglbnbr); } /* This function returns on all of the procesors the ** distributed part of the distributed structure of ** the given distributed ordering. The two array ** pointers which must be passed should both point to ** arrays of size dorderCblkDist(). ** It returns: ** - 0 : if the distributed tree structure could be computed. ** - !0 : on error. */ int dorderTreeDist ( const Dorder * restrict const ordeptr, const Dgraph * restrict const grafptr, Gnum * restrict const treeglbtab, Gnum * restrict const sizeglbtab) { const DorderLink * restrict linklocptr; Gnum * restrict dataloctab; Gnum * restrict dataglbtab; Gnum dblklocnum; Gnum dblklocnbr; /* Local number of distributed column blocks */ Gnum dblkglbnbr; /* Global number of distributed column blocks */ Gnum dblkglbnum; Gnum dblkglbtmp; int * restrict dblkcnttab; int * restrict dblkdsptab; int * restrict cblkdsptab; Gnum cblkglbtmp; Gnum * restrict srt1glbtab; Gnum * restrict srt2glbtab; int procglbnbr; int procnum; Gnum reduloctab[3]; Gnum reduglbtab[3]; for (linklocptr = ordeptr->linkdat.nextptr, dblklocnbr = 0; /* For all nodes in local ordering structure */ linklocptr != &ordeptr->linkdat; linklocptr = linklocptr->nextptr) { const DorderCblk * restrict cblklocptr; cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ if (cblklocptr->cblknum.proclocnum == ordeptr->proclocnum) { #ifdef SCOTCH_DEBUG_DORDER2 Gnum cblklocnum; cblklocnum = cblklocptr->cblknum.cblklocnum; if ((cblklocnum < 0) || (cblklocnum >= ordeptr->cblklocnbr)) { errorPrint ("dorderTreeDist: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ dblklocnbr ++; } } if (MPI_Allreduce (&dblklocnbr, &dblkglbnbr, 1, GNUM_MPI, MPI_SUM, ordeptr->proccomm) != MPI_SUCCESS) { /* Get overall number of distributed blocks */ errorPrint ("dorderTreeDist: communication error (1)"); return (1); } MPI_Comm_size (ordeptr->proccomm, &procglbnbr); reduloctab[0] = reduloctab[1] = reduloctab[2] = 0; if (memAllocGroup ((void **) (void *) &dblkcnttab, (size_t) ( procglbnbr * sizeof (int)), &dblkdsptab, (size_t) ( procglbnbr * sizeof (int)), /* TRICK: cblkdsptab used as secondary array after cblkcnttab */ &cblkdsptab, (size_t) ((procglbnbr + 1) * sizeof (int)), /* TRICK: have an array at least of size 2 */ &dataloctab, (size_t) ( dblklocnbr * 4 * sizeof (Gnum)), &dataglbtab, (size_t) ( dblkglbnbr * 4 * sizeof (Gnum)), &srt1glbtab, (size_t) ( dblkglbnbr * 2 * sizeof (Gnum)), /* TRICK: one more slot for root node */ &srt2glbtab, (size_t) ( dblkglbnbr * 2 * sizeof (Gnum)), NULL) == NULL) { /* TRICK: one more slot for root node */ errorPrint ("dorderTreeDist: out of memory"); reduloctab[0] = 1; /* Memory error */ } else { if (treeglbtab != NULL) reduloctab[1] = 1; /* Compute the "or" of any array being non-null */ if (sizeglbtab != NULL) { reduloctab[2] = reduloctab[1]; /* Compute the "and" of any array being non-null */ reduloctab[1] = 1; } } #ifdef SCOTCH_DEBUG_DORDER1 /* Communication cannot be merged with a useful one */ if (MPI_Allreduce (reduloctab, reduglbtab, 3, GNUM_MPI, MPI_SUM, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderTreeDist: communication error (1)"); reduglbtab[0] = /* Post-process error below */ reduglbtab[1] = /* Prevent Valgrind from yelling */ reduglbtab[2] = 1; } #else /* SCOTCH_DEBUG_DORDER1 */ reduglbtab[0] = reduloctab[0]; reduglbtab[1] = procglbnbr - 1 + reduloctab[1]; reduglbtab[2] = procglbnbr - 1 + reduloctab[2]; #endif /* SCOTCH_DEBUG_DORDER1 */ if (reduglbtab[1] != reduglbtab[2]) { /* If not both arrays provided on each of the candidate processors */ if (reduloctab[1] != reduloctab[2]) errorPrint ("dorderTreeDist: invalid parameters (1)"); reduglbtab[0] = 1; } if (reduglbtab[2] != procglbnbr) { errorPrint ("dorderTreeDist: invalid parameters (2)"); reduglbtab[0] = 1; } if (reduglbtab[0] != 0) { if (dblkcnttab != NULL) memFree (dblkcnttab); /* Free group leader */ return (1); } cblkdsptab[0] = (int) dblklocnbr; /* MPI only supports int as count type */ cblkdsptab[1] = (int) ordeptr->cblklocnbr; /* TRICK: cblkdsptab is at least of size 2 */ if (MPI_Allgather (cblkdsptab, 2, MPI_INT, dblkcnttab, 2, MPI_INT, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderTreeDist: communication error (2)"); return (1); } for (procnum = cblkglbtmp = 0; procnum < procglbnbr; procnum ++) { /* Accumulate un-based global start indices for all column blocks */ cblkdsptab[procnum] = cblkglbtmp; dblkcnttab[procnum] = dblkcnttab[2 * procnum] * 4; /* Four times for dataloctab */ cblkglbtmp += dblkcnttab[2 * procnum + 1]; } for (procnum = dblkglbtmp = 0; procnum < procglbnbr; procnum ++) { /* Accumulate un-based global start indices for distributed column blocks */ dblkdsptab[procnum] = dblkglbtmp; dblkglbtmp += dblkcnttab[procnum]; } for (linklocptr = ordeptr->linkdat.nextptr, dblklocnum = 0; /* For all nodes in local ordering structure */ linklocptr != &ordeptr->linkdat; linklocptr = linklocptr->nextptr) { const DorderCblk * restrict cblklocptr; cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ if (cblklocptr->cblknum.proclocnum == ordeptr->proclocnum) { /* If node is local */ dataloctab[4 * dblklocnum] = cblkdsptab[ordeptr->proclocnum] + cblklocptr->cblknum.cblklocnum; dataloctab[4 * dblklocnum + 1] = cblklocptr->ordeglbval; dataloctab[4 * dblklocnum + 2] = cblkdsptab[cblklocptr->fathnum.proclocnum] + cblklocptr->fathnum.cblklocnum; dataloctab[4 * dblklocnum + 3] = cblklocptr->vnodglbnbr; dblklocnum ++; } } if (MPI_Allgatherv (dataloctab, 4 * dblklocnbr, GNUM_MPI, dataglbtab, dblkcnttab, dblkdsptab, GNUM_MPI, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderTreeDist: communication error (3)"); return (1); } for (dblkglbnum = 0; dblkglbnum < dblkglbnbr; dblkglbnum ++) { srt1glbtab[2 * dblkglbnum] = dataglbtab[4 * dblkglbnum + 1]; srt1glbtab[2 * dblkglbnum + 1] = dataglbtab[4 * dblkglbnum]; } intSort2asc2 (srt1glbtab, dblkglbnbr); /* Sort nodes by ascending inverse start index to get permutation of column block indices */ for (dblkglbnum = 0; dblkglbnum < dblkglbnbr; dblkglbnum ++) { srt1glbtab[2 * dblkglbnum] = srt1glbtab[2 * dblkglbnum + 1]; srt1glbtab[2 * dblkglbnum + 1] = dblkglbnum; } intSort2asc2 (srt1glbtab, dblkglbnbr); /* Sort nodes by ascending column block index to match with the ones of dataglbtab */ for (dblkglbnum = 0; dblkglbnum < dblkglbnbr; dblkglbnum ++) { srt2glbtab[2 * dblkglbnum] = dataglbtab[4 * dblkglbnum + 2]; srt2glbtab[2 * dblkglbnum + 1] = dblkglbnum; } intSort2asc2 (srt2glbtab, dblkglbnbr); /* Sort father indices by ascending column block indices */ #ifdef SCOTCH_DEBUG_DORDER2 if (srt2glbtab[0] != -1) { /* If tree has no root */ errorPrint ("dorderTreeDist: internal error (2)"); memFree (dblkcnttab); /* Free group leader */ return (1); } if ((dblkglbnbr > 1) && (srt2glbtab[2] == -1)) { /* If tree has multiple roots */ errorPrint ("dorderTreeDist: internal error (3)"); memFree (dblkcnttab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ for (dblkglbnum = 1, dblkglbtmp = 0; dblkglbnum < dblkglbnbr; ) { /* Replace in block data the father column block indices by the new permuted indices */ if (srt2glbtab[2 * dblkglbnum] == srt1glbtab[2 * dblkglbtmp]) dataglbtab[4 * srt2glbtab[2 * (dblkglbnum ++) + 1] + 2] = srt1glbtab[2 * dblkglbtmp + 1]; else { #ifdef SCOTCH_DEBUG_DORDER2 if ((srt2glbtab[2 * dblkglbnum] < srt1glbtab[2 * dblkglbtmp]) || /* If column block index not found in table */ (dblkglbtmp >= (dblkglbnbr - 1))) { errorPrint ("dorderTreeDist: internal error (4)"); memFree (dblkcnttab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ dblkglbtmp ++; } } for (dblkglbnum = 0; dblkglbnum < dblkglbnbr; dblkglbnum ++) { srt2glbtab[2 * dblkglbnum] = dataglbtab[4 * dblkglbnum]; srt2glbtab[2 * dblkglbnum + 1] = dblkglbnum; } intSort2asc2 (srt2glbtab, dblkglbnbr); /* Sort father indices by ascending column block indices */ for (dblkglbnum = 0; dblkglbnum < dblkglbnbr; dblkglbnum ++) { #ifdef SCOTCH_DEBUG_DORDER2 if (srt1glbtab[2 * dblkglbnum] != srt2glbtab[2 * dblkglbnum]) { errorPrint ("dorderTreeDist: internal error (5)"); memFree (dblkcnttab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ treeglbtab[srt1glbtab[2 * dblkglbnum + 1]] = dataglbtab[4 * srt2glbtab[2 * dblkglbnum + 1] + 2]; sizeglbtab[srt1glbtab[2 * dblkglbnum + 1]] = dataglbtab[4 * srt2glbtab[2 * dblkglbnum + 1] + 3]; } memFree (dblkcnttab); /* Free group leader */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/graph_io_chac.c0000644000175300017530000003306311631334325022052 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_io_chac.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the I/O routines **/ /** for handling the Chaco graph format. **/ /** **/ /** DATES : # Version 3.2 : from : 06 nov 1997 **/ /** to 26 may 1998 **/ /** # Version 3.3 : from : 13 dec 1998 **/ /** to 24 dec 1998 **/ /** # Version 3.4 : from : 05 oct 1999 **/ /** to : 04 feb 2000 **/ /** # Version 4.0 : from : 18 dec 2001 **/ /** to 19 jan 2004 **/ /** # Version 5.0 : from : 04 feb 2007 **/ /** to 21 may 2008 **/ /** # Version 5.1 : from : 02 dec 2008 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GRAPH_IO_CHAC #include "module.h" #include "common.h" #include "geom.h" #include "graph.h" /* This routine loads the geometrical graph ** in the Chaco graph format, and allocates ** the proper structures. ** - 0 : on success. ** - !0 : on error. */ int graphGeomLoadChac ( Graph * restrict const grafptr, /* Graph to load */ Geom * restrict const geomptr, /* Geometry to load */ FILE * const filesrcptr, /* Topological data */ FILE * const filegeoptr, /* No use */ const char * const dataptr) /* No use */ { char chalinetab[80]; /* Header line */ long chavertnbr; /* Number of vertices */ Gnum chavertnum; /* Number of vertex read */ long chaedgenbr; /* Number of edges */ long chaflagval; /* Flag on numeric form */ char chaflagstr[4]; /* Flag for optional data */ char chabuffcar; /* Buffer for line processing */ Gnum edgenum; Gnum edlosum; Gnum vertnum; Gnum velosum; Gnum vlblmax; Gnum degrmax; do { /* Skip comment lines */ chabuffcar = getc (filesrcptr); /* Read first character */ if (chabuffcar == '%') { /* If comment line */ fscanf (filesrcptr, "%*[^\n]"); /* Purge line */ getc (filesrcptr); /* Purge newline */ } } while (chabuffcar == '%'); ungetc (chabuffcar, filesrcptr); chaflagval = 0; if ((fscanf (filesrcptr, "%79[^\n]%*[^\n]", chalinetab) != 1) || /* Read graph header */ (sscanf (chalinetab, "%ld%ld%ld", &chavertnbr, &chaedgenbr, &chaflagval) < 2)) { errorPrint ("graphGeomLoadChac: bad input (1)"); return (1); } getc (filesrcptr); /* Purge newline (cannot be merged with above fscanf) */ chaflagstr[0] = /* Pre-set flag array */ chaflagstr[1] = chaflagstr[2] = chaflagstr[3] = '\0'; chaflagstr[0] = '0' + ((chaflagval / 100) % 10); /* Set the flags */ chaflagstr[1] = '0' + ((chaflagval / 10) % 10); chaflagstr[2] = '0' + ((chaflagval) % 10); grafptr->flagval = GRAPHFREETABS; grafptr->baseval = 1; /* Chaco graphs are based */ grafptr->vertnbr = chavertnbr; grafptr->vertnnd = chavertnbr + 1; grafptr->edgenbr = chaedgenbr * 2; /* We are counting arcs */ if (((grafptr->verttax = (Gnum *) memAlloc (grafptr->vertnnd * sizeof (Gnum))) == NULL) || ((grafptr->edgetax = (Gnum *) memAlloc (grafptr->edgenbr * sizeof (Gnum))) == NULL)) { errorPrint ("graphGeomLoadChac: out of memory (1)"); if (grafptr->verttax != NULL) memFree (grafptr->verttax); return (1); } grafptr->edgetax -= grafptr->baseval; grafptr->verttax -= grafptr->baseval; grafptr->vendtax = grafptr->verttax + 1; if (chaflagstr[0] != '0') { if ((grafptr->vlbltax = (Gnum *) memAlloc (chavertnbr * sizeof (Gnum))) == NULL) { errorPrint ("graphGeomLoadChac: out of memory (2)"); memFree (grafptr); return (1); } grafptr->vlbltax -= grafptr->baseval; } velosum = grafptr->vertnbr; /* Assume no vertex loads */ if (chaflagstr[1] != '0') { if ((grafptr->velotax = (Gnum *) memAlloc (chavertnbr * sizeof (Gnum))) == NULL) { errorPrint ("graphGeomLoadChac: out of memory (3)"); memFree (grafptr); return (1); } grafptr->velotax -= grafptr->baseval; velosum = 0; } edlosum = grafptr->edgenbr; if (chaflagstr[2] != '0') { if ((grafptr->edlotax = (Gnum *) memAlloc (grafptr->edgenbr * sizeof (Gnum))) == NULL) { errorPrint ("graphGeomLoadChac: out of memory (4)"); memFree (grafptr); return (1); } grafptr->edlotax -= grafptr->baseval; edlosum = 0; } for (vertnum = edgenum = grafptr->baseval, degrmax = vlblmax = 0; vertnum < grafptr->vertnnd; vertnum ++) { do { /* Skip comment lines */ chabuffcar = getc (filesrcptr); /* Read first character */ if (chabuffcar == '%') { /* If comment line */ fscanf (filesrcptr, "%*[^\n]"); /* Purge line */ getc (filesrcptr); /* Purge newline */ } } while (chabuffcar == '%'); ungetc (chabuffcar, filesrcptr); /* Put character back to filesrcptr */ if (grafptr->vlbltax != NULL) { if ((intLoad (filesrcptr, &grafptr->vlbltax[vertnum]) != 1) || (grafptr->vlbltax[vertnum] < 1) || (grafptr->vlbltax[vertnum] > chavertnbr)) { errorPrint ("graphGeomLoadChac: bad input (2)"); graphFree (grafptr); return (1); } if (grafptr->vlbltax[vertnum] > vlblmax) vlblmax = grafptr->vlbltax[vertnum]; } if (grafptr->velotax != NULL) { if ((intLoad (filesrcptr, &grafptr->velotax[vertnum]) != 1) || (grafptr->velotax[vertnum] < 1)) { errorPrint ("graphGeomLoadChac: bad input (3)"); graphFree (grafptr); return (1); } velosum += grafptr->velotax[vertnum]; } grafptr->verttax[vertnum] = edgenum; /* Set based edge array index */ while (1) { /* Read graph edges */ fscanf (filesrcptr, "%*[ \t\r]"); /* Skip white spaces except '\n' */ chabuffcar = getc (filesrcptr); /* Read next char */ if (chabuffcar == EOF) /* If end of file reached */ chabuffcar = '\n'; /* Indicate line as complete */ if (chabuffcar == '\n') /* Exit loop if line is complete */ break; ungetc (chabuffcar, filesrcptr); /* Else put character back to stream */ if ((intLoad (filesrcptr, &chavertnum) != 1) || (chavertnum < 1) || (chavertnum > chavertnbr) || ((grafptr->edlotax != NULL) && ((intLoad (filesrcptr, &grafptr->edlotax[edgenum]) != 1) || (edlosum += grafptr->edlotax[edgenum], grafptr->edlotax[edgenum] < 1)))) { errorPrint ("graphGeomLoadChac: bad input (4)"); graphFree (grafptr); return (1); } if (edgenum > (grafptr->edgenbr + grafptr-> baseval)) { /* Test edge array overflow */ errorPrint ("graphGeomLoadChac: bad input (5)"); graphFree (grafptr); return (1); } grafptr->edgetax[edgenum ++] = chavertnum; } if ((edgenum - grafptr->verttax[vertnum]) > degrmax) degrmax = edgenum - grafptr->verttax[vertnum]; } grafptr->verttax[vertnum] = edgenum; /* Set end of based vertex array */ grafptr->velosum = velosum; grafptr->edlosum = edlosum; grafptr->degrmax = degrmax; if (grafptr->vlbltax != NULL) { /* If graph has labels */ if (graphLoad2 (grafptr->baseval, grafptr->vertnnd, /* Un-label graph data */ grafptr->verttax, grafptr->vendtax, grafptr->edgetax, vlblmax, grafptr->vlbltax) != 0) { errorPrint ("graphGeomLoadChac: cannot relabel graph"); graphFree (grafptr); return (1); } } #ifdef SCOTCH_DEBUG_GRAPH2 if (graphCheck (grafptr) != 0) { /* Check graph consistency */ errorPrint ("graphGeomLoadChac: internal error"); graphFree (grafptr); return (1); } #endif /* SCOTCH_DEBUG_GRAPH2 */ return (0); } /* This routine saves the geometrical graph ** in the Chaco graph format. ** It returns: ** - 0 : on succes ** - !0 : on error. */ int graphGeomSaveChac ( const Graph * restrict const grafptr, /* Graph to save */ const Geom * restrict const geomptr, /* Geometry to save */ FILE * const filesrcptr, /* Topological data */ FILE * const filegeoptr, /* No use */ const char * const dataptr) /* No use */ { Gnum baseadj; /* Base adjustment */ Gnum vertnum; /* Current vertex */ Gnum edgenum; /* Current edge */ char * sepaptr; /* Separator string */ int o; baseadj = 1 - grafptr->baseval; /* Output base is always 1 */ o = (fprintf (filesrcptr, GNUMSTRING "\t" GNUMSTRING "\t%c%c%c\n", /* Write graph header */ (Gnum) grafptr->vertnbr, (Gnum) (grafptr->edgenbr / 2), ((grafptr->vlbltax != NULL) ? '1' : '0'), ((grafptr->velotax != NULL) ? '1' : '0'), ((grafptr->edlotax != NULL) ? '1' : '0')) < 0); for (vertnum = grafptr->baseval; (o == 0) && (vertnum < grafptr->vertnnd); vertnum ++) { sepaptr = ""; /* Start lines as is */ if (grafptr->vlbltax != NULL) { o |= (fprintf (filesrcptr, GNUMSTRING, (Gnum) (grafptr->vlbltax[vertnum] + baseadj)) < 0); sepaptr = "\t"; } if (grafptr->velotax != NULL) { o |= (fprintf (filesrcptr, "%s" GNUMSTRING, sepaptr, (Gnum) grafptr->velotax[vertnum]) < 0); sepaptr = "\t"; } for (edgenum = grafptr->verttax[vertnum]; (o == 0) && (edgenum < grafptr->vendtax[vertnum]); edgenum ++) { if (grafptr->vlbltax != NULL) o |= (fprintf (filesrcptr, "%s" GNUMSTRING, sepaptr, (Gnum) (grafptr->vlbltax[grafptr->edgetax[edgenum]] + baseadj)) < 0); else o |= (fprintf (filesrcptr, "%s" GNUMSTRING, sepaptr, (Gnum) (grafptr->edgetax[edgenum] + baseadj)) < 0); if (grafptr->edlotax != NULL) o |= (fprintf (filesrcptr, " " GNUMSTRING, (Gnum) grafptr->edlotax[edgenum]) < 0); sepaptr = "\t"; } o |= (fprintf (filesrcptr, "\n") < 0); } if (o != 0) errorPrint ("graphGeomSaveChac: bad output"); return (o); } scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_gp.c0000644000175300017530000002744611631334325022446 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_gp.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders a subgraph (most **/ /** likely a separator) using the Gibbs, **/ /** Poole, and Stockmeyer algorithm. **/ /** **/ /** DATES : # Version 3.2 : from : 31 oct 1996 **/ /** to 27 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 02 oct 1998 **/ /** # Version 4.0 : from : 28 jun 2002 **/ /** to : 01 dec 2003 **/ /** # Version 4.0 : from : 10 sep 2007 **/ /** to : 10 sep 2007 **/ /** # Version 5.1 : from : 01 oct 2009 **/ /** to : 01 oct 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HGRAPH_ORDER_GP #include "module.h" #include "common.h" #include "graph.h" #include "order.h" #include "hgraph.h" #include "hgraph_order_gp.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hgraphOrderGp ( const Hgraph * restrict const grafptr, Order * restrict const ordeptr, const Gnum ordenum, OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ const HgraphOrderGpParam * restrict const paraptr) { HgraphOrgerGpQueue queudat; /* Neighbor queue */ HgraphOrderGpVertex * restrict vexxtax; /* Based access to vertex array */ Gnum passnum; /* Pass number */ Gnum rootnum; /* Number of root vertex */ Gnum diamnum; /* Vertex which achieves diameter */ int diamflag; /* Flag set if diameter changed */ Gnum diamdist; /* Maximum diameter value found */ Gnum vertdist; /* DIstance of current vertex */ Gnum vertnum; /* Number of current vertex */ Gnum edgenum; /* Number of current edge */ Gnum ordeval; /* Current ordering value */ Gnum ordevnd; /* End value of ordering */ const Gnum * restrict const verttax = grafptr->s.verttax; const Gnum * restrict const vnumtax = grafptr->s.vnumtax; const Gnum * restrict const vnhdtax = grafptr->vnhdtax; const Gnum * restrict const edgetax = grafptr->s.edgetax; if (memAllocGroup ((void **) (void *) &queudat.qtab, (size_t) (grafptr->vnohnbr * sizeof (Gnum)), &vexxtax, (size_t) (grafptr->vnohnbr * sizeof (HgraphOrderGpVertex)), NULL) == NULL) { errorPrint ("hgraphOrderGp: out of memory"); return (1); } memSet (vexxtax, 0, grafptr->vnohnbr * sizeof (HgraphOrderGpVertex)); /* Initialize pass numbers */ vexxtax -= grafptr->s.baseval; #ifdef SCOTCH_DEBUG_ORDER2 memSet (ordeptr->peritab + ordenum, ~0, grafptr->vnohnbr * sizeof (Gnum)); #endif /* SCOTCH_DEBUG_ORDER2 */ for (ordeval = ordenum, rootnum = grafptr->s.baseval, /* For all connected components */ ordevnd = ordeval + grafptr->vnohnbr; ordeval < ordevnd; ) { while (vexxtax[rootnum].passnum != 0) { /* Find first unallocated root */ rootnum ++; #ifdef SCOTCH_DEBUG_ORDER2 if (rootnum >= grafptr->vnohnnd) { errorPrint ("hgraphOrderGp: internal error (1)"); memFree (queudat.qtab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_ORDER2 */ } diamnum = rootnum; /* Start from found root */ diamdist = 0; for (diamflag = 0, passnum = 1; /* Loop if modifications */ (diamflag ++ == 0) && (passnum <= paraptr->passnbr); passnum ++) { Gnum diamdegr; /* Degree of current pseudo-peripherial vertex */ hgraphOrderGpQueueFlush (&queudat); /* Flush vertex queue */ hgraphOrderGpQueuePut (&queudat, diamnum); /* Start from diameter vertex */ vexxtax[diamnum].passnum = passnum; /* It has been enqueued */ vexxtax[diamnum].vertdist = 0; /* It is at distance zero */ diamdegr = vnhdtax[diamnum] - verttax[diamnum]; do { /* Loop on vertices in queue */ vertnum = hgraphOrderGpQueueGet (&queudat); /* Get vertex from queue */ #ifdef SCOTCH_DEBUG_ORDER2 if ((vertnum < grafptr->s.baseval) || (vertnum >= grafptr->vnohnnd)) { errorPrint ("hgraphOrderGp: internal error (2)"); memFree (queudat.qtab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_ORDER2 */ vertdist = vexxtax[vertnum].vertdist; /* Get vertex distance */ if ((vertdist > diamdist) || /* If vertex increases diameter */ ((vertdist == diamdist) && /* Or is at diameter distance */ ((vnhdtax[vertnum] - verttax[vertnum]) < diamdegr))) { /* With smaller degree */ diamnum = vertnum; /* Set it as new diameter vertex */ diamdist = vertdist; diamdegr = vnhdtax[vertnum] - verttax[vertnum]; diamflag = 0; } vertdist ++; /* Set neighbor distance */ for (edgenum = verttax[vertnum]; edgenum < vnhdtax[vertnum]; edgenum ++) { Gnum vertend; vertend = edgetax[edgenum]; #ifdef SCOTCH_DEBUG_ORDER2 if ((vertend < grafptr->s.baseval) || (vertend >= grafptr->vnohnnd)) { errorPrint ("hgraphOrderGp: internal error (3)"); memFree (queudat.qtab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_ORDER2 */ if (vexxtax[vertend].passnum < passnum) { /* If vertex not queued yet */ hgraphOrderGpQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ vexxtax[vertend].passnum = passnum; vexxtax[vertend].vertdist = vertdist; } } } while (! hgraphOrderGpQueueEmpty (&queudat)); /* As long as queue is not empty */ } hgraphOrderGpQueueFlush (&queudat); /* Flush vertex queue */ hgraphOrderGpQueuePut (&queudat, diamnum); /* Start from diameter vertex */ vexxtax[diamnum].passnum = passnum; /* Vertex has been enqueued */ do { /* Loop on vertices in queue */ vertnum = hgraphOrderGpQueueGet (&queudat); /* Get vertex from queue */ if (vexxtax[vertnum].passnum > passnum) /* If vertex already ordered (by-level ordering) */ continue; /* Skip to next vertex in queue */ vertdist = vexxtax[vertnum].vertdist; /* Get vertex distance */ do { /* Loop on vertices in layer */ Gnum edgennd; /* End of edge sub-array */ ordeptr->peritab[ordeval ++] = (vnumtax == NULL) ? vertnum : vnumtax[vertnum]; vexxtax[vertnum].passnum = passnum + 1; /* Set vertex as ordered */ for (edgenum = verttax[vertnum], edgennd = vnhdtax[vertnum], vertnum = ~0; edgenum < edgennd; edgenum ++) { /* Need edgennd because vertnum is overwritten */ Gnum vertend; vertend = edgetax[edgenum]; if ((vexxtax[vertend].vertdist == vertdist) && /* If neighbor vertex in same layer */ (vexxtax[vertend].passnum <= passnum)) { /* And not yet ordered */ vertnum = vertend; /* Set neighbor as next vertex */ edgenum ++; /* Process next neighbors, not this one again */ break; /* Process next neighbors without further testing */ } if (vexxtax[vertend].passnum < passnum) { /* Else if vertex not yet enqueued */ hgraphOrderGpQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ vexxtax[vertend].passnum = passnum; /* Set it as enqueued */ } } for ( ; edgenum < edgennd; edgenum ++) { /* Enqueue remaining neighbors */ Gnum vertend; vertend = edgetax[edgenum]; if (vexxtax[vertend].passnum < passnum) { /* If neighbor not yet enqueued */ hgraphOrderGpQueuePut (&queudat, vertend); /* Enqueue neighbor vertex */ vexxtax[vertend].passnum = passnum; /* Set it as enqueued */ } } } while (vertnum != ~0); } while (! hgraphOrderGpQueueEmpty (&queudat)); /* As long as queue is not empty */ } #ifdef SCOTCH_DEBUG_ORDER2 for (ordeval = ordenum; ordeval < ordenum + grafptr->vnohnbr; ordeval ++) { if (ordeptr->peritab[ordeval] == ~0) { errorPrint ("hgraphOrderGp: internal error (4)"); memFree (queudat.qtab); /* Free group leader */ return (1); } } #endif /* SCOTCH_DEBUG_ORDER2 */ memFree (queudat.qtab); /* Group freeing */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_match_sync_ptop.c0000644000175300017530000006136511631334325024031 0ustar hazelscthazelsct/* Copyright 2008,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_match_sync_ptop.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER (v5.0) **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the distributed graph matching **/ /** routines. **/ /** **/ /** DATES : # Version 5.1 : from : 01 dec 2008 **/ /** to : 22 apr 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH_MATCH #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_coarsen.h" #include "dgraph_match.h" /*************************************/ /* */ /* These routines handle distributed */ /* source graphs. */ /* */ /*************************************/ /* This routine performs a round of point-to-point ** communication to synchronize enqueued matching ** requests across processors. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphMatchSyncPtop ( DgraphMatchData * restrict const mateptr) { Gnum queulocnbr; Gnum queulocnum; Gnum matelocnbr; Gnum multlocnbr; Gnum vertlocadj; Gnum edgekptnbr; int procngbnbr; int procngbidx; int procngbnum; int vrcvreqnbr; Dgraph * restrict const grafptr = mateptr->c.finegrafptr; const int * restrict const procngbtab = grafptr->procngbtab; int * restrict const procgsttax = mateptr->c.procgsttax; const Gnum * restrict const procvgbtab = mateptr->procvgbtab; const Gnum * restrict const vertloctax = grafptr->vertloctax; const Gnum * restrict const vendloctax = grafptr->vendloctax; const Gnum * restrict const edgeloctax = grafptr->edgeloctax; const Gnum * restrict const edgegsttax = grafptr->edgegsttax; Gnum * restrict const queuloctab = mateptr->queuloctab; Gnum * restrict const mategsttax = mateptr->mategsttax; DgraphCoarsenMulti * restrict const multloctab = mateptr->c.multloctab; int * restrict const nsndidxtab = mateptr->c.nsndidxtab; DgraphCoarsenVert * const vsnddattab = mateptr->c.vsnddattab; /* [norestrict:async] */ procngbnbr = grafptr->procngbnbr; if (procngbnbr <= 0) /* Nothing to do */ return (0); #ifdef SCOTCH_DEBUG_DGRAPH2 if (edgeloctax == NULL) { errorPrint ("dgraphMatchSyncPtop: not implemented"); return (1); } if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphMatchSyncPtop: communication error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++) /* Reset indices for sending messages */ nsndidxtab[procngbnum] = mateptr->c.vsnddsptab[procngbtab[procngbnum]]; vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - grafptr->baseval; for (queulocnum = 0, queulocnbr = mateptr->queulocnbr; queulocnum < queulocnbr; queulocnum ++) { Gnum vertlocnum; Gnum vertgstnum; Gnum edgelocnum; Gnum mategstnum; Gnum mateglbnum; int procngbnum; int vsndidxnum; vertlocnum = queuloctab[queulocnum]; /* Get local vertex index */ mategstnum = mategsttax[vertlocnum]; /* Get mate (edge ?) index */ if (mategstnum >= -1) /* If vertex not willing to mate or matched locally after being considered during matching phase */ continue; edgelocnum = -2 - mategstnum; /* Get local edge to mate ghost vertex */ #ifdef SCOTCH_DEBUG_DGRAPH2 if ((edgelocnum < grafptr->baseval) || (edgelocnum >= (grafptr->edgelocsiz + grafptr->baseval)) || (mategsttax[edgegsttax[edgelocnum]] != -1)) { errorPrint ("dgraphMatchSyncPtop: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ mateglbnum = edgeloctax[edgelocnum]; vertgstnum = edgegsttax[edgelocnum]; procngbnum = procgsttax[vertgstnum]; /* Find neighbor owner process */ if (procngbnum < 0) { /* If neighbor not yet computed */ int procngbmax; procngbnum = 0; procngbmax = procngbnbr; while ((procngbmax - procngbnum) > 1) { /* Find owner process by dichotomy on procvgbtab */ int procngbmed; procngbmed = (procngbmax + procngbnum) / 2; if (procvgbtab[procngbmed] > mateglbnum) procngbmax = procngbmed; else procngbnum = procngbmed; } procgsttax[vertgstnum] = procngbnum; } #ifdef SCOTCH_DEBUG_DGRAPH2 if ((grafptr->procvrttab[procngbtab[procngbnum]] > mateglbnum) || (grafptr->procvrttab[procngbtab[procngbnum] + 1] <= mateglbnum)) { errorPrint ("dgraphMatchSyncPtop: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ vsndidxnum = nsndidxtab[procngbnum] ++; /* Get position of message in send array */ #ifdef SCOTCH_DEBUG_DGRAPH2 if (vsndidxnum >= mateptr->c.vsnddsptab[procngbtab[procngbnum] + 1]) { errorPrint ("dgraphMatchSyncPtop: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ vsnddattab[vsndidxnum].datatab[0] = vertlocnum + vertlocadj; vsnddattab[vsndidxnum].datatab[1] = mateglbnum; } for (procngbidx = 0; procngbidx < procngbnbr; procngbidx ++) { /* Post receives of mating requests in descending order */ int procngbnum; int procglbnum; procngbnum = (mateptr->c.procngbnxt + (procngbnbr - 1) - procngbidx) % procngbnbr; procglbnum = procngbtab[procngbnum]; if (MPI_Irecv (mateptr->c.vrcvdattab + mateptr->c.vrcvdsptab[procglbnum], 2 * (mateptr->c.vrcvdsptab[procglbnum + 1] - mateptr->c.vrcvdsptab[procglbnum]), GNUM_MPI, procglbnum, TAGMATCH, grafptr->proccomm, &mateptr->c.nrcvreqtab[procngbnum]) != MPI_SUCCESS) { errorPrint ("dgraphMatchSyncPtop: communication error (2)"); return (1); } } for (procngbidx = 0; procngbidx < procngbnbr; procngbidx ++) { /* Post sends of mating requests in ascending order */ int procngbnum; int procglbnum; procngbnum = (procngbidx + mateptr->c.procngbnxt) % procngbnbr; procglbnum = procngbtab[procngbnum]; if (MPI_Isend (vsnddattab + mateptr->c.vsnddsptab[procglbnum], 2 * (nsndidxtab[procngbnum] - mateptr->c.vsnddsptab[procglbnum]), GNUM_MPI, procglbnum, TAGMATCH, grafptr->proccomm, &mateptr->c.nsndreqtab[procngbnum]) != MPI_SUCCESS) { errorPrint ("dgraphMatchSyncPtop: communication error (3)"); return (1); } } matelocnbr = mateptr->matelocnbr; multlocnbr = mateptr->c.multlocnbr; edgekptnbr = mateptr->c.edgekptnbr; for (vrcvreqnbr = procngbnbr; vrcvreqnbr > 0; vrcvreqnbr --) { /* For all pending receive requests */ int procglbnum; int procngbnum; int vrcvidxnnd; int requrcvnum; int requnxtnum; /* Index of location where to pack requests to process when all messages arrive */ MPI_Status statdat; int statsiz; int o; #ifdef SCOTCH_DETERMINISTIC procngbnum = vrcvreqnbr - 1; o = MPI_Wait (&mateptr->c.nrcvreqtab[procngbnum], &statdat); #else /* SCOTCH_DETERMINISTIC */ o = MPI_Waitany (procngbnbr, mateptr->c.nrcvreqtab, &procngbnum, &statdat); #endif /* SCOTCH_DETERMINISTIC */ if ((o != MPI_SUCCESS) || (MPI_Get_count (&statdat, GNUM_MPI, &statsiz) != MPI_SUCCESS)) { errorPrint ("dgraphMatchSyncPtop: communication error (4)"); return (1); } #ifdef SCOTCH_DEBUG_DGRAPH2 if (statdat.MPI_SOURCE != procngbtab[procngbnum]) { errorPrint ("dgraphMatchSyncPtop: internal error (4)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ procglbnum = procngbtab[procngbnum]; vrcvidxnnd = mateptr->c.vrcvdsptab[procglbnum]; if (statsiz <= 0) { /* If query message is empty */ mateptr->c.nrcvidxtab[procngbnum] = -1; /* No need to send a reply */ continue; /* Skip message processing */ } else { Gnum vertsndnbr; /* Number of vertices to be sent to requesting neighbor */ Gnum edgesndnbr; /* Number of edges to be sent to requesting neighbor */ DgraphCoarsenVert * restrict const vrcvdattab = mateptr->c.vrcvdattab; /* Local restrict pointer only when data available (has been received) */ vertsndnbr = edgesndnbr = 0; for (requrcvnum = requnxtnum = vrcvidxnnd, vrcvidxnnd += (statsiz / 2); /* TRICK: each message item costs 2 Gnum's */ requrcvnum < vrcvidxnnd; requrcvnum ++) { Gnum vertglbnum; /* Our global number (the one seen as mate by sender) */ Gnum vertlocnum; /* Our local number (the one seen as mate by sender) */ Gnum vmatglbnum; /* Global number of requesting mate (sender of message) */ Gnum mategstnum; /* The mate we wanted to ask for */ vmatglbnum = vrcvdattab[requrcvnum].datatab[0]; /* Names are opposite because receiving side */ vertglbnum = vrcvdattab[requrcvnum].datatab[1]; vertlocnum = vertglbnum - vertlocadj; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((vertlocnum < grafptr->baseval) || /* If matching request is not directed towards our process */ (vertlocnum >= grafptr->vertlocnnd)) { errorPrint ("dgraphMatchSyncPtop: internal error (5)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ mategstnum = mategsttax[vertlocnum]; /* Get our local mating decision data */ if (mategstnum == -1) { /* If local vertex wanted for mating is free */ Gnum edgelocnum; for (edgelocnum = vertloctax[vertlocnum]; edgeloctax[edgelocnum] != vmatglbnum; edgelocnum ++) { #ifdef SCOTCH_DEBUG_DGRAPH2 if (edgelocnum >= vendloctax[vertlocnum]) { errorPrint ("dgraphMatchSyncPtop: internal error (6)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ } mategsttax[edgegsttax[edgelocnum]] = vertglbnum; /* We are no longer free */ mategsttax[vertlocnum] = vmatglbnum; /* Leave message as is to acknowledge it */ matelocnbr ++; vertsndnbr ++; edgesndnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; } else if (mategstnum < -1) { /* If local vertex is also asking for mating */ Gnum edgelocnum; Gnum mateglbnum; edgelocnum = -2 - mategstnum; mateglbnum = edgeloctax[edgelocnum]; /* Get global number of our remote mate */ if (mateglbnum == vmatglbnum) { /* If it is with the sender */ Gnum flagval; /* Flag for choosing side to create multinode */ mategsttax[vertlocnum] = mateglbnum; /* Say we are mated to inform future requesting processes in same pass */ mategsttax[edgegsttax[edgelocnum]] = vertglbnum; flagval = (mateglbnum > vertglbnum) ? 1 : 0; /* Compute pseudo-random flag always opposite for both ends */ flagval = ((mateglbnum + (mateglbnum - vertglbnum) * flagval) & 1) ^ flagval; if (flagval == 0) { /* If flag is even, create multinode */ multloctab[multlocnbr].vertglbnum[0] = vertglbnum; multloctab[multlocnbr].vertglbnum[1] = mategstnum; /* Remote mate: negative value */ multlocnbr ++; /* One more coarse vertex created */ edgekptnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; } else { /* If flag is odd, prepare to send vertex data at build time */ vertsndnbr ++; edgesndnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; } /* Go on by destroying message in all cases since both ends know what it is about */ vrcvdattab[requrcvnum --] = vrcvdattab[-- vrcvidxnnd]; /* Replace current message with another one and process it */ matelocnbr ++; /* One more local vertex mated on each side; no messages will tell it */ } else { /* If willing to mate but not with the sender, tell later with whom */ DgraphCoarsenVert vertdat; /* Temporary storage data for swapping vertices */ vertdat = vrcvdattab[requnxtnum]; /* Pack requests to process later at beginning of message */ vrcvdattab[requnxtnum].datatab[0] = vmatglbnum; vrcvdattab[requnxtnum].datatab[1] = -2 - vertlocnum; /* Build appropriate answer to mating request later, when all messages arrived */ if (requnxtnum ++ != requrcvnum) vrcvdattab[requrcvnum] = vertdat; /* Swap vertices if not already at the right place */ } } else /* If already matched, inform sender */ vrcvdattab[requrcvnum].datatab[1] = mategstnum; } mateptr->c.dcntloctab[procglbnum].vertsndnbr += vertsndnbr; mateptr->c.dcntloctab[procglbnum].edgesndnbr += edgesndnbr; } mateptr->c.nrcvidxtab[procngbnum] = vrcvidxnnd; } if (MPI_Waitall (procngbnbr, mateptr->c.nsndreqtab, MPI_STATUSES_IGNORE) != MPI_SUCCESS) { /* Wait for send requests of mating requests to complete */ errorPrint ("dgraphMatchSyncPtop: communication error (5)"); return (1); } #ifdef SCOTCH_DEBUG_DGRAPH2 if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphMatchSyncPtop: communication error (6)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ vrcvreqnbr = procngbnbr; /* Count number of receive requests we will have to consider */ for (procngbidx = 0; procngbidx < procngbnbr; procngbidx ++) { /* Post receives of mating replies in descending order */ int procngbnum; int procglbnum; procngbnum = (mateptr->c.procngbnxt + (procngbnbr - 1) - procngbidx) % procngbnbr; procglbnum = procngbtab[procngbnum]; if (nsndidxtab[procngbnum] <= mateptr->c.vsnddsptab[procglbnum]) { /* If we had sent an empty query message, do not expect any reply */ mateptr->c.nrcvreqtab[procngbnum] = MPI_REQUEST_NULL; vrcvreqnbr --; /* One less receive request to wait for */ continue; } if (MPI_Irecv (vsnddattab + mateptr->c.vsnddsptab[procglbnum], 2 * (mateptr->c.vsnddsptab[procglbnum + 1] - mateptr->c.vsnddsptab[procglbnum]), GNUM_MPI, procglbnum, TAGMATCH + 1, grafptr->proccomm, &mateptr->c.nrcvreqtab[procngbnum]) != MPI_SUCCESS) { errorPrint ("dgraphMatchSyncPtop: communication error (7)"); return (1); } } for (procngbidx = 0; procngbidx < procngbnbr; procngbidx ++) { /* Post sends of mating requests in ascending order */ int procngbnum; int procglbnum; int vsndidxnnd; procngbnum = (procngbidx + mateptr->c.procngbnxt) % procngbnbr; procglbnum = procngbtab[procngbnum]; vsndidxnnd = mateptr->c.nrcvidxtab[procngbnum]; /* Re-send (or not) the messages we have received to acknowledge */ if (vsndidxnnd >= 0) { /* If we had received a non-empty message (but reply might be empty) */ int vsndidxnum; DgraphCoarsenVert * restrict const vrcvdattab = mateptr->c.vrcvdattab; /* Local restrict pointer only when data available */ for (vsndidxnum = mateptr->c.vrcvdsptab[procglbnum]; /* Finalize unfinished messages */ vsndidxnum < vsndidxnnd; vsndidxnum ++) { Gnum vertlocnum; Gnum mateglbnum; vertlocnum = vrcvdattab[vsndidxnum].datatab[1]; if (vertlocnum >= 0) /* If no more unfinished messages to process, quit scanning */ break; vertlocnum = -2 - vertlocnum; mateglbnum = mategsttax[vertlocnum]; if (mateglbnum >= 0) /* If vertex we wanted to mate with has been mated in this round */ vrcvdattab[vsndidxnum].datatab[1] = mateglbnum; /* Propagate this information back to the requester */ else { /* Vertex mating data not yet available (maybe in answer) */ vrcvdattab[vsndidxnum] = vrcvdattab[-- vsndidxnnd]; /* Remove message as no reply means not willing */ if (vrcvdattab[vsndidxnum].datatab[1] < 0) /* If replacing message is also to be processed */ vsndidxnum --; /* Do not skip replaced message in next iteration */ } } if (MPI_Isend (vrcvdattab + mateptr->c.vrcvdsptab[procglbnum], 2 * (vsndidxnnd - mateptr->c.vrcvdsptab[procglbnum]), GNUM_MPI, procglbnum, TAGMATCH + 1, grafptr->proccomm, &mateptr->c.nsndreqtab[procngbnum]) != MPI_SUCCESS) { errorPrint ("dgraphMatchSyncPtop: communication error (8)"); return (1); } } #ifdef SCOTCH_DEBUG_DGRAPH2 else { if (mateptr->c.nsndreqtab[procngbnum] != MPI_REQUEST_NULL) { /* Should have been set by previous MPI_Waitall() */ errorPrint ("dgraphMatchSyncPtop: internal error (7)"); return (1); } } #endif /* SCOTCH_DEBUG_DGRAPH2 */ } #ifdef SCOTCH_DETERMINISTIC vrcvreqnbr = procngbnbr; /* For deterministic behavior, consider all neighbors in order, whether communicating or not */ #endif /* SCOTCH_DETERMINISTIC */ for ( ; vrcvreqnbr > 0; vrcvreqnbr --) { /* For all pending receive requests */ int vrcvidxnnd; int vrcvidxnum; int procngbnum; MPI_Status statdat; int statsiz; int o; #ifdef SCOTCH_DETERMINISTIC procngbnum = vrcvreqnbr - 1; if (mateptr->c.nrcvreqtab[procngbnum] == MPI_REQUEST_NULL) /* If we do not expect this message, skip it */ continue; o = MPI_Wait (&mateptr->c.nrcvreqtab[procngbnum], &statdat); #else /* SCOTCH_DETERMINISTIC */ o = MPI_Waitany (procngbnbr, mateptr->c.nrcvreqtab, &procngbnum, &statdat); #endif /* SCOTCH_DETERMINISTIC */ if ((o != MPI_SUCCESS) || (MPI_Get_count (&statdat, GNUM_MPI, &statsiz) != MPI_SUCCESS)) { errorPrint ("dgraphMatchSyncPtop: communication error (9)"); return (1); } for (vrcvidxnum = mateptr->c.vsnddsptab[procngbtab[procngbnum]], vrcvidxnnd = vrcvidxnum + (statsiz / 2); /* TRICK: each message item costs 2 Gnum's */ vrcvidxnum < vrcvidxnnd; vrcvidxnum ++) { Gnum edgelocnum; Gnum vertglbnum; /* Our global number (the one seen as mate by sender) */ Gnum vertlocnum; /* Our local number (the one seen as mate by sender) */ Gnum vmatglbnum; /* Global number of vertex to which the mate is mated */ Gnum mategstnum; /* The mate we wanted to ask for */ vertglbnum = vsnddattab[vrcvidxnum].datatab[0]; vmatglbnum = vsnddattab[vrcvidxnum].datatab[1]; vertlocnum = vertglbnum - vertlocadj; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((vertlocnum < grafptr->baseval) || /* If matching reply is not directed towards our process */ (vertlocnum >= grafptr->vertlocnnd)) { errorPrint ("dgraphMatchSyncPtop: internal error (8)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ mategstnum = mategsttax[vertlocnum]; /* Get our local mating decision data */ edgelocnum = -2 - mategstnum; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((mategstnum >= -1) || /* If we did not ask anything or if we were already matched, no reply message should come to us */ ((mategsttax[edgegsttax[edgelocnum]] >= 0) && /* Also, if our prospective mate was itself already set as matched by a previous reply */ (mategsttax[edgegsttax[edgelocnum]] != vertglbnum) && /* And this message is not the positive reply which acknowledges this mating */ (mategsttax[edgegsttax[edgelocnum]] != vmatglbnum))) { /* Or an informative negative reply which gives again the mate of the ghost */ errorPrint ("dgraphMatchSyncPtop: internal error (9)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (edgeloctax[edgelocnum] == vmatglbnum) { /* If positive answer from the mate we wanted */ mategsttax[vertlocnum] = vmatglbnum; /* Set local vertex as matched with the mate */ mategsttax[edgegsttax[edgelocnum]] = vertglbnum; /* Update state of ghost mate */ multloctab[multlocnbr].vertglbnum[0] = vertglbnum; multloctab[multlocnbr].vertglbnum[1] = mategstnum; /* Remote mate: negative value */ multlocnbr ++; /* One more coarse vertex created */ matelocnbr ++; edgekptnbr += vendloctax[vertlocnum] - vertloctax[vertlocnum]; } else { /* If negative answer from the mate we wanted */ mategsttax[vertlocnum] = -1; /* Reset local vertex as free for mating */ mategsttax[edgegsttax[edgelocnum]] = vmatglbnum; /* Update state of unwilling ghost mate */ } } } mateptr->matelocnbr = matelocnbr; mateptr->c.multlocnbr = multlocnbr; mateptr->c.edgekptnbr = edgekptnbr; if (MPI_Waitall (procngbnbr, mateptr->c.nsndreqtab, MPI_STATUSES_IGNORE) != MPI_SUCCESS) { /* Wait for send requests of mating requests to complete */ errorPrint ("dgraphMatchSyncPtop: communication error (10)"); return (1); } #ifdef SCOTCH_DEBUG_DGRAPH2 if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphMatchSyncPtop: communication error (11)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_match.h0000644000175300017530000001077511631334325021737 0ustar hazelscthazelsct/* Copyright 2007-2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_match.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER (v5.0) **/ /** **/ /** FUNCTION : This file provides the structure **/ /** definitions for the coasening phase of **/ /** the multi-level method. **/ /** **/ /** DATES : # Version 5.0 : from : 04 may 2006 **/ /** to : 21 jun 2007 **/ /** # Version 5.1 : from : 23 nov 2008 **/ /** to : 04 apr 2009 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /* This structure contains all the tables describing the matching state */ typedef struct DgraphMatchData_ { DgraphCoarsenData c; /*+ Coarsening structure +*/ Gnum * mategsttax; /*+ Mating table for local and ghost vertices +*/ Gnum matelocnbr; /*+ Number of local matchings +*/ Gnum * queuloctab; /*+ Queue of unmated local vertex +*/ Gnum queulocnbr; /*+ Number of enqueued unmated vertices +*/ Gnum * procvgbtab; /*+ Global vertex number bounds for neighboring processors [+1] +*/ float probval; /*+ Vertex mating probability (1.0 is certain) +*/ } DgraphMatchData; /* ** The function prototypes. */ int dgraphMatchInit (DgraphMatchData * restrict const, const float); void dgraphMatchExit (DgraphMatchData * restrict const); int dgraphMatchSync (DgraphMatchData * restrict const); int dgraphMatchSyncColl (DgraphMatchData * restrict const); int dgraphMatchSyncPtop (DgraphMatchData * restrict const); int dgraphMatchCheck (DgraphMatchData * restrict const); void dgraphMatchSc (DgraphMatchData * restrict const); void dgraphMatchHy (DgraphMatchData * restrict const); void dgraphMatchLc (DgraphMatchData * restrict const); void dgraphMatchLy (DgraphMatchData * restrict const); scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_order_f.c0000644000175300017530000001716511631334325024002 0ustar hazelscthazelsct/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_order_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** distributed graph ordering routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 16 feb 2007 **/ /** to 31 may 2008 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 25 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the ordering routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFDGRAPHORDERINIT, scotchfdgraphorderinit, ( \ const SCOTCH_Dgraph * const grafptr, \ SCOTCH_Dordering * const ordeptr, \ int * const revaptr), \ (grafptr, ordeptr, revaptr)) { *revaptr = SCOTCH_dgraphOrderInit (grafptr, ordeptr); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHORDEREXIT, scotchfdgraphorderexit, ( \ const SCOTCH_Dgraph * const grafptr, \ SCOTCH_Dordering * const ordeptr), \ (grafptr, ordeptr)) { SCOTCH_dgraphOrderExit (grafptr, ordeptr); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHORDERSAVE, scotchfdgraphordersave, ( \ const SCOTCH_Dgraph * const grafptr, \ const SCOTCH_Dordering * const ordeptr, \ int * const fileptr, \ int * const revaptr), \ (grafptr, ordeptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if (*fileptr == -1) /* If process is not the root */ stream = NULL; else { /* Open stream for root process */ if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFDGRAPHORDERSAVE: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFDGRAPHORDERSAVE: cannot open output stream"); close (filenum); *revaptr = 1; return; } } o = SCOTCH_dgraphOrderSave (grafptr, ordeptr, stream); if (stream != NULL) fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHORDERCOMPUTE, scotchfdgraphordercompute, ( \ SCOTCH_Dgraph * const grafptr, \ SCOTCH_Dordering * const ordeptr, \ SCOTCH_Strat * const stratptr, \ int * const revaptr), \ (grafptr, ordeptr, stratptr, revaptr)) { *revaptr = SCOTCH_dgraphOrderCompute (grafptr, ordeptr, stratptr); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHORDERCOMPUTELIST, scotchfdgraphordercomputelist, ( \ SCOTCH_Dgraph * const grafptr, \ SCOTCH_Dordering * const ordeptr, \ const SCOTCH_Num * listptr, \ const SCOTCH_Num * const listtab, \ SCOTCH_Strat * const stratptr, \ int * const revaptr), \ (grafptr, ordeptr, listptr, listtab, stratptr, revaptr)) { *revaptr = SCOTCH_dgraphOrderComputeList (grafptr, ordeptr, *listptr, listtab, stratptr); } /* ** */ FORTRAN ( \ SCOTCHFSTRATDGRAPHORDER, scotchfstratdgraphorder, ( \ SCOTCH_Strat * const stratptr, \ const char * const string, \ int * const revaptr, \ const int strnbr), \ (stratptr, string, revaptr, strnbr)) { char * restrict strtab; /* Pointer to null-terminated string */ if ((strtab = (char *) memAlloc (strnbr + 1)) == NULL) { /* Allocate temporary space */ errorPrint ("SCOTCHFSTRATDGRAPHORDER: out of memory (1)"); *revaptr = 1; } memCpy (strtab, string, strnbr); /* Copy string contents */ strtab[strnbr] = '\0'; /* Terminate string */ *revaptr = SCOTCH_stratDgraphOrder (stratptr, strtab); /* Call original routine */ memFree (strtab); /* Prevent compiler warnings */ } /* ** */ FORTRAN ( \ SCOTCHFSTRATDGRAPHORDERBUILD, scotchfstratdgraphorderbuild, ( \ SCOTCH_Strat * const stratptr, \ const SCOTCH_Num * const flagval, \ const SCOTCH_Num * const procnbr, \ const double * const balrat, \ int * const revaptr), \ (stratptr, flagval, procnbr, balrat, revaptr)) { *revaptr = SCOTCH_stratDgraphOrderBuild (stratptr, *flagval, *procnbr, *balrat); } scotch-5.1.12b.dfsg/src/libscotch/hgraph_induce.h0000644000175300017530000000575111631334325022114 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_induce.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the halo graph subgraph making **/ /** functions. **/ /** **/ /** DATES : # Version 4.0 : from : 10 jan 2002 **/ /** to 22 dec 2002 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef HGRAPH_INDUCE #define static #endif static int hgraphInduce2 (const Hgraph * const, Gnum * const, Hgraph * const, const Gnum, Gnum * const); static void hgraphInduce2L (const Hgraph * const, Gnum * const, Hgraph * const); static void hgraphInduce2U (const Hgraph * const, Gnum * const, Hgraph * const); static Gnum hgraphInduce3 (const Hgraph * const, const VertList * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_io_save_f.c0000644000175300017530000000777311631334325024320 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_io_save_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the distributed source graph handling **/ /** routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 16 may 2007 **/ /** to 16 may 2007 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 27 mar 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the graph handling routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFDGRAPHSAVE, scotchfdgraphsave, ( \ SCOTCH_Dgraph * const grafptr, \ int * const fileptr, \ int * const revaptr), \ (grafptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFDGRAPHSAVE: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFDGRAPHSAVE: cannot open output stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_dgraphSave (grafptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } scotch-5.1.12b.dfsg/src/libscotch/graph_io.c0000644000175300017530000004013311631334325021070 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_io.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles the source graph **/ /** input/output functions. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to 18 may 1993 **/ /** # Version 1.3 : from : 30 apr 1994 **/ /** to 18 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 31 oct 1994 **/ /** # Version 3.0 : from : 07 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 28 nov 1995 **/ /** to 08 jun 1996 **/ /** # Version 3.2 : from : 07 sep 1996 **/ /** to 15 mar 1999 **/ /** # Version 4.0 : from : 25 nov 2001 **/ /** to 21 jan 2004 **/ /** # Version 5.0 : from : 13 dec 2006 **/ /** to 10 sep 2007 **/ /** # Version 5.1 : from : 11 aug 2010 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GRAPH_IO #include "module.h" #include "common.h" #include "graph.h" #include "graph_io.h" /*******************************************/ /* */ /* These routines handle source graph I/O. */ /* */ /*******************************************/ /* This routine loads a source graph from ** the given stream. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int graphLoad ( Graph * restrict const grafptr, /* Graph structure to fill */ FILE * const stream, /* Stream from which to read graph data */ const Gnum baseval, /* Base value (-1 means keep file base) */ const GraphFlag flagval) /* Graph loading flags */ { Gnum edgenum; /* Number of edges really allocated */ Gnum edgennd; Gnum vlblnbr; /* = vertnbr if vertex labels */ Gnum vlblmax; /* Maximum vertex label number */ Gnum velonbr; /* = vertnbr if vertex loads wanted */ Gnum velosum; /* Sum of vertex loads */ Gnum edlonbr; /* = edgenbr if edge loads wanted */ Gnum edlosum; /* Sum of edge loads */ Gnum edgeval; /* Value where to read edge end */ Gnum baseadj; Gnum versval; Gnum degrmax; Gnum propval; char proptab[4]; Gnum vertnum; memSet (grafptr, 0, sizeof (Graph)); if (intLoad (stream, &versval) != 1) { /* Read version number */ errorPrint ("graphLoad: bad input (1)"); return (1); } if (versval != 0) { /* If version not zero */ errorPrint ("graphLoad: old-style graph format no longer supported"); return (1); } if ((intLoad (stream, &grafptr->vertnbr) != 1) || /* Read rest of header */ (intLoad (stream, &grafptr->edgenbr) != 1) || (intLoad (stream, &baseadj) != 1) || (intLoad (stream, &propval) != 1) || (propval < 0) || (propval > 111)) { errorPrint ("graphLoad: bad input (2)"); return (1); } sprintf (proptab, "%3.3d", (int) propval); /* Compute file properties */ proptab[0] -= '0'; /* Vertex labels flag */ proptab[1] -= '0'; /* Edge weights flag */ proptab[2] -= '0'; /* Vertex loads flag */ grafptr->flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; if (baseval == -1) { /* If keep file graph base */ grafptr->baseval = baseadj; /* Set graph base as file base */ baseadj = 0; /* No base adjustment needed */ } else { /* If set graph base */ grafptr->baseval = baseval; /* Set wanted graph base */ baseadj = baseval - baseadj; /* Update base adjust */ } if (proptab[0] != 0) /* If vertex labels, no base adjust */ baseadj = 0; velonbr = ((proptab[2] != 0) && ((flagval & GRAPHIONOLOADVERT) == 0)) ? grafptr->vertnbr : 0; vlblnbr = (proptab[0] != 0) ? grafptr->vertnbr : 0; edlonbr = ((proptab[1] != 0) && ((flagval & GRAPHIONOLOADEDGE) == 0)) ? grafptr->edgenbr : 0; if ((memAllocGroup ((void **) (void *) &grafptr->verttax, (size_t) ((grafptr->vertnbr + 1) * sizeof (Gnum)), &grafptr->velotax, (size_t) (velonbr * sizeof (Gnum)), &grafptr->vlbltax, (size_t) (vlblnbr * sizeof (Gnum)), NULL) == NULL) || (memAllocGroup ((void **) (void *) &grafptr->edgetax, (size_t) (grafptr->edgenbr * sizeof (Gnum)), &grafptr->edlotax, (size_t) (edlonbr * sizeof (Gnum)), NULL) == NULL)) { if (grafptr->verttax != NULL) memFree (grafptr->verttax); errorPrint ("graphLoad: out of memory"); graphFree (grafptr); return (1); } grafptr->vertnnd = grafptr->vertnbr + grafptr->baseval; grafptr->verttax -= grafptr->baseval; grafptr->vendtax = grafptr->verttax + 1; /* Use compact vertex array */ grafptr->velotax = (velonbr != 0) ? (grafptr->velotax - grafptr->baseval) : NULL; grafptr->vlbltax = (vlblnbr != 0) ? (grafptr->vlbltax - grafptr->baseval) : NULL; grafptr->edgetax -= grafptr->baseval; grafptr->edlotax = (edlonbr != 0) ? (grafptr->edlotax - grafptr->baseval) : NULL; vlblmax = grafptr->vertnnd - 1; /* No vertex labels known */ velosum = (grafptr->velotax == NULL) ? grafptr->vertnbr : 0; edlosum = (grafptr->edlotax == NULL) ? grafptr->edgenbr : 0; edgennd = grafptr->edgenbr + grafptr->baseval; degrmax = 0; /* No maximum degree yet */ for (vertnum = edgenum = grafptr->baseval; vertnum < grafptr->vertnnd; vertnum ++) { Gnum degrval; if (grafptr->vlbltax != NULL) { /* If must read label */ Gnum vlblval; /* Value where to read vertex label */ if (intLoad (stream, &vlblval) != 1) { /* Read label data */ errorPrint ("graphLoad: bad input (3)"); graphFree (grafptr); return (1); } grafptr->vlbltax[vertnum] = vlblval; if (grafptr->vlbltax[vertnum] > vlblmax) /* Get maximum vertex label */ vlblmax = grafptr->vlbltax[vertnum]; } if (proptab[2] != 0) { /* If must read vertex load */ Gnum veloval; /* Value where to read vertex load */ if (intLoad (stream, &veloval) != 1) { /* Read vertex load data */ errorPrint ("graphLoad: bad input (4)"); graphFree (grafptr); return (1); } if (grafptr->velotax != NULL) velosum += grafptr->velotax[vertnum] = veloval; } if (intLoad (stream, °rval) != 1) { /* Read vertex degree */ errorPrint ("graphLoad: bad input (5)"); graphFree (grafptr); return (1); } if (degrmax < degrval) /* Set maximum degree */ degrmax = degrval; grafptr->verttax[vertnum] = edgenum; /* Set index in edge array */ degrval += edgenum; if (degrval > edgennd) { /* Check if edge array overflows */ errorPrint ("graphLoad: invalid arc count (1)"); graphFree (grafptr); return (1); } for ( ; edgenum < degrval; edgenum ++) { if (proptab[1] != 0) { /* If must read edge load */ Gnum edloval; /* Value where to read edge load */ if (intLoad (stream, &edloval) != 1) { /* Read edge load data */ errorPrint ("graphLoad: bad input (6)"); graphFree (grafptr); return (1); } if (grafptr->edlotax != NULL) edlosum += grafptr->edlotax[edgenum] = (Gnum) edloval; } if (intLoad (stream, &edgeval) != 1) { /* Read edge data */ errorPrint ("graphLoad: bad input (7)"); graphFree (grafptr); return (1); } grafptr->edgetax[edgenum] = edgeval + baseadj; } } grafptr->verttax[vertnum] = edgenum; /* Set end of edge array */ if (edgenum != edgennd) { /* Check if number of edges is valid */ errorPrint ("graphLoad: invalid arc count (2)"); graphFree (grafptr); return (1); } grafptr->velosum = velosum; grafptr->edlosum = edlosum; grafptr->degrmax = degrmax; if (grafptr->vlbltax != NULL) { /* If vertex label renaming necessary */ if (graphLoad2 (grafptr->baseval, grafptr->vertnnd, grafptr->verttax, /* Rename edge ends */ grafptr->vendtax, grafptr->edgetax, vlblmax, grafptr->vlbltax) != 0) { errorPrint ("graphLoad: cannot relabel vertices"); graphFree (grafptr); return (1); } } #ifdef SCOTCH_DEBUG_GRAPH2 if (graphCheck (grafptr) != 0) { /* Check graph consistency */ errorPrint ("graphLoad: inconsistent graph data"); graphFree (grafptr); return (1); } #endif /* SCOTCH_DEBUG_GRAPH2 */ return (0); } int graphLoad2 ( const Gnum baseval, const Gnum vertnnd, const Gnum * const verttax, const Gnum * const vendtax, Gnum * restrict const edgetax, const Gnum vlblmax, const Gnum * const vlbltax) { Gnum vertnum; /* Number of current vertex */ Gnum * restrict indxtab; /* Vertex label/number index table */ if ((indxtab = (Gnum *) memAlloc ((vlblmax + 1) * sizeof (Gnum))) == NULL) { errorPrint ("graphLoad2: out of memory"); return (1); } memSet (indxtab, ~0, (vlblmax + 1) * sizeof (Gnum)); /* Assume labels not used */ for (vertnum = baseval; vertnum < vertnnd; vertnum ++) { if (indxtab[vlbltax[vertnum]] != ~0) { /* If vertex label already used */ errorPrint ("graphLoad2: duplicate vertex label"); memFree (indxtab); return (1); } indxtab[vlbltax[vertnum]] = vertnum; /* Set vertex number index */ } for (vertnum = baseval; vertnum < vertnnd; vertnum ++) { Gnum edgenum; /* Number of current edge */ for (edgenum = verttax[vertnum]; edgenum < vendtax[vertnum]; edgenum ++) { if (edgetax[edgenum] > vlblmax) { /* If invalid edge end number */ errorPrint ("graphLoad2: invalid arc end number (1)"); memFree (indxtab); return (1); } if (indxtab[edgetax[edgenum]] == ~0) { /* If unused edge end number */ errorPrint ("graphLoad2: invalid arc end number (2)"); memFree (indxtab); return (1); } edgetax[edgenum] = indxtab[edgetax[edgenum]]; /* Replace label by number */ } } memFree (indxtab); /* Free index array */ return (0); } /* This routine saves a source graph to ** the given stream, in the new-style ** graph format. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int graphSave ( const Graph * const grafptr, FILE * const stream) { Gnum vertnum; char propstr[4]; /* Property string */ int o; propstr[0] = (grafptr->vlbltax != NULL) ? '1' : '0'; /* Set property string */ propstr[1] = (grafptr->edlotax != NULL) ? '1' : '0'; propstr[2] = (grafptr->velotax != NULL) ? '1' : '0'; propstr[3] = '\0'; if (fprintf (stream, "0\n" GNUMSTRING "\t" GNUMSTRING "\n" GNUMSTRING "\t%3s\n", /* Write file header */ (Gnum) grafptr->vertnbr, (Gnum) grafptr->edgenbr, (Gnum) grafptr->baseval, propstr) == EOF) { errorPrint ("graphSave: bad output (1)"); return (1); } for (vertnum = grafptr->baseval, o = 0; (vertnum < grafptr->vertnnd) && (o == 0); vertnum ++) { Gnum edgenum; if (grafptr->vlbltax != NULL) /* Write vertex label if necessary */ o = (fprintf (stream, GNUMSTRING "\t", (Gnum) grafptr->vlbltax[vertnum]) == EOF); if (grafptr->velotax != NULL) /* Write vertex load if necessary */ o |= (fprintf (stream, GNUMSTRING "\t", (Gnum) grafptr->velotax[vertnum]) == EOF); o |= (fprintf (stream, GNUMSTRING, (Gnum) (grafptr->vendtax[vertnum] - grafptr->verttax[vertnum])) == EOF); /* Write vertex degree */ for (edgenum = grafptr->verttax[vertnum]; (edgenum < grafptr->vendtax[vertnum]) && (o == 0); edgenum ++) { Gnum vertend; o |= (putc ('\t', stream) == EOF); if (grafptr->edlotax != NULL) /* Write edge load if necessary */ o |= (fprintf (stream, GNUMSTRING "\t", (Gnum) grafptr->edlotax[edgenum]) == EOF); vertend = grafptr->edgetax[edgenum]; o |= (fprintf (stream, GNUMSTRING, (Gnum) ((grafptr->vlbltax != NULL) ? grafptr->vlbltax[vertend] : vertend)) == EOF); /* Write edge end */ } o |= (putc ('\n', stream) == EOF); } if (o != 0) errorPrint ("graphSave: bad output (2)"); return (o); } scotch-5.1.12b.dfsg/src/libscotch/common_file_compress.c0000644000175300017530000002556511631334325023516 0ustar hazelscthazelsct/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : common_file_compress.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles compressed streams **/ /** for compression. **/ /** **/ /** DATES : # Version 5.0 : from : 13 mar 2008 **/ /** to : 15 may 2008 **/ /** # Version 5.1 : from : 27 jun 2010 **/ /** to 27 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define COMMON_FILE #define COMMON_FILE_COMPRESS #ifndef COMMON_NOMODULE #include "module.h" #endif /* COMMON_NOMODULE */ #include "common.h" #include "common_file.h" #include "common_file_compress.h" #ifdef COMMON_FILE_COMPRESS_BZ2 #include "bzlib.h" #endif /* COMMON_FILE_COMPRESS_BZ2 */ #ifdef COMMON_FILE_COMPRESS_GZ #include "zlib.h" #endif /* COMMON_FILE_COMPRESS_GZ */ /* ** The static definitions. */ static FileCompressTab filetab[] = { #ifdef COMMON_FILE_COMPRESS_BZ2 { ".bz2", FILECOMPRESSTYPEBZ2, }, #else /* COMMON_FILE_COMPRESS_BZ2 */ { ".bz2", FILECOMPRESSTYPENOTIMPL }, #endif /* COMMON_FILE_COMPRESS_BZ */ #ifdef COMMON_FILE_COMPRESS_GZ { ".gz", FILECOMPRESSTYPEGZ, }, #else /* COMMON_FILE_COMPRESS_GZ */ { ".gz", FILECOMPRESSTYPENOTIMPL }, #endif /* COMMON_FILE_COMPRESS_GZ */ /* #ifdef COMMON_FILE_COMPRESS_LZMA */ /* TODO: Current lzmadec library does not offer compression to date */ /* { ".lzma", FILECOMPRESSTYPELZMA }, */ /* #else COMMON_FILE_COMPRESS_LZMA */ { ".lzma", FILECOMPRESSTYPENOTIMPL }, /* #endif /\* COMMON_FILE_COMPRESS_LZMA *\/ */ { NULL, FILECOMPRESSTYPENOTIMPL } }; /*********************************/ /* */ /* Basic routines for filenames. */ /* */ /*********************************/ /* This routine searches the given file name ** for relevant extensions and returns the ** corresponding code if it is the case. ** It returns: ** - FILECOMPRESSTYPENONE : no recognized file extension. ** - FILECOMPRESSTYPENOTIMPL : compression algorithm not implemented. ** - FILECOMPRESSTYPExxxx : implemented compression algorithm. */ int fileCompressType ( const char * const nameptr) /*+ Name string +*/ { int namelen; int i; namelen = strlen (nameptr); for (i = 0; filetab[i].name != NULL; i ++) { int extnlen; /* Name of extension string */ extnlen = strlen (filetab[i].name); if ((namelen >= extnlen) && (strncmp (filetab[i].name, nameptr + (namelen - extnlen), extnlen) == 0)) return (filetab[i].type); } return (FILECOMPRESSTYPENONE); } /* This routine creates a thread to compress the ** given stream according to the given compression ** algorithm. ** If threads are available, compression will be ** performed by an auxiliary thread. Else, a child process ** will be fork()'ed, and after completion this process ** will remain a zombie until the main process terminates. ** It returns: ** - !NULL : stream holding compressed data. ** - NULL : on error. */ static void * /* (void *) to comply to the Posix pthread API */ fileCompress2 ( FileCompressData * const dataptr) { switch (dataptr->typeval) { #ifdef COMMON_FILE_COMPRESS_BZ2 case FILECOMPRESSTYPEBZ2 : fileCompressBz2 (dataptr); break; #endif /* COMMON_FILE_COMPRESS_BZ2 */ #ifdef COMMON_FILE_COMPRESS_GZ case FILECOMPRESSTYPEGZ : fileCompressGz (dataptr); break; #endif /* COMMON_FILE_COMPRESS_GZ */ /* #ifdef COMMON_FILE_COMPRESS_LZMA /\* TODO: Current lzmadec library does not offer compression to date *\/ */ /* case FILECOMPRESSTYPELZMA : */ /* fileCompressLzma (dataptr); */ /* break; */ /* #endif /\* COMMON_FILE_COMPRESS_LZMA *\/ */ default : errorPrint ("fileCompress2: method not implemented"); } close (dataptr->innerfd); /* Close writer's end */ memFree (dataptr); /* Free buffers */ return ((void *) 0); /* Don't care anyway */ } FILE * fileCompress ( FILE * const stream, /*+ Uncompressed stream +*/ const int typeval) /*+ (Un)compression algorithm +*/ { int filetab[2]; FILE * writptr; FileCompressData * dataptr; #ifdef COMMON_PTHREAD pthread_t thrdval; #endif /* COMMON_PTHREAD */ if (typeval <= FILECOMPRESSTYPENONE) /* If uncompressed stream, return original stream pointer */ return (stream); if (pipe (filetab) != 0) { errorPrint ("fileCompress: cannot create pipe"); return (NULL); } if ((writptr = fdopen (filetab[1], "w")) == NULL) { errorPrint ("fileCompress: cannot create stream"); close (filetab[0]); close (filetab[1]); return (NULL); } if ((dataptr = memAlloc (sizeof (FileCompressData) + FILECOMPRESSDATASIZE)) == NULL) { errorPrint ("fileCompress: out of memory"); close (filetab[0]); fclose (writptr); return (NULL); } dataptr->typeval = typeval; /* Fill structure to be passed to compression thread/process */ dataptr->innerfd = filetab[0]; dataptr->outerstream = stream; /* Stream to write to */ #ifdef COMMON_PTHREAD if (pthread_create (&thrdval, NULL, (void * (*) (void *)) fileCompress2, (void *) dataptr) != 0) { /* If could not create thread */ errorPrint ("fileCompress: cannot create thread"); memFree (dataptr); close (filetab[0]); fclose (writptr); return (NULL); } #else /* COMMON_PTHREAD */ switch (fork ()) { case -1 : /* Error */ errorPrint ("fileCompress: cannot create child process"); memFree (dataptr); close (filetab[0]); fclose (writptr); return (NULL); case 0 : /* We are the son process */ fclose (writptr); /* Close writer pipe stream */ fileCompress2 (dataptr); /* Perform compression */ exit (0); /* Exit gracefully */ default : /* We are the father process */ close (filetab[0]); /* Close the reader pipe end */ } #endif /* COMMON_PTHREAD */ return (writptr); } /* This routine compresses a stream compressed in the ** gzip format. ** It returns: ** - void : in all cases. Compression stops immediately ** in case of error. */ #ifdef COMMON_FILE_COMPRESS_BZ2 static void fileCompressBz2 ( FileCompressData * const dataptr) { BZFILE * bzfile; int bzsize; int bzerror; if ((bzfile = BZ2_bzWriteOpen (&bzerror, dataptr->outerstream, 9, 0, 0)) == NULL) { errorPrint ("fileCompressBz2: cannot start compression"); BZ2_bzWriteClose (&bzerror, bzfile, 1, NULL, NULL); return; } while ((bzsize = read (dataptr->innerfd, &dataptr->datatab, FILECOMPRESSDATASIZE)) > 0) { /* Read from pipe */ BZ2_bzWrite (&bzerror, bzfile, &dataptr->datatab, bzsize); if (bzerror != BZ_OK) { errorPrint ("fileCompressBz2: cannot write"); break; } } if (bzsize < 0) { errorPrint ("fileCompressBz2: cannot read"); bzerror = BZ_STREAM_END; /* Will set abandon flag to 1 in BZ2_bzWriteClose */ } BZ2_bzWriteClose (&bzerror, bzfile, (bzerror != BZ_OK) ? 1 : 0, NULL, NULL); fclose (dataptr->outerstream); /* Do as zlib does */ } #endif /* COMMON_FILE_COMPRESS_BZ2 */ /* This routine compresses a stream compressed in the ** gzip format. ** It returns: ** - void : in all cases. Compression stops immediately ** in case of error. */ #ifdef COMMON_FILE_COMPRESS_GZ static void fileCompressGz ( FileCompressData * const dataptr) { gzFile gzfile; int gzsize; if ((gzfile = gzdopen (fileno (dataptr->outerstream), "wb")) == NULL) { errorPrint ("fileCompressGz: cannot start compression"); return; } gzsetparams (gzfile, 9, Z_DEFAULT_STRATEGY); /* Maximum compression */ while ((gzsize = read (dataptr->innerfd, &dataptr->datatab, FILECOMPRESSDATASIZE)) > 0) { /* Read from pipe */ if (gzwrite (gzfile, &dataptr->datatab, gzsize) != gzsize) { errorPrint ("fileCompressGz: cannot write"); break; } } if (gzsize < 0) errorPrint ("fileCompressGz: cannot read"); gzclose (gzfile); } #endif /* COMMON_FILE_COMPRESS_GZ */ scotch-5.1.12b.dfsg/src/libscotch/library_mesh_graph_f.c0000644000175300017530000000623611631334325023454 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_mesh_graph_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the mesh-to-graph converter of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 4.0 : from : 21 jan 2004 **/ /** to 21 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the mesh handling routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFMESHGRAPH, scotchfmeshgraph, ( \ const SCOTCH_Mesh * const meshptr, \ SCOTCH_Graph * const grafptr, \ int * const revaptr), \ (meshptr, grafptr, revaptr)) { *revaptr = SCOTCH_meshGraph (meshptr, grafptr); } scotch-5.1.12b.dfsg/src/libscotch/library_dmapping.h0000644000175300017530000000537511631334325022641 0ustar hazelscthazelsct/* Copyright 2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dmapping.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the library ordering **/ /** structure. **/ /** **/ /** DATES : # Version 5.1 : from : 16 jun 2008 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ Distributed mapping. +*/ typedef struct LibDmapping_ { Dmapping m; /*+ Distributed mapping data +*/ Gnum * termloctab; /*+ Local mapping array +*/ } LibDmapping; scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_si.c0000644000175300017530000000773711631334325022454 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_si.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders halo graph vertices **/ /** using a simple method. **/ /** **/ /** DATES : # Version 3.2 : from : 01 nov 1996 **/ /** to 21 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to 02 oct 1998 **/ /** # Version 4.0 : from : 19 dec 2001 **/ /** to 11 dec 2002 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HGRAPH_ORDER_SI #include "module.h" #include "common.h" #include "graph.h" #include "order.h" #include "hgraph.h" #include "hgraph_order_si.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hgraphOrderSi ( const Hgraph * restrict const grafptr, Order * restrict const ordeptr, const Gnum ordenum, /*+ Zero-based ordering number +*/ OrderCblk * restrict const cblkptr) /*+ Single column-block +*/ { Gnum vertnum; Gnum vnumnum; if (grafptr->s.vnumtax == NULL) { /* If graph is original graph */ for (vertnum = grafptr->s.baseval, vnumnum = ordenum; vertnum < grafptr->vnohnnd; vertnum ++, vnumnum ++) ordeptr->peritab[vnumnum] = vertnum; } else { /* Graph is not original graph */ for (vertnum = grafptr->s.baseval, vnumnum = ordenum; vertnum < grafptr->vnohnnd; vertnum ++, vnumnum ++) ordeptr->peritab[vnumnum] = grafptr->s.vnumtax[vertnum]; } return (0); } scotch-5.1.12b.dfsg/src/libscotch/mesh_induce_sepa.c0000644000175300017530000004673011631334325022604 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mesh_induce_sepa.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the source **/ /** mesh separator subgraph-making **/ /** functions. **/ /** **/ /** DATES : # Version 4.0 : from : 26 jan 2003 **/ /** to 11 may 2004 **/ /** # Version 5.0 : from : 12 sep 2007 **/ /** to 03 apr 2008 **/ /** **/ /** NOTES : # This routine differs from the **/ /** standard mesh induction routine by **/ /** the fact that neighboring elements do **/ /** not bear the same part number as the **/ /** vertices to keep and are found on the **/ /** fly. **/ /** **/ /** # This routine is used in hmeshInduce- **/ /** Nd to build the induced separator **/ /** mesh. **/ /** Since separator vertices are likely **/ /** to be surrounded by elements that **/ /** belong to different parts but connect **/ /** the same vertices in the separator, **/ /** a simple detection mechanism is used **/ /** to try to reduce the number of such **/ /** redundant elements. **/ /** Also, since this mesh is to be **/ /** ordered with the highest available **/ /** numbers, halo is not really needed **/ /** so this "mesh*" routine is used. If **/ /** halo was needed, a "hmesh*" routine **/ /** should be used instead. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define MESH #define MESH_INDUCE_SEPA #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" #include "mesh_induce_sepa.h" /***************************************/ /* */ /* This routine handles source meshes. */ /* */ /***************************************/ /* This routine builds the separator mesh ** induced by the original mesh, the list of ** selected separator node vertices, and the ** vertex part array. Elements which are ** adjacent to the selected nodes are themselves ** selected. ** The induced vnumtab array is the baseval-based ** list of remaining node vertices if the original ** mesh does not have a vnumtab, or the proper ** subset of the original vnumtab else. ** This routine builds a mesh with nodes first ** and elements last. If a halo version of this ** algorithm had to be created, it should be ** re-worked such that elements are put first ** and nodes last, to enforce the structure of ** halo meshes. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int meshInduceSepa ( const Mesh * restrict const orgmeshptr, /* Pointer to original mesh */ const GraphPart * restrict const orgparttax, /* Array of vertex partition flags */ const Gnum orgsepanbr, /* Number of node vertices in separator */ const Gnum * restrict const orgsepatab, /* Array of node indices */ Mesh * restrict const indmeshptr) /* Pointer to induced submesh */ { Gnum orgvertnbr; /* Number of vertices in original mesh */ Gnum orgbitssiz; /* Size of int array holding as many bits as element vertices */ unsigned int * restrict orgbitstab; /* Array of bit flags for mesh elements */ Gnum indvnumnum; /* Current vertex number index in separator node list */ Gnum * restrict indvneltax; /* Array of original numbers for induced elements */ Gnum indvelmnbr; /* (Approximate) number of element vertices in induced mesh */ Gnum indvertnbr; /* (Approximate) number of vertices in induced mesh */ Gnum indvnodnum; /* Number of current node vertex in induced mesh */ Gnum indvnlosum; /* Sum of node vertex load array */ Gnum indvelmnum; /* Number of current element vertex in induced mesh */ Gnum * restrict indedgetax; /* Based array to edge array of induced mesh */ Gnum indedgenum; /* Number of current edge to be created in induced mesh */ Gnum indedgenbr; /* (Approximate) number of edges in induced mesh graph */ Gnum * restrict orgindxtax; /* Original to induced vertex number translation */ MeshInduceSepaHash * restrict hashtab; /* Node hash array */ Gnum hashmsk; /* Mask for hash array */ void * restrict p; orgbitssiz = (orgmeshptr->velmnbr + (INTSIZEBITS - 1)) / INTSIZEBITS; /* Compute size of element bit array */ if ((orgbitstab = (unsigned int *) memAlloc (orgbitssiz * sizeof (unsigned int))) == NULL) { errorPrint ("meshInduceSepa: out of memory (1)"); return (1); } memSet (orgbitstab, ~0, orgbitssiz * sizeof (unsigned int)); for (indvnumnum = 0, indvelmnbr = 0, indedgenbr = 0; /* For all separator nodes in list */ indvnumnum < orgsepanbr; indvnumnum ++) { Gnum orgvnodnum; /* Number of current node in original mesh */ Gnum orgenodnum; orgvnodnum = orgsepatab[indvnumnum]; /* Get number of separator node */ for (orgenodnum = orgmeshptr->verttax[orgvnodnum], indedgenbr += (orgmeshptr->vendtax[orgvnodnum] - orgenodnum); orgenodnum < orgmeshptr->vendtax[orgvnodnum]; orgenodnum ++) { Gnum orgvelmidx; /* Index of incident element in bit array */ Gnum orgvelmbit; /* Bit to update in element bit array */ orgvelmidx = orgmeshptr->edgetax[orgenodnum] - orgmeshptr->velmbas; orgvelmbit = orgvelmidx & (INTSIZEBITS - 1); orgvelmidx /= INTSIZEBITS; indvelmnbr += (orgbitstab[orgvelmidx] >> orgvelmbit) & 1; /* Count element vertex if not yet accounted for */ orgbitstab[orgvelmidx] &= ~(1 << orgvelmbit); } } indedgenbr *= 2; /* Number of arcs is twice number of edges */ memFree (orgbitstab); memSet (indmeshptr, 0, sizeof (Mesh)); /* Initialize mesh fields */ indmeshptr->baseval = orgmeshptr->baseval; indmeshptr->flagval = MESHFREETABS | MESHVERTGROUP; indmeshptr->vnodnbr = orgsepanbr; /* Nodes first */ indmeshptr->vnodbas = indmeshptr->baseval; indmeshptr->vnodnnd = indmeshptr->velmbas = orgsepanbr + indmeshptr->baseval; /* Elements last */ indmeshptr->veisnbr = 0; /* No isolated elements */ for (hashmsk = 15; hashmsk < orgmeshptr->degrmax; hashmsk = hashmsk * 2 + 1) ; hashmsk = hashmsk * 4 + 3; /* Compute size of node hash table */ indvertnbr = indvelmnbr + orgsepanbr; /* Upper bound on number of all vertices */ if (orgmeshptr->velotax != NULL) { p = memAllocGroup ((void **) (void *) &indmeshptr->verttax, (size_t) (indvertnbr * sizeof (Gnum)), /* verttab is not compact */ &indmeshptr->vendtax, (size_t) (indvertnbr * sizeof (Gnum)), &indmeshptr->vnumtax, (size_t) (orgsepanbr * sizeof (Gnum)), /* vnumtab is of size indnodenbr */ &indmeshptr->velotax, (size_t) (orgsepanbr * sizeof (Gnum)), NULL); /* Element vertices assumed not weighted */ indmeshptr->velotax -= indmeshptr->vnodbas; } else p = memAllocGroup ((void **) (void *) &indmeshptr->verttax, (size_t) (indvertnbr * sizeof (Gnum)), &indmeshptr->vendtax, (size_t) (indvertnbr * sizeof (Gnum)), &indmeshptr->vnumtax, (size_t) (orgsepanbr * sizeof (Gnum)), NULL); /* vnumtab is of size indnodenbr */ orgvertnbr = orgmeshptr->velmnbr + orgmeshptr->vnodnbr; if (p != 0) { indmeshptr->verttax -= indmeshptr->baseval; indmeshptr->vendtax -= indmeshptr->baseval; indmeshptr->vnumtax -= indmeshptr->vnodbas; /* vnumtab is of size indmeshptr->vnodnbr */ p = memAllocGroup ((void **) (void *) &indedgetax, (size_t) (indedgenbr * sizeof (Gnum)), &indvneltax, (size_t) (indvelmnbr * sizeof (Gnum)), &orgindxtax, (size_t) (orgvertnbr * sizeof (Gnum)), &hashtab, (size_t) ((hashmsk + 1) * sizeof (MeshInduceSepaHash)), NULL); } if (p == 0) { errorPrint ("meshInduceSepa: out of memory (2)"); /* Allocate induced mesh graph structure */ return (1); } memSet (orgindxtax, ~0, orgvertnbr * sizeof (Gnum)); memSet (hashtab, ~0, (hashmsk + 1) * sizeof (MeshInduceSepaHash)); indedgetax -= indmeshptr->baseval; indvneltax -= indmeshptr->velmbas; orgindxtax -= orgmeshptr->baseval; for (indvnumnum = 0, indvnodnum = indedgenum = indmeshptr->baseval, indvelmnum = orgsepanbr + indvnodnum, indedgenbr = 0, indvnlosum = 0; indvnumnum < orgsepanbr; indvnumnum ++) { /* For all node vertices in separator */ Gnum orgvnodnum; /* Number of current node in original mesh */ Gnum orgenodnum; Gnum indenodnum; /* Current index in node edge sub-array */ orgvnodnum = orgsepatab[indvnumnum]; /* Get number of separator node */ if (orgindxtax[orgvnodnum] == ~0) /* If separator node not yet numbered */ orgindxtax[orgvnodnum] = indvnodnum ++; /* One more node vertex created */ indmeshptr->verttax[orgindxtax[orgvnodnum]] = indedgenum; /* Set beginning of edge sub-array */ indmeshptr->vnumtax[orgindxtax[orgvnodnum]] = orgvnodnum - (orgmeshptr->vnodbas - orgmeshptr->baseval); if (indmeshptr->velotax != NULL) { Gnum indvnloval; indvnloval = orgmeshptr->velotax[orgvnodnum]; indvnlosum += indvnloval; indmeshptr->velotax[orgindxtax[orgvnodnum]] = indvnloval; } indenodnum = indedgenum; /* Record position of node edge sub-array */ indedgenum += orgmeshptr->vendtax[orgvnodnum] - /* Reserve space for node edges */ orgmeshptr->verttax[orgvnodnum]; for (orgenodnum = orgmeshptr->verttax[orgvnodnum]; /* For all element vertices neighboring the separator node */ orgenodnum < orgmeshptr->vendtax[orgvnodnum]; orgenodnum ++) { Gnum orgvelmnum; /* Number of element node in original mesh */ orgvelmnum = orgmeshptr->edgetax[orgenodnum]; /* Get number of element */ if (orgindxtax[orgvelmnum] == -2) /* If discarded element */ continue; /* Skip to next element */ if (orgindxtax[orgvelmnum] == ~0) { /* If element not yet created */ Gnum indedgetmp; /* Save value for edge index */ Gnum orgeelmnum; Gnum indenodtmp; indmeshptr->verttax[indvelmnum] = indedgenum; /* Set beginning of element edge sub-array */ indedgetmp = indedgenum; for (orgeelmnum = orgmeshptr->verttax[orgvelmnum]; /* For all nodes neighboring the element vertex */ orgeelmnum < orgmeshptr->vendtax[orgvelmnum]; orgeelmnum ++) { Gnum orgvnodend; /* Number of current end node vertex in original mesh */ orgvnodend = orgmeshptr->edgetax[orgeelmnum]; /* Get number of end node */ if (orgparttax[orgvnodend] == 2) { /* If end node is in separator */ Gnum hashnum; if (orgindxtax[orgvnodend] == ~0) /* If end node not yet numbered */ orgindxtax[orgvnodend] = indvnodnum ++; /* Assign number to end node */ indedgetax[indedgenum ++] = orgindxtax[orgvnodend]; /* Add node to element edge sub-array */ for (hashnum = (orgindxtax[orgvnodend] * MESHINDUCESEPAHASHPRIME) & hashmsk; hashtab[hashnum].orgvelmnum == orgvelmnum; hashnum = (hashnum + 1) & hashmsk) ; hashtab[hashnum].orgvelmnum = orgvelmnum; /* Add vertex to hash table */ hashtab[hashnum].indvnodnum = orgindxtax[orgvnodend]; } } indmeshptr->vendtax[indvelmnum] = indedgenum; /* Set end of element edge sub-array */ for (indenodtmp = indenodnum - 1; indenodtmp >= indmeshptr->verttax[orgindxtax[orgvnodnum]]; indenodtmp --) { Gnum indvelmtmp; /* Number of current already declared element for current node */ Gnum indeelmtmp; /* Number of current edge of already declared element for current node */ Gnum mtchnbr; /* Number of matches between new element and current element */ indvelmtmp = indedgetax[indenodtmp]; for (indeelmtmp = indmeshptr->verttax[indvelmtmp], mtchnbr = 0; indeelmtmp < indmeshptr->vendtax[indvelmtmp]; indeelmtmp ++) { Gnum indvnodend; Gnum hashnum; indvnodend = indedgetax[indeelmtmp]; /* Get number of current end node of already declared element */ for (hashnum = (indvnodend * MESHINDUCESEPAHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { if (hashtab[hashnum].orgvelmnum != orgvelmnum) /* If end node not present */ break; if (hashtab[hashnum].indvnodnum == indvnodend) { /* If end node found */ mtchnbr ++; /* One more matching node */ break; } } } if (mtchnbr == (indedgenum - indmeshptr->verttax[indvelmnum])) { /* If we are useless */ orgindxtax[orgvelmnum] = -2; /* Never consider this element again */ indedgenum = indedgetmp; /* Recycle edge sub-array of new element */ break; /* No need to go any further */ } if (mtchnbr == (indmeshptr->vendtax[indvelmtmp] - indmeshptr->verttax[indvelmtmp])) { /* If other element is useless */ indedgenbr -= mtchnbr; /* Remove its edges */ indmeshptr->verttax[indvelmtmp] = indmeshptr->verttax[indvelmnum]; /* Recycle it into our element */ indmeshptr->vendtax[indvelmtmp] = indmeshptr->vendtax[indvelmnum]; orgindxtax[indvneltax[indvelmtmp]] = -2; indvneltax[indvelmtmp] = orgvelmnum; } } if (indenodtmp < indmeshptr->verttax[orgindxtax[orgvnodnum]]) { /* If new element distinct from all other neighboring elements */ indedgetax[indenodnum ++] = indvelmnum; /* Record element in edge sub-array of current node */ indedgenbr += indedgenum - indmeshptr->verttax[indvelmnum]; indvneltax[indvelmnum] = orgvelmnum; /* Record original number of element in case we have to remove it afterwards */ orgindxtax[orgvelmnum] = indvelmnum ++; } } else /* Element already exists */ indedgetax[indenodnum ++] = orgindxtax[orgvelmnum]; /* Record element in edge sub-array of current node */ } indmeshptr->vendtax[orgindxtax[orgvnodnum]] = indenodnum; /* Set end of edge sub-array for current node */ indedgenbr += (indenodnum - indmeshptr->verttax[orgindxtax[orgvnodnum]]); /* Account for thes edges */ } #ifdef SCOTCH_DEBUG_MESH2 if (indvnodnum != (orgsepanbr + indmeshptr->baseval)) { errorPrint ("meshInduceSepa: internal error"); return (1); } #endif /* SCOTCH_DEBUG_MESH2 */ indmeshptr->velmnbr = indvelmnum - indmeshptr->velmbas; indmeshptr->velmnnd = indvelmnum; indmeshptr->edgenbr = indedgenbr; if ((indmeshptr->edgetax = (Gnum *) memRealloc (indedgetax + indmeshptr->baseval, (indedgenum - indmeshptr->baseval) * sizeof (Gnum))) == NULL) { errorPrint ("meshInduceSepa: out of memory (3)"); memFree (indedgetax + indmeshptr->baseval); /* Free group leader */ meshFree (indmeshptr); return (1); } indmeshptr->edgetax -= indmeshptr->baseval; indmeshptr->velosum = indmeshptr->velmnbr; /* TODO: account for element weights */ indmeshptr->vnlosum = (indmeshptr->velotax == NULL) ? orgsepanbr : indvnlosum; indmeshptr->degrmax = orgmeshptr->degrmax; /* Rough estimate */ if (orgmeshptr->vnumtax != NULL) { /* If mesh is a submesh */ for (indvnodnum = indmeshptr->vnodbas; indvnodnum < indmeshptr->vnodnnd; indvnodnum ++) indmeshptr->vnumtax[indvnodnum] = orgmeshptr->vnumtax[indmeshptr->vnumtax[indvnodnum] + (orgmeshptr->vnodbas - orgmeshptr->baseval)]; } return (0); } scotch-5.1.12b.dfsg/src/libscotch/vmesh_separate_ml.h0000644000175300017530000000721511631334325023007 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh_separate_ml.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the multi-level node separation **/ /** routines. **/ /** **/ /** DATES : # Version 4.0 : from : 20 feb 2003 **/ /** to 31 aug 2005 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct VmeshSeparateMlParam_ { INT vnodnbr; /*+ Minimum number of node vertices +*/ double coarrat; /*+ Coarsening ratio +*/ MeshCoarsenType coartype; /*+ Element matching function type +*/ Strat * stratlow; /*+ Strategy at lowest level +*/ Strat * stratasc; /*+ Strategy at ascending levels +*/ } VmeshSeparateMlParam; /* ** The function prototypes. */ #ifndef VMESH_SEPARATE_ML #define static #endif static int vmeshSeparateMlCoarsen (const Vmesh * restrict const, Vmesh * restrict const, Gnum * restrict * const, const VmeshSeparateMlParam * const); static int vmeshSeparateMlUncoarsen (Vmesh * const, const Vmesh * const, const Gnum * restrict const); int vmeshSeparateMl (Vmesh * const, const VmeshSeparateMlParam * const); static int vmeshSeparateMl2 (Vmesh * const, const VmeshSeparateMlParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/kgraph_map_st.h0000644000175300017530000000707311631334325022132 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kgraph_map_st.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the strategy and method **/ /** tables and the generic entry point for **/ /** the graph multipartitioning methods. **/ /** **/ /** DATES : # Version 3.2 : from : 15 oct 1996 **/ /** to 29 sep 1997 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to 09 dec 1998 **/ /** # Version 4.0 : from : 12 jan 2004 **/ /** to 12 jan 2004 **/ /** # Version 5.1 : from : 13 jul 2010 **/ /** to 13 jul 2010 **/ /** **/ /************************************************************/ /* ** The type definitions. */ /*+ Method types. +*/ typedef enum KgraphMapStMethodType_ { KGRAPHMAPSTMETHML = 0, /*+ Multi-level +*/ KGRAPHMAPSTMETHRB, /*+ Dual Recursive Bipartitioning +*/ KGRAPHMAPSTMETHNBR /*+ Number of methods +*/ } KgraphMapStMethodType; /* ** The external declarations. */ extern StratTab kgraphmapststratab; /* ** The function prototypes. */ #ifndef KGRAPH_MAP_ST #define static #endif int kgraphMapSt (Kgraph * restrict const, const Strat * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/graph_base.c0000644000175300017530000001271111631334325021374 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_base.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the graph base **/ /** changing routine. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to 18 may 1993 **/ /** # Version 1.3 : from : 30 apr 1994 **/ /** to 18 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 31 oct 1994 **/ /** # Version 3.0 : from : 07 jul 1995 **/ /** to 28 sep 1995 **/ /** # Version 3.1 : from : 28 nov 1995 **/ /** to 08 jun 1996 **/ /** # Version 3.2 : from : 07 sep 1996 **/ /** to 15 sep 1998 **/ /** # Version 3.3 : from : 22 sep 1998 **/ /** to 31 dec 1998 **/ /** # Version 4.0 : from : 24 nov 2001 **/ /** to 22 apr 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GRAPH #include "module.h" #include "common.h" #include "graph.h" /****************************************/ /* */ /* These routines handle source graphs. */ /* */ /****************************************/ /* This routine sets the base of the given ** graph to the given base value, and returns ** the old base value. ** It returns: ** - old base value : in all cases. */ Gnum graphBase ( Graph * const grafptr, const Gnum baseval) { Gnum baseold; /* Old base value */ Gnum baseadj; /* Base adjustment */ Gnum vertnum; Gnum edgenum; if (grafptr->baseval == baseval) /* If nothing to do */ return (baseval); baseold = grafptr->baseval; /* Record old base value */ baseadj = baseval - baseold; /* Compute adjustment */ for (vertnum = grafptr->baseval; vertnum < grafptr->vertnnd; vertnum ++) { for (edgenum = grafptr->verttax[vertnum]; edgenum < grafptr->vendtax[vertnum]; edgenum ++) grafptr->edgetax[edgenum] += baseadj; grafptr->verttax[vertnum] += baseadj; } if (grafptr->vendtax != grafptr->verttax + 1) { /* If distinct vertex end array */ for (vertnum = grafptr->baseval; vertnum < grafptr->vertnnd; vertnum ++) grafptr->vendtax[vertnum] += baseadj; } else /* If same vertex end array (of size +1) */ grafptr->verttax[grafptr->vertnnd] += baseadj; /* Adjust last entry of verttax */ grafptr->verttax -= baseadj; /* Adjust array accesses */ grafptr->vendtax -= baseadj; grafptr->edgetax -= baseadj; if (grafptr->vnumtax != NULL) grafptr->vnumtax -= baseadj; if (grafptr->vlbltax != NULL) grafptr->vlbltax -= baseadj; if (grafptr->edlotax != NULL) grafptr->edlotax -= baseadj; grafptr->baseval = baseval; /* Set new base value */ grafptr->vertnnd += baseadj; return (baseold); /* Return old base value */ } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_st.h0000644000175300017530000001013211631334325023162 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_st.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the global separation **/ /** strategy and method tables. **/ /** **/ /** DATES : # Version 3.2 : from : 24 oct 1996 **/ /** to 14 nov 1997 **/ /** # Version 3.3 : from : 31 may 1999 **/ /** to 31 may 1999 **/ /** # Version 4.0 : from : 06 jan 2002 **/ /** to 19 aug 2004 **/ /** # Version 5.0 : from : 12 sep 2006 **/ /** to : 17 feb 2007 **/ /** # Version 5.1 : from : 30 oct 2007 **/ /** to : 30 oct 2007 **/ /** **/ /************************************************************/ /* ** The type definitions. */ /*+ Method types. +*/ typedef enum VgraphSeparateStMethodType_ { VGRAPHSEPASTMETHBD = 0, /*+ Banding strategy +*/ VGRAPHSEPASTMETHES, /*+ Edge separation strategy +*/ VGRAPHSEPASTMETHFM, /*+ Fiduccia-Mattheyses +*/ VGRAPHSEPASTMETHGG, /*+ Greedy Graph Growing +*/ VGRAPHSEPASTMETHGP, /*+ Gibbs-Poole-Stockmeyer +*/ VGRAPHSEPASTMETHML, /*+ Multi-level separation +*/ VGRAPHSEPASTMETHVW, /*+ Partition viewer +*/ VGRAPHSEPASTMETHZR, /*+ Zero method +*/ VGRAPHSEPASTMETHNBR /*+ Number of methods +*/ } VgraphSeparateStMethodType; /* ** The external declarations. */ extern StratTab vgraphseparateststratab; /* ** The function prototypes. */ #ifndef VGRAPH_SEPARATE_ST #define static #endif int vgraphSeparateSt (Vgraph * const, const Strat * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_order_io_block_f.c0000644000175300017530000001061511631334325025634 0ustar hazelscthazelsct/* Copyright 2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_order_io_block_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** distributed graph ordering routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 28 may 2008 **/ /** to 28 may 2008 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 27 mar 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the ordering routines. */ /* */ /**************************************/ FORTRAN ( \ SCOTCHFDGRAPHORDERSAVEBLOCK, scotchfdgraphordersaveblock, ( \ const SCOTCH_Dgraph * const grafptr, \ const SCOTCH_Dordering * const ordeptr, \ int * const fileptr, \ int * const revaptr), \ (grafptr, ordeptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if (*fileptr == -1) /* If process is not the root */ stream = NULL; else { /* Open stream for root process */ if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFDGRAPHORDERSAVEBLOCK: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFDGRAPHORDERSAVEBLOCK: cannot open output stream"); close (filenum); *revaptr = 1; return; } } o = SCOTCH_dgraphOrderSaveBlock (grafptr, ordeptr, stream); if (stream != NULL) fclose (stream); /* This closes filenum too */ *revaptr = o; } scotch-5.1.12b.dfsg/src/libscotch/library_graph_map_view_f.c0000644000175300017530000001011011631334325024311 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_map_view_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** mapping routines of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 4.0 : from : 21 nov 2005 **/ /** to 21 nov 2005 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 27 mar 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the mapping routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFGRAPHMAPVIEW, scotchfgraphmapview, ( \ const SCOTCH_Graph * const grafptr, \ const SCOTCH_Mapping * const mapptr, \ int * const fileptr, \ int * const revaptr), \ (grafptr, mapptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFGRAPHMAPVIEW: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFGRAPHMAPVIEW: cannot open output stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_graphMapView (grafptr, mapptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } scotch-5.1.12b.dfsg/src/libscotch/hdgraph_order_st.c0000644000175300017530000002547611631334325022633 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph_order_st.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the generic call to the **/ /** distributed graph ordering module, **/ /** using a given strategy. **/ /** **/ /** DATES : # Version 5.0 : from : 15 apr 2006 **/ /** to 21 aug 2006 **/ /** # Version 5.1 : from : 11 nov 2008 **/ /** to 11 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HDGRAPH_ORDER_ST #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "order.h" #include "hgraph.h" #include "hgraph_order_st.h" #include "dgraph.h" #include "dorder.h" #include "hdgraph.h" #include "hdgraph_order_nd.h" #include "hdgraph_order_si.h" #include "hdgraph_order_sq.h" #include "hdgraph_order_st.h" #include "vdgraph.h" #include "vdgraph_separate_st.h" /* ** The static and global variables. */ static Hdgraph hdgraphorderstgraphdummy; /* Dummy graph for offset computations */ static union { /* Default parameters for nested dissection method */ HdgraphOrderNdParam param; StratNodeMethodData padding; } hdgraphorderstdefaultnd = { { &stratdummy, &stratdummy, &stratdummy } }; static union { /* Default parameters for sequential method */ HdgraphOrderSqParam param; StratNodeMethodData padding; } hdgraphorderstdefaultsq = { { &stratdummy } }; static StratMethodTab hdgraphorderstmethtab[] = { /* Graph ordering methods array */ { HDGRAPHORDERSTMETHND, "n", hdgraphOrderNd, &hdgraphorderstdefaultnd }, { HDGRAPHORDERSTMETHSI, "s", hdgraphOrderSi, NULL }, { HDGRAPHORDERSTMETHSQ, "q", hdgraphOrderSq, &hdgraphorderstdefaultsq }, { -1, NULL, NULL, NULL } }; static StratParamTab hdgraphorderstparatab[] = { /* The method parameter list */ { HDGRAPHORDERSTMETHND, STRATPARAMSTRAT, "sep", (byte *) &hdgraphorderstdefaultnd.param, (byte *) &hdgraphorderstdefaultnd.param.sepstrat, (void *) &vdgraphseparateststratab }, { HDGRAPHORDERSTMETHND, STRATPARAMSTRAT, "ole", (byte *) &hdgraphorderstdefaultnd.param, (byte *) &hdgraphorderstdefaultnd.param.ordstratlea, (void *) &hdgraphorderststratab }, { HDGRAPHORDERSTMETHND, STRATPARAMSTRAT, "ose", (byte *) &hdgraphorderstdefaultnd.param, (byte *) &hdgraphorderstdefaultnd.param.ordstratsep, (void *) &hdgraphorderststratab }, { HDGRAPHORDERSTMETHND, STRATPARAMSTRAT, "osq", (byte *) &hdgraphorderstdefaultnd.param, (byte *) &hdgraphorderstdefaultnd.param.ordstratseq, (void *) &hgraphorderststratab }, { HDGRAPHORDERSTMETHSQ, STRATPARAMSTRAT, "strat", (byte *) &hdgraphorderstdefaultsq.param, (byte *) &hdgraphorderstdefaultsq.param.ordstratseq, (void *) &hgraphorderststratab }, { HDGRAPHORDERSTMETHNBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; static StratParamTab hdgraphorderstcondtab[] = { /* Graph condition parameter table */ { STRATNODECOND, STRATPARAMINT, "edge", (byte *) &hdgraphorderstgraphdummy, (byte *) &hdgraphorderstgraphdummy.s.edgeglbnbr, NULL }, { STRATNODECOND, STRATPARAMINT, "levl", (byte *) &hdgraphorderstgraphdummy, (byte *) &hdgraphorderstgraphdummy.levlnum, NULL }, { STRATNODECOND, STRATPARAMINT, "load", (byte *) &hdgraphorderstgraphdummy, (byte *) &hdgraphorderstgraphdummy.s.veloglbsum, NULL }, { STRATNODECOND, STRATPARAMDOUBLE, "mdeg", (byte *) &hdgraphorderstgraphdummy, (byte *) &hdgraphorderstgraphdummy.s.degrglbmax, NULL }, { STRATNODECOND, STRATPARAMINT, "proc", (byte *) &hdgraphorderstgraphdummy, (byte *) &hdgraphorderstgraphdummy.s.procglbnbr, NULL }, { STRATNODECOND, STRATPARAMINT, "rank", (byte *) &hdgraphorderstgraphdummy, (byte *) &hdgraphorderstgraphdummy.s.proclocnum, NULL }, { STRATNODECOND, STRATPARAMINT, "vert", (byte *) &hdgraphorderstgraphdummy, (byte *) &hdgraphorderstgraphdummy.s.vertglbnbr, NULL }, { STRATNODENBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; StratTab hdgraphorderststratab = { /* Strategy tables for graph ordering methods */ hdgraphorderstmethtab, hdgraphorderstparatab, hdgraphorderstcondtab }; /************************************/ /* */ /* This routine is the entry point */ /* for the graph ordering routines. */ /* */ /************************************/ /* This routine computes an ordering ** with respect to a given strategy. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int hdgraphOrderSt ( const Hdgraph * restrict const grafptr, /*+ Subgraph to order +*/ DorderCblk * restrict const cblkptr, /*+ Current column block +*/ const Strat * restrict const strat) /*+ Graph ordering strategy +*/ { StratTest val; int o; if (grafptr->s.vertglbnbr == 0) /* Return immediately if nothing to do */ return (0); o = 0; switch (strat->type) { case STRATNODECONCAT : errorPrint ("hdgraphOrderSt: concatenation operator not available for graph ordering strategies"); return (1); case STRATNODECOND : o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ if (o == 0) { /* If evaluation was correct */ #ifdef SCOTCH_DEBUG_HDGRAPH2 if ((val.typetest != STRATTESTVAL) && (val.typenode != STRATPARAMLOG)) { errorPrint ("hdgraphOrderSt: invalid test result"); o = 1; break; } #endif /* SCOTCH_DEBUG_HDGRAPH2 */ if (val.data.val.vallog == 1) /* If expression is true */ o = hdgraphOrderSt (grafptr, cblkptr, strat->data.cond.strat[0]); /* Apply first strategy */ else { /* Else if expression is false */ if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ o = hdgraphOrderSt (grafptr, cblkptr, strat->data.cond.strat[1]); /* Apply second strategy */ } } break; case STRATNODEEMPTY : hdgraphOrderSi (grafptr, cblkptr); /* Always maintain a consistent ordering */ break; case STRATNODESELECT : errorPrint ("hdgraphOrderSt: selection operator not available for graph ordering strategies"); return (1); #ifdef SCOTCH_DEBUG_HDGRAPH2 case STRATNODEMETHOD : #else /* SCOTCH_DEBUG_HDGRAPH2 */ default : #endif /* SCOTCH_DEBUG_HDGRAPH2 */ return (strat->tabl->methtab[strat->data.method.meth].func (grafptr, cblkptr, (void *) &strat->data.method.data)); #ifdef SCOTCH_DEBUG_HDGRAPH2 default : errorPrint ("hdgraphOrderSt: invalid parameter"); return (1); #endif /* SCOTCH_DEBUG_HDGRAPH2 */ } return (o); } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_fm.h0000644000175300017530000001513211631334325023143 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_fm.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the improved Fiduccia-Mattheyses **/ /** graph separation routine. **/ /** **/ /** DATES : # Version 3.2 : from : 02 nov 1997 **/ /** to 20 nov 1997 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 28 dec 1998 **/ /** # Version 4.0 : from : 13 dec 2001 **/ /** to 18 aug 2004 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Gain table subbits. +*/ #define VGRAPHSEPAFMGAINBITS 4 /*+ Prime number for hashing vertex numbers. +*/ #define VGRAPHSEPAFMHASHPRIME 17 /*+ Prime number for hashing +*/ /*+ Gain table vertex status. +*/ #define VGRAPHSEPAFMSTATEFREE ((GainLink *) 0) /*+ Vertex is free or separator-chained +*/ #define VGRAPHSEPAFMSTATESUCH ((GainLink *) 1) /*+ Separator vertex is used and chained +*/ #define VGRAPHSEPAFMSTATEUSED ((GainLink *) 2) /*+ Vertex already swapped once +*/ #define VGRAPHSEPAFMSTATELINK ((GainLink *) 3) /*+ Currently in gain table if higher +*/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct VgraphSeparateFmParam_ { INT movenbr; /*+ Maximum number of uneffective moves that can be done +*/ INT passnbr; /*+ Number of passes to be performed (-1 : infinite) +*/ double deltrat; /*+ Maximum weight imbalance ratio +*/ } VgraphSeparateFmParam; /*+ The hash vertex structure. For trick reasons, one of the gain table data structures is followed by a negative integer, and the other by a positive one. Thus, one can deduce the value of the pointer to the structure from a pointer to any of the gain table data structures. Moreover, some fields have special meaning: - gainlink0.next: state of vertex (see VGRAPHSEPAFMSTATEXXXX). - gainlink0.prev: simple chaining for separator vertices, if vertex is in chained state (((vertpart == 2) && (gainlink0.next == VGRAPHSEPAFMSTATEFREE)) || (gainlink0.next == VGRAPHSEPAFMSTATESUCH)). - gainlink1: double chained list of locked vertices, if ((gainlink0.next == VGRAPHSEPAFMSTATESUCH) || (gainlink0.next == VGRAPHSEPAFMSTATEUSED)). +*/ typedef struct VgraphSeparateFmVertex_ { GainLink gainlink0; /*+ Gain link if moved to part 0; FIRST +*/ Gnum veloval; /*+ TRICK: opposite of vertex load +*/ GainLink gainlink1; /*+ Gain link if moved to part 1; TRICK: before vertpart +*/ Gnum partval; /*+ Vertex part TRICK: same type as vertload +*/ Gnum compgain[2]; /*+ Separator gain if moved to given part; TRICK: not first +*/ Gnum mswpnum; /*+ Number of move sweep when data recorded +*/ Gnum vertnum; /*+ Number of vertex in hash table +*/ } VgraphSeparateFmVertex; /*+ The move recording structure. +*/ typedef struct VgraphSeparateFmSave_ { Gnum hashnum; /*+ Number of hash slot for saved vertex +*/ int partval; /*+ Saved vertex part value +*/ Gnum compgain[2]; /*+ Saved vertex gain +*/ } VgraphSeparateFmSave; /* ** The function prototypes. */ #ifndef VGRAPH_SEPARATE_FM #define static #endif int vgraphSeparateFm (Vgraph * const, const VgraphSeparateFmParam * const); static int vgraphSeparateFmResize (VgraphSeparateFmVertex * restrict * hashtabptr, Gnum * const, Gnum * const, VgraphSeparateFmSave * restrict *, const Gnum, GainTabl * const, GainLink * const); #ifdef SCOTCH_DEBUG_VGRAPH3 static int vgraphSeparateFmCheck (const Vgraph * const, const VgraphSeparateFmVertex * restrict const, const Gnum, const Gnum, const Gnum); #endif /* SCOTCH_DEBUG_VGRAPH3 */ static GainLink * vgraphSeparateFmTablGet (GainTabl * const, const Gnum, const Gnum, const int); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_build_f.c0000644000175300017530000001014611631334325023756 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_build_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the distributed source graph handling **/ /** routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 24 feb 2007 **/ /** to 18 jul 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /********************************************/ /* */ /* These routines are the Fortran API for */ /* the distributed graph handling routines. */ /* */ /********************************************/ /* ** */ FORTRAN ( \ SCOTCHFDGRAPHBUILD, scotchfdgraphbuild, ( \ SCOTCH_Dgraph * const grafptr, \ const SCOTCH_Num * const baseptr, \ const SCOTCH_Num * const vertlocptr, \ const SCOTCH_Num * const vertlocmpt, \ SCOTCH_Num * const vertloctab, \ SCOTCH_Num * const vendloctab, \ SCOTCH_Num * const veloloctab, \ SCOTCH_Num * const vlblloctab, \ const SCOTCH_Num * const edgelocptr, \ const SCOTCH_Num * const edgelocptz, \ SCOTCH_Num * const edgeloctab, \ SCOTCH_Num * const edgegsttab, \ SCOTCH_Num * const edloloctab, \ int * const revaptr), \ (grafptr, baseptr, vertlocptr, vertlocmpt, \ vertloctab, vendloctab, veloloctab, \ vlblloctab, edgelocptr, edgelocptz, \ edgeloctab, edgegsttab, edloloctab, \ revaptr)) { *revaptr = SCOTCH_dgraphBuild (grafptr, *baseptr, *vertlocptr, *vertlocmpt, vertloctab, vendloctab, veloloctab, vlblloctab, *edgelocptr, *edgelocptz, edgeloctab, edgegsttab, edloloctab); } scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_df.h0000644000175300017530000000743311631334325022570 0ustar hazelscthazelsct/* Copyright 2004,2007,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_df.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the function **/ /** declarations for the diffusion scheme **/ /** bipartitioning method. **/ /** **/ /** DATES : # Version 5.0 : from : 09 jan 2007 **/ /** to 28 may 2007 **/ /** # Version 5.1 : from : 29 oct 2007 **/ /** to 28 mar 2011 **/ /** **/ /************************************************************/ /* ** The defines. */ /* Small non-zero float value. */ #define BGRAPHBIPARTDFEPSILON (1.0F / (float) (GNUMMAX)) /*+ Sign masking operator. +*/ #define BGRAPHBIPARTDFGNUMSGNMSK(i) ((Gnum) 0 - (((Gunum) (i)) >> (sizeof (Gnum) * 8 - 1))) /* ** The type and structure definitions. */ /*+ Job selection policy types. +*/ typedef enum BgraphBipartDfType_ { BGRAPHBIPARTDFTYPEBAL = 0, /*+ Balance to average +*/ BGRAPHBIPARTDFTYPEKEEP /*+ Preserve current imbalance +*/ } BgraphBipartDfType; /*+ Method parameters. +*/ typedef struct BgraphBipartDfParam_ { INT passnbr; /*+ Number of passes to do +*/ double cdifval; /*+ Coefficient of diffused load +*/ double cremval; /*+ Coefficient of remaining load +*/ BgraphBipartDfType typeval; /*+ Type of balance to reach +*/ } BgraphBipartDfParam; /* ** The function prototypes. */ #ifndef BGRAPH_BIPART_DF #define static #endif int bgraphBipartDf (Bgraph * restrict const, const BgraphBipartDfParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/kgraph_map_ml.h0000644000175300017530000000721311631334325022110 0ustar hazelscthazelsct/* Copyright 2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kgraph_map_ml.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the multi-level graph mapping **/ /** routines. **/ /** **/ /** DATES : # Version 5.1 : from : 13 jul 2010 **/ /** to 13 jul 2010 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct KgraphMapMlParam_ { INT coarnbr; /*+ Minimum number of vertices +*/ double coarrat; /*+ Coarsening ratio +*/ GraphCoarsenType coartype; /*+ Edge matching function type +*/ Strat * stratlow; /*+ Strategy at lowest level +*/ Strat * stratasc; /*+ Strategy at ascending levels +*/ } KgraphMapMlParam; /* ** The function prototypes. */ #ifndef KGRAPH_MAP_ML #define static #endif static int kgraphMapMlCoarsen (const Kgraph * const, Kgraph * restrict const, GraphCoarsenMulti * restrict * const, const KgraphMapMlParam * const); static int kgraphMapMlUncoarsen (Kgraph * restrict const, Kgraph * restrict const, const GraphCoarsenMulti * const); int kgraphMapMl (Kgraph * restrict const, const KgraphMapMlParam * const); static int kgraphMapMl2 (Kgraph * restrict const, const KgraphMapMlParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_stat.h0000644000175300017530000000556611631334325023344 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /**********************************************************/ /* */ /* NAME : library_dgraph_stat.h */ /* */ /* AUTHOR : Francois PELLEGRINI */ /* */ /* FUNCTION : These lines are the data declarations */ /* for the distributed source graph */ /* analyzing routine. */ /* */ /* # Version 5.0 : from : 23 jun 2007 */ /* to 23 jun 2007 */ /* */ /**********************************************************/ /* ** The type and structure definitions. */ /* Communication structure for distributed graph statistics. */ typedef struct DgraphStatData_ { Gnum velomin; Gnum velomax; Gnum degrmin; Gnum degrmax; Gnum edlomin; Gnum edlomax; Gnum edlosum; double velodlt; double degrdlt; double edlodlt; } DgraphStatData; scotch-5.1.12b.dfsg/src/libscotch/dgraph_allreduce.c0000644000175300017530000001022011631334325022557 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_allreduce.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the distributed source **/ /** graph building routines. **/ /** **/ /** DATES : # Version 5.0 : from : 28 aug 2006 **/ /** to : 28 aug 2006 **/ /** **/ /************************************************************/ #define DGRAPH #include "module.h" #include "common.h" #include "dgraph.h" /* This routine creates an allreduce operator from ** the function pointer that is passed to it, and ** use it to perform an allreduce operation on the ** given data. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphAllreduceMaxSum2 ( Gnum * reduloctab, /* Pointer to array of local Gnum data */ Gnum * reduglbtab, /* Pointer to array of reduced Gnum data */ int redumaxsumnbr, /* Number of max + sum Gnum operations */ MPI_User_function * redufuncptr, /* Pointer to operator function */ MPI_Comm proccomm) /* Communicator to be used for reduction */ { MPI_Datatype redutypedat; /* Data type for finding best separator */ MPI_Op reduoperdat; /* Handle of MPI operator for finding best separator */ if ((MPI_Type_contiguous (redumaxsumnbr, GNUM_MPI, &redutypedat) != MPI_SUCCESS) || (MPI_Type_commit (&redutypedat) != MPI_SUCCESS) || (MPI_Op_create (redufuncptr, 1, &reduoperdat) != MPI_SUCCESS)) { errorPrint ("dgraphAllreduceMaxSum: communication error (1)"); return (1); } if (MPI_Allreduce (reduloctab, reduglbtab, 1, redutypedat, reduoperdat, proccomm) != MPI_SUCCESS) { errorPrint ("dgraphAllreduceMaxSum: communication error (2)"); return (1); } if ((MPI_Op_free (&reduoperdat) != MPI_SUCCESS) || (MPI_Type_free (&redutypedat) != MPI_SUCCESS)) { errorPrint ("dgraphAllreduceMaxSum: communication error (3)"); return (1); } return (0); } scotch-5.1.12b.dfsg/src/libscotch/hdgraph_order_si.h0000644000175300017530000000523011631334325022607 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph_order_si.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the simple halo graph **/ /** ordering routine. **/ /** **/ /** DATES : # Version 5.0 : from : 15 apr 2006 **/ /** to 15 apr 2006 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef HDGRAPH_ORDER_SI #define static #endif int hdgraphOrderSi (const Hdgraph * const, DorderCblk * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_check.c0000644000175300017530000000616011631334325023430 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_check.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the source **/ /** graph handling routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 26 aug 2006 **/ /** to 26 aug 2006 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "dgraph.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the distributed graph handling */ /* routines. */ /* */ /************************************/ /*+ This routine checks the consistency *** of the given graph. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_dgraphCheck ( const SCOTCH_Dgraph * const grafptr) { return (dgraphCheck ((const Dgraph * const) grafptr)); } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_es.c0000644000175300017530000010337711631334325023154 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_es.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a matrix ordering software. **/ /** This module computes the node separator **/ /** of a graph based on the edge-separation **/ /** module of "bgraph_bipart_st.c". **/ /** **/ /** DATES : # Version 3.2 : from : 17 oct 1996 **/ /** to : 07 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 18 aug 2004 **/ /** to 20 aug 2004 **/ /** # Version 5.0 : from : 24 jan 2007 **/ /** to 12 sep 2007 **/ /** # Version 5.1 : from : 09 nov 2008 **/ /** to 09 nov 2008 **/ /** **/ /** NOTES : # This algorithm comes from: **/ /** "Computing the Block Triangular form **/ /** of a Sparse Matrix", A. Pothen and **/ /** C.-J. Fan, ACM Trans. on Mathematical **/ /** Software, 16 (4), pp 303-324, 1990. **/ /** and from: **/ /** "Implementations of $O(n^{1/2}\tau)$ **/ /** assignment algorithms", I. Duff and **/ /** T. Wieberg, ACM Trans. on Math. **/ /** Software, 4, pp 267-287, 1988. **/ /** **/ /** # The choice of the separator to take, **/ /** either HR u SC u VC or HR u SR u VC, **/ /** is made regarding the size of the **/ /** separator only, irrespective of its **/ /** balance. This choice is made because **/ /** else an imbalance ratio should be **/ /** provided for this method, and because **/ /** it is assumed that the edge biparti- **/ /** tioning method is assumed to have **/ /** reached suitable balance. When they **/ /** are equal, the choice is biased **/ /** towards SR, because the xC block is **/ /** the one which has less vertices so **/ /** removing more separator vertices from **/ /** it would mean increasing imbalance. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VGRAPH_SEPARATE_ES #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "arch.h" #include "mapping.h" #include "bgraph.h" #include "bgraph_bipart_st.h" #include "vgraph.h" #include "vgraph_separate_es.h" /*********************************************/ /* */ /* These routines compute a vertex separator */ /* from an edge separator represented as a */ /* bipartite graph, by minimum covering. */ /* */ /*********************************************/ /* This routine computes a vertex separator ** from an edge separator represented as a ** bipartite graph, by minimum covering. ** It returns: ** - 0 : if a separator could be computed. ** - !0 : on error. */ static int vgraphSeparateEsCover ( const Graph * restrict const grafptr, /* Bipartite graph to cover */ const Gnum partnbr, /* Number of vertices in first part */ Gnum * const sepatab, /* Array of covering vertices */ Gnum * const sepaptr) /* Pointer to size of the array */ { Gnum * restrict levltax; /* Array of vertex level values */ Gnum levlmax; /* Maximum level searched */ Gnum * restrict listtab; /* List of reachable augmenting rows */ Gnum listnbr; /* Number of items in list */ Gnum * restrict matetax; /* Matching array */ Gnum * queutab; /* Queue of (free) column nodes */ Gnum * restrict queuhead; /* Head of queue */ Gnum * restrict queutail; /* Tail of queue */ VgraphSeparateEsTrav * restrict travtax; /* Array of traversal flag values */ VgraphSeparateEsType * restrict typetax; /* Vertex type in the graph */ Gnum loadcval; /* Load of subset (HR u SC u VC) */ Gnum loadrval; /* Load of subset (HR u SR u VC) */ Gnum sizecval; /* Load of subset (HR u SC u VC) */ Gnum sizerval; /* Load of subset (HR u SR u VC) */ Gnum vertnum; #ifdef SCOTCH_DEBUG_VGRAPH2 if (sizeof (VgraphSeparateEsType) > sizeof (VgraphSeparateEsTrav)) { /* Assert next trick will work */ errorPrint ("vgraphSeparateEsCover: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ if (memAllocGroup ((void **) (void *) &travtax, (size_t) (grafptr->vertnbr * sizeof (VgraphSeparateEsTrav)), &matetax, (size_t) (grafptr->vertnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("vgraphSeparateEsCover: out of memory (1)"); return (1); } if (memAllocGroup ((void **) (void *) &queutab, (size_t) (partnbr * sizeof (Gnum)), &levltax, (size_t) (grafptr->vertnbr * sizeof (Gnum)), &listtab, (size_t) (grafptr->vertnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("vgraphSeparateEsCover: out of memory (2)"); memFree (travtax); /* Not based yet */ return (1); } travtax -= grafptr->baseval; matetax -= grafptr->baseval; levltax -= grafptr->baseval; memSet (matetax + (partnbr + grafptr->baseval), ~0, (grafptr->vertnbr - partnbr) * sizeof (Gnum)); for (vertnum = grafptr->baseval; /* Compute a cheap matching */ vertnum < (partnbr + grafptr->baseval); vertnum ++) { Gnum edgenum; Gnum matenum; for (edgenum = grafptr->verttax[vertnum], matenum = ~0; /* Search a matching end vertex */ edgenum < grafptr->vendtax[vertnum]; edgenum ++) { Gnum vertend; vertend = grafptr->edgetax[edgenum]; if (matetax[vertend] == ~0) { /* If an unmatched end vertex is found */ matenum = vertend; matetax[vertend] = vertnum; break; } } matetax[vertnum] = matenum; } do { /* Matching augmentation loop */ queuhead = /* Flush the data structures */ queutail = queutab; listnbr = 0; memSet (levltax + grafptr->baseval, 0, grafptr->vertnbr * sizeof (Gnum)); memSet (travtax + grafptr->baseval, 0, grafptr->vertnbr * sizeof (Gnum)); levlmax = ~0; for (vertnum = grafptr->baseval; /* Enqueue unmatched column nodes */ vertnum < (partnbr + grafptr->baseval); vertnum ++) { if (matetax[vertnum] == ~0) { *queuhead ++ = vertnum; levltax[vertnum] = 1; } } while (queuhead > queutail) { /* As long as there are free columns */ Gnum vertcol; vertcol = *queutail ++; /* Get the free column vertex */ if (levltax[vertcol] < levlmax) { Gnum edgenum; travtax[vertcol] = VGRAPHSEPAESTRAVUSED; /* Column has been reached */ for (edgenum = grafptr->verttax[vertcol]; /* For all neighboring rows */ edgenum < grafptr->vendtax[vertcol]; edgenum ++) { Gnum vertrow; vertrow = grafptr->edgetax[edgenum]; if (travtax[vertrow] == VGRAPHSEPAESTRAVFREE) { /* If row not yet reached yet */ travtax[vertrow] = VGRAPHSEPAESTRAVUSED; /* Now it is */ if (matetax[vertrow] == ~0) { /* If row is unmatched */ listtab[listnbr ++] = vertrow; /* Put it in list */ levlmax = levltax[vertcol]; /* Do not go any further */ } else { /* Row is matched */ *queuhead ++ = matetax[vertrow]; /* Enqueue its matching column */ levltax[matetax[vertrow]] = levltax[vertcol] + 1; } } } } } if (listnbr <= 0) /* If no free rows could be reached */ break; /* Then the matching is maximal */ while (-- listnbr >= 0) /* For all rows in list, try to augment the matching */ vgraphSeparateEsCoverAugment (levltax, levlmax, matetax, travtax, grafptr->verttax, grafptr->vendtax, grafptr->edgetax, listtab[listnbr]); } while (1); memFree (queutab); /* Free group leader of arrays no longer in use */ typetax = (VgraphSeparateEsType *) travtax; /* TRICK: re-use traversal table as type table */ for (vertnum = grafptr->baseval; vertnum < (partnbr + grafptr->baseval); vertnum ++) /* Pre-set vertex types */ typetax[vertnum] = VGRAPHSEPAESTYPESC; for ( ; vertnum < grafptr->vertnnd; vertnum ++) typetax[vertnum] = VGRAPHSEPAESTYPESR; for (vertnum = grafptr->baseval; vertnum < (partnbr + grafptr->baseval); vertnum ++) /* For all column vertices */ if (matetax[vertnum] == ~0) /* If vertex is unmatched */ vgraphSeparateEsCoverCol (matetax, typetax, grafptr->verttax, grafptr->vendtax, grafptr->edgetax, vertnum); /* Find HC and HR */ for ( ; vertnum < grafptr->vertnnd; vertnum ++) /* For all row vertices */ if (matetax[vertnum] == ~0) /* If vertex is unmatched */ vgraphSeparateEsCoverRow (matetax, typetax, grafptr->verttax, grafptr->vendtax, grafptr->edgetax, vertnum); /* Find VC and VR */ sizecval = /* Reset sizes */ sizerval = 0; if (grafptr->velotax != NULL) { /* If graph vertices are weighted */ Gnum vertnum; loadcval = /* Reset loads */ loadrval = 0; for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { /* Accumulate loads */ VgraphSeparateEsType typeval; Gnum veloval; Gnum bitcval; Gnum bitrval; typeval = typetax[vertnum]; veloval = grafptr->velotax[vertnum]; bitcval = (typeval >> VGRAPHSEPAESTYPEBITC) & 1; bitrval = typeval >> VGRAPHSEPAESTYPEBITR; /* TRICK: highest bit so does not need mask */ loadcval += bitcval * veloval; /* Superscalar update */ loadrval += bitrval * veloval; sizecval += bitcval; sizerval += bitrval; } } else { /* Graph vertices are not weighted */ Gnum vertnum; for (vertnum = grafptr->baseval; vertnum < grafptr->vertnnd; vertnum ++) { /* Accumulate vertex sizes */ sizecval += (typetax[vertnum] >> VGRAPHSEPAESTYPEBITC) & 1; /* Superscalar update */ sizerval += typetax[vertnum] >> VGRAPHSEPAESTYPEBITR; /* TRICK: highest bit so does not need mask */ } loadcval = sizecval; /* Loads equal sizes */ loadrval = sizerval; } if (loadcval < loadrval) { /* If separator with SC is smaller */ Gnum vertnum; Gnum sepanum; *sepaptr = sizecval; for (vertnum = grafptr->baseval, sepanum = 0; vertnum < grafptr->vertnnd; vertnum ++) { if ((typetax[vertnum] & VGRAPHSEPAESTYPEHRSCVC) != 0) { #ifdef SCOTCH_DEBUG_VGRAPH2 if ((sepanum >= sizecval) || ((typetax[vertnum] != VGRAPHSEPAESTYPEHR) && (typetax[vertnum] != VGRAPHSEPAESTYPESC) && (typetax[vertnum] != VGRAPHSEPAESTYPEVC))) { errorPrint ("vgraphSeparateEsCover: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ sepatab[sepanum ++] = vertnum; } } #ifdef SCOTCH_DEBUG_VGRAPH2 if (sepanum != sizecval) { errorPrint ("vgraphSeparateEsCover: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ } else { /* If separator with SR is smaller */ Gnum vertnum; Gnum sepanum; *sepaptr = sizerval; for (vertnum = grafptr->baseval, sepanum = 0; vertnum < grafptr->vertnnd; vertnum ++) { if ((typetax[vertnum] & VGRAPHSEPAESTYPEHRSRVC) != 0) { #ifdef SCOTCH_DEBUG_VGRAPH2 if ((sepanum >= sizerval) || ((typetax[vertnum] != VGRAPHSEPAESTYPEHR) && (typetax[vertnum] != VGRAPHSEPAESTYPESR) && (typetax[vertnum] != VGRAPHSEPAESTYPEVC))) { errorPrint ("vgraphSeparateEsCover: internal error (4)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ sepatab[sepanum ++] = vertnum; } } #ifdef SCOTCH_DEBUG_VGRAPH2 if (sepanum != sizerval) { errorPrint ("vgraphSeparateEsCover: internal error (5)"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ } memFree (travtax + grafptr->baseval); /* Free group leader of remaining arrays */ return (0); } /* This routine augments the current matching ** by performing a backtracking depth-first ** search from a free row vertex to a free ** column vertex, guided by the level values. ** It returns: ** - 0 : backtracking succeeded. ** - !0 : could not find a valid return path. */ static int vgraphSeparateEsCoverAugment ( const Gnum * restrict const levltax, const Gnum levlcur, /* Current backtracking level */ Gnum * restrict const matetax, VgraphSeparateEsTrav * restrict const travtax, const Gnum * restrict const verttax, const Gnum * restrict const vendtax, const Gnum * restrict const edgetax, const Gnum vertrow) /* Row vertex to backtrack from */ { Gnum edgenum; travtax[vertrow] = VGRAPHSEPAESTRAVDRTY; /* Never re-use this row */ for (edgenum = verttax[vertrow]; edgenum < vendtax[vertrow]; edgenum ++) { Gnum vertcol; vertcol = edgetax[edgenum]; /* Get column vertex */ if ((travtax[vertcol] == VGRAPHSEPAESTRAVUSED) && /* If this column may be a backtracking path */ (levltax[vertcol] == levlcur)) { /* At the proper distance from a free column */ travtax[vertcol] = VGRAPHSEPAESTRAVDRTY; /* Never re-use this column */ if ((levlcur == 1) || /* If we have (recursively) reached a free column vertex */ (vgraphSeparateEsCoverAugment (levltax, levlcur - 1, matetax, travtax, verttax, vendtax, edgetax, matetax[vertcol]) == 0)) { matetax[vertcol] = vertrow; /* Switch the edges of the augmenting path */ matetax[vertrow] = vertcol; return (0); /* Backtracking process is under way */ } } } return (1); /* No improvement could be done */ } /* Starting from unmatched column and row vertices, ** these routines perform depth-first traversals of ** the bipartite graph, following alternating paths. ** It is assumed that the matchings are sufficently ** large, so that the depth of the trees is small ** and the stack will not overflow. ** They return: ** - VOID : in all cases. */ static void vgraphSeparateEsCoverCol ( const Gnum * restrict const matetax, VgraphSeparateEsType * restrict const typetax, const Gnum * restrict const verttax, const Gnum * restrict const vendtax, const Gnum * restrict const edgetax, const Gnum vertcol) /* Column vertex index */ { Gnum edgenum; if (typetax[vertcol] == VGRAPHSEPAESTYPEHC) /* If vertex already traversed */ return; typetax[vertcol] = VGRAPHSEPAESTYPEHC; for (edgenum = verttax[vertcol]; edgenum < vendtax[vertcol]; edgenum ++) { Gnum vertrow; vertrow = edgetax[edgenum]; if (typetax[vertrow] == VGRAPHSEPAESTYPEHR) /* If end vertex already traversed */ continue; /* Skip to next vertex */ typetax[vertrow] = VGRAPHSEPAESTYPEHR; if (matetax[vertrow] != ~0) /* If end vertex matched */ vgraphSeparateEsCoverCol (matetax, typetax, verttax, vendtax, edgetax, matetax[vertrow]); } } static void vgraphSeparateEsCoverRow ( const Gnum * restrict const matetax, VgraphSeparateEsType * restrict const typetax, const Gnum * restrict const verttax, const Gnum * restrict const vendtax, const Gnum * restrict const edgetax, const Gnum vertrow) /* Row vertex index */ { Gnum edgenum; if (typetax[vertrow] == VGRAPHSEPAESTYPEVR) /* If vertex already traversed */ return; typetax[vertrow] = VGRAPHSEPAESTYPEVR; for (edgenum = verttax[vertrow]; edgenum < vendtax[vertrow]; edgenum ++) { Gnum vertcol; vertcol = edgetax[edgenum]; if (typetax[vertcol] == VGRAPHSEPAESTYPEVC) /* If end vertex already traversed */ continue; /* Skip to next vertex */ typetax[vertcol] = VGRAPHSEPAESTYPEVC; if (matetax[vertcol] != ~0) /* If end vertex matched */ vgraphSeparateEsCoverRow (matetax, typetax, verttax, vendtax, edgetax, matetax[vertcol]); } } /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine separates the given graph by first ** computing an edge separator, according to the ** given bipartitioning strategy, and then turning ** it into a vertex separator. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int vgraphSeparateEs ( Vgraph * restrict const grafptr, /*+ Active graph +*/ const VgraphSeparateEsParam * const paraptr) /*+ Method parameters +*/ { Bgraph actgrafdat; /* Active graph structure */ Graph bipgrafdat; /* Bipartite graph structure */ actgrafdat.s = grafptr->s; /* Initialize active graph */ actgrafdat.s.flagval = grafptr->s.flagval & ~(GRAPHFREETABS | BGRAPHFREEPART | BGRAPHFREEFRON); actgrafdat.s.vnumtax = NULL; actgrafdat.s.vlbltax = NULL; actgrafdat.veextax = NULL; /* No external gains */ actgrafdat.parttax = grafptr->parttax; /* Inherit arrays from vertex separation graph */ actgrafdat.frontab = grafptr->frontab; bgraphInit2 (&actgrafdat, 1, 1, 1); /* Complete initialization and set all vertices to part 0 */ if (bgraphBipartSt (&actgrafdat, paraptr->strat) != 0) { /* Bipartition active subgraph */ errorPrint ("vgraphSeparateEs: cannot bipartition active graph"); return (1); } grafptr->compload[0] = actgrafdat.compload0; /* Reset vertex counts */ grafptr->compload[1] = actgrafdat.s.velosum - actgrafdat.compload0; grafptr->compsize[0] = actgrafdat.compsize0; grafptr->compsize[1] = actgrafdat.s.vertnbr - actgrafdat.compsize0; if (actgrafdat.fronnbr > 0) { /* If edge separator is not empty */ if (paraptr->widtval == VGRAPHSEPAESWIDTHTHIN) { /* If thin vertex separator wanted */ Gnum * restrict actvnumtax; Gnum actfronnum; Gnum bipvelosum; Gnum bipedgenbr; /* Number of edges in bipartite graph (i.e. arcs) */ Gnum bipedgenbr0; /* Number of edges adjacent to part 0 */ Gnum bipedgenbr1; /* Number of edges adjacent to part 1 */ Gnum bipvertnbr0; /* Number of vertices in part 0 */ Gnum bipvertnbr1; /* Number of vertices in part 1 */ Gnum bipvertnbrp; /* Number of vertices in part put in first place */ Gnum bippartval; /* Part of bipartite graph to be put in first place */ Gnum compsizep; /* Number of vertices to be removed from part p */ Gnum compload01; /* Load of vertices to be removed from both parts */ Gnum comploadp; /* Load of vertices to be removed from part p */ if ((actvnumtax = (Gnum *) memAlloc (actgrafdat.s.vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("vgraphSeparateEs: out of memory (1)"); return (1); } #ifdef SCOTCH_DEBUG_VGRAPH2 memSet (actvnumtax, ~0, actgrafdat.s.vertnbr * sizeof (Gnum)); #endif /* SCOTCH_DEBUG_VGRAPH2 */ actvnumtax -= actgrafdat.s.baseval; bipedgenbr = 0; /* Initialize bipartite graph counts */ bipvertnbr0 = bipvertnbr1 = 0; for (actfronnum = 0; actfronnum < actgrafdat.fronnbr; actfronnum ++) { /* For all frontier vertices */ Gnum actvertnum; int actpartval; Gnum actedgenum; actvertnum = grafptr->frontab[actfronnum]; actpartval = grafptr->parttax[actvertnum]; if (actpartval == 0) { /* Count separator edges only for nodes of one side and multply by 2 */ for (actedgenum = actgrafdat.s.verttax[actvertnum]; actedgenum < actgrafdat.s.vendtax[actvertnum]; actedgenum ++) bipedgenbr += (actpartval ^ grafptr->parttax[actgrafdat.s.edgetax[actedgenum]]); } actvnumtax[actvertnum] = actpartval * (bipvertnbr1 - bipvertnbr0) + bipvertnbr0; /* Count and number separator vertices on each side */ bipvertnbr0 += actpartval ^ 1; /* Superscalar update */ bipvertnbr1 += actpartval; } bipedgenbr *= 2; /* Count both sides of arcs */ bipgrafdat.flagval = GRAPHFREEVERT | GRAPHVERTGROUP; /* Initialize bipartite graph structure */ bipgrafdat.baseval = 0; /* Base bipartite graph from 0 */ bipgrafdat.vertnbr = bipgrafdat.vertnnd = bipvertnbr0 + bipvertnbr1; if (memAllocGroup ((void **) (void *) &bipgrafdat.verttax, (size_t) ((bipgrafdat.vertnbr + 1) * sizeof (Gnum)), &bipgrafdat.velotax, (size_t) ((actgrafdat.s.velotax != NULL) ? (bipgrafdat.vertnbr * sizeof (Gnum)) : 0), &bipgrafdat.vnumtax, (size_t) (bipgrafdat.vertnbr * sizeof (Gnum)), &bipgrafdat.edgetax, (size_t) (bipedgenbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("vgraphSeparateEs: out of memory (2)"); memFree (actvnumtax + actgrafdat.s.baseval); return (1); } bipgrafdat.vendtax = bipgrafdat.verttax + 1; if (actgrafdat.s.velotax == NULL) bipgrafdat.velotax = NULL; bipgrafdat.vlbltax = NULL; bipgrafdat.edgenbr = bipedgenbr; bipgrafdat.edlotax = NULL; bipgrafdat.edlosum = bipedgenbr; bipgrafdat.degrmax = grafptr->s.degrmax; bippartval = (bipvertnbr0 <= bipvertnbr1) ? 0 : 1; /* Select smallest part to be placed first */ if (bippartval == 0) { bipvertnbrp = bipvertnbr0; bipedgenbr0 = 0; bipedgenbr1 = bipedgenbr / 2; } else { bipvertnbrp = bipvertnbr1; bipedgenbr0 = bipedgenbr / 2; bipedgenbr1 = 0; } bipvelosum = 0; for (actfronnum = 0; actfronnum < actgrafdat.fronnbr; actfronnum ++) { /* For all frontier vertices */ Gnum actvertnum; int actpartval; Gnum bipvertnum; Gnum actedgenum; actvertnum = grafptr->frontab[actfronnum]; actpartval = grafptr->parttax[actvertnum]; bipvertnum = (actpartval ^ bippartval) * bipvertnbrp + actvnumtax[actvertnum]; if (bipgrafdat.velotax != NULL) { Gnum actveloval; actveloval = actgrafdat.s.velotax[actvertnum]; bipvelosum += actveloval; bipgrafdat.velotax[bipvertnum] = actveloval; } bipgrafdat.vnumtax[bipvertnum] = actvertnum; bipgrafdat.verttax[bipvertnum] = actpartval * (bipedgenbr1 - bipedgenbr0) + bipedgenbr0; for (actedgenum = actgrafdat.s.verttax[actvertnum]; /* Count separator edges */ actedgenum < actgrafdat.s.vendtax[actvertnum]; actedgenum ++) { Gnum actvertend; int actpartend; actvertend = actgrafdat.s.edgetax[actedgenum]; actpartend = grafptr->parttax[actvertend]; if (actpartend != actpartval) { Gnum bipedgenum; #ifdef SCOTCH_DEBUG_VGRAPH2 if (actvnumtax[actvertend] == ~0) { errorPrint ("vgraphSeparateEs: internal error (1)"); graphExit (&bipgrafdat); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ bipedgenum = actpartval * (bipedgenbr1 - bipedgenbr0) + bipedgenbr0; bipedgenbr0 += actpartval ^ 1; /* Superscalar update */ bipedgenbr1 += actpartval; bipgrafdat.edgetax[bipedgenum] = actvnumtax[actvertend] + (actpartend ^ bippartval) * bipvertnbrp; } } } bipgrafdat.verttax[bipgrafdat.vertnbr] = bipgrafdat.edgenbr; bipgrafdat.velosum = (bipgrafdat.velotax != NULL) ? bipvelosum : bipgrafdat.vertnbr; memFree (actvnumtax + actgrafdat.s.baseval); #ifdef SCOTCH_DEBUG_VGRAPH2 if (((bipedgenbr0 - bipedgenbr1) * bippartval + bipedgenbr1) != bipgrafdat.edgenbr) { errorPrint ("vgraphSeparateEs: internal error (2)"); graphExit (&bipgrafdat); return (1); } if (graphCheck (&bipgrafdat) != 0) { errorPrint ("vgraphSeparateEs: internal error (3)"); graphExit (&bipgrafdat); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ if (vgraphSeparateEsCover (&bipgrafdat, bipvertnbrp, grafptr->frontab, &grafptr->fronnbr) != 0) { errorPrint ("vgraphSeparateEs: cannot compute cover"); graphExit (&bipgrafdat); return (1); } compsizep = 0; if (actgrafdat.s.velotax != NULL) { /* If vertices are weighted */ Gnum fronnum; compload01 = comploadp = 0; for (fronnum = 0; fronnum < grafptr->fronnbr; fronnum ++) { Gnum bipvertnum; Gnum actvertnum; Gnum actveloval; bipvertnum = grafptr->frontab[fronnum]; actvertnum = bipgrafdat.vnumtax[bipvertnum]; actveloval = actgrafdat.s.velotax[actvertnum]; grafptr->frontab[fronnum] = actvertnum; /* Express vertices with respect to original graph */ grafptr->parttax[actvertnum] = 2; /* Write separator part for global renumbering */ compload01 += actveloval; if (bipvertnum < bipvertnbrp) { /* Update separator vertices */ compsizep ++; /* Superscalar update */ comploadp += actveloval; } } } else { /* Vertices are not weighted */ Gnum fronnum; for (fronnum = 0; fronnum < grafptr->fronnbr; fronnum ++) { Gnum bipvertnum; Gnum actvertnum; bipvertnum = grafptr->frontab[fronnum]; actvertnum = bipgrafdat.vnumtax[bipvertnum]; grafptr->frontab[fronnum] = actvertnum; /* Express vertices with respect to original graph */ grafptr->parttax[actvertnum] = 2; /* Write separator part for global renumbering */ if (bipvertnum < bipvertnbrp) /* Update separator vertices */ compsizep ++; /* Superscalar update */ } compload01 = grafptr->fronnbr; /* Loads are equivalent to sizes */ comploadp = compsizep; } grafptr->compsize[bippartval] -= compsizep; grafptr->compsize[bippartval ^ 1] -= grafptr->fronnbr - compsizep; grafptr->compload[bippartval] -= comploadp; grafptr->compload[bippartval ^ 1] -= compload01 - comploadp; graphExit (&bipgrafdat); } else { /* Fat separator wanted */ Gnum compsize1; /* Number of vertices to be removed from part 1 */ Gnum compload01; /* Load of vertices to be removed from both parts */ Gnum compload1; /* Load of vertices to be removed from part 1 */ compsize1 = 0; grafptr->fronnbr = actgrafdat.fronnbr; /* Keep separator as is */ if (actgrafdat.s.velotax != NULL) { /* If vertices are weighted */ Gnum fronnum; compload01 = compload1 = 0; for (fronnum = 0; fronnum < actgrafdat.fronnbr; fronnum ++) { Gnum vertnum; Gnum veloval; int partval; vertnum = grafptr->frontab[fronnum]; partval = grafptr->parttax[vertnum]; veloval = grafptr->s.velotax[vertnum]; compsize1 += partval; /* Superscalar update */ compload01 += veloval; compload1 += partval * veloval; grafptr->parttax[vertnum] = 2; /* Write separator part for global renumbering */ } } else { /* Vertices are not weighted */ Gnum fronnum; for (fronnum = 0; fronnum < actgrafdat.fronnbr; fronnum ++) { Gnum vertnum; int partval; vertnum = grafptr->frontab[fronnum]; partval = grafptr->parttax[vertnum]; compsize1 += partval; grafptr->parttax[vertnum] = 2; /* Write separator part for global renumbering */ } compload01 = actgrafdat.fronnbr; /* Loads are equivalent to sizes */ compload1 = compsize1; } grafptr->compsize[0] -= actgrafdat.fronnbr - compsize1; /* Update graph properties */ grafptr->compsize[1] -= compsize1; grafptr->compload[0] -= compload01 - compload1; grafptr->compload[1] -= compload1; } } grafptr->comploaddlt = grafptr->compload[0] - grafptr->compload[1]; grafptr->compload[2] = grafptr->s.velosum - grafptr->compload[0] - grafptr->compload[1]; grafptr->fronnbr = grafptr->s.vertnbr - grafptr->compsize[0] - grafptr->compsize[1]; #ifdef SCOTCH_DEBUG_VGRAPH2 if (vgraphCheck (grafptr) != 0) { errorPrint ("vgraphSeparateEs: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_es.h0000644000175300017530000001317111631334325023151 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_es.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the edge-separation-based node **/ /** separation module. **/ /** **/ /** DATES : # Version 3.2 : from : 24 oct 1996 **/ /** to : 07 sep 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 18 aug 2004 **/ /** to 19 aug 2004 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ Separator type. +*/ typedef enum VgraphSeparateEsWidth_ { VGRAPHSEPAESWIDTHTHIN, /*+ Thin vertex separator +*/ VGRAPHSEPAESWIDTHFAT /*+ Fat vertex separator +*/ } VgraphSeparateEsWidth; /*+ This structure holds the method parameters. +*/ typedef struct VgraphSeparateEsParam_ { Strat * strat; /*+ Edge bipartitioning strategy used +*/ VgraphSeparateEsWidth widtval; /*+ Separator width +*/ } VgraphSeparateEsParam; /*+ These are the type of subgraphs vertices belong to, used to represent the Dulmage- Mendelsohn decomposition. TRICK: item numbers have been carefully chosen, so that one can easily sort out vertices that belong to (HR u SC u VC) and to (HR u SR u VC). +*/ typedef enum VgraphSeparateEsType_ { VGRAPHSEPAESTYPEHC = 0x0000, VGRAPHSEPAESTYPEVR = 0x0001, VGRAPHSEPAESTYPEHRSCVC = 0x0002, /* Bit mask for testing */ VGRAPHSEPAESTYPESC = 0x0003, VGRAPHSEPAESTYPEHRSRVC = 0x0004, /* Bit mask for testing */ VGRAPHSEPAESTYPESR = 0x0005, VGRAPHSEPAESTYPEHR = 0x0006, VGRAPHSEPAESTYPEVC = 0x0007 } VgraphSeparateEsType; #define VGRAPHSEPAESTYPEBITC 1 /* Bit index for VGRAPHSEPAESTYPEHRSCVC */ #define VGRAPHSEPAESTYPEBITR 2 /* Bit index for VGRAPHSEPAESTYPEHRSRVC */ /*+ Vertex traversal flag. +*/ typedef enum VgraphSeparateEsTrav_ { VGRAPHSEPAESTRAVFREE = 0, /*+ Vertex not traversed +*/ VGRAPHSEPAESTRAVUSED, /*+ Vertex traversed by search for free rows +*/ VGRAPHSEPAESTRAVDRTY /*+ Vertex traversed by backtracking search for free columns +*/ } VgraphSeparateEsTrav; /* ** The function prototypes. */ #ifndef VGRAPH_SEPARATE_ES #define static #endif static int vgraphSeparateEsCover (const Graph * const, const Gnum, Gnum * const, Gnum * const); static int vgraphSeparateEsCoverAugment (const Gnum * restrict const, const Gnum, Gnum * restrict const, VgraphSeparateEsTrav * restrict const, const Gnum * restrict const, const Gnum * restrict const, const Gnum * restrict const, const Gnum); static void vgraphSeparateEsCoverCol (const Gnum * restrict const, VgraphSeparateEsType * restrict const, const Gnum * restrict const, const Gnum * restrict const, const Gnum * restrict const, const Gnum); static void vgraphSeparateEsCoverRow (const Gnum * restrict const, VgraphSeparateEsType * restrict const, const Gnum * restrict const, const Gnum * restrict const, const Gnum * restrict const, const Gnum); int vgraphSeparateEs (Vgraph * const, const VgraphSeparateEsParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/bdgraph_bipart_sq.h0000644000175300017530000000605511631334325022765 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_bipart_sq.h **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the sequential bipartitioning **/ /** routine for distributed graphs. **/ /** **/ /** DATES : # Version 5.1 : from : 19 nov 2007 **/ /** to : 20 nov 2007 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct BdgraphBipartSqParam_ { Strat * strat; /*+ Sequential bipartitioning strategy used +*/ } BdgraphBipartSqParam; /* ** The function prototypes. */ #ifndef BDGRAPH_BIPART_SQ #define static #endif int bdgraphBipartSq (Bdgraph * const, const BdgraphBipartSqParam * const); static void bdgraphBipartSqOpBest (const Gnum * const, Gnum * const, const int * const, const MPI_Datatype * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/hall_order_hd.c0000644000175300017530000011533511631334325022075 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hall_order_hd.c **/ /** **/ /** AUTHOR : Patrick AMESTOY **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders a halo graph or mesh **/ /** structure using the block-oriented Halo **/ /** Approximate (Multiple) Minimum Degree **/ /** algorithm, with super-variable **/ /** accounting (HaloAMD v2.0). **/ /** **/ /** DATES : # Version 3.2 : from : 09 aug 1998 **/ /** to 18 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 05 jan 1999 **/ /** # Version 4.0 : from : 14 jan 2003 **/ /** to : 29 aug 2007 **/ /** **/ /** NOTES : # This module contains pieces of code **/ /** that belong to other people; see **/ /** below. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HALL_ORDER_HD #include "module.h" #include "common.h" #include "graph.h" #include "hall_order_hd.h" /* -- translated by f2c (version 19970219). */ /** -------------------------------------------------------------------- **/ /** December 8th 2003 **/ /** Unique version for both graph of variables and graphs of elements **/ /** Let us refer to as **/ /** Gv a graph with only variables **/ /** Ge a graph with both variables and elements **/ /** **/ /** Notations used: **/ /** **/ /** Let V be the set of nodes **/ /** V = Ve + V0 + V1 **/ /** V0 = Set of variable nodes (not in halo) **/ /** V1 = Set of variable nodes (in halo) **/ /** Ve = Set of element nodes **/ /** **/ /** All 3 sets are disjoint, Ve and V1 can be empty **/ /** **/ /** Modifications w.r.t. previous version : **/ /** **/ /** New Input: **/ /** --------- **/ /** nbelts : integer holding size of Ve **/ /** =0 if Gv (graph of variables) **/ /** >0 if Ge **/ /** **/ /** Extension of the meaning of input entry len for nodes in Ve **/ /** --------- **/ /** len(i) = | Adj(i) | if i \in V0 U Ve **/ /** ( Note that in the case of a GE graph **/ /** if v\in V0 then len(v) = nb of elements adjacent to v ) **/ /** len(i) = - | Adj(i) | if i \in V1 **/ /** or -N -1 if | Adj(i) | = 0 and i \in V1 **/ /** **/ /** Modified the meaning of input entry elen **/ /** --------- **/ /** if e \in Ve then elen (e) = -N-1 **/ /** if v \in V0 then elen (v) = External degree of v **/ /** Gv : elen (v) = len(v) **/ /** Ge : elen (v) **/ /** should be computed in SCOTCH **/ /** if v \in V1 then elen (v) = 0 **/ /** **/ /** **/ /** Output is unchanged **/ /** --------- **/ /** **/ /** **/ /** End remarks done on December 8th 2003 **/ /** ---------------------------------------------------------------------**/ void hallOrderHdHalmd ( Gnum n, /* Matrix order */ Gnum nbelts, /* Number of elements */ Gnum iwlen, /* Length of array iw */ Gnum * restrict pe, /* Array of indexes in iw of start of row i */ Gnum pfree, /* Useful size in iw */ Gnum * restrict len, /* Array of lengths of adjacency lists */ Gnum * restrict iw, /* Adjacency list array */ Gnum * restrict nv, /* Array of element degrees */ Gnum * restrict elen, /* Array that holds the inverse permutation */ Gnum * restrict last, /* Array that holds the permutation */ Gnum * restrict ncmpa, /* Number of times array iw was compressed */ Gnum * restrict degree, /* Array that holds degree data */ Gnum * restrict head, /* Linked list structure */ Gnum * restrict next, /* Linked list structure */ Gnum * restrict w) /* Flag array */ { Gnum deg, degme, dext, dmax, e, elenme, eln, hash, hmod, i, ilast, inext, j, jlast, jnext, k, knt1, knt2, knt3, lenj, ln, me = 0, mem, mindeg, nel, newmem, nleft, nvi, nvj, nvpiv, slenme, we, wflg, wnvi, x, nbflag, nreal, lastd, nelme; Gnum p, p1, p2, p3, pdst, pend, pj, pme, pme1, pme2, pn, psrc; /** -------------------------------------------------------------------- **/ /** HALOAMD_V6: (January 1999, P. Amestoy) **/ /** *********** **/ /** 1/ ERROR 2 detection followed by stop statement suppressed. **/ /** 2/ Pb 1 identified in V5 was not correctly solved. **/ /** **/ /** HALOAMD_V5: (December 1998, P. Amestoy) **/ /** *********** **/ /** 1/ Solved problem with matrix psmigr 1, because upper bound degree **/ /** DEG>N was considered as a node of V1. **/ /** **/ /** HALOAMD_V4: (October 1998, P. Amestoy) **/ /** *********** **/ /** Only MA41 interface (ok for both scotch and MA41) is included in **/ /** this file. **/ /** **/ /** HALOAMD_V3: (August 1998, P. Amestoy) **/ /** ********** **/ /** Solved problem in version 2: variables of V1 with len(i)=0 were not **/ /** well processed. See modification of the input to characterize those **/ /** variables. **/ /** Problem detected by Jacko Koster while experimenting with C version **/ /** 2 of haloAMD in the context of multiple front method based on **/ /** MA27: "if for an interface variable i, row i in the matrix has only **/ /** a nonzero entry on the diagonal, we first remove this entry and **/ /** len(i) is set to zero on input to HALOAMD. However, this means that **/ /** HALOAMD will treat variable i as an interior variable (in V0) **/ /** instead as an interface variable (in V1). It is indeed a bit **/ /** strange to have such interface variables but we encountered some **/ /** in our debugging experiments with some random partitionings. **/ /** Solution: **/ /** IF on input i \in V1 and len(i)=0 (that is adjlist(i)={}) THEN **/ /** len(i) must be set on input to -N-1. **/ /** ENDIF **/ /** Therefore, all variables i / len(i) < 0 and only those are in V1. **/ /** Variables with len(i) = -N-1 are then processed differently at the **/ /** beginning of the code. **/ /** **/ /** HALOAMD_V2: (April 1998) **/ /** ********** **/ /** The end of the tree (including links to block of flagged indices **/ /** is built) . The list of flagged indices is considered as a dense **/ /** amalgamated node. **/ /** Tested on rosanna: ~amestoy/MA41_NEW/SUN_RISC_dbl/SOFT **/ /** **/ /** Comments on the OUTPUT: **/ /** ---------------------- **/ /** **/ /** Let V= V0 U V1 the nodes of the initial graph (|V|=n). **/ /** The assembly tree corresponds to the tree of the supernodes (or **/ /** supervariables). Each node of the assembly tree is then composed of **/ /** one principal variable and a list of secondary variables. The list **/ /** of variable of a node (principal + secondary variables) then **/ /** describes the structure of the diagonal bloc of the supernode. **/ /** The elimination tree denotes the tree of all the variables(=nodes) **/ /** and is therefore of order n. The arrays NV(N) and PE(N) give a **/ /** description of the assembly tree. **/ /** **/ /** 1/ Description of array nv(N) (on OUPUT) **/ /** nv(i)=0 i is a secondary variable. **/ /** N+1> nv(i) >0 i is a principal variable, nv(i) holds the number **/ /** of elements in column i of L (true degree of i) **/ /** nv(i) = N+1 then i is a flagged variable (belonging to V1) **/ /** **/ /** 2/ Description of array PE(N) (on OUPUT) **/ /** pe(i) = -(father of variable/node i) in the elimination tree. **/ /** If nv (i) .gt. 0, then i represents a node in the assembly tree, **/ /** and the parent of i is -pe (i), or zero if i is a root. **/ /** If nv (i) = 0, then (i,-pe (i)) represents an edge in a **/ /** subtree, the root of which is a node in the assembly tree. **/ /** **/ /** 3/ Example: **/ /** Let If be a root node father of Is in the assembly tree. **/ /** If is the principal variable of the node If and let If1, If2, If3 **/ /** be the secondary variables of node If. Is is the principal **/ /** variable of the node Is and let Is1, Is2 be the secondary **/ /** variables of node Is. **/ /** Then: **/ /** NV(If1)=NV(If2)=NV(If3) = 0 (secondary variables) **/ /** NV(Is1)=NV(Is2) = 0 (secondary variables) **/ /** NV(If) > 0 (principal variable) **/ /** NV(Is) > 0 (principal variable) **/ /** PE(If) = 0 (root node) **/ /** PE(Is) = -If (If is the father of Is in the assembly tree) **/ /** PE(If1)=PE(If2)=PE(If3)= -If (If is the principal variable) **/ /** PE(Is1)=PE(Is2)= -Is (Is is the principal variable) **/ /** **/ /** HALOAMD_V1: (September 1997) **/ /** ********** **/ /** Initial version designed to experiment the numerical (fill-in) **/ /** impact of taking into account the halo. This code should be able to **/ /** experiment no-halo, partial halo, complete halo. **/ /** -------------------------------------------------------------------- **/ /** HALOAMD is designed to process a graph composed of two types **/ /** of nodes, V0 and V1, extracted from a larger gragh. **/ /** V0^V1 = {}, **/ /** We used Min. degree heuristic to order only **/ /** nodes in V0, but the adjacency to nodes **/ /** in V1 is taken into account during ordering. **/ /** Nodes in V1 are odered at last. **/ /** Adjacency between nodes of V1 need not be provided, **/ /** however |len(i)| must always corresponds to the number of **/ /** edges effectively provided in the adjacency list of i. **/ /** On input : **/ /** ******** **/ /** Nodes INODE in V1 are flagged with len(INODE) = -degree **/ /** Update version HALO V3 (August 1998): **/ /** if len(i)=0 and i \in V1 then len(i) must be set **/ /** on input to -N-1. **/ /** ERROR return : **/ /** ************ **/ /** Negative value in ncmpa indicates an error detected **/ /** by HALOAMD. **/ /** **/ /** The graph provided MUST follow the rule: **/ /** if (i,j) is an edge in the gragh then **/ /** j must be in the adjacency list of i AND **/ /** i must be in the adjacency list of j. **/ /** **/ /** REMARKS : **/ /** ------- **/ /** 1/ Providing edges between nodes of V1 should not **/ /** affect the final ordering, only the amount of edges **/ /** of the halo should effectively affect the solution. **/ /** This code should work in the following cases: **/ /** 1/ halo not provided **/ /** 2/ halo partially provided **/ /** 3/ complete halo **/ /** 4/ complete halo+interconnection between nodes of V1. **/ /** **/ /** 1/ should run and provide identical results (w.r.t to **/ /** current implementation of AMD in SCOTCH). **/ /** 3/ and 4/ should provide identical results. **/ /** **/ /** 2/ All modifications of the MC47 initial code are indicated **/ /** with begin HALO .. end HALO **/ /** **/ /** Ordering of nodes in V0 is based on Approximate Minimum Degree **/ /** ordering algorithm, with aggressive absorption: **/ /** Given a representation of the nonzero pattern of a symmetric matrix, **/ /** A, (excluding the diagonal) perform an approximate minimum **/ /** (UMFPACK/MA38-style) degree ordering to compute a pivot order **/ /** such that fill-in in the Cholesky **/ /** factors A = LL^T is kept low. At each step, the pivot **/ /** selected is the one with the minimum UMFPACK/MA38-style **/ /** upper-bound on the external degree. Aggresive absorption is **/ /** used to tighten the bound on the degree. This can result an **/ /** significant improvement in the quality of the ordering for **/ /** some matrices. **/ /** The approximate degree algorithm implemented here is the **/ /** symmetric analogue of the degree update algorithm in MA38, by **/ /** Davis and Duff, also in the Harwell Subroutine Library. **/ /** **/ /** **** CAUTION: ARGUMENTS ARE NOT CHECKED FOR ERRORS ON INPUT. ***** **/ /** ** If you want error checking, a more versatile input format, and ** **/ /** ** a simpler user interface, then use MC47A/AD in the Harwell ** **/ /** ** Subroutine Library, which checks for errors, transforms the ** **/ /** ** input, and calls MC47B/BD. ** **/ /** ******************************************************************** **/ /** References: (UF Tech Reports are available via anonymous ftp **/ /** to ftp.cis.ufl.edu:cis/tech-reports). **/ /** [1] Timothy A. Davis and Iain Duff, "An unsymmetric-pattern **/ /** multifrontal method for sparse LU factorization", **/ /** SIAM J. Matrix Analysis and Applications, to appear. **/ /** also Univ. of Florida Technical Report TR-94-038. **/ /** Discuss UMFPACK / MA38. **/ /** [2] Patrick Amestoy, Timothy A. Davis, and Iain S. Duff, **/ /** "An approximate minimum degree ordering algorithm," **/ /** SIAM J. Matrix Analysis and Applications (to appear), **/ /** also Univ. of Florida Technical Report TR-94-039. **/ /** Discusses this routine. **/ /** [3] Alan George and Joseph Liu, "The evolution of the **/ /** minimum degree ordering algorithm," SIAM Review, vol. **/ /** 31, no. 1, pp. 1-19, March 1989. We list below the **/ /** features mentioned in that paper that this code **/ /** includes: **/ /** mass elimination: **/ /** Yes. MA27 relied on supervariable detection for mass **/ /** elimination. **/ /** indistinguishable nodes: **/ /** Yes (we call these "supervariables"). This was also **/ /** in the MA27 code - although we modified the method of **/ /** detecting them (the previous hash was the true degree, **/ /** which we no longer keep track of). A supervariable is **/ /** a set of rows with identical nonzero pattern. All **/ /** variables in a supervariable are eliminated together. **/ /** Each supervariable has as its numerical name that of **/ /** one of its variables (its principal variable). **/ /** quotient graph representation: **/ /** Yes. We use the term "element" for the cliques formed **/ /** during elimination. This was also in the MA27 code. **/ /** The algorithm can operate in place, but it will work **/ /** more efficiently if given some "elbow room." **/ /** element absorption: **/ /** Yes. This was also in the MA27 code. **/ /** external degree: **/ /** Yes. The MA27 code was based on the true degree. **/ /** incomplete degree update and multiple elimination: **/ /** No. This was not in MA27, either. Our method of **/ /** degree update within MC47B/BD is element-based, not **/ /** variable-based. It is thus not well-suited for use **/ /** with incomplete degree update or multiple elimination. **/ /** -------------------------------------------------------------------- **/ /** Authors, and Copyright (C) 1995 by: **/ /** Timothy A. Davis, Patrick Amestoy, Iain S. Duff, & **/ /** John K. Reid. **/ /** Modified (V1) by P.R. Amestoy ENSEEIHT (1997) **/ /** Modified (V2) by P.R. Amestoy ENSEEIHT (1998) **/ /** Modified (V3) by P.R. Amestoy ENSEEIHT (1998) **/ /** Modified (V4) by P.R. Amestoy ENSEEIHT (1998) **/ /** Modified (V5) by P.R. Amestoy ENSEEIHT (1998) **/ /** Modified (V6) by P.R. Amestoy ENSEEIHT (1999) **/ /** **/ /** Dates: September, 1995 **/ /** September, 1997 (halo AMD V1) **/ /** April, 1998 (halo AMD V2) **/ /** August, 1998 (halo AMD V3) **/ -- w; /* Parameter adjustments */ -- next; -- head; -- degree; -- last; -- elen; -- nv; -- len; -- pe; -- iw; wflg = 2; mindeg = 1; *ncmpa = 0; nel = 0; hmod = MAX (1, (n - 1)); dmax = 0; mem = pfree - 1; nbflag = 0; lastd = 0; memSet (last + 1, 0, n * sizeof (Gnum)); memSet (head + 1, 0, n * sizeof (Gnum)); if (nbelts == 0) { /* Patch 8/12/03 */ memSet (elen + 1, 0, n * sizeof (Gnum)); for (i = 1; i <= n; i ++) { nv[i] = 1; w[i] = 1; if (len[i] < 0) { degree[i] = n + 1; nbflag ++; if (len[i] == - (n + 1)) { /* Patch 09/08/98 */ len[i] = 0; pe[i] = 0; /* Patch 12/12/03 : Because of compress, we force skipping those entries (which are anyway empty) */ } else len[i] = - len[i]; } else degree[i] = len[i]; } } else { /* Patch 08/12/03 : Duplicate part of previous loop to avoid sytematic testing for elements */ for (i = 1; i <= n; i ++) { nv[i] = 1; w[i] = 1; if (len[i] < 0) { /* i \in V1 */ degree[i] = n + 1; nbflag ++; if (len[i] == - (n + 1)) { /* Patch 09/08/98 */ len[i] = 0; pe[i] = 0; /* Patch 12/12/03 : because of compress, we force skipping those entries (which are anyway empty) */ elen[i] = 0; /* Patch 16/12/03 */ } else { len[i] = - len[i]; elen[i] = len[i]; /* Patch 16/12/03 : only elements are adjacent to a variable */ } } else { /* i \in Ve or V0 */ if (elen[i] < 0) { /* i \in Ve */ nel ++; degree[i] = len[i]; elen[i] = - nel; dmax = MAX (dmax, degree[i]); /* Patch 11/03/04 */ } else { degree[i] = elen[i]; elen[i] = len[i]; /* Patch 16/12/03 : only elements are adjacent to a variable */ } } } } /* Temporary Patch 8/12/03 TODO REMOVE */ if (nbelts != nel) printf ("error 8Dec2003\n"); nreal = n - nbflag; for (i = 1; i <= n; i ++) { if (elen[i] < 0 ) /* Patch 16/12/03 : Skip elements */ continue; deg = degree[i]; if (deg == (n + 1)) { deg = n; if (lastd == 0) { lastd = i; head[deg] = i; next[i] = 0; last[i] = 0; } else { next[lastd] = i; last[i] = lastd; lastd = i; next[i] = 0; } } else if (deg > 0) { inext = head[deg]; if (inext != 0) last[inext] = i; next[i] = inext; head[deg] = i; } else { nel ++; elen[i] = - nel; pe[i] = 0; w[i] = 0; } } /* L20: */ nleft = n - nel; /* Patch v5 12/12/98 */ while (nel < nreal) { /* WHILE (selecting pivots) DO */ for (deg = mindeg; deg <= n; deg ++) { /* Patch 17/11/97 */ me = head[deg]; if (me > 0) break; /* GO to 50 */ } /* L40: */ mindeg = deg; if (me <= 0) { /* Error 1 */ *ncmpa = -n; return; } inext = next[me]; if (inext != 0) last[inext] = 0; head[deg] = inext; elenme = elen[me]; elen[me] = - (nel + 1); nvpiv = nv[me]; nel += nvpiv; nv[me] = - nvpiv; degme = 0; if (elenme == 0) { pme1 = pe[me]; pme2 = pme1 - 1; for (p = pme1; p <= pme1 + len[me] - 1; p ++) { i = iw[p]; nvi = nv[i]; if (nvi > 0) { degme += nvi; nv[i] = - nvi; pme2 ++; iw[pme2] = i; if (degree[i] <= n) { ilast = last[i]; inext = next[i]; if (inext != 0) last[inext] = ilast; if (ilast != 0) next[ilast] = inext; else head[degree[i]] = inext; } } } /* L60: */ newmem = 0; } else { p = pe[me]; pme1 = pfree; slenme = len[me] - elenme; for (knt1 = 1; knt1 <= elenme + 1; knt1 ++) { if (knt1 > elenme) { e = me; pj = p; ln = slenme; } else { e = iw[p ++]; pj = pe[e]; ln = len[e]; } for (knt2 = 1; knt2 <= ln; knt2 ++) { i = iw[pj ++]; nvi = nv[i]; if (nvi > 0) { if (pfree > iwlen) { pe[me] = p; len[me] -= knt1; if (len[me] == 0) pe[me] = 0; pe[e] = pj; len[e] = ln - knt2; if (len[e] == 0) pe[e] = 0; (*ncmpa) ++; for (j = 1; j <= n; j ++) { pn = pe[j]; if (pn > 0) { pe[j] = iw[pn]; iw[pn] = - j; } } /* L70: */ pdst = 1; psrc = 1; pend = pme1 - 1; while (psrc <= pend) { /* L80: */ j = - iw[psrc ++]; if (j > 0) { iw[pdst] = pe[j]; pe[j] = pdst ++; lenj = len[j]; for (knt3 = 0; knt3 <= lenj - 2; knt3 ++) iw[pdst + knt3] = iw[psrc + knt3]; pdst = pdst + (lenj - 1); psrc = psrc + (lenj - 1); } } p1 = pdst; for (psrc = pme1; psrc <= pfree - 1; psrc ++, pdst ++) /* L100: */ iw[pdst] = iw[psrc]; pme1 = p1; pfree = pdst; pj = pe[e]; p = pe[me]; } degme += nvi; nv[i] = - nvi; iw[pfree] = i; (pfree) ++; if (degree[i] <= n) { ilast = last[i]; inext = next[i]; if (inext != 0) last[inext] = ilast; if (ilast != 0) next[ilast] = inext; else head[degree[i]] = inext; } } } /* L110: */ if (e != me) { pe[e] = -me; w[e] = 0; } } /* L120: */ pme2 = pfree - 1; newmem = pfree - pme1; mem += newmem; } degree[me] = degme; pe[me] = pme1; len[me] = pme2 - pme1 + 1; if (wflg + n <= wflg) { for (x = 1; x <= n; x ++) { if (w[x] != 0) w[x] = 1; } /* L130: */ wflg = 2; } for (pme = pme1; pme <= pme2; pme ++) { i = iw[pme]; eln = elen[i]; if (eln > 0) { nvi = - nv[i]; wnvi = wflg - nvi; for (p = pe[i]; p < pe[i] + eln; p ++) { e = iw[p]; we = w[e]; if (we >= wflg) we -= nvi; else if (we != 0) we = degree[e] + wnvi; w[e] = we; } /* L140: */ } } /* L150: */ for (pme = pme1; pme <= pme2; pme ++) { i = iw[pme]; p1 = pe[i]; p2 = p1 + elen[i] - 1; pn = p1; hash = 0; deg = 0; for (p = p1; p <= p2; p ++) { e = iw[p]; dext = w[e] - wflg; if (dext > 0) { deg += dext; iw[pn ++] = e; hash += e; } else if (dext == 0) { pe[e] = -me; w[e] = 0; } } /* L160: */ elen[i] = pn - p1 + 1; p3 = pn; for (p = p2 + 1; p < p1 + len[i]; p ++) { j = iw[p]; nvj = nv[j]; if (nvj > 0) { deg += nvj; iw[pn ++] = j; hash += j; } } /* L170: */ if (degree[i] == (n + 1)) deg = n + 1; if (deg == 0) { pe[i] = - me; nvi = - nv[i]; degme -= nvi; nvpiv += nvi; nel += nvi; nv[i] = 0; elen[i] = 0; } else { if (degree[i] != (n + 1)) { /* Patch v6 05/01/99 */ deg = MIN (nleft, deg); /* Patch v5 12/12/98 */ degree[i] = MIN (degree[i], deg); } iw[pn] = iw[p3]; iw[p3] = iw[p1]; iw[p1] = me; len[i] = pn - p1 + 1; if (deg <= n) { hash = (hash % hmod) + 1; j = head[hash]; if (j <= 0) { next[i] = - j; head[hash] = - i; } else { next[i] = last[j]; last[j] = i; } last[i] = hash; } } } /* L180: */ degree[me] = degme; dmax = MAX (dmax, degme); wflg += dmax; if (wflg + n <= wflg) { for (x = 1; x <= n; x ++) { if (w[x] != 0) w[x] = 1; } wflg = 2; } for (pme = pme1; pme <= pme2; pme ++) { i = iw[pme]; if ((nv[i] < 0) && (degree[i] <= n)) { hash = last[i]; j = head[hash]; if (j == 0) continue; if (j < 0) { i = - j; head[hash] = 0; } else { i = last[j]; last[j] = 0; } if (i == 0) continue; L200: /* WHILE LOOP: */ if (next[i] != 0) { ln = len[i]; eln = elen[i]; for (p = pe[i] + 1; p < pe[i] + ln; p ++) w[iw[p]] = wflg; jlast = i; j = next[i]; L220: /* WHILE LOOP: */ if (j != 0) { if (len[j] != ln) goto L240; if (elen[j] != eln) goto L240; for (p = pe[j] + 1; p < pe[j] + ln; p ++) { if (w[iw[p]] != wflg) goto L240; } /* L230: */ pe[j] = -i; nv[i] += nv[j]; nv[j] = 0; elen[j] = 0; j = next[j]; next[jlast] = j; goto L220; L240: jlast = j; j = next[j]; goto L220; } wflg ++; i = next[i]; if (i != 0) goto L200; } } } p = pme1; nleft = n - nel; for (pme = pme1; pme <= pme2; pme ++) { i = iw[pme]; nvi = - nv[i]; if (nvi > 0) { nv[i] = nvi; if (degree[i] <= n) { deg = MIN (degree[i] + degme, nleft) - nvi; inext = head[deg]; if (inext != 0) last[inext] = i; next[i] = inext; last[i] = 0; head[deg] = i; mindeg = MIN (mindeg, deg); degree[i] = deg; } iw[p ++] = i; } } /* L260: */ nv[me] = nvpiv + degme; len[me] = p - pme1; if (len[me] == 0) { pe[me] = 0; w[me] = 0; } if (newmem != 0) { pfree = p; mem = mem - newmem + len[me]; } } /* END WHILE (selecting pivots) */ if (nel < n) { /* Patch 12/12/98 (old: nreal < n) */ for (deg = mindeg; deg <= n; deg ++) { me = head[deg]; if (me > 0) break; } mindeg = deg; nelme = - (nel + 1); for (x = 1; x <= n; x ++) { if ((pe[x] > 0) && (elen[x] < 0)) pe[x] = - me; else if (degree[x] == (n + 1)) { nel += nv[x]; pe[x] = - me; elen[x] = 0; nv[x] = 0; /* Patch 12/12/98 (old: n + 1) */ } } elen[me] = nelme; nv[me] = n - nreal; /* Patch 12/12/98 (old: n + 1) */ pe[me] = 0; if (nel != n) { /* Error 2 */ *ncmpa = - (n + 1); return; } } for (i = 1; i <= n; i ++) { if (elen[i] == 0) { j = - pe[i]; while (elen[j] >= 0) /* L270: */ j = - pe[j]; e = j; k = - elen[e]; j = i; while (elen[j] >= 0) { /* L280: */ jnext = - pe[j]; pe[j] = - e; if (elen[j] == 0) elen[j] = k ++; j = jnext; } elen[e] = - k; } } /* L290: */ #ifdef DEAD_CODE /* No need for permutations */ for (i = 1; i <= n; i ++) { /* Patch 19/10/98 */ k = abs (elen[i]); last[k] = i; elen[i] = k; } /* L300: */ #endif /* DEAD_CODE */ } scotch-5.1.12b.dfsg/src/libscotch/dgraph_io_save.c0000644000175300017530000001650011631334325022253 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_io.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the input/output routines for **/ /** distributed graphs. **/ /** **/ /** # Version P0.2 : from : 11 may 1999 **/ /** to 12 may 1999 **/ /** # Version 5.0 : from : 22 jul 2005 **/ /** to : 22 apr 2008 **/ /** # Version 5.1 : from : 11 aug 2010 **/ /** to : 11 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH_IO #include "module.h" #include "common.h" #include "dgraph.h" /* This routine saves a distributed source ** graph to the given streams. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphSave ( Dgraph * restrict const grafptr, /* Not const since halo may update structure */ FILE * const stream) { Gnum * restrict vlblgsttax; /* Based index to ghost label array */ Gnum vertlocnum; char propstr[4]; /* Property string */ int o; #ifdef SCOTCH_DEBUG_DGRAPH2 if (MPI_Barrier (grafptr->proccomm) != MPI_SUCCESS) { /* Synchronize for debugging */ errorPrint ("dgraphSave: communication error"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ propstr[0] = (grafptr->vlblloctax != NULL) ? '1' : '0'; /* Set property string */ propstr[1] = (grafptr->edloloctax != NULL) ? '1' : '0'; propstr[2] = (grafptr->veloloctax != NULL) ? '1' : '0'; propstr[3] = '\0'; if (fprintf (stream, "2\n" GNUMSTRING "\t" GNUMSTRING "\n" GNUMSTRING "\t" GNUMSTRING "\n" GNUMSTRING "\t" GNUMSTRING "\n" GNUMSTRING "\t%3s\n", /* Write file header */ (Gnum) grafptr->procglbnbr, (Gnum) grafptr->proclocnum, (Gnum) grafptr->vertglbnbr, (Gnum) grafptr->edgeglbnbr, (Gnum) grafptr->vertlocnbr, (Gnum) grafptr->edgelocnbr, (Gnum) grafptr->baseval, propstr) == EOF) { errorPrint ("dgraphSave: bad output (1)"); return (1); } vlblgsttax = NULL; /* Ghost label array free yet */ if ((grafptr->vlblloctax != NULL) || /* If graph has vertex labels or */ (grafptr->edgeloctax == NULL) || /* If no global index edge array present or */ (grafptr->procvrttab[grafptr->procglbnbr] != grafptr->procdsptab[grafptr->procglbnbr])){ /* If graph may have holes in its numbering */ if (dgraphGhst (grafptr) != 0) { /* Compute ghost edge array */ errorPrint ("dgraphSave: cannot compute ghost edge array"); return (1); } if ((vlblgsttax = (Gnum *) memAlloc (grafptr->vertgstnbr * sizeof (Gnum))) == NULL) { errorPrint ("dgraphSave: out of memory"); return (1); } if (grafptr->vlblloctax != NULL) memCpy (vlblgsttax, grafptr->vlblloctax + grafptr->baseval, grafptr->vertlocnbr * sizeof (Gnum)); else { for (vertlocnum = 0; vertlocnum < grafptr->vertlocnbr; vertlocnum ++) /* vlblgsttax is not based yet at this time */ vlblgsttax[vertlocnum] = (Gnum) grafptr->procvrttab[grafptr->proclocnum] + vertlocnum; } if (dgraphHaloSync (grafptr, (byte *) vlblgsttax, GNUM_MPI) != 0) { /* vlblgsttax is not based yet at this time */ errorPrint ("dgraphSave: cannot halo labels"); memFree (vlblgsttax); return (1); } vlblgsttax -= grafptr->baseval; } o = 0; for (vertlocnum = grafptr->baseval; (vertlocnum < grafptr->vertlocnnd) && (o == 0); vertlocnum ++) { Gnum edgelocnum; if (grafptr->vlblloctax != NULL) /* Write vertex label if necessary */ o = (fprintf (stream, GNUMSTRING "\t", (Gnum) vlblgsttax[vertlocnum]) == EOF); if (grafptr->veloloctax != NULL) /* Write vertex load if necessary */ o |= (fprintf (stream, GNUMSTRING "\t", (Gnum) grafptr->veloloctax[vertlocnum]) == EOF); o |= (fprintf (stream, GNUMSTRING, (Gnum) (grafptr->vendloctax[vertlocnum] - grafptr->vertloctax[vertlocnum])) == EOF); /* Write vertex degree */ for (edgelocnum = grafptr->vertloctax[vertlocnum]; edgelocnum < grafptr->vendloctax[vertlocnum]; edgelocnum ++) { o |= (putc ('\t', stream) == EOF); if (grafptr->edloloctax != NULL) /* Write edge load if necessary */ o |= (fprintf (stream, "\t" GNUMSTRING " ", (Gnum) grafptr->edloloctax[edgelocnum]) == EOF); o |= (fprintf (stream, GNUMSTRING, (Gnum) ((vlblgsttax != NULL) /* Write edge end */ ? vlblgsttax[grafptr->edgegsttax[edgelocnum]] : grafptr->edgeloctax[edgelocnum])) == EOF); } o |= (putc ('\n', stream) == EOF); } if (o != 0) errorPrint ("dgraphSave: bad output (2)"); if (vlblgsttax != NULL) /* Free ghost label array if used */ memFree (vlblgsttax + grafptr->baseval); return (o); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_order_gather_f.c0000644000175300017530000001042511631334325025324 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_order_gather_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** distributed ordering gathering routines **/ /** of the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 21 jul 2007 **/ /** to 22 jul 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the ordering routines. */ /* */ /**************************************/ FORTRAN ( \ SCOTCHFDGRAPHCORDERINIT, scotchfdgraphcorderinit, ( \ const SCOTCH_Dgraph * const grafptr, \ SCOTCH_Ordering * const ordeptr, \ SCOTCH_Num * const permtab, \ SCOTCH_Num * const peritab, \ SCOTCH_Num * const cblkptr, \ SCOTCH_Num * const rangtab, \ SCOTCH_Num * const treetab, \ int * const revaptr), \ (grafptr, ordeptr, permtab, peritab, \ cblkptr, rangtab, treetab, revaptr)) { *revaptr = SCOTCH_dgraphCorderInit (grafptr, ordeptr, permtab, peritab, cblkptr, rangtab, treetab); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHCORDEREXIT, scotchfdgraphcorderexit, ( \ const SCOTCH_Dgraph * const grafptr, \ SCOTCH_Ordering * const ordeptr), \ (grafptr, ordeptr)) { SCOTCH_dgraphCorderExit (grafptr, ordeptr); } /* ** */ FORTRAN ( \ SCOTCHFDGRAPHORDERGATHER, scotchfdgraphordergather, ( \ const SCOTCH_Dgraph * const grafptr, \ const SCOTCH_Dordering * const dordptr, \ SCOTCH_Ordering * const cordptr, \ int * const revaptr), \ (grafptr, dordptr, cordptr, revaptr)) { *revaptr = SCOTCH_dgraphOrderGather (grafptr, dordptr, cordptr); } scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_nd.c0000644000175300017530000002773711631334325022444 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_nd.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders graphs using the **/ /** nested dissection algorithm. **/ /** **/ /** DATES : # Version 3.2 : from : 17 oct 1996 **/ /** to : 21 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to 13 mar 1999 **/ /** # Version 4.0 : from : 03 jan 2002 **/ /** to 24 dec 2004 **/ /** # Version 5.0 : from : 19 dec 2006 **/ /** to 25 jul 2007 **/ /** # Version 5.1 : from : 24 oct 2010 **/ /** to 24 oct 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HGRAPH_ORDER_ND #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "order.h" #include "hgraph.h" #include "hgraph_order_nd.h" #include "hgraph_order_st.h" #include "vgraph.h" #include "vgraph_separate_st.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hgraphOrderNd ( const Hgraph * restrict const grafptr, Order * restrict const ordeptr, const Gnum ordenum, OrderCblk * restrict const cblkptr, const HgraphOrderNdParam * restrict const paraptr) { Hgraph indgrafdat; /* Halo graph data */ Gnum * vspvnumptr[3]; /* Pointers to vertex lists to fill */ VertList vsplisttab[3]; /* Array of separated part lists */ Vgraph vspgrafdat; /* Vertex separation graph data */ Gnum vspvertnum; /* Current vertex in separation graph */ int o; vspgrafdat.s.flagval = GRAPHNONE; /* Do not free contents of separation graph */ vspgrafdat.s.baseval = grafptr->s.baseval; vspgrafdat.s.vertnbr = grafptr->vnohnbr; /* Keep only non-halo vertices for separation */ vspgrafdat.s.vertnnd = grafptr->vnohnnd; vspgrafdat.s.verttax = grafptr->s.verttax; vspgrafdat.s.vendtax = grafptr->vnhdtax; vspgrafdat.s.velotax = grafptr->s.velotax; vspgrafdat.s.velosum = grafptr->vnlosum; vspgrafdat.s.vnumtax = grafptr->s.vnumtax; vspgrafdat.s.vlbltax = NULL; vspgrafdat.s.edgenbr = grafptr->enohnbr; vspgrafdat.s.edgetax = grafptr->s.edgetax; vspgrafdat.s.edlotax = grafptr->s.edlotax; vspgrafdat.s.edlosum = grafptr->enohsum; vspgrafdat.s.degrmax = grafptr->s.degrmax; if ((vspgrafdat.frontab = (Gnum *) memAlloc (vspgrafdat.s.vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("hgraphOrderNd: out of memory (1)"); return (1); } if ((vspgrafdat.parttax = (GraphPart *) memAlloc (vspgrafdat.s.vertnbr * sizeof (GraphPart))) == NULL) { errorPrint ("hgraphOrderNd: out of memory (2)"); memFree (vspgrafdat.frontab); return (1); } memSet (vspgrafdat.parttax, 0, vspgrafdat.s.vertnbr * sizeof (GraphPart)); /* Set all vertices to part 0 */ vspgrafdat.parttax -= vspgrafdat.s.baseval; vspgrafdat.fronnbr = 0; vspgrafdat.compload[0] = vspgrafdat.s.velosum; vspgrafdat.compload[1] = 0; vspgrafdat.compload[2] = 0; vspgrafdat.comploaddlt = vspgrafdat.s.velosum; vspgrafdat.compsize[0] = vspgrafdat.s.vertnbr; vspgrafdat.compsize[1] = 0; vspgrafdat.fronnbr = 0; vspgrafdat.levlnum = grafptr->levlnum; /* Set level of separation graph as level of halo graph */ if (vgraphSeparateSt (&vspgrafdat, paraptr->sepstrat) != 0) { /* Separate vertex-separation graph */ vgraphExit (&vspgrafdat); return (1); } if ((vspgrafdat.compsize[0] == 0) || /* If could not separate more */ (vspgrafdat.compsize[1] == 0)) { vgraphExit (&vspgrafdat); /* Free useless space */ hgraphOrderSt (grafptr, ordeptr, ordenum, cblkptr, paraptr->ordstratlea); /* Order this leaf */ return (0); /* Leaf has been processed */ } vsplisttab[0].vnumnbr = vspgrafdat.compsize[0]; /* Build vertex lists within frontier array */ vsplisttab[0].vnumtab = vspgrafdat.frontab + vspgrafdat.fronnbr; vsplisttab[1].vnumnbr = vspgrafdat.compsize[1]; vsplisttab[1].vnumtab = vsplisttab[0].vnumtab + vsplisttab[0].vnumnbr; vsplisttab[2].vnumnbr = vspgrafdat.fronnbr; vsplisttab[2].vnumtab = vspgrafdat.frontab; vspvnumptr[0] = vsplisttab[0].vnumtab; vspvnumptr[1] = vsplisttab[1].vnumtab; vspvnumptr[2] = vsplisttab[2].vnumtab; for (vspvertnum = vspgrafdat.s.baseval; vspvertnum < vspgrafdat.s.vertnnd; vspvertnum ++) { /* Fill lists */ *vspvnumptr[vspgrafdat.parttax[vspvertnum]] ++ = vspvertnum; #ifdef SCOTCH_DEBUG_HGRAPH2 if (vspgrafdat.parttax[vspvertnum] != 2) { /* If vertex does not separate */ Gnum vspedgenum; GraphPart vsppartnum; vsppartnum = 1 - vspgrafdat.parttax[vspvertnum]; /* Get opposite part value */ for (vspedgenum = vspgrafdat.s.verttax[vspvertnum]; vspedgenum < vspgrafdat.s.vendtax[vspvertnum]; vspedgenum ++) { if (vspgrafdat.parttax[vspgrafdat.s.edgetax[vspedgenum]] == vsppartnum) { /* If an edge crosses the separator */ errorPrint ("hgraphOrderNd: internal error (1)"); vgraphExit (&vspgrafdat); return (1); } } } #endif /* SCOTCH_DEBUG_HGRAPH2 */ } #ifdef SCOTCH_DEBUG_HGRAPH2 if ((vspvnumptr[0] != vsplisttab[0].vnumtab + vsplisttab[0].vnumnbr) || (vspvnumptr[1] != vsplisttab[1].vnumtab + vsplisttab[1].vnumnbr) || (vspvnumptr[2] != vsplisttab[2].vnumtab + vsplisttab[2].vnumnbr)) { errorPrint ("hgraphOrderNd: internal error (2)"); vgraphExit (&vspgrafdat); return (1); } #endif /* SCOTCH_DEBUG_HGRAPH2 */ memFree (vspgrafdat.parttax + vspgrafdat.s.baseval); /* Free useless space */ #ifdef SCOTCH_DEBUG_HGRAPH2 vspgrafdat.parttax = NULL; /* Will cause bug if re-read */ #endif /* SCOTCH_DEBUG_HGRAPH2 */ cblkptr->typeval = ORDERCBLKNEDI; /* Node becomes a nested dissection node */ if ((cblkptr->cblktab = (OrderCblk *) memAlloc (3 * sizeof (OrderCblk))) == NULL) { errorPrint ("hgraphOrderNd: out of memory (2)"); memFree (vspgrafdat.frontab); /* Free remaining space */ return (1); } cblkptr->cblktab[0].typeval = ORDERCBLKOTHR; /* Build column blocks */ cblkptr->cblktab[0].vnodnbr = vsplisttab[0].vnumnbr; cblkptr->cblktab[0].cblknbr = 0; cblkptr->cblktab[0].cblktab = NULL; cblkptr->cblktab[1].typeval = ORDERCBLKOTHR; cblkptr->cblktab[1].vnodnbr = vsplisttab[1].vnumnbr; cblkptr->cblktab[1].cblknbr = 0; cblkptr->cblktab[1].cblktab = NULL; if (vsplisttab[2].vnumnbr != 0) { /* If separator not empty */ cblkptr->cblknbr = 3; /* It is a three-cell tree node */ ordeptr->cblknbr += 2; /* Two more column blocks created */ ordeptr->treenbr += 3; /* Three more tree nodes created */ cblkptr->cblktab[2].typeval = ORDERCBLKOTHR; cblkptr->cblktab[2].vnodnbr = vsplisttab[2].vnumnbr; cblkptr->cblktab[2].cblknbr = 0; cblkptr->cblktab[2].cblktab = NULL; if (graphInduceList (&grafptr->s, &vsplisttab[2], &indgrafdat.s) != 0) { /* Perform non-halo induction for separator, as it will get highest numbers */ errorPrint ("hgraphOrderNd: cannot build induced subgraph (1)"); memFree (vspgrafdat.frontab); /* Free remaining space */ return (1); } indgrafdat.vnohnbr = indgrafdat.s.vertnbr; /* Fill halo graph structure of non-halo graph */ indgrafdat.vnohnnd = indgrafdat.s.vertnnd; indgrafdat.vnhdtax = indgrafdat.s.vendtax; indgrafdat.vnlosum = indgrafdat.s.velosum; indgrafdat.enohnbr = indgrafdat.s.edgenbr; indgrafdat.enohsum = indgrafdat.s.edlosum; indgrafdat.levlnum = grafptr->levlnum; /* Separator graph is at level of original graph */ o = hgraphOrderSt (&indgrafdat, ordeptr, ordenum + vsplisttab[0].vnumnbr + vsplisttab[1].vnumnbr, cblkptr->cblktab + 2, paraptr->ordstratsep); hgraphExit (&indgrafdat); } else { /* Separator is empty */ cblkptr->cblknbr = 2; /* It is a two-cell tree node */ ordeptr->cblknbr ++; /* One more column block created */ ordeptr->treenbr += 2; /* Two more tree nodes created */ o = 0; /* No separator ordering computed */ } if (o == 0) { if ((hgraphInduceList (grafptr, &vsplisttab[0], vsplisttab[2].vnumnbr + grafptr->s.vertnbr - grafptr->vnohnbr, &indgrafdat)) != 0) { errorPrint ("hgraphOrderNd: cannot build induced subgraph (2)"); memFree (vspgrafdat.frontab); /* Free remaining space */ return (1); } o = hgraphOrderNd (&indgrafdat, ordeptr, ordenum, cblkptr->cblktab, paraptr); hgraphExit (&indgrafdat); } if (o == 0) { if ((hgraphInduceList (grafptr, &vsplisttab[1], vsplisttab[2].vnumnbr + grafptr->s.vertnbr - grafptr->vnohnbr, &indgrafdat)) != 0) { errorPrint ("hgraphOrderNd: cannot build induced subgraph (3)"); memFree (vspgrafdat.frontab); /* Free remaining space */ return (1); } o = hgraphOrderNd (&indgrafdat, ordeptr, ordenum + vsplisttab[0].vnumnbr, cblkptr->cblktab + 1, paraptr); hgraphExit (&indgrafdat); } memFree (vspgrafdat.frontab); /* Free remaining space */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_io_load.c0000644000175300017530000001001611631334325023754 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_io_load.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the distri- **/ /** buted source graph loading routine of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 13 may 2007 **/ /** to 13 may 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "graph.h" #include "dgraph.h" #include "scotch.h" /****************************************/ /* */ /* These routines are the C API for the */ /* distributed graph handling routines. */ /* */ /****************************************/ /*+ This routine loads the given opaque graph *** structure with the data of the given stream. *** The base value allows the user to set the *** graph base to 0 or 1, or to the base value *** of the stream if the base value is equal *** to -1. On input, vertex loads are discarded if *** flagval is 1, edge loads are discarded if flagval *** is 2, and both if flagval is set to 3. *** It returns: *** - 0 : if the loading succeeded. *** - !0 : on error. +*/ int SCOTCH_dgraphLoad ( SCOTCH_Dgraph * const grafptr, FILE * const stream, const SCOTCH_Num baseval, const SCOTCH_Num flagval) { GraphFlag srcgrafflag; /* Graph flags */ if ((baseval < -1) || (baseval > 1)) { errorPrint ("SCOTCH_dgraphLoad: invalid base parameter"); return (1); } if ((flagval < 0) || (flagval > 3)) { errorPrint ("SCOTCH_dgraphLoad: invalid flag parameter"); return (1); } srcgrafflag = (((flagval & 1) != 0) ? GRAPHIONOLOADVERT : 0) + (((flagval & 2) != 0) ? GRAPHIONOLOADEDGE : 0); return (dgraphLoad ((Dgraph * const) grafptr, stream, (Gnum) baseval, srcgrafflag)); } scotch-5.1.12b.dfsg/src/libscotch/bdgraph_bipart_bd.c0000644000175300017530000005276611631334325022734 0ustar hazelscthazelsct/* Copyright 2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_bipart_bd.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module computes a bipartition of **/ /** the given distributed separator graph **/ /** by creating a band graph of given witdh **/ /** around the current frontier, computing **/ /** an improved bipartition of the band **/ /** graph, and projecting back the obtained **/ /** frontier to the original graph. **/ /** **/ /** DATES : # Version 5.1 : from : 11 nov 2007 **/ /** to : 14 apr 2011 **/ /** **/ /** NOTES : # Since only edges from local vertices **/ /** to local anchors are created in **/ /** dgraphBand(), the communication const **/ /** might be wrong if a local vertex of **/ /** the last layer is linked to a remote **/ /** vertex of different part which was **/ /** not in the band graph. Hence, commun- **/ /** ication costs have to be recomputed **/ /** from scratch. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BDGRAPH_BIPART_BD #include "module.h" #include "common.h" #include "parser.h" #include "arch.h" #include "dgraph.h" #include "dgraph_halo.h" #include "bdgraph.h" #include "bdgraph_bipart_bd.h" #include "bdgraph_bipart_st.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine computes a distributed band graph ** of given width around the current frontier and ** applies distributed bipartitioning routines to it. ** The distributed graph is not guaranteed to be ** balanced at at all. ** It returns: ** - 0 : if the distributed band graph could be computed. ** - !0 : on error. */ int bdgraphBipartBd ( Bdgraph * const orggrafptr, /*+ Distributed graph +*/ const BdgraphBipartBdParam * const paraptr) /*+ Method parameters +*/ { Bdgraph bndgrafdat; /* Bipartitioning band graph structure */ Gnum bndvertancnnd; /* End of local vertex array, without anchors */ Gnum bndvertlocnbr1; /* Number of band graph vertices in part 1 except anchor 1 */ Gnum bndvertlocnum; Gnum bndvertlvlnum; /* Based number of first band vertex in last layer */ Gnum bndvertlocancadj; /* Flag set when anchor(s) represent unexistent vertices */ Gnum bndvertglbancadj; /* Global adjustment of anchor vertices */ Gnum bndveexlocsum; /* Local sum of veexloctax array cells for band graph */ Gnum bndveexlocsum0; /* Local sum of veexloctax array cells in part 0 for band graph */ Gnum bndedlolocval; Gnum bndfronlocnum; Gnum orgfronlocnum; int * restrict orgflagloctab; Gnum orgvertlocnum; Gnum orgedlolocval; const int * restrict orgprocsidtab; int orgprocsidnbr; int orgprocsidnum; int orgprocsidval; Gnum complocsizeadj0; Gnum commlocloadintn; Gnum commlocloadintn2; /* Twice twice (4 times) the internal communication load of last layer */ Gnum commlocloadextn; Gnum commlocgainextn; Gnum reduloctab[7]; Gnum reduglbtab[7]; DgraphHaloRequest requdat; if (orggrafptr->fronglbnbr == 0) /* If no separator vertices, apply strategy to full (original) graph */ return (bdgraphBipartSt (orggrafptr, paraptr->stratorg)); if (dgraphBand (&orggrafptr->s, orggrafptr->fronlocnbr, orggrafptr->fronloctab, orggrafptr->partgsttax, orggrafptr->complocload0, orggrafptr->s.velolocsum - orggrafptr->complocload0, paraptr->distmax, &bndgrafdat.s, &bndgrafdat.fronloctab, &bndgrafdat.partgsttax, &bndvertlvlnum, &bndvertlocnbr1, &bndvertlocancadj) != 0) { errorPrint ("bdgraphBipartBd: cannot create band graph"); return (1); } bndvertancnnd = bndgrafdat.s.vertlocnnd - 2; reduloctab[0] = 0; /* Assume no memory allocation problem */ bndveexlocsum = bndveexlocsum0 = 0; bndgrafdat.veexloctax = NULL; /* Assume no external gains */ if (orggrafptr->veexloctax != NULL) { if ((bndgrafdat.veexloctax = memAlloc (bndgrafdat.s.vertlocnbr * sizeof (Gnum))) == NULL) { errorPrint ("bdgraphBipartBd: out of memory (1)"); reduloctab[0] = 1; /* Memory error */ } else { Gnum bndvertlocnum; bndgrafdat.veexloctax -= bndgrafdat.s.baseval; for (bndvertlocnum = bndgrafdat.s.baseval; bndvertlocnum < bndvertancnnd; bndvertlocnum ++) { Gnum veexval; veexval = orggrafptr->veexloctax[bndgrafdat.s.vnumloctax[bndvertlocnum]]; bndgrafdat.veexloctax[bndvertlocnum] = veexval; bndveexlocsum += veexval; bndveexlocsum0 += veexval & (((Gnum) bndgrafdat.partgsttax[bndvertlocnum]) - 1); } } } reduloctab[1] = bndgrafdat.s.vendloctax[bndvertancnnd] - bndgrafdat.s.vertloctax[bndvertancnnd] - (orggrafptr->s.procglbnbr - 1); /* Anchor degrees */ reduloctab[2] = bndgrafdat.s.vendloctax[bndvertancnnd + 1] - bndgrafdat.s.vertloctax[bndvertancnnd + 1] - (orggrafptr->s.procglbnbr - 1); bndgrafdat.complocsize0 = bndgrafdat.s.vertlocnbr - (bndvertlocnbr1 + 1); /* Add 1 for anchor vertex 1 */ complocsizeadj0 = orggrafptr->complocsize0 - bndgrafdat.complocsize0; /* -1 less because of anchor 0 */ reduloctab[3] = bndgrafdat.complocsize0; reduloctab[4] = bndvertlocancadj; /* Sum increases in size and load */ reduloctab[5] = bndveexlocsum; reduloctab[6] = bndveexlocsum0; if (MPI_Allreduce (reduloctab, reduglbtab, 7, GNUM_MPI, MPI_SUM, orggrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartBd: communication error (1)"); return (1); } if (reduglbtab[0] != 0) { bdgraphExit (&bndgrafdat); return (1); } if ((reduglbtab[1] == 0) || /* If graph is too small to have any usable anchors */ (reduglbtab[2] == 0)) { bdgraphExit (&bndgrafdat); return (bdgraphBipartSt (orggrafptr, paraptr->stratorg)); } bndvertglbancadj = reduglbtab[4]; bndgrafdat.veexglbsum = orggrafptr->veexglbsum; /* All external gains preserved */ bndgrafdat.fronlocnbr = orggrafptr->fronlocnbr; /* All separator vertices are kept in band graph */ bndgrafdat.fronglbnbr = orggrafptr->fronglbnbr; bndgrafdat.complocload0 = orggrafptr->complocload0 + bndvertlocancadj; /* All loads are kept in band graph */ bndgrafdat.compglbload0 = orggrafptr->compglbload0 + bndvertglbancadj; bndgrafdat.compglbload0min = orggrafptr->compglbload0min + bndvertglbancadj; /* Tilt extrema loads according to adjustments */ bndgrafdat.compglbload0max = orggrafptr->compglbload0max + bndvertglbancadj; bndgrafdat.compglbload0avg = orggrafptr->compglbload0avg + bndvertglbancadj; /* Tilt average load according to adjustments */ bndgrafdat.compglbload0dlt = orggrafptr->compglbload0dlt; bndgrafdat.compglbsize0 = reduglbtab[3]; bndgrafdat.commglbload = orggrafptr->commglbload; bndgrafdat.commglbgainextn = orggrafptr->commglbgainextn; bndgrafdat.commglbloadextn0 = orggrafptr->commglbloadextn0; bndgrafdat.commglbgainextn0 = orggrafptr->commglbgainextn0; bndgrafdat.domdist = orggrafptr->domdist; bndgrafdat.domwght[0] = orggrafptr->domwght[0]; bndgrafdat.domwght[1] = orggrafptr->domwght[1]; bndgrafdat.levlnum = orggrafptr->levlnum; if (bndgrafdat.veexloctax != NULL) { Gnum bndveexglbanc0; Gnum bndveexglbanc1; bndveexglbanc0 = (orggrafptr->veexglbsum + orggrafptr->commglbgainextn) / 2 - reduglbtab[6]; /* Compute global external gains of anchors */ bndveexglbanc1 = (orggrafptr->veexglbsum - bndveexglbanc0) - reduglbtab[5]; bndgrafdat.veexloctax[bndvertancnnd] = DATASIZE (bndveexglbanc0, bndgrafdat.s.procglbnbr, bndgrafdat.s.proclocnum); /* Spread gains across local anchors */ bndgrafdat.veexloctax[bndvertancnnd + 1] = DATASIZE (bndveexglbanc1, bndgrafdat.s.procglbnbr, bndgrafdat.s.proclocnum); } #ifdef SCOTCH_DEBUG_BDGRAPH2 if (bdgraphCheck (&bndgrafdat) != 0) { errorPrint ("bdgraphBipartBd: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ if (bdgraphBipartSt (&bndgrafdat, paraptr->stratbnd) != 0) { /* Separate distributed band graph */ errorPrint ("bdgraphBipartBd: cannot separate band graph"); bdgraphExit (&bndgrafdat); return (1); } reduloctab[0] = (Gnum) bndgrafdat.partgsttax[bndvertancnnd]; /* Check if anchor vertices remain in their parts */ reduloctab[1] = (Gnum) bndgrafdat.partgsttax[bndvertancnnd + 1]; reduloctab[2] = complocsizeadj0; reduloctab[3] = 0; /* Assume memory allocation is all right */ if ((orgflagloctab = memAlloc (flagSize (orggrafptr->s.vertlocnnd) * sizeof (int))) == NULL) { /* Eventually keep space for based indices */ errorPrint ("bdgraphBipartBd: out of memory (2)"); reduloctab[3] = 1; } if (MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 4, GNUM_MPI, MPI_SUM, orggrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartBd: communication error (2)"); return (1); } if (((reduglbtab[0] + reduglbtab[1]) != orggrafptr->s.procglbnbr) || /* If not all anchors of initial same parts in same parts */ ((reduglbtab[0] != 0) && (reduglbtab[0] != orggrafptr->s.procglbnbr)) || (reduglbtab[3] != 0)) { if (orgflagloctab != NULL) memFree (orgflagloctab); bdgraphExit (&bndgrafdat); /* Apply original strategy to full graph */ return (bdgraphBipartSt (orggrafptr, paraptr->stratorg)); } if (dgraphGhst (&bndgrafdat.s) != 0) { /* Compute ghost edge array if not already present */ errorPrint ("bdgraphBipartBd: cannot compute ghost edge array"); return (1); } if (reduglbtab[0] == orggrafptr->s.procglbnbr) { /* If all anchors swapped parts, swap all parts of original vertices */ Gnum orgvertnum; orggrafptr->complocsize0 = orggrafptr->s.vertlocnbr - reduloctab[2] - bndgrafdat.s.vertlocnbr + bndgrafdat.complocsize0; orggrafptr->compglbsize0 = orggrafptr->s.vertglbnbr - reduglbtab[2] - bndgrafdat.s.vertglbnbr + bndgrafdat.compglbsize0; for (orgvertnum = orggrafptr->s.baseval; orgvertnum < orggrafptr->s.vertlocnnd; orgvertnum ++) orggrafptr->partgsttax[orgvertnum] ^= 1; } else { orggrafptr->complocsize0 = reduloctab[2] + bndgrafdat.complocsize0; orggrafptr->compglbsize0 = reduglbtab[2] + bndgrafdat.compglbsize0; } for (bndvertlocnum = bndgrafdat.s.baseval; bndvertlocnum < bndvertancnnd; bndvertlocnum ++) /* Update part array of all vertices except anchors */ orggrafptr->partgsttax[bndgrafdat.s.vnumloctax[bndvertlocnum]] = bndgrafdat.partgsttax[bndvertlocnum]; dgraphHaloAsync (&orggrafptr->s, (byte *) (orggrafptr->partgsttax + orggrafptr->s.baseval), GRAPHPART_MPI, &requdat); /* Share part array of full graph */ commlocloadintn = commlocloadextn = commlocgainextn = 0; bndedlolocval = 1; /* Assume no edge loads */ for (bndvertlocnum = bndgrafdat.s.baseval; bndvertlocnum < bndvertlvlnum; bndvertlocnum ++) { /* For all vertices of band graph save for last layer */ Gnum bndedgelocnum; Gnum bndedgelocnnd; Gnum bndpartval; bndpartval = (Gnum) bndgrafdat.partgsttax[bndvertlocnum]; if (bndgrafdat.veexloctax != NULL) { commlocloadextn += bndgrafdat.veexloctax[bndvertlocnum] * bndpartval; commlocgainextn += bndgrafdat.veexloctax[bndvertlocnum] * (1 - bndpartval * 2); } for (bndedgelocnum = bndgrafdat.s.vertloctax[bndvertlocnum], bndedgelocnnd = bndgrafdat.s.vendloctax[bndvertlocnum]; bndedgelocnum < bndedgelocnnd; bndedgelocnum ++) { Gnum bndvertlocend; Gnum bndpartend; bndvertlocend = bndgrafdat.s.edgegsttax[bndedgelocnum]; bndpartend = bndgrafdat.partgsttax[bndvertlocend]; if (bndgrafdat.s.edloloctax != NULL) bndedlolocval = bndgrafdat.s.edloloctax[bndedgelocnum]; commlocloadintn += (bndpartval ^ bndpartend) * bndedlolocval; /* Internal load is accounted for twice */ } } for ( ; bndvertlocnum < bndvertancnnd; bndvertlocnum ++) { /* For all vertices of last layer, remove internal loads to band vertices once */ Gnum bndedgelocnum; Gnum bndedgelocnnd; Gnum bndpartval; bndpartval = (Gnum) bndgrafdat.partgsttax[bndvertlocnum]; if (bndgrafdat.veexloctax != NULL) { commlocloadextn += bndgrafdat.veexloctax[bndvertlocnum] * bndpartval; commlocgainextn += bndgrafdat.veexloctax[bndvertlocnum] * (1 - bndpartval * 2); } for (bndedgelocnum = bndgrafdat.s.vertloctax[bndvertlocnum], bndedgelocnnd = bndgrafdat.s.vendloctax[bndvertlocnum] - 1; /* "-1" to avoid anchor edges */ bndedgelocnum < bndedgelocnnd; bndedgelocnum ++) { Gnum bndvertlocend; Gnum bndpartend; bndvertlocend = bndgrafdat.s.edgegsttax[bndedgelocnum]; bndpartend = bndgrafdat.partgsttax[bndvertlocend]; if (bndgrafdat.s.edloloctax != NULL) bndedlolocval = bndgrafdat.s.edloloctax[bndedgelocnum]; commlocloadintn -= (bndpartval ^ bndpartend) * bndedlolocval; /* Remove internal loads to band graph vertices once because afterwards they will be accounted for twice */ } } memSet (orgflagloctab, 0, flagSize (orggrafptr->s.vertlocnnd) * sizeof (int)); /* Set vertices as not already considered */ for (bndfronlocnum = orgfronlocnum = 0; bndfronlocnum < bndgrafdat.fronlocnbr; bndfronlocnum ++) { /* Project back separator except for last layer */ Gnum bndvertlocnum; bndvertlocnum = bndgrafdat.fronloctab[bndfronlocnum]; if (bndvertlocnum < bndvertlvlnum) { /* If vertex does not belong to last layer */ Gnum orgvertlocnum; orgvertlocnum = bndgrafdat.s.vnumloctax[bndvertlocnum]; flagSet (orgflagloctab, orgvertlocnum); /* Set vertex as processed */ orggrafptr->fronloctab[orgfronlocnum ++] = orgvertlocnum; } } if (dgraphHaloWait (&requdat) != 0) { errorPrint ("bdgraphBipartBd: cannot complete asynchronous halo exchange"); return (1); } orgedlolocval = 1; /* Assume no edge loads */ commlocloadintn2 = 0; for (bndvertlocnum = bndvertlvlnum; bndvertlocnum < bndvertancnnd; bndvertlocnum ++) { /* For all vertices of last layer */ Gnum orgedgelocnum; Gnum orgedgelocnnd; Gnum orgvertlocnum; GraphPart orgpartval; Gnum orgflagval; orgvertlocnum = bndgrafdat.s.vnumloctax[bndvertlocnum]; orgpartval = bndgrafdat.partgsttax[bndvertlocnum]; orgflagval = 0; /* Assume vertex does not belong to the frontier */ for (orgedgelocnum = orggrafptr->s.vertloctax[orgvertlocnum], orgedgelocnnd = orggrafptr->s.vendloctax[orgvertlocnum]; orgedgelocnum < orgedgelocnnd; orgedgelocnum ++) { Gnum orgvertlocend; Gnum orgpartend; Gnum orgflagtmp; orgvertlocend = orggrafptr->s.edgegsttax[orgedgelocnum]; orgpartend = orggrafptr->partgsttax[orgvertlocend]; orgflagtmp = orgpartval ^ orgpartend; if (bndgrafdat.s.edloloctax != NULL) orgedlolocval = orggrafptr->s.edloloctax[orgedgelocnum]; orgflagval |= orgflagtmp; commlocloadintn2 += orgflagtmp * orgedlolocval; /* Internal load to band and original graph vertices are accounted for twice */ if ((orgflagtmp != 0) && (orgvertlocend < orggrafptr->s.vertlocnnd) && (flagVal (orgflagloctab, orgvertlocend) == 0)) { orggrafptr->fronloctab[orgfronlocnum ++] = orgvertlocend; flagSet (orgflagloctab, orgvertlocend); } } if ((orgflagval != 0) && (flagVal (orgflagloctab, orgvertlocnum) == 0)) orggrafptr->fronloctab[orgfronlocnum ++] = orgvertlocnum; flagSet (orgflagloctab, orgvertlocnum); /* Set vertex as processed anyway */ } commlocloadintn += 2 * commlocloadintn2; /* Add twice the internal load of original graph edges and once the one of band edges (one removed before) */ orggrafptr->complocload0 = bndgrafdat.complocload0 - bndvertlocancadj; orggrafptr->compglbload0 = bndgrafdat.compglbload0 - bndvertglbancadj; orggrafptr->compglbload0dlt = orggrafptr->compglbload0 - orggrafptr->compglbload0avg; orgprocsidnbr = orggrafptr->s.procsidnbr; if (orgprocsidnbr == 0) goto loop_exit; orgvertlocnum = orggrafptr->s.baseval; orgprocsidnum = 0; orgprocsidtab = orggrafptr->s.procsidtab; orgprocsidval = orgprocsidtab[orgprocsidnum ++]; while (1) { /* Scan all vertices which have foreign neighbors */ while (orgprocsidval < 0) { orgvertlocnum -= (Gnum) orgprocsidval; orgprocsidval = orgprocsidtab[orgprocsidnum ++]; } if (flagVal (orgflagloctab, orgvertlocnum) == 0) { /* If vertex not already processed */ Gnum orgedgelocnum; Gnum orgedgelocnnd; GraphPart orgpartval; orgpartval = orggrafptr->partgsttax[orgvertlocnum]; for (orgedgelocnum = orggrafptr->s.vertloctax[orgvertlocnum], orgedgelocnnd = orggrafptr->s.vendloctax[orgvertlocnum]; orgedgelocnum < orgedgelocnnd; orgedgelocnum ++) { if (orggrafptr->partgsttax[orggrafptr->s.edgegsttax[orgedgelocnum]] != orgpartval) { orggrafptr->fronloctab[orgfronlocnum ++] = orgvertlocnum; break; } } } do { if (orgprocsidnum >= orgprocsidnbr) goto loop_exit; } while ((orgprocsidval = orgprocsidtab[orgprocsidnum ++]) >= 0); } loop_exit : memFree (orgflagloctab); reduloctab[0] = commlocloadintn; /* Twice the internal load; sum globally before dividing by two */ reduloctab[1] = commlocloadextn; reduloctab[2] = commlocgainextn; reduloctab[3] = orgfronlocnum; if (MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 4, GNUM_MPI, MPI_SUM, orggrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartBd: communication error (3)"); return (1); } orggrafptr->fronlocnbr = orgfronlocnum; orggrafptr->fronglbnbr = reduglbtab[3]; orggrafptr->commglbload = (reduglbtab[0] / 2) * orggrafptr->domdist + reduglbtab[1]; orggrafptr->commglbgainextn = reduglbtab[2]; #ifdef SCOTCH_DEBUG_BDGRAPH2 if (bdgraphCheck (orggrafptr) != 0) { errorPrint ("bdgraphBipartBd: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ bdgraphExit (&bndgrafdat); return (0); } scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_bd.c0000644000175300017530000007427711631334325022571 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_bd.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module builds a band graph around **/ /** the frontier in order to decrease **/ /** problem size for the strategy to be **/ /** applied. **/ /** **/ /** DATES : # Version 5.0 : from : 27 nov 2006 **/ /** to : 23 dec 2007 **/ /** # Version 5.1 : from : 09 nov 2008 **/ /** to : 26 mar 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BGRAPH_BIPART_BD #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "arch.h" #include "bgraph.h" #include "bgraph_bipart_bd.h" #include "bgraph_bipart_st.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ int bgraphBipartBd ( Bgraph * restrict const orggrafptr, /*+ Active graph +*/ const BgraphBipartBdParam * const paraptr) /*+ Method parameters +*/ { BgraphBipartBdQueue queudat; /* Neighbor queue */ Gnum * restrict orgdisttax; /* Based access to distance array for original graph */ Gnum orgdistmax; /* Maximum distance allowed */ #define orgindxtax orgdisttax /* Recycle distance array as number indexing array */ Gnum orgfronnum; Gnum ancfronnum; Gnum bndfronnum; Bgraph bndgrafdat; /* Band graph structure */ Gnum bndvertnbr; /* Number of regular vertices in band graph (without anchors) */ Gnum bndvertnnd; Gnum * restrict bndvnumtax; /* Band vertex number array, recycling queudat.qtab */ Gnum * restrict bndveextax; /* External gain array of band graph, if present */ Gnum bndveexnbr; /* Number of external array vertices */ Gnum bndvelosum; /* Load of regular vertices in band graph */ Gnum bndedlosum; /* Sum of edge loads */ Gnum bndcompsize1; /* Number of regular vertices in part 1 of band graph */ Gnum bndcompload1; /* Load of regular vertices in part 1 */ Gnum bndvlvlnum; /* Index of first band graph vertex to belong to the last layer */ Gnum bndvertnum; Gnum bndeancnbr; /* Number of anchor edges */ Gnum bndedgenbr; /* Upper bound on the number of edges, including anchor edges */ Gnum bndedgenum; Gnum * restrict bndedgetax; Gnum * restrict bndedlotax; Gnum bndedgetmp; Gnum bnddegrmax; Gnum bndcommgainextn; /* Sum of all external gains in band graph */ Gnum bndcommgainextn1; /* Sum of external gains accounted for in load, since in part 1 */ size_t bndedlooftval; /* Offset of edge load array with respect to edge array */ const Gnum * restrict const orgverttax = orggrafptr->s.verttax; /* Fast accesses */ const Gnum * restrict const orgvendtax = orggrafptr->s.vendtax; const Gnum * restrict const orgvelotax = orggrafptr->s.velotax; const Gnum * restrict const orgedgetax = orggrafptr->s.edgetax; const Gnum * restrict const orgedlotax = orggrafptr->s.edlotax; if (orggrafptr->fronnbr == 0) /* If no separator vertices, apply strategy to full (original) graph */ return (bgraphBipartSt (orggrafptr, paraptr->stratorg)); orgdistmax = (Gnum) paraptr->distmax; if (orgdistmax < 1) /* To simplify algorithm, always at least one layer of vertices around separator */ orgdistmax = 1; if (memAllocGroup ((void **) (void *) &queudat.qtab, (size_t) (orggrafptr->s.vertnbr * sizeof (Gnum)), /* TRICK: no need of "+ 2" for anchor vertices (see below) */ &orgdisttax, (size_t) (orggrafptr->s.vertnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("bgraphBipartBd: out of memory (1)"); return (1); } memSet (orgdisttax, ~0, orggrafptr->s.vertnbr * sizeof (Gnum)); /* Initialize distance array */ orgdisttax -= orggrafptr->s.baseval; bgraphBipartBdQueueFlush (&queudat); /* Flush vertex queue */ bndedgenbr = 0; /* Guess upper bound on the number of edges */ bndvelosum = 0; bndcompsize1 = 0; bndcompload1 = 0; for (orgfronnum = 0; orgfronnum < orggrafptr->fronnbr; orgfronnum ++) { /* Enqueue frontier vertices */ Gnum orgvertnum; Gnum orgpartval; orgvertnum = orggrafptr->frontab[orgfronnum]; #ifdef SCOTCH_DEBUG_BGRAPH2 if ((orgvertnum < orggrafptr->s.baseval) || (orgvertnum >= orggrafptr->s.vertnnd)) { errorPrint ("bgraphBipartBd: internal error (1)"); memFree (queudat.qtab); /* Free group leader */ return (1); } if (orgdisttax[orgvertnum] != ~0) { errorPrint ("bgraphBipartBd: internal error (2)"); memFree (queudat.qtab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ orgpartval = orggrafptr->parttax[orgvertnum]; #ifdef SCOTCH_DEBUG_BGRAPH2 if ((orgpartval != 0) && (orgpartval != 1)) { errorPrint ("bgraphBipartBd: internal error (3)"); memFree (queudat.qtab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ bndcompsize1 += orgpartval; /* Count vertices in part 1 */ orgdisttax[orgvertnum] = 0; bgraphBipartBdQueuePut (&queudat, orgvertnum); if (orgvelotax != NULL) { Gnum orgveloval; orgveloval = orgvelotax[orgvertnum]; bndvelosum += orgveloval; bndcompload1 += orgveloval * orgpartval; } } do { /* Loop on vertices in queue */ Gnum orgvertnum; Gnum orgedgenum; Gnum orgdistval; orgvertnum = bgraphBipartBdQueueGet (&queudat); #ifdef SCOTCH_DEBUG_BGRAPH2 if ((orgvertnum < orggrafptr->s.baseval) || (orgvertnum >= orggrafptr->s.vertnnd)) { errorPrint ("bgraphBipartBd: internal error (4)"); memFree (queudat.qtab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ bndedgenbr += orgvendtax[orgvertnum] - orgverttax[orgvertnum]; /* Exact or upper bound on number of edges, including anchor edge(s) */ orgdistval = orgdisttax[orgvertnum]; /* Get vertex distance */ if (orgdistval >= orgdistmax) { /* If we belong to the farthest layer */ bndedgenbr ++; /* One more anchor edge, for the opposite */ continue; } orgdistval ++; /* Distance of neighbors */ for (orgedgenum = orgverttax[orgvertnum]; orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++) { Gnum orgvertend; orgvertend = orgedgetax[orgedgenum]; if (orgdisttax[orgvertend] == ~0) { /* If vertex not visited yet */ Gnum orgpartval; orgpartval = orggrafptr->parttax[orgvertend]; #ifdef SCOTCH_DEBUG_BGRAPH2 if ((orgpartval != 0) && (orgpartval != 1)) { errorPrint ("bgraphBipartBd: internal error (5)"); memFree (queudat.qtab); /* Free group leader */ return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ orgdisttax[orgvertend] = orgdistval; /* Enqueue vertex */ bgraphBipartBdQueuePut (&queudat, orgvertend); bndcompsize1 += orgpartval; /* Count vertices in part 1 */ if (orgvelotax != NULL) { Gnum orgveloval; orgveloval = orgvelotax[orgvertend]; bndvelosum += orgveloval; bndcompload1 += orgveloval * orgpartval; } } } } while (! bgraphBipartBdQueueEmpty (&queudat)); /* As long as queue is not empty */ bndvertnbr = queudat.head - queudat.qtab; /* Number of regular band graph vertices (withour anchors) is number of enqueued vertices */ if (orgvelotax == NULL) { bndvelosum = bndvertnbr; bndcompload1 = bndcompsize1; } if ((bndcompsize1 >= (orggrafptr->s.vertnbr - orggrafptr->compsize0)) || /* If either part has all of its vertices in band, use plain graph instead */ ((bndvertnbr - bndcompsize1) >= orggrafptr->compsize0)) { memFree (queudat.qtab); /* Free group leader */ return (bgraphBipartSt (orggrafptr, paraptr->stratorg)); } /* TRICK: since always at least one missing vertex per part, there is room for anchor vertices */ bndvertnnd = bndvertnbr + orggrafptr->s.baseval; bndvnumtax = queudat.qtab - orggrafptr->s.baseval; /* TRICK: re-use queue array as vertex number array since vertices taken in queue order */ for (bndvertnum = orggrafptr->s.baseval; bndvertnum < bndvertnnd; bndvertnum ++) { /* For vertices not belonging to last layer */ Gnum orgvertnum; orgvertnum = bndvnumtax[bndvertnum]; /* Get distance index of vertex */ if (orgindxtax[orgvertnum] >= paraptr->distmax) /* If vertex belongs to last layer */ break; orgindxtax[orgvertnum] = bndvertnum; } bndvlvlnum = bndvertnum; /* Get index of first vertex of last layer */ for ( ; bndvertnum < bndvertnnd; bndvertnum ++) /* For vertices belonging to last layer */ orgindxtax[bndvnumtax[bndvertnum]] = bndvertnum; bndvnumtax[bndvertnnd] = /* Anchor vertices do not have original vertex numbers */ bndvnumtax[bndvertnnd + 1] = -1; memSet (&bndgrafdat, 0, sizeof (Bgraph)); bndgrafdat.s.flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; /* All Bgraph arrays are non-freeable by bgraphExit() */ bndgrafdat.s.baseval = orggrafptr->s.baseval; bndgrafdat.s.vertnbr = bndvertnbr + 2; /* "+ 2" for anchor vertices */ bndgrafdat.s.vertnnd = bndvertnnd + 2; bndveexnbr = (orggrafptr->veextax != NULL) ? (bndvertnbr + 2) : 0; if (memAllocGroup ((void **) (void *) /* Do not allocate vnumtab but keep queudat.qtab instead */ &bndgrafdat.s.verttax, (size_t) ((bndvertnbr + 3) * sizeof (Gnum)), &bndgrafdat.s.velotax, (size_t) ((bndvertnbr + 2) * sizeof (Gnum)), &bndveextax, (size_t) (bndveexnbr * sizeof (Gnum)), &bndgrafdat.frontab, (size_t) ((bndvertnbr + 2) * sizeof (Gnum)), &bndgrafdat.parttax, (size_t) ((bndvertnbr + 2) * sizeof (GraphPart)), NULL) == NULL) { errorPrint ("bgraphBipartBd: out of memory (2)"); memFree (queudat.qtab); return (1); } bndgrafdat.parttax -= orggrafptr->s.baseval; /* Adjust base of arrays */ bndgrafdat.s.verttax -= orggrafptr->s.baseval; bndgrafdat.s.vendtax = bndgrafdat.s.verttax + 1; /* Band graph is compact */ bndgrafdat.s.velotax -= orggrafptr->s.baseval; bndgrafdat.s.vnumtax = bndvnumtax; /* Will not be freed as graph vertex arrays are said to be grouped */ bndgrafdat.s.velosum = orggrafptr->s.velosum; /* From now on we should free a Bgraph and not a Graph */ bndgrafdat.s.velotax[bndvertnnd] = orggrafptr->compload0 - (bndvelosum - bndcompload1); /* Set loads of anchor vertices */ bndgrafdat.s.velotax[bndvertnnd + 1] = orggrafptr->s.velosum - orggrafptr->compload0 - bndcompload1; if (bndveexnbr != 0) { bndveextax -= orggrafptr->s.baseval; bndgrafdat.veextax = bndveextax; } else bndveextax = NULL; if (memAllocGroup ((void **) (void *) &bndgrafdat.s.edgetax, (size_t) (bndedgenbr * sizeof (Gnum)), &bndgrafdat.s.edlotax, (size_t) (bndedgenbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("bgraphBipartBd: out of memory (3)"); bgraphExit (&bndgrafdat); memFree (queudat.qtab); return (1); } bndgrafdat.s.edgetax -= orggrafptr->s.baseval; bndgrafdat.s.edlotax -= orggrafptr->s.baseval; bndedgetax = bndgrafdat.s.edgetax; bndedlotax = bndgrafdat.s.edlotax; for (bndvertnum = bndedgenum = orggrafptr->s.baseval, bnddegrmax = bndedlosum = bndcommgainextn = bndcommgainextn1 = 0; bndvertnum < bndvlvlnum; bndvertnum ++) { /* Fill index array for vertices not belonging to last level */ Gnum orgvertnum; GraphPart orgpartval; Gnum orgedgenum; Gnum orgedloval; orgvertnum = bndvnumtax[bndvertnum]; orgpartval = orggrafptr->parttax[orgvertnum]; bndgrafdat.s.verttax[bndvertnum] = bndedgenum; bndgrafdat.s.velotax[bndvertnum] = (orgvelotax != NULL) ? orgvelotax[orgvertnum] : 1; bndgrafdat.parttax[bndvertnum] = orgpartval; if (bndveextax != NULL) { Gnum orgveexval; orgveexval = orggrafptr->veextax[orgvertnum]; bndveextax[bndvertnum] = orgveexval; bndcommgainextn += orgveexval; bndcommgainextn1 += orgveexval * (Gnum) orgpartval; } orgedloval = 1; /* Assume unity edge loads if not present */ for (orgedgenum = orgverttax[orgvertnum]; /* All edges of first levels are kept */ orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++, bndedgenum ++) { #ifdef SCOTCH_DEBUG_BGRAPH2 if ((bndedgenum >= (bndedgenbr + orggrafptr->s.baseval)) || (orgindxtax[orgedgetax[orgedgenum]] < 0)) { errorPrint ("bgraphBipartBd: internal error (6)"); bgraphExit (&bndgrafdat); memFree (queudat.qtab); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ if (orgedlotax != NULL) orgedloval = orgedlotax[orgedgenum]; bndedlosum += orgedloval; bndedgetax[bndedgenum] = orgindxtax[orgedgetax[orgedgenum]]; bndedlotax[bndedgenum] = orgedloval; } if (bnddegrmax < (bndedgenum - bndgrafdat.s.verttax[bndvertnum])) bnddegrmax = (bndedgenum - bndgrafdat.s.verttax[bndvertnum]); } bndeancnbr = 0; for ( ; bndvertnum < bndvertnnd; bndvertnum ++) { /* Fill index array for vertices belonging to last level */ Gnum orgvertnum; Gnum orgedgenum; GraphPart orgpartval; Gnum bnddegrval; Gnum orgedloval; Gnum ancedloval; /* Accumulated edge load for anchor edge */ orgvertnum = bndvnumtax[bndvertnum]; orgpartval = orggrafptr->parttax[orgvertnum]; bndgrafdat.s.verttax[bndvertnum] = bndedgenum; bndgrafdat.s.velotax[bndvertnum] = (orgvelotax != NULL) ? orgvelotax[orgvertnum] : 1; bndgrafdat.parttax[bndvertnum] = orgpartval; /* Record part for vertices of last level */ if (bndveextax != NULL) { Gnum orgveexval; orgveexval = orggrafptr->veextax[orgvertnum]; bndveextax[bndvertnum] = orgveexval; bndcommgainextn += orgveexval; bndcommgainextn1 += orgveexval * (Gnum) orgpartval; } ancedloval = 0; orgedloval = 1; /* Assume unity edge loads if not present */ for (orgedgenum = orgverttax[orgvertnum]; /* Keep only band edges */ orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++) { Gnum bndvertend; #ifdef SCOTCH_DEBUG_BGRAPH2 if (bndedgenum >= (bndedgenbr + orggrafptr->s.baseval)) { errorPrint ("bgraphBipartBd: internal error (7)"); bgraphExit (&bndgrafdat); memFree (queudat.qtab); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ if (orgedlotax != NULL) orgedloval = orgedlotax[orgedgenum]; bndedlosum += orgedloval; /* Normal arcs are accounted for twice; anchor arcs only once */ bndvertend = orgindxtax[orgedgetax[orgedgenum]]; if (bndvertend != ~0) { bndedgetax[bndedgenum] = bndvertend; bndedlotax[bndedgenum ++] = orgedloval; } else ancedloval += orgedloval; /* Accumulate loads of edges linking to anchor vertex */ } bndedlosum += ancedloval; /* Account for anchor edges a second time */ if (ancedloval > 0) { /* If vertex is connected to rest of part */ bndedlotax[bndedgenum] = ancedloval; bndedgetax[bndedgenum ++] = bndvertnnd + (Gnum) orgpartval; /* Add anchor edge to proper anchor vertex */ bndeancnbr ++; } bnddegrval = bndedgenum - bndgrafdat.s.verttax[bndvertnum]; if (bnddegrmax < bnddegrval) bnddegrmax = bnddegrval; } bndgrafdat.parttax[bndvertnnd] = 0; /* Set parts of anchor vertices */ bndgrafdat.parttax[bndvertnnd + 1] = 1; bndgrafdat.s.edlosum = bndedlosum; bndgrafdat.s.verttax[bndvertnnd] = bndedgenum; /* Mark end of regular edge array and start of first anchor edge array */ bndedgetmp = bndedgenum + bndeancnbr; #ifdef SCOTCH_DEBUG_BGRAPH2 if ((bndedgetmp - 1) >= (bndedgenbr + orggrafptr->s.baseval)) { errorPrint ("bgraphBipartBd: internal error (8)"); bgraphExit (&bndgrafdat); memFree (queudat.qtab); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ bndgrafdat.s.edgenbr = bndedgetmp - orggrafptr->s.baseval; bndgrafdat.s.verttax[bndvertnnd + 2] = bndedgetmp; /* Mark end of edge array with anchor vertices */ for (bndvertnum = bndvlvlnum; bndvertnum < bndvertnnd; bndvertnum ++) { /* Fill anchor edge arrays */ Gnum orgvertnum; orgvertnum = bndvnumtax[bndvertnum]; if (bndgrafdat.s.verttax[bndvertnum + 1] > bndgrafdat.s.verttax[bndvertnum]) { /* If vertex is not isolated */ Gnum bndedgelst; /* Number of last edge */ Gnum bndvertend; bndedgelst = bndgrafdat.s.verttax[bndvertnum + 1] - 1; bndvertend = bndedgetax[bndedgelst]; /* Get last neighbor of its edge sub-array */ if (bndvertend >= bndvertnnd) { /* If it is an anchor */ Gnum bndedloval; bndedloval = bndedlotax[bndedgelst]; bndedlosum += bndedloval; if (bndvertend == bndvertnnd) { /* Add edge from proper anchor */ bndedgetax[bndedgenum] = bndvertnum; bndedlotax[bndedgenum ++] = bndedloval; } else { bndedgetax[-- bndedgetmp] = bndvertnum; bndedlotax[bndedgetmp] = bndedloval; } } } } bndgrafdat.s.verttax[bndvertnnd + 1] = bndedgenum; /* Mark end of edge array of first anchor and start of second */ #ifdef SCOTCH_DEBUG_BGRAPH2 if (bndedgenum != bndedgetmp) { errorPrint ("bgraphBipartBd: internal error (9)"); bgraphExit (&bndgrafdat); memFree (queudat.qtab); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ if ((bndedgenum == bndgrafdat.s.verttax[bndvertnnd]) || /* If any of the anchor edges is isolated */ (bndedgenum == bndgrafdat.s.verttax[bndvertnnd + 2])) { bgraphExit (&bndgrafdat); /* Free all band graph related data */ memFree (queudat.qtab); return (bgraphBipartSt (orggrafptr, paraptr->stratorg)); /* Work on original graph */ } if (bnddegrmax < (bndgrafdat.s.verttax[bndvertnnd + 1] - bndgrafdat.s.verttax[bndvertnnd])) bnddegrmax = (bndgrafdat.s.verttax[bndvertnnd + 1] - bndgrafdat.s.verttax[bndvertnnd]); if (bnddegrmax < (bndgrafdat.s.verttax[bndvertnnd + 2] - bndgrafdat.s.verttax[bndvertnnd + 1])) bnddegrmax = (bndgrafdat.s.verttax[bndvertnnd + 2] - bndgrafdat.s.verttax[bndvertnnd + 1]); bndgrafdat.s.degrmax = bnddegrmax; bndedlooftval = bndedlotax - bndedgetax; bndgrafdat.s.edgetax = (Gnum *) memRealloc (bndedgetax + bndgrafdat.s.baseval, (bndedlooftval + bndgrafdat.s.edgenbr) * sizeof (Gnum)) - bndgrafdat.s.baseval; bndgrafdat.s.edlotax = bndgrafdat.s.edgetax + bndedlooftval; /* Use old index into old array as new index */ bndedgetax = bndgrafdat.s.edgetax; bndedlotax = bndgrafdat.s.edlotax; for (bndfronnum = 0, bndvertnum = orggrafptr->s.baseval; /* Fill band frontier array with first vertex indices as they make the separator */ bndfronnum < orggrafptr->fronnbr; bndfronnum ++, bndvertnum ++) bndgrafdat.frontab[bndfronnum] = bndvertnum; if (bndveextax != NULL) { Gnum bndcommloadintn; Gnum bndfronnnd; Gnum bndvertnum; Gnum bndedgenum; Gnum bndedloval; bndedloval = 1; /* Assume unity edge weights */ bndcommloadintn = 0; for (bndvertnum = orggrafptr->s.baseval, bndfronnnd = bndvertnum + orggrafptr->fronnbr; /* Compute communication load at frontier */ bndvertnum < bndfronnnd; bndvertnum ++) { Gnum bndpartval; bndpartval = (Gnum) bndgrafdat.parttax[bndvertnum]; if (bndpartval != 0) /* Process only frontier vertices in part 0 */ continue; for (bndedgenum = bndgrafdat.s.verttax[bndvertnum]; bndedgenum < bndgrafdat.s.vendtax[bndvertnum]; bndedgenum ++) { Gnum bndpartend; bndpartend = (Gnum) bndgrafdat.parttax[bndedgetax[bndedgenum]]; bndedloval = bndedlotax[bndedgenum]; bndcommloadintn += bndedloval * bndpartend; } } bndcommloadintn *= orggrafptr->domdist; bndveextax[bndvertnnd + 1] = (orggrafptr->commload - orggrafptr->commloadextn0 - bndcommloadintn) - bndcommgainextn1; bndveextax[bndvertnnd] = (orggrafptr->commload - orggrafptr->commloadextn0 - bndcommloadintn) - bndcommgainextn + bndcommgainextn1 + orggrafptr->commgainextn; } bndgrafdat.fronnbr = orggrafptr->fronnbr; bndgrafdat.compload0 = orggrafptr->compload0; bndgrafdat.compload0min = orggrafptr->compload0min; bndgrafdat.compload0max = orggrafptr->compload0max; bndgrafdat.compload0avg = orggrafptr->compload0avg; bndgrafdat.compload0dlt = orggrafptr->compload0dlt; bndgrafdat.compsize0 = bndvertnbr - bndcompsize1 + 1; /* "+ 1" for anchor vertex in part 0 */ bndgrafdat.commload = orggrafptr->commload; bndgrafdat.commloadextn0 = orggrafptr->commloadextn0; bndgrafdat.commgainextn = orggrafptr->commgainextn; bndgrafdat.commgainextn0 = orggrafptr->commgainextn0; bndgrafdat.domdist = orggrafptr->domdist; bndgrafdat.domwght[0] = orggrafptr->domwght[0]; bndgrafdat.domwght[1] = orggrafptr->domwght[1]; bndgrafdat.levlnum = orggrafptr->levlnum; bndgrafdat.bbalval = orggrafptr->bbalval; #ifdef SCOTCH_DEBUG_BGRAPH2 if ((graphCheck (&bndgrafdat.s) != 0) || /* Check band graph consistency */ (bgraphCheck (&bndgrafdat) != 0)) { errorPrint ("bgraphBipartBd: inconsistent band graph data"); bgraphExit (&bndgrafdat); memFree (queudat.qtab); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ if (bgraphBipartSt (&bndgrafdat, paraptr->stratbnd) != 0) { /* Apply strategy to band graph */ errorPrint ("bgraphBipartBd: cannot bipartition band graph"); bgraphExit (&bndgrafdat); memFree (queudat.qtab); return (1); } if (bndgrafdat.parttax[bndvertnnd] == /* If band graph was too small and anchors went to the same part, apply strategy on full graph */ bndgrafdat.parttax[bndvertnnd + 1]) { bgraphExit (&bndgrafdat); memFree (queudat.qtab); return (bgraphBipartSt (orggrafptr, paraptr->stratorg)); } orggrafptr->compload0 = bndgrafdat.compload0; orggrafptr->compload0dlt = bndgrafdat.compload0dlt; orggrafptr->commload = bndgrafdat.commload; orggrafptr->commgainextn = bndgrafdat.commgainextn; orggrafptr->bbalval = bndgrafdat.bbalval; if (bndgrafdat.parttax[bndvertnnd] != 0) { /* If anchors swapped parts, swap all parts of original vertices */ Gnum orgvertnum; orggrafptr->compsize0 = orggrafptr->s.vertnbr - orggrafptr->compsize0 - bndcompsize1 + bndgrafdat.compsize0 - 1; /* "- 1" for anchor 0 */ for (orgvertnum = orggrafptr->s.baseval; orgvertnum < orggrafptr->s.vertnnd; orgvertnum ++) orggrafptr->parttax[orgvertnum] ^= 1; } else orggrafptr->compsize0 = orggrafptr->compsize0 - (bndvertnbr - bndcompsize1) + bndgrafdat.compsize0 - 1; /* "- 1" for anchor 0 */ for (bndvertnum = bndgrafdat.s.baseval; bndvertnum < bndvertnnd; bndvertnum ++) /* Update part array of full graph */ orggrafptr->parttax[bndvnumtax[bndvertnum]] = bndgrafdat.parttax[bndvertnum]; for (bndfronnum = orgfronnum = ancfronnum = 0; /* Update frontier array of full graph */ bndfronnum < bndgrafdat.fronnbr; bndfronnum ++) { Gnum bndvertnum; Gnum orgvertnum; bndvertnum = bndgrafdat.frontab[bndfronnum]; orgvertnum = bndvnumtax[bndvertnum]; if (orgvertnum != -1) /* If frontier vertex is not an anchor vertex */ orggrafptr->frontab[orgfronnum ++] = orgvertnum; /* Record it as original frontier vertex */ else bndgrafdat.frontab[ancfronnum ++] = bndvertnum; /* Else record it for future processing */ } orgdistmax ++; /* Set flag to a value never used before */ while (ancfronnum > 0) { /* For all recorded frontier anchor vertices */ Gnum bndvertnum; /* Index of frontier anchor vertex in band graph */ GraphPart ancpartval; bndvertnum = bndgrafdat.frontab[-- ancfronnum]; ancpartval = bndgrafdat.parttax[bndvertnum]; for (bndedgenum = bndgrafdat.s.verttax[bndvertnum]; bndedgenum < bndgrafdat.s.vendtax[bndvertnum]; bndedgenum ++) { Gnum bndvertend; /* Index of neighbor of anchor vertex in band graph */ Gnum orgvertnum; /* Index of neighbor of anchor vertex in original graph */ Gnum orgedgenum; bndvertend = bndedgetax[bndedgenum]; if (bndgrafdat.parttax[bndvertend] == ancpartval) /* If neighbor is in same part as anchor, skip to next */ continue; orgvertnum = bndvnumtax[bndvertend]; for (orgedgenum = orgverttax[orgvertnum]; /* For all neighbors of neighbor */ orgedgenum < orgvendtax[orgvertnum]; orgedgenum ++) { Gnum orgvertend; orgvertend = orgedgetax[orgedgenum]; /* Get end vertex in original graph */ if (orgindxtax[orgvertend] == ~0) { /* If vertex never considered before */ #ifdef SCOTCH_DEBUG_BGRAPH2 if (orggrafptr->parttax[orgvertend] != ancpartval) { /* Original vertex should always be in same part as anchor */ errorPrint ("bgraphBipartBd: internal error (10)"); bgraphExit (&bndgrafdat); memFree (queudat.qtab); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ orggrafptr->frontab[orgfronnum ++] = orgvertend; /* Add vertex to frontier array */ orgindxtax[orgvertend] = orgdistmax; /* Flag vertex as already enqueued */ } } } } orggrafptr->fronnbr = orgfronnum; bgraphExit (&bndgrafdat); /* Free band graph structures */ memFree (queudat.qtab); #ifdef SCOTCH_DEBUG_BGRAPH2 if (bgraphCheck (orggrafptr) != 0) { errorPrint ("bgraphBipartBd: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_BGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/parser_yy.y0000644000175300017530000007174411631334325021357 0ustar hazelscthazelsct%{ /* Copyright 2004,2007,2008,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : parser_yy.y **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the syntactic parser **/ /** which processes strategy strings. **/ /** **/ /** DATES : # Version 3.1 : from : 07 nov 1995 **/ /** to 13 jun 1996 **/ /** # Version 3.2 : from : 24 sep 1996 **/ /** to 27 feb 1997 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 20 dec 2001 **/ /** to 11 jun 2004 **/ /** # Version 5.1 : from : 30 oct 2007 **/ /** to 24 jul 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define PARSER_YY #include "module.h" #include "common.h" #undef INTEGER /* In case someone defined them */ #undef DOUBLE #include "parser.h" #include "parser_ll.h" #include "parser_yy.h" /* #define SCOTCH_DEBUG_PARSER3 */ #ifdef SCOTCH_DEBUG_PARSER3 extern int yydebug; #define YYDEBUG 1 #endif /* SCOTCH_DEBUG_PARSER3 */ /* ** The static and global definitions. ** See also at the end of this file. */ static const StratTab * parserstrattab; /* Pointer to parsing tables */ static Strat * parserstratcurr = NULL; /* Pointer to current strategy node */ static StratParamTab * parserparamcurr = NULL; /* Pointer to current parameter */ extern unsigned int parsermethtokentab[]; /* Pre-definition for stupid compilers */ %} %union { char CASEVAL; /* Case value */ StratTest * TEST; /* Test type */ StratTestType TESTOP; /* Relational type */ double DOUBLE; /* Double-precision */ INT INTEGER; /* Integer */ char STRING[PARSERSTRINGLEN]; /* Character string */ struct { const StratTab * tabl; /* Current tables */ Strat * strat; /* Current method */ StratParamTab * param; /* Current parameter */ } SAVE; /* Parameter type */ Strat * STRAT; /* Strategy tree */ } %token METHODNAME %token PARAMNAME %token VALCASE VALDOUBLE VALINT VALSTRING %token VALSTRAT VALPARAM VALTEST %type TEST TESTOR TESTAND TESTNOT %type TESTREL TESTEXPR1 TESTEXPR2 TESTEXPR3 %type TESTEXPR4 TESTVAL TESTVAR %type TESTRELOP TESTEXPR1OP TESTEXPR2OP TESTEXPR3OP %type VALCASE %type VALDOUBLE VALSDOUBLE %type VALINT VALSINT %type VALSTRING %type STRATCONCAT STRATTEST STRATTESTELSE STRATEMPTY %type STRATGROUP STRATMETHOD STRATSELECT %type METHODNAME PARAMNAME %start STRAT %% /* ** These rules define the strategy grammar. */ STRAT : STRATSELECT { parserstratcurr = ($1); /* Save pointer to root of tree */ } ; STRATSELECT : STRATSELECT '|' STRATEMPTY { Strat * strat; if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { errorPrint ("stratParserParse: out of memory (2)"); stratExit ($1); stratExit ($3); YYABORT; } strat->tabl = parserstrattab; strat->type = STRATNODESELECT; strat->data.select.strat[0] = ($1); strat->data.select.strat[1] = ($3); ($$) = strat; } | STRATEMPTY ; STRATEMPTY : STRATCONCAT | { Strat * strat; if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { errorPrint ("stratParserParse: out of memory (3)"); YYABORT; } strat->tabl = parserstrattab; strat->type = STRATNODEEMPTY; ($$) = strat; } ; STRATCONCAT : STRATCONCAT STRATTEST { Strat * strat; if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { errorPrint ("stratParserParse: out of memory (4)"); stratExit ($1); stratExit ($2); YYABORT; } strat->tabl = parserstrattab; strat->type = STRATNODECONCAT; strat->data.concat.strat[0] = ($1); strat->data.concat.strat[1] = ($2); ($$) = strat; } | STRATTEST ; STRATTEST : { stratParserSelect (VALTEST); /* Parse parameter tokens */ } '/' TEST { stratParserSelect (VALSTRAT); /* Parse strategy tokens */ } '?' STRATSELECT STRATTESTELSE ';' { Strat * strat; if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { errorPrint ("stratParserParse: out of memory (1)"); stratExit ($6); if (($7) != NULL) stratExit ($7); stratTestExit ($3); YYABORT; } strat->tabl = parserstrattab; strat->type = STRATNODECOND; strat->data.cond.test = ($3); strat->data.cond.strat[0] = ($6); strat->data.cond.strat[1] = ($7); ($$) = strat; } | STRATGROUP ; STRATTESTELSE : ':' STRATSELECT { ($$) = ($2); } | { ($$) = NULL; } ; STRATGROUP : '(' STRATSELECT ')' { ($$) = ($2); } | STRATMETHOD ; STRATMETHOD : METHODNAME { Strat * strat; int meth; int methlen; StratMethodTab * methtab; int i, j; meth = methlen = 0; /* No method recognized yet */ methtab = parserstrattab->methtab; /* Point to the method table */ for (i = 0; methtab[i].name != NULL; i ++) { if ((strncasecmp (($1), /* Find longest matching code name */ methtab[i].name, j = strlen (methtab[i].name)) == 0) && (j > methlen)) { meth = methtab[i].meth; methlen = j; } } if (methlen == 0) { /* If method name not known */ errorPrint ("stratParserParse: invalid method name \"%s\", before \"%s\"", ($1), stratParserRemain ()); YYABORT; } if ((strat = (Strat *) memAlloc (sizeof (Strat))) == NULL) { errorPrint ("stratParserParse: out of memory (5)"); YYABORT; } strat->tabl = parserstrattab; strat->type = STRATNODEMETHOD; strat->data.method.meth = meth; /* Set method type */ if (methtab[meth].data != NULL) /* If default values exist */ memcpy (&strat->data.method.data, /* Set values to default */ methtab[meth].data, sizeof (StratNodeMethodData)); parserstratcurr = strat; /* Structure available for parameter processing */ } METHODPARAM { StratParamTab * paratab; int i; paratab = parserstrattab->paratab; /* Point to the parameter table */ for (i = 0; paratab[i].name != NULL; i ++) { if ((paratab[i].meth == parserstratcurr->data.method.meth) && /* If a strategy parameter found for this method */ (paratab[i].type == STRATPARAMSTRAT)) { if (*((Strat **) ((byte *) &parserstratcurr->data.method.data + /* And this parameter has not been set */ (paratab[i].dataofft - paratab[i].database))) == NULL) errorPrintW ("stratParserParse: strategy parameter \"%s\" of method \"%s\" not set, before \"%s\"", paratab[i].name, parserstrattab->methtab[parserstratcurr->data.method.meth].name, stratParserRemain ()); } } ($$) = parserstratcurr; /* Return current structure */ parserstratcurr = NULL; /* No current structure */ } ; METHODPARAM : { stratParserSelect (VALPARAM); /* Parse parameter tokens */ } '{' PARAMLIST { stratParserSelect (VALSTRAT); /* Parse strategy tokens */ } '}' | /* No parameters at all */ ; PARAMLIST : PARAMLIST ',' PARAMPARAM | PARAMPARAM ; PARAMPARAM : PARAMNAME { int para; int paralen; StratParamTab * paratab; int i, j; para = paralen = 0; /* No parameter recognized yet */ paratab = parserstrattab->paratab; /* Point to the parameter table */ for (i = 0; paratab[i].name != NULL; i ++) { if ((paratab[i].meth == parserstratcurr->data.method.meth) && (strncasecmp (($1), /* Find longest matching parameter name */ paratab[i].name, j = strlen (paratab[i].name)) == 0) && (j > paralen)) { para = i; paralen = j; } } if (paralen == 0) { errorPrint ("stratParserParse: invalid method parameter name \"%s\", before \"%s\"", ($1), stratParserRemain ()); YYABORT; } ($$).tabl = parserstrattab; /* Save current strategy tables */ parserparamcurr = ¶tab[para]; /* Save current parameter value */ stratParserSelect (parsermethtokentab[parserparamcurr->type]); if (parserparamcurr->type == STRATPARAMSTRAT) /* If parameter is a strategy */ parserstrattab = (StratTab *) parserparamcurr->datasltr; /* Use new strategy tables */ } '=' PARAMVAL { stratParserSelect (VALPARAM); /* Go-on reading parameters */ parserstrattab = ($2).tabl; /* Restore current strategy tables */ } ; PARAMVAL : VALCASE { char c; /* Character read */ char * p; /* Pointer to selector string */ int i; /* Index in selector string */ c = ($1); /* First, use char as is */ for (p = (char *) parserparamcurr->datasltr, i = 0; (*p != '\0') && (*p != c); p ++, i ++) ; if (*p == '\0') { /* Char was not found */ c = tolower (c); /* Convert char to lower case */ for (p = (char *) parserparamcurr->datasltr, i = 0; (*p != '\0') && (*p != c); p ++, i ++) ; if (*p == '\0') { errorPrint ("stratParserParse: invalid method parameter switch \"%s=%c\", before \"%s\"", parserparamcurr->name, ($1), stratParserRemain ()); YYABORT; } } #ifdef SCOTCH_DEBUG_PARSER2 if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (int)) > sizeof (StratNodeMethodData)) { errorPrint ("stratParserParse: internal error (1)"); YYABORT; } #endif /* SCOTCH_DEBUG_PARSER2 */ *((int *) ((byte *) &parserstratcurr->data.method.data + (parserparamcurr->dataofft - parserparamcurr->database))) = i; } | VALSDOUBLE { #ifdef SCOTCH_DEBUG_PARSER2 if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (double)) > sizeof (StratNodeMethodData)) { errorPrint ("stratParserParse: internal error (2)"); YYABORT; } #endif /* SCOTCH_DEBUG_PARSER2 */ *((double *) ((byte *) &parserstratcurr->data.method.data + (parserparamcurr->dataofft - parserparamcurr->database))) = ($1); } | VALSINT { #ifdef SCOTCH_DEBUG_PARSER2 if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (INT)) > sizeof (StratNodeMethodData)) { errorPrint ("stratParserParse: internal error (3)"); YYABORT; } #endif /* SCOTCH_DEBUG_PARSER2 */ *((INT *) ((byte *) &parserstratcurr->data.method.data + (parserparamcurr->dataofft - parserparamcurr->database))) = (INT) ($1); } | VALSTRING { #ifdef SCOTCH_DEBUG_PARSER2 if ((parserparamcurr->dataofft - parserparamcurr->database + strlen ($1) + 1) > sizeof (StratNodeMethodData)) { errorPrint ("stratParserParse: internal error (4)"); YYABORT; } #endif /* SCOTCH_DEBUG_PARSER2 */ strcpy ((char *) ((byte *) &parserstratcurr->data.method.data + (parserparamcurr->dataofft - parserparamcurr->database)), ($1)); } | { ($$).strat = parserstratcurr; ($$).param = parserparamcurr; parserstratcurr = NULL; parserparamcurr = NULL; } STRATSELECT { parserstratcurr = ($1).strat; /* Restore current method */ parserparamcurr = ($1).param; /* Restore current parameter */ #ifdef SCOTCH_DEBUG_PARSER2 if ((parserparamcurr->dataofft - parserparamcurr->database + sizeof (Strat *)) > sizeof (StratNodeMethodData)) { errorPrint ("stratParserParse: internal error (5)"); YYABORT; } #endif /* SCOTCH_DEBUG_PARSER2 */ *((Strat **) ((byte *) &parserstratcurr->data.method.data + (parserparamcurr->dataofft - parserparamcurr->database))) = ($2); } | error { errorPrint ("stratParserParse: invalid value for parameter \"%s\" of method \"%s\", before \"%s\"", parserparamcurr->name, parserstratcurr->tabl->methtab[parserstratcurr->data.method.meth].name, stratParserRemain ()); YYABORT; } ; TEST : TESTOR ; TESTOR : TESTOR '|' TESTAND { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (6)"); stratTestExit ($1); stratTestExit ($3); YYABORT; } test->typetest = STRATTESTOR; test->typenode = STRATPARAMLOG; test->data.test[0] = ($1); test->data.test[1] = ($3); ($$) = test; } | TESTAND ; TESTAND : TESTAND '&' TESTNOT { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (7)"); stratTestExit ($1); stratTestExit ($3); YYABORT; } test->typetest = STRATTESTAND; test->typenode = STRATPARAMLOG; test->data.test[0] = ($1); test->data.test[1] = ($3); ($$) = test; } | TESTNOT ; TESTNOT : '!' TESTNOT { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (8)"); stratTestExit ($2); YYABORT; } test->typetest = STRATTESTNOT; test->typenode = STRATPARAMLOG; test->data.test[0] = ($2); ($$) = test; } | '(' TESTOR ')' { ($$) = ($2); } | TESTREL ; TESTREL : TESTEXPR1 TESTRELOP TESTEXPR1 { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (9)"); stratTestExit ($1); stratTestExit ($3); YYABORT; } test->typetest = ($2); test->typenode = STRATPARAMLOG; test->data.test[0] = ($1); test->data.test[1] = ($3); ($$) = test; } ; TESTRELOP : '<' { ($$) = STRATTESTLT; } | '=' { ($$) = STRATTESTEQ; } | '>' { ($$) = STRATTESTGT; } ; TESTEXPR1 : TESTEXPR1 TESTEXPR1OP TESTEXPR2 { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (10)"); stratTestExit ($1); stratTestExit ($3); YYABORT; } test->typetest = ($2); test->data.test[0] = ($1); test->data.test[1] = ($3); ($$) = test; } | TESTEXPR2 ; TESTEXPR1OP : '+' { ($$) = STRATTESTADD; } | '-' { ($$) = STRATTESTSUB; } ; TESTEXPR2 : TESTEXPR2 TESTEXPR2OP TESTEXPR3 { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { stratTestExit ($1); stratTestExit ($3); errorPrint ("stratParserParse: out of memory (11)"); YYABORT; } test->typetest = ($2); test->data.test[0] = ($1); test->data.test[1] = ($3); ($$) = test; } | TESTEXPR3 ; TESTEXPR2OP : '*' { ($$) = STRATTESTMUL; } ; TESTEXPR3 : TESTEXPR3 TESTEXPR3OP TESTEXPR4 { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (12)"); stratTestExit ($1); stratTestExit ($3); YYABORT; } test->typetest = ($2); test->data.test[0] = ($1); test->data.test[1] = ($3); ($$) = test; } | TESTEXPR4 ; TESTEXPR3OP : '%' { ($$) = STRATTESTMOD; } ; TESTEXPR4 : '(' TESTEXPR1 ')' { ($$) = ($2); } | TESTVAL | TESTVAR ; TESTVAL : VALSDOUBLE { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (13)"); YYABORT; } test->typetest = STRATTESTVAL; test->typenode = STRATPARAMDOUBLE; test->data.val.valdbl = ($1); ($$) = test; } | VALSINT { StratTest * test; if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (14)"); YYABORT; } test->typetest = STRATTESTVAL; test->typenode = STRATPARAMINT; test->data.val.valint = ($1); ($$) = test; } ; TESTVAR : PARAMNAME { StratTest * test; StratParamTab * condtab; int para; int paralen; int i, j; para = paralen = 0; /* No parameter recognized yet */ condtab = parserstrattab->condtab; /* Point to parameter table */ for (i = 0; condtab[i].name != NULL; i ++) { if ((strncasecmp (($1), /* Find longest matching parameter name */ condtab[i].name, j = strlen (condtab[i].name)) == 0) && (j > paralen)) { para = i; paralen = j; } } if (paralen == 0) { errorPrint ("stratParserParse: invalid graph parameter name \"%s\", before \"%s\"", ($1), stratParserRemain ()); YYABORT; } if ((test = (StratTest *) memAlloc (sizeof (StratTest))) == NULL) { errorPrint ("stratParserParse: out of memory (15)"); YYABORT; } test->typetest = STRATTESTVAR; test->typenode = condtab[para].type; test->data.var.datatab = parserstrattab; test->data.var.datadisp = condtab[para].dataofft - condtab[para].database; ($$) = test; } ; VALSDOUBLE : TESTEXPR1OP VALDOUBLE { ($$) = (($1) == STRATTESTSUB) ? - ($2) : ($2); } | VALDOUBLE ; VALSINT : TESTEXPR1OP VALINT { ($$) = (($1) == STRATTESTSUB) ? - ($2) : ($2); } | VALINT ; %% /* ** The static and global definitions (bis). ** These are put at the end of the file because ** the token values that they use are not yet ** defined in the first section of the file. */ unsigned int parsermethtokentab[] = { /* Table for parameter/token type conversion */ VALCASE, VALDOUBLE, VALINT, -1, /* No logical parameters */ VALSTRAT, VALSTRING, -1 /* One more value to detect array overflow */ }; /************************************/ /* */ /* These routines drive the parser. */ /* */ /************************************/ /* This routine is the entry point for ** the strategy parser. ** It returns: ** - !NULL : pointer to the strategy. ** - NULL : on error. */ Strat * stratParserParse ( const StratTab * const strattab, /*+ Pointer to parsing tables +*/ const char * const string) /*+ Strategy string to parse +*/ { yyclearin; /* Reset the parser state */ #ifdef SCOTCH_DEBUG_PARSER3 yydebug = 1; /* Set debugging if needed */ #endif /* SCOTCH_DEBUG_PARSER3 */ stratParserInit (string); /* Initialize the lexical parser */ parserstrattab = strattab; /* Point to the parsing tables */ parserstratcurr = NULL; /* Clear up the temporary strategy pointer */ if (stratParserParse2 () != 0) { /* Parse the strategy string */ if (parserstratcurr != NULL) stratExit (parserstratcurr); return (NULL); } return (parserstratcurr); /* Return strategy pointer */ } /* This routine displays the parser error message. ** It returns: ** - 1 : in all cases. */ static int stratParserError ( const char * const errstr) { errorPrint ("stratParserParse: invalid strategy string, before \"%s\"", stratParserRemain ()); return (1); } scotch-5.1.12b.dfsg/src/libscotch/library_graph_coarsen.c0000644000175300017530000001062411631334325023641 0ustar hazelscthazelsct/* Copyright 2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_coarsen.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the graph **/ /** coarsening routine of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 5.1 : from : 07 aug 2011 **/ /** to 07 aug 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "graph.h" #include "graph_coarsen.h" #include "scotch.h" /*********************************/ /* */ /* This routine is the C API for */ /* the graph coarsening routine. */ /* */ /*********************************/ /*+ This routine creates a coarse graph from the *** given fine graph, unless the coarse graph is *** smaller than some threshold size or the *** coarsening ratio is above some other threshold. *** If the coarse graph is created, a coarse-to-fine *** vertex array is created, that contains a pair of *** fine indices for each coarse index. The contents *** of the Scotch internal array are copied to the *** array provided by the user. *** It returns: *** - 0 : if the graph has been coarsened. *** - 1 : if the graph could not be coarsened. *** - 2 : on error. +*/ int SCOTCH_graphCoarsen ( const SCOTCH_Graph * restrict const finegrafptr, /* Fine graph structure to fill */ SCOTCH_Graph * restrict const coargrafptr, /* Coarse graph */ SCOTCH_Num * restrict const coarmulttab, /* Pointer to multinode array */ const SCOTCH_Num coarnbr, /* Minimum number of coarse vertices */ const double coarrat) /* Maximum contraction ratio */ { GraphCoarsenMulti * restrict coarmultptr; int o; o = graphCoarsen ((const Graph * restrict const) finegrafptr, (Graph * restrict const) coargrafptr, &coarmultptr, coarnbr, coarrat, GRAPHCOARHEM); if (o == 0) { /* If coarsening succeeded */ SCOTCH_Num coarvertnbr; SCOTCH_graphSize (coargrafptr, &coarvertnbr, NULL); /* Get number of coarse vertices */ memCpy (coarmulttab, coarmultptr, coarvertnbr * 2 * sizeof (Gnum)); } return (o); } scotch-5.1.12b.dfsg/src/libscotch/bdgraph_bipart_zr.h0000644000175300017530000000530711631334325022774 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_bipart_zr.h **/ /** **/ /** AUTHOR : Jun-Ho HER **/ /** **/ /** FUNCTION : Part of a static mapper. **/ /** These lines are the data declarations **/ /** for the move-all-to-first-subdomain **/ /** distributed bipartitioning module. **/ /** **/ /** DATES : # Version 5.1 : from : 10 sep 2007 **/ /** to 26 oct 2007 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef BDGRAPH_BIPART_ZR #define static #endif int bdgraphBipartZr (Bdgraph * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/arch_torus.h0000644000175300017530000001705711631334325021467 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch_torus.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the tori graph target architecture **/ /** functions. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 12 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 30 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 17 aug 1995 **/ /** # Version 3.1 : from : 22 jul 1996 **/ /** to 23 jul 1996 **/ /** # Version 3.2 : from : 16 oct 1996 **/ /** to 14 may 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 05 nov 2003 **/ /** to 05 nov 2003 **/ /** # Version 5.1 : from : 21 jan 2008 **/ /** to 21 jan 2008 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ The 2D-torus definitions. +*/ typedef struct ArchTorus2_ { Anum c[2]; /*+ Mesh dimensions +*/ } ArchTorus2; typedef struct ArchTorus2Dom_ { Anum c[2][2]; /*+ Inclusive X and Y coordinates +*/ } ArchTorus2Dom; /*+ The 3D-torus definitions. +*/ typedef struct ArchTorus3_ { Anum c[3]; /*+ Mesh dimensions +*/ } ArchTorus3; typedef struct ArchTorus3Dom_ { Anum c[3][2]; /*+ Inclusive X, Y, and Z coordinates +*/ } ArchTorus3Dom; /* ** The function prototypes. */ #ifndef ARCH_TORUS #define static #endif int archTorus2ArchLoad (ArchTorus2 * restrict const, FILE * restrict const); int archTorus2ArchSave (const ArchTorus2 * const, FILE * restrict const); #define archTorus2ArchFree NULL ArchDomNum archTorus2DomNum (const ArchTorus2 * const, const ArchTorus2Dom * const); int archTorus2DomTerm (const ArchTorus2 * const, ArchTorus2Dom * restrict const, const ArchDomNum); Anum archTorus2DomSize (const ArchTorus2 * const, const ArchTorus2Dom * const); #define archTorus2DomWght archTorus2DomSize Anum archTorus2DomDist (const ArchTorus2 * const, const ArchTorus2Dom * const, const ArchTorus2Dom * const); int archTorus2DomFrst (const ArchTorus2 * const, ArchTorus2Dom * const); int archTorus2DomLoad (const ArchTorus2 * const, ArchTorus2Dom * const, FILE * restrict const); int archTorus2DomSave (const ArchTorus2 * const, const ArchTorus2Dom * const, FILE * restrict const); int archTorus2DomBipart (const ArchTorus2 * const, const ArchTorus2Dom * const, ArchTorus2Dom * restrict const, ArchTorus2Dom * restrict const); int archTorus2DomBipartO (const ArchTorus2 * const, const ArchTorus2Dom * const, ArchTorus2Dom * restrict const, ArchTorus2Dom * restrict const); int archTorus2DomBipartU (const ArchTorus2 * const, const ArchTorus2Dom * const, ArchTorus2Dom * restrict const, ArchTorus2Dom * restrict const); #ifdef SCOTCH_PTSCOTCH int archTorus2DomMpiType (const ArchTorus2 * const, MPI_Datatype * const); #endif /* SCOTCH_PTSCOTCH */ int archTorus3ArchLoad (ArchTorus3 * restrict const, FILE * restrict const); int archTorus3ArchSave (const ArchTorus3 * const, FILE * restrict const); #define archTorus3ArchFree NULL ArchDomNum archTorus3DomNum (const ArchTorus3 * const, const ArchTorus3Dom * const); int archTorus3DomTerm (const ArchTorus3 * const, ArchTorus3Dom * restrict const, const ArchDomNum); Anum archTorus3DomSize (const ArchTorus3 * const, const ArchTorus3Dom * const); #define archTorus3DomWght archTorus3DomSize Anum archTorus3DomDist (const ArchTorus3 * const, const ArchTorus3Dom * const, const ArchTorus3Dom * const); int archTorus3DomFrst (const ArchTorus3 * const, ArchTorus3Dom * const); int archTorus3DomLoad (const ArchTorus3 * const, ArchTorus3Dom * const, FILE * restrict const); int archTorus3DomSave (const ArchTorus3 * const, const ArchTorus3Dom * const, FILE * restrict const); int archTorus3DomBipart (const ArchTorus3 * const, const ArchTorus3Dom * const, ArchTorus3Dom * restrict const, ArchTorus3Dom * restrict const); #ifdef SCOTCH_PTSCOTCH int archTorus3DomMpiType (const ArchTorus3 * const, MPI_Datatype * const); #endif /* SCOTCH_PTSCOTCH */ #undef static scotch-5.1.12b.dfsg/src/libscotch/dorder_gather.c0000644000175300017530000005524411631334325022122 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dorder_gather.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles distributed **/ /** orderings. **/ /** **/ /** DATES : # Version 5.0 : from : 19 jul 2007 **/ /** to 10 sep 2007 **/ /** # Version 5.1 : from : 28 sep 2008 **/ /** to 28 sep 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DORDER #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_allreduce.h" #include "order.h" #include "dorder.h" #include "dorder_gather.h" /************************************/ /* */ /* These routines handle orderings. */ /* */ /************************************/ /* This function gathers the pieces of ** a distributed ordering to build a ** centralized ordering. ** It returns: ** - 0 : if ordering data are consistent. ** - !0 : on error. */ DGRAPHALLREDUCEMAXSUMOP (1, 1) int dorderGather ( const Dorder * restrict const dordptr, Order * restrict const cordptr) { Gnum leaflocnbr; int leafrcvnbr; DorderGatherLeaf * restrict leafrcvtab; int leafsndnbr; /* "int" since used as count in MPI_Gatherv */ DorderGatherLeaf * restrict leafsndtab; Gnum * restrict perircvtab; int perisndnbr; /* "int" since used as count in MPI_Gatherv */ Gnum * restrict perisndtab; int * restrict recvcnttab; int * restrict recvdsptab; const DorderLink * restrict linklocptr; Gnum vnodlocnbr; int procglbnbr; int protnum; Gnum reduloctab[2]; Gnum reduglbtab[2]; int cheklocval; int chekglbval; #ifdef SCOTCH_DEBUG_DORDER2 if ((DORDERCBLKNEDI == 0) || (DORDERCBLKNEDI != ORDERCBLKNEDI)) { errorPrint ("dorderGather: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ for (linklocptr = dordptr->linkdat.nextptr, leaflocnbr = vnodlocnbr = 0; /* For all nodes in local ordering structure */ linklocptr != &dordptr->linkdat; linklocptr = linklocptr->nextptr) { const DorderCblk * restrict cblklocptr; cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ if ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) { /* If node is leaf */ leaflocnbr ++; /* One more leaf fragment */ vnodlocnbr += cblklocptr->data.leaf.vnodlocnbr; /* And more node vertices */ } #ifdef SCOTCH_DEBUG_DORDER2 else if (cblklocptr->typeval != DORDERCBLKNEDI) { errorPrint ("dorderGather: invalid parameters"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ } MPI_Comm_size (dordptr->proccomm, &procglbnbr); if (cordptr != NULL) { Gnum vnodglbnbr; reduloctab[0] = (Gnum) dordptr->proclocnum; reduloctab[1] = 1; vnodglbnbr = 2 * procglbnbr; /* TRICK: use perircvtab array as gather array */ if (vnodglbnbr < (dordptr->vnodglbnbr - vnodlocnbr)) /* But should receive permutation indices too! */ vnodglbnbr = dordptr->vnodglbnbr - vnodlocnbr; /* TRICK: root will not receive from itself */ if (memAllocGroup ((void **) (void *) &recvcnttab, (size_t) (procglbnbr * sizeof (int)), &recvdsptab, (size_t) (procglbnbr * sizeof (int)), &perircvtab, (size_t) (vnodglbnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dorderGather: out of memory (1)"); reduloctab[0] = (Gnum) procglbnbr; /* Indicate memory error */ } } else { recvcnttab = NULL; /* Prepare possible freeing on error */ reduloctab[0] = reduloctab[1] = 0; } if (dgraphAllreduceMaxSum (reduloctab, reduglbtab, 1, 1, dordptr->proccomm) != 0) { errorPrint ("dorderGather: communication error (1)"); return (1); } if (reduglbtab[1] != 1) { errorPrint ("dorderGather: should have only one root"); reduglbtab[0] = (Gnum) procglbnbr; } if (reduglbtab[0] >= (Gnum) procglbnbr) { if (recvcnttab != NULL) memFree (recvcnttab); return (1); } protnum = (int) reduglbtab[0]; reduloctab[0] = leaflocnbr; reduloctab[1] = vnodlocnbr; if (MPI_Gather (reduloctab, 2, GNUM_MPI, perircvtab, 2, GNUM_MPI, protnum, dordptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderGather: communication error (2)"); return (1); } if (dordptr->proclocnum == protnum) { int procnum; perircvtab[2 * protnum] = 0; /* TRICK: root will not send to nor receive from itself to avoid unnecessary memory copy */ for (procnum = 0, leafrcvnbr = 0; procnum < procglbnbr; procnum ++) { recvdsptab[procnum] = leafrcvnbr; recvcnttab[procnum] = (int) (perircvtab[2 * procnum] * 2); /* TRICK: DorderGatherLeaf structures are made of 2 GNUM_MPI fields */ leafrcvnbr += recvcnttab[procnum]; } leafrcvnbr /= 2; /* TRICK: restore real number of leaf structures to be received */ leafsndnbr = 0; perisndnbr = 0; } else { leafrcvnbr = 0; leafsndnbr = (int) leaflocnbr; perisndnbr = (int) vnodlocnbr; } cheklocval = 0; if (memAllocGroup ((void **) (void *) &leafrcvtab, (size_t) (leafrcvnbr * sizeof (DorderGatherLeaf)), &leafsndtab, (size_t) (leafsndnbr * sizeof (DorderGatherLeaf)), &perisndtab, (size_t) (perisndnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dorderGather: out of memory (2)"); cheklocval = 1; } #ifdef SCOTCH_DEBUG_DORDER1 /* Communication cannot be merged with a useful one */ if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dordptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderGather: communication error (3)"); return (1); } #else /* SCOTCH_DEBUG_DORDER1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_DORDER1 */ if (chekglbval != 0) { if (recvcnttab != NULL) memFree (recvcnttab); return (1); } if (dordptr->proclocnum == protnum) { /* If root process */ #ifdef SCOTCH_DEBUG_DORDER2 memSet (cordptr->peritab, ~0, dordptr->vnodglbnbr * sizeof (Gnum)); #endif /* SCOTCH_DEBUG_DORDER2 */ for (linklocptr = dordptr->linkdat.nextptr; linklocptr != &dordptr->linkdat; linklocptr = linklocptr->nextptr) {; /* For all nodes */ const DorderCblk * restrict cblklocptr; cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ if ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) /* If tree node is leaf, copy fragment */ memCpy (cordptr->peritab + cblklocptr->data.leaf.ordelocval, cblklocptr->data.leaf.periloctab, cblklocptr->data.leaf.vnodlocnbr * sizeof (Gnum)); } } else { Gnum leaflocnum; Gnum vnodlocnum; for (linklocptr = dordptr->linkdat.nextptr, leaflocnum = vnodlocnum = 0; linklocptr != &dordptr->linkdat; linklocptr = linklocptr->nextptr) {; /* For all nodes */ const DorderCblk * restrict cblklocptr; cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ if ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) { /* If node is leaf */ leafsndtab[leaflocnum].ordelocval = cblklocptr->data.leaf.ordelocval; /* Fill send structures with permutation data */ leafsndtab[leaflocnum].vnodlocnbr = cblklocptr->data.leaf.vnodlocnbr; memCpy (perisndtab + vnodlocnum, cblklocptr->data.leaf.periloctab, cblklocptr->data.leaf.vnodlocnbr * sizeof (Gnum)); vnodlocnum += cblklocptr->data.leaf.vnodlocnbr; leaflocnum ++; } } leafsndnbr *= 2; /* TRICK: DorderGatherLeaf structures are made of 2 GNUM_MPI fields */ } if (MPI_Gatherv (leafsndtab, leafsndnbr, GNUM_MPI, leafrcvtab, recvcnttab, recvdsptab, GNUM_MPI, protnum, dordptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderGather: communication error (4)"); return (1); } if (dordptr->proclocnum == protnum) { int vnodglbnbr; int procnum; perircvtab[2 * protnum + 1] = 0; /* TRICK: root will not send to nor receive from itself to avoid unnecessary memory copy */ for (procnum = 0, vnodglbnbr = 0; procnum < procglbnbr; procnum ++) { recvdsptab[procnum] = vnodglbnbr; recvcnttab[procnum] = (int) perircvtab[2 * procnum + 1]; vnodglbnbr += recvcnttab[procnum]; } #ifdef SCOTCH_DEBUG_DORDER2 if (((Gnum) vnodglbnbr + vnodlocnbr) != dordptr->vnodglbnbr) { errorPrint ("dorderGather: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ } if (MPI_Gatherv (perisndtab, perisndnbr, GNUM_MPI, perircvtab, recvcnttab, recvdsptab, GNUM_MPI, protnum, dordptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderGather: communication error (5)"); return (1); } if (dordptr->proclocnum == protnum) { /* If root process */ int leafglbnum; int vnodglbnum; for (leafglbnum = vnodglbnum = 0; leafglbnum < leafrcvnbr; leafglbnum ++) { memCpy (cordptr->peritab + leafrcvtab[leafglbnum].ordelocval, perircvtab + vnodglbnum, leafrcvtab[leafglbnum].vnodlocnbr * sizeof (Gnum)); vnodglbnum += leafrcvtab[leafglbnum].vnodlocnbr; } memFree (recvcnttab); /* Free group leader */ } memFree (leafrcvtab); /* Free group leader */ if (dorderGatherTree (dordptr, cordptr, protnum) != 0) /* Gather ordering tree */ return (1); #ifdef SCOTCH_DEBUG_DORDER2 if (dordptr->proclocnum == protnum) { if (orderCheck (cordptr) != 0) { errorPrint ("dorderGather: invalid centralized ordering"); return (1); } } #endif /* SCOTCH_DEBUG_DORDER2 */ return (0); } /* This function gathers the pieces of ** a distributed ordering tree to build a ** centralized ordering tree. ** It returns: ** - 0 : if ordering data are consistent. ** - !0 : on error. */ int dorderGatherTree ( const Dorder * restrict const dordptr, Order * restrict const cordptr, const int protnum) { int treelocnbr; /* "int" since used as way to fill count array in MPI_Allgather */ Gnum treeglbnbr; DorderGatherNode * restrict treercvtab; int treesndnbr; /* "int" since used as count in MPI_Gatherv */ DorderGatherNode * treesndtab; DorderGatherNode * restrict treesndptr; int * restrict treecnttab; int * restrict treedsptab; DorderGatherCblk * restrict cblkglbtab; const DorderLink * restrict linklocptr; int procglbnbr; int procnum; int cheklocval; int chekglbval; for (linklocptr = dordptr->linkdat.nextptr, treelocnbr = 0; /* Count only purely local nodes */ linklocptr != &dordptr->linkdat; linklocptr = linklocptr->nextptr) { const DorderCblk * restrict cblklocptr; cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ #ifdef SCOTCH_DEBUG_DORDER2 if ((cblklocptr->cblknum.proclocnum != dordptr->proclocnum) && /* Local sub-nodes of non-locally rooted node not implemented */ ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) && (cblklocptr->data.leaf.nodelocnbr != 0)) { errorPrint ("dorderGatherTree: not implemented"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ if (cblklocptr->cblknum.proclocnum == dordptr->proclocnum) { treelocnbr ++; if ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) treelocnbr += (int) cblklocptr->data.leaf.nodelocnbr; } } MPI_Comm_size (dordptr->proccomm, &procglbnbr); treesndnbr = (dordptr->proclocnum == protnum) ? 0 : treelocnbr; /* TRICK: root will not send nor receive */ cheklocval = 0; if (memAllocGroup ((void **) (void *) &treecnttab, (size_t) (procglbnbr * sizeof (int)), &treedsptab, (size_t) (procglbnbr * sizeof (int)), &treesndtab, (size_t) (treesndnbr * sizeof (DorderGatherNode)), NULL) == NULL) { errorPrint ("dorderGatherTree: out of memory (1)"); cheklocval = 1; } #ifdef SCOTCH_DEBUG_DORDER1 /* Communication cannot be merged with a useful one */ if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dordptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderGatherTree: communication error (1)"); return (1); } #else /* SCOTCH_DEBUG_DORDER1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_DORDER1 */ if (chekglbval != 0) { if (treecnttab != NULL) memFree (treecnttab); return (1); } if (MPI_Allgather (&treelocnbr, 1, MPI_INT, treecnttab, 1, MPI_INT, dordptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderGatherTree: communication error (2)"); return (1); } for (procnum = 0, treeglbnbr = 0; procnum < procglbnbr; procnum ++) { /* Compute prefix sum of local numbers for global numbering */ treedsptab[procnum] = treeglbnbr; treeglbnbr += treecnttab[procnum]; } if (dordptr->proclocnum == protnum) { treecnttab[protnum] = 0; /* TRICK: root will not send to nor receive from itself to avoid unnecessary memory copy */ cordptr->treenbr = treeglbnbr; if (memAllocGroup ((void **) (void *) &treercvtab, (size_t) (treeglbnbr * sizeof (DorderGatherNode)), &cblkglbtab, (size_t) (treeglbnbr * sizeof (DorderGatherCblk)), NULL) == NULL) { errorPrint ("dorderGatherTree: out of memory (2)"); cheklocval = 1; } treesndptr = treercvtab + treedsptab[protnum]; /* TRICK: root process will build its column blocks in place as if received */ } else treesndptr = treesndtab; #ifdef SCOTCH_DEBUG_DORDER1 /* Communication cannot be merged with a useful one */ if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, dordptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderGather: communication error (3)"); return (1); } #else /* SCOTCH_DEBUG_DORDER1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_DORDER1 */ if (chekglbval != 0) { memFree (treecnttab); return (1); } for (linklocptr = dordptr->linkdat.nextptr; linklocptr != &dordptr->linkdat; linklocptr = linklocptr->nextptr) { /* For all nodes */ const DorderCblk * restrict cblklocptr; cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ if (cblklocptr->cblknum.proclocnum != dordptr->proclocnum) /* Skip non-local nodes */ continue; treesndptr->fathnum = treedsptab[cblklocptr->fathnum.proclocnum] + cblklocptr->fathnum.cblklocnum; /* If node is (part of) the root node */ treesndptr->typeval = (Gnum) (((cblklocptr->typeval & DORDERCBLKNEDI) != 0) ? ORDERCBLKNEDI : ORDERCBLKOTHR); treesndptr->vnodnbr = cblklocptr->vnodglbnbr; treesndptr->cblknum = cblklocptr->cblkfthnum; treesndptr ++; if ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) { /* If node is a distributed leaf */ Gnum cblkglbnum; Gnum cblkglbadj; const DorderNode * restrict nodelocptr; const DorderNode * restrict nodeloctnd; cblkglbnum = treedsptab[cblklocptr->cblknum.proclocnum] + cblklocptr->cblknum.cblklocnum; cblkglbadj = treedsptab[cblklocptr->cblknum.proclocnum] + cblklocptr->data.leaf.cblklocnum; for (nodelocptr = cblklocptr->data.leaf.nodeloctab, nodeloctnd = nodelocptr + cblklocptr->data.leaf.nodelocnbr; nodelocptr < nodeloctnd; nodelocptr ++) { /* Build nodes for all local nodes */ treesndptr->fathnum = (nodelocptr->fathnum == -1) ? cblkglbnum : (nodelocptr->fathnum + cblkglbadj); treesndptr->typeval = (Gnum) nodelocptr->typeval; treesndptr->vnodnbr = nodelocptr->vnodnbr; treesndptr->cblknum = nodelocptr->cblknum; treesndptr ++; } } #ifdef SCOTCH_DEBUG_DORDER2 else if (cblklocptr->typeval != DORDERCBLKNEDI) { errorPrint ("dorderGatherTree: invalid column block type"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ } #ifdef SCOTCH_DEBUG_DORDER2 if (treesndptr != ((dordptr->proclocnum == protnum) ? (treercvtab + treedsptab[protnum]) : treesndtab) + treelocnbr) { errorPrint ("dorderGatherTree: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ if (dordptr->proclocnum == protnum) { /* If node is root, adjust displacements in terms of Gnum and not DorderGatherNode */ for (procnum = 0; procnum < procglbnbr; procnum ++) { treecnttab[procnum] *= DORDERGATHERNODESIZE; treedsptab[procnum] *= DORDERGATHERNODESIZE; } } if (MPI_Gatherv (treesndtab, treesndnbr * DORDERGATHERNODESIZE, GNUM_MPI, treercvtab, treecnttab, treedsptab, GNUM_MPI, protnum, dordptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderGatherTree: communication error (4)"); return (1); } if (dordptr->proclocnum == protnum) { Gnum treeglbnum; Gnum cblkglbnbr; memSet (cblkglbtab, 0, treeglbnbr * sizeof (DorderGatherCblk)); /* Set all son counters to zero and all array pointers to NULL */ for (treeglbnum = 1; treeglbnum < treeglbnbr; treeglbnum ++) { /* For all local and received tree nodes except root node */ Gnum cblkfthnum; cblkfthnum = treercvtab[treeglbnum].fathnum; #ifdef SCOTCH_DEBUG_DORDER2 if ((cblkfthnum < 0) || /* Father of non-root node cannot be -1 */ (cblkfthnum >= treeglbnum)) { /* Father should always have smaller global node number */ errorPrint ("dorderGatherTree: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ cblkglbtab[cblkfthnum].cblknbr ++; /* Add a son to its father */ } for (treeglbnum = 0, cblkglbnbr = treeglbnbr; treeglbnum < treeglbnbr; treeglbnum ++) { /* For all local and received tree nodes */ if (cblkglbtab[treeglbnum].cblknbr > 0) { #ifdef SCOTCH_DEBUG_DORDER2 if (cblkglbtab[treeglbnum].cblknbr < 2) { /* Descendent nodes should comprise at least two column block slots */ errorPrint ("dorderGatherTree: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ cblkglbnbr --; /* One new subblock means one more shared frontier, so one less column block than nodes */ if ((cblkglbtab[treeglbnum].cblktab = memAlloc (cblkglbtab[treeglbnum].cblknbr * sizeof (OrderCblk))) == NULL) { errorPrint ("dorderGather: out of memory (3)"); while (-- treeglbnum >= 0) { if (cblkglbtab[treeglbnum].cblktab != NULL) memFree (cblkglbtab[treeglbnum].cblktab); } memFree (treercvtab); memFree (treecnttab); return (1); } } } cordptr->cblknbr = cblkglbnbr; cordptr->cblktre.typeval = (int) treercvtab[0].typeval; /* Process root node of separator tree */ cordptr->cblktre.vnodnbr = treercvtab[0].vnodnbr; cordptr->cblktre.cblknbr = cblkglbtab[0].cblknbr; cordptr->cblktre.cblktab = cblkglbtab[0].cblktab; /* Link its sons array */ for (treeglbnum = 1; treeglbnum < treeglbnbr; treeglbnum ++) { /* For all nodes except the root */ Gnum cblkfthnum; OrderCblk * restrict cblksonptr; cblkfthnum = treercvtab[treeglbnum].cblknum; #ifdef SCOTCH_DEBUG_DORDER2 if ((cblkfthnum < 0) || (cblkfthnum >= cblkglbtab[treercvtab[treeglbnum].fathnum].cblknbr)) { errorPrint ("dorderGatherTree: internal error (4)"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ cblksonptr = &cblkglbtab[treercvtab[treeglbnum].fathnum].cblktab[cblkfthnum]; /* Point to son's slot in father array */ cblksonptr->typeval = (int) treercvtab[treeglbnum].typeval; cblksonptr->vnodnbr = treercvtab[treeglbnum].vnodnbr; cblksonptr->cblknbr = cblkglbtab[treeglbnum].cblknbr; /* Link son column block array to column block structure */ cblksonptr->cblktab = cblkglbtab[treeglbnum].cblktab; } memFree (treercvtab); } memFree (treecnttab); return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_mesh_f.c0000644000175300017530000002255011631334325022270 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_mesh_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the source mesh handling routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 4.0 : from : 23 sep 2002 **/ /** to 13 dec 2005 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 15 apr 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the mesh handling routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFMESHINIT, scotchfmeshinit, ( \ SCOTCH_Mesh * const meshptr, \ int * const revaptr), \ (meshptr, revaptr)) { *revaptr = SCOTCH_meshInit (meshptr); } /* ** */ FORTRAN ( \ SCOTCHFMESHEXIT, scotchfmeshexit, ( \ SCOTCH_Mesh * const meshptr), \ (meshptr)) { SCOTCH_meshExit (meshptr); } /* When an input stream is built from the given ** file handle, it is set as unbuffered, so as to ** allow for multiple stream reads from the same ** file handle. If it were buffered, too many ** input characters would be read on the first ** block read. */ FORTRAN ( \ SCOTCHFMESHLOAD, scotchfmeshload, ( \ SCOTCH_Mesh * const meshptr, \ int * const fileptr, \ const SCOTCH_Num * const baseptr, \ int * const revaptr), \ (meshptr, fileptr, baseptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFMESHLOAD: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFMESHLOAD: cannot open input stream"); close (filenum); *revaptr = 1; return; } setbuf (stream, NULL); /* Do not buffer on input */ o = SCOTCH_meshLoad (meshptr, stream, *baseptr); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFMESHSAVE, scotchfmeshsave, ( \ const SCOTCH_Mesh * const meshptr, \ int * const fileptr, \ int * const revaptr), \ (meshptr, fileptr, revaptr)) { FILE * stream; /* Stream to build from handle */ int filenum; /* Duplicated handle */ int o; if ((filenum = dup (*fileptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFMESHSAVE: cannot duplicate handle"); *revaptr = 1; /* Indicate error */ return; } if ((stream = fdopen (filenum, "w")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFMESHSAVE: cannot open output stream"); close (filenum); *revaptr = 1; return; } o = SCOTCH_meshSave (meshptr, stream); fclose (stream); /* This closes filenum too */ *revaptr = o; } /* ** */ FORTRAN ( \ SCOTCHFMESHBUILD, scotchfmeshbuild, ( \ SCOTCH_Mesh * const meshptr, \ const SCOTCH_Num * const velmbas, \ const SCOTCH_Num * const vnodbas, \ const SCOTCH_Num * const velmnbr, \ const SCOTCH_Num * const vnodnbr, \ const SCOTCH_Num * const verttab, \ const SCOTCH_Num * const vendtab, \ const SCOTCH_Num * const velotab, \ const SCOTCH_Num * const vnlotab, \ const SCOTCH_Num * const vlbltab, \ const SCOTCH_Num * const edgenbr, \ const SCOTCH_Num * const edgetab, \ int * const revaptr), \ (meshptr, velmbas, vnodbas, velmnbr, vnodnbr, \ verttab, vendtab, velotab, vnlotab, vlbltab, \ edgenbr, edgetab, revaptr)) { *revaptr = SCOTCH_meshBuild (meshptr, *velmnbr, *vnodnbr, *velmbas, *vnodbas, verttab, vendtab, velotab, vnlotab, vlbltab, *edgenbr, edgetab); } /* ** */ FORTRAN ( \ SCOTCHFMESHCHECK, scotchfmeshcheck, ( \ const SCOTCH_Mesh * const meshptr, \ int * const revaptr), \ (meshptr, revaptr)) { *revaptr = SCOTCH_meshCheck (meshptr); } /* ** */ FORTRAN ( \ SCOTCHFMESHSIZE, scotchfmeshsize, ( \ const SCOTCH_Mesh * const meshptr, \ SCOTCH_Num * const velmnbr, \ SCOTCH_Num * const vnodnbr, \ SCOTCH_Num * const edgenbr), \ (meshptr, velmnbr, vnodnbr, edgenbr)) { SCOTCH_meshSize (meshptr, velmnbr, vnodnbr, edgenbr); } /* ** */ FORTRAN ( \ SCOTCHFMESHDATA, scotchfmeshdata, ( \ const SCOTCH_Mesh * const meshptr, \ const SCOTCH_Num * const indxptr, \ SCOTCH_Num * const velmbas, \ SCOTCH_Num * const vnodbas, \ SCOTCH_Num * const velmnbr, \ SCOTCH_Num * const vnodnbr, \ SCOTCH_Idx * const vertidx, \ SCOTCH_Idx * const vendidx, \ SCOTCH_Idx * const veloidx, \ SCOTCH_Idx * const vnloidx, \ SCOTCH_Idx * const vlblidx, \ SCOTCH_Num * const edgenbr, \ SCOTCH_Idx * const edgeidx, \ SCOTCH_Num * const degrnbr), \ (meshptr, indxptr, velmbas, vnodbas, velmnbr, vnodnbr, \ vertidx, vendidx, veloidx, vnloidx, vlblidx, \ edgenbr, edgeidx, degrnbr)) { SCOTCH_Num * verttab; /* Pointer to mesh arrays */ SCOTCH_Num * vendtab; SCOTCH_Num * velotab; SCOTCH_Num * vnlotab; SCOTCH_Num * vlbltab; SCOTCH_Num * edgetab; SCOTCH_meshData (meshptr, velmbas, vnodbas, velmnbr, vnodnbr, &verttab, &vendtab, &velotab, &vnlotab, &vlbltab, edgenbr, &edgetab, degrnbr); *vertidx = (verttab - indxptr) + 1; /* Add 1 since Fortran indices start at 1 */ *vendidx = (vendtab - indxptr) + 1; *veloidx = (velotab != NULL) ? (velotab - indxptr) + 1 : *vertidx; *vnloidx = (vnlotab != NULL) ? (vnlotab - indxptr) + 1 : *vertidx; *vlblidx = (vlbltab != NULL) ? (vlbltab - indxptr) + 1 : *vertidx; *edgeidx = (edgetab - indxptr) + 1; } scotch-5.1.12b.dfsg/src/libscotch/bdgraph_bipart_ex.c0000644000175300017530000005360411631334325022753 0ustar hazelscthazelsct/* Copyright 2010,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bdgraph_bipart_ex.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module bipartitions a distributed **/ /** active graph using a parallel gradient **/ /** method to balance the two parts as **/ /** evenly as possible. **/ /** **/ /** DATES : # Version 5.1 : from : 16 jul 2010 **/ /** to : 15 apr 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BDGRAPH_BIPART_EX #include "module.h" #include "common.h" #include "dgraph.h" #include "arch.h" #include "bdgraph.h" #include "bdgraph_bipart_ex.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the bipartitioning. ** It returns: ** - 0 : if bipartitioning could be computed. ** - 1 : on error. */ int bdgraphBipartEx ( Bdgraph * restrict const grafptr, /*+ Active graph +*/ const BdgraphBipartExParam * restrict const paraptr) /*+ Method parameters +*/ { int sbbtnbr; /* Number of subbits */ Gnum sbbtmsk; /* Subbit mask */ int gainsiz; /* Size of gain array */ int gainidx; Gnum * restrict gainloctab; Gnum * restrict gainglbtab; Gnum * restrict frstloctab; Gnum * restrict nextloctab; Gnum * restrict loadglbtab; const Gnum * restrict edgegsttax; Gnum edlolocval; Gnum fronlocnum; Gnum vertgstnum; Gnum vertlocnnd; Gnum complocsizedlt; /* Count of vertices moved locally */ Gnum complocloaddlt; /* Load of vertices moved locally */ Gnum compglbloaddlt; Gnum compglbloaddltmax; Gnum compglbloaddltmat; Gnum commlocgain; Gnum commlocgainextn; Gnum fronlocnbr; int * restrict movegsttab; int * restrict flagloctab; int cheklocval; int chekglbval; BdgraphBipartExSort * sorttab; size_t sortsiz; Gnum reduloctab[5]; Gnum reduglbtab[5]; Gnum partval; Gnum domdist; const Gnum * restrict const vertloctax = grafptr->s.vertloctax; /* Fast accesses */ const Gnum * restrict const vendloctax = grafptr->s.vendloctax; const Gnum * restrict const veloloctax = grafptr->s.veloloctax; const Gnum * restrict const veexloctax = grafptr->veexloctax; const Gnum * restrict const edloloctax = grafptr->s.edloloctax; Gnum * restrict const fronloctab = grafptr->fronloctab; GraphPart * restrict const partgsttax = grafptr->partgsttax; partval = (grafptr->compglbload0dlt > 0) ? 1 : 0; /* Get number of underloaded part to receive vertices */ compglbloaddltmax = (Gnum) ((double) grafptr->compglbload0avg * paraptr->deltval); compglbloaddltmat = (partval == 0) ? (grafptr->compglbload0avg - grafptr->compglbload0min) : (grafptr->compglbload0max - grafptr->compglbload0avg); if (compglbloaddltmax > compglbloaddltmat) compglbloaddltmax = compglbloaddltmat; if ((abs (grafptr->compglbload0dlt) < compglbloaddltmax) || /* If nothing to do */ (grafptr->fronglbnbr == 0)) /* Or if no current frontier */ return (0); /* This algorithm is useless */ if (dgraphGhst (&grafptr->s) != 0) { /* Compute ghost edge array if not already present */ errorPrint ("bdgraphBipartEx: cannot compute ghost edge array"); return (1); } sbbtnbr = (int) paraptr->sbbtnbr; sbbtmsk = (1 << sbbtnbr) - 1; gainsiz = ((sizeof (Gnum) << 3) - sbbtnbr) << (sbbtnbr + 1); /* Compute gain array size */ sortsiz = MAX ((grafptr->s.procglbnbr * sizeof (BdgraphBipartExSort)), /* TRICK: recycle */ (grafptr->fronlocnbr * sizeof (BdgraphBipartExMove))); cheklocval = 0; if (memAllocGroup ((void **) (void *) &gainglbtab, (size_t) (gainsiz * sizeof (Gnum)), &gainloctab, (size_t) (gainsiz * sizeof (Gnum)), &frstloctab, (size_t) (gainsiz * sizeof (Gnum)), &nextloctab, (size_t) (grafptr->fronlocnbr * sizeof (Gnum)), &loadglbtab, (size_t) (grafptr->s.procglbnbr * sizeof (Gnum)), &movegsttab, (size_t) (flagSize (grafptr->s.vertgstnbr + grafptr->s.baseval) * sizeof (int)), /* TRICK: use based vertices as flag array indices */ &flagloctab, (size_t) (flagSize (grafptr->s.vertlocnbr + grafptr->s.baseval) * sizeof (int)), &sorttab, (size_t) (sortsiz), NULL) == NULL) { errorPrint ("bdgraphBipartEx: out of memory"); cheklocval = 1; } else { memSet (gainloctab, 0, gainsiz * sizeof (Gnum)); /* Initialize gain array */ memSet (frstloctab, ~0, gainsiz * sizeof (Gnum)); /* Initialize linked list */ memSet (nextloctab, ~0, grafptr->fronlocnbr * sizeof (Gnum)); memSet (movegsttab, 0, flagSize (grafptr->s.vertgstnbr + grafptr->s.baseval) * sizeof (int)); /* TRICK: based sizes */ memSet (flagloctab, 0, flagSize (grafptr->s.vertlocnbr + grafptr->s.baseval) * sizeof (int)); } #ifdef SCOTCH_DEBUG_BDGRAPH1 if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartEx: communication error (1)"); return (1); } #else /* SCOTCH_DEBUG_BDGRAPH1 */ chekglbval = cheklocval; #endif /* SCOTCH_DEBUG_BDGRAPH1 */ if (chekglbval != 0) { if (gainglbtab != NULL) memFree (gainglbtab); /* Free group leader */ return (1); } domdist = (Gnum) grafptr->domdist; edgegsttax = grafptr->s.edgegsttax; edlolocval = 1; /* Assume no edge loads */ for (fronlocnum = 0; fronlocnum < grafptr->fronlocnbr; fronlocnum ++) { Gnum vertlocnum; Gnum velolocval; Gnum edgelocnum; Gnum commgain; int gainidx; int i; Gnum j; vertlocnum = fronloctab[fronlocnum]; if ((Gnum) partgsttax[vertlocnum] == partval) /* If vertex belongs to lighter part, skip it */ continue; for (edgelocnum = vertloctax[vertlocnum], commgain = 0; edgelocnum < vendloctax[vertlocnum]; edgelocnum ++) { Gnum vertlocend; Gnum partend; Gnum partdlt; vertlocend = edgegsttax[edgelocnum]; partend = (Gnum) partgsttax[vertlocend]; if (edloloctax != NULL) edlolocval = edloloctax[edgelocnum]; partdlt = partval ^ partend; /* Inverse of partdlt, because "partval" is the opposite */ commgain += (2 * partdlt - 1) * edlolocval; /* Since partdlt has reversed meaning, reverse gain too */ } commgain *= domdist; /* Adjust internal gains with respect to external gains */ if (veexloctax != NULL) commgain += (2 * partval - 1) * veexloctax[vertlocnum]; /* Partval has reversed meaning */ velolocval = (veloloctax != NULL) ? veloloctax[vertlocnum] : 1; if (commgain >= 0) { /* Compute table entry for gain */ for (i = 0, j = commgain; j > sbbtmsk; i ++, j >>= 1) ; i = (i << sbbtnbr) + (int) j; } else { for (i = 0, j = - (commgain + 1); j > sbbtmsk; i ++, j >>= 1) ; i = - ((i << sbbtnbr) + (int) j + 1); } gainidx = (gainsiz >> 1) + i; #ifdef SCOTCH_DEBUG_BDGRAPH2 if ((gainidx < 0) || (gainidx >= gainsiz)) { errorPrint ("bdgraphBipartEx: internal error"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ gainloctab[gainidx] += velolocval; /* Accumulate gain in proper cell */ nextloctab[fronlocnum] = frstloctab[gainidx]; /* Chain frontier vertex in gain list */ frstloctab[gainidx] = fronlocnum; } if (MPI_Allreduce (gainloctab, gainglbtab, gainsiz, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartEx: communication error (2)"); return (1); } complocloaddlt = 0; /* No moved vertices yet */ compglbloaddlt = abs (grafptr->compglbload0dlt); /* We want to reduce the absolute value of imbalance */ for (gainidx = 0; gainidx < gainsiz; gainidx ++) { Gnum compglbloadtmp; Gnum gainglbval; Gnum fronlocnum; gainglbval = gainglbtab[gainidx]; if (gainglbval <= 0) continue; compglbloadtmp = compglbloaddlt - gainglbval; if (compglbloadtmp < compglbloaddltmax) break; compglbloaddlt = compglbloadtmp; complocloaddlt += gainloctab[gainidx]; /* We moved that much load locally */ for (fronlocnum = frstloctab[gainidx]; fronlocnum != ~0; /* For all vertices in swapped gain slot */ fronlocnum = nextloctab[fronlocnum]) partgsttax[fronloctab[fronlocnum]] = (GraphPart) (partval | 2); /* Swap vertex part and flag vertex */ } if ((gainidx < gainsiz) && /* If we can make further adjustments */ (compglbloaddlt > compglbloaddltmax)) { /* And if there are some to make */ Gnum loadglbmax; int procglbnbr; int proclocnum; int procnum; int procmax; int sortnbr; int sortnum; if (MPI_Allgather (gainloctab + gainidx, 1, GNUM_MPI, loadglbtab, 1, GNUM_MPI, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartEx: communication error (3)"); return (1); } for (procnum = procmax = sortnbr = 0, loadglbmax = 0; /* For all potential contributions */ procnum < grafptr->s.procglbnbr; procnum ++) { if (loadglbtab[procnum] > 0) { if (loadglbtab[procnum] > loadglbmax) { /* Find maximum contribution index as starting point */ loadglbmax = loadglbtab[procnum]; procmax = procnum; } sorttab[sortnbr].veloval = loadglbtab[procnum]; sorttab[sortnbr].procnum = (Gnum) procnum; sortnbr ++; } } procglbnbr = grafptr->s.procglbnbr; for (sortnum = 0; sortnum < sortnbr; sortnum ++) /* Increase priority value from found maximum */ sorttab[sortnum].prioval = (sorttab[sortnum].procnum + procglbnbr - procmax) % procglbnbr; intSort3asc2 (sorttab, sortnbr); /* Sort contributions array unambiguously */ proclocnum = grafptr->s.proclocnum; for (sortnum = sortnbr - 1; sortnum >= 0; sortnum --) { /* Process contributions by descending load */ Gnum compglbloadtmp; compglbloadtmp = compglbloaddlt - sorttab[sortnum].veloval; if (compglbloadtmp < compglbloaddltmax) { /* If entire move would cause imbalance */ Gnum fronlocnum; BdgraphBipartExMove * movetab; Gnum movenbr; Gnum movenum; if (sorttab[sortnum].procnum != proclocnum) /* If this is not our job to handle it */ break; /* Nothing more to do for us */ movetab = (BdgraphBipartExMove *) sorttab; /* TRICK: recycle sorttab array as move array */ for (fronlocnum = frstloctab[gainidx], movenbr = 0; /* For all vertices in swapped gain slot */ fronlocnum != ~0; fronlocnum = nextloctab[fronlocnum], movenbr ++) { Gnum vertlocnum; vertlocnum = fronloctab[fronlocnum]; movetab[movenbr].veloval = (veloloctax != NULL) ? veloloctax[vertlocnum] : 1; movetab[movenbr].vertnum = vertlocnum; } intSort2asc1 (movetab, movenbr); /* Sort local moves by ascending load order */ for (movenum = movenbr - 1; movenum >= 0; movenum --) { /* For all potential moves by descending weight */ Gnum compglbloadtmp; compglbloadtmp = compglbloaddlt - movetab[movenum].veloval; if (compglbloadtmp >= compglbloaddltmax) { /* If move reduces imbalance */ partgsttax[movetab[movenum].vertnum] = (GraphPart) (partval | 2); /* Swap vertex part and flag vertex */ compglbloaddlt = compglbloadtmp; complocloaddlt += movetab[movenum].veloval; /* We moved that much load locally */ if (compglbloaddlt <= compglbloaddltmax) /* If nothing more to do, exit loop */ break; } } break; /* Nothing more to do */ } compglbloaddlt = compglbloadtmp; /* Accept move entirely */ if (sorttab[sortnum].procnum == proclocnum) { /* If we are the process to do it */ Gnum fronlocnum; complocloaddlt += sorttab[sortnum].veloval; /* We moved all of our local load for this gain */ for (fronlocnum = frstloctab[gainidx]; fronlocnum != ~0; /* For all vertices in swapped gain slot */ fronlocnum = nextloctab[fronlocnum]) partgsttax[fronloctab[fronlocnum]] = (GraphPart) (partval | 2); /* Swap vertex part and flag vertex */ break; /* We did our job; don't care about the rest */ } } } grafptr->complocload0 -= (2 * partval - 1) * complocloaddlt; /* Update according to load of moved vertices */ if (dgraphHaloSync (&grafptr->s, partgsttax + grafptr->s.baseval, GRAPHPART_MPI) != 0) { errorPrint ("bdgraphBipartEx: communication error (4)"); return (1); } for (vertgstnum = grafptr->s.vertlocnnd; /* For all received ghosts */ vertgstnum < grafptr->s.vertgstnnd; vertgstnum ++) { if ((partgsttax[vertgstnum] & 2) != 0) { /* If ghost vertex changed part */ partgsttax[vertgstnum] &= 1; /* Put it back in normal state */ flagSet (movegsttab, vertgstnum); /* While recording state change */ } } complocsizedlt = 0; /* No difference to number of vertices yet */ for (fronlocnum = 0, fronlocnbr = grafptr->fronlocnbr; fronlocnum < fronlocnbr; fronlocnum ++) { Gnum vertlocnum; vertlocnum = fronloctab[fronlocnum]; flagSet (flagloctab, vertlocnum); /* Record vertex as already seen */ if ((partgsttax[vertlocnum] & 2) != 0) { /* If frontier vertex changed part */ partgsttax[vertlocnum] &= 1; /* Put it back in normal state */ flagSet (movegsttab, vertlocnum); /* While recording state change */ complocsizedlt ++; /* One more vertex changed of part */ } } grafptr->complocsize0 -= (2 * partval - 1) * complocsizedlt; /* Update according to number of moved vertices */ if (grafptr->s.procsidnbr != 0) { /* Add potential new frontiers to frontier array */ Gnum vertlocnum; Gnum procsidnbr; Gnum procsidnum; int procsidval; const int * restrict const procsidtab = grafptr->s.procsidtab; vertlocnum = grafptr->s.baseval; procsidnbr = grafptr->s.procsidnbr; procsidnum = 0; procsidval = procsidtab[procsidnum ++]; while (1) { /* Scan all vertices which have foreign neighbors */ while (procsidval < 0) { vertlocnum -= (Gnum) procsidval; procsidval = procsidtab[procsidnum ++]; } if (flagVal (flagloctab, vertlocnum) == 0) { /* If vertex not already processed */ flagSet (flagloctab, vertlocnum); fronloctab[fronlocnbr ++] = vertlocnum; /* Record candidate frontier vertex */ } do { if (procsidnum >= procsidnbr) goto loop_exit; } while ((procsidval = procsidtab[procsidnum ++]) >= 0); } loop_exit : ; } edlolocval = 1; /* Assume no edge loads */ commlocgain = commlocgainextn = 0; for (fronlocnum = 0, vertlocnnd = grafptr->s.vertlocnnd; /* For all potential frontier vertices */ fronlocnum < fronlocnbr; ) { Gnum vertlocnum; Gnum edgelocnum; Gnum commcut; Gnum flagval; vertlocnum = fronloctab[fronlocnum]; partval = partgsttax[vertlocnum]; flagval = flagVal (movegsttab, vertlocnum); for (edgelocnum = vertloctax[vertlocnum], commcut = 0; edgelocnum < vendloctax[vertlocnum]; edgelocnum ++) { Gnum vertlocend; Gnum flagend; Gnum partend; Gnum partdlt; vertlocend = edgegsttax[edgelocnum]; partend = (Gnum) partgsttax[vertlocend]; flagend = (Gnum) flagVal (movegsttab, vertlocend); if (edloloctax != NULL) edlolocval = edloloctax[edgelocnum]; partdlt = partval ^ partend; /* Compute difference between new parts */ commcut |= partdlt; /* Accumulate difference */ if ((partdlt != 0) && /* If vertices belong to different parts */ (vertlocend < vertlocnnd) && /* And end vertex is local */ (flagVal (flagloctab, vertlocend) == 0)) { /* And end vertex not already queued */ fronloctab[fronlocnbr ++] = vertlocend; /* Add end vertex to frontier queue */ flagSet (flagloctab, vertlocend); /* Flag it to avoid multiple insertions */ } commlocgain += (((- partdlt) & edlolocval) - /* Compute difference between new and old communication loads */ ((- (partdlt ^ flagval ^ flagend)) & edlolocval)); } if (veexloctax != NULL) commlocgainextn += (partval - (partval ^ flagval)) * veexloctax[vertlocnum]; /* Compute half of difference in external load */ if (commcut == 0) { /* If vertex no longer belongs to frontier */ fronloctab[fronlocnum] = fronloctab[-- fronlocnbr]; /* Replace it by another one */ continue; /* Process replacement vertex */ } fronlocnum ++; /* Process next vertex */ } grafptr->fronlocnbr = fronlocnbr; /* Set new number of frontier vertices */ memFree (gainglbtab); /* Free group leader */ reduloctab[0] = grafptr->fronlocnbr; reduloctab[1] = grafptr->complocload0; reduloctab[2] = grafptr->complocsize0; reduloctab[3] = commlocgain * domdist; /* Send internal gain */ reduloctab[4] = commlocgainextn * 2; /* Send external gain */ if (MPI_Allreduce (reduloctab, reduglbtab, 5, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartEx: communication error (5)"); return (1); } grafptr->fronglbnbr = reduglbtab[0]; grafptr->compglbload0 = reduglbtab[1]; grafptr->compglbload0dlt = reduglbtab[1] - grafptr->compglbload0avg; grafptr->compglbsize0 = reduglbtab[2]; grafptr->commglbload += reduglbtab[3] / 2 + reduglbtab[4]; /* Add modifications, counted twice for internal gain */ grafptr->commglbgainextn -= reduglbtab[4]; /* Account for modifications in external gain */ #ifdef SCOTCH_DEBUG_BDGRAPH2 if (bdgraphCheck (grafptr) != 0) { errorPrint ("bdgraphBipartEx: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_match_check.c0000644000175300017530000002462011631334325023061 0ustar hazelscthazelsct/* Copyright 2008,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_match_check.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the distributed graph matching **/ /** routines. **/ /** **/ /** DATES : # Version 5.1 : from : 25 dec 2008 **/ /** to : 08 apr 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH_MATCH #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_coarsen.h" #include "dgraph_match.h" /*************************************/ /* */ /* These routines handle distributed */ /* matchings. */ /* */ /*************************************/ /* This routine checks the consistency of a ** given complete matching. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphMatchCheck ( DgraphMatchData * restrict const mateptr) { Gnum baseval; Gnum * restrict flaggsttax; int procngbnum; Gnum multlocnbr; Gnum multlocnum; Gnum vertglbnnd; Gnum vertlocnbr; Gnum vertlocnnd; Gnum vertlocnum; Gnum vertlocadj; int cheklocval; int chekglbval; Dgraph * restrict const grafptr = mateptr->c.finegrafptr; const int * restrict const procngbtab = grafptr->procngbtab; const Gnum * restrict const mategsttax = mateptr->mategsttax; DgraphCoarsenVert * restrict const vsnddattab = mateptr->c.vsnddattab; const DgraphCoarsenMulti * restrict const multloctab = mateptr->c.multloctab; const int * restrict const procgsttax = mateptr->c.procgsttax; const Gnum * restrict const edgeloctax = grafptr->edgeloctax; const Gnum * restrict const edgegsttax = grafptr->edgegsttax; const Gnum * restrict const vertloctax = grafptr->vertloctax; const Gnum * restrict const vendloctax = grafptr->vendloctax; int * restrict const nsndidxtab = mateptr->c.nsndidxtab; baseval = grafptr->baseval; cheklocval = 0; multlocnbr = mateptr->c.multlocnbr; if ((multlocnbr < 0) || (multlocnbr > grafptr->vertlocnbr)) { errorPrint ("dgraphMatchCheck: invalid number of multinodes"); cheklocval = 1; } vertlocnbr = grafptr->vertlocnbr; for (vertlocnum = baseval; vertlocnum < vertlocnbr; vertlocnum ++) { if (mategsttax[vertlocnum] < 0) { errorPrint ("dgraphMatchCheck: unmatched local vertex"); cheklocval = 1; break; } } if ((flaggsttax = memAlloc (grafptr->vertgstnbr * sizeof (Gnum))) == NULL) { errorPrint ("dgraphMatchCheck: out of memory"); cheklocval = 1; } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_SUM, mateptr->c.finegrafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphMatchCheck: communication error (1)"); chekglbval = 1; } if (chekglbval != 0) { if (flaggsttax != NULL) memFree (flaggsttax); return (1); } for (procngbnum = 0; procngbnum < grafptr->procngbnbr; procngbnum ++) /* Reset indices for sending messages */ nsndidxtab[procngbnum] = mateptr->c.vsnddsptab[procngbtab[procngbnum]]; memSet (flaggsttax, ~0, grafptr->vertgstnbr * sizeof (Gnum)); flaggsttax -= baseval; vertglbnnd = grafptr->vertglbnbr + baseval; vertlocnnd = grafptr->vertlocnnd; vertlocadj = grafptr->procvrttab[grafptr->proclocnum] - baseval; for (multlocnum = 0; multlocnum < multlocnbr; multlocnum ++) { Gnum vertglbnum; Gnum vertlocnum; Gnum vertglbend; vertglbnum = multloctab[multlocnum].vertglbnum[0]; vertlocnum = vertglbnum - vertlocadj; /* First vertex is always local */ if ((vertlocnum < baseval) || (vertlocnum >= vertlocnnd)) { errorPrint ("dgraphMatchCheck: invalid multinode vertex (1)"); goto abort; } if (flaggsttax[vertlocnum] != -1) { errorPrint ("dgraphMatchCheck: duplicate multinode vertex (1)"); goto abort; } flaggsttax[vertlocnum] = multlocnum + vertlocadj; vertglbend = multloctab[multlocnum].vertglbnum[1]; if (vertglbend < 0) { /* If end vertex is remote */ Gnum edgelocnum; Gnum vertgstend; int vsndidxnum; int procngbnum; edgelocnum = -2 - vertglbend; if ((edgelocnum < grafptr->baseval) || (edgelocnum >= (grafptr->edgelocsiz + grafptr->baseval))) { errorPrint ("dgraphMatchCheck: invalid multinode vertex (2)"); goto abort; } vertglbend = edgeloctax[edgelocnum]; if (mategsttax[vertlocnum] != vertglbend) { errorPrint ("dgraphMatchCheck: invalid mate array (1)"); goto abort; } vertgstend = edgegsttax[edgelocnum]; if (flaggsttax[vertgstend] != -1) { errorPrint ("dgraphMatchCheck: duplicate multinode vertex (2)"); goto abort; } flaggsttax[vertgstend] = multlocnum + vertlocadj; if (mategsttax[vertgstend] != vertglbnum) { errorPrint ("dgraphMatchCheck: invalid mate array (2)"); goto abort; } procngbnum = procgsttax[vertgstend]; /* Find neighbor owner process */ if ((procngbnum < 0) || (procngbnum >= grafptr->procngbnbr)) { /* If neighbor had not been computed or is wrong */ errorPrint ("dgraphMatchCheck: internal error (1)"); goto abort; } if ((grafptr->procvrttab[procngbtab[procngbnum]] > vertglbend) || (grafptr->procvrttab[procngbtab[procngbnum] + 1] <= vertglbend)) { errorPrint ("dgraphMatchCheck: internal error (2)"); goto abort; } vsndidxnum = nsndidxtab[procngbnum] ++; /* Get position of message in send array */ if (vsndidxnum >= mateptr->c.vsnddsptab[procngbtab[procngbnum] + 1]) { errorPrint ("dgraphMatchCheck: internal error (3)"); goto abort; } vsnddattab[vsndidxnum].datatab[0] = vertglbnum; vsnddattab[vsndidxnum].datatab[1] = vertglbend; } else { /* End vertex is local */ Gnum vertlocend; Gnum edgelocnum; Gnum edgelocnnd; if (mategsttax[vertlocnum] != vertglbend) { errorPrint ("dgraphMatchCheck: invalid mate array (3)"); goto abort; } if (vertglbend == vertglbnum) /* If single multinode */ continue; vertlocend = vertglbend - vertlocadj; if ((vertlocend < baseval) || (vertlocend >= vertlocnnd)) { errorPrint ("dgraphMatchCheck: invalid multinode vertex (3)"); goto abort; } edgelocnum = vertloctax[vertlocnum]; edgelocnnd = vendloctax[vertlocnum]; if (edgelocnum != edgelocnnd) { /* If first multinode vertex is not an isolated vertex */ for ( ; ; edgelocnum ++) { /* Loop on edges of first multinode vertex */ if (edgelocnum >= edgelocnnd) { /* If not a valid neighbor */ errorPrint ("dgraphMatchCheck: invalid multinode vertex (4)"); goto abort; } if (edgeloctax[edgelocnum] == vertglbend) /* If edge to end vertex found */ break; } } if (flaggsttax[vertlocend] != -1) { errorPrint ("dgraphMatchCheck: duplicate multinode vertex (3)"); goto abort; } flaggsttax[vertlocend] = multlocnum + vertlocadj; if (mategsttax[vertlocend] != vertglbnum) { errorPrint ("dgraphMatchCheck: invalid mate array (4)"); goto abort; } } } cheklocval = -1; abort: cheklocval ++; if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_SUM, mateptr->c.finegrafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphMatchCheck: communication error (2)"); chekglbval = 1; } if (chekglbval != 0) { memFree (flaggsttax + baseval); return (1); } /* TODO: Send messages and check consistency of matching on the receiving side */ memFree (flaggsttax + baseval); return (0); } scotch-5.1.12b.dfsg/src/libscotch/bgraph_store.c0000644000175300017530000001506311631334325021763 0ustar hazelscthazelsct/* Copyright 2004,2007,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_store.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the save data **/ /** structure handling routines for bipar- **/ /** tition graphs. **/ /** **/ /** DATES : # Version 3.3 : from : 17 oct 1998 **/ /** to 17 oct 1998 **/ /** # Version 4.0 : from : 18 dec 2001 **/ /** to 16 jun 2004 **/ /** # Version 5.1 : from : 22 feb 2011 **/ /** to 22 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define BGRAPH_STORE #include "module.h" #include "common.h" #include "graph.h" #include "arch.h" #include "bgraph.h" /**********************************/ /* */ /* Store graph handling routines. */ /* */ /**********************************/ /* This routine builds a save structure ** for the given active graph. ** It returns: ** - 0 : if allocation succeeded. ** - !0 : on error. */ int bgraphStoreInit ( const Bgraph * const grafptr, BgraphStore * const storptr) { Gnum savsize; savsize = (grafptr->s.vertnnd - grafptr->s.baseval) * (sizeof (GraphPart) + sizeof (Gnum)); /* Compute size for frontier and part arrays */ if ((storptr->datatab = (byte *) memAlloc (savsize)) == NULL) { /* Allocate save structure */ errorPrint ("bgraphStoreInit: out of memory"); return (1); } return (0); } /* This routine frees a save structure. ** It returns: ** - VOID : in all cases. */ void bgraphStoreExit ( BgraphStore * const storptr) { memFree (storptr->datatab); #ifdef SCOTCH_DEBUG_BGRAPH2 storptr->datatab = NULL; #endif /* SCOTCH_DEBUG_BGRAPH2 */ } /* This routine saves partition data from the ** given active graph to the given save structure. ** It returns: ** - VOID : in all cases. */ void bgraphStoreSave ( const Bgraph * const grafptr, BgraphStore * const storptr) { Gnum vertnbr; /* Number of vertices in graph */ byte * parttab; /* Pointer to part data save area */ byte * frontab; /* Pointer to frontier data save area */ storptr->fronnbr = grafptr->fronnbr; /* Save partition parameters */ storptr->compload0dlt = grafptr->compload0dlt; storptr->compsize0 = grafptr->compsize0; storptr->commload = grafptr->commload; storptr->commgainextn = grafptr->commgainextn; frontab = storptr->datatab; /* Compute data offsets within save structure */ parttab = frontab + grafptr->fronnbr * sizeof (Gnum); vertnbr = grafptr->s.vertnnd - grafptr->s.baseval; memCpy (frontab, grafptr->frontab, grafptr->fronnbr * sizeof (Gnum)); memCpy (parttab, grafptr->parttax + grafptr->s.baseval, vertnbr * sizeof (GraphPart)); } /* This routine updates partition data of the ** given active graph, using the given save graph. ** It returns: ** - VOID : in all cases. */ void bgraphStoreUpdt ( Bgraph * const grafptr, const BgraphStore * const storptr) { Gnum vertnbr; /* Number of vertices in graph */ byte * frontab; /* Pointer to frontier data save area */ byte * parttab; /* Pointer to part data save area */ grafptr->fronnbr = storptr->fronnbr; /* Load partition parameters */ grafptr->compload0 = storptr->compload0dlt + grafptr->compload0avg; grafptr->compload0dlt = storptr->compload0dlt; grafptr->compsize0 = storptr->compsize0; grafptr->commload = storptr->commload; grafptr->commgainextn = storptr->commgainextn; grafptr->bbalval = (double) ((grafptr->compload0dlt < 0) ? (- grafptr->compload0dlt) : grafptr->compload0dlt) / (double) grafptr->compload0avg; frontab = storptr->datatab; /* Compute data offsets within save structure */ parttab = frontab + grafptr->fronnbr * sizeof (Gnum); vertnbr = grafptr->s.vertnnd - grafptr->s.baseval; memCpy (grafptr->frontab, frontab, grafptr->fronnbr * sizeof (Gnum)); memCpy (grafptr->parttax + grafptr->s.baseval, parttab, vertnbr * sizeof (GraphPart)); #ifdef SCOTCH_DEBUG_BGRAPH2 if (bgraphCheck (grafptr) != 0) errorPrint ("bgraphStoreUpdt: inconsistent graph data"); #endif /* SCOTCH_DEBUG_BGRAPH2 */ } scotch-5.1.12b.dfsg/src/libscotch/library_mesh_io_habo.c0000644000175300017530000000664111631334325023446 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_mesh_io_habo.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the Harwell- **/ /** Boeing geometry and mesh handling **/ /** routines of the libSCOTCH library. **/ /** **/ /** DATES : # Version 4.0 : from : 19 jan 2004 **/ /** to 19 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "geom.h" #include "graph.h" #include "mesh.h" #include "scotch.h" /*************************************/ /* */ /* These routines are the C API for */ /* the Harwell-Boeing mesh and */ /* geometry handling routines. */ /* */ /*************************************/ /*+ This routine loads the given opaque geom *** structure with the data of the given stream. *** - 0 : if loading succeeded. *** - !0 : on error. +*/ int SCOTCH_meshGeomLoadHabo ( SCOTCH_Mesh * restrict const meshptr, SCOTCH_Geom * restrict const geomptr, FILE * const filesrcptr, FILE * const filegeoptr, const char * const dataptr) /* No use */ { return (meshGeomLoadHabo ((Mesh *) meshptr, (Geom *) geomptr, filesrcptr, filegeoptr, dataptr)); } scotch-5.1.12b.dfsg/src/libscotch/dorder_perm.h0000644000175300017530000000547111631334325021615 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /**********************************************************/ /* */ /* NAME : dorder_perm.h */ /* */ /* AUTHOR : Francois PELLEGRINI */ /* */ /* FUNCTION : These lines are the data declarations */ /* for the distributed source graph */ /* folding routines. */ /* */ /* # Version 5.0 : from : 14 oct 2007 */ /* to 14 oct 2007 */ /* */ /**********************************************************/ /* ** The type and structure definitions. */ /*+ The sort structure, used to sort permuted vertices. Field vertnum is first because of intSort2asc1. +*/ typedef struct DorderPermSort_ { Gnum vertnum; /*+ Vertex number: FIRST +*/ Gnum permnum; /*+ Direct permutation index +*/ } DorderPermSort; scotch-5.1.12b.dfsg/src/libscotch/gain.c0000644000175300017530000003214111631334325020216 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : gain.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles logarithmic gain **/ /** table structures. **/ /** **/ /** DATES : # Version 0.0 : from : 26 oct 1996 **/ /** to 30 nov 1996 **/ /** # Version 0.1 : from : 10 may 1999 **/ /** to 10 may 1999 **/ /** # Version 4.0 : from : 10 jan 2004 **/ /** to 18 mar 2005 **/ /** # Version 5.0 : from : 24 mar 2008 **/ /** to 24 mar 2008 **/ /** **/ /** NOTES : # Most of the contents of this module **/ /** comes from "map_b_fm" of the SCOTCH **/ /** project (v3.2). **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GAIN #include "module.h" #include "common.h" #include "gain.h" /* ** The static variables. */ static GainLink gainLinkDummy; /*+ Dummy link space for fast linked list operations +*/ /*************************************************/ /* */ /* These routines deal with generic gain tables. */ /* */ /*************************************************/ /* This routine allocates and initializes ** a gain table structure with the proper ** number of subbits. ** It returns: ** - !NULL : pointer to the gain table; ** - NULL : on error. */ GainTabl * gainTablInit ( const INT gainmax, const INT subbits) { GainEntr * entrptr; GainTabl * tablptr; INT totsize; if (gainmax >= GAIN_LINMAX) { /* If logarithmic indexing */ totsize = ((sizeof (INT) << 3) - subbits) << (subbits + 1); /* Allocate gain table */ if ((tablptr = (GainTabl *) memAlloc (sizeof (GainTabl) + (totsize - 1) * sizeof (GainEntr))) == NULL) return (NULL); tablptr->tablAdd = gainTablAddLog; tablptr->subbits = subbits; /* Fill gain table fields */ tablptr->submask = (1 << (subbits + 1)) - 1; /* Mask with all subbits, plus one, set to 1 */ } else { /* Linear indexing */ totsize = 2 * GAIN_LINMAX; /* Allocate gain table */ if ((tablptr = (GainTabl *) memAlloc (sizeof (GainTabl) + (totsize - 1) * sizeof (GainEntr))) == NULL) return (NULL); tablptr->tablAdd = gainTablAddLin; tablptr->subbits = 0; /* Fill gain table fields */ tablptr->submask = 0; } tablptr->totsize = totsize; tablptr->tabl = tablptr->tabk + (totsize / 2); tablptr->tend = tablptr->tabk + (totsize - 1); /* End of gain entry array */ tablptr->tmin = tablptr->tend; /* Entries of extremal gain */ tablptr->tmax = tablptr->tabk; for (entrptr = tablptr->tabk; /* Initialize gain table entries */ entrptr <= tablptr->tend; entrptr ++) entrptr->next = &gainLinkDummy; /* Point to dummy link area */ return (tablptr); } /* This routine deletes a gain list ** It returns: ** - VOID : in all cases. */ void gainTablExit ( GainTabl * const tablptr) { memFree (tablptr); /* Free table structure itself */ } /* This routine flushes the contents of ** the given gain table. ** It returns: ** - VOID : in all cases. */ void gainTablFree ( GainTabl * const tablptr) { GainEntr * entrptr; for (entrptr = tablptr->tmin; /* Flush only used area */ entrptr <= tablptr->tmax; entrptr ++) entrptr->next = &gainLinkDummy; /* Point to dummy link area */ tablptr->tmin = tablptr->tend; /* Entries of extremal gain */ tablptr->tmax = tablptr->tabk; } /* This routine adds a vertex to the table ** and table gain indicated in the vertex ** fields. ** It returns: ** - VOID : in all cases. */ void gainTablAddLin ( GainTabl * const tablptr, /*+ Pointer to gain table +*/ GainLink * const linkptr, /*+ Pointer to entry to add +*/ const INT gain) /*+ Gain value +*/ { GainEntr * entrptr; /* Pointer to gain entry */ GainLink * headptr; /* Pointer to head of list */ #ifdef SCOTCH_DEBUG_GAIN2 if (tablptr->tablAdd != gainTablAddLin) { errorPrint ("gainTablAddLin: table type mismatch"); return; } #endif /* SCOTCH_DEBUG_GAIN2 */ entrptr = tablptr->tabl + gain; if (entrptr < tablptr->tabk) entrptr = tablptr->tabk; else if (entrptr > tablptr->tend) entrptr = tablptr->tend; if (entrptr < tablptr->tmin) tablptr->tmin = entrptr; if (entrptr > tablptr->tmax) tablptr->tmax = entrptr; headptr = (GainLink *) entrptr; /* TRICK: assume gain entry is a link */ linkptr->tabl = entrptr; /* Set table position */ headptr->next->prev = linkptr; /* Link vertex in gain list: TRICK */ linkptr->prev = headptr; linkptr->next = headptr->next; headptr->next = linkptr; } /* This routine adds a vertex to the table ** and table gain indicated in the vertex ** fields. ** It returns: ** - VOID : in all cases. */ void gainTablAddLog ( GainTabl * const tablptr, /*+ Pointer to gain table +*/ GainLink * const linkptr, /*+ Pointer to entry to add +*/ const INT gain) /*+ Gain value +*/ { GainEntr * entrptr; /* Pointer to gain entry */ INT i, j; #ifdef SCOTCH_DEBUG_GAIN2 if (tablptr->tablAdd != gainTablAddLog) { errorPrint ("gainTablAddLog: table type mismatch"); return; } #endif /* SCOTCH_DEBUG_GAIN2 */ if (gain >= 0) { /* Compute table entry for gain */ for (i = 0, j = gain; j > tablptr->submask; i ++, j >>= 1) ; i = (i << tablptr->subbits) + j; } else { for (i = 0, j = - (gain + 1); j > tablptr->submask; i ++, j >>= 1) ; i = - ((i << tablptr->subbits) + j + 1); } entrptr = tablptr->tabl + i; if (entrptr < tablptr->tmin) tablptr->tmin = entrptr; if (entrptr > tablptr->tmax) tablptr->tmax = entrptr; #ifdef SCOTCH_DEBUG_GAIN3 if ((entrptr->next != &gainLinkDummy) && (entrptr->next->prev != (GainLink *) entrptr)) { errorPrint ("gainTablAddLog: bad first element"); return; } if (gainTablCheck (entrptr) != 0) { errorPrint ("gainTablAddLog: bad chaining"); } #endif /* SCOTCH_DEBUG_GAIN3 */ entrptr->next->prev = linkptr; /* Link vertex in gain list: TRICK */ linkptr->prev = (GainLink *) entrptr; linkptr->next = entrptr->next; linkptr->tabl = entrptr; /* Set table position */ entrptr->next = linkptr; } /* This routine removes a link ** from the table. ** It returns: ** - VOID : in all cases. */ #ifdef SCOTCH_DEBUG_GAIN1 /* Compiled only in debug mode */ void gainTablDel ( GainTabl * const tablptr, GainLink * const linkptr) /*+ Pointer to link to delete +*/ { #ifdef SCOTCH_DEBUG_GAIN3 if (linkptr->tabl != NULL) { if ((linkptr->tabl->next != &gainLinkDummy) && (linkptr->tabl->next->prev != (GainLink *) linkptr->tabl)) { errorPrint ("gainTablDel: bad first element"); return; } if (gainTablCheck (linkptr->tabl) != 0) { errorPrint ("gainTablDel: bad chaining"); return; } } #endif /* SCOTCH_DEBUG_GAIN3 */ linkptr->next->prev = linkptr->prev; /* TRICK: may write in dummy link area */ linkptr->prev->next = linkptr->next; } #endif /* SCOTCH_DEBUG_GAIN1 */ /* This routine returns the link of best ** gain in the table structure. ** It returns: ** - !NULL : pointer to the vertex. ** - NULL : if no such vertex available. */ GainLink * gainTablFrst ( GainTabl * const tablptr) { GainEntr * entrptr; for (entrptr = tablptr->tmin; entrptr <= tablptr->tend; entrptr ++) { if (entrptr->next != &gainLinkDummy) { tablptr->tmin = entrptr; #ifdef SCOTCH_DEBUG_GAIN3 if (gainTablCheck (entrptr) != 0) { errorPrint ("gainTablFrst: bad chaining"); return (NULL); } #endif /* SCOTCH_DEBUG_GAIN3 */ return (entrptr->next); } } tablptr->tmin = tablptr->tend; tablptr->tmax = tablptr->tabk; return (NULL); } /* This routine returns the next best vertex ** following the given vertex. ** It returns: ** - !NULL : pointer to the vertex. ** - NULL : if no such vertex available. */ GainLink * gainTablNext ( GainTabl * const tablptr, const GainLink * const linkptr) { GainEntr * entrptr; if (linkptr->next != &gainLinkDummy) { #ifdef SCOTCH_DEBUG_GAIN3 if (gainTablCheck (linkptr->tabl) != 0) { errorPrint ("gainTablNext: bad chaining (1)"); return (NULL); } #endif /* SCOTCH_DEBUG_GAIN3 */ return (linkptr->next); } for (entrptr = linkptr->tabl + 1; entrptr < tablptr->tend; entrptr ++) { if (entrptr->next != &gainLinkDummy) { #ifdef SCOTCH_DEBUG_GAIN3 if (gainTablCheck (entrptr) != 0) { errorPrint ("gainTablNext: bad chaining (2)"); return (NULL); } #endif /* SCOTCH_DEBUG_GAIN3 */ return (entrptr->next); } } return (NULL); } /* This routine checks the consistency of the ** given linked list. ** It returns: ** - !NULL : pointer to the vertex. ** - NULL : if no such vertex available. */ #ifdef SCOTCH_DEBUG_GAIN3 static int gainTablCheck2 ( GainEntr * const entrptr, GainLink * const linkptr) { GainLink * nextptr; int o; if (linkptr->next == &gainLinkDummy) /* If end of list successfully reached */ return (0); if (linkptr->next == NULL) /* If loop discovered */ return (1); if (linkptr->tabl != entrptr) return (1); nextptr = linkptr->next; /* Save pointer to next cell */ linkptr->next = NULL; /* Flag cell as already visited */ o = gainTablCheck2 (entrptr, nextptr); /* Process next cell */ linkptr->next = nextptr; /* Restore cell state */ return (o); } int gainTablCheck ( GainEntr * const entrptr) { if (entrptr->next == &gainLinkDummy) /* If end of list successfully reached */ return (0); if ((entrptr->next == NULL) || /* If problem with link */ (gainTablCheck2 (entrptr, entrptr->next) != 0)) { errorPrint ("gainTablCheck: bad linked list"); return (1); } return (0); } #endif /* SCOTCH_DEBUG_GAIN3 */ scotch-5.1.12b.dfsg/src/libscotch/dgraph_check.c0000644000175300017530000005573011631334325021713 0ustar hazelscthazelsct/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_check.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** Francois CHATENET (P0.0) **/ /** Sebastien FOUCAULT (P0.0) **/ /** Nicolas GICQUEL (P0.1) **/ /** Jerome LACOSTE (P0.1) **/ /** Cedric CHEVALIER **/ /** **/ /** FUNCTION : Part of a parallel static mapper. **/ /** This module contains the distributed **/ /** graph consistency checking routine. **/ /** **/ /** # Version P0.0 : from : 01 apr 1997 **/ /** to 20 jun 1997 **/ /** # Version P0.1 : from : 14 apr 1998 **/ /** to 20 jun 1998 **/ /** # Version P0.2 : from : 11 may 1999 **/ /** to 02 feb 2000 **/ /** # Version 5.0 : from : 04 jul 2005 **/ /** to : 10 sep 2007 **/ /** # Version 5.1 : from : 20 nov 2008 **/ /** to : 30 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH_CHECK #include "module.h" #include "common.h" #include "dgraph.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This function checks the consistency ** of the given distributed graph. ** It returns: ** - 0 : if graph data are consistent. ** - !0 : on error. */ int dgraphCheck ( const Dgraph * restrict const grafptr) { MPI_Comm proccomm; /* Graph communicator */ int procglbnbr; /* Number of processes sharing graph data */ int proclocnum; /* Number of this process */ int procrcvnum; /* Number of process from which to receive */ int procsndnum; /* Number of process to which to send */ int procngbsel; /* Value of the currently used neighbor buffers */ int procngbnum; /* Number of current neighbor process */ Gnum * procngbtab; /* Array of neighbor vertex ranges */ Gnum vertlocnum; Gnum vertngbmin; /* Smallest vertex number of neighbor process */ Gnum vertngbmax; /* Largest vertex number of neighbor process */ int vertngbnbr[2]; /* Size of the neighbor vertex arrays */ Gnum * restrict vertngbtab[2]; /* Array of two neighbor vertex arrays */ Gnum * restrict vendngbtab[2]; /* Array of two neighbor end vertex arrays */ Gnum edgelocnbr; /* Local number of edges */ int edgengbnbr[2]; /* Size of the neighbor vertex arrays */ Gnum * restrict edgengbtab[2]; /* Array of two neighbor edge arrays */ Gnum * restrict edlongbtab[2]; /* Array of two neighbor edge load arrays */ Gnum edlolocsiz; /* Size of neighbor edge load array (if any) */ int cheklocval; /* Local consistency flag */ int chekglbval; /* Global consistency flag */ Gnum reduloctab[20]; /* Arrays for reductions */ Gnum reduglbtab[20]; MPI_Request requloctab[8]; /* Arrays for pipelined communications */ MPI_Status statloctab[8]; proccomm = grafptr->proccomm; /* Simplify */ if (MPI_Barrier (proccomm) != MPI_SUCCESS) { /* Synchronize */ errorPrint ("dgraphCheck: communication error (1)"); return (1); } cheklocval = /* Assume everything is all right */ chekglbval = 0; MPI_Comm_size (proccomm, &procglbnbr); /* Get communicator data */ MPI_Comm_rank (proccomm, &proclocnum); if ((grafptr->procglbnbr != procglbnbr) || (grafptr->proclocnum != proclocnum) || ((grafptr->procdsptab == NULL) && (grafptr->vertlocnbr != 0))) { errorPrint ("dgraphCheck: inconsistent communication data (1)"); cheklocval = 1; } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCheck: communication error (2)"); return (1); } if (chekglbval != 0) return (1); reduloctab[0] = (grafptr->procdsptab == NULL) ? 0 : 1; /* If private data not initialized */ if (MPI_Allreduce (reduloctab, reduglbtab, 1, GNUM_MPI, MPI_SUM, proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCheck: communication error (3)"); return (1); } if (reduglbtab[0] == 0) /* If distributed graph is empty */ return (0); /* Do not go any further */ if (reduglbtab[0] != procglbnbr) { /* If private data not consistently here */ errorPrint ("dgraphCheck: inconsistent communication data (2)"); return (1); } for (procrcvnum = 0; procrcvnum < grafptr->procglbnbr; procrcvnum ++) { if ((grafptr->proccnttab[procrcvnum] < 0) || (grafptr->proccnttab[procrcvnum] != (grafptr->procdsptab[procrcvnum + 1] - grafptr->procdsptab[procrcvnum])) || (grafptr->proccnttab[procrcvnum] > (grafptr->procvrttab[procrcvnum + 1] - grafptr->procvrttab[procrcvnum]))) { errorPrint ("dgraphCheck: inconsistent communication data (3)"); cheklocval = 1; } } if (grafptr->proccnttab[proclocnum] != grafptr->vertlocnbr) { errorPrint ("dgraphCheck: inconsistent communication data (4)"); cheklocval = 1; } procrcvnum = (proclocnum + 1) % procglbnbr; /* Compute indices of neighbors */ procsndnum = (proclocnum - 1 + procglbnbr) % procglbnbr; if ((procngbtab = (Gnum *) memAlloc ((procglbnbr + 1) * sizeof (Gnum))) == NULL) { errorPrint ("dgraphCheck: out of memory (1)"); cheklocval = 1; } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCheck: communication error (4)"); return (1); } if (chekglbval != 0) { if (procngbtab != NULL) memFree (procngbtab); return (1); } MPI_Sendrecv (grafptr->procdsptab, procglbnbr + 1, GNUM_MPI, procsndnum, TAGPROCVRTTAB, /* Check vertex range array */ procngbtab, procglbnbr + 1, GNUM_MPI, procrcvnum, TAGPROCVRTTAB, proccomm, &statloctab[0]); for (procngbnum = 0; procngbnum <= procglbnbr; procngbnum ++) { if (grafptr->procdsptab[procngbnum] != procngbtab[procngbnum]) { errorPrint ("dgraphCheck: inconsistent communication data (5)"); cheklocval = 1; break; } } MPI_Sendrecv (grafptr->procvrttab, procglbnbr + 1, GNUM_MPI, procsndnum, TAGPROCVRTTAB, /* Check vertex range array */ procngbtab, procglbnbr + 1, GNUM_MPI, procrcvnum, TAGPROCVRTTAB, proccomm, &statloctab[0]); for (procngbnum = 0; procngbnum <= procglbnbr; procngbnum ++) { if (grafptr->procvrttab[procngbnum] != procngbtab[procngbnum]) { errorPrint ("dgraphCheck: inconsistent communication data (6)"); cheklocval = 1; break; } } memFree (procngbtab); if ((grafptr->baseval < 0) || /* Elementary constraints on graph fields */ (grafptr->baseval > 1) || /* Strong limitation on base value */ (grafptr->vertlocnbr < 0) || (grafptr->vertlocnnd != (grafptr->vertlocnbr + grafptr->baseval)) || (((grafptr->flagval & DGRAPHHASEDGEGST) != 0) && ((grafptr->vertgstnbr < grafptr->vertlocnbr) || (grafptr->vertgstnnd != (grafptr->vertgstnbr + grafptr->baseval)))) || (grafptr->edgelocnbr < 0) || (grafptr->edgelocsiz < grafptr->edgelocnbr)) { errorPrint ("dgraphCheck: inconsistent local graph data"); cheklocval = 1; } reduloctab[ 0] = grafptr->flagval; reduloctab[ 1] = - grafptr->flagval; reduloctab[ 2] = grafptr->baseval; reduloctab[ 3] = - grafptr->baseval; reduloctab[ 4] = grafptr->vertglbnbr; reduloctab[ 5] = - grafptr->vertglbnbr; reduloctab[ 6] = grafptr->vertglbmax; reduloctab[ 7] = - grafptr->vertglbmax; reduloctab[ 8] = grafptr->vertlocnbr; reduloctab[ 9] = grafptr->edgeglbnbr; reduloctab[10] = - grafptr->edgeglbnbr; reduloctab[11] = grafptr->edgeglbmax; reduloctab[12] = - grafptr->edgeglbmax; reduloctab[13] = grafptr->edgelocnbr; reduloctab[14] = grafptr->edgelocsiz; reduloctab[15] = grafptr->edgeglbsmx; reduloctab[16] = - grafptr->edgeglbsmx; reduloctab[17] = grafptr->degrglbmax; reduloctab[18] = - grafptr->degrglbmax; reduloctab[19] = (Gnum) cheklocval; if (MPI_Allreduce (reduloctab, reduglbtab, 20, GNUM_MPI, MPI_MAX, proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCheck: communication error (5)"); return (1); } if (reduglbtab[19] != 0) return (1); if ((reduglbtab[ 1] != - reduglbtab[ 0]) || /* Check if global graph data match */ (reduglbtab[ 3] != - reduglbtab[ 2]) || (reduglbtab[ 5] != - reduglbtab[ 4]) || (reduglbtab[ 7] != - reduloctab[ 6]) || (reduglbtab[ 8] != reduloctab[ 6]) || (reduglbtab[10] != - reduglbtab[ 9]) || (reduglbtab[12] != - reduglbtab[11]) || (reduglbtab[13] != reduloctab[11]) || /* Recompute and test maximum number of local edges */ (reduglbtab[14] != reduloctab[15]) || /* Recompute and test maximum size of local edge array */ (reduglbtab[16] != - reduloctab[15]) || (reduglbtab[18] != - reduloctab[17])) { errorPrint ("dgraphCheck: inconsistent global graph data (1)"); cheklocval = 1; } reduloctab[0] = (grafptr->veloloctax != NULL) ? 1 : 0; /* Check consistency */ reduloctab[1] = (grafptr->edgegsttax != NULL) ? 1 : 0; reduloctab[2] = (grafptr->edloloctax != NULL) ? 1 : 0; reduloctab[3] = (grafptr->vnumloctax != NULL) ? 1 : 0; reduloctab[4] = grafptr->vertlocnbr; /* Recompute local sizes */ reduloctab[5] = grafptr->edgelocnbr; reduloctab[6] = (Gnum) cheklocval; if (MPI_Allreduce (reduloctab, reduglbtab, 7, GNUM_MPI, MPI_SUM, proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCheck: communication error (6)"); return (1); } if (reduglbtab[6] != 0) return (1); if (((reduglbtab[0] != 0) && (reduglbtab[0] != procglbnbr)) || ((reduglbtab[1] != 0) && (reduglbtab[1] != procglbnbr)) || ((reduglbtab[2] != 0) && (reduglbtab[2] != procglbnbr)) || ((reduglbtab[3] != 0) && (reduglbtab[3] != procglbnbr)) || (reduglbtab[4] != grafptr->vertglbnbr) || (reduglbtab[5] != grafptr->edgeglbnbr)) { errorPrint ("dgraphCheck: inconsistent global graph data (2)"); cheklocval = 1; } for (vertlocnum = grafptr->baseval, edgelocnbr = 0; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) { Gnum edgelocnum; if ((grafptr->vendloctax[vertlocnum] < grafptr->vertloctax[vertlocnum]) || (grafptr->vendloctax[vertlocnum] > (grafptr->edgelocsiz + grafptr->baseval))) { errorPrint ("dgraphCheck: inconsistent local vertex arrays"); edgelocnbr = grafptr->edgelocnbr; /* Avoid unwanted cascaded error messages */ cheklocval = 1; break; } edgelocnbr += grafptr->vendloctax[vertlocnum] - grafptr->vertloctax[vertlocnum]; if ((grafptr->flagval & DGRAPHHASEDGEGST) != 0) { /* If ghost edge array is valid */ for (edgelocnum = grafptr->vertloctax[vertlocnum]; edgelocnum < grafptr->vendloctax[vertlocnum]; edgelocnum ++) { if ((grafptr->edgegsttax[edgelocnum] < grafptr->baseval) || (grafptr->edgegsttax[edgelocnum] >= grafptr->vertgstnnd)) { errorPrint ("dgraphCheck: inconsistent ghost edge array"); edgelocnbr = grafptr->edgelocnbr; /* Avoid unwanted cascaded error messages */ cheklocval = 1; break; } } } } if (edgelocnbr != grafptr->edgelocnbr) { errorPrint ("dgraphCheck: invalid local number of edges"); cheklocval = 1; } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCheck: communication error (7)"); return (1); } if (chekglbval != 0) return (1); if (grafptr->veloloctax != NULL) { /* We must check that load data are consistent */ Gnum velolocsum; Gnum veloglbsum; for (vertlocnum = grafptr->baseval, velolocsum = 0; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) velolocsum += grafptr->veloloctax[vertlocnum]; MPI_Allreduce (&velolocsum, &veloglbsum, 1, GNUM_MPI, MPI_SUM, proccomm); cheklocval = 0; if (velolocsum != grafptr->velolocsum) { errorPrint ("dgraphCheck: invalid local vertex load sum"); cheklocval = 1; } if (veloglbsum != grafptr->veloglbsum) { errorPrint ("dgraphCheck: invalid global vertex load sum"); cheklocval = 1; } MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm); if (chekglbval != 0) return (1); } edlolocsiz = (grafptr->edloloctax != NULL) ? grafptr->edgeglbsmx : 0; if (memAllocGroup ((void **) (void *) &vertngbtab[0], (size_t) (grafptr->vertglbmax * sizeof (Gnum)), /* Send vertex and vertex end arrays, even when they are compact */ &vertngbtab[1], (size_t) (grafptr->vertglbmax * sizeof (Gnum)), &vendngbtab[0], (size_t) (grafptr->vertglbmax * sizeof (Gnum)), &vendngbtab[1], (size_t) (grafptr->vertglbmax * sizeof (Gnum)), &edgengbtab[0], (size_t) (grafptr->edgeglbsmx * sizeof (Gnum)), &edgengbtab[1], (size_t) (grafptr->edgeglbsmx * sizeof (Gnum)), &edlongbtab[0], (size_t) (edlolocsiz * sizeof (Gnum)), &edlongbtab[1], (size_t) (edlolocsiz * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphCheck: out of memory (2)"); cheklocval = 1; } if (grafptr->edloloctax == NULL) { /* If graph edges are not weighted */ edlongbtab[0] = /* Edge load arrays are fake */ edlongbtab[1] = NULL; } if (MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm) != MPI_SUCCESS) { errorPrint ("dgraphCheck: communication error (8)"); return (1); } if (chekglbval != 0) { if (cheklocval == 0) memFree (vertngbtab[0]); /* Free group leader */ return (1); } MPI_Irecv (vertngbtab[0], grafptr->vertglbmax, GNUM_MPI, procrcvnum, TAGVERTLOCTAB, proccomm, &requloctab[0]); MPI_Irecv (vendngbtab[0], grafptr->vertglbmax, GNUM_MPI, procrcvnum, TAGVENDLOCTAB, proccomm, &requloctab[1]); MPI_Irecv (edgengbtab[0], grafptr->edgeglbsmx, GNUM_MPI, procrcvnum, TAGEDGELOCTAB, proccomm, &requloctab[2]); if (grafptr->edloloctax != NULL) MPI_Irecv (edlongbtab[0], grafptr->edgeglbsmx, GNUM_MPI, procrcvnum, TAGEDLOLOCTAB, proccomm, &requloctab[3]); MPI_Send (grafptr->vertloctax + grafptr->baseval, grafptr->vertlocnbr, GNUM_MPI, procsndnum, TAGVERTLOCTAB, proccomm); MPI_Send (grafptr->vendloctax + grafptr->baseval, grafptr->vertlocnbr, GNUM_MPI, procsndnum, TAGVENDLOCTAB, proccomm); MPI_Send (grafptr->edgeloctax + grafptr->baseval, grafptr->edgelocsiz, GNUM_MPI, procsndnum, TAGEDGELOCTAB, proccomm); if (grafptr->edloloctax != NULL) { /* Send synchronously vertloctab and vendloctab to avoid MPI Isend problem if same array */ MPI_Send (grafptr->edloloctax + grafptr->baseval, grafptr->edgelocsiz, GNUM_MPI, procsndnum, TAGEDLOLOCTAB, proccomm); MPI_Waitall (4, &requloctab[0], &statloctab[0]); } else MPI_Waitall (3, &requloctab[0], &statloctab[0]); MPI_Get_count (&statloctab[0], GNUM_MPI, &vertngbnbr[0]); MPI_Get_count (&statloctab[2], GNUM_MPI, &edgengbnbr[0]); for (procngbnum = (proclocnum + 1) % procglbnbr, procngbsel = 0; /* Loop on all other processes */ procngbnum != proclocnum; procngbnum = (procngbnum + 1) % procglbnbr, procngbsel ^= 1) { Gnum vertlocnum; Gnum vertglbnum; Gnum * restrict edgengbtax; Gnum * restrict edlongbtax; vertngbmin = grafptr->procvrttab[procngbnum]; /* Get neighbor vertex number range */ vertngbmax = grafptr->procvrttab[procngbnum + 1]; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((vertngbnbr[procngbsel] != grafptr->proccnttab[procngbnum]) || (vertngbnbr[procngbsel] > (vertngbmax - vertngbmin))) { errorPrint ("dgraphCheck: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (((procngbnum + 1) % procglbnbr) != proclocnum) { MPI_Irecv (vertngbtab[1 - procngbsel], grafptr->vertglbmax, GNUM_MPI, procrcvnum, TAGVERTLOCTAB, proccomm, &requloctab[4]); MPI_Irecv (vendngbtab[1 - procngbsel], grafptr->vertglbmax, GNUM_MPI, procrcvnum, TAGVENDLOCTAB, proccomm, &requloctab[5]); MPI_Irecv (edgengbtab[1 - procngbsel], grafptr->edgeglbsmx, GNUM_MPI, procrcvnum, TAGEDGELOCTAB, proccomm, &requloctab[6]); MPI_Isend (vertngbtab[procngbsel], vertngbnbr[procngbsel], GNUM_MPI, procsndnum, TAGVERTLOCTAB, proccomm, &requloctab[1]); MPI_Isend (vendngbtab[procngbsel], vertngbnbr[procngbsel], GNUM_MPI, procsndnum, TAGVENDLOCTAB, proccomm, &requloctab[2]); MPI_Isend (edgengbtab[procngbsel], edgengbnbr[procngbsel], GNUM_MPI, procsndnum, TAGEDGELOCTAB, proccomm, &requloctab[3]); if (grafptr->edloloctax != NULL) { MPI_Irecv (edlongbtab[1 - procngbsel], grafptr->edgeglbsmx, GNUM_MPI, procrcvnum, TAGEDLOLOCTAB, proccomm, &requloctab[7]); MPI_Isend (edlongbtab[procngbsel], edgengbnbr[procngbsel], GNUM_MPI, procsndnum, TAGEDLOLOCTAB, proccomm, &requloctab[0]); } } edgengbtax = edgengbtab[procngbsel] - grafptr->baseval; edlongbtax = (grafptr->edloloctax != NULL) ? (edlongbtab[procngbsel] - grafptr->baseval) : NULL; if (((procngbnum + 1) % procglbnbr) != proclocnum) { /* Before MPI 2.2, complete communications before accessing arrays being sent */ if (grafptr->edloloctax != NULL) MPI_Waitall (8, &requloctab[0], &statloctab[0]); else MPI_Waitall (6, &requloctab[1], &statloctab[1]); MPI_Get_count (&statloctab[4], GNUM_MPI, &vertngbnbr[1 - procngbsel]); MPI_Get_count (&statloctab[6], GNUM_MPI, &edgengbnbr[1 - procngbsel]); } for (vertlocnum = grafptr->baseval, vertglbnum = grafptr->procvrttab[proclocnum]; vertlocnum < grafptr->vertlocnnd; vertlocnum ++, vertglbnum ++) { Gnum edgelocnum; for (edgelocnum = grafptr->vertloctax[vertlocnum]; edgelocnum < grafptr->vendloctax[vertlocnum]; edgelocnum ++) { Gnum vertglbend; vertglbend = grafptr->edgeloctax[edgelocnum]; if ((vertglbend >= vertngbmin) && /* If end vertex belongs to current neighbor process */ (vertglbend < vertngbmax)) { Gnum edgengbnum; Gnum edgengbnnd; Gnum edgengbcnt; for (edgengbnum = vertngbtab[procngbsel][vertglbend - vertngbmin], edgengbnnd = vendngbtab[procngbsel][vertglbend - vertngbmin], edgengbcnt = 0; edgengbnum < edgengbnnd; edgengbnum ++) { if (edgengbtax[edgengbnum] == vertglbnum) { /* If matching edge found */ edgengbcnt ++; /* Account for it */ if ((edlongbtax != NULL) && /* If edge weights do not match */ (edlongbtax[edgengbnum] != grafptr->edloloctax[edgelocnum])) cheklocval = 3; } } if (edgengbcnt < 1) /* If matching edge not found */ cheklocval = 1; else if (edgengbcnt > 1) /* If duplicate edge */ cheklocval = 2; } } } MPI_Allreduce (&cheklocval, &chekglbval, 1, MPI_INT, MPI_MAX, proccomm); if (chekglbval != 0) { /* Error number ranges from 1 to 3 */ if (chekglbval == 1) errorPrint ("dgraphCheck: arc data do not match"); else if (chekglbval == 2) errorPrint ("dgraphCheck: duplicate arc"); else errorPrint ("dgraphCheck: arc load data do not match"); memFree (vertngbtab[0]); /* Free group leader */ return (1); } } memFree (vertngbtab[0]); /* Free group leader */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/vmesh_separate_gr.h0000644000175300017530000000565711631334325023017 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh_separate_gr.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the the graph separation-based node **/ /** separation method. **/ /** **/ /** DATES : # Version 4.0 : from : 11 oct 2003 **/ /** to 11 oct 2003 **/ /** **/ /************************************************************/ /* ** The defines. */ /* ** The type and structure definitions. */ /*+ Method parameters. +*/ typedef struct VmeshSeparateGrParam_ { Strat * stratptr; /*+ Graph separation strategy +*/ } VmeshSeparateGrParam; /* ** The function prototypes. */ #ifndef VMESH_SEPARATE_GR #define static #endif int vmeshSeparateGr (Vmesh * restrict const, const VmeshSeparateGrParam * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/vmesh_separate_st.h0000644000175300017530000000664611631334325023034 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh_separate_st.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the global mesh separation **/ /** strategy and method tables. **/ /** **/ /** DATES : # Version 4.0 : from : 20 sep 2002 **/ /** to 31 oct 2003 **/ /** **/ /************************************************************/ /* ** The type definitions. */ /*+ Method types. +*/ typedef enum VmeshSeparateStMethodType_ { VMESHSEPASTMETHFM = 0, /*+ Fiduccia-Mattheyses +*/ VMESHSEPASTMETHGG, /*+ Greedy Mesh Growing +*/ #ifdef SCOTCH_DEBUG_VMESH2 VMESHSEPASTMETHGR, /*+ Graph partitioning +*/ #endif /* SCOTCH_DEBUG_VMESH2 */ VMESHSEPASTMETHML, /*+ Multi-level separation +*/ VMESHSEPASTMETHZR, /*+ Zero method +*/ VMESHSEPASTMETHNBR /*+ Number of methods +*/ } VmeshSeparateStMethodType; /* ** The external declarations. */ extern StratTab vmeshseparateststratab; /* ** The function prototypes. */ #ifndef VMESH_SEPARATE_ST #define static #endif int vmeshSeparateSt (Vmesh * restrict const, const Strat * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/hdgraph.c0000644000175300017530000000700711631334325020720 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hdgraph.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the distributed graph general **/ /** purpose routines. **/ /** **/ /** DATES : # Version 5.0 : from : 21 apr 2006 **/ /** to : 21 apr 2006 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HDGRAPH #include "module.h" #include "common.h" #include "dgraph.h" #include "hdgraph.h" /******************************/ /* */ /* These routines handle halo */ /* distributed source graphs. */ /* */ /******************************/ /* This routine destroys a distributed halo graph ** structure. It is not a collective routine, as no ** communication is needed to perform the freeing of ** memory structures. ** It returns: ** - 0 : on success. ** - !0 : on error. */ void hdgraphExit ( Hdgraph * restrict const grafptr) { if ((grafptr->vhndloctax != grafptr->s.vertloctax + 1) && /* If graph has a halo, with a separate end vertex array */ ((grafptr->s.flagval & HDGRAPHFREEVHND) != 0)) memFree (grafptr->vhndloctax); dgraphExit (&grafptr->s); /* Free distributed graph data (flagval may be corrupted afterwards) */ #ifdef SCOTCH_DEBUG_HDGRAPH1 memSet (grafptr, 0, sizeof (Hdgraph)); #endif /* SCOTCH_DEBUG_HDGRAPH1 */ } scotch-5.1.12b.dfsg/src/libscotch/dgraph.h0000644000175300017530000004006311631334325020554 0ustar hazelscthazelsct/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Francois CHATENET (P0.0) **/ /** Sebastien FOUCAULT (P0.0) **/ /** Nicolas GICQUEL (P0.1) **/ /** Jerome LACOSTE (P0.1) **/ /** Cedric CHEVALIER (5.0) **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the distributed source graph **/ /** structure. **/ /** **/ /** DATES : # Version P0.0 : from : 01 apr 1997 **/ /** to : 20 jun 1997 **/ /** # Version P0.1 : from : 07 apr 1998 **/ /** to : 20 jun 1998 **/ /** # Version P0.2 : from : 11 may 1999 **/ /** to : 02 feb 2000 **/ /** # Version P0.3 : from : 16 jun 2005 **/ /** to : 16 jun 2005 **/ /** # Version 5.0 : from : 22 jul 2005 **/ /** to : 03 aug 2007 **/ /** # Version 5.1 : from : 11 nov 2007 **/ /** to : 20 feb 2011 **/ /** **/ /************************************************************/ #define DGRAPH_H #define PTSCOTCH_FOLD_DUP /* Activate folding on coarsening */ #ifndef SCOTCH_COMM_PTOP_RAT #define SCOTCH_COMM_PTOP_RAT 0.25 /* Percentage under which point-to-point is allowed */ #endif /* SCOTCH_COMM_PTOP_RAT */ /* ** The defines. */ /* Graph flags. */ #define DGRAPHNONE 0x0000 /* No options set */ #define DGRAPHFREEPRIV 0x0001 /* Set if private arrays freed on exit */ #define DGRAPHFREECOMM 0x0002 /* MPI communicator has to be freed */ #define DGRAPHFREETABS 0x0004 /* Set if local arrays freed on exit */ #define DGRAPHFREEPSID 0x0008 /* Set if procsidtab freed on exit */ #define DGRAPHFREEEDGEGST 0x0010 /* Set if edgegsttab freed on exit */ #define DGRAPHHASEDGEGST 0x0020 /* Edge ghost array computed */ #define DGRAPHVERTGROUP 0x0040 /* All vertex arrays grouped */ #define DGRAPHEDGEGROUP 0x0080 /* All edge arrays grouped */ #define DGRAPHFREEALL (DGRAPHFREEPRIV | DGRAPHFREECOMM | DGRAPHFREETABS | DGRAPHFREEPSID | DGRAPHFREEEDGEGST) #define DGRAPHCOMMPTOP 0x0100 /* Use point-to-point collective communication */ #define DGRAPHBITSUSED 0x00FF /* Significant bits for plain distributed graph routines */ #define DGRAPHBITSNOTUSED 0x0100 /* Value above which bits not used by plain distributed graph routines */ /* Used in algorithms */ #define COARPERTPRIME 31 /* Prime number */ #define COARHASHPRIME 179 /* Prime number */ /* ** The type and structure definitions. */ /* The graph basic types, which must be signed. */ #ifndef GNUMMAX /* If graph.h not included */ typedef INT Gnum; /* Vertex or edge number */ #define GNUMMAX (INTVALMAX) /* Maximum Gnum value */ #define GNUMSTRING INTSTRING /* String to printf a Gnum */ #endif /* GNUMMAX */ #define GNUM_MPI COMM_INT /* MPI type for Gnum is MPI type for INT */ #define GRAPHPART_MPI COMM_BYTE /* Raw byte type for graph parts */ /* Tags used for point-to-point communications. */ typedef enum DgraphTag_ { TAGPROCVRTTAB = 0, /*+ procvrttab message +*/ TAGVERTLOCTAB, /*+ vertloctab message +*/ TAGVENDLOCTAB, /*+ vendloctab message +*/ TAGVELOLOCTAB, /*+ veloloctab message +*/ TAGVNUMLOCTAB, /*+ vnumloctab message +*/ TAGVLBLLOCTAB, /*+ vlblloctab message +*/ TAGEDGELOCTAB, /*+ edgeloctab message +*/ TAGEDLOLOCTAB, /*+ edloloctab message +*/ TAGDATALOCTAB, /*+ Generic data message +*/ TAGOK, /*+ Positive answer +*/ TAGBAD, /*+ Negative answer +*/ TAGHALO = 100, /*+ Tag class for halo +*/ TAGCOARSEN = 200, /*+ Tag class for coarsening +*/ TAGMATCH = 300, /*+ Tag class for matching +*/ TAGFOLD = 400, /*+ Tag class for folding +*/ TAGBAND = 500 /*+ Tag class for band graph +*/ } DgraphTag; /*+ The graph flag type. +*/ typedef int DgraphFlag; /*+ Graph property flags +*/ /*+ The vertex part type, in compressed form. From graph.h +*/ #ifndef GRAPH_H typedef byte GraphPart; #endif /* GRAPH_H */ /* The distributed graph structure. */ typedef struct Dgraph_ { DgraphFlag flagval; /*+ Graph properties +*/ Gnum baseval; /*+ Base index for edge/vertex arrays +*/ Gnum vertglbnbr; /*+ Global number of vertices +*/ Gnum vertglbmax; /*+ Maximum number of local vertices over all processes +*/ Gnum vertgstnbr; /*+ Number of local + ghost vertices +*/ Gnum vertgstnnd; /*+ vertgstnbr + baseval +*/ Gnum vertlocnbr; /*+ Local number of vertices +*/ Gnum vertlocnnd; /*+ Local number of vertices + baseval +*/ Gnum * vertloctax; /*+ Local vertex beginning index array [based] +*/ Gnum * vendloctax; /*+ Local vertex end index array [based] +*/ Gnum * veloloctax; /*+ Local vertex load array if present +*/ Gnum velolocsum; /*+ Local sum of all vertex loads +*/ Gnum veloglbsum; /*+ Global sum of all vertex loads +*/ Gnum * vnumloctax; /*+ Arrays of global vertex numbers in original graph +*/ Gnum * vlblloctax; /*+ Arrays of vertex labels (when read from file) +*/ Gnum edgeglbnbr; /*+ Global number of arcs +*/ Gnum edgeglbmax; /*+ Maximum number of local edges over all processes +*/ Gnum edgelocnbr; /*+ Number of local edges +*/ Gnum edgelocsiz; /*+ Size of local edge array (= edgelocnbr when compact) +*/ Gnum edgeglbsmx; /*+ Maximum size of local edge arrays over all processes +*/ Gnum * edgegsttax; /*+ Edge array holding local indices of neighbors [based] +*/ Gnum * edgeloctax; /*+ Edge array holding global neighbor numbers [based] +*/ Gnum * edloloctax; /*+ Edge load array +*/ Gnum degrglbmax; /*+ Maximum degree over all processes +*/ MPI_Comm proccomm; /*+ Graph communicator +*/ int prockeyval; /*+ Communicator key value: folded communicators are distinct +*/ int procglbnbr; /*+ Number of processes sharing graph data +*/ int proclocnum; /*+ Number of this process +*/ Gnum * procvrttab; /*+ Global array of vertex number ranges [+1,based] +*/ Gnum * proccnttab; /*+ Count array for local number of vertices +*/ Gnum * procdsptab; /*+ Displacement array with respect to proccnttab [+1,based] +*/ int procngbnbr; /*+ Number of neighboring processes +*/ int procngbmax; /*+ Maximum number of neighboring processes +*/ int * procngbtab; /*+ Array of neighbor process numbers [sorted] +*/ int * procrcvtab; /*+ Number of vertices to receive in ghost vertex sub-arrays +*/ int procsndnbr; /*+ Overall size of local send array +*/ int * procsndtab; /*+ Number of vertices to send in ghost vertex sub-arrays +*/ int * procsidtab; /*+ Array of indices to build communication vectors (send) +*/ int procsidnbr; /*+ Size of the send index array +*/ } Dgraph; /* ** The function prototypes. */ int dgraphInit (Dgraph * const, MPI_Comm); void dgraphExit (Dgraph * const); void dgraphFree (Dgraph * const); int dgraphLoad (Dgraph * const, FILE * const, const Gnum, const DgraphFlag); int dgraphSave (Dgraph * const, FILE * const); int dgraphBuild (Dgraph * const, const Gnum, const Gnum, const Gnum, Gnum * const, Gnum * const, Gnum * const, Gnum * const, Gnum * const, const Gnum, const Gnum, Gnum * const, Gnum * const, Gnum * const); int dgraphBuild2 (Dgraph * const, const Gnum, const Gnum, const Gnum, Gnum * const, Gnum * const, Gnum * const, const Gnum, Gnum * const, Gnum * const, const Gnum, const Gnum, Gnum * const, Gnum * const, Gnum * const, const Gnum); int dgraphBuild3 (Dgraph * const, const Gnum, const Gnum, Gnum * const, Gnum * const, Gnum * const, const Gnum, Gnum * const, Gnum * const, const Gnum, const Gnum, Gnum * const, Gnum * const, Gnum * const, const Gnum); int dgraphBuild4 (Dgraph * const); int dgraphBuildHcub (Dgraph * const, const Gnum, const Gnum, const Gnum); int dgraphBuildGrid3D (Dgraph * const, const Gnum, const Gnum, const Gnum, const Gnum, const Gnum, const int); int dgraphCheck (const Dgraph * const); int dgraphView (const Dgraph * const, FILE * const); int dgraphGhst2 (Dgraph * const, const int); int dgraphBand (Dgraph * restrict const, const Gnum, Gnum * restrict const, const GraphPart * restrict const, const Gnum, const Gnum, Gnum, Dgraph * restrict const, Gnum * restrict * const, GraphPart * restrict * const, Gnum * const, Gnum * const, Gnum * const); int dgraphBandColl (Dgraph * restrict const, const Gnum, Gnum * restrict const, const Gnum, Gnum * restrict * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const); int dgraphBandPtop (Dgraph * restrict const, const Gnum, Gnum * restrict const, const Gnum, Gnum * restrict * restrict const, Gnum * restrict const, Gnum * restrict const, Gnum * restrict const); int dgraphFold (const Dgraph * restrict const, const int, Dgraph * restrict const, const void * restrict const, void ** restrict const, MPI_Datatype); int dgraphFold2 (const Dgraph * restrict const, const int, Dgraph * restrict const, MPI_Comm, const void * restrict const, void ** restrict const, MPI_Datatype); int dgraphFoldDup (const Dgraph * restrict const, Dgraph * restrict const, void * restrict const, void ** restrict const, MPI_Datatype); int dgraphInduceList (Dgraph * const, const Gnum, const Gnum * const, Dgraph * const); int dgraphInducePart (Dgraph * const, const GraphPart * restrict const, const Gnum, const GraphPart, Dgraph * const); #ifdef GRAPH_H int dgraphGather (const Dgraph * restrict const, Graph * restrict); int dgraphGather2 (const Dgraph * restrict const, Graph * restrict, const int, const Gnum); int dgraphGatherAll (const Dgraph * restrict const, Graph * restrict); int dgraphGatherAll2 (const Dgraph * restrict const, Graph * restrict, const Gnum, const int); int dgraphScatter (Dgraph * const, const Graph * const); #endif /* GRAPH_H */ int dgraphHaloSync (Dgraph * const, void * const, MPI_Datatype); /* ** The macro definitions. */ #define dgraphGhst(grafptr) dgraphGhst2 (grafptr, 0) /* Build ghost edge array in addition to local edge array */ #define dgraphGhstReplace(grafptr) dgraphGhst2 (grafptr, 1) /* Replace local edge array by ghost edge array */ #define dgraphHasGhst(grafptr) (((grafptr)->flagval & DGRAPHHASEDGEGST) != 0) /* If graph has a ghost edge array */ scotch-5.1.12b.dfsg/src/libscotch/library_mesh_graph.c0000644000175300017530000000623411631334325023145 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_mesh_graph.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the Scotch **/ /** mesh-to-graph converter. **/ /** **/ /** DATES : # Version 4.0 : from : 21 jan 2004 **/ /** to 21 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "graph.h" #include "mesh.h" #include "scotch.h" /*************************************/ /* */ /* These routines are the C API for */ /* the Scotch graph and geometry */ /* handling routines. */ /* */ /*************************************/ /*+ This routine loads the given opaque graph *** structure with the data of the given stream. *** - 0 : if loading succeeded. *** - !0 : on error. +*/ int SCOTCH_meshGraph ( const SCOTCH_Mesh * restrict const meshptr, SCOTCH_Graph * restrict const grafptr) { return (meshGraph ((Mesh *) meshptr, (Graph *) grafptr)); } scotch-5.1.12b.dfsg/src/libscotch/library_graph_io_chac.c0000644000175300017530000001003611631334325023571 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_io_chac.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the Chaco **/ /** geometry and graph handling routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 4.0 : from : 28 nov 2003 **/ /** to 19 jan 2004 **/ /** # Version 5.1 : from : 27 apr 2010 **/ /** to 27 apr 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "geom.h" #include "graph.h" #include "scotch.h" /*************************************/ /* */ /* These routines are the C API for */ /* the Chaco graph and geometry */ /* handling routines. */ /* */ /*************************************/ /*+ This routine loads the given opaque geom *** structure with the data of the given stream. *** - 0 : if loading succeeded. *** - !0 : on error. +*/ int SCOTCH_graphGeomLoadChac ( SCOTCH_Graph * restrict const grafptr, SCOTCH_Geom * restrict const geomptr, FILE * const filegrfptr, FILE * const filegeoptr, const char * const dataptr) { return (graphGeomLoadChac ((Graph *) grafptr, (Geom *) geomptr, filegrfptr, filegeoptr, dataptr)); } /*+ This routine saves the contents of the given *** opaque graph structure to the given stream. *** It returns: *** - 0 : if the saving succeeded. *** - !0 : on error. +*/ int SCOTCH_graphGeomSaveChac ( const SCOTCH_Graph * restrict const grafptr, const SCOTCH_Geom * restrict const geomptr, FILE * const filegrfptr, FILE * const filegeoptr, const char * const dataptr) { return (graphGeomSaveChac ((Graph *) grafptr, (Geom *) geomptr, filegrfptr, filegeoptr, dataptr)); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_fold.h0000644000175300017530000000662211631334325021563 0ustar hazelscthazelsct/* Copyright 2007-2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_fold.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the distributed source graph **/ /** folding routines. **/ /** **/ /** # Version 5.0 : from : 06 sep 2006 **/ /** to 06 sep 2006 **/ /** # Version 5.1 : from : 31 dec 2008 **/ /** to 01 jan 2009 **/ /** **/ /************************************************************/ /* ** The defines. */ /* Slot indices used for point-to-point folding communications. First indices are used for communications without further processing. At the moment, there are two anonymous slots: the first one for vnumloctab, and the second one for vertinfotab. */ typedef enum DgraphFoldTag_ { DGRAPHFOLDTAGENBR = 2, /*+ Edge size message +*/ DGRAPHFOLDTAGVERT, /*+ vertloctab message +*/ DGRAPHFOLDTAGVELO, /*+ veloloctab message +*/ DGRAPHFOLDTAGEDGE, /*+ edgeloctab message +*/ DGRAPHFOLDTAGEDLO, /*+ edgeloctab message +*/ DGRAPHFOLDTAGNBR /*+ Number of tags +*/ } DgraphFoldTag; scotch-5.1.12b.dfsg/src/libscotch/graph_io_habo.c0000644000175300017530000004430511631334325022066 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_io_habo.c **/ /** **/ /** AUTHORS : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the I/O routines **/ /** for handling the Harwell-Boeing matrix **/ /** format. **/ /** **/ /** DATES : # Version 3.2 : from : 06 nov 1997 **/ /** to 26 may 1998 **/ /** # Version 3.3 : from : 13 dec 1998 **/ /** to 24 dec 1998 **/ /** # Version 4.0 : from : 18 dec 2001 **/ /** to 21 mar 2005 **/ /** # Version 5.0 : from : 06 jun 2007 **/ /** to 31 aug 2007 **/ /** # Version 5.1 : from : 09 nov 2008 **/ /** to 27 apr 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define GRAPH_IO_HABO #include "module.h" #include "common.h" #include "geom.h" #include "graph.h" #include "graph_io_habo.h" /* This routine loads the geometrical graph ** in the Harwell-Boeing matrix format, and ** allocates the proper structures. ** - 0 : on success. ** - !0 : on error. */ int graphGeomLoadHabo ( Graph * restrict const grafptr, /* Graph to load */ Geom * restrict const geomptr, /* Geometry to load */ FILE * const filesrcptr, /* Topological data */ FILE * const filegeoptr, /* No use */ const char * const dataptr) /* Tag value */ { Gnum habmattag; /* Matrix tag number in file */ Gnum habmatnum; /* Current matrix number */ char habmatbuf[4][84]; /* Matrix header line buffers */ char habmattype[3]; /* Matrix type */ Gnum habcrdnbr; /* Total number of data lines */ Gnum habrhsnbr; /* Number of right hand side lines */ Gnum habrownbr; /* Number of rows */ GraphGeomHaboLine habcolfmt; /* Format of column line */ int habvalnum; /* Number of value in line */ Gnum habcolnbr; /* Number of columns */ Gnum habcolnum; /* Number of current column index */ Gnum * restrict habcoltab; /* Index array */ GraphGeomHaboLine habnzrfmt; /* Format of non-zero type */ Gnum habnzrnbr; /* Number of non-zero indices */ Gnum habnzrnum; /* Number of current row data */ Gnum * restrict habnzrtab; /* Row data array */ GraphGeomHaboHash * restrict hashtab; /* Neighbor hash table */ Gnum hashmsk; /* Mask for access to hash table */ Gnum vertnum; /* Number of current vertex */ Gnum edgenum; /* Number of current edge (arc) */ Gnum edgeold; /* Number of non-purged edge */ Gnum edgetmp; /* Temporary edge number */ Gnum degrmax; /* Maximum degree */ int c; if ((dataptr != NULL) && /* If tag value provided */ (dataptr[0] != '\0') && ((habmattag = (Gnum) atol (dataptr)) == 0) && /* Get tag value */ (dataptr[0] != '0')) { errorPrint ("graphGeomLoadHabo: invalid parameter"); return (1); } habmattype[0] = habmattype[1] = habmattype[2] = '\0'; for (habmatnum = 0; habmatnum <= habmattag; habmatnum ++) { /* Read headers and skip if necessary */ memSet (habmatbuf[0], ' ', &habmatbuf[3][83] - &habmatbuf[0][0]); /* Initialize header buffers */ if ((fgets (habmatbuf[0], 83, filesrcptr) == NULL) || /* Read graph header */ (fgets (habmatbuf[1], 83, filesrcptr) == NULL) || (fgets (habmatbuf[2], 83, filesrcptr) == NULL) || (fgets (habmatbuf[3], 83, filesrcptr) == NULL)) { errorPrint ("graphGeomLoadHabo: bad input (1)"); return (1); } habmatbuf[1][70] = '\0'; /* Extract header values */ habrhsnbr = (Gnum) atol (&habmatbuf[1][56]); habmatbuf[1][14] = '\0'; habcrdnbr = (Gnum) atol (&habmatbuf[1][00]); habmattype[0] = toupper (habmatbuf[2][0]); habmattype[1] = toupper (habmatbuf[2][1]); habmattype[2] = toupper (habmatbuf[2][2]); habmatbuf[2][56] = '\0'; habnzrnbr = (Gnum) atol (&habmatbuf[2][43]); habmatbuf[2][42] = '\0'; habcolnbr = (Gnum) atol (&habmatbuf[2][29]); habmatbuf[2][28] = '\0'; habrownbr = (Gnum) atol (&habmatbuf[2][14]); habmatbuf[3][32] = '\0'; if (graphGeomLoadHaboFormat (&habnzrfmt, &habmatbuf[3][16]) != 0) { errorPrint ("graphGeomLoadHabo: bad input (2)"); return (1); } habmatbuf[3][16] = '\0'; if (graphGeomLoadHaboFormat (&habcolfmt, &habmatbuf[3][0]) != 0) { errorPrint ("graphGeomLoadHabo: bad input (3)"); return (1); } if (habrhsnbr != 0) { while ((c = getc (filesrcptr)) != '\n'){ /* Skip RHS format line */ if (c == EOF) { errorPrint ("graphGeomLoadHabo: bad input (4)"); return (1); } } } if (habmatnum < habmattag) { /* If we have to skip file */ while (habcrdnbr -- > 0) { /* Skip all of file lines */ while ((c = getc (filesrcptr)) != '\n') { /* Skip line */ if (c == EOF) { errorPrint ("graphGeomLoadHabo: bad input (5)"); return (1); } } } } } if (habmattype[2] != 'A') { errorPrint ("graphGeomLoadHabo: only assembled matrices supported; for unassembled matrices, use the mesh version of the tools"); return (1); } if (habmattype[1] == 'R') { errorPrint ("graphGeomLoadHabo: rectangular matrices not supported"); return (1); } if (((grafptr->verttax = (Gnum *) memAlloc ((habcolnbr + 1) * sizeof (Gnum))) == NULL) || ((grafptr->edgetax = (Gnum *) memAllocGroup ((void **) (void *) &grafptr->edgetax, (size_t) (habnzrnbr * 2 * sizeof (Gnum)), &habcoltab, (size_t) ((habcolnbr + 1) * sizeof (Gnum)), &habnzrtab, (size_t) (habnzrnbr * sizeof (Gnum)), NULL)) == NULL)) { errorPrint ("graphGeomLoadHabo: out of memory (1)"); if (grafptr->verttax != NULL) { memFree (grafptr->verttax); grafptr->verttax = NULL; } return (1); } grafptr->flagval = GRAPHFREETABS; /* Totally new graph structure */ grafptr->baseval = 1; /* Harwell-Boeing graphs have base 1 */ grafptr->vertnbr = (Gnum) habcolnbr; grafptr->vertnnd = grafptr->vertnbr + 1; grafptr->velosum = grafptr->vertnbr; grafptr->vendtax = grafptr->verttax; /* Use compact representation for array based at 1 */ grafptr->verttax --; /* Base verttab array at 1, with vendtab = verttab + 1 */ grafptr->edgetax --; ungetc ('\n', filesrcptr); /* Create fake previous line */ for (habcolnum = 0, habvalnum = habcolfmt.datanbr; /* Eat up fake previous line */ habcolnum <= habcolnbr; habcolnum ++) { /* Read column indices */ Gnum habcolval; /* Current column value */ int habcolidx; /* Current index in column value */ c = getc (filesrcptr); if (habvalnum ++ >= habcolfmt.datanbr) { /* If all useful data read from line */ habvalnum = 1; /* Start at beginning of new line */ while ((c != '\n') && (c != '\r')) /* Eat up all remaining spaces */ c = getc (filesrcptr); while (((c = getc (filesrcptr)) == '\n') || (c == '\r')) ; /* Read till end of line */ for (habcolidx = 0; habcolidx < habcolfmt.strtnbr; habcolidx ++) /* Get start of line */ c = getc (filesrcptr); } habcolval = (c == ' ') ? 0 : (c - '0'); for (habcolidx = 1; habcolidx < habcolfmt.datalen; habcolidx ++) { if ((c = getc (filesrcptr)) != ' ') habcolval = habcolval * 10 + c - '0'; } if (c == EOF) { errorPrint ("graphGeomLoadHabo: bad input (6)"); graphFree (grafptr); return (1); } habcoltab[habcolnum] = habcolval; } if (habcoltab[habcolnbr] != (Gnum) habnzrnbr + 1) { errorPrint ("graphGeomLoadHabo: bad input (7)"); graphFree (grafptr); return (1); } memSet (grafptr->vendtax, 0, habcolnbr * sizeof (Gnum)); /* Here, vendtax = verttab */ for (vertnum = 1, habnzrnum = 0, habvalnum = habnzrfmt.datanbr; /* Start by eating end of previous line */ vertnum < grafptr->vertnnd; vertnum ++) { /* Read matrix pattern */ for ( ; habnzrnum < (habcoltab[vertnum] - 1); habnzrnum ++) { /* All right since vertnum is based at 1 */ Gnum habnzrval; /* Current non-zero value */ int habnzridx; /* Current index in non-zero value */ c = getc (filesrcptr); if (habvalnum ++ >= habnzrfmt.datanbr) { /* If all useful data read from line */ habvalnum = 1; /* Start at beginning of new line */ while ((c != '\n') && (c != '\r')) /* Eat up all remaining spaces */ c = getc (filesrcptr); while (((c = getc (filesrcptr)) == '\n') || (c == '\r')) ; /* Read till end of line */ for (habnzridx = 0; habnzridx < habnzrfmt.strtnbr; habnzridx ++) /* Get start of line */ c = getc (filesrcptr); } habnzrval = (c == ' ') ? 0 : (c - '0'); for (habnzridx = 1; habnzridx < habnzrfmt.datalen; habnzridx ++) { if ((c = getc (filesrcptr)) != ' ') habnzrval = habnzrval * 10 + c - '0'; } if (c == EOF) { errorPrint ("graphGeomLoadHabo: bad input (8)"); graphFree (grafptr); return (1); } habnzrtab[habnzrnum] = habnzrval; if (habnzrval != vertnum) { /* If not loop edge */ grafptr->verttax[vertnum] ++; /* Account for arc */ grafptr->verttax[habnzrval] ++; /* Add arc to symmetrize */ } } } degrmax = 1; for (vertnum = edgenum = 1; vertnum < grafptr->vertnnd; vertnum ++) { /* Build (superset of) vertex array */ Gnum edgetmp; edgetmp = grafptr->verttax[vertnum]; grafptr->verttax[vertnum] = edgenum; edgenum += edgetmp; if (edgetmp > degrmax) /* Update bound on maximum degree */ degrmax = edgetmp; } grafptr->verttax[vertnum] = edgenum; /* Set end of vertex array */ for (vertnum = 1, habnzrnum = 0; vertnum < grafptr->vertnnd; vertnum ++) { /* Build (superset of) edge array */ for ( ; habnzrnum < (habcoltab[vertnum] - 1); habnzrnum ++) { Gnum vertend; /* Number of end vertex */ vertend = habnzrtab[habnzrnum]; if (vertend != vertnum) { /* If not loop edge */ grafptr->edgetax[grafptr->verttax[vertnum] ++] = vertend; /* Build arc */ grafptr->edgetax[grafptr->verttax[vertend] ++] = vertnum; /* Symmetrize */ } } } for (hashmsk = 31; hashmsk < degrmax; hashmsk = hashmsk * 2 + 1) ; /* Set neighbor hash table size */ hashmsk = hashmsk * 4 + 3; if ((hashtab = (GraphGeomHaboHash *) memAlloc ((hashmsk + 1) * sizeof (GraphGeomHaboHash))) == NULL) { errorPrint ("graphGeomLoadHabo: out of memory (2)"); graphFree (grafptr); return (1); } memSet (hashtab, ~0, (hashmsk + 1) * sizeof (GraphGeomHaboHash)); /* Pre-set hash table */ degrmax = 1; for (vertnum = edgetmp = edgenum = 1; vertnum < grafptr->vertnnd; vertnum ++) { /* Remove duplicates from edge array */ for (edgeold = edgetmp, edgetmp = grafptr->verttax[vertnum], grafptr->verttax[vertnum] = edgenum; edgeold < edgetmp; edgeold ++) { Gnum vertend; /* Number of end vertex */ Gnum hashnum; /* Current hash index */ vertend = grafptr->edgetax[edgeold]; for (hashnum = (vertend * GRAPHGEOMHABOHASHPRIME) & hashmsk; ; hashnum = (hashnum + 1) & hashmsk) { if (hashtab[hashnum].vertnum != vertnum) { /* If edge not found */ hashtab[hashnum].vertnum = vertnum; hashtab[hashnum].vertend = vertend; grafptr->edgetax[edgenum ++] = vertend; break; } if (hashtab[hashnum].vertend == vertend) /* Do not add duplicate edges */ break; } } if ((edgenum - grafptr->verttax[vertnum]) > degrmax) /* Set real maximum degree */ degrmax = edgenum - grafptr->verttax[vertnum]; } grafptr->verttax[vertnum] = edgenum; /* Set end of vertex array */ grafptr->edgenbr = edgenum - 1; grafptr->edlosum = grafptr->edgenbr; grafptr->degrmax = degrmax; memFree (hashtab); grafptr->edgetax = ((Gnum *) memRealloc (grafptr->edgetax + 1, grafptr->edgenbr * sizeof (Gnum))) - 1; #ifdef SCOTCH_DEBUG_GRAPH2 if (graphCheck (grafptr) != 0) { /* Check graph consistency */ errorPrint ("graphGeomLoadHabo: internal error"); graphFree (grafptr); return (1); } #endif /* SCOTCH_DEBUG_GRAPH2 */ return (0); } /* This routine reads a Fortran format structure ** and returns the size of the integers to read. */ static int graphGeomLoadHaboFormat ( GraphGeomHaboLine * restrict const lineptr, /* Line format to fill */ const char * const dataptr) /* Format string */ { const char * restrict charptr; int number; /* Number to read */ lineptr->strtnbr = lineptr->datanbr = lineptr->datalen = 0; for (charptr = dataptr; ; charptr ++) { /* Skip to first '(' */ if (*charptr == '(') break; if (*charptr == '\0') /* Error if end of string */ return (1); } number = 0; /* Read number */ for (charptr ++ ; ; charptr ++) { if (*charptr == '\0') /* Error if end of string */ return (1); if (! isdigit ((int) (unsigned char) *charptr)) break; number = number * 10 + *charptr - '0'; } if ((*charptr == 'x') || (*charptr == 'X')) { /* If dummy characters at beginning of line */ lineptr->strtnbr = number; for (charptr ++; ; charptr ++) { /* Skip to first ',' */ if (*charptr == '\0') /* Error if end of string */ return (1); if (*charptr == ',') break; } number = 0; /* Read number */ for (charptr ++; *charptr != '\0'; charptr ++) { if (*charptr == '\0') /* Error if end of string */ return (1); if (! isdigit (*charptr < '0')) break; number = number * 10 + *charptr - '0'; } } if ((*charptr != 'I') && (*charptr != 'i')) /* If not integer specification */ return (1); lineptr->datanbr = number; number = 0; /* Read size of integer */ for (charptr ++; ; charptr ++) { if (*charptr == '\0') /* Error if end of string */ return (1); if (! isdigit ((int) (unsigned char) *charptr)) break; number = number * 10 + *charptr - '0'; } if (number == 0) return (1); lineptr->datalen = number; return (0); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_induce.c0000644000175300017530000006401111631334325022075 0ustar hazelscthazelsct/* Copyright 2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_induce.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Jun-Ho HER **/ /** **/ /** FUNCTION : This module handles the source graph **/ /** subgraph-making functions. **/ /** **/ /** DATES : # Version 5.0 : from : 08 apr 2006 **/ /** to : 10 sep 2007 **/ /** # Version 5.1 : from : 31 mar 2008 **/ /** to : 30 jul 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH #define DGRAPH_INDUCE #include "module.h" #include "common.h" #include "dgraph.h" /****************************************/ /* */ /* These routines handle source graphs. */ /* */ /****************************************/ /* This routine builds the graph induced ** by the original graph and the list of ** selected vertices. ** The induced vnumtab array is the global ** translation of the list array if the ** original graph does not have a vnumtab, ** or the proper subset of the original ** vnumtab else. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphInduceList ( Dgraph * restrict const orggrafptr, const Gnum indlistnbr, const Gnum * restrict const indlisttab, /* Local list of kept vertices */ Dgraph * restrict const indgrafptr) { Gnum * restrict orgindxgsttax; /* Based access to vertex translation array */ Gnum indvertlocnnd; /* Based index of end of local vertex array */ Gnum indvertlocnum; /* Number of current vertex in induced graph */ Gnum indvertglbnum; /* Number of current vertex in global ordering */ Gnum indvelolocnbr; /* Size of local vertex load array */ Gnum indvelolocsum; /* Sum of vertex loads */ Gnum indedgelocmax; /* (Approximate) number of edges in induced graph */ Gnum indedgelocnbr; /* Real number of edges in induced graph */ Gnum indedgelocnum; Gnum * restrict indedloloctax; Gnum inddegrlocmax; /* Local maximum degree */ const Gnum * restrict indlisttax; int cheklocval; int chekglbval; if (dgraphGhst (orggrafptr) != 0) { /* Compute ghost edge array if not already present */ errorPrint ("dgraphInduceList: cannot compute ghost edge array"); return (1); } dgraphInit (indgrafptr, orggrafptr->proccomm); indgrafptr->flagval = (DGRAPHFREEALL ^ DGRAPHFREECOMM) | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; if (orggrafptr->veloloctax != NULL) { indvelolocnbr = indlistnbr; indvelolocsum = 0; } else { indvelolocnbr = 0; indvelolocsum = indlistnbr; } indedgelocmax = orggrafptr->edgelocnbr; /* Choose best upper bound on number of edges (avoid multiply overflow) */ if ((orggrafptr->degrglbmax > 0) && (indlistnbr < (indedgelocmax / orggrafptr->degrglbmax))) indedgelocmax = indlistnbr * orggrafptr->degrglbmax; if (orggrafptr->edloloctax != NULL) /* If graph has edge weights */ indedgelocmax *= 2; /* Account for edge weights */ cheklocval = chekglbval = 0; if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ &indgrafptr->procdsptab, (size_t) ((orggrafptr->procglbnbr + 1) * sizeof (Gnum)), &indgrafptr->proccnttab, (size_t) (orggrafptr->procglbnbr * sizeof (Gnum)), &indgrafptr->procngbtab, (size_t) (orggrafptr->procglbnbr * sizeof (int)), &indgrafptr->procrcvtab, (size_t) (orggrafptr->procglbnbr * sizeof (int)), &indgrafptr->procsndtab, (size_t) (orggrafptr->procglbnbr * sizeof (int)), NULL) == NULL) { errorPrint ("dgraphInduceList: out of memory (1)"); cheklocval = 1; } else if (memAllocGroup ((void **) (void *) /* Allocate distributed graph public data */ &indgrafptr->vertloctax, (size_t) ((indlistnbr + 1) * sizeof (Gnum)), /* Compact vertex array */ &indgrafptr->vnumloctax, (size_t) (indlistnbr * sizeof (Gnum)), &indgrafptr->veloloctax, (size_t) (indvelolocnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphInduceList: out of memory (2)"); cheklocval = 1; } else if (indgrafptr->vertloctax -= orggrafptr->baseval, indgrafptr->vnumloctax -= orggrafptr->baseval, indgrafptr->veloloctax = (orggrafptr->veloloctax != NULL) ? indgrafptr->veloloctax - orggrafptr->baseval : NULL, memAllocGroup ((void **) (void *) &indgrafptr->edgeloctax, (size_t) (indedgelocmax * sizeof (Gnum)), /* Pre-allocate space for edgetab (and edlotab) */ &orgindxgsttax, (size_t) (orggrafptr->vertgstnbr * sizeof (Gnum)), NULL) == NULL) { /* orgindxgsttab is at the end */ errorPrint ("dgraphInduceList: out of memory (3)"); cheklocval = 1; } else indgrafptr->edgeloctax -= orggrafptr->baseval; if (cheklocval != 0) { /* In case of memory error */ Gnum procngbnum; Gnum dummyval; dummyval = -1; chekglbval = 1; if (MPI_Allgather (&dummyval, 1, GNUM_MPI, /* Use proccnttab of orggraf as dummy receive array (will be regenerated) */ orggrafptr->proccnttab, 1, GNUM_MPI, indgrafptr->proccomm) != MPI_SUCCESS) errorPrint ("dgraphInduceList: communication error (1)"); for (procngbnum = 1; procngbnum <= orggrafptr->procglbnbr; procngbnum ++) /* Rebuild proccnttab of orggraf */ orggrafptr->proccnttab[procngbnum - 1] = orggrafptr->procdsptab[procngbnum] - orggrafptr->procdsptab[procngbnum - 1]; } else { indgrafptr->procdsptab[0] = indlistnbr; if (MPI_Allgather (&indgrafptr->procdsptab[0], 1, GNUM_MPI, &indgrafptr->proccnttab[0], 1, GNUM_MPI, indgrafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphInduceList: communication error (2)"); chekglbval = 1; } else { Gnum procngbnum; indgrafptr->procdsptab[0] = orggrafptr->baseval; /* Build vertex-to-process array */ for (procngbnum = 0; procngbnum < indgrafptr->procglbnbr; procngbnum ++) { /* Process potential error flags from other processes */ if (indgrafptr->procdsptab[procngbnum] < 0) { /* If error notified by another process */ chekglbval = 1; break; } indgrafptr->procdsptab[procngbnum + 1] = indgrafptr->procdsptab[procngbnum] + indgrafptr->proccnttab[procngbnum]; } } indgrafptr->procvrttab = indgrafptr->procdsptab; /* Graph does not have holes */ } if (chekglbval != 0) { /* If something went wrong in all of the above */ dgraphExit (indgrafptr); return (1); } memSet (orgindxgsttax, ~0, orggrafptr->vertlocnbr * sizeof (Gnum)); /* Preset index array */ orgindxgsttax -= orggrafptr->baseval; indlisttax = indlisttab - orggrafptr->baseval; indvertlocnnd = indlistnbr + orggrafptr->baseval; for (indvertlocnum = orggrafptr->baseval, indvertglbnum = indgrafptr->procdsptab[indgrafptr->proclocnum], indedgelocmax = 0; /* Fill index array while recomputing tighter upper bound on arcs */ indvertlocnum < indvertlocnnd; indvertlocnum ++, indvertglbnum ++) { Gnum orgvertlocnum; orgvertlocnum = indlisttax[indvertlocnum]; orgindxgsttax[orgvertlocnum] = indvertglbnum; /* Mark selected vertices */ indedgelocmax += orggrafptr->vendloctax[orgvertlocnum] - orggrafptr->vertloctax[orgvertlocnum]; } if (dgraphHaloSync (orggrafptr, (byte *) (orgindxgsttax + orggrafptr->baseval), GNUM_MPI) != 0) { /* Share global indexing of subgraph vertices */ errorPrint ("dgraphInduceList: cannot perform halo exchange"); dgraphExit (indgrafptr); return (1); } indedloloctax = (orggrafptr->edloloctax != NULL) ? indgrafptr->edgeloctax + indedgelocmax : NULL; inddegrlocmax = 0; for (indvertlocnum = indedgelocnum = orggrafptr->baseval; indvertlocnum < indvertlocnnd; indvertlocnum ++) { Gnum orgvertlocnum; Gnum orgedgelocnum; orgvertlocnum = indlisttax[indvertlocnum]; indgrafptr->vertloctax[indvertlocnum] = indedgelocnum; if (indgrafptr->veloloctax != NULL) { /* If graph has vertex weights */ indvelolocsum += /* Accumulate vertex loads */ indgrafptr->veloloctax[indvertlocnum] = orggrafptr->veloloctax[orgvertlocnum]; } for (orgedgelocnum = orggrafptr->vertloctax[orgvertlocnum]; orgedgelocnum < orggrafptr->vendloctax[orgvertlocnum]; orgedgelocnum ++) { Gnum indvertgstend; indvertgstend = orgindxgsttax[orggrafptr->edgegsttax[orgedgelocnum]]; if (indvertgstend != ~0) { /* If edge should be kept */ indgrafptr->edgeloctax[indedgelocnum] = indvertgstend; if (indedloloctax != NULL) indedloloctax[indedgelocnum] = orggrafptr->edloloctax[orgedgelocnum]; indedgelocnum ++; } } if (inddegrlocmax < (indedgelocnum - indgrafptr->vertloctax[indvertlocnum])) inddegrlocmax = (indedgelocnum - indgrafptr->vertloctax[indvertlocnum]); } indgrafptr->vertloctax[indvertlocnum] = indedgelocnum; /* Mark end of edge array */ indedgelocnbr = indedgelocnum - orggrafptr->baseval; if (indedloloctax != NULL) { /* Re-allocate arrays and delete orgindxtab */ size_t indedlooftval; /* Offset of edge load array with respect to edge array */ indedlooftval = indedloloctax - indgrafptr->edgeloctax; indgrafptr->edgeloctax = memRealloc (indgrafptr->edgeloctax + orggrafptr->baseval, (indedlooftval + indedgelocnbr) * sizeof (Gnum)); indgrafptr->edgeloctax -= orggrafptr->baseval; indedloloctax = indgrafptr->edgeloctax + indedlooftval; /* Use old index into old array as new index to avoid alignment problems */ } else { indgrafptr->edgeloctax = memRealloc (indgrafptr->edgeloctax + orggrafptr->baseval, indedgelocnbr * sizeof (Gnum)); indgrafptr->edgeloctax -= orggrafptr->baseval; } if (orggrafptr->vnumloctax != NULL) { /* Adjust vnumloctax */ for (indvertlocnum = orggrafptr->baseval; indvertlocnum < indvertlocnnd; indvertlocnum ++) indgrafptr->vnumloctax[indvertlocnum] = orggrafptr->vnumloctax[indlisttax[indvertlocnum]]; } else { Gnum orgvertglbadj; orgvertglbadj = orggrafptr->procdsptab[orggrafptr->proclocnum] - orggrafptr->baseval; /* Set adjustement for global ordering */ for (indvertlocnum = orggrafptr->baseval; indvertlocnum < indvertlocnnd; indvertlocnum ++) indgrafptr->vnumloctax[indvertlocnum] = indlisttax[indvertlocnum] + orgvertglbadj; } indgrafptr->baseval = orggrafptr->baseval; indgrafptr->vertlocnbr = indlistnbr; indgrafptr->vertlocnnd = indlistnbr + orggrafptr->baseval; indgrafptr->vendloctax = indgrafptr->vertloctax + 1; /* Induced graph is compact */ indgrafptr->velolocsum = indvelolocsum; indgrafptr->edgelocnbr = indedgelocnbr; indgrafptr->edgelocsiz = indedgelocnbr; indgrafptr->edloloctax = indedloloctax; indgrafptr->degrglbmax = inddegrlocmax; /* Local maximum degree will be turned into global maximum degree */ if (dgraphBuild4 (indgrafptr) != 0) { errorPrint ("dgraphInduceList: cannot build induced graph"); return (1); } #ifdef SCOTCH_DEBUG_DGRAPH2 if (dgraphCheck (indgrafptr) != 0) { /* Check graph consistency */ errorPrint ("dgraphInduceList: inconsistent graph data"); dgraphExit (indgrafptr); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ return (0); } /* This routine builds the graph induced ** by the original graph and the vector of ** selected vertices. ** The induced vnumtab array is the global ** translation of the list array if the ** original graph does not have a vnumtab, ** or the proper subset of the original ** vnumtab else. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphInducePart ( Dgraph * restrict const orggrafptr, /* Pointer to original distributed graph */ const GraphPart * restrict const orgpartgsttax, /* Based array of local vertex partition flags */ const Gnum indvertnbr, /* Number of local vertices in selected part */ const GraphPart indpartval, Dgraph * restrict const indgrafptr) { Gnum * restrict orgindxgsttax; /* Based access to vertex translation array */ Gnum orgvertlocnum; /* Number of current vertex in original graph */ Gnum indvertlocnnd; /* Based index of end of local vertex array */ Gnum indvertlocnum; /* Number of current vertex in induced graph */ Gnum indvertglbnum; /* Number of current vertex in global ordering */ Gnum indvelolocnbr; /* Size of local vertex load array */ Gnum indvelolocsum; /* Sum of vertex loads */ Gnum indedgelocmax; /* (Approximate) number of edges in induced graph */ Gnum indedgelocnbr; /* Real number of edges in induced graph */ Gnum indedgelocnum; Gnum * restrict indedloloctax; Gnum inddegrlocmax; /* Local maximum degree */ int cheklocval; int chekglbval; if (dgraphGhst (orggrafptr) != 0) { /* Compute ghost edge array if not already present */ errorPrint ("dgraphInducePart: cannot compute ghost edge array"); return (1); } dgraphInit (indgrafptr, orggrafptr->proccomm); indgrafptr->flagval = (DGRAPHFREEALL ^ DGRAPHFREECOMM) | DGRAPHVERTGROUP | DGRAPHEDGEGROUP; indvertlocnnd = orggrafptr->baseval + indvertnbr; if (orggrafptr->veloloctax != NULL) { indvelolocnbr = indvertnbr; indvelolocsum = 0; } else { indvelolocnbr = 0; indvelolocsum = indvertnbr; } indedgelocmax = orggrafptr->edgelocnbr; /* Choose best upper bound on number of edges (avoid multiply overflow) */ if ((orggrafptr->degrglbmax > 0) && (indvertnbr < (indedgelocmax / orggrafptr->degrglbmax))) indedgelocmax = indvertnbr * orggrafptr->degrglbmax; if (orggrafptr->edloloctax != NULL) /* If graph has edge weights */ indedgelocmax *= 2; /* Account for edge weights */ cheklocval = chekglbval = 0; if (memAllocGroup ((void **) (void *) /* Allocate distributed graph private data */ &indgrafptr->procdsptab, (size_t) ((orggrafptr->procglbnbr + 1) * sizeof (Gnum)), &indgrafptr->proccnttab, (size_t) (orggrafptr->procglbnbr * sizeof (Gnum)), &indgrafptr->procngbtab, (size_t) (orggrafptr->procglbnbr * sizeof (int)), &indgrafptr->procrcvtab, (size_t) (orggrafptr->procglbnbr * sizeof (int)), &indgrafptr->procsndtab, (size_t) (orggrafptr->procglbnbr * sizeof (int)), NULL) == NULL) { errorPrint ("dgraphInducePart: out of memory (1)"); cheklocval = 1; } else if (memAllocGroup ((void **) (void *) /* Allocate distributed graph public data */ &indgrafptr->vertloctax, (size_t) ((indvertnbr + 1) * sizeof (Gnum)), /* Compact vertex array */ &indgrafptr->vnumloctax, (size_t) (indvertnbr * sizeof (Gnum)), &indgrafptr->veloloctax, (size_t) (indvelolocnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphInducePart: out of memory (2)"); cheklocval = 1; } else if (indgrafptr->vertloctax -= orggrafptr->baseval, indgrafptr->vnumloctax -= orggrafptr->baseval, indgrafptr->veloloctax = (orggrafptr->veloloctax != NULL) ? indgrafptr->veloloctax - orggrafptr->baseval : NULL, memAllocGroup ((void **) (void *) &indgrafptr->edgeloctax, (size_t) (indedgelocmax * sizeof (Gnum)), /* Pre-allocate space for edgetab (and edlotab) */ &orgindxgsttax, (size_t) (orggrafptr->vertgstnbr * sizeof (Gnum)), NULL) == NULL) { /* orgindxgsttab is at the end */ errorPrint ("dgraphInducePart: out of memory (3)"); cheklocval = 1; } else indgrafptr->edgeloctax -= orggrafptr->baseval; if (cheklocval != 0) { /* In case of memory error */ Gnum procngbnum; Gnum dummyval; dummyval = -1; chekglbval = 1; if (MPI_Allgather (&dummyval, 1, GNUM_MPI, /* Use proccnttab of orggraf as dummy receive array (will be regenerated) */ orggrafptr->proccnttab, 1, GNUM_MPI, indgrafptr->proccomm) != MPI_SUCCESS) errorPrint ("dgraphInducePart: communication error (1)"); for (procngbnum = 1; procngbnum <= orggrafptr->procglbnbr; procngbnum ++) /* Rebuild proccnttab of orggraf */ orggrafptr->proccnttab[procngbnum - 1] = orggrafptr->procdsptab[procngbnum] - orggrafptr->procdsptab[procngbnum - 1]; } else { indgrafptr->procdsptab[0] = indvertnbr; if (MPI_Allgather (&indgrafptr->procdsptab[0], 1, GNUM_MPI, &indgrafptr->proccnttab[0], 1, GNUM_MPI, indgrafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphInducePart: communication error (2)"); chekglbval = 1; } else { Gnum procngbnum; indgrafptr->procdsptab[0] = orggrafptr->baseval; /* Build vertex-to-process array */ for (procngbnum = 0; procngbnum < indgrafptr->procglbnbr; procngbnum ++) { /* Process potential error flags from other processes */ if (indgrafptr->procdsptab[procngbnum] < 0) { /* If error notified by another process */ chekglbval = 1; break; } indgrafptr->procdsptab[procngbnum + 1] = indgrafptr->procdsptab[procngbnum] + indgrafptr->proccnttab[procngbnum]; } } indgrafptr->procvrttab = indgrafptr->procdsptab; /* Graph does not have holes */ } if (chekglbval != 0) { /* If something went wrong in all of the above */ dgraphExit (indgrafptr); return (1); } memSet (orgindxgsttax, ~0, orggrafptr->vertlocnbr * sizeof (Gnum)); /* Preset index array */ orgindxgsttax -= orggrafptr->baseval; for (indvertlocnum = orggrafptr->baseval, indvertglbnum = indgrafptr->procdsptab[indgrafptr->proclocnum], indedgelocmax = 0, orgvertlocnum = orggrafptr->baseval; /* Fill index array while recomputing tighter upper bound on arcs */ orgvertlocnum < orggrafptr->vertlocnnd; orgvertlocnum ++) { if (orgpartgsttax[orgvertlocnum] == indpartval) { orgindxgsttax[orgvertlocnum] = indvertglbnum; /* Mark selected vertices */ indgrafptr->vnumloctax[indvertlocnum] = orgvertlocnum; indedgelocmax += orggrafptr->vendloctax[orgvertlocnum] - orggrafptr->vertloctax[orgvertlocnum]; indvertlocnum ++, indvertglbnum ++; } else orgindxgsttax[orgvertlocnum] = ~0; } #ifdef SCOTCH_DEBUG_DGRAPH2 if ((indvertlocnum - orggrafptr->baseval) != indvertnbr) { errorPrint ("dgraphInducePart: inconsistent data (1)"); dgraphExit (indgrafptr); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (dgraphHaloSync (orggrafptr, (byte *) (orgindxgsttax + orggrafptr->baseval), GNUM_MPI) != 0) { /* Share global indexing of subgraph vertices */ errorPrint ("dgraphInducePart: cannot perform halo exchange"); dgraphExit (indgrafptr); return (1); } indedloloctax = (orggrafptr->edloloctax != NULL) ? indgrafptr->edgeloctax + indedgelocmax : NULL; inddegrlocmax = 0; for (indvertlocnum = indedgelocnum = orggrafptr->baseval; indvertlocnum < indvertlocnnd; indvertlocnum ++) { Gnum orgvertlocnum; Gnum orgedgelocnum; orgvertlocnum = indgrafptr->vnumloctax[indvertlocnum]; indgrafptr->vertloctax[indvertlocnum] = indedgelocnum; if (indgrafptr->veloloctax != NULL) { /* If graph has vertex weights */ indvelolocsum += /* Accumulate vertex loads */ indgrafptr->veloloctax[indvertlocnum] = orggrafptr->veloloctax[orgvertlocnum]; } for (orgedgelocnum = orggrafptr->vertloctax[orgvertlocnum]; orgedgelocnum < orggrafptr->vendloctax[orgvertlocnum]; orgedgelocnum ++) { Gnum indvertgstend; indvertgstend = orgindxgsttax[orggrafptr->edgegsttax[orgedgelocnum]]; if (indvertgstend != ~0) { /* If edge should be kept */ indgrafptr->edgeloctax[indedgelocnum] = indvertgstend; if (indedloloctax != NULL) indedloloctax[indedgelocnum] = orggrafptr->edloloctax[orgedgelocnum]; indedgelocnum ++; } } if (inddegrlocmax < (indedgelocnum - indgrafptr->vertloctax[indvertlocnum])) inddegrlocmax = (indedgelocnum - indgrafptr->vertloctax[indvertlocnum]); } indedgelocnbr = indedgelocnum - orggrafptr->baseval; indgrafptr->vertloctax[indvertlocnum] = indedgelocnum; /* Mark end of edge array */ indgrafptr->baseval = orggrafptr->baseval; indgrafptr->vertlocnbr = indvertnbr; indgrafptr->vertlocnnd = indvertnbr + indgrafptr->baseval; indgrafptr->vendloctax = indgrafptr->vertloctax + 1; /* Induced graph is compact */ indgrafptr->velolocsum = indvelolocsum; indgrafptr->edgelocnbr = indedgelocnbr; indgrafptr->edgelocsiz = indedgelocnbr; if (indedloloctax != NULL) { /* Re-allocate arrays and delete orgindxtab */ size_t indedlooftval; /* Offset of edge load array with respect to edge array */ indedlooftval = indedloloctax - indgrafptr->edgeloctax; indgrafptr->edgeloctax = memRealloc (indgrafptr->edgeloctax + orggrafptr->baseval, (indedlooftval + indedgelocnbr) * sizeof (Gnum)); indgrafptr->edgeloctax -= orggrafptr->baseval; indedloloctax = indgrafptr->edgeloctax + indedlooftval; /* Use old index into old array as new index to avoid alignment problems */ } else { indgrafptr->edgeloctax = memRealloc (indgrafptr->edgeloctax + orggrafptr->baseval, indedgelocnbr * sizeof (Gnum)); indgrafptr->edgeloctax -= orggrafptr->baseval; } indvertlocnum = indgrafptr->baseval; if (orggrafptr->vnumloctax != NULL) { /* Adjust vnumloctax */ for ( ; indvertlocnum < indvertlocnnd; indvertlocnum ++) indgrafptr->vnumloctax[indvertlocnum] = orggrafptr->vnumloctax[indgrafptr->vnumloctax[indvertlocnum]]; } else { Gnum orgvertglbadj; orgvertglbadj = orggrafptr->procvrttab[orggrafptr->proclocnum] - orggrafptr->baseval; /* Set adjustement for global indexing */ for ( ; indvertlocnum < indvertlocnnd; indvertlocnum ++) indgrafptr->vnumloctax[indvertlocnum] += orgvertglbadj; } indgrafptr->edloloctax = indedloloctax; indgrafptr->degrglbmax = inddegrlocmax; /* Local maximum degree will be turned into global maximum degree */ if (dgraphBuild4 (indgrafptr) != 0) { errorPrint ("dgraphInducePart: cannot build induced graph"); return (1); } #ifdef SCOTCH_DEBUG_DGRAPH2 if (dgraphCheck (indgrafptr) != 0) { /* Check graph consistency */ errorPrint ("dgraphInducePart: inconsistent graph data (2)"); dgraphExit (indgrafptr); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/vdgraph_separate_sq.h0000644000175300017530000000606511631334325023335 0ustar hazelscthazelsct/* Copyright 2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_separate_sq.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declaration **/ /** for the sequential vertex separation **/ /** routine for distributed graphs. **/ /** **/ /** DATES : # Version 5.0 : from : 15 feb 2006 **/ /** to : 01 mar 2006 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct VdgraphSeparateSqParam_ { Strat * strat; /*+ Sequential separation strategy used +*/ } VdgraphSeparateSqParam; /* ** The function prototypes. */ #ifndef VDGRAPH_SEPARATE_SQ #define static #endif int vdgraphSeparateSq (Vdgraph * const, const VdgraphSeparateSqParam * const); static void vdgraphSeparateSqOpBest (const Gnum * const, Gnum * const, const int * const, const MPI_Datatype * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/bgraph_bipart_zr.h0000644000175300017530000000570611631334325022633 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : bgraph_bipart_zr.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : Part of a static mapper. **/ /** These lines are the data declarations **/ /** for the move-all-to-first-subdomain **/ /** bipartitioning module. **/ /** **/ /** DATES : # Version 3.2 : from : 23 aug 1996 **/ /** to 19 oct 1996 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 01 nov 2003 **/ /** to 01 nov 2003 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef BGRAPH_BIPART_ZR #define static #endif int bgraphBipartZr (Bgraph * restrict const); #undef static scotch-5.1.12b.dfsg/src/libscotch/dorder_perm.c0000644000175300017530000002457211631334325021613 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dorder_gather.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module handles distributed **/ /** orderings. **/ /** **/ /** DATES : # Version 5.0 : from : 13 oct 2007 **/ /** to 21 oct 2007 **/ /** # Version 5.1 : from : 26 sep 2008 **/ /** to 26 sep 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DORDER #include "module.h" #include "common.h" #include "dgraph.h" #include "dorder.h" #include "dorder_perm.h" /************************************/ /* */ /* These routines handle orderings. */ /* */ /************************************/ /* This function builds a distributed direct ** permutation from the information stored ** in the distributed ordering structure. ** It returns: ** - 0 : if the distributed permutation could be computed. ** - !0 : on error. */ int dorderPerm ( const Dorder * restrict const ordeptr, const Dgraph * restrict const grafptr, Gnum * restrict const permloctab) { Gnum * restrict permloctax; int * restrict sendcnttab; int * restrict senddsptab; int * restrict recvcnttab; int * restrict recvdsptab; DorderPermSort * restrict sortsndtab; DorderPermSort * restrict sortrcvtab; const DorderLink * restrict linklocptr; Gnum vnodlocnbr; Gnum vnodlocnum; int vnodrcvnbr; int vnodsndnbr; int procnum; Gnum reduloctab[2]; Gnum reduglbtab[2]; for (linklocptr = ordeptr->linkdat.nextptr, vnodlocnbr = 0; /* For all nodes in local ordering structure */ linklocptr != &ordeptr->linkdat; linklocptr = linklocptr->nextptr) { const DorderCblk * restrict cblklocptr; cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ if ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) /* If node is leaf */ vnodlocnbr += cblklocptr->data.leaf.vnodlocnbr; /* And more node vertices */ #ifdef SCOTCH_DEBUG_DORDER2 else if (cblklocptr->typeval != DORDERCBLKNEDI) { errorPrint ("dorderPerm: invalid parameters (1)"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ } reduloctab[0] = vnodlocnbr; reduloctab[1] = 0; if (memAllocGroup ((void **) (void *) &senddsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), &sendcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), &recvdsptab, (size_t) (grafptr->procglbnbr * sizeof (int)), &recvcnttab, (size_t) (grafptr->procglbnbr * sizeof (int)), &sortsndtab, (size_t) ((vnodlocnbr + 1) * sizeof (DorderPermSort)), /* "+1" for end marker */ &sortrcvtab, (size_t) (grafptr->vertlocnbr * sizeof (DorderPermSort)), NULL) == NULL) { errorPrint ("dorderPerm: out of memory"); reduloctab[1] = 1; } if (MPI_Allreduce (reduloctab, reduglbtab, 2, GNUM_MPI, MPI_SUM, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderPerm: communication error (1)"); reduglbtab[1] = 1; } if (reduglbtab[1] != 0) { if (senddsptab != NULL) memFree (senddsptab); /* Free group leader */ return (1); } if (reduglbtab[0] == 0) { /* If ordering structure is empty */ Gnum ordelocval; /* Based permutation start index */ memFree (senddsptab); /* Free group leader */ for (vnodlocnum = 0, ordelocval = grafptr->procvrttab[grafptr->proclocnum]; /* Build identity permutation */ vnodlocnum < grafptr->vertlocnbr; vnodlocnum ++) permloctab[vnodlocnum] = ordelocval ++; return (0); } if (reduglbtab[0] != grafptr->vertglbnbr) { errorPrint ("dorderPerm: invalid parameters (2)"); memFree (senddsptab); /* Free group leader */ return (1); } for (linklocptr = ordeptr->linkdat.nextptr, vnodlocnum = 0; /* For all nodes in local ordering structure */ linklocptr != &ordeptr->linkdat; linklocptr = linklocptr->nextptr) { const DorderCblk * restrict cblklocptr; cblklocptr = (DorderCblk *) linklocptr; /* TRICK: FIRST */ if ((cblklocptr->typeval & DORDERCBLKLEAF) != 0) { /* If node is leaf */ Gnum leaflocnbr; Gnum leaflocnum; Gnum ordelocval; /* Based permutation start index */ for (leaflocnum = 0, leaflocnbr = cblklocptr->data.leaf.vnodlocnbr, ordelocval = cblklocptr->data.leaf.ordelocval + ordeptr->baseval; leaflocnum < leaflocnbr; leaflocnum ++, vnodlocnum ++) { sortsndtab[vnodlocnum].vertnum = cblklocptr->data.leaf.periloctab[leaflocnum]; sortsndtab[vnodlocnum].permnum = ordelocval + leaflocnum; #ifdef SCOTCH_DEBUG_DORDER2 if ((sortsndtab[vnodlocnum].vertnum < ordeptr->baseval) || (sortsndtab[vnodlocnum].vertnum > (ordeptr->baseval + ordeptr->vnodglbnbr)) || (sortsndtab[vnodlocnum].permnum < ordeptr->baseval) || (sortsndtab[vnodlocnum].permnum > (ordeptr->baseval + ordeptr->vnodglbnbr))) { errorPrint ("dorderPerm: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ } } } sortsndtab[vnodlocnbr].vertnum = /* Set end marker */ sortsndtab[vnodlocnbr].permnum = GNUMMAX; intSort2asc1 (sortsndtab, vnodlocnbr); /* Sort permutation array by original vertex numbers, without marker */ for (vnodlocnum = 0, procnum = 0; procnum < grafptr->procglbnbr; ) { Gnum vnodsndnbr; Gnum procdspval; vnodsndnbr = 0; procdspval = grafptr->procdsptab[procnum + 1]; while (sortsndtab[vnodlocnum].vertnum < procdspval) { vnodsndnbr ++; vnodlocnum ++; #ifdef SCOTCH_DEBUG_DORDER2 if (vnodlocnum > vnodlocnbr) { /* If beyond regular indices plus end marker */ errorPrint ("dorderPerm: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ } sendcnttab[procnum ++] = (int) (vnodsndnbr * 2); /* Communication array for MPI, so (int), and "*2" because a Sort is 2 Gnums */ } #ifdef SCOTCH_DEBUG_DORDER2 if (vnodlocnum != vnodlocnbr) { errorPrint ("dorderPerm: internal error (3)"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ if (MPI_Alltoall (sendcnttab, 1, MPI_INT, recvcnttab, 1, MPI_INT, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderPerm: communication error (2)"); return (1); } for (procnum = 0, vnodrcvnbr = vnodsndnbr = 0; procnum < grafptr->procglbnbr; procnum ++) { /* Accumulate send and receive indices */ recvdsptab[procnum] = vnodrcvnbr; vnodrcvnbr += recvcnttab[procnum]; /* Accumulate "*2" values as counts */ senddsptab[procnum] = vnodsndnbr; vnodsndnbr += sendcnttab[procnum]; } if (MPI_Alltoallv (sortsndtab, sendcnttab, senddsptab, GNUM_MPI, sortrcvtab, recvcnttab, recvdsptab, GNUM_MPI, ordeptr->proccomm) != MPI_SUCCESS) { errorPrint ("dorderPerm: communication error (3)"); return (1); } #ifdef SCOTCH_DEBUG_DORDER2 memSet (permloctab, ~0, grafptr->vertlocnbr * sizeof (Gnum)); #endif /* SCOTCH_DEBUG_DORDER2 */ permloctax = permloctab - grafptr->procdsptab[grafptr->proclocnum]; /* Base local array through global indices */ for (vnodlocnum = 0; vnodlocnum < grafptr->vertlocnbr; vnodlocnum ++) { #ifdef SCOTCH_DEBUG_DORDER2 if (permloctax[sortrcvtab[vnodlocnum].vertnum] != ~0) { errorPrint ("dorderPerm: internal error (4)"); return (1); } #endif /* SCOTCH_DEBUG_DORDER2 */ permloctax[sortrcvtab[vnodlocnum].vertnum] = sortrcvtab[vnodlocnum].permnum; } #ifdef SCOTCH_DEBUG_DORDER2 for (vnodlocnum = 0; vnodlocnum < grafptr->vertlocnbr; vnodlocnum ++) { if (permloctab[vnodlocnum] == ~0) { errorPrint ("dorderPerm: internal error (5)"); return (1); } } #endif /* SCOTCH_DEBUG_DORDER2 */ memFree (senddsptab); /* Free group leader */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/kgraph_map_rb.c0000644000175300017530000001221511631334325022074 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kgraph_map_rb.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module performs the Dual Recursive **/ /** Bipartitioning mapping algorithm. **/ /** It is now a branching routine. **/ /** **/ /** DATES : # Version 0.0 : from : 31 mar 1993 **/ /** to 31 mar 1993 **/ /** # Version 1.0 : from : 04 oct 1993 **/ /** to 06 oct 1993 **/ /** # Version 1.1 : from : 15 oct 1993 **/ /** to 15 oct 1993 **/ /** # Version 1.3 : from : 09 apr 1994 **/ /** to 11 may 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to 17 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to 18 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 19 oct 1995 **/ /** # Version 3.1 : from : 30 oct 1995 **/ /** to 14 jun 1996 **/ /** # Version 3.2 : from : 23 aug 1996 **/ /** to 07 sep 1998 **/ /** # Version 3.3 : from : 19 oct 1998 **/ /** to 08 dec 1998 **/ /** # Version 3.4 : from : 01 jun 2001 **/ /** to 07 nov 2001 **/ /** # Version 4.0 : from : 12 jan 2004 **/ /** to 06 mar 2005 **/ /** # Version 5.1 : from : 22 nov 2007 **/ /** to 07 oct 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define KGRAPH_MAP_RB #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "arch.h" #include "mapping.h" #include "bgraph.h" #include "bgraph_bipart_st.h" #include "kgraph.h" #include "kgraph_map_rb.h" #include "kgraph_map_rb_map.h" #include "kgraph_map_rb_part.h" /********************************************/ /* */ /* This is the entry point for the Dual */ /* Recursive Bipartitioning mapping method. */ /* */ /********************************************/ /* This routine runs the Dual Recursive ** Bipartitioning algorithm. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int kgraphMapRb ( Kgraph * restrict const grafptr, const KgraphMapRbParam * restrict const paraptr) { int o; o = (archPart (&grafptr->m.archdat) ? kgraphMapRbPart : kgraphMapRbMap) (grafptr, paraptr); if (o != 0) return (o); #ifdef SCOTCH_DEBUG_KGRAPH2 if (kgraphCheck (grafptr) != 0) { errorPrint ("kgraphMapRb: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_KGRAPH2 */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/library_graph_check.c0000644000175300017530000000650511631334325023267 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_check.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the source **/ /** graph handling routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 3.2 : from : 18 aug 1998 **/ /** to 18 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to 01 nov 2001 **/ /** # Version 4.0 : from : 11 dec 2001 **/ /** to 22 apr 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "graph.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the graph handling routines. */ /* */ /************************************/ /*+ This routine checks the consistency *** of the given graph. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphCheck ( const SCOTCH_Graph * const grafptr) { return (graphCheck ((const Graph * const) grafptr)); } scotch-5.1.12b.dfsg/src/libscotch/vgraph.c0000644000175300017530000000757511631334325020604 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the separator **/ /** handling routines. **/ /** **/ /** DATES : # Version 3.2 : from : 24 aug 1996 **/ /** to 03 nov 1997 **/ /** # Version 4.0 : from : 12 dec 2001 **/ /** to 08 jan 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VGRAPH #include "module.h" #include "common.h" #include "graph.h" #include "vgraph.h" /*************************/ /* */ /* These routines handle */ /* separator graphs. */ /* */ /*************************/ /* This routine frees the contents ** of the given active graph. ** It returns: ** - VOID : in all cases. */ void vgraphExit ( Vgraph * const grafptr) { if (grafptr->parttax != NULL) memFree (grafptr->parttax + grafptr->s.baseval); if (grafptr->frontab != NULL) memFree (grafptr->frontab); graphFree (&grafptr->s); /* Free source graph */ #ifdef SCOTCH_DEBUG_VGRAPH2 memSet (grafptr, ~0, sizeof (Vgraph)); #endif /* SCOTCH_DEBUG_VGRAPH2 */ } /* This routine moves all of the graph ** vertices to the first part. ** It returns: ** - VOID : in all cases. */ void vgraphZero ( Vgraph * const grafptr) { memSet (grafptr->parttax + grafptr->s.baseval, 0, grafptr->s.vertnbr * sizeof (GraphPart)); /* Set all vertices to part 0 */ grafptr->compload[0] = grafptr->s.velosum; /* No frontier vertices */ grafptr->compload[1] = grafptr->compload[2] = 0; grafptr->comploaddlt = grafptr->s.velosum; grafptr->compsize[0] = grafptr->s.vertnbr; grafptr->compsize[1] = grafptr->fronnbr = 0; } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_gg.c0000644000175300017530000003343711631334325023141 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_gg.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module separates an active **/ /** graph using a vertex-oriented version **/ /** of the Greedy Graph Growing algorithm. **/ /** **/ /** DATES : # Version 3.2 : from : 10 nov 1997 **/ /** to 15 jul 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 19 dec 2001 **/ /** to 22 jan 2004 **/ /** # Version 5.0 : from : 02 jan 2007 **/ /** to 24 mar 2008 **/ /** # Version 5.1 : from : 09 nov 2008 **/ /** to 09 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VGRAPH_SEPARATE_GG #include "module.h" #include "common.h" #include "gain.h" #include "graph.h" #include "vgraph.h" #include "vgraph_separate_gg.h" /* ** The static variables. */ static const Gnum vgraphseparateggloadone = 1; /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the bipartitioning. ** It returns: ** - 0 : if the bipartitioning could be computed. ** - !0 : on error. */ int vgraphSeparateGg ( Vgraph * restrict const grafptr, /*+ Separation graph +*/ const VgraphSeparateGgParam * const paraptr) /*+ Method parameters +*/ { GainTabl * restrict tablptr; /* Pointer to gain table */ VgraphSeparateGgVertex * restrict vexxtax; /* Complementary vertex array */ Gnum vertnum; /* Index of current vertex */ Gnum * restrict permtab; /* Table for finding new roots */ Gnum permnum; /* Current permutation index */ Gnum fronnum; INT passnum; const Gnum * restrict velobax; /* Data for handling optional arrays */ Gnum velomsk; /* Mask for handling optional arrays */ Gnum comploaddlt; Gnum compload2; Gnum compsize1; Gnum compsize2; if (((tablptr = gainTablInit (GAIN_LINMAX, VGRAPHSEPAGGSUBBITS)) == NULL) || /* Use logarithmic array only */ ((vexxtax = (VgraphSeparateGgVertex *) memAlloc (grafptr->s.vertnbr * sizeof (VgraphSeparateGgVertex))) == NULL)) { errorPrint ("vgraphSeparateGg: out of memory (1)"); if (tablptr != NULL) gainTablExit (tablptr); return (1); } vexxtax -= grafptr->s.baseval; /* Base access to vexxtax */ permtab = NULL; /* Do not allocate permutation array yet */ if (grafptr->s.velotax == NULL) { /* Set accesses to optional arrays */ velobax = &vgraphseparateggloadone; /* In case vertices not weighted (least often) */ velomsk = 0; } else { velobax = grafptr->s.velotax; velomsk = ~((Gnum) 0); } for (passnum = 0; passnum < paraptr->passnbr; passnum ++) { /* For all passes */ VgraphSeparateGgVertex * vexxptr; /* Pointer to current vertex to swap */ memSet (vexxtax + grafptr->s.baseval, 0, grafptr->s.vertnbr * sizeof (VgraphSeparateGgVertex)); /* All vertices to part 0 */ gainTablFree (tablptr); /* Reset gain table */ permnum = 0; /* No permutation built yet */ comploaddlt = grafptr->s.velosum; /* Reset separation parameters */ compload2 = 0; vexxptr = vexxtax + (grafptr->s.baseval + intRandVal (grafptr->s.vertnbr)); /* Randomly select first root vertex */ do { /* Loop on root vertices */ Gnum vertnum; /* Number of current vertex */ Gnum veloval; /* Load of selected vertex */ Gnum compgain2; vexxptr->gainlink.next = /* TRICK: allow deletion of root vertex */ vexxptr->gainlink.prev = (GainLink *) vexxptr; #ifdef SCOTCH_DEBUG_GAIN2 vexxptr->gainlink.tabl = NULL; #endif /* SCOTCH_DEBUG_GAIN2 */ vertnum = vexxptr - vexxtax; /* Get root vertex based number */ if (grafptr->s.velotax == NULL) { /* If vertices not weighted */ veloval = 1; compgain2 = grafptr->s.vendtax[vertnum] - grafptr->s.verttax[vertnum] - 1; } else { /* Graph vertices are weighted */ Gnum edgenum; veloval = grafptr->s.velotax[vertnum]; compgain2 = - veloval; for (edgenum = grafptr->s.verttax[vertnum]; edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) compgain2 += grafptr->s.velotax[grafptr->s.edgetax[edgenum]]; } vexxptr->compgain2 = compgain2; /* Set root gain (root not in separator) */ comploaddlt -= veloval; /* Move vertex from part 0 to separator */ compload2 += veloval; do { /* While vertices can be retrieved */ VgraphSeparateGgVertex * sepaptr; /* List of vertices in separator */ Gnum veloval; /* Load of selected vertex */ Gnum edgenum; vertnum = vexxptr - vexxtax; /* Get number of selected vertex */ veloval = velobax[vertnum & velomsk]; if (comploaddlt < abs (comploaddlt - veloval)) { /* If swapping would cause imbalance */ permnum = grafptr->s.vertnbr; /* Terminate swapping process */ vexxptr = NULL; break; } gainTablDel (tablptr, (GainLink *) vexxptr); /* Remove vertex from table */ vexxptr->gainlink.next = VGRAPHSEPAGGSTATEPART1; /* Put vertex in part 1 */ compload2 += vexxptr->compgain2; /* Update partition parameters */ comploaddlt -= vexxptr->compgain2 + 2 * veloval; sepaptr = NULL; /* No separator vertices to relink yet */ for (edgenum = grafptr->s.verttax[vertnum]; /* (Re-)link neighbor vertices */ edgenum < grafptr->s.vendtax[vertnum]; edgenum ++) { Gnum vertend; VgraphSeparateGgVertex * vexxend; vertend = grafptr->s.edgetax[edgenum]; /* Point to end vertex */ vexxend = vexxtax + vertend; if (vexxend->gainlink.next == VGRAPHSEPAGGSTATEPART0) { /* If end in part 0 */ Gnum veloend; Gnum edgtnum; Gnum compgain2; vexxend->gainlink.next = VGRAPHSEPAGGSTATEPART2; /* Move vertex to separator */ vexxend->gainlink.prev = (GainLink *) sepaptr; /* Chain vertex */ sepaptr = vexxend; veloend = velobax[vertend & velomsk]; compgain2 = - veloend; for (edgtnum = grafptr->s.verttax[vertend]; edgtnum < grafptr->s.vendtax[vertend]; edgtnum ++) { Gnum vertent; VgraphSeparateGgVertex * vexxent; vertent = grafptr->s.edgetax[edgtnum]; /* Point to end vertex */ vexxent = vexxtax + vertent; if (vexxent->gainlink.next == VGRAPHSEPAGGSTATEPART0) compgain2 += velobax[vertent & velomsk]; else if (vexxent->gainlink.next >= VGRAPHSEPAGGSTATEPART2) { vexxent->compgain2 -= veloend; if (vexxent->gainlink.next >= VGRAPHSEPAGGSTATELINK) { gainTablDel (tablptr, (GainLink *) vexxent); /* Unlink vertex */ vexxent->gainlink.next = VGRAPHSEPAGGSTATEPART2; /* Chain vertex */ vexxent->gainlink.prev = (GainLink *) sepaptr; sepaptr = vexxent; } } } vexxend->compgain2 = compgain2; } } while (sepaptr != NULL) { /* For all vertices in chain list */ vexxptr = sepaptr; /* Unlink vertex from list */ sepaptr = (VgraphSeparateGgVertex *) vexxptr->gainlink.prev; gainTablAdd (tablptr, (GainLink *) vexxptr, vexxptr->compgain2); /* Relink it */ } } while ((vexxptr = (VgraphSeparateGgVertex *) gainTablFrst (tablptr)) != NULL); if (permnum == 0) { /* If permutation has not been built yet */ if (permtab == NULL) { /* If permutation array not allocated yet */ if ((permtab = (Gnum *) memAlloc (grafptr->s.vertnbr * sizeof (Gnum))) == NULL) { errorPrint ("vgraphSeparateGg: out of memory (2)"); memFree (vexxtax + grafptr->s.baseval); gainTablExit (tablptr); return (1); } intAscn (permtab, grafptr->s.vertnbr, grafptr->s.baseval); /* Initialize based permutation array */ } intPerm (permtab, grafptr->s.vertnbr); /* Build random permutation */ } for ( ; permnum < grafptr->s.vertnbr; permnum ++) { /* Find next root vertex */ if (vexxtax[permtab[permnum]].gainlink.next == VGRAPHSEPAGGSTATEPART0) { vexxptr = vexxtax + permtab[permnum ++]; break; } } } while (vexxptr != NULL); if ((passnum == 0) || /* If first try */ ( (grafptr->compload[2] > compload2) || /* Or if better solution reached */ ((grafptr->compload[2] == compload2) && (abs (grafptr->comploaddlt) > abs (comploaddlt))))) { Gnum vertnum; grafptr->comploaddlt = comploaddlt; /* Set graph parameters */ grafptr->compload[2] = compload2; for (vertnum = grafptr->s.baseval; vertnum < grafptr->s.vertnnd; vertnum ++) /* Copy bipartition state */ grafptr->parttax[vertnum] = (vexxtax[vertnum].gainlink.next <= VGRAPHSEPAGGSTATEPART2) ? (GraphPart) (intptr_t) vexxtax[vertnum].gainlink.next : (GraphPart) 2; } } if (permtab != NULL) /* Free work arrays */ memFree (permtab); memFree (vexxtax + grafptr->s.baseval); gainTablExit (tablptr); grafptr->compload[0] = (grafptr->s.velosum + grafptr->comploaddlt - grafptr->compload[2]) / 2; grafptr->compload[1] = grafptr->s.velosum - grafptr->compload[2] - grafptr->compload[0]; compsize1 = compsize2 = 0; for (vertnum = grafptr->s.baseval, fronnum = 0; vertnum < grafptr->s.vertnnd; vertnum ++) { Gnum partval; partval = (Gnum) grafptr->parttax[vertnum]; compsize1 += (partval & 1); /* Superscalar update */ compsize2 += (partval >> 1); if (partval == 2) /* If vertex belongs to frontier */ grafptr->frontab[fronnum ++] = vertnum; /* Record it in frontier array */ } grafptr->compsize[0] = grafptr->s.vertnbr - compsize1 - compsize2; grafptr->compsize[1] = compsize1; grafptr->fronnbr = compsize2; #ifdef SCOTCH_DEBUG_VGRAPH2 if (vgraphCheck (grafptr) != 0) { errorPrint ("vgraphSeparateGg: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_hd.h0000644000175300017530000000666011631334325022266 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_hd.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data declara- **/ /** tions for the block-oriented Halo **/ /** Approximate (Multiple) Minimum Degree **/ /** mesh ordering routine. **/ /** **/ /** DATES : # Version 4.0 : from : 09 dec 2003 **/ /** to 10 dec 2003 **/ /** # Version 5.1 : from : 01 oct 2009 **/ /** to : 01 oct 2009 **/ /** **/ /************************************************************/ /* ** The defines. */ #define HMESHORDERHDCOMPRAT 1.2L /*+ Compression ratio +*/ /* ** The type and structure definitions. */ /*+ This structure holds the method parameters. +*/ typedef struct HmeshOrderHdParam_ { INT colmin; /*+ Minimum number of columns +*/ INT colmax; /*+ Maximum number of columns +*/ double fillrat; /*+ Fill-in ratio +*/ } HmeshOrderHdParam; /* ** The function prototypes. */ #ifndef HMESH_ORDER_HD #define static #endif int hmeshOrderHd (const Hmesh * restrict const, Order * restrict const, const Gnum, OrderCblk * restrict const, const HmeshOrderHdParam * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/vmesh_separate_gg.c0000644000175300017530000005551711631334325022777 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh_separate_gg.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module separates a node separation **/ /** mesh using an element-oriented version **/ /** of the Greedy Graph Growing algorithm. **/ /** **/ /** DATES : # Version 4.0 : from : 16 sep 2002 **/ /** to 18 aug 2004 **/ /** # Version 5.0 : from : 12 sep 2007 **/ /** to 24 mar 2008 **/ /** # Version 5.1 : from : 09 nov 2008 **/ /** to 09 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VMESH_SEPARATE_GG #include "module.h" #include "common.h" #include "gain.h" #include "graph.h" #include "mesh.h" #include "vmesh.h" #include "vmesh_separate_gg.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the bipartitioning. ** It returns: ** - 0 : if the bipartitioning could be computed. ** - !0 : on error. */ int vmeshSeparateGg ( Vmesh * restrict const meshptr, /*+ Node separation mesh +*/ const VmeshSeparateGgParam * restrict const paraptr) /*+ Method parameters +*/ { GainTabl * restrict tablptr; /* Pointer to gain table */ byte * restrict vexxtab; /* Start of auxiliary arrays */ Gnum vexxsiz; /* Size of auxiliary arrays to be reset every pass */ VmeshSeparateGgElem * restrict velxtax; /* Based auxiliary element array */ VmeshSeparateGgNode * restrict vnoxtax; /* Based auxiliary node array */ Gnum * restrict velitax; /* Array of sums of weights of isolated neighboring nodes of elements */ Gnum * restrict velstax; /* Array of sums of weights of neighboring nodes of elements */ Gnum velssiz; /* Size of element neighboring node load sum array */ VmeshSeparateGgElem * sepaptr; /* Head of chained list of elements to re-link */ Gnum * restrict permtab; /* Element permutation table for finding new roots */ Gnum * permptr; /* Pointer to current permutation index */ INT passnum; /* Number of current pass */ Gnum ecmpsize0; /* Number of elements in part 0 */ Gnum ncmploaddlt; /* Current imbalance of bipartition */ Gnum ncmpload2; /* Current number of nodes in separator */ Gnum vnodnum; Gnum fronnum; Gnum ncmpsize1; Gnum ncmpsize2; if (meshptr->m.velmnbr == 0) { /* If only a single node or disconnected nodes */ vmeshZero (meshptr); /* Don't bother with parts */ return (0); } velssiz = (meshptr->m.vnlotax == NULL) ? 0 : meshptr->m.velmnbr; /* Compute size of vetex load sum array */ if (((tablptr = gainTablInit (GAINMAX, VMESHSEPAGGSUBBITS)) == NULL) || /* Use logarithmic array only */ ((vexxtab = (byte *) memAllocGroup ((void **) (void *) &velxtax, (size_t) (meshptr->m.velmnbr * sizeof (VmeshSeparateGgElem)), &vnoxtax, (size_t) (meshptr->m.vnodnbr * sizeof (VmeshSeparateGgNode)), &velitax, (size_t) (meshptr->m.velmnbr * sizeof (Gnum)), &velstax, (size_t) (velssiz * sizeof (Gnum)), NULL)) == NULL)) { /* Indicates end of group allocated array */ if (tablptr != NULL) gainTablExit (tablptr); errorPrint ("vmeshSeparateGg: out of memory (1)"); return (1); } vexxsiz = (byte *) velitax - vexxtab; /* Size of arrays that must be reset at each pass */ velxtax -= meshptr->m.velmbas; /* Base access to auxiliary arrays */ vnoxtax -= meshptr->m.vnodbas; velitax -= meshptr->m.velmbas; if (velssiz == 0) { /* If no vertex load array */ Gnum velmnum; for (velmnum = meshptr->m.velmbas; velmnum < meshptr->m.velmnnd; velmnum ++) { Gnum eelmnum; Gnum velisum; for (eelmnum = meshptr->m.verttax[velmnum], velisum = 0; eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { Gnum vnodnum; vnodnum = meshptr->m.edgetax[eelmnum]; if ((meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]) == 1) velisum --; } velitax[velmnum] = velisum; } } else { Gnum velmnum; velstax -= meshptr->m.velmbas; for (velmnum = meshptr->m.velmbas; velmnum < meshptr->m.velmnnd; velmnum ++) { Gnum eelmnum; Gnum velisum; Gnum velssum; for (eelmnum = meshptr->m.verttax[velmnum], velisum = velssum = 0; eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { Gnum vnodnum; Gnum vnloval; vnodnum = meshptr->m.edgetax[eelmnum]; vnloval = meshptr->m.vnlotax[vnodnum]; velssum += vnloval; if ((meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]) == 1) velisum -= vnloval; } velitax[velmnum] = velisum; velstax[velmnum] = velssum; } } permtab = NULL; /* Do not allocate permutation array yet */ for (passnum = 0; passnum < paraptr->passnbr; passnum ++) { /* For all passes */ VmeshSeparateGgElem * velxptr; /* Pointer to selected element */ memSet (vexxtab, 0, vexxsiz); /* All vertices to part 0 */ gainTablFree (tablptr); /* Reset gain table */ permptr = NULL; /* No permutation built yet */ ecmpsize0 = meshptr->m.velmnbr; /* All elements to part 0 */ ncmpload2 = 0; /* Reset separation parameters */ ncmploaddlt = meshptr->m.vnlosum; velxptr = (VmeshSeparateGgElem *) vexxtab + intRandVal (meshptr->m.velmnbr); /* Randomly select first root element vertex */ do { /* Loop on root element vertices */ Gnum velmnum; /* Number of current element to process */ velxptr->gainlink.next = /* TRICK: allow deletion of root vertex */ velxptr->gainlink.prev = (GainLink *) velxptr; velmnum = velxptr - velxtax; /* Get root element number */ { Gnum ncmpgain1; /* Gain (2->1) */ Gnum ncmpgain2; /* Gain (0->2) */ ncmpgain2 = (meshptr->m.vnlotax == NULL) /* Set gains */ ? meshptr->m.vendtax[velmnum] - meshptr->m.verttax[velmnum] : velstax[velmnum]; ncmpgain1 = velitax[velmnum]; velxptr->ncmpgain2 = ncmpgain1 + ncmpgain2; velxptr->ncmpgaindlt = ncmpgain1 - ncmpgain2; } do { /* While element vertices can be retrieved */ Gnum eelmnum; /* Number of current element edge */ velmnum = velxptr - velxtax; /* Get based number of selected element */ if (ncmploaddlt < abs (ncmploaddlt + velxtax[velmnum].ncmpgaindlt)) { /* If swapping would cause imbalance */ permptr = permtab + meshptr->m.velmnbr; /* Terminate swapping process */ velxptr = NULL; break; } ecmpsize0 --; /* One less element in part 0 */ gainTablDel (tablptr, (GainLink *) velxptr); /* Remove element from table */ velxptr->gainlink.next = VMESHSEPAGGSTATEPART1; /* Move element to part 1 */ ncmpload2 += velxptr->ncmpgain2; /* Update partition parameters */ ncmploaddlt += velxptr->ncmpgaindlt; sepaptr = NULL; /* No frontier elements to relink yet */ for (eelmnum = meshptr->m.verttax[velmnum]; /* For all neighbor node vertices */ eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { Gnum vnodnum; /* Number of current node neighbor */ vnodnum = meshptr->m.edgetax[eelmnum]; /* Get number of neighbor node */ #ifdef SCOTCH_DEBUG_VMESH2 if (vnoxtax[vnodnum].partval == 1) { errorPrint ("vmeshSeparateGg: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ if (vnoxtax[vnodnum].partval == 0) { /* If yet untouched neighbor node */ Gnum enodnum; /* Current egde of current neighbor node */ Gnum vnloval; vnloval = (meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum]; vnoxtax[vnodnum].partval = 2; /* Node now belongs to separator */ vnoxtax[vnodnum].commsize0 = meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum] - 1; vnoxtax[vnodnum].velmisum0 = - velmnum; for (enodnum = meshptr->m.verttax[vnodnum]; /* For all its elements */ enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { Gnum velmend; velmend = meshptr->m.edgetax[enodnum]; /* Get neighbor element */ vnoxtax[vnodnum].velmisum0 += velmend; /* Sum-up element indices for neighbor node */ #ifdef SCOTCH_DEBUG_VMESH2 if ((velxtax[velmend].gainlink.next == VMESHSEPAGGSTATEPART1) && (velmend != velmnum)) { errorPrint ("vmeshSeparateGg: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ if (velxtax[velmend].gainlink.next == VMESHSEPAGGSTATEPART0) { /* If untouched element */ Gnum ncmpgain1; /* Gain (2->1) */ Gnum ncmpgain2; /* Gain (0->2) */ #ifdef SCOTCH_DEBUG_VMESH2 Gnum eelmend; #endif /* SCOTCH_DEBUG_VMESH2 */ velxtax[velmend].gainlink.next = VMESHSEPAGGSTATEPART2; /* Move element to frontier */ velxtax[velmend].gainlink.prev = (GainLink *) sepaptr; /* Chain vertex */ sepaptr = &velxtax[velmend]; ncmpgain2 = (meshptr->m.vnlotax == NULL) /* Set gains */ ? meshptr->m.vendtax[velmend] - meshptr->m.verttax[velmend] - 1 : velstax[velmend] - vnloval; ncmpgain1 = velitax[velmend]; #ifdef SCOTCH_DEBUG_VMESH2 for (eelmend = meshptr->m.verttax[velmend]; /* For all its neighboring nodes */ eelmend < meshptr->m.vendtax[velmend]; eelmend ++) { Gnum vnodend; vnodend = meshptr->m.edgetax[eelmend]; if ((vnoxtax[vnodend].partval == 1) || ((vnoxtax[vnodend].partval == 2) && (vnodend != vnodnum))) { errorPrint ("vmeshSeparateGg: internal error (3)"); return (1); } if (meshptr->m.vendtax[vnodend] - meshptr->m.verttax[vnodend] == 1) { if (vnoxtax[vnodend].partval != 0) { errorPrint ("vmeshSeparateGg: internal error (4)"); return (1); } } } #endif /* SCOTCH_DEBUG_VMESH2 */ velxtax[velmend].ncmpgain2 = ncmpgain1 + ncmpgain2; velxtax[velmend].ncmpgaindlt = ncmpgain1 - ncmpgain2; } else { /* Neighbor element belongs to frontier */ velxtax[velmend].ncmpgain2 -= vnloval; /* One less node to add to separator for element */ velxtax[velmend].ncmpgaindlt += vnloval; /* One less node to remove from part 0 */ if (velxtax[velmend].gainlink.next >= VMESHSEPAGGSTATELINK) { gainTablDel (tablptr, (GainLink *) &velxtax[velmend]); /* Unlink vertex */ velxtax[velmend].gainlink.next = VMESHSEPAGGSTATEPART2; /* Chain vertex */ velxtax[velmend].gainlink.prev = (GainLink *) sepaptr; sepaptr = &velxtax[velmend]; } } } } else { /* Neighbor node already in separator */ vnoxtax[vnodnum].commsize0 --; /* One less neighbor element in part 0 */ vnoxtax[vnodnum].velmisum0 -= velmnum; /* Subtract index of removed element */ } if (vnoxtax[vnodnum].commsize0 == 0) /* If node no longer has neighbors in part 0 */ vnoxtax[vnodnum].partval = 1; /* Node moves from separator to part 1 */ else if (vnoxtax[vnodnum].commsize0 == 1) { /* If only one neighbor element in part 0 */ Gnum velmend; /* Index of remaining element in part 0 */ Gnum vnloval; velmend = vnoxtax[vnodnum].velmisum0; /* Get neighbor element from remaining index */ #ifdef SCOTCH_DEBUG_VMESH2 if (velxtax[velmend].gainlink.next < VMESHSEPAGGSTATEPART2) { /* Element should have been declared in part 0 at this stage */ errorPrint ("vmeshSeparateGg: internal error (5)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ vnloval = (meshptr->m.vnlotax == NULL) ? 1 : meshptr->m.vnlotax[vnodnum]; velxtax[velmend].ncmpgain2 -= vnloval; velxtax[velmend].ncmpgaindlt -= vnloval; if (velxtax[velmend].gainlink.next >= VMESHSEPAGGSTATELINK) { gainTablDel (tablptr, (GainLink *) &velxtax[velmend]); /* Unlink vertex */ velxtax[velmend].gainlink.next = VMESHSEPAGGSTATEPART2; /* Chain vertex */ velxtax[velmend].gainlink.prev = (GainLink *) sepaptr; sepaptr = &velxtax[velmend]; } } } while (sepaptr != NULL) { /* For all vertices in chain list */ velxptr = sepaptr; /* Unlink vertex from list */ sepaptr = (VmeshSeparateGgElem *) velxptr->gainlink.prev; gainTablAdd (tablptr, (GainLink *) velxptr, velxptr->ncmpgain2); /* Relink it */ } #ifdef SCOTCH_DEBUG_VMESH3 if (vmeshSeparateGgCheck (meshptr, ncmpload2, ncmploaddlt, velxtax, vnoxtax) != 0) { errorPrint ("vmeshSeparateGg: internal error (6)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH3 */ } while ((velxptr = (VmeshSeparateGgElem *) gainTablFrst (tablptr)) != NULL); if (permptr == NULL) { /* If element permutation not yet built */ if (permtab == NULL) { /* If permutation array not yet allocated */ if ((permtab = (Gnum *) memAlloc (meshptr->m.velmnbr * sizeof (Gnum))) == NULL) { errorPrint ("vmeshSeparateGg: out of memory (2)"); memFree (vexxtab); gainTablExit (tablptr); return (1); } intAscn (permtab, meshptr->m.velmnbr, meshptr->m.baseval); /* Initialize permutation array */ } intPerm (permtab, meshptr->m.velmnbr); /* Build random permutation */ permptr = permtab; /* Start at beginning of permutation */ } for ( ; permptr < permtab + meshptr->m.velmnbr; permptr ++) { /* Find next root vertex */ #ifdef SCOTCH_DEBUG_VMESH2 if (velxtax[*permptr].gainlink.next >= VMESHSEPAGGSTATEPART2) { errorPrint ("vmeshSeparateGg: internal error (7)"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ if (velxtax[*permptr].gainlink.next == VMESHSEPAGGSTATEPART0) { velxptr = velxtax + (*permptr ++); break; } } } while (velxptr != NULL); if ((passnum == 0) || /* If it is the first try */ ( (meshptr->ncmpload[2] > ncmpload2) || /* Or if better solution reached */ ((meshptr->ncmpload[2] == ncmpload2) && (abs (meshptr->ncmploaddlt) > abs (ncmploaddlt))))) { Gnum vertnum; meshptr->ecmpsize[0] = ecmpsize0; /* Set graph parameters */ meshptr->ncmpload[2] = ncmpload2; meshptr->ncmploaddlt = ncmploaddlt; for (vertnum = meshptr->m.velmbas; vertnum < meshptr->m.velmnnd; vertnum ++) /* Copy element bipartition state */ meshptr->parttax[vertnum] = (velxtax[vertnum].gainlink.next == VMESHSEPAGGSTATEPART1) ? 1 : 0; for (vertnum = meshptr->m.vnodbas; vertnum < meshptr->m.vnodnnd; vertnum ++) /* Copy node bipartition state */ meshptr->parttax[vertnum] = vnoxtax[vertnum].partval; } } meshptr->ecmpsize[1] = meshptr->m.velmnbr - meshptr->ecmpsize[0]; meshptr->ncmpload[1] = ((meshptr->m.vnlosum - meshptr->ncmpload[2]) - meshptr->ncmploaddlt) >> 1; meshptr->ncmpload[0] = (meshptr->m.vnlosum - meshptr->ncmpload[2]) - meshptr->ncmpload[1]; for (vnodnum = meshptr->m.vnodbas, fronnum = 0, ncmpsize1 = ncmpsize2 = 0; vnodnum < meshptr->m.vnodnnd; vnodnum ++) { Gnum partval; partval = meshptr->parttax[vnodnum]; ncmpsize1 += (partval & 1); /* Superscalar update */ ncmpsize2 += (partval >> 1); if (partval == 2) meshptr->frontab[fronnum ++] = vnodnum; /* Vertex belongs to frontier */ } meshptr->ncmpsize[0] = meshptr->m.vnodnbr - (ncmpsize1 + ncmpsize2); meshptr->ncmpsize[1] = ncmpsize1; meshptr->fronnbr = ncmpsize2; #ifdef SCOTCH_DEBUG_VMESH2 if (vmeshCheck (meshptr) != 0) { errorPrint ("vmeshSeparateGg: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_VMESH2 */ if (permtab != NULL) memFree (permtab); memFree (vexxtab); /* Free group leader */ gainTablExit (tablptr); /* printf ("GG Sepa\tsize=%ld\tload=%ld\tbal=%ld\n", (long) meshptr->fronnbr, (long) meshptr->ncmpload[2], (long) meshptr->ncmploaddlt); */ return (0); } /* This routine checks the consistency ** of the current bipartition. ** It returns: ** - 0 : if the bipartition is consistent. ** - !0 : on error. */ #ifdef SCOTCH_DEBUG_VMESH3 static int vmeshSeparateGgCheck ( Vmesh * restrict const meshptr, const Gnum ncmpload2, const Gnum ncmploaddlt, const VmeshSeparateGgElem * restrict const velxtax, const VmeshSeparateGgNode * restrict const vnoxtax) { Gnum vnodnum; Gnum vnloval; Gnum ncmpsize0c; Gnum ncmpsize1c; Gnum ncmpsize2c; Gnum ncmpload0c; Gnum ncmpload1c; Gnum ncmpload2c; ncmpsize1c = ncmpsize2c = ncmpload1c = ncmpload2c = 0; vnloval = 1; for (vnodnum = meshptr->m.vnodbas; vnodnum < meshptr->m.vnodnnd; vnodnum ++) { int partval; Gnum partval1; Gnum partval2; partval = vnoxtax[vnodnum].partval; partval1 = partval & 1; partval2 = partval >> 1; if (meshptr->m.vnlotax != NULL) vnloval = meshptr->m.vnlotax[vnodnum]; if (partval > 2) { errorPrint ("vmeshSeparateGgCheck: invalid node part value"); return (1); } ncmpsize1c += partval1; ncmpsize2c += partval2; ncmpload1c += partval1 * vnloval; ncmpload2c += partval2 * vnloval; } ncmpsize0c = meshptr->m.vnodnbr - ncmpsize1c - ncmpsize2c; ncmpload0c = meshptr->m.vnlosum - ncmpload1c - ncmpload2c; if (ncmpload2c != ncmpload2) { errorPrint ("vmeshSeparateGgCheck: invalid separator size"); return (1); } if (ncmploaddlt != (ncmpload0c - ncmpload1c)) { errorPrint ("vmeshSeparateGgCheck: invalid separator balance"); return (1); } return (0); } #endif /* SCOTCH_DEBUG_VMESH3 */ scotch-5.1.12b.dfsg/src/libscotch/dgraph_view.c0000644000175300017530000001633311631334325021604 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_view.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the distributed graph general **/ /** purpose routines. **/ /** **/ /** DATES : # Version P0.0 : from : 01 apr 1997 **/ /** to 01 apr 1997 **/ /** # Version P0.1 : from : 12 apr 1998 **/ /** to 20 jun 1998 **/ /** # Version 5.0 : from : 16 feb 2005 **/ /** to : 15 aug 2006 **/ /** # Version 5.1 : from : 11 aug 2010 **/ /** to : 12 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH #include "module.h" #include "common.h" #include "dgraph.h" /*************************************/ /* */ /* These routines handle distributed */ /* source graphs. */ /* */ /*************************************/ /* This routine displays the contents ** of the given graph structure. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int dgraphView ( const Dgraph * restrict const grafptr, FILE * const stream) { MPI_Comm proccomm; /* Graph communicator */ int procglbnbr; /* Number of processes sharing graph data */ int proclocnum; /* Number of this process */ int procngbnbr; int procngbnum; Gnum vertlocnum; Gnum edgelocnum; Gnum * edgelocptr; proccomm = grafptr->proccomm; /* Simplify */ MPI_Comm_size (proccomm, &procglbnbr); /* Rely on communicator data */ MPI_Comm_rank (proccomm, &proclocnum); fflush (stream); /* Flush previous data */ for (procngbnbr = 0; procngbnbr < procglbnbr; procngbnbr ++) { MPI_Barrier (proccomm); if (procngbnbr == proclocnum) { fprintf (stream, "Process %d:\n", proclocnum); fprintf (stream, " vertglbnbr: " GNUMSTRING "\n vertgstnbr: " GNUMSTRING "\n vertgstnnd: " GNUMSTRING "\n vertlocnbr: " GNUMSTRING "\n vertlocnnd: " GNUMSTRING "\n", (Gnum) grafptr->vertglbnbr, (Gnum) grafptr->vertgstnbr, (Gnum) grafptr->vertgstnnd, (Gnum) grafptr->vertlocnbr, (Gnum) grafptr->vertlocnnd); fprintf (stream, " vertloctax:"); if (grafptr->vendloctax == grafptr->vertloctax + 1) { for (vertlocnum = grafptr->baseval; vertlocnum <= grafptr->vertlocnnd; vertlocnum ++)/**/ fprintf (stream, " " GNUMSTRING, (Gnum) grafptr->vertloctax[vertlocnum]); fprintf (stream, " x\n vendloctax: = vertloctax + 1"); } else { for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) fprintf (stream, " " GNUMSTRING, (Gnum) grafptr->vertloctax[vertlocnum]); fprintf (stream, " vendloctax: x"); for (vertlocnum = grafptr->baseval; vertlocnum < grafptr->vertlocnnd; vertlocnum ++) fprintf (stream, " " GNUMSTRING, (Gnum) grafptr->vendloctax[vertlocnum]); } fprintf (stream, "\n edgeglbnbr: " GNUMSTRING "\n edgelocnbr: " GNUMSTRING "\n", (Gnum) grafptr->edgeglbnbr, (Gnum) grafptr->edgelocnbr); fprintf (stream, " edgeloctax:"); for (edgelocnum = grafptr->baseval, edgelocptr = grafptr->edgeloctax; edgelocnum < grafptr->edgelocnbr + grafptr->baseval; edgelocnum ++, edgelocptr ++) fprintf (stream, " " GNUMSTRING, (Gnum) *edgelocptr); if ((grafptr->flagval & DGRAPHHASEDGEGST) != 0) { fprintf (stream, "\n edgegsttax:"); for (edgelocnum = grafptr->baseval, edgelocptr = grafptr->edgegsttax; edgelocnum < grafptr->edgelocnbr + grafptr->baseval; edgelocnum ++, edgelocptr ++) fprintf (stream, " " GNUMSTRING, (Gnum) *edgelocptr); } fprintf (stream, "\n procdsptab:"); for (procngbnum = 0; procngbnum <= procglbnbr ; procngbnum ++) fprintf (stream, " " GNUMSTRING, (Gnum) grafptr->procdsptab[procngbnum]); fprintf (stream, "\n procngbnbr: %d", grafptr->procngbnbr); fprintf (stream, "\n procngbtab:"); for (procngbnum = 0; procngbnum < grafptr->procngbnbr; procngbnum ++) fprintf (stream, " %d", grafptr->procngbtab[procngbnum]); fprintf (stream, "\n procrcvtab:"); for (procngbnum = 0; procngbnum < grafptr->procglbnbr; procngbnum ++) fprintf (stream, " %d", grafptr->procrcvtab[procngbnum]); fprintf (stream, "\n procsndnbr: %d", grafptr->procsndnbr); fprintf (stream, "\n procsndtab:"); for (procngbnum = 0; procngbnum < grafptr->procglbnbr; procngbnum ++) fprintf (stream, " %d", grafptr->procsndtab[procngbnum]); fprintf (stream, "\n degrglbmax: " GNUMSTRING, (Gnum) grafptr->degrglbmax); fprintf (stream, "\n"); fflush (stream); /* Flush data */ } } MPI_Barrier (proccomm); return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_dgraph_build_grid3d_f.c0000644000175300017530000000734311631334325025217 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_dgraph_build_grid3d_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This file contains the Fortran API for **/ /** the source graph handling routines of **/ /** the libSCOTCH library. **/ /** **/ /** DATES : # Version 5.0 : from : 16 feb 2007 **/ /** to 16 feb 2007 **/ /** # Version 5.1 : from : 06 jun 2010 **/ /** to 06 jun 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the distributed graph handling */ /* routines. */ /* */ /**************************************/ /* ** */ FORTRAN ( \ SCOTCHFDGRAPHBUILDGRID3D, scotchfdgraphbuildgrid3d, ( \ SCOTCH_Dgraph * const grafptr, \ const SCOTCH_Num * const baseptr, \ const SCOTCH_Num * const dimxptr, \ const SCOTCH_Num * const dimyptr, \ const SCOTCH_Num * const dimzptr, \ const SCOTCH_Num * const incrptr, \ const int * const flagptr, \ int * const revaptr), \ (grafptr, baseptr, dimxptr, dimyptr, dimzptr, incrptr, flagptr, revaptr)) { *revaptr = SCOTCH_dgraphBuildGrid3D (grafptr, *baseptr, *dimxptr, *dimyptr, *dimzptr, *incrptr, *flagptr); } scotch-5.1.12b.dfsg/src/libscotch/vgraph_separate_ml.c0000644000175300017530000002474611631334325023157 0ustar hazelscthazelsct/* Copyright 2004,2007,2009 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vgraph_separate_ml.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module separates a separator **/ /** graph using a multi-level scheme. **/ /** **/ /** DATES : # Version 3.2 : from : 28 oct 1997 **/ /** to 05 nov 1997 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 01 oct 1998 **/ /** # Version 4.0 : from : 13 dec 2001 **/ /** to 20 mar 2005 **/ /** # Version 5.1 : from : 11 nov 2009 **/ /** to 11 nov 2009 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VGRAPH_SEPARATE_ML #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "graph_coarsen.h" #include "vgraph.h" #include "vgraph_separate_ml.h" #include "vgraph_separate_st.h" /*********************************************/ /* */ /* The coarsening and uncoarsening routines. */ /* */ /*********************************************/ /* This routine builds a coarser graph from the ** graph that is given on input. The coarser ** graphs differ at this stage from classical ** active graphs as their internal gains are not ** yet computed. ** It returns: ** - 0 : if the coarse graph has been built. ** - 1 : if threshold achieved or on error. */ static int vgraphSeparateMlCoarsen ( const Vgraph * restrict const finegrafptr, /*+ Finer graph +*/ Vgraph * restrict const coargrafptr, /*+ Coarser graph to build +*/ GraphCoarsenMulti * restrict * const coarmultptr, /*+ Pointer to multinode table to build +*/ const VgraphSeparateMlParam * const paraptr) /*+ Method parameters +*/ { if (graphCoarsen (&finegrafptr->s, &coargrafptr->s, coarmultptr, paraptr->coarnbr, paraptr->coarrat, paraptr->coartype) != 0) return (1); /* Return if coarsening failed */ coargrafptr->parttax = NULL; /* Do not allocate partition data yet */ coargrafptr->frontab = finegrafptr->frontab; /* Re-use frontier array for coarser graph */ coargrafptr->levlnum = finegrafptr->levlnum + 1; /* Graph level is coarsening level */ return (0); } /* This routine propagates the separation of the ** coarser graph back to the finer graph, according ** to the multinode table of collapsed vertices. ** After the separation is propagated, it finishes ** to compute the parameters of the finer graph that ** were not computed at the coarsening stage. ** It returns: ** - 0 : if coarse graph data has been propagated to fine graph. ** - !0 : on error. */ static int vgraphSeparateMlUncoarsen ( Vgraph * restrict const finegrafptr, /*+ Finer graph +*/ const Vgraph * restrict const coargrafptr, /*+ Coarser graph +*/ const GraphCoarsenMulti * restrict const coarmulttax) /*+ Multinode array +*/ { Gnum coarvertnum; /* Number of current coarse vertex */ Gnum finefronnbr; /* Number of frontier vertices in fine graph */ if (finegrafptr->parttax == NULL) { /* If partition array not yet allocated */ if ((finegrafptr->parttax = (GraphPart *) memAlloc (finegrafptr->s.vertnbr * sizeof (GraphPart))) == NULL) { errorPrint ("vgraphSeparateMlUncoarsen: out of memory"); return (1); /* Allocated data will be freed along with graph structure */ } finegrafptr->parttax -= finegrafptr->s.baseval; } if (coargrafptr != NULL) { /* If coarser graph provided */ GraphPart * restrict fineparttax; Gnum finesize1; /* Number of vertices in fine part 1 */ const GraphPart * restrict const coarparttax = coargrafptr->parttax; finesize1 = coargrafptr->compsize[1]; /* Pre-allocate size */ fineparttax = finegrafptr->parttax; for (coarvertnum = coargrafptr->s.baseval, finefronnbr = 0; coarvertnum < coargrafptr->s.vertnnd; coarvertnum ++) { GraphPart coarpartval; /* Value of current multinode part */ coarpartval = coarparttax[coarvertnum]; fineparttax[coarmulttax[coarvertnum].vertnum[0]] = coarpartval; if (coarpartval != 2) { /* If vertex is not in separator */ if (coarmulttax[coarvertnum].vertnum[0] != coarmulttax[coarvertnum].vertnum[1]) { fineparttax[coarmulttax[coarvertnum].vertnum[1]] = coarpartval; finesize1 += (Gnum) coarpartval; /* One extra vertex created in part 1 if (coarpartval == 1) */ } } else { /* Vertex is in separator */ finegrafptr->frontab[finefronnbr ++] = coarmulttax[coarvertnum].vertnum[0]; if (coarmulttax[coarvertnum].vertnum[0] != coarmulttax[coarvertnum].vertnum[1]) { fineparttax[coarmulttax[coarvertnum].vertnum[1]] = coarpartval; finegrafptr->frontab[finefronnbr ++] = coarmulttax[coarvertnum].vertnum[1]; /* One extra vertex in separator */ } } } finegrafptr->fronnbr = finefronnbr; finegrafptr->compload[0] = coargrafptr->compload[0]; finegrafptr->compload[1] = coargrafptr->compload[1]; finegrafptr->compload[2] = coargrafptr->compload[2]; finegrafptr->comploaddlt = coargrafptr->comploaddlt; finegrafptr->compsize[0] = finegrafptr->s.vertnbr - finefronnbr - finesize1; finegrafptr->compsize[1] = finesize1; } else /* No coarse graph provided */ vgraphZero (finegrafptr); /* Assign all vertices to part 0 */ #ifdef SCOTCH_DEBUG_VGRAPH2 if (vgraphCheck (finegrafptr) != 0) { errorPrint ("vgraphSeparateMlUncoarsen: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_VGRAPH2 */ return (0); } /* This routine recursively performs the ** separation recursion. ** It returns: ** - 0 : if separator could be computed. ** - !0 : on error. */ static int vgraphSeparateMl2 ( Vgraph * restrict const grafptr, /* Vertex-separation graph */ const VgraphSeparateMlParam * const paraptr) /* Method parameters */ { Vgraph coargrafdat; GraphCoarsenMulti * restrict coarmulttax; int o; if (vgraphSeparateMlCoarsen (grafptr, &coargrafdat, &coarmulttax, paraptr) == 0) { if (((o = vgraphSeparateMl2 (&coargrafdat, paraptr)) == 0) && ((o = vgraphSeparateMlUncoarsen (grafptr, &coargrafdat, coarmulttax)) == 0) && ((o = vgraphSeparateSt (grafptr, paraptr->stratasc)) != 0)) /* Apply ascending strategy */ errorPrint ("vgraphSeparateMl2: cannot apply ascending strategy"); coargrafdat.frontab = NULL; /* Prevent frontab of fine graph from being freed */ vgraphExit (&coargrafdat); } else { /* Cannot coarsen due to lack of memory or error */ if (((o = vgraphSeparateMlUncoarsen (grafptr, NULL, NULL)) == 0) && /* Finalize graph */ ((o = vgraphSeparateSt (grafptr, paraptr->stratlow)) != 0)) /* Apply low strategy */ errorPrint ("vgraphSeparateMl2: cannot apply low strategy"); } return (o); } /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the muti-level separation. ** It returns: ** - 0 : if separator could be computed. ** - 1 : on error. */ int vgraphSeparateMl ( Vgraph * const grafptr, /*+ Vertex-separation graph +*/ const VgraphSeparateMlParam * const paraptr) /*+ Method parameters +*/ { Gnum levlnum; /* Save value for graph level */ int o; levlnum = grafptr->levlnum; /* Save graph level */ grafptr->levlnum = 0; /* Initialize coarsening level */ o = vgraphSeparateMl2 (grafptr, paraptr); /* Perform multi-level separation */ grafptr->levlnum = levlnum; /* Restore graph level */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/hgraph_induce_edge.c0000644000175300017530000002563111631334325023072 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_induce_edge.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This commodity file contains the edge **/ /** arrays building subroutine which is **/ /** duplicated, with minor modifications, **/ /** into hgraph_induce.c **/ /** **/ /** DATES : # Version 4.0 : from : 10 jan 2002 **/ /** to 17 jan 2003 **/ /** # Version 5.0 : from : 19 dec 2006 **/ /** to 19 dec 2006 **/ /** # Version 5.1 : from : 24 oct 2010 **/ /** to 24 oct 2010 **/ /** **/ /************************************************************/ static void HGRAPHINDUCE2NAME ( const Hgraph * restrict const orggrafptr, /* Pointer to original halo graph */ Gnum * restrict const orgindxtax, /* Array of numbers of selected vertices */ Hgraph * restrict const indgrafptr) /* Pointer to induced halo graph */ { Gnum indvertnum; /* Number of current induced vertex */ Gnum indvertnnd; /* Number of after-last induced (halo) vertex */ Gnum indvelosum; /* Overall induced vertex load */ Gnum indedgenum; /* Number of current edge in induced halo subgraph */ Gnum indenohnbr; /* Number of non-halo edges in halo subgraph */ Gnum inddegrmax; /* Maximum degree */ #ifdef SCOTCH_DEBUG_HGRAPH2 Gnum indedgenbs; /* Revised number of edges in halo subgraph */ #endif /* SCOTCH_DEBUG_HGRAPH2 */ #ifdef HGRAPHINDUCE2L /* If edge loads present */ Gnum indedlosum; Gnum indenohsum; indedlosum = indenohsum = 0; #endif /* HGRAPHINDUCE2L */ inddegrmax = 0; for (indvertnum = indedgenum = indgrafptr->s.baseval, indvelosum = indenohnbr = 0, indvertnnd = indgrafptr->vnohnnd; /* For all non-halo vertices */ indvertnum < indgrafptr->vnohnnd; indvertnum ++) { Gnum orgvertnum; /* Number of current vertex in original halo graph */ Gnum orgedgenum; /* Number of current edge in original halo graph */ Gnum indedgennd; /* Index of after-last edge position in edge array */ Gnum indedhdnum; /* Index of after-last edge linking to non-halo vertices */ Gnum inddegrval; orgvertnum = indgrafptr->s.vnumtax[indvertnum]; indgrafptr->s.verttax[indvertnum] = indedgenum; indenohnbr -= indedgenum; /* Subtract base of non-halo edges */ if (indgrafptr->s.velotax != NULL) { /* If graph has vertex weights */ indvelosum += /* Accumulate vertex loads */ indgrafptr->s.velotax[indvertnum] = orggrafptr->s.velotax[orgvertnum]; } inddegrval = orggrafptr->s.vendtax[orgvertnum] - orggrafptr->s.verttax[orgvertnum]; /* Get degree of non-halo node */ if (inddegrmax < inddegrval) /* Keep maximum degree */ inddegrmax = inddegrval; for (orgedgenum = orggrafptr->s.verttax[orgvertnum], indedhdnum = indedgennd = indedgenum + inddegrval; orgedgenum < orggrafptr->s.vendtax[orgvertnum]; orgedgenum ++) { Gnum orgvertend; /* Number of current end vertex in original halo graph */ Gnum indvertend; /* Number of current end vertex in induced halo subgraph */ orgvertend = orggrafptr->s.edgetax[orgedgenum]; indvertend = orgindxtax[orgvertend]; if (indvertend == ~0) { /* If neighbor is yet undeclared halo vertex */ indgrafptr->s.vnumtax[indvertnnd] = orgvertend; /* Add number of halo vertex to array */ indvertend = orgindxtax[orgvertend] = indvertnnd ++; /* Get induced number of vertex */ } if (indvertend >= indgrafptr->vnohnnd) { /* If neighbor is halo vertex */ indedhdnum --; /* Add neighbor at end of edge sub-array */ indgrafptr->s.edgetax[indedhdnum] = indvertend; HGRAPHINDUCE2EDLOINIT (indedhdnum); } else { /* If heighbor is non-halo vertex */ indgrafptr->s.edgetax[indedgenum] = indvertend; /* Add neighbor at beginning of edge sub-array */ HGRAPHINDUCE2EDLOINIT (indedgenum); HGRAPHINDUCE2ENOHINIT; indedgenum ++; } } #ifdef SCOTCH_DEBUG_HGRAPH2 if (indedgenum != indedhdnum) { errorPrint (STRINGIFY (HGRAPHINDUCE2NAME) ": internal error (1)"); return; } #endif /* SCOTCH_DEBUG_HGRAPH2 */ indenohnbr += indedhdnum; /* Add position to number of non-halo edges */ indgrafptr->vnhdtax[indvertnum] = indedhdnum; /* Set end of non-halo sub-array */ indedgenum = indedgennd; /* Point to next free space in edge array */ } indgrafptr->vnlosum = (indgrafptr->s.velotax != NULL) ? indvelosum : indgrafptr->vnohnbr; indgrafptr->enohnbr = indenohnbr; #ifdef SCOTCH_DEBUG_HGRAPH2 indedgenbs = 2 * (indedgenum - indgrafptr->s.baseval) - indenohnbr; /* Compute total number of edges */ #endif /* SCOTCH_DEBUG_HGRAPH2 */ #ifdef HGRAPHINDUCE2L /* If edge loads present */ { Gnum * indedgetab; /* Dummy area to recieve un-based edgetab */ Gnum * indedlotab; /* Save of old position of edgetab array */ #ifndef SCOTCH_DEBUG_HGRAPH2 Gnum indedgenbs; /* Revised number of edges in halo subgraph */ indedgenbs = 2 * (indedgenum - indgrafptr->s.baseval) - indenohnbr; /* Compute total number of edges */ #endif /* SCOTCH_DEBUG_HGRAPH2 */ indedlotab = indgrafptr->s.edlotax + indgrafptr->s.baseval; /* Save old offset of move area */ memOffset (indgrafptr->s.edgetax + indgrafptr->s.baseval, /* Compute new offsets */ &indedgetab, (size_t) indedgenbs, &indgrafptr->s.edlotax, (size_t) indedgenbs, NULL); memMov (indgrafptr->s.edlotax, indedlotab, (indedgenum - indgrafptr->s.baseval) * sizeof (Gnum)); /* Move already existing edge load array */ indgrafptr->s.edlotax -= indgrafptr->s.baseval; } #endif /* HGRAPHINDUCE2L */ for ( ; indvertnum < indvertnnd; indvertnum ++) { /* For all halo vertices found during first pass */ Gnum orgvertnum; /* Number of current vertex in original halo graph */ Gnum orgedgenum; /* Number of current edge in original halo graph */ orgvertnum = indgrafptr->s.vnumtax[indvertnum]; indgrafptr->s.verttax[indvertnum] = indedgenum; if (indgrafptr->s.velotax != NULL) { /* If graph has vertex weights */ indvelosum += /* Accumulate vertex loads */ indgrafptr->s.velotax[indvertnum] = orggrafptr->s.velotax[orgvertnum]; } for (orgedgenum = orggrafptr->s.verttax[orgvertnum]; orgedgenum < orggrafptr->s.vendtax[orgvertnum]; orgedgenum ++) { Gnum orgvertend; /* Number of current end vertex in original halo graph */ Gnum indvertend; /* Number of current end vertex in induced halo subgraph */ orgvertend = orggrafptr->s.edgetax[orgedgenum]; indvertend = orgindxtax[orgvertend]; if ((indvertend != ~0) && /* If end vertex in induced halo subgraph */ (indvertend < indgrafptr->vnohnnd)) { /* And in its non-halo part only */ indgrafptr->s.edgetax[indedgenum] = indvertend; HGRAPHINDUCE2EDLOINIT (indedgenum); indedgenum ++; } } if (inddegrmax < (indedgenum - indgrafptr->s.verttax[indvertnum])) inddegrmax = (indedgenum - indgrafptr->s.verttax[indvertnum]); } #ifdef SCOTCH_DEBUG_HGRAPH2 if ((indedgenum - indgrafptr->s.baseval) != indedgenbs) { errorPrint (STRINGIFY (HGRAPHINDUCE2NAME) ": internal error (2)"); return; } #endif /* SCOTCH_DEBUG_HGRAPH2 */ indgrafptr->s.verttax[indvertnnd] = indedgenum; /* Set end of compact vertex array */ indgrafptr->s.vertnbr = indvertnnd - indgrafptr->s.baseval; indgrafptr->s.vertnnd = indvertnnd; indgrafptr->s.velosum = (indgrafptr->s.velotax != NULL) ? indvelosum : indgrafptr->s.vertnbr; indgrafptr->s.edgenbr = indedgenum - indgrafptr->s.baseval; /* Set actual number of edges */ indgrafptr->s.edlosum = HGRAPHINDUCE2EDLOSUM; indgrafptr->s.degrmax = inddegrmax; indgrafptr->enohsum = HGRAPHINDUCE2ENOHSUM; } scotch-5.1.12b.dfsg/src/libscotch/dorder.h0000644000175300017530000002427011631334325020570 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dorder.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the data **/ /** declarations for the generic **/ /** distributed ordering structure. **/ /** **/ /** DATES : # Version 5.0 : from : 15 apr 2006 **/ /** to 14 oct 2007 **/ /** # Version 5.1 : from : 28 nov 2007 **/ /** to 04 nov 2010 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Tag for MPI communications. +*/ #define DORDERTAGPERI 0 /*+ Column block separation tree cell flags. The DORDERCBLKNEDI value must correspond to a single bit and be equal to the ORDERCBLKNEDI value. +*/ #define DORDERCBLKNONE 0x0000 /*+ Not yet assigned +*/ #define DORDERCBLKNEDI 0x0001 /*+ Nested dissection separator node +*/ #define DORDERCBLKLEAF 0x0002 /*+ Distributed leaf +*/ /* ** The type and structure definitions. */ /*+ Distributed index of column block tree cell. +*/ typedef struct DorderIndex_ { int proclocnum; /*+ Number of this process +*/ Gnum cblklocnum; /*+ Local index of column block +*/ } DorderIndex; /*+ Link structure to double-chain all column blocks into the distributed ordering structure. Nodes are inserted at end of list such that a simple traversal gives nodes in ascending creation order, which is essential for locally-rooted nodes when gathering them on a centralized ordering. +*/ typedef struct DorderLink_ { struct DorderLink_ * nextptr; /*+ Pointer to previous column block +*/ struct DorderLink_ * prevptr; /*+ Pointer to next column block +*/ } DorderLink; /*+ Centralized column block node. +*/ typedef struct DorderNode_ { Gnum fathnum; /*+ Number of father in centralized node array +*/ int typeval; /*+ Centralized type of tree node +*/ Gnum vnodnbr; /*+ Number of nodes in this column block +*/ Gnum cblknum; /*+ Rank of column block in father column block array +*/ } DorderNode; /*+ Distributed column-block tree cell. Each cell defines a distributed column block, which is either a nested dissection node, with its two subgraphs and its separator, or a leaf. Leaves which are located on a single process can be nested dissection sequential nodes, with the sequential tree folded as a node array. Column blocks are given in ascending order within all sub-arrays, for proper infix traversal. +*/ typedef struct DorderCblk_ { DorderLink linkdat; /*+ Link to other blocks. TRICK: FIRST +*/ struct Dorder_ * ordelocptr; /*+ Pointer to local distributed ordering +*/ int typeval; /*+ Distributed type of tree node +*/ DorderIndex fathnum; /*+ Master index of parent column block +*/ DorderIndex cblknum; /*+ Master index of this column block +*/ Gnum ordeglbval; /*+ Un-based starting index of inverse permutation +*/ Gnum vnodglbnbr; /*+ Number of node vertices in subtree +*/ Gnum cblkfthnum; /*+ Rank of node in father column block array +*/ union { struct { /*+ Fragment of inverse permutation +*/ Gnum ordelocval; /*+ Starting index of inverse permutation +*/ Gnum vnodlocnbr; /*+ Number of node vertices in fragment +*/ Gnum * periloctab; /*+ Pointer to inverse permutation fragment +*/ Gnum nodelocnbr; /*+ Number of local column blocks +*/ DorderNode * nodeloctab; /*+ Array of local column blocks +*/ Gnum cblklocnum; /*+ Local number of first local column block +*/ } leaf; struct { /*+ Fragment of inverse permutation +*/ Gnum cblkglbnbr; /*+ Number of descendent nodes (2 or 3) +*/ } nedi; } data; } DorderCblk; /*+ Distributed ordering structure. A distributed block ordering is defined by fragments of its inverse permutation, distributed across all of the participating processes. For the sake of consistency between orderings that have been produced either from graphs or meshes, whether centralized or distributed, all ordering values are based from baseval. +*/ typedef struct Dorder_ { Gnum baseval; /*+ Base value for structures +*/ Gnum vnodglbnbr; /*+ Global number of node vertices +*/ Gnum cblklocnbr; /*+ Local number of unique locally-rooted distributed and sequential column blocks +*/ DorderLink linkdat; /*+ Link to column blocks +*/ MPI_Comm proccomm; /*+ Ordering global communicator +*/ int proclocnum; /*+ Rank of this process in the communicator +*/ #ifdef SCOTCH_PTHREAD pthread_mutex_t mutelocdat; /*+ Local mutex for counter and link updates +*/ #endif /* SCOTCH_PTHREAD */ } Dorder; /* ** The function prototypes. */ #ifndef DORDER #define static #endif int dorderInit (Dorder * const, const Gnum, const Gnum, MPI_Comm); void dorderExit (Dorder * const); void dorderFree (Dorder * const); #ifdef DGRAPH_H int dorderPerm (const Dorder * const, const Dgraph * const, Gnum * const); int dorderSave (const Dorder * const, const Dgraph * const, FILE * const); int dorderSaveBlock (const Dorder * const, const Dgraph * const, FILE * const); int dorderSaveMap (const Dorder * const, const Dgraph * const, FILE * const); int dorderSaveTree (const Dorder * const, const Dgraph * const, FILE * const); #ifdef ORDER_H int dorderSaveTree2 (const Dorder * restrict const, const Dgraph * restrict const, FILE * restrict const, int (*) (const Order * const, const Gnum * const, FILE * const)); #endif /* ORDER_H */ #endif /* DGRAPH_H */ Gnum dorderCblkDist (const Dorder * restrict const); int dorderTreeDist (const Dorder * restrict const, const Dgraph * restrict const, Gnum * restrict const, Gnum * restrict const); #ifdef ORDER_H int dorderGather (const Dorder * const, Order * const); int dorderGatherTree (const Dorder * const, Order * const, const int); #endif /* ORDER_H */ DorderCblk * dorderFrst (Dorder * const); DorderCblk * dorderNew (DorderCblk * const, MPI_Comm); DorderCblk * dorderNewSequ (DorderCblk * const); Gnum dorderNewSequIndex (DorderCblk * const, const Gnum); void dorderDispose (DorderCblk * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/graph_io_mmkt.h0000644000175300017530000000523311631334325022127 0ustar hazelscthazelsct/* Copyright 2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : graph_io_mmkt.h **/ /** **/ /** AUTHORS : Cedric CHEVALIER (v5.0) **/ /** Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the Input routines **/ /** for handling the Matrix Market format. **/ /** **/ /** DATES : # Version 5.0 : from : 17 jan 2008 **/ /** to : 14 mar 2008 **/ /** **/ /************************************************************/ /* ** The type and structure definitions. */ /* Structure representing edges to symmetrize. */ typedef struct GraphGeomMmktEdge_ { Gnum vertnum[2]; } GraphGeomMmktEdge; scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_st.c0000644000175300017530000003504211631334325022455 0ustar hazelscthazelsct/* Copyright 2004,2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_st.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the generic call to the **/ /** graph ordering module, using a given **/ /** strategy. **/ /** **/ /** DATES : # Version 3.2 : from : 19 oct 1996 **/ /** to 09 sep 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to 07 sep 2001 **/ /** # Version 4.0 : from : 27 dec 2001 **/ /** to 05 jan 2005 **/ /** # Version 5.0 : from : 31 may 2008 **/ /** to 31 may 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HGRAPH_ORDER_ST #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "order.h" #include "hgraph.h" #include "hgraph_order_bl.h" #include "hgraph_order_cp.h" #include "hgraph_order_gp.h" #include "hgraph_order_hd.h" #include "hgraph_order_hf.h" #include "hgraph_order_nd.h" #include "hgraph_order_si.h" #include "hgraph_order_st.h" #include "vgraph.h" #include "vgraph_separate_st.h" /* ** The static and global variables. */ static Hgraph hgraphorderstgraphdummy; /* Dummy graph for offset computations */ static union { /* Default parameters for block splitting method */ HgraphOrderBlParam param; /* Parameter zone */ StratNodeMethodData padding; /* To avoid reading out of structure */ } hgraphorderstdefaultbl = { { &stratdummy, 8 } }; static union { HgraphOrderCpParam param; StratNodeMethodData padding; } hgraphorderstdefaultcp = { { 0.70L, &stratdummy, &stratdummy } }; static union { HgraphOrderGpParam param; StratNodeMethodData padding; } hgraphorderstdefaultgp = { { 3 } }; static union { HgraphOrderHdParam param; StratNodeMethodData padding; } hgraphorderstdefaulthd = { { 1, 10000, 0.08L } }; static union { HgraphOrderHfParam param; StratNodeMethodData padding; } hgraphorderstdefaulthf = { { 1, 1000000, 0.08L } }; static union { /* Default parameters for nested dissection method */ HgraphOrderNdParam param; StratNodeMethodData padding; } hgraphorderstdefaultnd = { { &stratdummy, &stratdummy, &stratdummy } }; static StratMethodTab hgraphorderstmethtab[] = { /* Graph ordering methods array */ { HGRAPHORDERSTMETHBL, "b", hgraphOrderBl, &hgraphorderstdefaultbl }, { HGRAPHORDERSTMETHCP, "c", hgraphOrderCp, &hgraphorderstdefaultcp }, { HGRAPHORDERSTMETHGP, "g", hgraphOrderGp, &hgraphorderstdefaultgp }, { HGRAPHORDERSTMETHHD, "d", hgraphOrderHd, &hgraphorderstdefaulthd }, { HGRAPHORDERSTMETHHF, "f", hgraphOrderHf, &hgraphorderstdefaulthf }, { HGRAPHORDERSTMETHND, "n", hgraphOrderNd, &hgraphorderstdefaultnd }, { HGRAPHORDERSTMETHSI, "s", hgraphOrderSi, NULL }, { -1, NULL, NULL, NULL } }; static StratParamTab hgraphorderstparatab[] = { /* The method parameter list */ { HGRAPHORDERSTMETHBL, STRATPARAMSTRAT, "strat", (byte *) &hgraphorderstdefaultbl.param, (byte *) &hgraphorderstdefaultbl.param.strat, (void *) &hgraphorderststratab }, { HGRAPHORDERSTMETHBL, STRATPARAMINT, "cmin", (byte *) &hgraphorderstdefaultbl.param, (byte *) &hgraphorderstdefaultbl.param.cblkmin, NULL }, { HGRAPHORDERSTMETHCP, STRATPARAMDOUBLE, "rat", (byte *) &hgraphorderstdefaultcp.param, (byte *) &hgraphorderstdefaultcp.param.comprat, NULL }, { HGRAPHORDERSTMETHCP, STRATPARAMSTRAT, "cpr", (byte *) &hgraphorderstdefaultcp.param, (byte *) &hgraphorderstdefaultcp.param.stratcpr, (void *) &hgraphorderststratab }, { HGRAPHORDERSTMETHCP, STRATPARAMSTRAT, "unc", (byte *) &hgraphorderstdefaultcp.param, (byte *) &hgraphorderstdefaultcp.param.stratunc, (void *) &hgraphorderststratab }, { HGRAPHORDERSTMETHGP, STRATPARAMINT, "pass", (byte *) &hgraphorderstdefaultgp.param, (byte *) &hgraphorderstdefaultgp.param.passnbr, NULL }, { HGRAPHORDERSTMETHHD, STRATPARAMINT, "cmin", (byte *) &hgraphorderstdefaulthd.param, (byte *) &hgraphorderstdefaulthd.param.colmin, NULL }, { HGRAPHORDERSTMETHHD, STRATPARAMINT, "cmax", (byte *) &hgraphorderstdefaulthd.param, (byte *) &hgraphorderstdefaulthd.param.colmax, NULL }, { HGRAPHORDERSTMETHHD, STRATPARAMDOUBLE, "frat", (byte *) &hgraphorderstdefaulthd.param, (byte *) &hgraphorderstdefaulthd.param.fillrat, NULL }, { HGRAPHORDERSTMETHHF, STRATPARAMINT, "cmin", (byte *) &hgraphorderstdefaulthf.param, (byte *) &hgraphorderstdefaulthf.param.colmin, NULL }, { HGRAPHORDERSTMETHHF, STRATPARAMINT, "cmax", (byte *) &hgraphorderstdefaulthf.param, (byte *) &hgraphorderstdefaulthf.param.colmax, NULL }, { HGRAPHORDERSTMETHHF, STRATPARAMDOUBLE, "frat", (byte *) &hgraphorderstdefaulthf.param, (byte *) &hgraphorderstdefaulthf.param.fillrat, NULL }, { HGRAPHORDERSTMETHND, STRATPARAMSTRAT, "sep", (byte *) &hgraphorderstdefaultnd.param, (byte *) &hgraphorderstdefaultnd.param.sepstrat, (void *) &vgraphseparateststratab }, { HGRAPHORDERSTMETHND, STRATPARAMSTRAT, "ole", (byte *) &hgraphorderstdefaultnd.param, (byte *) &hgraphorderstdefaultnd.param.ordstratlea, (void *) &hgraphorderststratab }, { HGRAPHORDERSTMETHND, STRATPARAMSTRAT, "ose", (byte *) &hgraphorderstdefaultnd.param, (byte *) &hgraphorderstdefaultnd.param.ordstratsep, (void *) &hgraphorderststratab }, { HGRAPHORDERSTMETHNBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; static StratParamTab hgraphorderstcondtab[] = { /* Graph condition parameter table */ { STRATNODECOND, STRATPARAMINT, "edge", (byte *) &hgraphorderstgraphdummy, (byte *) &hgraphorderstgraphdummy.s.edgenbr, NULL }, { STRATNODECOND, STRATPARAMINT, "levl", (byte *) &hgraphorderstgraphdummy, (byte *) &hgraphorderstgraphdummy.levlnum, NULL }, { STRATNODECOND, STRATPARAMINT, "load", (byte *) &hgraphorderstgraphdummy, (byte *) &hgraphorderstgraphdummy.vnlosum, NULL }, { STRATNODECOND, STRATPARAMDOUBLE, "mdeg", (byte *) &hgraphorderstgraphdummy, (byte *) &hgraphorderstgraphdummy.s.degrmax, NULL }, { STRATNODECOND, STRATPARAMINT, "vert", (byte *) &hgraphorderstgraphdummy, (byte *) &hgraphorderstgraphdummy.vnohnbr, /* Only consider non-halo vertices */ NULL }, { STRATNODENBR, STRATPARAMINT, NULL, NULL, NULL, NULL } }; StratTab hgraphorderststratab = { /* Strategy tables for graph ordering methods */ hgraphorderstmethtab, hgraphorderstparatab, hgraphorderstcondtab }; /************************************/ /* */ /* This routine is the entry point */ /* for the graph ordering routines. */ /* */ /************************************/ /* This routine computes an ordering ** with respect to a given strategy. ** It returns: ** - 0 : on success. ** - !0 : on error. */ int hgraphOrderSt ( const Hgraph * restrict const grafptr, /*+ Subgraph to order +*/ Order * restrict const ordeptr, /*+ Ordering to complete +*/ const Gnum ordenum, /*+ Index to start ordering at +*/ OrderCblk * restrict const cblkptr, /*+ Current column block +*/ const Strat * restrict const strat) /*+ Graph ordering strategy +*/ { StratTest val; int o; if (grafptr->vnohnbr == 0) /* Return immediately if nothing to do */ return (0); o = 0; switch (strat->type) { case STRATNODECONCAT : errorPrint ("hgraphOrderSt: concatenation operator not available for graph ordering strategies"); return (1); case STRATNODECOND : o = stratTestEval (strat->data.cond.test, &val, (void *) grafptr); /* Evaluate expression */ if (o == 0) { /* If evaluation was correct */ #ifdef SCOTCH_DEBUG_HGRAPH2 if ((val.typetest != STRATTESTVAL) && (val.typenode != STRATPARAMLOG)) { errorPrint ("hgraphOrderSt: invalid test result"); o = 1; break; } #endif /* SCOTCH_DEBUG_HGRAPH2 */ if (val.data.val.vallog == 1) /* If expression is true */ o = hgraphOrderSt (grafptr, ordeptr, ordenum, cblkptr, strat->data.cond.strat[0]); /* Apply first strategy */ else { /* Else if expression is false */ if (strat->data.cond.strat[1] != NULL) /* And if there is an else statement */ o = hgraphOrderSt (grafptr, ordeptr, ordenum, cblkptr, strat->data.cond.strat[1]); /* Apply second strategy */ } } break; case STRATNODEEMPTY : hgraphOrderSi (grafptr, ordeptr, ordenum, cblkptr); /* Always maintain a consistent ordering */ break; case STRATNODESELECT : errorPrint ("hgraphOrderSt: selection operator not available for graph ordering strategies"); return (1); #ifdef SCOTCH_DEBUG_HGRAPH2 case STRATNODEMETHOD : #else /* SCOTCH_DEBUG_HGRAPH2 */ default : #endif /* SCOTCH_DEBUG_HGRAPH2 */ return (strat->tabl->methtab[strat->data.method.meth].func (grafptr, ordeptr, ordenum, cblkptr, (void *) &strat->data.method.data)); #ifdef SCOTCH_DEBUG_HGRAPH2 default : errorPrint ("hgraphOrderSt: invalid parameter"); return (1); #endif /* SCOTCH_DEBUG_HGRAPH2 */ } return (o); } scotch-5.1.12b.dfsg/src/libscotch/library_random.c0000644000175300017530000000566211631334325022314 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_random.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the random **/ /** generator control routine. **/ /** **/ /** DATES : # Version 4.0 : from : 15 jan 2005 **/ /** to 15 jun 2005 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the random handling routines. */ /* */ /************************************/ /*+ This routine resets the random generator *** to simulate a start from scratch. *** It returns: *** - void : in all cases. +*/ void SCOTCH_randomReset () { intRandReset (); } scotch-5.1.12b.dfsg/src/libscotch/library_graph_base.c0000644000175300017530000000625611631334325023127 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_base.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the source **/ /** graph handling routines of the **/ /** libSCOTCH library. **/ /** **/ /** DATES : # Version 4.0 : from : 22 apr 2004 **/ /** to 22 apr 2004 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "graph.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the graph handling routines. */ /* */ /************************************/ /* This routine sets the base of the given ** graph to the given base value, and returns ** the old base value. ** It returns: ** - old base value : in all cases. */ SCOTCH_Num SCOTCH_graphBase ( SCOTCH_Graph * const grafptr, const SCOTCH_Num baseval) { return ((SCOTCH_Num) graphBase ((Graph * const) grafptr, (Gnum) baseval)); } scotch-5.1.12b.dfsg/src/libscotch/vdgraph_separate_df.c0000644000175300017530000004267311631334325023303 0ustar hazelscthazelsct/* Copyright 2007,2008 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vdgraph_separate_df.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module computes a separator of the **/ /** given distributed separator graph by **/ /** applying a diffusion method to what is **/ /** assumed to be a distributed band graph. **/ /** **/ /** DATES : # Version 5.1 : from : 05 nov 2007 **/ /** to : 09 nov 2008 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define VDGRAPH_SEPARATE_DF #include "module.h" #include "common.h" #include "dgraph.h" #include "vdgraph.h" #include "vdgraph_separate_df.h" /* ** The static variables. */ static const Gnum vdgraphseparatedfloadone = 1; /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine computes a distributed separator ** by diffusion across what is assumed to be a ** distributed band graph. ** It returns: ** - 0 : if the separator could be computed. ** - !0 : on error. */ int vdgraphSeparateDf ( Vdgraph * const grafptr, /*+ Distributed graph +*/ const VdgraphSeparateDfParam * const paraptr) /*+ Method parameters +*/ { float * restrict ielsloctax; /* Inverse of degree array */ float * restrict difogsttax; /* Old diffusion value array */ float * restrict difngsttax; /* New diffusion value array */ const Gnum * restrict edgegsttax; Gnum fronlocnum; float compglbavg; Gnum complocload1; Gnum complocload2; Gnum complocsize1; const Gnum * restrict velolocbax; Gnum velolocmsk; float vanclocval[2]; float valolocval[2]; /* Fraction of load to remove from anchor vertices at each step */ Gnum vanclocnnd; Gnum vertlocnum; Gnum reduloctab[4]; /* Local degree of both anchor vertices, minus edges to other anchors, and their loads */ Gnum reduglbtab[4]; Gnum passnum; float cdifval; float cremval; Gnum psepval; /* Separator part */ int ovflval; /* Overflow flag value */ if (dgraphGhst (&grafptr->s) != 0) { /* Compute ghost edge array if not already present */ errorPrint ("vdgraphSeparateDf: cannot compute ghost edge array"); return (1); } reduloctab[0] = grafptr->s.vendloctax[grafptr->s.vertlocnnd - 2] - grafptr->s.vertloctax[grafptr->s.vertlocnnd - 2] - (grafptr->s.procglbnbr - 1); reduloctab[1] = grafptr->s.vendloctax[grafptr->s.vertlocnnd - 1] - grafptr->s.vertloctax[grafptr->s.vertlocnnd - 1] - (grafptr->s.procglbnbr - 1); if (grafptr->s.veloloctax == NULL) reduloctab[2] = reduloctab[3] = 1; else { reduloctab[2] = grafptr->s.veloloctax[grafptr->s.vertlocnnd - 2]; reduloctab[3] = grafptr->s.veloloctax[grafptr->s.vertlocnnd - 1]; } if (memAllocGroup ((void **) (void *) &ielsloctax, (size_t) (grafptr->s.vertlocnbr * sizeof (float)), &difogsttax, (size_t) (grafptr->s.vertgstnbr * sizeof (float)), &difngsttax, (size_t) (grafptr->s.vertgstnbr * sizeof (float)), NULL) == NULL) { errorPrint ("vdgraphSeparateDf: out of memory"); reduloctab[0] = -1; } else { ielsloctax -= grafptr->s.baseval; difogsttax -= grafptr->s.baseval; difngsttax -= grafptr->s.baseval; } if (MPI_Allreduce (reduloctab, reduglbtab, 4, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("vdgraphSeparateDf: communication error (1)"); return (1); } if (reduglbtab[0] < 0) { /* If memory error */ if (ielsloctax != NULL) memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ } if ((reduglbtab[0] == 0) || /* If graph is too small to have any usable anchors, leave partition as is */ (reduglbtab[1] == 0)) { memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ return (0); } psepval = paraptr->partval & 1; /* Coerce part in the {0,1} range */ compglbavg = (float) (grafptr->compglbload[0] + grafptr->compglbload[1]) * 0.5F; vanclocval[0] = (float) grafptr->compglbload[0]; if (vanclocval[0] < (compglbavg * (1.0F - (float) paraptr->deltval))) /* Enforce balance constraint */ vanclocval[0] = compglbavg * (1.0F - (float) paraptr->deltval); else if (vanclocval[0] > (compglbavg * (1.0F + (float) paraptr->deltval))) vanclocval[0] = compglbavg * (1.0F + (float) paraptr->deltval); vanclocval[1] = (float) (grafptr->compglbload[0] + grafptr->compglbload[1]) - vanclocval[0]; valolocval[0] = (float) reduglbtab[2]; /* Compute values to remove from anchor vertices */ valolocval[1] = (float) reduglbtab[3]; if (vanclocval[0] < valolocval[0]) /* If anchor in part 0 too large to reduce imbalance */ psepval = 1; /* Separator must be taken from part 1 to stick to anchor 0 */ else if (vanclocval[1] < valolocval[1]) /* Else if anchor in part 1 too large to reduce imbalance */ psepval = 0; /* It is from part 0 that separator must be extracted */ vanclocval[psepval] += (float) grafptr->compglbload[2]; /* Aggregate separator to proper part */ vanclocval[0] = - vanclocval[0]; /* Part 0 holds negative values */ vanclocval[1] -= VDGRAPHSEPARATEDFEPSILON; /* Slightly tilt value to add to part 1 */ for (vertlocnum = grafptr->s.baseval, vanclocnnd = grafptr->s.vertlocnnd - 2; /* Do not account for anchor vertices in diffusion computations */ vertlocnum < vanclocnnd; vertlocnum ++) { #ifdef SCOTCH_DEBUG_VDGRAPH2 if ((grafptr->s.vendloctax[vertlocnum] - grafptr->s.vertloctax[vertlocnum]) == 0) { errorPrint ("vdgraphSeparateDf: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ ielsloctax[vertlocnum] = 1.0F / (float) (grafptr->s.vendloctax[vertlocnum] - grafptr->s.vertloctax[vertlocnum]); difogsttax[vertlocnum] = 0.0F; } ielsloctax[vanclocnnd] = 1.0F / (float) reduglbtab[0]; ielsloctax[vanclocnnd + 1] = 1.0F / (float) reduglbtab[1]; difogsttax[vanclocnnd] = vanclocval[0] * ielsloctax[vanclocnnd]; /* Load anchor vertices for first pass */ difogsttax[vanclocnnd + 1] = vanclocval[1] * ielsloctax[vanclocnnd + 1]; difngsttax[vanclocnnd] = /* In case of isolated anchors, do not risk overflow because of NaN */ difngsttax[vanclocnnd + 1] = 0.0F; if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (difogsttax + grafptr->s.baseval), MPI_FLOAT) != 0) { /* Perform initial diffusion (and build communication structures) */ errorPrint ("vdgraphSeparateDf: cannot propagate diffusion data (1)"); memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ return (1); } ovflval = 0; cdifval = paraptr->cdifval; cremval = paraptr->cremval; edgegsttax = grafptr->s.edgegsttax; for (passnum = 0; ; ) { /* For all passes */ if (ovflval == 0) { /* If no overflow occured */ Gnum vertlocnum; float * diftgsttax; /* Temporary swap value */ float veloval; veloval = 1.0F; /* Assume no vertex loads */ for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) { Gnum edgelocnum; Gnum edgelocnnd; float diffval; diffval = 0.0F; for (edgelocnum = grafptr->s.vertloctax[vertlocnum], edgelocnnd = grafptr->s.vendloctax[vertlocnum]; edgelocnum < edgelocnnd; edgelocnum ++) diffval += difogsttax[edgegsttax[edgelocnum]]; diffval *= cdifval; diffval += (difogsttax[vertlocnum] * cremval) / ielsloctax[vertlocnum]; if (grafptr->s.veloloctax != NULL) veloval = (float) grafptr->s.veloloctax[vertlocnum]; if (diffval >= 0.0F) { diffval = (diffval - veloval) * ielsloctax[vertlocnum]; if (diffval <= 0.0F) diffval = +VDGRAPHSEPARATEDFEPSILON; } else { diffval = (diffval + veloval) * ielsloctax[vertlocnum]; if (diffval >= 0.0F) diffval = -VDGRAPHSEPARATEDFEPSILON; } if (isnan (diffval)) { /* If overflow occured */ ovflval = 1; /* We are in state of overflow */ goto abort; /* Exit this loop without swapping arrays */ } difngsttax[vertlocnum] = diffval; } for ( ; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { /* For the two local anchor vertices */ Gnum edgelocnum; Gnum edgelocnnd; float diffval; diffval = 0.0F; edgelocnum = grafptr->s.vertloctax[vertlocnum] + grafptr->s.procglbnbr - 1; /* Skip links to other anchors */ edgelocnnd = grafptr->s.vendloctax[vertlocnum]; if (edgelocnum == edgelocnnd) /* If isolated anchor */ continue; /* Barrel is empty */ for ( ; edgelocnum < edgelocnnd; edgelocnum ++) diffval += difogsttax[edgegsttax[edgelocnum]]; diffval *= cdifval; diffval += vanclocval[vertlocnum - vanclocnnd] + (difogsttax[vertlocnum] * cremval) / ielsloctax[vertlocnum]; if (diffval >= 0.0F) { diffval = (diffval - valolocval[vertlocnum - vanclocnnd]) * ielsloctax[vertlocnum]; if (diffval <= 0.0F) diffval = +VDGRAPHSEPARATEDFEPSILON; } else { diffval = (diffval + valolocval[vertlocnum - vanclocnnd]) * ielsloctax[vertlocnum]; if (diffval >= 0.0F) diffval = -VDGRAPHSEPARATEDFEPSILON; } if (isnan (diffval)) { /* If overflow occured */ ovflval = 1; /* We are in state of overflow */ goto abort; /* Exit this loop without swapping arrays */ } difngsttax[vertlocnum] = diffval; } diftgsttax = (float *) difngsttax; /* Swap old and new diffusion arrays */ difngsttax = (float *) difogsttax; /* Casts to prevent IBM compiler from yelling */ difogsttax = (float *) diftgsttax; } abort : /* If overflow occured, resume here */ if (++ passnum >= paraptr->passnbr) /* If maximum number of passes reached */ break; /* Exit main loop */ if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (difogsttax + grafptr->s.baseval), MPI_FLOAT) != 0) { errorPrint ("vdgraphSeparateDf: cannot propagate diffusion data (2)"); memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ return (1); } } for (vertlocnum = grafptr->s.baseval; vertlocnum < vanclocnnd; vertlocnum ++) /* Pre-set parts without separator */ grafptr->partgsttax[vertlocnum] = (difogsttax[vertlocnum] <= 0.0F) ? 0 : 1; grafptr->partgsttax[vanclocnnd] = 0; /* Set up parts in case anchors are isolated */ grafptr->partgsttax[vanclocnnd + 1] = 1; if (grafptr->s.veloloctax != NULL) { velolocbax = grafptr->s.veloloctax; velolocmsk = ~((Gnum) 0); } else { velolocbax = &vdgraphseparatedfloadone; velolocmsk = 0; } memFree (ielsloctax + grafptr->s.baseval); /* Free group leader */ if (dgraphHaloSync (&grafptr->s, (byte *) (void *) (grafptr->partgsttax + grafptr->s.baseval), GRAPHPART_MPI) != 0) { errorPrint ("vdgraphSeparateDf: cannot propagate part data"); return (1); } for (vertlocnum = grafptr->s.baseval, fronlocnum = complocsize1 = complocload1 = complocload2 = 0; vertlocnum < grafptr->s.vertlocnnd; vertlocnum ++) { Gnum partval; GraphPart partend; Gnum veloval; #ifdef SCOTCH_DEBUG_VDGRAPH2 if (grafptr->partgsttax[vertlocnum] > 1) { errorPrint ("vdgraphSeparateDf: internal error (2)"); break; /* Do not break upcoming collective communications */ } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ partend = grafptr->partgsttax[vertlocnum] ^ 1; partval = (Gnum) grafptr->partgsttax[vertlocnum]; veloval = velolocbax[vertlocnum & velolocmsk]; complocsize1 += partval; /* Here, part is 0 or 1 only */ complocload1 += partval * veloval; if (partval == psepval) { /* Only vertices of aggregated part can be in separator */ Gnum edgelocnum; for (edgelocnum = grafptr->s.vertloctax[vertlocnum]; edgelocnum < grafptr->s.vendloctax[vertlocnum]; edgelocnum ++) { #ifdef SCOTCH_DEBUG_VDGRAPH2 if (grafptr->partgsttax[edgegsttax[edgelocnum]] > 2) { errorPrint ("vdgraphSeparateDf: internal error (3)"); vertlocnum = grafptr->s.vertlocnnd; break; /* Do not break upcoming collective communications */ } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ if (grafptr->partgsttax[edgegsttax[edgelocnum]] == partend) { /* If end vertex is in other part (and not in separator) */ grafptr->fronloctab[fronlocnum ++] = vertlocnum; /* Record it as member of the separator */ grafptr->partgsttax[vertlocnum] = 2; complocload2 += veloval; break; /* No need to go further */ } } } } grafptr->complocload[0] = grafptr->s.velolocsum - complocload1; grafptr->complocload[1] = complocload1; grafptr->complocload[2] = complocload2; grafptr->complocload[psepval] -= complocload2; grafptr->complocsize[0] = grafptr->s.vertlocnbr - complocsize1; grafptr->complocsize[1] = complocsize1; grafptr->complocsize[psepval] -= fronlocnum; grafptr->complocsize[2] = fronlocnum; if (MPI_Allreduce (&grafptr->complocload[0], &grafptr->compglbload[0], 6, GNUM_MPI, MPI_SUM, grafptr->s.proccomm) != MPI_SUCCESS) { /* TRICK: all arrays */ errorPrint ("vdgraphSeparateDf: communication error (2)"); return (1); } grafptr->compglbloaddlt = grafptr->compglbload[0] - grafptr->compglbload[1]; #ifdef SCOTCH_DEBUG_VDGRAPH2 if (vdgraphCheck (grafptr) != 0) { errorPrint ("vdgraphSeparateDf: inconsistent graph data"); return (1); } #endif /* SCOTCH_DEBUG_VDGRAPH2 */ if (grafptr->s.proclocnum == 0) fprintf (stderr, "BROL " GNUMSTRING "," GNUMSTRING "," GNUMSTRING "(" GNUMSTRING ")\n", (Gnum) grafptr->compglbload[0], (Gnum) grafptr->compglbload[1], (Gnum) grafptr->compglbload[2], (Gnum) grafptr->compglbloaddlt); return (0); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_bl.c0000644000175300017530000001216111631334325022254 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_bl.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module resizes block data using **/ /** the block splitting post-processing **/ /** algorithm. **/ /** **/ /** DATES : # Version 4.0 : from : 28 sep 2002 **/ /** to 09 feb 2005 **/ /** # Version 5.0 : from : 25 jul 2007 **/ /** to : 25 jul 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH_ORDER_BL #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "order.h" #include "mesh.h" #include "hmesh.h" #include "hmesh_order_bl.h" #include "hmesh_order_st.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hmeshOrderBl ( const Hmesh * restrict const meshptr, Order * restrict const ordeptr, const Gnum ordenum, /*+ Zero-based ordering number +*/ OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ const HmeshOrderBlParam * restrict const paraptr) { Gnum cblknbr; /* Number of old column blocks before splitting */ Gnum cblknum; /* Number of current column block */ if (paraptr->cblkmin <= 0) { errorPrint ("hmeshOrderBl: invalid minimum block size"); return (1); } if (hmeshOrderSt (meshptr, ordeptr, ordenum, cblkptr, paraptr->strat) != 0) /* Perform ordering strategy */ return (1); if (cblkptr->cblktab == NULL) { /* If single column block */ if (cblkptr->vnodnbr < (2 * paraptr->cblkmin)) /* If block cannot be split */ return (0); cblknbr = cblkptr->vnodnbr / paraptr->cblkmin; /* Get new number of blocks */ if ((cblkptr->cblktab = (OrderCblk *) memAlloc (cblknbr * sizeof (OrderCblk))) == NULL) { errorPrint ("hgraphOrderBl: out of memory"); return (1); } ordeptr->treenbr += cblknbr; /* These more number of tree nodes */ ordeptr->cblknbr += cblknbr - 1; /* These more number of column blocks */ cblkptr->cblknbr = cblknbr; for (cblknum = 0; cblknum < cblknbr; cblknum ++) { cblkptr->cblktab[cblknum].typeval = ORDERCBLKOTHR; cblkptr->cblktab[cblknum].vnodnbr = ((cblkptr->vnodnbr + cblknbr - 1) - cblknum) / cblknbr; cblkptr->cblktab[cblknum].cblknbr = 0; cblkptr->cblktab[cblknum].cblktab = NULL; } } else { /* Block already partitioned */ for (cblknum = 0; cblknum < cblkptr->cblknbr; cblknum ++) { if (hmeshOrderBl (meshptr, ordeptr, ordenum, cblkptr->cblktab + cblknum, paraptr) != 0) return (1); } } return (0); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_build_grid3d.c0000644000175300017530000004471711631334325023174 0ustar hazelscthazelsct/* Copyright 2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_build_grid3d.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Cedric CHEVALIER (5.0) **/ /** **/ /** FUNCTION : These lines are the distributed source **/ /** graph building routines for 3D grid **/ /** graphs. **/ /** **/ /** DATES : # Version 5.0 : from : 21 jul 2005 **/ /** to : 10 sep 2007 **/ /** # Version 5.1 : from : 05 jun 2010 **/ /** to : 06 jun 2010 **/ /** **/ /************************************************************/ #define DGRAPH_BUILD_GRID3D #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_build_grid3d.h" /**************************************/ /* */ /* Vertex neighbor handling routines. */ /* */ /**************************************/ /* ** */ static Gnum dgraphBuildGrid3Dvertex26M ( const DgraphBuildGrid3DData * restrict const dataptr, const Gnum vertglbnum, Gnum edgelocnum, const Gnum posxval, const Gnum posyval, const Gnum poszval) { Gnum ngbxmin; Gnum ngbxmax; Gnum ngbxval; Gnum ngbymin; Gnum ngbymax; Gnum ngbyval; Gnum ngbzmin; Gnum ngbzmax; Gnum ngbzval; ngbxmin = (posxval > 0) ? -1 : 0; ngbymin = (posyval > 0) ? -1 : 0; ngbzmin = (poszval > 0) ? -1 : 0; ngbxmax = (posxval < (dataptr->dimxval - 1)) ? 1 : 0; ngbymax = (posyval < (dataptr->dimyval - 1)) ? 1 : 0; ngbzmax = (poszval < (dataptr->dimzval - 1)) ? 1 : 0; for (ngbzval = ngbzmin; ngbzval <= ngbzmax; ngbzval ++) { for (ngbyval = ngbymin; ngbyval <= ngbymax; ngbyval ++) { for (ngbxval = ngbxmin; ngbxval <= ngbxmax; ngbxval ++) { if ((ngbxval | ngbyval | ngbzval) != 0) /* If not loop edge */ DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, (posxval + dataptr->dimxval + ngbxval) % dataptr->dimxval, (posyval + dataptr->dimyval + ngbyval) % dataptr->dimyval, (poszval + dataptr->dimzval + ngbzval) % dataptr->dimzval); } } } return (edgelocnum); } /* ** */ static Gnum dgraphBuildGrid3Dvertex26T ( const DgraphBuildGrid3DData * restrict const dataptr, const Gnum vertglbnum, Gnum edgelocnum, const Gnum posxval, const Gnum posyval, const Gnum poszval) { Gnum ngbxmin; Gnum ngbxmax; Gnum ngbxval; Gnum ngbymin; Gnum ngbymax; Gnum ngbyval; Gnum ngbzmin; Gnum ngbzmax; Gnum ngbzval; ngbxmin = dataptr->t26.ngbxmin; ngbxmax = dataptr->t26.ngbxmax; ngbymin = dataptr->t26.ngbymin; ngbymax = dataptr->t26.ngbymax; ngbzmin = dataptr->t26.ngbzmin; ngbzmax = dataptr->t26.ngbzmax; for (ngbzval = ngbzmin; ngbzval <= ngbzmax; ngbzval ++) { for (ngbyval = ngbymin; ngbyval <= ngbymax; ngbyval ++) { for (ngbxval = ngbxmin; ngbxval <= ngbxmax; ngbxval ++) { Gnum vertglbend; vertglbend = (((poszval + ngbzval) % dataptr->dimzval) * dataptr->dimyval + ((posyval + ngbyval) % dataptr->dimyval)) * dataptr->dimxval + ((posxval + ngbxval) % dataptr->dimxval) + dataptr->baseval; if (vertglbend != vertglbnum) { /* If not loop edge */ if (dataptr->edloloctax != NULL) dataptr->edloloctax[edgelocnum] = ((vertglbend + vertglbnum) % 16) + 1; dataptr->edgeloctax[edgelocnum ++] = vertglbend; } } } } return (edgelocnum); } /* ** */ static Gnum dgraphBuildGrid3Dvertex6M ( const DgraphBuildGrid3DData * restrict const dataptr, const Gnum vertglbnum, Gnum edgelocnum, const Gnum posxval, const Gnum posyval, const Gnum poszval) { Gnum ngbxval; Gnum ngbyval; Gnum ngbzval; ngbxval = posxval - 1; if (ngbxval >= 0) DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, ngbxval, posyval, poszval); ngbxval = posxval + 1; if (ngbxval < dataptr->dimxval) DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, ngbxval, posyval, poszval); ngbyval = posyval - 1; if (ngbyval >= 0) DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, ngbyval, poszval); ngbyval = posyval + 1; if (ngbyval < dataptr->dimyval) DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, ngbyval, poszval); ngbzval = poszval - 1; if (ngbzval >= 0) DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, posyval, ngbzval); ngbzval = poszval + 1; if (ngbzval < dataptr->dimzval) DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, posyval, ngbzval); return (edgelocnum); } /* ** */ static Gnum dgraphBuildGrid3Dvertex6T ( const DgraphBuildGrid3DData * restrict const dataptr, const Gnum vertglbnum, Gnum edgelocnum, const Gnum posxval, const Gnum posyval, const Gnum poszval) { Gnum ngbxval; Gnum ngbyval; Gnum ngbzval; if (dataptr->dimxval > 1) { ngbxval = (posxval + 1) % dataptr->dimxval; DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, ngbxval, posyval, poszval); if (dataptr->dimxval > 2) { ngbxval = (posxval + dataptr->dimxval - 1) % dataptr->dimxval; DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, ngbxval, posyval, poszval); } } if (dataptr->dimyval > 1) { ngbyval = (posyval + 1) % dataptr->dimyval; DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, ngbyval, poszval); if (dataptr->dimyval > 2) { ngbyval = (posyval + dataptr->dimyval - 1) % dataptr->dimyval; DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, ngbyval, poszval); } } if (dataptr->dimzval > 1) { ngbzval = (poszval + 1) % dataptr->dimzval; DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, posyval, ngbzval); if (dataptr->dimzval > 2) { ngbzval = (poszval + dataptr->dimzval - 1) % dataptr->dimzval; DGRAPHBUILDGRID3DNGB (dataptr, vertglbnum, edgelocnum ++, posxval, posyval, ngbzval); } } return (edgelocnum); } /*******************************************/ /* */ /* The distributed graph building routine. */ /* */ /*******************************************/ /* This routine builds a distrbuted grid graph ** of the given dimensions. ** hashval is the increment between two vertex ** indices (1 for sliced meshes). ** flagval is a combilation of: ** - 1 : 26-neighbor mesh (default: 6-neighbor mesh). ** - 2 : torus (default: mesh) ** - 4 : weighted vertices (default: no weights). ** - 8 : weighted edges (default: no weights). ** It returns: ** - 0 : graph created. ** - !0 : on error. */ int dgraphBuildGrid3D ( Dgraph * restrict const grafptr, /* Graph */ const Gnum baseval, /* Base value */ const Gnum dimxval, /* First dimension */ const Gnum dimyval, /* Second dimension */ const Gnum dimzval, /* Third dimension */ const Gnum incrval, /* Increment step */ const int flagval) /* Grid type */ { DgraphBuildGrid3DData datadat; /* Data structure for creating vertices */ Gnum proclocadj; /* Number of processes with most vertices */ Gnum vertglbmin; /* Minimum global index of local vertices */ Gnum vertglbnbr; Gnum vertlocnbr; Gnum vertlocnnd; Gnum vertlocnum; Gnum * vertloctax; Gnum velolocsiz; Gnum velolocsum; Gnum * veloloctax; Gnum * vlblloctax; Gnum vlbllocsiz; Gnum edgelocsiz; Gnum edgelocnum; Gnum * edgeloctab; Gnum edlolocsiz; Gnum * edloloctab; Gnum degrglbmax; #ifdef SCOTCH_DEBUG_DGRAPH1 if ((dimxval < 1) || (dimyval < 1) || (dimzval < 1)) { /* At least one vertex */ errorPrint ("dgraphBuildGrid3D: invalid parameters (1)"); return (1); } if (incrval < 1) { errorPrint ("dgraphBuildGrid3D: invalid parameters (2)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH1 */ vertglbnbr = dimxval * dimyval * dimzval; vertlocnbr = DATASIZE (vertglbnbr, grafptr->procglbnbr, grafptr->proclocnum); if ((flagval & 1) != 0) { /* If 26-neighbor mesh */ degrglbmax = 26; if ((flagval & 2) != 0) { /* If torus graph */ datadat.t26.ngbxmin = (dimxval > 1) ? (dimxval - 1) : dimxval; /* Avoid loop edges */ datadat.t26.ngbxmax = (dimxval > 2) ? (dimxval + 1) : dimxval; datadat.t26.ngbymin = (dimyval > 1) ? (dimyval - 1) : dimyval; datadat.t26.ngbymax = (dimyval > 2) ? (dimyval + 1) : dimyval; datadat.t26.ngbzmin = (dimzval > 1) ? (dimzval - 1) : dimzval; datadat.t26.ngbzmax = (dimzval > 2) ? (dimzval + 1) : dimzval; datadat.funcvrtptr = dgraphBuildGrid3Dvertex26T; } else datadat.funcvrtptr = dgraphBuildGrid3Dvertex26M; } else { /* If 6-neighbor mesh */ degrglbmax = 6; datadat.funcvrtptr = ((flagval & 2) != 0) ? dgraphBuildGrid3Dvertex6T : dgraphBuildGrid3Dvertex6M; } edgelocsiz = vertlocnbr * degrglbmax; /* (Possibly upper bound on) number of edges */ vlbllocsiz = (incrval != 1) ? vertlocnbr : 0; /* If no hashing, no need for vertex labels */ velolocsiz = ((flagval & 4) != 0) ? vertlocnbr : 0; edlolocsiz = ((flagval & 8) != 0) ? edgelocsiz : 0; if (memAllocGroup ((void **) (void *) &vertloctax, (size_t) ((vertlocnbr + 1) * sizeof (Gnum)), /* +1 to indicate end of array */ &veloloctax, (size_t) (velolocsiz * sizeof (Gnum)), &vlblloctax, (size_t) (vlbllocsiz * sizeof (Gnum)), NULL) == NULL) { errorPrint ("dgraphBuildGrid3D: out of memory (1)"); return (1); } if (memAllocGroup ((void **) (void *) &edgeloctab, (size_t) (edgelocsiz * sizeof (Gnum)), &edloloctab, (size_t) (edlolocsiz * sizeof (Gnum)), NULL) == NULL) { memFree (vertloctax); errorPrint ("dgraphBuildGrid3D: out of memory (2)"); return (1); } datadat.baseval = baseval; datadat.dimxval = dimxval; datadat.dimyval = dimyval; datadat.dimzval = dimzval; datadat.edgeloctax = edgeloctab - baseval; datadat.edloloctax = ((flagval & 8) != 0) ? (edloloctab - baseval) : NULL; vertloctax = vertloctax - baseval; veloloctax = ((flagval & 4) != 0) ? (veloloctax - baseval) : NULL; vlblloctax = (incrval != 1) ? (vlblloctax - baseval) : NULL; proclocadj = vertglbnbr % grafptr->procglbnbr; /* Number of processes with +1 number of vertices */ vertglbmin = (vertglbnbr / grafptr->procglbnbr) * grafptr->proclocnum + MIN (grafptr->proclocnum, proclocadj); edgelocnum = vertlocnum = baseval; vertlocnnd = baseval + vertlocnbr; velolocsum = (veloloctax == NULL) ? vertlocnbr : 0; if (incrval != 1) { /* If strided or pseudo-randomly distributed mesh */ Gnum vertglbidx; /* Un-based global index of current vertex */ Gnum rondlocnbr; /* Number of already completed rounds of increments */ Gnum a; Gnum b; a = (vertglbnbr > incrval) ? vertglbnbr : incrval; /* Get biggest of the two */ b = (vertglbnbr + incrval) - a; /* Get smallest of the two */ do { Gnum t; t = a % b; if (t == 0) break; a = b; b = t; } while (b > 1); /* Compute GCD of vertglbnbr and incrval in b */ rondlocnbr = (vertglbmin * b) / vertglbnbr; vertglbidx = (vertglbmin * incrval + rondlocnbr) % vertglbnbr; /* Compute skewed index, with rounds */ for ( ; vertlocnum < vertlocnnd; vertlocnum ++) { Gnum vertglbnum; Gnum positmp; Gnum posxval; Gnum posyval; Gnum poszval; poszval = vertglbidx / (dimxval * dimyval); positmp = vertglbidx % (dimxval * dimyval); posyval = positmp / dimxval; posxval = positmp % dimxval; vertglbnum = vertglbidx + baseval; vertloctax[vertlocnum] = edgelocnum; vlblloctax[vertlocnum] = vertglbnum; if (veloloctax != NULL) { velolocsum += veloloctax[vertlocnum] = (vertglbnum % 16) + 1; } edgelocnum = datadat.funcvrtptr (&datadat, vertglbnum, edgelocnum, posxval, posyval, poszval); #ifdef SCOTCH_DEBUG_DGRAPH2 if (edgelocnum > (edgelocsiz + baseval)) { errorPrint ("dgraphBuildGrid3D: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ vertglbidx = (vertglbidx + incrval) % vertglbnbr; /* Add increment to global index */ if (vertglbidx == rondlocnbr) { /* If we looped back to the current beginning */ rondlocnbr ++; /* Start a new round of increments */ vertglbidx = rondlocnbr; } } } else { /* Regularly sliced mesh */ Gnum vertglbnum; /* Based global vertex number */ Gnum positmp; Gnum posxval; Gnum posyval; Gnum poszval; poszval = vertglbmin / (dimxval * dimyval); positmp = vertglbmin % (dimxval * dimyval); posyval = positmp / dimxval; posxval = positmp % dimxval; for (vertglbnum = vertglbmin + baseval; vertlocnum < vertlocnnd; vertlocnum ++, vertglbnum ++) { vertloctax[vertlocnum] = edgelocnum; if (veloloctax != NULL) { velolocsum += veloloctax[vertlocnum] = (vertglbnum % 16) + 1; } edgelocnum = datadat.funcvrtptr (&datadat, vertglbnum, edgelocnum, posxval, posyval, poszval); #ifdef SCOTCH_DEBUG_DGRAPH2 if (edgelocnum > (edgelocsiz + baseval)) { errorPrint ("dgraphBuildGrid3D: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ if (++ posxval >= dimxval) { posxval = 0; if (++ posyval >= dimyval) { posyval = 0; poszval ++; #ifdef SCOTCH_DEBUG_DGRAPH2 if ((poszval >= dimzval) && (vertglbnum < (vertglbnbr + baseval - 1))){ errorPrint ("dgraphBuildGrid3D: internal error (X)"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ } } } } vertloctax[vertlocnum] = edgelocnum; /* Mark end of local vertex array */ grafptr->flagval = (DGRAPHFREETABS | DGRAPHVERTGROUP | DGRAPHEDGEGROUP); /* All arrays will be freed on exit */ if (dgraphBuild2 (grafptr, baseval, /* Build distributed graph */ vertlocnbr, vertlocnbr, vertloctax, vertloctax + 1, veloloctax, velolocsum, NULL, vlblloctax, edgelocnum - baseval, edgelocsiz, datadat.edgeloctax, NULL, datadat.edloloctax, degrglbmax) != 0) { memFree (datadat.edgeloctax + baseval); /* Free memory group leaders */ memFree (vertloctax + baseval); return (1); } return (0); } scotch-5.1.12b.dfsg/src/libscotch/vmesh_separate_zr.h0000644000175300017530000000520211631334325023024 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : vmesh_separate_zr.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the move-all-to-first-subdomain **/ /** mesh node separation method. **/ /** **/ /** DATES : # Version 4.0 : from : 10 sep 2002 **/ /** to 10 sep 2002 **/ /** **/ /************************************************************/ /* ** The function prototypes. */ #ifndef VMESH_SEPARATE_ZR #define static #endif int vmeshSeparateZr (Vmesh * const); #undef static scotch-5.1.12b.dfsg/src/libscotch/arch.h0000644000175300017530000003560211631334325020227 0ustar hazelscthazelsct/* Copyright 2004,2007-2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : arch.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the generic target architecture **/ /** functions. **/ /** **/ /** DATES : # Version 0.0 : from : 01 dec 1992 **/ /** to : 24 mar 1993 **/ /** # Version 1.2 : from : 04 feb 1994 **/ /** to : 11 feb 1994 **/ /** # Version 1.3 : from : 20 apr 1994 **/ /** to : 20 apr 1994 **/ /** # Version 2.0 : from : 06 jun 1994 **/ /** to : 12 nov 1994 **/ /** # Version 2.1 : from : 07 apr 1995 **/ /** to : 30 jun 1995 **/ /** # Version 3.0 : from : 01 jul 1995 **/ /** to 08 sep 1995 **/ /** # Version 3.1 : from : 02 may 1996 **/ /** to 20 jul 1996 **/ /** # Version 3.2 : from : 07 sep 1996 **/ /** to 13 may 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 07 oct 1998 **/ /** # Version 3.4 : from : 08 nov 2001 **/ /** to 08 nov 2001 **/ /** # Version 4.0 : from : 01 jan 2002 **/ /** to 07 dec 2004 **/ /** # Version 5.1 : from : 11 dec 2007 **/ /** to 11 aug 2010 **/ /** **/ /************************************************************/ #define ARCH_H /* ** The defines. */ /*+ Architecture flags. +*/ #define ARCHNONE 0x0000 /*+ No options set +*/ #define ARCHPART 0x0001 /*+ Architecture without external gains +*/ #define ARCHVAR 0x0002 /*+ Variable-sized architecture +*/ /* ** The type and structure definitions. */ typedef INT Anum; /*+ Generic integer +*/ #define ANUMMAX INTVALMAX #define ANUMSTRING INTSTRING #define ANUM_MPI COMM_INT /*+ MPI type for Gnum is MPI type for INT +*/ /*+ The domain number type. +*/ typedef Anum ArchDomNum; /*+ Domain number +*/ #define ARCHDOMNOTTERM ((ArchDomNum) ~0) /*+ Not-terminal number +*/ /*+ The architecture class type. +*/ typedef struct ArchClass_ { char * archname; /*+ Architecture name +*/ int flagval; /*+ Architecture flags +*/ int (* archLoad) (); /*+ Architecture loading function +*/ int (* archSave) (); /*+ Architecture saving function +*/ int (* archFree) (); /*+ Architecture freeing function +*/ ArchDomNum (* domNum) (); /*+ Domain labeling function +*/ int (* domTerm) (); /*+ Terminal domain building function +*/ Anum (* domSize) (); /*+ Domain size function +*/ Anum (* domWght) (); /*+ Domain weight function +*/ Anum (* domDist) (); /*+ Distance computation function +*/ int (* domFrst) (); /*+ Compute biggest domain +*/ int (* domLoad) (); /*+ Domain loading routine +*/ int (* domSave) (); /*+ Domain saving routine +*/ int (* domBipart) (); /*+ Domain bipartitioning routine +*/ #ifdef SCOTCH_PTSCOTCH int (* domMpiType) (); /*+ Domain MPI type building routine +*/ #endif /* SCOTCH_PTSCOTCH */ int domsizeof; /*+ Size in bytes of domain data +*/ } ArchClass; /*+ The architecture type. +*/ typedef Anum ArchDummy[8]; /*+ Size of the dummy space that can hold any architecture +*/ typedef struct Arch_ { const ArchClass * class; /*+ Pointer to architecture class +*/ union { /*+ Architecture data +*/ ArchDummy dummy; /*+ Dummy data for external size setting +*/ #if 0 ArchDeco deco; /*+ Decomposition-described architecture +*/ ArchMesh2 mesh2; /*+ 2D-mesh architecture +*/ ArchMesh3 mesh3; /*+ 3D-mesh architecture +*/ ArchTorus2 torus2; /*+ 2D-torus architecture +*/ ArchTorus3 torus3; /*+ 3D-torus architecture +*/ ArchHcub hcub; /*+ Hypercube architecture +*/ ArchCmpltw cmpltw; /*+ Weighted complete graph architecture +*/ ArchCmplt cmplt; /*+ Complete graph architecture +*/ ArchLeaf leaf; /*+ Tree-leaf architecture +*/ ArchVcmplt vcmplt; /*+ Variable-sized complete graph architecture +*/ ArchVhcub vhcub; /*+ Variable-sized hypercube architecture +*/ #endif } data; } Arch; /*+ The domain structure type. +*/ typedef Anum ArchDomDummy[6]; /*+ Size of the dummy space that can hold any domain +*/ typedef struct ArchDom_ { union { /*+ The domain data +*/ ArchDomDummy dummy; /*+ Dummy data for external space setting +*/ #if 0 ArchDomDeco deco; /*+ Decomposition-descripted domain type +*/ ArchDomMesh2 mesh2; /*+ 2D-mesh domain type +*/ ArchDomMesh3 mesh3; /*+ 3D-mesh domain type +*/ ArchDomTorus2 torus2; /*+ 2D-torus domain type +*/ ArchDomTorus3 torus3; /*+ 3D-torus domain type +*/ ArchDomHcub hcub; /*+ Hypercube domain type +*/ ArchDomCmplt cmplt; /*+ Complete graph domain type +*/ ArchDomCmpltw cmpltw; /*+ Weighted complete graph domain type +*/ ArchDomLeaf leaf; /*+ Tree-leaf domain type +*/ ArchDomVcmplt vcmplt; /*+ Variable-sized complete graph domain type +*/ ArchDomVhcub vhcub; /*+ Variable-sized hypercube domain type +*/ #endif } data; } ArchDom; /* ** The function prototypes. */ #ifndef ARCH #define static #endif int archInit (Arch * restrict const); int archExit (Arch * restrict const); int archFree (Arch * restrict const); int archLoad (Arch * restrict const, FILE * const); int archSave (const Arch * const, FILE * const); char * archName (const Arch * const); const ArchClass * archClass (const char * const); ArchDomNum archDomNum (const Arch * const, const ArchDom * const); int archDomTerm (const Arch * const, ArchDom * const, const ArchDomNum); Anum archDomSize (const Arch * const, const ArchDom * const); Anum archDomWght (const Arch * const, const ArchDom * const); Anum archDomDist (const Arch * const, const ArchDom * const, const ArchDom * const); int archDomFrst (const Arch * const, ArchDom * const); int archDomLoad (const Arch * const, ArchDom * const, FILE * const); int archDomSave (const Arch * const, const ArchDom * const, FILE * const); int archDomBipart (const Arch * const, const ArchDom * const, ArchDom * const, ArchDom * const); #ifdef SCOTCH_PTSCOTCH int archDomMpiType (const Arch * const, MPI_Datatype * const); #endif /* SCOTCH_PTSCOTCH */ #undef static /* ** The macro definitions. */ #define archDomSizeof(a) ((a)->class->domsizeof) #define archName(a) (((a)->class == NULL) ? "" : (a)->class->archname) #define archPart(a) ((((a)->class->flagval) & ARCHPART) != 0) #define archVar(a) ((((a)->class->flagval) & ARCHVAR) != 0) #if ((! defined SCOTCH_DEBUG_ARCH2) || (defined ARCH)) #define archDomNum2(arch,dom) (((ArchDomNum (*) (const void * const, const void * const)) (arch)->class->domNum) ((const void * const) &(arch)->data, (const void * const) &(dom)->data)) #define archDomTerm2(arch,dom,num) (((int (*) (const void * const, void * const, const ArchDomNum)) (arch)->class->domTerm) ((void *) &(arch)->data, (void *) &(dom)->data, (num))) #define archDomSize2(arch,dom) (((Anum (*) (const void * const, const void * const)) (arch)->class->domSize) ((void *) &(arch)->data, (void *) &(dom)->data)) #define archDomWght2(arch,dom) (((Anum (*) (const void * const, const void * const)) (arch)->class->domWght) ((void *) &(arch)->data, (void *) &(dom)->data)) #define archDomDist2(arch,dom0,dom1) (((Anum (*) (const void * const, const void * const, const void * const)) (arch)->class->domDist) ((const void *) &(arch)->data, (const void *) &(dom0)->data, (const void *) &(dom1)->data)) #define archDomFrst2(arch,dom) (((int (*) (const void * const, void * const)) (arch)->class->domFrst) ((const void * const) &(arch)->data, (void * const) &(dom)->data)) #define archDomBipart2(arch,dom,dom0,dom1) (((int (*) (const void * const, const void * const, void * const, void * const)) (arch)->class->domBipart) ((const void * const) &(arch)->data, (const void * const) &(dom)->data, (void * const) &(dom0)->data, (void * const) &(dom1)->data)) #endif #ifndef SCOTCH_DEBUG_ARCH2 #define archDomNum archDomNum2 #define archDomTerm archDomTerm2 #define archDomSize archDomSize2 #define archDomWght archDomWght2 #define archDomDist archDomDist2 #define archDomFrst archDomFrst2 #define archDomBipart archDomBipart2 #endif /* SCOTCH_DEBUG_ARCH2 */ #ifdef SCOTCH_PTSCOTCH #define ARCHCLASSBLOCK(s,n,f) { s, f, \ arch##n##ArchLoad, \ arch##n##ArchSave, \ arch##n##ArchFree, \ arch##n##DomNum, \ arch##n##DomTerm, \ arch##n##DomSize, \ arch##n##DomWght, \ arch##n##DomDist, \ arch##n##DomFrst, \ arch##n##DomLoad, \ arch##n##DomSave, \ arch##n##DomBipart, \ arch##n##DomMpiType, \ sizeof (Arch##n##Dom) } #else /* SCOTCH_PTSCOTCH */ #define ARCHCLASSBLOCK(s,n,f) { s, f, \ arch##n##ArchLoad, \ arch##n##ArchSave, \ arch##n##ArchFree, \ arch##n##DomNum, \ arch##n##DomTerm, \ arch##n##DomSize, \ arch##n##DomWght, \ arch##n##DomDist, \ arch##n##DomFrst, \ arch##n##DomLoad, \ arch##n##DomSave, \ arch##n##DomBipart, \ sizeof (Arch##n##Dom) } #endif /* SCOTCH_PTSCOTCH */ #define ARCHCLASSBLOCKNULL { NULL, ARCHNONE } scotch-5.1.12b.dfsg/src/libscotch/hmesh_order_gp.c0000644000175300017530000002772511631334325022301 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_order_gp.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders a subgraph (most **/ /** likely a separator) using the Gibbs, **/ /** Poole, and Stockmeyer algorithm. **/ /** **/ /** DATES : # Version 3.2 : from : 31 oct 1996 **/ /** to 27 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 02 oct 1998 **/ /** # Version 4.0 : from : 05 nov 2002 **/ /** to : 27 jan 2004 **/ /** # Version 5.0 : from : 12 sep 2007 **/ /** to : 12 sep 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH_ORDER_GP #include "module.h" #include "common.h" #include "graph.h" #include "order.h" #include "mesh.h" #include "hmesh.h" #include "hmesh_order_gp.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hmeshOrderGp ( const Hmesh * restrict const meshptr, Order * restrict const ordeptr, const Gnum ordenum, OrderCblk * restrict const cblkptr, /*+ Single column-block +*/ const HmeshOrderGpParam * restrict const paraptr) { HmeshOrderGpQueue queue; /* Neighbor queue */ HmeshOrderGpVertex * restrict vexxtax; /* Based access to vertex array */ HmeshOrderGpVertex * rootptr; /* Pointer to root vertex */ Gnum passnum; /* Pass number */ int passflag; /* Flag set if diameter changed */ Gnum vdianum; /* Vertex which achieves diameter */ Gnum vdiadist; /* Maximum diameter value found */ Gnum vnodnbr; /* Number of vertices found yet */ Gnum ordeval; /* Current ordering value */ if (memAllocGroup ((void **) (void *) &queue.qtab, (size_t) ((meshptr->vnohnnd - meshptr->m.baseval) * sizeof (Gnum)), &vexxtax, (size_t) ((meshptr->m.velmnbr + meshptr->m.vnodnbr) * sizeof (HmeshOrderGpVertex)), NULL) == NULL) { errorPrint ("hmeshOrderGp: out of memory"); return (1); } vexxtax -= meshptr->m.baseval; /* Base vexxtab array */ memSet (vexxtax + meshptr->m.velmbas, 0, meshptr->m.velmnbr * sizeof (HmeshOrderGpVertex)); /* Initialize pass numbers for */ memSet (vexxtax + meshptr->m.vnodbas, 0, (meshptr->vnohnnd - meshptr->m.vnodbas) * sizeof (HmeshOrderGpVertex)); /* All but halo node vertices */ for (vnodnbr = 0, ordeval = ordenum, rootptr = vexxtax + meshptr->m.vnodbas, passnum = 1; /* For all connected components */ vnodnbr < meshptr->vnohnbr; passnum ++) { while (rootptr->passnum != 0) /* Find first unallocated root */ rootptr ++; vdianum = rootptr - vexxtax; /* Start from found root */ vdiadist = 0; for (passflag = 1; (passflag -- != 0) && (passnum <= paraptr->passnbr); passnum ++) { /* Loop if modifications */ hmeshOrderGpQueueFlush (&queue); /* Flush vertex queue */ hmeshOrderGpQueuePut (&queue, vdianum); /* Start from diameter vertex */ vexxtax[vdianum].passnum = passnum; /* It has been enqueued */ vexxtax[vdianum].vertdist = 0; /* It is at distance zero */ do { /* Loop on vertices in queue */ Gnum vnodnum; /* Number of current vertex */ Gnum vnoddist; /* Distance of current vertex */ Gnum enodnum; vnodnum = hmeshOrderGpQueueGet (&queue); /* Get vertex from queue */ vnoddist = vexxtax[vnodnum].vertdist; /* Get vertex distance */ if ((vnoddist > vdiadist) || /* If vertex increases diameter */ ((vnoddist == vdiadist) && /* Or is at diameter distance */ ((meshptr->m.vendtax[vnodnum] - meshptr->m.verttax[vnodnum]) < /* With smaller degree */ (meshptr->m.vendtax[vdianum] - meshptr->m.verttax[vdianum])))) { vdianum = vnodnum; /* Set it as new diameter vertex */ vdiadist = vnoddist; passflag = 1; } vnoddist ++; /* Set neighbor distance */ for (enodnum = meshptr->m.verttax[vnodnum]; enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { Gnum velmnum; Gnum eelmnum; velmnum = meshptr->m.edgetax[enodnum]; /* Get neighboring element */ if (vexxtax[velmnum].passnum >= passnum) /* If element already scanned */ continue; /* Skip to next element */ vexxtax[velmnum].passnum = passnum; /* Set element as scanned */ for (eelmnum = meshptr->m.verttax[velmnum]; /* For all neighboring non-halo nodes */ eelmnum < meshptr->vehdtax[velmnum]; eelmnum ++) { Gnum vnodend; /* Neighboring node */ vnodend = meshptr->m.edgetax[eelmnum]; /* Get neighboring node */ if (vexxtax[vnodend].passnum < passnum) { /* If node vertex not yet enqueued */ hmeshOrderGpQueuePut (&queue, vnodend); /* Enqueue neighbor vertex */ vexxtax[vnodend].passnum = passnum; vexxtax[vnodend].vertdist = vnoddist; } } } } while (! hmeshOrderGpQueueEmpty (&queue)); /* As long as queue is not empty */ } hmeshOrderGpQueueFlush (&queue); /* Flush vertex queue */ hmeshOrderGpQueuePut (&queue, vdianum); /* Start from diameter vertex */ vexxtax[vdianum].passnum = passnum; /* It has been enqueued */ do { /* Loop on vertices in queue */ Gnum vnodnum; /* Number of current vertex */ Gnum vnoddist; /* Distance of current vertex */ vnodnum = hmeshOrderGpQueueGet (&queue); /* Get vertex from queue */ if (vexxtax[vnodnum].passnum > passnum) /* If vertex already ordered */ continue; /* Skip to next vertex in queue */ vnoddist = vexxtax[vnodnum].vertdist; /* Get vertex distance */ do { /* Loop on vertices in layer */ Gnum enodnum; Gnum enodnnd; ordeptr->peritab[ordeval] = (meshptr->m.vnumtax == NULL) /* Order node vertex */ ? vnodnum - (meshptr->m.vnodbas - meshptr->m.baseval) : meshptr->m.vnumtax[vnodnum]; #ifdef SCOTCH_DEBUG_ORDER2 if ((ordeptr->peritab[ordeval] < ordeptr->baseval) || (ordeptr->peritab[ordeval] >= (ordeptr->baseval + ordeptr->vnodnbr))) { errorPrint ("hmeshOrderGp: invalid permutation index"); return (1); } #endif /* SCOTCH_DEBUG_ORDER2 */ ordeval ++; vexxtax[vnodnum].passnum = (passnum + 1); /* Set vertex as ordered */ vnodnbr ++; /* Count it */ for (enodnum = meshptr->m.verttax[vnodnum], enodnnd = meshptr->m.vendtax[vnodnum], vnodnum = ~0; enodnum < enodnnd; enodnum ++) { /* Order node vertices with high locality */ Gnum velmnum; /* Neighboring element */ Gnum eelmnum; velmnum = meshptr->m.edgetax[enodnum]; /* Get neighboring element */ if (vexxtax[velmnum].passnum >= passnum) /* If element already scanned */ continue; /* Skip to next element */ vexxtax[velmnum].passnum = passnum; /* Set element as scanned */ for (eelmnum = meshptr->m.verttax[velmnum]; /* For all neighboring non-halo nodes */ eelmnum < meshptr->vehdtax[velmnum]; eelmnum ++) { Gnum vnodend; /* Neighboring node */ vnodend = meshptr->m.edgetax[eelmnum]; /* Get neighboring node */ if (vexxtax[vnodend].passnum <= passnum) { /* If vertex not ordered yet */ if ((vnodnum == ~0) && /* If no next vertex set yet */ (vexxtax[vnodend].vertdist == vnoddist)) /* And in same layer */ vnodnum = vnodend; /* Set neighbor as next vertex */ else if (vexxtax[vnodend].passnum < passnum) { /* If not enqueued yet */ hmeshOrderGpQueuePut (&queue, vnodend); /* Enqueue neighbor vertex */ vexxtax[vnodend].passnum = passnum; /* Set it as enqueued */ } } } } } while (vnodnum != ~0); } while (! hmeshOrderGpQueueEmpty (&queue)); /* As long as queue is not empty */ } #ifdef SCOTCH_DEBUG_ORDER2 for (ordeval = ordenum; ordeval < (ordenum + meshptr->vnohnbr); ordeval ++) { if (ordeptr->peritab[ordeval] == ~0) { errorPrint ("hmeshOrderGp: internal error"); memFree (queue.qtab); /* Free group leader */ return (1); } } #endif /* SCOTCH_DEBUG_ORDER2 */ memFree (queue.qtab); /* Free group leader */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/hmesh_hgraph.c0000644000175300017530000003456011631334325021744 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hmesh_hgraph.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module contains the source halo **/ /** mesh to halo graph conversion function. **/ /** **/ /** DATES : # Version 4.0 : from : 30 nov 2003 **/ /** to 05 may 2004 **/ /** # Version 5.0 : from : 10 sep 2007 **/ /** to : 10 sep 2007 **/ /** **/ /** NOTES : # From a given halo mesh is created a **/ /** halo graph, such that all vertices of **/ /** the graph represent the nodes of the **/ /** mesh, and there exists an edge **/ /** between two vertices if there exists **/ /** at least one element to which the two **/ /** associated nodes belong. **/ /** While all non-halo nodes become non- **/ /** halo vertices, some halo nodes may **/ /** disappear from the graph if their **/ /** elements are only connected to other **/ /** halo nodes. **/ /** Since the contents of vnumtab are **/ /** based with respect to s.baseval and **/ /** not to vnodbas, the vnumtab array can **/ /** simply be shared by the graph. **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HMESH_HGRAPH #include "module.h" #include "common.h" #include "graph.h" #include "hgraph.h" #include "mesh.h" #include "hmesh.h" #include "hmesh_hgraph.h" /************************************/ /* */ /* The halo graph building routine. */ /* */ /************************************/ /* This routine builds a halo graph from ** the given halo mesh. ** It returns: ** - 0 : if the halo graph has been successfully built. ** - 1 : on error. */ int hmeshHgraph ( const Hmesh * restrict const meshptr, /*+ Original mesh +*/ Hgraph * restrict const grafptr) /*+ Graph to build +*/ { Gnum hashnbr; /* Number of vertices in hash table */ Gnum hashsiz; /* Size of hash table */ Gnum hashmsk; /* Mask for access to hash table */ HmeshHgraphHash * restrict hashtab; /* Table of edges to other node vertices */ Gnum edgemax; /* Upper bound of number of edges in mesh */ Gnum edgennd; /* Based upper bound on number of edges */ Gnum enohnbr; /* Number of non-halo edges */ Gnum edgenum; /* Number of current graph edge */ Gnum vertnum; /* Number of current graph vertex */ Gnum degrmax; #ifdef SCOTCH_DEBUG_HMESH2 if (hmeshCheck (meshptr) != 0) { errorPrint ("hmeshHgraph: invalid input halo mesh"); return (1); } #endif /* SCOTCH_DEBUG_HMESH2 */ grafptr->s.flagval = GRAPHFREETABS | GRAPHVERTGROUP | GRAPHEDGEGROUP; grafptr->s.baseval = meshptr->m.baseval; grafptr->s.vertnbr = meshptr->m.vnodnbr; grafptr->s.vertnnd = meshptr->m.vnodnbr + meshptr->m.baseval; grafptr->vnohnbr = meshptr->vnohnbr; grafptr->vnohnnd = meshptr->vnohnbr + grafptr->s.baseval; grafptr->vnlosum = meshptr->vnhlsum; for (hashsiz = 2, hashnbr = meshptr->m.degrmax * meshptr->m.degrmax * 2; /* Compute size of hash table */ hashsiz < hashnbr; hashsiz <<= 1) ; hashmsk = hashsiz - 1; if (memAllocGroup ((void **) (void *) &grafptr->s.verttax, (size_t) ((grafptr->s.vertnbr + 1) * sizeof (Gnum)), &grafptr->vnhdtax, (size_t) ( grafptr->vnohnbr * sizeof (Gnum)), NULL) == NULL) { errorPrint ("hmeshHgraph: out of memory (1)"); return (1); } if ((hashtab = memAlloc (hashsiz * sizeof (HmeshHgraphHash))) == NULL) { errorPrint ("hmeshHgraph: out of memory (2)"); memFree (grafptr->s.verttax); return (1); } grafptr->s.verttax -= grafptr->s.baseval; grafptr->s.vendtax = grafptr->s.verttax + 1; grafptr->vnhdtax -= grafptr->s.baseval; if (meshptr->m.vnumtax != NULL) /* If (node) vertex index array present, point to its relevant part */ grafptr->s.vnumtax = meshptr->m.vnumtax + (meshptr->m.vnodbas - grafptr->s.baseval); /* Since GRAPHVERTGROUP, no problem on graphFree */ if (meshptr->m.vnlotax != NULL) /* Keep node part of mesh (node) vertex load array as graph vertex load array */ grafptr->s.velotax = meshptr->m.vnlotax + (meshptr->m.vnodbas - grafptr->s.baseval); /* Since GRAPHVERTGROUP, no problem on graphFree */ grafptr->s.velosum = meshptr->m.vnlosum; edgemax = ((meshptr->m.degrmax * meshptr->m.degrmax) / 2 + 1) * meshptr->m.vnodnbr; /* Compute estimated number of edges in graph */ #ifdef SCOTCH_DEBUG_HMESH2 edgemax = meshptr->m.degrmax + 4; /* Test dynamic reallocation of edge array; 4 guarantees that 25% > 0 */ #endif /* SCOTCH_DEBUG_HMESH2 */ if ((grafptr->s.edgetax = memAlloc (edgemax * sizeof (Gnum))) == NULL) { errorPrint ("hmeshHgraph: out of memory (3)"); hgraphFree (grafptr); return (1); } grafptr->s.edgetax -= grafptr->s.baseval; memSet (hashtab, ~0, hashsiz * sizeof (HmeshHgraphHash)); /* Initialize hash table */ for (vertnum = edgenum = grafptr->s.baseval, edgennd = edgemax + grafptr->s.baseval, enohnbr = degrmax = 0; /* Build graph edges for non-halo vertices */ vertnum < grafptr->vnohnnd; vertnum ++) { Gnum vnodnum; Gnum hnodnum; Gnum enodnum; Gnum enhdnum; /* Index of first non-halo neighbor in edge array for current vertex */ grafptr->s.verttax[vertnum] = edgenum; vnodnum = vertnum + (meshptr->m.vnodbas - meshptr->m.baseval); hnodnum = (vnodnum * HMESHHGRAPHHASHPRIME) & hashmsk; /* Prevent adding loop edge */ hashtab[hnodnum].vertnum = vnodnum; hashtab[hnodnum].vertend = vnodnum; for (enodnum = meshptr->m.verttax[vnodnum], enhdnum = edgenum; enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { Gnum velmnum; Gnum eelmnum; velmnum = meshptr->m.edgetax[enodnum]; for (eelmnum = meshptr->m.verttax[velmnum]; eelmnum < meshptr->m.vendtax[velmnum]; eelmnum ++) { Gnum vnodend; Gnum hnodend; vnodend = meshptr->m.edgetax[eelmnum]; for (hnodend = (vnodend * HMESHHGRAPHHASHPRIME) & hashmsk; ; hnodend = (hnodend + 1) & hashmsk) { if (hashtab[hnodend].vertnum != vnodnum) { /* If edge not yet created */ Gnum vertend; if (edgenum == edgennd) { /* If edge array already full */ Gnum edgemax; Gnum * restrict edgetmp; edgemax = edgennd - grafptr->s.baseval; /* Increase size by 25 % */ edgemax = edgemax + (edgemax >> 2); if ((edgetmp = memRealloc (grafptr->s.edgetax + grafptr->s.baseval, edgemax * sizeof (Gnum))) == NULL) { errorPrint ("hmeshHgraph: out of memory (4)"); hgraphFree (grafptr); memFree (hashtab); return (1); } grafptr->s.edgetax = edgetmp - grafptr->s.baseval; edgennd = edgemax + grafptr->s.baseval; } hashtab[hnodend].vertnum = vnodnum; /* Record new edge */ hashtab[hnodend].vertend = vnodend; vertend = vnodend - (meshptr->m.vnodbas - grafptr->s.baseval); if (vnodend >= meshptr->vnohnnd) /* If halo edge */ grafptr->s.edgetax[edgenum ++] = vertend; /* Build at end of array */ else { /* If non-halo edge */ if (edgenum != enhdnum) /* If already halo edges */ grafptr->s.edgetax[edgenum] = grafptr->s.edgetax[enhdnum]; /* Make room */ grafptr->s.edgetax[enhdnum ++] = vertend; /* Record new edge */ edgenum ++; /* One more edge created */ } break; } if (hashtab[hnodend].vertend == vnodend) /* If edge already exists */ break; /* Skip to next neighbor */ } } } grafptr->vnhdtax[vertnum] = enhdnum; /* Set end of non-halo edge array */ enohnbr += enhdnum - grafptr->s.verttax[vertnum]; if ((edgenum - grafptr->s.verttax[vertnum]) > degrmax) /* Compute maximum degree */ degrmax = (edgenum - grafptr->s.verttax[vertnum]); } grafptr->enohnbr = enohnbr; /* All other edges will be halo edges */ for ( ; vertnum < grafptr->s.vertnnd; vertnum ++) { /* Build graph edges for halo vertices */ Gnum vnodnum; Gnum enodnum; vnodnum = vertnum + (meshptr->m.vnodbas - meshptr->m.baseval); grafptr->s.verttax[vertnum] = edgenum; for (enodnum = meshptr->m.verttax[vnodnum]; enodnum < meshptr->m.vendtax[vnodnum]; enodnum ++) { Gnum velmnum; Gnum eelmnum; velmnum = meshptr->m.edgetax[enodnum]; for (eelmnum = meshptr->m.verttax[velmnum]; /* Only consider non-halo edges of elements this time */ eelmnum < meshptr->vehdtax[velmnum]; eelmnum ++) { Gnum vnodend; Gnum hnodend; vnodend = meshptr->m.edgetax[eelmnum]; #ifdef SCOTCH_DEBUG_HMESH2 if (vnodend >= meshptr->vnohnnd) { /* Not visiting halo edges should prevent this */ errorPrint ("hmeshHgraph: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_HMESH2 */ for (hnodend = (vnodend * HMESHHGRAPHHASHPRIME) & hashmsk; ; hnodend = (hnodend + 1) & hashmsk) { if (hashtab[hnodend].vertnum != vnodnum) { /* If edge not yet created */ Gnum vertend; if (edgenum == edgennd) { /* If edge array already full */ Gnum edgemax; Gnum * restrict edgetmp; edgemax = edgennd - grafptr->s.baseval; /* Increase size by 25 % */ edgemax = edgemax + (edgemax >> 2); if ((edgetmp = memRealloc (grafptr->s.edgetax + grafptr->s.baseval, edgemax * sizeof (Gnum))) == NULL) { errorPrint ("hmeshHgraph: out of memory (5)"); hgraphFree (grafptr); memFree (hashtab); return (1); } grafptr->s.edgetax = edgetmp - grafptr->s.baseval; edgennd = edgemax + grafptr->s.baseval; } hashtab[hnodend].vertnum = vnodnum; /* Record new edge */ hashtab[hnodend].vertend = vnodend; vertend = vnodend - (meshptr->m.vnodbas - grafptr->s.baseval); grafptr->s.edgetax[edgenum ++] = vertend; /* Build halo edge */ break; } if (hashtab[hnodend].vertend == vnodend) /* If edge already exists */ break; /* Skip to next neighbor */ } } } if ((edgenum - grafptr->s.verttax[vertnum]) > degrmax) /* Compute maximum degree */ degrmax = (edgenum - grafptr->s.verttax[vertnum]); } grafptr->s.verttax[vertnum] = edgenum; /* Set end of vertex array */ grafptr->s.edgenbr = edgenum - grafptr->s.baseval; grafptr->s.degrmax = degrmax; memFree (hashtab); #ifdef SCOTCH_DEBUG_HMESH2 if (hgraphCheck (grafptr) != 0) { errorPrint ("hmeshHgraph: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_HMESH2 */ return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_graph_order.c0000644000175300017530000004747011631334325023333 0ustar hazelscthazelsct/* Copyright 2004,2007,2008,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_graph_order.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the API for the graph **/ /** ordering routines of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 3.2 : from : 19 aug 1998 **/ /** to 22 aug 1998 **/ /** # Version 3.3 : from : 01 oct 1998 **/ /** to 27 mar 1999 **/ /** # Version 4.0 : from : 29 jan 2002 **/ /** to 08 sep 2006 **/ /** # Version 5.0 : from : 19 dec 2006 **/ /** to 04 aug 2007 **/ /** # Version 5.1 : from : 30 oct 2007 **/ /** to 14 aug 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "order.h" #include "hgraph.h" #include "hgraph_order_st.h" #include "library_order.h" #include "scotch.h" /************************************/ /* */ /* These routines are the C API for */ /* the graph ordering routines. */ /* */ /************************************/ /*+ This routine initializes an API ordering *** with respect to the given source graph *** and the locations of output parameters. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphOrderInit ( const SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ SCOTCH_Ordering * const ordeptr, /*+ Ordering structure to initialize +*/ SCOTCH_Num * const permtab, /*+ Direct permutation array +*/ SCOTCH_Num * const peritab, /*+ Inverse permutation array +*/ SCOTCH_Num * const cblkptr, /*+ Pointer to number of column blocks +*/ SCOTCH_Num * const rangtab, /*+ Column block range array +*/ SCOTCH_Num * const treetab) /*+ Separator tree array +*/ { Graph * srcgrafptr; LibOrder * libordeptr; #ifdef SCOTCH_DEBUG_LIBRARY1 if (sizeof (SCOTCH_Ordering) < sizeof (LibOrder)) { errorPrint ("SCOTCH_graphOrderInit: internal error"); return (1); } #endif /* SCOTCH_DEBUG_LIBRARY1 */ srcgrafptr = (Graph *) grafptr; /* Use structure as source graph */ libordeptr = (LibOrder *) ordeptr; libordeptr->permtab = ((permtab == NULL) || ((void *) permtab == (void *) grafptr)) ? NULL : (Gnum *) permtab; libordeptr->peritab = ((peritab == NULL) || ((void *) peritab == (void *) grafptr)) ? NULL : (Gnum *) peritab; libordeptr->cblkptr = ((cblkptr == NULL) || ((void *) cblkptr == (void *) grafptr)) ? NULL : (Gnum *) cblkptr; libordeptr->rangtab = ((rangtab == NULL) || ((void *) rangtab == (void *) grafptr)) ? NULL : (Gnum *) rangtab; libordeptr->treetab = ((treetab == NULL) || ((void *) treetab == (void *) grafptr)) ? NULL : (Gnum *) treetab; return (orderInit (&libordeptr->o, srcgrafptr->baseval, srcgrafptr->vertnbr, libordeptr->peritab)); } /*+ This routine frees an API ordering. *** It returns: *** - VOID : in all cases. +*/ void SCOTCH_graphOrderExit ( const SCOTCH_Graph * const grafptr, SCOTCH_Ordering * const ordeptr) { orderExit (&((LibOrder *) ordeptr)->o); } /*+ This routine loads the contents of *** the given ordering from the given stream. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphOrderLoad ( const SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ SCOTCH_Ordering * restrict const ordeptr, /*+ Ordering to load +*/ FILE * restrict const stream) /*+ Output stream +*/ { Graph * srcgrafptr; LibOrder * libordeptr; srcgrafptr = (Graph *) grafptr; libordeptr = (LibOrder *) ordeptr; if (orderLoad (&libordeptr->o, srcgrafptr->vlbltax, stream) != 0) return (1); if (libordeptr->permtab != NULL) /* Build inverse permutation if wanted */ orderPeri (libordeptr->o.peritab, srcgrafptr->baseval, libordeptr->o.vnodnbr, libordeptr->permtab, srcgrafptr->baseval); return (0); } /*+ This routine saves the contents of *** the given ordering to the given stream. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphOrderSave ( const SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ const SCOTCH_Ordering * const ordeptr, /*+ Ordering to save +*/ FILE * const stream) /*+ Output stream +*/ { return (orderSave (&((LibOrder *) ordeptr)->o, ((Graph *) grafptr)->vlbltax + ((Graph *) grafptr)->baseval, stream)); } /*+ This routine saves to the given stream *** the mapping data associated with the *** given ordering. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphOrderSaveMap ( const SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ const SCOTCH_Ordering * const ordeptr, /*+ Ordering to save +*/ FILE * const stream) /*+ Output stream +*/ { return (orderSaveMap (&((LibOrder *) ordeptr)->o, ((Graph *) grafptr)->vlbltax, stream)); } /*+ This routine saves to the given stream *** the separator tree data associated with *** the given ordering. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphOrderSaveTree ( const SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ const SCOTCH_Ordering * const ordeptr, /*+ Ordering to save +*/ FILE * const stream) /*+ Output stream +*/ { return (orderSaveTree (&((LibOrder *) ordeptr)->o, ((Graph *) grafptr)->vlbltax, stream)); } /*+ This routine computes an ordering *** of the API ordering structure with *** respect to the given strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphOrderCompute ( SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ SCOTCH_Ordering * const ordeptr, /*+ Ordering to compute +*/ SCOTCH_Strat * const stratptr) /*+ Ordering strategy +*/ { return (SCOTCH_graphOrderComputeList (grafptr, ordeptr, ((Graph *) grafptr)->vertnbr, NULL, stratptr)); } /*+ This routine computes a partial ordering *** of the listed vertices of the API ordering *** structure graph with respect to the given *** strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphOrderComputeList ( SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ SCOTCH_Ordering * const ordeptr, /*+ Ordering to compute +*/ const SCOTCH_Num listnbr, /*+ Number of vertices in list +*/ const SCOTCH_Num * const listtab, /*+ List of vertex indices to order +*/ SCOTCH_Strat * const stratptr) /*+ Ordering strategy +*/ { Graph * restrict srcgrafptr; LibOrder * libordeptr; /* Pointer to ordering */ Hgraph halgrafdat; /* Halo source graph structure */ Hgraph halgraftmp; /* Halo source graph structure */ Hgraph * halgrafptr; /* Pointer to halo graph structure */ const Strat * ordstratptr; /* Pointer to ordering strategy */ OrderCblk * cblkptr; srcgrafptr = (Graph *) grafptr; libordeptr = (LibOrder *) ordeptr; /* Get ordering */ #ifdef SCOTCH_DEBUG_GRAPH2 if (graphCheck (srcgrafptr) != 0) { errorPrint ("SCOTCH_graphOrderComputeList: invalid input graph"); return (1); } #endif /* SCOTCH_DEBUG_GRAPH2 */ #ifdef SCOTCH_DEBUG_LIBRARY1 if ((listnbr < 0) || (listnbr > srcgrafptr->vertnbr)) { errorPrint ("SCOTCH_graphOrderComputeList: invalid parameters (1)"); return (1); } #endif /* SCOTCH_DEBUG_LIBRARY1 */ if (listnbr == 0) { /* If empty list, return identity peremutation */ Gnum vertnum; for (vertnum = 0; vertnum < srcgrafptr->vertnbr; vertnum ++) libordeptr->o.peritab[vertnum] = vertnum + srcgrafptr->baseval; return (0); } if (*((Strat **) stratptr) == NULL) /* Set default ordering strategy if necessary */ SCOTCH_stratGraphOrderBuild (stratptr, SCOTCH_STRATQUALITY, 0.2); ordstratptr = *((Strat **) stratptr); if (ordstratptr->tabl != &hgraphorderststratab) { errorPrint ("SCOTCH_graphOrderComputeList: not an ordering strategy"); return (1); } memCpy (&halgrafdat.s, grafptr, sizeof (Graph)); /* Copy non-halo graph data */ halgrafdat.s.flagval &= ~GRAPHFREETABS; /* Do not allow to free arrays */ halgrafdat.s.edlotax = NULL; /* Don't mind about edge loads */ halgrafdat.vnohnbr = halgrafdat.s.vertnbr; /* All vertices are non-halo */ halgrafdat.vnohnnd = halgrafdat.s.vertnnd; /* No halo present */ halgrafdat.vnhdtax = halgrafdat.s.vendtax; /* End of non-halo vertices */ halgrafdat.vnlosum = halgrafdat.s.velosum; /* Sum of node vertex weights */ halgrafdat.enohnbr = halgrafdat.s.edgenbr; /* No halo present */ halgrafdat.enohsum = halgrafdat.s.edlosum; halgrafdat.levlnum = 0; /* No nested dissection yet */ if (listnbr == srcgrafptr->vertnbr) { /* If work on full graph */ halgrafptr = &halgrafdat; cblkptr = &libordeptr->o.cblktre; } else { VertList listdat; Gnum * restrict peritax; Gnum listnum; Gnum vertnum; Gnum halonum; if ((cblkptr = (OrderCblk *) memAlloc (2 * sizeof (OrderCblk))) == NULL) { errorPrint ("SCOTCH_graphOrderComputeList: out of memory"); return (1); } libordeptr->o.treenbr = 3; libordeptr->o.cblknbr = 2; libordeptr->o.cblktre.typeval = ORDERCBLKNEDI; /* Node becomes a (fake) nested dissection node */ libordeptr->o.cblktre.vnodnbr = srcgrafptr->vertnbr; libordeptr->o.cblktre.cblknbr = 2; libordeptr->o.cblktre.cblktab = cblkptr; cblkptr[0].typeval = ORDERCBLKOTHR; /* Build column blocks */ cblkptr[0].vnodnbr = listnbr; cblkptr[0].cblknbr = 0; cblkptr[0].cblktab = NULL; cblkptr[1].typeval = ORDERCBLKOTHR; cblkptr[1].vnodnbr = srcgrafptr->vertnbr - listnbr; cblkptr[1].cblknbr = 0; cblkptr[1].cblktab = NULL; memSet (libordeptr->o.peritab, 0, srcgrafptr->vertnbr * sizeof (Gnum)); /* Fill inverse permutation with dummy values */ for (listnum = 0, peritax = libordeptr->o.peritab - srcgrafptr->baseval; listnum < listnbr; listnum ++) { #ifdef SCOTCH_DEBUG_LIBRARY2 if ((listtab[listnum] < srcgrafptr->baseval) || (listtab[listnum] >= srcgrafptr->vertnnd)) { errorPrint ("SCOTCH_graphOrderComputeList: invalid parameters (2)"); return (1); } #endif /* SCOTCH_DEBUG_LIBRARY2 */ peritax[listtab[listnum]] = ~0; /* TRICK: use peritab as flag array to mark used vertices */ } for (vertnum = halonum = srcgrafptr->vertnnd - 1; vertnum >= srcgrafptr->baseval; vertnum --) { if (peritax[vertnum] == 0) peritax[halonum --] = vertnum; } #ifdef SCOTCH_DEBUG_LIBRARY2 if (halonum != (listnbr + srcgrafptr->baseval - 1)) { errorPrint ("SCOTCH_graphOrderComputeList: internal error"); return (1); } #endif /* SCOTCH_DEBUG_LIBRARY2 */ listdat.vnumnbr = listnbr; listdat.vnumtab = (Gnum * const) listtab; if (hgraphInduceList (&halgrafdat, &listdat, srcgrafptr->vertnbr - listnbr, &halgraftmp) != 0) { errorPrint ("SCOTCH_graphOrderComputeList: cannot create induced subgraph"); return (1); } halgrafptr = &halgraftmp; } hgraphOrderSt (halgrafptr, &libordeptr->o, 0, cblkptr, ordstratptr); if (halgrafptr != &halgrafdat) /* If induced subgraph created */ hgraphExit (halgrafptr); /* Free it */ #ifdef SCOTCH_DEBUG_LIBRARY2 if (orderCheck (&libordeptr->o) != 0) return (1); #endif /* SCOTCH_DEBUG_LIBRARY2 */ if (libordeptr->permtab != NULL) /* Build direct permutation if wanted */ orderPeri (libordeptr->o.peritab, srcgrafptr->baseval, libordeptr->o.vnodnbr, libordeptr->permtab, srcgrafptr->baseval); if (libordeptr->rangtab != NULL) /* Build range array if column block data wanted */ orderRang (&libordeptr->o, libordeptr->rangtab); if (libordeptr->treetab != NULL) /* Build separator tree array if wanted */ orderTree (&libordeptr->o, libordeptr->treetab); if (libordeptr->cblkptr != NULL) /* Set number of column blocks if wanted */ *(libordeptr->cblkptr) = libordeptr->o.cblknbr; return (0); } /*+ This routine computes an ordering *** of the API ordering structure with *** respect to the given strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphOrder ( SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ SCOTCH_Strat * const stratptr, /*+ Ordering strategy +*/ SCOTCH_Num * const permtab, /*+ Ordering permutation +*/ SCOTCH_Num * const peritab, /*+ Inverse permutation array +*/ SCOTCH_Num * const cblkptr, /*+ Pointer to number of column blocks +*/ SCOTCH_Num * const rangtab, /*+ Column block range array +*/ SCOTCH_Num * const treetab) /*+ Separator tree array +*/ { SCOTCH_Ordering ordedat; int o; if (SCOTCH_graphOrderInit (grafptr, &ordedat, permtab, peritab, cblkptr, rangtab, treetab) != 0) return (1); o = SCOTCH_graphOrderCompute (grafptr, &ordedat, stratptr); SCOTCH_graphOrderExit (grafptr, &ordedat); return (o); } /*+ This routine computes an ordering *** of the subgraph of the API ordering *** structure graph induced by the given *** vertex list, with respect to the given *** strategy. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphOrderList ( SCOTCH_Graph * const grafptr, /*+ Graph to order +*/ const SCOTCH_Num listnbr, /*+ Number of vertices in list +*/ const SCOTCH_Num * const listtab, /*+ List of vertex indices to order +*/ SCOTCH_Strat * const stratptr, /*+ Ordering strategy +*/ SCOTCH_Num * const permtab, /*+ Ordering permutation +*/ SCOTCH_Num * const peritab, /*+ Inverse permutation array +*/ SCOTCH_Num * const cblkptr, /*+ Pointer to number of column blocks +*/ SCOTCH_Num * const rangtab, /*+ Column block range array +*/ SCOTCH_Num * const treetab) /*+ Column block range array +*/ { SCOTCH_Ordering ordedat; int o; SCOTCH_graphOrderInit (grafptr, &ordedat, permtab, peritab, cblkptr, rangtab, treetab); o = SCOTCH_graphOrderComputeList (grafptr, &ordedat, listnbr, listtab, stratptr); SCOTCH_graphOrderExit (grafptr, &ordedat); return (o); } /*+ This routine checks the consistency *** of the given graph ordering. *** It returns: *** - 0 : on success. *** - !0 : on error. +*/ int SCOTCH_graphOrderCheck ( const SCOTCH_Graph * const grafptr, const SCOTCH_Ordering * const ordeptr) /*+ Ordering to check +*/ { return (orderCheck (&((LibOrder *) ordeptr)->o)); } /*+ This routine parses the given *** graph ordering strategy. *** It returns: *** - 0 : if string successfully scanned. *** - !0 : on error. +*/ int SCOTCH_stratGraphOrder ( SCOTCH_Strat * const stratptr, const char * const string) { if (*((Strat **) stratptr) != NULL) stratExit (*((Strat **) stratptr)); if ((*((Strat **) stratptr) = stratInit (&hgraphorderststratab, string)) == NULL) { errorPrint ("SCOTCH_stratGraphOrder: error in ordering strategy"); return (1); } return (0); } /*+ This routine provides predefined *** ordering strategies. *** It returns: *** - 0 : if string successfully initialized. *** - !0 : on error. +*/ int SCOTCH_stratGraphOrderBuild ( SCOTCH_Strat * const stratptr, /*+ Strategy to create +*/ const SCOTCH_Num flagval, /*+ Desired characteristics +*/ const double balrat) /*+ Desired imbalance ratio +*/ { char bufftab[8192]; /* Should be enough */ char bbaltab[32]; strcpy (bufftab, "c{rat=0.7,cpr=n{sep=/(vert>240)?m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=(|h{pass=10})f{bal=}}}|m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=(|h{pass=10})f{bal=}}};,ole=f{cmin=0,cmax=100000,frat=0.0},ose=g},unc=n{sep=/(vert>240)?m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=(|h{pass=10})f{bal=}}}|m{type=h,rat=0.7,vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=},org=(|h{pass=10})f{bal=}}};,ole=f{cmin=15,cmax=100000,frat=0.0},ose=g}}"); sprintf (bbaltab, "%lf", balrat); stringSubst (bufftab, "", bbaltab); if (SCOTCH_stratGraphOrder (stratptr, bufftab) != 0) { errorPrint ("SCOTCH_stratGraphOrderBuild: error in sequential ordering strategy"); return (1); } return (0); } scotch-5.1.12b.dfsg/src/libscotch/library_mesh_io_habo_f.c0000644000175300017530000001207411631334325023750 0ustar hazelscthazelsct/* Copyright 2004,2007,2010 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : library_mesh_io_habo_f.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module is the Fortran API for the **/ /** mesh i/o routines of the libSCOTCH **/ /** library. **/ /** **/ /** DATES : # Version 4.0 : from : 24 nov 2005 **/ /** to 24 nov 2005 **/ /** # Version 5.1 : from : 27 mar 2010 **/ /** to 27 mar 2010 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define LIBRARY #include "module.h" #include "common.h" #include "scotch.h" /**************************************/ /* */ /* These routines are the Fortran API */ /* for the mapping routines. */ /* */ /**************************************/ /* String lengths are passed at the very ** end of the argument list. */ FORTRAN ( \ SCOTCHFMESHGEOMLOADHABO, scotchfmeshgeomloadhabo, ( \ SCOTCH_Mesh * const meshptr, \ SCOTCH_Geom * const geomptr, \ const int * const filegrfptr, \ const int * const filegeoptr, \ const char * const dataptr, /* No use */ \ int * const revaptr, \ const int datanbr), \ (meshptr, geomptr, filegrfptr, filegeoptr, dataptr, revaptr, datanbr)) { FILE * filegrfstream; /* Streams to build from handles */ FILE * filegeostream; int filegrfnum; /* Duplicated handle */ int filegeonum; int o; if ((filegrfnum = dup (*filegrfptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFMESHGEOMLOADHABO: cannot duplicate handle (1)"); *revaptr = 1; /* Indicate error */ return; } if ((filegeonum = dup (*filegeoptr)) < 0) { /* If cannot duplicate file descriptor */ errorPrint ("SCOTCHFMESHGEOMLOADHABO: cannot duplicate handle (2)"); close (filegrfnum); *revaptr = 1; /* Indicate error */ return; } if ((filegrfstream = fdopen (filegrfnum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFMESHGEOMLOADHABO: cannot open input stream (1)"); close (filegrfnum); close (filegeonum); *revaptr = 1; return; } if ((filegeostream = fdopen (filegeonum, "r")) == NULL) { /* Build stream from handle */ errorPrint ("SCOTCHFMESHGEOMLOADHABO: cannot open input stream (2)"); fclose (filegrfstream); close (filegeonum); *revaptr = 1; return; } o = SCOTCH_meshGeomLoadHabo (meshptr, geomptr, filegrfstream, filegeostream, NULL); fclose (filegrfstream); /* This closes file descriptors too */ fclose (filegeostream); *revaptr = o; } scotch-5.1.12b.dfsg/src/libscotch/mesh_induce_sepa.h0000644000175300017530000000573311631334325022607 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : mesh_induce_sepa.h **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : These lines are the data declarations **/ /** for the improved Fiduccia-Mattheyses **/ /** graph separation routine. **/ /** **/ /** DATES : # Version 4.0 : from : 04 feb 2003 **/ /** to 09 feb 2003 **/ /** **/ /************************************************************/ /* ** The defines. */ /*+ Prime number for hashing vertex numbers. +*/ #define MESHINDUCESEPAHASHPRIME 17 /*+ Prime number for hashing +*/ /* ** The type and structure definitions. */ /*+ The hash vertex structure. +*/ typedef struct MeshInduceSepaHash_ { Gnum orgvelmnum; /*+ Number of element in original mesh +*/ Gnum indvnodnum; /*+ Number of neighbor node vertex in induced mesh +*/ } MeshInduceSepaHash; scotch-5.1.12b.dfsg/src/libscotch/hgraph_order_hd.c0000644000175300017530000001567011631334325022427 0ustar hazelscthazelsct/* Copyright 2004,2007 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : hgraph_order_hd.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module orders a separator using **/ /** the block-oriented Halo Approximate **/ /** (Multiple) Minimum Degree algorithm, **/ /** with super-variable accounting (HaloAMD **/ /** v2.0). **/ /** **/ /** DATES : # Version 3.2 : from : 09 aug 1998 **/ /** to 18 aug 1998 **/ /** # Version 3.3 : from : 02 oct 1998 **/ /** to : 05 jan 1999 **/ /** # Version 4.0 : from : 14 jan 2003 **/ /** to : 23 jan 2004 **/ /** # Version 5.0 : from : 10 sep 2007 **/ /** to : 10 sep 2007 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define HGRAPH_ORDER_HD #include "module.h" #include "common.h" #include "graph.h" #include "order.h" #include "hgraph.h" #include "hall_order_hx.h" #include "hall_order_hd.h" #include "hgraph_order_hd.h" #include "hgraph_order_hx.h" #include "hgraph_order_si.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine performs the ordering. ** It returns: ** - 0 : if the ordering could be computed. ** - !0 : on error. */ int hgraphOrderHd ( const Hgraph * restrict const grafptr, Order * restrict const ordeptr, const Gnum ordenum, /*+ Zero-based ordering number +*/ OrderCblk * restrict const cblkptr, /*+ Multiple column-block +*/ const HgraphOrderHdParam * restrict const paraptr) { Gnum * restrict petab; Gnum pfree; Gnum iwlen; Gnum * restrict iwtab; Gnum * restrict lentab; Gnum * restrict nvartab; Gnum * restrict elentab; Gnum * restrict lasttab; Gnum * restrict leaftab; Gnum * restrict secntab; /* Array of index to first secondary variable */ Gnum * restrict nexttab; /* Array of index of next principal variable */ Gnum * restrict frsttab; Gnum ncmpa; Gnum n; /* Number of nodes to order (with halo or not) */ int o; if (grafptr->s.vertnbr < paraptr->colmin) /* If graph is too small, order simply */ return (hgraphOrderSi (grafptr, ordeptr, ordenum, cblkptr)); n = grafptr->s.vertnbr; iwlen = (Gnum) ((double) grafptr->s.edgenbr * HGRAPHORDERHDCOMPRAT) + 32; if (iwlen < n) /* Prepare to re-use array */ iwlen = n; if (memAllocGroup ((void **) (void *) &petab, (size_t) (n * sizeof (Gnum)), &iwtab, (size_t) (iwlen * sizeof (Gnum)), &lentab, (size_t) (n * sizeof (Gnum)), &nvartab, (size_t) (n * sizeof (Gnum)), &elentab, (size_t) (n * sizeof (Gnum)), &lasttab, (size_t) (n * sizeof (Gnum)), &leaftab, (size_t) (n * sizeof (Gnum)), &frsttab, (size_t) (n * sizeof (Gnum)), &secntab, (size_t) (n * sizeof (Gnum)), &nexttab, (size_t) (n * sizeof (Gnum)), NULL) == NULL) { errorPrint ("hgraphOrderHd: out of memory"); return (1); } hgraphOrderHxFill (grafptr, petab, lentab, iwtab, elentab, &pfree); hallOrderHdHalmd (n, 0, iwlen, petab, pfree, /* No elements here */ lentab, iwtab, nvartab, elentab, lasttab, &ncmpa, leaftab, secntab, nexttab, frsttab); if (ncmpa < 0) { errorPrint ("hgraphOrderHd: internal error"); memFree (petab); /* Free group leader */ return (1); } o = hallOrderHxBuild (grafptr->s.baseval, n, grafptr->vnohnbr, grafptr->s.vnumtax, ordeptr, cblkptr, nvartab - grafptr->s.baseval, lentab - grafptr->s.baseval, petab - grafptr->s.baseval, frsttab - grafptr->s.baseval, nexttab - grafptr->s.baseval, secntab - grafptr->s.baseval, iwtab - grafptr->s.baseval, elentab - grafptr->s.baseval, ordeptr->peritab + ordenum, /* Use given inverse permutation as inverse permutation space, never based */ leaftab, paraptr->colmin, paraptr->colmax, (float) paraptr->fillrat); memFree (petab); /* Free group leader */ return (o); } scotch-5.1.12b.dfsg/src/libscotch/dgraph_halo.c0000644000175300017530000004147111631334325021556 0ustar hazelscthazelsct/* Copyright 2007-2009,2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : dgraph_halo.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** Francois CHATENET (P0.0) **/ /** Sebastien FOUCAULT (P0.0) **/ /** Nicolas GICQUEL (P0.1) **/ /** Jerome LACOSTE (P0.1) **/ /** **/ /** FUNCTION : Part of a parallel static mapper. **/ /** This module contains the halo update **/ /** routines. **/ /** **/ /** # Version P0.0 : from : 01 apr 1997 **/ /** to 20 jun 1997 **/ /** # Version P0.1 : from : 14 apr 1998 **/ /** to 20 jun 1998 **/ /** # Version 5.0 : from : 28 feb 2006 **/ /** to 05 feb 2008 **/ /** # Version 5.1 : from : 28 aug 2008 **/ /** to 22 feb 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define DGRAPH_HALO #include "module.h" #include "common.h" #include "dgraph.h" #include "dgraph_halo.h" /* These routines fill the send arrays used by ** all of the halo routines. ** They return: ** - void : in all cases. */ #define DGRAPHHALOFILLNAME dgraphHaloFillGeneric #define DGRAPHHALOFILLSIZE attrglbsiz #define DGRAPHHALOFILLCOPY(d,s,n) memCpy ((d), (s), (n)) #include "dgraph_halo_fill.c" #undef DGRAPHHALOFILLNAME #undef DGRAPHHALOFILLSIZE #undef DGRAPHHALOFILLCOPY #define DGRAPHHALOFILLNAME dgraphHaloFillGnum #define DGRAPHHALOFILLSIZE sizeof (Gnum) #define DGRAPHHALOFILLCOPY(d,s,n) *((Gnum *) (d)) = *((Gnum *) (s)) #include "dgraph_halo_fill.c" #undef DGRAPHHALOFILLNAME #undef DGRAPHHALOFILLSIZE #undef DGRAPHHALOFILLCOPY #define DGRAPHHALOFILLNAME dgraphHaloFillGraphPart #define DGRAPHHALOFILLSIZE sizeof (GraphPart) #define DGRAPHHALOFILLCOPY(d,s,n) *((GraphPart *) (d)) = *((GraphPart *) (s)) #include "dgraph_halo_fill.c" #undef DGRAPHHALOFILLNAME #undef DGRAPHHALOFILLSIZE #undef DGRAPHHALOFILLCOPY #define DGRAPHHALOFILLNAME dgraphHaloFillInt /* In case Gnum is not int */ #define DGRAPHHALOFILLSIZE sizeof (int) #define DGRAPHHALOFILLCOPY(d,s,n) *((int *) (d)) = *((int *) (s)) #include "dgraph_halo_fill.c" #undef DGRAPHHALOFILLNAME #undef DGRAPHHALOFILLSIZE #undef DGRAPHHALOFILLCOPY static void dgraphHaloFill ( const Dgraph * restrict const grafptr, const void * restrict const attrgsttab, /* Attribute array to diffuse */ int attrglbsiz, /* Type extent of attribute */ byte * restrict const attrsndtab, /* Array for packing data to send */ int * const senddsptab, /* Temporary displacement array */ const int * restrict const sendcnttab) /* Count array */ { int procnum; byte ** attrdsptab; attrdsptab = (byte **) senddsptab; /* TRICK: use senddsptab (int *) as attrdsptab (byte **) */ attrdsptab[0] = attrsndtab; /* Pre-set send arrays for send buffer filling routines */ for (procnum = 1; procnum < grafptr->procglbnbr; procnum ++) attrdsptab[procnum] = attrdsptab[procnum - 1] + sendcnttab[procnum - 1] * attrglbsiz; if (attrglbsiz == sizeof (Gnum)) dgraphHaloFillGnum (grafptr, attrgsttab, attrglbsiz, attrdsptab); else if (attrglbsiz == sizeof (GraphPart)) dgraphHaloFillGraphPart (grafptr, attrgsttab, attrglbsiz, attrdsptab); else if (attrglbsiz == sizeof (int)) /* In case Gnum is not int (suitable for float's too) */ dgraphHaloFillInt (grafptr, attrgsttab, attrglbsiz, attrdsptab); else /* Generic but slower fallback routine */ dgraphHaloFillGeneric (grafptr, attrgsttab, attrglbsiz, attrdsptab); senddsptab[0] = 0; /* Pre-set send arrays for data sending routines */ for (procnum = 1; procnum < grafptr->procglbnbr; procnum ++) senddsptab[procnum] = senddsptab[procnum - 1] + sendcnttab[procnum - 1]; } /* This function checks that the data of proc{snd,rcv}tab ** are consistent. */ #ifdef SCOTCH_DEBUG_DGRAPH2 int dgraphHaloCheck ( const Dgraph * restrict const grafptr) { int * proctab; /* Array to collect data */ int procnum; int o; if ((proctab = memAlloc (grafptr->procglbnbr * sizeof (int))) == NULL) { errorPrint ("dgraphHaloCheck: out of memory"); return (1); } if (MPI_Alltoall (grafptr->procsndtab, 1, MPI_INT, proctab, 1, MPI_INT, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphHaloCheck: communication error"); memFree (proctab); /* Free group leader */ return (1); } o = 0; for (procnum = 0; procnum < grafptr->procglbnbr; procnum ++) { if (proctab[procnum] != grafptr->procrcvtab[procnum]) { errorPrint ("dgraphHaloCheck: data error"); o = 1; break; } } memFree (proctab); /* Free group leader */ return (o); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ /* These functions perform a synchronous collective ** halo diffusion operation on the ghost array given ** on input. ** It returns: ** - 0 : if the halo has been successfully propagated. ** - !0 : on error. */ static int dgraphHaloSync2 ( Dgraph * restrict const grafptr, void * restrict const attrgsttab, /* Attribute array to share */ const MPI_Datatype attrglbtype, /* Attribute datatype */ byte ** const attrsndptr, /* Pointer to array for packing data to send */ int ** const senddspptr, /* Pointers to communication displacement arrays */ int ** const recvdspptr, MPI_Request ** const requptr) /* Pointer to local request array for point-to-point */ { MPI_Aint attrglbsiz; /* Extent of attribute datatype */ int procngbsiz; /* Size of request array for point-to-point communications */ int procngbnum; int * restrict recvdsptab; const int * restrict procrcvtab; if (dgraphGhst (grafptr) != 0) { /* Compute ghost edge array if not already present */ errorPrint ("dgraphHaloSync2: cannot compute ghost edge array"); return (1); } procngbsiz = ((grafptr->flagval & DGRAPHCOMMPTOP) != 0) ? grafptr->procngbnbr : 0; MPI_Type_extent (attrglbtype, &attrglbsiz); /* Get type extent */ if (memAllocGroup ((void **) (void *) attrsndptr, (size_t) (grafptr->procsndnbr * attrglbsiz), senddspptr, (size_t) (grafptr->procglbnbr * MAX (sizeof (int), sizeof (byte *))), /* TRICK: use senddsptab (int *) as attrdsptab (byte **) */ recvdspptr, (size_t) (grafptr->procglbnbr * sizeof (int)), requptr, (size_t) (procngbsiz * 2 * sizeof (MPI_Request)), NULL) == NULL) { errorPrint ("dgraphHaloSync2: out of memory"); return (1); } dgraphHaloFill (grafptr, attrgsttab, attrglbsiz, *attrsndptr, *senddspptr, grafptr->procsndtab); /* Fill data arrays */ recvdsptab = *recvdspptr; procrcvtab = grafptr->procrcvtab; recvdsptab[0] = grafptr->vertlocnbr; for (procngbnum = 1; procngbnum < grafptr->procglbnbr; procngbnum ++) recvdsptab[procngbnum] = recvdsptab[procngbnum - 1] + procrcvtab[procngbnum - 1]; #ifdef SCOTCH_DEBUG_DGRAPH2 if (dgraphHaloCheck (grafptr) != 0) { errorPrint ("dgraphHaloSync2: invalid communication data"); return (1); } #endif /* SCOTCH_DEBUG_DGRAPH2 */ return (0); } int dgraphHaloSync ( Dgraph * restrict const grafptr, void * restrict const attrgsttab, /* Attribute array to share */ const MPI_Datatype attrglbtype) /* Attribute datatype */ { byte * attrsndtab; /* Array for packing data to send */ int * senddsptab; int * recvdsptab; MPI_Request * requtab; int o; if (dgraphHaloSync2 (grafptr, attrgsttab, attrglbtype, &attrsndtab, &senddsptab, &recvdsptab, &requtab) != 0) /* Prepare communication arrays */ return (1); o = 0; /* Assume success */ if ((grafptr->flagval & DGRAPHCOMMPTOP) != 0) { /* If point-to-point exchange */ MPI_Aint attrglbsiz; /* Extent of attribute datatype */ const int * restrict procrcvtab; const int * restrict procsndtab; const int * restrict procngbtab; int procngbnbr; int procngbnum; MPI_Comm proccomm; int requnbr; proccomm = grafptr->proccomm; procngbtab = grafptr->procngbtab; procngbnbr = grafptr->procngbnbr; procrcvtab = grafptr->procrcvtab; MPI_Type_extent (attrglbtype, &attrglbsiz); /* Get type extent */ for (procngbnum = procngbnbr - 1, requnbr = 0; procngbnum >= 0; procngbnum --, requnbr ++) { /* Post receives first */ int procglbnum; procglbnum = procngbtab[procngbnum]; if (MPI_Irecv ((byte *) attrgsttab + recvdsptab[procglbnum] * attrglbsiz, procrcvtab[procglbnum], attrglbtype, procglbnum, TAGHALO, proccomm, requtab + requnbr) != MPI_SUCCESS) { errorPrint ("dgraphHaloSync: communication error (1)"); o = 1; break; } } procsndtab = grafptr->procsndtab; for (procngbnum = 0; procngbnum < procngbnbr; procngbnum ++, requnbr ++) { /* Post sends afterwards */ int procglbnum; procglbnum = procngbtab[procngbnum]; if (MPI_Isend (attrsndtab + senddsptab[procglbnum] * attrglbsiz, procsndtab[procglbnum], attrglbtype, procglbnum, TAGHALO, proccomm, requtab + requnbr) != MPI_SUCCESS) { errorPrint ("dgraphHaloSync: communication error (2)"); o = 1; break; } } if (MPI_Waitall (requnbr, requtab, MPI_STATUSES_IGNORE) != MPI_SUCCESS) { errorPrint ("dgraphHaloSync: communication error (3)"); o = 1; } } else { /* Collective communication */ if (MPI_Alltoallv (attrsndtab, grafptr->procsndtab, senddsptab, attrglbtype, /* Perform diffusion */ attrgsttab, grafptr->procrcvtab, recvdsptab, attrglbtype, grafptr->proccomm) != MPI_SUCCESS) { errorPrint ("dgraphHaloSync: communication error (4)"); o = 1; } } memFree (attrsndtab); /* Free group leader */ return (o); } /* This function performs an asynchronous collective ** halo diffusion operation on the ghost array given ** on input. It fills the given request structure with ** the relevant data. ** It returns: ** - 0 : if the halo has been successfully propagated. ** - !0 : on error. */ #ifdef SCOTCH_PTHREAD static void * dgraphHaloAsync2 ( DgraphHaloRequest * restrict requptr) { return ((void *) (intptr_t) dgraphHaloSync (requptr->grafptr, requptr->attrgsttab, requptr->attrglbtype)); } #endif /* SCOTCH_PTHREAD */ void dgraphHaloAsync ( Dgraph * restrict const grafptr, void * restrict const attrgsttab, /* Attribute array to share */ const MPI_Datatype attrglbtype, /* Attribute datatype */ DgraphHaloRequest * restrict requptr) { #ifndef SCOTCH_PTHREAD #ifdef SCOTCH_MPI_ASYNC_COLL int * senddsptab; int * recvdsptab; #endif /* SCOTCH_MPI_ASYNC_COLL */ #endif /* SCOTCH_PTHREAD */ #ifdef SCOTCH_PTHREAD requptr->flagval = -1; /* Assume thread will be successfully launched */ requptr->grafptr = grafptr; requptr->attrgsttab = attrgsttab; requptr->attrglbtype = attrglbtype; if (pthread_create (&requptr->thrdval, NULL, (void * (*) (void *)) dgraphHaloAsync2, (void *) requptr) != 0) /* If could not create thread */ requptr->flagval = (int) (intptr_t) dgraphHaloAsync2 (requptr); /* Call function synchronously */ #else /* SCOTCH_PTHREAD */ #ifdef SCOTCH_MPI_ASYNC_COLL requptr->flagval = 1; /* Assume error */ requptr->attrsndtab = NULL; /* No memory */ if (dgraphHaloSync2 (grafptr, attrgsttab, attrglbtype, &requptr->attrsndtab, &senddsptab, &recvdsptab) != 0) /* Prepare communication arrays */ return; if (MPE_Ialltoallv (requptr->attrsndtab, grafptr->procsndtab, senddsptab, attrglbtype, /* Perform asynchronous collective communication */ attrgsttab, grafptr->procrcvtab, recvdsptab, attrglbtype, grafptr->proccomm, &requptr->requval) != MPI_SUCCESS) { errorPrint ("dgraphHaloAsync: communication error"); /* Group leader will be freed on wait routine */ return; } requptr->flagval = -1; /* Communication successfully launched */ #else /* SCOTCH_MPI_ASYNC_COLL */ requptr->flagval = dgraphHaloSync (grafptr, attrgsttab, attrglbtype); /* Last resort is synchronous communication */ #endif /* SCOTCH_MPI_ASYNC_COLL */ #endif /* SCOTCH_PTHREAD */ } /* This function performs an asynchronous collective ** halo diffusion operation on the ghost array given ** on input. It fills the given request structure with ** the relevant data. ** It returns: ** - 0 : if the halo has been successfully propagated. ** - !0 : on error. */ int dgraphHaloWait ( DgraphHaloRequest * restrict requptr) { #ifdef SCOTCH_PTHREAD void * o; if (requptr->flagval == -1) { /* If thread launched */ pthread_join (requptr->thrdval, &o); /* Wait for its completion */ requptr->flagval = (int) (intptr_t) o; /* Get thread return value */ } /* Else return value already known */ #else /* SCOTCH_PTHREAD */ #ifdef SCOTCH_MPI_ASYNC_COLL MPI_Status statval; if (requptr->flagval == -1) { /* If communication launched */ MPI_Wait (&requptr->requval, &statval); /* Wait for completion of asynchronous collective communication */ requptr->flagval = (statval.MPI_ERROR == MPI_SUCCESS) ? 0 : 1; /* Set return value accordingly */ } if (requptr->attrsndtab != NULL) /* Free group leader if it was successfully allocated before */ memFree (requptr->attrsndtab); #endif /* SCOTCH_MPI_ASYNC_COLL */ #endif /* SCOTCH_PTHREAD */ return (requptr->flagval); /* Return asynchronous or synchronous error code */ } scotch-5.1.12b.dfsg/src/libscotch/kdgraph_map_rb_part.c0000644000175300017530000004732611631334325023301 0ustar hazelscthazelsct/* Copyright 2008-2011 ENSEIRB, INRIA & CNRS ** ** This file is part of the Scotch software package for static mapping, ** graph partitioning and sparse matrix ordering. ** ** This software is governed by the CeCILL-C license under French law ** and abiding by the rules of distribution of free software. You can ** use, modify and/or redistribute the software under the terms of the ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following ** URL: "http://www.cecill.info". ** ** As a counterpart to the access to the source code and rights to copy, ** modify and redistribute granted by the license, users are provided ** only with a limited warranty and the software's author, the holder of ** the economic rights, and the successive licensors have only limited ** liability. ** ** In this respect, the user's attention is drawn to the risks associated ** with loading, using, modifying and/or developing or reproducing the ** software by the user in light of its specific status of free software, ** that may mean that it is complicated to manipulate, and that also ** therefore means that it is reserved for developers and experienced ** professionals having in-depth computer knowledge. Users are therefore ** encouraged to load and test the software's suitability as regards ** their requirements in conditions enabling the security of their ** systems and/or data to be ensured and, more generally, to use and ** operate it in the same conditions as regards security. ** ** The fact that you are presently reading this means that you have had ** knowledge of the CeCILL-C license and that you accept its terms. */ /************************************************************/ /** **/ /** NAME : kdgraph_map_rb_part.c **/ /** **/ /** AUTHOR : Francois PELLEGRINI **/ /** **/ /** FUNCTION : This module performs the Dual Recursive **/ /** Bipartitioning mapping algorithm **/ /** in parallel. It does so for complete **/ /** graph architectures, hence performing **/ /** plain graph partitioning, which **/ /** avoids to take care of what the other **/ /** processes are doing. **/ /** **/ /** DATES : # Version 5.1 : from : 21 jun 2008 **/ /** to 31 aug 2011 **/ /** **/ /************************************************************/ /* ** The defines and includes. */ #define KDGRAPH_MAP_RB #include "module.h" #include "common.h" #include "parser.h" #include "graph.h" #include "arch.h" #include "bgraph.h" #include "bgraph_bipart_st.h" #include "mapping.h" #include "kgraph.h" #include "kgraph_map_st.h" #include "dgraph.h" #include "dmapping.h" #include "bdgraph.h" #include "bdgraph_bipart_st.h" #include "kdgraph.h" #include "kdgraph_map_rb.h" #include "kdgraph_map_rb_part.h" #include "kdgraph_map_st.h" /*****************************/ /* */ /* This is the main routine. */ /* */ /*****************************/ /* This routine sequentially computes a mapping ** of the given subgraph and adds its result to ** the given distributed mapping. Since no ** cocycle data is needed, the un-synchronized ** sequential Scotch routine can be used as is. ** It returns: ** - 0 : if the mapping could be computed. ** - !0 : on error. */ static int kdgraphMapRbPartSequ ( KdgraphMapRbPartGraph * restrict const grafptr, Dmapping * restrict const mappptr, const KdgraphMapRbPartData * restrict const dataptr) { Graph * restrict cgrfptr; Kgraph kgrfdat; /* Centralized mapping graph */ DmappingFrag * restrict fragptr; cgrfptr = &grafptr->data.cgrfdat; if (mapInit2 (&kgrfdat.m, cgrfptr->baseval, cgrfptr->vertnbr, &mappptr->archdat, &grafptr->domnorg) != 0) { errorPrint ("kdgraphMapRbPartSequ: cannot initialize centralized mapping"); return (1); } if (kgraphInit (&kgrfdat, cgrfptr, &kgrfdat.m) != 0) { errorPrint ("kdgraphMapRbPartSequ: cannot initialize centralized graph"); return (1); } kgrfdat.s.flagval = cgrfptr->flagval; /* Free sequential graph along with mapping data */ kgrfdat.s.vnumtax = NULL; /* Remove index array if any */ kgrfdat.comploadrat = dataptr->comploadrat; /* Use ideal load of full graph and not of subgraph */ if (kgraphMapSt (&kgrfdat, dataptr->paraptr->stratseq) != 0) { /* Compute sequential mapping */ kgraphExit (&kgrfdat); return (1); } if (((fragptr = memAlloc (sizeof (DmappingFrag))) == NULL) || ((fragptr->vnumtab = memAlloc (cgrfptr->vertnbr * sizeof (Gnum))) == NULL)) { errorPrint ("kdgraphMapRbPartSequ: out of memory"); if (fragptr != NULL) memFree (fragptr); kgraphExit (&kgrfdat); return (1); } fragptr->vertnbr = cgrfptr->vertnbr; fragptr->parttab = kgrfdat.m.parttax + kgrfdat.m.baseval; fragptr->domnnbr = kgrfdat.m.domnnbr; fragptr->domntab = kgrfdat.m.domntab; kgrfdat.m.parttax = NULL; /* Keep sequential mapping arrays for distributed mapping fragment */ kgrfdat.m.domntab = NULL; if (kgrfdat.m.domnmax > kgrfdat.m.domnnbr) fragptr->domntab = memRealloc (fragptr->domntab, kgrfdat.m.domnnbr * sizeof (ArchDom)); /* Reallocate mapping array */ if (cgrfptr->vnumtax != NULL) memCpy (fragptr->vnumtab, cgrfptr->vnumtax + cgrfptr->baseval, cgrfptr->vertnbr * sizeof (Gnum)); else { Gnum vertadj; Gnum vertnum; for (vertnum = 0, vertadj = cgrfptr->baseval; vertnum < cgrfptr->vertnbr; vertnum ++) fragptr->vnumtab[vertnum] = vertadj + vertnum; } dmapAdd (mappptr, fragptr); /* Add mapping fragment */ kgraphExit (&kgrfdat); /* Free mapping without some of its arrays */ return (0); } /* This routine builds either a centralized or a ** distributed subgraph, according to the number ** of processes in the given part. The calling ** conventions of this routine have been designed ** so as to allow for multi-threading. */ static void * kdgraphMapRbPartFold2 ( void * const dataptr) /* Pointer to thread data */ { KdgraphMapRbPartThread * fldthrdptr; /* Thread input parameters */ KdgraphMapRbPartGraph * restrict fldgrafptr; /* Pointer to folded graph area */ Dgraph indgrafdat; /* Induced distributed graph */ void * o; fldthrdptr = (KdgraphMapRbPartThread *) dataptr; fldgrafptr = fldthrdptr->fldgrafptr; if (fldthrdptr->fldprocnbr == 0) /* If recursion stopped, build mapping of graph part */ return ((void *) (intptr_t) kdgraphMapRbAddPart (fldthrdptr->orggrafptr, fldthrdptr->mappptr, fldthrdptr->inddomnptr, fldthrdptr->indvertnbr, fldthrdptr->indparttax + fldthrdptr->orggrafptr->baseval, fldthrdptr->indpartval)); if (dgraphInducePart (fldthrdptr->orggrafptr, fldthrdptr->indparttax, /* Compute unfinished induced subgraph on all processes */ fldthrdptr->indvertnbr, fldthrdptr->indpartval, &indgrafdat) != 0) return ((void *) 1); if (fldthrdptr->fldprocnbr > 1) { /* If subpart has several processes, fold a distributed graph */ o = (void *) (intptr_t) dgraphFold2 (&indgrafdat, fldthrdptr->fldpartval, /* Fold temporary induced subgraph from all processes */ &fldgrafptr->data.dgrfdat, fldthrdptr->fldproccomm, NULL, NULL, MPI_INT); } else { /* Create a centralized graph */ Graph * restrict fldcgrfptr; fldcgrfptr = (fldthrdptr->fldprocnum == 0) ? &fldgrafptr->data.cgrfdat : NULL; /* See if we are the receiver */ o = (void *) (intptr_t) dgraphGather (&indgrafdat, fldcgrfptr); /* Gather centralized subgraph from all other processes */ } dgraphExit (&indgrafdat); /* Free temporary induced graph */ return (o); } static int kdgraphMapRbPartFold ( Bdgraph * restrict const actgrafptr, Dmapping * restrict const mappptr, const ArchDom * restrict const domsubtab, KdgraphMapRbPartGraph * restrict const fldgrafptr) { KdgraphMapRbPartThread fldthrdtab[2]; int fldprocnbr; /* Number of processes in part of this process */ int fldprocnbr0; /* Number of processes in first part */ int fldprocnum; int fldproccol; int fldpartval; Gnum indvertlocmax; /* Local number of vertices in biggest subgraph */ int indconttab[2]; /* Array of subjob continuation flags */ int indpartmax; /* Induced part having most vertices */ #ifdef SCOTCH_PTHREAD Dgraph orggrafdat; /* Structure for copying graph fields except communicator */ pthread_t thrdval; /* Data of second thread */ #endif /* SCOTCH_PTHREAD */ int o; indconttab[0] = /* Assume both jobs will not continue */ indconttab[1] = 0; if ((actgrafptr->compglbsize0 != 0) && /* If graph has been bipartitioned */ (actgrafptr->compglbsize0 != actgrafptr->s.vertglbnbr)) { if (archVar (&mappptr->archdat)) { /* If architecture is variable-sized */ if (actgrafptr->compglbsize0 > 1) /* If graph is not single vertex, go on */ indconttab[0] = 1; if ((actgrafptr->s.vertglbnbr - actgrafptr->compglbsize0) > 1) indconttab[1] = 1; } else { /* Architecture is not variable-sized */ if (archDomSize (&mappptr->archdat, &domsubtab[0]) > 1) /* Stop when target is one vertex */ indconttab[0] = 1; if (archDomSize (&mappptr->archdat, &domsubtab[1]) > 1) indconttab[1] = 1; } } if ((indconttab[0] + indconttab[1]) == 0) { /* If both subjobs stop */ fldgrafptr->procnbr = 0; /* Nothing to do on return */ return (kdgraphMapRbAddBoth (&actgrafptr->s, mappptr, domsubtab, actgrafptr->partgsttax + actgrafptr->s.baseval)); /* Map both subdomains in the same time */ } if ((2 * actgrafptr->compglbsize0) >= actgrafptr->s.vertglbnbr) { /* Get part of largest subgraph */ indpartmax = 0; indvertlocmax = actgrafptr->complocsize0; } else { indpartmax = 1; indvertlocmax = actgrafptr->s.vertlocnbr - actgrafptr->complocsize0; } fldprocnbr0 = (actgrafptr->s.procglbnbr + 1) / 2; /* Get number of processes in part 0 (always more than in part 1) */ fldthrdtab[0].mappptr = mappptr; /* Load data to pass to the subgraph building routines */ fldthrdtab[0].orggrafptr = &actgrafptr->s; fldthrdtab[0].inddomnptr = &domsubtab[indpartmax]; fldthrdtab[0].indvertnbr = indvertlocmax; fldthrdtab[0].indpartval = indpartmax; fldthrdtab[0].indparttax = actgrafptr->partgsttax; fldthrdtab[0].fldgrafptr = fldgrafptr; fldthrdtab[0].fldpartval = 0; fldthrdtab[0].fldprocnbr = indconttab[indpartmax] * fldprocnbr0; /* Stop if domain limited to one vertex */ fldthrdtab[1].mappptr = mappptr; fldthrdtab[1].orggrafptr = &actgrafptr->s; /* Assume jobs won't be run concurrently */ fldthrdtab[1].inddomnptr = &domsubtab[indpartmax ^ 1]; fldthrdtab[1].indvertnbr = actgrafptr->s.vertlocnbr - indvertlocmax; fldthrdtab[1].indpartval = indpartmax ^ 1; fldthrdtab[1].indparttax = actgrafptr->partgsttax; fldthrdtab[1].fldgrafptr = fldgrafptr; fldthrdtab[1].fldpartval = 1; fldthrdtab[1].fldprocnbr = indconttab[indpartmax ^ 1] * (actgrafptr->s.procglbnbr - fldprocnbr0); /* Stop if domain limited to one vertex */ if (actgrafptr->s.proclocnum < fldprocnbr0) { /* Compute color and rank in our future subpart */ fldpartval = 0; fldprocnum = actgrafptr->s.proclocnum; fldprocnbr = fldprocnbr0; } else { fldpartval = 1; fldprocnum = actgrafptr->s.proclocnum - fldprocnbr0; fldprocnbr = actgrafptr->s.procglbnbr - fldprocnbr0; } fldgrafptr->domnorg = *fldthrdtab[fldpartval].inddomnptr; /* Set data of our folded graph */ fldgrafptr->procnbr = fldthrdtab[fldpartval].fldprocnbr; fldgrafptr->levlnum = actgrafptr->levlnum + 1; /* One level down in the DRB process */ fldproccol = fldpartval; /* Split color is the part value */ if (fldgrafptr->procnbr <= 1) /* If our part will have only one processor or will stop */ fldproccol = MPI_UNDEFINED; /* Do not create any sub-communicator for it */ if (MPI_Comm_split (actgrafptr->s.proccomm, fldproccol, fldprocnum, &fldthrdtab[fldpartval].fldproccomm) != MPI_SUCCESS) { /* Assign folded communicator to proper part */ errorPrint ("kdgraphMapRbPartFold: communication error"); return (1); } fldthrdtab[fldpartval].fldprocnum = fldprocnum; /* This will be our rank afterwards */ fldthrdtab[fldpartval ^ 1].fldprocnum = -1; /* Other part will not be in communicator */ fldthrdtab[fldpartval ^ 1].fldproccomm = MPI_COMM_NULL; #ifdef SCOTCH_PTHREAD if ((indconttab[0] + indconttab[1]) == 2) { /* If both subjobs have meaningful things to do in parallel */ orggrafdat = actgrafptr->s; /* Create a separate graph structure to change its communicator */ orggrafdat.flagval = (orggrafdat.flagval & ~DGRAPHFREEALL) | DGRAPHFREECOMM; fldthrdtab[1].orggrafptr = &orggrafdat; MPI_Comm_dup (actgrafptr->s.proccomm, &orggrafdat.proccomm); /* Duplicate communicator to avoid interferences in communications */ if (pthread_create (&thrdval, NULL, kdgraphMapRbPartFold2, (void *) &fldthrdtab[1]) != 0) /* If could not create thread */ o = ((int) (intptr_t) kdgraphMapRbPartFold2 ((void *) &fldthrdtab[0])) || /* Perform inductions in sequence */ ((int) (intptr_t) kdgraphMapRbPartFold2 ((void *) &fldthrdtab[1])); else { /* Newly created thread is processing subgraph 1, so let's process subgraph 0 */ void * o2; o = (int) (intptr_t) kdgraphMapRbPartFold2 ((void *) &fldthrdtab[0]); /* Work on copy with private communicator */ pthread_join (thrdval, &o2); o |= (int) (intptr_t) o2; } MPI_Comm_free (&orggrafdat.proccomm); } else #endif /* SCOTCH_PTHREAD */ o = ((int) (intptr_t) kdgraphMapRbPartFold2 ((void *) &fldthrdtab[0])) || /* Perform inductions in sequence */ ((int) (intptr_t) kdgraphMapRbPartFold2 ((void *) &fldthrdtab[1])); return (o); } /* This routine performs the Dual Recursive ** Bipartitioning mapping in parallel. ** It returns: ** - 0 : if the mapping could be computed. ** - !0 : on error. */ static int kdgraphMapRbPart2 ( KdgraphMapRbPartGraph * restrict const grafptr, const KdgraphMapRbPartData * restrict const dataptr) { ArchDom domsubtab[2]; /* Temporary subdomains */ Bdgraph actgrafdat; /* Active bipartitioning graph */ KdgraphMapRbPartGraph indgrafdat; /* Induced folded graph area */ Gnum comploadavg; Dmapping * mappptr; int o; mappptr = dataptr->mappptr; o = ((archVar (&mappptr->archdat)) && /* If architecture is variable-sized */ (grafptr->data.dgrfdat.vertglbnbr <= 1)) /* And source subgraph is of minimal size */ ? 1 /* Then do not bipartition target more */ : archDomBipart (&mappptr->archdat, &grafptr->domnorg, &domsubtab[0], &domsubtab[1]); switch (o) { case 1 : /* If target domain is terminal */ return (kdgraphMapRbAddOne (&grafptr->data.dgrfdat, mappptr, &grafptr->domnorg)); /* Update mapping and return */ case 2 : /* On error */ errorPrint ("kdgraphMapRbPart2: cannot bipartition domain"); return (1); } if (dgraphGhst (&grafptr->data.dgrfdat) != 0) { /* Compute ghost edge array if not already present, to have vertgstnbr (and procsidtab) */ errorPrint ("kdgraphMapRbPart2: cannot compute ghost edge array"); return (1); } o = bdgraphInit (&actgrafdat, &grafptr->data.dgrfdat, NULL, &mappptr->archdat, domsubtab); /* Create active graph */ actgrafdat.levlnum = grafptr->levlnum; /* Initial level of bipartition graph is DRB recursion level */ comploadavg = (double) actgrafdat.s.veloglbsum / (double) archDomWght (&mappptr->archdat, &grafptr->domnorg); actgrafdat.compglbload0min = actgrafdat.compglbload0avg - (Gnum) MIN ((dataptr->comploadmax - comploadavg) * actgrafdat.domwght[0], (comploadavg - dataptr->comploadmin) * actgrafdat.domwght[1]); actgrafdat.compglbload0max = actgrafdat.compglbload0avg + (Gnum) MIN ((comploadavg - dataptr->comploadmin) * actgrafdat.domwght[0], (dataptr->comploadmax - comploadavg) * actgrafdat.domwght[1]); if ((o != 0) || (bdgraphBipartSt (&actgrafdat, dataptr->paraptr->stratsep) != 0)) { /* Bipartition edge-separation graph */ bdgraphExit (&actgrafdat); return (1); } o = kdgraphMapRbPartFold (&actgrafdat, mappptr, domsubtab, &indgrafdat); bdgraphExit (&actgrafdat); /* Free additional bipartitioning data */ dgraphExit (&grafptr->data.dgrfdat); /* Free graph before going to next level */ if (o == 0) { if (indgrafdat.procnbr == 1) /* If sequential job */ o = kdgraphMapRbPartSequ (&indgrafdat, mappptr, dataptr); else if (indgrafdat.procnbr > 1) /* If distributed job */ o = kdgraphMapRbPart2 (&indgrafdat, dataptr); } return (o); } int kdgraphMapRbPart ( Kdgraph * restrict const grafptr, Kdmapping * restrict const mappptr, const KdgraphMapRbParam * restrict const paraptr) { KdgraphMapRbPartGraph grafdat; KdgraphMapRbPartData datadat; grafdat.domnorg = grafptr->m.domnorg; /* Used in all cases */ grafdat.procnbr = grafptr->s.procglbnbr; grafdat.levlnum = 0; /* Set initial DRB level to zero */ datadat.mappptr = mappptr->mappptr; datadat.paraptr = paraptr; datadat.comploadrat = (double) grafptr->s.veloglbsum / (double) archDomWght (&mappptr->mappptr->archdat, &grafptr->m.domnorg); datadat.comploadmin = (1.0 - paraptr->kbalval) * datadat.comploadrat; datadat.comploadmax = (1.0 + paraptr->kbalval) * datadat.comploadrat; if (grafptr->s.procglbnbr <= 1) { /* If single process, switch immediately to sequential mode */ if (dgraphGather (&grafptr->s, &grafdat.data.cgrfdat) != 0) { errorPrint ("kdgraphMapRbPart: cannot centralize graph"); return (1); } return (kdgraphMapRbPartSequ (&grafdat, mappptr->mappptr, &datadat)); } grafdat.data.dgrfdat = grafptr->s; /* Create a clone graph that will never be freed */ grafdat.data.dgrfdat.flagval &= ~DGRAPHFREEALL; return (kdgraphMapRbPart2 (&grafdat, &datadat)); /* Perform DRB */ } scotch-5.1.12b.dfsg/src/Make.inc/0000755000175300017530000000000011511433245016604 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/src/Make.inc/mingw32/0000755000175300017530000000000011145123247020073 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/src/Make.inc/mingw32/gendll_0.sh0000755000175300017530000000157011145122447022122 0ustar hazelscthazelsct#! /bin/sh # (C) 2008 Yves Secretan (yves.secretan@ete.inrs.ca) # This software is governed by the CeCILL-C license under French law # and abiding by the rules of distribution of free software. You can # use, modify and/or redistribute the software under the terms of the # CeCILL-C license as circulated by CEA, CNRS and INRIA at the following # URL: "http://www.cecill.info". # # To be executed in a MSYS window. # # This file will link the PT-Scotch DLL. It must be adapted to reflect # your environment, in particular library path and library name. export OBJS="../../libscotch/lib*.o" export LDFLAGS="--shared -Wl,--allow-multiple-definition" export PGMFILES="/l" export LDPATH="-L../../../lib -L$PGMFILES/MPICH2/lib -L$PGMFILES/pthread-win32/lib" export LDLIBS="-lptscotch -lptscotcherr -lmpi -lpthreadGC2" gcc --output ../../../lib/libptscotch.dll $LDFLAGS $LDPATH $OBJS $LDLIBS scotch-5.1.12b.dfsg/src/Make.inc/mingw32/gendll_1.sh0000755000175300017530000000133511145122447022122 0ustar hazelscthazelsct#! /bin/sh # (C) 2008 Yves Secretan (yves.secretan@ete.inrs.ca) # This software is governed by the CeCILL-C license under French law # and abiding by the rules of distribution of free software. You can # use, modify and/or redistribute the software under the terms of the # CeCILL-C license as circulated by CEA, CNRS and INRIA at the following # URL: "http://www.cecill.info". # # To be executed in a MSYS window. # # This file creates the Exports definition file from the PT-Scotch DLL. # It must be adapted to reflect your environment, in particular library # path and library name. echo EXPORTS > ../../../lib/libptscotch.def nm ../../../lib/libptscotch.a | grep ' T _SCOTCH_' | sed 's/.* T _//' >> ../../../lib/libptscotch.def scotch-5.1.12b.dfsg/src/Make.inc/mingw32/README.txt0000644000175300017530000000116311145122447021573 0ustar hazelscthazelsctThese three script files can be used to create a Windows DLL from the PT-Scotch library on a MinGW32 system. They are intended to be called directly from the src/Make.inc/mingw32 directory and produce results in the lib directory. The first two ones must be called from a Unix-like shell window. The last one must be called from a MSDOS-like command window. These scripts are intended only as examples. They must be adapted to reflect your environment, in particular library path and library name. They have been provided by Yves Secretan (yves.secretan@ete.inrs.ca) and are licensed under the CeCILL-C libre/free license. scotch-5.1.12b.dfsg/src/Make.inc/mingw32/gendll_2.bat0000755000175300017530000000137711145122447022265 0ustar hazelscthazelsctREM (C) 2008 Yves Secretan (yves.secretan@ete.inrs.ca) REM This software is governed by the CeCILL-C license under French law REM and abiding by the rules of distribution of free software. You can REM use, modify and/or redistribute the software under the terms of the REM CeCILL-C license as circulated by CEA, CNRS and INRIA at the following REM URL: "http://www.cecill.info". REM REM To be executed in a DOS window. REM REM This file will create the PT-Scotch DLL. It must be adapted to reflect REM your environment, in particular library path and library name. REM set VC_PATH="C:\Program Files\Microsoft Visual Studio .NET\VC7\BIN" %VC_PATH%\vcvars32.bat && %VC_PATH%\lib.exe /def:..\..\..\lib\libptscotch.def /out:..\..\..\lib\libptscotch.dll scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.x86-64_cray-xt4_linux20000644000175300017530000000063311432232765024733 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = gmake AR = ar ARFLAGS = -ruv CAT = cat CCS = cc CCP = cc CCD = cc CFLAGS = -O3 -c99 -fast -fastsse -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME -Pscotchyy -olex.yy.c -DIDXSIZE64 CLIBFLAGS = LDFLAGS = -lm -lrt CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.power3_ibm_aix50000644000175300017530000000071211527231460024011 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = gmake AR = ar ARFLAGS = -X64 -ruv CAT = cat CCS = xlc_r CCP = mpcc_r CCD = xlc_r -I/usr/lpp/ppe.poe/include CFLAGS = -ma -q64 -qarch=auto -O3 -qstrict -qtune=pwr3 -qlanglvl=extc99 -s -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME -D_ALL_SOURCE CLIBFLAGS = LDFLAGS = -bmaxdata:0x80000000 -lpthread -lm CP = cp LEX = lex LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = yacc scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.i686_pc_linux2.nothreads0000644000175300017530000000062211432232765025466 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = make AR = ar ARFLAGS = -ruv CAT = cat CCS = gcc CCP = mpicc CCD = gcc CFLAGS = -O3 -Drestrict=__restrict -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER CLIBFLAGS = LDFLAGS = -lz -lm -lrt CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.i686_mac_darwin80000644000175300017530000000064711432232765024000 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = make AR = ar ARFLAGS = -ruv CAT = cat CCS = gcc CCP = mpicc CCD = mpicc CFLAGS = -O3 -Drestrict=__restrict -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DCOMMON_TIMING_OLD -DSCOTCH_PTHREAD -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER CLIBFLAGS = LDFLAGS = -lm CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.i686_pc_linux20000644000175300017530000000066411432232765023506 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = make AR = ar ARFLAGS = -ruv CAT = cat CCS = gcc CCP = mpicc CCD = gcc CFLAGS = -O3 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER -DSCOTCH_PTHREAD -Drestrict=__restrict CLIBFLAGS = LDFLAGS = -lz -lm -lrt CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.power6_ibm_aix50000644000175300017530000000066511527231461024024 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = gmake AR = ar ARFLAGS = -X64 -ruv CAT = cat CCS = xlc_r CCP = mpcc_r CCD = xlc_r -I/usr/lpp/ppe.poe/include CFLAGS = -ma -q64 -qarch=auto -O3 -qstrict -qtune=pwr6 -qlanglvl=extc99 -s -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME -D_ALL_SOURCE CLIBFLAGS = LDFLAGS = -lpthread -lm CP = cp LEX = lex LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = yacc scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.i686_pc_freebsd0000644000175300017530000000065411511433245023670 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = gmake AR = ar ARFLAGS = -ruv CAT = cat CCS = cc CCP = mpicc CCD = mpicc CFLAGS += -std=c99 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER CLIBFLAGS = LDFLAGS += -lz -lm -lpthread CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.x86-64_pc_freebsd0000600000175300017530000000071411511433245024035 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = gmake AR = ar ARFLAGS = -ruv CAT = cat CCS = cc CCP = mpicc CCD = cc CFLAGS += -std -fPIC -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER -DSCOTCH_PTHREAD -Drestrict=__restrict -DIDXSIZE64 CLIBFLAGS = LDFLAGS += -lz -lm -lthread CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.ppc450_ibm_bgp0000644000175300017530000000077711527231461023523 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = gmake AR = ar ARFLAGS = -ruv CAT = cat CCS = /bgsys/drivers/ppcfloor/comm/bin/mpixlc_r CCP = /bgsys/drivers/ppcfloor/comm/bin/mpixlc_r CCD = xlc_r -I/bgsys/drivers/ppcfloor/comm/include CFLAGS = -O3 -qstrict -qlanglvl=extc99 -qarch=450d -qtune=450 -s -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_DETERMINISTIC -D_ALL_SOURCE CLIBFLAGS = LDFLAGS = -lpthread -lm CP = cp LEX = lex LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = yacc scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.i686_pc_linux2.c990000644000175300017530000000067311466237125024113 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = make AR = ar ARFLAGS = -ruv CAT = cat CCS = gcc CCP = mpicc CCD = gcc CFLAGS = -std=c99 -O3 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER -DSCOTCH_PTHREAD CLIBFLAGS = LDFLAGS = -lz -lm -lrt CP = cp LEX = flex -Pscotchyy -D_XOPEN_SOURCE=600 -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.i686_mac_darwin10.icc0000644000175300017530000000066711432232765024610 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = make AR = ar ARFLAGS = -ruv CAT = cat CCS = icc CCP = mpicc CCD = icc CFLAGS = -O3 -restrict -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DCOMMON_TIMING_OLD -DCOMMON_FILE_COMPRESS_GZ -DSCOTCH_PTHREAD -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER CLIBFLAGS = LDFLAGS = -lz -lm CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.i686_pc_linux2.debug0000644000175300017530000000072311432232765024567 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = make AR = ar ARFLAGS = -ruv CAT = cat CCS = gcc CCP = mpicc CCD = gcc CFLAGS = -g -O0 -Drestrict=__restrict -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DSCOTCH_DEBUG_ALL -DSCOTCH_DETERMINISTIC -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER CLIBFLAGS = LDFLAGS = -g -lz -lm -lrt CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.mips_sgi_irix60000644000175300017530000000052111432232765023752 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = gmake AR = ar ARFLAGS = ruv CAT = cat CCS = xlc CCP = mpicc CCD = mpicc CFLAGS = -n32 -xansi -fullwarn -O2 -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME CLIBFLAGS = LDFLAGS = -lm CP = cp LEX = lex LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = yacc scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.x86-64_pc_linux20000644000175300017530000000070011432232765023655 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = make AR = ar ARFLAGS = -ruv CAT = cat CCS = gcc CCP = mpicc CCD = gcc CFLAGS = -O3 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER -DSCOTCH_PTHREAD -Drestrict=__restrict -DIDXSIZE64 CLIBFLAGS = LDFLAGS = -lz -lm -lrt CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.alpha_dec_osf10000644000175300017530000000053111432232765023650 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = gmake AR = ar ARFLAGS = ruv CAT = cat CCS = cc CCP = mpicc CCD = mpicc CFLAGS = -v -O3 -omp -ansi_alias -ansi_args -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME CLIBFLAGS = LDFLAGS = -lm CP = cp LEX = lex LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = yacc scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.i686_pc_linux2.shlib.debug0000644000175300017530000000074711432232765025675 0ustar hazelscthazelsctEXE = LIB = .so OBJ = .o MAKE = make AR = gcc ARFLAGS = -shared -o CAT = cat CCS = gcc CCP = mpicc CCD = gcc CFLAGS = -g -O0 -Drestrict=__restrict -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DSCOTCH_DEBUG_ALL -DSCOTCH_DETERMINISTIC -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER CLIBFLAGS = -shared -fPIC LDFLAGS = -g -lz -lm -lrt CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = echo YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.x86-64_pc_linux2.icc0000644000175300017530000000066711432232765024426 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = make AR = ar ARFLAGS = -ruv CAT = cat CCS = icc CCP = mpicc CCD = icc CFLAGS = -O3 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER -DSCOTCH_PTHREAD -restrict -DIDXSIZE64 CLIBFLAGS = LDFLAGS = -g -lz -lm -lrt CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.i686_pc_linux2.shlib0000644000175300017530000000071011432232765024576 0ustar hazelscthazelsctEXE = LIB = .so OBJ = .o MAKE = make AR = gcc ARFLAGS = -shared -o CAT = cat CCS = gcc CCP = mpicc CCD = gcc CFLAGS = -O3 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER -DSCOTCH_PTHREAD -Drestrict=__restrict CLIBFLAGS = -shared -fPIC LDFLAGS = -lz -lm -lrt CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = echo YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.i686_pc_mingw320000644000175300017530000000375711432232765023561 0ustar hazelscthazelsct# This make include file is intended for building under MinGW32. As is, # it relies on : # - pthread-win32 (http://sourceware.org/pthreads-win32/), # - zlib (http://www.zlib.net/) # - mpich2 (http://www.mcs.anl.gov/research/projects/mpich2/). # It must be adapted to reflect your environment, in particular # installation root directories, include path and library name. # Since all files are linked with the MPI libraries, this file is # for compiling PT-Scotch only. To compile Scotch, remove the # -DSCOTCH_PTSCOTCH flag, as well as all references to MPI in the # CFLAGS and CLIBFLAGS = LDFLAGS variables. EXE = LIB = .a OBJ = .o MAKE = make AR = ar ARFLAGS = -ruv CAT = cat CCS = gcc CCP = gcc CCD = gcc #--- Compiler/loader flags CFLAGS_CPL = -O0 -g3 CFLAGS_INC = CFLAGS_DEF = -DCOMMON_RANDOM_FIXED_SEED -DCOMMON_RANDOM_RAND -DCOMMON_STUB_FORK -DSCOTCH_PTSCOTCH -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER -D'pipe(pfds)=_pipe(pfds,1024,0x8000)' CLIBFLAGS = LDFLAGS = PGMFILES=$(PROGRAMFILES) #--- MPI MPI_ROOTDIR = $(PGMFILES)/MPICH2 CFLAGS_INC += -I$(MPI_ROOTDIR)/include #--- Comment/Uncomment for threaded MPI CLIBFLAGS = LDFLAGS += -L$(MPI_ROOTDIR)/lib -lm -lmpi #CLIBFLAGS = LDFLAGS += -L$(MPI_ROOTDIR)/lib -lm -lmpich2mt #--- Pthread : Uncomment for pthread support #PTHREAD_ROOTDIR = $(PGMFILES)/pthread-win32 #CFLAGS_INC += -I$(PTHREAD_ROOTDIR)/include #CLIBFLAGS = LDFLAGS += -L$(PTHREAD_ROOTDIR)/lib -lpthreadGC2 #--- zlib: Uncomment for compressed files #ZLIB_ROOTDIR = $(PGMFILES)/zlib-1.2.3 #CFLAGS_INC += -I$(ZLIB_ROOTDIR)/include #CLIBFLAGS = LDFLAGS += -L$(ZLIB_ROOTDIR)/lib -lzdll #--- COMMON_PTHREAD: Uncomment for compressed files #CFLAGS_DEF += -DCOMMON_PTHREAD -DCOMMON_FILE_COMPRESS_GZ #--- SCOTCH_PTHREAD: Uncomment for threaded MPI #CFLAGS_DEF += -DSCOTCH_PTHREAD CFLAGS = $(CFLAGS_CPL) $(CFLAGS_INC) $(CFLAGS_DEF) CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = cp MKDIR = mkdir MV = mv RANLIB = ranlib YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.i686_pc_linux2.prof0000644000175300017530000000067011432232765024450 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = make AR = ar ARFLAGS = -ruv CAT = cat CCS = gcc CCP = mpicc CCD = gcc CFLAGS = -pg -O3 -Drestrict=__restrict -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER CLIBFLAGS = LDFLAGS = -lz -lm -lrt CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.pa11_hp_ux100000644000175300017530000000054411432232765023132 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = gmake AR = ar ARFLAGS = ruv CAT = cat CCS = cc CCP = mpicc CCD = mpicc CFLAGS = -Aa -z +DA1.1 +w1 +O4 +Onoinitcheck +Onolimit -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME CLIBFLAGS = LDFLAGS = -lm CP = cp LEX = lex LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = yacc scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.i686_sun_solaris50000644000175300017530000000061511432232765024225 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = make AR = ar ARFLAGS = -ruv CAT = cat CCS = cc CCP = mpicc CCD = mpicc CFLAGS = -m64 -O3 -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_PTHREAD -DSCOTCH_RENAME -Du_int32_t=uint32_t -Du_int64_t=uint64_t CLIBFLAGS = LDFLAGS = -lz -lm -lrt CP = cp LEX = flex LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = yacc scotch-5.1.12b.dfsg/src/Make.inc/Makefile.inc.x86-64_pc_linux2.icc.debug0000644000175300017530000000101511432232765025477 0ustar hazelscthazelsctEXE = LIB = .a OBJ = .o MAKE = make AR = ar ARFLAGS = -ruv CAT = cat CCS = icc CCP = mpicc CCD = icc CFLAGS = -g -O0 -fp-model strict -traceback -check-uninit -fp-stack-check -DCOMMON_FILE_COMPRESS_GZ -DCOMMON_PTHREAD -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_DEBUG_ALL -DSCOTCH_DETERMINISTIC -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER -restrict -DIDXSIZE64 CLIBFLAGS = LDFLAGS = -g -lz -lm -lrt CP = cp LEX = flex -Pscotchyy -olex.yy.c LN = ln MKDIR = mkdir MV = mv RANLIB = ranlib YACC = bison -pscotchyy -y -b y scotch-5.1.12b.dfsg/LISEZ-MOI.txt0000644000175300017530000000056011145123754016446 0ustar hazelscthazelsctLes clauses selon lesquelles cette copie de la distribution logicielle Scotch 5.1 est mise votre disposition sont dfinies dans le fichier "LICENCE_fr.txt", situ dans le mme rpertoire que le prsent fichier. Si vous les acceptez, veuillez vous rfrer au fichier "INSTALL.txt", galement situ dans ce rpertoire, pour consulter les instructions d'installation. scotch-5.1.12b.dfsg/LICENCE_fr.txt0000644000175300017530000000061611145123753016670 0ustar hazelscthazelsctCette copie de la distribution logicielle Scotch 5.1 est distribue selon les termes de la licence de logiciel libre CeCILL-C. Une copie du texte de cette licence se trouve dans le sous-rpertoire "doc", dans le fichier appel "CeCILL-C_V1-fr.txt". Veuillez en lire attentivement les clauses. Vous ne pourrez utiliser cette copie de la distribution logicielle Scotch 5.1 que si vous les acceptez. scotch-5.1.12b.dfsg/doc/0000755000175300017530000000000011674404730015144 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/doc/CeCILL-C_V1-fr.txt0000644000175300017530000005314610667023470020043 0ustar hazelscthazelsct CONTRAT DE LICENCE DE LOGICIEL LIBRE CeCILL-C Avertissement Ce contrat est une licence de logiciel libre issue d'une concertation entre ses auteurs afin que le respect de deux grands principes prside sa rdaction: * d'une part, le respect des principes de diffusion des logiciels libres: accs au code source, droits tendus confrs aux utilisateurs, * d'autre part, la dsignation d'un droit applicable, le droit franais, auquel elle est conforme, tant au regard du droit de la responsabilit civile que du droit de la proprit intellectuelle et de la protection qu'il offre aux auteurs et titulaires des droits patrimoniaux sur un logiciel. Les auteurs de la licence CeCILL-C (pour Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre]) sont: Commissariat l'Energie Atomique - CEA, tablissement public de recherche caractre scientifique, technique et industriel, dont le sige est situ 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris. Centre National de la Recherche Scientifique - CNRS, tablissement public caractre scientifique et technologique, dont le sige est situ 3 rue Michel-Ange, 75794 Paris cedex 16. Institut National de Recherche en Informatique et en Automatique - INRIA, tablissement public caractre scientifique et technologique, dont le sige est situ Domaine de Voluceau, Rocquencourt, BP 105, 78153 Le Chesnay cedex. Prambule Ce contrat est une licence de logiciel libre dont l'objectif est de confrer aux utilisateurs la libert de modifier et de rutiliser le logiciel rgi par cette licence. L'exercice de cette libert est assorti d'une obligation de remettre la disposition de la communaut les modifications apportes au code source du logiciel afin de contribuer son volution. L'accessibilit au code source et les droits de copie, de modification et de redistribution qui dcoulent de ce contrat ont pour contrepartie de n'offrir aux utilisateurs qu'une garantie limite et de ne faire peser sur l'auteur du logiciel, le titulaire des droits patrimoniaux et les concdants successifs qu'une responsabilit restreinte. A cet gard l'attention de l'utilisateur est attire sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du logiciel par l'utilisateur tant donn sa spcificit de logiciel libre, qui peut le rendre complexe manipuler et qui le rserve donc des dveloppeurs ou des professionnels avertis possdant des connaissances informatiques approfondies. Les utilisateurs sont donc invits charger et tester l'adquation du logiciel leurs besoins dans des conditions permettant d'assurer la scurit de leurs systmes et/ou de leurs donnes et, plus gnralement, l'utiliser et l'exploiter dans les mmes conditions de scurit. Ce contrat peut tre reproduit et diffus librement, sous rserve de le conserver en l'tat, sans ajout ni suppression de clauses. Ce contrat est susceptible de s'appliquer tout logiciel dont le titulaire des droits patrimoniaux dcide de soumettre l'exploitation aux dispositions qu'il contient. Article 1 - DEFINITIONS Dans ce contrat, les termes suivants, lorsqu'ils seront crits avec une lettre capitale, auront la signification suivante: Contrat: dsigne le prsent contrat de licence, ses ventuelles versions postrieures et annexes. Logiciel: dsigne le logiciel sous sa forme de Code Objet et/ou de Code Source et le cas chant sa documentation, dans leur tat au moment de l'acceptation du Contrat par le Licenci. Logiciel Initial: dsigne le Logiciel sous sa forme de Code Source et ventuellement de Code Objet et le cas chant sa documentation, dans leur tat au moment de leur premire diffusion sous les termes du Contrat. Logiciel Modifi: dsigne le Logiciel modifi par au moins une Contribution Intgre. Code Source: dsigne l'ensemble des instructions et des lignes de programme du Logiciel et auquel l'accs est ncessaire en vue de modifier le Logiciel. Code Objet: dsigne les fichiers binaires issus de la compilation du Code Source. Titulaire: dsigne le ou les dtenteurs des droits patrimoniaux d'auteur sur le Logiciel Initial. Licenci: dsigne le ou les utilisateurs du Logiciel ayant accept le Contrat. Contributeur: dsigne le Licenci auteur d'au moins une Contribution Intgre. Concdant: dsigne le Titulaire ou toute personne physique ou morale distribuant le Logiciel sous le Contrat. Contribution Intgre: dsigne l'ensemble des modifications, corrections, traductions, adaptations et/ou nouvelles fonctionnalits intgres dans le Code Source par tout Contributeur. Module Li: dsigne un ensemble de fichiers sources y compris leur documentation qui, sans modification du Code Source, permet de raliser des fonctionnalits ou services supplmentaires ceux fournis par le Logiciel. Logiciel Driv: dsigne toute combinaison du Logiciel, modifi ou non, et d'un Module Li. Parties: dsigne collectivement le Licenci et le Concdant. Ces termes s'entendent au singulier comme au pluriel. Article 2 - OBJET Le Contrat a pour objet la concession par le Concdant au Licenci d'une licence non exclusive, cessible et mondiale du Logiciel telle que dfinie ci-aprs l'article 5 pour toute la dure de protection des droits portant sur ce Logiciel. Article 3 - ACCEPTATION 3.1 L'acceptation par le Licenci des termes du Contrat est rpute acquise du fait du premier des faits suivants: * (i) le chargement du Logiciel par tout moyen notamment par tlchargement partir d'un serveur distant ou par chargement partir d'un support physique; * (ii) le premier exercice par le Licenci de l'un quelconque des droits concds par le Contrat. 3.2 Un exemplaire du Contrat, contenant notamment un avertissement relatif aux spcificits du Logiciel, la restriction de garantie et la limitation un usage par des utilisateurs expriments a t mis disposition du Licenci pralablement son acceptation telle que dfinie l'article 3.1 ci dessus et le Licenci reconnat en avoir pris connaissance. Article 4 - ENTREE EN VIGUEUR ET DUREE 4.1 ENTREE EN VIGUEUR Le Contrat entre en vigueur la date de son acceptation par le Licenci telle que dfinie en 3.1. 4.2 DUREE Le Contrat produira ses effets pendant toute la dure lgale de protection des droits patrimoniaux portant sur le Logiciel. Article 5 - ETENDUE DES DROITS CONCEDES Le Concdant concde au Licenci, qui accepte, les droits suivants sur le Logiciel pour toutes destinations et pour la dure du Contrat dans les conditions ci-aprs dtailles. Par ailleurs, si le Concdant dtient ou venait dtenir un ou plusieurs brevets d'invention protgeant tout ou partie des fonctionnalits du Logiciel ou de ses composants, il s'engage ne pas opposer les ventuels droits confrs par ces brevets aux Licencis successifs qui utiliseraient, exploiteraient ou modifieraient le Logiciel. En cas de cession de ces brevets, le Concdant s'engage faire reprendre les obligations du prsent alina aux cessionnaires. 5.1 DROIT D'UTILISATION Le Licenci est autoris utiliser le Logiciel, sans restriction quant aux domaines d'application, tant ci-aprs prcis que cela comporte: 1. la reproduction permanente ou provisoire du Logiciel en tout ou partie par tout moyen et sous toute forme. 2. le chargement, l'affichage, l'excution, ou le stockage du Logiciel sur tout support. 3. la possibilit d'en observer, d'en tudier, ou d'en tester le fonctionnement afin de dterminer les ides et principes qui sont la base de n'importe quel lment de ce Logiciel; et ceci, lorsque le Licenci effectue toute opration de chargement, d'affichage, d'excution, de transmission ou de stockage du Logiciel qu'il est en droit d'effectuer en vertu du Contrat. 5.2 DROIT DE MODIFICATION Le droit de modification comporte le droit de traduire, d'adapter, d'arranger ou d'apporter toute autre modification au Logiciel et le droit de reproduire le logiciel en rsultant. Il comprend en particulier le droit de crer un Logiciel Driv. Le Licenci est autoris apporter toute modification au Logiciel sous rserve de mentionner, de faon explicite, son nom en tant qu'auteur de cette modification et la date de cration de celle-ci. 5.3 DROIT DE DISTRIBUTION Le droit de distribution comporte notamment le droit de diffuser, de transmettre et de communiquer le Logiciel au public sur tout support et par tout moyen ainsi que le droit de mettre sur le march titre onreux ou gratuit, un ou des exemplaires du Logiciel par tout procd. Le Licenci est autoris distribuer des copies du Logiciel, modifi ou non, des tiers dans les conditions ci-aprs dtailles. 5.3.1 DISTRIBUTION DU LOGICIEL SANS MODIFICATION Le Licenci est autoris distribuer des copies conformes du Logiciel, sous forme de Code Source ou de Code Objet, condition que cette distribution respecte les dispositions du Contrat dans leur totalit et soit accompagne: 1. d'un exemplaire du Contrat, 2. d'un avertissement relatif la restriction de garantie et de responsabilit du Concdant telle que prvue aux articles 8 et 9, et que, dans le cas o seul le Code Objet du Logiciel est redistribu, le Licenci permette un accs effectif au Code Source complet du Logiciel pendant au moins toute la dure de sa distribution du Logiciel, tant entendu que le cot additionnel d'acquisition du Code Source ne devra pas excder le simple cot de transfert des donnes. 5.3.2 DISTRIBUTION DU LOGICIEL MODIFIE Lorsque le Licenci apporte une Contribution Intgre au Logiciel, les conditions de distribution du Logiciel Modifi en rsultant sont alors soumises l'intgralit des dispositions du Contrat. Le Licenci est autoris distribuer le Logiciel Modifi sous forme de code source ou de code objet, condition que cette distribution respecte les dispositions du Contrat dans leur totalit et soit accompagne: 1. d'un exemplaire du Contrat, 2. d'un avertissement relatif la restriction de garantie et de responsabilit du Concdant telle que prvue aux articles 8 et 9, et que, dans le cas o seul le code objet du Logiciel Modifi est redistribu, le Licenci permette un accs effectif son code source complet pendant au moins toute la dure de sa distribution du Logiciel Modifi, tant entendu que le cot additionnel d'acquisition du code source ne devra pas excder le simple cot de transfert des donnes. 5.3.3 DISTRIBUTION DU LOGICIEL DERIVE Lorsque le Licenci cre un Logiciel Driv, ce Logiciel Driv peut tre distribu sous un contrat de licence autre que le prsent Contrat condition de respecter les obligations de mention des droits sur le Logiciel telles que dfinies l'article 6.4. Dans le cas o la cration du Logiciel Driv a ncessit une modification du Code Source le licenci s'engage ce que: 1. le Logiciel Modifi correspondant cette modification soit rgi par le prsent Contrat, 2. les Contributions Intgres dont le Logiciel Modifi rsulte soient clairement identifies et documentes, 3. le Licenci permette un accs effectif au code source du Logiciel Modifi, pendant au moins toute la dure de la distribution du Logiciel Driv, de telle sorte que ces modifications puissent tre reprises dans une version ultrieure du Logiciel, tant entendu que le cot additionnel d'acquisition du code source du Logiciel Modifi ne devra pas excder le simple cot du transfert des donnes. 5.3.4 COMPATIBILITE AVEC LA LICENCE CeCILL Lorsqu'un Logiciel Modifi contient une Contribution Intgre soumise au contrat de licence CeCILL, ou lorsqu'un Logiciel Driv contient un Module Li soumis au contrat de licence CeCILL, les stipulations prvues au troisime item de l'article 6.4 sont facultatives. Article 6 - PROPRIETE INTELLECTUELLE 6.1 SUR LE LOGICIEL INITIAL Le Titulaire est dtenteur des droits patrimoniaux sur le Logiciel Initial. Toute utilisation du Logiciel Initial est soumise au respect des conditions dans lesquelles le Titulaire a choisi de diffuser son oeuvre et nul autre n'a la facult de modifier les conditions de diffusion de ce Logiciel Initial. Le Titulaire s'engage ce que le Logiciel Initial reste au moins rgi par le Contrat et ce, pour la dure vise l'article 4.2. 6.2 SUR LES CONTRIBUTIONS INTEGREES Le Licenci qui a dvelopp une Contribution Intgre est titulaire sur celle-ci des droits de proprit intellectuelle dans les conditions dfinies par la lgislation applicable. 6.3 SUR LES MODULES LIES Le Licenci qui a dvelopp un Module Li est titulaire sur celui-ci des droits de proprit intellectuelle dans les conditions dfinies par la lgislation applicable et reste libre du choix du contrat rgissant sa diffusion dans les conditions dfinies l'article 5.3.3. 6.4 MENTIONS DES DROITS Le Licenci s'engage expressment: 1. ne pas supprimer ou modifier de quelque manire que ce soit les mentions de proprit intellectuelle apposes sur le Logiciel; 2. reproduire l'identique lesdites mentions de proprit intellectuelle sur les copies du Logiciel modifi ou non; 3. faire en sorte que l'utilisation du Logiciel, ses mentions de proprit intellectuelle et le fait qu'il est rgi par le Contrat soient indiqus dans un texte facilement accessible notamment depuis l'interface de tout Logiciel Driv. Le Licenci s'engage ne pas porter atteinte, directement ou indirectement, aux droits de proprit intellectuelle du Titulaire et/ou des Contributeurs sur le Logiciel et prendre, le cas chant, l'gard de son personnel toutes les mesures ncessaires pour assurer le respect des dits droits de proprit intellectuelle du Titulaire et/ou des Contributeurs. Article 7 - SERVICES ASSOCIES 7.1 Le Contrat n'oblige en aucun cas le Concdant la ralisation de prestations d'assistance technique ou de maintenance du Logiciel. Cependant le Concdant reste libre de proposer ce type de services. Les termes et conditions d'une telle assistance technique et/ou d'une telle maintenance seront alors dtermins dans un acte spar. Ces actes de maintenance et/ou assistance technique n'engageront que la seule responsabilit du Concdant qui les propose. 7.2 De mme, tout Concdant est libre de proposer, sous sa seule responsabilit, ses licencis une garantie, qui n'engagera que lui, lors de la redistribution du Logiciel et/ou du Logiciel Modifi et ce, dans les conditions qu'il souhaite. Cette garantie et les modalits financires de son application feront l'objet d'un acte spar entre le Concdant et le Licenci. Article 8 - RESPONSABILITE 8.1 Sous rserve des dispositions de l'article 8.2, le Licenci a la facult, sous rserve de prouver la faute du Concdant concern, de solliciter la rparation du prjudice direct qu'il subirait du fait du Logiciel et dont il apportera la preuve. 8.2 La responsabilit du Concdant est limite aux engagements pris en application du Contrat et ne saurait tre engage en raison notamment: (i) des dommages dus l'inexcution, totale ou partielle, de ses obligations par le Licenci, (ii) des dommages directs ou indirects dcoulant de l'utilisation ou des performances du Logiciel subis par le Licenci et (iii) plus gnralement d'un quelconque dommage indirect. En particulier, les Parties conviennent expressment que tout prjudice financier ou commercial (par exemple perte de donnes, perte de bnfices, perte d'exploitation, perte de clientle ou de commandes, manque gagner, trouble commercial quelconque) ou toute action dirige contre le Licenci par un tiers, constitue un dommage indirect et n'ouvre pas droit rparation par le Concdant. Article 9 - GARANTIE 9.1 Le Licenci reconnat que l'tat actuel des connaissances scientifiques et techniques au moment de la mise en circulation du Logiciel ne permet pas d'en tester et d'en vrifier toutes les utilisations ni de dtecter l'existence d'ventuels dfauts. L'attention du Licenci a t attire sur ce point sur les risques associs au chargement, l'utilisation, la modification et/ou au dveloppement et la reproduction du Logiciel qui sont rservs des utilisateurs avertis. Il relve de la responsabilit du Licenci de contrler, par tous moyens, l'adquation du produit ses besoins, son bon fonctionnement et de s'assurer qu'il ne causera pas de dommages aux personnes et aux biens. 9.2 Le Concdant dclare de bonne foi tre en droit de concder l'ensemble des droits attachs au Logiciel (comprenant notamment les droits viss l'article 5). 9.3 Le Licenci reconnat que le Logiciel est fourni "en l'tat" par le Concdant sans autre garantie, expresse ou tacite, que celle prvue l'article 9.2 et notamment sans aucune garantie sur sa valeur commerciale, son caractre scuris, innovant ou pertinent. En particulier, le Concdant ne garantit pas que le Logiciel est exempt d'erreur, qu'il fonctionnera sans interruption, qu'il sera compatible avec l'quipement du Licenci et sa configuration logicielle ni qu'il remplira les besoins du Licenci. 9.4 Le Concdant ne garantit pas, de manire expresse ou tacite, que le Logiciel ne porte pas atteinte un quelconque droit de proprit intellectuelle d'un tiers portant sur un brevet, un logiciel ou sur tout autre droit de proprit. Ainsi, le Concdant exclut toute garantie au profit du Licenci contre les actions en contrefaon qui pourraient tre diligentes au titre de l'utilisation, de la modification, et de la redistribution du Logiciel. Nanmoins, si de telles actions sont exerces contre le Licenci, le Concdant lui apportera son aide technique et juridique pour sa dfense. Cette aide technique et juridique est dtermine au cas par cas entre le Concdant concern et le Licenci dans le cadre d'un protocole d'accord. Le Concdant dgage toute responsabilit quant l'utilisation de la dnomination du Logiciel par le Licenci. Aucune garantie n'est apporte quant l'existence de droits antrieurs sur le nom du Logiciel et sur l'existence d'une marque. Article 10 - RESILIATION 10.1 En cas de manquement par le Licenci aux obligations mises sa charge par le Contrat, le Concdant pourra rsilier de plein droit le Contrat trente (30) jours aprs notification adresse au Licenci et reste sans effet. 10.2 Le Licenci dont le Contrat est rsili n'est plus autoris utiliser, modifier ou distribuer le Logiciel. Cependant, toutes les licences qu'il aura concdes antrieurement la rsiliation du Contrat resteront valides sous rserve qu'elles aient t effectues en conformit avec le Contrat. Article 11 - DISPOSITIONS DIVERSES 11.1 CAUSE EXTERIEURE Aucune des Parties ne sera responsable d'un retard ou d'une dfaillance d'excution du Contrat qui serait d un cas de force majeure, un cas fortuit ou une cause extrieure, telle que, notamment, le mauvais fonctionnement ou les interruptions du rseau lectrique ou de tlcommunication, la paralysie du rseau lie une attaque informatique, l'intervention des autorits gouvernementales, les catastrophes naturelles, les dgts des eaux, les tremblements de terre, le feu, les explosions, les grves et les conflits sociaux, l'tat de guerre... 11.2 Le fait, par l'une ou l'autre des Parties, d'omettre en une ou plusieurs occasions de se prvaloir d'une ou plusieurs dispositions du Contrat, ne pourra en aucun cas impliquer renonciation par la Partie intresse s'en prvaloir ultrieurement. 11.3 Le Contrat annule et remplace toute convention antrieure, crite ou orale, entre les Parties sur le mme objet et constitue l'accord entier entre les Parties sur cet objet. Aucune addition ou modification aux termes du Contrat n'aura d'effet l'gard des Parties moins d'tre faite par crit et signe par leurs reprsentants dment habilits. 11.4 Dans l'hypothse o une ou plusieurs des dispositions du Contrat s'avrerait contraire une loi ou un texte applicable, existants ou futurs, cette loi ou ce texte prvaudrait, et les Parties feraient les amendements ncessaires pour se conformer cette loi ou ce texte. Toutes les autres dispositions resteront en vigueur. De mme, la nullit, pour quelque raison que ce soit, d'une des dispositions du Contrat ne saurait entraner la nullit de l'ensemble du Contrat. 11.5 LANGUE Le Contrat est rdig en langue franaise et en langue anglaise, ces deux versions faisant galement foi. Article 12 - NOUVELLES VERSIONS DU CONTRAT 12.1 Toute personne est autorise copier et distribuer des copies de ce Contrat. 12.2 Afin d'en prserver la cohrence, le texte du Contrat est protg et ne peut tre modifi que par les auteurs de la licence, lesquels se rservent le droit de publier priodiquement des mises jour ou de nouvelles versions du Contrat, qui possderont chacune un numro distinct. Ces versions ultrieures seront susceptibles de prendre en compte de nouvelles problmatiques rencontres par les logiciels libres. 12.3 Tout Logiciel diffus sous une version donne du Contrat ne pourra faire l'objet d'une diffusion ultrieure que sous la mme version du Contrat ou une version postrieure. Article 13 - LOI APPLICABLE ET COMPETENCE TERRITORIALE 13.1 Le Contrat est rgi par la loi franaise. Les Parties conviennent de tenter de rgler l'amiable les diffrends ou litiges qui viendraient se produire par suite ou l'occasion du Contrat. 13.2 A dfaut d'accord amiable dans un dlai de deux (2) mois compter de leur survenance et sauf situation relevant d'une procdure d'urgence, les diffrends ou litiges seront ports par la Partie la plus diligente devant les Tribunaux comptents de Paris. Version 1.0 du 2006-09-05. scotch-5.1.12b.dfsg/doc/CeCILL-C_V1-en.txt0000644000175300017530000005254710667023470020042 0ustar hazelscthazelsct CeCILL-C FREE SOFTWARE LICENSE AGREEMENT Notice This Agreement is a Free Software license agreement that is the result of discussions between its authors in order to ensure compliance with the two main principles guiding its drafting: * firstly, compliance with the principles governing the distribution of Free Software: access to source code, broad rights granted to users, * secondly, the election of a governing law, French law, with which it is conformant, both as regards the law of torts and intellectual property law, and the protection that it offers to both authors and holders of the economic rights over software. The authors of the CeCILL-C (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre]) license are: Commissariat l'Energie Atomique - CEA, a public scientific, technical and industrial research establishment, having its principal place of business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France. Centre National de la Recherche Scientifique - CNRS, a public scientific and technological establishment, having its principal place of business at 3 rue Michel-Ange, 75794 Paris cedex 16, France. Institut National de Recherche en Informatique et en Automatique - INRIA, a public scientific and technological establishment, having its principal place of business at Domaine de Voluceau, Rocquencourt, BP 105, 78153 Le Chesnay cedex, France. Preamble The purpose of this Free Software license agreement is to grant users the right to modify and re-use the software governed by this license. The exercising of this right is conditional upon the obligation to make available to the community the modifications made to the source code of the software so as to contribute to its evolution. In consideration of access to the source code and the rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors only have limited liability. In this respect, the risks associated with loading, using, modifying and/or developing or reproducing the software by the user are brought to the user's attention, given its Free Software status, which may make it complicated to use, with the result that its use is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the suitability of the software as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions of security. This Agreement may be freely reproduced and published, provided it is not altered, and that no provisions are either added or removed herefrom. This Agreement may apply to any or all software for which the holder of the economic rights decides to submit the use thereof to its provisions. Article 1 - DEFINITIONS For the purpose of this Agreement, when the following expressions commence with a capital letter, they shall have the following meaning: Agreement: means this license agreement, and its possible subsequent versions and annexes. Software: means the software in its Object Code and/or Source Code form and, where applicable, its documentation, "as is" when the Licensee accepts the Agreement. Initial Software: means the Software in its Source Code and possibly its Object Code form and, where applicable, its documentation, "as is" when it is first distributed under the terms and conditions of the Agreement. Modified Software: means the Software modified by at least one Integrated Contribution. Source Code: means all the Software's instructions and program lines to which access is required so as to modify the Software. Object Code: means the binary files originating from the compilation of the Source Code. Holder: means the holder(s) of the economic rights over the Initial Software. Licensee: means the Software user(s) having accepted the Agreement. Contributor: means a Licensee having made at least one Integrated Contribution. Licensor: means the Holder, or any other individual or legal entity, who distributes the Software under the Agreement. Integrated Contribution: means any or all modifications, corrections, translations, adaptations and/or new functions integrated into the Source Code by any or all Contributors. Related Module: means a set of sources files including their documentation that, without modification to the Source Code, enables supplementary functions or services in addition to those offered by the Software. Derivative Software: means any combination of the Software, modified or not, and of a Related Module. Parties: mean both the Licensee and the Licensor. These expressions may be used both in singular and plural form. Article 2 - PURPOSE The purpose of the Agreement is the grant by the Licensor to the Licensee of a non-exclusive, transferable and worldwide license for the Software as set forth in Article 5 hereinafter for the whole term of the protection granted by the rights over said Software. Article 3 - ACCEPTANCE 3.1 The Licensee shall be deemed as having accepted the terms and conditions of this Agreement upon the occurrence of the first of the following events: * (i) loading the Software by any or all means, notably, by downloading from a remote server, or by loading from a physical medium; * (ii) the first time the Licensee exercises any of the rights granted hereunder. 3.2 One copy of the Agreement, containing a notice relating to the characteristics of the Software, to the limited warranty, and to the fact that its use is restricted to experienced users has been provided to the Licensee prior to its acceptance as set forth in Article 3.1 hereinabove, and the Licensee hereby acknowledges that it has read and understood it. Article 4 - EFFECTIVE DATE AND TERM 4.1 EFFECTIVE DATE The Agreement shall become effective on the date when it is accepted by the Licensee as set forth in Article 3.1. 4.2 TERM The Agreement shall remain in force for the entire legal term of protection of the economic rights over the Software. Article 5 - SCOPE OF RIGHTS GRANTED The Licensor hereby grants to the Licensee, who accepts, the following rights over the Software for any or all use, and for the term of the Agreement, on the basis of the terms and conditions set forth hereinafter. Besides, if the Licensor owns or comes to own one or more patents protecting all or part of the functions of the Software or of its components, the Licensor undertakes not to enforce the rights granted by these patents against successive Licensees using, exploiting or modifying the Software. If these patents are transferred, the Licensor undertakes to have the transferees subscribe to the obligations set forth in this paragraph. 5.1 RIGHT OF USE The Licensee is authorized to use the Software, without any limitation as to its fields of application, with it being hereinafter specified that this comprises: 1. permanent or temporary reproduction of all or part of the Software by any or all means and in any or all form. 2. loading, displaying, running, or storing the Software on any or all medium. 3. entitlement to observe, study or test its operation so as to determine the ideas and principles behind any or all constituent elements of said Software. This shall apply when the Licensee carries out any or all loading, displaying, running, transmission or storage operation as regards the Software, that it is entitled to carry out hereunder. 5.2 RIGHT OF MODIFICATION The right of modification includes the right to translate, adapt, arrange, or make any or all modifications to the Software, and the right to reproduce the resulting software. It includes, in particular, the right to create a Derivative Software. The Licensee is authorized to make any or all modification to the Software provided that it includes an explicit notice that it is the author of said modification and indicates the date of the creation thereof. 5.3 RIGHT OF DISTRIBUTION In particular, the right of distribution includes the right to publish, transmit and communicate the Software to the general public on any or all medium, and by any or all means, and the right to market, either in consideration of a fee, or free of charge, one or more copies of the Software by any means. The Licensee is further authorized to distribute copies of the modified or unmodified Software to third parties according to the terms and conditions set forth hereinafter. 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION The Licensee is authorized to distribute true copies of the Software in Source Code or Object Code form, provided that said distribution complies with all the provisions of the Agreement and is accompanied by: 1. a copy of the Agreement, 2. a notice relating to the limitation of both the Licensor's warranty and liability as set forth in Articles 8 and 9, and that, in the event that only the Object Code of the Software is redistributed, the Licensee allows effective access to the full Source Code of the Software at a minimum during the entire period of its distribution of the Software, it being understood that the additional cost of acquiring the Source Code shall not exceed the cost of transferring the data. 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE When the Licensee makes an Integrated Contribution to the Software, the terms and conditions for the distribution of the resulting Modified Software become subject to all the provisions of this Agreement. The Licensee is authorized to distribute the Modified Software, in source code or object code form, provided that said distribution complies with all the provisions of the Agreement and is accompanied by: 1. a copy of the Agreement, 2. a notice relating to the limitation of both the Licensor's warranty and liability as set forth in Articles 8 and 9, and that, in the event that only the object code of the Modified Software is redistributed, the Licensee allows effective access to the full source code of the Modified Software at a minimum during the entire period of its distribution of the Modified Software, it being understood that the additional cost of acquiring the source code shall not exceed the cost of transferring the data. 5.3.3 DISTRIBUTION OF DERIVATIVE SOFTWARE When the Licensee creates Derivative Software, this Derivative Software may be distributed under a license agreement other than this Agreement, subject to compliance with the requirement to include a notice concerning the rights over the Software as defined in Article 6.4. In the event the creation of the Derivative Software required modification of the Source Code, the Licensee undertakes that: 1. the resulting Modified Software will be governed by this Agreement, 2. the Integrated Contributions in the resulting Modified Software will be clearly identified and documented, 3. the Licensee will allow effective access to the source code of the Modified Software, at a minimum during the entire period of distribution of the Derivative Software, such that such modifications may be carried over in a subsequent version of the Software; it being understood that the additional cost of purchasing the source code of the Modified Software shall not exceed the cost of transferring the data. 5.3.4 COMPATIBILITY WITH THE CeCILL LICENSE When a Modified Software contains an Integrated Contribution subject to the CeCILL license agreement, or when a Derivative Software contains a Related Module subject to the CeCILL license agreement, the provisions set forth in the third item of Article 6.4 are optional. Article 6 - INTELLECTUAL PROPERTY 6.1 OVER THE INITIAL SOFTWARE The Holder owns the economic rights over the Initial Software. Any or all use of the Initial Software is subject to compliance with the terms and conditions under which the Holder has elected to distribute its work and no one shall be entitled to modify the terms and conditions for the distribution of said Initial Software. The Holder undertakes that the Initial Software will remain ruled at least by this Agreement, for the duration set forth in Article 4.2. 6.2 OVER THE INTEGRATED CONTRIBUTIONS The Licensee who develops an Integrated Contribution is the owner of the intellectual property rights over this Contribution as defined by applicable law. 6.3 OVER THE RELATED MODULES The Licensee who develops a Related Module is the owner of the intellectual property rights over this Related Module as defined by applicable law and is free to choose the type of agreement that shall govern its distribution under the conditions defined in Article 5.3.3. 6.4 NOTICE OF RIGHTS The Licensee expressly undertakes: 1. not to remove, or modify, in any manner, the intellectual property notices attached to the Software; 2. to reproduce said notices, in an identical manner, in the copies of the Software modified or not; 3. to ensure that use of the Software, its intellectual property notices and the fact that it is governed by the Agreement is indicated in a text that is easily accessible, specifically from the interface of any Derivative Software. The Licensee undertakes not to directly or indirectly infringe the intellectual property rights of the Holder and/or Contributors on the Software and to take, where applicable, vis--vis its staff, any and all measures required to ensure respect of said intellectual property rights of the Holder and/or Contributors. Article 7 - RELATED SERVICES 7.1 Under no circumstances shall the Agreement oblige the Licensor to provide technical assistance or maintenance services for the Software. However, the Licensor is entitled to offer this type of services. The terms and conditions of such technical assistance, and/or such maintenance, shall be set forth in a separate instrument. Only the Licensor offering said maintenance and/or technical assistance services shall incur liability therefor. 7.2 Similarly, any Licensor is entitled to offer to its licensees, under its sole responsibility, a warranty, that shall only be binding upon itself, for the redistribution of the Software and/or the Modified Software, under terms and conditions that it is free to decide. Said warranty, and the financial terms and conditions of its application, shall be subject of a separate instrument executed between the Licensor and the Licensee. Article 8 - LIABILITY 8.1 Subject to the provisions of Article 8.2, the Licensee shall be entitled to claim compensation for any direct loss it may have suffered from the Software as a result of a fault on the part of the relevant Licensor, subject to providing evidence thereof. 8.2 The Licensor's liability is limited to the commitments made under this Agreement and shall not be incurred as a result of in particular: (i) loss due the Licensee's total or partial failure to fulfill its obligations, (ii) direct or consequential loss that is suffered by the Licensee due to the use or performance of the Software, and (iii) more generally, any consequential loss. In particular the Parties expressly agree that any or all pecuniary or business loss (i.e. loss of data, loss of profits, operating loss, loss of customers or orders, opportunity cost, any disturbance to business activities) or any or all legal proceedings instituted against the Licensee by a third party, shall constitute consequential loss and shall not provide entitlement to any or all compensation from the Licensor. Article 9 - WARRANTY 9.1 The Licensee acknowledges that the scientific and technical state-of-the-art when the Software was distributed did not enable all possible uses to be tested and verified, nor for the presence of possible defects to be detected. In this respect, the Licensee's attention has been drawn to the risks associated with loading, using, modifying and/or developing and reproducing the Software which are reserved for experienced users. The Licensee shall be responsible for verifying, by any or all means, the suitability of the product for its requirements, its good working order, and for ensuring that it shall not cause damage to either persons or properties. 9.2 The Licensor hereby represents, in good faith, that it is entitled to grant all the rights over the Software (including in particular the rights set forth in Article 5). 9.3 The Licensee acknowledges that the Software is supplied "as is" by the Licensor without any other express or tacit warranty, other than that provided for in Article 9.2 and, in particular, without any warranty as to its commercial value, its secured, safe, innovative or relevant nature. Specifically, the Licensor does not warrant that the Software is free from any error, that it will operate without interruption, that it will be compatible with the Licensee's own equipment and software configuration, nor that it will meet the Licensee's requirements. 9.4 The Licensor does not either expressly or tacitly warrant that the Software does not infringe any third party intellectual property right relating to a patent, software or any other property right. Therefore, the Licensor disclaims any and all liability towards the Licensee arising out of any or all proceedings for infringement that may be instituted in respect of the use, modification and redistribution of the Software. Nevertheless, should such proceedings be instituted against the Licensee, the Licensor shall provide it with technical and legal assistance for its defense. Such technical and legal assistance shall be decided on a case-by-case basis between the relevant Licensor and the Licensee pursuant to a memorandum of understanding. The Licensor disclaims any and all liability as regards the Licensee's use of the name of the Software. No warranty is given as regards the existence of prior rights over the name of the Software or as regards the existence of a trademark. Article 10 - TERMINATION 10.1 In the event of a breach by the Licensee of its obligations hereunder, the Licensor may automatically terminate this Agreement thirty (30) days after notice has been sent to the Licensee and has remained ineffective. 10.2 A Licensee whose Agreement is terminated shall no longer be authorized to use, modify or distribute the Software. However, any licenses that it may have granted prior to termination of the Agreement shall remain valid subject to their having been granted in compliance with the terms and conditions hereof. Article 11 - MISCELLANEOUS 11.1 EXCUSABLE EVENTS Neither Party shall be liable for any or all delay, or failure to perform the Agreement, that may be attributable to an event of force majeure, an act of God or an outside cause, such as defective functioning or interruptions of the electricity or telecommunications networks, network paralysis following a virus attack, intervention by government authorities, natural disasters, water damage, earthquakes, fire, explosions, strikes and labor unrest, war, etc. 11.2 Any failure by either Party, on one or more occasions, to invoke one or more of the provisions hereof, shall under no circumstances be interpreted as being a waiver by the interested Party of its right to invoke said provision(s) subsequently. 11.3 The Agreement cancels and replaces any or all previous agreements, whether written or oral, between the Parties and having the same purpose, and constitutes the entirety of the agreement between said Parties concerning said purpose. No supplement or modification to the terms and conditions hereof shall be effective as between the Parties unless it is made in writing and signed by their duly authorized representatives. 11.4 In the event that one or more of the provisions hereof were to conflict with a current or future applicable act or legislative text, said act or legislative text shall prevail, and the Parties shall make the necessary amendments so as to comply with said act or legislative text. All other provisions shall remain effective. Similarly, invalidity of a provision of the Agreement, for any reason whatsoever, shall not cause the Agreement as a whole to be invalid. 11.5 LANGUAGE The Agreement is drafted in both French and English and both versions are deemed authentic. Article 12 - NEW VERSIONS OF THE AGREEMENT 12.1 Any person is authorized to duplicate and distribute copies of this Agreement. 12.2 So as to ensure coherence, the wording of this Agreement is protected and may only be modified by the authors of the License, who reserve the right to periodically publish updates or new versions of the Agreement, each with a separate number. These subsequent versions may address new issues encountered by Free Software. 12.3 Any Software distributed under a given version of the Agreement may only be subsequently distributed under the same version of the Agreement or a subsequent version. Article 13 - GOVERNING LAW AND JURISDICTION 13.1 The Agreement is governed by French law. The Parties agree to endeavor to seek an amicable solution to any disagreements or disputes that may arise during the performance of the Agreement. 13.2 Failing an amicable solution within two (2) months as from their occurrence, and unless emergency proceedings are necessary, the disagreements or disputes shall be referred to the Paris Courts having jurisdiction, by the more diligent Party. Version 1.0 dated 2006-09-05. scotch-5.1.12b.dfsg/man/0000755000175300017530000000000011145123343015141 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/man/man1/0000755000175300017530000000000011426102762016001 5ustar hazelscthazelsctscotch-5.1.12b.dfsg/man/man1/dgpart.10000644000175300017530000000002111627545546017353 0ustar hazelscthazelsct.so man1/dgmap.1 scotch-5.1.12b.dfsg/man/man1/gmap.10000644000175300017530000001462411627545546017034 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH gmap 1 "September 01, 2011" "" "Scotch user's manual" .SH NAME \fBgmap, gpart \fP- compute static mappings and partitions sequentially \fB .SH SYNOPSIS .nf .fam C \fBgmap\fP [\fIoptions\fP] [\fIgfile\fP] [\fItfile\fP] [\fImfile\fP] [\fIlfile\fP] .PP \fBgpart\fP [\fIoptions\fP] [\fInparts/\fIpwght\fP\fP] [\fIgfile\fP] [\fImfile\fP] [\fIlfile\fP] .fam T .fi .SH DESCRIPTION The \fBgmap\fP program computes, in a sequential way, a static mapping of a source graph onto a target graph. .PP The \fBgpart\fP program is a simplified interface to \fBgmap\fP, which performs graph partitioning instead of static mapping. Consequently, the desired number of parts has to be provided, in lieu of the target architecture. When using the program for graph clustering, the number of parts turns into maximum cluster weight. .PP The \fB-b\fP and \fB-c\fP options allow the user to set preferences on the behavior of the mapping strategy which is used by default. The \fB-m\fP option allows the user to define a custom mapping strategy. .PP The \fB-q\fP option turns the programs into graph clustering programs. In this case, \fBgmap\fP only accepts variable-sized target architectures. .PP Source graph file \fIgfile\fP can only be a centralized graph file. For \fBgmap\fP, the target architecture file \fItfile\fP describes either algorithmically-coded topologies such as meshes and hypercubes, or decomposition-defined architectures created by means of the \fBamk_grf\fP(1) program. The resulting mapping is stored in file \fImfile\fP. Eventual logging information (such as the one produced by option \fB-v\fP) is sent to file \fIlfile\fP. When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitely represented by a dash '-'. .PP When the proper libraries have been included at compile time, \fBgmap\fP and \fBgpart\fP can directly handle compressed graphs, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .SH OPTIONS .TP .B \fB-b\fP\fIval\fP Set maximum load imbalance ratio for graph partitioning or static mapping. When programs are used as clustering tools, this parameter sets the maximum load imbalance ratio for recursive bipartitions. Exclusive with the \fB-m\fP option. .TP .B \fB-c\fP\fIopt\fP Choose default mapping strategy according to one or several options among: .RS .TP .B b enforce load balance as much as possible. .TP .B q privilege quality over speed (default). .TP .B s privilege speed over quality. .TP .B t enforce safety. .PP It is exclusive with the \fB-m\fP option. .RE .TP .B \fB-h\fP Display some help. .TP .B \fB-m\fP\fIstrat\fP Use sequential mapping strategy \fIstrat\fP (see Scotch user's manual for more information). .TP .B \fB-q\fP (for \fBgpart\fP) .TP .B \fB-q\fP\fIpwght\fP (for \fBgmap\fP) Use the programs as graph clustering tools instead of static mapping or graph partitioning tools. For \fBgpart\fP, the number of parts will become the maximum cluster weight. For \fBgmap\fP, this number \fIpwght\fP has to be passed after the option. .TP .B \fB-V\fP Display program version and copyright. .TP .B \fB-v\fP\fIverb\fP Set verbose mode to \fIverb\fP. It is a set of one of more characters which can be: .RS .TP .B m mapping information. .TP .B s strategy information. .TP .B t timing information. .SH TARGET ARCHITECTURES Target architectures represent graphs onto which source graphs are mapped. In order to speed-up the obtainment of target architecture topological properties during the computation of mappings, some classical topologies are algorithmically coded into the mapper itself. These topologies are consequently simply defined by their code name, followed by their dimensional parameters: .TP .B cmplt \fIdim\fP unweighted complete graph of size \fIdim\fP. .TP .B cmpltw \fIdim\fP \fIw0\fP \fIw1\fP \.\.\. \fIwdim-1\fP weighted complete graph of size size and of respective loads \fIw0\fP, \fIw1\fP, \.\.\., \fIwdim-1\fP. .TP .B hcub \fIdim\fP hypercube of dimension \fIdim\fP. .TP .B leaf \fIhgt\fP \fIn0\fP \fIw0\fP \.\.\. \fInhgt-1\fP \fIwhgt-1\fP tree-leaf graph of height \fIhgt\fP with (\fIn0\fP times \fIn1\fP times \.\.\. \fInhgt-1\fP) vertices, with inter-cluster link weights of \fIw0\fP, \fIw1\fP, \.\.\. \fIwhgt-1\fP. .TP .B mesh2D \fIdimX\fP \fIdimY\fP 2D mesh of \fIdimX\fP times \fIdimY\fP nodes. .TP .B mesh3D \fIdimX\fP \fIdimY\fP \fIdimZ\fP 23 mesh of \fIdimX\fP times \fIdimY\fP times \fIdimZ\fP nodes. .TP .B torus2D \fIdimX\fP \fIdimY\fP 2D torus of \fIdimX\fP times \fIdimY\fP nodes. .TP .B torus3D \fIdimX\fP \fIdimY\fP \fIdimZ\fP 3D torus of \fIdimX\fP times \fIdimY\fP times \fIdimZ\fP nodes. .PP Other target topologies can be created from their source graph description by using the \fBamk_grf\fP(1) command. In this case, the target description will begin with the code name \fBdeco\fP. .SH MAPPINGS Mappings are represented by as many lines as there are vertices in the source graph. Each of these lines is made of two figures: the number of the vertex (or its label if source graph vertices are labeled) and the index of the target vertex to which it has been assigned. Target vertex indices range from 0 to the number of vertices in the target architecture (that is, the number of parts) minus one. .PP This block of lines is always preceded by the number of such lines. In most cases, since full mappings are requested, the number of lines is equal to the number of vertices in the source graph. .SH EXAMPLES Run \fBgpart\fP to compute a partition into 7 parts of graph 'brol.grf' and save the resulting ordering to file 'brol.map'. .PP .nf .fam C $ gpart 7 brol.grf brol.map .fam T .fi Run \fBgmap\fP to compute a partition, into 3 parts of respective weights 1, 2 and 4, of graph 'brol.grf' and save the resulting mapping to file 'brol.map'. The dash '-' standard file name is used so that the target architecture description is read from the standard input, through the pipe, as provided by the 'echo' shell command. .PP .nf .fam C $ echo "cmpltw 3 1 2 4" | gmap brol.grf - brol.map .fam T .fi .SH SEE ALSO \fBamk_grf\fP(1), \fBacpl\fP(1), \fBgmtst\fP(1), \fBdgmap\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/gbase.10000644000175300017530000000276211627545546017171 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH gbase 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBgbase \fP- sets the base value of a source graph \fB .SH SYNOPSIS .nf .fam C \fBgbase\fP [\fIoptions\fP] \fIbval\fP [\fIigfile\fP] [\fIogfile\fP] .fam T .fi .SH DESCRIPTION The \fBgbase\fP program allows one to set to \fIbval\fP the base value of a source graph, that is, the starting index used to number its vertices and edges. The base value can be set to 0 or 1, so that graphs can be easily imported from and/or exported to tools written in C or Fortran. Scotch can handle graphs irrespective of their base value. .PP When the proper libraries have been included at compile time, \fBgbase\fP can directly handle compressed graphs, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .SH OPTIONS .TP .B \fB-h\fP Display some help. .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Set the base of graph 'brol.grf' to 1, and write the modified graph to file 'brol_b1.grf'. .PP .nf .fam C $ gbase 1 brol.grf brol_b1.grf .fam T .fi .SH SEE ALSO \fBgcv\fP(1), \fBgmk_hy\fP(1), \fBgmk_msh\fP(1), \fBgtst\fP(1), \fBgmap\fP(1), \fBgord\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/dgmap.10000644000175300017530000001217411627545546017176 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH dgmap 1 "September 01, 2011" "" "PT-Scotch user's manual" .SH NAME \fBdgmap, dgpart \fP- compute static mappings and partitions in parallel \fB .SH SYNOPSIS .nf .fam C \fBdgmap\fP [\fIoptions\fP] [\fIgfile\fP] [\fItfile\fP] [\fImfile\fP] [\fIlfile\fP] .PP \fBdgpart\fP [\fIoptions\fP] [\fInparts/\fIpwght\fP\fP] [\fIgfile\fP] [\fImfile\fP] [\fIlfile\fP] .fam T .fi .SH DESCRIPTION The \fBdgmap\fP program computes, in a parallel way, a static mapping of a source graph onto a target graph. .PP The \fBdgpart\fP program is a simplified interface to \fBdgmap\fP, which performs graph partitioning instead of static mapping. Consequently, the desired number of parts has to be provided, in lieu of the target architecture. When using the program for graph clustering, the number of parts turns into maximum cluster weight. .PP The \fB-b\fP and \fB-c\fP options allow the user to set preferences on the behavior of the mapping strategy which is used by default. The \fB-m\fP option allows the user to define a custom mapping strategy. .PP The \fB-q\fP option turns the programs into graph clustering programs. In this case, \fBdgmap\fP only accepts variable-sized target architectures. .PP Source graph file \fIgfile\fP is either a centralized graph file, or a set of files representing fragments of a distributed graph. For \fBdgmap\fP, the target architecture file \fItfile\fP describes either algorithmically-coded topologies such as meshes and hypercubes, or decomposition-defined architectures created by means of the \fBamk_grf\fP(1) program. See \fBgmap\fP(1) for a description of target architectures. The resulting mapping is stored in file \fImfile\fP. Eventual logging information (such as the one produced by option \fB-v\fP) is sent to file \fIlfile\fP. When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitely represented by a dash '-'. .PP When the proper libraries have been included at compile time, \fBdgmap\fP and \fBdgpart\fP can directly handle compressed graphs, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .PP \fBdgmap\fP and \fBdgpart\fP base on implementations of the MPI interface to spread work across the processing elements. They are therefore not likely to be run directly, but instead through some launcher command such as \fBmpirun\fP. .SH OPTIONS .TP .B \fB-b\fP\fIval\fP Set maximum load imbalance ratio for graph partitioning or static mapping. When programs are used as clustering tools, this parameter sets the maximum load imbalance ratio for recursive bipartitions. Exclusive with the \fB-m\fP option. .TP .B \fB-c\fP\fIopt\fP Choose default mapping strategy according to one or several options among: .RS .TP .B b enforce load balance as much as possible. .TP .B q privilege quality over speed (default). .TP .B s privilege speed over quality. .TP .B t enforce safety. .TP .B x enforce scalability. .PP It is exclusive with the \fB-m\fP option. .RE .RE .PP .RS .TP .B \fB-h\fP Display some help. .TP .B \fB-m\fP\fIstrat\fP Use parallel mapping strategy \fIstrat\fP (see PT-Scotch user's manual for more information). .TP .B \fB-q\fP (for \fBdgpart\fP) .TP .B \fB-q\fP\fIpwght\fP (for \fBdgmap\fP) Use the programs as graph clustering tools instead of static mapping or graph partitioning tools. For \fBdgpart\fP, the number of parts will become the maximum cluster weight. For \fBdgmap\fP, this number \fIpwght\fP has to be passed after the option. .TP .B \fB-r\fP\fIpnum\fP Set root process for centralized files (default is 0). .TP .B \fB-V\fP Display program version and copyright. .TP .B \fB-v\fP\fIverb\fP Set verbose mode to \fIverb\fP. It is a set of one of more characters which can be: .RS .TP .B m mapping information. .TP .B s strategy information. .TP .B t timing information. .SH NOTE At the time being (version 5.1), \fBdgmap\fP cannot compute full static mappings as \fBgmap\fP(1) does, but only partitions (that is, mappings onto unweighted or weighted complete graphs). Target architectures other than the 'cmplt' and 'wcmplt' ones will lead to an error message. .SH EXAMPLES Run \fBdgpart\fP on 5 processing elements to compute a partition into 7 parts of graph brol.grf and save the resulting ordering to file brol.map. .PP .nf .fam C $ mpirun -np 5 dgpart 7 brol.grf brol.map .fam T .fi Run \fBdgpart\fP on 5 processing elements to partition into 7 parts the distributed graph stored on graph fragment files brol5-0.dgr to brol5-4.dgr, and save the resulting mapping to file brol.map (see \fBdgscat\fP(1) for an explanation of the '%p' and '%r' sequences in names of distributed graph fragments). .PP .nf .fam C $ mpirun -np 5 dgpart 7 brol%p-%r.dgr brol.map .fam T .fi .SH SEE ALSO \fBdgtst\fP(1), \fBdgscat\fP(1), \fBamk_grf\fP(1), \fBacpl\fP(1), \fBgmap\fP(1), \fBgmtst\fP(1). .PP PT-Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/mord.10000644000175300017530000000574711627545546017057 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH mord 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBmord \fP- compute sparse matrix orderings of meshes \fB .SH SYNOPSIS .nf .fam C \fBmord\fP [\fIoptions\fP] [\fImfile\fP] [\fIofile\fP] [\fIlfile\fP] .fam T .fi .SH DESCRIPTION The \fBmord\fP program computes, in a sequential way, an ordering of a Scotch source mesh representing the pattern of some symmetric sparse matrix. Only nodes of the mesh are effectively ordered. Elements provide connectivity information, such that every node is considered to be linked to all of the nodes which share at least an element with it. .PP Source mesh file \fImfile\fP can only be a centralized mesh file. The resulting ordering is stored in file \fIofile\fP. Eventual logging information (such as the one produced by option \fB-v\fP) is sent to file \fIlfile\fP. When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitely represented by a dash '-'. .PP When the proper libraries have been included at compile time, gord can directly handle compressed meshes, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.msh.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .SH OPTIONS .TP .B \fB-c\fPopt Choose default ordering strategy according to one or several \fIoptions\fP among: .RS .TP .B b enforce load balance as much as possible. .TP .B q privilege quality over speed (default). .TP .B s privilege speed over quality. .TP .B t enforce safety. .RE .TP .B \fB-h\fP Display some help. .TP .B \fB-m\fP\fImfile\fP Save column block mapping data to file \fImfile\fP. Mapping data specifies, for each node vertex, the index of the column block to which this node vertex belongs. .TP .B \fB-o\fP\fIstrat\fP Use sequential mesh ordering strategy \fIstrat\fP (see Scotch user's manual for more information). .TP .B \fB-t\fP\fItfile\fP Save partitioning tree data to file \fItfile\fP. Partitioning tree data specifies, for each node vertex, the index of the first node vertex of the parent block of the block to which the node vertex belongs. Altogether with the mapping data provided in file \fImfile\fP, it allows one to rebuild the separator tree of the nested dissection process. .TP .B \fB-V\fP Display program version and copyright. .TP .B \fB-v\fP\fIverb\fP Set verbose mode to \fIverb\fP. It is a set of one of more characters which can be: .RS .TP .B s strategy information. .TP .B t timing information. .SH EXAMPLE Reorder matrix mesh brol.msh and save the resulting ordering to file brol.ord using the default sequential mesh ordering strategy: .PP .nf .fam C $ mord brol.msh brol.ord .fam T .fi .SH SEE ALSO \fBgmk_msh\fP(1), \fBgotst\fP(1), \fBmtst\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/mmk_m3.10000644000175300017530000000002211627545546017256 0ustar hazelscthazelsct.so man1/mmk_m2.1 scotch-5.1.12b.dfsg/man/man1/amk_ccc.10000644000175300017530000000745111627545546017470 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH amk_ccc 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBamk_ccc, amk_fft2, amk_hy, amk_m2, amk_p2 \fP- create target architectures \fB .SH SYNOPSIS .nf .fam C \fBamk_ccc\fP [\fIoptions\fP] \fIdim\fP [\fItfile\fP] .PP \fBamk_fft2\fP [\fIoptions\fP] \fIdim\fP [\fItfile\fP] .PP \fBamk_hy\fP [\fIoptions\fP] \fIdim\fP [\fItfile\fP] .PP \fBamk_m2\fP [\fIoptions\fP] \fIdimX\fP [\fIdimY\fP] [\fItfile\fP] .PP \fBamk_p2\fP [\fIoptions\fP] [\fIwght0\fP] [\fIwght1\fP] [\fItfile\fP] .fam T .fi .SH DESCRIPTION The amk_* programs create target architecture files for some common, regular topologies. .PP \fBamk_ccc\fP creates a decomposition-defined cube-connected-cycle topology of dimension \fIdim\fP. The decomposition is performed first by bisection along the dimensions of the hypercube, then along the remaining cycle graphs. .PP \fBamk_fft2\fP creates a decomposition-defined fast-Fourier-transform topology of dimension \fIdim\fP. The decomposition is performed by recursive bisection of the vertices, by descending dimension (that is, bit number in the labeling of the vertices). .PP \fBamk_hy\fP creates a decomposition-defined hypercube topology of dimension \fIdim\fP. The decomposition is performed by recursive bisection of the vertices, by descending dimension (that is, bit number in the labeling of the vertices). Save for experimentation purposes, this program is deprecated, as the algorithmically-defined 'hcub' target architecture is a more convenient and efficient way to represent hypercube architectures. .PP \fBamk_m2\fP creates a decomposition-defined 2D regular grid topology of dimensions \fIdimX\fP and \fIdimY\fP. The decomposition is performed by recursive splitting along the dimensions, either by cutting the longest one, or by one-way dissection, depending on the '\fB-m\fP' option flag. Save for experimentation purposes, this program is deprecated, as the algorithmically-defined 'mesh2D' and 'mesh3D' target architectures are a more convenient and efficient way to represent 2D and 3D grid architectures. .PP \fBamk_p2\fP creates a weighted path graph topology comprising only two vertices of weights \fIwght0\fP and \fIwght1\fP. This is just a helper program, which builds a 'wcmplt' algorithmically-defined complete graph with two vertices. It may be used to compute weighted bisections of a graph. .PP When the proper libraries have been included at compile time, the amk_* programs can directly handle compressed files, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.tgt.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .SH OPTIONS .TP .B \fB-m\fP\fImeth\fP For \fBamk_m2\fP only. Perform either recursive dissection or one-way dissection, according to the given method flag: .RS .TP .B n perform nested dissection (default). .TP .B o perform one-way dissection (cut across Y, then X). .RE .TP .B \fB-h\fP Display some help. .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Create a cube-connected-cycle target architecture of dimension 4, and save it to file 'ccc4.tgt'. .PP .nf .fam C $ amk_ccc 4 ccc4.tgt .fam T .fi Run gmap to compute a bisection, into two parts of respective weights 3 and 5, of graph 'brol.grf' and save the resulting mapping to file 'brol.map'. The dash '-' standard file name is used so that the target architecture description is read from the standard input, through the pipe. .PP .nf .fam C $ amk_p2 3 5 | gmap brol.grf - brol.map .fam T .fi .SH SEE ALSO \fBacpl\fP(1), \fBatst\fP(1), \fBamk_grf\fP(1), \fBdgmap\fP(1), \fBgmap\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/atst.10000644000175300017530000000323511627545546017057 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH atst 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBatst \fP- test the consistency of target architectures \fB .SH SYNOPSIS .nf .fam C \fBatst\fP [\fIoptions\fP] [\fIafile\fP] [\fIlfile\fP] .fam T .fi .SH DESCRIPTION The \fBatst\fP program checks the consistency of a Scotch decomposition-defined target architecture and, in case of success, outputs some statistics regarding the number of target vertices and the length of paths linking them. Target architectures define the topology of the target graphs used by static mapping programs \fBgmap\fP(1) and \fBdgmap\fP(1). .PP The resulting statistics are stored in file \fIlfile\fP. When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitly represented by a dash '-'. .PP When the proper libraries have been included at compile time, \fBatst\fP can directly handle compressed files, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.tgt.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .SH OPTIONS .TP .B \fB-h\fP Display some help. .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Test the consistency of architecture arch.tgt: .PP .nf .fam C $ atst arch.tgt .fam T .fi .SH SEE ALSO \fBacpl\fP(1), \fBamk_ccc\fP(1), \fBamk_grf\fP(1), \fBdgmap\fP(1), \fBgmap\fP(1), \fBgmtst\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/gmk_msh.10000644000175300017530000000207411627545546017531 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH gmk_msh 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBgmk_msh \fP- create source graph from source mesh \fB .SH SYNOPSIS .nf .fam C \fBgmk_msh\fP [\fIoptions\fP] [\fImfile\fP] [\fIgfile\fP] .fam T .fi .SH DESCRIPTION The \fBgmk_msh\fP program creates a source graph from a source mesh. The vertices of the graph are the nodes of the mesh, and all mesh elements are turned into cliques, that is, there exists an edge between two vertices in the graph if there exists at least an element in the mesh which comprises the two associated nodes. .SH OPTIONS .TP .B \fB-h\fP Display some help. .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Create a source graph brol.grf from a source mesh brol.msh: .PP .nf .fam C $ gmk_msh brol.msh brol.grf .fam T .fi .SH SEE ALSO dgmap (1), \fBdgord\fP(1), \fBgbase\fP(1), \fBgmap\fP(1), \fBgord\fP(1), \fBgtst\fP(1), \fBmmk_m2\fP(1), \fBmord\fP(1), \fBmcv\fP(1), \fBmtst\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/amk_grf.10000644000175300017530000000504311627545546017511 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH amk_grf 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBamk_grf \fP- create target architecture from source graph \fB .SH SYNOPSIS .nf .fam C \fBamk_grf\fP [\fIoptions\fP] [\fIgfile\fP] [\fItfile\fP] .fam T .fi .SH DESCRIPTION The \fBamk_grf\fP program builds a decomposition-defined target architecture \fItfile\fP from a source graph \fIgfile\fP. .PP Target architectures define the topology of the target graphs used by static mapping programs \fBgmap\fP(1) and \fBdgmap\fP(1). Target architectures can be either algorithmically-defined, for common, regular topologies, or decomposition-defined, such as the ones produced by \fBamk_grf\fP. .PP When the proper libraries have been included at compile time, \fBamk_grf\fP can directly handle compressed files, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.tgt.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .PP Since decomposition-defined target architecture files have a size which is quadratic in the number of target vertices, because of the presence of a distance matrix structure, using compressed files to store them may save a lot of space. .SH OPTIONS .TP .B \fB-b\fP\fIstrat\fP Apply bipartitioning strategy \fIstrat\fP to compute the recursive bipartition of the whole source graph into smaller target subdomains. .TP .B \fB-h\fP Display some help. .TP .B \fB-l\fP\fIlfile\fP Only keep vertices the indices of which belong to the space-separated list stored in \fIlfile\fP. This allows one to create target architectures which can even be disjoint subsets of a larger target architecture, modeled as a graph. .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Create a decomposition-defined target architecture from a 2D regular grid source graph of dimension 3 times 5, and save it, as a compiled target architecture, under the \fBgzip\fP(1) format, to file 'm3x5.tgt.gz'. .PP .nf .fam C $ gmk_m2 3 5 | amk_grf | acpl - m3x5.tgt.gz .fam T .fi Note that, in this precise case, it would be much preferable to use directly the 'mesh2D' algorithmically-defined target architecture. .PP .nf .fam C $ echo "mesh2D 3 5" > m3x5.tgt .fam T .fi .SH SEE ALSO \fBacpl\fP(1), \fBamk_ccc\fP(1), \fBatst\fP(1), \fBdgmap\fP(1), \fBgmap\fP(1), \fBgmtst\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/gord.10000644000175300017530000000542111627545546017036 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH gord 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBgord \fP- compute sparse matrix orderings of graphs \fB .SH SYNOPSIS .nf .fam C \fBgord\fP [\fIoptions\fP] [\fIgfile\fP] [\fIofile\fP] [\fIlfile\fP] .fam T .fi .SH DESCRIPTION The \fBgord\fP program computes, in a sequential way, an ordering of a Scotch source graph representing the pattern of some symmetric sparse matrix. .PP Source graph file \fIgfile\fP can only be a centralized graph file. The resulting ordering is stored in file \fIofile\fP. Eventual logging information (such as the one produced by option \fB-v\fP) is sent to file \fIlfile\fP. When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitely represented by a dash '-'. .PP When the proper libraries have been included at compile time, \fBgord\fP can directly handle compressed graphs, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .SH OPTIONS .TP .B \fB-c\fPopt Choose default ordering strategy according to one or several \fIoptions\fP among: .RS .TP .B b enforce load balance as much as possible. .TP .B q privilege quality over speed (default). .TP .B s privilege speed over quality. .TP .B t enforce safety. .RE .TP .B \fB-h\fP Display some help. .TP .B \fB-m\fP\fImfile\fP Save column block mapping data to file \fImfile\fP. Mapping data specifies, for each vertex, the index of the column block to which this vertex belongs. .TP .B \fB-o\fP\fIstrat\fP Use sequential graph ordering strategy \fIstrat\fP (see Scotch user's manual for more information). .TP .B \fB-t\fP\fItfile\fP Save partitioning tree data to file \fItfile\fP. Partitioning tree data specifies, for each vertex, the index of the first vertex of the parent block of the block to which the vertex belongs. Altogether with the mapping data provided in file \fImfile\fP, it allows one to rebuild the separator tree of the nested dissection process. .TP .B \fB-V\fP Display program version and copyright. .TP .B \fB-v\fP\fIverb\fP Set verbose mode to \fIverb\fP. It is a set of one of more characters which can be: .RS .TP .B s strategy information. .TP .B t timing information. .SH EXAMPLE Reorder matrix graph brol.grf and save the resulting ordering to file brol.ord using the default sequential graph ordering strategy: .PP .nf .fam C $ gord brol.grf brol.ord .fam T .fi .SH SEE ALSO \fBdgord\fP(1), \fBgmk_hy\fP(1), \fBgtst\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/dgtst.10000644000175300017530000000474111627545546017234 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH dgtst 1 "February 14, 2011" "" "PT-Scotch user's manual" .SH NAME \fBdgtst \fP- test the consistency of source graphs in parallel \fB .SH SYNOPSIS .nf .fam C \fBdgtst\fP [\fIoptions\fP] [\fIgfile\fP] [\fIlfile\fP] .fam T .fi .SH DESCRIPTION The \fBdgtst\fP program checks, in a parallel way, the consistency of a Scotch source graph and, in case of success, outputs some statistics regarding edge weights, vertex weights, and vertex degrees. .PP It produces the very same results as the \fBgtst\fP(1) program of the Scotch sequential distribution, but unlike this latter it can handle distributed graphs. .PP Source graph file \fIgfile\fP is either a centralized graph file, or a set of files representing fragments of a distributed graph. The resulting statistics are stored in file \fIlfile\fP. When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitly represented by a dash '-'. .PP When the proper libraries have been included at compile time, \fBdgtst\fP can directly handle compressed graphs, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .PP \fBdgtst\fP bases on implementations of the MPI interface to spread work across the processing elements. It is therefore not likely to be run directly, but instead through some launcher command such as \fBmpirun\fP. .SH OPTIONS .TP .B \fB-h\fP Display some help. .TP .B \fB-r\fP\fIpnum\fP Set root process for centralized files (default is 0). .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Run \fBdgtst\fP on 5 processing elements to test the consistency of graph brol.grf .PP .nf .fam C $ mpirun -np 5 dgtst brol.grf .fam T .fi Run dgord on 5 processing elements to test the consistency of a distributed graph stored on graph fragment files brol5-0.dgr to brol5-4.dgr, and save the resulting ordering to file brol.ord (see \fBdgscat\fP(1) for an explanation of the '%p' and '%r' sequences in names of distributed graph fragments). .PP .nf .fam C $ mpirun -np 5 dgtst brol%p-%r.dgr brol.ord .fam T .fi .SH SEE ALSO \fBdgscat\fP(1), \fBgtst\fP(1), \fBdgord\fP(1). .PP PT-Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/gmtst.10000644000175300017530000000461611627545546017246 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH gmtst 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBgmtst \fP- compute statistics on mappings \fB .SH SYNOPSIS .nf .fam C \fBgmtst\fP [\fIoptions\fP] [\fIgfile\fP] [\fItfile\fP] [\fImfile\fP] [\fIlfile\fP] .fam T .fi .SH DESCRIPTION The \fBgmtst\fP program computes, in a sequential way, statistics on a static mapping, such as load imbalance ratio, edge dilation distribution, etc. It yields the same results as the ones produced by the \fB-vm\fP option of the \fBgmap\fP(1) program. .PP Source graph file \fIgfile\fP can only be a centralized graph file. File \fItfile\fP represents the target architecture onto which \fIgfile\fP was mapped. If mapping file \fImfile\fP was produced by \fBgpart\fP(1), the target architecture file to provide \fBgmtst\fP should describe a complete graph with the same number of vertices as the requested number of parts, for instance by means of the '\fBcmplt\fP \fInum\fP' algorithmically-described architecture. The resulting statistics are stored in file \fIlfile\fP. When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitly represented by a dash '-'. .PP When the proper libraries have been included at compile time, gtst can directly handle compressed graphs, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .SH OPTIONS .TP .B \fB-h\fP Display some help. .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLES Display statistics on mapping brol.map of graph brol.grf onto target architecture brol.tgt: .PP .nf .fam C $ gmtst brol.grf brol.tgt brol.map .fam T .fi Display statistics on partitioning brol.map of graph brol.grf into \fInum\fP parts. Note the use of the complete graph algorithmically-described architecture and of the shell pipe command to provide the complete target architecture description on the standard input of the \fBgmtst\fP command: .PP .nf .fam C $ echo "cmplt num" | gmtst brol.grf - brol.map .fam T .fi .SH SEE ALSO \fBgmap\fP(1), \fBgout\fP(1), \fBgtst\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/gtst.10000644000175300017530000000331611627545546017065 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH gtst 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBgtst \fP- test the consistency of source graphs \fB .SH SYNOPSIS .nf .fam C \fBgtst\fP [\fIoptions\fP] [\fIgfile\fP] [\fIlfile\fP] .fam T .fi .SH DESCRIPTION The \fBgtst\fP program checks, in a sequential way, the consistency of a Scotch source graph and, in case of success, outputs some statistics regarding edge weights, vertex weights, and vertex degrees. .PP It produces the very same results as the \fBdgtst\fP(1) program of the PT-Scotch parallel distribution, but unlike this latter it cannot handle distributed graphs. .PP Source graph file \fIgfile\fP can only be a centralized graph file. The resulting statistics are stored in file \fIlfile\fP. When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitly represented by a dash '-'. .PP When the proper libraries have been included at compile time, \fBgtst\fP can directly handle compressed graphs, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .SH OPTIONS .TP .B \fB-h\fP Display some help. .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Test the consistency of graph brol.grf: .PP .nf .fam C $ gtst brol.grf .fam T .fi .SH SEE ALSO \fBdgtst\fP(1), \fBgbase\fP(1), \fBgmap\fP(1), \fBgord\fP(1), \fBgout\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/gpart.10000644000175300017530000000002011627545546017206 0ustar hazelscthazelsct.so man1/gmap.1 scotch-5.1.12b.dfsg/man/man1/gmk_m3.10000644000175300017530000000002211627545546017250 0ustar hazelscthazelsct.so man1/gmk_hy.1 scotch-5.1.12b.dfsg/man/man1/amk_m2.10000644000175300017530000000002311627545546017242 0ustar hazelscthazelsct.so man1/amk_ccc.1 scotch-5.1.12b.dfsg/man/man1/gcv.10000644000175300017530000000500611627545546016661 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH gcv 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBgcv \fP- graph file converter \fB .SH SYNOPSIS .nf .fam C \fBgcv\fP [\fIoptions\fP] [\fIigfile\fP] [\fIogfile\fP] [\fIoxfile\fP] .fam T .fi .SH DESCRIPTION The \fBgcv\fP program converts Scotch graph files from and to other external file formats. .PP File \fIigfile\fP is converted into graph file \fIogfile\fP, with optional geometry data being put in geometry file \fIoxfile\fP, if it is available. .PP When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitly represented by a dash '-'. .PP When the proper libraries have been included at compile time, \fBgcv\fP can directly handle compressed graphs, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .SH OPTIONS .TP .B \fB-h\fP Display some help. .TP .B \fB-i\fP\fIifmt\fP Set format of input graph file, which can be: .RS .TP .B b\fInum\fP Boeing-Harwell format. This is a matrix format. Only square matrices are supported. Square matrices with unsymmetric pattern are symmetrized. In case the file contains several matrices, the \fInum\fP parameter allow the user to provide the index of the matrix to convert, starting from 0. When the \fInum\fP parameter is not set, it is assumed to be 0. .TP .B c Chaco format. This is an adjacency graph format, also used by MeTiS. .TP .B m Matrix Market format. This is a matrix format describing individual edges. Matrix pattern is symmetrized, such that rectangular matrices are eventually squared. .TP .B s Scotch graph format. This is an adjacency graph format. .RE .TP .B \fB-o\fP\fIofmt\fP Set format of output graph file, which can be: .RS .TP .B c Chaco format. .TP .B m Matrix Market symmetric pattern format. .TP .B s Scotch format. This is the default. .RE .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Convert a Matrix Market graph into a Scotch graph. Matrix Market files do not comprise geometry data, so no geometry file is needed on output: .PP .nf .fam C $ gcv -im brol.mm brol.grf .fam T .fi .SH SEE ALSO \fBgbase\fP(1), \fBgtst\fP(1), \fBgmap\fP(1), \fBgord\fP(1), \fBgout\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/dgord.10000644000175300017530000000716211627545546017206 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH dgord 1 "February 14, 2011" "" "PT-Scotch user's manual" .SH NAME \fBdgord \fP- compute sparse matrix orderings of graphs in parallel \fB .SH SYNOPSIS .nf .fam C \fBdgord\fP [\fIoptions\fP] [\fIgfile\fP] [\fIofile\fP] [\fIlfile\fP] .fam T .fi .SH DESCRIPTION The \fBdgord\fP program computes, in a parallel way, an ordering of a Scotch source graph representing the pattern of some symmetric sparse matrix. .PP Source graph file \fIgfile\fP is either a centralized graph file, or a set of files representing fragments of a distributed graph. The resulting ordering is stored in file \fIofile\fP. Eventual logging information (such as the one produced by option \fB-v\fP) is sent to file \fIlfile\fP. When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitely represented by a dash '-'. .PP When the proper libraries have been included at compile time, \fBdgord\fP can directly handle compressed graphs, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .PP \fBdgord\fP bases on implementations of the MPI interface to spread work across the processing elements. It is therefore not likely to be run directly, but instead through some launcher command such as \fBmpirun\fP. .SH OPTIONS .TP .B \fB-c\fPopt Choose default ordering strategy according to one or several \fIoptions\fP among: .RS .TP .B b enforce load balance as much as possible. .TP .B q privilege quality over speed (default). .TP .B s privilege speed over quality. .TP .B t enforce safety. .TP .B x enforce scalability. .RE .TP .B \fB-h\fP Display some help. .TP .B \fB-m\fP\fImfile\fP Save column block mapping data to file \fImfile\fP. Mapping data specifies, for each vertex, the index of the column block to which this vertex belongs. .TP .B \fB-o\fP\fIstrat\fP Use parallel graph ordering strategy \fIstrat\fP (see PT-Scotch user's manual for more information). .TP .B \fB-r\fP\fIpnum\fP Set root process for centralized files (default is 0). .TP .B \fB-t\fP\fItfile\fP Save partitioning tree data to file \fItfile\fP. Partitioning tree data specifies, for each vertex, the index of the first vertex of the parent block of the block to which the vertex belongs. Altogether with the mapping data provided in file \fImfile\fP, it allows one to rebuild the separator tree of the nested dissection process. .TP .B \fB-V\fP Display program version and copyright. .TP .B \fB-v\fP\fIverb\fP Set verbose mode to \fIverb\fP. It is a set of one of more characters which can be: .RS .TP .B s strategy information. .TP .B t timing information. .SH EXAMPLES Run \fBdgord\fP on 5 processing elements to reorder matrix graph brol.grf and save the resulting ordering to file brol.ord, using the default sequential graph ordering strategy: .PP .nf .fam C $ mpirun -np 5 dgord brol.grf brol.ord .fam T .fi Run \fBdgord\fP on 5 processing elements to reorder the distributed matrix stored on graph fragment files brol5-0.dgr to brol5-4.dgr, and save the resulting ordering to file brol.ord (see \fBdgscat\fP(1) for an explanation of the '%p' and '%r' sequences in names of distributed graph fragments). .PP .nf .fam C $ mpirun -np 5 dgord brol%p-%r.dgr brol.ord .fam T .fi .SH SEE ALSO \fBdgtst\fP(1), \fBdgscat\fP(1), \fBgmk_hy\fP(1), \fBgord\fP(1). .PP PT-Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/gmk_hy.10000644000175300017530000000364311627545546017365 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH gmk_hy 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBgmk_hy, gmk_m2, gmk_m3, gmk_ub2 \fP- create source graphs \fB .SH SYNOPSIS .nf .fam C \fBgmk_hy\fP [\fIoptions\fP] \fIdim\fP [\fIofile\fP] .PP \fBgmk_m2\fP [\fIoptions\fP] [\fB-g\fP\fIcfile\fP] \fIdimX\fP \fIdimY\fP [\fIofile\fP] .PP \fBgmk_m3\fP [\fIoptions\fP] [\fB-g\fP\fIcfile\fP] \fIdimX\fP \fIdimY\fP \fIdimZ\fP [\fIofile\fP] .PP \fBgmk_ub2\fP [\fIoptions\fP] \fIdim\fP .fam T .fi .SH DESCRIPTION The \fBgmk_\fP* programs create source graph files for some common, regular topologies. .PP \fBgmk_hy\fP creates a hypercube of dimension \fIdim\fP. .PP \fBgmk_m2\fP creates a 2D regular grid of dimensions \fIdimX\fP and \fIdimY\fP. .PP \fBgmk_m3\fP creates a 3D regular grid of dimensions \fIdimX\fP, \fIdimY\fP and \fIdimZ\fP. .PP \fBgmk_ub2\fP creates an unoriented de Bruijn graph of dimension \fIdim\fP. .SH OPTIONS .TP .B \fB-b\fP base For \fBgmk_m2\fP and \fBgmk_m3\fP only. Output graphs with base value set to base. Default value is 0. .TP .B \fB-e\fP For \fBgmk_m2\fP only. Build a 8-neighbor grid rather than a 4-neighbor grid. .TP .B \fB-g\fP\fIcfile\fP For \fBgmk_m2\fP and \fBgmk_m3\fP only. Output graph vertex coordinates (that is, geometry data to be used by \fBgout\fP(1)) in file \fIcfile\fP. .TP .B \fB-h\fP Display some help. .TP .B \fB-t\fP For \fBgmk_m2\fP and \fBgmk_m3\fP only. Create torus graphs, that is, graphs such that there exist loop edges between vertices of rank 0 and (\fIdim\fP-1) in every dimension. .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Create a 5x7 grid along with its geometry: .PP .nf .fam C $ gmk_m2 5 7 -g/tmp/m5x7.xyz /tmp/m5x7.grf .fam T .fi .SH SEE ALSO \fBgbase\fP(1), \fBgmk_msh\fP(1), \fBgtst\fP(1), \fBgmap\fP(1), \fBgord\fP(1), \fBgout\fP(1), \fBamk_grf\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/dggath.10000644000175300017530000000002211627545546017331 0ustar hazelscthazelsct.so man1/dgscat.1 scotch-5.1.12b.dfsg/man/man1/amk_p2.10000644000175300017530000000002311627545546017245 0ustar hazelscthazelsct.so man1/amk_ccc.1 scotch-5.1.12b.dfsg/man/man1/gmk_m2.10000644000175300017530000000002211627545546017247 0ustar hazelscthazelsct.so man1/gmk_hy.1 scotch-5.1.12b.dfsg/man/man1/gmk_ub2.10000644000175300017530000000002211627545546017421 0ustar hazelscthazelsct.so man1/gmk_hy.1 scotch-5.1.12b.dfsg/man/man1/gotst.10000644000175300017530000000367511627545546017254 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH gotst 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBgomtst \fP- compute statistics on sparse matrix orderings \fB .SH SYNOPSIS .nf .fam C \fBgotst\fP [\fIoptions\fP] [\fIgfile\fP] [\fIofile\fP] [\fIlfile\fP] .fam T .fi .SH DESCRIPTION The \fBgotst\fP program computes, in a sequential way, statistics on a sparse matrix ordering, such as fill-in, operation count, and separator tree parameters: minimum, maximum, average height and variance of its leaves. .PP Source graph file \fIgfile\fP can only be a centralized graph file. File \fIofile\fP represents the ordering of the symmetric sparse matrix the pattern of which is represented by \fIgfile\fP. The resulting statistics are stored in file \fIlfile\fP. When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitly represented by a dash '-'. .PP When the proper libraries have been included at compile time, gtst can directly handle compressed graphs, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .PP Since \fBgotst\fP performs sequentially the symbolic factorization of matrix \fIgfile\fP in order to compute fill-in and operation count numbers, this program can take a long time or even run out of memory, when applied to very large graphs. .SH OPTIONS .TP .B \fB-h\fP Display some help. .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Display statistics on ordering brol.ord of graph brol.grf: .PP .nf .fam C $ gotst brol.grf brol.ord .fam T .fi .SH SEE ALSO \fBgord\fP(1), \fBgtst\fP(1), \fBdgord\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/dgscat.10000644000175300017530000001236411627545546017354 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH dgscat 1 "February 14, 2011" "" "PT-Scotch user's manual" .SH NAME \fBdggath, dgscat, gscat \fP- convert distributed source graphs to or from centralized ones \fB .SH SYNOPSIS .nf .fam C \fBdggath\fP [\fIoptions\fP] [\fIigfile\fP] [\fIogfile\fP] .PP \fBdgscat\fP [\fIoptions\fP] [\fIigfile\fP] [\fIogfile\fP] .PP \fBgscat\fP [\fIoptions\fP] [\fIigfile\fP] [\fIogfile\fP] .fam T .fi .SH DESCRIPTION The \fBdggath\fP program gathers distributed graphs into centralized graphs. It reads a set of files \fIigfile\fP representing fragments of a distributed source graph, and writes them back on the form of a single centralized source graph \fIogfile\fP. .PP The \fBdgscat\fP program scatters centralized source graphs into distributed graphs. It reads a centralized source graph \fIigfile\fP and writes it back on the form of a set of files \fIogfile\fP representing fragments of the corresponding distributed source graph. .PP The \fBgscat\fP program does exactly the same as \fBdgscat\fP, but does not require to be run in a parallel environment. Since \fBgscat\fP processes the input centralized graph file as a text stream, it does not need to load the full graph in memory before building the distributed graph fragment files. It is therefore much less resource consuming, but does not allow for the checking of graph consistency, as it has no global vision of the graph structure. .PP When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitly represented by a dash '-'. .PP When the proper libraries have been included at compile time, \fBdggath\fP and \fBdgscat\fP can directly handle compressed graphs, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .PP \fBdggath\fP and \fBdgscat\fP base on implementations of the MPI interface to spread work across the processing elements. It is therefore not likely to be run directly, but instead through some launcher command such as \fBmpirun\fP. .SH DISTRIBUTED FILE NAMES In order to tell whether programs should read from, or write to, a single file located on only one processor, or to multiple instances of the same file on all of the processors, or else to distinct files on each of the processors, a special grammar has been designed, which is based on the '%' escape character. Four such escape sequences are defined, which are interpreted independently on every processor, prior to file opening. By default, when a filename is provided, it is assumed that the file is to be opened on only one of the processors, called the root processor, which is usually process 0 of the communicator within which the program is run. The index of the root processor can be changed by means of the \fB-r\fP option. Using any of the first three escape sequences below will instruct programs to open in parallel a file of name equal to the interpreted filename, on every processor on which they are run. .TP .B %p Replaced by the number of processes in the global communicator in which the program is run. Leads to parallel opening. .TP .B %r Replaced on each process running the program by the rank of this process in the global communicator. Leads to parallel opening. .TP .B %- Discarded, but leads to parallel opening. This sequence is mainly used to instruct programs to open on every processor a file of identical name. The opened files can be, according whether the given path leads to a shared directory or to directories that are local to each processor, either to the opening of multiple instances of the same file, or to the opening of distinct files which may each have a different content, respectively (but in this latter case it is much recommended to identify files by means of the '%r' sequence). .TP .B %% Replaced by a single '%' character. File names using this escape sequence are not considered for parallel opening, unless one or several of the three other escape sequences are also present. .RE .PP For instance, filename 'brol' will lead to the opening of file 'brol' on the root processor only, filename '%\fB-brol\fP' (or even 'br%\fB-ol\fP') will lead to the parallel opening of files called 'brol' on every processor, and filename 'brol%p-%r' will lead to the opening of files 'brol2-0' and 'brol2-1', respectively, on each of the two processors on which the program were to run. .SH OPTIONS .TP .B \fB-c\fP For \fBdggath\fP and \fBdgscat\fP only. Check the consistency of the input source graph after loading it into memory. .TP .B \fB-h\fP Display some help. .TP .B \fB-r\fP\fIpnum\fP Set root process for centralized files (default is 0). .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Run \fBdgscat\fP on 5 processing elements to scatter centralized graph file brol.grf into 5 gzipped file fragments brol5-0.dgr.gz to brol5-4.dgr.gz. .PP .nf .fam C $ mpirun -np 5 dgscat brol.grf brol%p-%r.dgr.gz .fam T .fi .SH SEE ALSO \fBdgmap\fP(1), \fBdgord\fP(1), \fBdgtst\fP(1), \fBgmk_hy\fP(1). .PP PT-Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/amk_fft2.10000644000175300017530000000002311627545546017565 0ustar hazelscthazelsct.so man1/amk_ccc.1 scotch-5.1.12b.dfsg/man/man1/acpl.10000644000175300017530000000455111627545546017025 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH acpl 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBacpl \fP- compile a target architectures \fB .SH SYNOPSIS .nf .fam C \fBacpl\fP [\fIoptions\fP] [\fIitfile\fP] [\fIotfile\fP] .fam T .fi .SH DESCRIPTION The \fBacpl\fP program compiles a decomposition-defined target architecture file \fIitfile\fP of type '\fBdeco\fP 0' into a compiled decomposition-defined target architecture of type '\fBdeco\fP 1', stored in file \fIotfile\fP. .PP Compiling a decomposition-defined architecture amounts to computing the distance matrix of all possible subdomains, from the distance matrix of all terminal subdomains provided in the '\fBdeco\fP 0' format. Since this computation is internally performed every time a '\fBdeco\fP 0' format is read, and is quadratic in time, pre-compiling the target architecture by means of \fBacpl\fP can save some time when repeatedly computing mappings on a large decomposition-defined '\fBdeco\fP 0' target architecture. .PP When the proper libraries have been included at compile time, \fBacpl\fP can directly handle compressed files, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.tgt.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .PP Since decomposition-defined target architecture files have a size which is quadratic in the number of target vertices, because of the distance matrix structures, using compressed files to store them may save a lot of space, especially for compiled target architecture files. .SH OPTIONS .TP .B \fB-h\fP Display some help. .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Create a compiled cube-connected-cycle target architecture of dimension 4, and save it under the \fBgzip\fP(1) format to file 'ccc4c.tgt.gz'. The dash '-' standard file name is used so that the '\fBdeco\fP 0' target architecture description produced by \fBamk_ccc\fP(1) is read from the standard input, through the pipe. .PP .nf .fam C $ amk_ccc 4 | acpl - ccc4c.tgt.gz .fam T .fi .SH SEE ALSO \fBamk_grf\fP(1), \fBamk_ccc\fP(1), \fBatst\fP(1), \fBdgmap\fP(1), \fBgmap\fP(1), \fBgmtst\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/amk_hy.10000644000175300017530000000002311627545546017344 0ustar hazelscthazelsct.so man1/amk_ccc.1 scotch-5.1.12b.dfsg/man/man1/gout.10000644000175300017530000001150211627545546017056 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH gout 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBgout \fP- output graphics from matrices and graphs \fB .SH SYNOPSIS .nf .fam C \fBgout\fP [\fIoptions\fP] [\fIgfile\fP] [\fIxfile\fP] [\fImfile\fP] [\fIvfile\fP] .fam T .fi .SH DESCRIPTION The \fBgout\fP program creates graphics files of various types, representing the Scotch graph and mapping data which is passed to it. .PP Source graph file \fIgfile\fP can only be a centralized graph file. File \fIxfile\fP stores its associated geometry, whenever necessary. File \fImfile\fP represents label information attached to each of the graph vertices, for instance the index of the part to which each vertex belongs in the case of a mapping file. File \fIvfile\fP is the output graphics file, the type of which may differ according to the input parameters. When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitly represented by a dash '-'. .PP When the proper libraries have been included at compile time, gtst can directly handle compressed graphs, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.grf.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .SH OPTIONS .TP .B \fB-h\fP Display some help. .TP .B \fB-g\fP\fIgeop\fP Geometry parameters, which can be an arbitrary combination of any of the following code letters: .RS .TP .B n Do not read geometry data, when it is not available or not required, such as when using the \fB-om\fP option. .TP .B p Permute Y and Z geometry dimensions. .TP .B r Rotate geometry by 90 degrees in the (X,Y) plane. .RE .TP .B \fB-h\fP Display some help. .TP .B \fB-mn\fP Do not read mapping data, when it is not available or not required. .TP .B \fB-o\fP\fIoutp\fP Select the output file type and allows to provide additional parameters between braces and separated by commas: .RS .TP .B i OpenInventor 3D mesh file, to be viewed by means of programs such as \fBivview\fP. Additional parameters for this output file type are: .RS .TP .B c Color output. .TP .B g Gray level output. .TP .B r Remove cut edges. .TP .B v View cut edges. .RE .TP .B m PostScript matrix pattern file. Additional parameters for this output file type are: .RS .TP .B e EPSF-type output. .TP .B f Full-page output. .RE .TP .B p PostScript 2D mesh file. This output module was intended for 2D meshes; as a fallback, the Z coordinate is projected according to isometric perspective rules, but drawings of full 3D objects are most likely to be unreadable. Additional parameters for this output file type are: .RS .TP .B c Color output. .TP .B g Gray level output. .TP .B e EPSF-type output. .TP .B f Full-page output. .TP .B s Short clipping (disks excluded). .TP .B l Large clipping (disks included). .TP .B a Avoid displaying disks. .TP .B d Display disks. .TP .B r Remove cut edges. .TP .B v View cut edges. .TP .B X=\fIrat\fP Maximum x clipping ratio (in [0.0;1.0]). .TP .B x=\fIrat\fP Minimum x clipping ratio. .TP .B Y=\fIrat\fP Maximum y clipping ratio. .TP .B y=\fIrat\fP Minimum y clipping ratio. .RE .TP .B t Tulip 3D mesh file. Additional parameters for this output file type are: .RS .TP .B b Black and white output. .TP .B c Color output. .TP .B a Avoid displaying disks. .TP .B d Display disks. .TP .B r Remove cut edges. .TP .B v View cut edges. .RE .RE .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLES Build an OpenInventor file of the mapping of graph brol.grf contained in file brol.map. Vertices with no mapping information attached to them will be rendered in white, while distinct colors will be used to represent the different parts. Cut edges will be removed: .PP .nf .fam C $ gout '-oi{r}' brol.grf brol.xyz brol.map brol.iv $ ivview brol.iv .fam T .fi Build an OpenInventor file of graph brol.grf without any vertex information associated to it. Mapping data are not required and will not be read, but a file name has to be provided, hence the '-': .PP .nf .fam C $ gout -oi -mn brol.grf brol.xyz - brol.iv .fam T .fi Output the pattern of matrix brol.grf on the form of a PostScript flat drawing. Geometry and mapping data are not required and will not be read, but file names have to be provided, hence the two '-'s: .PP .nf .fam C $ gout -om -gn -mn brol.grf - - brol.ps .fam T .fi Output a PostScript 2D drawing of a rectangular portion graph brol.grf, with disks representing mapping data: .PP .nf .fam C $ gout '-op{c,e,d,x=0.3,X=0.6,y=0.2,Y=0.5}' brol.grf brol.xyz brol.map brol.ps .fam T .fi .SH SEE ALSO \fBgmap\fP(1), \fBgout\fP(1), \fBgtst\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/mcv.10000644000175300017530000000402111627545546016663 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH mcv 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBmcv \fP- mesh file converter \fB .SH SYNOPSIS .nf .fam C \fBmcv\fP [\fIoptions\fP] [\fIimfile\fP] [\fIomfile\fP] [\fIoxfile\fP] .fam T .fi .SH DESCRIPTION The \fBmcv\fP program converts Scotch mesh files from and to other external file formats. .PP File \fIimfile\fP is converted into mesh file \fIomfile\fP, with optional geometry data being put in geometry file \fIoxfile\fP, if it is available. .PP When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitly represented by a dash '-'. .PP When the proper libraries have been included at compile time, \fBmcv\fP can directly handle compressed meshes, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.msh.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .SH OPTIONS .TP .B \fB-h\fP Display some help. .TP .B \fB-i\fP\fIifmt\fP Set format of input mesh file, which can be: .RS .TP .B b\fInum\fP Boeing-Harwell format. This is an elemental matrix format. Only square matrices are supported. In case the file contains several matrices, the \fInum\fP parameter allow the user to provide the index of the matrix to convert, starting from 0. When the \fInum\fP parameter is not set, it is assumed to be 0. .TP .B s Scotch mesh format. .RE .TP .B \fB-o\fP\fIofmt\fP Set format of output mesh file, which can be: .RS .TP .B s Scotch mesh format. This is the only possible choice at the time being. .RE .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Convert a Harwell-Boeing elemental mesh into a Scotch mesh. .PP .nf .fam C $ mcv -ib brol.hb brol.msh .fam T .fi .SH SEE ALSO \fBmtst\fP(1), \fBmord\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/mtst.10000644000175300017530000000304611627545546017073 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH mtst 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBmtst \fP- test the consistency of source meshes \fB .SH SYNOPSIS .nf .fam C \fBmtst\fP [\fIoptions\fP] [\fImfile\fP] [\fIlfile\fP] .fam T .fi .SH DESCRIPTION The \fBmtst\fP program checks, in a sequential way, the consistency of a Scotch source mesh and, in case of success, outputs some statistics regarding edge weights, node and element vertex weights, and node and element vertex degrees. .PP Source mesh file \fImfile\fP can only be a centralized mesh file. The resulting statistics are stored in file \fIlfile\fP. When file names are not specified, data is read from standard input and written to standard output. Standard streams can also be explicitly represented by a dash '-'. .PP When the proper libraries have been included at compile time, \fBmtst\fP can directly handle compressed meshes, both as input and output. A stream is treated as compressed whenever its name is postfixed with a compressed file extension, such as in 'brol.msh.bz2' or '-.gz'. The compression formats which can be supported are the bzip2 format ('.bz2'), the gzip format ('.gz'), and the lzma format ('.lzma', on input only). .SH OPTIONS .TP .B \fB-h\fP Display some help. .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Test the consistency of mesh brol.msh: .PP .nf .fam C $ mtst brol.msh .fam T .fi .SH SEE ALSO \fBmcv\fP(1), \fBmord\fP(1), \fBgmk_msh\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/man/man1/mmk_m2.10000644000175300017530000000301111627545546017256 0ustar hazelscthazelsct." Text automatically generated by txt2man .TH mmk_m2 1 "February 14, 2011" "" "Scotch user's manual" .SH NAME \fBmmk_m2, mmk_m3 \fP- create source meshes \fB .SH SYNOPSIS .nf .fam C \fBmmk_m2\fP [\fIoptions\fP] [\fB-g\fP\fIcfile\fP] \fIdimX\fP \fIdimY\fP [\fIofile\fP] .PP \fBmmk_m3\fP [\fIoptions\fP] [\fB-g\fP\fIcfile\fP] \fIdimX\fP \fIdimY\fP \fIdimZ\fP [\fIofile\fP] .fam T .fi .SH DESCRIPTION The \fBmmk_\fP* programs create source mesh files for some common, regular topologies. .PP \fBmmk_m2\fP creates a 2D regular mesh of \fIdimX\fP times \fIdimY\fP elements and (\fIdimX\fP+1) times (\fIdimY\fP+1) nodes, such that element (i,j) is connected to nodes (i,j), (i,j+1), (i+1,j) and (i+1,j+1). .PP \fBmmk_m3\fP creates a 3D regular mesh of \fIdimX\fP times \fIdimY\fP times \fIdimZ\fP elements and (\fIdimX\fP+1) times (\fIdimY\fP+1) times (\fIdimZ\fP+1) nodes, such that element (i,j,k) is connected to nodes (i,j,k), (i,j,k+1), (i,j+1,k), (i,j+1,k+1), (i+1,j,k), (i+1,j,k+1), (i+1,j+1,k) and (i+1,j+1,k+1). .SH OPTIONS .TP .B \fB-g\fP\fIcfile\fP Output graph vertex coordinates (that is, geometry data to be used by \fBgout\fP(1)) in file \fIcfile\fP. .TP .B \fB-h\fP Display some help. .TP .B \fB-V\fP Display program version and copyright. .SH EXAMPLE Create a mesh of 5x7 elements, along with its geometry: .PP .nf .fam C $ mmk_m2 5 7 -g/tmp/m5x7.xyz /tmp/m5x7.msh .fam T .fi .SH SEE ALSO \fBmord\fP(1), \fBmtst\fP(1), \fBgmk_msh\fP(1). .PP Scotch user's manual. .SH AUTHOR Francois Pellegrini scotch-5.1.12b.dfsg/LICENSE_en.txt0000644000175300017530000000051011145123754016675 0ustar hazelscthazelsctThis copy of the Scotch 5.1 distribution is licensed to you under the terms of the CeCILL-C free/libre software license. A copy of this license is available in subdirectory "doc", in file named "CeCILL-C_V1-en.txt". Please read its terms carefully. Only if you accept them can you use this copy of the Scotch 5.1 distribution. scotch-5.1.12b.dfsg/INSTALL.txt0000644000175300017530000003747111456646670016273 0ustar hazelscthazelsctScotch 5.1 installation instructions ==================================== 1) Mandatory tools ================== In order for you to compile Scotch and/or PT-Scotch, you must have GNU Make, Lex and Yacc installed on your system, as well as an implementation of the MPI message-passing library in the case of PT-Scotch. There is a possibility to install Scotch without having Lex or Yacc, but it may require the tuning of sample Flex and Bison (i.e., the GNU equivalents of Lex and Yacc) outputs created on a Linux system, which may need some tricky work to compile on other systems, because of different C library implementations. To check if GNU Make is installed and is found first, please type: %prompt% make --version It should read: % GNU Make x.xx % Copyright (C) 20xx Free Software Foundation, Inc. etc, etc. Alternatively, if GNU Make is installed but its directory does not appear first in the PATH variable that is searched for executables, you can try to locate it using the which command: %prompt% which make If several occurences of make are found, one might be GNU Make, so try to figure out which of them. To see if lex and yacc are present, type %prompt% which lex %prompt% which yacc (or "bison", the GNU flavor of yacc) If some of these are missing, please: - check your path variable (just in case they are located in some unusual place, such as /usr/local/bin, /opt/bin, /opt/local/bin/, /opt/gnu/bin, etc). Tools such as "which", "locate" or "find" may help you find them; - ask your system administrator (highly recommended); - install a copy of GNU Make of your own (less recommended, please ask your system administrator first). GNU Make is available from the FSF website, at: http://www.gnu.org/software/make/ and http://ftp.gnu.org/pub/gnu/make/ . A GNU version of lex and yacc is also available from the very same FSF website, at: http://www.gnu.org/software/flex/ http://ftp.gnu.org/non-gnu/flex/ http://www.gnu.org/software/bison/ http://ftp.gnu.org/pub/gnu/bison/ ; - use the "last resort" files placed in a directory judiciously called "last_resort", located in subdirectory "src/libscotch". These files are: . parser_ll.c . parser_ly.h . parser_yy.c . They should be copied in the directory where object files are created, and "touch"ed so that their modification date is more recent than the ones of the corresponding "parser_ll.l" and "parser_yy.y" files. Then cross your fingers and hope it compiles properly on your system. Else, you will have to dig in their code to have them compile properly... The Makefile of the libScotch library has been designed so as to copy the last_resort/* files automatically when the lex or yacc tools are not found. In this case, depending on your platform, you may also have to set the "-DSCOTCH_RENAME_PARSER" flag in order for all symbols to be properly redefined (see Section 2.2). 2) Configuration ================ 2.1) Creating the "Makefile.inc" file ------------------------------------- Go to the "src/" directory. Look in the "Make.inc/" subdirectory for a configuration file which matches your system configuration. If there is none, build a proper one in the "Make.inc/" subdirectory, basing on the structure of existing ones. In particular, the Makefile.inc file contains three variables which specify which C compiler to use. Their semantic is as follows: the compiler set in the variable CCS is used to compile the sequential (hence the "S" in "CCS") Scotch distribution. The compiler set in CCP is used for the parallel ("P") PT-Scotch distribution. The compiler set in CCD is used by both to compile the "dummysizes" ("D") executable, as explained below. Create a symbolic link from the configuration file to the current "src/" working directory, renaming it as "Makefile.inc": %prompt% ln -s Make.inc/Makefile.inc.xxxx_xxx_xxx Makefile.inc If symbolic links are not available on your system, make a plain copy of the file to a file named "Makefile.inc" in the current "src/" working directory: %prompt% cp Make.inc/Makefile.inc.xxxx_xxx_xxx Makefile.inc Some additional scripts, designed to ease the installation of Scotch on specific platforms, are also present in subdirectories of the Make.inc directory. This is for instance the case for the mingw32 platform. 2.2) Parser symbol conflicts ---------------------------- Since Scotch uses a parser to analyze its strategy strings, it may happen that the symbols of this parser conflict with the ones of another parser used in a third-party library. All "Makefile.inc.*" platform configuration files which base on flex / bison are already tailored so as to prevent such conflicts. If you use other parsing tools, you may have to provide other options. Another solution is to use the pre-processed parser files of the "src/libscotch/last_resort" subdirectory (corresponding operation instructions are given in Section 1). 2.3) Integer size issues ------------------------ By default, all integers used in Scotch and PT-Scotch are of the "int" C type, corresponding to the "INTEGER" type in Fortran. To coerce the size of the Scotch integer type to 32 or 64 bits, add the INTSIZE32 or INTSIZE64 flags, respectively, to the C compiler flags in the Makefile.inc configuration file. If you do so, make sure to use integer types of equivalent size to declare variables passed to Scotch routines from caller C and Fortran procedures. Also, when running on 32_64-bit architectures, some integer array indices returned by the Fortran interface have to be of a size equivalent to the one of the memory addresses, that is, 64 bits. The size of these variables is determined by the IDXSIZE32 and IDXSIZE64 flags, respectively. When none of them is provided, the size of the indices is assumed to be equivalent to the one of the Scotch integer type. For instance, on a 32-bit architecture, you can use 64-bit integers in Scotch by just setting the "-DINTSIZE64" flag, because addresses will remain on 32 bits. On a 32_64 architecture, you can use either 32-bit or 64-bit integers in Scotch, by setting the "-DINTSIZE32" or "-DINTSIZE64" flags accordingly, but in all cases you must set the "-DIDXSIZE64" flag in order for some of the routines of the Fortran interface to operate properly, because the array indices returned by these routines have to be stored as 64-bit quantities. Of course, on 64-bit architectures, another possibility is to tune your C and Fortran compilers to make them interpret all "int" and "INTEGER" types as 64 bit values. This solution is the simplest one, as there is no need to use any of the aforementioned flags, nor to hard-code type lengths in user's code. Yet, it prevents mixing 32 and 64-bit features, and may create problems when linking PT-Scotch if a corresponding MPI library is not available. Be careful not to mismatch the 32-bit and 64-bit versions of the "scotch.h" and "ptscotch.h" include files that are generated at compile time. When several versions of Scotch are simultaneously present on a system, Make sure to place the corresponding include and library files in separate directories. Since some of their fields are of different sizes, most Scotch data structures have different sizes, depending on integer or pointer sizes. Consequently, compiling a 64-bit executable with the 32-bit version of "scotch.h" may lead to unpredictable behavior because of memory overflow. 2.4) Compression libraries -------------------------- The binaries of the Scotch distribution can handle compressed graphs in input or output. Three compressed graph formats are currently supported: bzip2, gzip and lzma. In order for them to be actually activated, the proper libraries must be available on your system. On a Linux platform, they are called "zlib" for the gzip format, "libbz2" for the bzip2 format, and "liblzma" for the lzma format. Note that it is the "development" version (also called "devel", for short, within package names) of each of these libraries which is required for the compilation to succeed. According to the libraries installed on your system, you may set flags COMMON_FILE_COMPRESS_BZ2, COMMON_FILE_COMPRESS_GZ and/or COMMON_FILE_COMPRESS_LZMA in the CFLAGS variable of your Makefile.inc configuration file, to have these formats and their respective extensions ".bz2", ".gz" and ".lzma", recognized and handled by Scotch. 2.5) Threads issues ------------------- Scotch can also take advantage of Posix threads when they are available. They are used in two places: - to compress and uncompress file data. This can be done either by launching a service thread, or else by creating a separate process by means of a Posix fork() system call. This choice is controlled by the -DCOMMON_PTHREAD flag: if it is set, threads will be used, else fork() calls will be performed. For systems which do not support the fork() system call, such as the MinGW32 platform, one can set the -DCOMMON_STUB_FORK flag, which creates a stub fork() routine which always return an error. Therefore, without both fork() and threads, one must set the COMMON_STUB_FORK flag without setting COMMON_PTHREAD, so that compilation will successfully complete; however, in this case, compressed graphs shall not be handled in practice. - to create distributed graphs in parallel. Since this taks involves concurrent MPI communications, the MPI library must support the MPI_THREAD_MULTIPLE level. The use of threads within Scotch itself is controlled by the SCOTCH_PTHREAD flag, which is completely independent from the COMMON_PTHREAD flag. Any of them can be set without setting the other. Note that if you compile Scotch with the -DSCOTCH_PTHREAD flag, you will have to initialize your communication subsystem by using the MPI_Init_thread() MPI call, not MPI_Init(), and the provided thread support level value returned by the routine must be checked carefully. If you have doubts on the stability of your MPI implementation, it is better not to set -DSCOTCH_PTHREAD. For instance, on Linux platforms, concurrency problems have been experienced with MPICH2 versions prior to 1.0.7 using TCP; consequently, if the MPI implementation on your platform is based on an older MPICH2 version, do not set the SCOTCH_PTHREAD flag. 2.6) Monitoring memory allocation --------------------------------- Some memory allocation information can be aggregated if PT-Scotch is compiled with the -DCOMMON_MEMORY_TRACE flag. If it is the case, the "-va" option will make dgmap, dgord and dgpart output the minimum, maximum and average peak amount of memory used over all processors. 2.7) Deterministic behavior --------------------------- To ease the tracking down of bugs, it is possible to coerce PT-Scotch to have a deterministic behavior by setting the -DSCOTCH_DETERMINISTIC flag. This option may have a small impact on performance, since some asynchronous messages are received in a fixed order rather than being processed on a first-come first-serve basis. It will also impact the results, since the order in which messages are received is significant to some key algorithms such as the parallel coarsening phase. Setting this flag is also equivalent to setting the -DCOMMON_RANDOM_FIXED_SEED flag in the sequential routines. 2.8) Point-to-point or collective communications ------------------------------------------------ Since distributed graph vertices can have any initial distribution across processes, communication rounds are likely to involve all of the processes in an almost all-to-all scheme. In order to speed-up running time, most of these communications are performed by means of asynchronous sends and receives, which allows computations to overlap with communications. However, for large numbers of processes, this can lead to the saturation of the communication network of the target parallel machine. To avoid this, communication consuming routines also have a collective communication based version. The use of this version is enabled by default, as it greatly improves scalability for large numbers of processors. To disable it, set the -DSCOTCH_PTOP flag at compile time. 2.9) MeTiS compatibility library -------------------------------- In order to ease the adoption of Scotch/PT-Scotch by people who already developed code based on the MeTiS/ParMeTiS interface, a MeTiS compatibility library is included in the Scotch package. It provides stubs for the graph partitioning and ordering routines of MeTiS/ParMeTiS, but not for the service routines that are comprised in this package. Consequently, for people willing to use both libraries, that is, experiment with the graph partitioning features of Scotch while using the service routines of the genuine MeTiS package, special measures have to be taken. A first solution can be to coerce the linker to pick partitioning routines from the libscotch, and service routines from the libmetis. This can be done by placing the library names in this order as arguments to the linker command. Yet, some linkers may still report an error, as some symbols are multiply defined. Alternately, the names of the compatibility routines can be changed so as to avoid conflicts. When the -DSCOTCH_METIS_PREFIX flag is set at compile time, all Scotch versions of the MeTiS routines are prefixed with "SCOTCH_". Of course, this will require an equivalent change in the user's application code. 3) Compilation ============== Once you have performed the configuration of the "Makefile.inc" file, compile the Scotch distribution by typing "make scotch", or just "make", in the current "src/" working directory. To compile the PT-Scotch distribution, type "make ptscotch" in the same "src/" directory. This can be done in any order. The most common problem you may encounter when trying to compile PT-Scotch on a new platform relates to the "dummysizes" executable. The purpose of this program is to determine, on the target platform, the size of the opaque data structures of Scotch, and it has to be compiled and run before any library function can be compiled. In the parallel case, it has to take into account the sizes of some MPI data structures, such as MPI_Comm, and the most common way to have access to this information is to use some flavor of MPI-aware compilers such as "mpicc" which automatically refer to "mpi.h". Yet, on some platforms, programs compiled for parallel execution cannot be run interactively. Moreover, "dummysizes" itself does not contain any MPI calls, as it just wants to know the sizes of the data structures, and the communication susbystem of the platform may not want to run it. In any of these cases, compilation will break. It is possible to solve this problem by specifying, in the CCD variable of "Makefile.inc", how to compile "dummysizes" sequentially but with knowledge of the location of the "mpi.h" include file, for instance with the following line: CCD = my_sequential_cc -I/path/to/my/mpi/implementation/include/dir/ If no error occurs, all of the relevant header, library and executable files will be created and copied to the "../include/", "../lib/" and "../bin/" directories, relatively to your current "src/" working directory. Since headers, libraries and binaries of Scotch and PT-Scotch can coexist in these directories, you can compile both in sequence, in any order. Because Scotch and PT-Scotch share some of their sources, with distinct data structures, both must be fully compiled from scratch. This is why you may see the same files be compiled twice, and why all object files are cleaned before any compilation process. Further typing "make install" will perform a GNU-like installation, with header, library, binary and man files copied to the "include", "lib", "bin" and "man" subdirectories of the path specified in the "prefix" variable, which is set by default to "/usr/local". 4) Documentation and use ======================== The Scotch and PT-Scotch user's manuals are available in the "doc/" directory. They describe how to use the libscotch and ptlibscotch libraries, as well as the standalone programs of the Scotch and PT-Scotch distributions.