pax_global_header00006660000000000000000000000064133031546320014512gustar00rootroot0000000000000052 comment=614ec6f326c15a3d00bed3069b454f03351fe1fe ExaML-3.0.21/000077500000000000000000000000001330315463200125435ustar00rootroot00000000000000ExaML-3.0.21/.gitignore000066400000000000000000000001351330315463200145320ustar00rootroot00000000000000*.o parser/parser parser/parse-examl examl-KNL examl-MIC examl-AVX examl-OMP-AVX examl-OMP ExaML-3.0.21/README.md000066400000000000000000000022321330315463200140210ustar00rootroot00000000000000ExaML ===== Exascale Maximum Likelihood (ExaML) code for phylogenetic inference using MPI. This code implements the popular RAxML search algorithm for maximum likelihood based inference of phylogenetic trees. It uses a radically new MPI parallelization approach that yields improved parallel efficiency, in particular on partitioned multi-gene or whole-genome datasets. When using ExaML please cite the following paper: Alexey M. Kozlov, Andre J. Aberer, Alexandros Stamatakis: "ExaML Version 3: A Tool for Phylogenomic Analyses on Supercomputers." Bioinformatics (2015) 31 (15): 2577-2579. It is up to 4 times faster than RAxML-Light [1]. As RAxML-Light, ExaML also implements checkpointing, SSE3, AVX vectorization and memory saving techniques. [1] A. Stamatakis, A.J. Aberer, C. Goll, S.A. Smith, S.A. Berger, F. Izquierdo-Carrasco: "RAxML-Light: A Tool for computing TeraByte Phylogenies", Bioinformatics 2012; doi: 10.1093/bioinformatics/bts309. Intel Xeon Phi -------------- For details on running ExaML on Intel Xeon Phi, please refer to: - Knights Landing: [README_KNL.txt](README_KNL.txt) - Knights Corner: [README_MIC.txt](README_MIC.txt) ExaML-3.0.21/README_KNL.txt000066400000000000000000000057571330315463200147630ustar00rootroot00000000000000Using ExaML on the Intel Xeon Phi (Knights Landing) coprocessors Compiling under Linux --------------------- Please set your MPI/MIC environment (ask your sysadmin if unsure) and then run: cd examl make -f Makefile.KNL.icc This will create an executable named examl-KNL. Running ---------------------- 1. Use parse-examl to generate a binary alignment file as usual 2. You can run examl-KNL in OpenMP-only, MPI-only or in hybrid OpenMP/MPI mode (s. sample commands below). Unlike with KNC, I didn't notice any significant performance differences between those three configurations, so just choose whatever is easier/more convenient: OpenMP: OMP_NUM_THREADS=128 ./examl-KNL -s myTest.binary -m GAMMA -t myStart.tre -n myTest MPI: mpirun -n 128 -env OMP_NUM_THREADS 1 ./examl-KNL -s myTest.binary -m GAMMA -t myStart.tre -n myTest Hybrid: mpirun -n 8 -env OMP_NUM_THREADS 16 ./examl-KNL -s myTest.binary -m GAMMA -t myStart.tre -n myTest NOTE: although KNL has 4 logical threads/core, it usually doesn't make sense to use more then 2 threads/core with ExaML (since ExaML doesn't benefit for hyper-threading). Furthermore, please consider the general recommendations regarding number of alignment patterns per core given in the ExaML manual. 3. IMPORTANT: KNL on-card memory can be configured in one of two modes: "Flat" or "Cache". You should find out which one is set on you card(s), since it has important performance implications. - in "Cache" mode, no - in "Flat" mode, you should use numactl to explicitly bind ExaML process to the fast memory NUMA domain: numactl --membind=1 mpirun -n 128 -env OMP_NUM_THREADS 1 ./examl-KNL -s myTest.binary -m GAMMA -t myStart.tre -n myTest Obviously, it is not possible if memory requirements for your analysis exceed the on-card memory size (typically 16GB). In this case, you should either switch into "Cache" mode, or let ExaML run in the (slow) main memory. The latter option will typically induce a huge performance penalty (up to 5x), and thus is not recommended. Limitations & caveats --------------------- 1. Supported on the MIC: + DNA and AA alignments + GAMMA model of rate heterogeneity + multiple partitions + all AA substitution matrices supported by ExaML, including LG4 2. Currently NOT supported: - binary and generic multi-state alignments - PSR model - memory saving for gappy alignments (-S option) 3. Performance ExaML-MIC performs best on alignments with large number of sites and few taxa. The latter is due to the limited on-card memory of the MICs (s. above), so you might need to use multiple cards if the number of taxa is large. For details, please refer to: http://www.hicomb.org/papers/HICOMB2014-04.pdf and https://doi.org/10.1093/bioinformatics/btv184 Contact & Support -------------------- Please use RAxML google group to ask questions: https://groups.google.com/forum/?hl=en#!forum/raxml ExaML-3.0.21/README_MIC.txt000066400000000000000000000055211330315463200147340ustar00rootroot00000000000000Using ExaML on the Intel MIC/Intel Xeon Phi coprocessors Compiling under Linux --------------------- Please set your MPI/MIC environment (ask your sysadmin if unsure) and then run: make -f Makefile.AVX.gcc make -f Makefile.MIC.icc clean make -f Makefile.MIC.icc This will create two executables for both host(=CPU) and MIC - they will be named examl-AVX and examl-MIC, respectively. Running ---------------------- 1. Use parse-examl to generate a binary alignment file as usual. 2. You might want to allocate MPI ranks on both host CPUs and MICs (hybrid mode) or just on the MICs, depending on your configuration. Sample command line for running ExaML in hybrid mode (16 CPU core + 2 MIC cards): mpiexec -host myhost-ib -n 16 /scratch/examl-AVX -n mictest -s /scratch/mictest.binary -t /scratch/start.tre -m GAMMA -w /scratch : \ -host myhost-mic0 -n 30 -env OMP_NUM_THREADS 4 -env KMP_AFFINITY "granularity=fine,balanced" /scratch/examl-MIC -n mictest \ -s /scratch/mictest.binary -t /scratch/start.tre -m GAMMA -w /scratch : \ -host myhost-mic1 -n 30 -env OMP_NUM_THREADS 4 -env KMP_AFFINITY "granularity=fine,balanced" /scratch/examl-MIC -n mictest \ -s /scratch/mictest.binary -t /scratch/start.tre -m GAMMA -w /scratch Here, we use 1 MPI rank per core on the host CPUs. On each MIC, we start 30 ranks x 4 OpenMP threads, which gives 120 threads in total or 2 threads per MIC core. Changing the ratio of CPU:MIC ranks allows to fine-tune load balance for the specific hardware configuration at hand. Limitations & caveats --------------------- 1. Supported on the MIC: + DNA and AA alignments + GAMMA model of rate heterogeneity + multiple partitions + all AA substitution matrices supported by ExaML, including LG4 2. Currently NOT supported: - binary and generic multi-state alignments - PSR model - memory saving for gappy alignments (-S option) 3. Memory Compared to traditional CPUs, MIC cards have significantly lower memory-per-core value, which poses a problem for memory-intensive ML computations. Thus you should plan carefully and split your run over multiple cards, if needed. To estimate memory requirements for your dataset, you can use the web-calculator here: http://sco.h-its.org/exelixis/web/software/raxml/index.html#memcalc A similar tool tailored for MICs is coming soon, stay tuned :) 4. Performance ExaML-MIC performs best on alignments with large number of sites and few taxa. The latter is due to the limited on-card memory of the MICs (s. above), so you might need to use multiple cards if the number of taxa is large. For details, please refer to: http://www.hicomb.org/papers/HICOMB2014-04.pdf Contact & Support -------------------- Please use RAxML google group to ask questions: https://groups.google.com/forum/?hl=en#!forum/raxml ExaML-3.0.21/codeDocumentation/000077500000000000000000000000001330315463200162075ustar00rootroot00000000000000ExaML-3.0.21/codeDocumentation/PSR.txt000066400000000000000000000002551330315463200174160ustar00rootroot00000000000000To disable per-site rate category scaling in ExaML it suffices to comment out the function invocations for: updatePerSiteRates() and checkPerSiteRates() in the source code. ExaML-3.0.21/codeDocumentation/startupIllustration.pdf000066400000000000000000002236411330315463200230260ustar00rootroot00000000000000%PDF-1.5 % 6 0 obj << /Filter /FlateDecode /Length 223 >> stream x]j0 ~ Cqslrfhd8d7t0-$}?Yڿ2Ov >c\a)j.{Uo;öd{Q- ^\@C4:> stream xTkTT~ wED!d :Ft$UmiQƑX-G)Ơh0Uڈ# 6M&M ibh[kGLWZ߮sϽۏo?94"ZK#eqbÖ. `7@S徛!듲ysZT"ce"m.|w٢%ˣCt $8vќFeF)*F[?:*#4jdg޾XYniQjnPSyҩKCz8STgjUH}VW+-#S-nDs&=H=FTb,{sya5^%MG2_6ezl]IIj$k4L6|v%YӲӌVB/*lm5Jn5LhieځeS |hGP@X$GDrTk"CWXv4SHW:}AVAT1h1>6:hQet%F]!GH]6 Ua\DyΠMtAN %VN+j}HRMf;I:کuJ]tVP_)g)KHo Wo*TC5 =J\H--5MD:G;]lF:o`1>4yc5JAE|,mv}Q5E:WG*RQZf1ZJm2uXLkTMTlZ jO(Ajz-#uau@ qYzMn Qբ !3M/JԌ)5%DB)-]]ӊ$5; Iy6#}Ҵ}:$OdE |\^.4 ֏U2. .0̸8 cG^\8_.q^ s0e,O3^э?{.᷌b~ƫ%pkƯ2:xzmƛuNfO1Qo0^g㧌#6a'ZW{T+M064^Cž.zpJ/3Bxсy ~kr}4W00~ns9/v9#?Ť12v>v2Ŏj۷j{"g[vc8mbFAOohSO364 mPk4zF=ʨ.W|܁eXGK¨ 2aT0a,Lŷ jAf`c(ee0b_c.Q(D5ˋ3%\ƣ@3UA/pcz~51͆2N1TD3?T=01ٮ&`xƃA "񀞡# c' 1.ucrrFU+ɸo[ƈln"ۆa}ewMyCmiSCȴapFl"#^ Q8z0zT׃{<6uO<6HcT3Յ?WJG}}IaEDF/?zJz2)! 7%.Sju¬A=6Ab#D4#J̢V7,~4C`JπfZ[ N࿎İ endstream endobj 8 0 obj << /FontFamily (DejaVu Sans) /StemV 80 /ItalicAngle 0 /Type /FontDescriptor /FontName /TUWOJX+DejaVuSans /Ascent 928 /Flags 4 /FontFile2 9 0 R /FontBBox [-1020 -415 1680 1166] /CapHeight 1166 /Descent -235 /StemH 80 >> endobj 7 0 obj << /CIDSystemInfo << /Ordering (Identity) /Registry (Adobe) /Supplement 0 >> /Subtype /CIDFontType2 /Type /Font /W [0 [600 629]] /FontDescriptor 8 0 R /BaseFont /TUWOJX+DejaVuSans >> endobj 5 0 obj << /Encoding /Identity-H /ToUnicode 6 0 R /Subtype /Type0 /Type /Font /DescendantFonts [7 0 R] /BaseFont /TUWOJX+DejaVuSans >> endobj 11 0 obj << /Filter /FlateDecode /Length 440 >> stream x]Sn0+xLd ŇE|D5%_N93Ųy::y͟#mzs*tY%4g3:qxVTv|Ӣ^7e+7}3-#PZwIT|woOGlΔ7ݪ^' gҍʾ"%e"!Hm4H)ETjEQp]*bq#pشRw1'6=s:p:pC < {d3'hQZ| }p`A#xzЇN6^K#+EfteeF endstream endobj 13 0 obj << /Length1 11596 /Filter /FlateDecode /Length 8347 >> stream xzy|U9S]KoN,N[bBamx!"DA!A!b@61 1^`HN[ w?rj9Uu{z>oU%hd!6%iO#q$u'?6izѹKxO) hxL k !)x<'|v(f4ȣE'oICR9 qER ]#a7a36bn6M׬kl$:/CviY5U8Cw:F VF=0G>nx{rz#*v h܌#Zũ}~5*s\;.*"(Ӗd˶ ~WkӴRBK#hέ]wDQdNu5H%4Y3?OSګ-YO:;8F7M k9z-מ0&AdAO uQ^z4X#QWF룭yF!-jqrD_b]n[n_X *ʺ˾Qm|d\4Z)ni6>徔f4KZ3b53*+Q|>H|oy,F4GM$S &a" SJ5]Qev6ǿ\d7z7dPDI4ܑ=qm$eg)Z, yй-|cYs6E/}̾%2]Š`2Pu{vP^koG׺j+c}I(dr Eh7\!u ړ!N8)N KJYO5ؤ!Ѵ/FںlC]zpc]Љvgd]\Y[dD2Ѧ26'<ϧ\"wkjdO ? `7ARdG\k7K&+$ m':`NM7L p^k+3232?lKk:=uI\i|iB4qIթSnm|~ /LX_=}F8i7:q5'+1;DFl"w?Soݲ'oQuFM9C>BBxLcs2^Bo0\Q ϧ-Φz 1rs[Y)~ie(دb#qbX=S{Zu?ch;D="ǷOH%&.ՖKKm.i%Id`;8 ^IJ855=oCi%i VU]OF:A=!2B8&xqfq3vʌ#_|ھ[-<:q)^G MwX|つp$/ڴ;>bLWŐ@âX);H P¨9/ 1T[CZ63TfخϬ7ZcDA_5cr?.EJ)`iCQ9dfaOBg|R/}薈DpMg{M SXOl9tM|NjUvȴua!+6~?km wX.e6!dA=y*=0uri #,ՓCşkN.kJ?x{U-..b#݂E4f!If7#ou)!SST{"6G9o~~ Kik=. ]ㅓ9#:9jL-k^CA`å 9j/rۺF Hڦ RSc-0[ݾ3V8 =StUp0QxZV.QLJa{}I^kZYڔ:q(&.K`L3jb✙Y䢥vl:)%ɽi.qYekڭ[זoq{taSӇH_p؅ ߉/ŷqovp&O=(PF{LAGoͿ5šo|[Km.a' fS@^`{Yy;]MDcQS^Gjs"}7`U5%q9xdI#ܤ4nzpFzS#ctIuƱ_ݲ%ƙ`bQ}~s{nO}EǬ:zg߯{lf֔]u缾6\5 鈮ԺmhӺy_ndJ] wUǎ;1 ۩H م\ʳ*$3H@P0H,K),QUOM #u [ - %LUCcAt|?+Os%Yn7ΐ4 WI'0Wԋ[ Ǝ[ n,ĂYI;^SOSׅM5yf%fl:7eTLۯ_^OMe!? i3v}lgS:F36*&хFmrT$~e2+6+cudMTocQ$sV~J85jQN̮$-ϊ{2vY]ȷ(v;3LCw=sFS*y5[Oē++'kwy-^w ;KHi?^s5~w:OG@BZzo`¯Ada<76+Ӿ_XuF_yrΞ<%gieO?>?!]G/CZJ eZ*0Z5i4t] | xA%+V]S3@i!69irs']jNնV6ONi).[]n-fiPi(h-O{\zjsi./zEV1qI\St7VH}Oukh ,,%UM$k.%ךa$ A, A{>))#Qh}2)Si0MiՉ",2ΕϓKyeZkRi/#Zi ld/-`zu}F*v.^85;z=8>sMQ&4iLח}F|zo?*`YnUBEӴ0? VNku$  54MżB$l kr,!k¬~fϟ-Nvǀš8TIHnK"XͯudkHb\mȲH[-E2CAJ{+cqe: ]%pX^fVEBDߙ.%(AoRfcGDi-6PlJ r^Gҷ@k<<[~⼖a3u o'`|t)LĐ/4kH}qŅ &.jMֻS@;u hzf{ӼY]Cc_\Gr~}|c2^"FW՝泽T `8{dh,(Zr{%[,>MoZ!4~}~[st=}>Nş_ćҚQl"Џ{٪b*`\Š̈\u۞PIlk^/3X+ iLFnXVʕ'JxEPN8 !"1 2" @bIQRT|͑AT>OE,YYXDvH.D$ [18%M_"W?-ҒI?YuPmŋ`JkC(/5njkjZ`Mɽ].NRϚN 季]Oئ;ZB))^}WE ]bW/*jF:Y銕KBѧӷٻ|ghbm`ܠ=UaN.ZxeQ שEW ]x]̣KȥWs=(Oyq B7ӇTyr`NBiu(>u0#;;XoA1Q$Iw, v eL,S$b|-kMu3H39#vZ9z|Q+GG_1e77>>/[eO3p2y+ .s0Pdx#%7jpdb(Wq%O1$`0X +--`CKX~;ɢYR/֋wt4 qd\(=l:[YBENNy*KaGi>yDce(P<&m<:NstNlb|<|Ͻ}_(qn&\*[ڋ#H:$@:Hu69?D,11mFl8<C#7XK*YF|&5$.d#݆GX=k*}d 5ѓJuƺm:9W:da-!DnQd?K4ׂa`}]aI76fl&͂-| ߆%ޗ\{H Hf-dA"2°TbMHT,݇5i"<Qz;HsE`q$?0J*@%ǰx2~jDHǾ&qЙ -qQJݖ$6mאJr ft KbR2l{y\Hͥl]zӝ[omo/݇#*$uX8t ,GKͳqeK5!EM^1CPAʰxnGs#\FWI?0gZ!6'foYwVK{KW~_Mms5--yc13Wc!T@; n8ՁnX53;_<٤:LB (ݯm?>IPBpz7=C$ #?>nDkϿ Dh!w$Dk!wbv.ǬA֑,2V3IRHKnMxFl';CN0r۞Z(J6xb]^m`9uƧx]crm '{,2rB+m d,7q.˰|CU'DC0hǂ:MbkOϰ , /Dz$^XvF4 RI,%"}Ġ 1g aG) e$wz*0 Tdn G|#EH -4̄TvA op=?{7^ Z ]#o_gK# ^ _}οj/  *O]pmDx 8;,O>pd{7,_nXC)VR,1/2b xFB%-O/X`/Q^y c0[YlD#h<.DiF?>m$<"`x LP `I&Fx < `qc5>jpߟ cƞGQI|d4{E{[#~# g 6ɇE8!6,`P KyF6= w/^=mW=mC@ܼ{#tqnnyuY6ȼK!#]6HסKgwqBg:eBޱ:x}jRy:$ H8D qgX`_#/xD@z*J@$.%PwF?p.Gج&W[#A9AeTNZ\ DKVю/m_ endstream endobj 12 0 obj << /FontFamily (DejaVu Sans) /StemV 80 /ItalicAngle 0 /Type /FontDescriptor /FontName /IZBWOQ+DejaVuSans /Ascent 928 /Flags 32 /FontFile2 13 0 R /FontBBox [-1020 -415 1680 1166] /CapHeight 1166 /Descent -235 /StemH 80 >> endobj 10 0 obj << /Encoding /WinAnsiEncoding /ToUnicode 11 0 R /Widths [317 0 0 0 0 0 0 0 390 390 0 0 317 0 317 0 0 636 636 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 686 698 0 0 575 774 0 0 0 0 0 862 748 787 603 0 694 634 610 0 684 0 0 0 0 390 0 390 0 500 0 612 634 549 634 615 352 634 633 277 0 0 277 974 633 611 634 634 411 520 392 633 0 817 591 591 524 636 0 636] /Subtype /TrueType /Type /Font /FirstChar 32 /LastChar 125 /FontDescriptor 12 0 R /BaseFont /IZBWOQ+DejaVuSans >> endobj 4 0 obj << /Font << /f-0-1 5 0 R /f-0-0 10 0 R >> /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 14 0 obj << /Filter /FlateDecode /Length 838 >> stream xU]o6},/ { ۄ8AĴ–TFﻤbva /=ӌgd=^W3~*(GA[ W93Z͊} eqq'||F.M ow~fZr#FT$œIRdu$m[n(KWɯ9.d H,碸LTghK۪ 8K) cKPEsEvDu ĆeE־M2nP V$\*dJj&3R$FntUáTj>%9Jw"HM))MhDEwK?mo"mI7B|R?ʖR UB$1u;A(mMuЂ*q`H4~X᥂r'0m,wv: ҍ>0\Rlۢ>.}]ׅ5!2ޏe{]4 a#{tž Lסy:2lH -%/9|o!ꯥqC4mMxm[)_](k? wK ܆K] X+G':v:gcޜys@NJ%oOGd:ÍJleؐ!`q=Lz` v>4hvءGֹTWpz~AVZ¦!/j+_rpD+ 0~BF` K)*KNJS[4e>E3S endstream endobj 3 0 obj << /Resources 4 0 R /Type /Page /Parent 1 0 R /Contents 14 0 R /MediaBox [0 0 1619.052002 816.623413] /Group << /CS /DeviceRGB /I true /Type /Group /S /Transparency >> >> endobj 19 0 obj << /Filter /FlateDecode /Length 223 >> stream x]j0 ~ Cqslrfhd8d7t0-$}?Yڿ2Ov >c\a)j.{Uo;öd{Q- ^\@C4:> stream xTkTT~ wED!d :Ft$UmiQƑX-G)Ơh0Uڈ# 6M&M ibh[kGLWZ߮sϽۏo?94"ZK#eqbÖ. `7@S徛!듲ysZT"ce"m.|w٢%ˣCt $8vќFeF)*F[?:*#4jdg޾XYniQjnPSyҩKCz8STgjUH}VW+-#S-nDs&=H=FTb,{sya5^%MG2_6ezl]IIj$k4L6|v%YӲӌVB/*lm5Jn5LhieځeS |hGP@X$GDrTk"CWXv4SHW:}AVAT1h1>6:hQet%F]!GH]6 Ua\DyΠMtAN %VN+j}HRMf;I:کuJ]tVP_)g)KHo Wo*TC5 =J\H--5MD:G;]lF:o`1>4yc5JAE|,mv}Q5E:WG*RQZf1ZJm2uXLkTMTlZ jO(Ajz-#uau@ qYzMn Qբ !3M/JԌ)5%DB)-]]ӊ$5; Iy6#}Ҵ}:$OdE |\^.4 ֏U2. .0̸8 cG^\8_.q^ s0e,O3^э?{.᷌b~ƫ%pkƯ2:xzmƛuNfO1Qo0^g㧌#6a'ZW{T+M064^Cž.zpJ/3Bxсy ~kr}4W00~ns9/v9#?Ť12v>v2Ŏj۷j{"g[vc8mbFAOohSO364 mPk4zF=ʨ.W|܁eXGK¨ 2aT0a,Lŷ jAf`c(ee0b_c.Q(D5ˋ3%\ƣ@3UA/pcz~51͆2N1TD3?T=01ٮ&`xƃA "񀞡# c' 1.ucrrFU+ɸo[ƈln"ۆa}ewMyCmiSCȴapFl"#^ Q8z0zT׃{<6uO<6HcT3Յ?WJG}}IaEDF/?zJz2)! 7%.Sju¬A=6Ab#D4#J̢V7,~4C`JπfZ[ N࿎İ endstream endobj 21 0 obj << /FontFamily (DejaVu Sans) /StemV 80 /ItalicAngle 0 /Type /FontDescriptor /FontName /TUWOJX+DejaVuSans /Ascent 928 /Flags 4 /FontFile2 22 0 R /FontBBox [-1020 -415 1680 1166] /CapHeight 1166 /Descent -235 /StemH 80 >> endobj 20 0 obj << /CIDSystemInfo << /Ordering (Identity) /Registry (Adobe) /Supplement 0 >> /Subtype /CIDFontType2 /Type /Font /W [0 [600 629]] /FontDescriptor 21 0 R /BaseFont /TUWOJX+DejaVuSans >> endobj 18 0 obj << /Encoding /Identity-H /ToUnicode 19 0 R /Subtype /Type0 /Type /Font /DescendantFonts [20 0 R] /BaseFont /TUWOJX+DejaVuSans >> endobj 24 0 obj << /Filter /FlateDecode /Length 458 >> stream x]Sn0+xLd ŇA~D\1%_9I3y>,H ]kG:YNsOê*>.yZT~l~eoJk.ʜOu}3Mj׉jsX gҍ~c}2VFwDuT|"շ^ӴWӗo.o(R۶.ץb l+8NJM+.w'} gOĜ<0ǃy'TcOÞ g |⸖ >8@~<2=;>.uYk^cCN9;d8>Nߺ> stream xz{|EUyd&! aBĄsp( "* @ , yYL0*jˊ(3bv/jH*Lѻ{S:u!eS|4B&M[̌#$%*{ f{[Tt⑧CNӧҮk%˝je%!i^4~px piS,, pF9NG+vi"D  ^$v* ܠ(adԝןό0@TIR|->һez vGY+vJ>~roһox{M>V˞?;HeaN`?1iV Us{CuguYf^^|-L%>ԇvc&daZ,W+v5+(]‹Ē9NGm·;}Cھ6.4FF1kH:Wp~ +2iW!!^ 67 VtU3 [W}6MgپٱsQj_RzCnO&)ڝKNO4Mklm5NvWOqKWڋ4m9vxqHǗF52Ж2|Q fՊzKŨnHm05:ш9(iW%I6FItp4#4ly349uW7] }Wdg&d&f32;H A0)1?>?!?1ߟ1?uN҄RiʎR+SR^m{텂AҜ9ss%,K\_a2 pўh`I9!0Rs,d^>5jW:|;Iλx,GMy}+'=%w~ 5v森 EF#W{vy\7CTf⾖L]LD+%FQ,qKbOetCy(i$g6:XСM #5U~GM|w~鯷˷e %K{08e@ 'UJZz8^c4CYg^A7=QyfNm“VuK?_]=ߦlo;_͊oT*,~Gʫej Э}6qn[Жo+ͱi>&11an$$rYEp*ߚ5& tNЍX9UqHgwS+yy(_s͒2XbQCTĸqzg@jc1 ?cw6Ddx3|]";'tNL%uJ]2VW9<2vp\hXԌi-KېV֐|.1&PWvN83hwjTV$<>zߤ5knP}E,_;`Wt8ܹرI.[l?jNG\ʗ80dT5u~%*Ҩ*C=+&&ͅYͷcMKٱ`_GAKhdb0N]ۯRũ,B%MhqE<~v wuXd5!dE&=*}0يuJ% 1F{ick*1]䛚+?d tC /BOXniN *q{N-lE!݌H҆\«5/[ Z Y,zfTlǮ^{6XN]iK#b"HD^VN4q$(4+MWPY4dX׈`51AlM,Qym6&i&.h -]tPp0U&p:N1jntj fj)k1MQsػFUHz·YzFA~ma“:z )z?~>ߩNЋt1_>|'ߢ>oG}VtBt#|g1 El] 7̓k32#`bix:M;{OD=6wv,%f ݭV9w\v82il,F4/.E|"MirZg#YKˬx9&_s!vnRn{5$"1$q6 h!]%V |r )<&$m۶NoߠTܐ(]?}a7& zĀRgV4+b>g-|,?bg'ۏ#nX8}S`6x&\N }xgUDd jRSkm5WbSfx٫ 42&ׯ?x=iW7l-+oxSلu?<>:vMh!\w?m\hA8/9*~?~'!`B%gQTڴD%H"5,V_N0BHЋz.&L2EN %)ґMyë7^8pm, "^͝uCG!Q=2;$݄\2_([eb+c-jmu({JBzu/:bӣgrvʸ]^WbAli 1^/ Xl?Oo^<@zm)zn=,\|~W;hyӍ2ኁޒ3'^~G;Y,JھN|4>+ Ji;YBk~J<)=ܡds`Oyghg75۱Ry_s2wOWĴ__<,>={^|xC~,nYqזn+]̿o]`/~!CW?N]ܡܡkclcq4RHY0Y)ƽd>]ĖBT,VJjP[d+ RZ9-t3SIIųt%{nb_==;E5g{w" cO }Ugiz\^ t1Vz?}n>?)??5cqn"PG96M*Xa‰-w^IJ 4 C 1GVV&-"GE$Cwj|f?C]{:n-k#_x]6%M+'˟`3hI5‡^wZ+1% k}(/5 Œrϣ\>44(3.RDuG}xxR8I=o)!2f>aO0WUC)9n}ge-M߼qfi0~qْ=FWK_;g#kvyg|/8]D[J7ZѮl;}}vl԰9zI6Stʘ/arP[.jRV4]r)T}*Mr1gr>C=vL;RW}ch6Cu 5!#O\:je")0 [V=(z{4A/3_EL[P@D^`rw{^4lY&v %w15^uRLӬ9T Bj"(W4f])k[S xn5pk,tm<+bjb9[#kXآ=<6aSRygA (|X`zշ@7s-dZSiQ5,Maۆ5i&z!58^w Lm%e:Sbee &Ÿ!I sc4~8ŊٮbFiVG6Q 4H~-ЛgjC 0ÕfӉ0kE΄^1C)擇h1cZ$+XZT m'bONKPRǖ77A x?%n;plN6}+xe'I'BT[ZkSH"J" !f[4hÏ% s_";tƘhG-H6 FKg9url{bM%;JVX&=CװnX4RrpBGn-(NǒcF<#͏;x5ϑ|? < xK<^& Nr±3&(&%w`iqlm6?VJw ȓp^q!'+`,+A͊P9|lj@u"Y:֡> %jū&c/7iT70>+y2LJa۬w"nmVa^@y:~y݁#*"XV8>t%AI:g؂GMl!&GI7 eRhJOw|s;\Fױs0=_C][UAKjxفtX`DaU '&uK[W*"uKK+&V*hU<鿺i' nmuH`3O+!CNDGT?~,c齻;ubzWI&|oaaǃqxiݤa#G}/ q|owJǑ+]%m]%ex܆X7:I?|vWx *m~',?hz(@הXGUb[Bơ ^G#?:6 | x8<7b9DHQ6vJB|VyW!G^͖[nHh! QwK |ح; * ooH7|5J2 2F|QW+c2Y|* ?q\. !>Rp~+>X?Hx_{U3 ⬄3 n#JS"N"7$.ᤄ$* ^p„UQ#EO/ /-'[x>$XG%P% y': 8؏Bo}W.x6 v9BG*+`O OaSb{!<-mnتÓT8 (Ǘ+`&69FظeQ†b˰a/[e,`wk%<a>v+Ym5^Xm@)V*Ԫ4wV,7 MxT2 %-,]*t),)>QIX脇@jy`#m9fKx@}I[ ́b)aR/$LP(aF%%at1&pgd3 K=c}0Řpn!no%[+7&a%a#b;`0KĺA0eu% пGB.}8D` 8< zzEF=c\7#u!$b@f!2a@n6 l5 һDz!tI.H@Ԁ|+ %` $!YBG$8v@p/W!8%8!O#&A4 Bj݂kAbTs ZM W/  endstream endobj 25 0 obj << /FontFamily (DejaVu Sans) /StemV 80 /ItalicAngle 0 /Type /FontDescriptor /FontName /KDVMDP+DejaVuSans /Ascent 928 /Flags 32 /FontFile2 26 0 R /FontBBox [-1020 -415 1680 1166] /CapHeight 1166 /Descent -235 /StemH 80 >> endobj 23 0 obj << /Encoding /WinAnsiEncoding /ToUnicode 24 0 R /Widths [317 0 0 0 0 0 0 0 390 390 500 0 317 0 317 0 0 636 636 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 686 698 0 0 575 774 0 294 0 0 0 862 748 787 603 0 694 634 610 0 684 0 0 0 0 390 0 390 0 500 0 612 634 549 634 615 352 634 633 277 0 579 277 974 633 611 634 634 411 520 392 633 591 817 591 591 524 636 0 636] /Subtype /TrueType /Type /Font /FirstChar 32 /LastChar 125 /FontDescriptor 25 0 R /BaseFont /KDVMDP+DejaVuSans >> endobj 17 0 obj << /Font << /f-0-1 18 0 R /f-0-0 23 0 R >> /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 27 0 obj << /Filter /FlateDecode /Length 1338 >> stream xWYoF~篘G27{@mis}([$U R-*Ga\.ggv.e^Un S2ᡘ8A&`$h0Ƕ.Mm9?6|VӬzl6mq9-yqiL AhT:7V5MXҧ':K#~qO-f2vT_&$Jx+ďA!ɫNNmu^m*/j;U;mb`7+vS-z:R f7'-HIxl0+^1!7$lCxXF01܈vNڒptjV/'>\V f{5Hܾb)SS,&Jp!q$H86HBaGtP!CC ըi I>ENh2@e# *!kcӎt@QiW {}=M䯇 W9kP Өj]xvqu۬qce/dYal%jp){'Ӈ垬=]`HY=E\Re2~ c=bҼA#&O\mR BcmwMMVOx8mzǓwveQ=3ҀP-Λ(=)7 L5lQ7lۺ1Jc6D(rguRe|x4>+ f95GsR1O:-Ʉ"P&gbfAKdqghu4A3pW'ĹQhFEZBb 6o@/ax!fF0,*e]F;O9 v|ihÇF I3#B$ 'od^Kfr稸Üb(4ry[(ނ0L.yFopĈ:`;zsN!"SqR8lf;g!'#&( endstream endobj 16 0 obj << /Resources 17 0 R /Type /Page /Parent 1 0 R /Contents 27 0 R /MediaBox [0 0 1619.052002 816.623413] /Group << /CS /DeviceRGB /I true /Type /Group /S /Transparency >> >> endobj 32 0 obj << /Filter /FlateDecode /Length 223 >> stream x]j0 ~ Cqslrfhd8d7t0-$}?Yڿ2Ov >c\a)j.{Uo;öd{Q- ^\@C4:> stream xTkTT~ wED!d :Ft$UmiQƑX-G)Ơh0Uڈ# 6M&M ibh[kGLWZ߮sϽۏo?94"ZK#eqbÖ. `7@S徛!듲ysZT"ce"m.|w٢%ˣCt $8vќFeF)*F[?:*#4jdg޾XYniQjnPSyҩKCz8STgjUH}VW+-#S-nDs&=H=FTb,{sya5^%MG2_6ezl]IIj$k4L6|v%YӲӌVB/*lm5Jn5LhieځeS |hGP@X$GDrTk"CWXv4SHW:}AVAT1h1>6:hQet%F]!GH]6 Ua\DyΠMtAN %VN+j}HRMf;I:کuJ]tVP_)g)KHo Wo*TC5 =J\H--5MD:G;]lF:o`1>4yc5JAE|,mv}Q5E:WG*RQZf1ZJm2uXLkTMTlZ jO(Ajz-#uau@ qYzMn Qբ !3M/JԌ)5%DB)-]]ӊ$5; Iy6#}Ҵ}:$OdE |\^.4 ֏U2. .0̸8 cG^\8_.q^ s0e,O3^э?{.᷌b~ƫ%pkƯ2:xzmƛuNfO1Qo0^g㧌#6a'ZW{T+M064^Cž.zpJ/3Bxсy ~kr}4W00~ns9/v9#?Ť12v>v2Ŏj۷j{"g[vc8mbFAOohSO364 mPk4zF=ʨ.W|܁eXGK¨ 2aT0a,Lŷ jAf`c(ee0b_c.Q(D5ˋ3%\ƣ@3UA/pcz~51͆2N1TD3?T=01ٮ&`xƃA "񀞡# c' 1.ucrrFU+ɸo[ƈln"ۆa}ewMyCmiSCȴapFl"#^ Q8z0zT׃{<6uO<6HcT3Յ?WJG}}IaEDF/?zJz2)! 7%.Sju¬A=6Ab#D4#J̢V7,~4C`JπfZ[ N࿎İ endstream endobj 34 0 obj << /FontFamily (DejaVu Sans) /StemV 80 /ItalicAngle 0 /Type /FontDescriptor /FontName /TUWOJX+DejaVuSans /Ascent 928 /Flags 4 /FontFile2 35 0 R /FontBBox [-1020 -415 1680 1166] /CapHeight 1166 /Descent -235 /StemH 80 >> endobj 33 0 obj << /CIDSystemInfo << /Ordering (Identity) /Registry (Adobe) /Supplement 0 >> /Subtype /CIDFontType2 /Type /Font /W [0 [600 629]] /FontDescriptor 34 0 R /BaseFont /TUWOJX+DejaVuSans >> endobj 31 0 obj << /Encoding /Identity-H /ToUnicode 32 0 R /Subtype /Type0 /Type /Font /DescendantFonts [33 0 R] /BaseFont /TUWOJX+DejaVuSans >> endobj 37 0 obj << /Filter /FlateDecode /Length 459 >> stream x]Sn0 +t:0DgPC~"_=$z)~>i3k^73Ns|Y94Κ4ܯU]<.Uי^|3?2SΉ4#u}3ϛi$~՟xH|n%網$}'ٛn˙ cP,U+.KL{cQ\N<bBߋg`N N+ vwoiE›o>!6 8%@';Ї }{=?}hK]zIuuӉZ`ʇO?XXBHz!DI1IOB.\C; ܑ;"$ye!O9לˈٖfxJ) endstream endobj 39 0 obj << /Length1 12400 /Filter /FlateDecode /Length 8907 >> stream xzy|TEUwv:C脰%&$֖}q(ML EM0*jyÈN"ΛRުSB !:YN7uG $cB { IGsonυ..~~J{EsS\Ι7cN__JI)XBim$>l׉rqY&>p!+L1C)fJ1'M!9<%8ߥxAHj.o&O<?,Ԑ} lt}J I˓N=R;*>olNv@sf}f|c=cG.9MZZNS[2O]| h?V7h/JCI9B⢏TĥNia:8M9 M Q/;:a5.>;Z7ZwZmqyޓ͸|T%o{Fhsolno'u #Vs\Hdm>K/s,wlrxtBn8 W17w8kxxW:D;  ;..ً\ųDo=ȳv;]Y$L, aa%l pHHWGnP emzv>o*0i1Uh\k*c}cskVaTط;v\{EŜ1LNڕ,4G9lӘK7{˸ z'o->b8>i3܋֊s ob,)T#&StCXU9nW]WߐmgyG_K}hWfjnI%r/|2C^\vr:ꛑhߥxI w">V>*j>f4k 'b.v Vd3&IJCD1 @fT3nl2f}ڔ(/% !IS]փxig6I)հk:ٝ_9ٳ.ho:X~T>_b _$[U0B[j ;", D# N1S_Q?6X(A}tG}$Dd#Ns}qJ N>PZc8T#T4lY3295] }Wg%f%e%gR:L'`8%ܱ XRб }NIJ`Yʪҫү'R IɅ”9Is,OZ<<mPh=rRr#`d˵p(rC [sTuʞR¸L,dG3ni~hמ~=7ԕAȨpR!Ϻu+x|C;DL%j&+YԁRJRT/5J쥎Rg]jxW TԎ֞|@Ŧ7]y_Ԅ~o lߠ=xi}B'1h} pRiiƎs504%l~C6N%ut️9fT(8  Bm&i,׫W}#EƔ}D5:HXviEC4 >B{`( I"N]Ϳb;vxeWs/<4[wvgpM'v4&'!BIt#)j{Wv5ymsn$l䶀괩ގC;1^BoE+-IG ߗ' $݌nZ_nIDg%&ӛ9srF0#Sj}ھ᱐1EW 7!̌wef,ؐQq5\ꋀc2M>bfqfrXxdkN<~<{OL]nƁ[|<Թq).>Bj+n]ruX`R4L$>Ę'ɀiSm} (TFWPXytu+lgכ1 -b bYFڄPA#,ÊC#qsz;LR2 i!+B^(r9#jIQ 74e.jmZƎ6{>ܴBX2@! M>-NNg16bӄpZ'lpWRv"H6^d¾_XNIDA3ƈgz/hcmuﶂ˛2c^:rU˿CWإlE6NK=Q"X":Eʢ y=qi,+Yb媪ʊ[r˲__ 4D]'(a]_Aډ/{Y,/.mvDffl$CLNeHnq-#NS{Ybju~.UU LUip:MMM v'S,du*4ӆNUbNbQ}|7"W=Momb}!]6o=o}9;JOЁ FaE(̧R˻bؤʖceه}ڼ770 $YabPl5cſHG}E쌱"s4dq0*yd'slUL81O|mx~2b;V5t achbeg?Qy XP xᥧZH˩Obw/fdžES6d&\N}~{Y[ڴԚ:r|ba)UKQ!9+GI,R87KiiKq9ͻwo]#eԃ޺?ݦwɯaߺp᭓.|-?_%&=߭˯1}Crg~8v8,[\G_DoXp_ԦIN lϖ,m{)mJ0yw"{]>C in_!)@}o_]EX?IE ! a RLTyu-H7F+cfx׷5:{[M q߽_}?~Ϟm`o_힓(CB^ |d%m_A>Hϕa|{N~ӚwēxR{ʻC+ƟΎ}MƼBW'̟ӕFBrFf/3`?<,1]pϒOC~$/vyIügʶ|]o[pd/8+CK;t?~ĥ4K?QrKb\Ku Sfbe#3i ]0PjvCTEp@i#6:iZv1Έ:erՎV'۸$en-V+:H6R 1^/gb}1+eE(cVYcu]vipC誡c~"4᳇HtH!Qh Z'=HCSYal a>u%x6DbadXUܦf+PjtRDgY0Yd]̖"L,QJ%R"uV e2F;-t3OVemάt!{. bv@e{v^/Ug={Nwb rMPF~x; *aUWAeӬ(>+Ɉvjgd!H 5u]üj!4@J#j;Z+Us0iTtb4f ӖÖb}9[a[o`CJAYIu6C-D=DC}רUwh),=%KTHn"4~xj$6e=Jdw"۠5e.dqY(J"0y+h~79bs/3zm{j\/#_{6N׻@u hffb}jjڿ4VȘ|&A,L$ Z yWܨKb$s: w5t" gX BRLG1p"!_`*\@w>Fm4="oh z9qOstOwwi8p 8 Vqpм .05́^=#l4I3?J+,rhpePALXL,4HWlijLʣylf|x0ffym2"{\L*Vgc1Եgο:EޡoQҴy|1V7r&-ּVӟclRr*L #KM$1#"VyV&bɂ8b?SIYK E1#uu~~%-RS&:wO>;YGn޸q4ܸ|inyzY͝O{CΣYC*}+>wxӎpp5/f .XL5|SY#?_:K!wȝNmwݧ,~w<֖&`z,J~Ⱥ֍<{ {0{q+xр'xM]_o?ĺIu1P28}(6@$vW Top1J@^ic*r/Ǩ2x)A7ɡ9'z)#P:#pe{=b YH|X,W-JuJ,eO|@ӿ|8UcW:odLanl=l}N=] .nh^qw)kB"ɯETo-Y(uP\&o`xwY=OVwm}h- =Th.!p{'O=xUs!ykYwC2r sBGn-$|"6^/3B>b؃%ddRC/|9PLJp'g`?{)RNvKgRt۰8C6A+;FWsd+p6p\d%cHrX1:o'9N$u(=5-O\d^VBƑ]Jⵥb/7hTW0>x*Gcۭwbnm%VA^Hxm5"( GTLHӿVǼ~=Bu?6,t\!:<]lC&?LH&՜4q>v ҈ma9mm-D%V"|‹ 6ĺJlC|Lyye6N޶Ur|Q-x^jk1qg{yS#?4/wgBq|MYϨTY5!RBt4X@=a =!\K#YABbߘ[T FtDcBQ hGi mE$,A&ANAY:MZOqc&"ŚY},-\CC6wwI !ŷT7_7Ur\E6|~i.თgfLD.fzJ Ce ,OŹepv8|~@| Q$'] g*$qZ©$x'ޖpb)N$P/^p\«^: /I8fBꐨPKF‹/L//./>$^n!8*J8"ᰄj I8T:8X{ā>z_#=v{`=ˆTT#USŽ'b'~D<-v7la-EB*Jؼ)6wMNx6nxIl|lX )P揆`u$<a>|3]c^Xc@Vj2V0J +LxHr -YLF²eJDIHX,aBHx7¼Fs$̖p{SfĬpn(0CBI N;Lp&MŤF~q{6L0{?`,u6/:*F*_J #nEh3Z¨n1*F&:H7pp *ah% 0uaKphK(a@\u~u@ zލ+-zy!/yn5g8 &CdKɀLCd9 Ӏ5 5 ]D"]B!fHAZi.IB.Hqx XɍCH*D$$!~/Cġ$K~IJ<3e*=V8$i{,t7hT|L`R[p`-Hjnu@khѪ ?[Ko_ endstream endobj 38 0 obj << /FontFamily (DejaVu Sans) /StemV 80 /ItalicAngle 0 /Type /FontDescriptor /FontName /CFNXBZ+DejaVuSans /Ascent 928 /Flags 32 /FontFile2 39 0 R /FontBBox [-1020 -415 1680 1166] /CapHeight 1166 /Descent -235 /StemH 80 >> endobj 36 0 obj << /Encoding /WinAnsiEncoding /ToUnicode 37 0 R /Widths [317 0 0 0 0 0 0 0 390 390 500 0 317 0 317 0 0 636 636 0 0 0 0 0 0 0 0 0 0 0 0 0 0 684 686 698 0 0 575 774 0 294 0 0 0 862 748 787 603 0 694 634 610 0 684 0 0 0 0 390 0 390 0 500 0 612 634 549 634 615 352 634 633 277 0 0 277 974 633 611 634 634 411 520 392 633 591 817 591 591 524 636 0 636] /Subtype /TrueType /Type /Font /FirstChar 32 /LastChar 125 /FontDescriptor 38 0 R /BaseFont /CFNXBZ+DejaVuSans >> endobj 30 0 obj << /Font << /f-0-1 31 0 R /f-0-0 36 0 R >> /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 40 0 obj << /Filter /FlateDecode /Length 1161 >> stream xVn6}Ẉ\M.Z`7/NP(6xaK-7q{/Zv$"!}!f0[gWLGɔp"Xǵ2{34om(_M6͝(_Xz7߳_gUIDZ1 +sZ*@vèc\hGja='<~jb ˄0DM<\ 4:/{G mê@W곝Z'=&6+f[uAM'%P:Ì%'zȟb$y̒hi'E( ̈z.(ʀry-qp4j*<{a\|,rFJܾ9(JܖҚ椌[%(-Y4sL -HNP*EXa«cXGftޔmO۰>e8,綌rgSvQ?MӄjDK|Sf&Ĩ^hCOl&6 "}WO¢π(T& m*~_ ݅p'{[׋PRm! Wꦝ/W:|&Tog%6OuV_99 OshOS鈲;Fx萱tE}؀juB+"d jg*T㶗R#&k<^ۏ 邚 2҂Q*uCү N; `42d0%GEWh-sТ`T4STպ!a֫Qܨ6 q }+A0 T.;N;0&9--E\&G ZF9b 7<|n#rF2Y飕dV=uBN[d;1x ӢdJL;Nj?zR2s"RBIF LRS*G"2>ǣS2^qCn&e;Nz[<@Tp^^a!Q" 4q*  B1w endstream endobj 29 0 obj << /Resources 30 0 R /Type /Page /Parent 1 0 R /Contents 40 0 R /MediaBox [0 0 1619.052002 816.623413] /Group << /CS /DeviceRGB /I true /Type /Group /S /Transparency >> >> endobj 45 0 obj << /Filter /FlateDecode /Length 223 >> stream x]j0 ~ Cqslrfhd8d7t0-$}?Yڿ2Ov >c\a)j.{Uo;öd{Q- ^\@C4:> stream xTkTT~ wED!d :Ft$UmiQƑX-G)Ơh0Uڈ# 6M&M ibh[kGLWZ߮sϽۏo?94"ZK#eqbÖ. `7@S徛!듲ysZT"ce"m.|w٢%ˣCt $8vќFeF)*F[?:*#4jdg޾XYniQjnPSyҩKCz8STgjUH}VW+-#S-nDs&=H=FTb,{sya5^%MG2_6ezl]IIj$k4L6|v%YӲӌVB/*lm5Jn5LhieځeS |hGP@X$GDrTk"CWXv4SHW:}AVAT1h1>6:hQet%F]!GH]6 Ua\DyΠMtAN %VN+j}HRMf;I:کuJ]tVP_)g)KHo Wo*TC5 =J\H--5MD:G;]lF:o`1>4yc5JAE|,mv}Q5E:WG*RQZf1ZJm2uXLkTMTlZ jO(Ajz-#uau@ qYzMn Qբ !3M/JԌ)5%DB)-]]ӊ$5; Iy6#}Ҵ}:$OdE |\^.4 ֏U2. .0̸8 cG^\8_.q^ s0e,O3^э?{.᷌b~ƫ%pkƯ2:xzmƛuNfO1Qo0^g㧌#6a'ZW{T+M064^Cž.zpJ/3Bxсy ~kr}4W00~ns9/v9#?Ť12v>v2Ŏj۷j{"g[vc8mbFAOohSO364 mPk4zF=ʨ.W|܁eXGK¨ 2aT0a,Lŷ jAf`c(ee0b_c.Q(D5ˋ3%\ƣ@3UA/pcz~51͆2N1TD3?T=01ٮ&`xƃA "񀞡# c' 1.ucrrFU+ɸo[ƈln"ۆa}ewMyCmiSCȴapFl"#^ Q8z0zT׃{<6uO<6HcT3Յ?WJG}}IaEDF/?zJz2)! 7%.Sju¬A=6Ab#D4#J̢V7,~4C`JπfZ[ N࿎İ endstream endobj 47 0 obj << /FontFamily (DejaVu Sans) /StemV 80 /ItalicAngle 0 /Type /FontDescriptor /FontName /TUWOJX+DejaVuSans /Ascent 928 /Flags 4 /FontFile2 48 0 R /FontBBox [-1020 -415 1680 1166] /CapHeight 1166 /Descent -235 /StemH 80 >> endobj 46 0 obj << /CIDSystemInfo << /Ordering (Identity) /Registry (Adobe) /Supplement 0 >> /Subtype /CIDFontType2 /Type /Font /W [0 [600 629]] /FontDescriptor 47 0 R /BaseFont /TUWOJX+DejaVuSans >> endobj 44 0 obj << /Encoding /Identity-H /ToUnicode 45 0 R /Subtype /Type0 /Type /Font /DescendantFonts [46 0 R] /BaseFont /TUWOJX+DejaVuSans >> endobj 50 0 obj << /Filter /FlateDecode /Length 475 >> stream x]Sˎ@sVyn$d)\|Cq038H11>3յH9S@uuuAϧeUw5K*Kj̗yiZ9oWִzZ{o{yOiF)~+)y_g:߷OeW]s<*eؾ׬Z)~>|ϵcJmb.rMuGOӱKs,{(Muv]=>|\-;rp$Np=' : RK}}38<xrgq%P';! Oq x9Ɂsye9ż>|z0§|'eEeVYz`ɷ;;[b+yZiJ/ɐNߑ;"˾} 20O< 5j̤h߾N|سRJ2.` %n_< endstream endobj 52 0 obj << /Length1 13008 /Filter /FlateDecode /Length 9353 >> stream xzy|TEoU[wv:k !@bBam8hQd LXAlL0"JdЙ #P;;At~{]w{ԩs{6,$@7ꒊs$ ac&zO%|B(S:͚LH;&rn|xfqDBb]$U+:Lz9$-M=^ ㈤"}^_{jܜ.y!S)#\*;QZDm"ߡ*/fIXwq]Xa&D3P" 3 Q8ncmk\){AbImNw*fZd5.3^wVmԍ +⁎Z^OdVfI2bISIf|sϽl5]'MMuf_?=T0NԈ۸Ռ+؃PC|+}i&qꦡtNⴛ6;n60vCstM:%r]RRdT56eJpDѵfT.*5sݹCR\[ť6smT4xS&\5GQv=ɞmZj'%vNP ጢ^\a3 i!?x™oss+ȳRcm}csVf6;6;w;mf9q,4f,4KYl ?D$}>zrҙy.. mO\vFF", sp {IkP54Vv7372[k2܌ïx)ZM4=ݨ*L2lZ$vmƊC7o /=],!Smjܻj}Uʶ*6TJ0_,Z[u\7pu+2U)fEz^W oZ{} B))1i(71!A]CHYkOߊ[4Mm*Ul;u:خ=BuAf-E/5QPhKmAySM.ӱYf[UU:KEHM0ŗ`Di7Jve bUQ6j$闌 MN[ +3232{?lKk25ei\I|IB$qi))7S[~'OMꟚ0~aBVcQ- F蔓 FJ",WP'_7YVa>иh_ḷvq]c})) -3ue(28!WIʽv>noV!S FF0JZF^(v"wϼGr4 $g36_7[ܸw5g^鯷3N|]B}e2Fw ƂFAJ5*ΡDu80֙܌#S' 2BI:PU̷1qw; '܄= ?٣B҂t0NUWѭ}6q.-iTMZYU%ߩ=_[} 4D#G2ԲK+^ԅo baH úޯ|m;K ~4}r=nccXBm#tl F&*սr( 4m!-xRaAlvmfٌu?4ޜEd6 R:V~#r ~!> nj| !_bcjHRl8 &7>4,`G'J{>ZXoGX6uLKF\(WN4Sx9w9Gjݡ\lhЛX 8K4cDnFX>{#ҿ~'rzg]]ݫrb?Ջ[@Ŷx͗BC:mX5w0F^VFI4$Uk P[u4doXW`v2:A.Xy]BeoK/4KݰMY%$:p2 &c0Itj \3Ut]79k>clk tY;3Pf(Qڊ 뒤GK^=Y!ݧVF,:O<뛤F9}^v)/znD{h#y@kg]i.t杔-Ȱ6Gt4 #{6ȳOϡe?ݩT߷locXF\Z*.ce~T)ƷhH1Zx{`5ιѧk-s2mۥH$HԐnY`pzy_r %a>))y=R&]/Vo޼ZtgP*wyzϕ,{n]qOo`0I2@/1Q(m_G__ſھo>2aאZgp"csB8i:o#q:`ѝ<`EFRZLTy݌:Hwof$V~,[3:{d%Y$Eqkz({]=򑧧 WL録WחZ}{_̚-WuC<Ϲֵp^81LW4n.);c*$V)BSX ԰bRZ]m8 E Z8)MȲ2tAMttp}ҌU/ a40\G^%2rQȡ v5 i̷,lW˜11VغY[2P,Эy:j֡5Q|H;Py)@Z.|MduӮI!0,ԃFY[a@^Q1VXIIhS rH* g.@6@y* "SMh?$?LG\y)}V.+7fZ~Ni}靄f^7 D,))!BMˆn< B 3Ct埉t͛+4!nft^z[>$!pFYȉԵ4Jl+)bwɞY*Kf9`~ʶ`/:Z"I &Ro׋{gD*qQ.㬮U< u'NYeP-u(!#y<>+ħHDIR }̒gFψy&v1Y[8fq' Xl?tI]<@LDK t{tuָ_̻8+OڷolS.}_]S7!~K%̢wi&}Bs%o;PO)wy'oNmbs27 f*s x*B'M˂.alZ27[| >̭7#yk=[zP=Gyi^el./%l{okX ygȒu`2DJ˜@ D6&Jdy6x61̤s#-byRQjZ>X`+ayc#H7Ez?/?lRd7v~i?+U;m8J{QNy]>׊vY1$&_~Q%>\aUT@yp|0>țNA^ T+`\S.J=upOs0a8Ut/(z2KVJ;)l>+R beEJԀI=mN;TGk," EyZYM t-D1Fnק"O[IJ aSj-Ihƣ̋׍N "-1SY^c廘;qkyS\&.gqa-\/޽C,4-Yw֧=`ߏ yF|%8C Luh9֩5;IY|+ޚk a`7WDSKDYq"G:)2Le!fҕ2ejJqC|K#{.uSii`x,_'," ǹ@= fk@U%[y `j$6uO2{yXbӘIaZa+wgxs[{^SdP$/R$Ȋ )r&kl)#k1GE$AGj|f?n:/yWι.=CIÒ⹲XM߉I|| ~ÿ>~xdɒ.O`FDt̽H0 E8qFr_lGԇ[J '-%Bƌ:',U-a<%%K[$jhچu6I/%nimZrRV(zN>mV=o8]F[rY>gVqw}n~9rE4Rrʘ`r5G,;*RTс4Ё;#b.;xvݵGr2HJeQ,z쳓 +RW]{Gh8Iaʹz)7q(Y|p2:lٷ|_eq>8nIt_^%@Lͩ^S~ 1do҉^P uRLInD'x!€(+C+R8T9 osPes>֒5'`;һYW3eʘ'ɗu|d-kb|k^p7f>9pY~eZ0E2Da$<Bddc$v] +y >@^0UrFoCKfR*~ ɢYԝw~$ d\Ȟ,:͕ByQNEN lpe4<"J>zI1 w "4EB~iۤS:jA@Fq|dhv]~- kBBo]DTk-Y(SyJڙc.>UTN]bSW7I}r9/΍?st(9ׂut=H+"IV.ປׄy3 3_p\D:.b}efo'&%s U &"U֍2 4d5h\7Z5+2ߓt]y BIi 2"S*)TŰIFQ,φD·l\%t9[h{mr)Z SDHb5 /X_7>w4`}-Bdij 7dzXg8ISov8kmyDl;KF(׆khLx{Sw:SU+f*f8b6{]o5!5SIV+ajkQ,xRhI$,4u$+d3lkoT_bn[m!Ej4%hTZW˥fب샗QC ?H7ӬĴBE͏U7oo6= Oo5`IWC#P"xLjAIF9w9v]'3][75Y"!4ߏw>t ݆[Ev 3 ޗZǣF8,ҭI6o{$iC,d@ړH |H9RJv"CbVšٌ]B.Ab6z u,,Vƶ.7ᗨNK:A~)D/+"NJ(I؋$ד Gt$Ұ bۛȅt.ڊl)#_KxlkD`-pLRXZwe8jB@6gE 9L:@9)ŖB;/HKjOrJ7Pזc^"JTP|pqw)JWijj%ѕ<jHC!y6// Vc}{Vf G\b,+,R[l#?v&Ptn /wn÷PWuW7\e&|qm׆知tT'>΄r"#7m\~*C|p~i\% /1g\(yL8+Rw"V`o xK o 8. 5^p̄e^-y׎寽-1 6Ѡj9pH@W,?8?Ps^zo=vav8K/@>RQljl||K_fly|r;az;zXuNұ|vT&KBiPZVW Xa>{?XnXn@ V2Բ,5,6MX$`b-X'`_Eý(0m0K0TS<-Dfo>yFp? #G^F]|X+x 3Ň 0 0xAqv>0@@rW}axz:?z {zGw'{ U@.=K=tq6x Yvȼ3 #vH7cwtA gBZO+vn.nhm$ 섀m$ hDgP8C,j0V@L=D^*(THQ<"jpCl-  4*> P< 7%/`-D=gU`j‡ob endstream endobj 51 0 obj << /FontFamily (DejaVu Sans) /StemV 80 /ItalicAngle 0 /Type /FontDescriptor /FontName /NNEWLE+DejaVuSans /Ascent 928 /Flags 32 /FontFile2 52 0 R /FontBBox [-1020 -415 1680 1166] /CapHeight 1166 /Descent -235 /StemH 80 >> endobj 49 0 obj << /Encoding /WinAnsiEncoding /ToUnicode 50 0 R /Widths [317 0 0 0 0 0 0 0 390 390 500 0 317 0 317 336 636 636 636 636 636 0 0 0 0 0 0 0 0 0 0 0 0 684 686 698 0 0 575 774 0 294 0 0 0 862 748 787 603 0 694 634 610 0 684 0 0 0 0 390 0 390 0 500 0 612 634 549 634 615 352 634 633 277 0 579 277 974 633 611 634 634 411 520 392 633 0 817 591 591 524 636 0 636] /Subtype /TrueType /Type /Font /FirstChar 32 /LastChar 125 /FontDescriptor 51 0 R /BaseFont /NNEWLE+DejaVuSans >> endobj 43 0 obj << /Font << /f-0-1 44 0 R /f-0-0 49 0 R >> /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 53 0 obj << /Filter /FlateDecode /Length 1576 >> stream xWnF}W#e_@]A }Q([D =ClQN왙3M5{ vIljV~47*X/KlL^2 &xu1meB-$'`֣/D 7k)dymx 6c<&c0/*abfE5hUDLrex-q9Ig~@U u]GҦ+Vz]yUnW4rX%w2X(R&.Z)4sAsq~IG=G"R5^7E>tNbhi3Ahut&E)_=&_7~bZbB[h┣ ^S:nI9d~,kᵠ59CUXŽuaNsAPX/ EyAU4c#q5;W6ԭsZS[ |I$e]>yZO뛖mIOM1EF B-zduê8t+$Ybʛ#Hm:P^Vբ|3@jUϗpy)XtEyE8(]P > ?͉ġ.s/'cnI{q;P-˥ͤ!>2 *2Oޯ'aqA-uJ]r2!FhoLFg#) K -jRl% ;ŁsP$gȞd{y1 Oи__a(fUx`xGEʧ~`y ŔטU }M0.O_Kk7hi`Qqh!3&C@`SKxPS"x~:\B.Bh2Jv).NG-)\Έa>y%)6ΡwDJ/A^ ؈"| ؈F1z+D^#3*tqZl{} G:7 ĵC+zOK:X)1XЍi'E+$K0# EE״-Xc p@P1]@v ןeݳ"k@ciV:t̂f#Ynu LgwrY0Lhc!B endstream endobj 42 0 obj << /Resources 43 0 R /Type /Page /Parent 1 0 R /Contents 53 0 R /MediaBox [0 0 1619.052002 816.623413] /Group << /CS /DeviceRGB /I true /Type /Group /S /Transparency >> >> endobj 58 0 obj << /Filter /FlateDecode /Length 223 >> stream x]j0 ~ Cqslrfhd8d7t0-$}?Yڿ2Ov >c\a)j.{Uo;öd{Q- ^\@C4:> stream xTkTT~ wED!d :Ft$UmiQƑX-G)Ơh0Uڈ# 6M&M ibh[kGLWZ߮sϽۏo?94"ZK#eqbÖ. `7@S徛!듲ysZT"ce"m.|w٢%ˣCt $8vќFeF)*F[?:*#4jdg޾XYniQjnPSyҩKCz8STgjUH}VW+-#S-nDs&=H=FTb,{sya5^%MG2_6ezl]IIj$k4L6|v%YӲӌVB/*lm5Jn5LhieځeS |hGP@X$GDrTk"CWXv4SHW:}AVAT1h1>6:hQet%F]!GH]6 Ua\DyΠMtAN %VN+j}HRMf;I:کuJ]tVP_)g)KHo Wo*TC5 =J\H--5MD:G;]lF:o`1>4yc5JAE|,mv}Q5E:WG*RQZf1ZJm2uXLkTMTlZ jO(Ajz-#uau@ qYzMn Qբ !3M/JԌ)5%DB)-]]ӊ$5; Iy6#}Ҵ}:$OdE |\^.4 ֏U2. .0̸8 cG^\8_.q^ s0e,O3^э?{.᷌b~ƫ%pkƯ2:xzmƛuNfO1Qo0^g㧌#6a'ZW{T+M064^Cž.zpJ/3Bxсy ~kr}4W00~ns9/v9#?Ť12v>v2Ŏj۷j{"g[vc8mbFAOohSO364 mPk4zF=ʨ.W|܁eXGK¨ 2aT0a,Lŷ jAf`c(ee0b_c.Q(D5ˋ3%\ƣ@3UA/pcz~51͆2N1TD3?T=01ٮ&`xƃA "񀞡# c' 1.ucrrFU+ɸo[ƈln"ۆa}ewMyCmiSCȴapFl"#^ Q8z0zT׃{<6uO<6HcT3Յ?WJG}}IaEDF/?zJz2)! 7%.Sju¬A=6Ab#D4#J̢V7,~4C`JπfZ[ N࿎İ endstream endobj 60 0 obj << /FontFamily (DejaVu Sans) /StemV 80 /ItalicAngle 0 /Type /FontDescriptor /FontName /TUWOJX+DejaVuSans /Ascent 928 /Flags 4 /FontFile2 61 0 R /FontBBox [-1020 -415 1680 1166] /CapHeight 1166 /Descent -235 /StemH 80 >> endobj 59 0 obj << /CIDSystemInfo << /Ordering (Identity) /Registry (Adobe) /Supplement 0 >> /Subtype /CIDFontType2 /Type /Font /W [0 [600 629]] /FontDescriptor 60 0 R /BaseFont /TUWOJX+DejaVuSans >> endobj 57 0 obj << /Encoding /Identity-H /ToUnicode 58 0 R /Subtype /Type0 /Type /Font /DescendantFonts [59 0 R] /BaseFont /TUWOJX+DejaVuSans >> endobj 63 0 obj << /Filter /FlateDecode /Length 471 >> stream x]S͎ )8n+;[ɊTm/9GM6Rc[90C}=}>-y 紫i^bNCRcKs*a:lM[Ϗ۞eZW폲xC=}>4J[)E=z=s|߶?隖]ubܗa:\jk)y<-)]֘nRKj;~MZkVX2NB24Xq b)Yr,p 2ZK}}8<8rz^/[[kjjhjz"k#ŢO_u¿g98]{p?PA0Ss`_} kYkQk§|]Ա5# dÃ/[[ T<y }͐H㌄ +0C 5W8/̭ o7Wo-{X?n7/i" endstream endobj 65 0 obj << /Length1 12692 /Filter /FlateDecode /Length 9135 >> stream xz{|EoUyd&9! !HLH i|'4c"u] ޿uy3^!KW85&iS|a#$ú#S;9tu`Ӯx_ *^,v* Mܤ6Q8l8xqo<ߘe3yR7>WI6~xAH..ַUOotNvOsf:Rgy*-O>Tr)9Իer4vOY/oV?hJCI?9BO6ĥNia:8M: M Qo8za5]}~T>vTm}p^GxZzMlh0cQaqf5fߨn[[i;dO@C"lh=v:r#ILQ0pcn1q4ґvdZPht98fOKsY<#ˑwew xH Ԇ##\!s,A/qx۽ڽ8c}s,l!WYb[\ZKVkkk][JҾչյi1?4?1[d4gy9aGoZ>3[u|t&x'veYS\V6 8z}/;?2}/(ZK1}*L1BZ"W^,/;-kGoVXA[}32/'Cjmko/uvzl־.!l>b ^#ԖrEHB1[\ c][x`>>t$49iV'MK5I :4 6Nfxr._onAjJJJ dduJ %CPJCAbARArA CAUIU6U]KKj )f'N)K*K. NFݶN?v#/'%7 FjCO,v@[nRWNs]c9%S]<~W}S~c'wߗn;QW!#CQJk=b5nĆM%b&YRRT/5J쥎Rg]jxmiT֞t`6^yԄO:uj|O6oPWؾP(>8R4[k961'2\C:2wL3"]7=!=vLٱ͝fi`%Sy"LP'Cm֑>8  Bm&"i,7W}%ǔֈj:ő‹H@{` }Zn$$;[/sn+>vm߱͝-oY_I7\ uؙcFR2t-3y]sn$ǫxSy; nn{#? EZR 8jx?az$AO0H]}>zFzgKT7%sR@zJǴjc}c!-c`8nCCO2?^^!:Zz, c2M>b0fqfrhxrIkN4a?4'X7}h~P|8عر).[n{55܉w*:V~ )&aL8ɀԁ P©/10TáZ(+T+Vnn0bDAZ|c䁂ENl 2b!ޖa yo29$7BZȊRxوGD(\2fŎ4/cGZ=mAk,h7PpSmBfR(9\]hs8oqpkr9$/!_X$Zcijݨ3)_WSs Ż`ƴL}\5Dr)Ϣ@G!QRlXzD%ưNѧ|^OLj'ӓ^rUuU͊/+ϗ_~B mm+~KR¸_.؊߬;bw܅w Yd?]-zaTlϽ0`=8uiXM_ #yY%YiHH/7_F)7fgѰAl̞&L͒U gk;4m2DL.E߶\=rU\tAdX-F6Pa*Mu2 &c0Itj \3m)k;c6N]cUvfo#ah8aQb A qܧw;q^u^/K1}=_o;f}/]j=A.q>-HN"u14zjod9FP1Dix:M{{OD=^h8f9RstTk:>q:2i4QC.͋/龋"G vDY9o~<붗z]=xoF/&-? Q['l뜵t3`cHbegQ~5,ãi;Cއn%j9=«M S-iuRvFK5:uJM\o%v}[irDHy,Q.e]$q[!mc).7^Ui׮Mjlr#~{.wҥĤWvyM)PN{OQNv:7>u;,Vܗ/8Etifm GKpo^{Z*J0yw$ C=.8/ ^ 1ͷ7PЮc$"yI?Hw0v F)i&Ҽi: G$[7a҉NV~,O[t*jM~OW˽~}Κ4~6}*U^xcń7Զ'a\w溍\pa$/=x[[T ?՜U*lJdjXJ 3j)!`f \Mb`K:Rnߧ#wo/ч ژ #^ÝktC S=2;$݌\2_([ lu8{JAze8Jkr#Fq/_=EFƾ1 ;N ˅X*rPYJRM` jUe&*Kyj:NBsX(-o>ٰ8|VgԇXZTj)C^:ANR+J%ݪ0aiROa jZf6 7gMmnډYUMPDl 7DLXY!XaLvؾ.#3vMb{7Wp2ͬBnK }2+,( ;ѥFka+%'| 6Fk*CixM@@L!@ &GiNq 1nP|U .oZQ4=%|X_W9~Ecd2?n^c +j+=&N@bygzDBײGLK8h !}-O~dU#bDuX R kd%(u䣩;'%>WESy-dIm'!wSl+ɦ?nۡRye\u0wOW:?O?MyO;Z3|ޙvpC~,qo˷|>?+[0mz??ݐktirlcO\dgmb  5"8 TNy]3"a.eToəvnoe1rj[oFz>C~O G٣X_JbQ*ؤ׳z; D4P!tc~q"y =H4A J5hK:)F=x-ߞʆPVkFrG&:==jm6VgL#Et: L1S>M1r'b ebR,QKEZV/0QL6Ml#lωgg-Pf}s7Mw{~N߲C]jo9q8-ˉM5hڿ|y/_ʏ.yas̴jjg%N /06c@{kW0Ym͆v t%ԎLEW{<.Kcy(Nz@D] }Ԁ(+:k=h_oMPIo5jeU45 2ZJ+KORDfḧ́cO ǦG7*ţ լ.+EY[8};Zf1}$?aֵ. }bk0Ʀ۹މp 4XXрfsh6fݻW}#} Ugn~R^( -c-(2|eјYhd MvuIy4 C 1 (kTkcR;r>3%V:,[#\t}%+[g*+a3hiԖ(y+WaJp^jԵJrZ&4l,ʟ,3!Z><<%Y 3[WgLN0WU)5n4cOoWʖVnjuX?kٻZ7pshE5k}?5TzHik}[C'ܧE)K¥KV| ErNm-OCY$/xyP4 yڢ~,u5޲w YG\P]"ʊV"Q7%+W7r ]MǬFL(O Aw IUKG]xwqOw5q>D1Η$.7M d<^L,S$_bʶ|=kKzv2h+!#@7i֬I K?տS7WTo zY Kv*WM^,iTs UqV* &_ W$%w@p/W8%8!OۣA`lT/(E&G ւhP7 ZO3_ `\ endstream endobj 64 0 obj << /FontFamily (DejaVu Sans) /StemV 80 /ItalicAngle 0 /Type /FontDescriptor /FontName /CWTDEH+DejaVuSans /Ascent 928 /Flags 32 /FontFile2 65 0 R /FontBBox [-1020 -415 1680 1166] /CapHeight 1166 /Descent -235 /StemH 80 >> endobj 62 0 obj << /Encoding /WinAnsiEncoding /ToUnicode 63 0 R /Widths [317 0 0 0 0 0 0 0 390 390 500 0 317 0 317 0 0 636 636 0 636 0 0 0 0 0 0 336 0 0 0 0 0 684 686 698 770 0 575 774 0 294 0 0 0 862 748 787 603 0 694 634 610 0 684 0 685 0 0 390 0 390 0 500 0 612 634 549 634 615 352 634 633 277 0 0 277 974 633 611 634 634 411 520 392 633 0 817 591 591 524 636 0 636] /Subtype /TrueType /Type /Font /FirstChar 32 /LastChar 125 /FontDescriptor 64 0 R /BaseFont /CWTDEH+DejaVuSans >> endobj 56 0 obj << /Font << /f-0-1 57 0 R /f-0-0 62 0 R >> /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 66 0 obj << /Filter /FlateDecode /Length 1410 >> stream xWioF_1I#}EZ m(mlH7ۥ%41.oޜXpJkzYsBɼbZz9Ger6#NƳb5o~[ιny/9)]oO3Oi͔dfFNi捡u+@$BQqi$O1NyfOlg{_U#UH8{f>.Ǖ? HJv+˺l^гj{u7m0L%W&n\/6RY%) o FpE+&6$2Cfy7nW]ܜblYWҗջNr'Cv*Oƽ|a6i)2jڴ#-VDҭ,dmxG9KuV8<a8N/6V}:(G2 J8gX?:GS[ l\B+ !3fͨ˥0FUGlP[/PҦe.iպRRB2m=0L㐈&͌4s$`#,WwBww'~phohR+e??E~!WgTY1L51KËc[I4H:4YdP LYPqSnASqRxBF)oS VgV4R{D)&A6LA8@o"a0,0ܱ wY:C߃W!R8PH 1+H{s)/so:I endstream endobj 55 0 obj << /Resources 56 0 R /Type /Page /Parent 1 0 R /Contents 66 0 R /MediaBox [0 0 1619.052002 816.623413] /Group << /CS /DeviceRGB /I true /Type /Group /S /Transparency >> >> endobj 1 0 obj << /Kids [3 0 R 16 0 R 29 0 R 42 0 R 55 0 R] /Type /Pages /Count 5 >> endobj 68 0 obj << /Type /Catalog /Pages 1 0 R >> endobj 69 0 obj << /ModDate (D:20140528010448+02'00') /CreationDate (D:20140528010448+02'00') /Creator (pdftk 2.01 - www.pdftk.com) /Producer (itext-paulo-155 \(itextpdf.sf.net-lowagie.com\)) >> endobj xref 0 70 0000000000 65535 f 0000073789 00000 n 0000000000 65535 f 0000013529 00000 n 0000012511 00000 n 0000002701 00000 n 0000000015 00000 n 0000002500 00000 n 0000002264 00000 n 0000000313 00000 n 0000012039 00000 n 0000002845 00000 n 0000011800 00000 n 0000003361 00000 n 0000012615 00000 n 0000000000 65535 f 0000028337 00000 n 0000026816 00000 n 0000016410 00000 n 0000013718 00000 n 0000016207 00000 n 0000015969 00000 n 0000014017 00000 n 0000026336 00000 n 0000016557 00000 n 0000026097 00000 n 0000017091 00000 n 0000026922 00000 n 0000000000 65535 f 0000042964 00000 n 0000041620 00000 n 0000031220 00000 n 0000028528 00000 n 0000031017 00000 n 0000030779 00000 n 0000028827 00000 n 0000041140 00000 n 0000031367 00000 n 0000040901 00000 n 0000031902 00000 n 0000041726 00000 n 0000000000 65535 f 0000058476 00000 n 0000056717 00000 n 0000045847 00000 n 0000043155 00000 n 0000045644 00000 n 0000045406 00000 n 0000043454 00000 n 0000056229 00000 n 0000045994 00000 n 0000055990 00000 n 0000046545 00000 n 0000056823 00000 n 0000000000 65535 f 0000073598 00000 n 0000072005 00000 n 0000061359 00000 n 0000058667 00000 n 0000061156 00000 n 0000060918 00000 n 0000058966 00000 n 0000071519 00000 n 0000061506 00000 n 0000071280 00000 n 0000062053 00000 n 0000072111 00000 n 0000000000 65535 f 0000073876 00000 n 0000073928 00000 n trailer << /Info 69 0 R /ID [<3b364da62a47c0f26e83388595105f95>] /Root 68 0 R /Size 70 >> startxref 74124 %%EOF ExaML-3.0.21/codeDocumentation/startupIllustration.svg000066400000000000000000000725531330315463200230600ustar00rootroot00000000000000 image/svg+xml bytefile layout int sizeof(size_t),int numTax,size_t numPattern, int numPartitions, double gappyness { header int len1, char taxonName[len1], int len2, char taxonName[len2],... { taxon names partition1{ int states, int maxTipStates,size_t lower,size_t upper,size_t width, (unused)int dataType,int protModels,int autoProtModels,int protFreqs,boolean nonGTR,boolean optimizeBaseFrequencies,int numberOfCategories,int len,char partitionName[len],double frequencies[states]}partition 2{....}.... { partition infos int weights[numPattern] char yVector[numPattern] ByteFile *bFile ....pInfo* partitions.... 1. read header, taxa, partitions into ByteFile struct(use seekPos() to navigate in bytefile) PartitionAssignment *pAss 2. every process computes partition assignment partitions[0].yVectorpartitions[0].wgtpartitions[4].yVectorpartitions[4].wgt 3. process only reads data assigned to it (exa_fread/exa_fseek) 4. tree struct is initialized; bFile and pAss are deleted tree *tr ....pInfo *partitionData....Assign* assignments X X ExaML-3.0.21/examl/000077500000000000000000000000001330315463200136515ustar00rootroot00000000000000ExaML-3.0.21/examl/Makefile.AVX.gcc000066400000000000000000000050101330315463200164750ustar00rootroot00000000000000# Makefile August 2006 by Alexandros Stamatakis # Makefile cleanup October 2006, Courtesy of Peter Cordes CC = mpicc COMMON_FLAGS = -D__SIM_SSE3 -D__AVX -D_OPTIMIZED_FUNCTIONS -msse3 -D_GNU_SOURCE -fomit-frame-pointer -funroll-loops -D_USE_ALLREDUCE #-Wall -Wredundant-decls -Wreturn-type -Wswitch-default -Wunused-value -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wimport -Wunused -Wunused-function -Wunused-label -Wno-int-to-pointer-cast -Wbad-function-cast -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wstrict-prototypes -Wpointer-sign -Wextra -Wredundant-decls -Wunused -Wunused-function -Wunused-parameter -Wunused-value -Wunused-variable -Wformat -Wformat-nonliteral -Wparentheses -Wsequence-point -Wuninitialized -Wundef -Wbad-function-cast -Wno-unused-parameter OPT_FLAG_1 = -O1 OPT_FLAG_2 = -O2 CFLAGS = $(COMMON_FLAGS) $(OPT_FLAG_2) LIBRARIES = -lm -mavx RM = rm -f objs = axml.o optimizeModel.o trash.o searchAlgo.o topologies.o treeIO.o models.o evaluatePartialGenericSpecial.o evaluateGenericSpecial.o newviewGenericSpecial.o makenewzGenericSpecial.o bipartitionList.o restartHashTable.o avxLikelihood.o byteFile.o partitionAssignment.o communication.o quartets.o all : clean examl-AVX GLOBAL_DEPS = axml.h globalVariables.h ../versionHeader/version.h examl-AVX : $(objs) $(CC) -o examl-AVX $(objs) $(LIBRARIES) avxLikelihood.o : avxLikelihood.c $(GLOBAL_DEPS) $(CC) $(CFLAGS) -mavx -c -o avxLikelihood.o avxLikelihood.c models.o : models.c $(GLOBAL_DEPS) $(CC) $(COMMON_FLAGS) $(OPT_FLAG_1) -c -o models.o models.c bipartitionList.o : bipartitionList.c $(GLOBAL_DEPS) evaluatePartialSpecialGeneric.o : evaluatePartialSpecialGeneric.c $(GLOBAL_DEPS) optimizeModel.o : optimizeModel.c $(GLOBAL_DEPS) trash.o : trash.c $(GLOBAL_DEPS) axml.o : axml.c $(GLOBAL_DEPS) searchAlgo.o : searchAlgo.c $(GLOBAL_DEPS) topologies.o : topologies.c $(GLOBAL_DEPS) treeIO.o : treeIO.c $(GLOBAL_DEPS) quartets.o : quartets.c $(GLOBAL_DEPS) evaluatePartialGenericSpecial.o : evaluatePartialGenericSpecial.c $(GLOBAL_DEPS) evaluateGenericSpecial.o : evaluateGenericSpecial.c $(GLOBAL_DEPS) newviewGenericSpecial.o : newviewGenericSpecial.c $(GLOBAL_DEPS) makenewzGenericSpecial.o : makenewzGenericSpecial.c $(GLOBAL_DEPS) restartHashTable.o : restartHashTable.c $(GLOBAL_DEPS) byteFile.o : byteFile.c partitionAssignment.o : partitionAssignment.c $(GLOBAL_DEPS) communication.o : communication.c $(GLOBAL_DEPS) clean : $(RM) *.o examl-AVX dev : examl-AVX ExaML-3.0.21/examl/Makefile.KNL.icc000066400000000000000000000054231330315463200164750ustar00rootroot00000000000000# Makefile August 2006 by Alexandros Stamatakis # Makefile cleanup October 2006, Courtesy of Peter Cordes CC = mpicc #MICFLAGS = -D__MIC_NATIVE -mmic -opt-streaming-cache-evict=0 -openmp -D_USE_OMP #-D_PROFILE_MPI KNLFLAGS=-xMIC-AVX512 -fma -align -finline-functions -D__MIC_NATIVE -qopenmp -D_USE_OMP COMMON_FLAGS = -std=c99 -D__SIM_SSE3 -D_OPTIMIZED_FUNCTIONS -D_GNU_SOURCE -fomit-frame-pointer -funroll-loops -D_USE_ALLREDUCE $(KNLFLAGS) # -Wall -Wredundant-decls -Wreturn-type -Wswitch-default -Wunused-value -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wimport -Wunused -Wunused-function -Wunused-label -Wno-int-to-pointer-cast -Wbad-function-cast -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wstrict-prototypes -Wpointer-sign -Wextra -Wredundant-decls -Wunused -Wunused-function -Wunused-parameter -Wunused-value -Wunused-variable -Wformat -Wformat-nonliteral -Wparentheses -Wsequence-point -Wuninitialized -Wundef -Wbad-function-cast -Wno-unused-parameter OPT_FLAG_1 = -O1 OPT_FLAG_2 = -O2 CFLAGS = $(COMMON_FLAGS) $(OPT_FLAG_2) LIBRARIES = -lm -qopenmp #-mmic RM = rm -f objs = axml.o optimizeModel.o trash.o searchAlgo.o topologies.o treeIO.o models.o evaluatePartialGenericSpecial.o evaluateGenericSpecial.o newviewGenericSpecial.o makenewzGenericSpecial.o bipartitionList.o restartHashTable.o byteFile.o partitionAssignment.o communication.o mic_native_dna.o mic_native_aa.o quartets.o all : clean examl-KNL GLOBAL_DEPS = axml.h globalVariables.h examl-KNL : $(objs) $(CC) -o examl-KNL $(objs) $(LIBRARIES) models.o : models.c $(GLOBAL_DEPS) $(CC) $(COMMON_FLAGS) $(OPT_FLAG_1) -c -o models.o models.c partitionAssignment.o: partitionAssignment.o $(GLOBAL_DEPS) $(CC) $(COMMON_FLAGS) $(OPT_FLAG_1) -c -o partitionAssignment.o partitionAssignment.c bipartitionList.o : bipartitionList.c $(GLOBAL_DEPS) evaluatePartialSpecialGeneric.o : evaluatePartialSpecialGeneric.c $(GLOBAL_DEPS) optimizeModel.o : optimizeModel.c $(GLOBAL_DEPS) trash.o : trash.c $(GLOBAL_DEPS) axml.o : axml.c $(GLOBAL_DEPS) searchAlgo.o : searchAlgo.c $(GLOBAL_DEPS) topologies.o : topologies.c $(GLOBAL_DEPS) treeIO.o : treeIO.c $(GLOBAL_DEPS) evaluatePartialGenericSpecial.o : evaluatePartialGenericSpecial.c $(GLOBAL_DEPS) evaluateGenericSpecial.o : evaluateGenericSpecial.c $(GLOBAL_DEPS) newviewGenericSpecial.o : newviewGenericSpecial.c $(GLOBAL_DEPS) makenewzGenericSpecial.o : makenewzGenericSpecial.c $(GLOBAL_DEPS) restartHashTable.o : restartHashTable.c $(GLOBAL_DEPS) byteFile.o : byteFile.c communication.o : communication.c $(GLOBAL_DEPS) mic_native_dna.o : mic_native_dna.c $(GLOBAL_DEPS) mic_native_aa.o : mic_native_aa.c $(GLOBAL_DEPS) quartets.o : quartets.c $(GLOBAL_DEPS) clean : $(RM) *.o examl-KNL dev : examl-KNL ExaML-3.0.21/examl/Makefile.MIC.icc000066400000000000000000000052701330315463200164610ustar00rootroot00000000000000# Makefile August 2006 by Alexandros Stamatakis # Makefile cleanup October 2006, Courtesy of Peter Cordes CC = mpicc MICFLAGS = -D__MIC_NATIVE -mmic -qopt-streaming-cache-evict=0 -qopenmp -D_USE_OMP #-D_PROFILE_MPI COMMON_FLAGS = -std=c99 -D__SIM_SSE3 -D_OPTIMIZED_FUNCTIONS -D_GNU_SOURCE -fomit-frame-pointer -funroll-loops -D_USE_ALLREDUCE $(MICFLAGS) # -Wall -Wredundant-decls -Wreturn-type -Wswitch-default -Wunused-value -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wimport -Wunused -Wunused-function -Wunused-label -Wno-int-to-pointer-cast -Wbad-function-cast -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wstrict-prototypes -Wpointer-sign -Wextra -Wredundant-decls -Wunused -Wunused-function -Wunused-parameter -Wunused-value -Wunused-variable -Wformat -Wformat-nonliteral -Wparentheses -Wsequence-point -Wuninitialized -Wundef -Wbad-function-cast -Wno-unused-parameter OPT_FLAG_1 = -O1 OPT_FLAG_2 = -O2 CFLAGS = $(COMMON_FLAGS) $(OPT_FLAG_2) LIBRARIES = -lm -mmic -openmp RM = rm -f objs = axml.o optimizeModel.o trash.o searchAlgo.o topologies.o treeIO.o models.o evaluatePartialGenericSpecial.o evaluateGenericSpecial.o newviewGenericSpecial.o makenewzGenericSpecial.o bipartitionList.o restartHashTable.o byteFile.o partitionAssignment.o communication.o mic_native_dna.o mic_native_aa.o quartets.o all : clean examl-MIC GLOBAL_DEPS = axml.h globalVariables.h examl-MIC : $(objs) $(CC) -o examl-MIC $(objs) $(LIBRARIES) models.o : models.c $(GLOBAL_DEPS) $(CC) $(COMMON_FLAGS) $(OPT_FLAG_1) -c -o models.o models.c partitionAssignment.o: partitionAssignment.o $(GLOBAL_DEPS) $(CC) $(COMMON_FLAGS) $(OPT_FLAG_1) -c -o partitionAssignment.o partitionAssignment.c bipartitionList.o : bipartitionList.c $(GLOBAL_DEPS) evaluatePartialSpecialGeneric.o : evaluatePartialSpecialGeneric.c $(GLOBAL_DEPS) optimizeModel.o : optimizeModel.c $(GLOBAL_DEPS) trash.o : trash.c $(GLOBAL_DEPS) axml.o : axml.c $(GLOBAL_DEPS) searchAlgo.o : searchAlgo.c $(GLOBAL_DEPS) topologies.o : topologies.c $(GLOBAL_DEPS) treeIO.o : treeIO.c $(GLOBAL_DEPS) evaluatePartialGenericSpecial.o : evaluatePartialGenericSpecial.c $(GLOBAL_DEPS) evaluateGenericSpecial.o : evaluateGenericSpecial.c $(GLOBAL_DEPS) newviewGenericSpecial.o : newviewGenericSpecial.c $(GLOBAL_DEPS) makenewzGenericSpecial.o : makenewzGenericSpecial.c $(GLOBAL_DEPS) restartHashTable.o : restartHashTable.c $(GLOBAL_DEPS) byteFile.o : byteFile.c communication.o : communication.c $(GLOBAL_DEPS) mic_native_dna.o : mic_native_dna.c $(GLOBAL_DEPS) mic_native_aa.o : mic_native_aa.c $(GLOBAL_DEPS) quartets.o : quartets.c $(GLOBAL_DEPS) clean : $(RM) *.o examl-MIC dev : examl-MIC ExaML-3.0.21/examl/Makefile.OMP.AVX.gcc000066400000000000000000000050721330315463200171370ustar00rootroot00000000000000# Makefile August 2006 by Alexandros Stamatakis # Makefile cleanup October 2006, Courtesy of Peter Cordes CC = mpicc COMMON_FLAGS = -D__SIM_SSE3 -D__AVX -D_USE_OMP -fopenmp -D_OPTIMIZED_FUNCTIONS -msse3 -D_GNU_SOURCE -fomit-frame-pointer -funroll-loops -D_USE_ALLREDUCE -Wall # -Wredundant-decls -Wreturn-type -Wswitch-default -Wunused-value -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wimport -Wunused -Wunused-function -Wunused-label -Wno-int-to-pointer-cast -Wbad-function-cast -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wstrict-prototypes -Wpointer-sign -Wextra -Wredundant-decls -Wunused -Wunused-function -Wunused-parameter -Wunused-value -Wunused-variable -Wformat -Wformat-nonliteral -Wparentheses -Wsequence-point -Wuninitialized -Wundef -Wbad-function-cast -Wno-unused-parameter OPT_FLAG_1 = -O1 OPT_FLAG_2 = -O2 CFLAGS = $(COMMON_FLAGS) $(OPT_FLAG_2) LIBRARIES = -lm -mavx -fopenmp RM = rm -f objs = axml.o optimizeModel.o trash.o searchAlgo.o topologies.o treeIO.o models.o evaluatePartialGenericSpecial.o evaluateGenericSpecial.o newviewGenericSpecial.o makenewzGenericSpecial.o bipartitionList.o restartHashTable.o avxLikelihood.o byteFile.o partitionAssignment.o communication.o quartets.o all : clean examl-OMP-AVX GLOBAL_DEPS = axml.h globalVariables.h ../versionHeader/version.h examl-OMP-AVX : $(objs) $(CC) -o examl-OMP-AVX $(objs) $(LIBRARIES) avxLikelihood.o : avxLikelihood.c $(GLOBAL_DEPS) $(CC) $(CFLAGS) -mavx -c -o avxLikelihood.o avxLikelihood.c models.o : models.c $(GLOBAL_DEPS) $(CC) $(COMMON_FLAGS) $(OPT_FLAG_1) -c -o models.o models.c bipartitionList.o : bipartitionList.c $(GLOBAL_DEPS) evaluatePartialSpecialGeneric.o : evaluatePartialSpecialGeneric.c $(GLOBAL_DEPS) optimizeModel.o : optimizeModel.c $(GLOBAL_DEPS) trash.o : trash.c $(GLOBAL_DEPS) axml.o : axml.c $(GLOBAL_DEPS) searchAlgo.o : searchAlgo.c $(GLOBAL_DEPS) topologies.o : topologies.c $(GLOBAL_DEPS) treeIO.o : treeIO.c $(GLOBAL_DEPS) quartets.o : quartets.c $(GLOBAL_DEPS) evaluatePartialGenericSpecial.o : evaluatePartialGenericSpecial.c $(GLOBAL_DEPS) evaluateGenericSpecial.o : evaluateGenericSpecial.c $(GLOBAL_DEPS) newviewGenericSpecial.o : newviewGenericSpecial.c $(GLOBAL_DEPS) makenewzGenericSpecial.o : makenewzGenericSpecial.c $(GLOBAL_DEPS) restartHashTable.o : restartHashTable.c $(GLOBAL_DEPS) byteFile.o : byteFile.c partitionAssignment.o : partitionAssignment.c $(GLOBAL_DEPS) communication.o : communication.c $(GLOBAL_DEPS) clean : $(RM) *.o examl-OMP-AVX dev : examl-OMP-AVX ExaML-3.0.21/examl/Makefile.OMP.SSE3.gcc000066400000000000000000000047141330315463200172200ustar00rootroot00000000000000# Makefile August 2006 by Alexandros Stamatakis # Makefile cleanup October 2006, Courtesy of Peter Cordes CC = mpicc COMMON_FLAGS = -D_USE_OMP -fopenmp -D_GNU_SOURCE -D__SIM_SSE3 -msse3 -fomit-frame-pointer -funroll-loops -D_OPTIMIZED_FUNCTIONS -D_USE_ALLREDUCE -Wall #-Wunused-parameter -Wredundant-decls -Wreturn-type -Wswitch-default -Wunused-value -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wimport -Wunused -Wunused-function -Wunused-label -Wno-int-to-pointer-cast -Wbad-function-cast -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wstrict-prototypes -Wpointer-sign -Wextra -Wredundant-decls -Wunused -Wunused-function -Wunused-parameter -Wunused-value -Wunused-variable -Wformat -Wformat-nonliteral -Wparentheses -Wsequence-point -Wuninitialized -Wundef -Wbad-function-cast -Wno-unused-parameter OPT_FLAG_1 = -O1 OPT_FLAG_2 = -O2 CFLAGS = $(COMMON_FLAGS) $(OPT_FLAG_2) LIBRARIES = -lm -fopenmp RM = rm -f objs = axml.o optimizeModel.o trash.o searchAlgo.o topologies.o treeIO.o models.o evaluatePartialGenericSpecial.o evaluateGenericSpecial.o newviewGenericSpecial.o makenewzGenericSpecial.o bipartitionList.o restartHashTable.o byteFile.o partitionAssignment.o communication.o quartets.o all : clean examl-OMP GLOBAL_DEPS = axml.h globalVariables.h ../versionHeader/version.h examl-OMP : $(objs) $(CC) -o examl-OMP $(objs) $(LIBRARIES) models.o : models.c $(GLOBAL_DEPS) $(CC) $(COMMON_FLAGS) $(OPT_FLAG_1) -c -o models.o models.c bipartitionList.o : bipartitionList.c $(GLOBAL_DEPS) evaluatePartialSpecialGeneric.o : evaluatePartialSpecialGeneric.c $(GLOBAL_DEPS) optimizeModel.o : optimizeModel.c $(GLOBAL_DEPS) trash.o : trash.c $(GLOBAL_DEPS) axml.o : axml.c $(GLOBAL_DEPS) searchAlgo.o : searchAlgo.c $(GLOBAL_DEPS) topologies.o : topologies.c $(GLOBAL_DEPS) treeIO.o : treeIO.c $(GLOBAL_DEPS) models.o : models.c $(GLOBAL_DEPS) evaluatePartialGenericSpecial.o : evaluatePartialGenericSpecial.c $(GLOBAL_DEPS) evaluateGenericSpecial.o : evaluateGenericSpecial.c $(GLOBAL_DEPS) newviewGenericSpecial.o : newviewGenericSpecial.c $(GLOBAL_DEPS) makenewzGenericSpecial.o : makenewzGenericSpecial.c $(GLOBAL_DEPS) restartHashTable.o : restartHashTable.c $(GLOBAL_DEPS) byteFile.o : byteFile.c partitionAssignment.o : partitionAssignment.c $(GLOBAL_DEPS) communication.o : communication.c $(GLOBAL_DEPS) quartets.o : quartets.c $(GLOBAL_DEPS) clean : $(RM) *.o examl-OMP dev : examl-OMP ExaML-3.0.21/examl/Makefile.SSE3.gcc000066400000000000000000000046341330315463200165670ustar00rootroot00000000000000# Makefile August 2006 by Alexandros Stamatakis # Makefile cleanup October 2006, Courtesy of Peter Cordes CC = mpicc COMMON_FLAGS = -D_GNU_SOURCE -D__SIM_SSE3 -msse3 -fomit-frame-pointer -funroll-loops -D_OPTIMIZED_FUNCTIONS -D_USE_ALLREDUCE #-Wall -Wunused-parameter -Wredundant-decls -Wreturn-type -Wswitch-default -Wunused-value -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wimport -Wunused -Wunused-function -Wunused-label -Wno-int-to-pointer-cast -Wbad-function-cast -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wstrict-prototypes -Wpointer-sign -Wextra -Wredundant-decls -Wunused -Wunused-function -Wunused-parameter -Wunused-value -Wunused-variable -Wformat -Wformat-nonliteral -Wparentheses -Wsequence-point -Wuninitialized -Wundef -Wbad-function-cast -Wno-unused-parameter OPT_FLAG_1 = -O1 OPT_FLAG_2 = -O2 CFLAGS = $(COMMON_FLAGS) $(OPT_FLAG_2) LIBRARIES = -lm RM = rm -f objs = axml.o optimizeModel.o trash.o searchAlgo.o topologies.o treeIO.o models.o evaluatePartialGenericSpecial.o evaluateGenericSpecial.o newviewGenericSpecial.o makenewzGenericSpecial.o bipartitionList.o restartHashTable.o byteFile.o partitionAssignment.o communication.o quartets.o all : clean examl GLOBAL_DEPS = axml.h globalVariables.h ../versionHeader/version.h examl : $(objs) $(CC) -o examl $(objs) $(LIBRARIES) models.o : models.c $(GLOBAL_DEPS) $(CC) $(COMMON_FLAGS) $(OPT_FLAG_1) -c -o models.o models.c bipartitionList.o : bipartitionList.c $(GLOBAL_DEPS) evaluatePartialSpecialGeneric.o : evaluatePartialSpecialGeneric.c $(GLOBAL_DEPS) optimizeModel.o : optimizeModel.c $(GLOBAL_DEPS) trash.o : trash.c $(GLOBAL_DEPS) axml.o : axml.c $(GLOBAL_DEPS) searchAlgo.o : searchAlgo.c $(GLOBAL_DEPS) topologies.o : topologies.c $(GLOBAL_DEPS) treeIO.o : treeIO.c $(GLOBAL_DEPS) models.o : models.c $(GLOBAL_DEPS) evaluatePartialGenericSpecial.o : evaluatePartialGenericSpecial.c $(GLOBAL_DEPS) evaluateGenericSpecial.o : evaluateGenericSpecial.c $(GLOBAL_DEPS) newviewGenericSpecial.o : newviewGenericSpecial.c $(GLOBAL_DEPS) makenewzGenericSpecial.o : makenewzGenericSpecial.c $(GLOBAL_DEPS) restartHashTable.o : restartHashTable.c $(GLOBAL_DEPS) byteFile.o : byteFile.c partitionAssignment.o : partitionAssignment.c $(GLOBAL_DEPS) communication.o : communication.c $(GLOBAL_DEPS) quartets.o : quartets.c $(GLOBAL_DEPS) clean : $(RM) *.o examl dev : examl ExaML-3.0.21/examl/avxLikelihood.c000066400000000000000000003174201330315463200166260ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include "axml.h" #include #include #include #include #ifdef _FMA #include #define FMAMACC(a,b,c) _mm256_macc_pd(b,c,a) #endif extern const unsigned int mask32[32]; const union __attribute__ ((aligned (BYTE_ALIGNMENT))) { uint64_t i[4]; __m256d m; } absMask_AVX = {{0x7fffffffffffffffULL, 0x7fffffffffffffffULL, 0x7fffffffffffffffULL, 0x7fffffffffffffffULL}}; static inline __m256d hadd4(__m256d v, __m256d u) { __m256d a, b; v = _mm256_hadd_pd(v, v); a = _mm256_permute2f128_pd(v, v, 1); v = _mm256_add_pd(a, v); u = _mm256_hadd_pd(u, u); b = _mm256_permute2f128_pd(u, u, 1); u = _mm256_add_pd(b, u); v = _mm256_mul_pd(v, u); return v; } static inline __m256d hadd3(__m256d v) { __m256d a; v = _mm256_hadd_pd(v, v); a = _mm256_permute2f128_pd(v, v, 1); v = _mm256_add_pd(a, v); return v; } void newviewGTRGAMMA_AVX(int tipCase, double *x1, double *x2, double *x3, double *extEV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, const int n, double *left, double *right, int *wgt, int *scalerIncrement ) { int i, k, scale, addScale = 0; __m256d minlikelihood_avx = _mm256_set1_pd( minlikelihood ), twoto = _mm256_set1_pd(twotothe256); switch(tipCase) { case TIP_TIP: { double *uX1, umpX1[1024] __attribute__ ((aligned (BYTE_ALIGNMENT))), *uX2, umpX2[1024] __attribute__ ((aligned (BYTE_ALIGNMENT))); for (i = 1; i < 16; i++) { __m256d tv = _mm256_load_pd(&(tipVector[i * 4])); int j; for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { __m256d left1 = _mm256_load_pd(&left[j * 16 + k * 4]); left1 = _mm256_mul_pd(left1, tv); left1 = hadd3(left1); _mm256_store_pd(&umpX1[i * 64 + j * 16 + k * 4], left1); } for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { __m256d left1 = _mm256_load_pd(&right[j * 16 + k * 4]); left1 = _mm256_mul_pd(left1, tv); left1 = hadd3(left1); _mm256_store_pd(&umpX2[i * 64 + j * 16 + k * 4], left1); } } for(i = 0; i < n; i++) { uX1 = &umpX1[64 * tipX1[i]]; uX2 = &umpX2[64 * tipX2[i]]; for(k = 0; k < 4; k++) { __m256d xv = _mm256_setzero_pd(); int l; for(l = 0; l < 4; l++) { __m256d x1v = _mm256_mul_pd(_mm256_load_pd(&uX1[k * 16 + l * 4]), _mm256_load_pd(&uX2[k * 16 + l * 4])); __m256d evv = _mm256_load_pd(&extEV[l * 4]); #ifdef _FMA xv = FMAMACC(xv,x1v,evv); #else xv = _mm256_add_pd(xv, _mm256_mul_pd(x1v, evv)); #endif } _mm256_store_pd(&x3[16 * i + 4 * k], xv); } } } break; case TIP_INNER: { double *uX1, umpX1[1024] __attribute__ ((aligned (BYTE_ALIGNMENT))); for (i = 1; i < 16; i++) { __m256d tv = _mm256_load_pd(&(tipVector[i*4])); int j; for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { __m256d left1 = _mm256_load_pd(&left[j * 16 + k * 4]); left1 = _mm256_mul_pd(left1, tv); left1 = hadd3(left1); _mm256_store_pd(&umpX1[i * 64 + j * 16 + k * 4], left1); } } for(i = 0; i < n; i++) { __m256d xv[4]; scale = 1; uX1 = &umpX1[64 * tipX1[i]]; for(k = 0; k < 4; k++) { __m256d xvr = _mm256_load_pd(&(x2[i * 16 + k * 4])); int l; xv[k] = _mm256_setzero_pd(); for(l = 0; l < 4; l++) { __m256d x1v = _mm256_load_pd(&uX1[k * 16 + l * 4]), x2v = _mm256_mul_pd(xvr, _mm256_load_pd(&right[k * 16 + l * 4])); x2v = hadd3(x2v); x1v = _mm256_mul_pd(x1v, x2v); __m256d evv = _mm256_load_pd(&extEV[l * 4]); #ifdef _FMA xv[k] = FMAMACC(xv[k],x1v,evv); #else xv[k] = _mm256_add_pd(xv[k], _mm256_mul_pd(x1v, evv)); #endif } if(scale) { __m256d v1 = _mm256_and_pd(xv[k], absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) != 15) scale = 0; } } if(scale) { xv[0] = _mm256_mul_pd(xv[0], twoto); xv[1] = _mm256_mul_pd(xv[1], twoto); xv[2] = _mm256_mul_pd(xv[2], twoto); xv[3] = _mm256_mul_pd(xv[3], twoto); addScale += wgt[i]; } _mm256_store_pd(&x3[16 * i], xv[0]); _mm256_store_pd(&x3[16 * i + 4], xv[1]); _mm256_store_pd(&x3[16 * i + 8], xv[2]); _mm256_store_pd(&x3[16 * i + 12], xv[3]); } } break; case INNER_INNER: { for(i = 0; i < n; i++) { __m256d xv[4]; scale = 1; for(k = 0; k < 4; k++) { __m256d xvl = _mm256_load_pd(&(x1[i * 16 + k * 4])), xvr = _mm256_load_pd(&(x2[i * 16 + k * 4])); int l; xv[k] = _mm256_setzero_pd(); for(l = 0; l < 4; l++) { __m256d x1v = _mm256_mul_pd(xvl, _mm256_load_pd(&left[k * 16 + l * 4])), x2v = _mm256_mul_pd(xvr, _mm256_load_pd(&right[k * 16 + l * 4])); x1v = hadd4(x1v, x2v); __m256d evv = _mm256_load_pd(&extEV[l * 4]); xv[k] = _mm256_add_pd(xv[k], _mm256_mul_pd(x1v, evv)); } if(scale) { __m256d v1 = _mm256_and_pd(xv[k], absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) != 15) scale = 0; } } if(scale) { xv[0] = _mm256_mul_pd(xv[0], twoto); xv[1] = _mm256_mul_pd(xv[1], twoto); xv[2] = _mm256_mul_pd(xv[2], twoto); xv[3] = _mm256_mul_pd(xv[3], twoto); addScale += wgt[i]; } _mm256_store_pd(&x3[16 * i], xv[0]); _mm256_store_pd(&x3[16 * i + 4], xv[1]); _mm256_store_pd(&x3[16 * i + 8], xv[2]); _mm256_store_pd(&x3[16 * i + 12], xv[3]); } } break; default: assert(0); } *scalerIncrement = addScale; } void newviewGTRCAT_AVX(int tipCase, double *EV, int *cptr, double *x1_start, double *x2_start, double *x3_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement) { double *le, *ri, *x1, *x2; int i, addScale = 0; __m256d minlikelihood_avx = _mm256_set1_pd( minlikelihood ), twoto = _mm256_set1_pd(twotothe256); switch(tipCase) { case TIP_TIP: for (i = 0; i < n; i++) { int l; le = &left[cptr[i] * 16]; ri = &right[cptr[i] * 16]; x1 = &(tipVector[4 * tipX1[i]]); x2 = &(tipVector[4 * tipX2[i]]); __m256d vv = _mm256_setzero_pd(); for(l = 0; l < 4; l++) { __m256d x1v = _mm256_mul_pd(_mm256_load_pd(x1), _mm256_load_pd(&le[l * 4])), x2v = _mm256_mul_pd(_mm256_load_pd(x2), _mm256_load_pd(&ri[l * 4])); x1v = hadd4(x1v, x2v); __m256d evv = _mm256_load_pd(&EV[l * 4]); #ifdef _FMA vv = FMAMACC(vv,x1v,evv); #else vv = _mm256_add_pd(vv, _mm256_mul_pd(x1v, evv)); #endif } _mm256_store_pd(&x3_start[4 * i], vv); } break; case TIP_INNER: for (i = 0; i < n; i++) { int l; x1 = &(tipVector[4 * tipX1[i]]); x2 = &x2_start[4 * i]; le = &left[cptr[i] * 16]; ri = &right[cptr[i] * 16]; __m256d vv = _mm256_setzero_pd(); for(l = 0; l < 4; l++) { __m256d x1v = _mm256_mul_pd(_mm256_load_pd(x1), _mm256_load_pd(&le[l * 4])), x2v = _mm256_mul_pd(_mm256_load_pd(x2), _mm256_load_pd(&ri[l * 4])); x1v = hadd4(x1v, x2v); __m256d evv = _mm256_load_pd(&EV[l * 4]); #ifdef _FMA vv = FMAMACC(vv,x1v,evv); #else vv = _mm256_add_pd(vv, _mm256_mul_pd(x1v, evv)); #endif } __m256d v1 = _mm256_and_pd(vv, absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) == 15) { vv = _mm256_mul_pd(vv, twoto); addScale += wgt[i]; } _mm256_store_pd(&x3_start[4 * i], vv); } break; case INNER_INNER: for (i = 0; i < n; i++) { int l; x1 = &x1_start[4 * i]; x2 = &x2_start[4 * i]; le = &left[cptr[i] * 16]; ri = &right[cptr[i] * 16]; __m256d vv = _mm256_setzero_pd(); for(l = 0; l < 4; l++) { __m256d x1v = _mm256_mul_pd(_mm256_load_pd(x1), _mm256_load_pd(&le[l * 4])), x2v = _mm256_mul_pd(_mm256_load_pd(x2), _mm256_load_pd(&ri[l * 4])); x1v = hadd4(x1v, x2v); __m256d evv = _mm256_load_pd(&EV[l * 4]); #ifdef _FMA vv = FMAMACC(vv,x1v,evv); #else vv = _mm256_add_pd(vv, _mm256_mul_pd(x1v, evv)); #endif } __m256d v1 = _mm256_and_pd(vv, absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) == 15) { vv = _mm256_mul_pd(vv, twoto); addScale += wgt[i]; } _mm256_store_pd(&x3_start[4 * i], vv); } break; default: assert(0); } *scalerIncrement = addScale; } void newviewGTRCATPROT_AVX(int tipCase, double *extEV, int *cptr, double *x1, double *x2, double *x3, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement) { double *le, *ri, *v, *vl, *vr; int i, l, scale, addScale = 0; #ifdef _FMA int k; #endif switch(tipCase) { case TIP_TIP: { for (i = 0; i < n; i++) { le = &left[cptr[i] * 400]; ri = &right[cptr[i] * 400]; vl = &(tipVector[20 * tipX1[i]]); vr = &(tipVector[20 * tipX2[i]]); v = &x3[20 * i]; __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { __m256d x1v = _mm256_setzero_pd(), x2v = _mm256_setzero_pd(); double *ev = &extEV[l * 20], *lv = &le[l * 20], *rv = &ri[l * 20]; #ifdef _FMA for(k = 0; k < 20; k += 4) { __m256d vlv = _mm256_load_pd(&vl[k]); __m256d lvv = _mm256_load_pd(&lv[k]); x1v = FMAMACC(x1v,vlv,lvv); __m256d vrv = _mm256_load_pd(&vr[k]); __m256d rvv = _mm256_load_pd(&rv[k]); x2v = FMAMACC(x2v,vrv,rvv); } #else x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[0]), _mm256_load_pd(&lv[0]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[4]), _mm256_load_pd(&lv[4]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[8]), _mm256_load_pd(&lv[8]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[12]), _mm256_load_pd(&lv[12]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[16]), _mm256_load_pd(&lv[16]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[0]), _mm256_load_pd(&rv[0]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[4]), _mm256_load_pd(&rv[4]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[8]), _mm256_load_pd(&rv[8]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[12]), _mm256_load_pd(&rv[12]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[16]), _mm256_load_pd(&rv[16]))); #endif x1v = hadd4(x1v, x2v); #ifdef _FMA for(k = 0; k < 5; k++) { __m256d evv = _mm256_load_pd(&ev[k*4]); vv[k] = FMAMACC(vv[k],x1v,evv); } #else __m256d evv[5]; evv[0] = _mm256_load_pd(&ev[0]); evv[1] = _mm256_load_pd(&ev[4]); evv[2] = _mm256_load_pd(&ev[8]); evv[3] = _mm256_load_pd(&ev[12]); evv[4] = _mm256_load_pd(&ev[16]); vv[0] = _mm256_add_pd(vv[0], _mm256_mul_pd(x1v, evv[0])); vv[1] = _mm256_add_pd(vv[1], _mm256_mul_pd(x1v, evv[1])); vv[2] = _mm256_add_pd(vv[2], _mm256_mul_pd(x1v, evv[2])); vv[3] = _mm256_add_pd(vv[3], _mm256_mul_pd(x1v, evv[3])); vv[4] = _mm256_add_pd(vv[4], _mm256_mul_pd(x1v, evv[4])); #endif } _mm256_store_pd(&v[0], vv[0]); _mm256_store_pd(&v[4], vv[1]); _mm256_store_pd(&v[8], vv[2]); _mm256_store_pd(&v[12], vv[3]); _mm256_store_pd(&v[16], vv[4]); } } break; case TIP_INNER: for (i = 0; i < n; i++) { le = &left[cptr[i] * 400]; ri = &right[cptr[i] * 400]; vl = &(tipVector[20 * tipX1[i]]); vr = &x2[20 * i]; v = &x3[20 * i]; __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { __m256d x1v = _mm256_setzero_pd(), x2v = _mm256_setzero_pd(); double *ev = &extEV[l * 20], *lv = &le[l * 20], *rv = &ri[l * 20]; #ifdef _FMA for(k = 0; k < 20; k += 4) { __m256d vlv = _mm256_load_pd(&vl[k]); __m256d lvv = _mm256_load_pd(&lv[k]); x1v = FMAMACC(x1v,vlv,lvv); __m256d vrv = _mm256_load_pd(&vr[k]); __m256d rvv = _mm256_load_pd(&rv[k]); x2v = FMAMACC(x2v,vrv,rvv); } #else x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[0]), _mm256_load_pd(&lv[0]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[4]), _mm256_load_pd(&lv[4]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[8]), _mm256_load_pd(&lv[8]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[12]), _mm256_load_pd(&lv[12]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[16]), _mm256_load_pd(&lv[16]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[0]), _mm256_load_pd(&rv[0]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[4]), _mm256_load_pd(&rv[4]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[8]), _mm256_load_pd(&rv[8]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[12]), _mm256_load_pd(&rv[12]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[16]), _mm256_load_pd(&rv[16]))); #endif x1v = hadd4(x1v, x2v); __m256d evv[5]; evv[0] = _mm256_load_pd(&ev[0]); evv[1] = _mm256_load_pd(&ev[4]); evv[2] = _mm256_load_pd(&ev[8]); evv[3] = _mm256_load_pd(&ev[12]); evv[4] = _mm256_load_pd(&ev[16]); #ifdef _FMA for(k = 0; k < 5; k++) vv[k] = FMAMACC(vv[k],x1v,evv[k]); #else vv[0] = _mm256_add_pd(vv[0], _mm256_mul_pd(x1v, evv[0])); vv[1] = _mm256_add_pd(vv[1], _mm256_mul_pd(x1v, evv[1])); vv[2] = _mm256_add_pd(vv[2], _mm256_mul_pd(x1v, evv[2])); vv[3] = _mm256_add_pd(vv[3], _mm256_mul_pd(x1v, evv[3])); vv[4] = _mm256_add_pd(vv[4], _mm256_mul_pd(x1v, evv[4])); #endif } __m256d minlikelihood_avx = _mm256_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 20); l += 4) { __m256d v1 = _mm256_and_pd(vv[l / 4], absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) != 15) scale = 0; } if(scale) { __m256d twoto = _mm256_set1_pd(twotothe256); for(l = 0; l < 20; l += 4) vv[l / 4] = _mm256_mul_pd(vv[l / 4] , twoto); addScale += wgt[i]; } _mm256_store_pd(&v[0], vv[0]); _mm256_store_pd(&v[4], vv[1]); _mm256_store_pd(&v[8], vv[2]); _mm256_store_pd(&v[12], vv[3]); _mm256_store_pd(&v[16], vv[4]); } break; case INNER_INNER: for(i = 0; i < n; i++) { le = &left[cptr[i] * 400]; ri = &right[cptr[i] * 400]; vl = &x1[20 * i]; vr = &x2[20 * i]; v = &x3[20 * i]; __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { __m256d x1v = _mm256_setzero_pd(), x2v = _mm256_setzero_pd(); double *ev = &extEV[l * 20], *lv = &le[l * 20], *rv = &ri[l * 20]; x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[0]), _mm256_load_pd(&lv[0]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[4]), _mm256_load_pd(&lv[4]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[8]), _mm256_load_pd(&lv[8]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[12]), _mm256_load_pd(&lv[12]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[16]), _mm256_load_pd(&lv[16]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[0]), _mm256_load_pd(&rv[0]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[4]), _mm256_load_pd(&rv[4]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[8]), _mm256_load_pd(&rv[8]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[12]), _mm256_load_pd(&rv[12]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[16]), _mm256_load_pd(&rv[16]))); x1v = hadd4(x1v, x2v); #ifdef _FMA for(k = 0; k < 5; k++) { __m256d evv = _mm256_load_pd(&ev[k*4]); vv[k] = FMAMACC(vv[k],x1v,evv); } #else __m256d evv[5]; evv[0] = _mm256_load_pd(&ev[0]); evv[1] = _mm256_load_pd(&ev[4]); evv[2] = _mm256_load_pd(&ev[8]); evv[3] = _mm256_load_pd(&ev[12]); evv[4] = _mm256_load_pd(&ev[16]); vv[0] = _mm256_add_pd(vv[0], _mm256_mul_pd(x1v, evv[0])); vv[1] = _mm256_add_pd(vv[1], _mm256_mul_pd(x1v, evv[1])); vv[2] = _mm256_add_pd(vv[2], _mm256_mul_pd(x1v, evv[2])); vv[3] = _mm256_add_pd(vv[3], _mm256_mul_pd(x1v, evv[3])); vv[4] = _mm256_add_pd(vv[4], _mm256_mul_pd(x1v, evv[4])); #endif } __m256d minlikelihood_avx = _mm256_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 20); l += 4) { __m256d v1 = _mm256_and_pd(vv[l / 4], absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) != 15) scale = 0; } if(scale) { __m256d twoto = _mm256_set1_pd(twotothe256); for(l = 0; l < 20; l += 4) vv[l / 4] = _mm256_mul_pd(vv[l / 4] , twoto); addScale += wgt[i]; } _mm256_store_pd(&v[0], vv[0]); _mm256_store_pd(&v[4], vv[1]); _mm256_store_pd(&v[8], vv[2]); _mm256_store_pd(&v[12], vv[3]); _mm256_store_pd(&v[16], vv[4]); } break; default: assert(0); } *scalerIncrement = addScale; } void newviewGTRGAMMAPROT_AVX_LG4(int tipCase, double *x1, double *x2, double *x3, double *extEV[4], double *tipVector[4], int *ex3, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling) { double *uX1, *uX2, *v, x1px2, *vl, *vr; int i, j, l, k, scale, addScale = 0; #ifndef GCC_VERSION #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #endif #if GCC_VERSION < 40500 __m256d bitmask = _mm256_set_pd(0,0,0,-1); #else __m256i bitmask = _mm256_set_epi32(0, 0, 0, 0, 0, 0, -1, -1); #endif switch(tipCase) { case TIP_TIP: { double umpX1[1840] __attribute__ ((aligned (BYTE_ALIGNMENT))), umpX2[1840] __attribute__ ((aligned (BYTE_ALIGNMENT))); for(i = 0; i < 23; i++) { for(k = 0; k < 80; k++) { double *ll = &left[k * 20], *rr = &right[k * 20]; __m256d umpX1v = _mm256_setzero_pd(), umpX2v = _mm256_setzero_pd(); v = &(tipVector[k / 20][20 * i]); for(l = 0; l < 20; l+=4) { __m256d vv = _mm256_load_pd(&v[l]); #ifdef _FMA __m256d llv = _mm256_load_pd(&ll[l]); umpX1v = FMAMACC(umpX1v,vv,llv); __m256d rrv = _mm256_load_pd(&rr[l]); umpX2v = FMAMACC(umpX2v,vv,rrv); #else umpX1v = _mm256_add_pd(umpX1v,_mm256_mul_pd(vv,_mm256_load_pd(&ll[l]))); umpX2v = _mm256_add_pd(umpX2v,_mm256_mul_pd(vv,_mm256_load_pd(&rr[l]))); #endif } umpX1v = hadd3(umpX1v); umpX2v = hadd3(umpX2v); _mm256_maskstore_pd(&umpX1[80 * i + k], bitmask, umpX1v); _mm256_maskstore_pd(&umpX2[80 * i + k], bitmask, umpX2v); } } for(i = 0; i < n; i++) { uX1 = &umpX1[80 * tipX1[i]]; uX2 = &umpX2[80 * tipX2[i]]; for(j = 0; j < 4; j++) { __m256d vv[5]; v = &x3[i * 80 + j * 20]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(k = 0; k < 20; k++) { x1px2 = uX1[j * 20 + k] * uX2[j * 20 + k]; __m256d x1px2v = _mm256_set1_pd(x1px2); __m256d extEvv = _mm256_load_pd(&extEV[j][20 * k]); #ifdef _FMA vv[0] = FMAMACC(vv[0],x1px2v,extEvv); #else vv[0] = _mm256_add_pd(vv[0],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[0],vv[0]); extEvv = _mm256_load_pd(&extEV[j][20 * k + 4]); #ifdef _FMA vv[1] = FMAMACC(vv[1],x1px2v,extEvv); #else vv[1] = _mm256_add_pd(vv[1],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[4],vv[1]); extEvv = _mm256_load_pd(&extEV[j][20 * k + 8]); #ifdef _FMA vv[2] = FMAMACC(vv[2],x1px2v,extEvv); #else vv[2] = _mm256_add_pd(vv[2],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[8],vv[2]); extEvv = _mm256_load_pd(&extEV[j][20 * k + 12]); #ifdef _FMA vv[3] = FMAMACC(vv[3],x1px2v,extEvv); #else vv[3] = _mm256_add_pd(vv[3],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[12],vv[3]); extEvv = _mm256_load_pd(&extEV[j][20 * k + 16]); #ifdef _FMA vv[4] = FMAMACC(vv[4],x1px2v,extEvv); #else vv[4] = _mm256_add_pd(vv[4],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[16],vv[4]); } } } } break; case TIP_INNER: { double umpX1[1840] __attribute__ ((aligned (BYTE_ALIGNMENT))), ump_x2[20] __attribute__ ((aligned (BYTE_ALIGNMENT))); for(i = 0; i < 23; i++) { for(k = 0; k < 80; k++) { __m256d umpX1v = _mm256_setzero_pd(); v = &(tipVector[k / 20][20 * i]); for(l = 0; l < 20; l+=4) { __m256d vv = _mm256_load_pd(&v[l]); __m256d leftv = _mm256_load_pd(&left[k * 20 + l]); #ifdef _FMA umpX1v = FMAMACC(umpX1v, vv, leftv); #else umpX1v = _mm256_add_pd(umpX1v, _mm256_mul_pd(vv, leftv)); #endif } umpX1v = hadd3(umpX1v); _mm256_maskstore_pd(&umpX1[80 * i + k], bitmask, umpX1v); } } for (i = 0; i < n; i++) { uX1 = &umpX1[80 * tipX1[i]]; for(k = 0; k < 4; k++) { v = &(x2[80 * i + k * 20]); for(l = 0; l < 20; l++) { __m256d ump_x2v = _mm256_setzero_pd(); __m256d vv = _mm256_load_pd(&v[0]); __m256d rightv = _mm256_load_pd(&right[k*400+l*20+0]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[4]); rightv = _mm256_load_pd(&right[k*400+l*20+4]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[8]); rightv = _mm256_load_pd(&right[k*400+l*20+8]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[12]); rightv = _mm256_load_pd(&right[k*400+l*20+12]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[16]); rightv = _mm256_load_pd(&right[k*400+l*20+16]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif ump_x2v = hadd3(ump_x2v); _mm256_maskstore_pd(&ump_x2[l], bitmask, ump_x2v); } v = &(x3[80 * i + 20 * k]); __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { x1px2 = uX1[k * 20 + l] * ump_x2[l]; __m256d x1px2v = _mm256_set1_pd(x1px2); #ifdef _FMA __m256d ev = _mm256_load_pd(&extEV[l * 20 + 0]); vv[0] = FMAMACC(vv[0],x1px2v, ev); #else vv[0] = _mm256_add_pd(vv[0],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[k][l * 20 + 0]))); #endif _mm256_store_pd(&v[0],vv[0]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 4]); vv[1] = FMAMACC(vv[1],x1px2v, ev); #else vv[1] = _mm256_add_pd(vv[1],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[k][l * 20 + 4]))); #endif _mm256_store_pd(&v[4],vv[1]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 8]); vv[2] = FMAMACC(vv[2],x1px2v, ev); #else vv[2] = _mm256_add_pd(vv[2],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[k][l * 20 + 8]))); #endif _mm256_store_pd(&v[8],vv[2]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 12]); vv[3] = FMAMACC(vv[3],x1px2v, ev); #else vv[3] = _mm256_add_pd(vv[3],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[k][l * 20 + 12]))); #endif _mm256_store_pd(&v[12],vv[3]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 16]); vv[4] = FMAMACC(vv[4],x1px2v, ev); #else vv[4] = _mm256_add_pd(vv[4],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[k][l * 20 + 16]))); #endif _mm256_store_pd(&v[16],vv[4]); } } v = &x3[80 * i]; __m256d minlikelihood_avx = _mm256_set1_pd(minlikelihood); scale = 1; for(l = 0; scale && (l < 80); l += 4) { __m256d vv = _mm256_load_pd(&v[l]); __m256d vv_abs = _mm256_and_pd(vv,absMask_AVX.m); vv_abs = _mm256_cmp_pd(vv_abs,minlikelihood_avx,_CMP_LT_OS); if(_mm256_movemask_pd(vv_abs) != 15) scale = 0; } if(scale) { __m256d twotothe256v = _mm256_set_pd(twotothe256,twotothe256,twotothe256,twotothe256); for(l = 0; l < 80; l += 4) { __m256d vv = _mm256_load_pd(&v[l]); _mm256_store_pd(&v[l],_mm256_mul_pd(vv,twotothe256v)); } if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } } break; case INNER_INNER: for(i = 0; i < n; i++) { scale = 1; for(k = 0; k < 4; k++) { vl = &(x1[80 * i + 20 * k]); vr = &(x2[80 * i + 20 * k]); v = &(x3[80 * i + 20 * k]); __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { __m256d al = _mm256_setzero_pd(); __m256d ar = _mm256_setzero_pd(); __m256d leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 0]); __m256d rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 0]); __m256d vlv = _mm256_load_pd(&vl[0]); __m256d vrv = _mm256_load_pd(&vr[0]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 4]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 4]); vlv = _mm256_load_pd(&vl[4]); vrv = _mm256_load_pd(&vr[4]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 8]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 8]); vlv = _mm256_load_pd(&vl[8]); vrv = _mm256_load_pd(&vr[8]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 12]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 12]); vlv = _mm256_load_pd(&vl[12]); vrv = _mm256_load_pd(&vr[12]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 16]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 16]); vlv = _mm256_load_pd(&vl[16]); vrv = _mm256_load_pd(&vr[16]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif /**************************************************************************************************************/ al = hadd3(al); ar = hadd3(ar); al = _mm256_mul_pd(ar,al); /************************************************************************************************************/ #ifdef _FMA __m256d ev = _mm256_load_pd(&extEV[20 * l + 0]); vv[0] = FMAMACC(vv[0], al, ev); #else vv[0] = _mm256_add_pd(vv[0],_mm256_mul_pd(al, _mm256_load_pd(&extEV[k][20 * l + 0]))); #endif _mm256_store_pd(&v[0],vv[0]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 4]); vv[1] = FMAMACC(vv[1], al, ev); #else vv[1] = _mm256_add_pd(vv[1],_mm256_mul_pd(al, _mm256_load_pd(&extEV[k][20 * l + 4]))); #endif _mm256_store_pd(&v[4],vv[1]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 8]); vv[2] = FMAMACC(vv[2], al, ev); #else vv[2] = _mm256_add_pd(vv[2],_mm256_mul_pd(al, _mm256_load_pd(&extEV[k][20 * l + 8]))); #endif _mm256_store_pd(&v[8],vv[2]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 12]); vv[3] = FMAMACC(vv[3], al, ev); #else vv[3] = _mm256_add_pd(vv[3],_mm256_mul_pd(al, _mm256_load_pd(&extEV[k][20 * l + 12]))); #endif _mm256_store_pd(&v[12],vv[3]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 16]); vv[4] = FMAMACC(vv[4], al, ev); #else vv[4] = _mm256_add_pd(vv[4],_mm256_mul_pd(al, _mm256_load_pd(&extEV[k][20 * l + 16]))); #endif _mm256_store_pd(&v[16],vv[4]); } } v = &(x3[80 * i]); scale = 1; __m256d minlikelihood_avx = _mm256_set1_pd(minlikelihood); for(l = 0; scale && (l < 80); l += 4) { __m256d vv = _mm256_load_pd(&v[l]); __m256d vv_abs = _mm256_and_pd(vv,absMask_AVX.m); vv_abs = _mm256_cmp_pd(vv_abs,minlikelihood_avx,_CMP_LT_OS); if(_mm256_movemask_pd(vv_abs) != 15) scale = 0; } if(scale) { __m256d twotothe256v = _mm256_set_pd(twotothe256,twotothe256,twotothe256,twotothe256); for(l = 0; l < 80; l += 4) { __m256d vv = _mm256_load_pd(&v[l]); _mm256_store_pd(&v[l],_mm256_mul_pd(vv,twotothe256v)); } if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } break; default: assert(0); } if(useFastScaling) *scalerIncrement = addScale; } void newviewGTRGAMMAPROT_AVX(int tipCase, double *x1, double *x2, double *x3, double *extEV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement) { double *uX1, *uX2, *v, x1px2, *vl, *vr; int i, j, l, k, scale, addScale = 0; #ifndef GCC_VERSION #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #endif #if GCC_VERSION < 40500 __m256d bitmask = _mm256_set_pd(0,0,0,-1); #else __m256i bitmask = _mm256_set_epi32(0, 0, 0, 0, 0, 0, -1, -1); #endif switch(tipCase) { case TIP_TIP: { double umpX1[1840] __attribute__ ((aligned (BYTE_ALIGNMENT))), umpX2[1840] __attribute__ ((aligned (BYTE_ALIGNMENT))); for(i = 0; i < 23; i++) { v = &(tipVector[20 * i]); for(k = 0; k < 80; k++) { double *ll = &left[k * 20], *rr = &right[k * 20]; __m256d umpX1v = _mm256_setzero_pd(), umpX2v = _mm256_setzero_pd(); for(l = 0; l < 20; l+=4) { __m256d vv = _mm256_load_pd(&v[l]); #ifdef _FMA __m256d llv = _mm256_load_pd(&ll[l]); umpX1v = FMAMACC(umpX1v,vv,llv); __m256d rrv = _mm256_load_pd(&rr[l]); umpX2v = FMAMACC(umpX2v,vv,rrv); #else umpX1v = _mm256_add_pd(umpX1v,_mm256_mul_pd(vv,_mm256_load_pd(&ll[l]))); umpX2v = _mm256_add_pd(umpX2v,_mm256_mul_pd(vv,_mm256_load_pd(&rr[l]))); #endif } umpX1v = hadd3(umpX1v); umpX2v = hadd3(umpX2v); _mm256_maskstore_pd(&umpX1[80 * i + k], bitmask, umpX1v); _mm256_maskstore_pd(&umpX2[80 * i + k], bitmask, umpX2v); } } for(i = 0; i < n; i++) { uX1 = &umpX1[80 * tipX1[i]]; uX2 = &umpX2[80 * tipX2[i]]; for(j = 0; j < 4; j++) { __m256d vv[5]; v = &x3[i * 80 + j * 20]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(k = 0; k < 20; k++) { x1px2 = uX1[j * 20 + k] * uX2[j * 20 + k]; __m256d x1px2v = _mm256_set1_pd(x1px2); __m256d extEvv = _mm256_load_pd(&extEV[20 * k]); #ifdef _FMA vv[0] = FMAMACC(vv[0],x1px2v,extEvv); #else vv[0] = _mm256_add_pd(vv[0],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[0],vv[0]); extEvv = _mm256_load_pd(&extEV[20 * k + 4]); #ifdef _FMA vv[1] = FMAMACC(vv[1],x1px2v,extEvv); #else vv[1] = _mm256_add_pd(vv[1],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[4],vv[1]); extEvv = _mm256_load_pd(&extEV[20 * k + 8]); #ifdef _FMA vv[2] = FMAMACC(vv[2],x1px2v,extEvv); #else vv[2] = _mm256_add_pd(vv[2],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[8],vv[2]); extEvv = _mm256_load_pd(&extEV[20 * k + 12]); #ifdef _FMA vv[3] = FMAMACC(vv[3],x1px2v,extEvv); #else vv[3] = _mm256_add_pd(vv[3],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[12],vv[3]); extEvv = _mm256_load_pd(&extEV[20 * k + 16]); #ifdef _FMA vv[4] = FMAMACC(vv[4],x1px2v,extEvv); #else vv[4] = _mm256_add_pd(vv[4],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[16],vv[4]); } } } } break; case TIP_INNER: { double umpX1[1840] __attribute__ ((aligned (BYTE_ALIGNMENT))), ump_x2[20] __attribute__ ((aligned (BYTE_ALIGNMENT))); for(i = 0; i < 23; i++) { v = &(tipVector[20 * i]); for(k = 0; k < 80; k++) { __m256d umpX1v = _mm256_setzero_pd(); for(l = 0; l < 20; l+=4) { __m256d vv = _mm256_load_pd(&v[l]); __m256d leftv = _mm256_load_pd(&left[k * 20 + l]); #ifdef _FMA umpX1v = FMAMACC(umpX1v, vv, leftv); #else umpX1v = _mm256_add_pd(umpX1v, _mm256_mul_pd(vv, leftv)); #endif } umpX1v = hadd3(umpX1v); _mm256_maskstore_pd(&umpX1[80 * i + k], bitmask, umpX1v); } } for (i = 0; i < n; i++) { uX1 = &umpX1[80 * tipX1[i]]; for(k = 0; k < 4; k++) { v = &(x2[80 * i + k * 20]); for(l = 0; l < 20; l++) { __m256d ump_x2v = _mm256_setzero_pd(); __m256d vv = _mm256_load_pd(&v[0]); __m256d rightv = _mm256_load_pd(&right[k*400+l*20+0]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[4]); rightv = _mm256_load_pd(&right[k*400+l*20+4]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[8]); rightv = _mm256_load_pd(&right[k*400+l*20+8]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[12]); rightv = _mm256_load_pd(&right[k*400+l*20+12]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[16]); rightv = _mm256_load_pd(&right[k*400+l*20+16]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif ump_x2v = hadd3(ump_x2v); _mm256_maskstore_pd(&ump_x2[l], bitmask, ump_x2v); } v = &(x3[80 * i + 20 * k]); __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { x1px2 = uX1[k * 20 + l] * ump_x2[l]; __m256d x1px2v = _mm256_set1_pd(x1px2); #ifdef _FMA __m256d ev = _mm256_load_pd(&extEV[l * 20 + 0]); vv[0] = FMAMACC(vv[0],x1px2v, ev); #else vv[0] = _mm256_add_pd(vv[0],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 0]))); #endif _mm256_store_pd(&v[0],vv[0]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 4]); vv[1] = FMAMACC(vv[1],x1px2v, ev); #else vv[1] = _mm256_add_pd(vv[1],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 4]))); #endif _mm256_store_pd(&v[4],vv[1]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 8]); vv[2] = FMAMACC(vv[2],x1px2v, ev); #else vv[2] = _mm256_add_pd(vv[2],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 8]))); #endif _mm256_store_pd(&v[8],vv[2]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 12]); vv[3] = FMAMACC(vv[3],x1px2v, ev); #else vv[3] = _mm256_add_pd(vv[3],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 12]))); #endif _mm256_store_pd(&v[12],vv[3]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 16]); vv[4] = FMAMACC(vv[4],x1px2v, ev); #else vv[4] = _mm256_add_pd(vv[4],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 16]))); #endif _mm256_store_pd(&v[16],vv[4]); } } v = &x3[80 * i]; __m256d minlikelihood_avx = _mm256_set1_pd(minlikelihood); scale = 1; for(l = 0; scale && (l < 80); l += 4) { __m256d vv = _mm256_load_pd(&v[l]); __m256d vv_abs = _mm256_and_pd(vv,absMask_AVX.m); vv_abs = _mm256_cmp_pd(vv_abs,minlikelihood_avx,_CMP_LT_OS); if(_mm256_movemask_pd(vv_abs) != 15) scale = 0; } if(scale) { __m256d twotothe256v = _mm256_set_pd(twotothe256,twotothe256,twotothe256,twotothe256); for(l = 0; l < 80; l += 4) { __m256d vv = _mm256_load_pd(&v[l]); _mm256_store_pd(&v[l],_mm256_mul_pd(vv,twotothe256v)); } addScale += wgt[i]; } } } break; case INNER_INNER: for(i = 0; i < n; i++) { scale = 1; for(k = 0; k < 4; k++) { vl = &(x1[80 * i + 20 * k]); vr = &(x2[80 * i + 20 * k]); v = &(x3[80 * i + 20 * k]); __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { __m256d al = _mm256_setzero_pd(); __m256d ar = _mm256_setzero_pd(); __m256d leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 0]); __m256d rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 0]); __m256d vlv = _mm256_load_pd(&vl[0]); __m256d vrv = _mm256_load_pd(&vr[0]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 4]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 4]); vlv = _mm256_load_pd(&vl[4]); vrv = _mm256_load_pd(&vr[4]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 8]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 8]); vlv = _mm256_load_pd(&vl[8]); vrv = _mm256_load_pd(&vr[8]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 12]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 12]); vlv = _mm256_load_pd(&vl[12]); vrv = _mm256_load_pd(&vr[12]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 16]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 16]); vlv = _mm256_load_pd(&vl[16]); vrv = _mm256_load_pd(&vr[16]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif /**************************************************************************************************************/ al = hadd3(al); ar = hadd3(ar); al = _mm256_mul_pd(ar,al); /************************************************************************************************************/ #ifdef _FMA __m256d ev = _mm256_load_pd(&extEV[20 * l + 0]); vv[0] = FMAMACC(vv[0], al, ev); #else vv[0] = _mm256_add_pd(vv[0],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 0]))); #endif _mm256_store_pd(&v[0],vv[0]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 4]); vv[1] = FMAMACC(vv[1], al, ev); #else vv[1] = _mm256_add_pd(vv[1],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 4]))); #endif _mm256_store_pd(&v[4],vv[1]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 8]); vv[2] = FMAMACC(vv[2], al, ev); #else vv[2] = _mm256_add_pd(vv[2],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 8]))); #endif _mm256_store_pd(&v[8],vv[2]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 12]); vv[3] = FMAMACC(vv[3], al, ev); #else vv[3] = _mm256_add_pd(vv[3],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 12]))); #endif _mm256_store_pd(&v[12],vv[3]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 16]); vv[4] = FMAMACC(vv[4], al, ev); #else vv[4] = _mm256_add_pd(vv[4],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 16]))); #endif _mm256_store_pd(&v[16],vv[4]); } } v = &(x3[80 * i]); scale = 1; __m256d minlikelihood_avx = _mm256_set1_pd(minlikelihood); for(l = 0; scale && (l < 80); l += 4) { __m256d vv = _mm256_load_pd(&v[l]); __m256d vv_abs = _mm256_and_pd(vv,absMask_AVX.m); vv_abs = _mm256_cmp_pd(vv_abs,minlikelihood_avx,_CMP_LT_OS); if(_mm256_movemask_pd(vv_abs) != 15) scale = 0; } if(scale) { __m256d twotothe256v = _mm256_set_pd(twotothe256,twotothe256,twotothe256,twotothe256); for(l = 0; l < 80; l += 4) { __m256d vv = _mm256_load_pd(&v[l]); _mm256_store_pd(&v[l],_mm256_mul_pd(vv,twotothe256v)); } addScale += wgt[i]; } } break; default: assert(0); } *scalerIncrement = addScale; } /***** functions with memory saving ******************************/ void newviewGTRGAMMA_AVX_GAPPED_SAVE(int tipCase, double *x1_start, double *x2_start, double *x3_start, double *extEV, double *tipVector, int *ex3, unsigned char *tipX1, unsigned char *tipX2, const int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn ) { int i, k, scale, scaleGap, addScale = 0; __m256d minlikelihood_avx = _mm256_set1_pd( minlikelihood ), twoto = _mm256_set1_pd(twotothe256); double *x1, *x2, *x3, *x1_ptr = x1_start, *x2_ptr = x2_start; switch(tipCase) { case TIP_TIP: { double *uX1, umpX1[1024] __attribute__ ((aligned (BYTE_ALIGNMENT))), *uX2, umpX2[1024] __attribute__ ((aligned (BYTE_ALIGNMENT))); for (i = 1; i < 16; i++) { __m256d tv = _mm256_load_pd(&(tipVector[i * 4])); int j; for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { __m256d left1 = _mm256_load_pd(&left[j * 16 + k * 4]); left1 = _mm256_mul_pd(left1, tv); left1 = hadd3(left1); _mm256_store_pd(&umpX1[i * 64 + j * 16 + k * 4], left1); } for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { __m256d left1 = _mm256_load_pd(&right[j * 16 + k * 4]); left1 = _mm256_mul_pd(left1, tv); left1 = hadd3(left1); _mm256_store_pd(&umpX2[i * 64 + j * 16 + k * 4], left1); } } x3 = x3_gapColumn; { uX1 = &umpX1[960]; uX2 = &umpX2[960]; for(k = 0; k < 4; k++) { __m256d xv = _mm256_setzero_pd(); int l; for(l = 0; l < 4; l++) { __m256d x1v = _mm256_mul_pd(_mm256_load_pd(&uX1[k * 16 + l * 4]), _mm256_load_pd(&uX2[k * 16 + l * 4])); __m256d evv = _mm256_load_pd(&extEV[l * 4]); #ifdef _FMA xv = FMAMACC(xv,x1v,evv); #else xv = _mm256_add_pd(xv, _mm256_mul_pd(x1v, evv)); #endif } _mm256_store_pd(&x3[4 * k], xv); } } x3 = x3_start; for(i = 0; i < n; i++) { if(!(x3_gap[i / 32] & mask32[i % 32])) { uX1 = &umpX1[64 * tipX1[i]]; uX2 = &umpX2[64 * tipX2[i]]; for(k = 0; k < 4; k++) { __m256d xv = _mm256_setzero_pd(); int l; for(l = 0; l < 4; l++) { __m256d x1v = _mm256_mul_pd(_mm256_load_pd(&uX1[k * 16 + l * 4]), _mm256_load_pd(&uX2[k * 16 + l * 4])); __m256d evv = _mm256_load_pd(&extEV[l * 4]); #ifdef _FMA xv = FMAMACC(xv,x1v,evv); #else xv = _mm256_add_pd(xv, _mm256_mul_pd(x1v, evv)); #endif } _mm256_store_pd(&x3[4 * k], xv); } x3 += 16; } } } break; case TIP_INNER: { double *uX1, umpX1[1024] __attribute__ ((aligned (BYTE_ALIGNMENT))); for (i = 1; i < 16; i++) { __m256d tv = _mm256_load_pd(&(tipVector[i*4])); int j; for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { __m256d left1 = _mm256_load_pd(&left[j * 16 + k * 4]); left1 = _mm256_mul_pd(left1, tv); left1 = hadd3(left1); _mm256_store_pd(&umpX1[i * 64 + j * 16 + k * 4], left1); } } { __m256d xv[4]; scaleGap = 1; uX1 = &umpX1[960]; x2 = x2_gapColumn; x3 = x3_gapColumn; for(k = 0; k < 4; k++) { __m256d xvr = _mm256_load_pd(&(x2[k * 4])); int l; xv[k] = _mm256_setzero_pd(); for(l = 0; l < 4; l++) { __m256d x1v = _mm256_load_pd(&uX1[k * 16 + l * 4]), x2v = _mm256_mul_pd(xvr, _mm256_load_pd(&right[k * 16 + l * 4])); x2v = hadd3(x2v); x1v = _mm256_mul_pd(x1v, x2v); __m256d evv = _mm256_load_pd(&extEV[l * 4]); #ifdef _FMA xv[k] = FMAMACC(xv[k],x1v,evv); #else xv[k] = _mm256_add_pd(xv[k], _mm256_mul_pd(x1v, evv)); #endif } if(scaleGap) { __m256d v1 = _mm256_and_pd(xv[k], absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) != 15) scaleGap = 0; } } if(scaleGap) { xv[0] = _mm256_mul_pd(xv[0], twoto); xv[1] = _mm256_mul_pd(xv[1], twoto); xv[2] = _mm256_mul_pd(xv[2], twoto); xv[3] = _mm256_mul_pd(xv[3], twoto); } _mm256_store_pd(&x3[0], xv[0]); _mm256_store_pd(&x3[4], xv[1]); _mm256_store_pd(&x3[8], xv[2]); _mm256_store_pd(&x3[12], xv[3]); } x3 = x3_start; for(i = 0; i < n; i++) { if((x3_gap[i / 32] & mask32[i % 32])) { if(scaleGap) { if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } else { if(x2_gap[i / 32] & mask32[i % 32]) x2 = x2_gapColumn; else { x2 = x2_ptr; x2_ptr += 16; } __m256d xv[4]; scale = 1; uX1 = &umpX1[64 * tipX1[i]]; for(k = 0; k < 4; k++) { __m256d xvr = _mm256_load_pd(&(x2[k * 4])); int l; xv[k] = _mm256_setzero_pd(); for(l = 0; l < 4; l++) { __m256d x1v = _mm256_load_pd(&uX1[k * 16 + l * 4]), x2v = _mm256_mul_pd(xvr, _mm256_load_pd(&right[k * 16 + l * 4])); x2v = hadd3(x2v); x1v = _mm256_mul_pd(x1v, x2v); __m256d evv = _mm256_load_pd(&extEV[l * 4]); #ifdef _FMA xv[k] = FMAMACC(xv[k],x1v,evv); #else xv[k] = _mm256_add_pd(xv[k], _mm256_mul_pd(x1v, evv)); #endif } if(scale) { __m256d v1 = _mm256_and_pd(xv[k], absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) != 15) scale = 0; } } if(scale) { xv[0] = _mm256_mul_pd(xv[0], twoto); xv[1] = _mm256_mul_pd(xv[1], twoto); xv[2] = _mm256_mul_pd(xv[2], twoto); xv[3] = _mm256_mul_pd(xv[3], twoto); if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } _mm256_store_pd(&x3[0], xv[0]); _mm256_store_pd(&x3[4], xv[1]); _mm256_store_pd(&x3[8], xv[2]); _mm256_store_pd(&x3[12], xv[3]); x3 += 16; } } } break; case INNER_INNER: { { x1 = x1_gapColumn; x2 = x2_gapColumn; x3 = x3_gapColumn; __m256d xv[4]; scaleGap = 1; for(k = 0; k < 4; k++) { __m256d xvl = _mm256_load_pd(&(x1[k * 4])), xvr = _mm256_load_pd(&(x2[k * 4])); int l; xv[k] = _mm256_setzero_pd(); for(l = 0; l < 4; l++) { __m256d x1v = _mm256_mul_pd(xvl, _mm256_load_pd(&left[k * 16 + l * 4])), x2v = _mm256_mul_pd(xvr, _mm256_load_pd(&right[k * 16 + l * 4])); x1v = hadd4(x1v, x2v); __m256d evv = _mm256_load_pd(&extEV[l * 4]); xv[k] = _mm256_add_pd(xv[k], _mm256_mul_pd(x1v, evv)); } if(scaleGap) { __m256d v1 = _mm256_and_pd(xv[k], absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) != 15) scaleGap = 0; } } if(scaleGap) { xv[0] = _mm256_mul_pd(xv[0], twoto); xv[1] = _mm256_mul_pd(xv[1], twoto); xv[2] = _mm256_mul_pd(xv[2], twoto); xv[3] = _mm256_mul_pd(xv[3], twoto); } _mm256_store_pd(&x3[0], xv[0]); _mm256_store_pd(&x3[4], xv[1]); _mm256_store_pd(&x3[8], xv[2]); _mm256_store_pd(&x3[12], xv[3]); } x3 = x3_start; for(i = 0; i < n; i++) { if(x3_gap[i / 32] & mask32[i % 32]) { if(scaleGap) { if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } else { if(x1_gap[i / 32] & mask32[i % 32]) x1 = x1_gapColumn; else { x1 = x1_ptr; x1_ptr += 16; } if(x2_gap[i / 32] & mask32[i % 32]) x2 = x2_gapColumn; else { x2 = x2_ptr; x2_ptr += 16; } __m256d xv[4]; scale = 1; for(k = 0; k < 4; k++) { __m256d xvl = _mm256_load_pd(&(x1[k * 4])), xvr = _mm256_load_pd(&(x2[k * 4])); int l; xv[k] = _mm256_setzero_pd(); for(l = 0; l < 4; l++) { __m256d x1v = _mm256_mul_pd(xvl, _mm256_load_pd(&left[k * 16 + l * 4])), x2v = _mm256_mul_pd(xvr, _mm256_load_pd(&right[k * 16 + l * 4])); x1v = hadd4(x1v, x2v); __m256d evv = _mm256_load_pd(&extEV[l * 4]); xv[k] = _mm256_add_pd(xv[k], _mm256_mul_pd(x1v, evv)); } if(scale) { __m256d v1 = _mm256_and_pd(xv[k], absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) != 15) scale = 0; } } if(scale) { xv[0] = _mm256_mul_pd(xv[0], twoto); xv[1] = _mm256_mul_pd(xv[1], twoto); xv[2] = _mm256_mul_pd(xv[2], twoto); xv[3] = _mm256_mul_pd(xv[3], twoto); if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } _mm256_store_pd(&x3[0], xv[0]); _mm256_store_pd(&x3[4], xv[1]); _mm256_store_pd(&x3[8], xv[2]); _mm256_store_pd(&x3[12], xv[3]); x3 += 16; } } } break; default: assert(0); } if(useFastScaling) *scalerIncrement = addScale; } void newviewGTRCAT_AVX_GAPPED_SAVE(int tipCase, double *EV, int *cptr, double *x1_start, double *x2_start, double *x3_start, double *tipVector, int *ex3, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn, const int maxCats) { double *le, *ri, *x1, *x2, *x3, *x1_ptr = x1_start, *x2_ptr = x2_start, *x3_ptr = x3_start; int i, scaleGap = 0, addScale = 0; __m256d minlikelihood_avx = _mm256_set1_pd( minlikelihood ), twoto = _mm256_set1_pd(twotothe256); { int l; x1 = x1_gapColumn; x2 = x2_gapColumn; x3 = x3_gapColumn; le = &left[maxCats * 16]; ri = &right[maxCats * 16]; __m256d vv = _mm256_setzero_pd(); for(l = 0; l < 4; l++) { __m256d x1v = _mm256_mul_pd(_mm256_load_pd(x1), _mm256_load_pd(&le[l * 4])), x2v = _mm256_mul_pd(_mm256_load_pd(x2), _mm256_load_pd(&ri[l * 4])); x1v = hadd4(x1v, x2v); __m256d evv = _mm256_load_pd(&EV[l * 4]); #ifdef _FMA vv = FMAMACC(vv,x1v,evv); #else vv = _mm256_add_pd(vv, _mm256_mul_pd(x1v, evv)); #endif } if(tipCase != TIP_TIP) { __m256d v1 = _mm256_and_pd(vv, absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) == 15) { vv = _mm256_mul_pd(vv, twoto); scaleGap = 1; } } _mm256_store_pd(x3, vv); } switch(tipCase) { case TIP_TIP: for (i = 0; i < n; i++) { if(noGap(x3_gap, i)) { int l; x1 = &(tipVector[4 * tipX1[i]]); x2 = &(tipVector[4 * tipX2[i]]); x3 = x3_ptr; if(isGap(x1_gap, i)) le = &left[maxCats * 16]; else le = &left[cptr[i] * 16]; if(isGap(x2_gap, i)) ri = &right[maxCats * 16]; else ri = &right[cptr[i] * 16]; __m256d vv = _mm256_setzero_pd(); for(l = 0; l < 4; l++) { __m256d x1v = _mm256_mul_pd(_mm256_load_pd(x1), _mm256_load_pd(&le[l * 4])), x2v = _mm256_mul_pd(_mm256_load_pd(x2), _mm256_load_pd(&ri[l * 4])); x1v = hadd4(x1v, x2v); __m256d evv = _mm256_load_pd(&EV[l * 4]); #ifdef _FMA vv = FMAMACC(vv,x1v,evv); #else vv = _mm256_add_pd(vv, _mm256_mul_pd(x1v, evv)); #endif } _mm256_store_pd(x3, vv); x3_ptr += 4; } } break; case TIP_INNER: for (i = 0; i < n; i++) { if(isGap(x3_gap, i)) { if(scaleGap) { if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } else { int l; x1 = &(tipVector[4 * tipX1[i]]); x3 = x3_ptr; if(isGap(x1_gap, i)) le = &left[maxCats * 16]; else le = &left[cptr[i] * 16]; if(isGap(x2_gap, i)) { ri = &right[maxCats * 16]; x2 = x2_gapColumn; } else { ri = &right[cptr[i] * 16]; x2 = x2_ptr; x2_ptr += 4; } __m256d vv = _mm256_setzero_pd(); for(l = 0; l < 4; l++) { __m256d x1v = _mm256_mul_pd(_mm256_load_pd(x1), _mm256_load_pd(&le[l * 4])), x2v = _mm256_mul_pd(_mm256_load_pd(x2), _mm256_load_pd(&ri[l * 4])); x1v = hadd4(x1v, x2v); __m256d evv = _mm256_load_pd(&EV[l * 4]); #ifdef _FMA vv = FMAMACC(vv,x1v,evv); #else vv = _mm256_add_pd(vv, _mm256_mul_pd(x1v, evv)); #endif } __m256d v1 = _mm256_and_pd(vv, absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) == 15) { vv = _mm256_mul_pd(vv, twoto); if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } _mm256_store_pd(x3, vv); x3_ptr += 4; } } break; case INNER_INNER: for (i = 0; i < n; i++) { if(isGap(x3_gap, i)) { if(scaleGap) { if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } else { int l; x3 = x3_ptr; if(isGap(x1_gap, i)) { x1 = x1_gapColumn; le = &left[maxCats * 16]; } else { le = &left[cptr[i] * 16]; x1 = x1_ptr; x1_ptr += 4; } if(isGap(x2_gap, i)) { x2 = x2_gapColumn; ri = &right[maxCats * 16]; } else { ri = &right[cptr[i] * 16]; x2 = x2_ptr; x2_ptr += 4; } __m256d vv = _mm256_setzero_pd(); for(l = 0; l < 4; l++) { __m256d x1v = _mm256_mul_pd(_mm256_load_pd(x1), _mm256_load_pd(&le[l * 4])), x2v = _mm256_mul_pd(_mm256_load_pd(x2), _mm256_load_pd(&ri[l * 4])); x1v = hadd4(x1v, x2v); __m256d evv = _mm256_load_pd(&EV[l * 4]); #ifdef _FMA vv = FMAMACC(vv,x1v,evv); #else vv = _mm256_add_pd(vv, _mm256_mul_pd(x1v, evv)); #endif } __m256d v1 = _mm256_and_pd(vv, absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) == 15) { vv = _mm256_mul_pd(vv, twoto); if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } _mm256_store_pd(x3, vv); x3_ptr += 4; } } break; default: assert(0); } if(useFastScaling) *scalerIncrement = addScale; } void newviewGTRCATPROT_AVX_GAPPED_SAVE(int tipCase, double *extEV, int *cptr, double *x1, double *x2, double *x3, double *tipVector, int *ex3, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn, const int maxCats) { double *le, *ri, *v, *vl, *vr, *x1_ptr = x1, *x2_ptr = x2, *x3_ptr = x3; int i, l, scale, addScale = 0, scaleGap = 0; #ifdef _FMA int k; #endif { le = &left[maxCats * 400]; ri = &right[maxCats * 400]; vl = x1_gapColumn; vr = x2_gapColumn; v = x3_gapColumn; __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { __m256d x1v = _mm256_setzero_pd(), x2v = _mm256_setzero_pd(); double *ev = &extEV[l * 20], *lv = &le[l * 20], *rv = &ri[l * 20]; x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[0]), _mm256_load_pd(&lv[0]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[4]), _mm256_load_pd(&lv[4]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[8]), _mm256_load_pd(&lv[8]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[12]), _mm256_load_pd(&lv[12]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[16]), _mm256_load_pd(&lv[16]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[0]), _mm256_load_pd(&rv[0]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[4]), _mm256_load_pd(&rv[4]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[8]), _mm256_load_pd(&rv[8]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[12]), _mm256_load_pd(&rv[12]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[16]), _mm256_load_pd(&rv[16]))); x1v = hadd4(x1v, x2v); #ifdef _FMA for(k = 0; k < 5; k++) { __m256d evv = _mm256_load_pd(&ev[k*4]); vv[k] = FMAMACC(vv[k],x1v,evv); } #else __m256d evv[5]; evv[0] = _mm256_load_pd(&ev[0]); evv[1] = _mm256_load_pd(&ev[4]); evv[2] = _mm256_load_pd(&ev[8]); evv[3] = _mm256_load_pd(&ev[12]); evv[4] = _mm256_load_pd(&ev[16]); vv[0] = _mm256_add_pd(vv[0], _mm256_mul_pd(x1v, evv[0])); vv[1] = _mm256_add_pd(vv[1], _mm256_mul_pd(x1v, evv[1])); vv[2] = _mm256_add_pd(vv[2], _mm256_mul_pd(x1v, evv[2])); vv[3] = _mm256_add_pd(vv[3], _mm256_mul_pd(x1v, evv[3])); vv[4] = _mm256_add_pd(vv[4], _mm256_mul_pd(x1v, evv[4])); #endif } if(tipCase != TIP_TIP) { __m256d minlikelihood_avx = _mm256_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 20); l += 4) { __m256d v1 = _mm256_and_pd(vv[l / 4], absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) != 15) scale = 0; } if(scale) { __m256d twoto = _mm256_set1_pd(twotothe256); for(l = 0; l < 20; l += 4) vv[l / 4] = _mm256_mul_pd(vv[l / 4] , twoto); scaleGap = 1; } } _mm256_store_pd(&v[0], vv[0]); _mm256_store_pd(&v[4], vv[1]); _mm256_store_pd(&v[8], vv[2]); _mm256_store_pd(&v[12], vv[3]); _mm256_store_pd(&v[16], vv[4]); } switch(tipCase) { case TIP_TIP: { for (i = 0; i < n; i++) { if(noGap(x3_gap, i)) { vl = &(tipVector[20 * tipX1[i]]); vr = &(tipVector[20 * tipX2[i]]); v = x3_ptr; if(isGap(x1_gap, i)) le = &left[maxCats * 400]; else le = &left[cptr[i] * 400]; if(isGap(x2_gap, i)) ri = &right[maxCats * 400]; else ri = &right[cptr[i] * 400]; __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { __m256d x1v = _mm256_setzero_pd(), x2v = _mm256_setzero_pd(); double *ev = &extEV[l * 20], *lv = &le[l * 20], *rv = &ri[l * 20]; #ifdef _FMA for(k = 0; k < 20; k += 4) { __m256d vlv = _mm256_load_pd(&vl[k]); __m256d lvv = _mm256_load_pd(&lv[k]); x1v = FMAMACC(x1v,vlv,lvv); __m256d vrv = _mm256_load_pd(&vr[k]); __m256d rvv = _mm256_load_pd(&rv[k]); x2v = FMAMACC(x2v,vrv,rvv); } #else x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[0]), _mm256_load_pd(&lv[0]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[4]), _mm256_load_pd(&lv[4]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[8]), _mm256_load_pd(&lv[8]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[12]), _mm256_load_pd(&lv[12]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[16]), _mm256_load_pd(&lv[16]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[0]), _mm256_load_pd(&rv[0]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[4]), _mm256_load_pd(&rv[4]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[8]), _mm256_load_pd(&rv[8]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[12]), _mm256_load_pd(&rv[12]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[16]), _mm256_load_pd(&rv[16]))); #endif x1v = hadd4(x1v, x2v); #ifdef _FMA for(k = 0; k < 5; k++) { __m256d evv = _mm256_load_pd(&ev[k*4]); vv[k] = FMAMACC(vv[k],x1v,evv); } #else __m256d evv[5]; evv[0] = _mm256_load_pd(&ev[0]); evv[1] = _mm256_load_pd(&ev[4]); evv[2] = _mm256_load_pd(&ev[8]); evv[3] = _mm256_load_pd(&ev[12]); evv[4] = _mm256_load_pd(&ev[16]); vv[0] = _mm256_add_pd(vv[0], _mm256_mul_pd(x1v, evv[0])); vv[1] = _mm256_add_pd(vv[1], _mm256_mul_pd(x1v, evv[1])); vv[2] = _mm256_add_pd(vv[2], _mm256_mul_pd(x1v, evv[2])); vv[3] = _mm256_add_pd(vv[3], _mm256_mul_pd(x1v, evv[3])); vv[4] = _mm256_add_pd(vv[4], _mm256_mul_pd(x1v, evv[4])); #endif } _mm256_store_pd(&v[0], vv[0]); _mm256_store_pd(&v[4], vv[1]); _mm256_store_pd(&v[8], vv[2]); _mm256_store_pd(&v[12], vv[3]); _mm256_store_pd(&v[16], vv[4]); x3_ptr += 20; } } } break; case TIP_INNER: for (i = 0; i < n; i++) { if(isGap(x3_gap, i)) { if(scaleGap) { if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } else { vl = &(tipVector[20 * tipX1[i]]); vr = x2_ptr; v = x3_ptr; if(isGap(x1_gap, i)) le = &left[maxCats * 400]; else le = &left[cptr[i] * 400]; if(isGap(x2_gap, i)) { ri = &right[maxCats * 400]; vr = x2_gapColumn; } else { ri = &right[cptr[i] * 400]; vr = x2_ptr; x2_ptr += 20; } __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { __m256d x1v = _mm256_setzero_pd(), x2v = _mm256_setzero_pd(); double *ev = &extEV[l * 20], *lv = &le[l * 20], *rv = &ri[l * 20]; #ifdef _FMA for(k = 0; k < 20; k += 4) { __m256d vlv = _mm256_load_pd(&vl[k]); __m256d lvv = _mm256_load_pd(&lv[k]); x1v = FMAMACC(x1v,vlv,lvv); __m256d vrv = _mm256_load_pd(&vr[k]); __m256d rvv = _mm256_load_pd(&rv[k]); x2v = FMAMACC(x2v,vrv,rvv); } #else x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[0]), _mm256_load_pd(&lv[0]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[4]), _mm256_load_pd(&lv[4]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[8]), _mm256_load_pd(&lv[8]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[12]), _mm256_load_pd(&lv[12]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[16]), _mm256_load_pd(&lv[16]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[0]), _mm256_load_pd(&rv[0]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[4]), _mm256_load_pd(&rv[4]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[8]), _mm256_load_pd(&rv[8]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[12]), _mm256_load_pd(&rv[12]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[16]), _mm256_load_pd(&rv[16]))); #endif x1v = hadd4(x1v, x2v); __m256d evv[5]; evv[0] = _mm256_load_pd(&ev[0]); evv[1] = _mm256_load_pd(&ev[4]); evv[2] = _mm256_load_pd(&ev[8]); evv[3] = _mm256_load_pd(&ev[12]); evv[4] = _mm256_load_pd(&ev[16]); #ifdef _FMA for(k = 0; k < 5; k++) vv[k] = FMAMACC(vv[k],x1v,evv[k]); #else vv[0] = _mm256_add_pd(vv[0], _mm256_mul_pd(x1v, evv[0])); vv[1] = _mm256_add_pd(vv[1], _mm256_mul_pd(x1v, evv[1])); vv[2] = _mm256_add_pd(vv[2], _mm256_mul_pd(x1v, evv[2])); vv[3] = _mm256_add_pd(vv[3], _mm256_mul_pd(x1v, evv[3])); vv[4] = _mm256_add_pd(vv[4], _mm256_mul_pd(x1v, evv[4])); #endif } __m256d minlikelihood_avx = _mm256_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 20); l += 4) { __m256d v1 = _mm256_and_pd(vv[l / 4], absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) != 15) scale = 0; } if(scale) { __m256d twoto = _mm256_set1_pd(twotothe256); for(l = 0; l < 20; l += 4) vv[l / 4] = _mm256_mul_pd(vv[l / 4] , twoto); if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } _mm256_store_pd(&v[0], vv[0]); _mm256_store_pd(&v[4], vv[1]); _mm256_store_pd(&v[8], vv[2]); _mm256_store_pd(&v[12], vv[3]); _mm256_store_pd(&v[16], vv[4]); x3_ptr += 20; } } break; case INNER_INNER: for(i = 0; i < n; i++) { if(isGap(x3_gap, i)) { if(scaleGap) { if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } else { v = x3_ptr; if(isGap(x1_gap, i)) { vl = x1_gapColumn; le = &left[maxCats * 400]; } else { le = &left[cptr[i] * 400]; vl = x1_ptr; x1_ptr += 20; } if(isGap(x2_gap, i)) { vr = x2_gapColumn; ri = &right[maxCats * 400]; } else { ri = &right[cptr[i] * 400]; vr = x2_ptr; x2_ptr += 20; } __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { __m256d x1v = _mm256_setzero_pd(), x2v = _mm256_setzero_pd(); double *ev = &extEV[l * 20], *lv = &le[l * 20], *rv = &ri[l * 20]; x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[0]), _mm256_load_pd(&lv[0]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[4]), _mm256_load_pd(&lv[4]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[8]), _mm256_load_pd(&lv[8]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[12]), _mm256_load_pd(&lv[12]))); x1v = _mm256_add_pd(x1v, _mm256_mul_pd(_mm256_load_pd(&vl[16]), _mm256_load_pd(&lv[16]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[0]), _mm256_load_pd(&rv[0]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[4]), _mm256_load_pd(&rv[4]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[8]), _mm256_load_pd(&rv[8]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[12]), _mm256_load_pd(&rv[12]))); x2v = _mm256_add_pd(x2v, _mm256_mul_pd(_mm256_load_pd(&vr[16]), _mm256_load_pd(&rv[16]))); x1v = hadd4(x1v, x2v); #ifdef _FMA for(k = 0; k < 5; k++) { __m256d evv = _mm256_load_pd(&ev[k*4]); vv[k] = FMAMACC(vv[k],x1v,evv); } #else __m256d evv[5]; evv[0] = _mm256_load_pd(&ev[0]); evv[1] = _mm256_load_pd(&ev[4]); evv[2] = _mm256_load_pd(&ev[8]); evv[3] = _mm256_load_pd(&ev[12]); evv[4] = _mm256_load_pd(&ev[16]); vv[0] = _mm256_add_pd(vv[0], _mm256_mul_pd(x1v, evv[0])); vv[1] = _mm256_add_pd(vv[1], _mm256_mul_pd(x1v, evv[1])); vv[2] = _mm256_add_pd(vv[2], _mm256_mul_pd(x1v, evv[2])); vv[3] = _mm256_add_pd(vv[3], _mm256_mul_pd(x1v, evv[3])); vv[4] = _mm256_add_pd(vv[4], _mm256_mul_pd(x1v, evv[4])); #endif } __m256d minlikelihood_avx = _mm256_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 20); l += 4) { __m256d v1 = _mm256_and_pd(vv[l / 4], absMask_AVX.m); v1 = _mm256_cmp_pd(v1, minlikelihood_avx, _CMP_LT_OS); if(_mm256_movemask_pd( v1 ) != 15) scale = 0; } if(scale) { __m256d twoto = _mm256_set1_pd(twotothe256); for(l = 0; l < 20; l += 4) vv[l / 4] = _mm256_mul_pd(vv[l / 4] , twoto); if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } _mm256_store_pd(&v[0], vv[0]); _mm256_store_pd(&v[4], vv[1]); _mm256_store_pd(&v[8], vv[2]); _mm256_store_pd(&v[12], vv[3]); _mm256_store_pd(&v[16], vv[4]); x3_ptr += 20; } } break; default: assert(0); } if(useFastScaling) *scalerIncrement = addScale; } void newviewGTRGAMMAPROT_AVX_GAPPED_SAVE(int tipCase, double *x1_start, double *x2_start, double *x3_start, double *extEV, double *tipVector, int *ex3, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn) { double *x1 = x1_start, *x2 = x2_start, *x3_ptr = x3_start, *x2_ptr = x2_start, *x1_ptr = x1_start, *uX1, *uX2, *v, x1px2, *vl, *vr; int i, j, l, k, gapScaling = 0, scale, addScale = 0; #ifndef GCC_VERSION #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #endif #if GCC_VERSION < 40500 __m256d bitmask = _mm256_set_pd(0,0,0,-1); #else __m256i bitmask = _mm256_set_epi32(0, 0, 0, 0, 0, 0, -1, -1); #endif switch(tipCase) { case TIP_TIP: { double umpX1[1840] __attribute__ ((aligned (BYTE_ALIGNMENT))), umpX2[1840] __attribute__ ((aligned (BYTE_ALIGNMENT))); for(i = 0; i < 23; i++) { v = &(tipVector[20 * i]); for(k = 0; k < 80; k++) { double *ll = &left[k * 20], *rr = &right[k * 20]; __m256d umpX1v = _mm256_setzero_pd(), umpX2v = _mm256_setzero_pd(); for(l = 0; l < 20; l+=4) { __m256d vv = _mm256_load_pd(&v[l]); #ifdef _FMA __m256d llv = _mm256_load_pd(&ll[l]); umpX1v = FMAMACC(umpX1v,vv,llv); __m256d rrv = _mm256_load_pd(&rr[l]); umpX2v = FMAMACC(umpX2v,vv,rrv); #else umpX1v = _mm256_add_pd(umpX1v,_mm256_mul_pd(vv,_mm256_load_pd(&ll[l]))); umpX2v = _mm256_add_pd(umpX2v,_mm256_mul_pd(vv,_mm256_load_pd(&rr[l]))); #endif } umpX1v = hadd3(umpX1v); umpX2v = hadd3(umpX2v); _mm256_maskstore_pd(&umpX1[80 * i + k], bitmask, umpX1v); _mm256_maskstore_pd(&umpX2[80 * i + k], bitmask, umpX2v); } } { uX1 = &umpX1[1760]; uX2 = &umpX2[1760]; for(j = 0; j < 4; j++) { __m256d vv[5]; v = &x3_gapColumn[j * 20]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(k = 0; k < 20; k++) { x1px2 = uX1[j * 20 + k] * uX2[j * 20 + k]; __m256d x1px2v = _mm256_set1_pd(x1px2); __m256d extEvv = _mm256_load_pd(&extEV[20 * k]); #ifdef _FMA vv[0] = FMAMACC(vv[0],x1px2v,extEvv); #else vv[0] = _mm256_add_pd(vv[0],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[0],vv[0]); extEvv = _mm256_load_pd(&extEV[20 * k + 4]); #ifdef _FMA vv[1] = FMAMACC(vv[1],x1px2v,extEvv); #else vv[1] = _mm256_add_pd(vv[1],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[4],vv[1]); extEvv = _mm256_load_pd(&extEV[20 * k + 8]); #ifdef _FMA vv[2] = FMAMACC(vv[2],x1px2v,extEvv); #else vv[2] = _mm256_add_pd(vv[2],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[8],vv[2]); extEvv = _mm256_load_pd(&extEV[20 * k + 12]); #ifdef _FMA vv[3] = FMAMACC(vv[3],x1px2v,extEvv); #else vv[3] = _mm256_add_pd(vv[3],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[12],vv[3]); extEvv = _mm256_load_pd(&extEV[20 * k + 16]); #ifdef _FMA vv[4] = FMAMACC(vv[4],x1px2v,extEvv); #else vv[4] = _mm256_add_pd(vv[4],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[16],vv[4]); } } } for(i = 0; i < n; i++) { if(!(x3_gap[i / 32] & mask32[i % 32])) { uX1 = &umpX1[80 * tipX1[i]]; uX2 = &umpX2[80 * tipX2[i]]; for(j = 0; j < 4; j++) { __m256d vv[5]; v = &x3_ptr[j * 20]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(k = 0; k < 20; k++) { x1px2 = uX1[j * 20 + k] * uX2[j * 20 + k]; __m256d x1px2v = _mm256_set1_pd(x1px2); __m256d extEvv = _mm256_load_pd(&extEV[20 * k]); #ifdef _FMA vv[0] = FMAMACC(vv[0],x1px2v,extEvv); #else vv[0] = _mm256_add_pd(vv[0],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[0],vv[0]); extEvv = _mm256_load_pd(&extEV[20 * k + 4]); #ifdef _FMA vv[1] = FMAMACC(vv[1],x1px2v,extEvv); #else vv[1] = _mm256_add_pd(vv[1],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[4],vv[1]); extEvv = _mm256_load_pd(&extEV[20 * k + 8]); #ifdef _FMA vv[2] = FMAMACC(vv[2],x1px2v,extEvv); #else vv[2] = _mm256_add_pd(vv[2],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[8],vv[2]); extEvv = _mm256_load_pd(&extEV[20 * k + 12]); #ifdef _FMA vv[3] = FMAMACC(vv[3],x1px2v,extEvv); #else vv[3] = _mm256_add_pd(vv[3],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[12],vv[3]); extEvv = _mm256_load_pd(&extEV[20 * k + 16]); #ifdef _FMA vv[4] = FMAMACC(vv[4],x1px2v,extEvv); #else vv[4] = _mm256_add_pd(vv[4],_mm256_mul_pd(x1px2v,extEvv)); #endif _mm256_store_pd(&v[16],vv[4]); } } x3_ptr += 80; } } } break; case TIP_INNER: { double umpX1[1840] __attribute__ ((aligned (BYTE_ALIGNMENT))), ump_x2[20] __attribute__ ((aligned (BYTE_ALIGNMENT))); for(i = 0; i < 23; i++) { v = &(tipVector[20 * i]); for(k = 0; k < 80; k++) { __m256d umpX1v = _mm256_setzero_pd(); for(l = 0; l < 20; l+=4) { __m256d vv = _mm256_load_pd(&v[l]); __m256d leftv = _mm256_load_pd(&left[k * 20 + l]); #ifdef _FMA umpX1v = FMAMACC(umpX1v, vv, leftv); #else umpX1v = _mm256_add_pd(umpX1v, _mm256_mul_pd(vv, leftv)); #endif } umpX1v = hadd3(umpX1v); _mm256_maskstore_pd(&umpX1[80 * i + k], bitmask, umpX1v); } } { uX1 = &umpX1[1760]; for(k = 0; k < 4; k++) { v = &(x2_gapColumn[k * 20]); for(l = 0; l < 20; l++) { __m256d ump_x2v = _mm256_setzero_pd(); __m256d vv = _mm256_load_pd(&v[0]); __m256d rightv = _mm256_load_pd(&right[k*400+l*20+0]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[4]); rightv = _mm256_load_pd(&right[k*400+l*20+4]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[8]); rightv = _mm256_load_pd(&right[k*400+l*20+8]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[12]); rightv = _mm256_load_pd(&right[k*400+l*20+12]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[16]); rightv = _mm256_load_pd(&right[k*400+l*20+16]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif ump_x2v = hadd3(ump_x2v); _mm256_maskstore_pd(&ump_x2[l], bitmask, ump_x2v); } v = &x3_gapColumn[20 * k]; __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { x1px2 = uX1[k * 20 + l] * ump_x2[l]; __m256d x1px2v = _mm256_set1_pd(x1px2); #ifdef _FMA __m256d ev = _mm256_load_pd(&extEV[l * 20 + 0]); vv[0] = FMAMACC(vv[0],x1px2v, ev); #else vv[0] = _mm256_add_pd(vv[0],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 0]))); #endif _mm256_store_pd(&v[0],vv[0]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 4]); vv[1] = FMAMACC(vv[1],x1px2v, ev); #else vv[1] = _mm256_add_pd(vv[1],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 4]))); #endif _mm256_store_pd(&v[4],vv[1]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 8]); vv[2] = FMAMACC(vv[2],x1px2v, ev); #else vv[2] = _mm256_add_pd(vv[2],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 8]))); #endif _mm256_store_pd(&v[8],vv[2]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 12]); vv[3] = FMAMACC(vv[3],x1px2v, ev); #else vv[3] = _mm256_add_pd(vv[3],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 12]))); #endif _mm256_store_pd(&v[12],vv[3]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 16]); vv[4] = FMAMACC(vv[4],x1px2v, ev); #else vv[4] = _mm256_add_pd(vv[4],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 16]))); #endif _mm256_store_pd(&v[16],vv[4]); } } v = x3_gapColumn; __m256d minlikelihood_avx = _mm256_set1_pd(minlikelihood); scale = 1; for(l = 0; scale && (l < 80); l += 4) { __m256d vv = _mm256_load_pd(&v[l]); __m256d vv_abs = _mm256_and_pd(vv,absMask_AVX.m); vv_abs = _mm256_cmp_pd(vv_abs,minlikelihood_avx,_CMP_LT_OS); if(_mm256_movemask_pd(vv_abs) != 15) scale = 0; } if(scale) { __m256d twotothe256v = _mm256_set_pd(twotothe256,twotothe256,twotothe256,twotothe256); gapScaling = 1; for(l = 0; l < 80; l += 4) { __m256d vv = _mm256_load_pd(&v[l]); _mm256_store_pd(&v[l],_mm256_mul_pd(vv,twotothe256v)); } } } for (i = 0; i < n; i++) { if((x3_gap[i / 32] & mask32[i % 32])) { if(gapScaling) { if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } else { uX1 = &umpX1[80 * tipX1[i]]; if(x2_gap[i / 32] & mask32[i % 32]) x2 = x2_gapColumn; else { x2 = x2_ptr; x2_ptr += 80; } for(k = 0; k < 4; k++) { v = &(x2[k * 20]); for(l = 0; l < 20; l++) { __m256d ump_x2v = _mm256_setzero_pd(); __m256d vv = _mm256_load_pd(&v[0]); __m256d rightv = _mm256_load_pd(&right[k*400+l*20+0]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[4]); rightv = _mm256_load_pd(&right[k*400+l*20+4]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[8]); rightv = _mm256_load_pd(&right[k*400+l*20+8]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[12]); rightv = _mm256_load_pd(&right[k*400+l*20+12]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif vv = _mm256_load_pd(&v[16]); rightv = _mm256_load_pd(&right[k*400+l*20+16]); #ifdef _FMA ump_x2v = FMAMACC(ump_x2v,vv,rightv); #else ump_x2v = _mm256_add_pd(ump_x2v, _mm256_mul_pd(vv, rightv)); #endif ump_x2v = hadd3(ump_x2v); _mm256_maskstore_pd(&ump_x2[l], bitmask, ump_x2v); } v = &x3_ptr[k * 20]; __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { x1px2 = uX1[k * 20 + l] * ump_x2[l]; __m256d x1px2v = _mm256_set1_pd(x1px2); #ifdef _FMA __m256d ev = _mm256_load_pd(&extEV[l * 20 + 0]); vv[0] = FMAMACC(vv[0],x1px2v, ev); #else vv[0] = _mm256_add_pd(vv[0],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 0]))); #endif _mm256_store_pd(&v[0],vv[0]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 4]); vv[1] = FMAMACC(vv[1],x1px2v, ev); #else vv[1] = _mm256_add_pd(vv[1],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 4]))); #endif _mm256_store_pd(&v[4],vv[1]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 8]); vv[2] = FMAMACC(vv[2],x1px2v, ev); #else vv[2] = _mm256_add_pd(vv[2],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 8]))); #endif _mm256_store_pd(&v[8],vv[2]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 12]); vv[3] = FMAMACC(vv[3],x1px2v, ev); #else vv[3] = _mm256_add_pd(vv[3],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 12]))); #endif _mm256_store_pd(&v[12],vv[3]); #ifdef _FMA ev = _mm256_load_pd(&extEV[l * 20 + 16]); vv[4] = FMAMACC(vv[4],x1px2v, ev); #else vv[4] = _mm256_add_pd(vv[4],_mm256_mul_pd(x1px2v, _mm256_load_pd(&extEV[l * 20 + 16]))); #endif _mm256_store_pd(&v[16],vv[4]); } } v = x3_ptr; __m256d minlikelihood_avx = _mm256_set1_pd(minlikelihood); scale = 1; for(l = 0; scale && (l < 80); l += 4) { __m256d vv = _mm256_load_pd(&v[l]); __m256d vv_abs = _mm256_and_pd(vv,absMask_AVX.m); vv_abs = _mm256_cmp_pd(vv_abs,minlikelihood_avx,_CMP_LT_OS); if(_mm256_movemask_pd(vv_abs) != 15) scale = 0; } if(scale) { __m256d twotothe256v = _mm256_set_pd(twotothe256,twotothe256,twotothe256,twotothe256); for(l = 0; l < 80; l += 4) { __m256d vv = _mm256_load_pd(&v[l]); _mm256_store_pd(&v[l],_mm256_mul_pd(vv,twotothe256v)); } if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } x3_ptr += 80; } } } break; case INNER_INNER: for(k = 0; k < 4; k++) { vl = &(x1_gapColumn[20 * k]); vr = &(x2_gapColumn[20 * k]); v = &(x3_gapColumn[20 * k]); __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { __m256d al = _mm256_setzero_pd(); __m256d ar = _mm256_setzero_pd(); __m256d leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 0]); __m256d rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 0]); __m256d vlv = _mm256_load_pd(&vl[0]); __m256d vrv = _mm256_load_pd(&vr[0]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 4]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 4]); vlv = _mm256_load_pd(&vl[4]); vrv = _mm256_load_pd(&vr[4]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 8]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 8]); vlv = _mm256_load_pd(&vl[8]); vrv = _mm256_load_pd(&vr[8]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 12]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 12]); vlv = _mm256_load_pd(&vl[12]); vrv = _mm256_load_pd(&vr[12]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 16]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 16]); vlv = _mm256_load_pd(&vl[16]); vrv = _mm256_load_pd(&vr[16]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif /**************************************************************************************************************/ al = hadd3(al); ar = hadd3(ar); al = _mm256_mul_pd(ar,al); /************************************************************************************************************/ #ifdef _FMA __m256d ev = _mm256_load_pd(&extEV[20 * l + 0]); vv[0] = FMAMACC(vv[0], al, ev); #else vv[0] = _mm256_add_pd(vv[0],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 0]))); #endif _mm256_store_pd(&v[0],vv[0]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 4]); vv[1] = FMAMACC(vv[1], al, ev); #else vv[1] = _mm256_add_pd(vv[1],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 4]))); #endif _mm256_store_pd(&v[4],vv[1]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 8]); vv[2] = FMAMACC(vv[2], al, ev); #else vv[2] = _mm256_add_pd(vv[2],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 8]))); #endif _mm256_store_pd(&v[8],vv[2]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 12]); vv[3] = FMAMACC(vv[3], al, ev); #else vv[3] = _mm256_add_pd(vv[3],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 12]))); #endif _mm256_store_pd(&v[12],vv[3]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 16]); vv[4] = FMAMACC(vv[4], al, ev); #else vv[4] = _mm256_add_pd(vv[4],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 16]))); #endif _mm256_store_pd(&v[16],vv[4]); } } v = x3_gapColumn; scale = 1; __m256d minlikelihood_avx = _mm256_set1_pd(minlikelihood); for(l = 0; scale && (l < 80); l += 4) { __m256d vv = _mm256_load_pd(&v[l]); __m256d vv_abs = _mm256_and_pd(vv,absMask_AVX.m); vv_abs = _mm256_cmp_pd(vv_abs,minlikelihood_avx,_CMP_LT_OS); if(_mm256_movemask_pd(vv_abs) != 15) scale = 0; } if(scale) { __m256d twotothe256v = _mm256_set_pd(twotothe256,twotothe256,twotothe256,twotothe256); gapScaling = 1; for(l = 0; l < 80; l += 4) { __m256d vv = _mm256_load_pd(&v[l]); _mm256_store_pd(&v[l],_mm256_mul_pd(vv,twotothe256v)); } } for(i = 0; i < n; i++) { if(x3_gap[i / 32] & mask32[i % 32]) { if(gapScaling) { if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } else { if(x1_gap[i / 32] & mask32[i % 32]) x1 = x1_gapColumn; else { x1 = x1_ptr; x1_ptr += 80; } if(x2_gap[i / 32] & mask32[i % 32]) x2 = x2_gapColumn; else { x2 = x2_ptr; x2_ptr += 80; } for(k = 0; k < 4; k++) { vl = &(x1[20 * k]); vr = &(x2[20 * k]); v = &(x3_ptr[20 * k]); __m256d vv[5]; vv[0] = _mm256_setzero_pd(); vv[1] = _mm256_setzero_pd(); vv[2] = _mm256_setzero_pd(); vv[3] = _mm256_setzero_pd(); vv[4] = _mm256_setzero_pd(); for(l = 0; l < 20; l++) { __m256d al = _mm256_setzero_pd(); __m256d ar = _mm256_setzero_pd(); __m256d leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 0]); __m256d rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 0]); __m256d vlv = _mm256_load_pd(&vl[0]); __m256d vrv = _mm256_load_pd(&vr[0]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 4]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 4]); vlv = _mm256_load_pd(&vl[4]); vrv = _mm256_load_pd(&vr[4]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 8]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 8]); vlv = _mm256_load_pd(&vl[8]); vrv = _mm256_load_pd(&vr[8]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 12]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 12]); vlv = _mm256_load_pd(&vl[12]); vrv = _mm256_load_pd(&vr[12]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif leftv = _mm256_load_pd(&left[k * 400 + l * 20 + 16]); rightv = _mm256_load_pd(&right[k * 400 + l * 20 + 16]); vlv = _mm256_load_pd(&vl[16]); vrv = _mm256_load_pd(&vr[16]); #ifdef _FMA al = FMAMACC(al, vlv, leftv); ar = FMAMACC(ar, vrv, rightv); #else al = _mm256_add_pd(al,_mm256_mul_pd(vlv,leftv)); ar = _mm256_add_pd(ar,_mm256_mul_pd(vrv,rightv)); #endif /**************************************************************************************************************/ al = hadd3(al); ar = hadd3(ar); al = _mm256_mul_pd(ar,al); /************************************************************************************************************/ #ifdef _FMA __m256d ev = _mm256_load_pd(&extEV[20 * l + 0]); vv[0] = FMAMACC(vv[0], al, ev); #else vv[0] = _mm256_add_pd(vv[0],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 0]))); #endif _mm256_store_pd(&v[0],vv[0]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 4]); vv[1] = FMAMACC(vv[1], al, ev); #else vv[1] = _mm256_add_pd(vv[1],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 4]))); #endif _mm256_store_pd(&v[4],vv[1]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 8]); vv[2] = FMAMACC(vv[2], al, ev); #else vv[2] = _mm256_add_pd(vv[2],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 8]))); #endif _mm256_store_pd(&v[8],vv[2]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 12]); vv[3] = FMAMACC(vv[3], al, ev); #else vv[3] = _mm256_add_pd(vv[3],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 12]))); #endif _mm256_store_pd(&v[12],vv[3]); #ifdef _FMA ev = _mm256_load_pd(&extEV[20 * l + 16]); vv[4] = FMAMACC(vv[4], al, ev); #else vv[4] = _mm256_add_pd(vv[4],_mm256_mul_pd(al, _mm256_load_pd(&extEV[20 * l + 16]))); #endif _mm256_store_pd(&v[16],vv[4]); } } v = x3_ptr; scale = 1; __m256d minlikelihood_avx = _mm256_set1_pd(minlikelihood); for(l = 0; scale && (l < 80); l += 4) { __m256d vv = _mm256_load_pd(&v[l]); __m256d vv_abs = _mm256_and_pd(vv,absMask_AVX.m); vv_abs = _mm256_cmp_pd(vv_abs,minlikelihood_avx,_CMP_LT_OS); if(_mm256_movemask_pd(vv_abs) != 15) scale = 0; } if(scale) { __m256d twotothe256v = _mm256_set_pd(twotothe256,twotothe256,twotothe256,twotothe256); for(l = 0; l < 80; l += 4) { __m256d vv = _mm256_load_pd(&v[l]); _mm256_store_pd(&v[l],_mm256_mul_pd(vv,twotothe256v)); } if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } x3_ptr += 80; } } break; default: assert(0); } if(useFastScaling) *scalerIncrement = addScale; } ExaML-3.0.21/examl/axml.c000066400000000000000000002174621330315463200147720ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifdef WIN32 #include #endif #ifndef WIN32 #include #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #if ! (defined(__ppc) || defined(__powerpc__) || defined(PPC)) #include /* special bug fix, enforces denormalized numbers to be flushed to zero, without this program is a tiny bit faster though. #include #define MM_DAZ_MASK 0x0040 #define MM_DAZ_ON 0x0040 #define MM_DAZ_OFF 0x0000 */ #endif #include "axml.h" #include "globalVariables.h" #include "byteFile.h" #include "partitionAssignment.h" #ifdef __MIC_NATIVE #include "mic_native.h" #endif /***************** UTILITY FUNCTIONS **************************/ /*pInfo *cleanPinfoInit() { pInfo *p = (pInfo*)malloc(sizeof(pInfo)); return p; }*/ void storeExecuteMaskInTraversalDescriptor(tree *tr) { int model; for(model = 0; model < tr->NumberOfModels; model++) tr->td[0].executeModel[model] = tr->executeModel[model]; } void storeValuesInTraversalDescriptor(tree *tr, double *value) { int model; for(model = 0; model < tr->NumberOfModels; model++) tr->td[0].parameterValues[model] = value[model]; } void myBinFwrite(void *ptr, size_t size, size_t nmemb, FILE *byteFile) { size_t bytes_read; bytes_read = fwrite(ptr, size, nmemb, byteFile); assert(bytes_read == nmemb); } void myBinFread(void *ptr, size_t size, size_t nmemb, FILE *byteFile) { size_t bytes_read; bytes_read = fread(ptr, size, nmemb, byteFile); assert(bytes_read == nmemb); } static void outOfMemory(void) { printf("ExaML process %d was not able to allocate enough memory.\n", processID); printf("Please check the approximate memory consumption of your dataset using\n"); printf("the memory calculator at http://www.exelixis-lab.org/web/software/raxml/index.html.\n"); printf("ExaML will exit now\n"); MPI_Abort(MPI_COMM_WORLD, -1); exit(-1); } void *malloc_aligned(size_t size) { void *ptr = (void *)NULL; int res; #ifdef WIN32 ptr = _aligned_malloc(size, BYTE_ALIGNMENT);; #else res = posix_memalign( &ptr, BYTE_ALIGNMENT, size ); if(res != 0) { outOfMemory(); assert(0); } #endif return ptr; } static void printBoth(FILE *f, const char* format, ... ) { if(processID == 0) { va_list args; va_start(args, format); vfprintf(f, format, args ); va_end(args); va_start(args, format); vprintf(format, args ); va_end(args); } } void printBothOpen(const char* format, ... ) { if(processID == 0) { FILE *f = myfopen(infoFileName, "ab"); va_list args; va_start(args, format); vfprintf(f, format, args ); va_end(args); va_start(args, format); vprintf(format, args ); va_end(args); fclose(f); } } static void printBothOpenDifferentFile(char *fileName, const char* format, ... ) { if(processID == 0) { FILE *f = myfopen(fileName, "ab"); va_list args; va_start(args, format); vfprintf(f, format, args ); va_end(args); fclose(f); } } boolean getSmoothFreqs(int dataType) { assert(MIN_MODEL < dataType && dataType < MAX_MODEL); return pLengths[dataType].smoothFrequencies; } const unsigned int *getBitVector(int dataType) { assert(MIN_MODEL < dataType && dataType < MAX_MODEL); return pLengths[dataType].bitVector; } int getStates(int dataType) { assert(MIN_MODEL < dataType && dataType < MAX_MODEL); return pLengths[dataType].states; } int getUndetermined(int dataType) { assert(MIN_MODEL < dataType && dataType < MAX_MODEL); return pLengths[dataType].undetermined; } char getInverseMeaning(int dataType, unsigned char state) { assert(MIN_MODEL < dataType && dataType < MAX_MODEL); return pLengths[dataType].inverseMeaning[state]; } partitionLengths *getPartitionLengths(pInfo *p) { int dataType = p->dataType, states = p->states, tipLength = p->maxTipStates; assert(states != -1 && tipLength != -1); assert(MIN_MODEL < dataType && dataType < MAX_MODEL); pLength.leftLength = pLength.rightLength = states * states; pLength.eignLength = states; pLength.evLength = states * states; pLength.eiLength = states * states; pLength.substRatesLength = (states * states - states) / 2; pLength.frequenciesLength = states; pLength.tipVectorLength = tipLength * states; pLength.symmetryVectorLength = (states * states - states) / 2; pLength.frequencyGroupingLength = states; pLength.nonGTR = FALSE; return (&pLengths[dataType]); } size_t discreteRateCategories(int rateHetModel) { size_t result; switch(rateHetModel) { case CAT: result = 1; break; case GAMMA: result = 4; break; default: assert(0); } return result; } double gettime(void) { #ifdef WIN32 time_t tp; struct tm localtm; tp = time(NULL); localtm = *localtime(&tp); return 60.0*localtm.tm_min + localtm.tm_sec; #else struct timeval ttime; gettimeofday(&ttime , NULL); return ttime.tv_sec + ttime.tv_usec * 0.000001; #endif } int gettimeSrand(void) { #ifdef WIN32 time_t tp; struct tm localtm; tp = time(NULL); localtm = *localtime(&tp); return 24*60*60*localtm.tm_yday + 60*60*localtm.tm_hour + 60*localtm.tm_min + localtm.tm_sec; #else struct timeval ttime; gettimeofday(&ttime , NULL); return ttime.tv_sec + ttime.tv_usec; #endif } double randum (long *seed) { long sum, mult0, mult1, seed0, seed1, seed2, newseed0, newseed1, newseed2; double res; mult0 = 1549; seed0 = *seed & 4095; sum = mult0 * seed0; newseed0 = sum & 4095; sum >>= 12; seed1 = (*seed >> 12) & 4095; mult1 = 406; sum += mult0 * seed1 + mult1 * seed0; newseed1 = sum & 4095; sum >>= 12; seed2 = (*seed >> 24) & 255; sum += mult0 * seed2 + mult1 * seed1; newseed2 = sum & 255; *seed = newseed2 << 24 | newseed1 << 12 | newseed0; res = 0.00390625 * (newseed2 + 0.000244140625 * (newseed1 + 0.000244140625 * newseed0)); return res; } static int filexists(char *filename) { FILE *fp; int res; fp = fopen(filename,"rb"); if(fp) { res = 1; fclose(fp); } else res = 0; return res; } FILE *myfopen(const char *path, const char *mode) { FILE *fp = fopen(path, mode); if(strcmp(mode,"r") == 0 || strcmp(mode,"rb") == 0) { if(fp) return fp; else { if(processID == 0) printf("The file %s you want to open for reading does not exist, exiting ...\n", path); errorExit(-1); return (FILE *)NULL; } } else { if(fp) return fp; else { if(processID == 0) printf("The file %s ExaML wants to open for writing or appending can not be opened [mode: %s], exiting ...\n", path, mode); errorExit(-1); return (FILE *)NULL; } } } /********************* END UTILITY FUNCTIONS ********************/ /******************************some functions for the likelihood computation ****************************/ boolean isTip(int number, int maxTips) { assert(number > 0); if(number <= maxTips) return TRUE; else return FALSE; } void getxnode (nodeptr p) { nodeptr s; if ((s = p->next)->x || (s = s->next)->x) { p->x = s->x; s->x = 0; } assert(p->x); } void hookup (nodeptr p, nodeptr q, double *z, int numBranches) { int i; p->back = q; q->back = p; for(i = 0; i < numBranches; i++) p->z[i] = q->z[i] = z[i]; } void hookupDefault (nodeptr p, nodeptr q, int numBranches) { int i; p->back = q; q->back = p; for(i = 0; i < numBranches; i++) p->z[i] = q->z[i] = defaultz; } /***********************reading and initializing input ******************/ boolean whitechar (int ch) { return (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r'); } static unsigned int KISS32(void) { static unsigned int x = 123456789, y = 362436069, z = 21288629, w = 14921776, c = 0; unsigned int t; x += 545925293; y ^= (y<<13); y ^= (y>>17); y ^= (y<<5); t = z + w + c; z = w; c = (t>>31); w = t & 2147483647; return (x+y+w); } static boolean setupTree (tree *tr) { nodeptr p0, p, q; int i, j, tips, inter; tr->bigCutoff = FALSE; tr->maxCategories = MAX(4, tr->categories); tr->partitionContributions = (double *)malloc(sizeof(double) * tr->NumberOfModels); tr->partitionWeights = (double *)malloc(sizeof(double) * tr->NumberOfModels); for(i = 0; i < tr->NumberOfModels; i++) { tr->partitionContributions[i] = -1.0; tr->partitionWeights[i] = -1.0; } tr->perPartitionLH = (double *)malloc(sizeof(double) * tr->NumberOfModels); for(i = 0; i < tr->NumberOfModels; i++) tr->perPartitionLH[i] = 0.0; tips = tr->mxtips; inter = tr->mxtips - 1; /* printf("%d tips\t%d inner\n", tips, inter); */ tr->treeStringLength = tr->mxtips * (nmlngth+128) + 256 + tr->mxtips * 2; tr->tree_string = (char*)calloc(tr->treeStringLength, sizeof(char)); tr->tree0 = (char*)calloc(tr->treeStringLength, sizeof(char)); tr->tree1 = (char*)calloc(tr->treeStringLength, sizeof(char)); /* TODO, must that be so long ? */ /* assert(0); */ tr->td[0].count = 0; tr->td[0].ti = (traversalInfo *)malloc(sizeof(traversalInfo) * tr->mxtips); tr->td[0].executeModel = (boolean *)malloc(sizeof(boolean) * tr->NumberOfModels); tr->td[0].parameterValues = (double *)malloc(sizeof(double) * tr->NumberOfModels); tr->constraintVector = (int *)malloc((2 * tr->mxtips) * sizeof(int)); if (!(p0 = (nodeptr) malloc((tips + 3*inter) * sizeof(node)))) { printf("ERROR: Unable to obtain sufficient tree memory\n"); return FALSE; } tr->nodeBaseAddress = p0; if (!(tr->nodep = (nodeptr *) malloc((2*tr->mxtips) * sizeof(nodeptr)))) { printf("ERROR: Unable to obtain sufficient tree memory, too\n"); return FALSE; } tr->nodep[0] = (node *) NULL; /* Use as 1-based array */ for (i = 1; i <= tips; i++) { p = p0++; p->hash = KISS32(); /* hast table stuff */ p->x = 0; p->xBips = 0; p->number = i; p->next = p; p->back = (node *)NULL; tr->nodep[i] = p; } for (i = tips + 1; i <= tips + inter; i++) { q = (node *) NULL; for (j = 1; j <= 3; j++) { p = p0++; if(j == 1) { p->xBips = 1; p->x = 1; } else { p->xBips = 0; p->x = 0; } p->number = i; p->next = q; p->back = (node *) NULL; p->hash = 0; q = p; } p->next->next->next = p; tr->nodep[i] = p; } tr->likelihood = unlikely; tr->start = (node *) NULL; tr->ntips = 0; tr->nextnode = 0; for(i = 0; i < tr->numBranches; i++) tr->partitionSmoothed[i] = FALSE; tr->bitVectors = (unsigned int **)NULL; tr->vLength = 0; tr->h = (hashtable*)NULL; tr->nameHash = initStringHashTable(10 * tr->mxtips); return TRUE; } static void initAdef(analdef *adef) { adef->max_rearrange = 21; adef->stepwidth = 5; adef->initial = 10; adef->bestTrav = 10; adef->initialSet = FALSE; adef->mode = BIG_RAPID_MODE; adef->likelihoodEpsilon = 0.1; adef->permuteTreeoptimize = FALSE; adef->perGeneBranchLengths = FALSE; adef->useCheckpoint = FALSE; adef->useQuartetGrouping = FALSE; adef->numberRandomQuartets = 0; adef->quartetCkpInterval = 1000; #ifdef _BAYESIAN adef->bayesian = FALSE; #endif } static int modelExists(char *model, tree *tr) { if(strcmp(model, "PSR\0") == 0) { tr->rateHetModel = CAT; return 1; } if(strcmp(model, "GAMMA\0") == 0) { tr->rateHetModel = GAMMA; return 1; } return 0; } /*********************************** *********************************************************/ static void printVersionInfo(void) { if(processID == 0) printf("\n\nThis is %s version %s released by Alexandros Stamatakis, Andre J. Aberer, and Alexey Kozlov on %s.\n\n", programName, programVersion, programDate); } static void printMinusFUsage(void) { printf("\n"); printf(" \"-f d\": new rapid hill-climbing \n"); printf(" DEFAULT: ON\n"); printf("\n"); printf(" \"-f e\": compute the likelihood of a bunch of trees passed via -t\n"); printf(" this option will do a quick and dirty optimization without re-optimizng\n"); printf(" the model parameters for each tree\n"); printf("\n"); printf(" \"-f E\": compute the likelihood of a bunch of trees passed via -t\n"); printf(" this option will do a thorough optimization that re-optimizes\n"); printf(" the model parameters for each tree\n"); printf("\n"); printf(" \"-f o\": old and slower rapid hill-climbing without heuristic cutoff\n"); printf("\n"); printf(" \"-f q\": fast quartet calculator\n"); printf("\n"); printf(" DEFAULT for \"-f\": new rapid hill climbing\n"); printf("\n"); } static void printREADME(void) { if(processID == 0) { printVersionInfo(); printf("\n"); printf("\nTo report bugs use the RAxML google group\n"); printf("Please send me all input files, the exact invocation, details of the HW and operating system,\n"); printf("as well as all error messages printed to screen.\n\n\n"); printf("examl|examl-AVX\n"); printf(" -s binarySequenceFileName\n"); printf(" -n outputFileNames\n"); printf(" -m rateHeterogeneityModel\n"); printf(" -t userStartingTree|-R binaryCheckpointFile|-g constraintTree -p randomNumberSeed\n"); printf(" [-a]\n"); printf(" [-B numberOfMLtreesToSave]\n"); printf(" [-c numberOfCategories]\n"); printf(" [-D]\n"); printf(" [-e likelihoodEpsilon] \n"); printf(" [-f d|e|E|o|q]\n"); printf(" [-h] \n"); printf(" [-i initialRearrangementSetting] \n"); printf(" [-I quartetCheckpointInterval] \n"); printf(" [-M]\n"); printf(" [-r randomQuartetNumber] \n"); printf(" [-S]\n"); printf(" [-v]\n"); printf(" [-w outputDirectory] \n"); printf(" [-Y quartetGroupingFileName]\n"); printf(" [--auto-prot=ml|bic|aic|aicc]\n"); printf("\n"); printf(" -a use the median for the discrete approximation of the GAMMA model of rate heterogeneity\n"); printf("\n"); printf(" DEFAULT: OFF\n"); printf("\n"); printf(" -B specify the number of best ML trees to save and print to file\n"); printf("\n"); printf(" -c Specify number of distinct rate catgories for ExaML when modelOfEvolution\n"); printf(" is set to GTRPSR\n"); printf(" Individual per-site rates are categorized into numberOfCategories rate \n"); printf(" categories to accelerate computations. \n"); printf("\n"); printf(" DEFAULT: 25\n"); printf("\n"); printf(" -D ML search convergence criterion. This will break off ML searches if the relative \n"); printf(" Robinson-Foulds distance between the trees obtained from two consecutive lazy SPR cycles\n"); printf(" is smaller or equal to 1%s. Usage recommended for very large datasets in terms of taxa.\n", "%"); printf(" On trees with more than 500 taxa this will yield execution time improvements of approximately 50%s\n", "%"); printf(" While yielding only slightly worse trees.\n"); printf("\n"); printf(" DEFAULT: OFF\n"); printf("\n"); printf(" -e set model optimization precision in log likelihood units for final\n"); printf(" optimization of model parameters\n"); printf("\n"); printf(" DEFAULT: 0.1 \n"); printf("\n"); printf(" -f select algorithm:\n"); printMinusFUsage(); printf("\n"); printf(" -g Pass a multi-furcating constraint tree to ExaML. The tree needs to contain all taxa of the alignment!\n"); printf(" When using this option you also need to specify a random number seed via \"-p\"\n"); printf("\n"); printf(" -h Display this help message.\n"); printf("\n"); printf(" -i Initial rearrangement setting for the subsequent application of topological \n"); printf(" changes phase\n"); printf("\n"); printf(" -I Set after how many quartet evaluations a new checkpoint will be printed.\n"); printf("\n"); printf(" DEFAULT: 1000\n"); printf("\n"); printf(" -m Model of rate heterogeneity\n"); printf("\n"); printf(" select \"-m PSR\" for the per-site rate category model (this used to be called CAT in RAxML)\n"); printf(" select \"-m GAMMA\" for the gamma model of rate heterogeneity with 4 discrete rates\n"); printf("\n"); printf(" -M Switch on estimation of individual per-partition branch lengths. Only has effect when used in combination with \"-q\"\n"); printf(" Branch lengths for individual partitions will be printed to separate files\n"); printf(" A weighted average of the branch lengths is computed by using the respective partition lengths\n"); printf("\n"); printf(" DEFAULT: OFF\n"); printf("\n"); printf(" -n Specifies the name of the output file.\n"); printf("\n"); printf(" -p Specify a random number seed, required in conjunction with the \"-g\" option for constraint trees\n"); printf("\n"); printf(" -R read in a binary checkpoint file called ExaML_binaryCheckpoint.RUN_ID_number\n"); printf("\n"); printf(" -r Pass the number of quartets to randomly sub-sample from the possible number of quartets for the given taxon set.\n"); printf(" Only works in combination with -f q !\n"); printf("\n"); printf(" -s Specify the name of the BINARY alignment data file generated by the parser component\n"); printf("\n"); printf(" -S turn on memory saving option for gappy multi-gene alignments. For large and gappy datasets specify -S to save memory\n"); printf(" This will produce slightly different likelihood values, may be a bit slower but can reduce memory consumption\n"); printf(" from 70GB to 19GB on very large and gappy datasets\n"); printf("\n"); printf(" -t Specify a user starting tree file name in Newick format\n"); printf("\n"); printf(" -v Display version information\n"); printf("\n"); printf(" -w FULL (!) path to the directory into which ExaML shall write its output files\n"); printf("\n"); printf(" DEFAULT: current directory\n"); printf("\n"); printf(" -Y Pass a quartet grouping file name defining four groups from which to draw quartets\n"); printf(" The file input format must contain 4 groups in the following form:\n"); printf(" (Chicken, Human, Loach), (Cow, Carp), (Mouse, Rat, Seal), (Whale, Frog);\n"); printf(" Only works in combination with -f q !\n"); printf("\n"); printf("\n"); printf(" --auto-prot=ml|bic|aic|aicc When using automatic protein model selection you can chose the criterion for selecting these models.\n"); printf(" RAxML will test all available prot subst. models except for LG4M, LG4X and GTR-based models, with and without empirical base frequencies.\n"); printf(" You can chose between ML score based selection and the BIC, AIC, and AICc criteria.\n"); printf("\n"); printf(" DEFAULT: ml\n"); printf("\n\n\n\n"); } } static void analyzeRunId(char id[128]) { int i = 0; while(id[i] != '\0') { if(i >= 128) { printf("Error: run id after \"-n\" is too long, it has %d characters please use a shorter one\n", i); assert(0); } if(id[i] == '/') { printf("Error character %c not allowed in run ID\n", id[i]); assert(0); } i++; } if(i == 0) { printf("Error: please provide a string for the run id after \"-n\" \n"); assert(0); } } static void get_args(int argc, char *argv[], analdef *adef, tree *tr) { boolean resultDirSet = FALSE; char resultDir[1024] = "", //*optarg, model[1024] = "", modelChar; double likelihoodEpsilon; int fOptionCount = 0, c, nameSet = 0, treeSet = 0, modelSet = 0, byteFileSet = 0, seedSet = 0; /*********** tr inits **************/ tr->doCutoff = TRUE; tr->secondaryStructureModel = SEC_16; /* default setting */ tr->searchConvergenceCriterion = FALSE; tr->rateHetModel = GAMMA; tr->multiStateModel = GTR_MULTI_STATE; tr->useGappedImplementation = FALSE; tr->saveMemory = FALSE; tr->constraintTree = FALSE; tr->fastTreeEvaluation = FALSE; /* tr->manyPartitions = FALSE; */ tr->categories = 25; tr->gapyness = 0.0; tr->saveBestTrees = 0; tr->useMedian = FALSE; tr->autoProteinSelectionType = AUTO_ML; /********* tr inits end*************/ //while(!bad_opt && ((c = mygetopt(argc,argv,"R:B:e:c:f:i:m:t:g:w:n:s:p:vhMSDa", &optind, &optarg))!=-1)) static int flag; while(1) { static struct option long_options[2] = { {"auto-prot", required_argument, &flag, 1}, {0, 0, 0, 0} }; int option_index; flag = 0; c = getopt_long(argc, argv, "R:B:Y:I:e:c:f:i:m:t:g:w:n:s:p:r:vhMSDa", long_options, &option_index); if(c == -1) break; if(flag > 0) { switch(option_index) { case 0: { char *autoModels[4] = {"ml", "bic", "aic", "aicc"}; int k; for(k = 0; k < 4; k++) if(strcmp(optarg, autoModels[k]) == 0) break; if(k == 4) { printf("\nError, unknown protein model selection type, you can specify one of the following selection criteria:\n\n"); for(k = 0; k < 4; k++) printf("--auto-prot=%s\n", autoModels[k]); printf("\n"); errorExit(-1); } else { switch(k) { case 0: tr->autoProteinSelectionType = AUTO_ML; break; case 1: tr->autoProteinSelectionType = AUTO_BIC; break; case 2: tr->autoProteinSelectionType = AUTO_AIC; break; case 3: tr->autoProteinSelectionType = AUTO_AICC; break; default: assert(0); } } } break; default: assert(0); } } else switch(c) { case 'Y': adef->useQuartetGrouping = TRUE; strcpy(quartetGroupingFileName, optarg); break; case 'r': sscanf(optarg, "%lu", &(adef->numberRandomQuartets)); assert(adef->numberRandomQuartets > 0); break; case 'p': sscanf(optarg,"%u", &(tr->randomSeed)); seedSet = 1; break; case 'a': tr->useMedian = TRUE; break; case 'B': sscanf(optarg,"%d", &(tr->saveBestTrees)); if(tr->saveBestTrees < 0) { printf("Number of best trees to save must be greater than 0!\n"); errorExit(-1); } break; case 's': strcpy(byteFileName, optarg); byteFileSet = TRUE; /*printf("%s \n", byteFileName);*/ break; case 'S': tr->saveMemory = TRUE; break; case 'D': tr->searchConvergenceCriterion = TRUE; break; case 'R': adef->useCheckpoint = TRUE; strcpy(binaryCheckpointInputName, optarg); break; case 'I': sscanf(optarg, "%lu", &(adef->quartetCkpInterval)); break; case 'M': adef->perGeneBranchLengths = TRUE; break; case 'e': sscanf(optarg,"%lf", &likelihoodEpsilon); adef->likelihoodEpsilon = likelihoodEpsilon; break; case 'v': printVersionInfo(); errorExit(0); case 'h': printREADME(); errorExit(0); case 'c': sscanf(optarg, "%d", &tr->categories); break; case 'f': sscanf(optarg, "%c", &modelChar); fOptionCount++; if(fOptionCount > 1) { printf("\nError: only one of the various \"-f \" options can be used per ExaML run!\n"); printf("They are mutually exclusive! exiting ...\n\n"); errorExit(-1); } switch(modelChar) { case 'e': adef->mode = TREE_EVALUATION; tr->fastTreeEvaluation = TRUE; break; case 'E': adef->mode = TREE_EVALUATION; tr->fastTreeEvaluation = FALSE; break; case 'd': adef->mode = BIG_RAPID_MODE; tr->doCutoff = TRUE; break; case 'o': adef->mode = BIG_RAPID_MODE; tr->doCutoff = FALSE; break; case 'q': adef->mode = QUARTET_CALCULATION; break; default: { if(processID == 0) { printf("Error select one of the following algorithms via -f :\n"); printMinusFUsage(); } errorExit(-1); } } break; case 'i': sscanf(optarg, "%d", &adef->initial); adef->initialSet = TRUE; break; case 'n': strcpy(run_id,optarg); analyzeRunId(run_id); nameSet = 1; break; case 'w': strcpy(resultDir, optarg); resultDirSet = TRUE; break; case 't': strcpy(tree_file, optarg); treeSet = 1; break; case 'g': strcpy(tree_file, optarg); treeSet = 1; tr->constraintTree = TRUE; break; case 'm': strcpy(model,optarg); if(modelExists(model, tr) == 0) { if(processID == 0) { printf("Rate heterogeneity Model %s does not exist\n\n", model); printf("For per site rates (called CAT in previous versions) use: PSR\n"); printf("For GAMMA use: GAMMA\n"); } errorExit(-1); } else modelSet = 1; break; default: errorExit(-1); } } if(adef->useQuartetGrouping && adef->mode != QUARTET_CALCULATION) { if(processID == 0) printf("\nError, you must specify \"-Y quartetGroupingFileName\" in combination with \"-f q\"\n"); errorExit(-1); } if(adef->numberRandomQuartets > 0 && adef->mode != QUARTET_CALCULATION) { if(processID == 0) printf("\nError, you must specify \"-r randomQuartetNumber\" in combination with \"-f q\"\n"); errorExit(-1); } if((adef->numberRandomQuartets > 0) && (adef->useQuartetGrouping)) { if(processID == 0) printf("\nError, you must specify either \"-r randomQuartetNumber\" or \"-Y quartetGroupingFileName\"\n"); errorExit(-1); } if(tr->constraintTree) { if(!seedSet && processID == 0) { printf("\nError, you must specify a random number seed via \"-p\" when using a constraint\n"); printf("tree via \"-g\" \n"); errorExit(-1); } } if(!byteFileSet) { if(processID == 0) printf("\nError, you must specify a binary format data file with the \"-s\" option\n"); errorExit(-1); } if(!modelSet) { if(processID == 0) printf("\nError, you must specify a model of rate heterogeneity with the \"-m\" option\n"); errorExit(-1); } if(!nameSet) { if(processID == 0) printf("\nError: please specify a name for this run with -n\n"); errorExit(-1); } if(!treeSet && !adef->useCheckpoint) { if(processID == 0) { printf("\nError: please either specify a starting tree for this run with -t\n"); printf("or re-start the run from a checkpoint with -R\n"); } errorExit(-1); } { const char *separator = "/"; if(resultDirSet) { char dir[1024] = ""; if(resultDir[0] != separator[0]) strcat(dir, separator); strcat(dir, resultDir); if(dir[strlen(dir) - 1] != separator[0]) strcat(dir, separator); strcpy(workdir, dir); } else { char dir[1024] = "", *result = getcwd(dir, sizeof(dir)); assert(result != (char*)NULL); if(dir[strlen(dir) - 1] != separator[0]) strcat(dir, separator); strcpy(workdir, dir); } } return; } void errorExit(int e) { MPI_Finalize(); exit(e); } static void makeFileNames(void) { int infoFileExists = 0; strcpy(resultFileName, workdir); strcpy(logFileName, workdir); strcpy(infoFileName, workdir); strcpy(treeFileName, workdir); strcpy(binaryCheckpointName, workdir); strcpy(modelFileName, workdir); strcpy(quartetFileName, workdir); strcat(resultFileName, "ExaML_result."); strcat(logFileName, "ExaML_log."); strcat(infoFileName, "ExaML_info."); strcat(binaryCheckpointName, "ExaML_binaryCheckpoint."); strcat(modelFileName, "ExaML_modelFile."); strcat(treeFileName, "ExaML_TreeFile."); strcat(quartetFileName, "ExaML_quartets."); strcat(resultFileName, run_id); strcat(logFileName, run_id); strcat(infoFileName, run_id); strcat(binaryCheckpointName, run_id); strcat(modelFileName, run_id); strcat(treeFileName, run_id); strcat(quartetFileName, run_id); infoFileExists = filexists(infoFileName); if(infoFileExists) { if(processID == 0) { printf("ExaML output files with the run ID <%s> already exist \n", run_id); printf("in directory %s ...... exiting\n", workdir); } errorExit(-1); } } /***********************reading and initializing input ******************/ /********************PRINTING various INFO **************************************/ static void printModelAndProgramInfo(tree *tr, analdef *adef, int argc, char *argv[]) { if(processID == 0) { int i, model; FILE *infoFile = myfopen(infoFileName, "ab"); char modelType[128]; if(tr->useMedian) strcpy(modelType, "GAMMA with Median"); else strcpy(modelType, "GAMMA"); printBoth(infoFile, "\n\nThis is %s version %s released by Alexandros Stamatakis, Andre Aberer, and Alexey Kozlov in %s.\n\n", programName, programVersion, programDate); printBoth(infoFile, "\nAlignment has %zu distinct alignment patterns\n\n", tr->originalCrunchedLength); printBoth(infoFile, "Proportion of gaps and completely undetermined characters in this alignment: %3.2f%s\n", 100.0 * tr->gapyness, "%"); switch(adef->mode) { case BIG_RAPID_MODE: printBoth(infoFile, "\nExaML rapid hill-climbing mode\n\n"); break; case TREE_EVALUATION: printBoth(infoFile, "\nExaML %s tree evaluation mode\n\n", (tr->fastTreeEvaluation)?"fast":"slow"); break; case QUARTET_CALCULATION: printBoth(infoFile, "\nExaML quartet evaluation mode\n\n"); break; default: assert(0); } if(adef->perGeneBranchLengths) printBoth(infoFile, "Using %d distinct models/data partitions with individual per partition branch length optimization\n\n\n", tr->NumberOfModels); else printBoth(infoFile, "Using %d distinct models/data partitions with joint branch length optimization\n\n\n", tr->NumberOfModels); printBoth(infoFile, "All free model parameters will be estimated by ExaML\n"); if(tr->rateHetModel == GAMMA || tr->rateHetModel == GAMMA_I) printBoth(infoFile, "%s model of rate heteorgeneity, ML estimate of alpha-parameter\n\n", modelType); else { printBoth(infoFile, "ML estimate of %d per site rate categories\n\n", tr->categories); } for(model = 0; model < tr->NumberOfModels; model++) { printBoth(infoFile, "Partition: %d\n", model); printBoth(infoFile, "Alignment Patterns: %d\n", tr->partitionData[model].upper - tr->partitionData[model].lower); printBoth(infoFile, "Name: %s\n", tr->partitionData[model].partitionName); switch(tr->partitionData[model].dataType) { case DNA_DATA: printBoth(infoFile, "DataType: DNA\n"); printBoth(infoFile, "Substitution Matrix: GTR\n"); if(tr->partitionData[model].optimizeBaseFrequencies) printBoth(infoFile, "ML optimization of base frequencies\n"); break; case AA_DATA: assert(tr->partitionData[model].protModels >= 0 && tr->partitionData[model].protModels < NUM_PROT_MODELS); printBoth(infoFile, "DataType: AA\n"); printBoth(infoFile, "Substitution Matrix: %s\n", protModels[tr->partitionData[model].protModels]); if(!tr->partitionData[model].optimizeBaseFrequencies) printBoth(infoFile, "Using %s Base Frequencies\n", (tr->partitionData[model].protFreqs == 1)?"empirical":"fixed"); else printBoth(infoFile, "ML optimization of base frequencies\n"); break; case BINARY_DATA: printBoth(infoFile, "DataType: BINARY/MORPHOLOGICAL\n"); printBoth(infoFile, "Substitution Matrix: Uncorrected\n"); break; /* case SECONDARY_DATA: printBoth(infoFile, "DataType: SECONDARY STRUCTURE\n"); printBoth(infoFile, "Substitution Matrix: %s\n", secondaryModelList[tr->secondaryStructureModel]); break; case SECONDARY_DATA_6: printBoth(infoFile, "DataType: SECONDARY STRUCTURE 6 STATE\n"); printBoth(infoFile, "Substitution Matrix: %s\n", secondaryModelList[tr->secondaryStructureModel]); break; case SECONDARY_DATA_7: printBoth(infoFile, "DataType: SECONDARY STRUCTURE 7 STATE\n"); printBoth(infoFile, "Substitution Matrix: %s\n", secondaryModelList[tr->secondaryStructureModel]); break; case GENERIC_32: printBoth(infoFile, "DataType: Multi-State with %d distinct states in use (maximum 32)\n",tr->partitionData[model].states); switch(tr->multiStateModel) { case ORDERED_MULTI_STATE: printBoth(infoFile, "Substitution Matrix: Ordered Likelihood\n"); break; case MK_MULTI_STATE: printBoth(infoFile, "Substitution Matrix: MK model\n"); break; case GTR_MULTI_STATE: printBoth(infoFile, "Substitution Matrix: GTR\n"); break; default: assert(0); } break; case GENERIC_64: printBoth(infoFile, "DataType: Codon\n"); break; */ default: assert(0); } printBoth(infoFile, "\n\n\n"); } printBoth(infoFile, "\n"); printBoth(infoFile, "ExaML was called as follows:\n\n"); for(i = 0; i < argc; i++) printBoth(infoFile,"%s ", argv[i]); printBoth(infoFile,"\n\n\n"); fclose(infoFile); } } void printResult(tree *tr, analdef *adef, boolean finalPrint) { if(processID == 0) { FILE *logFile; char temporaryFileName[1024] = ""; strcpy(temporaryFileName, resultFileName); switch(adef->mode) { case TREE_EVALUATION: Tree2String(tr->tree_string, tr, tr->start->back, TRUE, TRUE, FALSE, FALSE, finalPrint, SUMMARIZE_LH, FALSE, FALSE); logFile = myfopen(temporaryFileName, "wb"); fprintf(logFile, "%s", tr->tree_string); fclose(logFile); if(adef->perGeneBranchLengths) printTreePerGene(tr, adef, temporaryFileName, "wb"); break; case BIG_RAPID_MODE: if(finalPrint) { switch(tr->rateHetModel) { case GAMMA: case GAMMA_I: Tree2String(tr->tree_string, tr, tr->start->back, TRUE, TRUE, FALSE, FALSE, finalPrint, SUMMARIZE_LH, FALSE, FALSE); logFile = myfopen(temporaryFileName, "wb"); fprintf(logFile, "%s", tr->tree_string); fclose(logFile); if(adef->perGeneBranchLengths) printTreePerGene(tr, adef, temporaryFileName, "wb"); break; case CAT: /*Tree2String(tr->tree_string, tr, tr->start->back, FALSE, TRUE, FALSE, FALSE, finalPrint, adef, NO_BRANCHES, FALSE, FALSE);*/ Tree2String(tr->tree_string, tr, tr->start->back, TRUE, TRUE, FALSE, FALSE, TRUE, SUMMARIZE_LH, FALSE, FALSE); logFile = myfopen(temporaryFileName, "wb"); fprintf(logFile, "%s", tr->tree_string); fclose(logFile); break; default: assert(0); } } else { Tree2String(tr->tree_string, tr, tr->start->back, FALSE, TRUE, FALSE, FALSE, finalPrint, NO_BRANCHES, FALSE, FALSE); logFile = myfopen(temporaryFileName, "wb"); fprintf(logFile, "%s", tr->tree_string); fclose(logFile); } break; default: printf("FATAL ERROR call to printResult from undefined STATE %d\n", adef->mode); exit(-1); break; } } } void printLog(tree *tr) { if(processID == 0) { FILE *logFile; double t; t = gettime() - masterTime; logFile = myfopen(logFileName, "ab"); /* printf("%f %1.40f\n", t, tr->likelihood); */ fprintf(logFile, "%f %f\n", t, tr->likelihood); fclose(logFile); } } void getDataTypeString(tree *tr, int model, char typeOfData[1024]) { switch(tr->partitionData[model].dataType) { case AA_DATA: strcpy(typeOfData,"AA"); break; case DNA_DATA: strcpy(typeOfData,"DNA"); break; case BINARY_DATA: strcpy(typeOfData,"BINARY/MORPHOLOGICAL"); break; case SECONDARY_DATA: strcpy(typeOfData,"SECONDARY 16 STATE MODEL USING "); strcat(typeOfData, secondaryModelList[tr->secondaryStructureModel]); break; case SECONDARY_DATA_6: strcpy(typeOfData,"SECONDARY 6 STATE MODEL USING "); strcat(typeOfData, secondaryModelList[tr->secondaryStructureModel]); break; case SECONDARY_DATA_7: strcpy(typeOfData,"SECONDARY 7 STATE MODEL USING "); strcat(typeOfData, secondaryModelList[tr->secondaryStructureModel]); break; case GENERIC_32: strcpy(typeOfData,"Multi-State"); break; case GENERIC_64: strcpy(typeOfData,"Codon"); break; default: assert(0); } } static void printRatesDNA_BIN(int n, double *r, char **names, char *fileName) { int i, j, c; for(i = 0, c = 0; i < n; i++) { for(j = i + 1; j < n; j++) { if(i == n - 2 && j == n - 1) printBothOpenDifferentFile(fileName, "rate %s <-> %s: %f\n", names[i], names[j], 1.0); else printBothOpenDifferentFile(fileName, "rate %s <-> %s: %f\n", names[i], names[j], r[c]); c++; } } } static void printRatesRest(int n, double *r, char **names, char *fileName) { int i, j, c; for(i = 0, c = 0; i < n; i++) { for(j = i + 1; j < n; j++) { printBothOpenDifferentFile(fileName, "rate %s <-> %s: %f\n", names[i], names[j], r[c]); c++; } } } static double branchLength(int model, double *z, tree *tr) { double x; x = z[model]; assert(x > 0); if (x < zmin) x = zmin; assert(x <= zmax); x = -log(x); return x; } static double treeLengthRec(nodeptr p, tree *tr, int model) { double x = branchLength(model, p->z, tr); if(isTip(p->number, tr->mxtips)) return x; else { double acc = 0; nodeptr q; q = p->next; while(q != p) { acc += treeLengthRec(q->back, tr, model); q = q->next; } return acc + x; } } static double treeLength(tree *tr, int model) { return treeLengthRec(tr->start->back, tr, model); } static void printFreqs(int n, double *f, char **names, char *fileName) { int k; for(k = 0; k < n; k++) printBothOpenDifferentFile(fileName, "freq pi(%s): %f\n", names[k], f[k]); } static void printModelParams(tree *tr, analdef *adef, int treeIteration) { int model; double *f = (double*)NULL, *r = (double*)NULL; char fileName[2048], buf[64]; strcpy(fileName, modelFileName); if(treeIteration >= 0) { strcat(fileName, "."); sprintf(buf, "%d", treeIteration); strcat(fileName, buf); } for(model = 0; model < tr->NumberOfModels; model++) { double tl; char typeOfData[1024]; getDataTypeString(tr, model, typeOfData); printBothOpenDifferentFile(fileName, "\n\n"); printBothOpenDifferentFile(fileName, "Model Parameters of Partition %d, Name: %s, Type of Data: %s\n", model, tr->partitionData[model].partitionName, typeOfData); if(tr->rateHetModel == GAMMA) printBothOpenDifferentFile(fileName, "alpha: %f\n", tr->partitionData[model].alpha); if(adef->perGeneBranchLengths) tl = treeLength(tr, model); else tl = treeLength(tr, 0); printBothOpenDifferentFile(fileName, "Tree-Length: %f\n", tl); f = tr->partitionData[model].frequencies; r = tr->partitionData[model].substRates; switch(tr->partitionData[model].dataType) { case AA_DATA: { char *freqNames[20] = {"A", "R", "N ","D", "C", "Q", "E", "G", "H", "I", "L", "K", "M", "F", "P", "S", "T", "W", "Y", "V"}; if(tr->partitionData[model].protModels == LG4M || tr->partitionData[model].protModels == LG4X) { int k; for(k = 0; k < 4; k++) { printBothOpenDifferentFile(fileName, "LGM %d\n", k); printRatesRest(20, tr->partitionData[model].substRates_LG4[k], freqNames, fileName); printBothOpenDifferentFile(fileName, "\n"); printFreqs(20, tr->partitionData[model].frequencies_LG4[k], freqNames, fileName); } } printRatesRest(20, r, freqNames, fileName); printBothOpenDifferentFile(fileName, "\n"); printFreqs(20, f, freqNames, fileName); } break; case DNA_DATA: { char *freqNames[4] = {"A", "C", "G", "T"}; printRatesDNA_BIN(4, r, freqNames, fileName); printBothOpenDifferentFile(fileName, "\n"); printFreqs(4, f, freqNames, fileName); } break; case BINARY_DATA: { char *freqNames[2] = {"0", "1"}; printRatesDNA_BIN(2, r, freqNames, fileName); printBothOpenDifferentFile(fileName, "\n"); printFreqs(2, f, freqNames, fileName); } break; default: assert(0); } printBothOpenDifferentFile(fileName, "\n"); } printBothOpenDifferentFile(fileName, "\n"); } static void finalizeInfoFile(tree *tr, analdef *adef) { if(processID == 0) { double t; t = gettime() - masterTime; accumulatedTime = accumulatedTime + t; switch(adef->mode) { case BIG_RAPID_MODE: printBothOpen("\n\nOverall Time for 1 Inference %f\n", t); printBothOpen("\nOverall accumulated Time (in case of restarts): %f\n\n", accumulatedTime); printBothOpen("Likelihood : %f\n", tr->likelihood); printBothOpen("\n\n"); printBothOpen("Model parameters written to: %s\n", modelFileName); printBothOpen("Final tree written to: %s\n", resultFileName); printBothOpen("Execution Log File written to: %s\n", logFileName); printBothOpen("Execution information file written to: %s\n",infoFileName); break; case TREE_EVALUATION: printBothOpen("\n\nOverall Time for evaluating the likelihood of %d trees: %f secs\n\n", tr->numberOfTrees, t); printBothOpen("\n\nThe model parameters of the trees have been written to files called %s.i\n", modelFileName); printBothOpen("where i is the number of the tree\n\n"); printBothOpen("Note that, in case of a restart from a checkpoint, some tree model files will have been produced by previous runs!\n\n"); printBothOpen("The trees with branch lengths have been written to file: %s\n", treeFileName); printBothOpen("They are in the same order as in the input file!\n\n"); break; case QUARTET_CALCULATION: printBothOpen("\n\nOverall quartet computation time: %f secs\n", t); printBothOpen("\nAll quartets and corresponding likelihoods written to file %s\n", quartetFileName); break; default: assert(0); } } } /************************************************************************************/ static int iterated_bitcount(unsigned int n) { int count=0; while(n) { count += n & 0x1u ; n >>= 1 ; } return count; } /*static char bits_in_16bits [0x1u << 16];*/ static void compute_bits_in_16bits(char *bits_in_16bits) { unsigned int i; /* size is 65536 */ for (i = 0; i < (0x1u<<16); i++) bits_in_16bits[i] = iterated_bitcount(i); return ; } unsigned int precomputed16_bitcount (unsigned int n, char *bits_in_16bits) { /* works only for 32-bit int*/ return bits_in_16bits [n & 0xffffu] + bits_in_16bits [(n >> 16) & 0xffffu] ; } static void clean_MPI_Exit(void) { MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); } static void error_MPI_Exit(void) { MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); exit(1); } static void initializePartitions(tree *tr) { size_t i, len, j, width; int model, maxCategories; compute_bits_in_16bits(tr->bits_in_16bits); maxCategories = tr->maxCategories; for(model = 0; model < tr->NumberOfModels; model++) { const partitionLengths *pl = getPartitionLengths(&(tr->partitionData[model])); //must already be set as a consequence of alloc in function readPartitions //and the subsequent copy of bf->partitions into tr->partitions! assert(tr->partitionData[model].partitionName != (char*)NULL); //printf("Partition name %s\n", tr->partitionData[model].partitionName); width = tr->partitionData[model].width; /* globalScaler needs to be 2 * tr->mxtips such that scalers of inner AND tip nodes can be added without a case switch to this end, it must also be initialized with zeros -> calloc */ len = 2 * tr->mxtips; tr->partitionData[model].globalScaler = (unsigned int *)calloc(len, sizeof(unsigned int)); #ifdef _USE_OMP tr->partitionData[model].threadGlobalScaler = (unsigned int**) calloc(tr->nThreads, sizeof(unsigned int*)); tr->partitionData[model].reductionBuffer = (double*) calloc(tr->nThreads, sizeof(double)); tr->partitionData[model].reductionBuffer2 = (double*) calloc(tr->nThreads, sizeof(double)); int t; for (t = 0; t < tr->maxThreadsPerModel; ++t) { Assign* pAss = tr->partThreadAssigns[model * tr->maxThreadsPerModel + t]; if (pAss) { int tid = pAss->procId; tr->partitionData[model].threadGlobalScaler[tid] = (unsigned int *)calloc(len, sizeof(unsigned int)); } } #endif tr->partitionData[model].left = (double *)malloc_aligned(pl->leftLength * (maxCategories + 1) * sizeof(double)); tr->partitionData[model].right = (double *)malloc_aligned(pl->rightLength * (maxCategories + 1) * sizeof(double)); tr->partitionData[model].EIGN = (double*)malloc(pl->eignLength * sizeof(double)); tr->partitionData[model].EV = (double*)malloc_aligned(pl->evLength * sizeof(double)); tr->partitionData[model].EI = (double*)malloc(pl->eiLength * sizeof(double)); tr->partitionData[model].substRates = (double *)malloc(pl->substRatesLength * sizeof(double)); //must already be set as a consequence of alloc in function readPartitions //and the subsequent copy of bf->partitions into tr->partitions! assert(tr->partitionData[model].frequencies != (double*)NULL); //tr->partitionData[model].frequencies = (double*)malloc(pl->frequenciesLength * sizeof(double)); tr->partitionData[model].freqExponents = (double*)malloc(pl->frequenciesLength * sizeof(double)); tr->partitionData[model].empiricalFrequencies = (double*)malloc(pl->frequenciesLength * sizeof(double)); tr->partitionData[model].tipVector = (double *)malloc_aligned(pl->tipVectorLength * sizeof(double)); if(tr->partitionData[model].protModels == LG4M || tr->partitionData[model].protModels == LG4X) { int k; for(k = 0; k < 4; k++) { tr->partitionData[model].rawEIGN_LG4[k] = (double*)malloc(pl->eignLength * sizeof(double)); tr->partitionData[model].EIGN_LG4[k] = (double*)malloc(pl->eignLength * sizeof(double)); tr->partitionData[model].EV_LG4[k] = (double*)malloc_aligned(pl->evLength * sizeof(double)); tr->partitionData[model].EI_LG4[k] = (double*)malloc(pl->eiLength * sizeof(double)); tr->partitionData[model].substRates_LG4[k] = (double *)malloc(pl->substRatesLength * sizeof(double)); tr->partitionData[model].frequencies_LG4[k] = (double*)malloc(pl->frequenciesLength * sizeof(double)); tr->partitionData[model].tipVector_LG4[k] = (double *)malloc_aligned(pl->tipVectorLength * sizeof(double)); } } tr->partitionData[model].symmetryVector = (int *)malloc(pl->symmetryVectorLength * sizeof(int)); tr->partitionData[model].frequencyGrouping = (int *)malloc(pl->frequencyGroupingLength * sizeof(int)); tr->partitionData[model].perSiteRates = (double *)malloc(sizeof(double) * tr->maxCategories); // tr->partitionData[model].nonGTR = FALSE; // tr->partitionData[model].optimizeBaseFrequencies = FALSE; //tr->partitionData[model].gammaRates = (double*)malloc(sizeof(double) * 4); tr->partitionData[model].xVector = (double **)malloc(sizeof(double*) * tr->mxtips); for(j = 0; j < (size_t)tr->mxtips; j++) tr->partitionData[model].xVector[j] = (double*)NULL; tr->partitionData[model].xSpaceVector = (size_t *)calloc(tr->mxtips, sizeof(size_t)); #ifdef __MIC_NATIVE tr->partitionData[model].mic_EV = (double*)malloc_aligned(4 * pl->evLength * sizeof(double)); tr->partitionData[model].mic_tipVector = (double*)malloc_aligned(4 * pl->tipVectorLength * sizeof(double)); tr->partitionData[model].mic_umpLeft = (double*)malloc_aligned(4 * pl->tipVectorLength * sizeof(double)); tr->partitionData[model].mic_umpRight = (double*)malloc_aligned(4 * pl->tipVectorLength * sizeof(double)); /* for Xeon Phi, sumBuffer must be padded to the multiple of 8 (because of site blocking in kernels) */ const int padded_width = GET_PADDED_WIDTH(width); const int span = (size_t)(tr->partitionData[model].states) * discreteRateCategories(tr->rateHetModel); tr->partitionData[model].sumBuffer = (double *)malloc_aligned(padded_width * span * sizeof(double)); /* fill padding entries with 1. (will be corrected for with zero site weights in wgt) */ { int k; for (k = width*span; k < padded_width*span; ++k) tr->partitionData[model].sumBuffer[k] = 1.; } #else tr->partitionData[model].sumBuffer = (double *)malloc_aligned(width * (size_t)(tr->partitionData[model].states) * discreteRateCategories(tr->rateHetModel) * sizeof(double)); #endif /* tr->partitionData[model].wgt = (int *)malloc_aligned(width * sizeof(int)); */ /* rateCategory must be assigned using calloc() at start up there is only one rate category 0 for all sites */ if(width > 0 && tr->saveMemory) { tr->partitionData[model].gapVectorLength = ((int)width / 32) + 1; len = tr->partitionData[model].gapVectorLength * 2 * tr->mxtips; tr->partitionData[model].gapVector = (unsigned int*)calloc(len, sizeof(unsigned int)); tr->partitionData[model].gapColumn = (double *)malloc_aligned(((size_t)tr->mxtips) * ((size_t)(tr->partitionData[model].states)) * discreteRateCategories(tr->rateHetModel) * sizeof(double)); } else { tr->partitionData[model].gapVectorLength = 0; tr->partitionData[model].gapVector = (unsigned int*)NULL; tr->partitionData[model].gapColumn = (double*)NULL; } } /* set up the averaged frac changes per partition such that no further reading accesses to aliaswgt are necessary and we can free the array for the GAMMA model */ { /* definitions: sizeof(short) <= sizeof(int) <= sizeof(long) size_t defined by address space (here: 64 bit). size_t + MPI is a bad idea: in the mpi2.2 standard, they do not mention it once. */ unsigned long *modelWeights = (unsigned long*) calloc(tr->NumberOfModels, sizeof(unsigned long)); size_t wgtsum = 0; /* determine my weights per partition */ for(model = 0; model < tr->NumberOfModels; model++) { const pInfo partition = tr->partitionData[model] ; size_t i = 0; for(i = 0; i < partition.width; ++i) modelWeights[model] += (long) partition.wgt[i]; } MPI_Allreduce(MPI_IN_PLACE, modelWeights, tr->NumberOfModels, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); /* determine sum */ for(model = 0; model < tr->NumberOfModels; ++model) wgtsum += modelWeights[model]; for(model = 0; model < tr->NumberOfModels; model++) { tr->partitionWeights[model] = (double)modelWeights[model]; tr->partitionContributions[model] = ((double)modelWeights[model]) / ((double)wgtsum); } free(modelWeights); } /* initialize gap bit vectors at tips when memory saving option is enabled */ if(tr->saveMemory) { for(model = 0; model NumberOfModels; model++) { int undetermined = getUndetermined(tr->partitionData[model].dataType); width = tr->partitionData[model].width; if(width > 0) { for(j = 1; j <= (size_t)(tr->mxtips); j++) for(i = 0; i < width; i++) if(tr->partitionData[model].yVector[j][i] == undetermined) tr->partitionData[model].gapVector[tr->partitionData[model].gapVectorLength * j + i / 32] |= mask32[i % 32]; } } } } static void initializeTree(tree *tr, analdef *adef) { size_t i ; if(adef->perGeneBranchLengths) tr->numBranches = tr->NumberOfModels; else tr->numBranches = 1; if(NUM_BRANCHES < tr->numBranches) { if(processID == 0 ) printf("You have specified per-partition branch lengths (-M option) with %d models. \n\ Please set #define NUM_BRANCHES in axml.h to %d (or higher) and recompile %s\n", tr->NumberOfModels,tr->NumberOfModels, programName ); error_MPI_Exit(); } /* If we use the RF-based convergence criterion we will need to allocate some hash tables. let's not worry about this right now, because it is indeed ExaML-specific */ tr->executeModel = (boolean *)calloc( tr->NumberOfModels, sizeof(boolean)); for(i = 0; i < (size_t)tr->NumberOfModels; i++) tr->executeModel[i] = TRUE; setupTree(tr); if(tr->searchConvergenceCriterion && processID == 0) { tr->bitVectors = initBitVector(tr->mxtips, &(tr->vLength)); tr->h = initHashTable(tr->mxtips * 4); } for(i = 1; i <= (size_t)tr->mxtips; i++) addword(tr->nameList[i], tr->nameHash, i); initializePartitions(tr); initModel(tr); } static int getNumberOfTrees(char *fileName, boolean getOffsets, exa_off_t *treeOffsets) { FILE *f = myfopen(fileName, "r"); int trees = 0, ch; if(getOffsets) treeOffsets[trees] = 0; while((ch = fgetc(f)) != EOF) { if(ch == ';') { trees++; if(getOffsets) treeOffsets[trees] = exa_ftell(f) + 1; } } assert(trees > 0); fclose(f); return trees; } static void optimizeTrees(tree *tr, analdef *adef) { exa_off_t *treeOffsets; int i; tr->numberOfTrees = getNumberOfTrees(tree_file, FALSE, (exa_off_t *)NULL); if(processID == 0) accumulatedTime = 0.0; treeOffsets = (exa_off_t *)malloc(sizeof(exa_off_t) * (tr->numberOfTrees + 1)); tr->likelihoods = (double *)malloc(sizeof(double) * tr->numberOfTrees); tr->treeStrings = (char *)malloc(sizeof(char) * (size_t)tr->treeStringLength * (size_t)tr->numberOfTrees); getNumberOfTrees(tree_file, TRUE, treeOffsets); if(processID == 0) printBothOpen("\n\nFound %d trees to evaluate\n\n", tr->numberOfTrees); i = 0; if(adef->useCheckpoint) { restart(tr, adef); i = ckp.treeIteration; if(tr->fastTreeEvaluation && i > 0) treeEvaluate(tr, 2); else modOpt(tr, 0.1, adef, i); tr->likelihoods[i] = tr->likelihood; Tree2String(tr->tree_string, tr, tr->start->back, TRUE, TRUE, FALSE, FALSE, FALSE, SUMMARIZE_LH, FALSE, FALSE); memcpy(&(tr->treeStrings[(size_t)tr->treeStringLength * (size_t)i]), tr->tree_string, sizeof(char) * tr->treeStringLength); if(processID == 0) printModelParams(tr, adef, i); i++; } for(; i < tr->numberOfTrees; i++) { FILE *treeFile = myfopen(tree_file, "rb"); if(exa_fseek(treeFile, treeOffsets[i], SEEK_SET) != 0) assert(0); tr->likelihood = unlikely; treeReadLen(treeFile, tr, FALSE, FALSE, FALSE); fclose(treeFile); tr->start = tr->nodep[1]; if(i > 0) resetBranches(tr); evaluateGeneric(tr, tr->start, TRUE); if(tr->fastTreeEvaluation && i > 0) { ckp.state = MOD_OPT; ckp.treeIteration = i; writeCheckpoint(tr, adef); treeEvaluate(tr, 2); } else { treeEvaluate(tr, 1); modOpt(tr, 0.1, adef, i); } tr->likelihoods[i] = tr->likelihood; Tree2String(tr->tree_string, tr, tr->start->back, TRUE, TRUE, FALSE, FALSE, FALSE, SUMMARIZE_LH, FALSE, FALSE); memcpy(&(tr->treeStrings[(size_t)tr->treeStringLength * (size_t)i]), tr->tree_string, sizeof(char) * tr->treeStringLength); if(processID == 0) printModelParams(tr, adef, i); } if(processID == 0) { FILE *f = myfopen(treeFileName, "w"); for(i = 0; i < tr->numberOfTrees; i++) { printBothOpen("Likelihood tree %d: %f \n", i, tr->likelihoods[i]); fprintf(f, "%s", &(tr->treeStrings[(size_t)tr->treeStringLength * (size_t)i])); } fclose(f); } } static void readByteFile (tree *tr, int commRank, int commSize ) { /* read stuff that is cheap; do not change the order! */ ByteFile *bFile = NULL; initializeByteFile(&bFile, byteFileName); readHeader(bFile); readTaxa(bFile); readPartitions(bFile); /* calculate optimal distribution of data */ PartitionAssignment *pAss = NULL; initializePartitionAssignment(&pAss, bFile->partitions, bFile->numPartitions, commSize); assign(pAss); if(commRank == 0 ) { printf("\n"); printAssignments(pAss); printf("\n"); printLoad(pAss); printf("\n"); } /* now the data of this process is in this struct */ readMyData(bFile,pAss, commRank ); /* carry over the information to the tree */ initializeTreeFromByteFile(bFile, tr); /* just fills up tr->partAssigns that contains the representation of the assignment that we will need */ copyAssignmentInfoToTree(pAss, tr); deletePartitionAssignment(pAss); deleteByteFile(bFile); } #ifdef _USE_OMP void allocateXVectors(tree* tr) { nodeptr p = tr->start, q = p->back; tr->td[0].ti[0].pNumber = p->number; tr->td[0].ti[0].qNumber = q->number; tr->td[0].count = 1; computeTraversalInfo(q, &(tr->td[0].ti[0]), &(tr->td[0].count), tr->mxtips, tr->numBranches, FALSE); traversalInfo *ti = tr->td[0].ti; int i, model; for(i = 1; i < tr->td[0].count; i++) { traversalInfo *tInfo = &ti[i]; /* now loop over all partitions for nodes p, q, and r of the current traversal vector entry */ for(model = 0; model < tr->NumberOfModels; model++) { /* printf("new view on model %d with width %d\n", model, width); */ size_t width = (size_t)tr->partitionData[model].width; double *x3_start = tr->partitionData[model].xVector[tInfo->pNumber - tr->mxtips - 1]; size_t rateHet = discreteRateCategories(tr->rateHetModel), /* get the number of states in the data stored in partition model */ states = (size_t)tr->partitionData[model].states, /* get the length of the current likelihood array stored at node p. This is important mainly for the SEV-based memory saving option described in here: F. Izquierdo-Carrasco, S.A. Smith, A. Stamatakis: "Algorithms, Data Structures, and Numerics for Likelihood-based Phylogenetic Inference of Huge Trees". So tr->partitionData[model].xSpaceVector[i] provides the length of the allocated conditional array of partition model and node i */ availableLength = tr->partitionData[model].xSpaceVector[(tInfo->pNumber - tr->mxtips - 1)], requiredLength = 0; /* memory saving stuff, not important right now, but if you are interested ask Fernando */ if(tr->saveMemory) { size_t j, setBits = 0; unsigned int *x1_gap = &(tr->partitionData[model].gapVector[tInfo->qNumber * tr->partitionData[model].gapVectorLength]), *x2_gap = &(tr->partitionData[model].gapVector[tInfo->rNumber * tr->partitionData[model].gapVectorLength]), *x3_gap = &(tr->partitionData[model].gapVector[tInfo->pNumber * tr->partitionData[model].gapVectorLength]); for(j = 0; j < (size_t)tr->partitionData[model].gapVectorLength; j++) { x3_gap[j] = x1_gap[j] & x2_gap[j]; setBits += (size_t)(precomputed16_bitcount(x3_gap[j], tr->bits_in_16bits)); } requiredLength = (width - setBits) * rateHet * states * sizeof(double); } else /* if we are not trying to save memory the space required to store an inner likelihood array is the number of sites in the partition times the number of states of the data type in the partition times the number of discrete GAMMA rates (1 for CAT essentially) times 8 bytes */ requiredLength = width * rateHet * states * sizeof(double); /* Initially, even when not using memory saving no space is allocated for inner likelihood arrats hence availableLength will be zero at the very first time we traverse the tree. Hence we need to allocate something here */ if(requiredLength != availableLength) { /* if there is a vector of incorrect length assigned here i.e., x3 != NULL we must free it first */ if(x3_start) free(x3_start); /* allocate memory: note that here we use a byte-boundary aligned malloc, because we need the vectors to be aligned at 16 BYTE (SSE3) or 32 BYTE (AVX) boundaries! */ x3_start = (double*)malloc_aligned(requiredLength); /* update the data structures for consistent bookkeeping */ tr->partitionData[model].xVector[tInfo->pNumber - tr->mxtips - 1] = x3_start; tr->partitionData[model].xSpaceVector[(tInfo->pNumber - tr->mxtips - 1)] = requiredLength; } } // for model } // for traversal } void assignPartitionsToThreads(tree *tr, int commRank) { pInfo** rankPartitions = (pInfo **)calloc(tr->NumberOfModels, sizeof(pInfo*) ); int i; for (i = 0; i < tr->NumberOfModels; ++i) { rankPartitions[i] = (pInfo *)calloc(1, sizeof(pInfo)); rankPartitions[i]->lower = 0; rankPartitions[i]->upper = tr->partitionData[i].width; rankPartitions[i]->width = rankPartitions[i]->upper; rankPartitions[i]->states = tr->partitionData[i].states; } PartitionAssignment *pAss = NULL; initializePartitionAssignment(&pAss, rankPartitions, tr->NumberOfModels, tr->nThreads); /* */ for(i = 0; i < pAss->numPartitions; ++i) { Partition *p = pAss->partitions + i; p->width = (int) ceil((float) p->width / (float) VECTOR_PADDING); } assign(pAss); /* Align partition sizes to the boundary (needed for site-blocking on the MIC) */ int j; for(i = 0; i < pAss->numProc; ++i) { for(j = 0; j < pAss->numAssignPerProc[i] ; ++j) { Assignment *a = &pAss->assignPerProc[i][j]; a->offset *= VECTOR_PADDING; a->width *= VECTOR_PADDING; /* adjust width of last chunk -> must NOT include padding */ size_t realWidth = rankPartitions[a->partId]->width; if (a->offset + a->width > realWidth) a->width = realWidth - a->offset; } } printf("Partition assignments to threads: \n"); printAssignments(pAss); printf("\n"); printLoad(pAss); printf("\n"); copyThreadAssignmentInfoToTree(pAss, tr); deletePartitionAssignment(pAss); for (i = 0; i < tr->NumberOfModels; ++i) free(rankPartitions[i]); free(rankPartitions); } #endif int main (int argc, char *argv[]) { MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &processID); MPI_Comm_size(MPI_COMM_WORLD, &processes); printf("\nThis is ExaML FINE-GRAIN MPI Process Number: %d\n", processID); MPI_Barrier(MPI_COMM_WORLD); { tree *tr = (tree*)malloc(sizeof(tree)); analdef *adef = (analdef*)malloc(sizeof(analdef)); /* tell the CPU to ignore exceptions generated by denormalized floating point values. If this is not done, depending on the input data, the likelihood functions can exhibit substantial run-time differences for vectors of equal length. */ #if ! (defined(__ppc) || defined(__powerpc__) || defined(PPC)) _mm_setcsr( _mm_getcsr() | _MM_FLUSH_ZERO_ON); #endif /* get the start time */ masterTime = gettime(); /* initialize the analysis parameters in struct adef to default values */ initAdef(adef); /* parse command line arguments: this has a side effect on tr struct and adef struct variables */ get_args(argc, argv, adef, tr); /* generate the ExaML output file names and store them in strings */ makeFileNames(); #ifdef _USE_OMP if(tr->saveMemory) { printBothOpen("\nError: Memory saving option \"-S\" is not supported by the OpenMP version of ExaML!\n\n"); error_MPI_Exit(); } #endif readByteFile(tr, processID, processes ); #ifdef _USE_OMP tr->nThreads = omp_get_max_threads(); assignPartitionsToThreads(tr, processID); #endif initializeTree(tr, adef); if(processID == 0) { printModelAndProgramInfo(tr, adef, argc, argv); printBothOpen("Memory Saving Option: %s\n", (tr->saveMemory == TRUE)?"ENABLED":"DISABLED"); } /* do some error checks for the LG4 model and the binary models and the MIC and exit gracefully */ { int countBinary = 0, countLG4 = 0, model; #ifdef __MIC_NATIVE if(tr->saveMemory) { printBothOpen("Error: There is no MIC support yet for the memory saving option \"-S\"!\n\n"); error_MPI_Exit(); } if(tr->rateHetModel == CAT) { printBothOpen("Error: There is no MIC support yet for the PSR model!\n\n"); error_MPI_Exit(); } #endif for(model = 0; model < tr->NumberOfModels; model++) { if(tr->partitionData[model].protModels == LG4M || tr->partitionData[model].protModels == LG4X) countLG4++; if(tr->partitionData[model].states == 2) countBinary++; } if(countLG4 > 0) { if(tr->saveMemory == TRUE) { printBothOpen("Error: the LG4 substitution model does not work in combination with the \"-S\" memory saving flag!\n\n"); error_MPI_Exit(); } if(tr->rateHetModel == CAT) { printBothOpen("Error: the LG4 substitution model does not work for proportion of invariavble sites estimates!\n\n"); error_MPI_Exit(); } } if(countBinary > 0) { if(tr->saveMemory == TRUE) { printBothOpen("Error: Binary data partitions can not be used in combination with the \"-S\" memory saving flag!\n\n"); error_MPI_Exit(); } #ifdef __MIC_NATIVE printBothOpen("Error: There is no MIC support yet for binary data partitions!\n\n"); error_MPI_Exit(); #endif } if(countBinary > 0) { if(tr->saveMemory == TRUE) { printBothOpen("Error: Binary data partitions can not be used in combination with the \"-S\" memory saving flag!\n\n"); error_MPI_Exit(); } #ifdef __MIC_NATIVE printBothOpen("Error: There is no MIC support yet for binary data partitions!\n\n"); error_MPI_Exit(); #endif } } /* this will re-start ExaML exactly where it has left off from a checkpoint file, while checkpointing is important and has to be implemented for the library we should not worry about this right now */ switch(adef->mode) { case TREE_EVALUATION: optimizeTrees(tr, adef); break; case BIG_RAPID_MODE: if(adef->useCheckpoint) { /* read checkpoint file */ restart(tr, adef); /* continue tree search where we left it off */ computeBIGRAPID(tr, adef, TRUE); /* now print the model parameters to file */ if(processID == 0) printModelParams(tr, adef, -1); } else { /* not important, only used to keep track of total accumulated exec time when checkpointing and restarts were used */ if(processID == 0) accumulatedTime = 0.0; /* get the starting tree: here we just parse the tree passed via the command line and do an initial likelihood computation traversal which we maybe should skip, TODO */ getStartingTree(tr); #ifdef _USE_OMP allocateXVectors(tr); #endif /* here we do an initial full tree traversal on the starting tree using the Felsenstein pruning algorithm This should basically be the first call to the library that actually computes something :-) */ evaluateGeneric(tr, tr->start, TRUE); /* the treeEvaluate() function repeatedly iterates over the entire tree to optimize branch lengths until convergence */ treeEvaluate(tr, 1); /* now start the ML search algorithm */ computeBIGRAPID(tr, adef, TRUE); /* now print the model parameters to file */ if(processID == 0) printModelParams(tr, adef, -1); } break; case QUARTET_CALCULATION: computeQuartets(tr, adef); break; default: assert(0); } /* print some more nonsense into the ExaML_info file */ if(processID == 0) finalizeInfoFile(tr, adef); } /* return 0 which means that our unix program terminated correctly, the return value is not 1 here */ clean_MPI_Exit(); return 0; } ExaML-3.0.21/examl/axml.h000066400000000000000000001142051330315463200147660ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses * with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifndef _AXML_H #define _AXML_H #include #include #include #include #include "../versionHeader/version.h" #ifdef __MIC_NATIVE #define BYTE_ALIGNMENT 64 #define VECTOR_PADDING 8 #elif defined __AVX #define BYTE_ALIGNMENT 32 #define VECTOR_PADDING 1 #else #define BYTE_ALIGNMENT 16 #define VECTOR_PADDING 1 #endif #define GET_PADDED_WIDTH(w) w % VECTOR_PADDING == 0 ? w : w + (VECTOR_PADDING - (w % VECTOR_PADDING)) #include #ifdef _USE_OMP #include "omp.h" #endif /* BEGIN: file streams */ #ifdef _GNU_SOURCE /* notice, that the gnu source macro implies posix compliance */ /* these are posix compliant functions. They potentially work on files larger than 2 GB (for gcc this can be ensured using the following macro) */ #define exa_fseek fseeko #define exa_ftell ftello #define exa_off_t off_t /* only usefull for ftello/fseeko: ensure that we are using 64-bit types for representing an offset */ #define _FILE_OFFSET_BITS 64 #else #define exa_fseek fseek #define exa_ftell ftell #define exa_off_t long #endif /* END: file streams */ #define MAX_TIP_EV 0.999999999 /* max tip vector value, sum of EVs needs to be smaller than 1.0, otherwise the numerics break down */ #define smoothings 32 /* maximum smoothing passes through tree */ #define iterations 10 /* maximum iterations of iterations per insert */ #define newzpercycle 1 /* iterations of makenewz per tree traversal */ #define nmlngth 256 /* number of characters in species name */ #define deltaz 0.00001 /* test of net branch length change in update */ #define defaultz 0.9 /* value of z assigned as starting point */ #define unlikely -1.0E300 /* low likelihood for initialization */ #define AUTO_ML 0 #define AUTO_BIC 1 #define AUTO_AIC 2 #define AUTO_AICC 3 #define SUMMARIZE_LENGTH -3 #define SUMMARIZE_LH -2 #define NO_BRANCHES -1 #define MASK_LENGTH 32 #define GET_BITVECTOR_LENGTH(x) ((x % MASK_LENGTH) ? (x / MASK_LENGTH + 1) : (x / MASK_LENGTH)) #define zmin 1.0E-15 /* max branch prop. to -log(zmin) (= 34) */ #define zmax (1.0 - 1.0E-6) /* min branch prop. to 1.0-zmax (= 1.0E-6) */ #define twotothe256 \ 115792089237316195423570985008687907853269984665640564039457584007913129639936.0 /* 2**256 (exactly) */ #define minlikelihood (1.0/twotothe256) #define minusminlikelihood -minlikelihood /* 18446744073709551616.0 */ /*4294967296.0*/ /* 18446744073709551616.0 */ /* 2**64 (exactly) */ /* 4294967296 2**32 */ #define badRear -1 #define NUM_BRANCHES 256 #define TRUE 1 #define FALSE 0 #define LIKELIHOOD_EPSILON 0.0000001 #define AA_SCALE 10.0 #define AA_SCALE_PLUS_EPSILON 10.001 /* ALPHA_MIN is critical -> numerical instability, eg for 4 discrete rate cats */ /* and alpha = 0.01 the lowest rate r_0 is */ /* 0.00000000000000000000000000000000000000000000000000000000000034878079110511010487 */ /* which leads to numerical problems Table for alpha settings below: */ /* */ /* 0.010000 0.00000000000000000000000000000000000000000000000000000000000034878079110511010487 */ /* 0.010000 yielded nasty numerical bugs in at least one case ! */ /* 0.020000 0.00000000000000000000000000000044136090435925743185910935350715027016962154188875 */ /* 0.030000 0.00000000000000000000476844846859006690412039180149775802624789852441798419292220 */ /* 0.040000 0.00000000000000049522423236954066431210260930029681736928018820007024736185030633 */ /* 0.050000 0.00000000000050625351310359203371872643495343928538368616365517027588794007897377 */ /* 0.060000 0.00000000005134625283884191118711474021861409372524676086868566926568746566772461 */ /* 0.070000 0.00000000139080650074206434685544624965062437960128249869740102440118789672851562 */ /* 0.080000 0.00000001650681201563587066858709818343436959153791576682124286890029907226562500 */ /* 0.090000 0.00000011301977332931251259273962858978301859735893231118097901344299316406250000 */ /* 0.100000 0.00000052651925834844387815526344648331402709118265192955732345581054687500000000 */ #define ALPHA_MIN 0.02 #define ALPHA_MAX 1000.0 #define RATE_MIN 0.0000001 #define RATE_MAX 1000000.0 #define INVAR_MIN 0.0001 #define INVAR_MAX 0.9999 #define TT_MIN 0.0000001 #define TT_MAX 1000000.0 #define FREQ_MIN 0.001 #define LG4X_RATE_MIN 0.0000001 #define LG4X_RATE_MAX 1000.0 /* previous values between 0.001 and 0.000001 TO AVOID NUMERICAL PROBLEMS WHEN FREQ == 0 IN PARTITIONED MODELS, ESPECIALLY WITH AA previous value of FREQ_MIN was: 0.000001, but this seemed to cause problems with some of the 7-state secondary structure models with some rather exotic small toy test datasets, on the other hand 0.001 caused problems with some of the 16-state secondary structure models For some reason the frequency settings seem to be repeatedly causing numerical problems */ #define ITMAX 100 #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d); #define SIGN(a,b) ((b) > 0.0 ? fabs(a) : -fabs(a)) #define ABS(x) (((x)<0) ? (-(x)) : (x)) #define MIN(x,y) (((x)<(y)) ? (x) : (y)) #define MAX(x,y) (((x)>(y)) ? (x) : (y)) #define NINT(x) ((int) ((x)>0 ? ((x)+0.5) : ((x)-0.5))) #define LOG(x) log(x) #define FABS(x) fabs(x) #define EXP(x) exp(x) #define PointGamma(prob,alpha,beta) PointChi2(prob,2.0*(alpha))/(2.0*(beta)) //#define programName "ExaML" //#define programVersion "2.0.3" //#define programDate "June 25 2014" #define TREE_EVALUATION 0 #define BIG_RAPID_MODE 1 #define QUARTET_CALCULATION 2 #define M_GTRCAT 1 #define M_GTRGAMMA 2 #define M_BINCAT 3 #define M_BINGAMMA 4 #define M_PROTCAT 5 #define M_PROTGAMMA 6 #define M_32CAT 7 #define M_32GAMMA 8 #define M_64CAT 9 #define M_64GAMMA 10 #define DAYHOFF 0 #define DCMUT 1 #define JTT 2 #define MTREV 3 #define WAG 4 #define RTREV 5 #define CPREV 6 #define VT 7 #define BLOSUM62 8 #define MTMAM 9 #define LG 10 #define MTART 11 #define MTZOA 12 #define PMB 13 #define HIVB 14 #define HIVW 15 #define JTTDCMUT 16 #define FLU 17 #define STMTREV 18 #define AUTO 19 #define LG4M 20 #define LG4X 21 #define GTR 22 /* GTR always needs to be the last one */ #define NUM_PROT_MODELS 23 /* bipartition stuff */ #define BIPARTITIONS_ALL 0 #define GET_BIPARTITIONS_BEST 1 #define DRAW_BIPARTITIONS_BEST 2 #define BIPARTITIONS_BOOTSTOP 3 #define BIPARTITIONS_RF 4 /* bootstopping stuff */ #define BOOTSTOP_PERMUTATIONS 100 #define START_BSTOP_TEST 10 #define FC_THRESHOLD 99 #define FC_SPACING 50 #define FC_LOWER 0.99 #define FC_INIT 20 #define FREQUENCY_STOP 0 #define MR_STOP 1 #define MRE_STOP 2 #define MRE_IGN_STOP 3 #define MR_CONSENSUS 0 #define MRE_CONSENSUS 1 #define STRICT_CONSENSUS 2 /* bootstopping stuff end */ #define TIP_TIP 0 #define TIP_INNER 1 #define INNER_INNER 2 #define MIN_MODEL -1 #define BINARY_DATA 0 #define DNA_DATA 1 #define AA_DATA 2 #define SECONDARY_DATA 3 #define SECONDARY_DATA_6 4 #define SECONDARY_DATA_7 5 #define GENERIC_32 6 #define GENERIC_64 7 #define MAX_MODEL 8 #define SEC_6_A 0 #define SEC_6_B 1 #define SEC_6_C 2 #define SEC_6_D 3 #define SEC_6_E 4 #define SEC_7_A 5 #define SEC_7_B 6 #define SEC_7_C 7 #define SEC_7_D 8 #define SEC_7_E 9 #define SEC_7_F 10 #define SEC_16 11 #define SEC_16_A 12 #define SEC_16_B 13 #define SEC_16_C 14 #define SEC_16_D 15 #define SEC_16_E 16 #define SEC_16_F 17 #define SEC_16_I 18 #define SEC_16_J 19 #define SEC_16_K 20 #define ORDERED_MULTI_STATE 0 #define MK_MULTI_STATE 1 #define GTR_MULTI_STATE 2 #define CAT 0 #define GAMMA 1 #define GAMMA_I 2 typedef int boolean; typedef struct { double lh; int tree; double weight; } elw; struct ent { unsigned int *bitVector; unsigned int *treeVector; unsigned int amountTips; int *supportVector; unsigned int bipNumber; unsigned int bipNumber2; unsigned int supportFromTreeset[2]; struct ent *next; }; typedef struct ent entry; typedef unsigned int hashNumberType; /*typedef uint_fast32_t parsimonyNumber;*/ #define PCF 32 /* typedef uint64_t parsimonyNumber; #define PCF 16 typedef unsigned char parsimonyNumber; #define PCF 2 */ typedef struct { hashNumberType tableSize; entry **table; hashNumberType entryCount; } hashtable; struct stringEnt { int nodeNumber; char *word; struct stringEnt *next; }; typedef struct stringEnt stringEntry; typedef struct { hashNumberType tableSize; stringEntry **table; } stringHashtable; typedef struct ratec { double accumulatedSiteLikelihood; double rate; } rateCategorize; typedef struct { int tipCase; int pNumber; int qNumber; int rNumber; double qz[NUM_BRANCHES]; double rz[NUM_BRANCHES]; } traversalInfo; typedef struct { traversalInfo *ti; int count; int functionType; boolean traversalHasChanged; boolean *executeModel; double *parameterValues; } traversalData; struct noderec; typedef struct { unsigned int *vector; int support; struct noderec *oP; struct noderec *oQ; } branchInfo; typedef struct { boolean valid; int partitions; int *partitionList; } linkageData; typedef struct { int entries; linkageData* ld; } linkageList; typedef struct noderec { double z[NUM_BRANCHES]; #ifdef _BAYESIAN double z_tmp[NUM_BRANCHES]; #endif struct noderec *next; struct noderec *back; hashNumberType hash; int number; char x; char xPars; char xBips; } node, *nodeptr; typedef struct { double lh; int number; } info; typedef struct bInf { double likelihood; nodeptr node; } bestInfo; typedef struct iL { bestInfo *list; int n; int valid; } infoList; typedef unsigned int parsimonyNumber; typedef struct { int states; int maxTipStates; size_t lower; size_t upper; size_t width; size_t offset; /* NEW: makes the data assigned to this process identifiable (since we now, that all data from one partition must be in one contiguous chunk). */ int dataType; int protModels; int autoProtModels; int protFreqs; boolean nonGTR; boolean optimizeBaseFrequencies; int numberOfCategories; char *partitionName; int *symmetryVector; int *frequencyGrouping; double *sumBuffer; double gammaRates[4]; double *EIGN; double *EV; double *EI; double *left; double *right; /* LG4 */ double *rawEIGN_LG4[4]; double *EIGN_LG4[4]; double *EV_LG4[4]; double *EI_LG4[4]; double *frequencies_LG4[4]; double *tipVector_LG4[4]; double *substRates_LG4[4]; /* LG4X */ double weights[4]; double weightExponents[4]; double weightsBuffer[4]; double weightExponentsBuffer[4]; /* LG4 */ double *frequencies; double *freqExponents; double *empiricalFrequencies; double *tipVector; double *substRates; double *perSiteRates; int *wgt; int *rateCategory; double alpha; double **xVector; size_t *xSpaceVector; unsigned char **yVector; unsigned char *yResource; /* contains the entire array, that is referenced in yVector */ unsigned int *globalScaler; int gapVectorLength; unsigned int *gapVector; double *gapColumn; size_t parsimonyLength; parsimonyNumber *parsVect; double *lhs; double *patrat; #ifdef _USE_OMP /* thread-private data for OMP version */ unsigned int **threadGlobalScaler; double *reductionBuffer; double *reductionBuffer2; #endif #ifdef __MIC_NATIVE double *mic_EV; double *mic_tipVector; /* these arrays will store the precomputed product of tipVector and left/right P-matrix */ double *mic_umpLeft; double *mic_umpRight; #endif } pInfo; typedef struct { int left; int right; double likelihood; } lhEntry; typedef struct { int count; int size; lhEntry *entries; } lhList; typedef struct List_{ void *value; struct List_ *next; } List; #define REARR_SETTING 1 #define FAST_SPRS 2 #define SLOW_SPRS 3 #define MOD_OPT 4 #define QUARTETS 5 typedef struct { boolean useMedian; int saveBestTrees; boolean saveMemory; boolean searchConvergenceCriterion; boolean perGeneBranchLengths; //adef double likelihoodEpsilon; //adef int categories; int mode; //adef int fastTreeEvaluation; boolean initialSet;//adef int initial;//adef int rateHetModel; int autoProteinSelectionType; //quartets boolean useQuartetGrouping;//adef unsigned long int numberRandomQuartets;//adef } commandLine; typedef struct { int state; /* search algorithm */ unsigned int vLength; boolean constraintTree; int rearrangementsMax; int rearrangementsMin; int thoroughIterations; int fastIterations; int treeVectorLength; int mintrav; int maxtrav; int bestTrav; int Thorough; int optimizeRateCategoryInvocations; double accumulatedTime; double startLH; double lh; double previousLh; double difference; double epsilon; boolean impr; boolean cutoff; double tr_startLH; double tr_endLH; double tr_likelihood; double tr_bestOfNode; double tr_lhCutoff; double tr_lhAVG; double tr_lhDEC; int tr_NumberOfCategories; int tr_itCount; int tr_doCutoff; /* modOpt */ int catOpt; int treeIteration; /* quartets */ long seed; int flavor; uint64_t quartetCounter; long filePosition; char quartetFileName[1024]; //FILE NAME??? /* command line settings */ commandLine cmd; } checkPointState; typedef struct { double EIGN[19] __attribute__ ((aligned (BYTE_ALIGNMENT))); double EV[400] __attribute__ ((aligned (BYTE_ALIGNMENT))); double EI[380] __attribute__ ((aligned (BYTE_ALIGNMENT))); double substRates[190]; double frequencies[20] ; double tipVector[460] __attribute__ ((aligned (BYTE_ALIGNMENT))); double left[1600] __attribute__ ((aligned (BYTE_ALIGNMENT))); double right[1600] __attribute__ ((aligned (BYTE_ALIGNMENT))); } siteAAModels; typedef struct assign { int partitionId; int procId; /* to which process is the partition assigned */ size_t offset; /* what is the offset of this assignment */ size_t width; } Assign ; typedef struct { int *ti; unsigned int randomSeed; boolean constraintTree; boolean useGappedImplementation; boolean saveMemory; int saveBestTrees; stringHashtable *nameHash; pInfo *partitionData; char *secondaryStructureInput; boolean *executeModel; double *perPartitionLH; traversalData td[1]; int maxCategories; int categories; double coreLZ[NUM_BRANCHES]; int numBranches; branchInfo *bInf; int multiStateModel; boolean curvatOK[NUM_BRANCHES]; /* the stuff below is shared among DNA and AA, span does not change depending on datatype */ /* model stuff end */ unsigned char **yVector; int secondaryStructureModel; size_t originalCrunchedLength; int *secondaryStructurePairs; double *partitionContributions; double *partitionWeights; double lhCutoff; double lhAVG; unsigned long lhDEC; unsigned long itCount; int numberOfInvariableColumns; int weightOfInvariableColumns; int rateHetModel; double startLH; double endLH; double likelihood; node **nodep; nodeptr nodeBaseAddress; node *start; int mxtips; int *constraintVector; int numberOfSecondaryColumns; boolean searchConvergenceCriterion; int ntips; int nextnode; int NumberOfModels; boolean bigCutoff; boolean partitionSmoothed[NUM_BRANCHES]; boolean partitionConverged[NUM_BRANCHES]; boolean rooted; boolean doCutoff; double gapyness; char **nameList; char *tree_string; char *treeStrings; char *tree0; char *tree1; int treeStringLength; unsigned int bestParsimony; unsigned int *parsimonyScore; double bestOfNode; nodeptr removeNode; nodeptr insertNode; double zqr[NUM_BRANCHES]; double currentZQR[NUM_BRANCHES]; double currentLZR[NUM_BRANCHES]; double currentLZQ[NUM_BRANCHES]; double currentLZS[NUM_BRANCHES]; double currentLZI[NUM_BRANCHES]; double lzs[NUM_BRANCHES]; double lzq[NUM_BRANCHES]; double lzr[NUM_BRANCHES]; double lzi[NUM_BRANCHES]; unsigned int **bitVectors; unsigned int vLength; hashtable *h; char bits_in_16bits [0x1u << 16]; boolean useMedian; int autoProteinSelectionType; int numberOfTrees; double *likelihoods; boolean fastTreeEvaluation; int numAssignments; Assign *partAssigns; /** IMPORTANT: introducing a few resource pointers. All memeory needed for example for per-partition patrats is owned by these basepointers, the per-partition pointer just points at the contiguous block of memory. The big advantage, why I really think, this is worth it is, that these base pointers can be used to conveniently gather/scatter all data at a master. The master still has to reorder the gathered data, but less copying is necessary at the workers REQUIREMENTS: * all memory necessary for a partition must be in a contiguous block, * memory for partitions is ordered by partition id (first * partition 1, then partition 2,... ) */ double *patrat_basePtr; int *rateCategory_basePtr; double *lhs_basePtr; #ifdef _USE_OMP /* number of OMP threads*/ int nThreads; /* maximum number of partitions assigned to a single thread */ int maxModelsPerThread; /* maximum number of threads assigned to a single partition */ int maxThreadsPerModel; /* partition-to-threads assignments: indexed by thread */ Assign **threadPartAssigns; /* partition-to-threads assignments: indexed by partition id */ Assign **partThreadAssigns; #endif } tree; /***************************************************************/ typedef struct { int partitionNumber; int partitionLength; } partitionType; typedef struct { double z[NUM_BRANCHES]; nodeptr p, q; int cp, cq; } connectRELL, *connptrRELL; typedef struct { connectRELL *connect; int start; double likelihood; } topolRELL; typedef struct { int max; topolRELL **t; } topolRELL_LIST; /**************************************************************/ typedef struct conntyp { double z[NUM_BRANCHES]; /* branch length */ node *p, *q; /* parent and child sectors */ void *valptr; /* pointer to value of subtree */ int descend; /* pointer to first connect of child */ int sibling; /* next connect from same parent */ } connect, *connptr; typedef struct { double likelihood; int initialTreeNumber; connect *links; /* pointer to first connect (start) */ node *start; int nextlink; /* index of next available connect */ /* tr->start = tpl->links->p */ int ntips; int nextnode; int scrNum; /* position in sorted list of scores */ int tplNum; /* position in sorted list of trees */ } topol; typedef struct { double best; /* highest score saved */ double worst; /* lowest score saved */ topol *start; /* starting tree for optimization */ topol **byScore; topol **byTopol; int nkeep; /* maximum topologies to save */ int nvalid; /* number of topologies saved */ int ninit; /* number of topologies initialized */ int numtrees; /* number of alternatives tested */ boolean improved; } bestlist; #define randomTree 0 #define givenTree 1 #define parsimonyTree 2 typedef struct { int bestTrav; int max_rearrange; int stepwidth; int initial; boolean initialSet; int mode; boolean perGeneBranchLengths; boolean permuteTreeoptimize; boolean compressPatterns; double likelihoodEpsilon; boolean useCheckpoint; boolean useQuartetGrouping; unsigned long int numberRandomQuartets; unsigned long int quartetCkpInterval; #ifdef _BAYESIAN boolean bayesian; #endif } analdef; typedef struct { int leftLength; int rightLength; int eignLength; int evLength; int eiLength; int substRatesLength; int frequenciesLength; int tipVectorLength; int symmetryVectorLength; int frequencyGroupingLength; boolean nonGTR; int undetermined; const char *inverseMeaning; int states; boolean smoothFrequencies; const unsigned int *bitVector; } partitionLengths; /****************************** FUNCTIONS ****************************************************/ #ifdef _BAYESIAN extern void mcmc(tree *tr, analdef *adef); #endif boolean isThisMyPartition(tree *localTree, int tid, int model); extern boolean allSmoothed(tree *tr); extern int treeFindTipName(FILE *fp, tree *tr, boolean check); extern void computePlacementBias(tree *tr, analdef *adef); extern int lookupWord(char *s, stringHashtable *h); extern void getDataTypeString(tree *tr, int model, char typeOfData[1024]); extern unsigned int genericBitCount(unsigned int* bitVector, unsigned int bitVectorLength); extern int countTips(nodeptr p, int numsp); extern entry *initEntry(void); extern void computeRogueTaxa(tree *tr, char* treeSetFileName, analdef *adef); extern unsigned int precomputed16_bitcount(unsigned int n, char *bits_in_16bits); extern size_t discreteRateCategories(int rateHetModel); extern partitionLengths * getPartitionLengths(pInfo *p); extern boolean getSmoothFreqs(int dataType); extern const unsigned int *getBitVector(int dataType); extern int getUndetermined(int dataType); extern int getStates(int dataType); extern char getInverseMeaning(int dataType, unsigned char state); extern double gettime ( void ); extern int gettimeSrand ( void ); extern double randum ( long *seed ); extern void getxnode ( nodeptr p ); extern void hookup ( nodeptr p, nodeptr q, double *z, int numBranches); extern void hookupDefault ( nodeptr p, nodeptr q, int numBranches); extern boolean whitechar ( int ch ); extern void errorExit ( int e ); extern void printResult ( tree *tr, analdef *adef, boolean finalPrint ); extern void printBootstrapResult ( tree *tr, analdef *adef, boolean finalPrint ); extern void printBipartitionResult ( tree *tr, analdef *adef, boolean finalPrint ); extern void printLog ( tree *tr); extern void printStartingTree ( tree *tr, analdef *adef, boolean finalPrint ); extern void writeInfoFile ( analdef *adef, tree *tr, double t ); extern int main ( int argc, char *argv[] ); extern void calcBipartitions ( tree *tr, analdef *adef, char *bestTreeFileName, char *bootStrapFileName ); extern void initReversibleGTR (tree *tr, int model); extern double LnGamma ( double alpha ); extern double IncompleteGamma ( double x, double alpha, double ln_gamma_alpha ); extern double PointNormal ( double prob ); extern double PointChi2 ( double prob, double v ); extern void makeGammaCats (double alpha, double *gammaRates, int K, boolean useMedian); extern void initModel ( tree *tr); extern void doAllInOne ( tree *tr, analdef *adef ); extern void classifyML(tree *tr, analdef *adef); extern void resetBranches ( tree *tr ); extern void modOpt ( tree *tr, double likelihoodEpsilon, analdef *adef, int treeIteration); extern void computeBOOTRAPID (tree *tr, analdef *adef, long *radiusSeed); extern void optimizeRAPID ( tree *tr, analdef *adef ); extern void thoroughOptimization ( tree *tr, analdef *adef, topolRELL_LIST *rl, int index ); extern int treeOptimizeThorough ( tree *tr, int mintrav, int maxtrav); extern void computeQuartets(tree *tr, analdef *adef); extern void makeRandomTree ( tree *tr); extern void nodeRectifier ( tree *tr ); extern void makeParsimonyTreeFast(tree *tr); extern void allocateParsimonyDataStructures(tree *tr); extern void freeParsimonyDataStructures(tree *tr); extern void parsimonySPR(nodeptr p, tree *tr); extern FILE *myfopen(const char *path, const char *mode); extern boolean initrav ( tree *tr, nodeptr p ); extern void initravPartition ( tree *tr, nodeptr p, int model ); extern boolean update ( tree *tr, nodeptr p ); extern boolean smooth ( tree *tr, nodeptr p ); extern boolean smoothTree ( tree *tr, int maxtimes ); extern boolean localSmooth ( tree *tr, nodeptr p, int maxtimes ); extern boolean localSmoothMulti(tree *tr, nodeptr p, int maxtimes, int model); extern void initInfoList ( int n ); extern void freeInfoList ( void ); extern void insertInfoList ( nodeptr node, double likelihood ); extern boolean smoothRegion ( tree *tr, nodeptr p, int region ); extern boolean regionalSmooth ( tree *tr, nodeptr p, int maxtimes, int region ); extern nodeptr removeNodeBIG ( tree *tr, nodeptr p, int numBranches); extern nodeptr removeNodeRestoreBIG ( tree *tr, nodeptr p ); extern boolean insertBIG ( tree *tr, nodeptr p, nodeptr q, int numBranches); extern boolean insertRestoreBIG ( tree *tr, nodeptr p, nodeptr q ); extern boolean testInsertBIG ( tree *tr, nodeptr p, nodeptr q ); extern void addTraverseBIG ( tree *tr, nodeptr p, nodeptr q, int mintrav, int maxtrav ); extern int rearrangeBIG ( tree *tr, nodeptr p, int mintrav, int maxtrav ); extern void traversalOrder ( nodeptr p, int *count, nodeptr *nodeArray ); extern double treeOptimizeRapid ( tree *tr, int mintrav, int maxtrav, analdef *adef, bestlist *bt, bestlist *bestML); extern boolean testInsertRestoreBIG ( tree *tr, nodeptr p, nodeptr q ); extern void restoreTreeFast ( tree *tr ); extern int determineRearrangementSetting ( tree *tr, analdef *adef, bestlist *bestT, bestlist *bt, bestlist *bestML); extern void computeBIGRAPID ( tree *tr, analdef *adef, boolean estimateModel); extern boolean treeEvaluate ( tree *tr, double smoothFactor ); extern boolean treeEvaluatePartition ( tree *tr, double smoothFactor, int model ); extern void meshTreeSearch(tree *tr, analdef *adef, int thorough); extern void initTL ( topolRELL_LIST *rl, tree *tr, int n ); extern void freeTL ( topolRELL_LIST *rl); extern void restoreTL ( topolRELL_LIST *rl, tree *tr, int n ); extern void resetTL ( topolRELL_LIST *rl ); extern void saveTL ( topolRELL_LIST *rl, tree *tr, int index ); extern int saveBestTree (bestlist *bt, tree *tr, boolean keepIdenticalTrees); extern int recallBestTree (bestlist *bt, int rank, tree *tr); extern int initBestTree ( bestlist *bt, int newkeep, int numsp ); extern void resetBestTree ( bestlist *bt ); extern boolean freeBestTree ( bestlist *bt ); extern char *Tree2String ( char *treestr, tree *tr, nodeptr p, boolean printBranchLengths, boolean printNames, boolean printLikelihood, boolean rellTree, boolean finalPrint, int perGene, boolean branchLabelSupport, boolean printSHSupport); extern void printTreePerGene(tree *tr, analdef *adef, char *fileName, char *permission); extern int treeReadLen (FILE *fp, tree *tr, boolean readBranches, boolean readNodeLabels, boolean topologyOnly); extern void treeReadTopologyString(char *treeString, tree *tr); extern boolean treeReadLenMULT ( FILE *fp, tree *tr, int *partCount); extern void getStartingTree ( tree *tr); extern void computeBootStopOnly(tree *tr, char *bootStrapFileName, analdef *adef); extern boolean bootStop(tree *tr, hashtable *h, int numberOfTrees, double *pearsonAverage, unsigned int **bitVectors, int treeVectorLength, unsigned int vectorLength); extern void computeConsensusOnly(tree *tr, char* treeSetFileName, analdef *adef); extern double evaluatePartialGeneric (tree *, int i, double ki, int _model); extern void evaluateGeneric (tree *tr, nodeptr p, boolean fullTraversal); extern void newviewGeneric (tree *tr, nodeptr p, boolean masked); extern void newviewGenericMulti (tree *tr, nodeptr p, int model); extern void makenewzGeneric(tree *tr, nodeptr p, nodeptr q, double *z0, int maxiter, double *result, boolean mask); extern void makenewzGenericDistance(tree *tr, int maxiter, double *z0, double *result, int taxon1, int taxon2); extern double evaluatePartitionGeneric (tree *tr, nodeptr p, int model); extern void newviewPartitionGeneric (tree *tr, nodeptr p, int model); extern double evaluateGenericVector (tree *tr, nodeptr p); extern void categorizeGeneric (tree *tr, nodeptr p); extern double makenewzPartitionGeneric(tree *tr, nodeptr p, nodeptr q, double z0, int maxiter, int model); extern boolean isTip(int number, int maxTips); extern void computeTraversalInfo(nodeptr p, traversalInfo *ti, int *counter, int maxTips, int numBranches, boolean partialTraversal); extern void newviewIterative(tree *tr, int startIndex); extern void evaluateIterative(tree *); extern void *malloc_aligned( size_t size); extern void storeExecuteMaskInTraversalDescriptor(tree *tr); extern void storeValuesInTraversalDescriptor(tree *tr, double *value); extern void makenewzIterative(tree *); extern void execCore(tree *, volatile double *dlnLdlz, volatile double *d2lnLdlz2); extern void determineFullTraversal(nodeptr p, tree *tr); /*extern void optRateCat(tree *, int i, double lower_spacing, double upper_spacing, double *lhs);*/ extern double evaluateGenericInitravPartition(tree *tr, nodeptr p, int model); extern void evaluateGenericVectorIterative(tree *, int startIndex, int endIndex); extern void categorizeIterative(tree *, int startIndex, int endIndex); extern void fixModelIndices(tree *tr, int endsite, boolean fixRates); extern void calculateModelOffsets(tree *tr); extern void gammaToCat(tree *tr); extern void catToGamma(tree *tr, analdef *adef); extern nodeptr findAnyTip(nodeptr p, int numsp); extern void parseProteinModel(analdef *adef); extern void computeNextReplicate(tree *tr, long *seed, int *originalRateCategories, int *originalInvariant, boolean isRapid, boolean fixRates); /*extern void computeNextReplicate(tree *tr, analdef *adef, int *originalRateCategories, int *originalInvariant);*/ extern void putWAG(double *ext_initialRates); extern void reductionCleanup(tree *tr, int *originalRateCategories, int *originalInvariant); extern void parseSecondaryStructure(tree *tr, analdef *adef, int sites); extern void printPartitions(tree *tr); extern void compareBips(tree *tr, char *bootStrapFileName, analdef *adef); extern void computeRF(tree *tr, char *bootStrapFileName, analdef *adef); extern unsigned int **initBitVector(int mxtips, unsigned int *vectorLength); extern hashtable *copyHashTable(hashtable *src, unsigned int vectorLength); extern hashtable *initHashTable(unsigned int n); extern void cleanupHashTable(hashtable *h, int state); extern double convergenceCriterion(hashtable *h, int mxtips); extern void freeBitVectors(unsigned int **v, int n); extern void freeHashTable(hashtable *h); extern stringHashtable *initStringHashTable(hashNumberType n); extern void addword(char *s, stringHashtable *h, int nodeNumber); extern void printBothOpen(const char* format, ... ); extern void initRateMatrix(tree *tr); extern void bitVectorInitravSpecial(unsigned int **bitVectors, nodeptr p, int numsp, unsigned int vectorLength, hashtable *h, int treeNumber, int function, branchInfo *bInf, int *countBranches, int treeVectorLength, boolean traverseOnly, boolean computeWRF); extern int getIncrement(tree *tr, int model); extern void writeBinaryModel(tree *tr); extern void readBinaryModel(tree *tr); extern void treeEvaluateRandom (tree *tr, double smoothFactor); extern void treeEvaluateProgressive(tree *tr); extern void testGapped(tree *tr); extern boolean issubset(unsigned int* bipA, unsigned int* bipB, unsigned int vectorLen); extern boolean compatible(entry* e1, entry* e2, unsigned int bvlen); extern int *permutationSH(tree *tr, int nBootstrap, long _randomSeed); extern void checkPerSiteRates(const tree * const tr ); extern void restart(tree *tr, analdef *adef); extern void writeCheckpoint(tree *tr, analdef *adef); extern boolean isGap(unsigned int *x, int pos); extern boolean noGap(unsigned int *x, int pos); extern void scaleLG4X_EIGN(tree *tr, int model); extern void myBinFwrite(void *ptr, size_t size, size_t nmemb, FILE *byteFile); extern void myBinFread(void *ptr, size_t size, size_t nmemb, FILE *byteFile); #ifdef __AVX extern void newviewGTRGAMMAPROT_AVX_LG4(int tipCase, double *x1, double *x2, double *x3, double *extEV[4], double *tipVector[4], int *ex3, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling); extern void newviewGTRCAT_AVX(int tipCase, double *EV, int *cptr, double *x1_start, double *x2_start, double *x3_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement); extern void newviewGTRCATPROT_AVX(int tipCase, double *extEV, int *cptr, double *x1, double *x2, double *x3, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement); extern void newviewGTRGAMMA_AVX(int tipCase, double *x1_start, double *x2_start, double *x3_start, double *EV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, const int n, double *left, double *right, int *wgt, int *scalerIncrement ); extern void newviewGTRGAMMAPROT_AVX(int tipCase, double *x1, double *x2, double *x3, double *extEV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement); /* memory saving functions */ void newviewGTRCAT_AVX_GAPPED_SAVE(int tipCase, double *EV, int *cptr, double *x1_start, double *x2_start, double *x3_start, double *tipVector, int *ex3, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn, const int maxCats); void newviewGTRCATPROT_AVX_GAPPED_SAVE(int tipCase, double *extEV, int *cptr, double *x1, double *x2, double *x3, double *tipVector, int *ex3, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn, const int maxCats); void newviewGTRGAMMA_AVX_GAPPED_SAVE(int tipCase, double *x1_start, double *x2_start, double *x3_start, double *extEV, double *tipVector, int *ex3, unsigned char *tipX1, unsigned char *tipX2, const int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn ); void newviewGTRGAMMAPROT_AVX_GAPPED_SAVE(int tipCase, double *x1_start, double *x2_start, double *x3_start, double *extEV, double *tipVector, int *ex3, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn); #endif /* from communication.c */ void calculateLengthAndDisplPerProcess(tree *tr, int **length_result, int **disp_result); void scatterDistrbutedArray(tree *tr, void *src, void *destination, MPI_Datatype type, int *countPerProc, int *displPerProc); void gatherDistributedArray(tree *tr, void **destination, void *src, MPI_Datatype type, int* countPerProc, int *displPerProc); #endif # ExaML-3.0.21/examl/bipartitionList.c000066400000000000000000000301711330315463200171770ustar00rootroot00000000000000/* RAxML-HPC, a program for sequential and parallel estimation of phylogenetic trees * Copyright March 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * stamatak@ics.forth.gr * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis: "An Efficient Program for phylogenetic Inference Using Simulated Annealing". * Proceedings of IPDPS2005, Denver, Colorado, April 2005. * * AND * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifndef WIN32 #include #include #include #include #endif #include #include #include #include #include #include #include #include #include "axml.h" extern const unsigned int mask32[32]; extern int processID; static void getxnodeBips (nodeptr p) { nodeptr s; if ((s = p->next)->xBips || (s = s->next)->xBips) { p->xBips = s->xBips; s->xBips = 0; } assert(p->xBips); } entry *initEntry(void) { entry *e = (entry*)malloc(sizeof(entry)); e->bitVector = (unsigned int*)NULL; e->treeVector = (unsigned int*)NULL; e->supportVector = (int*)NULL; e->bipNumber = 0; e->bipNumber2 = 0; e->supportFromTreeset[0] = 0; e->supportFromTreeset[1] = 0; e->next = (entry*)NULL; return e; } hashtable *initHashTable(hashNumberType n) { /* init with primes static const hashNumberType initTable[] = {53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; */ /* init with powers of two */ static const hashNumberType initTable[] = {64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648U}; hashtable *h = (hashtable*)malloc(sizeof(hashtable)); hashNumberType tableSize, i, primeTableLength = sizeof(initTable)/sizeof(initTable[0]), maxSize = (hashNumberType)-1; assert(n <= maxSize); i = 0; while(initTable[i] < n && i < primeTableLength) i++; assert(i < primeTableLength); tableSize = initTable[i]; h->table = (entry**)calloc(tableSize, sizeof(entry*)); h->tableSize = tableSize; h->entryCount = 0; return h; } void freeHashTable(hashtable *h) { hashNumberType i, entryCount = 0; for(i = 0; i < h->tableSize; i++) { if(h->table[i] != NULL) { entry *e = h->table[i]; entry *previous; do { previous = e; e = e->next; if(previous->bitVector) free(previous->bitVector); if(previous->treeVector) free(previous->treeVector); if(previous->supportVector) free(previous->supportVector); free(previous); entryCount++; } while(e != NULL); } } assert(entryCount == h->entryCount); free(h->table); } void cleanupHashTable(hashtable *h, int state) { hashNumberType k, entryCount = 0, removeCount = 0; assert(state == 1 || state == 0); for(k = 0, entryCount = 0; k < h->tableSize; k++) { if(h->table[k] != NULL) { entry *e = h->table[k]; entry *start = (entry*)NULL; entry *lastValid = (entry*)NULL; do { if(state == 0) { e->treeVector[0] = e->treeVector[0] & 2; assert(!(e->treeVector[0] & 1)); } else { e->treeVector[0] = e->treeVector[0] & 1; assert(!(e->treeVector[0] & 2)); } if(e->treeVector[0] != 0) { if(!start) start = e; lastValid = e; e = e->next; } else { entry *remove = e; e = e->next; removeCount++; if(lastValid) lastValid->next = remove->next; if(remove->bitVector) free(remove->bitVector); if(remove->treeVector) free(remove->treeVector); if(remove->supportVector) free(remove->supportVector); free(remove); } entryCount++; } while(e != NULL); if(!start) { assert(!lastValid); h->table[k] = NULL; } else { h->table[k] = start; } } } assert(entryCount == h->entryCount); h->entryCount -= removeCount; } unsigned int **initBitVector(int mxtips, unsigned int *vectorLength) { unsigned int **bitVectors = (unsigned int **)malloc(sizeof(unsigned int*) * 2 * mxtips); int i; if(mxtips % MASK_LENGTH == 0) *vectorLength = mxtips / MASK_LENGTH; else *vectorLength = 1 + (mxtips / MASK_LENGTH); for(i = 1; i <= mxtips; i++) { bitVectors[i] = (unsigned int *)calloc(*vectorLength, sizeof(unsigned int)); assert(bitVectors[i]); bitVectors[i][(i - 1) / MASK_LENGTH] |= mask32[(i - 1) % MASK_LENGTH]; } for(i = mxtips + 1; i < 2 * mxtips; i++) { bitVectors[i] = (unsigned int *)malloc(sizeof(unsigned int) * *vectorLength); assert(bitVectors[i]); } return bitVectors; } void freeBitVectors(unsigned int **v, int n) { int i; for(i = 1; i < n; i++) free(v[i]); } static void newviewBipartitions(unsigned int **bitVectors, nodeptr p, int numsp, unsigned int vectorLength) { if(isTip(p->number, numsp)) return; { nodeptr q = p->next->back, r = p->next->next->back; unsigned int *vector = bitVectors[p->number], *left = bitVectors[q->number], *right = bitVectors[r->number]; unsigned int i; assert(processID == 0); while(!p->xBips) { if(!p->xBips) getxnodeBips(p); } p->hash = q->hash ^ r->hash; if(isTip(q->number, numsp) && isTip(r->number, numsp)) { for(i = 0; i < vectorLength; i++) vector[i] = left[i] | right[i]; } else { if(isTip(q->number, numsp) || isTip(r->number, numsp)) { if(isTip(r->number, numsp)) { nodeptr tmp = r; r = q; q = tmp; } while(!r->xBips) { if(!r->xBips) newviewBipartitions(bitVectors, r, numsp, vectorLength); } for(i = 0; i < vectorLength; i++) vector[i] = left[i] | right[i]; } else { while((!r->xBips) || (!q->xBips)) { if(!q->xBips) newviewBipartitions(bitVectors, q, numsp, vectorLength); if(!r->xBips) newviewBipartitions(bitVectors, r, numsp, vectorLength); } for(i = 0; i < vectorLength; i++) vector[i] = left[i] | right[i]; } } } } static void insertHashRF(unsigned int *bitVector, hashtable *h, unsigned int vectorLength, int treeNumber, int treeVectorLength, hashNumberType position, int support, boolean computeWRF) { if(h->table[position] != NULL) { entry *e = h->table[position]; do { unsigned int i; for(i = 0; i < vectorLength; i++) if(bitVector[i] != e->bitVector[i]) break; if(i == vectorLength) { e->treeVector[treeNumber / MASK_LENGTH] |= mask32[treeNumber % MASK_LENGTH]; if(computeWRF) { e->supportVector[treeNumber] = support; assert(0 <= treeNumber && treeNumber < treeVectorLength * MASK_LENGTH); } return; } e = e->next; } while(e != (entry*)NULL); e = initEntry(); /*e->bitVector = (unsigned int*)calloc(vectorLength, sizeof(unsigned int));*/ e->bitVector = (unsigned int*)malloc_aligned(vectorLength * sizeof(unsigned int)); memset(e->bitVector, 0, vectorLength * sizeof(unsigned int)); e->treeVector = (unsigned int*)calloc(treeVectorLength, sizeof(unsigned int)); if(computeWRF) e->supportVector = (int*)calloc(treeVectorLength * MASK_LENGTH, sizeof(int)); e->treeVector[treeNumber / MASK_LENGTH] |= mask32[treeNumber % MASK_LENGTH]; if(computeWRF) { e->supportVector[treeNumber] = support; assert(0 <= treeNumber && treeNumber < treeVectorLength * MASK_LENGTH); } memcpy(e->bitVector, bitVector, sizeof(unsigned int) * vectorLength); e->next = h->table[position]; h->table[position] = e; } else { entry *e = initEntry(); /*e->bitVector = (unsigned int*)calloc(vectorLength, sizeof(unsigned int)); */ e->bitVector = (unsigned int*)malloc_aligned(vectorLength * sizeof(unsigned int)); memset(e->bitVector, 0, vectorLength * sizeof(unsigned int)); e->treeVector = (unsigned int*)calloc(treeVectorLength, sizeof(unsigned int)); if(computeWRF) e->supportVector = (int*)calloc(treeVectorLength * MASK_LENGTH, sizeof(int)); e->treeVector[treeNumber / MASK_LENGTH] |= mask32[treeNumber % MASK_LENGTH]; if(computeWRF) { e->supportVector[treeNumber] = support; assert(0 <= treeNumber && treeNumber < treeVectorLength * MASK_LENGTH); } memcpy(e->bitVector, bitVector, sizeof(unsigned int) * vectorLength); h->table[position] = e; } h->entryCount = h->entryCount + 1; } void bitVectorInitravSpecial(unsigned int **bitVectors, nodeptr p, int numsp, unsigned int vectorLength, hashtable *h, int treeNumber, int function, branchInfo *bInf, int *countBranches, int treeVectorLength, boolean traverseOnly, boolean computeWRF) { if(isTip(p->number, numsp)) return; else { nodeptr q = p->next; do { bitVectorInitravSpecial(bitVectors, q->back, numsp, vectorLength, h, treeNumber, function, bInf, countBranches, treeVectorLength, traverseOnly, computeWRF); q = q->next; } while(q != p); newviewBipartitions(bitVectors, p, numsp, vectorLength); assert(p->xBips); assert(!traverseOnly); if(!(isTip(p->back->number, numsp))) { unsigned int *toInsert = bitVectors[p->number]; hashNumberType position = p->hash % h->tableSize; assert(!(toInsert[0] & 1)); assert(!computeWRF); switch(function) { case BIPARTITIONS_RF: insertHashRF(toInsert, h, vectorLength, treeNumber, treeVectorLength, position, 0, computeWRF); *countBranches = *countBranches + 1; break; default: assert(0); } } } } double convergenceCriterion(hashtable *h, int mxtips) { int rf = 0; unsigned int collisions = 0, k = 0, entryCount = 0; double rrf; for(k = 0, entryCount = 0; k < h->tableSize; k++) { if(h->table[k] != NULL) { entry *e = h->table[k]; unsigned int slotCollisions = 0; do { unsigned int *vector = e->treeVector; if(((vector[0] & 1) > 0) + ((vector[0] & 2) > 0) == 1) rf++; entryCount++; slotCollisions++; e = e->next; } while(e != NULL); collisions += (slotCollisions - 1); } } assert(entryCount == h->entryCount); rrf = (double)rf/((double)(2 * (mxtips - 3))); #ifdef _DEBUG_CHECKPOINTING printf("Collisions: %u\n", collisions); #endif return rrf; } ExaML-3.0.21/examl/byteFile.c000066400000000000000000000275741330315463200155770ustar00rootroot00000000000000#include #if defined(__APPLE__) #include #else #include #endif #include "byteFile.h" #include #ifdef __MIC_NATIVE #include "mic_native.h" #endif #define READ_VAR(file,var) assert( fread(&var, sizeof(var),1, file ) == 1 ) #define READ_ARRAY(file, arrPtr, numElem, size) assert( fread(arrPtr, size, numElem, file) == (unsigned int) numElem) extern int processID; /** seekPos finds the position in the byte file where a certain type of information is stored. See byteFile.h for possible values of "pos" . Notice, that this is a "fall-through" switch statement: if -- for instance -- we want to get to the position of the taxa, we have to skip everything that comes prior to the taxa in the file (but naturally not the taxa themselves). */ static void seekPos(ByteFile *bf, int pos) { exa_off_t toSkip = 0; int i; switch(pos) { case ALN_ALIGNMENT: /* skips partitions */ { assert(bf->hasRead & ALN_PARTITIONS); pInfo p ; toSkip += bf->numPartitions * ( sizeof(p.states) + sizeof(p.maxTipStates) + sizeof(p.lower) + sizeof(p.upper) + sizeof(p.width) + sizeof(p.dataType) + sizeof(p.protModels) + sizeof(p.protFreqs) + sizeof(p.nonGTR) + sizeof(p.optimizeBaseFrequencies)); /* skip the names and their lengths */ for( i = 0 ; i < bf->numPartitions; ++i) { pInfo *p = bf->partitions[i]; toSkip += (strlen(p->partitionName)+1 ) * sizeof(char) + sizeof(int); toSkip += sizeof(double) * p->states; /* also skip frequncies */ } } case ALN_PARTITIONS: /* skips taxa */ { assert(bf->hasRead & ALN_TAXA); for(i = 0; i < bf->numTax; ++i) toSkip += (strlen(bf->taxaNames[i]) + 1) * sizeof(char) + sizeof(int); } case ALN_TAXA: /* skips weights */ { assert(bf->hasRead & ALN_HEAD); toSkip += bf->numPattern * sizeof(int); } case ALN_WEIGHTS: /* skips header */ { toSkip += sizeof(bf->numTax) + sizeof(bf->numPattern) + sizeof(bf->numPartitions) + sizeof(bf->gappyness); } case ALN_HEAD : toSkip += (3 * sizeof(int)); /* skips the initial int that tells us how many bytes a size_t has as well as the integer for the version number and the magic integer number */ break; default : assert(0); } exa_fseek(bf->fh, toSkip, SEEK_SET); } /** initializes ByteFile **bf */ void initializeByteFile(ByteFile **bf, char *name) { *bf = (ByteFile *)calloc(1,sizeof(ByteFile)); ByteFile *result = *bf; result->fh = myfopen(name, "rb"); int sizeOfSizeT = 0, version = 0, magicNumber = 0; READ_VAR(result->fh, sizeOfSizeT); if(sizeOfSizeT != sizeof(size_t)) { if(processID == 0) { printf("\nError: the address data type has a size of %d bits on the current system while on the system on which you created the binary alignment file using the parser the address size is %d bits!\n", 8 * (int)sizeof(size_t), 8 * sizeOfSizeT); printf("Usually this indicates that the parser was executed on a 32-bit system while you are trying to run ExaML on a 64-bit system.\n"); printf("Please parse the binary alignment file on the same hardware on which you intend to run ExaML.\n\n\n"); } MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); exit(-1); } //check that version numbers of parser and ExaML match READ_VAR(result->fh, version); if(version != (int)programVersionInt) { if(processID == 0) { printf("\nError: Version number %d of ExaML parser and version number %d of ExaML don't match.\n", version, (int)programVersionInt); printf("You are either using an outdated version of the parser or of ExaML.\n"); printf("Hasta siempre comandante.\n\n\n"); } MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); exit(-1); } READ_VAR(result->fh, magicNumber); if(magicNumber != 6517718) { if(processID == 0) { printf("\nError: The magic number %d of ExaML parser and magic number %d of ExaML don't match.\n", magicNumber, 6517718); printf("Something went terribly wrong here.\n"); printf("Hasta la victoria siempre.\n\n\n"); } MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); exit(-1); } } /** a shallow cleanup of ByteFile *bf. Notice, that various data may have been copied (by pointer value) to our tree instance and therefore should not be clean up. */ void deleteByteFile(ByteFile *bf) { /* only a shallow free! pointers inside the pInfo must persist */ int i; if(bf->partitions) { for( i = 0; i < bf->numPartitions; ++i) free(bf->partitions[i]); free(bf->partitions); } if(bf->fh) fclose(bf->fh); if(bf->taxaNames ) { for(i = 0; i < bf->numTax; ++i) free(bf->taxaNames[i] ); } free(bf->taxaNames); free(bf); } /** only reads initial header information */ void readHeader(ByteFile* bf) { seekPos(bf, ALN_HEAD); READ_VAR(bf->fh, bf->numTax); READ_VAR(bf->fh, bf->numPattern); READ_VAR(bf->fh, bf->numPartitions); READ_VAR(bf->fh, bf->gappyness) ; bf->hasRead |= ALN_HEAD; } /** reads partition information from the byte file. */ void readPartitions(ByteFile *bf) { int i ; seekPos(bf, ALN_PARTITIONS); assert(bf->partitions == (pInfo **)NULL); bf->partitions = (pInfo **)calloc(bf->numPartitions, sizeof(pInfo*) ); for(i = 0; i < bf->numPartitions; ++i) { bf->partitions[i] = (pInfo*)calloc(1,sizeof(pInfo)); pInfo* p = bf->partitions[i]; p->frequencies = (double*)NULL; p->partitionName = (char *)NULL; READ_VAR(bf->fh, p->states); READ_VAR(bf->fh, p->maxTipStates); READ_VAR(bf->fh, p->lower); READ_VAR(bf->fh, p->upper); /* DONT use this value! */ READ_VAR(bf->fh, p->width); p->width = 0; READ_VAR(bf->fh, p->dataType); READ_VAR(bf->fh, p->protModels); //READ_VAR(bf->fh, p->autoProtModels); READ_VAR(bf->fh, p->protFreqs); READ_VAR(bf->fh, p->nonGTR); READ_VAR(bf->fh, p->optimizeBaseFrequencies); // READ_VAR(bf->fh, p->numberOfCategories); /* read string */ unsigned int len = 0; READ_VAR(bf->fh, len); p->partitionName = (char*)calloc(len,sizeof(char)); READ_ARRAY(bf->fh, p->partitionName, len, sizeof(char)); p->frequencies = (double*)calloc(p->states, sizeof(double)); READ_ARRAY(bf->fh, p->frequencies, p->states , sizeof(double)); } bf->hasRead |= ALN_PARTITIONS; } /** reads the taxon names from the byte file */ void readTaxa(ByteFile *bf) { int i; assert(bf->taxaNames == (char **)NULL); seekPos(bf, ALN_TAXA); bf->taxaNames = (char **)calloc(bf->numTax, sizeof(char*)); for(i = 0; i < bf->numTax; ++i) { int len = 0; READ_VAR(bf->fh, len ); bf->taxaNames[i] = (char*)calloc(len, sizeof(char)); READ_ARRAY(bf->fh, bf->taxaNames[i], len, sizeof(char)); } bf->hasRead |= ALN_TAXA; } // #define OLD_LAYOUT /** uses the information in the PartitionAssignment to only extract data relevant to this process (weights and alignment characters). */ void readMyData(ByteFile *bf, PartitionAssignment *pa, int procId) { seekPos(bf, ALN_ALIGNMENT); exa_off_t alnPos = exa_ftell(bf->fh); size_t len; int numAssign = pa->numAssignPerProc[procId]; Assignment *myAssigns = pa->assignPerProc[procId]; /* first read aln characters */ int i,j ; for(i = 0; i < numAssign; ++i ) { Assignment a = myAssigns[i]; /* printf("reading for: ") ; */ /* printAssignment(a, procId); */ pInfo *partition = bf->partitions[a.partId]; partition->width = a.width; partition->offset = a.offset; len = bf->numTax * a.width; partition->yResource = (unsigned char*)malloc_aligned( len * sizeof(unsigned char)); memset(partition->yResource,0,len * sizeof(unsigned char)); partition->yVector = (unsigned char**) calloc(bf->numTax + 1 , sizeof(unsigned char*)); for(j = 1; j <= bf->numTax; ++j) partition->yVector[j] = partition->yResource + (j-1) * a.width; #ifdef OLD_LAYOUT for(j = 1; j <= bf->numTax; ++j ) { exa_off_t pos = alnPos + ( bf->numPattern * (j-1) + partition->lower + a.offset ) * sizeof(unsigned char); assert(alnPos <= pos); exa_fseek(bf->fh, pos, SEEK_SET); READ_ARRAY(bf->fh, partition->yVector[j], a.width, sizeof(unsigned char)); } #else /* if the entire partition is assigned to this process, read it in one go. Otherwise, several seeks are necessary. */ if( a.width == (partition->upper - partition->lower ) ) { exa_off_t pos = alnPos + (partition->lower * bf->numTax) * sizeof(unsigned char); assert(alnPos <= pos); exa_fseek(bf->fh, pos, SEEK_SET); READ_ARRAY(bf->fh, partition->yResource, a.width * bf->numTax, sizeof(unsigned char)); } else { for(j = 1; j <= bf->numTax; ++j ) { exa_off_t pos = alnPos + sizeof(unsigned char) * ( (partition->lower * bf->numTax ) /* until start of partition */ + ((j-1) * (partition->upper - partition->lower) ) /* until start of sequence of taxon within partition */ + a.offset ) ; assert(alnPos <= pos); exa_fseek(bf->fh, pos, SEEK_SET); READ_ARRAY(bf->fh, partition->yVector[j], a.width, sizeof(unsigned char)); } } #endif } /* now read weights */ seekPos(bf, ALN_WEIGHTS); exa_off_t wgtPos = exa_ftell(bf->fh); assert( ! (wgtPos < 0) ); for(i = 0; i < numAssign; ++i) { Assignment a = myAssigns[i]; pInfo *partition = bf->partitions[a.partId]; #ifdef __MIC_NATIVE /* for Xeon Phi, wgt must be padded to the multiple of 8 (because of site blocking in kernels) */ const int padded_width = GET_PADDED_WIDTH(a.width); len = padded_width * sizeof(int); #else len = a.width * sizeof(int); #endif partition->wgt = (int*)malloc_aligned( len); memset(partition->wgt, 0, len); exa_off_t pos = wgtPos + (partition->lower + a.offset) * sizeof(int); assert(wgtPos <= pos ); exa_fseek(bf->fh, pos, SEEK_SET); READ_ARRAY(bf->fh, partition->wgt, a.width, sizeof(int)); } bf->hasRead |= ALN_ALIGNMENT; bf->hasRead |= ALN_WEIGHTS; } /** copies all relevant information from our byte file to the tree instance. */ void initializeTreeFromByteFile(ByteFile *bf, tree *tr) { assert( ( bf->hasRead & ALN_HEAD ) && (bf->hasRead & ALN_WEIGHTS) && (bf->hasRead & ALN_TAXA) && (bf->hasRead & ALN_PARTITIONS) && (bf->hasRead & ALN_ALIGNMENT ) ); /* some additional stuff we read */ tr->mxtips = bf->numTax; tr->originalCrunchedLength = bf->numPattern; tr->NumberOfModels = bf->numPartitions; tr->gapyness = bf->gappyness; /* deep copy of taxa */ int i ; tr->nameList = (char **)calloc((size_t)(tr->mxtips + 1), sizeof(char *) ); tr->nameList[0] = (char *)NULL; for(i = 1; i <= bf->numTax; ++i) { tr->nameList[i] = (char*)calloc(strlen(bf->taxaNames[i-1]) + 1, sizeof(char)); strcpy(tr->nameList[i], bf->taxaNames[i-1]); } /* * shallow copy of partitions * * partition contains only shallow copies of a few data arrays that * needed to be initialized at this point */ int myLength = 0; tr->partitionData = (pInfo*)calloc(tr->NumberOfModels, sizeof(pInfo)); for(i = 0; i < tr->NumberOfModels; ++i) { tr->partitionData[i] = *(bf->partitions[i]); myLength += tr->partitionData[i].width; assert( bf->partitions[i]->wgt != (int*)NULL || bf->partitions[i]->width == 0); assert( ( tr->partitionData[i].wgt != (int*)NULL) || ( tr->partitionData[i].width == 0 ) ); } } ExaML-3.0.21/examl/byteFile.h000066400000000000000000000022061330315463200155650ustar00rootroot00000000000000#ifndef _BYTE_FILE #define _BYTE_FILE #include "axml.h" #include "partitionAssignment.h" #define ALN_HEAD 1 #define ALN_WEIGHTS 2 #define ALN_TAXA 4 #define ALN_PARTITIONS 8 #define ALN_ALIGNMENT 16 typedef struct { int numTax; size_t numPattern; int numPartitions; double gappyness; pInfo **partitions; char **taxaNames; FILE *fh; char hasRead ; } ByteFile; /* constructor */ void initializeByteFile(ByteFile **bf, char *name); /* deletor */ void deleteByteFile(ByteFile *bf) ; /* reads the header of a byte file */ void readHeader(ByteFile* bf); /* reads partition information in a byte file */ void readPartitions(ByteFile *bf); /* reads the taxon names in a byte file */ void readTaxa(ByteFile *bf); /* reads weights and alignment characters in a byte file */ void readMyData(ByteFile *bf, PartitionAssignment *pa, int procId); /* initializes a tree from a byte file. @notice Since shallow copies are involved, you cannot copy the information from a byte file into multiple tree instances. */ void initializeTreeFromByteFile(ByteFile *bf, tree *tr); #endif ExaML-3.0.21/examl/communication.c000066400000000000000000000121461330315463200166660ustar00rootroot00000000000000#include #include #include #include #include "axml.h" extern int processes; extern int processID; /** computes the count and displacement for gatherv/scatterv, assuming that the new partition assignment algorithm was used */ void calculateLengthAndDisplPerProcess(tree *tr, int **length_result, int **disp_result) { int i; *length_result = (int*) calloc((size_t) processes , sizeof(int)); *disp_result = (int*) calloc((size_t) processes, sizeof(int)); int* numPerProc = *length_result; int* displPerProc= *disp_result; for(i = 0; i < tr->numAssignments; ++i) { Assign* ass = &(tr->partAssigns[i]); numPerProc[ass->procId] += ass->width; } displPerProc[0] = 0; for(i = 1; i < processes ; ++i) displPerProc[i] = displPerProc[i-1] + numPerProc[i-1]; } static size_t mapMpiTypeToSize(MPI_Datatype type) { if(type == MPI_INT) return sizeof(int); else if(type == MPI_DOUBLE) return sizeof(double); else { assert(0); return 0; } } /** scatters a distributed array (e.g., what used to be tr->rateCategory) to partition-specfic arrays (e.g., tr->partitionData[i].rateCategory). This works, because tr->partitionData[i].rateCategory is a non-owning pointer to a position in the global resource array (e.g., tr->rateCategory_basePtr). */ void scatterDistrbutedArray(tree *tr, void *src, void *destination, MPI_Datatype type, int *countPerProc, int *displPerProc) { int i; size_t typeLen = mapMpiTypeToSize(type); char *srcReordered = (char *)NULL; /* master must reorder the data */ if(processID == 0) { srcReordered = (char *)malloc(tr->originalCrunchedLength * typeLen); int *seenPerProcesses = (int *)calloc((size_t) processes, sizeof(int)); Assign *aIter = tr->partAssigns; Assign *aEnd = &(tr->partAssigns[ tr->numAssignments ] ); while(aIter != aEnd) { pInfo *partition = &(tr->partitionData[ aIter->partitionId ]) ; memcpy( srcReordered + ( (size_t) displPerProc[aIter->procId] + (size_t) seenPerProcesses[aIter->procId] ) * typeLen , ((char*) src) + (partition->lower + aIter->offset) * typeLen, aIter->width * typeLen); seenPerProcesses[aIter->procId] += aIter->width; ++aIter; } for(i = 0; i < processes; ++i) assert(seenPerProcesses[i] == countPerProc[i]) ; free(seenPerProcesses); } MPI_Scatterv(srcReordered, countPerProc, displPerProc, type, destination, countPerProc[processID], type, 0, MPI_COMM_WORLD); /* after this scatter, every process already has the data correctly ordered at its repective base pointer */ if(processID == 0) free(srcReordered); } /** gathers a distributed array (e.g., what used to be tr->rateCategory) to partition-specfic arrays (e.g., tr->partitionData[i].rateCategory). This works, because tr->partitionData[i].rateCategory is a non-owning pointer to a position in the global resource array (e.g., tr->rateCategory_basePtr). */ void gatherDistributedArray(tree *tr, void **destinationPtr, void *src, MPI_Datatype type, int* countPerProc, int *displPerProc) { /* this is the raw array that the master will obtain from his peers. Data in this arrays are ordered per process */ char *destinationUnordered = (char*)NULL; char *destination = (char*)NULL; size_t typeLen = mapMpiTypeToSize(type); if(processID == 0) { //TODO one pointer is of type void the other of type char, not really nice *destinationPtr = (void *)malloc( tr->originalCrunchedLength * typeLen); destinationUnordered = (char *)malloc( tr->originalCrunchedLength * typeLen); destination = *destinationPtr; } MPI_Gatherv(src, countPerProc[processID], type, destinationUnordered, countPerProc, displPerProc, type,0 , MPI_COMM_WORLD ); /* here the master reorders the array it has obtained. Afterwards, destinationPtr is a pointer to the array that contains the global array that can be indexed by alignment position (i.e., if we have gathered tr->partitionData[i].lhs, then *destinationPtr corresponds to what previously was tr->lhs). This strongly couples the respective distributed array to tr->partAssigns. */ if(processID == 0) { int i, *seenPerProcesses = (int*) calloc(processes, sizeof(int)); Assign *aIter = tr->partAssigns; Assign *aEnd = tr->partAssigns + tr->numAssignments; while(aIter != aEnd) { pInfo *partition = &(tr->partitionData[aIter->partitionId]); memcpy(destination + (size_t) (partition->lower + aIter->offset) * typeLen, destinationUnordered + (size_t) (displPerProc[aIter->procId] + seenPerProcesses[aIter->procId]) * typeLen , typeLen * aIter->width); seenPerProcesses[aIter->procId] += aIter->width; ++aIter ; } /* check, if everything has been reordered */ for(i = 0; i < processes; ++i) assert(seenPerProcesses[i] == countPerProc[i]); free(seenPerProcesses); free(destinationUnordered); } } ExaML-3.0.21/examl/evaluateGenericSpecial.c000066400000000000000000001564661330315463200204430ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifndef WIN32 #include #endif #include #include #include #include #include #include #include "axml.h" /* the set of functions in here computes the log likelihood at a given branch (the virtual root of a tree) */ /* includes for using SSE3 intrinsics */ #ifdef __SIM_SSE3 #include #include /*#include */ #endif #ifdef __MIC_NATIVE #include "mic_native.h" #endif /* global variables of pthreads version, reductionBuffer is the global array that is used for implementing deterministic reduction operations, that is, the total log likelihood over the partial log lieklihoods for the sites that each thread has computed NumberOfThreads is just the number of threads. Note the volatile modifier here, that guarantees that the compiler will not do weird optimizations rearraengements of the code accessing those variables, because it does not know that several concurrent threads will access those variables simulatenously */ extern const char inverseMeaningDNA[16]; extern int processID; /* a pre-computed 32-bit integer mask */ extern const unsigned int mask32[32]; /* the function below computes the P matrix from the decomposition of the Q matrix and the respective rate categories for a single partition */ static void calcDiagptable(const double z, const int states, const int numberOfCategories, const double *rptr, const double *EIGN, double *diagptable) { int i, l; double lz, *lza = (double *)malloc(sizeof(double) * states); /* transform the root branch length to the log and check if it is not too small */ if (z < zmin) lz = log(zmin); else lz = log(z); /* do some pre-computations to avoid redundant computations further below */ for(i = 0; i < states; i++) lza[i] = EIGN[i] * lz; /* loop over the number of per-site or discrete gamma rate categories */ for(i = 0; i < numberOfCategories; i++) { /* diagptable is a pre-allocated array of doubles that stores the P-Matrix the first entry is always 1.0 */ diagptable[i * states] = 1.0; /* compute the P matrix for all remaining states of the model */ for(l = 1; l < states; l++) diagptable[i * states + l] = EXP(rptr[i] * lza[l]); } free(lza); } static void calcDiagptableFlex_LG4(double z, int numberOfCategories, double *rptr, double *EIGN[4], double *diagptable, const int numStates) { int i, l; double lz; assert(numStates <= 64); if (z < zmin) lz = log(zmin); else lz = log(z); for(i = 0; i < numberOfCategories; i++) { diagptable[i * numStates + 0] = 1.0; for(l = 1; l < numStates; l++) diagptable[i * numStates + l] = EXP(rptr[i] * EIGN[i][l] * lz); } } #ifndef _OPTIMIZED_FUNCTIONS /* below a a slow generic implementation of the likelihood computation at the root under the GAMMA model */ static double evaluateGAMMA_FLEX(int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, const int n, double *diagptable, const int states) { double sum = 0.0, term, *x1, *x2; int i, j, k; /* span is the offset within the likelihood array at an inner node that gets us from the values of site i to the values of site i + 1 */ const int span = states * 4; /* we distingusih between two cases here: one node of the two nodes defining the branch at which we put the virtual root is a tip. Both nodes can not be tips because we do not allow for two-taxon trees ;-) Nota that, if a node is a tip, this will always be tipX1. This is done for code simplicity and the flipping of the nodes is done before when we compute the traversal descriptor. */ /* the left node is a tip */ if(tipX1) { /* loop over the sites of this partition */ for (i = 0; i < n; i++) { /* access pre-computed tip vector values via a lookup table */ x1 = &(tipVector[states * tipX1[i]]); /* access the other(inner) node at the other end of the branch */ x2 = &(x2_start[span * i]); /* loop over GAMMA rate categories, hard-coded as 4 in RAxML */ for(j = 0, term = 0.0; j < 4; j++) /* loop over states and multiply them with the P matrix */ for(k = 0; k < states; k++) term += x1[k] * x2[j * states + k] * diagptable[j * states + k]; /* take the log of the likelihood and multiply the per-gamma rate likelihood by 1/4. Under the GAMMA model the 4 discrete GAMMA rates all have the same probability of 0.25 */ term = LOG(0.25 * FABS(term)); sum += wptr[i] * term; } } else { for (i = 0; i < n; i++) { /* same as before, only that now we access two inner likelihood vectors x1 and x2 */ x1 = &(x1_start[span * i]); x2 = &(x2_start[span * i]); for(j = 0, term = 0.0; j < 4; j++) for(k = 0; k < states; k++) term += x1[j * states + k] * x2[j * states + k] * diagptable[j * states + k]; term = LOG(0.25 * FABS(term)); sum += wptr[i] * term; } } return sum; } /* a generic and slow implementation of the CAT model of rate heterogeneity */ static double evaluateCAT_FLEX (int *cptr, int *wptr, double *x1, double *x2, double *tipVector, unsigned char *tipX1, int n, double *diagptable_start, const int states) { double sum = 0.0, term, *diagptable, *left, *right; int i, l; /* chosing between tip vectors and non tip vectors is identical in all flavors of this function ,regardless of whether we are using CAT, GAMMA, DNA or protein data etc */ if(tipX1) { for (i = 0; i < n; i++) { /* same as in the GAMMA implementation */ left = &(tipVector[states * tipX1[i]]); right = &(x2[states * i]); /* important difference here, we do not have, as for GAMMA 4 P matrices assigned to each site, but just one. However those P-Matrices can be different for the sites. Hence we index into the precalculated P-matrices for individual sites via the category pointer cptr[i] */ diagptable = &diagptable_start[states * cptr[i]]; /* similar to gamma, with the only difference that we do not integrate (sum) over the discrete gamma rates, but simply compute the likelihood of the site and the given P-matrix */ for(l = 0, term = 0.0; l < states; l++) term += left[l] * right[l] * diagptable[l]; /* take the log */ term = LOG(FABS(term)); /* multiply the log with the pattern weight of this site. The site pattern for which we just computed the likelihood may represent several alignment columns sites that have been compressed into one site pattern if they are exactly identical AND evolve under the same model, i.e., form part of the same partition. */ sum += wptr[i] * term; } } else { for (i = 0; i < n; i++) { /* as before we now access the likelihood arrayes of two inner nodes */ left = &x1[states * i]; right = &x2[states * i]; diagptable = &diagptable_start[states * cptr[i]]; for(l = 0, term = 0.0; l < states; l++) term += left[l] * right[l] * diagptable[l]; term = LOG(FABS(term)); sum += wptr[i] * term; } } return sum; } #endif /* below are the function headers for unreadeble highly optimized versions of the above functions for DNA and protein data that also use SSE3 intrinsics and implement some memory saving tricks. The actual functions can be found at the end of this source file. All other likelihood function implementation files: newviewGenericSpacial.c makenewzSpecial.c evaluatePartialGenericSpecial.c are also structured like this To decide which set of function implementations to use you will have to undefine or define _OPTIMIZED_FUNCTIONS in the Makefile */ #ifdef _OPTIMIZED_FUNCTIONS static double evaluateGTRGAMMA_BINARY(int *ex1, int *ex2, int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, const int n, double *diagptable, const boolean fastScaling); static double evaluateGTRCAT_BINARY (int *ex1, int *ex2, int *cptr, int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, int n, double *diagptable_start, const boolean fastScaling); static double evaluateGTRGAMMAPROT_LG4(int *ex1, int *ex2, int *wptr, double *x1, double *x2, double *tipVector[4], unsigned char *tipX1, int n, double *diagptable, const boolean fastScaling, double *weights); /* GAMMA for proteins with memory saving */ static double evaluateGTRGAMMAPROT_GAPPED_SAVE (int *wptr, double *x1, double *x2, double *tipVector, unsigned char *tipX1, int n, double *diagptable, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap); /* GAMMA for proteins */ static double evaluateGTRGAMMAPROT (int *wptr, double *x1, double *x2, double *tipVector, unsigned char *tipX1, int n, double *diagptable); /* CAT for proteins */ static double evaluateGTRCATPROT (int *cptr, int *wptr, double *x1, double *x2, double *tipVector, unsigned char *tipX1, int n, double *diagptable_start); /* CAT for proteins with memory saving */ static double evaluateGTRCATPROT_SAVE (int *cptr, int *wptr, double *x1, double *x2, double *tipVector, unsigned char *tipX1, int n, double *diagptable_start, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap); /* analogous DNA fuctions */ static double evaluateGTRCAT_SAVE (int *cptr, int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, int n, double *diagptable_start, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap); static double evaluateGTRGAMMA_GAPPED_SAVE(int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, const int n, double *diagptable, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap); static double evaluateGTRGAMMA(int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, const int n, double *diagptable); static double evaluateGTRCAT (int *cptr, int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, int n, double *diagptable_start); #endif /* This is the core function for computing the log likelihood at a branch */ void evaluateIterative(tree *tr) { /* the branch lengths and node indices of the virtual root branch are always the first one that are stored in the very important traversal array data structure that describes a partial or full tree traversal */ /* get the branch length at the root */ double *pz = tr->td[0].ti[0].qz; /* get the node number of the node to the left and right of the branch that defines the virtual rooting */ int pNumber = tr->td[0].ti[0].pNumber, qNumber = tr->td[0].ti[0].qNumber; /* before we can compute the likelihood at the virtual root, we need to do a partial or full tree traversal to compute the conditional likelihoods of the vectors as specified in the traversal descriptor. Maintaining this tarversal descriptor consistent will unfortunately be the responsibility of users. This is tricky, if as planned for here, we use a rooted view (described somewhere in Felsenstein's book) for the conditional vectors with respect to the tree */ /* iterate over all valid entries in the traversal descriptor */ newviewIterative(tr, 1); int m; #ifdef _USE_OMP #pragma omp parallel for #endif for(m = 0; m < tr->NumberOfModels; m++) { /* check if this partition has to be processed now - otherwise no need to compute P matrix */ if(!tr->td[0].executeModel[m] || tr->partitionData[m].width == 0) continue; int categories, states = tr->partitionData[m].states; double z, *rateCategories, *diagptable = tr->partitionData[m].left; /* if we are using a per-partition branch length estimate, the branch has an index, otherwise, for a joint branch length estimate over all partitions we just use the branch length value with index 0 */ if(tr->numBranches > 1) z = pz[m]; else z = pz[0]; /* figure out if we are using the CAT or GAMMA model of rate heterogeneity and set pointers to the rate heterogeneity rate arrays and also set the number of distinct rate categories appropriately. Under GAMMA this is constant and hard-coded as 4, weheras under CAT the number of site-wise rate categories can vary in the course of computations up to a user defined maximum value of site categories (default: 25) */ if(tr->rateHetModel == CAT) { rateCategories = tr->partitionData[m].perSiteRates; categories = tr->partitionData[m].numberOfCategories; } else { rateCategories = tr->partitionData[m].gammaRates; categories = 4; } if(tr->partitionData[m].protModels == LG4M || tr->partitionData[m].protModels == LG4X) calcDiagptableFlex_LG4(z, 4, tr->partitionData[m].gammaRates, tr->partitionData[m].EIGN_LG4, diagptable, 20); else calcDiagptable(z, states, categories, rateCategories, tr->partitionData[m].EIGN, diagptable); } /* after the above call we are sure that we have properly and consistently computed the conditionals to the right and left of the virtual root and we can now invoke the the log likelihood computation */ /* we need to loop over all partitions. Note that we may have a mix of DNA, protein binary data etc partitions */ #ifdef _USE_OMP #pragma omp parallel #endif { int m, model, maxModel; #ifdef _USE_OMP maxModel = tr->maxModelsPerThread; #else maxModel = tr->NumberOfModels; #endif for(m = 0; m < maxModel; m++) { /* just defaults -> if partion wasn't assigned to this thread, it will be ignored later on */ size_t width = 0, offset = 0; double *diagptable = (double*)NULL, *perPartitionLH = (double*)NULL; unsigned int *globalScaler = (unsigned int*)NULL; #ifdef _USE_OMP int tid = omp_get_thread_num(); /* check if this thread should process this partition */ Assign* pAss = tr->threadPartAssigns[tid * tr->maxModelsPerThread + m]; if(pAss) { model = pAss->partitionId; width = pAss->width; offset = pAss->offset; assert(model < tr->NumberOfModels); diagptable = tr->partitionData[model].left; globalScaler = tr->partitionData[model].threadGlobalScaler[tid]; perPartitionLH = &tr->partitionData[model].reductionBuffer[tid]; } else break; #else model = m; /* number of sites in this partition */ width = (size_t)tr->partitionData[model].width; offset = 0; /* set this pointer to the memory area where space has been reserved a priori for storing the P matrix at the root */ diagptable = tr->partitionData[model].left; globalScaler = tr->partitionData[model].globalScaler; perPartitionLH = &tr->perPartitionLH[model]; #endif /* Important part of the tarversal descriptor: figure out if we need to recalculate the likelihood of this partition: The reasons why this is important in terms of performance are given in this paper here which you should actually read: A. Stamatakis, M. Ott: "Load Balance in the Phylogenetic Likelihood Kernel". Proceedings of ICPP 2009, accepted for publication, Vienna, Austria, September 2009 The width > 0 check is for checking if under the cyclic data distribution of per-partition sites to threads this thread does indeed have a site of the current partition. */ if(tr->td[0].executeModel[model] && width > 0) { int rateHet = (int)discreteRateCategories(tr->rateHetModel), /* get the number of states in the partition, e.g.: 4 = DNA, 20 = Protein */ states = tr->partitionData[model].states, /* span for single alignment site (in doubles!) */ span = rateHet * states; size_t /* offset for current thread's data in global xVector (in doubles!) */ x_offset = offset * (size_t)span; int /* integer weight vector with pattern compression weights */ *wgt = tr->partitionData[model].wgt + offset, /* integer rate category vector (for each pattern, _number_ of PSR category assigned to it, NOT actual rate!) */ *rateCategory = tr->partitionData[model].rateCategory + offset; double partitionLikelihood = 0.0, *weights = tr->partitionData[model].weights, *x1_start = (double*)NULL, *x2_start = (double*)NULL, *x1_gapColumn = (double*)NULL, *x2_gapColumn = (double*)NULL; unsigned int *x1_gap = (unsigned int*)NULL, *x2_gap = (unsigned int*)NULL; unsigned char *tip = (unsigned char*)NULL; /* figure out if we need to address tip vectors (a char array that indexes into a precomputed tip likelihood value array or if we need to address inner vectors */ /* either node p or node q is a tip */ if(isTip(pNumber, tr->mxtips) || isTip(qNumber, tr->mxtips)) { /* q is a tip */ if(isTip(qNumber, tr->mxtips)) { /* get the start address of the inner likelihood vector x2 for partition model, note that inner nodes are enumerated/indexed starting at 0 to save allocating some space for additional pointers */ x2_start = tr->partitionData[model].xVector[pNumber - tr->mxtips -1] + x_offset; /* get the corresponding tip vector */ tip = tr->partitionData[model].yVector[qNumber] + offset; /* memory saving stuff, let's deal with this later or ask Fernando ;-) */ if(tr->saveMemory) { x2_gap = &(tr->partitionData[model].gapVector[pNumber * tr->partitionData[model].gapVectorLength]); x2_gapColumn = &(tr->partitionData[model].gapColumn[(pNumber - tr->mxtips - 1) * states * rateHet]); } } else { /* p is a tip, same as above */ x2_start = tr->partitionData[model].xVector[qNumber - tr->mxtips - 1] + x_offset; tip = tr->partitionData[model].yVector[pNumber] + offset; if(tr->saveMemory) { x2_gap = &(tr->partitionData[model].gapVector[qNumber * tr->partitionData[model].gapVectorLength]); x2_gapColumn = &(tr->partitionData[model].gapColumn[(qNumber - tr->mxtips - 1) * states * rateHet]); } } } else { /* neither p nor q are tips, hence we need to get the addresses of two inner vectors */ x1_start = tr->partitionData[model].xVector[pNumber - tr->mxtips - 1] + x_offset; x2_start = tr->partitionData[model].xVector[qNumber - tr->mxtips - 1] + x_offset; /* memory saving option */ if(tr->saveMemory) { x1_gap = &(tr->partitionData[model].gapVector[pNumber * tr->partitionData[model].gapVectorLength]); x2_gap = &(tr->partitionData[model].gapVector[qNumber * tr->partitionData[model].gapVectorLength]); x1_gapColumn = &tr->partitionData[model].gapColumn[(pNumber - tr->mxtips - 1) * states * rateHet]; x2_gapColumn = &tr->partitionData[model].gapColumn[(qNumber - tr->mxtips - 1) * states * rateHet]; } } #ifndef _OPTIMIZED_FUNCTIONS /* generic slow functions, memory saving option is not implemented for these */ assert(!tr->saveMemory); /* decide wheter CAT or GAMMA is used and compute log like */ if(tr->rateHetModel == CAT) partitionLikelihood = evaluateCAT_FLEX(tr->partitionData[model].rateCategory, wgt, x1_start, x2_start, tr->partitionData[model].tipVector, tip, width, diagptable, states); else partitionLikelihood = evaluateGAMMA_FLEX(wgt, x1_start, x2_start, tr->partitionData[model].tipVector, tip, width, diagptable, states); #else /* for the optimized functions we have a dedicated, optimized function implementation for each rate heterogeneity and data type combination, we switch over the number of states and the rate heterogeneity model */ switch(states) { case 2: #ifdef __MIC_NATIVE assert(0 && "Binary data model is not implemented on Intel MIC"); #else assert(!tr->saveMemory); if(tr->rateHetModel == CAT) partitionLikelihood = evaluateGTRCAT_BINARY((int *)NULL, (int *)NULL, rateCategory, wgt, x1_start, x2_start, tr->partitionData[model].tipVector, tip, width, diagptable, TRUE); else partitionLikelihood = evaluateGTRGAMMA_BINARY((int *)NULL, (int *)NULL, wgt, x1_start, x2_start, tr->partitionData[model].tipVector, tip, width, diagptable, TRUE); #endif break; case 4: /* DNA */ { if(tr->rateHetModel == CAT) { if(tr->saveMemory) #ifdef __MIC_NATIVE assert(0 && "Neither CAT model of rate heterogeneity nor memory saving are implemented on Intel MIC"); #else partitionLikelihood = evaluateGTRCAT_SAVE(rateCategory, wgt, x1_start, x2_start, tr->partitionData[model].tipVector, tip, width, diagptable, x1_gapColumn, x2_gapColumn, x1_gap, x2_gap); #endif else #ifdef __MIC_NATIVE assert(0 && "CAT model of rate heterogeneity is not implemented on Intel MIC"); #else partitionLikelihood = evaluateGTRCAT(rateCategory, wgt, x1_start, x2_start, tr->partitionData[model].tipVector, tip, width, diagptable); #endif } else { if(tr->saveMemory) #ifdef __MIC_NATIVE assert(0 && "Memory saving is not implemented on Intel MIC"); #else partitionLikelihood = evaluateGTRGAMMA_GAPPED_SAVE(wgt, x1_start, x2_start, tr->partitionData[model].tipVector, tip, width, diagptable, x1_gapColumn, x2_gapColumn, x1_gap, x2_gap); #endif else #ifdef __MIC_NATIVE partitionLikelihood = evaluateGAMMA_MIC(wgt, x1_start, x2_start, tr->partitionData[model].mic_tipVector, tip, width, diagptable); #else partitionLikelihood = evaluateGTRGAMMA(wgt, x1_start, x2_start, tr->partitionData[model].tipVector, tip, width, diagptable); #endif } } break; case 20: /* proteins */ { if(tr->rateHetModel == CAT) { if(tr->saveMemory) #ifdef __MIC_NATIVE assert(0 && "Neither CAT model of rate heterogeneity nor memory saving are implemented on Intel MIC"); #else partitionLikelihood = evaluateGTRCATPROT_SAVE(rateCategory, wgt, x1_start, x2_start, tr->partitionData[model].tipVector, tip, width, diagptable, x1_gapColumn, x2_gapColumn, x1_gap, x2_gap); #endif else #ifdef __MIC_NATIVE assert(0 && "CAT model of rate heterogeneity is not implemented on Intel MIC"); #else partitionLikelihood = evaluateGTRCATPROT(rateCategory, wgt, x1_start, x2_start, tr->partitionData[model].tipVector, tip, width, diagptable); #endif } else { if(tr->saveMemory) #ifdef __MIC_NATIVE assert(0 && "Memory saving is not implemented on Intel MIC"); #else partitionLikelihood = evaluateGTRGAMMAPROT_GAPPED_SAVE(wgt, x1_start, x2_start, tr->partitionData[model].tipVector, tip, width, diagptable, x1_gapColumn, x2_gapColumn, x1_gap, x2_gap); #endif else { if(tr->partitionData[model].protModels == LG4M || tr->partitionData[model].protModels == LG4X) #ifdef __MIC_NATIVE partitionLikelihood = evaluateGAMMAPROT_LG4_MIC(wgt, x1_start, x2_start, tr->partitionData[model].mic_tipVector, tip, width, diagptable, weights); #else partitionLikelihood = evaluateGTRGAMMAPROT_LG4((int *)NULL, (int *)NULL, wgt, x1_start, x2_start, tr->partitionData[model].tipVector_LG4, tip, width, diagptable, TRUE, weights); #endif else #ifdef __MIC_NATIVE partitionLikelihood = evaluateGAMMAPROT_MIC(wgt, x1_start, x2_start, tr->partitionData[model].mic_tipVector, tip, width, diagptable); #else partitionLikelihood = evaluateGTRGAMMAPROT(wgt, x1_start, x2_start, tr->partitionData[model].tipVector, tip, width, diagptable); #endif } } } break; default: assert(0); } #endif /* now here is a nasty part, for each partition and each node we maintain an integer counter to count how often how many entries per node were scaled by a constant factor. Here we use this information generated during Felsenstein's pruning algorithm by the newview() functions to undo the preceding scaling multiplications at the root, for mathematical details you should actually read: A. Stamatakis: "Orchestrating the Phylogenetic Likelihood Function on Emerging Parallel Architectures". In B. Schmidt, editor, Bioinformatics: High Performance Parallel Computer Architectures, 85-115, CRC Press, Taylor & Francis, 2010. There's a copy of this book in my office */ partitionLikelihood += (globalScaler[pNumber] + globalScaler[qNumber]) * LOG(minlikelihood); /* check that there was no major numerical screw-up, the log likelihood should be < 0.0 always */ assert(partitionLikelihood < 0.0); /* now we have the correct log likelihood for the current partition after undoing scaling multiplications */ /* finally, we also store the per partition log likelihood which is important for optimizing the alpha parameter of this partition for example */ *perPartitionLH = partitionLikelihood; } else { /* if the current thread does not have a single site of this partition it is important to set the per partition log like to 0.0 because of the reduction operation that will take place later-on. That is, the values of tr->perPartitionLH across all threads need to be in a consistent state, always ! */ if(width == 0) *perPartitionLH = 0.0; else { assert(tr->td[0].executeModel[model] == FALSE && *perPartitionLH < 0.0); } } } /* for model */ } /* OMP parallel */ #ifdef _USE_OMP /* perform reduction of per-partition LH scores */ int model, t; for(model = 0; model < tr->NumberOfModels; model++) { if (!tr->td[0].executeModel[model]) continue; tr->perPartitionLH[model] = 0.0; for(t = 0; t < tr->maxThreadsPerModel; t++) { Assign* pAss = tr->partThreadAssigns[model * tr->maxThreadsPerModel + t]; if (pAss) { int tid = pAss->procId; tr->perPartitionLH[model] += tr->partitionData[model].reductionBuffer[tid]; } } } #endif } void evaluateGeneric (tree *tr, nodeptr p, boolean fullTraversal) { /* now this may be the entry point of the library to compute the log like at a branch defined by p and p->back == q */ volatile double result = 0.0; nodeptr q = p->back; int i, model; /* set the first entry of the traversal descriptor to contain the indices of nodes p and q */ tr->td[0].ti[0].pNumber = p->number; tr->td[0].ti[0].qNumber = q->number; /* copy the branch lengths of the tree into the first entry of the traversal descriptor. if -M is not used tr->numBranches must be 1 */ for(i = 0; i < tr->numBranches; i++) tr->td[0].ti[0].qz[i] = q->z[i]; /* now compute how many conditionals must be re-computed/re-oriented by newview to be able to calculate the likelihood at the root defined by p and q. */ /* one entry in the traversal descriptor is already used, hence set the tarversal length counter to 1 */ tr->td[0].count = 1; /* do we need to recompute any of the vectors at or below p ? */ if(fullTraversal) { assert(isTip(p->number, tr->mxtips)); computeTraversalInfo(q, &(tr->td[0].ti[0]), &(tr->td[0].count), tr->mxtips, tr->numBranches, FALSE); } else { if(!p->x) computeTraversalInfo(p, &(tr->td[0].ti[0]), &(tr->td[0].count), tr->mxtips, tr->numBranches, TRUE); /* recompute/reorient any descriptors at or below q ? computeTraversalInfo computes and stores the newview() to be executed for the traversal descriptor */ if(!q->x) computeTraversalInfo(q, &(tr->td[0].ti[0]), &(tr->td[0].count), tr->mxtips, tr->numBranches, TRUE); } /* now we copy this partition execute mask into the traversal descriptor which must come from the calling program, the logic of this should not form part of the library */ storeExecuteMaskInTraversalDescriptor(tr); /* also store in the traversal descriptor that something has changed i.e., in the parallel case that the traversal descriptor list of nodes needs to be broadcast once again */ tr->td[0].traversalHasChanged = TRUE; evaluateIterative(tr); { double *recv = (double *)malloc(sizeof(double) * tr->NumberOfModels); #ifdef _USE_ALLREDUCE MPI_Allreduce(tr->perPartitionLH, recv, tr->NumberOfModels, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); #else MPI_Reduce(tr->perPartitionLH, recv, tr->NumberOfModels, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Bcast(recv, tr->NumberOfModels, MPI_DOUBLE, 0, MPI_COMM_WORLD); #endif memcpy(tr->perPartitionLH, recv, tr->NumberOfModels * sizeof(double)); for(model = 0; model < tr->NumberOfModels; model++) result += tr->perPartitionLH[model]; free(recv); } /* set the tree data structure likelihood value to the total likelihood */ tr->likelihood = result; /* MPI_Barrier(MPI_COMM_WORLD); printf("Process %d likelihood: %f\n", processID, tr->likelihood); MPI_Barrier(MPI_COMM_WORLD); */ /* do some bookkeeping to have traversalHasChanged in a consistent state */ tr->td[0].traversalHasChanged = FALSE; } /* below are the optimized function versions with geeky intrinsics */ #ifdef _OPTIMIZED_FUNCTIONS /* binary data */ static double evaluateGTRCAT_BINARY (int *ex1, int *ex2, int *cptr, int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, int n, double *diagptable_start, const boolean fastScaling) { double sum = 0.0, term; int i; double *diagptable, *x1, *x2; if(tipX1) { for (i = 0; i < n; i++) { double t[2] __attribute__ ((aligned (BYTE_ALIGNMENT))); x1 = &(tipVector[2 * tipX1[i]]); x2 = &(x2_start[2 * i]); diagptable = &(diagptable_start[2 * cptr[i]]); _mm_store_pd(t, _mm_mul_pd(_mm_load_pd(x1), _mm_mul_pd(_mm_load_pd(x2), _mm_load_pd(diagptable)))); if(fastScaling) term = log(fabs(t[0] + t[1])); else term = log(fabs(t[0] + t[1])) + (ex2[i] * log(minlikelihood)); sum += wptr[i] * term; } } else { for (i = 0; i < n; i++) { double t[2] __attribute__ ((aligned (BYTE_ALIGNMENT))); x1 = &x1_start[2 * i]; x2 = &x2_start[2 * i]; diagptable = &diagptable_start[2 * cptr[i]]; _mm_store_pd(t, _mm_mul_pd(_mm_load_pd(x1), _mm_mul_pd(_mm_load_pd(x2), _mm_load_pd(diagptable)))); if(fastScaling) term = log(fabs(t[0] + t[1])); else term = log(fabs(t[0] + t[1])) + ((ex1[i] + ex2[i]) * log(minlikelihood)); sum += wptr[i] * term; } } return sum; } static double evaluateGTRGAMMA_BINARY(int *ex1, int *ex2, int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, const int n, double *diagptable, const boolean fastScaling) { double sum = 0.0, term; int i, j; double *x1, *x2; if(tipX1) { for (i = 0; i < n; i++) { double t[2] __attribute__ ((aligned (BYTE_ALIGNMENT))); __m128d termv, x1v, x2v, dv; x1 = &(tipVector[2 * tipX1[i]]); x2 = &x2_start[8 * i]; termv = _mm_set1_pd(0.0); for(j = 0; j < 4; j++) { x1v = _mm_load_pd(&x1[0]); x2v = _mm_load_pd(&x2[j * 2]); dv = _mm_load_pd(&diagptable[j * 2]); x1v = _mm_mul_pd(x1v, x2v); x1v = _mm_mul_pd(x1v, dv); termv = _mm_add_pd(termv, x1v); } _mm_store_pd(t, termv); if(fastScaling) term = log(0.25 * (fabs(t[0] + t[1]))); else term = log(0.25 * (fabs(t[0] + t[1]))) + (ex2[i] * log(minlikelihood)); sum += wptr[i] * term; } } else { for (i = 0; i < n; i++) { double t[2] __attribute__ ((aligned (BYTE_ALIGNMENT))); __m128d termv, x1v, x2v, dv; x1 = &x1_start[8 * i]; x2 = &x2_start[8 * i]; termv = _mm_set1_pd(0.0); for(j = 0; j < 4; j++) { x1v = _mm_load_pd(&x1[j * 2]); x2v = _mm_load_pd(&x2[j * 2]); dv = _mm_load_pd(&diagptable[j * 2]); x1v = _mm_mul_pd(x1v, x2v); x1v = _mm_mul_pd(x1v, dv); termv = _mm_add_pd(termv, x1v); } _mm_store_pd(t, termv); if(fastScaling) term = log(0.25 * (fabs(t[0] + t[1]))); else term = log(0.25 * (fabs(t[0] + t[1]))) + ((ex1[i] +ex2[i]) * log(minlikelihood)); sum += wptr[i] * term; } } return sum; } /* binary data end */ static double evaluateGTRGAMMAPROT_LG4(int *ex1, int *ex2, int *wptr, double *x1, double *x2, double *tipVector[4], unsigned char *tipX1, int n, double *diagptable, const boolean fastScaling, double *weights) { double sum = 0.0, term; int i, j, l; double *left, *right; if(tipX1) { for (i = 0; i < n; i++) { #ifdef __SIM_SSE3 __m128d tv = _mm_setzero_pd(); for(j = 0, term = 0.0; j < 4; j++) { double *d = &diagptable[j * 20]; __m128d t = _mm_setzero_pd(), w = _mm_set1_pd(weights[j]); left = &(tipVector[j][20 * tipX1[i]]); right = &(x2[80 * i + 20 * j]); for(l = 0; l < 20; l+=2) { __m128d mul = _mm_mul_pd(_mm_load_pd(&left[l]), _mm_load_pd(&right[l])); t = _mm_add_pd(t, _mm_mul_pd(mul, _mm_load_pd(&d[l]))); } tv = _mm_add_pd(tv, _mm_mul_pd(t, w)); } tv = _mm_hadd_pd(tv, tv); _mm_storel_pd(&term, tv); #else for(j = 0, term = 0.0; j < 4; j++) { double t = 0.0; left = &(tipVector[j][20 * tipX1[i]]); right = &(x2[80 * i + 20 * j]); for(l = 0; l < 20; l++) t += left[l] * right[l] * diagptable[j * 20 + l]; term += weights[j] * t; } #endif if(fastScaling) term = LOG(FABS(term)); else term = LOG(FABS(term)) + (ex2[i] * LOG(minlikelihood)); sum += wptr[i] * term; } } else { for (i = 0; i < n; i++) { #ifdef __SIM_SSE3 __m128d tv = _mm_setzero_pd(); for(j = 0, term = 0.0; j < 4; j++) { double *d = &diagptable[j * 20]; __m128d t = _mm_setzero_pd(), w = _mm_set1_pd(weights[j]); left = &(x1[80 * i + 20 * j]); right = &(x2[80 * i + 20 * j]); for(l = 0; l < 20; l+=2) { __m128d mul = _mm_mul_pd(_mm_load_pd(&left[l]), _mm_load_pd(&right[l])); t = _mm_add_pd(t, _mm_mul_pd(mul, _mm_load_pd(&d[l]))); } tv = _mm_add_pd(tv, _mm_mul_pd(t, w)); } tv = _mm_hadd_pd(tv, tv); _mm_storel_pd(&term, tv); #else for(j = 0, term = 0.0; j < 4; j++) { double t = 0.0; left = &(x1[80 * i + 20 * j]); right = &(x2[80 * i + 20 * j]); for(l = 0; l < 20; l++) t += left[l] * right[l] * diagptable[j * 20 + l]; term += weights[j] * t; } #endif if(fastScaling) term = LOG(FABS(term)); else term = LOG(FABS(term)) + ((ex1[i] + ex2[i])*LOG(minlikelihood)); sum += wptr[i] * term; } } return sum; } static double evaluateGTRGAMMAPROT_GAPPED_SAVE (int *wptr, double *x1, double *x2, double *tipVector, unsigned char *tipX1, int n, double *diagptable, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap) { double sum = 0.0, term; int i, j, l; double *left, *right, *x1_ptr = x1, *x2_ptr = x2, *x1v, *x2v; if(tipX1) { for (i = 0; i < n; i++) { if(x2_gap[i / 32] & mask32[i % 32]) x2v = x2_gapColumn; else { x2v = x2_ptr; x2_ptr += 80; } __m128d tv = _mm_setzero_pd(); left = &(tipVector[20 * tipX1[i]]); for(j = 0, term = 0.0; j < 4; j++) { double *d = &diagptable[j * 20]; right = &(x2v[20 * j]); for(l = 0; l < 20; l+=2) { __m128d mul = _mm_mul_pd(_mm_load_pd(&left[l]), _mm_load_pd(&right[l])); tv = _mm_add_pd(tv, _mm_mul_pd(mul, _mm_load_pd(&d[l]))); } } tv = _mm_hadd_pd(tv, tv); _mm_storel_pd(&term, tv); term = LOG(0.25 * FABS(term)); sum += wptr[i] * term; } } else { for (i = 0; i < n; i++) { if(x1_gap[i / 32] & mask32[i % 32]) x1v = x1_gapColumn; else { x1v = x1_ptr; x1_ptr += 80; } if(x2_gap[i / 32] & mask32[i % 32]) x2v = x2_gapColumn; else { x2v = x2_ptr; x2_ptr += 80; } __m128d tv = _mm_setzero_pd(); for(j = 0, term = 0.0; j < 4; j++) { double *d = &diagptable[j * 20]; left = &(x1v[20 * j]); right = &(x2v[20 * j]); for(l = 0; l < 20; l+=2) { __m128d mul = _mm_mul_pd(_mm_load_pd(&left[l]), _mm_load_pd(&right[l])); tv = _mm_add_pd(tv, _mm_mul_pd(mul, _mm_load_pd(&d[l]))); } } tv = _mm_hadd_pd(tv, tv); _mm_storel_pd(&term, tv); term = LOG(0.25 * FABS(term)); sum += wptr[i] * term; } } return sum; } static double evaluateGTRGAMMAPROT (int *wptr, double *x1, double *x2, double *tipVector, unsigned char *tipX1, int n, double *diagptable) { double sum = 0.0, term; int i, j, l; double *left, *right; if(tipX1) { for (i = 0; i < n; i++) { __m128d tv = _mm_setzero_pd(); left = &(tipVector[20 * tipX1[i]]); for(j = 0, term = 0.0; j < 4; j++) { double *d = &diagptable[j * 20]; right = &(x2[80 * i + 20 * j]); for(l = 0; l < 20; l+=2) { __m128d mul = _mm_mul_pd(_mm_load_pd(&left[l]), _mm_load_pd(&right[l])); tv = _mm_add_pd(tv, _mm_mul_pd(mul, _mm_load_pd(&d[l]))); } } tv = _mm_hadd_pd(tv, tv); _mm_storel_pd(&term, tv); term = LOG(0.25 * FABS(term)); sum += wptr[i] * term; } } else { for (i = 0; i < n; i++) { __m128d tv = _mm_setzero_pd(); for(j = 0, term = 0.0; j < 4; j++) { double *d = &diagptable[j * 20]; left = &(x1[80 * i + 20 * j]); right = &(x2[80 * i + 20 * j]); for(l = 0; l < 20; l+=2) { __m128d mul = _mm_mul_pd(_mm_load_pd(&left[l]), _mm_load_pd(&right[l])); tv = _mm_add_pd(tv, _mm_mul_pd(mul, _mm_load_pd(&d[l]))); } } tv = _mm_hadd_pd(tv, tv); _mm_storel_pd(&term, tv); term = LOG(0.25 * FABS(term)); sum += wptr[i] * term; } } return sum; } static double evaluateGTRCATPROT (int *cptr, int *wptr, double *x1, double *x2, double *tipVector, unsigned char *tipX1, int n, double *diagptable_start) { double sum = 0.0, term; double *diagptable, *left, *right; int i, l; if(tipX1) { for (i = 0; i < n; i++) { left = &(tipVector[20 * tipX1[i]]); right = &(x2[20 * i]); diagptable = &diagptable_start[20 * cptr[i]]; __m128d tv = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) { __m128d lv = _mm_load_pd(&left[l]); __m128d rv = _mm_load_pd(&right[l]); __m128d mul = _mm_mul_pd(lv, rv); __m128d dv = _mm_load_pd(&diagptable[l]); tv = _mm_add_pd(tv, _mm_mul_pd(mul, dv)); } tv = _mm_hadd_pd(tv, tv); _mm_storel_pd(&term, tv); term = LOG(FABS(term)); sum += wptr[i] * term; } } else { for (i = 0; i < n; i++) { left = &x1[20 * i]; right = &x2[20 * i]; diagptable = &diagptable_start[20 * cptr[i]]; __m128d tv = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) { __m128d lv = _mm_load_pd(&left[l]); __m128d rv = _mm_load_pd(&right[l]); __m128d mul = _mm_mul_pd(lv, rv); __m128d dv = _mm_load_pd(&diagptable[l]); tv = _mm_add_pd(tv, _mm_mul_pd(mul, dv)); } tv = _mm_hadd_pd(tv, tv); _mm_storel_pd(&term, tv); term = LOG(FABS(term)); sum += wptr[i] * term; } } return sum; } static double evaluateGTRCATPROT_SAVE (int *cptr, int *wptr, double *x1, double *x2, double *tipVector, unsigned char *tipX1, int n, double *diagptable_start, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap) { double sum = 0.0, term, *diagptable, *left, *right, *left_ptr = x1, *right_ptr = x2; int i, l; if(tipX1) { for (i = 0; i < n; i++) { left = &(tipVector[20 * tipX1[i]]); if(isGap(x2_gap, i)) right = x2_gapColumn; else { right = right_ptr; right_ptr += 20; } diagptable = &diagptable_start[20 * cptr[i]]; __m128d tv = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) { __m128d lv = _mm_load_pd(&left[l]); __m128d rv = _mm_load_pd(&right[l]); __m128d mul = _mm_mul_pd(lv, rv); __m128d dv = _mm_load_pd(&diagptable[l]); tv = _mm_add_pd(tv, _mm_mul_pd(mul, dv)); } tv = _mm_hadd_pd(tv, tv); _mm_storel_pd(&term, tv); term = LOG(FABS(term)); sum += wptr[i] * term; } } else { for (i = 0; i < n; i++) { if(isGap(x1_gap, i)) left = x1_gapColumn; else { left = left_ptr; left_ptr += 20; } if(isGap(x2_gap, i)) right = x2_gapColumn; else { right = right_ptr; right_ptr += 20; } diagptable = &diagptable_start[20 * cptr[i]]; __m128d tv = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) { __m128d lv = _mm_load_pd(&left[l]); __m128d rv = _mm_load_pd(&right[l]); __m128d mul = _mm_mul_pd(lv, rv); __m128d dv = _mm_load_pd(&diagptable[l]); tv = _mm_add_pd(tv, _mm_mul_pd(mul, dv)); } tv = _mm_hadd_pd(tv, tv); _mm_storel_pd(&term, tv); term = LOG(FABS(term)); sum += wptr[i] * term; } } return sum; } static double evaluateGTRCAT_SAVE (int *cptr, int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, int n, double *diagptable_start, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap) { double sum = 0.0, term; int i; double *diagptable, *x1, *x2, *x1_ptr = x1_start, *x2_ptr = x2_start; if(tipX1) { for (i = 0; i < n; i++) { double t[2] __attribute__ ((aligned (BYTE_ALIGNMENT))); __m128d x1v1, x1v2, x2v1, x2v2, dv1, dv2; x1 = &(tipVector[4 * tipX1[i]]); if(isGap(x2_gap, i)) x2 = x2_gapColumn; else { x2 = x2_ptr; x2_ptr += 4; } diagptable = &diagptable_start[4 * cptr[i]]; x1v1 = _mm_load_pd(&x1[0]); x1v2 = _mm_load_pd(&x1[2]); x2v1 = _mm_load_pd(&x2[0]); x2v2 = _mm_load_pd(&x2[2]); dv1 = _mm_load_pd(&diagptable[0]); dv2 = _mm_load_pd(&diagptable[2]); x1v1 = _mm_mul_pd(x1v1, x2v1); x1v1 = _mm_mul_pd(x1v1, dv1); x1v2 = _mm_mul_pd(x1v2, x2v2); x1v2 = _mm_mul_pd(x1v2, dv2); x1v1 = _mm_add_pd(x1v1, x1v2); _mm_store_pd(t, x1v1); term = LOG(FABS(t[0] + t[1])); sum += wptr[i] * term; } } else { for (i = 0; i < n; i++) { double t[2] __attribute__ ((aligned (BYTE_ALIGNMENT))); __m128d x1v1, x1v2, x2v1, x2v2, dv1, dv2; if(isGap(x1_gap, i)) x1 = x1_gapColumn; else { x1 = x1_ptr; x1_ptr += 4; } if(isGap(x2_gap, i)) x2 = x2_gapColumn; else { x2 = x2_ptr; x2_ptr += 4; } diagptable = &diagptable_start[4 * cptr[i]]; x1v1 = _mm_load_pd(&x1[0]); x1v2 = _mm_load_pd(&x1[2]); x2v1 = _mm_load_pd(&x2[0]); x2v2 = _mm_load_pd(&x2[2]); dv1 = _mm_load_pd(&diagptable[0]); dv2 = _mm_load_pd(&diagptable[2]); x1v1 = _mm_mul_pd(x1v1, x2v1); x1v1 = _mm_mul_pd(x1v1, dv1); x1v2 = _mm_mul_pd(x1v2, x2v2); x1v2 = _mm_mul_pd(x1v2, dv2); x1v1 = _mm_add_pd(x1v1, x1v2); _mm_store_pd(t, x1v1); term = LOG(FABS(t[0] + t[1])); sum += wptr[i] * term; } } return sum; } static double evaluateGTRGAMMA_GAPPED_SAVE(int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, const int n, double *diagptable, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap) { double sum = 0.0, term; int i, j; double *x1, *x2, *x1_ptr = x1_start, *x2_ptr = x2_start; if(tipX1) { for (i = 0; i < n; i++) { double t[2] __attribute__ ((aligned (BYTE_ALIGNMENT))); __m128d termv, x1v, x2v, dv; x1 = &(tipVector[4 * tipX1[i]]); if(x2_gap[i / 32] & mask32[i % 32]) x2 = x2_gapColumn; else { x2 = x2_ptr; x2_ptr += 16; } termv = _mm_set1_pd(0.0); for(j = 0; j < 4; j++) { x1v = _mm_load_pd(&x1[0]); x2v = _mm_load_pd(&x2[j * 4]); dv = _mm_load_pd(&diagptable[j * 4]); x1v = _mm_mul_pd(x1v, x2v); x1v = _mm_mul_pd(x1v, dv); termv = _mm_add_pd(termv, x1v); x1v = _mm_load_pd(&x1[2]); x2v = _mm_load_pd(&x2[j * 4 + 2]); dv = _mm_load_pd(&diagptable[j * 4 + 2]); x1v = _mm_mul_pd(x1v, x2v); x1v = _mm_mul_pd(x1v, dv); termv = _mm_add_pd(termv, x1v); } _mm_store_pd(t, termv); term = LOG(0.25 * FABS(t[0] + t[1])); sum += wptr[i] * term; } } else { for (i = 0; i < n; i++) { double t[2] __attribute__ ((aligned (BYTE_ALIGNMENT))); __m128d termv, x1v, x2v, dv; if(x1_gap[i / 32] & mask32[i % 32]) x1 = x1_gapColumn; else { x1 = x1_ptr; x1_ptr += 16; } if(x2_gap[i / 32] & mask32[i % 32]) x2 = x2_gapColumn; else { x2 = x2_ptr; x2_ptr += 16; } termv = _mm_set1_pd(0.0); for(j = 0; j < 4; j++) { x1v = _mm_load_pd(&x1[j * 4]); x2v = _mm_load_pd(&x2[j * 4]); dv = _mm_load_pd(&diagptable[j * 4]); x1v = _mm_mul_pd(x1v, x2v); x1v = _mm_mul_pd(x1v, dv); termv = _mm_add_pd(termv, x1v); x1v = _mm_load_pd(&x1[j * 4 + 2]); x2v = _mm_load_pd(&x2[j * 4 + 2]); dv = _mm_load_pd(&diagptable[j * 4 + 2]); x1v = _mm_mul_pd(x1v, x2v); x1v = _mm_mul_pd(x1v, dv); termv = _mm_add_pd(termv, x1v); } _mm_store_pd(t, termv); term = LOG(0.25 * FABS(t[0] + t[1])); sum += wptr[i] * term; } } return sum; } static double evaluateGTRGAMMA(int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, const int n, double *diagptable) { double sum = 0.0, term; int i, j; double *x1, *x2; if(tipX1) { for (i = 0; i < n; i++) { double t[2] __attribute__ ((aligned (BYTE_ALIGNMENT))); __m128d termv, x1v, x2v, dv; x1 = &(tipVector[4 * tipX1[i]]); x2 = &x2_start[16 * i]; termv = _mm_set1_pd(0.0); for(j = 0; j < 4; j++) { x1v = _mm_load_pd(&x1[0]); x2v = _mm_load_pd(&x2[j * 4]); dv = _mm_load_pd(&diagptable[j * 4]); x1v = _mm_mul_pd(x1v, x2v); x1v = _mm_mul_pd(x1v, dv); termv = _mm_add_pd(termv, x1v); x1v = _mm_load_pd(&x1[2]); x2v = _mm_load_pd(&x2[j * 4 + 2]); dv = _mm_load_pd(&diagptable[j * 4 + 2]); x1v = _mm_mul_pd(x1v, x2v); x1v = _mm_mul_pd(x1v, dv); termv = _mm_add_pd(termv, x1v); } _mm_store_pd(t, termv); term = LOG(0.25 * FABS(t[0] + t[1])); sum += wptr[i] * term; } } else { for (i = 0; i < n; i++) { double t[2] __attribute__ ((aligned (BYTE_ALIGNMENT))); __m128d termv, x1v, x2v, dv; x1 = &x1_start[16 * i]; x2 = &x2_start[16 * i]; termv = _mm_set1_pd(0.0); for(j = 0; j < 4; j++) { x1v = _mm_load_pd(&x1[j * 4]); x2v = _mm_load_pd(&x2[j * 4]); dv = _mm_load_pd(&diagptable[j * 4]); x1v = _mm_mul_pd(x1v, x2v); x1v = _mm_mul_pd(x1v, dv); termv = _mm_add_pd(termv, x1v); x1v = _mm_load_pd(&x1[j * 4 + 2]); x2v = _mm_load_pd(&x2[j * 4 + 2]); dv = _mm_load_pd(&diagptable[j * 4 + 2]); x1v = _mm_mul_pd(x1v, x2v); x1v = _mm_mul_pd(x1v, dv); termv = _mm_add_pd(termv, x1v); } _mm_store_pd(t, termv); term = LOG(0.25 * FABS(t[0] + t[1])); sum += wptr[i] * term; } } return sum; } static double evaluateGTRCAT (int *cptr, int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, int n, double *diagptable_start) { double sum = 0.0, term; int i; double *diagptable, *x1, *x2; if(tipX1) { for (i = 0; i < n; i++) { double t[2] __attribute__ ((aligned (BYTE_ALIGNMENT))); __m128d x1v1, x1v2, x2v1, x2v2, dv1, dv2; x1 = &(tipVector[4 * tipX1[i]]); x2 = &x2_start[4 * i]; diagptable = &diagptable_start[4 * cptr[i]]; x1v1 = _mm_load_pd(&x1[0]); x1v2 = _mm_load_pd(&x1[2]); x2v1 = _mm_load_pd(&x2[0]); x2v2 = _mm_load_pd(&x2[2]); dv1 = _mm_load_pd(&diagptable[0]); dv2 = _mm_load_pd(&diagptable[2]); x1v1 = _mm_mul_pd(x1v1, x2v1); x1v1 = _mm_mul_pd(x1v1, dv1); x1v2 = _mm_mul_pd(x1v2, x2v2); x1v2 = _mm_mul_pd(x1v2, dv2); x1v1 = _mm_add_pd(x1v1, x1v2); _mm_store_pd(t, x1v1); term = LOG(FABS(t[0] + t[1])); sum += wptr[i] * term; } } else { for (i = 0; i < n; i++) { double t[2] __attribute__ ((aligned (BYTE_ALIGNMENT))); __m128d x1v1, x1v2, x2v1, x2v2, dv1, dv2; x1 = &x1_start[4 * i]; x2 = &x2_start[4 * i]; diagptable = &diagptable_start[4 * cptr[i]]; x1v1 = _mm_load_pd(&x1[0]); x1v2 = _mm_load_pd(&x1[2]); x2v1 = _mm_load_pd(&x2[0]); x2v2 = _mm_load_pd(&x2[2]); dv1 = _mm_load_pd(&diagptable[0]); dv2 = _mm_load_pd(&diagptable[2]); x1v1 = _mm_mul_pd(x1v1, x2v1); x1v1 = _mm_mul_pd(x1v1, dv1); x1v2 = _mm_mul_pd(x1v2, x2v2); x1v2 = _mm_mul_pd(x1v2, dv2); x1v1 = _mm_add_pd(x1v1, x1v2); _mm_store_pd(t, x1v1); term = LOG(FABS(t[0] + t[1])); sum += wptr[i] * term; } } return sum; } #endif ExaML-3.0.21/examl/evaluatePartialGenericSpecial.c000066400000000000000000000660051330315463200217450ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifndef WIN32 #include #endif #include #include #include #include #include #include #include "axml.h" #ifdef __SIM_SSE3 #include #include #endif #if defined(_OPTIMIZED_FUNCTIONS) && !defined(__MIC_NATIVE) static inline void computeVectorGTRCATPROT(double *lVector, int *eVector, double ki, int i, double qz, double rz, traversalInfo *ti, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int mxtips); static double evaluatePartialGTRCATPROT(int i, double ki, int counter, traversalInfo *ti, double qz, int w, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int branchReference, int mxtips); static inline void computeVectorGTRGAMMAPROT(double *lVector, int *eVector, double *gammaRates, int i, double qz, double rz, traversalInfo *ti, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int mxtips); static double evaluatePartialGTRGAMMAPROT(int i, int counter, traversalInfo *ti, double qz, int w, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, double *gammaRates, int branchReference, int mxtips); static inline void computeVectorGTRCAT(double *lVector, int *eVector, double ki, int i, double qz, double rz, traversalInfo *ti, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int mxtips); static double evaluatePartialGTRCAT(int i, double ki, int counter, traversalInfo *ti, double qz, int w, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int branchReference, int mxtips); static inline void computeVectorGTRCAT_BINARY(double *lVector, int *eVector, double ki, int i, double qz, double rz, traversalInfo *ti, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int mxtips); static double evaluatePartialGTRCAT_BINARY(int i, double ki, int counter, traversalInfo *ti, double qz, int w, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int branchReference, int mxtips); #else static inline void computeVectorCAT_FLEX(double *lVector, int *eVector, double ki, int i, double qz, double rz, traversalInfo *ti, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int mxtips, const int states) { double *d1 = (double *)malloc(sizeof(double) * states), *d2 = (double *)malloc(sizeof(double) * states), *x1px2 = (double *)malloc(sizeof(double) * states), ump_x1, ump_x2, lz1, lz2, *x1, *x2, *x3; int scale, j, k, pNumber = ti->pNumber, rNumber = ti->rNumber, qNumber = ti->qNumber; x3 = &lVector[states * (pNumber - mxtips)]; switch(ti->tipCase) { case TIP_TIP: x1 = &(tipVector[states * yVector[qNumber][i]]); x2 = &(tipVector[states * yVector[rNumber][i]]); break; case TIP_INNER: x1 = &(tipVector[states * yVector[qNumber][i]]); x2 = &(lVector[states * (rNumber - mxtips)]); break; case INNER_INNER: x1 = &(lVector[states * (qNumber - mxtips)]); x2 = &(lVector[states * (rNumber - mxtips)]); break; default: assert(0); } lz1 = qz * ki; lz2 = rz * ki; d1[0] = x1[0]; d2[0] = x2[0]; for(j = 1; j < states; j++) { d1[j] = x1[j] * EXP(EIGN[j] * lz1); d2[j] = x2[j] * EXP(EIGN[j] * lz2); } for(j = 0; j < states; j++) { ump_x1 = 0.0; ump_x2 = 0.0; for(k = 0; k < states; k++) { ump_x1 += d1[k] * EI[j * states + k]; ump_x2 += d2[k] * EI[j * states + k]; } x1px2[j] = ump_x1 * ump_x2; } for(j = 0; j < states; j++) x3[j] = 0.0; for(j = 0; j < states; j++) for(k = 0; k < states; k++) x3[k] += x1px2[j] * EV[states * j + k]; scale = 1; for(j = 0; scale && (j < states); j++) scale = ((x3[j] < minlikelihood) && (x3[j] > minusminlikelihood)); if(scale) { for(j = 0; j < states; j++) x3[j] *= twotothe256; *eVector = *eVector + 1; } free(d1); free(d2); free(x1px2); return; } static double evaluatePartialCAT_FLEX(int i, double ki, int counter, traversalInfo *ti, double qz, int w, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int branchReference, int mxtips, const int states) { int scale = 0, k; double *lVector = (double *)malloc_aligned(sizeof(double) * states * mxtips), *d = (double *)malloc_aligned(sizeof(double) * states), lz, term, *x1, *x2; traversalInfo *trav = &ti[0]; assert(isTip(trav->pNumber, mxtips)); x1 = &(tipVector[states * yVector[trav->pNumber][i]]); for(k = 1; k < counter; k++) { double qz = ti[k].qz[branchReference], rz = ti[k].rz[branchReference]; qz = (qz > zmin) ? log(qz) : log(zmin); rz = (rz > zmin) ? log(rz) : log(zmin); computeVectorCAT_FLEX(lVector, &scale, ki, i, qz, rz, &ti[k], EIGN, EI, EV, tipVector, yVector, mxtips, states); } x2 = &lVector[states * (trav->qNumber - mxtips)]; assert(0 <= (trav->qNumber - mxtips) && (trav->qNumber - mxtips) < mxtips); if(qz < zmin) lz = zmin; lz = log(qz); lz *= ki; d[0] = 1.0; for(k = 1; k < states; k++) d[k] = EXP (EIGN[k] * lz); term = 0.0; for(k = 0; k < states; k++) term += x1[k] * x2[k] * d[k]; term = LOG(FABS(term)) + (scale * LOG(minlikelihood)); term = term * w; free(lVector); free(d); return term; } #endif double evaluatePartialGeneric (tree *tr, int i, double ki, int _model) { double result; int branchReference, states = tr->partitionData[_model].states; int index; index = i; if(tr->numBranches > 1) branchReference = _model; else branchReference = 0; #ifndef _OPTIMIZED_FUNCTIONS if(tr->rateHetModel == CAT) result = evaluatePartialCAT_FLEX(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference], tr->partitionData[_model].wgt[index], tr->partitionData[_model].EIGN, tr->partitionData[_model].EI, tr->partitionData[_model].EV, tr->partitionData[_model].tipVector, tr->partitionData[_model].yVector, branchReference, tr->mxtips, states); else /* the per-site site likelihood function should only be called for the CAT model under the GAMMA model this is required only for estimating per-site protein models which has however been removed in this version of the code */ assert(0); #elif defined(__MIC_NATIVE) if (tr->rateHetModel == CAT) result = evaluatePartialCAT_FLEX(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference], tr->partitionData[_model].wgt[index], tr->partitionData[_model].EIGN, tr->partitionData[_model].EI, tr->partitionData[_model].EV, tr->partitionData[_model].tipVector, tr->partitionData[_model].yVector, branchReference, tr->mxtips, states); else assert(0); #else switch(states) { case 2: assert(!tr->saveMemory); assert(tr->rateHetModel == CAT); result = evaluatePartialGTRCAT_BINARY(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference], tr->partitionData[_model].wgt[index], tr->partitionData[_model].EIGN, tr->partitionData[_model].EI, tr->partitionData[_model].EV, tr->partitionData[_model].tipVector, tr->partitionData[_model].yVector, branchReference, tr->mxtips); break; case 4: /* DNA */ assert(tr->rateHetModel == CAT); result = evaluatePartialGTRCAT(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference], tr->partitionData[_model].wgt[index], tr->partitionData[_model].EIGN, tr->partitionData[_model].EI, tr->partitionData[_model].EV, tr->partitionData[_model].tipVector, tr->partitionData[_model].yVector, branchReference, tr->mxtips); break; case 20: /* proteins */ if(tr->rateHetModel == CAT) result = evaluatePartialGTRCATPROT(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference], tr->partitionData[_model].wgt[index], tr->partitionData[_model].EIGN, tr->partitionData[_model].EI, tr->partitionData[_model].EV, tr->partitionData[_model].tipVector, tr->partitionData[_model].yVector, branchReference, tr->mxtips); else result = evaluatePartialGTRGAMMAPROT(index, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference], tr->partitionData[_model].wgt[index], tr->partitionData[_model].EIGN, tr->partitionData[_model].EI, tr->partitionData[_model].EV, tr->partitionData[_model].tipVector, tr->partitionData[_model].yVector, tr->partitionData[_model].gammaRates, branchReference, tr->mxtips); break; default: assert(0); } #endif return result; } #ifdef _OPTIMIZED_FUNCTIONS static inline void computeVectorGTRCAT_BINARY(double *lVector, int *eVector, double ki, int i, double qz, double rz, traversalInfo *ti, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int mxtips) { double d1, d2, ump_x1, ump_x2, x1px2[2], lz1, lz2; double *x1, *x2, *x3; int j, k, pNumber = ti->pNumber, rNumber = ti->rNumber, qNumber = ti->qNumber; x3 = &lVector[2 * (pNumber - mxtips)]; switch(ti->tipCase) { case TIP_TIP: x1 = &(tipVector[2 * yVector[qNumber][i]]); x2 = &(tipVector[2 * yVector[rNumber][i]]); break; case TIP_INNER: x1 = &(tipVector[2 * yVector[qNumber][i]]); x2 = &lVector[2 * (rNumber - mxtips)]; break; case INNER_INNER: x1 = &lVector[2 * (qNumber - mxtips)]; x2 = &lVector[2 * (rNumber - mxtips)]; break; default: assert(0); } lz1 = qz * ki; lz2 = rz * ki; d1 = x1[1] * EXP(EIGN[1] * lz1); d2 = x2[1] * EXP(EIGN[1] * lz2); for(j = 0; j < 2; j++) { ump_x1 = x1[0]; ump_x2 = x2[0]; ump_x1 += d1 * EI[j * 2 + 1]; ump_x2 += d2 * EI[j * 2 + 1]; x1px2[j] = ump_x1 * ump_x2; } for(j = 0; j < 2; j++) x3[j] = 0.0; for(j = 0; j < 2; j++) for(k = 0; k < 2; k++) x3[k] += x1px2[j] * EV[2 * j + k]; if (x3[0] < minlikelihood && x3[0] > minusminlikelihood && x3[1] < minlikelihood && x3[1] > minusminlikelihood ) { x3[0] *= twotothe256; x3[1] *= twotothe256; *eVector = *eVector + 1; } return; } static double evaluatePartialGTRCAT_BINARY(int i, double ki, int counter, traversalInfo *ti, double qz, int w, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int branchReference, int mxtips) { double lz, term; double d; double *x1, *x2; int scale = 0, k; double *lVector = (double *)malloc(sizeof(double) * 2 * mxtips); traversalInfo *trav = &ti[0]; assert(isTip(trav->pNumber, mxtips)); x1 = &(tipVector[2 * yVector[trav->pNumber][i]]); for(k = 1; k < counter; k++) { double qz = ti[k].qz[branchReference], rz = ti[k].rz[branchReference]; qz = (qz > zmin) ? log(qz) : log(zmin); rz = (rz > zmin) ? log(rz) : log(zmin); computeVectorGTRCAT_BINARY(lVector, &scale, ki, i, qz, rz, &ti[k], EIGN, EI, EV, tipVector, yVector, mxtips); } x2 = &lVector[2 * (trav->qNumber - mxtips)]; assert(0 <= (trav->qNumber - mxtips) && (trav->qNumber - mxtips) < mxtips); if(qz < zmin) lz = zmin; lz = log(qz); lz *= ki; d = EXP(EIGN[1] * lz); term = x1[0] * x2[0]; term += x1[1] * x2[1] * d; term = LOG(FABS(term)) + (scale * LOG(minlikelihood)); term = term * w; free(lVector); return term; } static inline void computeVectorGTRCATPROT(double *lVector, int *eVector, double ki, int i, double qz, double rz, traversalInfo *ti, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int mxtips) { double *x1, *x2, *x3; int pNumber = ti->pNumber, rNumber = ti->rNumber, qNumber = ti->qNumber; x3 = &(lVector[20 * (pNumber - mxtips)]); switch(ti->tipCase) { case TIP_TIP: x1 = &(tipVector[20 * yVector[qNumber][i]]); x2 = &(tipVector[20 * yVector[rNumber][i]]); break; case TIP_INNER: x1 = &(tipVector[20 * yVector[qNumber][i]]); x2 = &( lVector[20 * (rNumber - mxtips)]); break; case INNER_INNER: x1 = &(lVector[20 * (qNumber - mxtips)]); x2 = &(lVector[20 * (rNumber - mxtips)]); break; default: assert(0); } { double e1[20] __attribute__ ((aligned (BYTE_ALIGNMENT))), e2[20] __attribute__ ((aligned (BYTE_ALIGNMENT))), d1[20] __attribute__ ((aligned (BYTE_ALIGNMENT))), d2[20] __attribute__ ((aligned (BYTE_ALIGNMENT))), lz1, lz2; int l, k, scale; lz1 = qz * ki; lz2 = rz * ki; e1[0] = 1.0; e2[0] = 1.0; for(l = 1; l < 20; l++) { e1[l] = EXP(EIGN[l] * lz1); e2[l] = EXP(EIGN[l] * lz2); } for(l = 0; l < 20; l+=2) { __m128d d1v = _mm_mul_pd(_mm_load_pd(&x1[l]), _mm_load_pd(&e1[l])); __m128d d2v = _mm_mul_pd(_mm_load_pd(&x2[l]), _mm_load_pd(&e2[l])); _mm_store_pd(&d1[l], d1v); _mm_store_pd(&d2[l], d2v); } __m128d zero = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) _mm_store_pd(&x3[l], zero); for(l = 0; l < 20; l++) { double *ev = &EV[l * 20]; __m128d ump_x1v = _mm_setzero_pd(); __m128d ump_x2v = _mm_setzero_pd(); __m128d x1px2v; for(k = 0; k < 20; k+=2) { __m128d eiv = _mm_load_pd(&EI[20 * l + k]); __m128d d1v = _mm_load_pd(&d1[k]); __m128d d2v = _mm_load_pd(&d2[k]); ump_x1v = _mm_add_pd(ump_x1v, _mm_mul_pd(d1v, eiv)); ump_x2v = _mm_add_pd(ump_x2v, _mm_mul_pd(d2v, eiv)); } ump_x1v = _mm_hadd_pd(ump_x1v, ump_x1v); ump_x2v = _mm_hadd_pd(ump_x2v, ump_x2v); x1px2v = _mm_mul_pd(ump_x1v, ump_x2v); for(k = 0; k < 20; k+=2) { __m128d ex3v = _mm_load_pd(&x3[k]); __m128d EVV = _mm_load_pd(&ev[k]); ex3v = _mm_add_pd(ex3v, _mm_mul_pd(x1px2v, EVV)); _mm_store_pd(&x3[k], ex3v); } } scale = 1; for(l = 0; scale && (l < 20); l++) scale = ((x3[l] < minlikelihood) && (x3[l] > minusminlikelihood)); if(scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 20; l+=2) { __m128d ex3v = _mm_mul_pd(_mm_load_pd(&x3[l]),twoto); _mm_store_pd(&x3[l], ex3v); } *eVector = *eVector + 1; } return; } } static double evaluatePartialGTRCATPROT(int i, double ki, int counter, traversalInfo *ti, double qz, int w, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int branchReference, int mxtips) { double lz, term; double d[20]; double *x1, *x2; int scale = 0, k, l; double *lVector = (double *)malloc_aligned(sizeof(double) * 20 * mxtips), myEI[400] __attribute__ ((aligned (BYTE_ALIGNMENT))); traversalInfo *trav = &ti[0]; for(k = 0; k < 20; k++) { for(l = 0; l < 20; l++) myEI[k * 20 + l] = EI[k * 20 + l]; } assert(isTip(trav->pNumber, mxtips)); x1 = &(tipVector[20 * yVector[trav->pNumber][i]]); for(k = 1; k < counter; k++) { double qz = ti[k].qz[branchReference], rz = ti[k].rz[branchReference]; qz = (qz > zmin) ? log(qz) : log(zmin); rz = (rz > zmin) ? log(rz) : log(zmin); computeVectorGTRCATPROT(lVector, &scale, ki, i, qz, rz, &ti[k], EIGN, myEI, EV, tipVector, yVector, mxtips); } x2 = &lVector[20 * (trav->qNumber - mxtips)]; assert(0 <= (trav->qNumber - mxtips) && (trav->qNumber - mxtips) < mxtips); if(qz < zmin) lz = zmin; lz = log(qz); lz *= ki; d[0] = 1.0; for(l = 1; l < 20; l++) d[l] = EXP (EIGN[l] * lz); term = 0.0; for(l = 0; l < 20; l++) term += x1[l] * x2[l] * d[l]; term = LOG(FABS(term)) + (scale * LOG(minlikelihood)); term = term * w; free(lVector); return term; } static inline void computeVectorGTRGAMMAPROT(double *lVector, int *eVector, double *gammaRates, int i, double qz, double rz, traversalInfo *ti, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int mxtips) { double *x1, *x2, *x3; int s, pNumber = ti->pNumber, rNumber = ti->rNumber, qNumber = ti->qNumber, index1[4], index2[4]; x3 = &(lVector[80 * (pNumber - mxtips)]); switch(ti->tipCase) { case TIP_TIP: x1 = &(tipVector[20 * yVector[qNumber][i]]); x2 = &(tipVector[20 * yVector[rNumber][i]]); for(s = 0; s < 4; s++) { index1[s] = 0; index2[s] = 0; } break; case TIP_INNER: x1 = &(tipVector[20 * yVector[qNumber][i]]); x2 = &( lVector[80 * (rNumber - mxtips)]); for(s = 0; s < 4; s++) index1[s] = 0; for(s = 0; s < 4; s++) index2[s] = s; break; case INNER_INNER: x1 = &(lVector[80 * (qNumber - mxtips)]); x2 = &(lVector[80 * (rNumber - mxtips)]); for(s = 0; s < 4; s++) { index1[s] = s; index2[s] = s; } break; default: assert(0); } { double e1[20] __attribute__ ((aligned (BYTE_ALIGNMENT))), e2[20] __attribute__ ((aligned (BYTE_ALIGNMENT))), d1[20] __attribute__ ((aligned (BYTE_ALIGNMENT))), d2[20] __attribute__ ((aligned (BYTE_ALIGNMENT))), lz1, lz2; int l, k, scale, j; for(j = 0; j < 4; j++) { lz1 = qz * gammaRates[j]; lz2 = rz * gammaRates[j]; e1[0] = 1.0; e2[0] = 1.0; for(l = 1; l < 20; l++) { e1[l] = EXP(EIGN[l] * lz1); e2[l] = EXP(EIGN[l] * lz2); } for(l = 0; l < 20; l+=2) { __m128d d1v = _mm_mul_pd(_mm_load_pd(&x1[20 * index1[j] + l]), _mm_load_pd(&e1[l])); __m128d d2v = _mm_mul_pd(_mm_load_pd(&x2[20 * index2[j] + l]), _mm_load_pd(&e2[l])); _mm_store_pd(&d1[l], d1v); _mm_store_pd(&d2[l], d2v); } __m128d zero = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) _mm_store_pd(&x3[j * 20 + l], zero); for(l = 0; l < 20; l++) { double *ev = &EV[l * 20]; __m128d ump_x1v = _mm_setzero_pd(); __m128d ump_x2v = _mm_setzero_pd(); __m128d x1px2v; for(k = 0; k < 20; k+=2) { __m128d eiv = _mm_load_pd(&EI[20 * l + k]); __m128d d1v = _mm_load_pd(&d1[k]); __m128d d2v = _mm_load_pd(&d2[k]); ump_x1v = _mm_add_pd(ump_x1v, _mm_mul_pd(d1v, eiv)); ump_x2v = _mm_add_pd(ump_x2v, _mm_mul_pd(d2v, eiv)); } ump_x1v = _mm_hadd_pd(ump_x1v, ump_x1v); ump_x2v = _mm_hadd_pd(ump_x2v, ump_x2v); x1px2v = _mm_mul_pd(ump_x1v, ump_x2v); for(k = 0; k < 20; k+=2) { __m128d ex3v = _mm_load_pd(&x3[j * 20 + k]); __m128d EVV = _mm_load_pd(&ev[k]); ex3v = _mm_add_pd(ex3v, _mm_mul_pd(x1px2v, EVV)); _mm_store_pd(&x3[j * 20 + k], ex3v); } } } scale = 1; for(l = 0; scale && (l < 80); l++) scale = ((x3[l] < minlikelihood) && (x3[l] > minusminlikelihood)); if(scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 80; l+=2) { __m128d ex3v = _mm_mul_pd(_mm_load_pd(&x3[l]),twoto); _mm_store_pd(&x3[l], ex3v); } *eVector = *eVector + 1; } return; } } static double evaluatePartialGTRGAMMAPROT(int i, int counter, traversalInfo *ti, double qz, int w, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, double *gammaRates, int branchReference, int mxtips) { double lz, term; double d[80]; double *x1, *x2; int scale = 0, k, l, j; double *lVector = (double *)malloc_aligned(sizeof(double) * 80 * mxtips), myEI[400] __attribute__ ((aligned (BYTE_ALIGNMENT))); traversalInfo *trav = &ti[0]; for(k = 0; k < 20; k++) { for(l = 0; l < 20; l++) myEI[k * 20 + l] = EI[k * 20 + l]; } assert(isTip(trav->pNumber, mxtips)); x1 = &(tipVector[20 * yVector[trav->pNumber][i]]); for(k = 1; k < counter; k++) { double qz = ti[k].qz[branchReference], rz = ti[k].rz[branchReference]; qz = (qz > zmin) ? log(qz) : log(zmin); rz = (rz > zmin) ? log(rz) : log(zmin); computeVectorGTRGAMMAPROT(lVector, &scale, gammaRates, i, qz, rz, &ti[k], EIGN, myEI, EV, tipVector, yVector, mxtips); } x2 = &lVector[80 * (trav->qNumber - mxtips)]; assert(0 <= (trav->qNumber - mxtips) && (trav->qNumber - mxtips) < mxtips); if(qz < zmin) lz = zmin; lz = log(qz); for(j = 0; j < 4; j++) { d[20 * j] = 1.0; for(l = 1; l < 20; l++) d[20 * j + l] = EXP(EIGN[l] * lz * gammaRates[j]); } for(j = 0, term = 0.0; j < 4; j++) { for(l = 0; l < 20; l++) term += x1[l] * x2[20 * j + l] * d[j * 20 + l]; } term = LOG(0.25 * FABS(term)) + (scale * LOG(minlikelihood)); term = term * w; free(lVector); return term; } static inline void computeVectorGTRCAT(double *lVector, int *eVector, double ki, int i, double qz, double rz, traversalInfo *ti, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int mxtips) { double d1[3], d2[3], ump_x1, ump_x2, x1px2[4], lz1, lz2; double *x1, *x2, *x3; int j, k, pNumber = ti->pNumber, rNumber = ti->rNumber, qNumber = ti->qNumber; x3 = &lVector[4 * (pNumber - mxtips)]; switch(ti->tipCase) { case TIP_TIP: x1 = &(tipVector[4 * yVector[qNumber][i]]); x2 = &(tipVector[4 * yVector[rNumber][i]]); break; case TIP_INNER: x1 = &(tipVector[4 * yVector[qNumber][i]]); x2 = &lVector[4 * (rNumber - mxtips)]; break; case INNER_INNER: x1 = &lVector[4 * (qNumber - mxtips)]; x2 = &lVector[4 * (rNumber - mxtips)]; break; default: assert(0); } lz1 = qz * ki; lz2 = rz * ki; for(j = 0; j < 3; j++) { d1[j] = x1[j + 1] * EXP(EIGN[j + 1] * lz1); d2[j] = x2[j + 1] * EXP(EIGN[j + 1] * lz2); } for(j = 0; j < 4; j++) { ump_x1 = x1[0]; ump_x2 = x2[0]; for(k = 0; k < 3; k++) { ump_x1 += d1[k] * EI[j * 4 + k + 1]; ump_x2 += d2[k] * EI[j * 4 + k + 1]; } x1px2[j] = ump_x1 * ump_x2; } for(j = 0; j < 4; j++) x3[j] = 0.0; for(j = 0; j < 4; j++) for(k = 0; k < 4; k++) x3[k] += x1px2[j] * EV[4 * j + k]; if (x3[0] < minlikelihood && x3[0] > minusminlikelihood && x3[1] < minlikelihood && x3[1] > minusminlikelihood && x3[2] < minlikelihood && x3[2] > minusminlikelihood && x3[3] < minlikelihood && x3[3] > minusminlikelihood) { x3[0] *= twotothe256; x3[1] *= twotothe256; x3[2] *= twotothe256; x3[3] *= twotothe256; *eVector = *eVector + 1; } return; } static double evaluatePartialGTRCAT(int i, double ki, int counter, traversalInfo *ti, double qz, int w, double *EIGN, double *EI, double *EV, double *tipVector, unsigned char **yVector, int branchReference, int mxtips) { double lz, term; double d[3]; double *x1, *x2; int scale = 0, k; double *lVector = (double *)malloc_aligned(sizeof(double) * 4 * mxtips); traversalInfo *trav = &ti[0]; assert(isTip(trav->pNumber, mxtips)); x1 = &(tipVector[4 * yVector[trav->pNumber][i]]); for(k = 1; k < counter; k++) { double qz = ti[k].qz[branchReference], rz = ti[k].rz[branchReference]; qz = (qz > zmin) ? log(qz) : log(zmin); rz = (rz > zmin) ? log(rz) : log(zmin); computeVectorGTRCAT(lVector, &scale, ki, i, qz, rz, &ti[k], EIGN, EI, EV, tipVector, yVector, mxtips); } x2 = &lVector[4 * (trav->qNumber - mxtips)]; assert(0 <= (trav->qNumber - mxtips) && (trav->qNumber - mxtips) < mxtips); if(qz < zmin) lz = zmin; lz = log(qz); lz *= ki; d[0] = EXP (EIGN[1] * lz); d[1] = EXP (EIGN[2] * lz); d[2] = EXP (EIGN[3] * lz); term = x1[0] * x2[0]; term += x1[1] * x2[1] * d[0]; term += x1[2] * x2[2] * d[1]; term += x1[3] * x2[3] * d[2]; term = LOG(FABS(term)) + (scale * LOG(minlikelihood)); term = term * w; free(lVector); return term; } #endif ExaML-3.0.21/examl/globalVariables.h000066400000000000000000000204771330315463200171250ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ int processes; double *globalResult; int processID; infoList iList; int Thorough = 0; checkPointState ckp; char run_id[128] = "", workdir[1024] = "", seq_file[1024] = "", tree_file[1024]="", weightFileName[1024] = "", resultFileName[1024] = "", logFileName[1024] = "", infoFileName[1024] = "", randomFileName[1024] = "", proteinModelFileName[1024] = "", binaryCheckpointName[1024] = "", binaryCheckpointInputName[1024] = "", byteFileName[1024] = "", modelFileName[1024] = "", treeFileName[1024] = "", quartetGroupingFileName[1024], quartetFileName[1024]; char *protModels[NUM_PROT_MODELS] = {"DAYHOFF", "DCMUT", "JTT", "MTREV", "WAG", "RTREV", "CPREV", "VT", "BLOSUM62", "MTMAM", "LG", "MTART", "MTZOA", "PMB", "HIVB", "HIVW", "JTTDCMUT", "FLU", "STMTREV", "AUTO", "LG4M", "LG4X", "GTR"}; const char inverseMeaningBINARY[4] = {'_', '0', '1', '-'}; const char inverseMeaningDNA[16] = {'_', 'A', 'C', 'M', 'G', 'R', 'S', 'V', 'T', 'W', 'Y', 'H', 'K', 'D', 'B', '-'}; const char inverseMeaningPROT[23] = {'A','R', 'N', 'D', 'C', 'Q', 'E', 'G', 'H', 'I', 'L', 'K', 'M', 'F', 'P', 'S', 'T', 'W', 'Y', 'V', 'B', 'Z', '-'}; const char inverseMeaningGeneric32[33] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', '-'}; const char inverseMeaningGeneric64[33] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', '-'}; const unsigned int bitVectorIdentity[256] = {0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 ,19 ,20 ,21 ,22 ,23 ,24 ,25 ,26 , 27 ,28 ,29 ,30 ,31 ,32 ,33 ,34 ,35 ,36 ,37 ,38 ,39 ,40 ,41 ,42 ,43 ,44 ,45 ,46 ,47 ,48 ,49 ,50 ,51 , 52 ,53 ,54 ,55 ,56 ,57 ,58 ,59 ,60 ,61 ,62 ,63 ,64 ,65 ,66 ,67 ,68 ,69 ,70 ,71 ,72 ,73 ,74 ,75 ,76 , 77 ,78 ,79 ,80 ,81 ,82 ,83 ,84 ,85 ,86 ,87 ,88 ,89 ,90 ,91 ,92 ,93 ,94 ,95 ,96 ,97 ,98 ,99 ,100 ,101 , 102 ,103 ,104 ,105 ,106 ,107 ,108 ,109 ,110 ,111 ,112 ,113 ,114 ,115 ,116 ,117 ,118 ,119 ,120 ,121 ,122 , 123 ,124 ,125 ,126 ,127 ,128 ,129 ,130 ,131 ,132 ,133 ,134 ,135 ,136 ,137 ,138 ,139 ,140 ,141 ,142 ,143 , 144 ,145 ,146 ,147 ,148 ,149 ,150 ,151 ,152 ,153 ,154 ,155 ,156 ,157 ,158 ,159 ,160 ,161 ,162 ,163 ,164 , 165 ,166 ,167 ,168 ,169 ,170 ,171 ,172 ,173 ,174 ,175 ,176 ,177 ,178 ,179 ,180 ,181 ,182 ,183 ,184 ,185 , 186 ,187 ,188 ,189 ,190 ,191 ,192 ,193 ,194 ,195 ,196 ,197 ,198 ,199 ,200 ,201 ,202 ,203 ,204 ,205 ,206 , 207 ,208 ,209 ,210 ,211 ,212 ,213 ,214 ,215 ,216 ,217 ,218 ,219 ,220 ,221 ,222 ,223 ,224 ,225 ,226 ,227 , 228 ,229 ,230 ,231 ,232 ,233 ,234 ,235 ,236 ,237 ,238 ,239 ,240 ,241 ,242 ,243 ,244 ,245 ,246 ,247 ,248 , 249 ,250 ,251 ,252 ,253 ,254 ,255}; const unsigned int bitVectorAA[23] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 12 /* N | D */, 96 /*Q | E*/, 1048575 /* - */}; const unsigned int bitVectorSecondary[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255, 0, 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 0, 257, 514, 771, 1028, 1285, 1542, 1799, 2056, 2313, 2570, 2827, 3084, 3341, 3598, 3855, 0, 272, 544, 816, 1088, 1360, 1632, 1904, 2176, 2448, 2720, 2992, 3264, 3536, 3808, 4080, 0, 273, 546, 819, 1092, 1365, 1638, 1911, 2184, 2457, 2730, 3003, 3276, 3549, 3822, 4095, 0, 4096, 8192, 12288, 16384, 20480, 24576, 28672, 32768, 36864, 40960, 45056, 49152, 53248, 57344, 61440, 0, 4097, 8194, 12291, 16388, 20485, 24582, 28679, 32776, 36873, 40970, 45067, 49164, 53261, 57358, 61455, 0, 4112, 8224, 12336, 16448, 20560, 24672, 28784, 32896, 37008, 41120, 45232, 49344, 53456, 57568, 61680, 0, 4113, 8226, 12339, 16452, 20565, 24678, 28791, 32904, 37017, 41130, 45243, 49356, 53469, 57582, 61695, 0, 4352, 8704, 13056, 17408, 21760, 26112, 30464, 34816, 39168, 43520, 47872, 52224, 56576, 60928, 65280, 0, 4353, 8706, 13059, 17412, 21765, 26118, 30471, 34824, 39177, 43530, 47883, 52236, 56589, 60942, 65295, 0, 4368, 8736, 13104, 17472, 21840, 26208, 30576, 34944, 39312, 43680, 48048, 52416, 56784, 61152, 65520, 0, 4369, 8738, 13107, 17476, 21845, 26214, 30583, 34952, 39321, 43690, 48059, 52428, 56797, 61166, 65535}; const unsigned int bitVector32[33] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648u, 4294967295u}; /*const unsigned int bitVector64[65] = {};*/ const unsigned int mask32[32] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648U}; const char *secondaryModelList[21] = { "S6A (GTR)", "S6B", "S6C", "S6D", "S6E", "S7A (GTR)", "S7B", "S7C", "S7D", "S7E", "S7F", "S16 (GTR)", "S16A", "S16B", "S16C", "S16D", "S16E", "S16F", "S16I", "S16J", "S16K"}; double masterTime; double accumulatedTime; int optimizeRateCategoryInvocations = 1; partitionLengths pLengths[MAX_MODEL] = { /* BINARY */ //{4, 4, 2, 4, 2, 1, 2, 8, 2, 2, FALSE, 3, inverseMeaningBINARY, 2, FALSE, bitVectorIdentity}, //eiLength changed from 2 -> 4 {4, 4, 2, 4, 4, 1, 2, 8, 2, 2, FALSE, 3, inverseMeaningBINARY, 2, FALSE, bitVectorIdentity}, /* DNA */ {16, 16, 4, 16, 16, 6, 4, 64, 6, 4, FALSE, 15, inverseMeaningDNA, 4, FALSE, bitVectorIdentity}, /* AA */ {400, 400, 20, 400, 400, 190, 20, 460, 190, 20, FALSE, 22, inverseMeaningPROT, 20, TRUE, bitVectorAA}, /* SECONDARY_DATA */ {256, 256, 16, 256, 256, 120, 16, 4096, 120, 16, FALSE, 255, (char*)NULL, 16, TRUE, bitVectorSecondary}, /* SECONDARY_DATA_6 */ {36, 36, 6, 36, 36, 15, 6, 384, 15, 6, FALSE, 63, (char*)NULL, 6, TRUE, bitVectorIdentity}, /* SECONDARY_DATA_7 */ {49, 49, 7, 49, 49, 21, 7, 896, 21, 7, FALSE, 127, (char*)NULL, 7, TRUE, bitVectorIdentity}, /* 32 states */ {1024, 1024, 32, 1024, 1024, 496, 32, 1056, 496, 32, FALSE, 32, inverseMeaningGeneric32, 32, TRUE, bitVector32}, /* 64 states */ {4096, 4096, 64, 4096, 4096, 2016, 64, 4160, 64, 2016, FALSE, 64, (char*)NULL, 64, TRUE, (unsigned int*)NULL} }; partitionLengths pLength; ExaML-3.0.21/examl/makenewzGenericSpecial.c000066400000000000000000002146041330315463200204430ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with * thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifndef WIN32 #include #endif #include #include #include #include #include #include #include "axml.h" #ifdef __SIM_SSE3 #include #include /*#include */ #endif /* includes MIC-optimized functions */ #ifdef __MIC_NATIVE #include "mic_native.h" #endif /* pointers to reduction buffers for storing and gathering the first and second derivative of the likelihood in Pthreads and MPI */ extern int processID; extern const unsigned int mask32[32]; /*******************/ /* generic function to get the required pointers to the data associated with the left and right node that define a branch */ static void getVects(tree *tr, unsigned char **tipX1, unsigned char **tipX2, double **x1_start, double **x2_start, int *tipCase, int model, double **x1_gapColumn, double **x2_gapColumn, unsigned int **x1_gap, unsigned int **x2_gap, size_t offset) { int rateHet = (int)discreteRateCategories(tr->rateHetModel), states = tr->partitionData[model].states, span = rateHet * states; size_t x_offset = offset * (size_t)span; int pNumber, qNumber; /* get the left and right node number of the nodes defining the branch we want to optimize */ pNumber = tr->td[0].ti[0].pNumber; qNumber = tr->td[0].ti[0].qNumber; /* initialize to NULL */ *x1_start = (double*)NULL, *x2_start = (double*)NULL; *tipX1 = (unsigned char*)NULL, *tipX2 = (unsigned char*)NULL; /* switch over the different tip cases again here */ if(isTip(pNumber, tr->mxtips) || isTip(qNumber, tr->mxtips)) { if(!( isTip(pNumber, tr->mxtips) && isTip(qNumber, tr->mxtips)) ) { *tipCase = TIP_INNER; if(isTip(qNumber, tr->mxtips)) { *tipX1 = tr->partitionData[model].yVector[qNumber] + offset; *x2_start = tr->partitionData[model].xVector[pNumber - tr->mxtips - 1] + x_offset; if(tr->saveMemory) { *x2_gap = &(tr->partitionData[model].gapVector[pNumber * tr->partitionData[model].gapVectorLength]); *x2_gapColumn = &tr->partitionData[model].gapColumn[(pNumber - tr->mxtips - 1) * states * rateHet]; } } else { *tipX1 = tr->partitionData[model].yVector[pNumber] + offset; *x2_start = tr->partitionData[model].xVector[qNumber - tr->mxtips - 1] + x_offset; if(tr->saveMemory) { *x2_gap = &(tr->partitionData[model].gapVector[qNumber * tr->partitionData[model].gapVectorLength]); *x2_gapColumn = &tr->partitionData[model].gapColumn[(qNumber - tr->mxtips - 1) * states * rateHet]; } } } else { /* note that tip tip should normally not occur since this means that we are trying to optimize a branch in a two-taxon tree. However, this has been inherited be some RAxML function that optimized pair-wise distances between all taxa in a tree */ *tipCase = TIP_TIP; *tipX1 = tr->partitionData[model].yVector[pNumber] + offset; *tipX2 = tr->partitionData[model].yVector[qNumber] + offset; } } else { *tipCase = INNER_INNER; *x1_start = tr->partitionData[model].xVector[pNumber - tr->mxtips - 1] + x_offset; *x2_start = tr->partitionData[model].xVector[qNumber - tr->mxtips - 1] + x_offset; if(tr->saveMemory) { *x1_gap = &(tr->partitionData[model].gapVector[pNumber * tr->partitionData[model].gapVectorLength]); *x1_gapColumn = &tr->partitionData[model].gapColumn[(pNumber - tr->mxtips - 1) * states * rateHet]; *x2_gap = &(tr->partitionData[model].gapVector[qNumber * tr->partitionData[model].gapVectorLength]); *x2_gapColumn = &tr->partitionData[model].gapColumn[(qNumber - tr->mxtips - 1) * states * rateHet]; } } } /* this is actually a pre-computation and storage of values that remain constant while we change the value of the branch length we want to adapt. the target pointer sumtable is a single pre-allocated array that has the same size as a conditional likelihood vector at an inner node. So if we want to do a Newton-Rpahson optimization we only execute this function once in the beginning for each new branch we are considering ! */ #ifndef _OPTIMIZED_FUNCTIONS static void sumCAT_FLEX(int tipCase, double *sumtable, double *x1, double *x2, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, const int states) { int i, l; double *sum, *left, *right; switch(tipCase) { /* switch over possible configurations of the nodes p and q defining the branch */ case TIP_TIP: for (i = 0; i < n; i++) { left = &(tipVector[states * tipX1[i]]); right = &(tipVector[states * tipX2[i]]); sum = &sumtable[states * i]; /* just multiply the values with each other for each site, note the similarity with evaluate() we precompute the product which will remain constant and then just multiply this pre-computed product with the changing P matrix exponentaions that depend on the branch lengths */ for(l = 0; l < states; l++) sum[l] = left[l] * right[l]; } break; case TIP_INNER: /* same as for TIP_TIP only that we now access on tip vector and one inner vector. You may also observe that we do not consider using scaling vectors anywhere here. This is because we are interested in the first and second derivatives of the likelihood and hence the addition of the log() of the scaling factor times the number of scaling events becomes obsolete through the derivative */ for (i = 0; i < n; i++) { left = &(tipVector[states * tipX1[i]]); right = &x2[states * i]; sum = &sumtable[states * i]; for(l = 0; l < states; l++) sum[l] = left[l] * right[l]; } break; case INNER_INNER: for (i = 0; i < n; i++) { left = &x1[states * i]; right = &x2[states * i]; sum = &sumtable[states * i]; for(l = 0; l < states; l++) sum[l] = left[l] * right[l]; } break; default: assert(0); } } /* same thing for GAMMA models. The only noteworthy thing here is that we have an additional inner loop over the number of discrete gamma rates. The data access pattern is also different since for tip vector accesses through our lookup table, we do not distnguish between rates Note the different access pattern in TIP_INNER: left = &(tipVector[states * tipX1[i]]); right = &(x2[span * i + l * states]); */ static void sumGAMMA_FLEX(int tipCase, double *sumtable, double *x1, double *x2, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, const int states) { int i, l, k; const int span = 4 * states; double *left, *right, *sum; switch(tipCase) { case TIP_TIP: for(i = 0; i < n; i++) { left = &(tipVector[states * tipX1[i]]); right = &(tipVector[states * tipX2[i]]); for(l = 0; l < 4; l++) { sum = &sumtable[i * span + l * states]; for(k = 0; k < states; k++) sum[k] = left[k] * right[k]; } } break; case TIP_INNER: for(i = 0; i < n; i++) { left = &(tipVector[states * tipX1[i]]); for(l = 0; l < 4; l++) { right = &(x2[span * i + l * states]); sum = &sumtable[i * span + l * states]; for(k = 0; k < states; k++) sum[k] = left[k] * right[k]; } } break; case INNER_INNER: for(i = 0; i < n; i++) { for(l = 0; l < 4; l++) { left = &(x1[span * i + l * states]); right = &(x2[span * i + l * states]); sum = &(sumtable[i * span + l * states]); for(k = 0; k < states; k++) sum[k] = left[k] * right[k]; } } break; default: assert(0); } } #endif /* optimized functions for branch length optimization */ #ifdef _OPTIMIZED_FUNCTIONS static void sumGAMMA_BINARY(int tipCase, double *sumtable, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n); static void coreGTRGAMMA_BINARY(const int upper, double *sumtable, volatile double *d1, volatile double *d2, double *EIGN, double *gammaRates, double lz, int *wrptr); static void coreGTRCAT_BINARY(int upper, int numberOfCategories, double *sum, volatile double *d1, volatile double *d2, double *rptr, double *EIGN, int *cptr, double lz, int *wgt); static void sumCAT_BINARY(int tipCase, double *sum, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n); static void sumCAT_SAVE(int tipCase, double *sum, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap); static void sumGAMMA_GAPPED_SAVE(int tipCase, double *sumtable, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap); static void sumGAMMA(int tipCase, double *sumtable, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n); static void sumCAT(int tipCase, double *sum, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n); static void sumGAMMAPROT_GAPPED_SAVE(int tipCase, double *sumtable, double *x1, double *x2, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap); static void sumGAMMAPROT_LG4(int tipCase, double *sumtable, double *x1, double *x2, double *tipVector[4], unsigned char *tipX1, unsigned char *tipX2, int n); static void sumGAMMAPROT(int tipCase, double *sumtable, double *x1, double *x2, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n); static void sumGTRCATPROT(int tipCase, double *sumtable, double *x1, double *x2, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n); static void sumGTRCATPROT_SAVE(int tipCase, double *sumtable, double *x1, double *x2, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap); static void coreGTRGAMMAPROT_LG4(double *gammaRates, double *EIGN[4], double *sumtable, int upper, int *wrptr, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double lz, double *weights); static void coreGTRGAMMA(const int upper, double *sumtable, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double *EIGN, double *gammaRates, double lz, int *wgt); static void coreGTRCAT(int upper, int numberOfCategories, double *sum, volatile double *d1, volatile double *d2, int *wgt, double *rptr, double *EIGN, int *cptr, double lz); static void coreGTRGAMMAPROT(double *gammaRates, double *EIGN, double *sumtable, int upper, int *wgt, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double lz); static void coreGTRCATPROT(double *EIGN, double lz, int numberOfCategories, double *rptr, int *cptr, int upper, int *wgt, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double *sumtable); #endif #ifndef _OPTIMIZED_FUNCTIONS /* now this is the core function of the newton-Raphson based branch length optimization that actually computes the first and second derivative of the likelihood given a new proposed branch length lz */ static void coreCAT_FLEX(int upper, int numberOfCategories, double *sum, volatile double *d1, volatile double *d2, int *wgt, double *rptr, double *EIGN, int *cptr, double lz, const int states) { int i, l; double *d, /* arrays to store stuff we can pre-compute */ *d_start = (double *)malloc_aligned(numberOfCategories * states * sizeof(double)), *e =(double *)malloc_aligned(states * sizeof(double)), *s = (double *)malloc_aligned(states * sizeof(double)), *dd = (double *)malloc_aligned(states * sizeof(double)), inv_Li, dlnLidlz, d2lnLidlz2, dlnLdlz = 0.0, d2lnLdlz2 = 0.0; d = d_start; e[0] = 0.0; s[0] = 0.0; dd[0] = 0.0; /* we are pre-computing values for computing the first and second derivative of P(lz) since this requires an exponetial that the only thing we really have to derive here */ for(l = 1; l < states; l++) { s[l] = EIGN[l]; e[l] = EIGN[l] * EIGN[l]; dd[l] = s[l] * lz; } /* compute the P matrices and their derivatives for all per-site rate categories */ for(i = 0; i < numberOfCategories; i++) { d[states * i] = 1.0; for(l = 1; l < states; l++) d[states * i + l] = EXP(dd[l] * rptr[i]); } /* now loop over the sites in this partition to obtain the per-site 1st and 2nd derivatives */ for (i = 0; i < upper; i++) { double r = rptr[cptr[i]], wr1 = r * wgt[i], wr2 = r * r * wgt[i]; /* get the correct p matrix for the rate at the current site i */ d = &d_start[states * cptr[i]]; /* this is the likelihood at site i, NOT the log likelihood, we don't need the log likelihood to compute derivatives ! */ inv_Li = sum[states * i]; /* those are for storing the first and second derivative of the Likelihood at site i */ dlnLidlz = 0.0; d2lnLidlz2 = 0.0; /* now multiply the likelihood and the first and second derivative with the appropriate derivatives of P(lz) */ for(l = 1; l < states; l++) { double tmpv = d[l] * sum[states * i + l]; inv_Li += tmpv; dlnLidlz += tmpv * s[l]; d2lnLidlz2 += tmpv * e[l]; } /* below we are implementing the other mathematical operations that are required to obtain the deirivatives */ inv_Li = 1.0/ FABS(inv_Li); dlnLidlz *= inv_Li; d2lnLidlz2 *= inv_Li; /* under the CAT model, wrptr[] and wr2ptr[] are pre-computed extension sof the weight pointer: wrptr[i] = wgt[i] * rptr[cptr[i]]. and wr2ptr[i] = wgt[i] * rptr[cptr[i]] * rptr[cptr[i]] this is also something that is required for the derivatives because when computing the derivative of the exponential() the rate must be multiplied with the exponential wgt is just the pattern site wieght */ /* compute the accumulated first and second derivatives of this site */ dlnLdlz += wr1 * dlnLidlz; d2lnLdlz2 += wr2 * (d2lnLidlz2 - dlnLidlz * dlnLidlz); } /* set the result values, i.e., the sum of the per-site first and second derivatives of the likelihood function for this partition. */ *d1 = dlnLdlz; *d2 = d2lnLdlz2; /* free the temporary arrays */ free(d_start); free(e); free(s); free(dd); } static void coreGAMMA_FLEX(int upper, double *sumtable, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double *EIGN, double *gammaRates, double lz, int *wgt, const int states) { double *sum, diagptable[1024], /* TODO make this dynamic */ dlnLdlz = 0.0, d2lnLdlz2 = 0.0, ki, kisqr, tmp, inv_Li, dlnLidlz, d2lnLidlz2; int i, j, l; const int gammaStates = 4 * states; /* pre-compute the derivatives of the P matrix for all discrete GAMMA rates */ for(i = 0; i < 4; i++) { ki = gammaRates[i]; kisqr = ki * ki; for(l = 1; l < states; l++) { diagptable[i * gammaStates + l * 4] = EXP(EIGN[l] * ki * lz); diagptable[i * gammaStates + l * 4 + 1] = EIGN[l] * ki; diagptable[i * gammaStates + l * 4 + 2] = EIGN[l] * EIGN[l] * kisqr; } } /* loop over sites in this partition */ for (i = 0; i < upper; i++) { double r = rptr[cptr[i]], wr1 = r * wgt[i], wr2 = r * r * wgt[i]; /* access the array with pre-computed values */ sum = &sumtable[i * gammaStates]; /* initial per-site likelihood and 1st and 2nd derivatives */ inv_Li = 0.0; dlnLidlz = 0.0; d2lnLidlz2 = 0.0; /* loop over discrete GAMMA rates */ for(j = 0; j < 4; j++) { inv_Li += sum[j * states]; for(l = 1; l < states; l++) { inv_Li += (tmp = diagptable[j * gammaStates + l * 4] * sum[j * states + l]); dlnLidlz += tmp * diagptable[j * gammaStates + l * 4 + 1]; d2lnLidlz2 += tmp * diagptable[j * gammaStates + l * 4 + 2]; } } /* finalize derivative computation */ /* note that wrptr[] here unlike in CAT above is the integer weight vector of the current site The operations: EIGN[l] * ki; EIGN[l] * EIGN[l] * kisqr; that are hidden in CAT in wrptr (at least the * ki and * ki *ki part of them are done explicitely here */ inv_Li = 1.0 / FABS(inv_Li); dlnLidlz *= inv_Li; d2lnLidlz2 *= inv_Li; dlnLdlz += wr1 * dlnLidlz; d2lnLdlz2 += wr2 * (d2lnLidlz2 - dlnLidlz * dlnLidlz); } *ext_dlnLdlz = dlnLdlz; *ext_d2lnLdlz2 = d2lnLdlz2; } #endif /* the function below is called only once at the very beginning of each Newton-Raphson procedure for optimizing barnch lengths. It initially invokes an iterative newview call to get a consistent pair of vectors at the left and the right end of the branch and thereafter invokes the one-time only precomputation of values (sumtable) that can be re-used in each Newton-Raphson iteration. Once this function has been called we can execute the actual NR procedure */ void makenewzIterative(tree *tr) { /* call newvieIterative to get the likelihood arrays to the left and right of the branch */ newviewIterative(tr, 1); /* loop over all partoitions to do the precomputation of the sumTable buffer This is analogous to the newviewIterative() and evaluateIterative() implementations. */ #ifdef _USE_OMP #pragma omp parallel #endif { int m, model, maxModel, tipCase; #ifdef _USE_OMP maxModel = tr->maxModelsPerThread; #else maxModel = tr->NumberOfModels; #endif double *x1_start = (double*)NULL, *x2_start = (double*)NULL; unsigned char *tipX1, *tipX2; double *x1_gapColumn = (double*)NULL, *x2_gapColumn = (double*)NULL; unsigned int *x1_gap = (unsigned int*)NULL, *x2_gap = (unsigned int*)NULL; for(m = 0; m < maxModel; m++) { size_t width = 0, offset = 0; #ifdef _USE_OMP int tid = omp_get_thread_num(); /* check if this thread should process this partition */ Assign* pAss = tr->threadPartAssigns[tid * tr->maxModelsPerThread + m]; if(pAss) { model = pAss->partitionId; width = pAss->width; offset = pAss->offset; } else break; #else model = m; /* number of sites in this partition */ width = (size_t)tr->partitionData[model].width; offset = 0; #endif if(tr->td[0].executeModel[model] && width > 0) { int rateHet = (int)discreteRateCategories(tr->rateHetModel), /* get the number of states in the partition, e.g.: 4 = DNA, 20 = Protein */ states = tr->partitionData[model].states, /* span for single alignment site (in doubles!) */ span = rateHet * states; size_t /* offset for current thread's data in global xVector (in doubles!) */ x_offset = offset * (size_t)span; getVects(tr, &tipX1, &tipX2, &x1_start, &x2_start, &tipCase, model, &x1_gapColumn, &x2_gapColumn, &x1_gap, &x2_gap, offset); double *sumBuffer = tr->partitionData[model].sumBuffer + x_offset; #ifndef _OPTIMIZED_FUNCTIONS assert(!tr->saveMemory); if(tr->rateHetModel == CAT) sumCAT_FLEX(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].tipVector, tipX1, tipX2, width, states); else sumGAMMA_FLEX(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].tipVector, tipX1, tipX2, width, states); #else switch(states) { case 2: #ifdef __MIC_NATIVE assert(0 && "Binary data model is not implemented on Intel MIC"); #else assert(!tr->saveMemory); if(tr->rateHetModel == CAT) sumCAT_BINARY(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].tipVector, tipX1, tipX2, width); else sumGAMMA_BINARY(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].tipVector, tipX1, tipX2, width); #endif break; case 4: /* DNA */ if(tr->rateHetModel == CAT) { if(tr->saveMemory) #ifdef __MIC_NATIVE assert(0 && "Neither CAT model of rate heterogeneity nor memory saving are implemented on Intel MIC"); #else sumCAT_SAVE(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].tipVector, tipX1, tipX2, width, x1_gapColumn, x2_gapColumn, x1_gap, x2_gap); #endif else #ifdef __MIC_NATIVE assert(0 && "CAT model of rate heterogeneity is not implemented on Intel MIC"); #else sumCAT(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].tipVector, tipX1, tipX2, width); #endif } else { if(tr->saveMemory) #ifdef __MIC_NATIVE assert(0 && "Memory saving is not implemented on Intel MIC"); #else sumGAMMA_GAPPED_SAVE(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].tipVector, tipX1, tipX2, width, x1_gapColumn, x2_gapColumn, x1_gap, x2_gap); #endif else #ifdef __MIC_NATIVE sumGAMMA_MIC(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].mic_tipVector, tipX1, tipX2, width); #else sumGAMMA(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].tipVector, tipX1, tipX2, width); #endif } break; case 20: /* proteins */ if(tr->rateHetModel == CAT) { if(tr->saveMemory) #ifdef __MIC_NATIVE assert(0 && "Neither CAT model of rate heterogeneity nor memory saving are implemented on Intel MIC"); #else sumGTRCATPROT_SAVE(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].tipVector, tipX1, tipX2, width, x1_gapColumn, x2_gapColumn, x1_gap, x2_gap); #endif else #ifdef __MIC_NATIVE assert(0 && "CAT model of rate heterogeneity is not implemented on Intel MIC"); #else sumGTRCATPROT(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].tipVector, tipX1, tipX2, width); #endif } else { if(tr->saveMemory) #ifdef __MIC_NATIVE assert(0 && "Memory saving is not implemented on Intel MIC"); #else sumGAMMAPROT_GAPPED_SAVE(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].tipVector, tipX1, tipX2, width, x1_gapColumn, x2_gapColumn, x1_gap, x2_gap); #endif else { if(tr->partitionData[model].protModels == LG4M || tr->partitionData[model].protModels == LG4X) #ifdef __MIC_NATIVE sumGAMMAPROT_LG4_MIC(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].mic_tipVector, tipX1, tipX2, width); #else sumGAMMAPROT_LG4(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].tipVector_LG4, tipX1, tipX2, width); #endif else #ifdef __MIC_NATIVE sumGAMMAPROT_MIC(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].mic_tipVector, tipX1, tipX2, width); #else sumGAMMAPROT(tipCase, sumBuffer, x1_start, x2_start, tr->partitionData[model].tipVector, tipX1, tipX2, width); #endif } } break; default: assert(0); } #endif } } // for model } // omp parallel region } /* this function actually computes the first and second derivatives of the likelihood for a given branch stored in tr->coreLZ[model] Note that in the parallel case coreLZ must always be broadcasted together with the traversal descriptor, at least for optimizing branch lengths */ void execCore(tree *tr, volatile double *_dlnLdlz, volatile double *_d2lnLdlz2) { #ifdef _USE_OMP #pragma omp parallel #endif { int m, model, maxModel, branchIndex; #ifdef _USE_OMP int tid = omp_get_thread_num(), nModels = (tr->numBranches > 1) ? tr->NumberOfModels : 1, p; /* Clear reduction buffers: since in OMP version each thread works only on a subset of partitions, * and their order is arbitrary, it's easier to perform this initialization before the main loop, * just to be on the safe side. */ for(p = 0; p < nModels; p++) { tr->partitionData[p].reductionBuffer[tid] = 0.; tr->partitionData[p].reductionBuffer2[tid] = 0.; } maxModel = tr->maxModelsPerThread; #else maxModel = tr->NumberOfModels; #endif double lz; /* double buffer_dlnLdlz[NUM_BRANCHES], buffer_d2lnLdlz2[NUM_BRANCHES];*/ /* loop over partitions */ for(m = 0; m < maxModel; m++) { size_t width = 0, offset = 0; #ifdef _USE_OMP /* check if this thread should process this partition */ Assign* pAss = tr->threadPartAssigns[tid * tr->maxModelsPerThread + m]; if (pAss) { model = pAss->partitionId; width = GET_PADDED_WIDTH(pAss->width); offset = pAss->offset; } else break; #else model = m; /* number of sites in this partition */ width = (size_t)tr->partitionData[model].width; offset = 0; #endif volatile double *d1acc = (double*) NULL, *d2acc = (double*) NULL; /* figure out if we are optimizing branch lengths individually per partition or jointly across all partitions. If we do this on a per partition basis, we also need to compute and store the per-partition derivatives of the likelihood separately, otherwise not */ if(tr->numBranches > 1) { branchIndex = model; lz = tr->td[0].parameterValues[model]; } else { branchIndex = 0; lz = tr->td[0].parameterValues[0]; } #ifdef _USE_OMP d1acc = &tr->partitionData[branchIndex].reductionBuffer[tid]; d2acc = &tr->partitionData[branchIndex].reductionBuffer2[tid]; #else d1acc = &_dlnLdlz[branchIndex]; d2acc = &_d2lnLdlz2[branchIndex]; /* We need to reset accumulated derivative values in two cases: a) per-partition derivatives or * b) joint derivatives AND we're processing the first partition */ if (branchIndex == model) { *d1acc = 0.0; *d2acc = 0.0; } #endif /* check if we (the present thread for instance) needs to compute something at all for the present partition */ if(tr->td[0].executeModel[model] && width > 0) { int rateHet = (int)discreteRateCategories(tr->rateHetModel), /* get the number of states in the partition, e.g.: 4 = DNA, 20 = Protein */ states = tr->partitionData[model].states, /* span for single alignment site (in doubles!) */ span = rateHet * states, /* offset for current thread's data in global xVector (in doubles!) */ x_offset = offset * span, /* integer weight vector with pattern compression weights */ *wgt = tr->partitionData[model].wgt + offset, /* integer rate category vector (for each pattern, _number_ of PSR category assigned to it, NOT actual rate!) */ *rateCategory = tr->partitionData[model].rateCategory + offset; /* set a pointer to the part of the pre-computed sumBuffer we are going to access */ double *weights = tr->partitionData[model].weights, *sumBuffer = tr->partitionData[model].sumBuffer + x_offset; volatile double dlnLdlz = 0.0, d2lnLdlz2 = 0.0; #ifndef _OPTIMIZED_FUNCTIONS /* compute first and second derivatives with the slow generic functions */ if(tr->rateHetModel == CAT) coreCAT_FLEX(width, tr->partitionData[model].numberOfCategories, sumBuffer, &dlnLdlz, &d2lnLdlz2, wgt, tr->partitionData[model].perSiteRates, tr->partitionData[model].EIGN, rateCategory, lz, states); else coreGAMMA_FLEX(width, sumBuffer, &dlnLdlz, &d2lnLdlz2, tr->partitionData[model].EIGN, tr->partitionData[model].gammaRates, lz, wgt, states); #else switch(states) { case 2: #ifdef __MIC_NATIVE assert(0 && "Binary data model is not implemented on Intel MIC"); #else assert(!tr->saveMemory); if(tr->rateHetModel == CAT) coreGTRCAT_BINARY(width, tr->partitionData[model].numberOfCategories, sumBuffer, &dlnLdlz, &d2lnLdlz2, tr->partitionData[model].perSiteRates, tr->partitionData[model].EIGN, rateCategory, lz, wgt); else coreGTRGAMMA_BINARY(width, sumBuffer, &dlnLdlz, &d2lnLdlz2, tr->partitionData[model].EIGN, tr->partitionData[model].gammaRates, lz, wgt); #endif break; case 4: /* DNA */ if(tr->rateHetModel == CAT) #ifdef __MIC_NATIVE assert(0 && "CAT model of rate heterogeneity is not implemented on Intel MIC"); #else coreGTRCAT(width, tr->partitionData[model].numberOfCategories, sumBuffer, &dlnLdlz, &d2lnLdlz2, wgt, tr->partitionData[model].perSiteRates, tr->partitionData[model].EIGN, rateCategory, lz); #endif else #ifdef __MIC_NATIVE coreGTRGAMMA_MIC(width, sumBuffer, &dlnLdlz, &d2lnLdlz2, tr->partitionData[model].EIGN, tr->partitionData[model].gammaRates, lz, wgt); #else coreGTRGAMMA(width, sumBuffer, &dlnLdlz, &d2lnLdlz2, tr->partitionData[model].EIGN, tr->partitionData[model].gammaRates, lz, wgt); #endif break; case 20: /* proteins */ if(tr->rateHetModel == CAT) #ifdef __MIC_NATIVE assert(0 && "CAT model of rate heterogeneity is not implemented on Intel MIC"); #else coreGTRCATPROT(tr->partitionData[model].EIGN, lz, tr->partitionData[model].numberOfCategories, tr->partitionData[model].perSiteRates, rateCategory, width, wgt, &dlnLdlz, &d2lnLdlz2, sumBuffer); #endif else { if(tr->partitionData[model].protModels == LG4M || tr->partitionData[model].protModels == LG4X) #ifdef __MIC_NATIVE coreGTRGAMMAPROT_LG4_MIC(width, sumBuffer, &dlnLdlz, &d2lnLdlz2, tr->partitionData[model].EIGN_LG4, tr->partitionData[model].gammaRates, lz, wgt, weights); #else { //printf("model %d weights %f %f %f %f\n", model, weights[0], weights[1], weights[2], weights[3]); coreGTRGAMMAPROT_LG4(tr->partitionData[model].gammaRates, tr->partitionData[model].EIGN_LG4, sumBuffer, width, wgt, &dlnLdlz, &d2lnLdlz2, lz, weights); } #endif else #ifdef __MIC_NATIVE coreGTRGAMMAPROT_MIC(width, sumBuffer, &dlnLdlz, &d2lnLdlz2, tr->partitionData[model].EIGN, tr->partitionData[model].gammaRates, lz, wgt); #else coreGTRGAMMAPROT(tr->partitionData[model].gammaRates, tr->partitionData[model].EIGN, sumBuffer, width, wgt, &dlnLdlz, &d2lnLdlz2, lz); #endif } break; default: assert(0); } #endif /* store first and second derivative */ *d1acc += dlnLdlz; *d2acc += d2lnLdlz2; } else { /* set to 0 to make the reduction operation consistent */ if(width == 0 && (tr->numBranches > 1)) { *d1acc = 0.0; *d2acc = 0.0; } if(width > 0 && (tr->numBranches > 1)) { assert(tr->td[0].executeModel[model] == FALSE); /* _dlnLdlz[model] = 0.0; _d2lnLdlz2[model] = 0.0;*/ } } } // for model } // omp parallel section #ifdef _USE_OMP /* perform reduction of 1st and 2nd derivative values */ int model, tid; int nModels = (tr->numBranches > 1) ? tr->NumberOfModels : 1; for(model = 0; model < nModels; model++) { _dlnLdlz[model] = 0.0; _d2lnLdlz2[model] = 0.0; for(tid = 0; tid < tr->nThreads; tid++) { _dlnLdlz[model] += tr->partitionData[model].reductionBuffer[tid]; _d2lnLdlz2[model] += tr->partitionData[model].reductionBuffer2[tid]; } } #endif } /* the function below actually implements the iterative Newton-Raphson procedure. It is particularly messy and hard to read because for the case of per-partition branch length estimates it needs to keep track of whetehr the Newton Raphson procedure has converged for each partition individually. The rational efor doing it like this is also provided in: A. Stamatakis, M. Ott: "Load Balance in the Phylogenetic Likelihood Kernel". Proceedings of ICPP 2009, */ static void topLevelMakenewz(tree *tr, double *z0, int _maxiter, double *result) { double z[NUM_BRANCHES], zprev[NUM_BRANCHES], zstep[NUM_BRANCHES]; double dlnLdlz[NUM_BRANCHES], d2lnLdlz2[NUM_BRANCHES]; int i, maxiter[NUM_BRANCHES], model; boolean firstIteration = TRUE; boolean outerConverged[NUM_BRANCHES]; boolean loopConverged; /* figure out if this is on a per partition basis or jointly across all partitions */ /* initialize loop convergence variables etc. maxiter is the maximum number of NR iterations we are going to do before giving up */ for(i = 0; i < tr->numBranches; i++) { z[i] = z0[i]; maxiter[i] = _maxiter; outerConverged[i] = FALSE; tr->curvatOK[i] = TRUE; } /* nested do while loops of Newton-Raphson */ do { /* check if we ar done for partition i or if we need to adapt the branch length again */ for(i = 0; i < tr->numBranches; i++) { if(outerConverged[i] == FALSE && tr->curvatOK[i] == TRUE) { tr->curvatOK[i] = FALSE; zprev[i] = z[i]; zstep[i] = (1.0 - zmax) * z[i] + zmin; } } for(i = 0; i < tr->numBranches; i++) { /* other case, the outer loop hasn't converged but we are trying to approach the maximum from the wrong side */ if(outerConverged[i] == FALSE && tr->curvatOK[i] == FALSE) { double lz; if (z[i] < zmin) z[i] = zmin; else if (z[i] > zmax) z[i] = zmax; lz = log(z[i]); tr->coreLZ[i] = lz; } } /* set the execution mask */ if(tr->numBranches > 1) { assert(tr->numBranches == tr->NumberOfModels); for(model = 0; model < tr->NumberOfModels; model++) { if(tr->executeModel[model]) tr->executeModel[model] = !tr->curvatOK[model]; } } else { for(model = 0; model < tr->NumberOfModels; model++) tr->executeModel[model] = !tr->curvatOK[0]; } /* store it in traversal descriptor */ storeExecuteMaskInTraversalDescriptor(tr); /* store the new branch length values to be tested in traversal descriptor */ storeValuesInTraversalDescriptor(tr, &(tr->coreLZ[0])); /* sequential part, if this is the first newton-raphson implementation, do the precomputations as well, otherwise just execute the computation of the derivatives */ if(firstIteration) { makenewzIterative(tr); firstIteration = FALSE; } execCore(tr, dlnLdlz, d2lnLdlz2); { double *send = (double *)malloc(sizeof(double) * tr->numBranches * 2), *recv = (double *)malloc(sizeof(double) * tr->numBranches * 2); memcpy(&send[0], dlnLdlz, sizeof(double) * tr->numBranches); memcpy(&send[tr->numBranches], d2lnLdlz2, sizeof(double) * tr->numBranches); #ifdef _USE_ALLREDUCE /* the MPI_Allreduce implementation is apparently sometimes not deterministic */ MPI_Allreduce(send, recv, tr->numBranches * 2, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); #else MPI_Reduce(send, recv, tr->numBranches * 2, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Bcast(recv, tr->numBranches * 2, MPI_DOUBLE, 0, MPI_COMM_WORLD); #endif memcpy(dlnLdlz, &recv[0], sizeof(double) * tr->numBranches); memcpy(d2lnLdlz2, &recv[tr->numBranches], sizeof(double) * tr->numBranches); free(send); free(recv); } /* do a NR step, if we are on the correct side of the maximum that's okay, otherwise shorten branch */ for(i = 0; i < tr->numBranches; i++) { if(outerConverged[i] == FALSE && tr->curvatOK[i] == FALSE) { if ((d2lnLdlz2[i] >= 0.0) && (z[i] < zmax)) zprev[i] = z[i] = 0.37 * z[i] + 0.63; /* Bad curvature, shorten branch */ else tr->curvatOK[i] = TRUE; } } /* do the standard NR step to obrain the next value, depending on the state for each partition */ for(i = 0; i < tr->numBranches; i++) { if(tr->curvatOK[i] == TRUE && outerConverged[i] == FALSE) { if (d2lnLdlz2[i] < 0.0) { double tantmp = -dlnLdlz[i] / d2lnLdlz2[i]; if (tantmp < 100) { z[i] *= EXP(tantmp); if (z[i] < zmin) z[i] = zmin; if (z[i] > 0.25 * zprev[i] + 0.75) z[i] = 0.25 * zprev[i] + 0.75; } else z[i] = 0.25 * zprev[i] + 0.75; } if (z[i] > zmax) z[i] = zmax; /* decrement the maximum number of itarations */ maxiter[i] = maxiter[i] - 1; /* check if the outer loop has converged */ //old code below commented out, integrated new PRELIMINARY BUG FIX ! //this needs further work at some point! /* if(maxiter[i] > 0 && (ABS(z[i] - zprev[i]) > zstep[i])) outerConverged[i] = FALSE; else outerConverged[i] = TRUE; */ if((ABS(z[i] - zprev[i]) > zstep[i])) { /* We should make a more informed decision here, based on the log like improvement */ if(maxiter[i] < -20) { z[i] = z0[i]; outerConverged[i] = TRUE; } else outerConverged[i] = FALSE; } else outerConverged[i] = TRUE; } } /* check if the loop has converged for all partitions */ loopConverged = TRUE; for(i = 0; i < tr->numBranches; i++) loopConverged = loopConverged && outerConverged[i]; } while (!loopConverged); /* reset partition execution mask */ for(model = 0; model < tr->NumberOfModels; model++) tr->executeModel[model] = TRUE; /* copy the new branches in the result array of branches. if we don't do a per partition estimate of branches this will only set result[0] */ for(i = 0; i < tr->numBranches; i++) result[i] = z[i]; } /* function called from RAxML to optimize a given branch with current branch lengths z0 between nodes p and q. The new branch lengths will be stored in result */ void makenewzGeneric(tree *tr, nodeptr p, nodeptr q, double *z0, int maxiter, double *result, boolean mask) { int i; /* the first entry of the traversal descriptor stores the node pair that defines the branch */ tr->td[0].ti[0].pNumber = p->number; tr->td[0].ti[0].qNumber = q->number; for(i = 0; i < tr->numBranches; i++) { tr->td[0].ti[0].qz[i] = z0[i]; if(mask) { if(tr->partitionConverged[i]) tr->executeModel[i] = FALSE; else tr->executeModel[i] = TRUE; } else assert(tr->executeModel[i]); } /* compute the traversal descriptor of the likelihood vectors that need to be re-computed first in makenewzIterative */ tr->td[0].count = 1; if(!p->x) computeTraversalInfo(p, &(tr->td[0].ti[0]), &(tr->td[0].count), tr->mxtips, tr->numBranches, TRUE); if(!q->x) computeTraversalInfo(q, &(tr->td[0].ti[0]), &(tr->td[0].count), tr->mxtips, tr->numBranches, TRUE); /* call the Newton-Raphson procedure */ topLevelMakenewz(tr, z0, maxiter, result); /* fix eceuteModel this seems to be a bit redundant with topLevelMakenewz */ for(i = 0; i < tr->numBranches; i++) tr->executeModel[i] = TRUE; } /* below are, once again the optimized functions */ #ifdef _OPTIMIZED_FUNCTIONS /**** binary ***/ static void coreGTRCAT_BINARY(int upper, int numberOfCategories, double *sum, volatile double *d1, volatile double *d2, double *rptr, double *EIGN, int *cptr, double lz, int *wgt) { int i; double *d, *d_start, tmp_0, inv_Li, dlnLidlz, d2lnLidlz2, dlnLdlz = 0.0, d2lnLdlz2 = 0.0; double e[2]; double dd1; /*e[0] = EIGN[0]; e[1] = EIGN[0] * EIGN[0];*/ e[0] = EIGN[1]; e[1] = EIGN[1] * EIGN[1]; d = d_start = (double *)malloc((size_t)numberOfCategories * sizeof(double)); dd1 = e[0] * lz; for(i = 0; i < numberOfCategories; i++) d[i] = exp(dd1 * rptr[i]); for (i = 0; i < upper; i++) { double r = rptr[cptr[i]], wr1 = r * wgt[i], wr2 = r * r * wgt[i]; d = &d_start[cptr[i]]; inv_Li = sum[2 * i]; inv_Li += (tmp_0 = d[0] * sum[2 * i + 1]); inv_Li = 1.0/fabs(inv_Li); dlnLidlz = tmp_0 * e[0]; d2lnLidlz2 = tmp_0 * e[1]; dlnLidlz *= inv_Li; d2lnLidlz2 *= inv_Li; dlnLdlz += wr1 * dlnLidlz; d2lnLdlz2 += wr2 * (d2lnLidlz2 - dlnLidlz * dlnLidlz); } *d1 = dlnLdlz; *d2 = d2lnLdlz2; free(d_start); } static void coreGTRGAMMA_BINARY(const int upper, double *sumtable, volatile double *d1, volatile double *d2, double *EIGN, double *gammaRates, double lz, int *wrptr) { double dlnLdlz = 0.0, d2lnLdlz2 = 0.0, ki, kisqr, inv_Li, dlnLidlz, d2lnLidlz2, *sum, diagptable0[8] __attribute__ ((aligned (BYTE_ALIGNMENT))), diagptable1[8] __attribute__ ((aligned (BYTE_ALIGNMENT))), diagptable2[8] __attribute__ ((aligned (BYTE_ALIGNMENT))); int i, j; for(i = 0; i < 4; i++) { ki = gammaRates[i]; kisqr = ki * ki; diagptable0[i * 2] = 1.0; diagptable1[i * 2] = 0.0; diagptable2[i * 2] = 0.0; diagptable0[i * 2 + 1] = exp(EIGN[1] * ki * lz); diagptable1[i * 2 + 1] = EIGN[1] * ki; diagptable2[i * 2 + 1] = EIGN[1] * EIGN[1] * kisqr; } for (i = 0; i < upper; i++) { __m128d a0 = _mm_setzero_pd(); __m128d a1 = _mm_setzero_pd(); __m128d a2 = _mm_setzero_pd(); sum = &sumtable[i * 8]; for(j = 0; j < 4; j++) { double *d0 = &diagptable0[j * 2], *d1 = &diagptable1[j * 2], *d2 = &diagptable2[j * 2]; __m128d tmpv = _mm_mul_pd(_mm_load_pd(d0), _mm_load_pd(&sum[j * 2])); a0 = _mm_add_pd(a0, tmpv); a1 = _mm_add_pd(a1, _mm_mul_pd(tmpv, _mm_load_pd(d1))); a2 = _mm_add_pd(a2, _mm_mul_pd(tmpv, _mm_load_pd(d2))); } a0 = _mm_hadd_pd(a0, a0); a1 = _mm_hadd_pd(a1, a1); a2 = _mm_hadd_pd(a2, a2); _mm_storel_pd(&inv_Li, a0); _mm_storel_pd(&dlnLidlz, a1); _mm_storel_pd(&d2lnLidlz2, a2); inv_Li = 1.0 / fabs(inv_Li); dlnLidlz *= inv_Li; d2lnLidlz2 *= inv_Li; dlnLdlz += wrptr[i] * dlnLidlz; d2lnLdlz2 += wrptr[i] * (d2lnLidlz2 - dlnLidlz * dlnLidlz); } *d1 = dlnLdlz; *d2 = d2lnLdlz2; } static void sumGAMMA_BINARY(int tipCase, double *sumtable, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n) { double *x1, *x2, *sum; int i, j; /* C-OPT once again switch over possible configurations at inner node */ switch(tipCase) { case TIP_TIP: /* C-OPT main for loop overt alignment length */ for (i = 0; i < n; i++) { x1 = &(tipVector[2 * tipX1[i]]); x2 = &(tipVector[2 * tipX2[i]]); sum = &sumtable[i * 8]; for(j = 0; j < 4; j++) _mm_store_pd( &sum[j*2], _mm_mul_pd( _mm_load_pd( &x1[0] ), _mm_load_pd( &x2[0] ))); } break; case TIP_INNER: for (i = 0; i < n; i++) { x1 = &(tipVector[2 * tipX1[i]]); x2 = &x2_start[8 * i]; sum = &sumtable[8 * i]; for(j = 0; j < 4; j++) _mm_store_pd( &sum[j*2], _mm_mul_pd( _mm_load_pd( &x1[0] ), _mm_load_pd( &x2[j * 2] ))); } break; case INNER_INNER: for (i = 0; i < n; i++) { x1 = &x1_start[8 * i]; x2 = &x2_start[8 * i]; sum = &sumtable[8 * i]; for(j = 0; j < 4; j++) _mm_store_pd( &sum[j*2], _mm_mul_pd( _mm_load_pd( &x1[j * 2] ), _mm_load_pd( &x2[j * 2] ))); } break; default: assert(0); } } static void sumCAT_BINARY(int tipCase, double *sum, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n) { int i; double *x1, *x2; switch(tipCase) { case TIP_TIP: for (i = 0; i < n; i++) { x1 = &(tipVector[2 * tipX1[i]]); x2 = &(tipVector[2 * tipX2[i]]); _mm_store_pd(&sum[i * 2], _mm_mul_pd( _mm_load_pd(x1), _mm_load_pd(x2))); } break; case TIP_INNER: for (i = 0; i < n; i++) { x1 = &(tipVector[2 * tipX1[i]]); x2 = &x2_start[2 * i]; _mm_store_pd(&sum[i * 2], _mm_mul_pd( _mm_load_pd(x1), _mm_load_pd(x2))); } break; case INNER_INNER: for (i = 0; i < n; i++) { x1 = &x1_start[2 * i]; x2 = &x2_start[2 * i]; _mm_store_pd(&sum[i * 2], _mm_mul_pd( _mm_load_pd(x1), _mm_load_pd(x2))); } break; default: assert(0); } } /*** binary end ****/ static void sumCAT_SAVE(int tipCase, double *sum, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap) { int i; double *x1, *x2, *x1_ptr = x1_start, *x2_ptr = x2_start; switch(tipCase) { case TIP_TIP: for (i = 0; i < n; i++) { x1 = &(tipVector[4 * tipX1[i]]); x2 = &(tipVector[4 * tipX2[i]]); _mm_store_pd( &sum[i*4 + 0], _mm_mul_pd( _mm_load_pd( &x1[0] ), _mm_load_pd( &x2[0] ))); _mm_store_pd( &sum[i*4 + 2], _mm_mul_pd( _mm_load_pd( &x1[2] ), _mm_load_pd( &x2[2] ))); } break; case TIP_INNER: for (i = 0; i < n; i++) { x1 = &(tipVector[4 * tipX1[i]]); if(isGap(x2_gap, i)) x2 = x2_gapColumn; else { x2 = x2_ptr; x2_ptr += 4; } _mm_store_pd( &sum[i*4 + 0], _mm_mul_pd( _mm_load_pd( &x1[0] ), _mm_load_pd( &x2[0] ))); _mm_store_pd( &sum[i*4 + 2], _mm_mul_pd( _mm_load_pd( &x1[2] ), _mm_load_pd( &x2[2] ))); } break; case INNER_INNER: for (i = 0; i < n; i++) { if(isGap(x1_gap, i)) x1 = x1_gapColumn; else { x1 = x1_ptr; x1_ptr += 4; } if(isGap(x2_gap, i)) x2 = x2_gapColumn; else { x2 = x2_ptr; x2_ptr += 4; } _mm_store_pd( &sum[i*4 + 0], _mm_mul_pd( _mm_load_pd( &x1[0] ), _mm_load_pd( &x2[0] ))); _mm_store_pd( &sum[i*4 + 2], _mm_mul_pd( _mm_load_pd( &x1[2] ), _mm_load_pd( &x2[2] ))); } break; default: assert(0); } } static void sumGAMMA_GAPPED_SAVE(int tipCase, double *sumtable, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap) { double *x1, *x2, *sum, *x1_ptr = x1_start, *x2_ptr = x2_start; int i, j, k; switch(tipCase) { case TIP_TIP: for (i = 0; i < n; i++) { x1 = &(tipVector[4 * tipX1[i]]); x2 = &(tipVector[4 * tipX2[i]]); sum = &sumtable[i * 16]; for(j = 0; j < 4; j++) for(k = 0; k < 4; k+=2) _mm_store_pd( &sum[j*4 + k], _mm_mul_pd( _mm_load_pd( &x1[k] ), _mm_load_pd( &x2[k] ))); } break; case TIP_INNER: for (i = 0; i < n; i++) { x1 = &(tipVector[4 * tipX1[i]]); if(x2_gap[i / 32] & mask32[i % 32]) x2 = x2_gapColumn; else { x2 = x2_ptr; x2_ptr += 16; } sum = &sumtable[16 * i]; for(j = 0; j < 4; j++) for(k = 0; k < 4; k+=2) _mm_store_pd( &sum[j*4 + k], _mm_mul_pd( _mm_load_pd( &x1[k] ), _mm_load_pd( &x2[j * 4 + k] ))); } break; case INNER_INNER: for (i = 0; i < n; i++) { if(x1_gap[i / 32] & mask32[i % 32]) x1 = x1_gapColumn; else { x1 = x1_ptr; x1_ptr += 16; } if(x2_gap[i / 32] & mask32[i % 32]) x2 = x2_gapColumn; else { x2 = x2_ptr; x2_ptr += 16; } sum = &sumtable[16 * i]; for(j = 0; j < 4; j++) for(k = 0; k < 4; k+=2) _mm_store_pd( &sum[j*4 + k], _mm_mul_pd( _mm_load_pd( &x1[j * 4 + k] ), _mm_load_pd( &x2[j * 4 + k] ))); } break; default: assert(0); } } static void sumGAMMA(int tipCase, double *sumtable, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n) { double *x1, *x2, *sum; int i, j, k; /* C-OPT once again switch over possible configurations at inner node */ switch(tipCase) { case TIP_TIP: /* C-OPT main for loop overt alignment length */ for (i = 0; i < n; i++) { x1 = &(tipVector[4 * tipX1[i]]); x2 = &(tipVector[4 * tipX2[i]]); sum = &sumtable[i * 16]; for(j = 0; j < 4; j++) for(k = 0; k < 4; k+=2) _mm_store_pd( &sum[j*4 + k], _mm_mul_pd( _mm_load_pd( &x1[k] ), _mm_load_pd( &x2[k] ))); } break; case TIP_INNER: for (i = 0; i < n; i++) { x1 = &(tipVector[4 * tipX1[i]]); x2 = &x2_start[16 * i]; sum = &sumtable[16 * i]; for(j = 0; j < 4; j++) for(k = 0; k < 4; k+=2) _mm_store_pd( &sum[j*4 + k], _mm_mul_pd( _mm_load_pd( &x1[k] ), _mm_load_pd( &x2[j * 4 + k] ))); } break; case INNER_INNER: for (i = 0; i < n; i++) { x1 = &x1_start[16 * i]; x2 = &x2_start[16 * i]; sum = &sumtable[16 * i]; for(j = 0; j < 4; j++) for(k = 0; k < 4; k+=2) _mm_store_pd( &sum[j*4 + k], _mm_mul_pd( _mm_load_pd( &x1[j * 4 + k] ), _mm_load_pd( &x2[j * 4 + k] ))); } break; default: assert(0); } } static void sumCAT(int tipCase, double *sum, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n) { int i; double *x1, *x2; switch(tipCase) { case TIP_TIP: for (i = 0; i < n; i++) { x1 = &(tipVector[4 * tipX1[i]]); x2 = &(tipVector[4 * tipX2[i]]); _mm_store_pd( &sum[i*4 + 0], _mm_mul_pd( _mm_load_pd( &x1[0] ), _mm_load_pd( &x2[0] ))); _mm_store_pd( &sum[i*4 + 2], _mm_mul_pd( _mm_load_pd( &x1[2] ), _mm_load_pd( &x2[2] ))); } break; case TIP_INNER: for (i = 0; i < n; i++) { x1 = &(tipVector[4 * tipX1[i]]); x2 = &x2_start[4 * i]; _mm_store_pd( &sum[i*4 + 0], _mm_mul_pd( _mm_load_pd( &x1[0] ), _mm_load_pd( &x2[0] ))); _mm_store_pd( &sum[i*4 + 2], _mm_mul_pd( _mm_load_pd( &x1[2] ), _mm_load_pd( &x2[2] ))); } break; case INNER_INNER: for (i = 0; i < n; i++) { x1 = &x1_start[4 * i]; x2 = &x2_start[4 * i]; _mm_store_pd( &sum[i*4 + 0], _mm_mul_pd( _mm_load_pd( &x1[0] ), _mm_load_pd( &x2[0] ))); _mm_store_pd( &sum[i*4 + 2], _mm_mul_pd( _mm_load_pd( &x1[2] ), _mm_load_pd( &x2[2] ))); } break; default: assert(0); } } static void sumGAMMAPROT_GAPPED_SAVE(int tipCase, double *sumtable, double *x1, double *x2, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap) { int i, l, k; double *left, *right, *sum, *x1_ptr = x1, *x2_ptr = x2, *x1v, *x2v; switch(tipCase) { case TIP_TIP: for(i = 0; i < n; i++) { left = &(tipVector[20 * tipX1[i]]); right = &(tipVector[20 * tipX2[i]]); for(l = 0; l < 4; l++) { sum = &sumtable[i * 80 + l * 20]; for(k = 0; k < 20; k+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[k]), _mm_load_pd(&right[k])); _mm_store_pd(&sum[k], sumv); } } } break; case TIP_INNER: for(i = 0; i < n; i++) { left = &(tipVector[20 * tipX1[i]]); if(x2_gap[i / 32] & mask32[i % 32]) x2v = x2_gapColumn; else { x2v = x2_ptr; x2_ptr += 80; } for(l = 0; l < 4; l++) { right = &(x2v[l * 20]); sum = &sumtable[i * 80 + l * 20]; for(k = 0; k < 20; k+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[k]), _mm_load_pd(&right[k])); _mm_store_pd(&sum[k], sumv); } } } break; case INNER_INNER: for(i = 0; i < n; i++) { if(x1_gap[i / 32] & mask32[i % 32]) x1v = x1_gapColumn; else { x1v = x1_ptr; x1_ptr += 80; } if(x2_gap[i / 32] & mask32[i % 32]) x2v = x2_gapColumn; else { x2v = x2_ptr; x2_ptr += 80; } for(l = 0; l < 4; l++) { left = &(x1v[l * 20]); right = &(x2v[l * 20]); sum = &(sumtable[i * 80 + l * 20]); for(k = 0; k < 20; k+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[k]), _mm_load_pd(&right[k])); _mm_store_pd(&sum[k], sumv); } } } break; default: assert(0); } } static void sumGAMMAPROT_LG4(int tipCase, double *sumtable, double *x1, double *x2, double *tipVector[4], unsigned char *tipX1, unsigned char *tipX2, int n) { int i, l, k; double *left, *right, *sum; switch(tipCase) { case TIP_TIP: for(i = 0; i < n; i++) { for(l = 0; l < 4; l++) { left = &(tipVector[l][20 * tipX1[i]]); right = &(tipVector[l][20 * tipX2[i]]); sum = &sumtable[i * 80 + l * 20]; #ifdef __SIM_SSE3 for(k = 0; k < 20; k+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[k]), _mm_load_pd(&right[k])); _mm_store_pd(&sum[k], sumv); } #else for(k = 0; k < 20; k++) sum[k] = left[k] * right[k]; #endif } } break; case TIP_INNER: for(i = 0; i < n; i++) { for(l = 0; l < 4; l++) { left = &(tipVector[l][20 * tipX1[i]]); right = &(x2[80 * i + l * 20]); sum = &sumtable[i * 80 + l * 20]; #ifdef __SIM_SSE3 for(k = 0; k < 20; k+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[k]), _mm_load_pd(&right[k])); _mm_store_pd(&sum[k], sumv); } #else for(k = 0; k < 20; k++) sum[k] = left[k] * right[k]; #endif } } break; case INNER_INNER: for(i = 0; i < n; i++) { for(l = 0; l < 4; l++) { left = &(x1[80 * i + l * 20]); right = &(x2[80 * i + l * 20]); sum = &(sumtable[i * 80 + l * 20]); #ifdef __SIM_SSE3 for(k = 0; k < 20; k+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[k]), _mm_load_pd(&right[k])); _mm_store_pd(&sum[k], sumv); } #else for(k = 0; k < 20; k++) sum[k] = left[k] * right[k]; #endif } } break; default: assert(0); } } static void sumGAMMAPROT(int tipCase, double *sumtable, double *x1, double *x2, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n) { int i, l, k; double *left, *right, *sum; switch(tipCase) { case TIP_TIP: for(i = 0; i < n; i++) { left = &(tipVector[20 * tipX1[i]]); right = &(tipVector[20 * tipX2[i]]); for(l = 0; l < 4; l++) { sum = &sumtable[i * 80 + l * 20]; for(k = 0; k < 20; k+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[k]), _mm_load_pd(&right[k])); _mm_store_pd(&sum[k], sumv); } } } break; case TIP_INNER: for(i = 0; i < n; i++) { left = &(tipVector[20 * tipX1[i]]); for(l = 0; l < 4; l++) { right = &(x2[80 * i + l * 20]); sum = &sumtable[i * 80 + l * 20]; for(k = 0; k < 20; k+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[k]), _mm_load_pd(&right[k])); _mm_store_pd(&sum[k], sumv); } } } break; case INNER_INNER: for(i = 0; i < n; i++) { for(l = 0; l < 4; l++) { left = &(x1[80 * i + l * 20]); right = &(x2[80 * i + l * 20]); sum = &(sumtable[i * 80 + l * 20]); for(k = 0; k < 20; k+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[k]), _mm_load_pd(&right[k])); _mm_store_pd(&sum[k], sumv); } } } break; default: assert(0); } } static void sumGTRCATPROT(int tipCase, double *sumtable, double *x1, double *x2, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n) { int i, l; double *sum, *left, *right; switch(tipCase) { case TIP_TIP: for (i = 0; i < n; i++) { left = &(tipVector[20 * tipX1[i]]); right = &(tipVector[20 * tipX2[i]]); sum = &sumtable[20 * i]; for(l = 0; l < 20; l+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[l]), _mm_load_pd(&right[l])); _mm_store_pd(&sum[l], sumv); } } break; case TIP_INNER: for (i = 0; i < n; i++) { left = &(tipVector[20 * tipX1[i]]); right = &x2[20 * i]; sum = &sumtable[20 * i]; for(l = 0; l < 20; l+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[l]), _mm_load_pd(&right[l])); _mm_store_pd(&sum[l], sumv); } } break; case INNER_INNER: for (i = 0; i < n; i++) { left = &x1[20 * i]; right = &x2[20 * i]; sum = &sumtable[20 * i]; for(l = 0; l < 20; l+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[l]), _mm_load_pd(&right[l])); _mm_store_pd(&sum[l], sumv); } } break; default: assert(0); } } static void sumGTRCATPROT_SAVE(int tipCase, double *sumtable, double *x1, double *x2, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *x1_gapColumn, double *x2_gapColumn, unsigned int *x1_gap, unsigned int *x2_gap) { int i, l; double *sum, *left, *right, *left_ptr = x1, *right_ptr = x2; switch(tipCase) { case TIP_TIP: for (i = 0; i < n; i++) { left = &(tipVector[20 * tipX1[i]]); right = &(tipVector[20 * tipX2[i]]); sum = &sumtable[20 * i]; for(l = 0; l < 20; l+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[l]), _mm_load_pd(&right[l])); _mm_store_pd(&sum[l], sumv); } } break; case TIP_INNER: for (i = 0; i < n; i++) { left = &(tipVector[20 * tipX1[i]]); if(isGap(x2_gap, i)) right = x2_gapColumn; else { right = right_ptr; right_ptr += 20; } sum = &sumtable[20 * i]; for(l = 0; l < 20; l+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[l]), _mm_load_pd(&right[l])); _mm_store_pd(&sum[l], sumv); } } break; case INNER_INNER: for (i = 0; i < n; i++) { if(isGap(x1_gap, i)) left = x1_gapColumn; else { left = left_ptr; left_ptr += 20; } if(isGap(x2_gap, i)) right = x2_gapColumn; else { right = right_ptr; right_ptr += 20; } sum = &sumtable[20 * i]; for(l = 0; l < 20; l+=2) { __m128d sumv = _mm_mul_pd(_mm_load_pd(&left[l]), _mm_load_pd(&right[l])); _mm_store_pd(&sum[l], sumv); } } break; default: assert(0); } } static void coreGTRGAMMA(const int upper, double *sumtable, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double *EIGN, double *gammaRates, double lz, int *wgt) { double dlnLdlz = 0.0, d2lnLdlz2 = 0.0, ki, kisqr, inv_Li, dlnLidlz, d2lnLidlz2, *sum, diagptable0[16] __attribute__ ((aligned (BYTE_ALIGNMENT))), diagptable1[16] __attribute__ ((aligned (BYTE_ALIGNMENT))), diagptable2[16] __attribute__ ((aligned (BYTE_ALIGNMENT))); int i, j, l; for(i = 0; i < 4; i++) { ki = gammaRates[i]; kisqr = ki * ki; diagptable0[i * 4] = 1.0; diagptable1[i * 4] = 0.0; diagptable2[i * 4] = 0.0; for(l = 1; l < 4; l++) { diagptable0[i * 4 + l] = EXP(EIGN[l] * ki * lz); diagptable1[i * 4 + l] = EIGN[l] * ki; diagptable2[i * 4 + l] = EIGN[l] * EIGN[l] * kisqr; } } for (i = 0; i < upper; i++) { __m128d a0 = _mm_setzero_pd(); __m128d a1 = _mm_setzero_pd(); __m128d a2 = _mm_setzero_pd(); sum = &sumtable[i * 16]; for(j = 0; j < 4; j++) { double *d0 = &diagptable0[j * 4], *d1 = &diagptable1[j * 4], *d2 = &diagptable2[j * 4]; for(l = 0; l < 4; l+=2) { __m128d tmpv = _mm_mul_pd(_mm_load_pd(&d0[l]), _mm_load_pd(&sum[j * 4 + l])); a0 = _mm_add_pd(a0, tmpv); a1 = _mm_add_pd(a1, _mm_mul_pd(tmpv, _mm_load_pd(&d1[l]))); a2 = _mm_add_pd(a2, _mm_mul_pd(tmpv, _mm_load_pd(&d2[l]))); } } a0 = _mm_hadd_pd(a0, a0); a1 = _mm_hadd_pd(a1, a1); a2 = _mm_hadd_pd(a2, a2); _mm_storel_pd(&inv_Li, a0); _mm_storel_pd(&dlnLidlz, a1); _mm_storel_pd(&d2lnLidlz2, a2); inv_Li = 1.0 / FABS(inv_Li); dlnLidlz *= inv_Li; d2lnLidlz2 *= inv_Li; dlnLdlz += wgt[i] * dlnLidlz; d2lnLdlz2 += wgt[i] * (d2lnLidlz2 - dlnLidlz * dlnLidlz); } *ext_dlnLdlz = dlnLdlz; *ext_d2lnLdlz2 = d2lnLdlz2; } static void coreGTRCAT(int upper, int numberOfCategories, double *sum, volatile double *d1, volatile double *d2, int *wgt, double *rptr, double *EIGN, int *cptr, double lz) { int i; double *d, *d_start, inv_Li, dlnLidlz, d2lnLidlz2, dlnLdlz = 0.0, d2lnLdlz2 = 0.0; double e1[4] __attribute__ ((aligned (BYTE_ALIGNMENT))); double e2[4] __attribute__ ((aligned (BYTE_ALIGNMENT))); double dd1, dd2, dd3; __m128d e1v[2], e2v[2]; e1[0] = 0.0; e2[0] = 0.0; e1[1] = EIGN[1]; e2[1] = EIGN[1] * EIGN[1]; e1[2] = EIGN[2]; e2[2] = EIGN[2] * EIGN[2]; e1[3] = EIGN[3]; e2[3] = EIGN[3] * EIGN[3]; e1v[0]= _mm_load_pd(&e1[0]); e1v[1]= _mm_load_pd(&e1[2]); e2v[0]= _mm_load_pd(&e2[0]); e2v[1]= _mm_load_pd(&e2[2]); d = d_start = (double *)malloc_aligned(numberOfCategories * 4 * sizeof(double)); dd1 = EIGN[1] * lz; dd2 = EIGN[2] * lz; dd3 = EIGN[3] * lz; for(i = 0; i < numberOfCategories; i++) { d[i * 4 + 0] = 1.0; d[i * 4 + 1] = EXP(dd1 * rptr[i]); d[i * 4 + 2] = EXP(dd2 * rptr[i]); d[i * 4 + 3] = EXP(dd3 * rptr[i]); } for (i = 0; i < upper; i++) { double *s = &sum[4 * i]; double r = rptr[cptr[i]], wr1 = r * wgt[i], wr2 = r * r * wgt[i]; d = &d_start[4 * cptr[i]]; __m128d tmp_0v =_mm_mul_pd(_mm_load_pd(&d[0]),_mm_load_pd(&s[0])); __m128d tmp_1v =_mm_mul_pd(_mm_load_pd(&d[2]),_mm_load_pd(&s[2])); __m128d inv_Liv = _mm_add_pd(tmp_0v, tmp_1v); __m128d dlnLidlzv = _mm_add_pd(_mm_mul_pd(tmp_0v, e1v[0]), _mm_mul_pd(tmp_1v, e1v[1])); __m128d d2lnLidlz2v = _mm_add_pd(_mm_mul_pd(tmp_0v, e2v[0]), _mm_mul_pd(tmp_1v, e2v[1])); inv_Liv = _mm_hadd_pd(inv_Liv, inv_Liv); dlnLidlzv = _mm_hadd_pd(dlnLidlzv, dlnLidlzv); d2lnLidlz2v = _mm_hadd_pd(d2lnLidlz2v, d2lnLidlz2v); _mm_storel_pd(&inv_Li, inv_Liv); _mm_storel_pd(&dlnLidlz, dlnLidlzv); _mm_storel_pd(&d2lnLidlz2, d2lnLidlz2v); inv_Li = 1.0/FABS(inv_Li); dlnLidlz *= inv_Li; d2lnLidlz2 *= inv_Li; dlnLdlz += wr1 * dlnLidlz; d2lnLdlz2 += wr2 * (d2lnLidlz2 - dlnLidlz * dlnLidlz); } *d1 = dlnLdlz; *d2 = d2lnLdlz2; free(d_start); } static void coreGTRGAMMAPROT_LG4(double *gammaRates, double *EIGN[4], double *sumtable, int upper, int *wrptr, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double lz, double *weights) { double *sum, diagptable0[80] __attribute__ ((aligned (BYTE_ALIGNMENT))), diagptable1[80] __attribute__ ((aligned (BYTE_ALIGNMENT))), diagptable2[80] __attribute__ ((aligned (BYTE_ALIGNMENT))); int i, j, l; double dlnLdlz = 0; double d2lnLdlz2 = 0; double ki, kisqr; for(i = 0; i < 4; i++) { ki = gammaRates[i]; kisqr = ki * ki; diagptable0[i * 20] = 1.0; diagptable1[i * 20] = 0.0; diagptable2[i * 20] = 0.0; for(l = 1; l < 20; l++) { diagptable0[i * 20 + l] = EXP(EIGN[i][l] * ki * lz); diagptable1[i * 20 + l] = EIGN[i][l] * ki; diagptable2[i * 20 + l] = EIGN[i][l] * EIGN[i][l] * kisqr; } } for (i = 0; i < upper; i++) { double inv_Li = 0.0, dlnLidlz = 0.0, d2lnLidlz2 = 0.0; sum = &sumtable[i * 80]; for(j = 0; j < 4; j++) { double l0, l1, l2, *d0 = &diagptable0[j * 20], *d1 = &diagptable1[j * 20], *d2 = &diagptable2[j * 20]; __m128d a0 = _mm_setzero_pd(), a1 = _mm_setzero_pd(), a2 = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) { __m128d tmpv = _mm_mul_pd(_mm_load_pd(&d0[l]), _mm_load_pd(&sum[j * 20 +l])); a0 = _mm_add_pd(a0, tmpv); a1 = _mm_add_pd(a1, _mm_mul_pd(tmpv, _mm_load_pd(&d1[l]))); a2 = _mm_add_pd(a2, _mm_mul_pd(tmpv, _mm_load_pd(&d2[l]))); } a0 = _mm_hadd_pd(a0, a0); a1 = _mm_hadd_pd(a1, a1); a2 = _mm_hadd_pd(a2, a2); _mm_storel_pd(&l0, a0); _mm_storel_pd(&l1, a1); _mm_storel_pd(&l2, a2); inv_Li += weights[j] * l0; dlnLidlz += weights[j] * l1; d2lnLidlz2 += weights[j] * l2; } inv_Li = 1.0 / FABS(inv_Li); dlnLidlz *= inv_Li; d2lnLidlz2 *= inv_Li; dlnLdlz += wrptr[i] * dlnLidlz; d2lnLdlz2 += wrptr[i] * (d2lnLidlz2 - dlnLidlz * dlnLidlz); } *ext_dlnLdlz = dlnLdlz; *ext_d2lnLdlz2 = d2lnLdlz2; } static void coreGTRGAMMAPROT(double *gammaRates, double *EIGN, double *sumtable, int upper, int *wgt, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double lz) { double *sum, diagptable0[80] __attribute__ ((aligned (BYTE_ALIGNMENT))), diagptable1[80] __attribute__ ((aligned (BYTE_ALIGNMENT))), diagptable2[80] __attribute__ ((aligned (BYTE_ALIGNMENT))); int i, j, l; double dlnLdlz = 0; double d2lnLdlz2 = 0; double ki, kisqr; double inv_Li, dlnLidlz, d2lnLidlz2; for(i = 0; i < 4; i++) { ki = gammaRates[i]; kisqr = ki * ki; diagptable0[i * 20] = 1.0; diagptable1[i * 20] = 0.0; diagptable2[i * 20] = 0.0; for(l = 1; l < 20; l++) { diagptable0[i * 20 + l] = EXP(EIGN[l] * ki * lz); diagptable1[i * 20 + l] = EIGN[l] * ki; diagptable2[i * 20 + l] = EIGN[l] * EIGN[l] * kisqr; } } for (i = 0; i < upper; i++) { __m128d a0 = _mm_setzero_pd(); __m128d a1 = _mm_setzero_pd(); __m128d a2 = _mm_setzero_pd(); sum = &sumtable[i * 80]; for(j = 0; j < 4; j++) { double *d0 = &diagptable0[j * 20], *d1 = &diagptable1[j * 20], *d2 = &diagptable2[j * 20]; for(l = 0; l < 20; l+=2) { __m128d tmpv = _mm_mul_pd(_mm_load_pd(&d0[l]), _mm_load_pd(&sum[j * 20 +l])); a0 = _mm_add_pd(a0, tmpv); a1 = _mm_add_pd(a1, _mm_mul_pd(tmpv, _mm_load_pd(&d1[l]))); a2 = _mm_add_pd(a2, _mm_mul_pd(tmpv, _mm_load_pd(&d2[l]))); } } a0 = _mm_hadd_pd(a0, a0); a1 = _mm_hadd_pd(a1, a1); a2 = _mm_hadd_pd(a2, a2); _mm_storel_pd(&inv_Li, a0); _mm_storel_pd(&dlnLidlz, a1); _mm_storel_pd(&d2lnLidlz2, a2); inv_Li = 1.0 / FABS(inv_Li); dlnLidlz *= inv_Li; d2lnLidlz2 *= inv_Li; dlnLdlz += wgt[i] * dlnLidlz; d2lnLdlz2 += wgt[i] * (d2lnLidlz2 - dlnLidlz * dlnLidlz); } *ext_dlnLdlz = dlnLdlz; *ext_d2lnLdlz2 = d2lnLdlz2; } static void coreGTRCATPROT(double *EIGN, double lz, int numberOfCategories, double *rptr, int *cptr, int upper, int *wgt, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double *sumtable) { int i, l; double *d1, *d_start, *sum; double e[20] __attribute__ ((aligned (BYTE_ALIGNMENT))), s[20] __attribute__ ((aligned (BYTE_ALIGNMENT))), dd[20] __attribute__ ((aligned (BYTE_ALIGNMENT))); double inv_Li, dlnLidlz, d2lnLidlz2; double dlnLdlz = 0.0; double d2lnLdlz2 = 0.0; d1 = d_start = (double *)malloc_aligned(numberOfCategories * 20 * sizeof(double)); e[0] = 0.0; s[0] = 0.0; for(l = 1; l < 20; l++) { e[l] = EIGN[l] * EIGN[l]; s[l] = EIGN[l]; dd[l] = s[l] * lz; } for(i = 0; i < numberOfCategories; i++) { d1[20 * i] = 1.0; for(l = 1; l < 20; l++) d1[20 * i + l] = EXP(dd[l] * rptr[i]); } for (i = 0; i < upper; i++) { __m128d a0 = _mm_setzero_pd(); __m128d a1 = _mm_setzero_pd(); __m128d a2 = _mm_setzero_pd(); double r = rptr[cptr[i]], wr1 = r * wgt[i], wr2 = r * r * wgt[i]; d1 = &d_start[20 * cptr[i]]; sum = &sumtable[20 * i]; for(l = 0; l < 20; l+=2) { __m128d tmpv = _mm_mul_pd(_mm_load_pd(&d1[l]), _mm_load_pd(&sum[l])); a0 = _mm_add_pd(a0, tmpv); __m128d sv = _mm_load_pd(&s[l]); a1 = _mm_add_pd(a1, _mm_mul_pd(tmpv, sv)); __m128d ev = _mm_load_pd(&e[l]); a2 = _mm_add_pd(a2, _mm_mul_pd(tmpv, ev)); } a0 = _mm_hadd_pd(a0, a0); a1 = _mm_hadd_pd(a1, a1); a2 = _mm_hadd_pd(a2, a2); _mm_storel_pd(&inv_Li, a0); _mm_storel_pd(&dlnLidlz, a1); _mm_storel_pd(&d2lnLidlz2, a2); inv_Li = 1.0/FABS(inv_Li); dlnLidlz *= inv_Li; d2lnLidlz2 *= inv_Li; dlnLdlz += wr1 * dlnLidlz; d2lnLdlz2 += wr2 * (d2lnLidlz2 - dlnLidlz * dlnLidlz); } *ext_dlnLdlz = dlnLdlz; *ext_d2lnLdlz2 = d2lnLdlz2; free(d_start); } #endif ExaML-3.0.21/examl/mic_native.h000066400000000000000000000105261330315463200161440ustar00rootroot00000000000000#ifndef MIC_NATIVE_H_ #define MIC_NATIVE_H_ //#define VECTOR_PADDING 8 //#define GET_PADDED_WIDTH(w) w % VECTOR_PADDING == 0 ? w : w + (VECTOR_PADDING - (w % VECTOR_PADDING)) // general functions void updateModel_MIC(pInfo* part); // DNA data void makeP_DNA_MIC(double z1, double z2, double *rptr, double *EI, double *EIGN, int numberOfCategories, double *left, double *right, boolean saveMem, int maxCat); void precomputeTips_DNA_MIC(int tipCase, double *tipVector, double *left, double *right, double *umpLeft, double *umpRight, int numberOfCategories); void newviewGTRGAMMA_MIC(int tipCase, double *x1, double *x2, double *x3, double *extEV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, double *umpLeft, double *umpRight); double evaluateGAMMA_MIC(int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, const int n, double *diagptable); void sumGAMMA_MIC(int tipCase, double *sumtable, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n); void coreGTRGAMMA_MIC(const int upper, double *sumtable, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double *EIGN, double *gammaRates, double lz, int *wrptr); void sumcoreGTRGAMMA_MIC(int tipCase, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, const int n, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double *EIGN, double *gammaRates, double lz, int *wgt); // protein data - single matrix void makeP_PROT_MIC(double z1, double z2, double *rptr, double *EI, double *EIGN, int numberOfCategories, double *left, double *right, boolean saveMem, int maxCat); void precomputeTips_PROT_MIC(int tipCase, double *tipVector, double *left, double *right, double *umpLeft, double *umpRight, int numberOfCategories); void newviewGTRGAMMAPROT_MIC(int tipCase, double *x1, double *x2, double *x3, double *extEV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, double *umpLeft, double *umpRight); double evaluateGAMMAPROT_MIC(int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, const int n, double *diagptable); void sumGAMMAPROT_MIC(int tipCase, double *sumtable, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n); void coreGTRGAMMAPROT_MIC(const int upper, double *sumtable, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double *EIGN, double *gammaRates, double lz, int *wrptr); // protein data - LG4 void updateModel_LG4_MIC(pInfo* part); void makeP_PROT_LG4_MIC(double z1, double z2, double *rptr, double *EI[4], double *EIGN[4], int numberOfCategories, double *left, double *right); void precomputeTips_PROT_LG4_MIC(int tipCase, double *tipVector[4], double *left, double *right, double *umpLeft, double *umpRight, int numberOfCategories); void newviewGTRGAMMAPROT_LG4_MIC(int tipCase, double *x1, double *x2, double *x3, double *extEV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, double *umpLeft, double *umpRight); double evaluateGAMMAPROT_LG4_MIC(int *wptr, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, const int n, double *diagptable, double* weights); void sumGAMMAPROT_LG4_MIC(int tipCase, double *sumtable, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n); void coreGTRGAMMAPROT_LG4_MIC(const int upper, double *sumtable, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double *EIGN[4], double *gammaRates, double lz, int *wrptr, double* weights); #endif /* MIC_NATIVE_H_ */ ExaML-3.0.21/examl/mic_native_aa.c000066400000000000000000001147721330315463200166100ustar00rootroot00000000000000#include #include #include #include "axml.h" #include "mic_native.h" static const int states = 20; static const int statesSquare = 20 * 20; static const int span = 20 * 4; static const int maxStateValue = 23; void makeP_PROT_MIC(double z1, double z2, double *rptr, double *EI, double *EIGN, int numberOfCategories, double *left, double *right, boolean saveMem, int maxCat) { int i, j, k, span = states * numberOfCategories; /* assign some space for pre-computing and later re-using functions */ double lz1[20] __attribute__((aligned(BYTE_ALIGNMENT))); double lz2[20] __attribute__((aligned(BYTE_ALIGNMENT))); double d1[20] __attribute__((aligned(BYTE_ALIGNMENT))); double d2[20] __attribute__((aligned(BYTE_ALIGNMENT))); /* multiply branch lengths with eigenvalues */ for(i = 1; i < states; i++) { lz1[i] = EIGN[i] * z1; lz2[i] = EIGN[i] * z2; } /* loop over the number of rate categories, this will be 4 for the GAMMA model and variable for the CAT model */ for(i = 0; i < numberOfCategories; i++) { /* exponentiate the rate multiplied by the branch */ for(j = 1; j < states; j++) { d1[j] = EXP(rptr[i] * lz1[j]); d2[j] = EXP(rptr[i] * lz2[j]); } /* now fill the P matrices for the two branch length values */ for(j = 0; j < states; j++) { /* left and right are pre-allocated arrays */ left[i * states + j] = 1.0; right[i * states + j] = 1.0; for(k = 1; k < states; k++) { left[k * span + i * states + j] = d1[k] * EI[states * j + k]; right[k * span + i * states + j] = d2[k] * EI[states * j + k]; } } } /* if memory saving is enabled and we are using CAT we need to do one additional P matrix calculation for a rate of 1.0 to compute the entries of a column/tree site comprising only gaps */ if(saveMem) { i = maxCat; for(j = 1; j < states; j++) { d1[j] = EXP (lz1[j]); d2[j] = EXP (lz2[j]); } for(j = 0; j < states; j++) { left[statesSquare * i + states * j] = 1.0; right[statesSquare * i + states * j] = 1.0; for(k = 1; k < states; k++) { left[statesSquare * i + states * j + k] = d1[k] * EI[states * j + k]; right[statesSquare * i + states * j + k] = d2[k] * EI[states * j + k]; } } } } void precomputeTips_PROT_MIC(int tipCase, double *tipVector, double *left, double *right, double *umpLeft, double *umpRight, int numberOfCategories) { /* no precomputation needed if both children are inner nodes */ if (tipCase == INNER_INNER) return; const int span = states * numberOfCategories, umpSize = span * maxStateValue; for(int k = 0; k < umpSize; ++k) { umpLeft[k] = 0.0; umpRight[k] = 0.0; } for(int i = 0; i < maxStateValue; ++i) { for(int l = 0; l < states; ++l) { #pragma ivdep #pragma vector aligned for(int k = 0; k < span; ++k) { umpLeft[span * i + k] += tipVector[i * states + l] * left[l * span + k]; if (tipCase == TIP_TIP) umpRight[span * i + k] += tipVector[i * states + l] * right[l * span + k]; } } } } inline void mic_fma4x80(const double* inv, double* outv, double* mulv) { __mmask8 k1 = _mm512_int2mask(0x0F); __mmask8 k2 = _mm512_int2mask(0xF0); for(int l = 0; l < 80; l += 40) { __m512d t = _mm512_setzero_pd(); t = _mm512_extload_pd(&inv[l], _MM_UPCONV_PD_NONE, _MM_BROADCAST_1X8, _MM_HINT_NONE); __m512d m = _mm512_load_pd(&mulv[l]); __m512d acc = _mm512_load_pd(&outv[l]); __m512d r = _mm512_fmadd_pd(t, m, acc); _mm512_store_pd(&outv[l], r); m = _mm512_load_pd(&mulv[l + 8]); acc = _mm512_load_pd(&outv[l + 8]); r = _mm512_fmadd_pd(t, m, acc); _mm512_store_pd(&outv[l + 8], r); t = _mm512_mask_extload_pd(t, k1, &inv[l], _MM_UPCONV_PD_NONE, _MM_BROADCAST_1X8, _MM_HINT_NONE); t = _mm512_mask_extload_pd(t, k2, &inv[l+20], _MM_UPCONV_PD_NONE, _MM_BROADCAST_1X8, _MM_HINT_NONE); m = _mm512_load_pd(&mulv[l + 16]); acc = _mm512_load_pd(&outv[l + 16]); r = _mm512_fmadd_pd(t, m, acc); _mm512_store_pd(&outv[l + 16], r); t = _mm512_extload_pd(&inv[l+20], _MM_UPCONV_PD_NONE, _MM_BROADCAST_1X8, _MM_HINT_NONE); m = _mm512_load_pd(&mulv[l + 24]); acc = _mm512_load_pd(&outv[l + 24]); r = _mm512_fmadd_pd(t, m, acc); _mm512_store_pd(&outv[l + 24], r); m = _mm512_load_pd(&mulv[l + 32]); acc = _mm512_load_pd(&outv[l + 32]); r = _mm512_fmadd_pd(t, m, acc); _mm512_store_pd(&outv[l + 32], r); } } void newviewGTRGAMMAPROT_MIC(int tipCase, double *x1, double *x2, double *x3, double *extEV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, double *umpLeft, double *umpRight) { __m512d minlikelihood_MIC = _mm512_set1_pd(minlikelihood); __m512d twotothe256_MIC = _mm512_set1_pd(twotothe256); __m512i absMask_MIC = _mm512_set1_epi64(0x7fffffffffffffffULL); int addScale = 0; double *aEV = extEV, *aRight = right, *aLeft = left, *umpX1 = umpLeft, *umpX2 = umpRight; switch(tipCase) { case TIP_TIP: { /* multiply all possible tip state vectors with the respective P-matrices */ for (int i = 0; i < n; i++) { const double *uX1 = &umpX1[span * tipX1[i]]; const double *uX2 = &umpX2[span * tipX2[i]]; double uX[span] __attribute__((aligned(BYTE_ALIGNMENT))); double* v3 = &x3[i * span]; #pragma ivdep #pragma vector aligned for(int l = 0; l < span; ++l) { uX[l] = uX1[l] * uX2[l]; v3[l] = 0.; } for(int k = 0; k < states; ++k) { for (int j = 0; j < span; j += 8) { _mm_prefetch((const char *)&aEV[span*(k+1) + j], _MM_HINT_T0); } mic_fma4x80(&uX[k], v3, &aEV[k * span]); } } // sites loop } break; case TIP_INNER: { for (int i = 0; i < n; i++) { #pragma unroll(10) for (int j = 0; j < span; j += 8) { _mm_prefetch((const char *)&x2[span*(i+1) + j], _MM_HINT_T1); // _mm_prefetch((const char *)&x2[span*(i+1) + j], _MM_HINT_T0); } /* access pre-computed value based on the raw sequence data tipX1 that is used as an index */ double* uX1 = &umpX1[span * tipX1[i]]; double uX2[span] __attribute__((aligned(BYTE_ALIGNMENT))); double uX[span] __attribute__((aligned(BYTE_ALIGNMENT))); double* v3 = &(x3[span * i]); const double* v2 = &(x2[span * i]); #pragma vector aligned for(int l = 0; l < span; ++l) { uX2[l] = 0.; } for(int k = 0; k < states; ++k) { #pragma unroll(10) for (int j = 0; j < span; j += 8) { _mm_prefetch((const char *)&aRight[span*(k+1) + j], _MM_HINT_T0); } mic_fma4x80(&v2[k], uX2, &aRight[k * span]); } #pragma ivdep #pragma vector aligned for(int l = 0; l < span; ++l) { uX[l] = uX1[l] * uX2[l]; v3[l] = 0.; } for(int k = 0; k < states; ++k) { #pragma unroll(10) for (int j = 0; j < span; j += 8) { _mm_prefetch((const char *)&aEV[span*(k+1) + j], _MM_HINT_T0); } mic_fma4x80(&uX[k], v3, &aEV[k * span]); } __m512d t1 = _mm512_load_pd(&v3[0]); t1 = _mm512_castsi512_pd(_mm512_and_epi64(_mm512_castpd_si512(t1), absMask_MIC)); double vmax = _mm512_reduce_max_pd(t1); for (int l = 8; l < span; l += 8) { __m512d t = _mm512_load_pd(&v3[l]); t = _mm512_castsi512_pd(_mm512_and_epi64(_mm512_castpd_si512(t), absMask_MIC)); double vmax2 = _mm512_reduce_max_pd(t); vmax = MAX(vmax, vmax2); } if (vmax < minlikelihood) { #pragma vector aligned nontemporal for(int l = 0; l < span; l++) v3[l] *= twotothe256; addScale += wgt[i]; } } // site loop } break; case INNER_INNER: { /* same as above, without pre-computations */ for (int i = 0; i < n; i++) { #pragma unroll(10) for (int j = 0; j < span; j += 8) { _mm_prefetch((const char *)&x1[span*(i+1) + j], _MM_HINT_T1); _mm_prefetch((const char *)&x2[span*(i+1) + j], _MM_HINT_T1); // _mm_prefetch((const char *)&x1[span*(i+1) + j], _MM_HINT_T0); // _mm_prefetch((const char *)&x2[span*(i+1) + j], _MM_HINT_T0); } double uX1[span] __attribute__((aligned(BYTE_ALIGNMENT))); double uX2[span] __attribute__((aligned(BYTE_ALIGNMENT))); double uX[span] __attribute__((aligned(BYTE_ALIGNMENT))); double* v3 = &(x3[span * i]); const double* v1 = &(x1[span * i]); const double* v2 = &(x2[span * i]); #pragma vector aligned for(int l = 0; l < span; ++l) { uX1[l] = 0.; uX2[l] = 0.; } for(int k = 0; k < states; ++k) { #pragma unroll(10) for (int j = 0; j < span; j += 8) { _mm_prefetch((const char *)&aRight[span*(k+1) + j], _MM_HINT_T0); _mm_prefetch((const char *)&aLeft[span*(k+1) + j], _MM_HINT_T0); } mic_fma4x80(&v1[k], uX1, &aLeft[k * span]); mic_fma4x80(&v2[k], uX2, &aRight[k * span]); } #pragma ivdep #pragma vector aligned for(int l = 0; l < span; ++l) { uX[l] = uX1[l] * uX2[l]; v3[l] = 0.; } for(int k = 0; k < states; ++k) { #pragma unroll(10) for (int j = 0; j < span; j += 8) { _mm_prefetch((const char *)&aEV[span*(k+1) + j], _MM_HINT_T0); } mic_fma4x80(&uX[k], v3, &aEV[k * span]); } __m512d t1 = _mm512_load_pd(&v3[0]); t1 = _mm512_castsi512_pd(_mm512_and_epi64(_mm512_castpd_si512(t1), absMask_MIC)); double vmax = _mm512_reduce_max_pd(t1); for (int l = 8; l < span; l += 8) { __m512d t = _mm512_load_pd(&v3[l]); t = _mm512_castsi512_pd(_mm512_and_epi64(_mm512_castpd_si512(t), absMask_MIC)); double vmax2 = _mm512_reduce_max_pd(t); vmax = MAX(vmax, vmax2); } if (vmax < minlikelihood) { #pragma vector aligned nontemporal for(int l = 0; l < span; l++) v3[l] *= twotothe256; addScale += wgt[i]; } } } break; default: // assert(0); break; } *scalerIncrement = addScale; } double evaluateGAMMAPROT_MIC(int *wgt, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, const int n, double *diagptable) { double sum = 0.0; /* the left node is a tip */ if(tipX1) { double *aTipVec = tipVector; /* loop over the sites of this partition */ for (int i = 0; i < n; i++) { /* access pre-computed tip vector values via a lookup table */ const double *x1 = &(aTipVec[span * tipX1[i]]); /* access the other(inner) node at the other end of the branch */ const double *x2 = &(x2_start[span * i]); #pragma unroll(10) for (int k = 0; k < span; k += 8) { _mm_prefetch((const char *) &x2_start[span*(i+2) + k], _MM_HINT_T1); _mm_prefetch((const char *) &x2_start[span*(i+1) + k], _MM_HINT_T0); } double term = 0.; #pragma ivdep #pragma vector aligned #pragma noprefetch x2 for(int j = 0; j < span; j++) { term += x1[j] * x2[j] * diagptable[j]; } term = log(0.25 * fabs(term)); sum += wgt[i] * term; } } else { for (int i = 0; i < n; i++) { #pragma unroll(10) for (int k = 0; k < span; k += 8) { _mm_prefetch((const char *) &x1_start[span*(i+2) + k], _MM_HINT_T1); _mm_prefetch((const char *) &x1_start[span*(i+1) + k], _MM_HINT_T0); _mm_prefetch((const char *) &x2_start[span*(i+2) + k], _MM_HINT_T1); _mm_prefetch((const char *) &x2_start[span*(i+1) + k], _MM_HINT_T0); } const double *x1 = &(x1_start[span * i]); const double *x2 = &(x2_start[span * i]); double term = 0.; #pragma ivdep #pragma vector aligned #pragma noprefetch x1 x2 for(int j = 0; j < span; j++) term += x1[j] * x2[j] * diagptable[j]; term = log(0.25 * fabs(term)); sum += wgt[i] * term; } } return sum; } void sumGAMMAPROT_MIC(int tipCase, double *sumtable, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n) { double *aTipVec = tipVector; switch(tipCase) { case TIP_TIP: { for(int i = 0; i < n; i++) { const double *left = &(aTipVec[span * tipX1[i]]); const double *right = &(aTipVec[span * tipX2[i]]); #pragma ivdep #pragma vector aligned nontemporal for(int l = 0; l < span; l++) { sumtable[i * span + l] = left[l] * right[l]; } } } break; case TIP_INNER: { for(int i = 0; i < n; i++) { #pragma unroll(10) for (int k = 0; k < span; k += 8) { _mm_prefetch((const char *) &x2_start[span*(i+2) + k], _MM_HINT_T1); _mm_prefetch((const char *) &x2_start[span*(i+1) + k], _MM_HINT_T0); } const double *left = &(aTipVec[span * tipX1[i]]); const double *right = &(x2_start[span * i]); #pragma ivdep #pragma vector aligned nontemporal #pragma noprefetch right for(int l = 0; l < span; l++) { sumtable[i * span + l] = left[l] * right[l]; } } } break; case INNER_INNER: { for(int i = 0; i < n; i++) { #pragma unroll(10) for (int k = 0; k < span; k += 8) { _mm_prefetch((const char *) &x1_start[span*(i+2) + k], _MM_HINT_T1); _mm_prefetch((const char *) &x1_start[span*(i+1) + k], _MM_HINT_T0); _mm_prefetch((const char *) &x2_start[span*(i+2) + k], _MM_HINT_T1); _mm_prefetch((const char *) &x2_start[span*(i+1) + k], _MM_HINT_T0); } const double *left = &(x1_start[span * i]); const double *right = &(x2_start[span * i]); #pragma ivdep #pragma vector aligned nontemporal #pragma noprefetch left right for(int l = 0; l < span; l++) { sumtable[i * span + l] = left[l] * right[l]; } } } break; // default: // assert(0); } } void coreGTRGAMMAPROT_MIC(const int upper, double *sumtable, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double *EIGN, double *gammaRates, double lz, int *wgt) { static const int states = 20; static const int span = 20 * 4; double diagptable0[span] __attribute__((aligned(BYTE_ALIGNMENT))); double diagptable1[span] __attribute__((aligned(BYTE_ALIGNMENT))); double diagptable2[span] __attribute__((aligned(BYTE_ALIGNMENT))); double diagptable01[span] __attribute__((aligned(BYTE_ALIGNMENT))); double diagptable02[span] __attribute__((aligned(BYTE_ALIGNMENT))); /* pre-compute the derivatives of the P matrix for all discrete GAMMA rates */ for(int i = 0; i < 4; i++) { const double ki = gammaRates[i]; const double kisqr = ki * ki; diagptable0[i*states] = 1.; diagptable1[i*states] = 0.; diagptable2[i*states] = 0.; for(int l = 1; l < states; l++) { diagptable0[i * states + l] = exp(EIGN[l] * ki * lz); diagptable1[i * states + l] = EIGN[l] * ki; diagptable2[i * states + l] = EIGN[l] * EIGN[l] * kisqr; } } #pragma ivdep for(int i = 0; i < span; i++) { diagptable01[i] = diagptable0[i] * diagptable1[i]; diagptable02[i] = diagptable0[i] * diagptable2[i]; } /* loop over sites in this partition */ const int aligned_width = upper % 8 == 0 ? upper / 8 : upper / 8 + 1; double dlnLBuf[8] __attribute__((aligned(BYTE_ALIGNMENT))); double d2lnLBuf[8] __attribute__((aligned(BYTE_ALIGNMENT))); for (int j = 0; j < 8; ++j) { dlnLBuf[j] = 0.; d2lnLBuf[j] = 0.; } __mmask16 k1 = _mm512_int2mask(0x000000FF); for (int i = 0; i < aligned_width; i++) { /* access the array with pre-computed values */ const double *sum = &sumtable[i * span * 8]; /* initial per-site likelihood and 1st and 2nd derivatives */ double invBuf[8] __attribute__((aligned(BYTE_ALIGNMENT))); double d1Buf[8] __attribute__((aligned(BYTE_ALIGNMENT))); double d2Buf[8] __attribute__((aligned(BYTE_ALIGNMENT))); __m512d invVec; __m512d d1Vec; __m512d d2Vec; int mask = 0x01; #pragma noprefetch sum #pragma unroll(8) for(int j = 0; j < 8; j++) { #pragma unroll(10) for (int k = 0; k < span; k += 8) { _mm_prefetch((const char *) &sum[span*(j+2) + k], _MM_HINT_T1); _mm_prefetch((const char *) &sum[span*(j+1) + k], _MM_HINT_T0); } __m512d inv_1 = _mm512_setzero_pd(); __m512d d1_1 = _mm512_setzero_pd(); __m512d d2_1 = _mm512_setzero_pd(); for (int offset = 0; offset < span; offset += 8) { __m512d d0_1 = _mm512_load_pd(&diagptable0[offset]); __m512d d01_1 = _mm512_load_pd(&diagptable01[offset]); __m512d d02_1 = _mm512_load_pd(&diagptable02[offset]); __m512d s_1 = _mm512_load_pd(&sum[j*span + offset]); inv_1 = _mm512_fmadd_pd(d0_1, s_1, inv_1); d1_1 = _mm512_fmadd_pd(d01_1, s_1, d1_1); d2_1 = _mm512_fmadd_pd(d02_1, s_1, d2_1); } __mmask8 k1 = _mm512_int2mask(mask); mask <<= 1; // reduce inv_1 = _mm512_add_pd (inv_1, _mm512_swizzle_pd(inv_1, _MM_SWIZ_REG_CDAB)); inv_1 = _mm512_add_pd (inv_1, _mm512_swizzle_pd(inv_1, _MM_SWIZ_REG_BADC)); inv_1 = _mm512_add_pd (inv_1, _mm512_castsi512_pd(_mm512_permute4f128_epi32(_mm512_castpd_si512(inv_1), _MM_PERM_BADC))); invVec = _mm512_mask_mov_pd(invVec, k1, inv_1); d1_1 = _mm512_add_pd (d1_1, _mm512_swizzle_pd(d1_1, _MM_SWIZ_REG_CDAB)); d1_1 = _mm512_add_pd (d1_1, _mm512_swizzle_pd(d1_1, _MM_SWIZ_REG_BADC)); d1_1 = _mm512_add_pd (d1_1, _mm512_castsi512_pd(_mm512_permute4f128_epi32(_mm512_castpd_si512(d1_1), _MM_PERM_BADC))); d1Vec = _mm512_mask_mov_pd(d1Vec, k1, d1_1); d2_1 = _mm512_add_pd (d2_1, _mm512_swizzle_pd(d2_1, _MM_SWIZ_REG_CDAB)); d2_1 = _mm512_add_pd (d2_1, _mm512_swizzle_pd(d2_1, _MM_SWIZ_REG_BADC)); d2_1 = _mm512_add_pd (d2_1, _mm512_castsi512_pd(_mm512_permute4f128_epi32(_mm512_castpd_si512(d2_1), _MM_PERM_BADC))); d2Vec = _mm512_mask_mov_pd(d2Vec, k1, d2_1); } _mm512_store_pd(&invBuf[0], invVec); _mm512_store_pd(&d1Buf[0], d1Vec); _mm512_store_pd(&d2Buf[0], d2Vec); #pragma ivdep #pragma vector aligned for (int j = 0; j < 8; ++j) { const double inv_Li = 1.0 / invBuf[j]; const double d1 = d1Buf[j] * inv_Li; const double d2 = d2Buf[j] * inv_Li; dlnLBuf[j] += wgt[i * 8 + j] * d1; d2lnLBuf[j] += wgt[i * 8 + j] * (d2 - d1 * d1); } } // site loop double dlnLdlz = 0.; double d2lnLdlz2 = 0.; for (int j = 0; j < 8; ++j) { dlnLdlz += dlnLBuf[j]; d2lnLdlz2 += d2lnLBuf[j]; } *ext_dlnLdlz = dlnLdlz; *ext_d2lnLdlz2 = d2lnLdlz2; } /**** * PROTEIN - LG4 */ void updateModel_LG4_MIC(pInfo* part) { double **EV = part->EV_LG4, **tipVector = part->tipVector_LG4, *aEV = part->mic_EV, *aTipVector = part->mic_tipVector; const int states = part->states, span = 4 * states, maxState = getUndetermined(part->dataType) + 1; int k, l; #pragma ivdep for (l = 0; l < 4 * states * states; ++l) { aEV[l] = EV[(l % span) / states][(l / span) * states + (l % states)]; } for(int k = 0; k < maxState; k++) { for(int j = 0; j < 4; j++) { for(int l = 0; l < states; l++) { aTipVector[k*span + j*states + l] = tipVector[j][k*states + l]; } } } } void makeP_PROT_LG4_MIC(double z1, double z2, double *rptr, double *EI[4], double *EIGN[4], int numberOfCategories, double *left, double *right) { int i, j, k; double d1[64], d2[64]; for(i = 0; i < numberOfCategories; i++) { for(j = 1; j < states; j++) { d1[j] = EXP (rptr[i] * EIGN[i][j] * z1); d2[j] = EXP (rptr[i] * EIGN[i][j] * z2); } for(j = 0; j < states; j++) { left[i * states + j] = 1.0; right[i * states + j] = 1.0; for(k = 1; k < states; k++) { left[k * span + i * states + j] = d1[k] * EI[i][states * j + k]; right[k * span + i * states + j] = d2[k] * EI[i][states * j + k]; } } } } void precomputeTips_PROT_LG4_MIC(int tipCase, double *tipVector[4], double *left, double *right, double *umpLeft, double *umpRight, int numberOfCategories) { /* no precomputation needed if both children are inner nodes */ if (tipCase == INNER_INNER) return; const int span = states * numberOfCategories, umpSize = span * maxStateValue; for(int k = 0; k < umpSize; ++k) { umpLeft[k] = 0.0; umpRight[k] = 0.0; } for(int i = 0; i < maxStateValue; ++i) { for(int l = 0; l < states; ++l) { #pragma ivdep #pragma vector aligned for(int k = 0; k < span; ++k) { umpLeft[span * i + k] += tipVector[k/20][i * states + l] * left[l * span + k]; if (tipCase == TIP_TIP) umpRight[span * i + k] += tipVector[k/20][i * states + l] * right[l * span + k]; } } } } void newviewGTRGAMMAPROT_LG4_MIC(int tipCase, double *x1, double *x2, double *x3, double *extEV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, double *umpLeft, double *umpRight) { __m512d minlikelihood_MIC = _mm512_set1_pd(minlikelihood); __m512d twotothe256_MIC = _mm512_set1_pd(twotothe256); __m512i absMask_MIC = _mm512_set1_epi64(0x7fffffffffffffffULL); int addScale = 0; /* we assume that P-matrix and eigenvectors are in correct layout already */ double *aEV = extEV, *aRight = right, *aLeft = left, *umpX1 = umpLeft, *umpX2 = umpRight; switch(tipCase) { case TIP_TIP: { for (int i = 0; i < n; i++) { const double *uX1 = &umpX1[span * tipX1[i]]; const double *uX2 = &umpX2[span * tipX2[i]]; double uX[span] __attribute__((aligned(BYTE_ALIGNMENT))); double* v3 = &x3[i * span]; #pragma ivdep #pragma vector aligned for(int l = 0; l < span; ++l) { uX[l] = uX1[l] * uX2[l]; v3[l] = 0.; } for(int k = 0; k < states; ++k) { for (int j = 0; j < span; j += 8) { _mm_prefetch((const char *)&aEV[span*(k+1) + j], _MM_HINT_T0); } mic_fma4x80(&uX[k], v3, &aEV[k * span]); } } // sites loop } break; case TIP_INNER: { for (int i = 0; i < n; i++) { #pragma unroll(10) for (int j = 0; j < span; j += 8) { _mm_prefetch((const char *)&x2[span*(i+1) + j], _MM_HINT_T1); // _mm_prefetch((const char *)&x2[span*(i+1) + j], _MM_HINT_T0); } /* access pre-computed value based on the raw sequence data tipX1 that is used as an index */ double* uX1 = &umpX1[span * tipX1[i]]; double uX2[span] __attribute__((aligned(BYTE_ALIGNMENT))); double uX[span] __attribute__((aligned(BYTE_ALIGNMENT))); double* v3 = &(x3[span * i]); const double* v2 = &(x2[span * i]); #pragma vector aligned for(int l = 0; l < span; ++l) { uX2[l] = 0.; } for(int k = 0; k < states; ++k) { #pragma unroll(10) for (int j = 0; j < span; j += 8) { _mm_prefetch((const char *)&aRight[span*(k+1) + j], _MM_HINT_T0); } mic_fma4x80(&v2[k], uX2, &aRight[k * span]); } #pragma ivdep #pragma vector aligned for(int l = 0; l < span; ++l) { uX[l] = uX1[l] * uX2[l]; v3[l] = 0.; } for(int k = 0; k < states; ++k) { #pragma unroll(10) for (int j = 0; j < span; j += 8) { _mm_prefetch((const char *)&aEV[span*(k+1) + j], _MM_HINT_T0); } mic_fma4x80(&uX[k], v3, &aEV[k * span]); } __m512d t1 = _mm512_load_pd(&v3[0]); t1 = _mm512_castsi512_pd(_mm512_and_epi64(_mm512_castpd_si512(t1), absMask_MIC)); double vmax = _mm512_reduce_max_pd(t1); for (int l = 8; l < span; l += 8) { __m512d t = _mm512_load_pd(&v3[l]); t = _mm512_castsi512_pd(_mm512_and_epi64(_mm512_castpd_si512(t), absMask_MIC)); double vmax2 = _mm512_reduce_max_pd(t); vmax = MAX(vmax, vmax2); } if (vmax < minlikelihood) { #pragma vector aligned nontemporal for(int l = 0; l < span; l++) v3[l] *= twotothe256; addScale += wgt[i]; } } // site loop } break; case INNER_INNER: { for (int i = 0; i < n; i++) { #pragma unroll(10) for (int j = 0; j < span; j += 8) { _mm_prefetch((const char *)&x1[span*(i+1) + j], _MM_HINT_T1); _mm_prefetch((const char *)&x2[span*(i+1) + j], _MM_HINT_T1); // _mm_prefetch((const char *)&x1[span*(i+1) + j], _MM_HINT_T0); // _mm_prefetch((const char *)&x2[span*(i+1) + j], _MM_HINT_T0); } double uX1[span] __attribute__((aligned(BYTE_ALIGNMENT))); double uX2[span] __attribute__((aligned(BYTE_ALIGNMENT))); double uX[span] __attribute__((aligned(BYTE_ALIGNMENT))); double* v3 = &(x3[span * i]); const double* v1 = &(x1[span * i]); const double* v2 = &(x2[span * i]); #pragma vector aligned for(int l = 0; l < span; ++l) { uX1[l] = 0.; uX2[l] = 0.; } for(int k = 0; k < states; ++k) { #pragma unroll(10) for (int j = 0; j < span; j += 8) { _mm_prefetch((const char *)&aRight[span*(k+1) + j], _MM_HINT_T0); _mm_prefetch((const char *)&aLeft[span*(k+1) + j], _MM_HINT_T0); } mic_fma4x80(&v1[k], uX1, &aLeft[k * span]); mic_fma4x80(&v2[k], uX2, &aRight[k * span]); } #pragma ivdep #pragma vector aligned for(int l = 0; l < span; ++l) { uX[l] = uX1[l] * uX2[l]; v3[l] = 0.; } for(int k = 0; k < states; ++k) { #pragma unroll(10) for (int j = 0; j < span; j += 8) { _mm_prefetch((const char *)&aEV[span*(k+1) + j], _MM_HINT_T0); } mic_fma4x80(&uX[k], v3, &aEV[k * span]); } __m512d t1 = _mm512_load_pd(&v3[0]); t1 = _mm512_castsi512_pd(_mm512_and_epi64(_mm512_castpd_si512(t1), absMask_MIC)); double vmax = _mm512_reduce_max_pd(t1); for (int l = 8; l < span; l += 8) { __m512d t = _mm512_load_pd(&v3[l]); t = _mm512_castsi512_pd(_mm512_and_epi64(_mm512_castpd_si512(t), absMask_MIC)); // double vmax2 = _mm512_reduce_max_pd(t); double vmax2 = _mm512_reduce_max_pd(t); vmax = MAX(vmax, vmax2); } if (vmax < minlikelihood) { #pragma vector aligned nontemporal for(int l = 0; l < span; l++) v3[l] *= twotothe256; addScale += wgt[i]; } } } break; default: // assert(0); break; } *scalerIncrement = addScale; } double evaluateGAMMAPROT_LG4_MIC(int *wgt, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, const int n, double *diagptable, double *weights) { double wtable[span] __attribute__((aligned(BYTE_ALIGNMENT))); /* pre-multiply diagptable entries with the corresponding weights */ for(int j = 0; j < 4; j++) for(int k = 0; k < states; k++) { wtable[j * states + k] = diagptable[j * states + k] * weights[j]; } double sum = 0.0; /* the left node is a tip */ if(tipX1) { /* loop over the sites of this partition */ for (int i = 0; i < n; i++) { const double *aTipVec = tipVector; /* access pre-computed tip vector values via a lookup table */ const double *x1 = &(aTipVec[span * tipX1[i]]); /* access the other(inner) node at the other end of the branch */ const double *x2 = &(x2_start[span * i]); #pragma unroll(10) for (int k = 0; k < span; k += 8) { _mm_prefetch((const char *) &x2_start[span*(i+2) + k], _MM_HINT_T1); _mm_prefetch((const char *) &x2_start[span*(i+1) + k], _MM_HINT_T0); } double term = 0.; #pragma ivdep #pragma vector aligned #pragma noprefetch x2 for(int j = 0; j < span; j++) { term += x1[j] * x2[j] * wtable[j]; } term = log(fabs(term)); sum += wgt[i] * term; } } else { for (int i = 0; i < n; i++) { #pragma unroll(10) for (int k = 0; k < span; k += 8) { _mm_prefetch((const char *) &x1_start[span*(i+2) + k], _MM_HINT_T1); _mm_prefetch((const char *) &x1_start[span*(i+1) + k], _MM_HINT_T0); _mm_prefetch((const char *) &x2_start[span*(i+2) + k], _MM_HINT_T1); _mm_prefetch((const char *) &x2_start[span*(i+1) + k], _MM_HINT_T0); } const double *x1 = &(x1_start[span * i]); const double *x2 = &(x2_start[span * i]); double term = 0.; #pragma ivdep #pragma vector aligned #pragma noprefetch x1 x2 for(int j = 0; j < span; j++) term += x1[j] * x2[j] * wtable[j]; term = log(fabs(term)); sum += wgt[i] * term; } } return sum; } void sumGAMMAPROT_LG4_MIC(int tipCase, double *sumtable, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n) { const double *aTipVec = tipVector; switch(tipCase) { case TIP_TIP: { for(int i = 0; i < n; i++) { const double *left = &(aTipVec[span * tipX1[i]]); const double *right = &(aTipVec[span * tipX2[i]]); #pragma ivdep #pragma vector aligned nontemporal for(int l = 0; l < span; l++) { sumtable[i * span + l] = left[l] * right[l]; } } } break; case TIP_INNER: { for(int i = 0; i < n; i++) { #pragma unroll(10) for (int k = 0; k < span; k += 8) { _mm_prefetch((const char *) &x2_start[span*(i+2) + k], _MM_HINT_T1); _mm_prefetch((const char *) &x2_start[span*(i+1) + k], _MM_HINT_T0); } const double *left = &(aTipVec[span * tipX1[i]]); const double *right = &(x2_start[span * i]); #pragma ivdep #pragma vector aligned nontemporal #pragma noprefetch right for(int l = 0; l < span; l++) { sumtable[i * span + l] = left[l] * right[l]; } } } break; case INNER_INNER: { for(int i = 0; i < n; i++) { #pragma unroll(10) for (int k = 0; k < span; k += 8) { _mm_prefetch((const char *) &x1_start[span*(i+2) + k], _MM_HINT_T1); _mm_prefetch((const char *) &x1_start[span*(i+1) + k], _MM_HINT_T0); _mm_prefetch((const char *) &x2_start[span*(i+2) + k], _MM_HINT_T1); _mm_prefetch((const char *) &x2_start[span*(i+1) + k], _MM_HINT_T0); } const double *left = &(x1_start[span * i]); const double *right = &(x2_start[span * i]); #pragma ivdep #pragma vector aligned nontemporal #pragma noprefetch left right for(int l = 0; l < span; l++) { sumtable[i * span + l] = left[l] * right[l]; } } } break; // default: // assert(0); } } void coreGTRGAMMAPROT_LG4_MIC(const int upper, double *sumtable, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double *EIGN[4], double *gammaRates, double lz, int *wgt, double *weights) { double diagptable0[span] __attribute__((aligned(BYTE_ALIGNMENT))); double diagptable1[span] __attribute__((aligned(BYTE_ALIGNMENT))); double diagptable2[span] __attribute__((aligned(BYTE_ALIGNMENT))); double diagptable01[span] __attribute__((aligned(BYTE_ALIGNMENT))); double diagptable02[span] __attribute__((aligned(BYTE_ALIGNMENT))); /* pre-compute the derivatives of the P matrix for all discrete GAMMA rates */ for(int i = 0; i < 4; i++) { const double ki = gammaRates[i]; const double kisqr = ki * ki; diagptable0[i*states] = 1. * weights[i]; diagptable1[i*states] = 0.; diagptable2[i*states] = 0.; for(int l = 1; l < states; l++) { diagptable0[i * states + l] = exp(EIGN[i][l] * ki * lz) * weights[i]; diagptable1[i * states + l] = EIGN[i][l] * ki; diagptable2[i * states + l] = EIGN[i][l] * EIGN[i][l] * kisqr; } } #pragma ivdep for(int i = 0; i < span; i++) { diagptable01[i] = diagptable0[i] * diagptable1[i]; diagptable02[i] = diagptable0[i] * diagptable2[i]; } /* loop over sites in this partition */ const int aligned_width = upper % 8 == 0 ? upper / 8 : upper / 8 + 1; double dlnLdlz = 0.; double d2lnLdlz2 = 0.; __mmask16 k1 = _mm512_int2mask(0x000000FF); for (int i = 0; i < aligned_width; i++) { /* access the array with pre-computed values */ const double *sum = &sumtable[i * span * 8]; /* initial per-site likelihood and 1st and 2nd derivatives */ double invBuf[8] __attribute__((aligned(BYTE_ALIGNMENT))); double d1Buf[8] __attribute__((aligned(BYTE_ALIGNMENT))); double d2Buf[8] __attribute__((aligned(BYTE_ALIGNMENT))); __m512d invVec; __m512d d1Vec; __m512d d2Vec; int mask = 0x01; #pragma noprefetch sum #pragma unroll(8) for(int j = 0; j < 8; j++) { #pragma unroll(10) for (int k = 0; k < span; k += 8) { _mm_prefetch((const char *) &sum[span*(j+2) + k], _MM_HINT_T1); _mm_prefetch((const char *) &sum[span*(j+1) + k], _MM_HINT_T0); } __m512d inv_1 = _mm512_setzero_pd(); __m512d d1_1 = _mm512_setzero_pd(); __m512d d2_1 = _mm512_setzero_pd(); for (int offset = 0; offset < span; offset += 8) { __m512d d0_1 = _mm512_load_pd(&diagptable0[offset]); __m512d d01_1 = _mm512_load_pd(&diagptable01[offset]); __m512d d02_1 = _mm512_load_pd(&diagptable02[offset]); __m512d s_1 = _mm512_load_pd(&sum[j*span + offset]); inv_1 = _mm512_fmadd_pd(d0_1, s_1, inv_1); d1_1 = _mm512_fmadd_pd(d01_1, s_1, d1_1); d2_1 = _mm512_fmadd_pd(d02_1, s_1, d2_1); } __mmask8 k1 = _mm512_int2mask(mask); mask <<= 1; // reduce inv_1 = _mm512_add_pd (inv_1, _mm512_swizzle_pd(inv_1, _MM_SWIZ_REG_CDAB)); inv_1 = _mm512_add_pd (inv_1, _mm512_swizzle_pd(inv_1, _MM_SWIZ_REG_BADC)); inv_1 = _mm512_add_pd (inv_1, _mm512_castsi512_pd(_mm512_permute4f128_epi32(_mm512_castpd_si512(inv_1), _MM_PERM_BADC))); invVec = _mm512_mask_mov_pd(invVec, k1, inv_1); d1_1 = _mm512_add_pd (d1_1, _mm512_swizzle_pd(d1_1, _MM_SWIZ_REG_CDAB)); d1_1 = _mm512_add_pd (d1_1, _mm512_swizzle_pd(d1_1, _MM_SWIZ_REG_BADC)); d1_1 = _mm512_add_pd (d1_1, _mm512_castsi512_pd(_mm512_permute4f128_epi32(_mm512_castpd_si512(d1_1), _MM_PERM_BADC))); d1Vec = _mm512_mask_mov_pd(d1Vec, k1, d1_1); d2_1 = _mm512_add_pd (d2_1, _mm512_swizzle_pd(d2_1, _MM_SWIZ_REG_CDAB)); d2_1 = _mm512_add_pd (d2_1, _mm512_swizzle_pd(d2_1, _MM_SWIZ_REG_BADC)); d2_1 = _mm512_add_pd (d2_1, _mm512_castsi512_pd(_mm512_permute4f128_epi32(_mm512_castpd_si512(d2_1), _MM_PERM_BADC))); d2Vec = _mm512_mask_mov_pd(d2Vec, k1, d2_1); } _mm512_store_pd(&invBuf[0], invVec); _mm512_store_pd(&d1Buf[0], d1Vec); _mm512_store_pd(&d2Buf[0], d2Vec); #pragma ivdep #pragma vector aligned for (int j = 0; j < 8; ++j) { const double inv_Li = 1.0 / invBuf[j]; const double d1 = d1Buf[j] * inv_Li; const double d2 = d2Buf[j] * inv_Li; dlnLdlz += wgt[i * 8 + j] * d1; d2lnLdlz2 += wgt[i * 8 + j] * (d2 - d1 * d1); } } // site loop *ext_dlnLdlz = dlnLdlz; *ext_d2lnLdlz2 = d2lnLdlz2; } ExaML-3.0.21/examl/mic_native_dna.c000066400000000000000000000510721330315463200167620ustar00rootroot00000000000000#include #include #include #include "axml.h" #include "mic_native.h" static const int states = 4; static const int statesSquare = 16; static const int span = 4 * 4; static const int maxStateValue = 16; /* Common functions */ void updateModel_MIC(pInfo* part) { double *EV = part->EV, *tipVector = part->tipVector, *aEV = part->mic_EV, *aTipVector = part->mic_tipVector; const int states = part->states, span = 4 * states, maxState = getUndetermined(part->dataType) + 1; int k, l; #pragma ivdep for (l = 0; l < 4 * states * states; ++l) { aEV[l] = EV[(l / span) * states + (l % states)]; } for(int k = 0; k < maxState; k++) { #pragma ivdep for(int l = 0; l < states; l++) { aTipVector[k*span + l] = aTipVector[k*span + states + l] = aTipVector[k*span + 2*states + l] = aTipVector[k*span + 3*states + l] = tipVector[k*states + l]; } } } /* DNA */ void makeP_DNA_MIC(double z1, double z2, double *rptr, double *EI, double *EIGN, int numberOfCategories, double *left, double *right, boolean saveMem, int maxCat) { int i, j, k, span = states * numberOfCategories; /* assign some space for pre-computing and later re-using functions */ double lz1[4] __attribute__((aligned(BYTE_ALIGNMENT))); double lz2[4] __attribute__((aligned(BYTE_ALIGNMENT))); double d1[4] __attribute__((aligned(BYTE_ALIGNMENT))); double d2[4] __attribute__((aligned(BYTE_ALIGNMENT))); /* multiply branch lengths with eigenvalues */ for(i = 1; i < states; i++) { lz1[i] = EIGN[i] * z1; lz2[i] = EIGN[i] * z2; } /* loop over the number of rate categories, this will be 4 for the GAMMA model and variable for the CAT model */ for(i = 0; i < numberOfCategories; i++) { /* exponentiate the rate multiplied by the branch */ for(j = 1; j < states; j++) { d1[j] = EXP(rptr[i] * lz1[j]); d2[j] = EXP(rptr[i] * lz2[j]); } /* now fill the P matrices for the two branch length values */ for(j = 0; j < states; j++) { /* left and right are pre-allocated arrays */ left[i * states + j] = 1.0; right[i * states + j] = 1.0; for(k = 1; k < states; k++) { left[k * span + i * states + j] = d1[k] * EI[states * j + k]; right[k * span + i * states + j] = d2[k] * EI[states * j + k]; } } } /* if memory saving is enabled and we are using CAT we need to do one additional P matrix calculation for a rate of 1.0 to compute the entries of a column/tree site comprising only gaps */ if(saveMem) { i = maxCat; for(j = 1; j < states; j++) { d1[j] = EXP (lz1[j]); d2[j] = EXP (lz2[j]); } for(j = 0; j < states; j++) { left[statesSquare * i + states * j] = 1.0; right[statesSquare * i + states * j] = 1.0; for(k = 1; k < states; k++) { left[statesSquare * i + states * j + k] = d1[k] * EI[states * j + k]; right[statesSquare * i + states * j + k] = d2[k] * EI[states * j + k]; } } } } void precomputeTips_DNA_MIC(int tipCase, double *tipVector, double *left, double *right, double *umpLeft, double *umpRight, int numberOfCategories) { /* no precomputation needed if both children are inner nodes */ if (tipCase == INNER_INNER) return; const int span = states * 4, umpSize = span * 16; for(int k = 0; k < umpSize; ++k) { umpLeft[k] = 0.0; umpRight[k] = 0.0; } for(int i = 0; i < maxStateValue; ++i) { for(int l = 0; l < states; ++l) { #pragma ivdep #pragma vector aligned for(int k = 0; k < span; ++k) { umpLeft[span * i + k] += tipVector[i * states + l] * left[l * span + k]; if (tipCase == TIP_TIP) umpRight[span * i + k] += tipVector[i * states + l] * right[l * span + k]; } } } } inline void mic_fma4x16(const double* inv, double* outv, double* mulv) { __mmask8 k1 = _mm512_int2mask(0x0F); __mmask8 k2 = _mm512_int2mask(0xF0); __m512d acc1 = _mm512_setzero_pd(); __m512d acc2 = _mm512_setzero_pd(); __m512d t; for(int k = 0; k < 4; k++) { t = _mm512_mask_extload_pd(t, k1, &inv[0 + k], _MM_UPCONV_PD_NONE, _MM_BROADCAST_1X8, _MM_HINT_NONE); t = _mm512_mask_extload_pd(t, k2, &inv[4 + k], _MM_UPCONV_PD_NONE, _MM_BROADCAST_1X8, _MM_HINT_NONE); __m512d m = _mm512_load_pd(&mulv[k * 16]); acc1 = _mm512_fmadd_pd(t, m, acc1); t = _mm512_mask_extload_pd(t, k1, &inv[8 + k], _MM_UPCONV_PD_NONE, _MM_BROADCAST_1X8, _MM_HINT_NONE); t = _mm512_mask_extload_pd(t, k2, &inv[12 + k], _MM_UPCONV_PD_NONE, _MM_BROADCAST_1X8, _MM_HINT_NONE); m = _mm512_load_pd(&mulv[k * 16 + 8]); acc2 = _mm512_fmadd_pd(t, m, acc2); } _mm512_store_pd(&outv[0], acc1); _mm512_store_pd(&outv[8], acc2); } void newviewGTRGAMMA_MIC(int tipCase, double *x1, double *x2, double *x3, double *extEV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, double *umpLeft, double *umpRight) { __m512d minlikelihood_MIC = _mm512_set1_pd(minlikelihood); __m512d twotothe256_MIC = _mm512_set1_pd(twotothe256); __m512i absMask_MIC = _mm512_set1_epi64(0x7fffffffffffffffULL); int addScale = 0; /* we assume that P-matrix and eigenvectors are in correct layout already */ double *aEV = extEV, *aRight = right, *aLeft = left, *umpX1 = umpLeft, *umpX2 = umpRight; switch(tipCase) { case TIP_TIP: { #pragma noprefetch umpX1,umpX2 for (int i = 0; i < n; i++) { _mm_prefetch((const char *)&x3[span*(i+8)], _MM_HINT_ET1); _mm_prefetch((const char *)&x3[span*(i+8) + 8], _MM_HINT_ET1); _mm_prefetch((const char *)&x3[span*(i+1)], _MM_HINT_ET0); _mm_prefetch((const char *)&x3[span*(i+1) + 8], _MM_HINT_ET0); const double *uX1 = &umpX1[16 * tipX1[i]]; const double *uX2 = &umpX2[16 * tipX2[i]]; double uX[16] __attribute__((aligned(64))); #pragma ivdep #pragma vector aligned for(int l = 0; l < 16; ++l) { uX[l] = uX1[l] * uX2[l]; } double* v3 = &x3[i * 16]; mic_fma4x16(uX, v3, aEV); } // sites loop } break; case TIP_INNER: { #pragma noprefetch umpX1 for (int i = 0; i < n; i++) { _mm_prefetch((const char *)&x2[span*(i+16)], _MM_HINT_T1); _mm_prefetch((const char *)&x2[span*(i+16) + 8], _MM_HINT_T1); _mm_prefetch((const char *)&x3[span*(i+16)], _MM_HINT_ET1); _mm_prefetch((const char *)&x3[span*(i+16) + 8], _MM_HINT_ET1); _mm_prefetch((const char *)&x2[span*(i+1)], _MM_HINT_T0); _mm_prefetch((const char *)&x2[span*(i+1) + 8], _MM_HINT_T0); _mm_prefetch((const char *)&x3[span*(i+1)], _MM_HINT_ET0); _mm_prefetch((const char *)&x3[span*(i+1) + 8], _MM_HINT_ET0); /* access pre-computed value based on the raw sequence data tipX1 that is used as an index */ double* uX1 = &umpX1[span * tipX1[i]]; double uX2[16] __attribute__((aligned(64))); double uX[16] __attribute__((aligned(64))); const double* v2 = &(x2[16 * i]); mic_fma4x16(v2, uX2, aRight); #pragma ivdep #pragma vector aligned for(int l = 0; l < 16; ++l) { uX[l] = uX1[l] * uX2[l]; } double* v3 = &(x3[span * i]); mic_fma4x16(uX, v3, aEV); __m512d t1 = _mm512_load_pd(&v3[0]); t1 = _mm512_castsi512_pd(_mm512_and_epi64(_mm512_castpd_si512(t1), absMask_MIC)); double vmax1 = _mm512_reduce_max_pd(t1); __m512d t2 = _mm512_load_pd(&v3[8]); t2 = _mm512_castsi512_pd(_mm512_and_epi64(_mm512_castpd_si512(t2), absMask_MIC)); double vmax2 = _mm512_reduce_max_pd(t2); if(vmax1 < minlikelihood && vmax2 < minlikelihood) { /* t1 = _mm512_mul_pd(t1, twotothe256_MIC); _mm512_store_pd(&v3[0], t1); t2 = _mm512_mul_pd(t2, twotothe256_MIC); _mm512_store_pd(&v3[8], t2);*/ #pragma vector aligned nontemporal for(int l = 0; l < span; l++) v3[l] *= twotothe256; addScale += wgt[i]; } } // site loop } break; case INNER_INNER: { for (int i = 0; i < n; i++) { _mm_prefetch((const char *) &x1[span*(i+8)], _MM_HINT_T1); _mm_prefetch((const char *) &x1[span*(i+8) + 8], _MM_HINT_T1); _mm_prefetch((const char *) &x2[span*(i+8)], _MM_HINT_T1); _mm_prefetch((const char *) &x2[span*(i+8) + 8], _MM_HINT_T1); _mm_prefetch((const char *) &x3[span*(i+8)], _MM_HINT_ET1); _mm_prefetch((const char *) &x3[span*(i+8) + 8], _MM_HINT_ET1); _mm_prefetch((const char *) &x1[span*(i+1)], _MM_HINT_T0); _mm_prefetch((const char *) &x1[span*(i+1) + 8], _MM_HINT_T0); _mm_prefetch((const char *) &x2[span*(i+1)], _MM_HINT_T0); _mm_prefetch((const char *) &x2[span*(i+1) + 8], _MM_HINT_T0); _mm_prefetch((const char *) &x3[span*(i+1)], _MM_HINT_ET0); _mm_prefetch((const char *) &x3[span*(i+1) + 8], _MM_HINT_ET0); double uX1[16] __attribute__((aligned(64))); double uX2[16] __attribute__((aligned(64))); double uX[16] __attribute__((aligned(64))); const double* v1 = &(x1[span * i]); const double* v2 = &(x2[span * i]); mic_fma4x16(v1, uX1, aLeft); mic_fma4x16(v2, uX2, aRight); #pragma ivdep #pragma vector aligned for(int l = 0; l < 16; ++l) { uX[l] = uX1[l] * uX2[l]; } double* v3 = &(x3[span * i]); mic_fma4x16(uX, v3, aEV); __m512d t1 = _mm512_load_pd(&v3[0]); t1 = _mm512_castsi512_pd(_mm512_and_epi64(_mm512_castpd_si512(t1), absMask_MIC)); double vmax1 = _mm512_reduce_max_pd(t1); __m512d t2 = _mm512_load_pd(&v3[8]); t2 = _mm512_castsi512_pd(_mm512_and_epi64(_mm512_castpd_si512(t2), absMask_MIC)); double vmax2 = _mm512_reduce_max_pd(t2); if(vmax1 < minlikelihood && vmax2 < minlikelihood) { /* t1 = _mm512_mul_pd(t1, twotothe256_MIC); _mm512_store_pd(&v3[0], t1); t2 = _mm512_mul_pd(t2, twotothe256_MIC); _mm512_store_pd(&v3[8], t2); */ #pragma vector aligned nontemporal for(int l = 0; l < span; l++) v3[l] *= twotothe256; addScale += wgt[i]; } } } break; default: // assert(0); break; } *scalerIncrement = addScale; } double evaluateGAMMA_MIC(int *wgt, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, const int n, double *diagptable) { double sum = 0.0; /* the left node is a tip */ if(tipX1) { double *aTipVec = tipVector; /* loop over the sites of this partition */ for (int i = 0; i < n; i++) { /* access pre-computed tip vector values via a lookup table */ const double *x1 = &(aTipVec[16 * tipX1[i]]); /* access the other(inner) node at the other end of the branch */ const double *x2 = &(x2_start[span * i]); double term = 0.; #pragma ivdep #pragma vector aligned for(int j = 0; j < 16; j++) term += x1[j] * x2[j] * diagptable[j]; term = log(0.25 * fabs(term)); sum += wgt[i] * term; } } else { for (int i = 0; i < n; i++) { _mm_prefetch((const char *) &x1_start[span*(i+8)], _MM_HINT_T1); _mm_prefetch((const char *) &x1_start[span*(i+8) + 8], _MM_HINT_T1); _mm_prefetch((const char *) &x2_start[span*(i+8)], _MM_HINT_T1); _mm_prefetch((const char *) &x2_start[span*(i+8) + 8], _MM_HINT_T1); _mm_prefetch((const char *) &x1_start[span*(i+1)], _MM_HINT_T0); _mm_prefetch((const char *) &x1_start[span*(i+1) + 8], _MM_HINT_T0); _mm_prefetch((const char *) &x2_start[span*(i+1)], _MM_HINT_T0); _mm_prefetch((const char *) &x2_start[span*(i+1) + 8], _MM_HINT_T0); const double *x1 = &(x1_start[span * i]); const double *x2 = &(x2_start[span * i]); double term = 0.; #pragma ivdep #pragma vector aligned for(int j = 0; j < 16; j++) term += x1[j] * x2[j] * diagptable[j]; term = log(0.25 * fabs(term)); sum += wgt[i] * term; } } return sum; } void sumGAMMA_MIC(int tipCase, double *sumtable, double *x1_start, double *x2_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n) { const double *aTipVec = tipVector; switch(tipCase) { case TIP_TIP: { #pragma unroll(8) for(int i = 0; i < n; i++) { const double *left = &(aTipVec[16 * tipX1[i]]); const double *right = &(aTipVec[16 * tipX2[i]]); #pragma ivdep #pragma vector aligned nontemporal for(int l = 0; l < 16; l++) { sumtable[i * span + l] = left[l] * right[l]; } } } break; case TIP_INNER: { #pragma unroll(8) for(int i = 0; i < n; i++) { _mm_prefetch((const char *) &x2_start[span*(i+32)], _MM_HINT_T1); _mm_prefetch((const char *) &x2_start[span*(i+32) + 8], _MM_HINT_T1); _mm_prefetch((const char *) &x2_start[span*(i+8)], _MM_HINT_T0); _mm_prefetch((const char *) &x2_start[span*(i+8) + 8], _MM_HINT_T0); const double *left = &(aTipVec[16 * tipX1[i]]); const double *right = &(x2_start[span * i]); #pragma ivdep #pragma vector aligned nontemporal for(int l = 0; l < 16; l++) { sumtable[i * span + l] = left[l] * right[l]; } } } break; case INNER_INNER: { #pragma unroll(8) for(int i = 0; i < n; i++) { _mm_prefetch((const char *) &x1_start[span*(i+16)], _MM_HINT_T1); _mm_prefetch((const char *) &x1_start[span*(i+16) + 8], _MM_HINT_T1); _mm_prefetch((const char *) &x2_start[span*(i+16)], _MM_HINT_T1); _mm_prefetch((const char *) &x2_start[span*(i+16) + 8], _MM_HINT_T1); _mm_prefetch((const char *) &x1_start[span*(i+4)], _MM_HINT_T0); _mm_prefetch((const char *) &x1_start[span*(i+4) + 8], _MM_HINT_T0); _mm_prefetch((const char *) &x2_start[span*(i+4)], _MM_HINT_T0); _mm_prefetch((const char *) &x2_start[span*(i+4) + 8], _MM_HINT_T0); const double *left = &(x1_start[span * i]); const double *right = &(x2_start[span * i]); #pragma ivdep #pragma vector aligned nontemporal for(int l = 0; l < 16; l++) { sumtable[i * span + l] = left[l] * right[l]; } } } break; // default: // assert(0); } } void coreGTRGAMMA_MIC(const int upper, double *sumtable, volatile double *ext_dlnLdlz, volatile double *ext_d2lnLdlz2, double *EIGN, double *gammaRates, double lz, int *wgt) { double diagptable0[16] __attribute__((aligned(64))); double diagptable1[16] __attribute__((aligned(64))); double diagptable2[16] __attribute__((aligned(64))); double diagptable01[16] __attribute__((aligned(64))); double diagptable02[16] __attribute__((aligned(64))); /* pre-compute the derivatives of the P matrix for all discrete GAMMA rates */ for(int i = 0; i < 4; i++) { const double ki = gammaRates[i]; const double kisqr = ki * ki; diagptable0[i*4] = 1.; diagptable1[i*4] = 0.; diagptable2[i*4] = 0.; for(int l = 1; l < 4; l++) { diagptable0[i * 4 + l] = exp(EIGN[l] * ki * lz); diagptable1[i * 4 + l] = EIGN[l] * ki; diagptable2[i * 4 + l] = EIGN[l] * EIGN[l] * kisqr; } } #pragma ivdep for(int i = 0; i < 16; i++) { diagptable01[i] = diagptable0[i] * diagptable1[i]; diagptable02[i] = diagptable0[i] * diagptable2[i]; } /* loop over sites in this partition */ const int aligned_width = upper % 8 == 0 ? upper / 8 : upper / 8 + 1; double dlnLBuf[8] __attribute__((aligned(64))); double d2lnLBuf[8] __attribute__((aligned(64))); for (int j = 0; j < 8; ++j) { dlnLBuf[j] = 0.; d2lnLBuf[j] = 0.; } __mmask16 k1 = _mm512_int2mask(0x000000FF); for (int i = 0; i < aligned_width; i++) { _mm_prefetch((const char *) &sumtable[i * span * 8], _MM_HINT_T0); _mm_prefetch((const char *) &sumtable[i * span * 8 + 8], _MM_HINT_T0); /* access the array with pre-computed values */ const double *sum = &sumtable[i * span * 8]; /* initial per-site likelihood and 1st and 2nd derivatives */ double invBuf[8] __attribute__((aligned(64))); double d1Buf[8] __attribute__((aligned(64))); double d2Buf[8] __attribute__((aligned(64))); __m512d invVec; __m512d d1Vec; __m512d d2Vec; int mask = 0x01; #pragma noprefetch sum #pragma unroll(8) for(int j = 0; j < 8; j++) { _mm_prefetch((const char *) &sum[span*(j+8)], _MM_HINT_T1); _mm_prefetch((const char *) &sum[span*(j+8) + 8], _MM_HINT_T1); _mm_prefetch((const char *) &sum[span*(j+1)], _MM_HINT_T0); _mm_prefetch((const char *) &sum[span*(j+1) + 8], _MM_HINT_T0); __m512d d0_1 = _mm512_load_pd(&diagptable0[0]); __m512d d0_2 = _mm512_load_pd(&diagptable0[8]); __m512d d01_1 = _mm512_load_pd(&diagptable01[0]); __m512d d01_2 = _mm512_load_pd(&diagptable01[8]); __m512d d02_1 = _mm512_load_pd(&diagptable02[0]); __m512d d02_2 = _mm512_load_pd(&diagptable02[8]); __m512d s_1 = _mm512_load_pd(&sum[j*16]); __m512d s_2 = _mm512_load_pd(&sum[j*16 + 8]); __m512d inv_1 = _mm512_mul_pd(d0_1, s_1); __m512d d1_1 = _mm512_mul_pd(d01_1, s_1); __m512d d2_1 = _mm512_mul_pd(d02_1, s_1); __m512d inv_2 = _mm512_fmadd_pd(d0_2, s_2, inv_1); __m512d d1_2 = _mm512_fmadd_pd(d01_2, s_2, d1_1); __m512d d2_2 = _mm512_fmadd_pd(d02_2, s_2, d2_1); __mmask8 k1 = _mm512_int2mask(mask); mask <<= 1; // reduce inv_2 = _mm512_add_pd (inv_2, _mm512_swizzle_pd(inv_2, _MM_SWIZ_REG_CDAB)); inv_2 = _mm512_add_pd (inv_2, _mm512_swizzle_pd(inv_2, _MM_SWIZ_REG_BADC)); inv_2 = _mm512_add_pd (inv_2, _mm512_castsi512_pd(_mm512_permute4f128_epi32(_mm512_castpd_si512(inv_2), _MM_PERM_BADC))); invVec = _mm512_mask_mov_pd(invVec, k1, inv_2); d1_2 = _mm512_add_pd (d1_2, _mm512_swizzle_pd(d1_2, _MM_SWIZ_REG_CDAB)); d1_2 = _mm512_add_pd (d1_2, _mm512_swizzle_pd(d1_2, _MM_SWIZ_REG_BADC)); d1_2 = _mm512_add_pd (d1_2, _mm512_castsi512_pd(_mm512_permute4f128_epi32(_mm512_castpd_si512(d1_2), _MM_PERM_BADC))); d1Vec = _mm512_mask_mov_pd(d1Vec, k1, d1_2); d2_2 = _mm512_add_pd (d2_2, _mm512_swizzle_pd(d2_2, _MM_SWIZ_REG_CDAB)); d2_2 = _mm512_add_pd (d2_2, _mm512_swizzle_pd(d2_2, _MM_SWIZ_REG_BADC)); d2_2 = _mm512_add_pd (d2_2, _mm512_castsi512_pd(_mm512_permute4f128_epi32(_mm512_castpd_si512(d2_2), _MM_PERM_BADC))); d2Vec = _mm512_mask_mov_pd(d2Vec, k1, d2_2); } _mm512_store_pd(&invBuf[0], invVec); _mm512_store_pd(&d1Buf[0], d1Vec); _mm512_store_pd(&d2Buf[0], d2Vec); #pragma ivdep #pragma vector aligned for (int j = 0; j < 8; ++j) { const double inv_Li = 1.0 / invBuf[j]; const double d1 = d1Buf[j] * inv_Li; const double d2 = d2Buf[j] * inv_Li; dlnLBuf[j] += wgt[i * 8 + j] * d1; d2lnLBuf[j] += wgt[i * 8 + j] * (d2 - d1 * d1); } } // site loop double dlnLdlz = 0.; double d2lnLdlz2 = 0.; for (int j = 0; j < 8; ++j) { dlnLdlz += dlnLBuf[j]; d2lnLdlz2 += d2lnLBuf[j]; } *ext_dlnLdlz = dlnLdlz; *ext_d2lnLdlz2 = d2lnLdlz2; } ExaML-3.0.21/examl/models.c000066400000000000000000005526421330315463200153160ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands * of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifndef WIN32 #include #include #include #include #endif #include #include #include #include #include #include #include "axml.h" #ifdef __MIC_NATIVE #include "mic_native.h" #endif extern int optimizeRatesInvocations; extern int optimizeRateCategoryInvocations; extern int optimizeAlphaInvocations; extern int optimizeTTRatioInvocations; extern int optimizeInvarInvocations; extern const unsigned int bitVectorSecondary[256]; extern const unsigned int bitVector32[33]; extern const unsigned int bitVectorAA[23]; extern const unsigned int bitVectorIdentity[256]; extern const partitionLengths pLengths[MAX_MODEL]; //extern FILE *byteFile; void putWAG(double *ext_initialRates) { double scaler, q[20][20], daa[400]; int i, j, r; daa[ 1*20+ 0] = 55.15710; daa[ 2*20+ 0] = 50.98480; daa[ 2*20+ 1] = 63.53460; daa[ 3*20+ 0] = 73.89980; daa[ 3*20+ 1] = 14.73040; daa[ 3*20+ 2] = 542.94200; daa[ 4*20+ 0] = 102.70400; daa[ 4*20+ 1] = 52.81910; daa[ 4*20+ 2] = 26.52560; daa[ 4*20+ 3] = 3.02949; daa[ 5*20+ 0] = 90.85980; daa[ 5*20+ 1] = 303.55000; daa[ 5*20+ 2] = 154.36400; daa[ 5*20+ 3] = 61.67830; daa[ 5*20+ 4] = 9.88179; daa[ 6*20+ 0] = 158.28500; daa[ 6*20+ 1] = 43.91570; daa[ 6*20+ 2] = 94.71980; daa[ 6*20+ 3] = 617.41600; daa[ 6*20+ 4] = 2.13520; daa[ 6*20+ 5] = 546.94700; daa[ 7*20+ 0] = 141.67200; daa[ 7*20+ 1] = 58.46650; daa[ 7*20+ 2] = 112.55600; daa[ 7*20+ 3] = 86.55840; daa[ 7*20+ 4] = 30.66740; daa[ 7*20+ 5] = 33.00520; daa[ 7*20+ 6] = 56.77170; daa[ 8*20+ 0] = 31.69540; daa[ 8*20+ 1] = 213.71500; daa[ 8*20+ 2] = 395.62900; daa[ 8*20+ 3] = 93.06760; daa[ 8*20+ 4] = 24.89720; daa[ 8*20+ 5] = 429.41100; daa[ 8*20+ 6] = 57.00250; daa[ 8*20+ 7] = 24.94100; daa[ 9*20+ 0] = 19.33350; daa[ 9*20+ 1] = 18.69790; daa[ 9*20+ 2] = 55.42360; daa[ 9*20+ 3] = 3.94370; daa[ 9*20+ 4] = 17.01350; daa[ 9*20+ 5] = 11.39170; daa[ 9*20+ 6] = 12.73950; daa[ 9*20+ 7] = 3.04501; daa[ 9*20+ 8] = 13.81900; daa[10*20+ 0] = 39.79150; daa[10*20+ 1] = 49.76710; daa[10*20+ 2] = 13.15280; daa[10*20+ 3] = 8.48047; daa[10*20+ 4] = 38.42870; daa[10*20+ 5] = 86.94890; daa[10*20+ 6] = 15.42630; daa[10*20+ 7] = 6.13037; daa[10*20+ 8] = 49.94620; daa[10*20+ 9] = 317.09700; daa[11*20+ 0] = 90.62650; daa[11*20+ 1] = 535.14200; daa[11*20+ 2] = 301.20100; daa[11*20+ 3] = 47.98550; daa[11*20+ 4] = 7.40339; daa[11*20+ 5] = 389.49000; daa[11*20+ 6] = 258.44300; daa[11*20+ 7] = 37.35580; daa[11*20+ 8] = 89.04320; daa[11*20+ 9] = 32.38320; daa[11*20+10] = 25.75550; daa[12*20+ 0] = 89.34960; daa[12*20+ 1] = 68.31620; daa[12*20+ 2] = 19.82210; daa[12*20+ 3] = 10.37540; daa[12*20+ 4] = 39.04820; daa[12*20+ 5] = 154.52600; daa[12*20+ 6] = 31.51240; daa[12*20+ 7] = 17.41000; daa[12*20+ 8] = 40.41410; daa[12*20+ 9] = 425.74600; daa[12*20+10] = 485.40200; daa[12*20+11] = 93.42760; daa[13*20+ 0] = 21.04940; daa[13*20+ 1] = 10.27110; daa[13*20+ 2] = 9.61621; daa[13*20+ 3] = 4.67304; daa[13*20+ 4] = 39.80200; daa[13*20+ 5] = 9.99208; daa[13*20+ 6] = 8.11339; daa[13*20+ 7] = 4.99310; daa[13*20+ 8] = 67.93710; daa[13*20+ 9] = 105.94700; daa[13*20+10] = 211.51700; daa[13*20+11] = 8.88360; daa[13*20+12] = 119.06300; daa[14*20+ 0] = 143.85500; daa[14*20+ 1] = 67.94890; daa[14*20+ 2] = 19.50810; daa[14*20+ 3] = 42.39840; daa[14*20+ 4] = 10.94040; daa[14*20+ 5] = 93.33720; daa[14*20+ 6] = 68.23550; daa[14*20+ 7] = 24.35700; daa[14*20+ 8] = 69.61980; daa[14*20+ 9] = 9.99288; daa[14*20+10] = 41.58440; daa[14*20+11] = 55.68960; daa[14*20+12] = 17.13290; daa[14*20+13] = 16.14440; daa[15*20+ 0] = 337.07900; daa[15*20+ 1] = 122.41900; daa[15*20+ 2] = 397.42300; daa[15*20+ 3] = 107.17600; daa[15*20+ 4] = 140.76600; daa[15*20+ 5] = 102.88700; daa[15*20+ 6] = 70.49390; daa[15*20+ 7] = 134.18200; daa[15*20+ 8] = 74.01690; daa[15*20+ 9] = 31.94400; daa[15*20+10] = 34.47390; daa[15*20+11] = 96.71300; daa[15*20+12] = 49.39050; daa[15*20+13] = 54.59310; daa[15*20+14] = 161.32800; daa[16*20+ 0] = 212.11100; daa[16*20+ 1] = 55.44130; daa[16*20+ 2] = 203.00600; daa[16*20+ 3] = 37.48660; daa[16*20+ 4] = 51.29840; daa[16*20+ 5] = 85.79280; daa[16*20+ 6] = 82.27650; daa[16*20+ 7] = 22.58330; daa[16*20+ 8] = 47.33070; daa[16*20+ 9] = 145.81600; daa[16*20+10] = 32.66220; daa[16*20+11] = 138.69800; daa[16*20+12] = 151.61200; daa[16*20+13] = 17.19030; daa[16*20+14] = 79.53840; daa[16*20+15] = 437.80200; daa[17*20+ 0] = 11.31330; daa[17*20+ 1] = 116.39200; daa[17*20+ 2] = 7.19167; daa[17*20+ 3] = 12.97670; daa[17*20+ 4] = 71.70700; daa[17*20+ 5] = 21.57370; daa[17*20+ 6] = 15.65570; daa[17*20+ 7] = 33.69830; daa[17*20+ 8] = 26.25690; daa[17*20+ 9] = 21.24830; daa[17*20+10] = 66.53090; daa[17*20+11] = 13.75050; daa[17*20+12] = 51.57060; daa[17*20+13] = 152.96400; daa[17*20+14] = 13.94050; daa[17*20+15] = 52.37420; daa[17*20+16] = 11.08640; daa[18*20+ 0] = 24.07350; daa[18*20+ 1] = 38.15330; daa[18*20+ 2] = 108.60000; daa[18*20+ 3] = 32.57110; daa[18*20+ 4] = 54.38330; daa[18*20+ 5] = 22.77100; daa[18*20+ 6] = 19.63030; daa[18*20+ 7] = 10.36040; daa[18*20+ 8] = 387.34400; daa[18*20+ 9] = 42.01700; daa[18*20+10] = 39.86180; daa[18*20+11] = 13.32640; daa[18*20+12] = 42.84370; daa[18*20+13] = 645.42800; daa[18*20+14] = 21.60460; daa[18*20+15] = 78.69930; daa[18*20+16] = 29.11480; daa[18*20+17] = 248.53900; daa[19*20+ 0] = 200.60100; daa[19*20+ 1] = 25.18490; daa[19*20+ 2] = 19.62460; daa[19*20+ 3] = 15.23350; daa[19*20+ 4] = 100.21400; daa[19*20+ 5] = 30.12810; daa[19*20+ 6] = 58.87310; daa[19*20+ 7] = 18.72470; daa[19*20+ 8] = 11.83580; daa[19*20+ 9] = 782.13000; daa[19*20+10] = 180.03400; daa[19*20+11] = 30.54340; daa[19*20+12] = 205.84500; daa[19*20+13] = 64.98920; daa[19*20+14] = 31.48870; daa[19*20+15] = 23.27390; daa[19*20+16] = 138.82300; daa[19*20+17] = 36.53690; daa[19*20+18] = 31.47300; for(i = 0; i < 20; i++) for(j = 0; j < 20; j++) q[i][j] = 0.0; for (i=0; i<20; i++) for (j=0; j max) max = temp; } scaler = AA_SCALE / max; /* SCALING HAS BEEN RE-INTRODUCED TO RESOLVE NUMERICAL PROBLEMS */ r = 0; for(i = 0; i < 19; i++) { for(j = i + 1; j < 20; j++) { q[i][j] *= scaler; assert(q[i][j] <= AA_SCALE_PLUS_EPSILON); initialRates[r++] = q[i][j]; } } } static void mytred2(double **a, const int n, double *d, double *e) { int l, k, j, i; double scale, hh, h, g, f; for (i = n; i > 1; i--) { l = i - 1; h = 0.0; scale = 0.0; if (l > 1) { for (k = 1; k <= l; k++) scale += fabs(a[k - 1][i - 1]); if (scale == 0.0) e[i - 1] = a[l - 1][i - 1]; else { for (k = 1; k <= l; k++) { a[k - 1][i - 1] /= scale; h += a[k - 1][i - 1] * a[k - 1][i - 1]; } f = a[l - 1][i - 1]; g = ((f > 0) ? -sqrt(h) : sqrt(h)); /* diff */ e[i - 1] = scale * g; h -= f * g; a[l - 1][i - 1] = f - g; f = 0.0; for (j = 1; j <= l; j++) { a[i - 1][j - 1] = a[j - 1][i - 1] / h; g = 0.0; for (k = 1; k <= j; k++) g += a[k - 1][j - 1] * a[k - 1][i - 1]; for (k = j + 1; k <= l; k++) g += a[j - 1][k - 1] * a[k - 1][i - 1]; e[j - 1] = g / h; f += e[j - 1] * a[j - 1][i - 1]; } hh = f / (h + h); for (j = 1; j <= l; j++) { f = a[j - 1][i - 1]; g = e[j - 1] - hh * f; e[j - 1] = g; for (k = 1; k <= j; k++) a[k - 1][j - 1] -= (f * e[k - 1] + g * a[k - 1][i - 1]); } } } else e[i - 1] = a[l - 1][i - 1]; d[i - 1] = h; } d[0] = 0.0; e[0] = 0.0; for (i = 1; i <= n; i++) { l = i - 1; if (d[i - 1] != 0.0) { for (j = 1; j <= l; j++) { g = 0.0; for (k = 1; k <= l; k++) g += a[k - 1][i - 1] * a[j - 1][k - 1]; for(k = 1; k <= l; k++) a[j - 1][k - 1] -= g * a[i - 1][k - 1]; } } d[i - 1] = a[i - 1][i - 1]; a[i - 1][i - 1] = 1.0; for (j = 1; j <= l; j++) a[i - 1][j - 1] = a[j - 1][i - 1] = 0.0; } } /*#define MYSIGN(a,b) ((b)<0 ? -fabs(a) : fabs(a))*/ static int mytqli(double *d, double *e, const int n, double **z) { int m, l, iter, i, k; double s, r, p, g, f, dd, c, b; for (i = 2; i <= n; i++) e[i - 2] = e[i - 1]; e[n - 1] = 0.0; for (l = 1; l <= n; l++) { iter = 0; do { for (m = l; m <= n - 1; m++) { dd = fabs(d[m - 1]) + fabs(d[m]); if (fabs(e[m - 1]) + dd == dd) break; } if (m != l) { assert(iter < 30); g = (d[l] - d[l - 1]) / (2.0 * e[l - 1]); r = sqrt((g * g) + 1.0); g = d[m - 1] - d[l - 1] + e[l - 1] / (g + ((g < 0)?-fabs(r):fabs(r)));/*MYSIGN(r, g));*/ s = c = 1.0; p = 0.0; for (i = m - 1; i >= l; i--) { f = s * e[i - 1]; b = c * e[i - 1]; if (fabs(f) >= fabs(g)) { c = g / f; r = sqrt((c * c) + 1.0); e[i] = f * r; c *= (s = 1.0 / r); } else { s = f / g; r = sqrt((s * s) + 1.0); e[i] = g * r; s *= (c = 1.0 / r); } g = d[i] - p; r = (d[i - 1] - g) * s + 2.0 * c * b; p = s * r; d[i] = g + p; g = c * r - b; for (k = 1; k <= n; k++) { f = z[i][k-1]; z[i][k-1] = s * z[i - 1][k - 1] + c * f; z[i - 1][k - 1] = c * z[i - 1][k - 1] - s * f; } } d[l - 1] = d[l - 1] - p; e[l - 1] = g; e[m - 1] = 0.0; } } while (m != l); } return (1); } static void makeEigen(double **_a, const int n, double *d, double *e) { mytred2(_a, n, d, e); mytqli(d, e, n, _a); } static void initGeneric(const int n, const unsigned int *valueVector, int valueVectorLength, double *ext_EIGN, double *EV, double *EI, double *frequencies, double *ext_initialRates, double *tipVector, int model) { double fracchange = 0.0, **r, **a, **EIGV, *initialRates = ext_initialRates, *f, *e, *d, *invfreq, *EIGN, *eptr; int i, j, k, m, l; r = (double **)malloc(n * sizeof(double *)); EIGV = (double **)malloc(n * sizeof(double *)); a = (double **)malloc(n * sizeof(double *)); for(i = 0; i < n; i++) { a[i] = (double*)malloc(n * sizeof(double)); EIGV[i] = (double*)malloc(n * sizeof(double)); r[i] = (double*)malloc(n * sizeof(double)); } f = (double*)malloc(n * sizeof(double)); e = (double*)malloc(n * sizeof(double)); d = (double*)malloc(n * sizeof(double)); invfreq = (double*)malloc(n * sizeof(double)); EIGN = (double*)malloc(n * sizeof(double)); for(l = 0; l < n; l++) f[l] = frequencies[l]; i = 0; for(j = 0; j < n; j++) for(k = 0; k < n; k++) r[j][k] = 0.0; for(j = 0; j < n - 1; j++) for (k = j+1; k < n; k++) r[j][k] = initialRates[i++]; for (j = 0; j < n; j++) { r[j][j] = 0.0; for (k = 0; k < j; k++) r[j][k] = r[k][j]; } for (j = 0; j< n; j++) for (k = 0; k< n; k++) fracchange += f[j] * r[j][k] * f[k]; m = 0; for(i=0; i< n; i++) a[i][i] = 0; /* assert(r[n - 2][n - 1] == 1.0);*/ for(i=0; i < n; i++) { for(j=i+1; j < n; j++) { double factor = initialRates[m++]; a[i][j] = a[j][i] = factor * sqrt( f[i] * f[j]); a[i][i] -= factor * f[j]; a[j][j] -= factor * f[i]; } } makeEigen(a, n, d, e); for(i=0; i -1e-8) { if (i != 0) { double tmp = d[i], sum=0; d[i] = d[0]; d[0] = tmp; for (j=0; j < n; j++) { tmp = a[i][j]; a[i][j] = a[0][j]; sum += (a[0][j] = tmp); } for (j=0; j < n; j++) a[0][j] /= sum; } break; } } for (i=0; i< n; i++) { EIGN[i] = -d[i]; for (j=0; j 0.0); } eptr = EV; for(i = 0; i < n; i++) for(j = 0; j < n; j++) { *eptr++ = EIGV[i][j]; } for(i = 0; i < n; i++) for(j = 0; j < n; j++) { if(j == 0) EI[i * n + j] = 1.0; else EI[i * n + j] = EV[i * n + j] * invfreq[i]; } /* printf("EIGN\n"); for(i = 0; i < n; i++) printf("%f ", ext_EIGN[i]); printf("\n"); printf("EI\n"); for(i = 0; i < n; i++) { for(j = 0; j < n; j++) { printf("%f ", EI[i * n + j]); } printf("\n"); } */ for(i=0; i < valueVectorLength; i++) { unsigned int value = valueVector[i]; for(j = 0; j < n; j++) tipVector[i * n + j] = 0; if(value > 0) { for (j = 0; j < n; j++) { if ((value >> j) & 1) { int l; for(l = 0; l < n; l++) tipVector[i * n + l] += EIGV[j][l]; } } } } for(i = 0; i < valueVectorLength; i++) { for(j = 0; j < n; j++) if(tipVector[i * n + j] > MAX_TIP_EV) tipVector[i * n + j] = MAX_TIP_EV; } for(i = 0; i < n; i++) { free(EIGV[i]); free(a[i]); free(r[i]); } free(r); free(a); free(EIGV); free(f); free(e); free(d); free(invfreq); free(EIGN); } void initReversibleGTR(tree *tr, int model) { double *ext_EIGN = tr->partitionData[model].EIGN, *EV = tr->partitionData[model].EV, *EI = tr->partitionData[model].EI, *frequencies = tr->partitionData[model].frequencies, *ext_initialRates = tr->partitionData[model].substRates, *tipVector = tr->partitionData[model].tipVector; int states = tr->partitionData[model].states; switch(tr->partitionData[model].dataType) { case GENERIC_32: case GENERIC_64: case SECONDARY_DATA_6: case SECONDARY_DATA_7: case SECONDARY_DATA: case DNA_DATA: case BINARY_DATA: initGeneric(states, getBitVector(tr->partitionData[model].dataType), getUndetermined(tr->partitionData[model].dataType) + 1, ext_EIGN, EV, EI, frequencies, ext_initialRates, tipVector, model); break; case AA_DATA: if(tr->partitionData[model].protModels != GTR) { double f[20]; if(tr->partitionData[model].protModels == LG4M || tr->partitionData[model].protModels == LG4X) { int i; for(i = 0; i < 4; i++) { initProtMat(f, tr->partitionData[model].protModels, &(tr->partitionData[model].substRates_LG4[i][0]), i); if(!tr->partitionData[model].protFreqs && !tr->partitionData[model].optimizeBaseFrequencies) memcpy(tr->partitionData[model].frequencies_LG4[i], f, 20 * sizeof(double)); //for(l = 0; l < 20; l++) // tr->partitionData[model].frequencies_LG4[i][l] = f[l]; else memcpy(tr->partitionData[model].frequencies_LG4[i], frequencies, 20 * sizeof(double)); } } else { if(tr->partitionData[model].protModels == AUTO) initProtMat(f, tr->partitionData[model].autoProtModels, ext_initialRates, 0); else initProtMat(f, tr->partitionData[model].protModels, ext_initialRates, 0); /*if(adef->protEmpiricalFreqs && tr->NumberOfModels == 1) assert(tr->partitionData[model].protFreqs);*/ if(tr->partitionData[model].protModels == AUTO) { if(tr->partitionData[model].protFreqs) memcpy(frequencies, f, 20 * sizeof(double)); else memcpy(frequencies, tr->partitionData[model].empiricalFrequencies, 20 * sizeof(double)); } else { if(!tr->partitionData[model].optimizeBaseFrequencies) { if(!tr->partitionData[model].protFreqs) { memcpy(frequencies, f, 20 * sizeof(double)); /*for(l = 0; l < 20; l++) frequencies[l] = f[l]; */ } else { memcpy(frequencies, tr->partitionData[model].empiricalFrequencies, 20 * sizeof(double)); /*for(l = 0; l < 20; l++) frequencies[l] = tr->partitionData[model].empiricalFrequencies[l]; */ } } } } } if(tr->partitionData[model].protModels == LG4M || tr->partitionData[model].protModels == LG4X) { int i; for(i = 0; i < 4; i++) initGeneric(states, bitVectorAA, 23, tr->partitionData[model].rawEIGN_LG4[i], tr->partitionData[model].EV_LG4[i], tr->partitionData[model].EI_LG4[i], tr->partitionData[model].frequencies_LG4[i], tr->partitionData[model].substRates_LG4[i], tr->partitionData[model].tipVector_LG4[i], model); scaleLG4X_EIGN(tr, model); } else initGeneric(states, bitVectorAA, 23, ext_EIGN, EV, EI, frequencies, ext_initialRates, tipVector, model); break; default: assert(0); } #ifdef __MIC_NATIVE if(tr->partitionData[model].protModels == LG4M || tr->partitionData[model].protModels == LG4X) updateModel_LG4_MIC(&tr->partitionData[model]); else updateModel_MIC(&tr->partitionData[model]); #endif } double LnGamma (double alpha) { /* returns ln(gamma(alpha)) for alpha>0, accurate to 10 decimal places. Stirling's formula is used for the central polynomial part of the procedure. Pike MC & Hill ID (1966) Algorithm 291: Logarithm of the gamma function. Communications of the Association for Computing Machinery, 9:684 */ double x, f, z, result; x = alpha; f = 0.0; if ( x < 7.0) { f = 1.0; z = alpha - 1.0; while ((z = z + 1.0) < 7.0) { f *= z; } x = z; assert(f != 0.0); f=-log(f); } z = 1/(x*x); result = f + (x-0.5)*log(x) - x + .918938533204673 + (((-.000595238095238*z+.000793650793651)*z-.002777777777778)*z +.083333333333333)/x; return result; } double IncompleteGamma (double x, double alpha, double ln_gamma_alpha) { /* returns the incomplete gamma ratio I(x,alpha) where x is the upper limit of the integration and alpha is the shape parameter. returns (-1) if in error ln_gamma_alpha = ln(Gamma(alpha)), is almost redundant. (1) series expansion if (alpha>x || x<=1) (2) continued fraction otherwise RATNEST FORTRAN by Bhattacharjee GP (1970) The incomplete gamma integral. Applied Statistics, 19: 285-287 (AS32) */ int i; double p=alpha, g=ln_gamma_alpha; double accurate=1e-8, overflow=1e30; double factor, gin=0, rn=0, a=0,b=0,an=0,dif=0, term=0, pn[6]; if (x==0) return (0); if (x<0 || p<=0) return (-1); factor=exp(p*log(x)-x-g); if (x>1 && x>=p) goto l30; /* (1) series expansion */ gin=1; term=1; rn=p; l20: rn++; term*=x/rn; gin+=term; if (term > accurate) goto l20; gin*=factor/p; goto l50; l30: /* (2) continued fraction */ a=1-p; b=a+x+1; term=0; pn[0]=1; pn[1]=x; pn[2]=x+1; pn[3]=x*b; gin=pn[2]/pn[3]; l32: a++; b+=2; term++; an=a*term; for (i=0; i<2; i++) pn[i+4]=b*pn[i+2]-an*pn[i]; if (pn[5] == 0) goto l35; rn=pn[4]/pn[5]; dif=fabs(gin-rn); if (dif>accurate) goto l34; if (dif<=accurate*rn) goto l42; l34: gin=rn; l35: for (i=0; i<4; i++) pn[i]=pn[i+2]; if (fabs(pn[4]) < overflow) goto l32; for (i=0; i<4; i++) pn[i]/=overflow; goto l32; l42: gin=1-factor*gin; l50: return (gin); } double PointNormal (double prob) { /* returns z so that Prob{x.999998 || v<=0) return (-1); g = LnGamma(v/2); xx=v/2; c=xx-1; if (v >= -1.24*log(p)) goto l1; ch=pow((p*xx*exp(g+xx*aa)), 1/xx); if (ch-e<0) return (ch); goto l4; l1: if (v>.32) goto l3; ch=0.4; a=log(1-p); l2: q=ch; p1=1+ch*(4.67+ch); p2=ch*(6.73+ch*(6.66+ch)); t=-0.5+(4.67+2*ch)/p1 - (6.73+ch*(13.32+3*ch))/p2; ch-=(1-exp(a+g+.5*ch+c*aa)*p2/p1)/t; if (fabs(q/ch-1)-.01 <= 0) goto l4; else goto l2; l3: x=PointNormal (p); p1=0.222222/v; ch=v*pow((x*sqrt(p1)+1-p1), 3.0); if (ch>2.2*v+6) ch=-2*(log(1-p)-c*log(.5*ch)+g); l4: q=ch; p1=.5*ch; if ((t=IncompleteGamma (p1, xx, g))< 0.0) { printf ("IncompleteGamma \n"); return (-1); } p2=p-t; t=p2*exp(xx*aa+g+p1-c*log(ch)); b=t/ch; a=0.5*t-b*c; s1=(210+a*(140+a*(105+a*(84+a*(70+60*a))))) / 420; s2=(420+a*(735+a*(966+a*(1141+1278*a))))/2520; s3=(210+a*(462+a*(707+932*a)))/2520; s4=(252+a*(672+1182*a)+c*(294+a*(889+1740*a)))/5040; s5=(84+264*a+c*(175+606*a))/2520; s6=(120+c*(346+127*c))/5040; ch+=t*(1+0.5*t*s1-b*c*(s1-b*(s2-b*(s3-b*(s4-b*(s5-b*s6)))))); if (fabs(q/ch-1) > e) goto l4; return (ch); } void makeGammaCats(double alpha, double *gammaRates, int K, boolean useMedian) { int i; double factor = alpha / alpha * K, lnga1, alfa = alpha, beta = alpha, *gammaProbs = (double *)malloc(K * sizeof(double)); /* Note that ALPHA_MIN setting is somewhat critical due to */ /* numerical instability caused by very small rate[0] values */ /* induced by low alpha values around 0.01 */ assert(alfa >= ALPHA_MIN); if(useMedian) { double middle = 1.0 / (2.0*K), t = 0.0; for(i = 0; i < K; i++) gammaRates[i] = PointGamma((double)(i * 2 + 1) * middle, alfa, beta); for (i = 0; i < K; i++) t += gammaRates[i]; for( i = 0; i < K; i++) gammaRates[i] *= factor / t; } else { lnga1 = LnGamma(alfa + 1); for (i = 0; i < K - 1; i++) gammaProbs[i] = PointGamma((i + 1.0) / K, alfa, beta); for (i = 0; i < K - 1; i++) gammaProbs[i] = IncompleteGamma(gammaProbs[i] * beta, alfa + 1, lnga1); gammaRates[0] = gammaProbs[0] * factor; gammaRates[K - 1] = (1 - gammaProbs[K - 2]) * factor; for (i= 1; i < K - 1; i++) gammaRates[i] = (gammaProbs[i] - gammaProbs[i - 1]) * factor; } /* assert(gammaRates[0] >= 0.00000000000000000000000000000044136090435925743185910935350715027016962154188875); */ free(gammaProbs); return; } static void setRates(double *r, int rates) { int i; //changed to 1.0 instead of 0.5 for making the //implementation of an interface function to set other models //than GTR easier for(i = 0; i < rates - 1; i++) r[i] = 1.0; r[rates - 1] = 1.0; } void initRateMatrix(tree *tr) { int model; for(model = 0; model < tr->NumberOfModels; model++) { int i, states = tr->partitionData[model].states, rates = (states * states - states) / 2; switch(tr->partitionData[model].dataType) { case BINARY_DATA: case DNA_DATA: case SECONDARY_DATA: case SECONDARY_DATA_6: case SECONDARY_DATA_7: setRates(tr->partitionData[model].substRates, rates); break; case GENERIC_32: case GENERIC_64: switch(tr->multiStateModel) { case ORDERED_MULTI_STATE: { int j, k, i = 0; for(j = 0; j < states; j++) for(k = j + 1; k < states; k++) tr->partitionData[model].substRates[i++] = (double)(k - j); assert(i == rates); } break; case MK_MULTI_STATE: for(i = 0; i < rates; i++) tr->partitionData[model].substRates[i] = 1.0; break; case GTR_MULTI_STATE: setRates(tr->partitionData[model].substRates, rates); break; default: assert(0); } break; case AA_DATA: if(tr->partitionData[model].protModels == GTR) putWAG(tr->partitionData[model].substRates); break; default: assert(0); } if(tr->partitionData[model].nonGTR) { assert(tr->partitionData[model].dataType == SECONDARY_DATA || tr->partitionData[model].dataType == SECONDARY_DATA_6 || tr->partitionData[model].dataType == SECONDARY_DATA_7); for(i = 0; i < rates; i++) { if(tr->partitionData[model].symmetryVector[i] == -1) tr->partitionData[model].substRates[i] = 0.0; else { if(tr->partitionData[model].symmetryVector[i] == tr->partitionData[model].symmetryVector[rates - 1]) tr->partitionData[model].substRates[i] = 1.0; } } } } } static void setSymmetry(int *s, int *sDest, const int sCount, int *f, int *fDest, const int fCount) { int i; for(i = 0; i < sCount; i++) sDest[i] = s[i]; for(i = 0; i < fCount; i++) fDest[i] = f[i]; } static void setupSecondaryStructureSymmetries(tree *tr) { int model; for(model = 0; model < tr->NumberOfModels; model++) { if(tr->partitionData[model].dataType == SECONDARY_DATA || tr->partitionData[model].dataType == SECONDARY_DATA_6 || tr->partitionData[model].dataType == SECONDARY_DATA_7) { switch(tr->secondaryStructureModel) { case SEC_6_A: tr->partitionData[model].nonGTR = FALSE; break; case SEC_6_B: { int f[6] = {0, 1, 2, 3, 4, 5}; int s[15] = {2, 0, 1, 2, 2, 2, 2, 0, 1, 1, 2, 2, 2, 2, 1}; setSymmetry(s, tr->partitionData[model].symmetryVector, 15, f, tr->partitionData[model].frequencyGrouping, 6); tr->partitionData[model].nonGTR = TRUE; } break; case SEC_6_C: { int f[6] = {0, 2, 2, 1, 0, 1}; int s[15] = {2, 0, 1, 2, 2, 2, 2, 0, 1, 1, 2, 2, 2, 2, 1}; setSymmetry(s, tr->partitionData[model].symmetryVector, 15, f, tr->partitionData[model].frequencyGrouping, 6); tr->partitionData[model].nonGTR = TRUE; } break; case SEC_6_D: { int f[6] = {0, 2, 2, 1, 0, 1}; int s[15] = {2, -1, 1, 2, 2, 2, 2, -1, 1, 1, 2, 2, 2, 2, 1}; setSymmetry(s, tr->partitionData[model].symmetryVector, 15, f, tr->partitionData[model].frequencyGrouping, 6); tr->partitionData[model].nonGTR = TRUE; } break; case SEC_6_E: { int f[6] = {0, 1, 2, 3, 4, 5}; int s[15] = {2, -1, 1, 2, 2, 2, 2, -1, 1, 1, 2, 2, 2, 2, 1}; setSymmetry(s, tr->partitionData[model].symmetryVector, 15, f, tr->partitionData[model].frequencyGrouping, 6); tr->partitionData[model].nonGTR = TRUE; } break; case SEC_7_A: tr->partitionData[model].nonGTR = FALSE; break; case SEC_7_B: { int f[7] = {0, 2, 2, 1, 0, 1, 3}; int s[21] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; setSymmetry(s, tr->partitionData[model].symmetryVector, 21, f, tr->partitionData[model].frequencyGrouping, 7); tr->partitionData[model].nonGTR = TRUE; } break; case SEC_7_C: { int f[7] = {0, 1, 2, 3, 4, 5, 6}; int s[21] = {-1, -1, 0, -1, -1, 4, -1, -1, -1, 3, 5, 1, -1, -1, 6, -1, -1, 7, 2, 8, 9}; setSymmetry(s, tr->partitionData[model].symmetryVector, 21, f, tr->partitionData[model].frequencyGrouping, 7); tr->partitionData[model].nonGTR = TRUE; } break; case SEC_7_D: { int f[7] = {0, 1, 2, 3, 4, 5, 6}; int s[21] = {2, 0, 1, 2, 2, 3, 2, 2, 0, 1, 3, 1, 2, 2, 3, 2, 2, 3, 1, 3, 3}; setSymmetry(s, tr->partitionData[model].symmetryVector, 21, f, tr->partitionData[model].frequencyGrouping, 7); tr->partitionData[model].nonGTR = TRUE; } break; case SEC_7_E: { int f[7] = {0, 1, 2, 3, 4, 5, 6}; int s[21] = {-1, -1, 0, -1, -1, 1, -1, -1, -1, 0, 1, 0, -1, -1, 1, -1, -1, 1, 0, 1, 1}; setSymmetry(s, tr->partitionData[model].symmetryVector, 21, f, tr->partitionData[model].frequencyGrouping, 7); tr->partitionData[model].nonGTR = TRUE; } break; case SEC_7_F: { int f[7] = {0, 2, 2, 1, 0, 1, 3}; int s[21] = {2, 0, 1, 2, 2, 3, 2, 2, 0, 1, 3, 1, 2, 2, 3, 2, 2, 3, 1, 3, 3}; setSymmetry(s, tr->partitionData[model].symmetryVector, 21, f, tr->partitionData[model].frequencyGrouping, 7); tr->partitionData[model].nonGTR = TRUE; } break; case SEC_16: tr->partitionData[1].nonGTR = FALSE; break; case SEC_16_A: { int f[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; int s[120] = {/* AA */ 4, 4, 3, 4, -1, -1, -1, 4, -1, -1, -1, 3, -1, -1, -1, /* AC */ 4, 3, -1, 4, -1, -1, -1, 3, -1, -1, -1, 4, -1, -1, /* AG */ 3, -1, -1, 3, -1, -1, -1, 4, -1, -1, -1, 3, -1, /* AU */ -1, -1, 2, 3, -1, 0, -1, 1, 2, -1, 2, 3, /* CA */ 4, 3, 4, 4, -1, -1, -1, 3, -1, -1, -1, /* CC */ 3, 4, -1, 3, -1, -1, -1, 4, -1, -1, /* CG */ 3, -1, 2, 3, 2, 0, -1, 1, -1, /* CU */ -1, -1, -1, 3, -1, -1, -1, 4, /* GA */ 3, 4, 3, 3, -1, -1, -1, /* GC */ 3, 1, 2, 3, 2, -1, /* GG */ 3, -1, -1, 3, -1, /* GU */ 2, -1, 2, 3, /* UA */ 3, 1, 3, /* UC */ 3, 4, /* UG */ 3}; setSymmetry(s, tr->partitionData[model].symmetryVector, 120, f, tr->partitionData[model].frequencyGrouping, 16); tr->partitionData[model].nonGTR = TRUE; } break; case SEC_16_B: { int f[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; int s[120] = {/* AA */ 0, 0, 0, 0, -1, -1, -1, 0, -1, -1, -1, 0, -1, -1, -1, /* AC */ 0, 0, -1, 0, -1, -1, -1, 0, -1, -1, -1, 0, -1, -1, /* AG */ 0, -1, -1, 0, -1, -1, -1, 0, -1, -1, -1, 0, -1, /* AU */ -1, -1, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, /* CA */ 0, 0, 0, 0, -1, -1, -1, 0, -1, -1, -1, /* CC */ 0, 0, -1, 0, -1, -1, -1, 0, -1, -1, /* CG */ 0, -1, 0, 0, 0, 0, -1, 0, -1, /* CU */ -1, -1, -1, 0, -1, -1, -1, 0, /* GA */ 0, 0, 0, 0, -1, -1, -1, /* GC */ 0, 0, 0, 0, 0, -1, /* GG */ 0, -1, -1, 0, -1, /* GU */ 0, -1, 0, 0, /* UA */ 0, 0, 0, /* UC */ 0, 0, /* UG */ 0}; setSymmetry(s, tr->partitionData[model].symmetryVector, 120, f, tr->partitionData[model].frequencyGrouping, 16); tr->partitionData[model].nonGTR = TRUE; } break; case SEC_16_C: case SEC_16_D: case SEC_16_E: case SEC_16_F: case SEC_16_I: case SEC_16_J: case SEC_16_K: assert(0); default: assert(0); } } } } /* this function is only called once at program start-up ! */ static void initializeBaseFreqs(tree *tr) { size_t model; for(model = 0; model < (size_t)tr->NumberOfModels; model++) { if(tr->partitionData[model].optimizeBaseFrequencies) { //set all base frequencies to identical starting values 1.0 / numberOfDataStates //if we want to optimize base freqeuncies for the current partition int l, numFreqs = tr->partitionData[model].states; double f = 1.0 / ((double)numFreqs); for(l = 0; l < numFreqs; l++) { tr->partitionData[model].frequencies[l] = f; tr->partitionData[model].empiricalFrequencies[l] = f; } } else { //otherwise, at startup examl reads and stores the empirical base frequencies as determined by the //parser code in .frequencies, now we just store them in .empiricalFrequencies such that we can //overwrite .frequencies without losing the empirical base freqs memcpy(tr->partitionData[model].empiricalFrequencies, tr->partitionData[model].frequencies, sizeof(double) * tr->partitionData[model].states); } } } /* this function is only called once at program start-up ! */ void initModel(tree *tr) { int model; optimizeRateCategoryInvocations = 1; tr->numberOfInvariableColumns = 0; tr->weightOfInvariableColumns = 0; if(tr->rateHetModel == CAT) { for(model = 0; model < tr->NumberOfModels; model++) { tr->partitionData[model].numberOfCategories = 1; tr->partitionData[model].perSiteRates[0] = 1.0; size_t i; for(i = 0; i < tr->partitionData[model].width; ++i) { tr->partitionData[model].rateCategory[i] = 0; tr->partitionData[model].patrat[i] = 1.; } } checkPerSiteRates(tr); } setupSecondaryStructureSymmetries(tr); initRateMatrix(tr); initializeBaseFreqs(tr); for(model = 0; model < tr->NumberOfModels; model++) { int k; tr->partitionData[model].alpha = 1.0; if(tr->partitionData[model].protModels == AUTO) tr->partitionData[model].autoProtModels = WAG; /* initialize by WAG per default when AUTO is used */ makeGammaCats(tr->partitionData[model].alpha, tr->partitionData[model].gammaRates, 4, tr->useMedian); for(k = 0; k < tr->partitionData[model].states; k++) tr->partitionData[model].freqExponents[k] = 0.0; //LG4X inits for(k = 0; k < 4; k++) { tr->partitionData[model].weights[k] = 0.25; tr->partitionData[model].weightExponents[k] = 0.0; } initReversibleGTR(tr, model); } } ExaML-3.0.21/examl/newviewGenericSpecial.c000066400000000000000000005266751330315463200203240ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifndef WIN32 #include #endif #include #include #include #include #include #include #include #include #include "axml.h" #ifdef __SIM_SSE3 #include #include #include /* required to compute the absoliute values of double precision numbers with SSE3 */ const union __attribute__ ((aligned (BYTE_ALIGNMENT))) { uint64_t i[2]; __m128d m; } absMask = {{0x7fffffffffffffffULL , 0x7fffffffffffffffULL }}; #endif /* includes MIC-optimized functions */ #ifdef __MIC_NATIVE #include "mic_native.h" #endif extern int processID; /* bit mask */ extern const unsigned int mask32[32]; /* generic function for computing the P matrices, for computing the conditional likelihood at a node p, given child nodes q and r we compute P(z1) and P(z2) here */ static void makeP(double z1, double z2, double *rptr, double *EI, double *EIGN, int numberOfCategories, double *left, double *right, boolean saveMem, int maxCat, const int states) { int i, j, k, /* square of the number of states = P-matrix size */ statesSquare = states * states; /* assign some space for pre-computing and later re-using functions */ double *lz1 = (double*)malloc(sizeof(double) * states), *lz2 = (double*)malloc(sizeof(double) * states), *d1 = (double*)malloc(sizeof(double) * states), *d2 = (double*)malloc(sizeof(double) * states); /* multiply branch lengths with eigenvalues */ for(i = 1; i < states; i++) { lz1[i] = EIGN[i] * z1; lz2[i] = EIGN[i] * z2; } /* loop over the number of rate categories, this will be 4 for the GAMMA model and variable for the CAT model */ for(i = 0; i < numberOfCategories; i++) { /* exponentiate the rate multiplied by the branch */ for(j = 1; j < states; j++) { d1[j] = EXP(rptr[i] * lz1[j]); d2[j] = EXP(rptr[i] * lz2[j]); } /* now fill the P matrices for the two branch length values */ for(j = 0; j < states; j++) { /* left and right are pre-allocated arrays */ left[statesSquare * i + states * j] = 1.0; right[statesSquare * i + states * j] = 1.0; for(k = 1; k < states; k++) { left[statesSquare * i + states * j + k] = d1[k] * EI[states * j + k]; right[statesSquare * i + states * j + k] = d2[k] * EI[states * j + k]; } } } /* if memory saving is enabled and we are using CAT we need to do one additional P matrix calculation for a rate of 1.0 to compute the entries of a column/tree site comprising only gaps */ if(saveMem) { i = maxCat; for(j = 1; j < states; j++) { d1[j] = EXP (lz1[j]); d2[j] = EXP (lz2[j]); } for(j = 0; j < states; j++) { left[statesSquare * i + states * j] = 1.0; right[statesSquare * i + states * j] = 1.0; for(k = 1; k < states; k++) { left[statesSquare * i + states * j + k] = d1[k] * EI[states * j + k]; right[statesSquare * i + states * j + k] = d2[k] * EI[states * j + k]; } } } /* free the temporary buffers */ free(lz1); free(lz2); free(d1); free(d2); } static void makeP_FlexLG4(double z1, double z2, double *rptr, double *EI[4], double *EIGN[4], int numberOfCategories, double *left, double *right, const int numStates) { int i, j, k; const int statesSquare = numStates * numStates; double d1[64], d2[64]; assert(numStates <= 64); for(i = 0; i < numberOfCategories; i++) { for(j = 1; j < numStates; j++) { d1[j] = EXP (rptr[i] * EIGN[i][j] * z1); d2[j] = EXP (rptr[i] * EIGN[i][j] * z2); } for(j = 0; j < numStates; j++) { left[statesSquare * i + numStates * j] = 1.0; right[statesSquare * i + numStates * j] = 1.0; for(k = 1; k < numStates; k++) { left[statesSquare * i + numStates * j + k] = d1[k] * EI[i][numStates * j + k]; right[statesSquare * i + numStates * j + k] = d2[k] * EI[i][numStates * j + k]; } } } } /* The functions here are organized in a similar way as in evaluateGenericSpecial.c I provide generic, slow but readable function implementations for computing the conditional likelihood arrays at p, given child nodes q and r. Once again we need two generic function implementations, one for CAT and one for GAMMA */ #ifndef _OPTIMIZED_FUNCTIONS static void newviewCAT_FLEX(int tipCase, double *extEV, int *cptr, double *x1, double *x2, double *x3, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, const int states) { double *le, *ri, *v, *vl, *vr, ump_x1, ump_x2, x1px2; int i, l, j, scale, addScale = 0; const int statesSquare = states * states; /* here we switch over the different cases for efficiency, but also because each case accesses different data types. We consider three cases: either q and r are both tips, q or r are tips, and q and r are inner nodes. */ switch(tipCase) { /* both child nodes of p weher we want to update the conditional likelihood are tips */ case TIP_TIP: /* loop over sites */ for (i = 0; i < n; i++) { /* set a pointer to the P-Matrices for the rate category of this site */ le = &left[cptr[i] * statesSquare]; ri = &right[cptr[i] * statesSquare]; /* pointers to the likelihood entries of the tips q (vl) and r (vr) We will do reading accesses to these values only. */ vl = &(tipVector[states * tipX1[i]]); vr = &(tipVector[states * tipX2[i]]); /* address of the conditional likelihood array entres at site i. This is a writing access to v */ v = &x3[states * i]; /* initialize v */ for(l = 0; l < states; l++) v[l] = 0.0; /* loop over states to compute the cond likelihoods at p (v) */ for(l = 0; l < states; l++) { ump_x1 = 0.0; ump_x2 = 0.0; /* le and ri are the P-matrices */ for(j = 0; j < states; j++) { ump_x1 += vl[j] * le[l * states + j]; ump_x2 += vr[j] * ri[l * states + j]; } x1px2 = ump_x1 * ump_x2; /* multiply with matrix of eigenvectors extEV */ for(j = 0; j < states; j++) v[j] += x1px2 * extEV[l * states + j]; } } break; case TIP_INNER: /* same as above, only that now vl is a tip and vr is the conditional probability vector at an inner node. Note that, if we have the case that either q or r is a tip, the nodes will be flipped to ensure that tipX1 always points to the sequence at the tip. */ for (i = 0; i < n; i++) { le = &left[cptr[i] * statesSquare]; ri = &right[cptr[i] * statesSquare]; /* access tip vector lookup table */ vl = &(tipVector[states * tipX1[i]]); /* access conditional likelihoo arrays */ /* again, vl and vr are reading accesses, while v is a writing access */ vr = &x2[states * i]; v = &x3[states * i]; /* same as in the loop above */ for(l = 0; l < states; l++) v[l] = 0.0; for(l = 0; l < states; l++) { ump_x1 = 0.0; ump_x2 = 0.0; for(j = 0; j < states; j++) { ump_x1 += vl[j] * le[l * states + j]; ump_x2 += vr[j] * ri[l * states + j]; } x1px2 = ump_x1 * ump_x2; for(j = 0; j < states; j++) v[j] += x1px2 * extEV[l * states + j]; } /* now let's check for numerical scaling. The maths in RAxML are a bit non-standard to avoid/economize on arithmetic operations at the virtual root and for branch length optimization and hence values stored in the conditional likelihood vectors can become negative. Below we check if all absolute values stored at position i of v are smaller than a pre-defined value in axml.h. If they are all smaller we can then safely multiply them by a large, constant number twotothe256 (without numerical overflow) that is also speced in axml.h */ scale = 1; for(l = 0; scale && (l < states); l++) scale = ((v[l] < minlikelihood) && (v[l] > minusminlikelihood)); if(scale) { for(l = 0; l < states; l++) v[l] *= twotothe256; /* if we have scaled the entries to prevent underflow, we need to keep track of how many scaling multiplications we did per node such as to undo them at the virtual root, e.g., in evaluateGeneric() Note here, that, if we scaled the site we need to increment the scaling counter by the wieght, i.e., the number of sites this potentially compressed pattern represents ! */ addScale += wgt[i]; } } break; case INNER_INNER: /* same as above, only that the two child nodes q and r are now inner nodes */ for(i = 0; i < n; i++) { le = &left[cptr[i] * statesSquare]; ri = &right[cptr[i] * statesSquare]; /* index conditional likelihood vectors of inner nodes */ vl = &x1[states * i]; vr = &x2[states * i]; v = &x3[states * i]; for(l = 0; l < states; l++) v[l] = 0.0; for(l = 0; l < states; l++) { ump_x1 = 0.0; ump_x2 = 0.0; for(j = 0; j < states; j++) { ump_x1 += vl[j] * le[l * states + j]; ump_x2 += vr[j] * ri[l * states + j]; } x1px2 = ump_x1 * ump_x2; for(j = 0; j < states; j++) v[j] += x1px2 * extEV[l * states + j]; } scale = 1; for(l = 0; scale && (l < states); l++) scale = ((v[l] < minlikelihood) && (v[l] > minusminlikelihood)); if(scale) { for(l = 0; l < states; l++) v[l] *= twotothe256; addScale += wgt[i]; } } break; default: assert(0); } /* increment the scaling counter by the additional scalings done at node p */ *scalerIncrement = addScale; } static void newviewGAMMA_FLEX(int tipCase, double *x1, double *x2, double *x3, double *extEV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, const int states, const int maxStateValue) { double *uX1, *uX2, *v, x1px2, *vl, *vr, al, ar; int i, j, l, k, scale, addScale = 0; const int statesSquare = states * states, span = states * 4, /* this is required for doing some pre-computations that help to save numerical operations. What we are actually computing here are additional lookup tables for each possible state a certain data-type can assume. for DNA with ambuguity coding this is 15, for proteins this is 22 or 23, since there also exist one or two amibguity codes for protein data. Essentially this is very similar to the tip vectors which we also use as lookup tables */ precomputeLength = maxStateValue * span; switch(tipCase) { case TIP_TIP: { /* allocate pre-compute memory space */ double *umpX1 = (double*)malloc(sizeof(double) * precomputeLength), *umpX2 = (double*)malloc(sizeof(double) * precomputeLength); /* multiply all possible tip state vectors with the respective P-matrices */ for(i = 0; i < maxStateValue; i++) { v = &(tipVector[states * i]); for(k = 0; k < span; k++) { umpX1[span * i + k] = 0.0; umpX2[span * i + k] = 0.0; for(l = 0; l < states; l++) { umpX1[span * i + k] += v[l] * left[k * states + l]; umpX2[span * i + k] += v[l] * right[k * states + l]; } } } for(i = 0; i < n; i++) { /* access the precomputed arrays (pre-computed multiplication of conditional with the tip state) */ uX1 = &umpX1[span * tipX1[i]]; uX2 = &umpX2[span * tipX2[i]]; /* loop over discrete GAMMA rates */ for(j = 0; j < 4; j++) { /* the rest is the same as for CAT */ v = &x3[i * span + j * states]; for(k = 0; k < states; k++) v[k] = 0.0; for(k = 0; k < states; k++) { x1px2 = uX1[j * states + k] * uX2[j * states + k]; for(l = 0; l < states; l++) v[l] += x1px2 * extEV[states * k + l]; } } } /* free precomputed vectors */ free(umpX1); free(umpX2); } break; case TIP_INNER: { /* we do analogous pre-computations as above, with the only difference that we now do them only for one tip vector */ double *umpX1 = (double*)malloc(sizeof(double) * precomputeLength), *ump_x2 = (double*)malloc(sizeof(double) * states); /* precompute P and left tip vector product */ for(i = 0; i < maxStateValue; i++) { v = &(tipVector[states * i]); for(k = 0; k < span; k++) { umpX1[span * i + k] = 0.0; for(l = 0; l < states; l++) umpX1[span * i + k] += v[l] * left[k * states + l]; } } for (i = 0; i < n; i++) { /* access pre-computed value based on the raw sequence data tipX1 that is used as an index */ uX1 = &umpX1[span * tipX1[i]]; /* loop over discrete GAMMA rates */ for(k = 0; k < 4; k++) { v = &(x2[span * i + k * states]); for(l = 0; l < states; l++) { ump_x2[l] = 0.0; for(j = 0; j < states; j++) ump_x2[l] += v[j] * right[k * statesSquare + l * states + j]; } v = &(x3[span * i + states * k]); for(l = 0; l < states; l++) v[l] = 0; for(l = 0; l < states; l++) { x1px2 = uX1[k * states + l] * ump_x2[l]; for(j = 0; j < states; j++) v[j] += x1px2 * extEV[l * states + j]; } } /* also do numerical scaling as above. Note that here we need to scale 4 * 4 values for DNA or 4 * 20 values for protein data. If they are ALL smaller than our threshold, we scale. Note that, this can cause numerical problems with GAMMA, if the values generated by the four discrete GAMMA rates are too different. For details, see: F. Izquierdo-Carrasco, S.A. Smith, A. Stamatakis: "Algorithms, Data Structures, and Numerics for Likelihood-based Phylogenetic Inference of Huge Trees" */ v = &x3[span * i]; scale = 1; for(l = 0; scale && (l < span); l++) scale = (ABS(v[l]) < minlikelihood); if (scale) { for(l = 0; l < span; l++) v[l] *= twotothe256; addScale += wgt[i]; } } free(umpX1); free(ump_x2); } break; case INNER_INNER: /* same as above, without pre-computations */ for (i = 0; i < n; i++) { for(k = 0; k < 4; k++) { vl = &(x1[span * i + states * k]); vr = &(x2[span * i + states * k]); v = &(x3[span * i + states * k]); for(l = 0; l < states; l++) v[l] = 0; for(l = 0; l < states; l++) { al = 0.0; ar = 0.0; for(j = 0; j < states; j++) { al += vl[j] * left[k * statesSquare + l * states + j]; ar += vr[j] * right[k * statesSquare + l * states + j]; } x1px2 = al * ar; for(j = 0; j < states; j++) v[j] += x1px2 * extEV[states * l + j]; } } v = &(x3[span * i]); scale = 1; for(l = 0; scale && (l < span); l++) scale = ((ABS(v[l]) < minlikelihood)); if(scale) { for(l = 0; l < span; l++) v[l] *= twotothe256; addScale += wgt[i]; } } break; default: assert(0); } /* as above, increment the global counter that counts scaling multiplications by the scaling multiplications carried out for computing the likelihood array at node p */ *scalerIncrement = addScale; } #endif /* The function below computes partial traversals only down to the point/node in the tree where the conditional likelihhod vector summarizing a subtree is already oriented in the correct direction */ void computeTraversalInfo(nodeptr p, traversalInfo *ti, int *counter, int maxTips, int numBranches, boolean partialTraversal) { /* if it's a tip we don't do anything */ if(isTip(p->number, maxTips)) return; { int i; /* get the left and right descendants */ nodeptr q = p->next->back, r = p->next->next->back; /* if the left and right children are tips there is not that much to do */ if(isTip(r->number, maxTips) && isTip(q->number, maxTips)) { /* fix the orientation of p->x */ if (! p->x) getxnode(p); assert(p->x); /* add the current node triplet p,q,r to the traversal descriptor */ ti[*counter].tipCase = TIP_TIP; ti[*counter].pNumber = p->number; ti[*counter].qNumber = q->number; ti[*counter].rNumber = r->number; /* copy branches to traversal descriptor */ for(i = 0; i < numBranches; i++) { ti[*counter].qz[i] = q->z[i]; ti[*counter].rz[i] = r->z[i]; } /* increment length counter */ *counter = *counter + 1; } else { /* if either r or q are tips, flip them to make sure that the tip data is stored for q */ if(isTip(r->number, maxTips) || isTip(q->number, maxTips)) { if(isTip(r->number, maxTips)) { nodeptr tmp = r; r = q; q = tmp; } /* if the orientation of the liklihood vector at r is not correct we need to re-compute it and descend into its subtree to figure out if there are more vrctors in there to re-compute and re-orient */ if(!r->x || !partialTraversal) computeTraversalInfo(r, ti, counter, maxTips, numBranches, partialTraversal); if(! p->x) getxnode(p); /* make sure that everything is consistent now */ assert(p->x && r->x); /* store data for p, q, r in the traversal descriptor */ ti[*counter].tipCase = TIP_INNER; ti[*counter].pNumber = p->number; ti[*counter].qNumber = q->number; ti[*counter].rNumber = r->number; for(i = 0; i < numBranches; i++) { ti[*counter].qz[i] = q->z[i]; ti[*counter].rz[i] = r->z[i]; } *counter = *counter + 1; } else { /* same as above, only now q and r are inner nodes. Hence if they are not oriented correctly they will need to be recomputed and we need to descend into the respective subtrees to check if everything is consistent in there, potentially expanding the traversal descriptor */ if(! q->x || !partialTraversal) computeTraversalInfo(q, ti, counter, maxTips, numBranches, partialTraversal); if(! r->x || !partialTraversal) computeTraversalInfo(r, ti, counter, maxTips, numBranches, partialTraversal); if(! p->x) getxnode(p); /* check that the vector orientations are consistent now */ assert(p->x && r->x && q->x); ti[*counter].tipCase = INNER_INNER; ti[*counter].pNumber = p->number; ti[*counter].qNumber = q->number; ti[*counter].rNumber = r->number; for(i = 0; i < numBranches; i++) { ti[*counter].qz[i] = q->z[i]; ti[*counter].rz[i] = r->z[i]; } *counter = *counter + 1; } } } } /* below are the optimized unrolled, and vectorized versions of the above generi cfunctions for computing the conditional likelihood at p given child nodes q and r. The actual implementation is located at the end/bottom of this file. */ #if (defined(_OPTIMIZED_FUNCTIONS) && !defined(__AVX)) static void newviewGTRGAMMAPROT_LG4(int tipCase, double *x1, double *x2, double *x3, double *extEV[4], double *tipVector[4], int *ex3, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling); static void newviewGTRGAMMA_GAPPED_SAVE(int tipCase, double *x1_start, double *x2_start, double *x3_start, double *EV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, const int n, double *left, double *right, int *wgt, int *scalerIncrement, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn); static void newviewGTRGAMMA(int tipCase, double *x1_start, double *x2_start, double *x3_start, double *EV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, const int n, double *left, double *right, int *wgt, int *scalerIncrement ); static void newviewGTRCAT( int tipCase, double *EV, int *cptr, double *x1_start, double *x2_start, double *x3_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement); static void newviewGTRCAT_SAVE( int tipCase, double *EV, int *cptr, double *x1_start, double *x2_start, double *x3_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn, const int maxCats); static void newviewGTRGAMMAPROT_GAPPED_SAVE(int tipCase, double *x1, double *x2, double *x3, double *extEV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn ); static void newviewGTRGAMMAPROT(int tipCase, double *x1, double *x2, double *x3, double *extEV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement); static void newviewGTRCATPROT(int tipCase, double *extEV, int *cptr, double *x1, double *x2, double *x3, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement ); static void newviewGTRCATPROT_SAVE(int tipCase, double *extEV, int *cptr, double *x1, double *x2, double *x3, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn, const int maxCats); #endif #ifdef _OPTIMIZED_FUNCTIONS static void newviewGTRCAT_BINARY( int tipCase, double *EV, int *cptr, double *x1_start, double *x2_start, double *x3_start, double *tipVector, int *ex3, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling); static void newviewGTRGAMMA_BINARY(int tipCase, double *x1_start, double *x2_start, double *x3_start, double *EV, double *tipVector, int *ex3, unsigned char *tipX1, unsigned char *tipX2, const int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling ); #endif boolean isGap(unsigned int *x, int pos) { return (x[pos / 32] & mask32[pos % 32]); } boolean noGap(unsigned int *x, int pos) { return (!(x[pos / 32] & mask32[pos % 32])); } /* now this is the function that just iterates over the length of the traversal descriptor and just computes the conditional likelihhod arrays in the order given by the descriptor. So in a sense, this function has no clue that there is any tree-like structure in the traversal descriptor, it just operates on an array of structs of given length */ extern const char inverseMeaningDNA[16]; void newviewIterative (tree *tr, int startIndex) { traversalInfo *ti = tr->td[0].ti; int i; /* loop over traversal descriptor length. Note that on average we only re-compute the conditionals on 3 -4 nodes in RAxML */ for(i = startIndex; i < tr->td[0].count; i++) { traversalInfo *tInfo = &ti[i]; int model; #ifdef _USE_OMP #pragma omp parallel for #endif for(model = 0; model < tr->NumberOfModels; model++) { /* check if this partition has to be processed now - otherwise no need to compute P matrix */ if(!tr->td[0].executeModel[model] || tr->partitionData[model].width == 0) continue; int categories, states = tr->partitionData[model].states; double qz, rz, *rateCategories, *left = tr->partitionData[model].left, *right = tr->partitionData[model].right; /* figure out what kind of rate heterogeneity approach we are using */ if(tr->rateHetModel == CAT) { rateCategories = tr->partitionData[model].perSiteRates; categories = tr->partitionData[model].numberOfCategories; } else { rateCategories = tr->partitionData[model].gammaRates; categories = 4; } /* if we use per-partition branch length optimization get the branch length of partition model and take the log otherwise use the joint branch length among all partitions that is always stored at index [0] */ if(tr->numBranches > 1) { qz = tInfo->qz[model]; rz = tInfo->rz[model]; } else { qz = tInfo->qz[0]; rz = tInfo->rz[0]; } qz = (qz > zmin) ? log(qz) : log(zmin); rz = (rz > zmin) ? log(rz) : log(zmin); /* compute the left and right P matrices */ #ifdef __MIC_NATIVE switch (tr->partitionData[model].states) { case 2: /* BINARY data */ assert(0 && "Binary data model is not implemented on Intel MIC"); break; case 4: /* DNA data */ { makeP_DNA_MIC(qz, rz, rateCategories, tr->partitionData[model].EI, tr->partitionData[model].EIGN, categories, left, right, tr->saveMemory, tr->maxCategories); precomputeTips_DNA_MIC(tInfo->tipCase, tr->partitionData[model].tipVector, left, right, tr->partitionData[model].mic_umpLeft, tr->partitionData[model].mic_umpRight, categories); } break; case 20: /* AA data */ { if(tr->partitionData[model].protModels == LG4M || tr->partitionData[model].protModels == LG4X) { makeP_PROT_LG4_MIC(qz, rz, tr->partitionData[model].gammaRates, tr->partitionData[model].EI_LG4, tr->partitionData[model].EIGN_LG4, 4, left, right); precomputeTips_PROT_LG4_MIC(tInfo->tipCase, tr->partitionData[model].tipVector_LG4, left, right, tr->partitionData[model].mic_umpLeft, tr->partitionData[model].mic_umpRight, categories); } else { makeP_PROT_MIC(qz, rz, rateCategories, tr->partitionData[model].EI, tr->partitionData[model].EIGN, categories, left, right, tr->saveMemory, tr->maxCategories); precomputeTips_PROT_MIC(tInfo->tipCase, tr->partitionData[model].tipVector, left, right, tr->partitionData[model].mic_umpLeft, tr->partitionData[model].mic_umpRight, categories); } } break; default: assert(0); } #else if(tr->partitionData[model].protModels == LG4M || tr->partitionData[model].protModels == LG4X) makeP_FlexLG4(qz, rz, tr->partitionData[model].gammaRates, tr->partitionData[model].EI_LG4, tr->partitionData[model].EIGN_LG4, 4, left, right, 20); else makeP(qz, rz, rateCategories, tr->partitionData[model].EI, tr->partitionData[model].EIGN, categories, left, right, tr->saveMemory, tr->maxCategories, states); #endif } // for model /* now loop over all partitions for nodes p, q, and r of the current traversal vector entry */ #ifdef _USE_OMP #pragma omp parallel #endif { int m, model, maxModel; #ifdef _USE_OMP maxModel = tr->maxModelsPerThread; #else maxModel = tr->NumberOfModels; #endif for(m = 0; m < maxModel; m++) { size_t width = 0, offset = 0; double *left = (double*)NULL, *right = (double*)NULL; unsigned int *globalScaler = (unsigned int*)NULL; #ifdef _USE_OMP int tid = omp_get_thread_num(); /* check if this thread should process this partition */ Assign* pAss = tr->threadPartAssigns[tid * tr->maxModelsPerThread + m]; if(pAss) { assert(tid == pAss->procId); model = pAss->partitionId; width = pAss->width; offset = pAss->offset; left = tr->partitionData[model].left; right = tr->partitionData[model].right; globalScaler = tr->partitionData[model].threadGlobalScaler[tid]; } else break; #else model = m; /* number of sites in this partition */ width = (size_t)tr->partitionData[model].width; offset = 0; /* set the pointers to the left and right P matrices to the pre-allocated memory space for storing them */ left = tr->partitionData[model].left; right = tr->partitionData[model].right; globalScaler = tr->partitionData[model].globalScaler; #endif /* this conditional statement is exactly identical to what we do in evaluateIterative */ if(tr->td[0].executeModel[model] && width > 0) { double *x1_start = (double*)NULL, *x2_start = (double*)NULL, *x3_start = (double*)NULL, //tr->partitionData[model].xVector[tInfo->pNumber - tr->mxtips - 1], *x1_gapColumn = (double*)NULL, *x2_gapColumn = (double*)NULL, *x3_gapColumn = (double*)NULL; int scalerIncrement = 0, /* integer wieght vector with pattern compression weights */ *wgt = tr->partitionData[model].wgt + offset, /* integer rate category vector (for each pattern, _number_ of PSR category assigned to it, NOT actual rate!) */ *rateCategory = tr->partitionData[model].rateCategory + offset; unsigned int *x1_gap = (unsigned int*)NULL, *x2_gap = (unsigned int*)NULL, *x3_gap = (unsigned int*)NULL; unsigned char *tipX1 = (unsigned char *)NULL, *tipX2 = (unsigned char *)NULL; size_t gapOffset = 0, rateHet = discreteRateCategories(tr->rateHetModel), /* get the number of states in the data stored in partition model */ states = (size_t)tr->partitionData[model].states, /* span for single alignment site (in doubles!) */ span = rateHet * states, x_offset = offset * (size_t)span, /* get the length of the current likelihood array stored at node p. This is important mainly for the SEV-based memory saving option described in here: F. Izquierdo-Carrasco, S.A. Smith, A. Stamatakis: "Algorithms, Data Structures, and Numerics for Likelihood-based Phylogenetic Inference of Huge Trees". So tr->partitionData[model].xSpaceVector[i] provides the length of the allocated conditional array of partition model and node i */ availableLength = tr->partitionData[model].xSpaceVector[(tInfo->pNumber - tr->mxtips - 1)], requiredLength = 0; x3_start = tr->partitionData[model].xVector[tInfo->pNumber - tr->mxtips - 1] + x_offset; /* memory saving stuff, not important right now, but if you are interested ask Fernando */ if(tr->saveMemory) { size_t j, setBits = 0; gapOffset = states * (size_t)getUndetermined(tr->partitionData[model].dataType); x1_gap = &(tr->partitionData[model].gapVector[tInfo->qNumber * tr->partitionData[model].gapVectorLength]); x2_gap = &(tr->partitionData[model].gapVector[tInfo->rNumber * tr->partitionData[model].gapVectorLength]); x3_gap = &(tr->partitionData[model].gapVector[tInfo->pNumber * tr->partitionData[model].gapVectorLength]); for(j = 0; j < (size_t)tr->partitionData[model].gapVectorLength; j++) { x3_gap[j] = x1_gap[j] & x2_gap[j]; setBits += (size_t)(precomputed16_bitcount(x3_gap[j], tr->bits_in_16bits)); } requiredLength = (width - setBits) * rateHet * states * sizeof(double); } else /* if we are not trying to save memory the space required to store an inner likelihood array is the number of sites in the partition times the number of states of the data type in the partition times the number of discrete GAMMA rates (1 for CAT essentially) times 8 bytes */ requiredLength = width * rateHet * states * sizeof(double); /* Initially, even when not using memory saving no space is allocated for inner likelihood arrats hence availableLength will be zero at the very first time we traverse the tree. Hence we need to allocate something here */ #ifndef _USE_OMP if(requiredLength != availableLength) { /* if there is a vector of incorrect length assigned here i.e., x3 != NULL we must free it first */ if(x3_start) free(x3_start); /* allocate memory: note that here we use a byte-boundary aligned malloc, because we need the vectors to be aligned at 16 BYTE (SSE3) or 32 BYTE (AVX) boundaries! */ x3_start = (double*)malloc_aligned(requiredLength); /* update the data structures for consistent bookkeeping */ tr->partitionData[model].xVector[tInfo->pNumber - tr->mxtips - 1] = x3_start; tr->partitionData[model].xSpaceVector[(tInfo->pNumber - tr->mxtips - 1)] = requiredLength; } #endif /* now just set the pointers for data accesses in the newview() implementations above to the corresponding values according to the tip case */ switch(tInfo->tipCase) { case TIP_TIP: tipX1 = tr->partitionData[model].yVector[tInfo->qNumber] + offset; tipX2 = tr->partitionData[model].yVector[tInfo->rNumber] + offset; if(tr->saveMemory) { x1_gapColumn = &(tr->partitionData[model].tipVector[gapOffset]); x2_gapColumn = &(tr->partitionData[model].tipVector[gapOffset]); x3_gapColumn = &tr->partitionData[model].gapColumn[(tInfo->pNumber - tr->mxtips - 1) * states * rateHet]; } break; case TIP_INNER: tipX1 = tr->partitionData[model].yVector[tInfo->qNumber] + offset; x2_start = tr->partitionData[model].xVector[tInfo->rNumber - tr->mxtips - 1] + x_offset; if(tr->saveMemory) { x1_gapColumn = &(tr->partitionData[model].tipVector[gapOffset]); x2_gapColumn = &tr->partitionData[model].gapColumn[(tInfo->rNumber - tr->mxtips - 1) * states * rateHet]; x3_gapColumn = &tr->partitionData[model].gapColumn[(tInfo->pNumber - tr->mxtips - 1) * states * rateHet]; } break; case INNER_INNER: x1_start = tr->partitionData[model].xVector[tInfo->qNumber - tr->mxtips - 1] + x_offset; x2_start = tr->partitionData[model].xVector[tInfo->rNumber - tr->mxtips - 1] + x_offset; if(tr->saveMemory) { x1_gapColumn = &tr->partitionData[model].gapColumn[(tInfo->qNumber - tr->mxtips - 1) * states * rateHet]; x2_gapColumn = &tr->partitionData[model].gapColumn[(tInfo->rNumber - tr->mxtips - 1) * states * rateHet]; x3_gapColumn = &tr->partitionData[model].gapColumn[(tInfo->pNumber - tr->mxtips - 1) * states * rateHet]; } break; default: assert(0); } #ifndef _OPTIMIZED_FUNCTIONS /* memory saving not implemented */ assert(!tr->saveMemory); /* figure out if we need to compute the CAT or GAMMA model of rate heterogeneity */ if(tr->rateHetModel == CAT) newviewCAT_FLEX(tInfo->tipCase, tr->partitionData[model].EV, rateCategory, x1_start, x2_start, x3_start, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, states); else newviewGAMMA_FLEX(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].EV, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, states, getUndetermined(tr->partitionData[model].dataType) + 1); #else /* dedicated highly optimized functions. Analogously to the functions in evaluateGeneric() we also siwtch over the state number */ switch(states) { case 2: #ifdef __MIC_NATIVE assert(0 && "Binary data model is not implemented on Intel MIC"); #else assert(!tr->saveMemory); if(tr->rateHetModel == CAT) newviewGTRCAT_BINARY(tInfo->tipCase, tr->partitionData[model].EV, rateCategory, x1_start, x2_start, x3_start, tr->partitionData[model].tipVector, (int*)NULL, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, TRUE); else newviewGTRGAMMA_BINARY(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].EV, tr->partitionData[model].tipVector, (int *)NULL, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, TRUE); #endif break; case 4: /* DNA */ if(tr->rateHetModel == CAT) { if(tr->saveMemory) #ifdef __MIC_NATIVE assert(0 && "Neither CAT model of rate heterogeneity nor memory saving are implemented on Intel MIC"); #elif __AVX newviewGTRCAT_AVX_GAPPED_SAVE(tInfo->tipCase, tr->partitionData[model].EV, rateCategory, x1_start, x2_start, x3_start, tr->partitionData[model].tipVector, (int*)NULL, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, TRUE, x1_gap, x2_gap, x3_gap, x1_gapColumn, x2_gapColumn, x3_gapColumn, tr->maxCategories); #else newviewGTRCAT_SAVE(tInfo->tipCase, tr->partitionData[model].EV, rateCategory, x1_start, x2_start, x3_start, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, x1_gap, x2_gap, x3_gap, x1_gapColumn, x2_gapColumn, x3_gapColumn, tr->maxCategories); #endif else #ifdef __MIC_NATIVE assert(0 && "CAT model of rate heterogeneity is not implemented on Intel MIC"); #elif __AVX newviewGTRCAT_AVX(tInfo->tipCase, tr->partitionData[model].EV, rateCategory, x1_start, x2_start, x3_start, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement); #else newviewGTRCAT(tInfo->tipCase, tr->partitionData[model].EV, rateCategory, x1_start, x2_start, x3_start, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement); #endif } else { if(tr->saveMemory) #ifdef __MIC_NATIVE assert(0 && "Memory saving is not implemented on Intel MIC"); #elif __AVX newviewGTRGAMMA_AVX_GAPPED_SAVE(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].EV, tr->partitionData[model].tipVector, (int*)NULL, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, TRUE, x1_gap, x2_gap, x3_gap, x1_gapColumn, x2_gapColumn, x3_gapColumn); #else newviewGTRGAMMA_GAPPED_SAVE(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].EV, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, x1_gap, x2_gap, x3_gap, x1_gapColumn, x2_gapColumn, x3_gapColumn); #endif else #ifdef __MIC_NATIVE newviewGTRGAMMA_MIC(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].mic_EV, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, tr->partitionData[model].mic_umpLeft, tr->partitionData[model].mic_umpRight); #elif __AVX newviewGTRGAMMA_AVX(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].EV, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement); #else newviewGTRGAMMA(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].EV, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement); #endif } break; case 20: /* proteins */ if(tr->rateHetModel == CAT) { if(tr->saveMemory) { #ifdef __MIC_NATIVE assert(0 && "Neither CAT model of rate heterogeneity nor memory saving are implemented on Intel MIC"); #elif __AVX newviewGTRCATPROT_AVX_GAPPED_SAVE(tInfo->tipCase, tr->partitionData[model].EV, rateCategory, x1_start, x2_start, x3_start, tr->partitionData[model].tipVector, (int*)NULL, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, TRUE, x1_gap, x2_gap, x3_gap, x1_gapColumn, x2_gapColumn, x3_gapColumn, tr->maxCategories); #else newviewGTRCATPROT_SAVE(tInfo->tipCase, tr->partitionData[model].EV, rateCategory, x1_start, x2_start, x3_start, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, x1_gap, x2_gap, x3_gap, x1_gapColumn, x2_gapColumn, x3_gapColumn, tr->maxCategories); #endif } else { #ifdef __MIC_NATIVE assert(0 && "CAT model of rate heterogeneity is not implemented on Intel MIC"); #elif __AVX newviewGTRCATPROT_AVX(tInfo->tipCase, tr->partitionData[model].EV, rateCategory, x1_start, x2_start, x3_start, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement); #else newviewGTRCATPROT(tInfo->tipCase, tr->partitionData[model].EV, rateCategory, x1_start, x2_start, x3_start, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement); #endif } } else { if(tr->saveMemory) { #ifdef __MIC_NATIVE assert(0 && "Memory saving is not implemented on Intel MIC"); #elif __AVX newviewGTRGAMMAPROT_AVX_GAPPED_SAVE(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].EV, tr->partitionData[model].tipVector, (int*)NULL, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, TRUE, x1_gap, x2_gap, x3_gap, x1_gapColumn, x2_gapColumn, x3_gapColumn); #else newviewGTRGAMMAPROT_GAPPED_SAVE(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].EV, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, x1_gap, x2_gap, x3_gap, x1_gapColumn, x2_gapColumn, x3_gapColumn); #endif } else { if(tr->partitionData[model].protModels == LG4M || tr->partitionData[model].protModels == LG4X) { #ifdef __MIC_NATIVE newviewGTRGAMMAPROT_LG4_MIC(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].mic_EV, tr->partitionData[model].mic_tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, tr->partitionData[model].mic_umpLeft, tr->partitionData[model].mic_umpRight); #elif __AVX newviewGTRGAMMAPROT_AVX_LG4(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].EV_LG4, tr->partitionData[model].tipVector_LG4, (int*)NULL, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, TRUE); #else newviewGTRGAMMAPROT_LG4(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].EV_LG4, tr->partitionData[model].tipVector_LG4, (int*)NULL, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, TRUE); #endif } else { #ifdef __MIC_NATIVE newviewGTRGAMMAPROT_MIC(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].mic_EV, tr->partitionData[model].mic_tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement, tr->partitionData[model].mic_umpLeft, tr->partitionData[model].mic_umpRight); #elif __AVX newviewGTRGAMMAPROT_AVX(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].EV, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement); #else newviewGTRGAMMAPROT(tInfo->tipCase, x1_start, x2_start, x3_start, tr->partitionData[model].EV, tr->partitionData[model].tipVector, tipX1, tipX2, width, left, right, wgt, &scalerIncrement); #endif } } } break; default: assert(0); } #endif /* important step, here we essentiallt recursively compute the number of scaling multiplications at node p: it's the sum of the number of scaling multiplications already conducted for computing nodes q and r plus the scaling multiplications done at node p */ globalScaler[tInfo->pNumber] = globalScaler[tInfo->qNumber] + globalScaler[tInfo->rNumber] + (unsigned int)scalerIncrement; /* check that we are not getting an integer overflow ! */ assert(globalScaler[tInfo->pNumber] < INT_MAX); } } // for model } // omp parallel block } // for traversal } /* here is the generic function that could be called from the user program it re-computes the vector at node p (regardless of whether it's orientation is correct and then it also re-computes reciursively the likelihood arrays in the subtrees of p as needed and if needed */ void newviewGeneric (tree *tr, nodeptr p, boolean masked) { /* if it's a tip there is nothing to do */ if(isTip(p->number, tr->mxtips)) return; /* the first entry of the traversal descriptor is always reserved for evaluate or branch length optimization calls, hence we start filling the array at the second entry with index one. This is not very nice and should be fixed at some point */ tr->td[0].count = 0; /* compute the traversal descriptor */ computeTraversalInfo(p, &(tr->td[0].ti[0]), &(tr->td[0].count), tr->mxtips, tr->numBranches, TRUE); /* the traversal descriptor has been recomputed -> not sure if it really always changes, something to optimize in the future */ tr->td[0].traversalHasChanged = TRUE; /* We do a masked newview, i.e., do not execute newvies for each partition, when for example doing a branch length optimization on the entire tree when branches are estimated on a per partition basis. you may imagine that for partition 5 the branch length optimization has already converged whereas for partition 6 we still need to go over the tree again. This is explained in more detail in: A. Stamatakis, M. Ott: "Load Balance in the Phylogenetic Likelihood Kernel". Proceedings of ICPP 2009 The external boolean array tr->partitionConverged[] contains exactly that information and is copied to executeModel and subsequently to the executeMask of the traversal descriptor */ if(masked) { int model; for(model = 0; model < tr->NumberOfModels; model++) { if(tr->partitionConverged[model]) tr->executeModel[model] = FALSE; else tr->executeModel[model] = TRUE; } } /* if there is something to re-compute */ if(tr->td[0].count > 0) { /* store execute mask in traversal descriptor */ storeExecuteMaskInTraversalDescriptor(tr); newviewIterative(tr, 0); } /* clean up */ if(masked) { int model; for(model = 0; model < tr->NumberOfModels; model++) tr->executeModel[model] = TRUE; } tr->td[0].traversalHasChanged = FALSE; } /* optimized function implementations */ #if (defined(_OPTIMIZED_FUNCTIONS) && !defined(__AVX)) static void newviewGTRGAMMA_GAPPED_SAVE(int tipCase, double *x1_start, double *x2_start, double *x3_start, double *EV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, const int n, double *left, double *right, int *wgt, int *scalerIncrement, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn) { int i, j, k, l, addScale = 0, scaleGap = 0; double *x1, *x2, *x3, *x1_ptr = x1_start, *x2_ptr = x2_start, max, maxima[2] __attribute__ ((aligned (BYTE_ALIGNMENT))), EV_t[16] __attribute__ ((aligned (BYTE_ALIGNMENT))); __m128d values[8], EVV[8]; for(k = 0; k < 4; k++) for (l=0; l < 4; l++) EV_t[4 * l + k] = EV[4 * k + l]; for(k = 0; k < 8; k++) EVV[k] = _mm_load_pd(&EV_t[k * 2]); switch(tipCase) { case TIP_TIP: { double *uX1, umpX1[256] __attribute__ ((aligned (BYTE_ALIGNMENT))), *uX2, umpX2[256] __attribute__ ((aligned (BYTE_ALIGNMENT))); for (i = 1; i < 16; i++) { __m128d x1_1 = _mm_load_pd(&(tipVector[i*4])); __m128d x1_2 = _mm_load_pd(&(tipVector[i*4 + 2])); for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { __m128d left1 = _mm_load_pd(&left[j*16 + k*4]); __m128d left2 = _mm_load_pd(&left[j*16 + k*4 + 2]); __m128d acc = _mm_setzero_pd(); acc = _mm_add_pd(acc, _mm_mul_pd(left1, x1_1)); acc = _mm_add_pd(acc, _mm_mul_pd(left2, x1_2)); acc = _mm_hadd_pd(acc, acc); _mm_storel_pd(&umpX1[i*16 + j*4 + k], acc); } for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { __m128d left1 = _mm_load_pd(&right[j*16 + k*4]); __m128d left2 = _mm_load_pd(&right[j*16 + k*4 + 2]); __m128d acc = _mm_setzero_pd(); acc = _mm_add_pd(acc, _mm_mul_pd(left1, x1_1)); acc = _mm_add_pd(acc, _mm_mul_pd(left2, x1_2)); acc = _mm_hadd_pd(acc, acc); _mm_storel_pd(&umpX2[i*16 + j*4 + k], acc); } } uX1 = &umpX1[240]; uX2 = &umpX2[240]; for (j = 0; j < 4; j++) { __m128d uX1_k0_sse = _mm_load_pd( &uX1[j * 4] ); __m128d uX1_k2_sse = _mm_load_pd( &uX1[j * 4 + 2] ); __m128d uX2_k0_sse = _mm_load_pd( &uX2[j * 4] ); __m128d uX2_k2_sse = _mm_load_pd( &uX2[j * 4 + 2] ); __m128d x1px2_k0 = _mm_mul_pd( uX1_k0_sse, uX2_k0_sse ); __m128d x1px2_k2 = _mm_mul_pd( uX1_k2_sse, uX2_k2_sse ); __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); _mm_store_pd( &x3_gapColumn[j * 4 + 0], EV_t_l0_k0 ); _mm_store_pd( &x3_gapColumn[j * 4 + 2], EV_t_l2_k0 ); } x3 = x3_start; for (i = 0; i < n; i++) { if(!(x3_gap[i / 32] & mask32[i % 32])) { uX1 = &umpX1[16 * tipX1[i]]; uX2 = &umpX2[16 * tipX2[i]]; for (j = 0; j < 4; j++) { __m128d uX1_k0_sse = _mm_load_pd( &uX1[j * 4] ); __m128d uX1_k2_sse = _mm_load_pd( &uX1[j * 4 + 2] ); __m128d uX2_k0_sse = _mm_load_pd( &uX2[j * 4] ); __m128d uX2_k2_sse = _mm_load_pd( &uX2[j * 4 + 2] ); // // multiply left * right // __m128d x1px2_k0 = _mm_mul_pd( uX1_k0_sse, uX2_k0_sse ); __m128d x1px2_k2 = _mm_mul_pd( uX1_k2_sse, uX2_k2_sse ); // // multiply with EV matrix (!?) // __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); _mm_store_pd( &x3[j * 4 + 0], EV_t_l0_k0 ); _mm_store_pd( &x3[j * 4 + 2], EV_t_l2_k0 ); } x3 += 16; } } } break; case TIP_INNER: { double *uX1, umpX1[256] __attribute__ ((aligned (BYTE_ALIGNMENT))); for (i = 1; i < 16; i++) { __m128d x1_1 = _mm_load_pd(&(tipVector[i*4])); __m128d x1_2 = _mm_load_pd(&(tipVector[i*4 + 2])); for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { __m128d left1 = _mm_load_pd(&left[j*16 + k*4]); __m128d left2 = _mm_load_pd(&left[j*16 + k*4 + 2]); __m128d acc = _mm_setzero_pd(); acc = _mm_add_pd(acc, _mm_mul_pd(left1, x1_1)); acc = _mm_add_pd(acc, _mm_mul_pd(left2, x1_2)); acc = _mm_hadd_pd(acc, acc); _mm_storel_pd(&umpX1[i*16 + j*4 + k], acc); } } { __m128d maxv =_mm_setzero_pd(); scaleGap = 0; x2 = x2_gapColumn; x3 = x3_gapColumn; uX1 = &umpX1[240]; for (j = 0; j < 4; j++) { double *x2_p = &x2[j*4]; double *right_k0_p = &right[j*16]; double *right_k1_p = &right[j*16 + 1*4]; double *right_k2_p = &right[j*16 + 2*4]; double *right_k3_p = &right[j*16 + 3*4]; __m128d x2_0 = _mm_load_pd( &x2_p[0] ); __m128d x2_2 = _mm_load_pd( &x2_p[2] ); __m128d right_k0_0 = _mm_load_pd( &right_k0_p[0] ); __m128d right_k0_2 = _mm_load_pd( &right_k0_p[2] ); __m128d right_k1_0 = _mm_load_pd( &right_k1_p[0] ); __m128d right_k1_2 = _mm_load_pd( &right_k1_p[2] ); __m128d right_k2_0 = _mm_load_pd( &right_k2_p[0] ); __m128d right_k2_2 = _mm_load_pd( &right_k2_p[2] ); __m128d right_k3_0 = _mm_load_pd( &right_k3_p[0] ); __m128d right_k3_2 = _mm_load_pd( &right_k3_p[2] ); right_k0_0 = _mm_mul_pd( x2_0, right_k0_0); right_k0_2 = _mm_mul_pd( x2_2, right_k0_2); right_k1_0 = _mm_mul_pd( x2_0, right_k1_0); right_k1_2 = _mm_mul_pd( x2_2, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k0_2); right_k1_0 = _mm_hadd_pd( right_k1_0, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k1_0); right_k2_0 = _mm_mul_pd( x2_0, right_k2_0); right_k2_2 = _mm_mul_pd( x2_2, right_k2_2); right_k3_0 = _mm_mul_pd( x2_0, right_k3_0); right_k3_2 = _mm_mul_pd( x2_2, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k2_2); right_k3_0 = _mm_hadd_pd( right_k3_0, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k3_0); __m128d uX1_k0_sse = _mm_load_pd( &uX1[j * 4] ); __m128d uX1_k2_sse = _mm_load_pd( &uX1[j * 4 + 2] ); __m128d x1px2_k0 = _mm_mul_pd( uX1_k0_sse, right_k0_0 ); __m128d x1px2_k2 = _mm_mul_pd( uX1_k2_sse, right_k2_0 ); __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); values[j * 2] = EV_t_l0_k0; values[j * 2 + 1] = EV_t_l2_k0; maxv = _mm_max_pd(maxv, _mm_and_pd(EV_t_l0_k0, absMask.m)); maxv = _mm_max_pd(maxv, _mm_and_pd(EV_t_l2_k0, absMask.m)); } _mm_store_pd(maxima, maxv); max = MAX(maxima[0], maxima[1]); if(max < minlikelihood) { scaleGap = 1; __m128d sv = _mm_set1_pd(twotothe256); _mm_store_pd(&x3[0], _mm_mul_pd(values[0], sv)); _mm_store_pd(&x3[2], _mm_mul_pd(values[1], sv)); _mm_store_pd(&x3[4], _mm_mul_pd(values[2], sv)); _mm_store_pd(&x3[6], _mm_mul_pd(values[3], sv)); _mm_store_pd(&x3[8], _mm_mul_pd(values[4], sv)); _mm_store_pd(&x3[10], _mm_mul_pd(values[5], sv)); _mm_store_pd(&x3[12], _mm_mul_pd(values[6], sv)); _mm_store_pd(&x3[14], _mm_mul_pd(values[7], sv)); } else { _mm_store_pd(&x3[0], values[0]); _mm_store_pd(&x3[2], values[1]); _mm_store_pd(&x3[4], values[2]); _mm_store_pd(&x3[6], values[3]); _mm_store_pd(&x3[8], values[4]); _mm_store_pd(&x3[10], values[5]); _mm_store_pd(&x3[12], values[6]); _mm_store_pd(&x3[14], values[7]); } } x3 = x3_start; for (i = 0; i < n; i++) { if((x3_gap[i / 32] & mask32[i % 32])) { if(scaleGap) { addScale += wgt[i]; } } else { __m128d maxv =_mm_setzero_pd(); if(x2_gap[i / 32] & mask32[i % 32]) x2 = x2_gapColumn; else { x2 = x2_ptr; x2_ptr += 16; } uX1 = &umpX1[16 * tipX1[i]]; for (j = 0; j < 4; j++) { double *x2_p = &x2[j*4]; double *right_k0_p = &right[j*16]; double *right_k1_p = &right[j*16 + 1*4]; double *right_k2_p = &right[j*16 + 2*4]; double *right_k3_p = &right[j*16 + 3*4]; __m128d x2_0 = _mm_load_pd( &x2_p[0] ); __m128d x2_2 = _mm_load_pd( &x2_p[2] ); __m128d right_k0_0 = _mm_load_pd( &right_k0_p[0] ); __m128d right_k0_2 = _mm_load_pd( &right_k0_p[2] ); __m128d right_k1_0 = _mm_load_pd( &right_k1_p[0] ); __m128d right_k1_2 = _mm_load_pd( &right_k1_p[2] ); __m128d right_k2_0 = _mm_load_pd( &right_k2_p[0] ); __m128d right_k2_2 = _mm_load_pd( &right_k2_p[2] ); __m128d right_k3_0 = _mm_load_pd( &right_k3_p[0] ); __m128d right_k3_2 = _mm_load_pd( &right_k3_p[2] ); right_k0_0 = _mm_mul_pd( x2_0, right_k0_0); right_k0_2 = _mm_mul_pd( x2_2, right_k0_2); right_k1_0 = _mm_mul_pd( x2_0, right_k1_0); right_k1_2 = _mm_mul_pd( x2_2, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k0_2); right_k1_0 = _mm_hadd_pd( right_k1_0, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k1_0); right_k2_0 = _mm_mul_pd( x2_0, right_k2_0); right_k2_2 = _mm_mul_pd( x2_2, right_k2_2); right_k3_0 = _mm_mul_pd( x2_0, right_k3_0); right_k3_2 = _mm_mul_pd( x2_2, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k2_2); right_k3_0 = _mm_hadd_pd( right_k3_0, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k3_0); { // // load left side from tip vector // __m128d uX1_k0_sse = _mm_load_pd( &uX1[j * 4] ); __m128d uX1_k2_sse = _mm_load_pd( &uX1[j * 4 + 2] ); // // multiply left * right // __m128d x1px2_k0 = _mm_mul_pd( uX1_k0_sse, right_k0_0 ); __m128d x1px2_k2 = _mm_mul_pd( uX1_k2_sse, right_k2_0 ); // // multiply with EV matrix (!?) // __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); values[j * 2] = EV_t_l0_k0; values[j * 2 + 1] = EV_t_l2_k0; maxv = _mm_max_pd(maxv, _mm_and_pd(EV_t_l0_k0, absMask.m)); maxv = _mm_max_pd(maxv, _mm_and_pd(EV_t_l2_k0, absMask.m)); } } _mm_store_pd(maxima, maxv); max = MAX(maxima[0], maxima[1]); if(max < minlikelihood) { __m128d sv = _mm_set1_pd(twotothe256); _mm_store_pd(&x3[0], _mm_mul_pd(values[0], sv)); _mm_store_pd(&x3[2], _mm_mul_pd(values[1], sv)); _mm_store_pd(&x3[4], _mm_mul_pd(values[2], sv)); _mm_store_pd(&x3[6], _mm_mul_pd(values[3], sv)); _mm_store_pd(&x3[8], _mm_mul_pd(values[4], sv)); _mm_store_pd(&x3[10], _mm_mul_pd(values[5], sv)); _mm_store_pd(&x3[12], _mm_mul_pd(values[6], sv)); _mm_store_pd(&x3[14], _mm_mul_pd(values[7], sv)); addScale += wgt[i]; } else { _mm_store_pd(&x3[0], values[0]); _mm_store_pd(&x3[2], values[1]); _mm_store_pd(&x3[4], values[2]); _mm_store_pd(&x3[6], values[3]); _mm_store_pd(&x3[8], values[4]); _mm_store_pd(&x3[10], values[5]); _mm_store_pd(&x3[12], values[6]); _mm_store_pd(&x3[14], values[7]); } x3 += 16; } } } break; case INNER_INNER: { __m128d maxv =_mm_setzero_pd(); scaleGap = 0; x1 = x1_gapColumn; x2 = x2_gapColumn; x3 = x3_gapColumn; for (j = 0; j < 4; j++) { double *x1_p = &x1[j*4]; double *left_k0_p = &left[j*16]; double *left_k1_p = &left[j*16 + 1*4]; double *left_k2_p = &left[j*16 + 2*4]; double *left_k3_p = &left[j*16 + 3*4]; __m128d x1_0 = _mm_load_pd( &x1_p[0] ); __m128d x1_2 = _mm_load_pd( &x1_p[2] ); __m128d left_k0_0 = _mm_load_pd( &left_k0_p[0] ); __m128d left_k0_2 = _mm_load_pd( &left_k0_p[2] ); __m128d left_k1_0 = _mm_load_pd( &left_k1_p[0] ); __m128d left_k1_2 = _mm_load_pd( &left_k1_p[2] ); __m128d left_k2_0 = _mm_load_pd( &left_k2_p[0] ); __m128d left_k2_2 = _mm_load_pd( &left_k2_p[2] ); __m128d left_k3_0 = _mm_load_pd( &left_k3_p[0] ); __m128d left_k3_2 = _mm_load_pd( &left_k3_p[2] ); left_k0_0 = _mm_mul_pd(x1_0, left_k0_0); left_k0_2 = _mm_mul_pd(x1_2, left_k0_2); left_k1_0 = _mm_mul_pd(x1_0, left_k1_0); left_k1_2 = _mm_mul_pd(x1_2, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k0_2 ); left_k1_0 = _mm_hadd_pd( left_k1_0, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k1_0); left_k2_0 = _mm_mul_pd(x1_0, left_k2_0); left_k2_2 = _mm_mul_pd(x1_2, left_k2_2); left_k3_0 = _mm_mul_pd(x1_0, left_k3_0); left_k3_2 = _mm_mul_pd(x1_2, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k2_2); left_k3_0 = _mm_hadd_pd( left_k3_0, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k3_0); double *x2_p = &x2[j*4]; double *right_k0_p = &right[j*16]; double *right_k1_p = &right[j*16 + 1*4]; double *right_k2_p = &right[j*16 + 2*4]; double *right_k3_p = &right[j*16 + 3*4]; __m128d x2_0 = _mm_load_pd( &x2_p[0] ); __m128d x2_2 = _mm_load_pd( &x2_p[2] ); __m128d right_k0_0 = _mm_load_pd( &right_k0_p[0] ); __m128d right_k0_2 = _mm_load_pd( &right_k0_p[2] ); __m128d right_k1_0 = _mm_load_pd( &right_k1_p[0] ); __m128d right_k1_2 = _mm_load_pd( &right_k1_p[2] ); __m128d right_k2_0 = _mm_load_pd( &right_k2_p[0] ); __m128d right_k2_2 = _mm_load_pd( &right_k2_p[2] ); __m128d right_k3_0 = _mm_load_pd( &right_k3_p[0] ); __m128d right_k3_2 = _mm_load_pd( &right_k3_p[2] ); right_k0_0 = _mm_mul_pd( x2_0, right_k0_0); right_k0_2 = _mm_mul_pd( x2_2, right_k0_2); right_k1_0 = _mm_mul_pd( x2_0, right_k1_0); right_k1_2 = _mm_mul_pd( x2_2, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k0_2); right_k1_0 = _mm_hadd_pd( right_k1_0, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k1_0); right_k2_0 = _mm_mul_pd( x2_0, right_k2_0); right_k2_2 = _mm_mul_pd( x2_2, right_k2_2); right_k3_0 = _mm_mul_pd( x2_0, right_k3_0); right_k3_2 = _mm_mul_pd( x2_2, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k2_2); right_k3_0 = _mm_hadd_pd( right_k3_0, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k3_0); __m128d x1px2_k0 = _mm_mul_pd( left_k0_0, right_k0_0 ); __m128d x1px2_k2 = _mm_mul_pd( left_k2_0, right_k2_0 ); __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); values[j * 2] = EV_t_l0_k0; values[j * 2 + 1] = EV_t_l2_k0; maxv = _mm_max_pd(maxv, _mm_and_pd(EV_t_l0_k0, absMask.m)); maxv = _mm_max_pd(maxv, _mm_and_pd(EV_t_l2_k0, absMask.m)); } _mm_store_pd(maxima, maxv); max = MAX(maxima[0], maxima[1]); if(max < minlikelihood) { __m128d sv = _mm_set1_pd(twotothe256); scaleGap = 1; _mm_store_pd(&x3[0], _mm_mul_pd(values[0], sv)); _mm_store_pd(&x3[2], _mm_mul_pd(values[1], sv)); _mm_store_pd(&x3[4], _mm_mul_pd(values[2], sv)); _mm_store_pd(&x3[6], _mm_mul_pd(values[3], sv)); _mm_store_pd(&x3[8], _mm_mul_pd(values[4], sv)); _mm_store_pd(&x3[10], _mm_mul_pd(values[5], sv)); _mm_store_pd(&x3[12], _mm_mul_pd(values[6], sv)); _mm_store_pd(&x3[14], _mm_mul_pd(values[7], sv)); } else { _mm_store_pd(&x3[0], values[0]); _mm_store_pd(&x3[2], values[1]); _mm_store_pd(&x3[4], values[2]); _mm_store_pd(&x3[6], values[3]); _mm_store_pd(&x3[8], values[4]); _mm_store_pd(&x3[10], values[5]); _mm_store_pd(&x3[12], values[6]); _mm_store_pd(&x3[14], values[7]); } } x3 = x3_start; for (i = 0; i < n; i++) { if(x3_gap[i / 32] & mask32[i % 32]) { if(scaleGap) { addScale += wgt[i]; } } else { __m128d maxv =_mm_setzero_pd(); if(x1_gap[i / 32] & mask32[i % 32]) x1 = x1_gapColumn; else { x1 = x1_ptr; x1_ptr += 16; } if(x2_gap[i / 32] & mask32[i % 32]) x2 = x2_gapColumn; else { x2 = x2_ptr; x2_ptr += 16; } for (j = 0; j < 4; j++) { double *x1_p = &x1[j*4]; double *left_k0_p = &left[j*16]; double *left_k1_p = &left[j*16 + 1*4]; double *left_k2_p = &left[j*16 + 2*4]; double *left_k3_p = &left[j*16 + 3*4]; __m128d x1_0 = _mm_load_pd( &x1_p[0] ); __m128d x1_2 = _mm_load_pd( &x1_p[2] ); __m128d left_k0_0 = _mm_load_pd( &left_k0_p[0] ); __m128d left_k0_2 = _mm_load_pd( &left_k0_p[2] ); __m128d left_k1_0 = _mm_load_pd( &left_k1_p[0] ); __m128d left_k1_2 = _mm_load_pd( &left_k1_p[2] ); __m128d left_k2_0 = _mm_load_pd( &left_k2_p[0] ); __m128d left_k2_2 = _mm_load_pd( &left_k2_p[2] ); __m128d left_k3_0 = _mm_load_pd( &left_k3_p[0] ); __m128d left_k3_2 = _mm_load_pd( &left_k3_p[2] ); left_k0_0 = _mm_mul_pd(x1_0, left_k0_0); left_k0_2 = _mm_mul_pd(x1_2, left_k0_2); left_k1_0 = _mm_mul_pd(x1_0, left_k1_0); left_k1_2 = _mm_mul_pd(x1_2, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k0_2 ); left_k1_0 = _mm_hadd_pd( left_k1_0, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k1_0); left_k2_0 = _mm_mul_pd(x1_0, left_k2_0); left_k2_2 = _mm_mul_pd(x1_2, left_k2_2); left_k3_0 = _mm_mul_pd(x1_0, left_k3_0); left_k3_2 = _mm_mul_pd(x1_2, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k2_2); left_k3_0 = _mm_hadd_pd( left_k3_0, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k3_0); // // multiply/add right side // double *x2_p = &x2[j*4]; double *right_k0_p = &right[j*16]; double *right_k1_p = &right[j*16 + 1*4]; double *right_k2_p = &right[j*16 + 2*4]; double *right_k3_p = &right[j*16 + 3*4]; __m128d x2_0 = _mm_load_pd( &x2_p[0] ); __m128d x2_2 = _mm_load_pd( &x2_p[2] ); __m128d right_k0_0 = _mm_load_pd( &right_k0_p[0] ); __m128d right_k0_2 = _mm_load_pd( &right_k0_p[2] ); __m128d right_k1_0 = _mm_load_pd( &right_k1_p[0] ); __m128d right_k1_2 = _mm_load_pd( &right_k1_p[2] ); __m128d right_k2_0 = _mm_load_pd( &right_k2_p[0] ); __m128d right_k2_2 = _mm_load_pd( &right_k2_p[2] ); __m128d right_k3_0 = _mm_load_pd( &right_k3_p[0] ); __m128d right_k3_2 = _mm_load_pd( &right_k3_p[2] ); right_k0_0 = _mm_mul_pd( x2_0, right_k0_0); right_k0_2 = _mm_mul_pd( x2_2, right_k0_2); right_k1_0 = _mm_mul_pd( x2_0, right_k1_0); right_k1_2 = _mm_mul_pd( x2_2, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k0_2); right_k1_0 = _mm_hadd_pd( right_k1_0, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k1_0); right_k2_0 = _mm_mul_pd( x2_0, right_k2_0); right_k2_2 = _mm_mul_pd( x2_2, right_k2_2); right_k3_0 = _mm_mul_pd( x2_0, right_k3_0); right_k3_2 = _mm_mul_pd( x2_2, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k2_2); right_k3_0 = _mm_hadd_pd( right_k3_0, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k3_0); // // multiply left * right // __m128d x1px2_k0 = _mm_mul_pd( left_k0_0, right_k0_0 ); __m128d x1px2_k2 = _mm_mul_pd( left_k2_0, right_k2_0 ); // // multiply with EV matrix (!?) // __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); values[j * 2] = EV_t_l0_k0; values[j * 2 + 1] = EV_t_l2_k0; maxv = _mm_max_pd(maxv, _mm_and_pd(EV_t_l0_k0, absMask.m)); maxv = _mm_max_pd(maxv, _mm_and_pd(EV_t_l2_k0, absMask.m)); } _mm_store_pd(maxima, maxv); max = MAX(maxima[0], maxima[1]); if(max < minlikelihood) { __m128d sv = _mm_set1_pd(twotothe256); _mm_store_pd(&x3[0], _mm_mul_pd(values[0], sv)); _mm_store_pd(&x3[2], _mm_mul_pd(values[1], sv)); _mm_store_pd(&x3[4], _mm_mul_pd(values[2], sv)); _mm_store_pd(&x3[6], _mm_mul_pd(values[3], sv)); _mm_store_pd(&x3[8], _mm_mul_pd(values[4], sv)); _mm_store_pd(&x3[10], _mm_mul_pd(values[5], sv)); _mm_store_pd(&x3[12], _mm_mul_pd(values[6], sv)); _mm_store_pd(&x3[14], _mm_mul_pd(values[7], sv)); addScale += wgt[i]; } else { _mm_store_pd(&x3[0], values[0]); _mm_store_pd(&x3[2], values[1]); _mm_store_pd(&x3[4], values[2]); _mm_store_pd(&x3[6], values[3]); _mm_store_pd(&x3[8], values[4]); _mm_store_pd(&x3[10], values[5]); _mm_store_pd(&x3[12], values[6]); _mm_store_pd(&x3[14], values[7]); } x3 += 16; } } break; default: assert(0); } *scalerIncrement = addScale; } static void newviewGTRGAMMA(int tipCase, double *x1_start, double *x2_start, double *x3_start, double *EV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, const int n, double *left, double *right, int *wgt, int *scalerIncrement ) { int i, j, k, l, addScale = 0; double *x1, *x2, *x3, max, maxima[2] __attribute__ ((aligned (BYTE_ALIGNMENT))), EV_t[16] __attribute__ ((aligned (BYTE_ALIGNMENT))); __m128d values[8], EVV[8]; for(k = 0; k < 4; k++) for (l=0; l < 4; l++) EV_t[4 * l + k] = EV[4 * k + l]; for(k = 0; k < 8; k++) EVV[k] = _mm_load_pd(&EV_t[k * 2]); switch(tipCase) { case TIP_TIP: { double *uX1, umpX1[256] __attribute__ ((aligned (BYTE_ALIGNMENT))), *uX2, umpX2[256] __attribute__ ((aligned (BYTE_ALIGNMENT))); for (i = 1; i < 16; i++) { __m128d x1_1 = _mm_load_pd(&(tipVector[i*4])); __m128d x1_2 = _mm_load_pd(&(tipVector[i*4 + 2])); for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { __m128d left1 = _mm_load_pd(&left[j*16 + k*4]); __m128d left2 = _mm_load_pd(&left[j*16 + k*4 + 2]); __m128d acc = _mm_setzero_pd(); acc = _mm_add_pd(acc, _mm_mul_pd(left1, x1_1)); acc = _mm_add_pd(acc, _mm_mul_pd(left2, x1_2)); acc = _mm_hadd_pd(acc, acc); _mm_storel_pd(&umpX1[i*16 + j*4 + k], acc); } for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { __m128d left1 = _mm_load_pd(&right[j*16 + k*4]); __m128d left2 = _mm_load_pd(&right[j*16 + k*4 + 2]); __m128d acc = _mm_setzero_pd(); acc = _mm_add_pd(acc, _mm_mul_pd(left1, x1_1)); acc = _mm_add_pd(acc, _mm_mul_pd(left2, x1_2)); acc = _mm_hadd_pd(acc, acc); _mm_storel_pd(&umpX2[i*16 + j*4 + k], acc); } } for (i = 0; i < n; i++) { x3 = &x3_start[i * 16]; uX1 = &umpX1[16 * tipX1[i]]; uX2 = &umpX2[16 * tipX2[i]]; for (j = 0; j < 4; j++) { __m128d uX1_k0_sse = _mm_load_pd( &uX1[j * 4] ); __m128d uX1_k2_sse = _mm_load_pd( &uX1[j * 4 + 2] ); __m128d uX2_k0_sse = _mm_load_pd( &uX2[j * 4] ); __m128d uX2_k2_sse = _mm_load_pd( &uX2[j * 4 + 2] ); // // multiply left * right // __m128d x1px2_k0 = _mm_mul_pd( uX1_k0_sse, uX2_k0_sse ); __m128d x1px2_k2 = _mm_mul_pd( uX1_k2_sse, uX2_k2_sse ); // // multiply with EV matrix (!?) // __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); _mm_store_pd( &x3[j * 4 + 0], EV_t_l0_k0 ); _mm_store_pd( &x3[j * 4 + 2], EV_t_l2_k0 ); } } } break; case TIP_INNER: { double *uX1, umpX1[256] __attribute__ ((aligned (BYTE_ALIGNMENT))); for (i = 1; i < 16; i++) { __m128d x1_1 = _mm_load_pd(&(tipVector[i*4])); __m128d x1_2 = _mm_load_pd(&(tipVector[i*4 + 2])); for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { __m128d left1 = _mm_load_pd(&left[j*16 + k*4]); __m128d left2 = _mm_load_pd(&left[j*16 + k*4 + 2]); __m128d acc = _mm_setzero_pd(); acc = _mm_add_pd(acc, _mm_mul_pd(left1, x1_1)); acc = _mm_add_pd(acc, _mm_mul_pd(left2, x1_2)); acc = _mm_hadd_pd(acc, acc); _mm_storel_pd(&umpX1[i*16 + j*4 + k], acc); } } for (i = 0; i < n; i++) { __m128d maxv =_mm_setzero_pd(); x2 = &x2_start[i * 16]; x3 = &x3_start[i * 16]; uX1 = &umpX1[16 * tipX1[i]]; for (j = 0; j < 4; j++) { // // multiply/add right side // double *x2_p = &x2[j*4]; double *right_k0_p = &right[j*16]; double *right_k1_p = &right[j*16 + 1*4]; double *right_k2_p = &right[j*16 + 2*4]; double *right_k3_p = &right[j*16 + 3*4]; __m128d x2_0 = _mm_load_pd( &x2_p[0] ); __m128d x2_2 = _mm_load_pd( &x2_p[2] ); __m128d right_k0_0 = _mm_load_pd( &right_k0_p[0] ); __m128d right_k0_2 = _mm_load_pd( &right_k0_p[2] ); __m128d right_k1_0 = _mm_load_pd( &right_k1_p[0] ); __m128d right_k1_2 = _mm_load_pd( &right_k1_p[2] ); __m128d right_k2_0 = _mm_load_pd( &right_k2_p[0] ); __m128d right_k2_2 = _mm_load_pd( &right_k2_p[2] ); __m128d right_k3_0 = _mm_load_pd( &right_k3_p[0] ); __m128d right_k3_2 = _mm_load_pd( &right_k3_p[2] ); right_k0_0 = _mm_mul_pd( x2_0, right_k0_0); right_k0_2 = _mm_mul_pd( x2_2, right_k0_2); right_k1_0 = _mm_mul_pd( x2_0, right_k1_0); right_k1_2 = _mm_mul_pd( x2_2, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k0_2); right_k1_0 = _mm_hadd_pd( right_k1_0, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k1_0); right_k2_0 = _mm_mul_pd( x2_0, right_k2_0); right_k2_2 = _mm_mul_pd( x2_2, right_k2_2); right_k3_0 = _mm_mul_pd( x2_0, right_k3_0); right_k3_2 = _mm_mul_pd( x2_2, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k2_2); right_k3_0 = _mm_hadd_pd( right_k3_0, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k3_0); { // // load left side from tip vector // __m128d uX1_k0_sse = _mm_load_pd( &uX1[j * 4] ); __m128d uX1_k2_sse = _mm_load_pd( &uX1[j * 4 + 2] ); // // multiply left * right // __m128d x1px2_k0 = _mm_mul_pd( uX1_k0_sse, right_k0_0 ); __m128d x1px2_k2 = _mm_mul_pd( uX1_k2_sse, right_k2_0 ); // // multiply with EV matrix (!?) // __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); values[j * 2] = EV_t_l0_k0; values[j * 2 + 1] = EV_t_l2_k0; maxv = _mm_max_pd(maxv, _mm_and_pd(EV_t_l0_k0, absMask.m)); maxv = _mm_max_pd(maxv, _mm_and_pd(EV_t_l2_k0, absMask.m)); } } _mm_store_pd(maxima, maxv); max = MAX(maxima[0], maxima[1]); if(max < minlikelihood) { __m128d sv = _mm_set1_pd(twotothe256); _mm_store_pd(&x3[0], _mm_mul_pd(values[0], sv)); _mm_store_pd(&x3[2], _mm_mul_pd(values[1], sv)); _mm_store_pd(&x3[4], _mm_mul_pd(values[2], sv)); _mm_store_pd(&x3[6], _mm_mul_pd(values[3], sv)); _mm_store_pd(&x3[8], _mm_mul_pd(values[4], sv)); _mm_store_pd(&x3[10], _mm_mul_pd(values[5], sv)); _mm_store_pd(&x3[12], _mm_mul_pd(values[6], sv)); _mm_store_pd(&x3[14], _mm_mul_pd(values[7], sv)); addScale += wgt[i]; } else { _mm_store_pd(&x3[0], values[0]); _mm_store_pd(&x3[2], values[1]); _mm_store_pd(&x3[4], values[2]); _mm_store_pd(&x3[6], values[3]); _mm_store_pd(&x3[8], values[4]); _mm_store_pd(&x3[10], values[5]); _mm_store_pd(&x3[12], values[6]); _mm_store_pd(&x3[14], values[7]); } } } break; case INNER_INNER: for (i = 0; i < n; i++) { __m128d maxv =_mm_setzero_pd(); x1 = &x1_start[i * 16]; x2 = &x2_start[i * 16]; x3 = &x3_start[i * 16]; for (j = 0; j < 4; j++) { double *x1_p = &x1[j*4]; double *left_k0_p = &left[j*16]; double *left_k1_p = &left[j*16 + 1*4]; double *left_k2_p = &left[j*16 + 2*4]; double *left_k3_p = &left[j*16 + 3*4]; __m128d x1_0 = _mm_load_pd( &x1_p[0] ); __m128d x1_2 = _mm_load_pd( &x1_p[2] ); __m128d left_k0_0 = _mm_load_pd( &left_k0_p[0] ); __m128d left_k0_2 = _mm_load_pd( &left_k0_p[2] ); __m128d left_k1_0 = _mm_load_pd( &left_k1_p[0] ); __m128d left_k1_2 = _mm_load_pd( &left_k1_p[2] ); __m128d left_k2_0 = _mm_load_pd( &left_k2_p[0] ); __m128d left_k2_2 = _mm_load_pd( &left_k2_p[2] ); __m128d left_k3_0 = _mm_load_pd( &left_k3_p[0] ); __m128d left_k3_2 = _mm_load_pd( &left_k3_p[2] ); left_k0_0 = _mm_mul_pd(x1_0, left_k0_0); left_k0_2 = _mm_mul_pd(x1_2, left_k0_2); left_k1_0 = _mm_mul_pd(x1_0, left_k1_0); left_k1_2 = _mm_mul_pd(x1_2, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k0_2 ); left_k1_0 = _mm_hadd_pd( left_k1_0, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k1_0); left_k2_0 = _mm_mul_pd(x1_0, left_k2_0); left_k2_2 = _mm_mul_pd(x1_2, left_k2_2); left_k3_0 = _mm_mul_pd(x1_0, left_k3_0); left_k3_2 = _mm_mul_pd(x1_2, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k2_2); left_k3_0 = _mm_hadd_pd( left_k3_0, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k3_0); // // multiply/add right side // double *x2_p = &x2[j*4]; double *right_k0_p = &right[j*16]; double *right_k1_p = &right[j*16 + 1*4]; double *right_k2_p = &right[j*16 + 2*4]; double *right_k3_p = &right[j*16 + 3*4]; __m128d x2_0 = _mm_load_pd( &x2_p[0] ); __m128d x2_2 = _mm_load_pd( &x2_p[2] ); __m128d right_k0_0 = _mm_load_pd( &right_k0_p[0] ); __m128d right_k0_2 = _mm_load_pd( &right_k0_p[2] ); __m128d right_k1_0 = _mm_load_pd( &right_k1_p[0] ); __m128d right_k1_2 = _mm_load_pd( &right_k1_p[2] ); __m128d right_k2_0 = _mm_load_pd( &right_k2_p[0] ); __m128d right_k2_2 = _mm_load_pd( &right_k2_p[2] ); __m128d right_k3_0 = _mm_load_pd( &right_k3_p[0] ); __m128d right_k3_2 = _mm_load_pd( &right_k3_p[2] ); right_k0_0 = _mm_mul_pd( x2_0, right_k0_0); right_k0_2 = _mm_mul_pd( x2_2, right_k0_2); right_k1_0 = _mm_mul_pd( x2_0, right_k1_0); right_k1_2 = _mm_mul_pd( x2_2, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k0_2); right_k1_0 = _mm_hadd_pd( right_k1_0, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k1_0); right_k2_0 = _mm_mul_pd( x2_0, right_k2_0); right_k2_2 = _mm_mul_pd( x2_2, right_k2_2); right_k3_0 = _mm_mul_pd( x2_0, right_k3_0); right_k3_2 = _mm_mul_pd( x2_2, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k2_2); right_k3_0 = _mm_hadd_pd( right_k3_0, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k3_0); // // multiply left * right // __m128d x1px2_k0 = _mm_mul_pd( left_k0_0, right_k0_0 ); __m128d x1px2_k2 = _mm_mul_pd( left_k2_0, right_k2_0 ); // // multiply with EV matrix (!?) // __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); values[j * 2] = EV_t_l0_k0; values[j * 2 + 1] = EV_t_l2_k0; maxv = _mm_max_pd(maxv, _mm_and_pd(EV_t_l0_k0, absMask.m)); maxv = _mm_max_pd(maxv, _mm_and_pd(EV_t_l2_k0, absMask.m)); } _mm_store_pd(maxima, maxv); max = MAX(maxima[0], maxima[1]); if(max < minlikelihood) { __m128d sv = _mm_set1_pd(twotothe256); _mm_store_pd(&x3[0], _mm_mul_pd(values[0], sv)); _mm_store_pd(&x3[2], _mm_mul_pd(values[1], sv)); _mm_store_pd(&x3[4], _mm_mul_pd(values[2], sv)); _mm_store_pd(&x3[6], _mm_mul_pd(values[3], sv)); _mm_store_pd(&x3[8], _mm_mul_pd(values[4], sv)); _mm_store_pd(&x3[10], _mm_mul_pd(values[5], sv)); _mm_store_pd(&x3[12], _mm_mul_pd(values[6], sv)); _mm_store_pd(&x3[14], _mm_mul_pd(values[7], sv)); addScale += wgt[i]; } else { _mm_store_pd(&x3[0], values[0]); _mm_store_pd(&x3[2], values[1]); _mm_store_pd(&x3[4], values[2]); _mm_store_pd(&x3[6], values[3]); _mm_store_pd(&x3[8], values[4]); _mm_store_pd(&x3[10], values[5]); _mm_store_pd(&x3[12], values[6]); _mm_store_pd(&x3[14], values[7]); } } break; default: assert(0); } *scalerIncrement = addScale; } static void newviewGTRCAT( int tipCase, double *EV, int *cptr, double *x1_start, double *x2_start, double *x3_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement) { double *le, *ri, *x1, *x2, *x3, EV_t[16] __attribute__ ((aligned (BYTE_ALIGNMENT))); int i, j, scale, addScale = 0; __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ), sc = _mm_set1_pd(twotothe256), EVV[8]; for(i = 0; i < 4; i++) for (j=0; j < 4; j++) EV_t[4 * j + i] = EV[4 * i + j]; for(i = 0; i < 8; i++) EVV[i] = _mm_load_pd(&EV_t[i * 2]); switch(tipCase) { case TIP_TIP: for (i = 0; i < n; i++) { x1 = &(tipVector[4 * tipX1[i]]); x2 = &(tipVector[4 * tipX2[i]]); x3 = &x3_start[i * 4]; le = &left[cptr[i] * 16]; ri = &right[cptr[i] * 16]; __m128d x1_0 = _mm_load_pd( &x1[0] ); __m128d x1_2 = _mm_load_pd( &x1[2] ); __m128d left_k0_0 = _mm_load_pd( &le[0] ); __m128d left_k0_2 = _mm_load_pd( &le[2] ); __m128d left_k1_0 = _mm_load_pd( &le[4] ); __m128d left_k1_2 = _mm_load_pd( &le[6] ); __m128d left_k2_0 = _mm_load_pd( &le[8] ); __m128d left_k2_2 = _mm_load_pd( &le[10] ); __m128d left_k3_0 = _mm_load_pd( &le[12] ); __m128d left_k3_2 = _mm_load_pd( &le[14] ); left_k0_0 = _mm_mul_pd(x1_0, left_k0_0); left_k0_2 = _mm_mul_pd(x1_2, left_k0_2); left_k1_0 = _mm_mul_pd(x1_0, left_k1_0); left_k1_2 = _mm_mul_pd(x1_2, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k0_2 ); left_k1_0 = _mm_hadd_pd( left_k1_0, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k1_0); left_k2_0 = _mm_mul_pd(x1_0, left_k2_0); left_k2_2 = _mm_mul_pd(x1_2, left_k2_2); left_k3_0 = _mm_mul_pd(x1_0, left_k3_0); left_k3_2 = _mm_mul_pd(x1_2, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k2_2); left_k3_0 = _mm_hadd_pd( left_k3_0, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k3_0); __m128d x2_0 = _mm_load_pd( &x2[0] ); __m128d x2_2 = _mm_load_pd( &x2[2] ); __m128d right_k0_0 = _mm_load_pd( &ri[0] ); __m128d right_k0_2 = _mm_load_pd( &ri[2] ); __m128d right_k1_0 = _mm_load_pd( &ri[4] ); __m128d right_k1_2 = _mm_load_pd( &ri[6] ); __m128d right_k2_0 = _mm_load_pd( &ri[8] ); __m128d right_k2_2 = _mm_load_pd( &ri[10] ); __m128d right_k3_0 = _mm_load_pd( &ri[12] ); __m128d right_k3_2 = _mm_load_pd( &ri[14] ); right_k0_0 = _mm_mul_pd( x2_0, right_k0_0); right_k0_2 = _mm_mul_pd( x2_2, right_k0_2); right_k1_0 = _mm_mul_pd( x2_0, right_k1_0); right_k1_2 = _mm_mul_pd( x2_2, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k0_2); right_k1_0 = _mm_hadd_pd( right_k1_0, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k1_0); right_k2_0 = _mm_mul_pd( x2_0, right_k2_0); right_k2_2 = _mm_mul_pd( x2_2, right_k2_2); right_k3_0 = _mm_mul_pd( x2_0, right_k3_0); right_k3_2 = _mm_mul_pd( x2_2, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k2_2); right_k3_0 = _mm_hadd_pd( right_k3_0, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k3_0); __m128d x1px2_k0 = _mm_mul_pd( left_k0_0, right_k0_0 ); __m128d x1px2_k2 = _mm_mul_pd( left_k2_0, right_k2_0 ); __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); _mm_store_pd(x3, EV_t_l0_k0); _mm_store_pd(&x3[2], EV_t_l2_k0); } break; case TIP_INNER: for (i = 0; i < n; i++) { x1 = &(tipVector[4 * tipX1[i]]); x2 = &x2_start[4 * i]; x3 = &x3_start[4 * i]; le = &left[cptr[i] * 16]; ri = &right[cptr[i] * 16]; __m128d x1_0 = _mm_load_pd( &x1[0] ); __m128d x1_2 = _mm_load_pd( &x1[2] ); __m128d left_k0_0 = _mm_load_pd( &le[0] ); __m128d left_k0_2 = _mm_load_pd( &le[2] ); __m128d left_k1_0 = _mm_load_pd( &le[4] ); __m128d left_k1_2 = _mm_load_pd( &le[6] ); __m128d left_k2_0 = _mm_load_pd( &le[8] ); __m128d left_k2_2 = _mm_load_pd( &le[10] ); __m128d left_k3_0 = _mm_load_pd( &le[12] ); __m128d left_k3_2 = _mm_load_pd( &le[14] ); left_k0_0 = _mm_mul_pd(x1_0, left_k0_0); left_k0_2 = _mm_mul_pd(x1_2, left_k0_2); left_k1_0 = _mm_mul_pd(x1_0, left_k1_0); left_k1_2 = _mm_mul_pd(x1_2, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k0_2 ); left_k1_0 = _mm_hadd_pd( left_k1_0, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k1_0); left_k2_0 = _mm_mul_pd(x1_0, left_k2_0); left_k2_2 = _mm_mul_pd(x1_2, left_k2_2); left_k3_0 = _mm_mul_pd(x1_0, left_k3_0); left_k3_2 = _mm_mul_pd(x1_2, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k2_2); left_k3_0 = _mm_hadd_pd( left_k3_0, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k3_0); __m128d x2_0 = _mm_load_pd( &x2[0] ); __m128d x2_2 = _mm_load_pd( &x2[2] ); __m128d right_k0_0 = _mm_load_pd( &ri[0] ); __m128d right_k0_2 = _mm_load_pd( &ri[2] ); __m128d right_k1_0 = _mm_load_pd( &ri[4] ); __m128d right_k1_2 = _mm_load_pd( &ri[6] ); __m128d right_k2_0 = _mm_load_pd( &ri[8] ); __m128d right_k2_2 = _mm_load_pd( &ri[10] ); __m128d right_k3_0 = _mm_load_pd( &ri[12] ); __m128d right_k3_2 = _mm_load_pd( &ri[14] ); right_k0_0 = _mm_mul_pd( x2_0, right_k0_0); right_k0_2 = _mm_mul_pd( x2_2, right_k0_2); right_k1_0 = _mm_mul_pd( x2_0, right_k1_0); right_k1_2 = _mm_mul_pd( x2_2, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k0_2); right_k1_0 = _mm_hadd_pd( right_k1_0, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k1_0); right_k2_0 = _mm_mul_pd( x2_0, right_k2_0); right_k2_2 = _mm_mul_pd( x2_2, right_k2_2); right_k3_0 = _mm_mul_pd( x2_0, right_k3_0); right_k3_2 = _mm_mul_pd( x2_2, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k2_2); right_k3_0 = _mm_hadd_pd( right_k3_0, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k3_0); __m128d x1px2_k0 = _mm_mul_pd( left_k0_0, right_k0_0 ); __m128d x1px2_k2 = _mm_mul_pd( left_k2_0, right_k2_0 ); __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); scale = 1; __m128d v1 = _mm_and_pd(EV_t_l0_k0, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; else { v1 = _mm_and_pd(EV_t_l2_k0, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } if(scale) { _mm_store_pd(&x3[0], _mm_mul_pd(EV_t_l0_k0, sc)); _mm_store_pd(&x3[2], _mm_mul_pd(EV_t_l2_k0, sc)); addScale += wgt[i]; } else { _mm_store_pd(x3, EV_t_l0_k0); _mm_store_pd(&x3[2], EV_t_l2_k0); } } break; case INNER_INNER: for (i = 0; i < n; i++) { x1 = &x1_start[4 * i]; x2 = &x2_start[4 * i]; x3 = &x3_start[4 * i]; le = &left[cptr[i] * 16]; ri = &right[cptr[i] * 16]; __m128d x1_0 = _mm_load_pd( &x1[0] ); __m128d x1_2 = _mm_load_pd( &x1[2] ); __m128d left_k0_0 = _mm_load_pd( &le[0] ); __m128d left_k0_2 = _mm_load_pd( &le[2] ); __m128d left_k1_0 = _mm_load_pd( &le[4] ); __m128d left_k1_2 = _mm_load_pd( &le[6] ); __m128d left_k2_0 = _mm_load_pd( &le[8] ); __m128d left_k2_2 = _mm_load_pd( &le[10] ); __m128d left_k3_0 = _mm_load_pd( &le[12] ); __m128d left_k3_2 = _mm_load_pd( &le[14] ); left_k0_0 = _mm_mul_pd(x1_0, left_k0_0); left_k0_2 = _mm_mul_pd(x1_2, left_k0_2); left_k1_0 = _mm_mul_pd(x1_0, left_k1_0); left_k1_2 = _mm_mul_pd(x1_2, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k0_2 ); left_k1_0 = _mm_hadd_pd( left_k1_0, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k1_0); left_k2_0 = _mm_mul_pd(x1_0, left_k2_0); left_k2_2 = _mm_mul_pd(x1_2, left_k2_2); left_k3_0 = _mm_mul_pd(x1_0, left_k3_0); left_k3_2 = _mm_mul_pd(x1_2, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k2_2); left_k3_0 = _mm_hadd_pd( left_k3_0, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k3_0); __m128d x2_0 = _mm_load_pd( &x2[0] ); __m128d x2_2 = _mm_load_pd( &x2[2] ); __m128d right_k0_0 = _mm_load_pd( &ri[0] ); __m128d right_k0_2 = _mm_load_pd( &ri[2] ); __m128d right_k1_0 = _mm_load_pd( &ri[4] ); __m128d right_k1_2 = _mm_load_pd( &ri[6] ); __m128d right_k2_0 = _mm_load_pd( &ri[8] ); __m128d right_k2_2 = _mm_load_pd( &ri[10] ); __m128d right_k3_0 = _mm_load_pd( &ri[12] ); __m128d right_k3_2 = _mm_load_pd( &ri[14] ); right_k0_0 = _mm_mul_pd( x2_0, right_k0_0); right_k0_2 = _mm_mul_pd( x2_2, right_k0_2); right_k1_0 = _mm_mul_pd( x2_0, right_k1_0); right_k1_2 = _mm_mul_pd( x2_2, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k0_2); right_k1_0 = _mm_hadd_pd( right_k1_0, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k1_0); right_k2_0 = _mm_mul_pd( x2_0, right_k2_0); right_k2_2 = _mm_mul_pd( x2_2, right_k2_2); right_k3_0 = _mm_mul_pd( x2_0, right_k3_0); right_k3_2 = _mm_mul_pd( x2_2, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k2_2); right_k3_0 = _mm_hadd_pd( right_k3_0, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k3_0); __m128d x1px2_k0 = _mm_mul_pd( left_k0_0, right_k0_0 ); __m128d x1px2_k2 = _mm_mul_pd( left_k2_0, right_k2_0 ); __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); scale = 1; __m128d v1 = _mm_and_pd(EV_t_l0_k0, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; else { v1 = _mm_and_pd(EV_t_l2_k0, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } if(scale) { _mm_store_pd(&x3[0], _mm_mul_pd(EV_t_l0_k0, sc)); _mm_store_pd(&x3[2], _mm_mul_pd(EV_t_l2_k0, sc)); addScale += wgt[i]; } else { _mm_store_pd(x3, EV_t_l0_k0); _mm_store_pd(&x3[2], EV_t_l2_k0); } } break; default: assert(0); } *scalerIncrement = addScale; } static void newviewGTRCAT_SAVE( int tipCase, double *EV, int *cptr, double *x1_start, double *x2_start, double *x3_start, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn, const int maxCats) { double *le, *ri, *x1, *x2, *x3, *x1_ptr = x1_start, *x2_ptr = x2_start, *x3_ptr = x3_start, EV_t[16] __attribute__ ((aligned (BYTE_ALIGNMENT))); int i, j, scale, scaleGap = 0, addScale = 0; __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ), sc = _mm_set1_pd(twotothe256), EVV[8]; for(i = 0; i < 4; i++) for (j=0; j < 4; j++) EV_t[4 * j + i] = EV[4 * i + j]; for(i = 0; i < 8; i++) EVV[i] = _mm_load_pd(&EV_t[i * 2]); { x1 = x1_gapColumn; x2 = x2_gapColumn; x3 = x3_gapColumn; le = &left[maxCats * 16]; ri = &right[maxCats * 16]; __m128d x1_0 = _mm_load_pd( &x1[0] ); __m128d x1_2 = _mm_load_pd( &x1[2] ); __m128d left_k0_0 = _mm_load_pd( &le[0] ); __m128d left_k0_2 = _mm_load_pd( &le[2] ); __m128d left_k1_0 = _mm_load_pd( &le[4] ); __m128d left_k1_2 = _mm_load_pd( &le[6] ); __m128d left_k2_0 = _mm_load_pd( &le[8] ); __m128d left_k2_2 = _mm_load_pd( &le[10] ); __m128d left_k3_0 = _mm_load_pd( &le[12] ); __m128d left_k3_2 = _mm_load_pd( &le[14] ); left_k0_0 = _mm_mul_pd(x1_0, left_k0_0); left_k0_2 = _mm_mul_pd(x1_2, left_k0_2); left_k1_0 = _mm_mul_pd(x1_0, left_k1_0); left_k1_2 = _mm_mul_pd(x1_2, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k0_2 ); left_k1_0 = _mm_hadd_pd( left_k1_0, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k1_0); left_k2_0 = _mm_mul_pd(x1_0, left_k2_0); left_k2_2 = _mm_mul_pd(x1_2, left_k2_2); left_k3_0 = _mm_mul_pd(x1_0, left_k3_0); left_k3_2 = _mm_mul_pd(x1_2, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k2_2); left_k3_0 = _mm_hadd_pd( left_k3_0, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k3_0); __m128d x2_0 = _mm_load_pd( &x2[0] ); __m128d x2_2 = _mm_load_pd( &x2[2] ); __m128d right_k0_0 = _mm_load_pd( &ri[0] ); __m128d right_k0_2 = _mm_load_pd( &ri[2] ); __m128d right_k1_0 = _mm_load_pd( &ri[4] ); __m128d right_k1_2 = _mm_load_pd( &ri[6] ); __m128d right_k2_0 = _mm_load_pd( &ri[8] ); __m128d right_k2_2 = _mm_load_pd( &ri[10] ); __m128d right_k3_0 = _mm_load_pd( &ri[12] ); __m128d right_k3_2 = _mm_load_pd( &ri[14] ); right_k0_0 = _mm_mul_pd( x2_0, right_k0_0); right_k0_2 = _mm_mul_pd( x2_2, right_k0_2); right_k1_0 = _mm_mul_pd( x2_0, right_k1_0); right_k1_2 = _mm_mul_pd( x2_2, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k0_2); right_k1_0 = _mm_hadd_pd( right_k1_0, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k1_0); right_k2_0 = _mm_mul_pd( x2_0, right_k2_0); right_k2_2 = _mm_mul_pd( x2_2, right_k2_2); right_k3_0 = _mm_mul_pd( x2_0, right_k3_0); right_k3_2 = _mm_mul_pd( x2_2, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k2_2); right_k3_0 = _mm_hadd_pd( right_k3_0, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k3_0); __m128d x1px2_k0 = _mm_mul_pd( left_k0_0, right_k0_0 ); __m128d x1px2_k2 = _mm_mul_pd( left_k2_0, right_k2_0 ); __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); if(tipCase != TIP_TIP) { scale = 1; __m128d v1 = _mm_and_pd(EV_t_l0_k0, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; else { v1 = _mm_and_pd(EV_t_l2_k0, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } if(scale) { _mm_store_pd(&x3[0], _mm_mul_pd(EV_t_l0_k0, sc)); _mm_store_pd(&x3[2], _mm_mul_pd(EV_t_l2_k0, sc)); scaleGap = TRUE; } else { _mm_store_pd(x3, EV_t_l0_k0); _mm_store_pd(&x3[2], EV_t_l2_k0); } } else { _mm_store_pd(x3, EV_t_l0_k0); _mm_store_pd(&x3[2], EV_t_l2_k0); } } switch(tipCase) { case TIP_TIP: for (i = 0; i < n; i++) { if(noGap(x3_gap, i)) { x1 = &(tipVector[4 * tipX1[i]]); x2 = &(tipVector[4 * tipX2[i]]); x3 = x3_ptr; if(isGap(x1_gap, i)) le = &left[maxCats * 16]; else le = &left[cptr[i] * 16]; if(isGap(x2_gap, i)) ri = &right[maxCats * 16]; else ri = &right[cptr[i] * 16]; __m128d x1_0 = _mm_load_pd( &x1[0] ); __m128d x1_2 = _mm_load_pd( &x1[2] ); __m128d left_k0_0 = _mm_load_pd( &le[0] ); __m128d left_k0_2 = _mm_load_pd( &le[2] ); __m128d left_k1_0 = _mm_load_pd( &le[4] ); __m128d left_k1_2 = _mm_load_pd( &le[6] ); __m128d left_k2_0 = _mm_load_pd( &le[8] ); __m128d left_k2_2 = _mm_load_pd( &le[10] ); __m128d left_k3_0 = _mm_load_pd( &le[12] ); __m128d left_k3_2 = _mm_load_pd( &le[14] ); left_k0_0 = _mm_mul_pd(x1_0, left_k0_0); left_k0_2 = _mm_mul_pd(x1_2, left_k0_2); left_k1_0 = _mm_mul_pd(x1_0, left_k1_0); left_k1_2 = _mm_mul_pd(x1_2, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k0_2 ); left_k1_0 = _mm_hadd_pd( left_k1_0, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k1_0); left_k2_0 = _mm_mul_pd(x1_0, left_k2_0); left_k2_2 = _mm_mul_pd(x1_2, left_k2_2); left_k3_0 = _mm_mul_pd(x1_0, left_k3_0); left_k3_2 = _mm_mul_pd(x1_2, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k2_2); left_k3_0 = _mm_hadd_pd( left_k3_0, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k3_0); __m128d x2_0 = _mm_load_pd( &x2[0] ); __m128d x2_2 = _mm_load_pd( &x2[2] ); __m128d right_k0_0 = _mm_load_pd( &ri[0] ); __m128d right_k0_2 = _mm_load_pd( &ri[2] ); __m128d right_k1_0 = _mm_load_pd( &ri[4] ); __m128d right_k1_2 = _mm_load_pd( &ri[6] ); __m128d right_k2_0 = _mm_load_pd( &ri[8] ); __m128d right_k2_2 = _mm_load_pd( &ri[10] ); __m128d right_k3_0 = _mm_load_pd( &ri[12] ); __m128d right_k3_2 = _mm_load_pd( &ri[14] ); right_k0_0 = _mm_mul_pd( x2_0, right_k0_0); right_k0_2 = _mm_mul_pd( x2_2, right_k0_2); right_k1_0 = _mm_mul_pd( x2_0, right_k1_0); right_k1_2 = _mm_mul_pd( x2_2, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k0_2); right_k1_0 = _mm_hadd_pd( right_k1_0, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k1_0); right_k2_0 = _mm_mul_pd( x2_0, right_k2_0); right_k2_2 = _mm_mul_pd( x2_2, right_k2_2); right_k3_0 = _mm_mul_pd( x2_0, right_k3_0); right_k3_2 = _mm_mul_pd( x2_2, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k2_2); right_k3_0 = _mm_hadd_pd( right_k3_0, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k3_0); __m128d x1px2_k0 = _mm_mul_pd( left_k0_0, right_k0_0 ); __m128d x1px2_k2 = _mm_mul_pd( left_k2_0, right_k2_0 ); __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); _mm_store_pd(x3, EV_t_l0_k0); _mm_store_pd(&x3[2], EV_t_l2_k0); x3_ptr += 4; } } break; case TIP_INNER: for (i = 0; i < n; i++) { if(isGap(x3_gap, i)) { if(scaleGap) addScale += wgt[i]; } else { x1 = &(tipVector[4 * tipX1[i]]); x2 = x2_ptr; x3 = x3_ptr; if(isGap(x1_gap, i)) le = &left[maxCats * 16]; else le = &left[cptr[i] * 16]; if(isGap(x2_gap, i)) { ri = &right[maxCats * 16]; x2 = x2_gapColumn; } else { ri = &right[cptr[i] * 16]; x2 = x2_ptr; x2_ptr += 4; } __m128d x1_0 = _mm_load_pd( &x1[0] ); __m128d x1_2 = _mm_load_pd( &x1[2] ); __m128d left_k0_0 = _mm_load_pd( &le[0] ); __m128d left_k0_2 = _mm_load_pd( &le[2] ); __m128d left_k1_0 = _mm_load_pd( &le[4] ); __m128d left_k1_2 = _mm_load_pd( &le[6] ); __m128d left_k2_0 = _mm_load_pd( &le[8] ); __m128d left_k2_2 = _mm_load_pd( &le[10] ); __m128d left_k3_0 = _mm_load_pd( &le[12] ); __m128d left_k3_2 = _mm_load_pd( &le[14] ); left_k0_0 = _mm_mul_pd(x1_0, left_k0_0); left_k0_2 = _mm_mul_pd(x1_2, left_k0_2); left_k1_0 = _mm_mul_pd(x1_0, left_k1_0); left_k1_2 = _mm_mul_pd(x1_2, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k0_2 ); left_k1_0 = _mm_hadd_pd( left_k1_0, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k1_0); left_k2_0 = _mm_mul_pd(x1_0, left_k2_0); left_k2_2 = _mm_mul_pd(x1_2, left_k2_2); left_k3_0 = _mm_mul_pd(x1_0, left_k3_0); left_k3_2 = _mm_mul_pd(x1_2, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k2_2); left_k3_0 = _mm_hadd_pd( left_k3_0, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k3_0); __m128d x2_0 = _mm_load_pd( &x2[0] ); __m128d x2_2 = _mm_load_pd( &x2[2] ); __m128d right_k0_0 = _mm_load_pd( &ri[0] ); __m128d right_k0_2 = _mm_load_pd( &ri[2] ); __m128d right_k1_0 = _mm_load_pd( &ri[4] ); __m128d right_k1_2 = _mm_load_pd( &ri[6] ); __m128d right_k2_0 = _mm_load_pd( &ri[8] ); __m128d right_k2_2 = _mm_load_pd( &ri[10] ); __m128d right_k3_0 = _mm_load_pd( &ri[12] ); __m128d right_k3_2 = _mm_load_pd( &ri[14] ); right_k0_0 = _mm_mul_pd( x2_0, right_k0_0); right_k0_2 = _mm_mul_pd( x2_2, right_k0_2); right_k1_0 = _mm_mul_pd( x2_0, right_k1_0); right_k1_2 = _mm_mul_pd( x2_2, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k0_2); right_k1_0 = _mm_hadd_pd( right_k1_0, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k1_0); right_k2_0 = _mm_mul_pd( x2_0, right_k2_0); right_k2_2 = _mm_mul_pd( x2_2, right_k2_2); right_k3_0 = _mm_mul_pd( x2_0, right_k3_0); right_k3_2 = _mm_mul_pd( x2_2, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k2_2); right_k3_0 = _mm_hadd_pd( right_k3_0, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k3_0); __m128d x1px2_k0 = _mm_mul_pd( left_k0_0, right_k0_0 ); __m128d x1px2_k2 = _mm_mul_pd( left_k2_0, right_k2_0 ); __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); scale = 1; __m128d v1 = _mm_and_pd(EV_t_l0_k0, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; else { v1 = _mm_and_pd(EV_t_l2_k0, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } if(scale) { _mm_store_pd(&x3[0], _mm_mul_pd(EV_t_l0_k0, sc)); _mm_store_pd(&x3[2], _mm_mul_pd(EV_t_l2_k0, sc)); addScale += wgt[i]; } else { _mm_store_pd(x3, EV_t_l0_k0); _mm_store_pd(&x3[2], EV_t_l2_k0); } x3_ptr += 4; } } break; case INNER_INNER: for (i = 0; i < n; i++) { if(isGap(x3_gap, i)) { if(scaleGap) addScale += wgt[i]; } else { x3 = x3_ptr; if(isGap(x1_gap, i)) { x1 = x1_gapColumn; le = &left[maxCats * 16]; } else { le = &left[cptr[i] * 16]; x1 = x1_ptr; x1_ptr += 4; } if(isGap(x2_gap, i)) { x2 = x2_gapColumn; ri = &right[maxCats * 16]; } else { ri = &right[cptr[i] * 16]; x2 = x2_ptr; x2_ptr += 4; } __m128d x1_0 = _mm_load_pd( &x1[0] ); __m128d x1_2 = _mm_load_pd( &x1[2] ); __m128d left_k0_0 = _mm_load_pd( &le[0] ); __m128d left_k0_2 = _mm_load_pd( &le[2] ); __m128d left_k1_0 = _mm_load_pd( &le[4] ); __m128d left_k1_2 = _mm_load_pd( &le[6] ); __m128d left_k2_0 = _mm_load_pd( &le[8] ); __m128d left_k2_2 = _mm_load_pd( &le[10] ); __m128d left_k3_0 = _mm_load_pd( &le[12] ); __m128d left_k3_2 = _mm_load_pd( &le[14] ); left_k0_0 = _mm_mul_pd(x1_0, left_k0_0); left_k0_2 = _mm_mul_pd(x1_2, left_k0_2); left_k1_0 = _mm_mul_pd(x1_0, left_k1_0); left_k1_2 = _mm_mul_pd(x1_2, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k0_2 ); left_k1_0 = _mm_hadd_pd( left_k1_0, left_k1_2); left_k0_0 = _mm_hadd_pd( left_k0_0, left_k1_0); left_k2_0 = _mm_mul_pd(x1_0, left_k2_0); left_k2_2 = _mm_mul_pd(x1_2, left_k2_2); left_k3_0 = _mm_mul_pd(x1_0, left_k3_0); left_k3_2 = _mm_mul_pd(x1_2, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k2_2); left_k3_0 = _mm_hadd_pd( left_k3_0, left_k3_2); left_k2_0 = _mm_hadd_pd( left_k2_0, left_k3_0); __m128d x2_0 = _mm_load_pd( &x2[0] ); __m128d x2_2 = _mm_load_pd( &x2[2] ); __m128d right_k0_0 = _mm_load_pd( &ri[0] ); __m128d right_k0_2 = _mm_load_pd( &ri[2] ); __m128d right_k1_0 = _mm_load_pd( &ri[4] ); __m128d right_k1_2 = _mm_load_pd( &ri[6] ); __m128d right_k2_0 = _mm_load_pd( &ri[8] ); __m128d right_k2_2 = _mm_load_pd( &ri[10] ); __m128d right_k3_0 = _mm_load_pd( &ri[12] ); __m128d right_k3_2 = _mm_load_pd( &ri[14] ); right_k0_0 = _mm_mul_pd( x2_0, right_k0_0); right_k0_2 = _mm_mul_pd( x2_2, right_k0_2); right_k1_0 = _mm_mul_pd( x2_0, right_k1_0); right_k1_2 = _mm_mul_pd( x2_2, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k0_2); right_k1_0 = _mm_hadd_pd( right_k1_0, right_k1_2); right_k0_0 = _mm_hadd_pd( right_k0_0, right_k1_0); right_k2_0 = _mm_mul_pd( x2_0, right_k2_0); right_k2_2 = _mm_mul_pd( x2_2, right_k2_2); right_k3_0 = _mm_mul_pd( x2_0, right_k3_0); right_k3_2 = _mm_mul_pd( x2_2, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k2_2); right_k3_0 = _mm_hadd_pd( right_k3_0, right_k3_2); right_k2_0 = _mm_hadd_pd( right_k2_0, right_k3_0); __m128d x1px2_k0 = _mm_mul_pd( left_k0_0, right_k0_0 ); __m128d x1px2_k2 = _mm_mul_pd( left_k2_0, right_k2_0 ); __m128d EV_t_l0_k0 = EVV[0]; __m128d EV_t_l0_k2 = EVV[1]; __m128d EV_t_l1_k0 = EVV[2]; __m128d EV_t_l1_k2 = EVV[3]; __m128d EV_t_l2_k0 = EVV[4]; __m128d EV_t_l2_k2 = EVV[5]; __m128d EV_t_l3_k0 = EVV[6]; __m128d EV_t_l3_k2 = EVV[7]; EV_t_l0_k0 = _mm_mul_pd( x1px2_k0, EV_t_l0_k0 ); EV_t_l0_k2 = _mm_mul_pd( x1px2_k2, EV_t_l0_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l0_k2 ); EV_t_l1_k0 = _mm_mul_pd( x1px2_k0, EV_t_l1_k0 ); EV_t_l1_k2 = _mm_mul_pd( x1px2_k2, EV_t_l1_k2 ); EV_t_l1_k0 = _mm_hadd_pd( EV_t_l1_k0, EV_t_l1_k2 ); EV_t_l0_k0 = _mm_hadd_pd( EV_t_l0_k0, EV_t_l1_k0 ); EV_t_l2_k0 = _mm_mul_pd( x1px2_k0, EV_t_l2_k0 ); EV_t_l2_k2 = _mm_mul_pd( x1px2_k2, EV_t_l2_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l2_k2 ); EV_t_l3_k0 = _mm_mul_pd( x1px2_k0, EV_t_l3_k0 ); EV_t_l3_k2 = _mm_mul_pd( x1px2_k2, EV_t_l3_k2 ); EV_t_l3_k0 = _mm_hadd_pd( EV_t_l3_k0, EV_t_l3_k2 ); EV_t_l2_k0 = _mm_hadd_pd( EV_t_l2_k0, EV_t_l3_k0 ); scale = 1; __m128d v1 = _mm_and_pd(EV_t_l0_k0, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; else { v1 = _mm_and_pd(EV_t_l2_k0, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } if(scale) { _mm_store_pd(&x3[0], _mm_mul_pd(EV_t_l0_k0, sc)); _mm_store_pd(&x3[2], _mm_mul_pd(EV_t_l2_k0, sc)); addScale += wgt[i]; } else { _mm_store_pd(x3, EV_t_l0_k0); _mm_store_pd(&x3[2], EV_t_l2_k0); } x3_ptr += 4; } } break; default: assert(0); } *scalerIncrement = addScale; } static void newviewGTRGAMMAPROT_GAPPED_SAVE(int tipCase, double *x1, double *x2, double *x3, double *extEV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn ) { double *uX1, *uX2, *v; double x1px2; int i, j, l, k, scale, addScale = 0, gapScaling = 0; double *vl, *vr, *x1v, *x2v, *x1_ptr = x1, *x2_ptr = x2, *x3_ptr = x3; switch(tipCase) { case TIP_TIP: { double umpX1[1840], umpX2[1840]; for(i = 0; i < 23; i++) { v = &(tipVector[20 * i]); for(k = 0; k < 80; k++) { double *ll = &left[k * 20]; double *rr = &right[k * 20]; __m128d umpX1v = _mm_setzero_pd(); __m128d umpX2v = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) { __m128d vv = _mm_load_pd(&v[l]); umpX1v = _mm_add_pd(umpX1v, _mm_mul_pd(vv, _mm_load_pd(&ll[l]))); umpX2v = _mm_add_pd(umpX2v, _mm_mul_pd(vv, _mm_load_pd(&rr[l]))); } umpX1v = _mm_hadd_pd(umpX1v, umpX1v); umpX2v = _mm_hadd_pd(umpX2v, umpX2v); _mm_storel_pd(&umpX1[80 * i + k], umpX1v); _mm_storel_pd(&umpX2[80 * i + k], umpX2v); } } { uX1 = &umpX1[1760]; uX2 = &umpX2[1760]; for(j = 0; j < 4; j++) { v = &x3_gapColumn[j * 20]; __m128d zero = _mm_setzero_pd(); for(k = 0; k < 20; k+=2) _mm_store_pd(&v[k], zero); for(k = 0; k < 20; k++) { double *eev = &extEV[k * 20]; x1px2 = uX1[j * 20 + k] * uX2[j * 20 + k]; __m128d x1px2v = _mm_set1_pd(x1px2); for(l = 0; l < 20; l+=2) { __m128d vv = _mm_load_pd(&v[l]); __m128d ee = _mm_load_pd(&eev[l]); vv = _mm_add_pd(vv, _mm_mul_pd(x1px2v,ee)); _mm_store_pd(&v[l], vv); } } } } for(i = 0; i < n; i++) { if(!(x3_gap[i / 32] & mask32[i % 32])) { uX1 = &umpX1[80 * tipX1[i]]; uX2 = &umpX2[80 * tipX2[i]]; for(j = 0; j < 4; j++) { v = &x3_ptr[j * 20]; __m128d zero = _mm_setzero_pd(); for(k = 0; k < 20; k+=2) _mm_store_pd(&v[k], zero); for(k = 0; k < 20; k++) { double *eev = &extEV[k * 20]; x1px2 = uX1[j * 20 + k] * uX2[j * 20 + k]; __m128d x1px2v = _mm_set1_pd(x1px2); for(l = 0; l < 20; l+=2) { __m128d vv = _mm_load_pd(&v[l]); __m128d ee = _mm_load_pd(&eev[l]); vv = _mm_add_pd(vv, _mm_mul_pd(x1px2v,ee)); _mm_store_pd(&v[l], vv); } } } x3_ptr += 80; } } } break; case TIP_INNER: { double umpX1[1840], ump_x2[20]; for(i = 0; i < 23; i++) { v = &(tipVector[20 * i]); for(k = 0; k < 80; k++) { double *ll = &left[k * 20]; __m128d umpX1v = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) { __m128d vv = _mm_load_pd(&v[l]); umpX1v = _mm_add_pd(umpX1v, _mm_mul_pd(vv, _mm_load_pd(&ll[l]))); } umpX1v = _mm_hadd_pd(umpX1v, umpX1v); _mm_storel_pd(&umpX1[80 * i + k], umpX1v); } } { uX1 = &umpX1[1760]; for(k = 0; k < 4; k++) { v = &(x2_gapColumn[k * 20]); for(l = 0; l < 20; l++) { double *r = &right[k * 400 + l * 20]; __m128d ump_x2v = _mm_setzero_pd(); for(j = 0; j < 20; j+= 2) { __m128d vv = _mm_load_pd(&v[j]); __m128d rr = _mm_load_pd(&r[j]); ump_x2v = _mm_add_pd(ump_x2v, _mm_mul_pd(vv, rr)); } ump_x2v = _mm_hadd_pd(ump_x2v, ump_x2v); _mm_storel_pd(&ump_x2[l], ump_x2v); } v = &(x3_gapColumn[20 * k]); __m128d zero = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], zero); for(l = 0; l < 20; l++) { double *eev = &extEV[l * 20]; x1px2 = uX1[k * 20 + l] * ump_x2[l]; __m128d x1px2v = _mm_set1_pd(x1px2); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); __m128d ee = _mm_load_pd(&eev[j]); vv = _mm_add_pd(vv, _mm_mul_pd(x1px2v,ee)); _mm_store_pd(&v[j], vv); } } } { v = x3_gapColumn; __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 80); l += 2) { __m128d vv = _mm_load_pd(&v[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } } if (scale) { gapScaling = 1; __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 80; l+=2) { __m128d ex3v = _mm_load_pd(&v[l]); _mm_store_pd(&v[l], _mm_mul_pd(ex3v,twoto)); } } } for (i = 0; i < n; i++) { if((x3_gap[i / 32] & mask32[i % 32])) { if(gapScaling) { addScale += wgt[i]; } } else { uX1 = &umpX1[80 * tipX1[i]]; if(x2_gap[i / 32] & mask32[i % 32]) x2v = x2_gapColumn; else { x2v = x2_ptr; x2_ptr += 80; } for(k = 0; k < 4; k++) { v = &(x2v[k * 20]); for(l = 0; l < 20; l++) { double *r = &right[k * 400 + l * 20]; __m128d ump_x2v = _mm_setzero_pd(); for(j = 0; j < 20; j+= 2) { __m128d vv = _mm_load_pd(&v[j]); __m128d rr = _mm_load_pd(&r[j]); ump_x2v = _mm_add_pd(ump_x2v, _mm_mul_pd(vv, rr)); } ump_x2v = _mm_hadd_pd(ump_x2v, ump_x2v); _mm_storel_pd(&ump_x2[l], ump_x2v); } v = &x3_ptr[20 * k]; __m128d zero = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], zero); for(l = 0; l < 20; l++) { double *eev = &extEV[l * 20]; x1px2 = uX1[k * 20 + l] * ump_x2[l]; __m128d x1px2v = _mm_set1_pd(x1px2); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); __m128d ee = _mm_load_pd(&eev[j]); vv = _mm_add_pd(vv, _mm_mul_pd(x1px2v,ee)); _mm_store_pd(&v[j], vv); } } } { v = x3_ptr; __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 80); l += 2) { __m128d vv = _mm_load_pd(&v[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } } if (scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 80; l+=2) { __m128d ex3v = _mm_load_pd(&v[l]); _mm_store_pd(&v[l], _mm_mul_pd(ex3v,twoto)); } addScale += wgt[i]; } x3_ptr += 80; } } } break; case INNER_INNER: { for(k = 0; k < 4; k++) { vl = &(x1_gapColumn[20 * k]); vr = &(x2_gapColumn[20 * k]); v = &(x3_gapColumn[20 * k]); __m128d zero = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], zero); for(l = 0; l < 20; l++) { { __m128d al = _mm_setzero_pd(); __m128d ar = _mm_setzero_pd(); double *ll = &left[k * 400 + l * 20]; double *rr = &right[k * 400 + l * 20]; double *EVEV = &extEV[20 * l]; for(j = 0; j < 20; j+=2) { __m128d lv = _mm_load_pd(&ll[j]); __m128d rv = _mm_load_pd(&rr[j]); __m128d vll = _mm_load_pd(&vl[j]); __m128d vrr = _mm_load_pd(&vr[j]); al = _mm_add_pd(al, _mm_mul_pd(vll, lv)); ar = _mm_add_pd(ar, _mm_mul_pd(vrr, rv)); } al = _mm_hadd_pd(al, al); ar = _mm_hadd_pd(ar, ar); al = _mm_mul_pd(al, ar); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); __m128d EVV = _mm_load_pd(&EVEV[j]); vv = _mm_add_pd(vv, _mm_mul_pd(al, EVV)); _mm_store_pd(&v[j], vv); } } } } { v = x3_gapColumn; __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 80); l += 2) { __m128d vv = _mm_load_pd(&v[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } } if (scale) { gapScaling = 1; __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 80; l+=2) { __m128d ex3v = _mm_load_pd(&v[l]); _mm_store_pd(&v[l], _mm_mul_pd(ex3v,twoto)); } } } for (i = 0; i < n; i++) { if(x3_gap[i / 32] & mask32[i % 32]) { if(gapScaling) { addScale += wgt[i]; } } else { if(x1_gap[i / 32] & mask32[i % 32]) x1v = x1_gapColumn; else { x1v = x1_ptr; x1_ptr += 80; } if(x2_gap[i / 32] & mask32[i % 32]) x2v = x2_gapColumn; else { x2v = x2_ptr; x2_ptr += 80; } for(k = 0; k < 4; k++) { vl = &(x1v[20 * k]); vr = &(x2v[20 * k]); v = &x3_ptr[20 * k]; __m128d zero = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], zero); for(l = 0; l < 20; l++) { { __m128d al = _mm_setzero_pd(); __m128d ar = _mm_setzero_pd(); double *ll = &left[k * 400 + l * 20]; double *rr = &right[k * 400 + l * 20]; double *EVEV = &extEV[20 * l]; for(j = 0; j < 20; j+=2) { __m128d lv = _mm_load_pd(&ll[j]); __m128d rv = _mm_load_pd(&rr[j]); __m128d vll = _mm_load_pd(&vl[j]); __m128d vrr = _mm_load_pd(&vr[j]); al = _mm_add_pd(al, _mm_mul_pd(vll, lv)); ar = _mm_add_pd(ar, _mm_mul_pd(vrr, rv)); } al = _mm_hadd_pd(al, al); ar = _mm_hadd_pd(ar, ar); al = _mm_mul_pd(al, ar); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); __m128d EVV = _mm_load_pd(&EVEV[j]); vv = _mm_add_pd(vv, _mm_mul_pd(al, EVV)); _mm_store_pd(&v[j], vv); } } } } { v = x3_ptr; __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 80); l += 2) { __m128d vv = _mm_load_pd(&v[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } } if (scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 80; l+=2) { __m128d ex3v = _mm_load_pd(&v[l]); _mm_store_pd(&v[l], _mm_mul_pd(ex3v,twoto)); } addScale += wgt[i]; } x3_ptr += 80; } } break; default: assert(0); } *scalerIncrement = addScale; } static void newviewGTRGAMMAPROT(int tipCase, double *x1, double *x2, double *x3, double *extEV, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement) { double *uX1, *uX2, *v; double x1px2; int i, j, l, k, scale, addScale = 0; double *vl, *vr; switch(tipCase) { case TIP_TIP: { double umpX1[1840], umpX2[1840]; for(i = 0; i < 23; i++) { v = &(tipVector[20 * i]); for(k = 0; k < 80; k++) { double *ll = &left[k * 20]; double *rr = &right[k * 20]; __m128d umpX1v = _mm_setzero_pd(); __m128d umpX2v = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) { __m128d vv = _mm_load_pd(&v[l]); umpX1v = _mm_add_pd(umpX1v, _mm_mul_pd(vv, _mm_load_pd(&ll[l]))); umpX2v = _mm_add_pd(umpX2v, _mm_mul_pd(vv, _mm_load_pd(&rr[l]))); } umpX1v = _mm_hadd_pd(umpX1v, umpX1v); umpX2v = _mm_hadd_pd(umpX2v, umpX2v); _mm_storel_pd(&umpX1[80 * i + k], umpX1v); _mm_storel_pd(&umpX2[80 * i + k], umpX2v); } } for(i = 0; i < n; i++) { uX1 = &umpX1[80 * tipX1[i]]; uX2 = &umpX2[80 * tipX2[i]]; for(j = 0; j < 4; j++) { v = &x3[i * 80 + j * 20]; __m128d zero = _mm_setzero_pd(); for(k = 0; k < 20; k+=2) _mm_store_pd(&v[k], zero); for(k = 0; k < 20; k++) { double *eev = &extEV[k * 20]; x1px2 = uX1[j * 20 + k] * uX2[j * 20 + k]; __m128d x1px2v = _mm_set1_pd(x1px2); for(l = 0; l < 20; l+=2) { __m128d vv = _mm_load_pd(&v[l]); __m128d ee = _mm_load_pd(&eev[l]); vv = _mm_add_pd(vv, _mm_mul_pd(x1px2v,ee)); _mm_store_pd(&v[l], vv); } } } } } break; case TIP_INNER: { double umpX1[1840], ump_x2[20]; for(i = 0; i < 23; i++) { v = &(tipVector[20 * i]); for(k = 0; k < 80; k++) { double *ll = &left[k * 20]; __m128d umpX1v = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) { __m128d vv = _mm_load_pd(&v[l]); umpX1v = _mm_add_pd(umpX1v, _mm_mul_pd(vv, _mm_load_pd(&ll[l]))); } umpX1v = _mm_hadd_pd(umpX1v, umpX1v); _mm_storel_pd(&umpX1[80 * i + k], umpX1v); } } for (i = 0; i < n; i++) { uX1 = &umpX1[80 * tipX1[i]]; for(k = 0; k < 4; k++) { v = &(x2[80 * i + k * 20]); for(l = 0; l < 20; l++) { double *r = &right[k * 400 + l * 20]; __m128d ump_x2v = _mm_setzero_pd(); for(j = 0; j < 20; j+= 2) { __m128d vv = _mm_load_pd(&v[j]); __m128d rr = _mm_load_pd(&r[j]); ump_x2v = _mm_add_pd(ump_x2v, _mm_mul_pd(vv, rr)); } ump_x2v = _mm_hadd_pd(ump_x2v, ump_x2v); _mm_storel_pd(&ump_x2[l], ump_x2v); } v = &(x3[80 * i + 20 * k]); __m128d zero = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], zero); for(l = 0; l < 20; l++) { double *eev = &extEV[l * 20]; x1px2 = uX1[k * 20 + l] * ump_x2[l]; __m128d x1px2v = _mm_set1_pd(x1px2); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); __m128d ee = _mm_load_pd(&eev[j]); vv = _mm_add_pd(vv, _mm_mul_pd(x1px2v,ee)); _mm_store_pd(&v[j], vv); } } } { v = &(x3[80 * i]); __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 80); l += 2) { __m128d vv = _mm_load_pd(&v[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } } if (scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 80; l+=2) { __m128d ex3v = _mm_load_pd(&v[l]); _mm_store_pd(&v[l], _mm_mul_pd(ex3v,twoto)); } addScale += wgt[i]; } } } break; case INNER_INNER: for (i = 0; i < n; i++) { for(k = 0; k < 4; k++) { vl = &(x1[80 * i + 20 * k]); vr = &(x2[80 * i + 20 * k]); v = &(x3[80 * i + 20 * k]); __m128d zero = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], zero); for(l = 0; l < 20; l++) { { __m128d al = _mm_setzero_pd(); __m128d ar = _mm_setzero_pd(); double *ll = &left[k * 400 + l * 20]; double *rr = &right[k * 400 + l * 20]; double *EVEV = &extEV[20 * l]; for(j = 0; j < 20; j+=2) { __m128d lv = _mm_load_pd(&ll[j]); __m128d rv = _mm_load_pd(&rr[j]); __m128d vll = _mm_load_pd(&vl[j]); __m128d vrr = _mm_load_pd(&vr[j]); al = _mm_add_pd(al, _mm_mul_pd(vll, lv)); ar = _mm_add_pd(ar, _mm_mul_pd(vrr, rv)); } al = _mm_hadd_pd(al, al); ar = _mm_hadd_pd(ar, ar); al = _mm_mul_pd(al, ar); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); __m128d EVV = _mm_load_pd(&EVEV[j]); vv = _mm_add_pd(vv, _mm_mul_pd(al, EVV)); _mm_store_pd(&v[j], vv); } } } } { v = &(x3[80 * i]); __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 80); l += 2) { __m128d vv = _mm_load_pd(&v[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } } if (scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 80; l+=2) { __m128d ex3v = _mm_load_pd(&v[l]); _mm_store_pd(&v[l], _mm_mul_pd(ex3v,twoto)); } addScale += wgt[i]; } } break; default: assert(0); } *scalerIncrement = addScale; } static void newviewGTRCATPROT(int tipCase, double *extEV, int *cptr, double *x1, double *x2, double *x3, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement ) { double *le, *ri, *v, *vl, *vr; int i, l, j, scale, addScale = 0; switch(tipCase) { case TIP_TIP: { for (i = 0; i < n; i++) { le = &left[cptr[i] * 400]; ri = &right[cptr[i] * 400]; vl = &(tipVector[20 * tipX1[i]]); vr = &(tipVector[20 * tipX2[i]]); v = &x3[20 * i]; for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], _mm_setzero_pd()); for(l = 0; l < 20; l++) { __m128d x1v = _mm_setzero_pd(); __m128d x2v = _mm_setzero_pd(); double *ev = &extEV[l * 20], *lv = &le[l * 20], *rv = &ri[l * 20]; for(j = 0; j < 20; j+=2) { x1v = _mm_add_pd(x1v, _mm_mul_pd(_mm_load_pd(&vl[j]), _mm_load_pd(&lv[j]))); x2v = _mm_add_pd(x2v, _mm_mul_pd(_mm_load_pd(&vr[j]), _mm_load_pd(&rv[j]))); } x1v = _mm_hadd_pd(x1v, x1v); x2v = _mm_hadd_pd(x2v, x2v); x1v = _mm_mul_pd(x1v, x2v); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); vv = _mm_add_pd(vv, _mm_mul_pd(x1v, _mm_load_pd(&ev[j]))); _mm_store_pd(&v[j], vv); } } } } break; case TIP_INNER: { for (i = 0; i < n; i++) { le = &left[cptr[i] * 400]; ri = &right[cptr[i] * 400]; vl = &(tipVector[20 * tipX1[i]]); vr = &x2[20 * i]; v = &x3[20 * i]; for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], _mm_setzero_pd()); for(l = 0; l < 20; l++) { __m128d x1v = _mm_setzero_pd(); __m128d x2v = _mm_setzero_pd(); double *ev = &extEV[l * 20], *lv = &le[l * 20], *rv = &ri[l * 20]; for(j = 0; j < 20; j+=2) { x1v = _mm_add_pd(x1v, _mm_mul_pd(_mm_load_pd(&vl[j]), _mm_load_pd(&lv[j]))); x2v = _mm_add_pd(x2v, _mm_mul_pd(_mm_load_pd(&vr[j]), _mm_load_pd(&rv[j]))); } x1v = _mm_hadd_pd(x1v, x1v); x2v = _mm_hadd_pd(x2v, x2v); x1v = _mm_mul_pd(x1v, x2v); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); vv = _mm_add_pd(vv, _mm_mul_pd(x1v, _mm_load_pd(&ev[j]))); _mm_store_pd(&v[j], vv); } } { __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 20); l += 2) { __m128d vv = _mm_load_pd(&v[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } } if(scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 20; l+=2) { __m128d ex3v = _mm_load_pd(&v[l]); _mm_store_pd(&v[l], _mm_mul_pd(ex3v,twoto)); } addScale += wgt[i]; } } } break; case INNER_INNER: for(i = 0; i < n; i++) { le = &left[cptr[i] * 400]; ri = &right[cptr[i] * 400]; vl = &x1[20 * i]; vr = &x2[20 * i]; v = &x3[20 * i]; for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], _mm_setzero_pd()); for(l = 0; l < 20; l++) { __m128d x1v = _mm_setzero_pd(); __m128d x2v = _mm_setzero_pd(); double *ev = &extEV[l * 20], *lv = &le[l * 20], *rv = &ri[l * 20]; for(j = 0; j < 20; j+=2) { x1v = _mm_add_pd(x1v, _mm_mul_pd(_mm_load_pd(&vl[j]), _mm_load_pd(&lv[j]))); x2v = _mm_add_pd(x2v, _mm_mul_pd(_mm_load_pd(&vr[j]), _mm_load_pd(&rv[j]))); } x1v = _mm_hadd_pd(x1v, x1v); x2v = _mm_hadd_pd(x2v, x2v); x1v = _mm_mul_pd(x1v, x2v); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); vv = _mm_add_pd(vv, _mm_mul_pd(x1v, _mm_load_pd(&ev[j]))); _mm_store_pd(&v[j], vv); } } { __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 20); l += 2) { __m128d vv = _mm_load_pd(&v[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } } if(scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 20; l+=2) { __m128d ex3v = _mm_load_pd(&v[l]); _mm_store_pd(&v[l], _mm_mul_pd(ex3v,twoto)); } addScale += wgt[i]; } } break; default: assert(0); } *scalerIncrement = addScale; } static void newviewGTRCATPROT_SAVE(int tipCase, double *extEV, int *cptr, double *x1, double *x2, double *x3, double *tipVector, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, unsigned int *x1_gap, unsigned int *x2_gap, unsigned int *x3_gap, double *x1_gapColumn, double *x2_gapColumn, double *x3_gapColumn, const int maxCats) { double *le, *ri, *v, *vl, *vr, *x1_ptr = x1, *x2_ptr = x2, *x3_ptr = x3; int i, l, j, scale, scaleGap = 0, addScale = 0; { vl = x1_gapColumn; vr = x2_gapColumn; v = x3_gapColumn; le = &left[maxCats * 400]; ri = &right[maxCats * 400]; for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], _mm_setzero_pd()); for(l = 0; l < 20; l++) { __m128d x1v = _mm_setzero_pd(); __m128d x2v = _mm_setzero_pd(); double *ev = &extEV[l * 20], *lv = &le[l * 20], *rv = &ri[l * 20]; for(j = 0; j < 20; j+=2) { x1v = _mm_add_pd(x1v, _mm_mul_pd(_mm_load_pd(&vl[j]), _mm_load_pd(&lv[j]))); x2v = _mm_add_pd(x2v, _mm_mul_pd(_mm_load_pd(&vr[j]), _mm_load_pd(&rv[j]))); } x1v = _mm_hadd_pd(x1v, x1v); x2v = _mm_hadd_pd(x2v, x2v); x1v = _mm_mul_pd(x1v, x2v); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); vv = _mm_add_pd(vv, _mm_mul_pd(x1v, _mm_load_pd(&ev[j]))); _mm_store_pd(&v[j], vv); } } if(tipCase != TIP_TIP) { __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 20); l += 2) { __m128d vv = _mm_load_pd(&v[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } if(scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 20; l+=2) { __m128d ex3v = _mm_load_pd(&v[l]); _mm_store_pd(&v[l], _mm_mul_pd(ex3v,twoto)); } scaleGap = TRUE; } } } switch(tipCase) { case TIP_TIP: { for (i = 0; i < n; i++) { if(noGap(x3_gap, i)) { vl = &(tipVector[20 * tipX1[i]]); vr = &(tipVector[20 * tipX2[i]]); v = x3_ptr; if(isGap(x1_gap, i)) le = &left[maxCats * 400]; else le = &left[cptr[i] * 400]; if(isGap(x2_gap, i)) ri = &right[maxCats * 400]; else ri = &right[cptr[i] * 400]; for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], _mm_setzero_pd()); for(l = 0; l < 20; l++) { __m128d x1v = _mm_setzero_pd(); __m128d x2v = _mm_setzero_pd(); double *ev = &extEV[l * 20], *lv = &le[l * 20], *rv = &ri[l * 20]; for(j = 0; j < 20; j+=2) { x1v = _mm_add_pd(x1v, _mm_mul_pd(_mm_load_pd(&vl[j]), _mm_load_pd(&lv[j]))); x2v = _mm_add_pd(x2v, _mm_mul_pd(_mm_load_pd(&vr[j]), _mm_load_pd(&rv[j]))); } x1v = _mm_hadd_pd(x1v, x1v); x2v = _mm_hadd_pd(x2v, x2v); x1v = _mm_mul_pd(x1v, x2v); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); vv = _mm_add_pd(vv, _mm_mul_pd(x1v, _mm_load_pd(&ev[j]))); _mm_store_pd(&v[j], vv); } } x3_ptr += 20; } } } break; case TIP_INNER: { for (i = 0; i < n; i++) { if(isGap(x3_gap, i)) { if(scaleGap) addScale += wgt[i]; } else { vl = &(tipVector[20 * tipX1[i]]); vr = x2_ptr; v = x3_ptr; if(isGap(x1_gap, i)) le = &left[maxCats * 400]; else le = &left[cptr[i] * 400]; if(isGap(x2_gap, i)) { ri = &right[maxCats * 400]; vr = x2_gapColumn; } else { ri = &right[cptr[i] * 400]; vr = x2_ptr; x2_ptr += 20; } for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], _mm_setzero_pd()); for(l = 0; l < 20; l++) { __m128d x1v = _mm_setzero_pd(); __m128d x2v = _mm_setzero_pd(); double *ev = &extEV[l * 20], *lv = &le[l * 20], *rv = &ri[l * 20]; for(j = 0; j < 20; j+=2) { x1v = _mm_add_pd(x1v, _mm_mul_pd(_mm_load_pd(&vl[j]), _mm_load_pd(&lv[j]))); x2v = _mm_add_pd(x2v, _mm_mul_pd(_mm_load_pd(&vr[j]), _mm_load_pd(&rv[j]))); } x1v = _mm_hadd_pd(x1v, x1v); x2v = _mm_hadd_pd(x2v, x2v); x1v = _mm_mul_pd(x1v, x2v); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); vv = _mm_add_pd(vv, _mm_mul_pd(x1v, _mm_load_pd(&ev[j]))); _mm_store_pd(&v[j], vv); } } { __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 20); l += 2) { __m128d vv = _mm_load_pd(&v[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } } if(scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 20; l+=2) { __m128d ex3v = _mm_load_pd(&v[l]); _mm_store_pd(&v[l], _mm_mul_pd(ex3v,twoto)); } addScale += wgt[i]; } x3_ptr += 20; } } } break; case INNER_INNER: for(i = 0; i < n; i++) { if(isGap(x3_gap, i)) { if(scaleGap) addScale += wgt[i]; } else { v = x3_ptr; if(isGap(x1_gap, i)) { vl = x1_gapColumn; le = &left[maxCats * 400]; } else { le = &left[cptr[i] * 400]; vl = x1_ptr; x1_ptr += 20; } if(isGap(x2_gap, i)) { vr = x2_gapColumn; ri = &right[maxCats * 400]; } else { ri = &right[cptr[i] * 400]; vr = x2_ptr; x2_ptr += 20; } for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], _mm_setzero_pd()); for(l = 0; l < 20; l++) { __m128d x1v = _mm_setzero_pd(); __m128d x2v = _mm_setzero_pd(); double *ev = &extEV[l * 20], *lv = &le[l * 20], *rv = &ri[l * 20]; for(j = 0; j < 20; j+=2) { x1v = _mm_add_pd(x1v, _mm_mul_pd(_mm_load_pd(&vl[j]), _mm_load_pd(&lv[j]))); x2v = _mm_add_pd(x2v, _mm_mul_pd(_mm_load_pd(&vr[j]), _mm_load_pd(&rv[j]))); } x1v = _mm_hadd_pd(x1v, x1v); x2v = _mm_hadd_pd(x2v, x2v); x1v = _mm_mul_pd(x1v, x2v); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); vv = _mm_add_pd(vv, _mm_mul_pd(x1v, _mm_load_pd(&ev[j]))); _mm_store_pd(&v[j], vv); } } { __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 20); l += 2) { __m128d vv = _mm_load_pd(&v[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } } if(scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 20; l+=2) { __m128d ex3v = _mm_load_pd(&v[l]); _mm_store_pd(&v[l], _mm_mul_pd(ex3v,twoto)); } addScale += wgt[i]; } x3_ptr += 20; } } break; default: assert(0); } *scalerIncrement = addScale; } static void newviewGTRGAMMAPROT_LG4(int tipCase, double *x1, double *x2, double *x3, double *extEV[4], double *tipVector[4], int *ex3, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling) { double *uX1, *uX2, *v; double x1px2; int i, j, l, k, scale, addScale = 0; double *vl, *vr; #ifndef __SIM_SSE3 double al, ar; #endif switch(tipCase) { case TIP_TIP: { double umpX1[1840], umpX2[1840]; for(i = 0; i < 23; i++) { for(k = 0; k < 80; k++) { v = &(tipVector[k / 20][20 * i]); #ifdef __SIM_SSE3 double *ll = &left[k * 20]; double *rr = &right[k * 20]; __m128d umpX1v = _mm_setzero_pd(); __m128d umpX2v = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) { __m128d vv = _mm_load_pd(&v[l]); umpX1v = _mm_add_pd(umpX1v, _mm_mul_pd(vv, _mm_load_pd(&ll[l]))); umpX2v = _mm_add_pd(umpX2v, _mm_mul_pd(vv, _mm_load_pd(&rr[l]))); } umpX1v = _mm_hadd_pd(umpX1v, umpX1v); umpX2v = _mm_hadd_pd(umpX2v, umpX2v); _mm_storel_pd(&umpX1[80 * i + k], umpX1v); _mm_storel_pd(&umpX2[80 * i + k], umpX2v); #else umpX1[80 * i + k] = 0.0; umpX2[80 * i + k] = 0.0; for(l = 0; l < 20; l++) { umpX1[80 * i + k] += v[l] * left[k * 20 + l]; umpX2[80 * i + k] += v[l] * right[k * 20 + l]; } #endif } } for(i = 0; i < n; i++) { uX1 = &umpX1[80 * tipX1[i]]; uX2 = &umpX2[80 * tipX2[i]]; for(j = 0; j < 4; j++) { v = &x3[i * 80 + j * 20]; #ifdef __SIM_SSE3 __m128d zero = _mm_setzero_pd(); for(k = 0; k < 20; k+=2) _mm_store_pd(&v[k], zero); for(k = 0; k < 20; k++) { double *eev = &extEV[j][k * 20]; x1px2 = uX1[j * 20 + k] * uX2[j * 20 + k]; __m128d x1px2v = _mm_set1_pd(x1px2); for(l = 0; l < 20; l+=2) { __m128d vv = _mm_load_pd(&v[l]); __m128d ee = _mm_load_pd(&eev[l]); vv = _mm_add_pd(vv, _mm_mul_pd(x1px2v,ee)); _mm_store_pd(&v[l], vv); } } #else for(k = 0; k < 20; k++) v[k] = 0.0; for(k = 0; k < 20; k++) { x1px2 = uX1[j * 20 + k] * uX2[j * 20 + k]; for(l = 0; l < 20; l++) v[l] += x1px2 * extEV[j][20 * k + l]; } #endif } } } break; case TIP_INNER: { double umpX1[1840], ump_x2[20]; for(i = 0; i < 23; i++) { for(k = 0; k < 80; k++) { v = &(tipVector[k / 20][20 * i]); #ifdef __SIM_SSE3 double *ll = &left[k * 20]; __m128d umpX1v = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) { __m128d vv = _mm_load_pd(&v[l]); umpX1v = _mm_add_pd(umpX1v, _mm_mul_pd(vv, _mm_load_pd(&ll[l]))); } umpX1v = _mm_hadd_pd(umpX1v, umpX1v); _mm_storel_pd(&umpX1[80 * i + k], umpX1v); #else umpX1[80 * i + k] = 0.0; for(l = 0; l < 20; l++) umpX1[80 * i + k] += v[l] * left[k * 20 + l]; #endif } } for (i = 0; i < n; i++) { uX1 = &umpX1[80 * tipX1[i]]; for(k = 0; k < 4; k++) { v = &(x2[80 * i + k * 20]); #ifdef __SIM_SSE3 for(l = 0; l < 20; l++) { double *r = &right[k * 400 + l * 20]; __m128d ump_x2v = _mm_setzero_pd(); for(j = 0; j < 20; j+= 2) { __m128d vv = _mm_load_pd(&v[j]); __m128d rr = _mm_load_pd(&r[j]); ump_x2v = _mm_add_pd(ump_x2v, _mm_mul_pd(vv, rr)); } ump_x2v = _mm_hadd_pd(ump_x2v, ump_x2v); _mm_storel_pd(&ump_x2[l], ump_x2v); } v = &(x3[80 * i + 20 * k]); __m128d zero = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], zero); for(l = 0; l < 20; l++) { double *eev = &extEV[k][l * 20]; x1px2 = uX1[k * 20 + l] * ump_x2[l]; __m128d x1px2v = _mm_set1_pd(x1px2); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); __m128d ee = _mm_load_pd(&eev[j]); vv = _mm_add_pd(vv, _mm_mul_pd(x1px2v,ee)); _mm_store_pd(&v[j], vv); } } #else for(l = 0; l < 20; l++) { ump_x2[l] = 0.0; for(j = 0; j < 20; j++) ump_x2[l] += v[j] * right[k * 400 + l * 20 + j]; } v = &(x3[80 * i + 20 * k]); for(l = 0; l < 20; l++) v[l] = 0; for(l = 0; l < 20; l++) { x1px2 = uX1[k * 20 + l] * ump_x2[l]; for(j = 0; j < 20; j++) v[j] += x1px2 * extEV[k][l * 20 + j]; } #endif } #ifdef __SIM_SSE3 { v = &(x3[80 * i]); __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 80); l += 2) { __m128d vv = _mm_load_pd(&v[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } } #else v = &x3[80 * i]; scale = 1; for(l = 0; scale && (l < 80); l++) scale = (ABS(v[l]) < minlikelihood); #endif if (scale) { #ifdef __SIM_SSE3 __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 80; l+=2) { __m128d ex3v = _mm_load_pd(&v[l]); _mm_store_pd(&v[l], _mm_mul_pd(ex3v,twoto)); } #else for(l = 0; l < 80; l++) v[l] *= twotothe256; #endif if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } } break; case INNER_INNER: for (i = 0; i < n; i++) { for(k = 0; k < 4; k++) { vl = &(x1[80 * i + 20 * k]); vr = &(x2[80 * i + 20 * k]); v = &(x3[80 * i + 20 * k]); #ifdef __SIM_SSE3 __m128d zero = _mm_setzero_pd(); for(l = 0; l < 20; l+=2) _mm_store_pd(&v[l], zero); #else for(l = 0; l < 20; l++) v[l] = 0; #endif for(l = 0; l < 20; l++) { #ifdef __SIM_SSE3 { __m128d al = _mm_setzero_pd(); __m128d ar = _mm_setzero_pd(); double *ll = &left[k * 400 + l * 20]; double *rr = &right[k * 400 + l * 20]; double *EVEV = &extEV[k][20 * l]; for(j = 0; j < 20; j+=2) { __m128d lv = _mm_load_pd(&ll[j]); __m128d rv = _mm_load_pd(&rr[j]); __m128d vll = _mm_load_pd(&vl[j]); __m128d vrr = _mm_load_pd(&vr[j]); al = _mm_add_pd(al, _mm_mul_pd(vll, lv)); ar = _mm_add_pd(ar, _mm_mul_pd(vrr, rv)); } al = _mm_hadd_pd(al, al); ar = _mm_hadd_pd(ar, ar); al = _mm_mul_pd(al, ar); for(j = 0; j < 20; j+=2) { __m128d vv = _mm_load_pd(&v[j]); __m128d EVV = _mm_load_pd(&EVEV[j]); vv = _mm_add_pd(vv, _mm_mul_pd(al, EVV)); _mm_store_pd(&v[j], vv); } } #else al = 0.0; ar = 0.0; for(j = 0; j < 20; j++) { al += vl[j] * left[k * 400 + l * 20 + j]; ar += vr[j] * right[k * 400 + l * 20 + j]; } x1px2 = al * ar; for(j = 0; j < 20; j++) v[j] += x1px2 * extEV[k][20 * l + j]; #endif } } #ifdef __SIM_SSE3 { v = &(x3[80 * i]); __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 80); l += 2) { __m128d vv = _mm_load_pd(&v[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } } #else v = &(x3[80 * i]); scale = 1; for(l = 0; scale && (l < 80); l++) scale = ((ABS(v[l]) < minlikelihood)); #endif if (scale) { #ifdef __SIM_SSE3 __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 80; l+=2) { __m128d ex3v = _mm_load_pd(&v[l]); _mm_store_pd(&v[l], _mm_mul_pd(ex3v,twoto)); } #else for(l = 0; l < 80; l++) v[l] *= twotothe256; #endif if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } break; default: assert(0); } if(useFastScaling) *scalerIncrement = addScale; } #endif #ifdef _OPTIMIZED_FUNCTIONS /*** BINARY DATA functions *****/ static void newviewGTRCAT_BINARY( int tipCase, double *EV, int *cptr, double *x1_start, double *x2_start, double *x3_start, double *tipVector, int *ex3, unsigned char *tipX1, unsigned char *tipX2, int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling) { double *le, *ri, *x1, *x2, *x3; int i, l, scale, addScale = 0; switch(tipCase) { case TIP_TIP: { for(i = 0; i < n; i++) { x1 = &(tipVector[2 * tipX1[i]]); x2 = &(tipVector[2 * tipX2[i]]); x3 = &x3_start[2 * i]; le = &left[cptr[i] * 4]; ri = &right[cptr[i] * 4]; _mm_store_pd(x3, _mm_setzero_pd()); for(l = 0; l < 2; l++) { __m128d al = _mm_mul_pd(_mm_load_pd(x1), _mm_load_pd(&le[l * 2])); __m128d ar = _mm_mul_pd(_mm_load_pd(x2), _mm_load_pd(&ri[l * 2])); al = _mm_hadd_pd(al, al); ar = _mm_hadd_pd(ar, ar); al = _mm_mul_pd(al, ar); __m128d vv = _mm_load_pd(x3); __m128d EVV = _mm_load_pd(&EV[2 * l]); vv = _mm_add_pd(vv, _mm_mul_pd(al, EVV)); _mm_store_pd(x3, vv); } } } break; case TIP_INNER: { for (i = 0; i < n; i++) { x1 = &(tipVector[2 * tipX1[i]]); x2 = &x2_start[2 * i]; x3 = &x3_start[2 * i]; le = &left[cptr[i] * 4]; ri = &right[cptr[i] * 4]; _mm_store_pd(x3, _mm_setzero_pd()); for(l = 0; l < 2; l++) { __m128d al = _mm_mul_pd(_mm_load_pd(x1), _mm_load_pd(&le[l * 2])); __m128d ar = _mm_mul_pd(_mm_load_pd(x2), _mm_load_pd(&ri[l * 2])); al = _mm_hadd_pd(al, al); ar = _mm_hadd_pd(ar, ar); al = _mm_mul_pd(al, ar); __m128d vv = _mm_load_pd(x3); __m128d EVV = _mm_load_pd(&EV[2 * l]); vv = _mm_add_pd(vv, _mm_mul_pd(al, EVV)); _mm_store_pd(x3, vv); } __m128d minlikelihood_sse = _mm_set1_pd(minlikelihood); scale = 1; __m128d v1 = _mm_and_pd(_mm_load_pd(x3), absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; if(scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); __m128d ex3v = _mm_load_pd(x3); _mm_store_pd(x3, _mm_mul_pd(ex3v,twoto)); if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } } break; case INNER_INNER: for (i = 0; i < n; i++) { x1 = &x1_start[2 * i]; x2 = &x2_start[2 * i]; x3 = &x3_start[2 * i]; le = &left[cptr[i] * 4]; ri = &right[cptr[i] * 4]; _mm_store_pd(x3, _mm_setzero_pd()); for(l = 0; l < 2; l++) { __m128d al = _mm_mul_pd(_mm_load_pd(x1), _mm_load_pd(&le[l * 2])); __m128d ar = _mm_mul_pd(_mm_load_pd(x2), _mm_load_pd(&ri[l * 2])); al = _mm_hadd_pd(al, al); ar = _mm_hadd_pd(ar, ar); al = _mm_mul_pd(al, ar); __m128d vv = _mm_load_pd(x3); __m128d EVV = _mm_load_pd(&EV[2 * l]); vv = _mm_add_pd(vv, _mm_mul_pd(al, EVV)); _mm_store_pd(x3, vv); } __m128d minlikelihood_sse = _mm_set1_pd(minlikelihood); scale = 1; __m128d v1 = _mm_and_pd(_mm_load_pd(x3), absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; if(scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); __m128d ex3v = _mm_load_pd(x3); _mm_store_pd(x3, _mm_mul_pd(ex3v,twoto)); if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } break; default: assert(0); } if(useFastScaling) *scalerIncrement = addScale; } static void newviewGTRGAMMA_BINARY(int tipCase, double *x1_start, double *x2_start, double *x3_start, double *EV, double *tipVector, int *ex3, unsigned char *tipX1, unsigned char *tipX2, const int n, double *left, double *right, int *wgt, int *scalerIncrement, const boolean useFastScaling ) { double *x1, *x2, *x3; int i, k, l, scale, addScale = 0; switch(tipCase) { case TIP_TIP: for (i = 0; i < n; i++) { x1 = &(tipVector[2 * tipX1[i]]); x2 = &(tipVector[2 * tipX2[i]]); for(k = 0; k < 4; k++) { x3 = &(x3_start[8 * i + 2 * k]); _mm_store_pd(x3, _mm_setzero_pd()); for(l = 0; l < 2; l++) { __m128d al = _mm_mul_pd(_mm_load_pd(x1), _mm_load_pd(&left[k * 4 + l * 2])); __m128d ar = _mm_mul_pd(_mm_load_pd(x2), _mm_load_pd(&right[k * 4 + l * 2])); al = _mm_hadd_pd(al, al); ar = _mm_hadd_pd(ar, ar); al = _mm_mul_pd(al, ar); __m128d vv = _mm_load_pd(x3); __m128d EVV = _mm_load_pd(&EV[2 * l]); vv = _mm_add_pd(vv, _mm_mul_pd(al, EVV)); _mm_store_pd(x3, vv); } } } break; case TIP_INNER: for (i = 0; i < n; i++) { x1 = &(tipVector[2 * tipX1[i]]); for(k = 0; k < 4; k++) { x2 = &(x2_start[8 * i + 2 * k]); x3 = &(x3_start[8 * i + 2 * k]); _mm_store_pd(x3, _mm_setzero_pd()); for(l = 0; l < 2; l++) { __m128d al = _mm_mul_pd(_mm_load_pd(x1), _mm_load_pd(&left[k * 4 + l * 2])); __m128d ar = _mm_mul_pd(_mm_load_pd(x2), _mm_load_pd(&right[k * 4 + l * 2])); al = _mm_hadd_pd(al, al); ar = _mm_hadd_pd(ar, ar); al = _mm_mul_pd(al, ar); __m128d vv = _mm_load_pd(x3); __m128d EVV = _mm_load_pd(&EV[2 * l]); vv = _mm_add_pd(vv, _mm_mul_pd(al, EVV)); _mm_store_pd(x3, vv); } } x3 = &(x3_start[8 * i]); __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 8); l += 2) { __m128d vv = _mm_load_pd(&x3[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } if(scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 8; l+=2) { __m128d ex3v = _mm_load_pd(&x3[l]); _mm_store_pd(&x3[l], _mm_mul_pd(ex3v,twoto)); } if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } break; case INNER_INNER: for (i = 0; i < n; i++) { for(k = 0; k < 4; k++) { x1 = &(x1_start[8 * i + 2 * k]); x2 = &(x2_start[8 * i + 2 * k]); x3 = &(x3_start[8 * i + 2 * k]); _mm_store_pd(x3, _mm_setzero_pd()); for(l = 0; l < 2; l++) { __m128d al = _mm_mul_pd(_mm_load_pd(x1), _mm_load_pd(&left[k * 4 + l * 2])); __m128d ar = _mm_mul_pd(_mm_load_pd(x2), _mm_load_pd(&right[k * 4 + l * 2])); al = _mm_hadd_pd(al, al); ar = _mm_hadd_pd(ar, ar); al = _mm_mul_pd(al, ar); __m128d vv = _mm_load_pd(x3); __m128d EVV = _mm_load_pd(&EV[2 * l]); vv = _mm_add_pd(vv, _mm_mul_pd(al, EVV)); _mm_store_pd(x3, vv); } } x3 = &(x3_start[8 * i]); __m128d minlikelihood_sse = _mm_set1_pd( minlikelihood ); scale = 1; for(l = 0; scale && (l < 8); l += 2) { __m128d vv = _mm_load_pd(&x3[l]); __m128d v1 = _mm_and_pd(vv, absMask.m); v1 = _mm_cmplt_pd(v1, minlikelihood_sse); if(_mm_movemask_pd( v1 ) != 3) scale = 0; } if(scale) { __m128d twoto = _mm_set_pd(twotothe256, twotothe256); for(l = 0; l < 8; l+=2) { __m128d ex3v = _mm_load_pd(&x3[l]); _mm_store_pd(&x3[l], _mm_mul_pd(ex3v,twoto)); } if(useFastScaling) addScale += wgt[i]; else ex3[i] += 1; } } break; default: assert(0); } if(useFastScaling) *scalerIncrement = addScale; } /**** BINARY DATA functions end ****/ #endif ExaML-3.0.21/examl/optimizeModel.c000066400000000000000000002257411330315463200166510ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands * of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifndef WIN32 #include #endif #include #include #include #include #include #include #include "axml.h" static const double MNBRAK_GOLD = 1.618034; static const double MNBRAK_TINY = 1.e-20; static const double MNBRAK_GLIMIT = 100.0; static const double BRENT_ZEPS = 1.e-5; static const double BRENT_CGOLD = 0.3819660; extern int optimizeRatesInvocations; extern int optimizeRateCategoryInvocations; extern int optimizeAlphaInvocations; extern int optimizeInvarInvocations; extern double masterTime; extern char ratesFileName[1024]; extern char workdir[1024]; extern char run_id[128]; extern char lengthFileName[1024]; extern char lengthFileNameModel[1024]; extern char *protModels[NUM_PROT_MODELS]; extern checkPointState ckp; extern int processes; extern int processID; static void optParamGeneric(tree *tr, double modelEpsilon, linkageList *ll, int numberOfModels, int rateNumber, double lim_inf, double lim_sup, int whichParameterType); // FLAG for easier debugging of model parameter optimization routines //#define _DEBUG_MOD_OPT /*********************FUNCTIONS FOOR EXACT MODEL OPTIMIZATION UNDER GTRGAMMA ***************************************/ static void setRateModel(tree *tr, int model, double rate, int position) { int states = tr->partitionData[model].states, numRates = (states * states - states) / 2; if(tr->partitionData[model].dataType == DNA_DATA) assert(position >= 0 && position < (numRates - 1)); else assert(position >= 0 && position < numRates); assert(tr->partitionData[model].dataType != BINARY_DATA); assert(rate >= RATE_MIN && rate <= RATE_MAX); if(tr->partitionData[model].nonGTR) { int i, index = tr->partitionData[model].symmetryVector[position], lastRate = tr->partitionData[model].symmetryVector[numRates - 1]; for(i = 0; i < numRates; i++) { if(tr->partitionData[model].symmetryVector[i] == index) { if(index == lastRate) tr->partitionData[model].substRates[i] = 1.0; else tr->partitionData[model].substRates[i] = rate; } //printf("%f ", tr->partitionData[model].substRates[i]); } //printf("\n"); } else tr->partitionData[model].substRates[position] = rate; } //LIBRARY: the only thing that we will need to do here is to //replace linkList by a string and also add some error correction //code static linkageList* initLinkageList(int *linkList, tree *tr) { int k, partitions, numberOfModels = 0, i, pos; linkageList *ll = (linkageList*)malloc(sizeof(linkageList)); for(i = 0; i < tr->NumberOfModels; i++) { assert(linkList[i] >= 0 && linkList[i] < tr->NumberOfModels); if(linkList[i] > numberOfModels) numberOfModels = linkList[i]; } numberOfModels++; ll->entries = numberOfModels; ll->ld = (linkageData*)malloc(sizeof(linkageData) * numberOfModels); for(i = 0; i < numberOfModels; i++) { ll->ld[i].valid = TRUE; partitions = 0; for(k = 0; k < tr->NumberOfModels; k++) if(linkList[k] == i) partitions++; ll->ld[i].partitions = partitions; ll->ld[i].partitionList = (int*)malloc(sizeof(int) * partitions); for(k = 0, pos = 0; k < tr->NumberOfModels; k++) if(linkList[k] == i) ll->ld[i].partitionList[pos++] = k; } return ll; } static linkageList* initLinkageListString(char *linkageString, tree *tr) { int *list = (int*)malloc(sizeof(int) * tr->NumberOfModels), j; linkageList *l; char *str1, *saveptr, *ch = (char *)calloc(strlen(linkageString), sizeof(char)), *token; strncpy(ch, linkageString, strlen(linkageString)); for(j = 0, str1 = ch; ;j++, str1 = (char *)NULL) { token = strtok_r(str1, ",", &saveptr); if(token == (char *)NULL) break; assert(j < tr->NumberOfModels); list[j] = atoi(token); //printf("%d: %s\n", j, token); } free(ch); l = initLinkageList(list, tr); free(list); return l; } static void init_Q_MatrixSymmetries(char *linkageString, tree *tr, int model) { int states = tr->partitionData[model].states, numberOfRates = ((states * states - states) / 2), *list = (int *)malloc(sizeof(int) * numberOfRates), j, max = -1; char *str1, *saveptr, *ch = (char*)calloc(strlen(linkageString), sizeof(char)), *token; strncpy(ch, linkageString, strlen(linkageString)); for(j = 0, str1 = ch; ;j++, str1 = (char *)NULL) { token = strtok_r(str1, ",", &saveptr); if(token == (char *)NULL) break; assert(j < numberOfRates); list[j] = atoi(token); } free(ch); for(j = 0; j < numberOfRates; j++) { assert(list[j] <= j); assert(list[j] <= max + 1); if(list[j] > max) max = list[j]; } assert(numberOfRates == 6); for(j = 0; j < numberOfRates; j++) tr->partitionData[model].symmetryVector[j] = list[j]; //less than the maximum possible number of rate parameters if(max < numberOfRates - 1) tr->partitionData[model].nonGTR = TRUE; free(list); } static linkageList* initLinkageListGTR(tree *tr) { int i, *links = (int*)malloc(sizeof(int) * tr->NumberOfModels), firstAA = tr->NumberOfModels + 2, countGTR = 0, countOtherModel = 0; linkageList* ll; for(i = 0; i < tr->NumberOfModels; i++) { if(tr->partitionData[i].dataType == AA_DATA) { if(tr->partitionData[i].protModels == GTR) { if(i < firstAA) firstAA = i; countGTR++; } else countOtherModel++; } } assert((countGTR > 0 && countOtherModel == 0) || (countGTR == 0 && countOtherModel > 0) || (countGTR == 0 && countOtherModel == 0)); if(countGTR == 0) { for(i = 0; i < tr->NumberOfModels; i++) links[i] = i; } else { for(i = 0; i < tr->NumberOfModels; i++) { switch(tr->partitionData[i].dataType) { case DNA_DATA: case BINARY_DATA: case GENERIC_32: case GENERIC_64: case SECONDARY_DATA: case SECONDARY_DATA_6: case SECONDARY_DATA_7: links[i] = i; break; case AA_DATA: links[i] = firstAA; break; default: assert(0); } } } ll = initLinkageList(links, tr); free(links); return ll; } static void freeLinkageList( linkageList* ll) { int i; for(i = 0; i < ll->entries; i++) free(ll->ld[i].partitionList); free(ll->ld); free(ll); } #define ALPHA_F 0 #define RATE_F 1 #define FREQ_F 2 #define LXRATE_F 3 #define LXWEIGHT_F 4 void scaleLG4X_EIGN(tree *tr, int model) { double acc = 0.0; int i, l; for(i = 0; i < 4; i++) acc += tr->partitionData[model].weights[i] * tr->partitionData[model].gammaRates[i]; acc = 1.0 / acc; /* printf("update %f %f %f %f %f\n", acc, tr->partitionData[model].gammaRates[0], tr->partitionData[model].gammaRates[1], tr->partitionData[model].gammaRates[2], tr->partitionData[model].gammaRates[3]); printf("weigths: %f %f %f %f\n", tr->partitionData[model].weights[0], tr->partitionData[model].weights[1], tr->partitionData[model].weights[2], tr->partitionData[model].weights[3]); */ for(i = 0; i < 4; i++) for(l = 0; l < 20; l++) tr->partitionData[model].EIGN_LG4[i][l] = tr->partitionData[model].rawEIGN_LG4[i][l] * acc; } static void updateWeights(tree *tr, int model, int rate, double value) { int j; double w = 0.0; assert(rate >= 0 && rate < 4); tr->partitionData[model].weightExponents[rate] = value; for(j = 0; j < 4; j++) w += exp(tr->partitionData[model].weightExponents[j]); for(j = 0; j < 4; j++) tr->partitionData[model].weights[j] = exp(tr->partitionData[model].weightExponents[j]) / w; } static void optimizeWeights(tree *tr, double modelEpsilon, linkageList *ll, int numberOfModels) { int i; double initialLH = 0.0, finalLH = 0.0; evaluateGeneric(tr, tr->start, TRUE); initialLH = tr->likelihood; //printf("W: %f %f [%f] ->", tr->perPartitionLH[0], tr->perPartitionLH[1], initialLH); for(i = 0; i < 4; i++) optParamGeneric(tr, modelEpsilon, ll, numberOfModels, i, -1000000.0, 200.0, LXWEIGHT_F); //optLG4X_Weights(tr, ll, numberOfModels, i, modelEpsilon); evaluateGeneric(tr, tr->start, TRUE); finalLH = tr->likelihood; if(finalLH < initialLH) printf("Final: %f initial: %f\n", finalLH, initialLH); assert(finalLH >= initialLH); //printf("%f %f [%f]\n", tr->perPartitionLH[0], tr->perPartitionLH[1], finalLH); } static void changeModelParameters(int index, int rateNumber, double value, int whichParameterType, tree *tr) { switch(whichParameterType) { case RATE_F: setRateModel(tr, index, value, rateNumber); initReversibleGTR(tr, index); break; case ALPHA_F: tr->partitionData[index].alpha = value; makeGammaCats(tr->partitionData[index].alpha, tr->partitionData[index].gammaRates, 4, tr->useMedian); break; case FREQ_F: { int states = tr->partitionData[index].states, j; double w = 0.0; tr->partitionData[index].freqExponents[rateNumber] = value; for(j = 0; j < states; j++) w += exp(tr->partitionData[index].freqExponents[j]); for(j = 0; j < states; j++) tr->partitionData[index].frequencies[j] = exp(tr->partitionData[index].freqExponents[j]) / w; initReversibleGTR(tr, index); } break; case LXRATE_F: tr->partitionData[index].gammaRates[rateNumber] = value; scaleLG4X_EIGN(tr, index); break; case LXWEIGHT_F: updateWeights(tr, index, rateNumber, value); scaleLG4X_EIGN(tr, index); break; default: assert(0); } } static void evaluateChange(tree *tr, int rateNumber, double *value, double *result, boolean* converged, int whichFunction, int numberOfModels, linkageList *ll, double modelEpsilon) { int i, k, pos; for(i = 0, pos = 0; i < ll->entries; i++) { if(ll->ld[i].valid) { if(converged[pos]) { //if parameter optimizations for this specific model have converged //set executeModel to FALSE for(k = 0; k < ll->ld[i].partitions; k++) tr->executeModel[ll->ld[i].partitionList[k]] = FALSE; } else { for(k = 0; k < ll->ld[i].partitions; k++) { int index = ll->ld[i].partitionList[k]; changeModelParameters(index, rateNumber, value[pos], whichFunction, tr); } } pos++; } else { // if this partition is not being optimized anyway (e.g., we may be optimizing GTR rates for all DNA partitions, // but there are also a couple of Protein partitions with fixed models like WAG, JTT, etc.) set executeModel to FALSE for(k = 0; k < ll->ld[i].partitions; k++) tr->executeModel[ll->ld[i].partitionList[k]] = FALSE; } } assert(pos == numberOfModels); //some error checks for individual model parameters switch(whichFunction) { case RATE_F: assert(rateNumber != -1); break; case ALPHA_F: break; case LXRATE_F: assert(rateNumber != -1); case LXWEIGHT_F: assert(rateNumber != -1); break; case FREQ_F: break; default: assert(0); } switch(whichFunction) { case RATE_F: case ALPHA_F: case LXRATE_F: case FREQ_F: case LXWEIGHT_F: evaluateGeneric(tr, tr->start, TRUE); break; default: assert(0); } //LIBRARY: need to switch over parallel regions here either call //the one for the rates or for alpha! //commented out evaluate below in the course of the LG4X integration //evaluateGeneric(tr, tr->start, TRUE); for(i = 0, pos = 0; i < ll->entries; i++) { if(ll->ld[i].valid) { result[pos] = 0.0; for(k = 0; k < ll->ld[i].partitions; k++) { int index = ll->ld[i].partitionList[k]; assert(tr->perPartitionLH[index] <= 0.0); result[pos] -= tr->perPartitionLH[index]; } pos++; } //set execute model for ALL partitions to true again //for consistency for(k = 0; k < ll->ld[i].partitions; k++) { int index = ll->ld[i].partitionList[k]; tr->executeModel[index] = TRUE; } } assert(pos == numberOfModels); } static void brentGeneric(double *ax, double *bx, double *cx, double *fb, double tol, double *xmin, double *result, int numberOfModels, int whichFunction, int rateNumber, tree *tr, linkageList *ll, double *lim_inf, double *lim_sup) { int iter, i; double *a = (double *)malloc(sizeof(double) * numberOfModels), *b = (double *)malloc(sizeof(double) * numberOfModels), *d = (double *)malloc(sizeof(double) * numberOfModels), *etemp = (double *)malloc(sizeof(double) * numberOfModels), *fu = (double *)malloc(sizeof(double) * numberOfModels), *fv = (double *)malloc(sizeof(double) * numberOfModels), *fw = (double *)malloc(sizeof(double) * numberOfModels), *fx = (double *)malloc(sizeof(double) * numberOfModels), *p = (double *)malloc(sizeof(double) * numberOfModels), *q = (double *)malloc(sizeof(double) * numberOfModels), *r = (double *)malloc(sizeof(double) * numberOfModels), *tol1 = (double *)malloc(sizeof(double) * numberOfModels), *tol2 = (double *)malloc(sizeof(double) * numberOfModels), *u = (double *)malloc(sizeof(double) * numberOfModels), *v = (double *)malloc(sizeof(double) * numberOfModels), *w = (double *)malloc(sizeof(double) * numberOfModels), *x = (double *)malloc(sizeof(double) * numberOfModels), *xm = (double *)malloc(sizeof(double) * numberOfModels), *e = (double *)malloc(sizeof(double) * numberOfModels); boolean *converged = (boolean *)malloc(sizeof(boolean) * numberOfModels); boolean allConverged; for(i = 0; i < numberOfModels; i++) converged[i] = FALSE; for(i = 0; i < numberOfModels; i++) { e[i] = 0.0; d[i] = 0.0; } for(i = 0; i < numberOfModels; i++) { a[i]=((ax[i] < cx[i]) ? ax[i] : cx[i]); b[i]=((ax[i] > cx[i]) ? ax[i] : cx[i]); x[i] = w[i] = v[i] = bx[i]; fw[i] = fv[i] = fx[i] = fb[i]; } for(i = 0; i < numberOfModels; i++) { assert(a[i] >= lim_inf[i] && a[i] <= lim_sup[i]); assert(b[i] >= lim_inf[i] && b[i] <= lim_sup[i]); assert(x[i] >= lim_inf[i] && x[i] <= lim_sup[i]); assert(v[i] >= lim_inf[i] && v[i] <= lim_sup[i]); assert(w[i] >= lim_inf[i] && w[i] <= lim_sup[i]); } for(iter = 1; iter <= ITMAX; iter++) { allConverged = TRUE; for(i = 0; i < numberOfModels && allConverged; i++) allConverged = allConverged && converged[i]; if(allConverged) { free(converged); free(a); free(b); free(d); free(etemp); free(fu); free(fv); free(fw); free(fx); free(p); free(q); free(r); free(tol1); free(tol2); free(u); free(v); free(w); free(x); free(xm); free(e); return; } for(i = 0; i < numberOfModels; i++) { if(!converged[i]) { assert(a[i] >= lim_inf[i] && a[i] <= lim_sup[i]); assert(b[i] >= lim_inf[i] && b[i] <= lim_sup[i]); assert(x[i] >= lim_inf[i] && x[i] <= lim_sup[i]); assert(v[i] >= lim_inf[i] && v[i] <= lim_sup[i]); assert(w[i] >= lim_inf[i] && w[i] <= lim_sup[i]); xm[i] = 0.5 * (a[i] + b[i]); tol2[i] = 2.0 * (tol1[i] = tol * fabs(x[i]) + BRENT_ZEPS); if(fabs(x[i] - xm[i]) <= (tol2[i] - 0.5 * (b[i] - a[i]))) { result[i] = -fx[i]; xmin[i] = x[i]; converged[i] = TRUE; } else { if(fabs(e[i]) > tol1[i]) { r[i] = (x[i] - w[i]) * (fx[i] - fv[i]); q[i] = (x[i] - v[i]) * (fx[i] - fw[i]); p[i] = (x[i] - v[i]) * q[i] - (x[i] - w[i]) * r[i]; q[i] = 2.0 * (q[i] - r[i]); if(q[i] > 0.0) p[i] = -p[i]; q[i] = fabs(q[i]); etemp[i] = e[i]; e[i] = d[i]; if((fabs(p[i]) >= fabs(0.5 * q[i] * etemp[i])) || (p[i] <= q[i] * (a[i]-x[i])) || (p[i] >= q[i] * (b[i] - x[i]))) d[i] = BRENT_CGOLD * (e[i] = (x[i] >= xm[i] ? a[i] - x[i] : b[i] - x[i])); else { d[i] = p[i] / q[i]; u[i] = x[i] + d[i]; if( u[i] - a[i] < tol2[i] || b[i] - u[i] < tol2[i]) d[i] = SIGN(tol1[i], xm[i] - x[i]); } } else { d[i] = BRENT_CGOLD * (e[i] = (x[i] >= xm[i] ? a[i] - x[i]: b[i] - x[i])); } u[i] = ((fabs(d[i]) >= tol1[i]) ? (x[i] + d[i]): (x[i] +SIGN(tol1[i], d[i]))); } if(!converged[i]) assert(u[i] >= lim_inf[i] && u[i] <= lim_sup[i]); } } evaluateChange(tr, rateNumber, u, fu, converged, whichFunction, numberOfModels, ll, tol); for(i = 0; i < numberOfModels; i++) { if(!converged[i]) { if(fu[i] <= fx[i]) { if(u[i] >= x[i]) a[i] = x[i]; else b[i] = x[i]; SHFT(v[i],w[i],x[i],u[i]); SHFT(fv[i],fw[i],fx[i],fu[i]); } else { if(u[i] < x[i]) a[i] = u[i]; else b[i] = u[i]; if(fu[i] <= fw[i] || w[i] == x[i]) { v[i] = w[i]; w[i] = u[i]; fv[i] = fw[i]; fw[i] = fu[i]; } else { if(fu[i] <= fv[i] || v[i] == x[i] || v[i] == w[i]) { v[i] = u[i]; fv[i] = fu[i]; } } } assert(a[i] >= lim_inf[i] && a[i] <= lim_sup[i]); assert(b[i] >= lim_inf[i] && b[i] <= lim_sup[i]); assert(x[i] >= lim_inf[i] && x[i] <= lim_sup[i]); assert(v[i] >= lim_inf[i] && v[i] <= lim_sup[i]); assert(w[i] >= lim_inf[i] && w[i] <= lim_sup[i]); assert(u[i] >= lim_inf[i] && u[i] <= lim_sup[i]); } } } free(converged); free(a); free(b); free(d); free(etemp); free(fu); free(fv); free(fw); free(fx); free(p); free(q); free(r); free(tol1); free(tol2); free(u); free(v); free(w); free(x); free(xm); free(e); printf("\n. Too many iterations in BRENT !"); assert(0); } static int brakGeneric(double *param, double *ax, double *bx, double *cx, double *fa, double *fb, double *fc, double *lim_inf, double *lim_sup, int numberOfModels, int rateNumber, int whichFunction, tree *tr, linkageList *ll, double modelEpsilon) { double *ulim = (double *)malloc(sizeof(double) * numberOfModels), *u = (double *)malloc(sizeof(double) * numberOfModels), *r = (double *)malloc(sizeof(double) * numberOfModels), *q = (double *)malloc(sizeof(double) * numberOfModels), *fu = (double *)malloc(sizeof(double) * numberOfModels), *dum = (double *)malloc(sizeof(double) * numberOfModels), *temp = (double *)malloc(sizeof(double) * numberOfModels); int i, *state = (int *)malloc(sizeof(int) * numberOfModels), *endState = (int *)malloc(sizeof(int) * numberOfModels); boolean *converged = (boolean *)malloc(sizeof(boolean) * numberOfModels); boolean allConverged; for(i = 0; i < numberOfModels; i++) converged[i] = FALSE; for(i = 0; i < numberOfModels; i++) { state[i] = 0; endState[i] = 0; u[i] = 0.0; param[i] = ax[i]; if(param[i] > lim_sup[i]) param[i] = ax[i] = lim_sup[i]; if(param[i] < lim_inf[i]) param[i] = ax[i] = lim_inf[i]; assert(param[i] >= lim_inf[i] && param[i] <= lim_sup[i]); } evaluateChange(tr, rateNumber, param, fa, converged, whichFunction, numberOfModels, ll, modelEpsilon); for(i = 0; i < numberOfModels; i++) { param[i] = bx[i]; if(param[i] > lim_sup[i]) param[i] = bx[i] = lim_sup[i]; if(param[i] < lim_inf[i]) param[i] = bx[i] = lim_inf[i]; assert(param[i] >= lim_inf[i] && param[i] <= lim_sup[i]); } evaluateChange(tr, rateNumber, param, fb, converged, whichFunction, numberOfModels, ll, modelEpsilon); for(i = 0; i < numberOfModels; i++) { if (fb[i] > fa[i]) { SHFT(dum[i],ax[i],bx[i],dum[i]); SHFT(dum[i],fa[i],fb[i],dum[i]); } cx[i] = bx[i] + MNBRAK_GOLD * (bx[i] - ax[i]); param[i] = cx[i]; if(param[i] > lim_sup[i]) param[i] = cx[i] = lim_sup[i]; if(param[i] < lim_inf[i]) param[i] = cx[i] = lim_inf[i]; assert(param[i] >= lim_inf[i] && param[i] <= lim_sup[i]); } evaluateChange(tr, rateNumber, param, fc, converged, whichFunction, numberOfModels, ll, modelEpsilon); while(1) { allConverged = TRUE; for(i = 0; i < numberOfModels && allConverged; i++) allConverged = allConverged && converged[i]; if(allConverged) { for(i = 0; i < numberOfModels; i++) { if(ax[i] > lim_sup[i]) ax[i] = lim_sup[i]; if(ax[i] < lim_inf[i]) ax[i] = lim_inf[i]; if(bx[i] > lim_sup[i]) bx[i] = lim_sup[i]; if(bx[i] < lim_inf[i]) bx[i] = lim_inf[i]; if(cx[i] > lim_sup[i]) cx[i] = lim_sup[i]; if(cx[i] < lim_inf[i]) cx[i] = lim_inf[i]; } free(converged); free(ulim); free(u); free(r); free(q); free(fu); free(dum); free(temp); free(state); free(endState); return 0; } for(i = 0; i < numberOfModels; i++) { if(!converged[i]) { switch(state[i]) { case 0: endState[i] = 0; if(!(fb[i] > fc[i])) converged[i] = TRUE; else { if(ax[i] > lim_sup[i]) ax[i] = lim_sup[i]; if(ax[i] < lim_inf[i]) ax[i] = lim_inf[i]; if(bx[i] > lim_sup[i]) bx[i] = lim_sup[i]; if(bx[i] < lim_inf[i]) bx[i] = lim_inf[i]; if(cx[i] > lim_sup[i]) cx[i] = lim_sup[i]; if(cx[i] < lim_inf[i]) cx[i] = lim_inf[i]; r[i]=(bx[i]-ax[i])*(fb[i]-fc[i]); q[i]=(bx[i]-cx[i])*(fb[i]-fa[i]); u[i]=(bx[i])-((bx[i]-cx[i])*q[i]-(bx[i]-ax[i])*r[i])/ (2.0*SIGN(MAX(fabs(q[i]-r[i]),MNBRAK_TINY),q[i]-r[i])); ulim[i]=(bx[i])+MNBRAK_GLIMIT*(cx[i]-bx[i]); if(u[i] > lim_sup[i]) u[i] = lim_sup[i]; if(u[i] < lim_inf[i]) u[i] = lim_inf[i]; if(ulim[i] > lim_sup[i]) ulim[i] = lim_sup[i]; if(ulim[i] < lim_inf[i]) ulim[i] = lim_inf[i]; if ((bx[i]-u[i])*(u[i]-cx[i]) > 0.0) { param[i] = u[i]; if(param[i] > lim_sup[i]) param[i] = u[i] = lim_sup[i]; if(param[i] < lim_inf[i]) param[i] = u[i] = lim_inf[i]; endState[i] = 1; } else { if ((cx[i]-u[i])*(u[i]-ulim[i]) > 0.0) { param[i] = u[i]; if(param[i] > lim_sup[i]) param[i] = u[i] = lim_sup[i]; if(param[i] < lim_inf[i]) param[i] = u[i] = lim_inf[i]; endState[i] = 2; } else { if ((u[i]-ulim[i])*(ulim[i]-cx[i]) >= 0.0) { u[i] = ulim[i]; param[i] = u[i]; if(param[i] > lim_sup[i]) param[i] = u[i] = ulim[i] = lim_sup[i]; if(param[i] < lim_inf[i]) param[i] = u[i] = ulim[i] = lim_inf[i]; endState[i] = 0; } else { u[i]=(cx[i])+MNBRAK_GOLD*(cx[i]-bx[i]); param[i] = u[i]; endState[i] = 0; if(param[i] > lim_sup[i]) param[i] = u[i] = lim_sup[i]; if(param[i] < lim_inf[i]) param[i] = u[i] = lim_inf[i]; } } } } break; case 1: endState[i] = 0; break; case 2: endState[i] = 3; break; default: assert(0); } assert(param[i] >= lim_inf[i] && param[i] <= lim_sup[i]); } } evaluateChange(tr, rateNumber, param, temp, converged, whichFunction, numberOfModels, ll, modelEpsilon); for(i = 0; i < numberOfModels; i++) { if(!converged[i]) { switch(endState[i]) { case 0: fu[i] = temp[i]; SHFT(ax[i],bx[i],cx[i],u[i]); SHFT(fa[i],fb[i],fc[i],fu[i]); state[i] = 0; break; case 1: fu[i] = temp[i]; if (fu[i] < fc[i]) { ax[i]=(bx[i]); bx[i]=u[i]; fa[i]=(fb[i]); fb[i]=fu[i]; converged[i] = TRUE; } else { if (fu[i] > fb[i]) { assert(u[i] >= lim_inf[i] && u[i] <= lim_sup[i]); cx[i]=u[i]; fc[i]=fu[i]; converged[i] = TRUE; } else { u[i]=(cx[i])+MNBRAK_GOLD*(cx[i]-bx[i]); param[i] = u[i]; if(param[i] > lim_sup[i]) {param[i] = u[i] = lim_sup[i];} if(param[i] < lim_inf[i]) {param[i] = u[i] = lim_inf[i];} state[i] = 1; } } break; case 2: fu[i] = temp[i]; if (fu[i] < fc[i]) { SHFT(bx[i],cx[i],u[i], cx[i]+MNBRAK_GOLD*(cx[i]-bx[i])); state[i] = 2; } else { state[i] = 0; SHFT(ax[i],bx[i],cx[i],u[i]); SHFT(fa[i],fb[i],fc[i],fu[i]); } break; case 3: SHFT(fb[i],fc[i],fu[i], temp[i]); SHFT(ax[i],bx[i],cx[i],u[i]); SHFT(fa[i],fb[i],fc[i],fu[i]); state[i] = 0; break; default: assert(0); } } } } assert(0); free(converged); free(ulim); free(u); free(r); free(q); free(fu); free(dum); free(temp); free(state); free(endState); return(0); } /*******************************************************************************************************/ /******** LG4X ***************************************************************************************/ static void optLG4X(tree *tr, double modelEpsilon, linkageList *ll, int numberOfModels) { int i; for(i = 0; i < 4; i++) { optParamGeneric(tr, modelEpsilon, ll, numberOfModels, i, LG4X_RATE_MIN, LG4X_RATE_MAX, LXRATE_F); optimizeWeights(tr, modelEpsilon, ll, numberOfModels); } } /**********************************************************************************************************/ /* ALPHA PARAM ********************************************************************************************/ //this function is required for implementing the LG4X model later-on static void optAlphasGeneric(tree *tr, double modelEpsilon, linkageList *ll) { int i, non_LG4X_Partitions = 0, LG4X_Partitions = 0; /* assumes homogeneous super-partitions, that either contain DNA or AA partitions !*/ /* does not check whether AA are all linked */ /* first do non-LG4X partitions */ for(i = 0; i < ll->entries; i++) { switch(tr->partitionData[ll->ld[i].partitionList[0]].dataType) { case DNA_DATA: case BINARY_DATA: case SECONDARY_DATA: case SECONDARY_DATA_6: case SECONDARY_DATA_7: case GENERIC_32: case GENERIC_64: ll->ld[i].valid = TRUE; non_LG4X_Partitions++; break; case AA_DATA: //to be implemented later-on if(tr->partitionData[ll->ld[i].partitionList[0]].protModels == LG4X) { LG4X_Partitions++; ll->ld[i].valid = FALSE; } else { ll->ld[i].valid = TRUE; non_LG4X_Partitions++; } break; default: assert(0); } } if(non_LG4X_Partitions > 0) optParamGeneric(tr, modelEpsilon, ll, non_LG4X_Partitions, -1, ALPHA_MIN, ALPHA_MAX, ALPHA_F); /* then LG4x partitions */ for(i = 0; i < ll->entries; i++) { switch(tr->partitionData[ll->ld[i].partitionList[0]].dataType) { case DNA_DATA: case BINARY_DATA: case SECONDARY_DATA: case SECONDARY_DATA_6: case SECONDARY_DATA_7: case GENERIC_32: case GENERIC_64: ll->ld[i].valid = FALSE; break; case AA_DATA: if(tr->partitionData[ll->ld[i].partitionList[0]].protModels == LG4X) ll->ld[i].valid = TRUE; else ll->ld[i].valid = FALSE; break; default: assert(0); } } if(LG4X_Partitions > 0) optLG4X(tr, modelEpsilon, ll, LG4X_Partitions); for(i = 0; i < ll->entries; i++) ll->ld[i].valid = TRUE; } static double minFreq(int index, int whichFreq, tree *tr, double absoluteMin) { double min = 0.0, *w = tr->partitionData[index].freqExponents, c = 0.0; int states = tr->partitionData[index].states, i; for(i = 0; i < states; i++) if(i != whichFreq) c += exp(w[i]); min = log(FREQ_MIN) + log(c) - log (1.0 - FREQ_MIN); if(0) { double check = exp(min) / (exp(min) + c); printf("check %f\n", check); printf("min: %f \n", min); } return MAX(min, absoluteMin); } static double maxFreq(int index, int whichFreq, tree *tr, double absoluteMax) { double max = 0.0, *w = tr->partitionData[index].freqExponents, c = 0.0; int states = tr->partitionData[index].states, i; for(i = 0; i < states; i++) if(i != whichFreq) c += exp(w[i]); max = log(1.0 - ((double)(states - 1) * FREQ_MIN)) + log(c) - log ((double)(states - 1) * FREQ_MIN); if(0) { double check = exp(max) / (exp(max) + c); printf("check max %f\n", check); printf("max: %f \n", max); } return MIN(max, absoluteMax); } static void optParamGeneric(tree *tr, double modelEpsilon, linkageList *ll, int numberOfModels, int rateNumber, double _lim_inf, double _lim_sup, int whichParameterType) { int l, k, j, pos; double *startRates = (double *)malloc(sizeof(double) * numberOfModels * 4), *startWeights = (double *)malloc(sizeof(double) * numberOfModels * 4), *startExponents = (double *)malloc(sizeof(double) * numberOfModels * 4), *startValues = (double *)malloc(sizeof(double) * numberOfModels), *startLH = (double *)malloc(sizeof(double) * numberOfModels), *endLH = (double *)malloc(sizeof(double) * numberOfModels), *_a = (double *)malloc(sizeof(double) * numberOfModels), *_b = (double *)malloc(sizeof(double) * numberOfModels), *_c = (double *)malloc(sizeof(double) * numberOfModels), *_fa = (double *)malloc(sizeof(double) * numberOfModels), *_fb = (double *)malloc(sizeof(double) * numberOfModels), *_fc = (double *)malloc(sizeof(double) * numberOfModels), *_param = (double *)malloc(sizeof(double) * numberOfModels), *_x = (double *)malloc(sizeof(double) * numberOfModels), *lim_inf = (double *)malloc(sizeof(double) * numberOfModels), *lim_sup = (double *)malloc(sizeof(double) * numberOfModels); evaluateGeneric(tr, tr->start, TRUE); #ifdef _DEBUG_MOD_OPT double initialLH = tr->likelihood; #endif /* at this point here every worker has the traversal data it needs for the search */ for(l = 0, pos = 0; l < ll->entries; l++) { if(ll->ld[l].valid) { endLH[pos] = unlikely; startLH[pos] = 0.0; for(j = 0; j < ll->ld[l].partitions; j++) { int index = ll->ld[l].partitionList[j]; startLH[pos] += tr->perPartitionLH[index]; switch(whichParameterType) { case ALPHA_F: lim_inf[pos] = _lim_inf; lim_sup[pos] = _lim_sup; startValues[pos] = tr->partitionData[index].alpha; break; case RATE_F: lim_inf[pos] = _lim_inf; lim_sup[pos] = _lim_sup; startValues[pos] = tr->partitionData[index].substRates[rateNumber]; break; case FREQ_F: lim_inf[pos] = minFreq(index, rateNumber, tr, _lim_inf); lim_sup[pos] = maxFreq(index, rateNumber, tr, _lim_sup); startValues[pos] = tr->partitionData[index].freqExponents[rateNumber]; break; case LXRATE_F: lim_inf[pos] = _lim_inf; lim_sup[pos] = _lim_sup; assert(rateNumber >= 0 && rateNumber < 4); startValues[pos] = tr->partitionData[index].gammaRates[rateNumber]; memcpy(&startRates[pos * 4], tr->partitionData[index].gammaRates, 4 * sizeof(double)); memcpy(&startExponents[pos * 4], tr->partitionData[index].weightExponents, 4 * sizeof(double)); memcpy(&startWeights[pos * 4], tr->partitionData[index].weights, 4 * sizeof(double)); break; case LXWEIGHT_F: lim_inf[pos] = _lim_inf; lim_sup[pos] = _lim_sup; assert(rateNumber >= 0 && rateNumber < 4); startValues[pos] = tr->partitionData[index].weightExponents[rateNumber]; break; default: assert(0); } } pos++; } } assert(pos == numberOfModels); for(k = 0, pos = 0; k < ll->entries; k++) { if(ll->ld[k].valid) { _a[pos] = startValues[pos] + 0.1; _b[pos] = startValues[pos] - 0.1; if(_a[pos] < lim_inf[pos]) _a[pos] = lim_inf[pos]; if(_a[pos] > lim_sup[pos]) _a[pos] = lim_sup[pos]; if(_b[pos] < lim_inf[pos]) _b[pos] = lim_inf[pos]; if(_b[pos] > lim_sup[pos]) _b[pos] = lim_sup[pos]; pos++; } } assert(pos == numberOfModels); brakGeneric(_param, _a, _b, _c, _fa, _fb, _fc, lim_inf, lim_sup, numberOfModels, rateNumber, whichParameterType, tr, ll, modelEpsilon); for(k = 0; k < numberOfModels; k++) { assert(_a[k] >= lim_inf[k] && _a[k] <= lim_sup[k]); assert(_b[k] >= lim_inf[k] && _b[k] <= lim_sup[k]); assert(_c[k] >= lim_inf[k] && _c[k] <= lim_sup[k]); } brentGeneric(_a, _b, _c, _fb, modelEpsilon, _x, endLH, numberOfModels, whichParameterType, rateNumber, tr, ll, lim_inf, lim_sup); for(k = 0, pos = 0; k < ll->entries; k++) { if(ll->ld[k].valid) { if(startLH[pos] > endLH[pos]) { //if the initial likelihood was better than the likelihodo after optimization, we set the values back //to their original values for(j = 0; j < ll->ld[k].partitions; j++) { int index = ll->ld[k].partitionList[j]; changeModelParameters(index, rateNumber, startValues[pos], whichParameterType, tr); } } else { //otherwise we set the value to the optimized value //this used to be a bug in standard RAxML, before I fixed it //I was not using _x[pos] as value that needs to be set for(j = 0; j < ll->ld[k].partitions; j++) { int index = ll->ld[k].partitionList[j]; changeModelParameters(index, rateNumber, _x[pos], whichParameterType, tr); } } pos++; } } //LIBRARY call the barrier here in the LIBRARY to update model params at all threads/processes ! assert(pos == numberOfModels); free(startLH); free(endLH); free(_a); free(_b); free(_c); free(_fa); free(_fb); free(_fc); free(_param); free(_x); free(startValues); free(startRates); free(startWeights); free(startExponents); free(lim_inf); free(lim_sup); #ifdef _DEBUG_MOD_OPT evaluateGeneric(tr, tr->start, TRUE); if(tr->likelihood < initialLH) printf("%f %f\n", tr->likelihood, initialLH); assert(tr->likelihood >= initialLH); #endif } //******************** rate optimization functions ***************************************************/ static void optFreqs(tree *tr, double modelEpsilon, linkageList *ll, int numberOfModels, int states) { int rateNumber; double freqMin = -1000000.0, freqMax = 200.0; for(rateNumber = 0; rateNumber < states; rateNumber++) optParamGeneric(tr, modelEpsilon, ll, numberOfModels, rateNumber, freqMin, freqMax, FREQ_F); } static void optBaseFreqs(tree *tr, double modelEpsilon, linkageList *ll) { int i, states, dnaPartitions = 0, aaPartitions = 0, binaryPartitions = 0; /* first do DNA */ for(i = 0; i < ll->entries; i++) { switch(tr->partitionData[ll->ld[i].partitionList[0]].dataType) { case DNA_DATA: states = tr->partitionData[ll->ld[i].partitionList[0]].states; if(tr->partitionData[ll->ld[i].partitionList[0]].optimizeBaseFrequencies) { ll->ld[i].valid = TRUE; dnaPartitions++; } else ll->ld[i].valid = FALSE; break; case AA_DATA: case BINARY_DATA: ll->ld[i].valid = FALSE; break; default: assert(0); } } if(dnaPartitions > 0) optFreqs(tr, modelEpsilon, ll, dnaPartitions, states); /* then AA */ for(i = 0; i < ll->entries; i++) { switch(tr->partitionData[ll->ld[i].partitionList[0]].dataType) { case AA_DATA: states = tr->partitionData[ll->ld[i].partitionList[0]].states; if(tr->partitionData[ll->ld[i].partitionList[0]].optimizeBaseFrequencies) { ll->ld[i].valid = TRUE; aaPartitions++; } else ll->ld[i].valid = FALSE; break; case DNA_DATA: case BINARY_DATA: ll->ld[i].valid = FALSE; break; default: assert(0); } } if(aaPartitions > 0) optFreqs(tr, modelEpsilon, ll, aaPartitions, states); //then binary for(i = 0; i < ll->entries; i++) { switch(tr->partitionData[ll->ld[i].partitionList[0]].dataType) { case BINARY_DATA: states = tr->partitionData[ll->ld[i].partitionList[0]].states; if(tr->partitionData[ll->ld[i].partitionList[0]].optimizeBaseFrequencies) { ll->ld[i].valid = TRUE; binaryPartitions++; } else ll->ld[i].valid = FALSE; break; case DNA_DATA: case AA_DATA: ll->ld[i].valid = FALSE; break; default: assert(0); } } if(binaryPartitions > 0) optFreqs(tr, modelEpsilon, ll, binaryPartitions, states); for(i = 0; i < ll->entries; i++) ll->ld[i].valid = TRUE; } //new version for optimizing rates, an external loop that iterates over the rates static void optRates(tree *tr, double modelEpsilon, linkageList *ll, int numberOfModels, int states) { int rateNumber, numberOfRates = ((states * states - states) / 2) - 1; for(rateNumber = 0; rateNumber < numberOfRates; rateNumber++) optParamGeneric(tr, modelEpsilon, ll, numberOfModels, rateNumber, RATE_MIN, RATE_MAX, RATE_F); } static boolean AAisGTR(tree *tr) { int i, count = 0; for(i = 0; i < tr->NumberOfModels; i++) { if(tr->partitionData[i].dataType == AA_DATA) { count++; if(tr->partitionData[i].protModels != GTR) return FALSE; } } if(count == 0) return FALSE; return TRUE; } static void optRatesGeneric(tree *tr, double modelEpsilon, linkageList *ll) { int i, dnaPartitions = 0, aaPartitions = 0, states = -1; /* assumes homogeneous super-partitions, that either contain DNA or AA partitions !*/ /* does not check whether AA are all linked */ /* first do DNA */ for(i = 0; i < ll->entries; i++) { switch(tr->partitionData[ll->ld[i].partitionList[0]].dataType) { case DNA_DATA: states = tr->partitionData[ll->ld[i].partitionList[0]].states; ll->ld[i].valid = TRUE; dnaPartitions++; break; case BINARY_DATA: case AA_DATA: case SECONDARY_DATA: case SECONDARY_DATA_6: case SECONDARY_DATA_7: case GENERIC_32: case GENERIC_64: ll->ld[i].valid = FALSE; break; default: assert(0); } } if(dnaPartitions > 0) optRates(tr, modelEpsilon, ll, dnaPartitions, states); /* then AA for GTR */ if(AAisGTR(tr)) { for(i = 0; i < ll->entries; i++) { switch(tr->partitionData[ll->ld[i].partitionList[0]].dataType) { case AA_DATA: states = tr->partitionData[ll->ld[i].partitionList[0]].states; ll->ld[i].valid = TRUE; aaPartitions++; break; case DNA_DATA: case BINARY_DATA: case SECONDARY_DATA: case SECONDARY_DATA_6: case SECONDARY_DATA_7: ll->ld[i].valid = FALSE; break; default: assert(0); } } assert(aaPartitions == 1); optRates(tr, modelEpsilon, ll, aaPartitions, states); } for(i = 0; i < ll->entries; i++) ll->ld[i].valid = TRUE; } /*********************FUNCTIONS FOR APPROXIMATE MODEL OPTIMIZATION ***************************************/ static int catCompare(const void *p1, const void *p2) { rateCategorize *rc1 = (rateCategorize *)p1; rateCategorize *rc2 = (rateCategorize *)p2; double i = rc1->accumulatedSiteLikelihood; double j = rc2->accumulatedSiteLikelihood; if (i > j) return (1); if (i < j) return (-1); return (0); } static void categorizePartition(tree *tr, rateCategorize *rc, int model, int lower, int upper, double *patrat, int *rateCategory /* temporary; used to be tr->rateCategory */ ) { int zeroCounter, i, k; double diff, min; for (i = lower, zeroCounter = 0; i < upper; i++, zeroCounter++) { double temp = patrat[i]; int found = 0; for(k = 0; k < tr->partitionData[model].numberOfCategories; k++) { if(temp == rc[k].rate || (fabs(temp - rc[k].rate) < 0.001)) { found = 1; rateCategory[i] = k; break; } } if(!found) { min = fabs(temp - rc[0].rate); rateCategory[i] = 0; for(k = 1; k < tr->partitionData[model].numberOfCategories; k++) { diff = fabs(temp - rc[k].rate); if(diff < min) { min = diff; rateCategory[i] = k; } } } } for(k = 0; k < tr->partitionData[model].numberOfCategories; k++) tr->partitionData[model].perSiteRates[k] = rc[k].rate; } static void optRateCatPthreads(tree *tr, double lower_spacing, double upper_spacing) { #ifdef _USE_OMP #pragma omp parallel #endif { int m, model, maxModel; #ifdef _USE_OMP maxModel = tr->maxModelsPerThread; #else maxModel = tr->NumberOfModels; #endif for(m = 0; m < maxModel; m++) { /* just defaults -> if partion wasn't assigned to this thread, it will be ignored later on */ size_t width = 0, offset = 0; #ifdef _USE_OMP int tid = omp_get_thread_num(); /* check if this thread should process this partition */ Assign* pAss = tr->threadPartAssigns[tid * tr->maxModelsPerThread + m]; if(pAss) { model = pAss->partitionId; width = pAss->width; offset = pAss->offset; assert(model < tr->NumberOfModels); } else break; #else model = m; /* number of sites in this partition */ width = (size_t)tr->partitionData[model].width; offset = 0; #endif size_t i; pInfo *partition = &(tr->partitionData[model]); for( i = offset; i < offset + width; ++i) { double initialRate, initialLikelihood, leftLH, rightLH, leftRate, rightRate, v; const double epsilon = 0.00001; int k; initialRate = partition->patrat[i]; initialLikelihood = evaluatePartialGeneric(tr, i, initialRate, model); /* i is real i ??? */ leftLH = rightLH = initialLikelihood; leftRate = rightRate = initialRate; k = 1; while((initialRate - k * lower_spacing > 0.0001) && ((v = evaluatePartialGeneric(tr, i, initialRate - k * lower_spacing, model)) > leftLH) && (fabs(leftLH - v) > epsilon)) { #ifndef WIN32 if(isnan(v)) assert(0); #endif leftLH = v; leftRate = initialRate - k * lower_spacing; k++; } k = 1; while(((v = evaluatePartialGeneric(tr, i, initialRate + k * upper_spacing, model)) > rightLH) && (fabs(rightLH - v) > epsilon)) { #ifndef WIN32 if(isnan(v)) assert(0); #endif rightLH = v; rightRate = initialRate + k * upper_spacing; k++; } if(rightLH > initialLikelihood || leftLH > initialLikelihood) { if(rightLH > leftLH) { partition->patrat[i] = rightRate; partition->lhs[i] = rightLH; } else { partition->patrat[i] = leftRate; partition->lhs[i] = leftLH; } } else partition->lhs[i] = initialLikelihood; } } } } /** determines the weighted rates for each partition. Intended for use with normalization of the CAT model rates. Since information about rates and weights is distributed (each process only has the respective info for the data assigned to it), we have to communicate with peer processes. Notice, that weightPerPart could actually be stored in a variable, since the result does not change... output: weightPerPart_result -- the sum of weights per partition weightedRates_result -- sum of rates per partition weighted by site weight */ static void getWeightsAndWeightedRates(const tree * const tr, int **weightPerPart_result, double **weightedRates_result ) { int i, *weightPerPart = (int *)NULL; double *weightedRates = (double *)NULL; *weightPerPart_result = (int*)calloc((size_t)tr->NumberOfModels, sizeof(int)); *weightedRates_result = (double*) calloc((size_t)tr->NumberOfModels, sizeof(double)); weightedRates = *weightedRates_result; weightPerPart = *weightPerPart_result; for(i = 0; i < tr->NumberOfModels; ++i) { size_t j; pInfo *partition = &(tr->partitionData[i]); for(j = 0; j < partition->width; ++j) { int c = partition->rateCategory[j]; weightPerPart[i] += partition->wgt[j]; assert(0 <= c && c < tr->maxCategories); weightedRates[i] += ((double)partition->wgt[j]) * partition->perSiteRates[c]; } } MPI_Allreduce(MPI_IN_PLACE, weightPerPart, tr->NumberOfModels, MPI_INT, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(MPI_IN_PLACE, weightedRates, tr->NumberOfModels, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); for( i = 0; i < tr->NumberOfModels; ++i) { assert(weightPerPart[i] > 0 ); assert(weightedRates[i] > 0.0 ); } } /* this used to be updatePerSiteRates without scaling. Previously, updatePerSiteRates without scaling only conducted a check about whether sites are scaled correctly. */ //Andre but isn't this checking that the rates have been scaled correctly? //shouldn't the assertions fail in this case, i.e., without scaling ? void checkPerSiteRates(const tree *const tr ) { int i, *weightPerPart = (int *)NULL; double *weightedRates = (double *)NULL; /* determine the sum of weights (weightPerPart) and the sum of all rates of a partition weighted by site weights */ getWeightsAndWeightedRates(tr, &weightPerPart, &weightedRates); if(tr->numBranches > 1 ) { /* check if the mean of rates of each partition is 1 */ for(i = 0; i < tr->NumberOfModels; ++i) { double accRat = weightedRates[i] / (double)weightPerPart[i]; assert(fabs(accRat - 1.0) < 1e-5); } } else { /* check, if the overall mean of rates is 1 */ double accRat = 0.0, accWgt = 0.0; for(i = 0; i < tr->NumberOfModels; ++i) { accRat += weightedRates[i]; accWgt += weightPerPart[i]; } accRat /= (double)accWgt; assert(fabs(accRat - 1.0) < 1e-5); } free(weightedRates); free(weightPerPart); } /** updatePerSiteRates is called after the master has categorized rates into several categories and every process has obtained the categorization for only the data assigned to it. Now, we still have to scale the rates, s.t. they are 1 on average. Thus, some communication is still needed to determine the total weight and the weighted rates (because this information is destributed). Notice that this function previously had two modes (scaleRates = {TRUE,FALSE}). Previously, scaleRates = FALSE, only performed a check on whether rates are scaled correctly such that the average rate is 1. For clarity, this functionality is now in a separate function called checkPerSiteRates. */ static void updatePerSiteRates(tree *tr) { int i, *weightPerPart = (int *)NULL; double *weightedRates = (double *)NULL; getWeightsAndWeightedRates(tr, &weightPerPart, &weightedRates); if(tr->numBranches > 1 ) { /* scale each partition, s.t. average rate within the partition is 1 */ for(i = 0; i < tr->NumberOfModels; ++i) { int j; double scaler = weightedRates[i] / (double)weightPerPart[i]; scaler = 1.0 / scaler; for(j = 0; j < tr->partitionData[i].numberOfCategories; ++j) tr->partitionData[i].perSiteRates[j] *= scaler; } } else { /* scale, s.t. average rate is 1 */ double scaler = 0.0, accWgt = 0.0; for(i = 0; i < tr->NumberOfModels; ++i) { scaler += weightedRates[i]; accWgt += weightPerPart[i]; } scaler /= (double)accWgt; scaler = 1.0 / scaler; for(i = 0; i < tr->NumberOfModels; ++i) { pInfo *partition = &(tr->partitionData[i]); int j; for(j = 0; j < partition->numberOfCategories; ++j) partition->perSiteRates[j] *= scaler; } } free(weightedRates); free(weightPerPart); /* finally check, whether the rates are scaled correctly, s.t. their mean is 1 */ checkPerSiteRates(tr); } /* gathers optimized rates and the associated persite-lnls from all processes at the master. Notice that for instance tr->patrat_basePtr already contain all rate data of a single process. Output: optRates_result -- (only at master) a pointer to an array of optimized rates (corresponds to what used to be tr->patratStored) lnls_result -- (only at master) a pointer to an array with persite-lnls that correspond to the newly proposed rate (used to be tr->lhs) */ static void gatherOptimizedRates(tree *tr, double **optRates_result, double **lnls_result) { /* determine counts and displacement for data for each processor */ int *numPerProc = (int *)NULL, *displPerProc = (int *)NULL; calculateLengthAndDisplPerProcess(tr, &numPerProc, &displPerProc); gatherDistributedArray( tr, (void**) optRates_result, tr->patrat_basePtr, MPI_DOUBLE, numPerProc, displPerProc); gatherDistributedArray(tr , (void**) lnls_result, tr->lhs_basePtr, MPI_DOUBLE, numPerProc, displPerProc); free(numPerProc); free(displPerProc); } /* The master creates rate categories and assigns the rate categories to processes. Only executed by the master to assure consistent categorization. This code used to be the first part of of optimizeRateCategories() and has only slightly been modified. Input: patrat -- a global array of optimized rates (used to be tr->patratStored) lnls -- a global array of per-site lnls (used to be tr->lhs) Output: rateCategory_result -- a pointer to a global array of rate categories (used to be tr->rateCategory) side effect: tr->partitionData[i].perSiteRates gets computed in categorizePartition. */ static void categorizeTheRates(tree *tr, double *patrat, double *lnls, int maxCategories, int **rateCategory_result) { int model, i; *rateCategory_result = (int*) calloc((size_t)tr->originalCrunchedLength, sizeof(int)); for(model = 0; model < tr->NumberOfModels; model++) { double temp = 0.0; int where = 1, found = 0, width = tr->partitionData[model].upper - tr->partitionData[model].lower, upper = tr->partitionData[model].upper, lower = tr->partitionData[model].lower; rateCategorize *rc = (rateCategorize *)malloc(sizeof(rateCategorize) * width); for (i = 0; i < width; i++) { rc[i].accumulatedSiteLikelihood = 0.0; rc[i].rate = 0.0; } rc[0].accumulatedSiteLikelihood = lnls[lower]; rc[0].rate = patrat[lower]; for (i = lower + 1; i < upper; i++) { int k; temp = patrat[i]; found = 0; for(k = 0; k < where; k++) { if(temp == rc[k].rate || (fabs(temp - rc[k].rate) < 0.001)) { found = 1; rc[k].accumulatedSiteLikelihood += lnls[i]; break; } } if(!found) { rc[where].rate = temp; rc[where].accumulatedSiteLikelihood += lnls[i]; where++; } } qsort(rc, where, sizeof(rateCategorize), catCompare); if(where < maxCategories) { tr->partitionData[model].numberOfCategories = where; categorizePartition(tr, rc, model, lower, upper, patrat, *rateCategory_result); } else { tr->partitionData[model].numberOfCategories = maxCategories; categorizePartition(tr, rc, model, lower, upper, patrat, *rateCategory_result); } free(rc); } } /* #define PRINT_RAT_CAT */ /** informs all peer processes about * rateCategory * numberOfCategories * perSiteRates of their data */ static void scatterProcessedRates(tree *tr, int *rateCategory) { int i, *countPerProc = (int *)NULL, *displPerProc = (int *)NULL, *numCatPerPart = (int*) calloc((size_t)tr->NumberOfModels, sizeof(int)); if(processID == 0) { for(i = 0; i < tr->NumberOfModels; ++i) numCatPerPart[i] = tr->partitionData[i].numberOfCategories; } MPI_Bcast(numCatPerPart, tr->NumberOfModels, MPI_INT, 0,MPI_COMM_WORLD); for(i = 0; i < tr->NumberOfModels; ++i) tr->partitionData[i].numberOfCategories = numCatPerPart[i]; free(numCatPerPart); /* for simplicity, broad cast all peSiteRates */ for(i = 0; i < tr->NumberOfModels; ++i) MPI_Bcast(tr->partitionData[i].perSiteRates, tr->maxCategories, MPI_DOUBLE, 0, MPI_COMM_WORLD); /* prepare for scattering */ calculateLengthAndDisplPerProcess(tr, &countPerProc, &displPerProc); #ifdef PRINT_RAT_CAT if(processID == 0) { printf("rates BEFORE: "); for(i = 0; i < tr->originalCrunchedLength; ++i) printf("%d,", rateCategory[i]); printf("\n"); } #endif scatterDistrbutedArray(tr, rateCategory, tr->rateCategory_basePtr, MPI_INT, countPerProc, displPerProc); #ifdef PRINT_RAT_CAT int len = getMyCharacterLength(tr); printf("basepointer AFTER: "); for(i = 0; i < len ; ++i) printf("%d,", tr->rateCategory_basePtr[i]); printf("\n"); #endif free(countPerProc); free(displPerProc); } /* backup for one partition */ typedef struct { double *patrat; int *rateCategory; double *perSiteRates; int numberOfCategories; } RateBackup; /** This function creates a backup of all data relevant for CAT-rate assignment. Previously, the backup info has been stored in patratStored. Or maybe it is the otherway around and patrat was the backup, while patratStored contained the actual optimized rates. Output: resultPtr -- contains the backup */ static void backupRates(tree *tr, RateBackup** resultPtr) { int i, numCat = tr->maxCategories; RateBackup *backup; *resultPtr = (RateBackup* ) calloc((size_t)tr->NumberOfModels, sizeof(RateBackup)); backup = *resultPtr; for(i = 0; i < tr->NumberOfModels; ++i) { pInfo *partition = &(tr->partitionData[i]); RateBackup *bk = backup + i; bk->patrat = (double*)calloc((size_t)partition->width, sizeof(double)); bk->perSiteRates = (double*) calloc((size_t)numCat, sizeof(double)); bk->rateCategory = (int*) calloc((size_t)partition->width, sizeof(int)) ; bk->numberOfCategories = partition->numberOfCategories; memcpy(bk->patrat, partition->patrat, sizeof(double) * (size_t)partition->width); memcpy(bk->perSiteRates, partition->perSiteRates, sizeof(double) * (size_t)numCat); memcpy(bk->rateCategory, partition->rateCategory, sizeof(int) * (size_t)partition->width); } } static void restoreBackupRates(tree *tr , RateBackup *rb) { int numCat = tr->maxCategories, i; for(i = 0; i < tr->NumberOfModels; ++i) { pInfo *partition = &(tr->partitionData[i]); RateBackup *bk = rb + i; partition->numberOfCategories = bk->numberOfCategories; memcpy(partition->patrat, bk->patrat, sizeof(double) * (size_t)partition->width); memcpy(partition->perSiteRates, bk->perSiteRates, sizeof(double) * (size_t)numCat); memcpy(partition->rateCategory, bk->rateCategory, sizeof(int) * (size_t)partition->width); } } static void deleteBackupRates(tree *tr, RateBackup** rbPtr) { int i ; for(i = 0; i< tr->NumberOfModels; ++i) { RateBackup *rb = &((*rbPtr)[i]); free(rb->patrat); free(rb->perSiteRates); free(rb->rateCategory); } free(*rbPtr); rbPtr = (RateBackup **)NULL; } static void optimizeRateCategories(tree *tr, int _maxCategories) { assert(_maxCategories > 0); if(_maxCategories == 1) return; double lower_spacing, upper_spacing, initialLH = tr->likelihood, *optRates = (double*)NULL, *lnls = (double*)NULL; int *rateCategory = (int *)NULL, maxCategories = _maxCategories ; RateBackup *rateBackup = (RateBackup *)NULL; assert(isTip(tr->start->number, tr->mxtips)); evaluateGeneric(tr, tr->start, TRUE); if(optimizeRateCategoryInvocations == 1) { lower_spacing = 0.5 / ((double)optimizeRateCategoryInvocations); upper_spacing = 1.0 / ((double)optimizeRateCategoryInvocations); } else { lower_spacing = 0.05 / ((double)optimizeRateCategoryInvocations); upper_spacing = 0.1 / ((double)optimizeRateCategoryInvocations); } if(lower_spacing < 0.001) lower_spacing = 0.001; if(upper_spacing < 0.001) upper_spacing = 0.001; optimizeRateCategoryInvocations++; //store old rate category assignment backupRates(tr, &rateBackup); /* process specific: each process optimizes rates for data assigned to it */ optRateCatPthreads(tr, lower_spacing, upper_spacing); /* gather rates and lnls at the master */ gatherOptimizedRates(tr, &optRates, &lnls); /* master has all necessary info now and can categorize the rates */ if(processID == 0) { categorizeTheRates(tr, optRates, lnls, maxCategories, &rateCategory ); /* only allocated at master */ free(optRates); free(lnls); } scatterProcessedRates(tr, rateCategory ); if(processID == 0) free(rateCategory); /* every process has now new rates and a new category assignment. However, we still have to scale the rates, such their weighted mean rate is 1. */ updatePerSiteRates(tr); evaluateGeneric(tr, tr->start, TRUE); if(tr->likelihood < initialLH) { restoreBackupRates(tr, rateBackup); //Andre I don't understand the comment below ... //can per-site rate scaling still be dis-abled in this version of the code? /* => Andre: I am afraid neither do I. Comparing it to the original code, I think everything should be fine: we restore the previous state and check, whether rates are scaled correctly. */ /* cannot do that any more here */ checkPerSiteRates(tr); evaluateGeneric(tr, tr->start, TRUE); assert(initialLH == tr->likelihood); } deleteBackupRates(tr,&rateBackup); } /*****************************************************************************************************/ void resetBranches(tree *tr) { nodeptr p, q; int nodes, i; nodes = tr->mxtips + 3 * (tr->mxtips - 2); p = tr->nodep[1]; while (nodes-- > 0) { for(i = 0; i < tr->numBranches; i++) p->z[i] = defaultz; q = p->next; while(q != p) { for(i = 0; i < tr->numBranches; i++) q->z[i] = defaultz; q = q->next; } p++; } } static void printAAmatrix(tree *tr, double epsilon) { if(AAisGTR(tr)) { int model; for(model = 0; model < tr->NumberOfModels; model++) { if(tr->partitionData[model].dataType == AA_DATA) { char gtrFileName[1024]; char epsilonStr[1024]; FILE *gtrFile; double *rates = tr->partitionData[model].substRates; double *f = tr->partitionData[model].frequencies; double q[20][20]; int r = 0; int i, j; assert(tr->partitionData[model].protModels == GTR); sprintf(epsilonStr, "%f", epsilon); strcpy(gtrFileName, workdir); strcat(gtrFileName, "RAxML_proteinGTRmodel."); strcat(gtrFileName, run_id); strcat(gtrFileName, "_"); strcat(gtrFileName, epsilonStr); gtrFile = myfopen(gtrFileName, "wb"); for(i = 0; i < 20; i++) for(j = 0; j < 20; j++) q[i][j] = 0.0; for(i = 0; i < 19; i++) for(j = i + 1; j < 20; j++) q[i][j] = rates[r++]; for(i = 0; i < 20; i++) for(j = 0; j <= i; j++) { if(i == j) q[i][j] = 0.0; else q[i][j] = q[j][i]; } for(i = 0; i < 20; i++) { for(j = 0; j < 20; j++) fprintf(gtrFile, "%1.80f ", q[i][j]); fprintf(gtrFile, "\n"); } for(i = 0; i < 20; i++) fprintf(gtrFile, "%1.80f ", f[i]); fprintf(gtrFile, "\n"); fclose(gtrFile); printBothOpen("\nPrinted intermediate AA substitution matrix to file %s\n\n", gtrFileName); break; } } } } static void optModel(tree *tr, int numProteinModels, int *bestIndex, double *bestScores, boolean empiricalFreqs) { int i, model; for(model = 0; model < tr->NumberOfModels; model++) { bestIndex[model] = -1; bestScores[model] = unlikely; } for(i = 0; i < numProteinModels; i++) { for(model = 0; model < tr->NumberOfModels; model++) { if(tr->partitionData[model].protModels == AUTO) { if(empiricalFreqs) tr->partitionData[model].protFreqs = 0; else tr->partitionData[model].protFreqs = 1; assert(!tr->partitionData[model].optimizeBaseFrequencies); tr->partitionData[model].autoProtModels = i; initReversibleGTR(tr, model); } } resetBranches(tr); evaluateGeneric(tr, tr->start, TRUE); treeEvaluate(tr, 0.5); //if(processID == 0) //printf("Subst Model %d Freqs: %s like %f %f\n", i, (empiricalFreqs == TRUE)?"empirical":"fixed", tr->likelihood, tr->perPartitionLH[0]); for(model = 0; model < tr->NumberOfModels; model++) { if(tr->partitionData[model].protModels == AUTO) { /* if(processID == 0) { int k; for(k = 0; k < 20; k++) printf("%f ", tr->partitionData[model].frequencies[k]); printf("\n"); } */ if(tr->perPartitionLH[model] > bestScores[model]) { bestScores[model] = tr->perPartitionLH[model]; bestIndex[model] = i; } } } } } static void autoProtein(tree *tr, analdef *adef) { int countAutos = 0, model; for(model = 0; model < tr->NumberOfModels; model++) if(tr->partitionData[model].protModels == AUTO) countAutos++; if(countAutos > 0) { int numProteinModels = AUTO, *bestIndex = (int*)malloc(sizeof(int) * tr->NumberOfModels), *oldIndex = (int*)malloc(sizeof(int) * tr->NumberOfModels), *bestIndexEmpFreqs = (int*)malloc(sizeof(int) * tr->NumberOfModels); boolean *oldFreqs = (boolean*)malloc(sizeof(boolean) * tr->NumberOfModels); double startLH, *bestScores = (double*)malloc(sizeof(double) * tr->NumberOfModels), *bestScoresEmpFreqs = (double*)malloc(sizeof(double) * tr->NumberOfModels); topolRELL_LIST *rl = (topolRELL_LIST *)malloc(sizeof(topolRELL_LIST)); char *autoModels[4] = {"ML", "BIC", "AIC", "AICc"}; initTL(rl, tr, 1); saveTL(rl, tr, 0); evaluateGeneric(tr, tr->start, TRUE); startLH = tr->likelihood; for(model = 0; model < tr->NumberOfModels; model++) { oldIndex[model] = tr->partitionData[model].autoProtModels; oldFreqs[model] = tr->partitionData[model].protFreqs; } optModel(tr, numProteinModels, bestIndex, bestScores, FALSE); optModel(tr, numProteinModels, bestIndexEmpFreqs, bestScoresEmpFreqs, TRUE); printBothOpen("Automatic protein model assignment algorithm using %s criterion:\n\n", autoModels[tr->autoProteinSelectionType]); for(model = 0; model < tr->NumberOfModels; model++) { if(tr->partitionData[model].protModels == AUTO) { int bestIndexFixed = bestIndex[model], bestIndexEmp = bestIndexEmpFreqs[model]; double bestLhFixed = bestScores[model], bestLhEmp = bestScoresEmpFreqs[model], samples = 0.0, freeParamsFixed = 0.0, freeParamsEmp = 0.0; samples = tr->partitionWeights[model]; //printf("Sample size %f\n", samples); assert(samples != -1.0 && samples > 0.0); //we always deal with comprehensive trees in ExaML assert(tr->ntips == tr->mxtips); freeParamsFixed = freeParamsEmp = (2 * tr->ntips - 3); freeParamsEmp += 19.0; switch(tr->rateHetModel) { case CAT: freeParamsFixed += (double)tr->partitionData[model].numberOfCategories; freeParamsEmp += (double)tr->partitionData[model].numberOfCategories; break; case GAMMA: freeParamsFixed += 1.0; freeParamsEmp += 1.0; break; case GAMMA_I: freeParamsFixed += 2.0; freeParamsEmp += 2.0; break; default: assert(0); } switch(tr->autoProteinSelectionType) { case AUTO_ML: if(bestLhFixed > bestLhEmp) { tr->partitionData[model].autoProtModels = bestIndexFixed; tr->partitionData[model].protFreqs = 1; } else { tr->partitionData[model].autoProtModels = bestIndexEmp; tr->partitionData[model].protFreqs = 0; } break; case AUTO_BIC: { //BIC: -2 * lnL + k * ln(n) double bicFixed = -2.0 * bestLhFixed + freeParamsFixed * log(samples), bicEmp = -2.0 * bestLhEmp + freeParamsEmp * log(samples); if(bicFixed < bicEmp) { tr->partitionData[model].autoProtModels = bestIndexFixed; tr->partitionData[model].protFreqs = 1; } else { tr->partitionData[model].autoProtModels = bestIndexEmp; tr->partitionData[model].protFreqs = 0; } } break; case AUTO_AIC: { //AIC: 2 * (k - lnL) double aicFixed = 2.0 * (freeParamsFixed - bestLhFixed), aicEmp = 2.0 * (freeParamsEmp - bestLhEmp); if(aicFixed < aicEmp) { tr->partitionData[model].autoProtModels = bestIndexFixed; tr->partitionData[model].protFreqs = 1; } else { tr->partitionData[model].autoProtModels = bestIndexEmp; tr->partitionData[model].protFreqs = 0; } } break; case AUTO_AICC: { //AICc: AIC + (2 * k * (k + 1))/(n - k - 1) double aiccFixed, aiccEmp; /* * Even though samples and freeParamsFixed are fp variables, they are actually integers. * That's why we are comparing with a 0.5 threshold. */ if(fabs(samples - freeParamsFixed - 1.0) < 0.5) aiccFixed = 0.0; else aiccFixed = (2.0 * (freeParamsFixed - bestLhFixed)) + ((2.0 * freeParamsFixed * (freeParamsFixed + 1.0)) / (samples - freeParamsFixed - 1.0)); if(fabs(samples - freeParamsEmp - 1.0) < 0.5) aiccEmp = 0.0; else aiccEmp = (2.0 * (freeParamsEmp - bestLhEmp)) + ((2.0 * freeParamsEmp * (freeParamsEmp + 1.0)) / (samples - freeParamsEmp - 1.0)); if(aiccFixed < aiccEmp) { tr->partitionData[model].autoProtModels = bestIndexFixed; tr->partitionData[model].protFreqs = 1; } else { tr->partitionData[model].autoProtModels = bestIndexEmp; tr->partitionData[model].protFreqs = 0; } } break; default: assert(0); } initReversibleGTR(tr, model); printBothOpen("\tPartition: %d best-scoring AA model: %s likelihood %f with %s base frequencies\n", model, protModels[tr->partitionData[model].autoProtModels], (tr->partitionData[model].protFreqs == 1)?bestLhFixed:bestLhEmp, (tr->partitionData[model].protFreqs == 1)?"fixed":"empirical"); } } printBothOpen("\n\n"); resetBranches(tr); evaluateGeneric(tr, tr->start, TRUE); treeEvaluate(tr, 2.0); //printf("exit %f\n", tr->likelihood); if(tr->likelihood < startLH) { for(model = 0; model < tr->NumberOfModels; model++) { if(tr->partitionData[model].protModels == AUTO) { tr->partitionData[model].autoProtModels = oldIndex[model]; tr->partitionData[model].protFreqs = oldFreqs[model] ; initReversibleGTR(tr, model); } } restoreTL(rl, tr, 0); evaluateGeneric(tr, tr->start, TRUE); } assert(tr->likelihood >= startLH); freeTL(rl); free(rl); free(oldIndex); free(bestIndex); free(bestScores); free(bestIndexEmpFreqs); free(bestScoresEmpFreqs); free(oldFreqs); } } static void checkMatrixSymnmetriesAndLinkage(tree *tr, linkageList *ll) { int i; for(i = 0; i < ll->entries; i++) { int partitions = ll->ld[i].partitions; if(partitions > 1) { int k, reference = ll->ld[i].partitionList[0]; for(k = 1; k < partitions; k++) { int index = ll->ld[i].partitionList[k]; int states = tr->partitionData[index].states, rates = ((states * states - states) / 2); if(tr->partitionData[reference].nonGTR != tr->partitionData[index].nonGTR) assert(0); if(tr->partitionData[reference].nonGTR) { int j; for(j = 0; j < rates; j++) { if(tr->partitionData[reference].symmetryVector[j] != tr->partitionData[index].symmetryVector[j]) assert(0); } } } } } } static void checkTolerance(double l1, double l2) { if(l1 < l2) { double tolerance = fabs(MAX(l1, l2) * 0.000000000001); if(fabs(l1 - l2) > MIN(0.1, tolerance)) { printf("Likelihood problem in model optimization l1: %1.40f l2: %1.40f tolerance: %1.40f\n", l1, l2, tolerance); assert(0); } } } void modOpt(tree *tr, double likelihoodEpsilon, analdef *adef, int treeIteration) { int i, catOpt = 0, *unlinked = (int *)malloc(sizeof(int) * tr->NumberOfModels); double inputLikelihood, currentLikelihood, modelEpsilon = 0.0001; linkageList *alphaList, *rateList, *freqList; for(i = 0; i < tr->NumberOfModels; i++) unlinked[i] = i; //test code for library if(0) { //assuming that we have three partitions for testing here alphaList = initLinkageListString("0,1,2", tr); rateList = initLinkageListString("0,1,1", tr); init_Q_MatrixSymmetries("0,1,2,3,4,5", tr, 0); init_Q_MatrixSymmetries("0,1,2,3,4,4", tr, 1); init_Q_MatrixSymmetries("0,1,1,2,3,4", tr, 2); //function that checks that partitions that have linked Q matrices as in our example above //will not have different configurations of the Q matrix as set by the init_Q_MatrixSymmetries() function //e.g., on would have HKY and one would have GTR, while the user claimes that they are linked //in our example, the Q matrices of partitions 1 and 2 are linked //but we set different matrix symmetries via // init_Q_MatrixSymmetries("0,1,2,3,4,4", tr, 1); // and // init_Q_MatrixSymmetries("0,1,1,2,3,4", tr, 2); // //the function just let's assertions fail for the time being ..... checkMatrixSymnmetriesAndLinkage(tr, rateList); } else { alphaList = initLinkageList(unlinked, tr); freqList = initLinkageList(unlinked, tr); rateList = initLinkageListGTR(tr); } tr->start = tr->nodep[1]; if(adef->useCheckpoint && adef->mode == TREE_EVALUATION) { assert(ckp.state == MOD_OPT); catOpt = ckp.catOpt; } inputLikelihood = tr->likelihood; evaluateGeneric(tr, tr->start, TRUE); assert(inputLikelihood == tr->likelihood); do { if(adef->mode == TREE_EVALUATION) { ckp.state = MOD_OPT; ckp.catOpt = catOpt; ckp.treeIteration = treeIteration; writeCheckpoint(tr, adef); } currentLikelihood = tr->likelihood; #ifdef _DEBUG_MOD_OPT printf("start: %f\n", currentLikelihood); #endif optRatesGeneric(tr, modelEpsilon, rateList); evaluateGeneric(tr, tr->start, TRUE); #ifdef _DEBUG_MOD_OPT printf("after rates %f\n", tr->likelihood); #endif autoProtein(tr, adef); treeEvaluate(tr, 0.0625); #ifdef _DEBUG_MOD_OPT evaluateGeneric(tr, tr->start, TRUE); printf("after br-len 1 %f\n", tr->likelihood); #endif evaluateGeneric(tr, tr->start, TRUE); optBaseFreqs(tr, modelEpsilon, freqList); evaluateGeneric(tr, tr->start, TRUE); treeEvaluate(tr, 0.0625); #ifdef _DEBUG_MOD_OPT evaluateGeneric(tr, tr->start, TRUE); printf("after optBaseFreqs 1 %f\n", tr->likelihood); #endif switch(tr->rateHetModel) { case GAMMA: optAlphasGeneric(tr, modelEpsilon, alphaList); evaluateGeneric(tr, tr->start, TRUE); #ifdef _DEBUG_MOD_OPT printf("after alphas %f\n", tr->likelihood); #endif treeEvaluate(tr, 0.1); #ifdef _DEBUG_MOD_OPT evaluateGeneric(tr, tr->start, TRUE); printf("after br-len 2 %f\n", tr->likelihood); #endif break; case CAT: if(catOpt < 3) { evaluateGeneric(tr, tr->start, TRUE); optimizeRateCategories(tr, tr->categories); #ifdef _DEBUG_MOD_OPT evaluateGeneric(tr, tr->start, TRUE); printf("after cat-opt %f\n", tr->likelihood); #endif catOpt++; } break; default: assert(0); } checkTolerance(tr->likelihood, currentLikelihood); /* if(tr->likelihood < currentLikelihood) printf("%f %f\n", tr->likelihood, currentLikelihood); assert(tr->likelihood >= currentLikelihood); */ printAAmatrix(tr, fabs(currentLikelihood - tr->likelihood)); } while(fabs(currentLikelihood - tr->likelihood) > likelihoodEpsilon); free(unlinked); freeLinkageList(freqList); freeLinkageList(alphaList); freeLinkageList(rateList); } ExaML-3.0.21/examl/partitionAssignment.c000066400000000000000000000422551330315463200200670ustar00rootroot00000000000000#include #include #include #include "partitionAssignment.h" extern int processID; void initializePartitionAssignment( PartitionAssignment **pAssPtr, pInfo **partitions, int numPart, int numProc) { int i; PartitionAssignment *pAss; *pAssPtr = (PartitionAssignment*)calloc(1, sizeof(PartitionAssignment)); pAss = *pAssPtr; pAss->numProc = numProc; pAss->numPartitions = numPart; pAss->partitions = (Partition *)calloc((size_t)pAss->numPartitions, sizeof(Partition)); for(i = 0; i < numPart; ++i) { Partition *p = pAss->partitions + i; p->id = i; p->width = partitions[i]->upper - partitions[i]->lower; p->type = partitions[i]->states; } pAss->assignPerProc = (Assignment **)calloc((size_t)pAss->numProc , sizeof(Assignment*)); pAss->numAssignPerProc = (int *)calloc((size_t)pAss->numProc, sizeof(int)); } void deletePartitionAssignment(PartitionAssignment *pAss) { int i; free(pAss->partitions); for(i = 0; i < pAss->numProc; ++i) free(pAss->assignPerProc[i]); free(pAss->assignPerProc); free(pAss); } static int partSort(const void *a, const void *b ) { return ((const Partition*)a)->width - ((const Partition*) b)->width ; } /** helper function that executes the assignment of a partial assignment (only numElem character are assigned) */ static void assignPartitionPartial(PartitionAssignment *pa, Partition* p, int procId, int *numAssigned, size_t *sizeAssigned, size_t offset, size_t numElem) { Assignment *a; int newArrayLen; ++numAssigned[procId]; ++pa->numAssignPerProc[procId]; newArrayLen = pa->numAssignPerProc[procId]; pa->assignPerProc[procId] = (Assignment*)realloc(pa->assignPerProc[procId], newArrayLen * sizeof(Assignment)); a = pa->assignPerProc[procId] + (newArrayLen-1); a->offset = offset; a->partId = p->id; a->width = numElem; sizeAssigned[procId] += numElem; } /** helper function that executes the assignment of a full partition */ static void assignPartitionFull(PartitionAssignment* pa, Partition* p, int procId, int *numAssigned, size_t *sizeAssigned) { assignPartitionPartial(pa, p, procId, numAssigned, sizeAssigned, 0, p->width); } /** Request a process to which a part of the partition should be assigned to. At this stage there are processes that have one more partition assignment than others. These have been categorized into two stacks (high and low). For each stack, we have in iter variable (of type int**) that gets decremented, if an element is removed from the stack and a the start of the array that allows us to determine when the stack is empty. popAndYield tries to satisfy the request for a process with more or less assignments (see wantLow), but will return any process, if the request cannot be fulfilled. If both queues are empty, it will return -1. */ static int popAndYield(int **procsHighIter, int *procsHighStart, int **procsLowIter, int *procsLowStart, boolean wantLow) { boolean fromHigh = FALSE, fromLow = FALSE; int result = -1; if(wantLow) { if(*procsLowIter - procsLowStart > 0) fromLow = TRUE; else if(*procsHighIter - procsHighStart > 0) fromHigh = TRUE; } else { if(*procsHighIter - procsHighStart > 0 ) fromHigh = TRUE; else if(*procsLowIter - procsLowStart > 0) fromLow = TRUE; } if(fromHigh) { result = **procsHighIter; --(*procsHighIter); } else if(fromLow) { result = **procsLowIter; --(*procsLowIter); } return result; } static void assignThesePartitions(PartitionAssignment* pa, Partition *partitions, int numCur) { int proc, remainder, /* number of processes that receive 1 character less than other s */ i, numFull = 0, /* number of processes that cannot take any more */ numLow = 0, /* */ *numAssigned = (int *)NULL, /* number of characters assigned to a process */ *procsHighIter = (int *)NULL, /* stack of processes that have one assignment more than others */ *procsLowIter = (int *)NULL, /* stack of processes that have one assignment less than others */ *procsLowStart = (int *)NULL, /* start of stack */ *procsHighStart = (int *)NULL, /* start of stack */ highProc, /* id of a process that potentially has more partitions assigned than others */ lowProc; /* id of a process that potentially has less partitions assigned than others */ size_t totalElems = 0, *sizeAssigned = (size_t *)NULL, toAdd, cap; /* defines a cap: once we have assigned this many characters, the remaining processes will get one character less */ boolean iterate = TRUE; Partition *partIter = partitions, *partEnd = partitions +numCur; /* The following implements Kassian's algorithm. Originally, his algorithm consists of 5 phases */ /* Sorts partitions according to their size. According to Kassians algorithm, this step is NOT obligatory. However, if we do it, then phase 3 (called "top-up" phase) is not necessary (this has been clarified with Kassian). */ qsort(partitions, numCur, sizeof(Partition), partSort); for(i = 0; i < numCur; ++i) totalElems += partitions[i].width; cap = ceil( (double)totalElems / (double)pa->numProc ); remainder = cap * pa->numProc - totalElems; assert(remainder >= 0 ); numAssigned = (int *)calloc((size_t)pa->numProc, sizeof(int)); sizeAssigned = (size_t *)calloc((size_t)pa->numProc, sizeof(size_t)); /* phase 2: initial distribution of full partitions to procesess. We distribute full partitions until for the first time, we cannot assign an entire partition any more, because this would exceed the number of characters we want to assign to this process */ while(iterate) { for(proc = 0; proc < pa->numProc;++proc) { if(partIter < partEnd && sizeAssigned[proc] + partIter->width <= cap) { assignPartitionFull(pa, partIter, proc, numAssigned, sizeAssigned); if(sizeAssigned[proc] == cap) { ++numFull; if(numFull == pa->numProc - remainder) --cap; } ++partIter; } else { numLow = numAssigned[proc]; iterate = FALSE; break; } } } /* phase 3: top-up => not necessary because of previous sorting */ /* phase 4: stick breaking Here we partially assign the remaining partitions to processes until every process has as many characters as it can take. */ /* first categorize processes into two stacks, dependent on whether they have gotton one more partition than others */ procsHighIter = (int*)calloc((size_t)pa->numProc + 1, sizeof(int)); procsLowIter = (int *)calloc((size_t)pa->numProc + 1, sizeof(int)); procsLowStart = procsLowIter; procsHighStart = procsHighIter; numFull = 0; for(proc = 0; proc < pa->numProc; ++proc) { if(sizeAssigned[proc] < cap) { if(numAssigned[proc] == numLow) { ++procsLowIter; *procsLowIter = proc; } else { ++procsHighIter; *procsHighIter = proc; } } else ++numFull; } assert((procsHighIter - procsHighStart) + (procsLowIter - procsLowStart) + numFull == pa->numProc); toAdd = (partIter < partEnd) ? partIter->width : 0 ; highProc = popAndYield(&procsHighIter, procsHighStart, &procsLowIter, procsLowStart, FALSE); lowProc = popAndYield(&procsHighIter, procsHighStart, &procsLowIter, procsLowStart, TRUE); /* now assign as long as there is something to assign. Once both stacks are empty, popAndYield yields -1. This then breaks the loop condition here. */ while( ! (highProc == -1 && lowProc == -1 && (procsHighIter - procsHighStart <= 0 ) && (procsLowIter - procsLowStart <= 0 )) ) { /* try to finish a assignments for a process that has many partitions */ if(highProc != -1 && sizeAssigned[highProc] + toAdd >= cap) { size_t toTransfer = cap - sizeAssigned[highProc], offset = partIter->width - toAdd; assignPartitionPartial( pa, partIter, highProc, numAssigned, sizeAssigned, offset, toTransfer); toAdd -= toTransfer; if(toAdd == 0 && partIter < partEnd ) { ++partIter; toAdd = partIter < partEnd ? partIter->width : 0; } ++numFull; if(numFull == pa->numProc - remainder) --cap; highProc = popAndYield(&procsHighIter, procsHighStart, &procsLowIter, procsLowStart, FALSE); } else if(lowProc != -1) { /* assign the enitre remaining portion to a process that still has fewer partitions */ if(sizeAssigned[lowProc] + toAdd < cap) { size_t offset = partIter->width - toAdd; assignPartitionPartial(pa, partIter, lowProc, numAssigned, sizeAssigned, offset, toAdd); if(highProc != -1 ) { ++procsHighIter; *procsHighIter = highProc; } highProc = lowProc; toAdd = 0; if( partIter != partEnd ) { ++partIter; toAdd = partIter < partEnd ? partIter->width : 0 ; } lowProc = popAndYield(&procsHighIter, procsHighStart, &procsLowIter, procsLowStart, TRUE); } else { /* assign as much as possible to a process with less partitions (the rest probably needs to be assigned to the next process) */ size_t toTransfer = cap - sizeAssigned[lowProc], offset = partIter->width - toAdd; assignPartitionPartial(pa, partIter, lowProc, numAssigned, sizeAssigned, offset, toTransfer); toAdd -= toTransfer; if(toAdd == 0 && partIter < partEnd) { ++partIter; toAdd = partIter < partEnd ? partIter->width : 0; } ++numFull; if(numFull == pa->numProc - remainder) --cap ; lowProc = popAndYield(&procsHighIter, procsHighStart, &procsLowIter, procsLowStart, FALSE); } } else { /* should not occurr, but I am not entirely happly with this assert. */ assert(0); } } assert(toAdd == 0 ); assert(partIter == partEnd); free(numAssigned); free(sizeAssigned); } /** Assigns all partitions. Notice that for each data type (currently only AA and DNA), we execute the algorithm separately. Thus, in the worst case imbalances for AA and DNA could hit the same processes (but this is probably not worth bothering). */ void assign(PartitionAssignment *pa) { int partitionsHandled = 0, curType = -1, j, i; /* only handling 3 types (BIN, DNA, AA) at the moment. Please adapt, when the number of types increases. */ int types[3] = { 2, 4, 20 }; for(j = 0; j < 3 ; ++j) { size_t cnt; Partition *curPartitions = (Partition *)NULL; curType = types[j]; /* count number of type */ cnt = 0; for(i = 0; i < pa->numPartitions; ++i) { if(pa->partitions[i].type == curType) ++cnt; } if(cnt == 0 ) continue; curPartitions = (Partition*)calloc((size_t)cnt, sizeof(Partition)); cnt = 0; for(i = 0; i< pa->numPartitions; ++i) { if(pa->partitions[i].type == curType) curPartitions[cnt++] = pa->partitions[i]; } assignThesePartitions(pa, curPartitions, cnt); free(curPartitions); partitionsHandled += cnt; } assert(partitionsHandled == pa->numPartitions); } void printAssignment(Assignment a, int procid) { printf("p: %d\t(%lu,%lu) -> proc %d\n", a.partId, a.offset, a.width , procid); } void printAssignments(PartitionAssignment *pa) { int i,j; printf("proc\toffset\tlength\tpart\n"); for(i = 0; i < pa->numProc; ++i) { for(j = 0; j < pa->numAssignPerProc[i] ; ++j) { Assignment a = pa->assignPerProc[i][j]; printf("%d\t%lu\t%lu\t%d\n", i,a.offset, a.width, a.partId); } } } void printLoad(PartitionAssignment *pa) { int i, j, *numsPerProc = (int *)calloc((size_t)pa->numProc, sizeof(int)); size_t *sitesPerProc = (size_t *)calloc((size_t)pa->numProc, sizeof(size_t)); for(i = 0; i< pa->numProc; ++i) { for(j = 0; j < pa->numAssignPerProc[i]; ++j) { Assignment a = pa->assignPerProc[i][j]; sitesPerProc[i] += a.width; ++numsPerProc[i]; } } printf("#proc\t#part\t#sites\n"); for( i = 0; i < pa->numProc ; ++i) printf("%d\t%d\t%lu\n", i, numsPerProc[i], sitesPerProc[i]); free(numsPerProc); free(sitesPerProc); } /** allocates global arrays for CAT and sets the pointers in each pInfo instance. */ static void setupBasePointersInTree(tree *tr) { size_t len = 0; int i; for(i = 0; i < tr->NumberOfModels; ++i) len += tr->partitionData[i].width ; tr->patrat_basePtr = (double*) calloc((size_t)len, sizeof(double)); tr->rateCategory_basePtr = (int*) calloc((size_t)len, sizeof(int)); tr->lhs_basePtr = (double*) calloc((size_t)len, sizeof(double)); len = 0; for(i = 0; i < tr->NumberOfModels; ++i) { if(tr->partitionData[i].width > 0) { tr->partitionData[i].rateCategory = tr->rateCategory_basePtr + len; tr->partitionData[i].patrat = tr->patrat_basePtr + len; tr->partitionData[i].lhs = tr->lhs_basePtr + len ; } else { tr->partitionData[i].rateCategory = (int *)NULL; tr->partitionData[i].patrat = (double*)NULL; tr->partitionData[i].lhs = (double*)NULL; } len += tr->partitionData[i].width; } } static int sortById(const void *a, const void *b) { return ((Assign*) a)->partitionId - ((Assign*) b)->partitionId ; } void copyAssignmentInfoToTree(PartitionAssignment *pa, tree *tr) { int i, numAssign = 0; Assign *assIter; for(i = 0; i < pa->numProc; ++i) numAssign += pa->numAssignPerProc[i]; /* copy the partition assignment to the tree structure */ tr->numAssignments = numAssign; tr->partAssigns = (Assign *)calloc((size_t)numAssign, sizeof(Assign)); assIter = tr->partAssigns; for(i = 0; i < pa->numProc; ++i) { int j; for( j = 0 ; j < pa->numAssignPerProc[i]; ++j) { Assignment *ass = pa->assignPerProc[i] + j; assIter->procId = i; assIter->offset = ass->offset; assIter->width = ass->width; assIter->partitionId = ass->partId; ++assIter; } } /* the sorting makes it easier to deal with the assignments later in case of a gather/scatter at the master. Thus, we do not need to jump around in the array that be obtained or send to a process, because we are sure that the data is ordered the same we as we obtained. */ qsort(tr->partAssigns, tr->numAssignments, sizeof(Assign), sortById); if(tr->rateHetModel == CAT) setupBasePointersInTree( tr); } #ifdef _USE_OMP void copyThreadAssignmentInfoToTree(PartitionAssignment *pa, tree *tr) { int i, j; /* we want to know max number of partitions assigned to a single thread -> mainly for memory allocation */ int *numsPerProc = (int *)calloc((size_t)pa->numProc, sizeof(int)), *numsPerPart = (int *)calloc((size_t)pa->numPartitions, sizeof(int)); for(i = 0; i< pa->numProc; ++i) { for(j = 0; j < pa->numAssignPerProc[i]; ++j) { Assignment *a = &pa->assignPerProc[i][j]; ++numsPerProc[i]; ++numsPerPart[a->partId]; } } int pmax = 0; for(i = 1; i< pa->numProc; ++i) { if (numsPerProc[i] > numsPerProc[pmax]) pmax = i; } /* save max partition count to the tree structure */ tr->maxModelsPerThread = numsPerProc[pmax]; assert(tr->maxModelsPerThread > 0 && tr->maxModelsPerThread <= pa->numPartitions); pmax = 0; for(i = 1; i< pa->numPartitions; ++i) { if (numsPerPart[i] > numsPerPart[pmax]) pmax = i; } /* save max threads count to the tree structure */ tr->maxThreadsPerModel = numsPerPart[pmax]; assert(tr->maxThreadsPerModel > 0 && tr->maxThreadsPerModel <= pa->numProc); free(numsPerProc); free(numsPerPart); printf("\n maxModelsPerThread: %d, maxThreadsPerModel: %d\n", tr->maxModelsPerThread, tr->maxThreadsPerModel); /* copy the partition assignment to the tree structure */ int threadPartSize = pa->numProc * tr->maxModelsPerThread, partThreadSize = pa->numPartitions * tr->maxThreadsPerModel; tr->threadPartAssigns = (Assign **)calloc((size_t)threadPartSize, sizeof(Assign*)); tr->partThreadAssigns = (Assign **)calloc((size_t)partThreadSize, sizeof(Assign*)); for(i = 0; i < pa->numProc; ++i) { int partCount = 0; for( j = 0 ; j < pa->numAssignPerProc[i]; ++j) { Assignment *ass = pa->assignPerProc[i] + j; Assign* pTreeAss = (Assign *)calloc(1, sizeof(Assign)); pTreeAss->procId = i; pTreeAss->offset = ass->offset; pTreeAss->width = ass->width; pTreeAss->partitionId = ass->partId; size_t ind = i * tr->maxModelsPerThread + partCount; assert(ind < (i+1) * tr->maxModelsPerThread); tr->threadPartAssigns[ind] = pTreeAss; ++partCount; ind = ass->partId * tr->maxThreadsPerModel; while (tr->partThreadAssigns[ind]) ++ind; assert( ind < (ass->partId+1) * tr->maxThreadsPerModel); tr->partThreadAssigns[ind] = pTreeAss; } } } #endif ExaML-3.0.21/examl/partitionAssignment.h000066400000000000000000000023471330315463200200720ustar00rootroot00000000000000#ifndef _PARTITIION_ASSIGNMENT #define _PARTITIION_ASSIGNMENT #include "axml.h" #define not ! typedef struct { int partId; size_t width; size_t offset; } Assignment; typedef struct { int id; size_t width; int type; } Partition; typedef struct { int numProc; int numPartitions; Partition *partitions; Assignment **assignPerProc; /* procid -> array of assignments */ int *numAssignPerProc; /* procid -> size of above array */ } PartitionAssignment; /* constructor */ void initializePartitionAssignment( PartitionAssignment **pAssPtr, pInfo **partitions, int numPart, int numProc); /* deletor */ void deletePartitionAssignment(PartitionAssignment *pAss); /* assign partitions to all proceses */ void assign(PartitionAssignment *pa); /* prints a single assignment */ void printAssignment(Assignment a, int procid); /* calculates and prints the load (number of partitions and number of sites) for each process */ void printLoad(PartitionAssignment *pa); void copyAssignmentInfoToTree(PartitionAssignment *pa, tree *tr); #ifdef _USE_OMP void copyThreadAssignmentInfoToTree(PartitionAssignment *pa, tree *tr); #endif void printAssignments(PartitionAssignment *pa); #endif ExaML-3.0.21/examl/quartets.c000066400000000000000000000417451330315463200157000ustar00rootroot00000000000000/* RAxML-HPC, a program for sequential and parallel estimation of phylogenetic trees * Copyright March 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * stamatak@ics.forth.gr * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis: "An Efficient Program for phylogenetic Inference Using Simulated Annealing". * Proceedings of IPDPS2005, Denver, Colorado, April 2005. * * AND * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #include #include #include #include #include #include #include #include #include #include #include #include "axml.h" extern double masterTime; extern char workdir[1024]; extern char run_id[128]; extern char quartetGroupingFileName[1024]; extern char quartetFileName[1024]; extern checkPointState ckp; extern int processID; /* a parser error function */ static void parseError(int c) { printBothOpen("Quartet grouping parser expecting symbol: %c\n", c); assert(0); } /* parser for the taxon grouping format, one has to specify 4 groups in a newick-like format from which quartets (a substantially smaller number compared to ungrouped quartets) will be drawn */ static void groupingParser(char *quartetGroupFileName, int *groups[4], int groupSize[4], tree *tr) { FILE *f = myfopen(quartetGroupFileName, "r"); int taxonCounter = 0, n, state = 0, groupCounter = 0, ch, i; printBothOpen("%s\n", quartetGroupFileName); for(i = 0; i < 4; i++) { groups[i] = (int*)malloc(sizeof(int) * (tr->mxtips + 1)); groupSize[i] = 0; } while((ch = getc(f)) != EOF) { if(!whitechar(ch)) { switch(state) { case 0: if(ch != '(') parseError('('); state = 1; break; case 1: ungetc(ch, f); n = treeFindTipName(f, tr, FALSE); if(n <= 0 || n > tr->mxtips) printBothOpen("parsing error, raxml is expecting to read a taxon name, found \"%c\" instead\n", ch); assert(n > 0 && n <= tr->mxtips); taxonCounter++; groups[groupCounter][groupSize[groupCounter]] = n; groupSize[groupCounter] = groupSize[groupCounter] + 1; state = 2; break; case 2: if(ch == ',') state = 1; else { if(ch == ')') { groupCounter++; state = 3; } else parseError('?'); } break; case 3: if(groupCounter == 4) { if(ch == ';') state = 4; else parseError(';'); } else { if(ch != ',') parseError(','); state = 0; } break; case 4: printBothOpen("Error: extra char after ; %c\n", ch); assert(0); default: assert(0); } } } assert(state == 4); assert(groupCounter == 4); assert(taxonCounter == tr->mxtips); printBothOpen("Successfully parsed quartet groups\n\n"); /* print out the taxa that have been assigned to the 4 groups */ for(i = 0; i < 4; i++) { int j; printBothOpen("group %d has %d members\n", i, groupSize[i]); for(j = 0; j < groupSize[i]; j++) printBothOpen("%s\n", tr->nameList[groups[i][j]]); printBothOpen("\n"); } fclose(f); } /*****************************/ static void nniSmooth(tree *tr, nodeptr p, int maxtimes) { int i; for(i = 0; i < tr->numBranches; i++) tr->partitionConverged[i] = FALSE; while (--maxtimes >= 0) { for(i = 0; i < tr->numBranches; i++) tr->partitionSmoothed[i] = TRUE; assert(!isTip(p->number, tr->mxtips)); assert(!isTip(p->back->number, tr->mxtips)); update(tr, p); update(tr, p->next); update(tr, p->next->next); update(tr, p->back->next); update(tr, p->back->next->next); if (allSmoothed(tr)) break; } for(i = 0; i < tr->numBranches; i++) { tr->partitionSmoothed[i] = FALSE; tr->partitionConverged[i] = FALSE; } } static double quartetLikelihood(tree *tr, nodeptr p1, nodeptr p2, nodeptr p3, nodeptr p4, nodeptr q1, nodeptr q2, analdef *adef, boolean firstQuartet) { /* build a quartet tree, where q1 and q2 are the inner nodes and p1, p2, p3, p4 are the tips of the quartet where the sequence data is located. initially set all branch lengths to the default value. */ /* for the tree and node data structure used, please see one of the last chapter's of Joe Felsensteins book. */ hookupDefault(q1, q2, tr->numBranches); hookupDefault(q1->next, p1, tr->numBranches); hookupDefault(q1->next->next, p2, tr->numBranches); hookupDefault(q2->next, p3, tr->numBranches); hookupDefault(q2->next->next, p4, tr->numBranches); /* now compute the likelihood vectors at the two inner nodes of the tree, here the virtual root is located between the two inner nodes q1 and q2. */ newviewGeneric(tr, q1, FALSE); newviewGeneric(tr, q2, FALSE); /* call a function that is also used for NNIs that iteratively optimizes all 5 branch lengths in the tree. Note that 16 is an important tuning parameter, this integer value determines how many times we visit all branches until we give up further optimizing the branch length configuration. */ nniSmooth(tr, q1, 16); /* now compute the log likelihood of the tree for the virtual root located between inner nodes q1 and q2 */ /* debugging code { double l; */ evaluateGeneric(tr, q1->back->next->next, FALSE); /* debugging code l = tr->likelihood; newviewGeneric(tr, q1); newviewGeneric(tr, q2); evaluateGeneric(tr, q1); assert(ABS(l - tr->likelihood) < 0.00001); } */ return (tr->likelihood); } static void computeAllThreeQuartets(tree *tr, nodeptr q1, nodeptr q2, int t1, int t2, int t3, int t4, FILE *f, analdef *adef) { /* set the tip nodes to different sequences with the tip indices t1, t2, t3, t4 */ nodeptr p1 = tr->nodep[t1], p2 = tr->nodep[t2], p3 = tr->nodep[t3], p4 = tr->nodep[t4]; double l; /* first quartet */ /* compute the likelihood of tree ((p1, p2), (p3, p4)) */ l = quartetLikelihood(tr, p1, p2, p3, p4, q1, q2, adef, TRUE); if(processID == 0) fprintf(f, "%d %d | %d %d: %f\n", p1->number, p2->number, p3->number, p4->number, l); /* second quartet */ /* compute the likelihood of tree ((p1, p3), (p2, p4)) */ l = quartetLikelihood(tr, p1, p3, p2, p4, q1, q2, adef, FALSE); if(processID == 0) fprintf(f, "%d %d | %d %d: %f\n", p1->number, p3->number, p2->number, p4->number, l); /* third quartet */ /* compute the likelihood of tree ((p1, p4), (p2, p3)) */ l = quartetLikelihood(tr, p1, p4, p2, p3, q1, q2, adef, FALSE); if(processID == 0) fprintf(f, "%d %d | %d %d: %f\n", p1->number, p4->number, p2->number, p3->number, l); } /* the three quartet options: all quartets, randomly sub-sample a certain number n of quartets, subsample all quartets from 4 pre-defined groups of quartets */ static void writeQuartetCheckpoint(uint64_t quartetCounter, FILE *f, tree *tr, analdef *adef) { if(quartetCounter % adef->quartetCkpInterval == 0) { ckp.quartetCounter = quartetCounter; if(processID == 0) { fflush(f); ckp.filePosition = ftell(f); } printBothOpen("\nPrinting checkpoint after %f seconds of run-time\n", gettime() - masterTime); writeCheckpoint(tr, adef); } } #define ALL_QUARTETS 0 #define RANDOM_QUARTETS 1 #define GROUPED_QUARTETS 2 void computeQuartets(tree *tr, analdef *adef) { /* some indices for generating quartets in an arbitrary way */ int flavor = ALL_QUARTETS, //type of quartet calculation i, t1, t2, t3, t4, *groups[4], groupSize[4]; double fraction = 0.0; uint64_t randomQuartets = (uint64_t)(adef->numberRandomQuartets), //number of random quartets to compute quartetCounter = 0, //total number of possible quartets, note that we count the following ((A,B),(C,D)), ((A,C),(B,D)), ((A,D),(B,C)) as one quartet here numberOfQuartets = ((uint64_t)tr->mxtips * ((uint64_t)tr->mxtips - 1) * ((uint64_t)tr->mxtips - 2) * ((uint64_t)tr->mxtips - 3)) / 24; /* use two inner tree nodes for building quartet trees */ nodeptr q1 = tr->nodep[tr->mxtips + 1], q2 = tr->nodep[tr->mxtips + 2]; FILE *f; long seed = (long)(tr->randomSeed); /***********************************/ /* get a starting tree on which we optimize the likelihood model parameters: either reads in a tree or computes a randomized stepwise addition parsimony tree */ if(adef->useCheckpoint) { /* read checkpoint file */ restart(tr, adef); strcpy(quartetFileName, workdir); strcat(quartetFileName, basename(ckp.quartetFileName)); printBothOpen("Time for reading checkpoint file: %f\n\n", gettime() - masterTime); seed = ckp.seed; if(processID == 0) { f = myfopen(quartetFileName, "r+"); fseek(f, ckp.filePosition, SEEK_SET); if(ftruncate(fileno(f), ckp.filePosition) != 0) assert(0); } } else { getStartingTree(tr); evaluateGeneric(tr, tr->start, TRUE); treeEvaluate(tr, 1); /* optimize model parameters on that comprehensive tree that can subsequently be used for evaluation of quartet likelihoods */ modOpt(tr, adef->likelihoodEpsilon, adef, 0); printBothOpen("Time for parsing input tree or building parsimony tree and optimizing model parameters: %f\n\n", gettime() - masterTime); printBothOpen("Tree likelihood: %f\n\n", tr->likelihood); if(processID == 0) f = myfopen(quartetFileName, "w"); } /* figure out which flavor of quartets we want to compute */ if(adef->useQuartetGrouping) { //quartet grouping evaluates all possible quartets from four disjoint //sets of user-specified taxon names flavor = GROUPED_QUARTETS; //parse the four disjoint sets of taxon names specified by the user from file groupingParser(quartetGroupingFileName, groups, groupSize, tr); } else { //if the user specified more random quartets to sample than there actually //exist for the number of taxa, then fix this. if(randomQuartets == 0 || randomQuartets >= numberOfQuartets) //TODO add usre warning? if second case above true? flavor = ALL_QUARTETS; else { //compute the fraction of random quartets to sample //there may be an issue here with the unit64_t <-> double cast fraction = (double)randomQuartets / (double)numberOfQuartets; assert(fraction < 1.0); flavor = RANDOM_QUARTETS; } } ckp.state = QUARTETS; ckp.seed = seed; strncpy(ckp.quartetFileName, quartetFileName, 1024); /* print some output on what we are doing*/ switch(flavor) { case ALL_QUARTETS: printBothOpen("There are %" PRIu64 " quartet sets for which RAxML will evaluate all %" PRIu64 " quartet trees\n", numberOfQuartets, numberOfQuartets * 3); break; case RANDOM_QUARTETS: printBothOpen("There are %" PRIu64 " quartet sets for which RAxML will randomly sub-sambple %" PRIu64 " sets (%f per cent), i.e., compute %" PRIu64 " quartet trees\n", numberOfQuartets, randomQuartets, 100 * fraction, randomQuartets * 3); break; case GROUPED_QUARTETS: printBothOpen("There are 4 quartet groups from which RAxML will evaluate all %u quartet trees\n", (unsigned int)groupSize[0] * (unsigned int)groupSize[1] * (unsigned int)groupSize[2] * (unsigned int)groupSize[3] * 3); break; default: assert(0); } /* print taxon name to taxon number correspondance table to output file */ if(!adef->useCheckpoint) { if(processID == 0) fprintf(f, "Taxon names and indices:\n\n"); for(i = 1; i <= tr->mxtips; i++) { if(processID == 0) fprintf(f, "%s %d\n", tr->nameList[i], i); assert(tr->nodep[i]->number == i); } if(processID == 0) { fprintf(f, "\n\n"); fflush(f); } } /* do a loop to generate some quartets to test. note that tip nodes/sequences in RAxML are indexed from 1,...,n and not from 0,...,n-1 as one might expect tr->mxtips is the maximum number of tips in the alignment/tree */ //now do the respective quartet evaluations by switching over the three distinct flavors switch(flavor) { case ALL_QUARTETS: { /* compute all possible quartets */ for(t1 = 1; t1 <= tr->mxtips; t1++) for(t2 = t1 + 1; t2 <= tr->mxtips; t2++) for(t3 = t2 + 1; t3 <= tr->mxtips; t3++) for(t4 = t3 + 1; t4 <= tr->mxtips; t4++) { if((adef->useCheckpoint && quartetCounter >= ckp.quartetCounter) || !adef->useCheckpoint) { writeQuartetCheckpoint(quartetCounter, f, tr, adef); computeAllThreeQuartets(tr, q1, q2, t1, t2, t3, t4, f, adef); } quartetCounter++; } assert(quartetCounter == numberOfQuartets); } break; case RANDOM_QUARTETS: { //endless loop ta make sure we randomly sub-sample exactly as many quartets as the user specified //This is not very elegant, but it works, note however, that especially when the number of //random quartets to be sampled is large, that is, close to the total number of quartets //some quartets may be sampled twice by pure chance. To randomly sample unique quartets //using hashes or bitmaps to store which quartets have already been sampled is not memory efficient. //Insetad, we need to use a random number generator that can generate a unique series of random numbers //and then have a function f() that maps those random numbers to the corresponding index quartet (t1, t2, t3, t4). do { //loop over all quartets for(t1 = 1; t1 <= tr->mxtips; t1++) for(t2 = t1 + 1; t2 <= tr->mxtips; t2++) for(t3 = t2 + 1; t3 <= tr->mxtips; t3++) for(t4 = t3 + 1; t4 <= tr->mxtips; t4++) { //chose a random number double r = randum(&seed); //if the random number is smaller than the fraction of quartets to subsample //evaluate the likelihood of the current quartet if(r < fraction) { if((adef->useCheckpoint && quartetCounter >= ckp.quartetCounter) || !adef->useCheckpoint) { writeQuartetCheckpoint(quartetCounter, f, tr, adef); //function that computes the likelihood for all three possible unrooted trees //defined by the given quartet of taxa computeAllThreeQuartets(tr, q1, q2, t1, t2, t3, t4, f, adef); } //increment quartet counter that counts how many quartets we have evaluated quartetCounter++; } //exit endless loop if we have randomly sub-sampled as many quartets as the user specified if(quartetCounter == randomQuartets) goto DONE; } } while(1); DONE: assert(quartetCounter == randomQuartets); } break; case GROUPED_QUARTETS: { /* compute all quartets that can be built out of the four pre-defined groups */ for(t1 = 0; t1 < groupSize[0]; t1++) for(t2 = 0; t2 < groupSize[1]; t2++) for(t3 = 0; t3 < groupSize[2]; t3++) for(t4 = 0; t4 < groupSize[3]; t4++) { int i1 = groups[0][t1], i2 = groups[1][t2], i3 = groups[2][t3], i4 = groups[3][t4]; if((adef->useCheckpoint && quartetCounter >= ckp.quartetCounter) || !adef->useCheckpoint) { writeQuartetCheckpoint(quartetCounter, f, tr, adef); computeAllThreeQuartets(tr, q1, q2, i1, i2, i3, i4, f, adef); } quartetCounter++; } printBothOpen("\nComputed all %" PRIu64 " possible grouped quartets\n", quartetCounter); } break; default: assert(0); } if(processID == 0) fclose(f); } ExaML-3.0.21/examl/restartHashTable.c000066400000000000000000000162461330315463200172660ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifndef WIN32 #include #include #include #include #endif #include #include #include #include #include #include #include "axml.h" static boolean treeNeedString(const char *fp, char c1, int *position) { char c2 = fp[(*position)++]; if(c2 == c1) return TRUE; else { int lower = MAX(0, *position - 20), upper = *position + 20; printf("Tree Parsing ERROR: Expecting '%c', found: '%c'\n", c1, c2); printf("Context: \n"); while(lower < upper && fp[lower]) printf("%c", fp[lower++]); printf("\n"); return FALSE; } } static boolean treeLabelEndString (char ch) { switch(ch) { case '\0': case '\t': case '\n': case '\r': case ' ': case ':': case ',': case '(': case ')': case ';': return TRUE; default: break; } return FALSE; } static boolean treeGetLabelString (const char *fp, char *lblPtr, int maxlen, int *position) { char ch; boolean done, lblfound; if (--maxlen < 0) lblPtr = (char *)NULL; else if(lblPtr == NULL) maxlen = 0; ch = fp[(*position)++]; done = treeLabelEndString(ch); lblfound = !done; while(!done) { if(treeLabelEndString(ch)) break; if(--maxlen >= 0) *lblPtr++ = ch; ch = fp[(*position)++]; } (*position)--; if (lblPtr != NULL) *lblPtr = '\0'; return lblfound; } static boolean treeFlushLabelString(const char *fp, int *position) { return treeGetLabelString(fp, (char *) NULL, (int) 0, position); } static boolean treeProcessLengthString (const char *fp, double *dptr, int *position) { (*position)++; if(sscanf(&fp[*position], "%lf", dptr) != 1) { printf("ERROR: treeProcessLength: Problem reading branch length\n"); assert(0); } while(fp[*position] != ',' && fp[*position] != ')' && fp[*position] != ';') *position = *position + 1; return TRUE; } static int treeFlushLenString (const char *fp, int *position) { double dummy; char ch; ch = fp[(*position)++]; if(ch == ':') { if(!treeProcessLengthString(fp, &dummy, position)) return 0; return 1; } (*position)--; return 1; } static int treeFindTipByLabelString(char *str, tree *tr) { int lookup = lookupWord(str, tr->nameHash); if(lookup > 0) { assert(! tr->nodep[lookup]->back); return lookup; } else { printf("ERROR: Cannot find tree species: %s\n", str); return 0; } } static int treeFindTipNameString (const char *fp, tree *tr, int *position) { char str[nmlngth+2]; int n; if(treeGetLabelString(fp, str, nmlngth+2, position)) n = treeFindTipByLabelString(str, tr); else n = 0; return n; } static boolean addElementLenString(const char *fp, tree *tr, nodeptr p, int *position) { nodeptr q; int n, fres; char ch; if ((ch = fp[(*position)++]) == '(') { n = (tr->nextnode)++; if (n > 2*(tr->mxtips) - 2) { if (tr->rooted || n > 2*(tr->mxtips) - 1) { printf("ERROR: Too many internal nodes. Is tree rooted?\n"); printf(" Deepest splitting should be a trifurcation.\n"); return FALSE; } else { tr->rooted = TRUE; } } q = tr->nodep[n]; if (!addElementLenString(fp, tr, q->next, position)) return FALSE; if (!treeNeedString(fp, ',', position)) return FALSE; if (!addElementLenString(fp, tr, q->next->next, position)) return FALSE; if (!treeNeedString(fp, ')', position)) return FALSE; treeFlushLabelString(fp, position); } else { (*position)--; if ((n = treeFindTipNameString(fp, tr, position)) <= 0) return FALSE; q = tr->nodep[n]; if (tr->start->number > n) tr->start = q; (tr->ntips)++; } fres = treeFlushLenString(fp, position); if(!fres) return FALSE; hookupDefault(p, q, tr->numBranches); return TRUE; } void treeReadTopologyString(char *treeString, tree *tr) { char *fp = treeString; nodeptr p; int position = 0, i; char ch; for(i = 1; i <= tr->mxtips; i++) tr->nodep[i]->back = (node *)NULL; for(i = tr->mxtips + 1; i < 2 * tr->mxtips; i++) { tr->nodep[i]->back = (nodeptr)NULL; tr->nodep[i]->next->back = (nodeptr)NULL; tr->nodep[i]->next->next->back = (nodeptr)NULL; tr->nodep[i]->number = i; tr->nodep[i]->next->number = i; tr->nodep[i]->next->next->number = i; } tr->start = tr->nodep[1]; tr->ntips = 0; tr->nextnode = tr->mxtips + 1; tr->rooted = FALSE; p = tr->nodep[(tr->nextnode)++]; assert(fp[position++] == '('); if (! addElementLenString(fp, tr, p, &position)) assert(0); if (! treeNeedString(fp, ',', &position)) assert(0); if (! addElementLenString(fp, tr, p->next, &position)) assert(0); if(!tr->rooted) { if ((ch = fp[position++]) == ',') { if (! addElementLenString(fp, tr, p->next->next, &position)) assert(0); } else assert(0); } else assert(0); if (! treeNeedString(fp, ')', &position)) assert(0); treeFlushLabelString(fp, &position); if (!treeFlushLenString(fp, &position)) assert(0); if (!treeNeedString(fp, ';', &position)) assert(0); if(tr->rooted) assert(0); else tr->start = tr->nodep[1]; printf("Tree parsed\n"); } ExaML-3.0.21/examl/searchAlgo.c000066400000000000000000002043511330315463200160720ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifndef WIN32 #include #include #include #include #endif #include #include #include #include #include #include #include "axml.h" extern int processes; extern int Thorough; extern int optimizeRateCategoryInvocations; extern infoList iList; extern char seq_file[1024]; extern char resultFileName[1024]; extern char tree_file[1024]; extern char workdir[1024]; extern char run_id[128]; extern double masterTime; extern double accumulatedTime; extern checkPointState ckp; extern partitionLengths pLengths[MAX_MODEL]; extern char binaryCheckpointName[1024]; extern char binaryCheckpointInputName[1024]; extern int processID; static int checker(tree *tr, nodeptr p) { int group = tr->constraintVector[p->number]; if(isTip(p->number, tr->mxtips)) { group = tr->constraintVector[p->number]; return group; } else { if(group != -9) return group; group = checker(tr, p->next->back); if(group != -9) return group; group = checker(tr, p->next->next->back); if(group != -9) return group; return -9; } } boolean initrav (tree *tr, nodeptr p) { nodeptr q; if (!isTip(p->number, tr->mxtips)) { q = p->next; do { if (! initrav(tr, q->back)) return FALSE; q = q->next; } while (q != p); newviewGeneric(tr, p, FALSE); } return TRUE; } /* #define _DEBUG_UPDATE */ boolean update(tree *tr, nodeptr p) { nodeptr q; boolean smoothedPartitions[NUM_BRANCHES]; int i; double z[NUM_BRANCHES], z0[NUM_BRANCHES]; double _deltaz; #ifdef _DEBUG_UPDATE double startLH; evaluateGeneric(tr, p, FALSE); startLH = tr->likelihood; #endif q = p->back; for(i = 0; i < tr->numBranches; i++) z0[i] = q->z[i]; if(tr->numBranches > 1) makenewzGeneric(tr, p, q, z0, newzpercycle, z, TRUE); else makenewzGeneric(tr, p, q, z0, newzpercycle, z, FALSE); for(i = 0; i < tr->numBranches; i++) smoothedPartitions[i] = tr->partitionSmoothed[i]; for(i = 0; i < tr->numBranches; i++) { if(!tr->partitionConverged[i]) { _deltaz = deltaz; if(ABS(z[i] - z0[i]) > _deltaz) { smoothedPartitions[i] = FALSE; } p->z[i] = q->z[i] = z[i]; } } #ifdef _DEBUG_UPDATE evaluateGeneric(tr, p, FALSE); if(tr->likelihood <= startLH) { if(fabs(tr->likelihood - startLH) > 0.01) { printf("%f %f\n", startLH, tr->likelihood); assert(0); } } #endif for(i = 0; i < tr->numBranches; i++) tr->partitionSmoothed[i] = smoothedPartitions[i]; return TRUE; } boolean smooth (tree *tr, nodeptr p) { nodeptr q; if (! update(tr, p)) return FALSE; /* Adjust branch */ if (! isTip(p->number, tr->mxtips)) { /* Adjust descendants */ q = p->next; while (q != p) { if (! smooth(tr, q->back)) return FALSE; q = q->next; } if(tr->numBranches > 1) newviewGeneric(tr, p, TRUE); else newviewGeneric(tr, p, FALSE); } return TRUE; } boolean allSmoothed(tree *tr) { int i; boolean result = TRUE; for(i = 0; i < tr->numBranches; i++) { if(tr->partitionSmoothed[i] == FALSE) result = FALSE; else tr->partitionConverged[i] = TRUE; } return result; } boolean smoothTree (tree *tr, int maxtimes) { nodeptr p, q; int i, count = 0; p = tr->start; for(i = 0; i < tr->numBranches; i++) tr->partitionConverged[i] = FALSE; while (--maxtimes >= 0) { for(i = 0; i < tr->numBranches; i++) tr->partitionSmoothed[i] = TRUE; if (! smooth(tr, p->back)) return FALSE; if (!isTip(p->number, tr->mxtips)) { q = p->next; while (q != p) { if (! smooth(tr, q->back)) return FALSE; q = q->next; } } count++; if (allSmoothed(tr)) break; } for(i = 0; i < tr->numBranches; i++) tr->partitionConverged[i] = FALSE; return TRUE; } boolean localSmooth (tree *tr, nodeptr p, int maxtimes) { nodeptr q; int i; if (isTip(p->number, tr->mxtips)) return FALSE; for(i = 0; i < tr->numBranches; i++) tr->partitionConverged[i] = FALSE; while (--maxtimes >= 0) { for(i = 0; i < tr->numBranches; i++) tr->partitionSmoothed[i] = TRUE; q = p; do { if (! update(tr, q)) return FALSE; q = q->next; } while (q != p); if (allSmoothed(tr)) break; } for(i = 0; i < tr->numBranches; i++) { tr->partitionSmoothed[i] = FALSE; tr->partitionConverged[i] = FALSE; } return TRUE; } static void resetInfoList(void) { int i; iList.valid = 0; for(i = 0; i < iList.n; i++) { iList.list[i].node = (nodeptr)NULL; iList.list[i].likelihood = unlikely; } } void initInfoList(int n) { int i; iList.n = n; iList.valid = 0; iList.list = (bestInfo *)malloc(sizeof(bestInfo) * n); for(i = 0; i < n; i++) { iList.list[i].node = (nodeptr)NULL; iList.list[i].likelihood = unlikely; } } void freeInfoList(void) { free(iList.list); } void insertInfoList(nodeptr node, double likelihood) { int i; int min = 0; double min_l = iList.list[0].likelihood; for(i = 1; i < iList.n; i++) { if(iList.list[i].likelihood < min_l) { min = i; min_l = iList.list[i].likelihood; } } if(likelihood > min_l) { iList.list[min].likelihood = likelihood; iList.list[min].node = node; iList.valid += 1; } if(iList.valid > iList.n) iList.valid = iList.n; } boolean smoothRegion (tree *tr, nodeptr p, int region) { nodeptr q; if (! update(tr, p)) return FALSE; /* Adjust branch */ if(region > 0) { if (!isTip(p->number, tr->mxtips)) { q = p->next; while (q != p) { if (! smoothRegion(tr, q->back, --region)) return FALSE; q = q->next; } newviewGeneric(tr, p, FALSE); } } return TRUE; } boolean regionalSmooth (tree *tr, nodeptr p, int maxtimes, int region) { nodeptr q; int i; if (isTip(p->number, tr->mxtips)) return FALSE; /* Should be an error */ for(i = 0; i < tr->numBranches; i++) tr->partitionConverged[i] = FALSE; while (--maxtimes >= 0) { for(i = 0; i < tr->numBranches; i++) tr->partitionSmoothed[i] = TRUE; q = p; do { if (! smoothRegion(tr, q, region)) return FALSE; q = q->next; } while (q != p); if (allSmoothed(tr)) break; } for(i = 0; i < tr->numBranches; i++) tr->partitionSmoothed[i] = FALSE; for(i = 0; i < tr->numBranches; i++) tr->partitionConverged[i] = FALSE; return TRUE; } /* localSmooth */ nodeptr removeNodeBIG (tree *tr, nodeptr p, int numBranches) { double zqr[NUM_BRANCHES], result[NUM_BRANCHES]; nodeptr q, r; int i; q = p->next->back; r = p->next->next->back; for(i = 0; i < numBranches; i++) zqr[i] = q->z[i] * r->z[i]; makenewzGeneric(tr, q, r, zqr, iterations, result, FALSE); for(i = 0; i < numBranches; i++) tr->zqr[i] = result[i]; hookup(q, r, result, numBranches); p->next->next->back = p->next->back = (node *) NULL; return q; } nodeptr removeNodeRestoreBIG (tree *tr, nodeptr p) { nodeptr q, r; q = p->next->back; r = p->next->next->back; newviewGeneric(tr, q, FALSE); newviewGeneric(tr, r, FALSE); hookup(q, r, tr->currentZQR, tr->numBranches); p->next->next->back = p->next->back = (node *) NULL; return q; } boolean insertBIG (tree *tr, nodeptr p, nodeptr q, int numBranches) { nodeptr r, s; int i; r = q->back; s = p->back; for(i = 0; i < numBranches; i++) tr->lzi[i] = q->z[i]; if(Thorough) { double zqr[NUM_BRANCHES], zqs[NUM_BRANCHES], zrs[NUM_BRANCHES], lzqr, lzqs, lzrs, lzsum, lzq, lzr, lzs, lzmax; double defaultArray[NUM_BRANCHES]; double e1[NUM_BRANCHES], e2[NUM_BRANCHES], e3[NUM_BRANCHES]; double *qz; qz = q->z; for(i = 0; i < numBranches; i++) defaultArray[i] = defaultz; makenewzGeneric(tr, q, r, qz, iterations, zqr, FALSE); makenewzGeneric(tr, q, s, defaultArray, iterations, zqs, FALSE); makenewzGeneric(tr, r, s, defaultArray, iterations, zrs, FALSE); for(i = 0; i < numBranches; i++) { lzqr = (zqr[i] > zmin) ? log(zqr[i]) : log(zmin); lzqs = (zqs[i] > zmin) ? log(zqs[i]) : log(zmin); lzrs = (zrs[i] > zmin) ? log(zrs[i]) : log(zmin); lzsum = 0.5 * (lzqr + lzqs + lzrs); lzq = lzsum - lzrs; lzr = lzsum - lzqs; lzs = lzsum - lzqr; lzmax = log(zmax); if (lzq > lzmax) {lzq = lzmax; lzr = lzqr; lzs = lzqs;} else if (lzr > lzmax) {lzr = lzmax; lzq = lzqr; lzs = lzrs;} else if (lzs > lzmax) {lzs = lzmax; lzq = lzqs; lzr = lzrs;} e1[i] = exp(lzq); e2[i] = exp(lzr); e3[i] = exp(lzs); } hookup(p->next, q, e1, numBranches); hookup(p->next->next, r, e2, numBranches); hookup(p, s, e3, numBranches); } else { double z[NUM_BRANCHES]; for(i = 0; i < numBranches; i++) { z[i] = sqrt(q->z[i]); if(z[i] < zmin) z[i] = zmin; if(z[i] > zmax) z[i] = zmax; } hookup(p->next, q, z, tr->numBranches); hookup(p->next->next, r, z, tr->numBranches); } newviewGeneric(tr, p, FALSE); if(Thorough) { localSmooth(tr, p, smoothings); for(i = 0; i < numBranches; i++) { tr->lzq[i] = p->next->z[i]; tr->lzr[i] = p->next->next->z[i]; tr->lzs[i] = p->z[i]; } } return TRUE; } boolean insertRestoreBIG (tree *tr, nodeptr p, nodeptr q) { nodeptr r, s; r = q->back; s = p->back; if(Thorough) { hookup(p->next, q, tr->currentLZQ, tr->numBranches); hookup(p->next->next, r, tr->currentLZR, tr->numBranches); hookup(p, s, tr->currentLZS, tr->numBranches); } else { double z[NUM_BRANCHES]; int i; for(i = 0; i < tr->numBranches; i++) { double zz; zz = sqrt(q->z[i]); if(zz < zmin) zz = zmin; if(zz > zmax) zz = zmax; z[i] = zz; } hookup(p->next, q, z, tr->numBranches); hookup(p->next->next, r, z, tr->numBranches); } newviewGeneric(tr, p, FALSE); return TRUE; } static void restoreTopologyOnly(tree *tr, bestlist *bt, bestlist *bestML) { nodeptr p = tr->removeNode; nodeptr q = tr->insertNode; double qz[NUM_BRANCHES], pz[NUM_BRANCHES], p1z[NUM_BRANCHES], p2z[NUM_BRANCHES]; nodeptr p1, p2, r, s; double currentLH = tr->likelihood; int i; p1 = p->next->back; p2 = p->next->next->back; for(i = 0; i < tr->numBranches; i++) { p1z[i] = p1->z[i]; p2z[i] = p2->z[i]; } hookup(p1, p2, tr->currentZQR, tr->numBranches); p->next->next->back = p->next->back = (node *) NULL; for(i = 0; i < tr->numBranches; i++) { qz[i] = q->z[i]; pz[i] = p->z[i]; } r = q->back; s = p->back; if(Thorough) { hookup(p->next, q, tr->currentLZQ, tr->numBranches); hookup(p->next->next, r, tr->currentLZR, tr->numBranches); hookup(p, s, tr->currentLZS, tr->numBranches); } else { double z[NUM_BRANCHES]; for(i = 0; i < tr->numBranches; i++) { z[i] = sqrt(q->z[i]); if(z[i] < zmin) z[i] = zmin; if(z[i] > zmax) z[i] = zmax; } hookup(p->next, q, z, tr->numBranches); hookup(p->next->next, r, z, tr->numBranches); } tr->likelihood = tr->bestOfNode; saveBestTree(bt, tr, TRUE); if(tr->saveBestTrees) saveBestTree(bestML, tr, FALSE); tr->likelihood = currentLH; hookup(q, r, qz, tr->numBranches); p->next->next->back = p->next->back = (nodeptr) NULL; if(Thorough) hookup(p, s, pz, tr->numBranches); hookup(p->next, p1, p1z, tr->numBranches); hookup(p->next->next, p2, p2z, tr->numBranches); } boolean testInsertBIG (tree *tr, nodeptr p, nodeptr q) { double qz[NUM_BRANCHES], pz[NUM_BRANCHES]; nodeptr r; boolean doIt = TRUE; double startLH = tr->endLH; int i; r = q->back; for(i = 0; i < tr->numBranches; i++) { qz[i] = q->z[i]; pz[i] = p->z[i]; } if(tr->constraintTree) { int rNumber, qNumber, pNumber; doIt = FALSE; rNumber = tr->constraintVector[r->number]; qNumber = tr->constraintVector[q->number]; pNumber = tr->constraintVector[p->number]; if(pNumber == -9) pNumber = checker(tr, p->back); if(pNumber == -9) doIt = TRUE; else { if(qNumber == -9) qNumber = checker(tr, q); if(rNumber == -9) rNumber = checker(tr, r); if(pNumber == rNumber || pNumber == qNumber) doIt = TRUE; } } if(doIt) { if (! insertBIG(tr, p, q, tr->numBranches)) return FALSE; evaluateGeneric(tr, p->next->next, FALSE); if(tr->likelihood > tr->bestOfNode) { tr->bestOfNode = tr->likelihood; tr->insertNode = q; tr->removeNode = p; for(i = 0; i < tr->numBranches; i++) { tr->currentZQR[i] = tr->zqr[i]; tr->currentLZR[i] = tr->lzr[i]; tr->currentLZQ[i] = tr->lzq[i]; tr->currentLZS[i] = tr->lzs[i]; } } if(tr->likelihood > tr->endLH) { tr->insertNode = q; tr->removeNode = p; for(i = 0; i < tr->numBranches; i++) tr->currentZQR[i] = tr->zqr[i]; tr->endLH = tr->likelihood; } hookup(q, r, qz, tr->numBranches); p->next->next->back = p->next->back = (nodeptr) NULL; if(Thorough) { nodeptr s = p->back; hookup(p, s, pz, tr->numBranches); } if((tr->doCutoff) && (tr->likelihood < startLH)) { tr->lhAVG += (startLH - tr->likelihood); tr->lhDEC++; if((startLH - tr->likelihood) >= tr->lhCutoff) return FALSE; else return TRUE; } else return TRUE; } else return TRUE; } void addTraverseBIG(tree *tr, nodeptr p, nodeptr q, int mintrav, int maxtrav) { if (--mintrav <= 0) { if (! testInsertBIG(tr, p, q)) return; } if ((!isTip(q->number, tr->mxtips)) && (--maxtrav > 0)) { addTraverseBIG(tr, p, q->next->back, mintrav, maxtrav); addTraverseBIG(tr, p, q->next->next->back, mintrav, maxtrav); } } int rearrangeBIG(tree *tr, nodeptr p, int mintrav, int maxtrav) { double p1z[NUM_BRANCHES], p2z[NUM_BRANCHES], q1z[NUM_BRANCHES], q2z[NUM_BRANCHES]; nodeptr p1, p2, q, q1, q2; int mintrav2, i; boolean doP = TRUE, doQ = TRUE; if (maxtrav < 1 || mintrav > maxtrav) return 0; q = p->back; if (!isTip(p->number, tr->mxtips) && doP) { p1 = p->next->back; p2 = p->next->next->back; if(!isTip(p1->number, tr->mxtips) || !isTip(p2->number, tr->mxtips)) { for(i = 0; i < tr->numBranches; i++) { p1z[i] = p1->z[i]; p2z[i] = p2->z[i]; } if (! removeNodeBIG(tr, p, tr->numBranches)) return badRear; if (!isTip(p1->number, tr->mxtips)) { addTraverseBIG(tr, p, p1->next->back, mintrav, maxtrav); addTraverseBIG(tr, p, p1->next->next->back, mintrav, maxtrav); } if (!isTip(p2->number, tr->mxtips)) { addTraverseBIG(tr, p, p2->next->back, mintrav, maxtrav); addTraverseBIG(tr, p, p2->next->next->back, mintrav, maxtrav); } hookup(p->next, p1, p1z, tr->numBranches); hookup(p->next->next, p2, p2z, tr->numBranches); newviewGeneric(tr, p, FALSE); } } if (!isTip(q->number, tr->mxtips) && maxtrav > 0 && doQ) { q1 = q->next->back; q2 = q->next->next->back; /*if (((!q1->tip) && (!q1->next->back->tip || !q1->next->next->back->tip)) || ((!q2->tip) && (!q2->next->back->tip || !q2->next->next->back->tip))) */ if ( ( ! isTip(q1->number, tr->mxtips) && (! isTip(q1->next->back->number, tr->mxtips) || ! isTip(q1->next->next->back->number, tr->mxtips)) ) || ( ! isTip(q2->number, tr->mxtips) && (! isTip(q2->next->back->number, tr->mxtips) || ! isTip(q2->next->next->back->number, tr->mxtips)) ) ) { for(i = 0; i < tr->numBranches; i++) { q1z[i] = q1->z[i]; q2z[i] = q2->z[i]; } if (! removeNodeBIG(tr, q, tr->numBranches)) return badRear; mintrav2 = mintrav > 2 ? mintrav : 2; if (/*! q1->tip*/ !isTip(q1->number, tr->mxtips)) { addTraverseBIG(tr, q, q1->next->back, mintrav2 , maxtrav); addTraverseBIG(tr, q, q1->next->next->back, mintrav2 , maxtrav); } if (/*! q2->tip*/ ! isTip(q2->number, tr->mxtips)) { addTraverseBIG(tr, q, q2->next->back, mintrav2 , maxtrav); addTraverseBIG(tr, q, q2->next->next->back, mintrav2 , maxtrav); } hookup(q->next, q1, q1z, tr->numBranches); hookup(q->next->next, q2, q2z, tr->numBranches); newviewGeneric(tr, q, FALSE); } } return 1; } double treeOptimizeRapid(tree *tr, int mintrav, int maxtrav, analdef *adef, bestlist *bt, bestlist *bestML) { int i, index, *perm = (int*)NULL; nodeRectifier(tr); if (maxtrav > tr->mxtips - 3) maxtrav = tr->mxtips - 3; resetInfoList(); resetBestTree(bt); tr->startLH = tr->endLH = tr->likelihood; if(tr->doCutoff) { if(tr->bigCutoff) { if(tr->itCount == 0) tr->lhCutoff = 0.5 * (tr->likelihood / -1000.0); else tr->lhCutoff = 0.5 * ((tr->lhAVG) / ((double)(tr->lhDEC))); } else { if(tr->itCount == 0) tr->lhCutoff = tr->likelihood / -1000.0; else tr->lhCutoff = (tr->lhAVG) / ((double)(tr->lhDEC)); } tr->itCount = tr->itCount + 1; tr->lhAVG = 0; tr->lhDEC = 0; } /* printf("DoCutoff: %d\n", tr->doCutoff); printf("%d %f %f %f\n", tr->itCount, tr->lhAVG, tr->lhDEC, tr->lhCutoff); printf("%d %d\n", mintrav, maxtrav); */ for(i = 1; i <= tr->mxtips + tr->mxtips - 2; i++) { tr->bestOfNode = unlikely; if(adef->permuteTreeoptimize) index = perm[i]; else index = i; if(rearrangeBIG(tr, tr->nodep[index], mintrav, maxtrav)) { if(Thorough) { if(tr->endLH > tr->startLH) { restoreTreeFast(tr); tr->startLH = tr->endLH = tr->likelihood; saveBestTree(bt, tr, TRUE); if(tr->saveBestTrees) saveBestTree(bestML, tr, FALSE); } else { if(tr->bestOfNode != unlikely) restoreTopologyOnly(tr, bt, bestML); } } else { insertInfoList(tr->nodep[index], tr->bestOfNode); if(tr->endLH > tr->startLH) { restoreTreeFast(tr); tr->startLH = tr->endLH = tr->likelihood; } } } } if(!Thorough) { Thorough = 1; for(i = 0; i < iList.valid; i++) { tr->bestOfNode = unlikely; if(rearrangeBIG(tr, iList.list[i].node, mintrav, maxtrav)) { if(tr->endLH > tr->startLH) { restoreTreeFast(tr); tr->startLH = tr->endLH = tr->likelihood; saveBestTree(bt, tr, TRUE); if(tr->saveBestTrees) saveBestTree(bestML, tr, FALSE); } else { if(tr->bestOfNode != unlikely) { restoreTopologyOnly(tr, bt, bestML); } } } } Thorough = 0; } if(adef->permuteTreeoptimize) free(perm); return tr->startLH; } boolean testInsertRestoreBIG (tree *tr, nodeptr p, nodeptr q) { if(Thorough) { if (! insertBIG(tr, p, q, tr->numBranches)) return FALSE; evaluateGeneric(tr, p->next->next, FALSE); } else { if (! insertRestoreBIG(tr, p, q)) return FALSE; { nodeptr x, y; x = p->next->next; y = p->back; if(! isTip(x->number, tr->mxtips) && isTip(y->number, tr->mxtips)) { while ((! x->x)) { if (! (x->x)) newviewGeneric(tr, x, FALSE); } } if(isTip(x->number, tr->mxtips) && !isTip(y->number, tr->mxtips)) { while ((! y->x)) { if (! (y->x)) newviewGeneric(tr, y, FALSE); } } if(!isTip(x->number, tr->mxtips) && !isTip(y->number, tr->mxtips)) { while ((! x->x) || (! y->x)) { if (! (x->x)) newviewGeneric(tr, x, FALSE); if (! (y->x)) newviewGeneric(tr, y, FALSE); } } } tr->likelihood = tr->endLH; } return TRUE; } void restoreTreeFast(tree *tr) { removeNodeRestoreBIG(tr, tr->removeNode); testInsertRestoreBIG(tr, tr->removeNode, tr->insertNode); } static void writeTree(tree *tr, FILE *f) { int x = tr->mxtips + 3 * (tr->mxtips - 1); nodeptr base = tr->nodeBaseAddress; myBinFwrite(&(tr->start->number), sizeof(int), 1, f); myBinFwrite(&base, sizeof(nodeptr), 1, f); myBinFwrite(tr->nodeBaseAddress, sizeof(node), x, f); } int ckpCount = 0; /** gathers patrat and rateCategory */ static void gatherDistributedCatInfos(tree *tr, int **rateCategory_result, double **patrat_result) { /* countPerProc and displPerProc must be int, since the MPI functino signatures demand so */ int *countPerProc = (int*)NULL, *displPerProc = (int*)NULL; calculateLengthAndDisplPerProcess(tr, &countPerProc, &displPerProc); if(processID == 0) { *rateCategory_result = (int*)calloc((size_t)tr->originalCrunchedLength , sizeof(int)); *patrat_result = (double*)calloc((size_t)tr->originalCrunchedLength, sizeof(double)); } gatherDistributedArray(tr, (void**) patrat_result, tr->patrat_basePtr, MPI_DOUBLE , countPerProc, displPerProc); gatherDistributedArray(tr, (void**) rateCategory_result, tr->rateCategory_basePtr, MPI_INT, countPerProc, displPerProc ); free(countPerProc); free(displPerProc); } /** added parameters patrat and rateCategory. The checkpoint writer has to gather this distributed information first. */ static void writeCheckpointInner(tree *tr, int *rateCategory, double *patrat, analdef *adef) { int model; char extendedName[2048], buf[64]; FILE *f; /* only master should write the checkpoint */ assert(processID == 0); strcpy(extendedName, binaryCheckpointName); strcat(extendedName, "_"); sprintf(buf, "%d", ckpCount); strcat(extendedName, buf); ckpCount++; f = myfopen(extendedName, "w"); ckp.cmd.useMedian = tr->useMedian; ckp.cmd.saveBestTrees = tr->saveBestTrees; ckp.cmd.saveMemory = tr->saveMemory; ckp.cmd.searchConvergenceCriterion = tr->searchConvergenceCriterion; ckp.cmd.perGeneBranchLengths = adef->perGeneBranchLengths; //adef ckp.cmd.likelihoodEpsilon = adef->likelihoodEpsilon; //adef ckp.cmd.categories = tr->categories; ckp.cmd.mode = adef->mode; //adef ckp.cmd.fastTreeEvaluation = tr->fastTreeEvaluation; ckp.cmd.initialSet = adef->initialSet;//adef ckp.cmd.initial = adef->initial;//adef ckp.cmd.rateHetModel = tr->rateHetModel; ckp.cmd.autoProteinSelectionType = tr->autoProteinSelectionType; ckp.cmd.useQuartetGrouping = adef->useQuartetGrouping; ckp.cmd.numberRandomQuartets = adef->numberRandomQuartets; /* cdta */ ckp.accumulatedTime = accumulatedTime + (gettime() - masterTime); ckp.constraintTree = tr->constraintTree; /* printf("Acc time: %f\n", ckp.accumulatedTime); */ myBinFwrite(&ckp, sizeof(checkPointState), 1, f); if(tr->constraintTree) myBinFwrite(tr->constraintVector, sizeof(int), 2 * tr->mxtips, f); myBinFwrite(tr->tree0, sizeof(char), tr->treeStringLength, f); myBinFwrite(tr->tree1, sizeof(char), tr->treeStringLength, f); if(tr->rateHetModel == CAT) { myBinFwrite(rateCategory, sizeof(int), tr->originalCrunchedLength, f); myBinFwrite(patrat, sizeof(double), tr->originalCrunchedLength, f); } //end for(model = 0; model < tr->NumberOfModels; model++) { int dataType = tr->partitionData[model].dataType; myBinFwrite(&(tr->partitionData[model].numberOfCategories), sizeof(int), 1, f); myBinFwrite(tr->partitionData[model].perSiteRates, sizeof(double), tr->maxCategories, f); myBinFwrite(tr->partitionData[model].EIGN, sizeof(double), pLengths[dataType].eignLength, f); myBinFwrite(tr->partitionData[model].EV, sizeof(double), pLengths[dataType].evLength, f); myBinFwrite(tr->partitionData[model].EI, sizeof(double), pLengths[dataType].eiLength, f); myBinFwrite(tr->partitionData[model].freqExponents, sizeof(double), pLengths[dataType].frequenciesLength, f); myBinFwrite(tr->partitionData[model].frequencies, sizeof(double), pLengths[dataType].frequenciesLength, f); myBinFwrite(tr->partitionData[model].tipVector, sizeof(double), pLengths[dataType].tipVectorLength, f); myBinFwrite(tr->partitionData[model].substRates, sizeof(double), pLengths[dataType].substRatesLength, f); //LG4X related variables myBinFwrite(tr->partitionData[model].weights , sizeof(double), 4, f); myBinFwrite(tr->partitionData[model].weightExponents , sizeof(double), 4, f); //myBinFwrite(tr->partitionData[model].weightsBuffer , sizeof(double), 4, f); //myBinFwrite(tr->partitionData[model].weightExponentsBuffer , sizeof(double), 4, f); //LG4X end if(tr->partitionData[model].protModels == LG4M || tr->partitionData[model].protModels == LG4X) { int k; for(k = 0; k < 4; k++) { myBinFwrite(tr->partitionData[model].rawEIGN_LG4[k], sizeof(double), pLengths[dataType].eignLength, f); myBinFwrite(tr->partitionData[model].EIGN_LG4[k], sizeof(double), pLengths[dataType].eignLength, f); myBinFwrite(tr->partitionData[model].EV_LG4[k], sizeof(double), pLengths[dataType].evLength, f); myBinFwrite(tr->partitionData[model].EI_LG4[k], sizeof(double), pLengths[dataType].eiLength, f); myBinFwrite(tr->partitionData[model].frequencies_LG4[k], sizeof(double), pLengths[dataType].frequenciesLength, f); myBinFwrite(tr->partitionData[model].tipVector_LG4[k], sizeof(double), pLengths[dataType].tipVectorLength, f); myBinFwrite(tr->partitionData[model].substRates_LG4[k], sizeof(double), pLengths[dataType].substRatesLength, f); } } myBinFwrite(&(tr->partitionData[model].alpha), sizeof(double), 1, f); myBinFwrite(&(tr->partitionData[model].gammaRates), sizeof(double), 4, f); myBinFwrite(&(tr->partitionData[model].protModels), sizeof(int), 1, f); myBinFwrite(&(tr->partitionData[model].autoProtModels), sizeof(int), 1, f); } if(ckp.state == MOD_OPT) { myBinFwrite(tr->likelihoods, sizeof(double), tr->numberOfTrees, f); myBinFwrite(tr->treeStrings, sizeof(char), (size_t)tr->treeStringLength * (size_t)tr->numberOfTrees, f); } writeTree(tr, f); fclose(f); /* printBothOpen("\nCheckpoint written to: %s likelihood: %f\n", extendedName, tr->likelihood); */ } void writeCheckpoint(tree *tr, analdef *adef) { int *rateCategory = (int *)NULL; double *patrat = (double *)NULL; if(tr->rateHetModel == CAT) gatherDistributedCatInfos(tr, &rateCategory, &patrat); if(processID == 0) { writeCheckpointInner(tr, rateCategory, patrat, adef); if(tr->rateHetModel == CAT) { free(rateCategory); free(patrat); } } } static void readTree(tree *tr, FILE *f) { int nodeNumber, x = tr->mxtips + 3 * (tr->mxtips - 1); nodeptr startAddress; myBinFread(&nodeNumber, sizeof(int), 1, f); tr->start = tr->nodep[nodeNumber]; /*printf("Start: %d %d\n", tr->start->number, nodeNumber);*/ myBinFread(&startAddress, sizeof(nodeptr), 1, f); /*printf("%u %u\n", (size_t)startAddress, (size_t)tr->nodeBaseAddress);*/ myBinFread(tr->nodeBaseAddress, sizeof(node), x, f); { int i; size_t offset; boolean addIt; if(startAddress > tr->nodeBaseAddress) { addIt = FALSE; offset = (size_t)startAddress - (size_t)tr->nodeBaseAddress; } else { addIt = TRUE; offset = (size_t)tr->nodeBaseAddress - (size_t)startAddress; } for(i = 0; i < x; i++) { if(addIt) { tr->nodeBaseAddress[i].next = (nodeptr)((size_t)tr->nodeBaseAddress[i].next + offset); tr->nodeBaseAddress[i].back = (nodeptr)((size_t)tr->nodeBaseAddress[i].back + offset); } else { tr->nodeBaseAddress[i].next = (nodeptr)((size_t)tr->nodeBaseAddress[i].next - offset); tr->nodeBaseAddress[i].back = (nodeptr)((size_t)tr->nodeBaseAddress[i].back - offset); } } } evaluateGeneric(tr, tr->start, TRUE); if(ckp.state != QUARTETS) printBothOpen("ExaML Restart with likelihood: %1.50f\n", tr->likelihood); } static void genericError(void) { printBothOpen("\nError: command lines used in initial run and re-start from checkpoint do not match!\n"); } static void checkCommandLineArguments(tree *tr, analdef *adef) { boolean match = TRUE; if(ckp.cmd.useMedian != tr->useMedian) { genericError(); printBothOpen("\nDisagreement in median for gamma option: -a\n"); match = FALSE; } if(ckp.cmd.saveBestTrees != tr->saveBestTrees) { genericError(); printBothOpen("\nDisagreement in tree saving option: -B\n"); match = FALSE; } if(ckp.cmd.saveMemory != tr->saveMemory) { genericError(); printBothOpen("\nDisagreement in memory saving option: -S\n"); match = FALSE; } if(ckp.cmd.searchConvergenceCriterion != tr->searchConvergenceCriterion) { genericError(); printBothOpen("\nDisagreement in search convergence criterion: -D\n"); match = FALSE; } if(ckp.cmd.perGeneBranchLengths != adef->perGeneBranchLengths) { genericError(); printBothOpen("\nDisagreement in using per-partition branch lengths: -M\n"); match = FALSE; } if(ckp.cmd.likelihoodEpsilon != adef->likelihoodEpsilon) { genericError(); printBothOpen("\nDisagreement in likelihood epsilon value: -e\n"); match = FALSE; } if(ckp.cmd.categories != tr->categories) { genericError(); printBothOpen("\nDisagreement in number of PSR rate categories: -c\n"); match = FALSE; } if(ckp.cmd.mode != adef->mode) { genericError(); printBothOpen("\nDisagreement in tree search or evaluation mode\n"); match = FALSE; } if(ckp.cmd.fastTreeEvaluation != tr->fastTreeEvaluation) { genericError(); printBothOpen("\nDisagreement in fast tree evaluation: -e|-E\n"); match = FALSE; } if(ckp.cmd.initialSet != adef->initialSet) { genericError(); printBothOpen("\nDisagreement in rearrangement radius limitation setting: -i\n"); match = FALSE; } if(ckp.cmd.initial != adef->initial) { genericError(); printBothOpen("\nDisagreement in rearrangement radius value: -i\n"); match = FALSE; } if(ckp.cmd.rateHetModel != tr->rateHetModel) { genericError(); printBothOpen("\nDisagreement in rate heterogeneity model: -m\n"); match = FALSE; } if(ckp.cmd.autoProteinSelectionType != tr->autoProteinSelectionType) { genericError(); printBothOpen("\nDisagreement in protein model selection criterion: --auto-prot\n"); match = FALSE; } if(ckp.cmd.useQuartetGrouping != adef->useQuartetGrouping) { genericError(); printBothOpen("\nDisagreement in quartet grouping option: -Y\n"); match = FALSE; } if(ckp.cmd.numberRandomQuartets != adef->numberRandomQuartets) { genericError(); printBothOpen("\nDisagreement in number of random quartet subsamples: -r\n"); match = FALSE; } if(!match) { printBothOpen("\nExaML will exit now ...\n\n"); errorExit(-1); } } static void readCheckpoint(tree *tr, analdef *adef) { int model; FILE *f = myfopen(binaryCheckpointInputName, "rb"); /* cdta */ myBinFread(&ckp, sizeof(checkPointState), 1, f); checkCommandLineArguments(tr, adef); tr->constraintTree = ckp.constraintTree; if(tr->constraintTree) myBinFread(tr->constraintVector, sizeof(int), 2 * tr->mxtips, f); tr->ntips = tr->mxtips; tr->startLH = ckp.tr_startLH; tr->endLH = ckp.tr_endLH; tr->likelihood = ckp.tr_likelihood; tr->bestOfNode = ckp.tr_bestOfNode; tr->lhCutoff = ckp.tr_lhCutoff; tr->lhAVG = ckp.tr_lhAVG; tr->lhDEC = ckp.tr_lhDEC; tr->itCount = ckp.tr_itCount; Thorough = ckp.Thorough; accumulatedTime = ckp.accumulatedTime; /* printf("Accumulated time so far: %f\n", accumulatedTime); */ optimizeRateCategoryInvocations = ckp.optimizeRateCategoryInvocations; myBinFread(tr->tree0, sizeof(char), tr->treeStringLength, f); myBinFread(tr->tree1, sizeof(char), tr->treeStringLength, f); if(tr->searchConvergenceCriterion && processID == 0) { int bCounter = 0; if((ckp.state == FAST_SPRS && ckp.fastIterations > 0) || (ckp.state == SLOW_SPRS && ckp.thoroughIterations > 0)) { #ifdef _DEBUG_CHECKPOINTING printf("parsing Tree 0\n"); #endif treeReadTopologyString(tr->tree0, tr); bitVectorInitravSpecial(tr->bitVectors, tr->nodep[1]->back, tr->mxtips, tr->vLength, tr->h, 0, BIPARTITIONS_RF, (branchInfo *)NULL, &bCounter, 1, FALSE, FALSE); assert(bCounter == tr->mxtips - 3); } bCounter = 0; if((ckp.state == FAST_SPRS && ckp.fastIterations > 1) || (ckp.state == SLOW_SPRS && ckp.thoroughIterations > 1)) { #ifdef _DEBUG_CHECKPOINTING printf("parsing Tree 1\n"); #endif treeReadTopologyString(tr->tree1, tr); bitVectorInitravSpecial(tr->bitVectors, tr->nodep[1]->back, tr->mxtips, tr->vLength, tr->h, 1, BIPARTITIONS_RF, (branchInfo *)NULL, &bCounter, 1, FALSE, FALSE); assert(bCounter == tr->mxtips - 3); } } if(tr->rateHetModel == CAT ) { /* every process reads its data */ /* Andre will this also work if we re-start with a different number of processors? have you tested? => Andre: yes that works: before writing the checkpoint, we gather all lhs/patrat with gatherDistributedCatInfos. This function calls gatherDisributedArray in communication.c. gatherDistributedArray takes care of reordering the data it obtained from the various processes, such the correct global array (i.e., indexing consistent with character position) is obtained. Thus, the indexing below (for reading in the patrat/lhs again) works correctly. */ /* Andre I think tr->originalCrunchedLength is of type size_t??? -> casting required ? Andre: in the very worst case, pPos overflows. There is not much one can do here. See explanation about fseek/fseeko at other location. But I have added an assert, in case something goes wrong */ exa_off_t rPos = exa_ftell(f), pPos = rPos + sizeof(int) * tr->originalCrunchedLength; /* fails, in case reading failed (ftello returns -1) or an overflow happened */ assert( ! ( rPos < 0 || pPos < 0 ) && rPos <= pPos ) ; /* first patrat then rateCategory */ Assign *aIter = tr->partAssigns, *aEnd = &(tr->partAssigns [ tr->numAssignments ]) ; /* Andre coould you maybe add a drawing (scanned drawn by hand if you like) documenting this layout ? => Andre: TODO */ while(aIter != aEnd) { if(aIter->procId == processID) { pInfo *partition = &(tr->partitionData[aIter->partitionId]); exa_off_t theOffset = pPos + (partition->lower + aIter->offset) * sizeof(double); assert(pPos <= theOffset); exa_fseek(f, theOffset, SEEK_SET); myBinFread(partition->patrat, sizeof(double), aIter->width, f); theOffset = rPos + (partition->lower + aIter->offset) * sizeof(int); assert(rPos <= theOffset); exa_fseek(f, theOffset, SEEK_SET); myBinFread(partition->rateCategory, sizeof(int), aIter->width, f); } ++aIter; } /* Set file pointer to the end of both of the arrays */ exa_fseek(f, pPos + tr->originalCrunchedLength * sizeof(double) , SEEK_SET); } //end for(model = 0; model < tr->NumberOfModels; model++) { int dataType = tr->partitionData[model].dataType; myBinFread(&(tr->partitionData[model].numberOfCategories), sizeof(int), 1, f); myBinFread(tr->partitionData[model].perSiteRates, sizeof(double), tr->maxCategories, f); myBinFread(tr->partitionData[model].EIGN, sizeof(double), pLengths[dataType].eignLength, f); myBinFread(tr->partitionData[model].EV, sizeof(double), pLengths[dataType].evLength, f); myBinFread(tr->partitionData[model].EI, sizeof(double), pLengths[dataType].eiLength, f); myBinFread(tr->partitionData[model].freqExponents, sizeof(double), pLengths[dataType].frequenciesLength, f); myBinFread(tr->partitionData[model].frequencies, sizeof(double), pLengths[dataType].frequenciesLength, f); myBinFread(tr->partitionData[model].tipVector, sizeof(double), pLengths[dataType].tipVectorLength, f); myBinFread(tr->partitionData[model].substRates, sizeof(double), pLengths[dataType].substRatesLength, f); //LG4X related variables myBinFread(tr->partitionData[model].weights , sizeof(double), 4, f); myBinFread(tr->partitionData[model].weightExponents , sizeof(double), 4, f); //myBinFread(tr->partitionData[model].weightsBuffer , sizeof(double), 4, f); //myBinFread(tr->partitionData[model].weightExponentsBuffer , sizeof(double), 4, f); //LG4X end if(tr->partitionData[model].protModels == LG4X || tr->partitionData[model].protModels == LG4M) { int k; for(k = 0; k < 4; k++) { myBinFread(tr->partitionData[model].rawEIGN_LG4[k], sizeof(double), pLengths[dataType].eignLength, f); myBinFread(tr->partitionData[model].EIGN_LG4[k], sizeof(double), pLengths[dataType].eignLength, f); myBinFread(tr->partitionData[model].EV_LG4[k], sizeof(double), pLengths[dataType].evLength, f); myBinFread(tr->partitionData[model].EI_LG4[k], sizeof(double), pLengths[dataType].eiLength, f); myBinFread(tr->partitionData[model].frequencies_LG4[k], sizeof(double), pLengths[dataType].frequenciesLength, f); myBinFread(tr->partitionData[model].tipVector_LG4[k], sizeof(double), pLengths[dataType].tipVectorLength, f); myBinFread(tr->partitionData[model].substRates_LG4[k], sizeof(double), pLengths[dataType].substRatesLength, f); } } myBinFread(&(tr->partitionData[model].alpha), sizeof(double), 1, f); myBinFread(&(tr->partitionData[model].gammaRates), sizeof(double), 4, f); //conditional added by Andre modified by me //only overwrite values of discrete gamma cats by calling makeGammaCats if not using //LG4X! if(tr->rateHetModel != CAT && !(tr->partitionData[model].protModels == LG4X)) makeGammaCats(tr->partitionData[model].alpha, tr->partitionData[model].gammaRates, 4, tr->useMedian); myBinFread(&(tr->partitionData[model].protModels), sizeof(int), 1, f); myBinFread(&(tr->partitionData[model].autoProtModels), sizeof(int), 1, f); } if(ckp.state == MOD_OPT) { myBinFread(tr->likelihoods, sizeof(double), tr->numberOfTrees, f); myBinFread(tr->treeStrings, sizeof(char), (size_t)tr->treeStringLength * (size_t)tr->numberOfTrees, f); } if(tr->rateHetModel == CAT) checkPerSiteRates(tr); readTree(tr, f); fclose(f); } void restart(tree *tr, analdef *adef) { readCheckpoint(tr, adef); switch(ckp.state) { case REARR_SETTING: assert(adef->mode == BIG_RAPID_MODE); break; case FAST_SPRS: assert(adef->mode == BIG_RAPID_MODE); break; case SLOW_SPRS: assert(adef->mode == BIG_RAPID_MODE); break; case MOD_OPT: assert(adef->mode == TREE_EVALUATION); break; case QUARTETS: assert(adef->mode == QUARTET_CALCULATION); break; default: assert(0); } } int determineRearrangementSetting(tree *tr, analdef *adef, bestlist *bestT, bestlist *bt, bestlist *bestML) { const int MaxFast = 26; int i, maxtrav = 5, bestTrav = 5; double startLH = tr->likelihood; boolean impr = TRUE, cutoff = tr->doCutoff; if(adef->useCheckpoint) { assert(ckp.state == REARR_SETTING); maxtrav = ckp.maxtrav; bestTrav = ckp.bestTrav; startLH = ckp.startLH; impr = ckp.impr; cutoff = ckp.cutoff; adef->useCheckpoint = FALSE; } tr->doCutoff = FALSE; resetBestTree(bt); #ifdef _DEBUG_CHECKPOINTING printBothOpen("MAXTRAV: %d\n", maxtrav); #endif assert(Thorough == 0); while(impr && maxtrav < MaxFast) { recallBestTree(bestT, 1, tr); nodeRectifier(tr); /* Andre I believe that the code below, except for writeCheckpoint cann still only be executed by process 0 => Andre: all other processes need to enter writeCheckpoint, because of the gather that happens there. But the assignments to the checkpoint state are not necessary for all processes; does it matter? */ { ckp.optimizeRateCategoryInvocations = optimizeRateCategoryInvocations; ckp.cutoff = cutoff; ckp.state = REARR_SETTING; ckp.maxtrav = maxtrav; ckp.bestTrav = bestTrav; ckp.startLH = startLH; ckp.impr = impr; ckp.tr_startLH = tr->startLH; ckp.tr_endLH = tr->endLH; ckp.tr_likelihood = tr->likelihood; ckp.tr_bestOfNode = tr->bestOfNode; ckp.tr_lhCutoff = tr->lhCutoff; ckp.tr_lhAVG = tr->lhAVG; ckp.tr_lhDEC = tr->lhDEC; ckp.tr_itCount = tr->itCount; writeCheckpoint(tr, adef); } if (maxtrav > tr->mxtips - 3) maxtrav = tr->mxtips - 3; tr->startLH = tr->endLH = tr->likelihood; /* printBothOpen("TRAV: %d lh %f MNZC %d\n", maxtrav, tr->likelihood, mnzc); */ { int changes = 0; for(i = 1; i <= tr->mxtips + tr->mxtips - 2; i++) { tr->bestOfNode = unlikely; if(rearrangeBIG(tr, tr->nodep[i], 1, maxtrav)) { if(tr->endLH > tr->startLH) { restoreTreeFast(tr); tr->startLH = tr->endLH = tr->likelihood; changes++; } } } /* evaluateGeneric(tr, tr->start, TRUE); printBothOpen("Changes: %d TRAV: %d lh %f MNZC %d\n", changes, maxtrav, tr->likelihood, mnzc); */ } treeEvaluate(tr, 0.25); /* printBothOpen("TRAV: %d lh %f MNZC %d\n", maxtrav, tr->likelihood, mnzc); */ saveBestTree(bt, tr, TRUE); if(tr->saveBestTrees) saveBestTree(bestML, tr, FALSE); #ifdef _DEBUG_CHECKPOINTING printBothOpen("TRAV: %d lh %f MNZC %d\n", maxtrav, tr->likelihood, mnzc); #endif if(tr->likelihood > startLH) { startLH = tr->likelihood; printLog(tr); bestTrav = maxtrav; impr = TRUE; } else impr = FALSE; if(tr->doCutoff) { tr->lhCutoff = (tr->lhAVG) / ((double)(tr->lhDEC)); tr->itCount = tr->itCount + 1; tr->lhAVG = 0; tr->lhDEC = 0; } maxtrav += 5; } recallBestTree(bt, 1, tr); tr->doCutoff = cutoff; #ifdef _DEBUG_CHECKPOINTING printBothOpen("BestTrav %d\n", bestTrav); #endif return bestTrav; } void computeBIGRAPID (tree *tr, analdef *adef, boolean estimateModel) { int i, impr, bestTrav = 0, treeVectorLength = 0, rearrangementsMax = 0, rearrangementsMin = 0, thoroughIterations = 0, fastIterations = 0; double lh = unlikely, previousLh = unlikely, difference, epsilon; bestlist *bestML, *bestT, *bt; /* now here is the RAxML hill climbing search algorithm */ tr->lhAVG = 0.0; tr->lhDEC = 0.0; /* initialization for the hash table to compute RF distances */ if(tr->searchConvergenceCriterion && processID == 0) treeVectorLength = 1; /* initialize two lists of size 1 and size 20 that will keep track of the best and 20 best tree topologies respectively */ bestT = (bestlist *) malloc(sizeof(bestlist)); bestT->ninit = 0; initBestTree(bestT, 1, tr->mxtips); bt = (bestlist *) malloc(sizeof(bestlist)); bt->ninit = 0; initBestTree(bt, 20, tr->mxtips); if(tr->saveBestTrees > 0) { bestML = (bestlist *) malloc(sizeof(bestlist)); bestML->ninit = 0; initBestTree(bestML, tr->saveBestTrees, tr->mxtips); } else bestML = (bestlist *)NULL; /* initialize an additional data structure used by the search algo, all of this is pretty RAxML-specific and should probably not be in the library */ initInfoList(50); /* some pretty atbitrary thresholds */ difference = 10.0; epsilon = 0.01; /* Thorough = 0 means that we will do fast SPR inbsertions without optimizing the three branches adjacent to the subtree insertion position via Newton-Raphson */ Thorough = 0; /* if we are not using a checkpoint and estimateModel is set to TRUE we call the function that optimizes model parameters, such as the CAT model assignment, the alpha paremeter or the rates in the GTR matrix. Otherwise we just optimize the branch lengths. Note that the second parameter of treeEvaluate() controls how many times we will iterate over all branches of the tree until we give up, provided that, the br-len opt. has not converged before. */ if(!adef->useCheckpoint) { if(estimateModel) modOpt(tr, 10.0, adef, 0); else treeEvaluate(tr, 2); } /* print some stuff to the RAxML_log file */ printLog(tr); /* save the current tree (which is the input tree parsed via -t in the bestT list */ saveBestTree(bestT, tr, TRUE); /* if the rearrangmenet radius has been set by the user ie. adef->initailSet == TRUE then just set the apppropriate parameter. Otherwise, call the function determineRearrangementSetting() that seeks for the best radius by executing SPR moves on the initial tree with different radii and returns the smallest radius that yields the best log likelihood score after applying one cycle of SPR moves to the tree */ if(!adef->initialSet) { if((!adef->useCheckpoint) || (adef->useCheckpoint && ckp.state == REARR_SETTING)) { bestTrav = adef->bestTrav = determineRearrangementSetting(tr, adef, bestT, bt, bestML); printBothOpen("\nBest rearrangement radius: %d\n", bestTrav); } } else { bestTrav = adef->bestTrav = adef->initial; printBothOpen("\nUser-defined rearrangement radius: %d\n", bestTrav); } /* some checkpointing noise */ if(!(adef->useCheckpoint && (ckp.state == FAST_SPRS || ckp.state == SLOW_SPRS))) { /* optimize model params more thoroughly or just optimize branch lengths */ if(estimateModel) modOpt(tr, 5.0, adef, 0); else treeEvaluate(tr, 1); } /* save the current tree again, while the topology has not changed, the branch lengths have changed in the meantime, hence we need to store them again */ saveBestTree(bestT, tr, TRUE); /* set the loop variable to TRUE */ impr = 1; /* this is for the additional RAxML heuristics described imn this paper here: A. Stamatakis, F. Blagojevic, C.D. Antonopoulos, D.S. Nikolopoulos: "Exploring new Search Algorithms and Hardware for Phylogenetics: RAxML meets the IBM Cell". In Journal of VLSI Signal Processing Systems, 48(3):271-286, 2007. This is turned on by default */ if(tr->doCutoff) tr->itCount = 0; /* figure out where to continue computations if we restarted from a checkpoint */ if(adef->useCheckpoint && ckp.state == FAST_SPRS) goto START_FAST_SPRS; if(adef->useCheckpoint && ckp.state == SLOW_SPRS) goto START_SLOW_SPRS; while(impr) { START_FAST_SPRS: /* if re-starting from checkpoint set the required variable values to the values that they had when the checkpoint was written */ if(adef->useCheckpoint && ckp.state == FAST_SPRS) { optimizeRateCategoryInvocations = ckp.optimizeRateCategoryInvocations; impr = ckp.impr; Thorough = ckp.Thorough; bestTrav = ckp.bestTrav; treeVectorLength = ckp.treeVectorLength; rearrangementsMax = ckp.rearrangementsMax; rearrangementsMin = ckp.rearrangementsMin; thoroughIterations = ckp.thoroughIterations; fastIterations = ckp.fastIterations; lh = ckp.lh; previousLh = ckp.previousLh; difference = ckp.difference; epsilon = ckp.epsilon; tr->likelihood = ckp.tr_likelihood; tr->lhCutoff = ckp.tr_lhCutoff; tr->lhAVG = ckp.tr_lhAVG; tr->lhDEC = ckp.tr_lhDEC; tr->itCount = ckp.tr_itCount; adef->useCheckpoint = FALSE; } else /* otherwise, restore the currently best tree */ recallBestTree(bestT, 1, tr); /* save states of algorithmic/heuristic variables for printing the next checkpoint */ /* Andre I believe that the code below, except for writeCheckpoint cann still only be executed by process 0 => Andre: see above */ { ckp.state = FAST_SPRS; ckp.optimizeRateCategoryInvocations = optimizeRateCategoryInvocations; ckp.impr = impr; ckp.Thorough = Thorough; ckp.bestTrav = bestTrav; ckp.treeVectorLength = treeVectorLength; ckp.rearrangementsMax = rearrangementsMax; ckp.rearrangementsMin = rearrangementsMin; ckp.thoroughIterations = thoroughIterations; ckp.fastIterations = fastIterations; ckp.lh = lh; ckp.previousLh = previousLh; ckp.difference = difference; ckp.epsilon = epsilon; ckp.bestTrav = bestTrav; ckp.impr = impr; ckp.tr_startLH = tr->startLH; ckp.tr_endLH = tr->endLH; ckp.tr_likelihood = tr->likelihood; ckp.tr_bestOfNode = tr->bestOfNode; ckp.tr_lhCutoff = tr->lhCutoff; ckp.tr_lhAVG = tr->lhAVG; ckp.tr_lhDEC = tr->lhDEC; ckp.tr_itCount = tr->itCount; /* write a binary checkpoint */ writeCheckpoint(tr, adef); } /* this is the aforementioned convergence criterion that requires computing the RF, let's not worry about this right now */ if(tr->searchConvergenceCriterion && processID == 0) { int bCounter = 0; char *buffer = (char*)calloc(tr->treeStringLength, sizeof(char)); if(fastIterations > 1) cleanupHashTable(tr->h, (fastIterations % 2)); bitVectorInitravSpecial(tr->bitVectors, tr->nodep[1]->back, tr->mxtips, tr->vLength, tr->h, fastIterations % 2, BIPARTITIONS_RF, (branchInfo *)NULL, &bCounter, 1, FALSE, FALSE); #ifdef _DEBUG_CHECKPOINTING printf("Storing tree in slot %d\n", fastIterations % 2); #endif Tree2String(buffer, tr, tr->start->back, FALSE, TRUE, FALSE, FALSE, FALSE, SUMMARIZE_LH, FALSE, FALSE); if(fastIterations % 2 == 0) memcpy(tr->tree0, buffer, tr->treeStringLength * sizeof(char)); else memcpy(tr->tree1, buffer, tr->treeStringLength * sizeof(char)); free(buffer); assert(bCounter == tr->mxtips - 3); if(fastIterations > 0) { double rrf = convergenceCriterion(tr->h, tr->mxtips); MPI_Bcast(&rrf, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); if(rrf <= 0.01) /* 1% cutoff */ { printBothOpen("ML fast search converged at fast SPR cycle %d with stopping criterion\n", fastIterations); printBothOpen("Relative Robinson-Foulds (RF) distance between respective best trees after one succseful SPR cycle: %f%s\n", rrf, "%"); cleanupHashTable(tr->h, 0); cleanupHashTable(tr->h, 1); goto cleanup_fast; } else printBothOpen("ML search convergence criterion fast cycle %d->%d Relative Robinson-Foulds %f\n", fastIterations - 1, fastIterations, rrf); } } if(tr->searchConvergenceCriterion && processID != 0 && fastIterations > 0) { double rrf; MPI_Bcast(&rrf, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); if(rrf <= 0.01) /* 1% cutoff */ goto cleanup_fast; } /* count how many fast iterations with so-called fast SPR moves we have executed */ fastIterations++; /* optimize branch lengths */ treeEvaluate(tr, 1.0); /* save the tree with those branch lengths again */ saveBestTree(bestT, tr, TRUE); /* print the log likelihood */ printLog(tr); /* print this intermediate tree to file */ printResult(tr, adef, FALSE); /* update the current best likelihood */ lh = previousLh = tr->likelihood; /* in here we actually do a cycle of SPR moves */ treeOptimizeRapid(tr, 1, bestTrav, adef, bt, bestML); /* set impr to 0 since in the immediately following for loop we check if the SPR moves above have generated a better tree */ impr = 0; /* loop over the 20 best trees generated by the fast SPR moves, and check if they improve the likelihood after all of their branch lengths have been optimized */ for(i = 1; i <= bt->nvalid; i++) { /* restore tree i from list generated by treeOptimizeRapid */ recallBestTree(bt, i, tr); /* optimize branch lengths of this tree */ treeEvaluate(tr, 0.25); /* calc. the likelihood improvement */ difference = ((tr->likelihood > previousLh)? tr->likelihood - previousLh: previousLh - tr->likelihood); /* if the likelihood has improved save the current tree as best tree and continue */ /* note that we always compre this tree to the likelihood of the previous best tree */ if(tr->likelihood > lh && difference > epsilon) { impr = 1; lh = tr->likelihood; saveBestTree(bestT, tr, TRUE); } } #ifdef _DEBUG_CHECKPOINTING printBothOpen("FAST LH: %f\n", lh); #endif } /* needed for this RF-based convergence criterion that I actually describe in here: A. Stamatakis: "Phylogenetic Search Algorithms for Maximum Likelihood". In M. Elloumi, A.Y. Zomaya, editors. Algorithms in Computational Biology: techniques, Approaches and Applications, John Wiley and Sons a copy of this book is in my office */ if(tr->searchConvergenceCriterion && processID == 0) { cleanupHashTable(tr->h, 0); cleanupHashTable(tr->h, 1); } cleanup_fast: /* now we have jumped out of the loop that executes fast SPRs, and next we will execute a loop that executes throough SPR cycles (with SPR moves that optimize via newton-Raphson all adjacent branches to the insertion point) until no through SPR move can be found that improves the likelihood further. A classic hill climbing algo. */ Thorough = 1; impr = 1; /* restore the currently best tree. this si actually required, because we do not know which tree is actually stored in the tree data structure when the above loop exits */ recallBestTree(bestT, 1, tr); /* RE-TRAVERSE THE ENTIRE TREE */ evaluateGeneric(tr, tr->start, TRUE); #ifdef _DEBUG_CHECKPOINTING printBothOpen("After Fast SPRs Final %f\n", tr->likelihood); #endif /* optimize model params (including branch lengths) or just optimize branch lengths and leave the other model parameters (GTR rates, alhpa) alone */ if(estimateModel) modOpt(tr, 1.0, adef, 0); else treeEvaluate(tr, 1.0); /* start loop that executes thorough SPR cycles */ while(1) { /* once again if we want to restart from a checkpoint that was written during this loop we need to restore the values of the variables appropriately */ START_SLOW_SPRS: if(adef->useCheckpoint && ckp.state == SLOW_SPRS) { optimizeRateCategoryInvocations = ckp.optimizeRateCategoryInvocations; impr = ckp.impr; Thorough = ckp.Thorough; bestTrav = ckp.bestTrav; treeVectorLength = ckp.treeVectorLength; rearrangementsMax = ckp.rearrangementsMax; rearrangementsMin = ckp.rearrangementsMin; thoroughIterations = ckp.thoroughIterations; fastIterations = ckp.fastIterations; lh = ckp.lh; previousLh = ckp.previousLh; difference = ckp.difference; epsilon = ckp.epsilon; tr->likelihood = ckp.tr_likelihood; tr->lhCutoff = ckp.tr_lhCutoff; tr->lhAVG = ckp.tr_lhAVG; tr->lhDEC = ckp.tr_lhDEC; tr->itCount = ckp.tr_itCount; adef->useCheckpoint = FALSE; } else /* otherwise we restore the currently best tree and load it from bestT into our tree data structuire tr */ recallBestTree(bestT, 1, tr); /* now, we write a checkpoint */ /* Andre I believe that the code below, except for writeCheckpoint cann still only be executed by process 0 => Andre: see above */ { ckp.state = SLOW_SPRS; ckp.optimizeRateCategoryInvocations = optimizeRateCategoryInvocations; ckp.impr = impr; ckp.Thorough = Thorough; ckp.bestTrav = bestTrav; ckp.treeVectorLength = treeVectorLength; ckp.rearrangementsMax = rearrangementsMax; ckp.rearrangementsMin = rearrangementsMin; ckp.thoroughIterations = thoroughIterations; ckp.fastIterations = fastIterations; ckp.lh = lh; ckp.previousLh = previousLh; ckp.difference = difference; ckp.epsilon = epsilon; ckp.bestTrav = bestTrav; ckp.impr = impr; ckp.tr_startLH = tr->startLH; ckp.tr_endLH = tr->endLH; ckp.tr_likelihood = tr->likelihood; ckp.tr_bestOfNode = tr->bestOfNode; ckp.tr_lhCutoff = tr->lhCutoff; ckp.tr_lhAVG = tr->lhAVG; ckp.tr_lhDEC = tr->lhDEC; ckp.tr_itCount = tr->itCount; /* write binary checkpoint to file */ writeCheckpoint(tr, adef); } if(impr) { /* if the logl has improved write out some stuff and adapt the rearrangement radii */ printResult(tr, adef, FALSE); /* minimum rearrangement radius */ rearrangementsMin = 1; /* max radius, this is probably something I need to explain at the whiteboard */ rearrangementsMax = adef->stepwidth; /* once again the convergence criterion */ if(tr->searchConvergenceCriterion && processID == 0) { int bCounter = 0; char *buffer = (char*)calloc(tr->treeStringLength, sizeof(char)); if(thoroughIterations > 1) cleanupHashTable(tr->h, (thoroughIterations % 2)); bitVectorInitravSpecial(tr->bitVectors, tr->nodep[1]->back, tr->mxtips, tr->vLength, tr->h, thoroughIterations % 2, BIPARTITIONS_RF, (branchInfo *)NULL, &bCounter, 1, FALSE, FALSE); #ifdef _DEBUG_CHECKPOINTING printf("Storing tree in slot %d\n", thoroughIterations % 2); #endif Tree2String(buffer, tr, tr->start->back, FALSE, TRUE, FALSE, FALSE, FALSE, SUMMARIZE_LH, FALSE, FALSE); if(thoroughIterations % 2 == 0) memcpy(tr->tree0, buffer, tr->treeStringLength * sizeof(char)); else memcpy(tr->tree1, buffer, tr->treeStringLength * sizeof(char)); free(buffer); assert(bCounter == tr->mxtips - 3); if(thoroughIterations > 0) { double rrf = convergenceCriterion(tr->h, tr->mxtips); MPI_Bcast(&rrf, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); if(rrf <= 0.01) /* 1% cutoff */ { printBothOpen("ML search converged at thorough SPR cycle %d with stopping criterion\n", thoroughIterations); printBothOpen("Relative Robinson-Foulds (RF) distance between respective best trees after one succseful SPR cycle: %f%s\n", rrf, "%"); goto cleanup; } else printBothOpen("ML search convergence criterion thorough cycle %d->%d Relative Robinson-Foulds %f\n", thoroughIterations - 1, thoroughIterations, rrf); } } if(tr->searchConvergenceCriterion && processID != 0 && thoroughIterations > 0) { double rrf; MPI_Bcast(&rrf, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); if(rrf <= 0.01) /* 1% cutoff */ goto cleanup; } thoroughIterations++; } else { /* if the lnl has not imrpved by the current SPR cycle adapt the min and max rearrangemnt radii and try again */ rearrangementsMax += adef->stepwidth; rearrangementsMin += adef->stepwidth; /* if we have already tried them then abandon this loop, the search has converged */ if(rearrangementsMax > adef->max_rearrange) goto cleanup; } /* optimize branch lengths of best tree */ treeEvaluate(tr, 1.0); /* do some bokkeeping and printouts again */ previousLh = lh = tr->likelihood; saveBestTree(bestT, tr, TRUE); printLog(tr); /* do a cycle of thorough SPR moves with the minimum and maximum rearrangement radii */ treeOptimizeRapid(tr, rearrangementsMin, rearrangementsMax, adef, bt, bestML); impr = 0; /* once again get the best 20 trees produced by the SPR cycle, load them from the bt tree list into tr optimize their branch lengths and figure out if the LnL of the tree has improved */ for(i = 1; i <= bt->nvalid; i++) { recallBestTree(bt, i, tr); treeEvaluate(tr, 0.25); difference = ((tr->likelihood > previousLh)? tr->likelihood - previousLh: previousLh - tr->likelihood); if(tr->likelihood > lh && difference > epsilon) { impr = 1; lh = tr->likelihood; saveBestTree(bestT, tr, TRUE); } } #ifdef _DEBUG_CHECKPOINTING printBothOpen("SLOW LH: %f\n", lh); #endif } cleanup: /* do a final full tree traversal, not sure if this is required here */ evaluateGeneric(tr, tr->start, TRUE); #ifdef _DEBUG_CHECKPOINTING printBothOpen("After SLOW SPRs Final %f\n", tr->likelihood); #endif printBothOpen("\nLikelihood of best tree: %f\n", tr->likelihood); /* print the absolut best tree */ printLog(tr); printResult(tr, adef, TRUE); /* print other good trees encountered during the search */ if(tr->saveBestTrees > 0) { char fileName[2048] = "", buf[64] = ""; printBothOpen("\n\nEvaluating %d other good ML trees\n\n", bestML->nvalid); for(i = 1; i <= bestML->nvalid; i++) { recallBestTree(bestML, i, tr); /*treeEvaluate(tr, 0.25);*/ printBothOpen("tree %d likelihood %1.80f\n", i, tr->likelihood); if(processID == 0) { FILE *treeFile; strcpy(fileName, workdir); strcat(fileName, "RAxML_"); sprintf(buf, "%d", bestML->nvalid); strcat(fileName, buf); strcat(fileName, "_goodTrees."); strcat(fileName, run_id); treeFile = myfopen(fileName, "a"); Tree2String(tr->tree_string, tr, tr->start->back, TRUE, TRUE, FALSE, FALSE, TRUE, SUMMARIZE_LH, FALSE, FALSE); fprintf(treeFile, "%s", tr->tree_string); fclose(treeFile); } } printBothOpen("\n\nOther good trees written to file %s\n", fileName); } /* free data structures */ if(tr->searchConvergenceCriterion && processID == 0) { freeBitVectors(tr->bitVectors, 2 * tr->mxtips); free(tr->bitVectors); freeHashTable(tr->h); free(tr->h); } freeBestTree(bestT); free(bestT); freeBestTree(bt); free(bt); freeInfoList(); /* and we are done, return to main() in axml.c */ } boolean treeEvaluate (tree *tr, double smoothFactor) /* Evaluate a user tree */ { boolean result; result = smoothTree(tr, (int)((double)smoothings * smoothFactor)); assert(result); //make sure that all vectors are oriented correctly ! evaluateGeneric(tr, tr->start, TRUE); return TRUE; } ExaML-3.0.21/examl/topologies.c000066400000000000000000000357721330315463200162170ustar00rootroot00000000000000 /* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifndef WIN32 #include #include #include #include #endif #include #include #include #include #include #include #include "axml.h" static void saveTopolRELLRec(tree *tr, nodeptr p, topolRELL *tpl, int *i, int numsp, int numBranches) { int k; if(isTip(p->number, numsp)) return; else { nodeptr q = p->next; while(q != p) { tpl->connect[*i].p = q; tpl->connect[*i].q = q->back; if(tr->constraintTree) { tpl->connect[*i].cp = tr->constraintVector[q->number]; tpl->connect[*i].cq = tr->constraintVector[q->back->number]; } for(k = 0; k < numBranches; k++) tpl->connect[*i].z[k] = q->z[k]; *i = *i + 1; saveTopolRELLRec(tr, q->back, tpl, i, numsp, numBranches); q = q->next; } } } static void saveTopolRELL(tree *tr, topolRELL *tpl) { nodeptr p = tr->start; int k, i = 0; tpl->likelihood = tr->likelihood; tpl->start = 1; tpl->connect[i].p = p; tpl->connect[i].q = p->back; if(tr->constraintTree) { tpl->connect[i].cp = tr->constraintVector[p->number]; tpl->connect[i].cq = tr->constraintVector[p->back->number]; } for(k = 0; k < tr->numBranches; k++) tpl->connect[i].z[k] = p->z[k]; i++; saveTopolRELLRec(tr, p->back, tpl, &i, tr->mxtips, tr->numBranches); assert(i == 2 * tr->mxtips - 3); } static void restoreTopolRELL(tree *tr, topolRELL *tpl) { int i; for (i = 0; i < 2 * tr->mxtips - 3; i++) { hookup(tpl->connect[i].p, tpl->connect[i].q, tpl->connect[i].z, tr->numBranches); tr->constraintVector[tpl->connect[i].p->number] = tpl->connect[i].cp; tr->constraintVector[tpl->connect[i].q->number] = tpl->connect[i].cq; } tr->likelihood = tpl->likelihood; tr->start = tr->nodep[tpl->start]; /* TODO */ } void initTL(topolRELL_LIST *rl, tree *tr, int n) { int i; rl->max = n; rl->t = (topolRELL **)malloc(sizeof(topolRELL *) * n); for(i = 0; i < n; i++) { rl->t[i] = (topolRELL *)malloc(sizeof(topolRELL)); rl->t[i]->connect = (connectRELL *)malloc((2 * tr->mxtips - 3) * sizeof(connectRELL)); rl->t[i]->likelihood = unlikely; } } void freeTL(topolRELL_LIST *rl) { int i; for(i = 0; i < rl->max; i++) { free(rl->t[i]->connect); free(rl->t[i]); } free(rl->t); } void restoreTL(topolRELL_LIST *rl, tree *tr, int n) { assert(n >= 0 && n < rl->max); restoreTopolRELL(tr, rl->t[n]); } void resetTL(topolRELL_LIST *rl) { int i; for(i = 0; i < rl->max; i++) rl->t[i]->likelihood = unlikely; } void saveTL(topolRELL_LIST *rl, tree *tr, int index) { assert(index >= 0 && index < rl->max); if(tr->likelihood > rl->t[index]->likelihood) saveTopolRELL(tr, rl->t[index]); } static void *tipValPtr (nodeptr p) { return (void *) & p->number; } static int cmpTipVal (void *v1, void *v2) { int i1, i2; i1 = *((int *) v1); i2 = *((int *) v2); return (i1 < i2) ? -1 : ((i1 == i2) ? 0 : 1); } /* These are the only routines that need to UNDERSTAND topologies */ static topol *setupTopol (int maxtips) { topol *tpl; if (! (tpl = (topol *) malloc(sizeof(topol))) || ! (tpl->links = (connptr) malloc((2*maxtips-3) * sizeof(connect)))) { printf("ERROR: Unable to get topology memory"); tpl = (topol *) NULL; } else { tpl->likelihood = unlikely; tpl->start = (node *) NULL; tpl->nextlink = 0; tpl->ntips = 0; tpl->nextnode = 0; tpl->scrNum = 0; /* position in sorted list of scores */ tpl->tplNum = 0; /* position in sorted list of trees */ } return tpl; } static void freeTopol (topol *tpl) { free(tpl->links); free(tpl); } static int saveSubtree (nodeptr p, topol *tpl, int numsp, int numBranches) { connptr r, r0; nodeptr q, s; int t, t0, t1, k; r0 = tpl->links; r = r0 + (tpl->nextlink)++; r->p = p; r->q = q = p->back; for(k = 0; k < numBranches; k++) r->z[k] = p->z[k]; r->descend = 0; /* No children (yet) */ if (isTip(q->number, numsp)) { r->valptr = tipValPtr(q); /* Assign value */ } else { /* Internal node, look at children */ s = q->next; /* First child */ do { t = saveSubtree(s, tpl, numsp, numBranches); /* Generate child's subtree */ t0 = 0; /* Merge child into list */ t1 = r->descend; while (t1 && (cmpTipVal(r0[t1].valptr, r0[t].valptr) < 0)) { t0 = t1; t1 = r0[t1].sibling; } if (t0) r0[t0].sibling = t; else r->descend = t; r0[t].sibling = t1; s = s->next; /* Next child */ } while (s != q); r->valptr = r0[r->descend].valptr; /* Inherit first child's value */ } /* End of internal node processing */ return (r - r0); } static nodeptr minSubtreeTip (nodeptr p0, int numsp) { nodeptr minTip, p, testTip; if (isTip(p0->number, numsp)) return p0; p = p0->next; minTip = minSubtreeTip(p->back, numsp); while ((p = p->next) != p0) { testTip = minSubtreeTip(p->back, numsp); if (cmpTipVal(tipValPtr(testTip), tipValPtr(minTip)) < 0) minTip = testTip; } return minTip; } static nodeptr minTreeTip (nodeptr p, int numsp) { nodeptr minp, minpb; minp = minSubtreeTip(p, numsp); minpb = minSubtreeTip(p->back, numsp); return (cmpTipVal(tipValPtr(minp), tipValPtr(minpb)) < 0 ? minp : minpb); } static void saveTree (tree *tr, topol *tpl) /* Save a tree topology in a standard order so that first branches * from a node contain lower value tips than do second branches from * the node. The root tip should have the lowest value of all. */ { connptr r; tpl->nextlink = 0; /* Reset link pointer */ r = tpl->links + saveSubtree(minTreeTip(tr->start, tr->mxtips), tpl, tr->mxtips, tr->numBranches); /* Save tree */ r->sibling = 0; tpl->likelihood = tr->likelihood; tpl->start = tr->start; tpl->ntips = tr->ntips; tpl->nextnode = tr->nextnode; } /* saveTree */ static boolean restoreTree (topol *tpl, tree *tr) { connptr r; nodeptr p, p0; int i; for (i = 1; i <= 2*(tr->mxtips) - 2; i++) { /* Uses p = p->next at tip */ p0 = p = tr->nodep[i]; do { p->back = (nodeptr) NULL; p = p->next; } while (p != p0); } /* Copy connections from topology */ for (r = tpl->links, i = 0; i < tpl->nextlink; r++, i++) hookup(r->p, r->q, r->z, tr->numBranches); tr->likelihood = tpl->likelihood; tr->start = tpl->start; tr->ntips = tpl->ntips; tr->nextnode = tpl->nextnode; evaluateGeneric(tr, tr->start, TRUE); return TRUE; } int initBestTree (bestlist *bt, int newkeep, int numsp) { /* initBestTree */ int i; bt->nkeep = 0; if (bt->ninit <= 0) { if (! (bt->start = setupTopol(numsp))) return 0; bt->ninit = -1; bt->nvalid = 0; bt->numtrees = 0; bt->best = unlikely; bt->improved = FALSE; bt->byScore = (topol **) malloc((newkeep+1) * sizeof(topol *)); bt->byTopol = (topol **) malloc((newkeep+1) * sizeof(topol *)); if (! bt->byScore || ! bt->byTopol) { printf( "initBestTree: malloc failure\n"); return 0; } } else if (ABS(newkeep) > bt->ninit) { if (newkeep < 0) newkeep = -(bt->ninit); else newkeep = bt->ninit; } if (newkeep < 1) { /* Use negative newkeep to clear list */ newkeep = -newkeep; if (newkeep < 1) newkeep = 1; bt->nvalid = 0; bt->best = unlikely; } if (bt->nvalid >= newkeep) { bt->nvalid = newkeep; bt->worst = bt->byScore[newkeep]->likelihood; } else { bt->worst = unlikely; } for (i = bt->ninit + 1; i <= newkeep; i++) { if (! (bt->byScore[i] = setupTopol(numsp))) break; bt->byTopol[i] = bt->byScore[i]; bt->ninit = i; } return (bt->nkeep = MIN(newkeep, bt->ninit)); } /* initBestTree */ void resetBestTree (bestlist *bt) { /* resetBestTree */ bt->best = unlikely; bt->worst = unlikely; bt->nvalid = 0; bt->improved = FALSE; } /* resetBestTree */ boolean freeBestTree(bestlist *bt) { /* freeBestTree */ while (bt->ninit >= 0) freeTopol(bt->byScore[(bt->ninit)--]); /* VALGRIND */ free(bt->byScore); free(bt->byTopol); /* VALGRIND END */ freeTopol(bt->start); return TRUE; } /* freeBestTree */ /* Compare two trees, assuming that each is in standard order. Return * -1 if first preceeds second, 0 if they are identical, or +1 if first * follows second in standard order. Lower number tips preceed higher * number tips. A tip preceeds a corresponding internal node. Internal * nodes are ranked by their lowest number tip. */ static int cmpSubtopol (connptr p10, connptr p1, connptr p20, connptr p2) { connptr p1d, p2d; int cmp; if (! p1->descend && ! p2->descend) /* Two tips */ return cmpTipVal(p1->valptr, p2->valptr); if (! p1->descend) return -1; /* p1 = tip, p2 = node */ if (! p2->descend) return 1; /* p2 = tip, p1 = node */ p1d = p10 + p1->descend; p2d = p20 + p2->descend; while (1) { /* Two nodes */ if ((cmp = cmpSubtopol(p10, p1d, p20, p2d))) return cmp; /* Subtrees */ if (! p1d->sibling && ! p2d->sibling) return 0; /* Lists done */ if (! p1d->sibling) return -1; /* One done, other not */ if (! p2d->sibling) return 1; /* One done, other not */ p1d = p10 + p1d->sibling; /* Neither done */ p2d = p20 + p2d->sibling; } } static int cmpTopol (void *tpl1, void *tpl2) { connptr r1, r2; int cmp; r1 = ((topol *) tpl1)->links; r2 = ((topol *) tpl2)->links; cmp = cmpTipVal(tipValPtr(r1->p), tipValPtr(r2->p)); if (cmp) return cmp; return cmpSubtopol(r1, r1, r2, r2); } static int cmpTplScore (void *tpl1, void *tpl2) { double l1, l2; l1 = ((topol *) tpl1)->likelihood; l2 = ((topol *) tpl2)->likelihood; return (l1 > l2) ? -1 : ((l1 == l2) ? 0 : 1); } /* Find an item in a sorted list of n items. If the item is in the list, * return its index. If it is not in the list, return the negative of the * position into which it should be inserted. */ static int findInList (void *item, void *list[], int n, int (* cmpFunc)(void *, void *)) { int mid, hi, lo, cmp = 0; if (n < 1) return -1; /* No match; first index */ lo = 1; mid = 0; hi = n; while (lo < hi) { mid = (lo + hi) >> 1; cmp = (* cmpFunc)(item, list[mid-1]); if (cmp) { if (cmp < 0) hi = mid; else lo = mid + 1; } else return mid; /* Exact match */ } if (lo != mid) { cmp = (* cmpFunc)(item, list[lo-1]); if (cmp == 0) return lo; } if (cmp > 0) lo++; /* Result of step = 0 test */ return -lo; } static int findTreeInList (bestlist *bt, tree *tr) { topol *tpl; tpl = bt->byScore[0]; saveTree(tr, tpl); return findInList((void *) tpl, (void **) (& (bt->byTopol[1])), bt->nvalid, cmpTopol); } int saveBestTree (bestlist *bt, tree *tr, boolean keepIdenticalTrees) { topol *tpl, *reuse; int tplNum, scrNum, reuseScrNum, reuseTplNum, i, oldValid, newValid; tplNum = findTreeInList(bt, tr); tpl = bt->byScore[0]; oldValid = newValid = bt->nvalid; if(tplNum > 0) { /* Topology is in list */ if(!keepIdenticalTrees) return 0; reuse = bt->byTopol[tplNum]; /* Matching topol */ reuseScrNum = reuse->scrNum; reuseTplNum = reuse->tplNum; } /* Good enough to keep? */ else { if(tr->likelihood < bt->worst) return 0; else { /* Topology is not in list */ tplNum = -tplNum; /* Add to list (not replace) */ if (newValid < bt->nkeep) bt->nvalid = ++newValid; reuseScrNum = newValid; /* Take worst tree */ reuse = bt->byScore[reuseScrNum]; reuseTplNum = (newValid > oldValid) ? newValid : reuse->tplNum; if (tr->likelihood > bt->start->likelihood) bt->improved = TRUE; } } scrNum = findInList((void *) tpl, (void **) (& (bt->byScore[1])), oldValid, cmpTplScore); scrNum = ABS(scrNum); if (scrNum < reuseScrNum) { for (i = reuseScrNum; i > scrNum; i--) (bt->byScore[i] = bt->byScore[i-1])->scrNum = i; } else { if (scrNum > reuseScrNum) { scrNum--; for (i = reuseScrNum; i < scrNum; i++) (bt->byScore[i] = bt->byScore[i+1])->scrNum = i; } } if(tplNum < reuseTplNum) for (i = reuseTplNum; i > tplNum; i--) (bt->byTopol[i] = bt->byTopol[i-1])->tplNum = i; else { if (tplNum > reuseTplNum) { tplNum--; for (i = reuseTplNum; i < tplNum; i++) (bt->byTopol[i] = bt->byTopol[i+1])->tplNum = i; } } tpl->scrNum = scrNum; tpl->tplNum = tplNum; bt->byTopol[tplNum] = bt->byScore[scrNum] = tpl; bt->byScore[0] = reuse; if (scrNum == 1) bt->best = tr->likelihood; if (newValid == bt->nkeep) bt->worst = bt->byScore[newValid]->likelihood; return scrNum; } int recallBestTree (bestlist *bt, int rank, tree *tr) { if (rank < 1) rank = 1; if (rank > bt->nvalid) rank = bt->nvalid; if (rank > 0) if (! restoreTree(bt->byScore[rank], tr)) return FALSE; return rank; } ExaML-3.0.21/examl/trash.c000066400000000000000000000032221330315463200151350ustar00rootroot00000000000000#ifndef WIN32 #include #include #include #include #endif #include #include #include #include #include #include #include #include "axml.h" static void reorderNodes(tree *tr, nodeptr *np, nodeptr p, int *count) { int i, found = 0; if(isTip(p->number, tr->mxtips)) return; else { for(i = tr->mxtips + 1; (i <= (tr->mxtips + tr->mxtips - 1)) && (found == 0); i++) { if (p == np[i] || p == np[i]->next || p == np[i]->next->next) { if(p == np[i]) tr->nodep[*count + tr->mxtips + 1] = np[i]; else { if(p == np[i]->next) tr->nodep[*count + tr->mxtips + 1] = np[i]->next; else tr->nodep[*count + tr->mxtips + 1] = np[i]->next->next; } found = 1; *count = *count + 1; } } assert(found != 0); reorderNodes(tr, np, p->next->back, count); reorderNodes(tr, np, p->next->next->back, count); } } void nodeRectifier(tree *tr) { nodeptr *np = (nodeptr *)malloc(2 * tr->mxtips * sizeof(nodeptr)); int i; int count = 0; tr->start = tr->nodep[1]; tr->rooted = FALSE; /* TODO why is tr->rooted set to FALSE here ?*/ for(i = tr->mxtips + 1; i <= (tr->mxtips + tr->mxtips - 1); i++) np[i] = tr->nodep[i]; reorderNodes(tr, np, tr->start->back, &count); free(np); } nodeptr findAnyTip(nodeptr p, int numsp) { return isTip(p->number, numsp) ? p : findAnyTip(p->next->back, numsp); } ExaML-3.0.21/examl/treeIO.c000066400000000000000000000643721330315463200152200ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifndef WIN32 #include #include #include #include #endif #include #include #include #include #include #include #include "axml.h" extern char infoFileName[1024]; extern char tree_file[1024]; extern char *likelihood_key; extern char *ntaxa_key; extern char *smoothed_key; extern double masterTime; stringHashtable *initStringHashTable(hashNumberType n) { /* init with primes */ static const hashNumberType initTable[] = {53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; /* init with powers of two static const hashNumberType initTable[] = {64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648U}; */ stringHashtable *h = (stringHashtable*)malloc(sizeof(stringHashtable)); hashNumberType tableSize, i, primeTableLength = sizeof(initTable)/sizeof(initTable[0]), maxSize = (hashNumberType)-1; assert(n <= maxSize); i = 0; while(initTable[i] < n && i < primeTableLength) i++; assert(i < primeTableLength); tableSize = initTable[i]; h->table = (stringEntry**)calloc(tableSize, sizeof(stringEntry*)); h->tableSize = tableSize; return h; } static hashNumberType hashString(char *p, hashNumberType tableSize) { hashNumberType h = 0; for(; *p; p++) h = 31 * h + *p; return (h % tableSize); } void addword(char *s, stringHashtable *h, int nodeNumber) { hashNumberType position = hashString(s, h->tableSize); stringEntry *p = h->table[position]; for(; p!= NULL; p = p->next) { if(strcmp(s, p->word) == 0) return; } p = (stringEntry *)malloc(sizeof(stringEntry)); assert(p); p->nodeNumber = nodeNumber; p->word = (char*)calloc(strlen(s) + 1, sizeof(char)); strcpy(p->word, s); p->next = h->table[position]; h->table[position] = p; } int lookupWord(char *s, stringHashtable *h) { hashNumberType position = hashString(s, h->tableSize); stringEntry *p = h->table[position]; for(; p!= NULL; p = p->next) { if(strcmp(s, p->word) == 0) return p->nodeNumber; } return -1; } int countTips(nodeptr p, int numsp) { if(isTip(p->number, numsp)) return 1; { nodeptr q; int tips = 0; q = p->next; while(q != p) { tips += countTips(q->back, numsp); q = q->next; } return tips; } } static double getBranchLength(tree *tr, int perGene, nodeptr p) { double z = 0.0, x = 0.0; assert(perGene != NO_BRANCHES); if(tr->numBranches == 1) { z = p->z[0]; if (z < zmin) z = zmin; x = -log(z); } else { if(perGene == SUMMARIZE_LH) { int i; double avgX = 0.0; for(i = 0; i < tr->numBranches; i++) { z = p->z[i]; if(z < zmin) z = zmin; x = -log(z); avgX += x * tr->partitionContributions[i]; } x = avgX; } else { assert(perGene >= 0 && perGene < tr->numBranches); z = p->z[perGene]; if(z < zmin) z = zmin; x = -log(z); } } return x; } static char *Tree2StringREC(char *treestr, tree *tr, nodeptr p, boolean printBranchLengths, boolean printNames, boolean printLikelihood, boolean rellTree, boolean finalPrint, int perGene, boolean branchLabelSupport, boolean printSHSupport) { char *nameptr; if(isTip(p->number, tr->mxtips)) { if(printNames) { nameptr = tr->nameList[p->number]; sprintf(treestr, "%s", nameptr); } else sprintf(treestr, "%d", p->number); while (*treestr) treestr++; } else { *treestr++ = '('; treestr = Tree2StringREC(treestr, tr, p->next->back, printBranchLengths, printNames, printLikelihood, rellTree, finalPrint, perGene, branchLabelSupport, printSHSupport); *treestr++ = ','; treestr = Tree2StringREC(treestr, tr, p->next->next->back, printBranchLengths, printNames, printLikelihood, rellTree, finalPrint, perGene, branchLabelSupport, printSHSupport); if(p == tr->start->back) { *treestr++ = ','; treestr = Tree2StringREC(treestr, tr, p->back, printBranchLengths, printNames, printLikelihood, rellTree, finalPrint, perGene, branchLabelSupport, printSHSupport); } *treestr++ = ')'; } if(p == tr->start->back) { if(printBranchLengths && !rellTree) sprintf(treestr, ":0.0;\n"); else sprintf(treestr, ";\n"); } else { if(rellTree || branchLabelSupport || printSHSupport) { if(( !isTip(p->number, tr->mxtips)) && ( !isTip(p->back->number, tr->mxtips))) { assert(0); /*assert(p->bInf != (branchInfo *)NULL);*/ /*if(rellTree) sprintf(treestr, "%d:%8.20f", p->bInf->support, p->z[0]); if(branchLabelSupport) sprintf(treestr, ":%8.20f[%d]", p->z[0], p->bInf->support); if(printSHSupport) sprintf(treestr, ":%8.20f[%d]", getBranchLength(tr, perGene, p), p->bInf->support); */ } else { if(rellTree || branchLabelSupport) sprintf(treestr, ":%8.20f", p->z[0]); if(printSHSupport) sprintf(treestr, ":%8.20f", getBranchLength(tr, perGene, p)); } } else { if(printBranchLengths) sprintf(treestr, ":%8.20f", getBranchLength(tr, perGene, p)); else sprintf(treestr, "%s", "\0"); } } while (*treestr) treestr++; return treestr; } char *Tree2String(char *treestr, tree *tr, nodeptr p, boolean printBranchLengths, boolean printNames, boolean printLikelihood, boolean rellTree, boolean finalPrint, int perGene, boolean branchLabelSupport, boolean printSHSupport) { if(rellTree) assert(!branchLabelSupport && !printSHSupport); if(branchLabelSupport) assert(!rellTree && !printSHSupport); if(printSHSupport) assert(!branchLabelSupport && !rellTree); Tree2StringREC(treestr, tr, p, printBranchLengths, printNames, printLikelihood, rellTree, finalPrint, perGene, branchLabelSupport, printSHSupport); while (*treestr) treestr++; return treestr; } void printTreePerGene(tree *tr, analdef *adef, char *fileName, char *permission) { FILE *treeFile; char extendedTreeFileName[1024]; char buf[16]; int i; assert(adef->perGeneBranchLengths); for(i = 0; i < tr->numBranches; i++) { strcpy(extendedTreeFileName, fileName); sprintf(buf,"%d", i); strcat(extendedTreeFileName, ".PARTITION."); strcat(extendedTreeFileName, buf); /*printf("Partitiuon %d file %s\n", i, extendedTreeFileName);*/ Tree2String(tr->tree_string, tr, tr->start->back, TRUE, TRUE, FALSE, FALSE, TRUE, i, FALSE, FALSE); treeFile = myfopen(extendedTreeFileName, permission); fprintf(treeFile, "%s", tr->tree_string); fclose(treeFile); } } /*=======================================================================*/ /* Read a tree from a file */ /*=======================================================================*/ /* 1.0.A Processing of quotation marks in comment removed */ static int treeFinishCom (FILE *fp, char **strp) { int ch; while ((ch = getc(fp)) != EOF && ch != ']') { if (strp != NULL) *(*strp)++ = ch; /* save character */ if (ch == '[') { /* nested comment; find its end */ if ((ch = treeFinishCom(fp, strp)) == EOF) break; if (strp != NULL) *(*strp)++ = ch; /* save closing ] */ } } if (strp != NULL) **strp = '\0'; /* terminate string */ return ch; } /* treeFinishCom */ static int treeGetCh (FILE *fp) /* get next nonblank, noncomment character */ { /* treeGetCh */ int ch; while ((ch = getc(fp)) != EOF) { if (whitechar(ch)) ; else if (ch == '[') { /* comment; find its end */ if ((ch = treeFinishCom(fp, (char **) NULL)) == EOF) break; } else break; } return ch; } /* treeGetCh */ static boolean treeLabelEnd (int ch) { switch (ch) { case EOF: case '\0': case '\t': case '\n': case '\r': case ' ': case ':': case ',': case '(': case ')': case ';': return TRUE; default: break; } return FALSE; } static boolean treeGetLabel (FILE *fp, char *lblPtr, int maxlen) { int ch; boolean done, quoted, lblfound; if (--maxlen < 0) lblPtr = (char *) NULL; else if (lblPtr == NULL) maxlen = 0; ch = getc(fp); done = treeLabelEnd(ch); lblfound = ! done; quoted = (ch == '\''); if (quoted && ! done) { ch = getc(fp); done = (ch == EOF); } while (! done) { if (quoted) { if (ch == '\'') { ch = getc(fp); if (ch != '\'') break; } } else if (treeLabelEnd(ch)) break; if (--maxlen >= 0) *lblPtr++ = ch; ch = getc(fp); if (ch == EOF) break; } if (ch != EOF) (void) ungetc(ch, fp); if (lblPtr != NULL) *lblPtr = '\0'; return lblfound; } static boolean treeFlushLabel (FILE *fp) { return treeGetLabel(fp, (char *) NULL, (int) 0); } static int treeFindTipByLabelString(char *str, tree *tr, boolean check) { int lookup = lookupWord(str, tr->nameHash); if(lookup > 0) { if(check) assert(! tr->nodep[lookup]->back); return lookup; } else { printf("ERROR: Cannot find tree species: %s\n", str); return 0; } } int treeFindTipName(FILE *fp, tree *tr, boolean check) { char str[nmlngth+2]; int n; if(treeGetLabel(fp, str, nmlngth+2)) n = treeFindTipByLabelString(str, tr, check); else n = 0; return n; } static void treeEchoContext (FILE *fp1, FILE *fp2, int n) { /* treeEchoContext */ int ch; boolean waswhite; waswhite = TRUE; while (n > 0 && ((ch = getc(fp1)) != EOF)) { if (whitechar(ch)) { ch = waswhite ? '\0' : ' '; waswhite = TRUE; } else { waswhite = FALSE; } if (ch > '\0') {putc(ch, fp2); n--;} } } /* treeEchoContext */ static boolean treeProcessLength (FILE *fp, double *dptr) { int ch; if ((ch = treeGetCh(fp)) == EOF) return FALSE; /* Skip comments */ (void) ungetc(ch, fp); if (fscanf(fp, "%lf", dptr) != 1) { printf("ERROR: treeProcessLength: Problem reading branch length\n"); treeEchoContext(fp, stdout, 40); printf("\n"); return FALSE; } return TRUE; } static int treeFlushLen (FILE *fp) { double dummy; int ch; ch = treeGetCh(fp); if (ch == ':') { ch = treeGetCh(fp); ungetc(ch, fp); if(!treeProcessLength(fp, & dummy)) return 0; return 1; } if (ch != EOF) (void) ungetc(ch, fp); return 1; } static boolean treeNeedCh (FILE *fp, int c1, char *where) { int c2; if ((c2 = treeGetCh(fp)) == c1) return TRUE; printf("ERROR: Expecting '%c' %s tree; found:", c1, where); if (c2 == EOF) { printf("End-of-File"); } else { ungetc(c2, fp); treeEchoContext(fp, stdout, 40); } putchar('\n'); if(c1 == ':') printf("RAxML may be expecting to read a tree that contains branch lengths\n"); return FALSE; } static boolean addElementLen (FILE *fp, tree *tr, nodeptr p, boolean readBranchLengths, boolean readNodeLabels, int *lcount) { nodeptr q; int n, ch, fres; if ((ch = treeGetCh(fp)) == '(') { n = (tr->nextnode)++; if (n > 2*(tr->mxtips) - 2) { if (tr->rooted || n > 2*(tr->mxtips) - 1) { printf("ERROR: Too many internal nodes. Is tree rooted?\n"); printf(" Deepest splitting should be a trifurcation.\n"); return FALSE; } else { assert(!readNodeLabels); tr->rooted = TRUE; } } q = tr->nodep[n]; if (! addElementLen(fp, tr, q->next, readBranchLengths, readNodeLabels, lcount)) return FALSE; if (! treeNeedCh(fp, ',', "in")) return FALSE; if (! addElementLen(fp, tr, q->next->next, readBranchLengths, readNodeLabels, lcount)) return FALSE; if (! treeNeedCh(fp, ')', "in")) return FALSE; if(readNodeLabels) { char label[64]; int support; if(treeGetLabel (fp, label, 10)) { int val = sscanf(label, "%d", &support); assert(val == 1); /*printf("LABEL %s Number %d\n", label, support);*/ /*p->support = q->support = support;*/ /*printf("%d %d %d %d\n", p->support, q->support, p->number, q->number);*/ assert(p->number > tr->mxtips && q->number > tr->mxtips); *lcount = *lcount + 1; } } else (void) treeFlushLabel(fp); } else { ungetc(ch, fp); if ((n = treeFindTipName(fp, tr, TRUE)) <= 0) return FALSE; q = tr->nodep[n]; if (tr->start->number > n) tr->start = q; (tr->ntips)++; } if(readBranchLengths) { double branch; if (! treeNeedCh(fp, ':', "in")) return FALSE; if (! treeProcessLength(fp, &branch)) return FALSE; /*printf("Branch %8.20f %d\n", branch, tr->numBranches);*/ hookup(p, q, &branch, tr->numBranches); } else { fres = treeFlushLen(fp); if(!fres) return FALSE; hookupDefault(p, q, tr->numBranches); } return TRUE; } static nodeptr uprootTree (tree *tr, nodeptr p, boolean readBranchLengths) { nodeptr q, r, s, start; int n, i; for(i = tr->mxtips + 1; i < 2 * tr->mxtips - 1; i++) assert(i == tr->nodep[i]->number); if(isTip(p->number, tr->mxtips) || p->back) { printf("ERROR: Unable to uproot tree.\n"); printf(" Inappropriate node marked for removal.\n"); assert(0); } assert(p->back == (nodeptr)NULL); tr->nextnode = tr->nextnode - 1; assert(tr->nextnode < 2 * tr->mxtips); n = tr->nextnode; assert(tr->nodep[tr->nextnode]); if (n != tr->mxtips + tr->ntips - 1) { printf("ERROR: Unable to uproot tree. Inconsistent\n"); printf(" number of tips and nodes for rooted tree.\n"); assert(0); } q = p->next->back; /* remove p from tree */ r = p->next->next->back; assert(p->back == (nodeptr)NULL); if(readBranchLengths) { double b[NUM_BRANCHES]; int i; for(i = 0; i < tr->numBranches; i++) b[i] = (r->z[i] + q->z[i]); hookup (q, r, b, tr->numBranches); } else hookupDefault(q, r, tr->numBranches); if(tr->constraintTree) { if(tr->constraintVector[p->number] != 0) { printf("Root node to remove should have top-level grouping of 0\n"); assert(0); } } assert(!(isTip(r->number, tr->mxtips) && isTip(q->number, tr->mxtips))); assert(p->number > tr->mxtips); if(tr->ntips > 2 && p->number != n) { q = tr->nodep[n]; /* transfer last node's conections to p */ r = q->next; s = q->next->next; if(tr->constraintTree) tr->constraintVector[p->number] = tr->constraintVector[q->number]; hookup(p, q->back, q->z, tr->numBranches); /* move connections to p */ hookup(p->next, r->back, r->z, tr->numBranches); hookup(p->next->next, s->back, s->z, tr->numBranches); q->back = q->next->back = q->next->next->back = (nodeptr) NULL; } else p->back = p->next->back = p->next->next->back = (nodeptr) NULL; assert(tr->ntips > 2); start = findAnyTip(tr->nodep[tr->mxtips + 1], tr->mxtips); assert(isTip(start->number, tr->mxtips)); tr->rooted = FALSE; return start; } int treeReadLen (FILE *fp, tree *tr, boolean readBranches, boolean readNodeLabels, boolean topologyOnly) { nodeptr p; int i, ch, lcount = 0; for (i = 1; i <= tr->mxtips; i++) { tr->nodep[i]->back = (node *) NULL; /*if(topologyOnly) tr->nodep[i]->support = -1;*/ } for(i = tr->mxtips + 1; i < 2 * tr->mxtips; i++) { tr->nodep[i]->back = (nodeptr)NULL; tr->nodep[i]->next->back = (nodeptr)NULL; tr->nodep[i]->next->next->back = (nodeptr)NULL; tr->nodep[i]->number = i; tr->nodep[i]->next->number = i; tr->nodep[i]->next->next->number = i; /*if(topologyOnly) { tr->nodep[i]->support = -2; tr->nodep[i]->next->support = -2; tr->nodep[i]->next->next->support = -2; }*/ } if(topologyOnly) tr->start = tr->nodep[tr->mxtips]; else tr->start = tr->nodep[1]; tr->ntips = 0; tr->nextnode = tr->mxtips + 1; for(i = 0; i < tr->numBranches; i++) tr->partitionSmoothed[i] = FALSE; tr->rooted = FALSE; p = tr->nodep[(tr->nextnode)++]; while((ch = treeGetCh(fp)) != '('); if(!topologyOnly) assert(readBranches == FALSE && readNodeLabels == FALSE); if (! addElementLen(fp, tr, p, readBranches, readNodeLabels, &lcount)) assert(0); if (! treeNeedCh(fp, ',', "in")) assert(0); if (! addElementLen(fp, tr, p->next, readBranches, readNodeLabels, &lcount)) assert(0); if (! tr->rooted) { if ((ch = treeGetCh(fp)) == ',') { if (! addElementLen(fp, tr, p->next->next, readBranches, readNodeLabels, &lcount)) assert(0); } else { /* A rooted format */ tr->rooted = TRUE; if (ch != EOF) (void) ungetc(ch, fp); } } else { p->next->next->back = (nodeptr) NULL; } if (! treeNeedCh(fp, ')', "in")) assert(0); if(topologyOnly) assert(!(tr->rooted && readNodeLabels)); (void) treeFlushLabel(fp); if (! treeFlushLen(fp)) assert(0); if (! treeNeedCh(fp, ';', "at end of")) assert(0); if (tr->rooted) { assert(!readNodeLabels); p->next->next->back = (nodeptr) NULL; tr->start = uprootTree(tr, p->next->next, FALSE); if (! tr->start) { printf("FATAL ERROR UPROOTING TREE\n"); assert(0); } } else tr->start = findAnyTip(p, tr->mxtips); assert(tr->ntips == tr->mxtips); return lcount; } static int randomInt(int n) { return rand() %n; } static boolean addElementLenMULT (FILE *fp, tree *tr, nodeptr p, int partitionCounter, int *partCount) { nodeptr q, r, s; int n, ch, fres, rn; double randomResolution; int old; tr->constraintVector[p->number] = partitionCounter; if ((ch = treeGetCh(fp)) == '(') { *partCount = *partCount + 1; old = *partCount; n = (tr->nextnode)++; if (n > 2*(tr->mxtips) - 2) { if (tr->rooted || n > 2*(tr->mxtips) - 1) { printf("ERROR: Too many internal nodes. Is tree rooted?\n"); printf(" Deepest splitting should be a trifurcation.\n"); return FALSE; } else { tr->rooted = TRUE; } } q = tr->nodep[n]; tr->constraintVector[q->number] = *partCount; if (! addElementLenMULT(fp, tr, q->next, old, partCount)) return FALSE; if (! treeNeedCh(fp, ',', "in")) return FALSE; if (! addElementLenMULT(fp, tr, q->next->next, old, partCount)) return FALSE; hookupDefault(p, q, tr->numBranches); while((ch = treeGetCh(fp)) == ',') { n = (tr->nextnode)++; if (n > 2*(tr->mxtips) - 2) { if (tr->rooted || n > 2*(tr->mxtips) - 1) { printf("ERROR: Too many internal nodes. Is tree rooted?\n"); printf(" Deepest splitting should be a trifurcation.\n"); return FALSE; } else { tr->rooted = TRUE; } } r = tr->nodep[n]; tr->constraintVector[r->number] = *partCount; rn = randomInt(10000); if(rn == 0) randomResolution = 0; else randomResolution = ((double)rn)/10000.0; if(randomResolution < 0.5) { s = q->next->back; r->back = q->next; q->next->back = r; r->next->back = s; s->back = r->next; addElementLenMULT(fp, tr, r->next->next, old, partCount); } else { s = q->next->next->back; r->back = q->next->next; q->next->next->back = r; r->next->back = s; s->back = r->next; addElementLenMULT(fp, tr, r->next->next, old, partCount); } } if(ch != ')') { printf("Missing /) in treeReadLenMULT\n"); exit(-1); } (void) treeFlushLabel(fp); } else { ungetc(ch, fp); if ((n = treeFindTipName(fp, tr, TRUE)) <= 0) return FALSE; q = tr->nodep[n]; tr->constraintVector[q->number] = partitionCounter; if (tr->start->number > n) tr->start = q; (tr->ntips)++; hookupDefault(p, q, tr->numBranches); } fres = treeFlushLen(fp); if(!fres) return FALSE; return TRUE; } boolean treeReadLenMULT (FILE *fp, tree *tr, int *partCount) { nodeptr p, r, s; int i, ch, n, rn; int partitionCounter = 0; double randomResolution; srand(tr->randomSeed); for(i = 0; i < 2 * tr->mxtips; i++) tr->constraintVector[i] = -1; for (i = 1; i <= tr->mxtips; i++) tr->nodep[i]->back = (node *) NULL; for(i = tr->mxtips + 1; i < 2 * tr->mxtips; i++) { tr->nodep[i]->back = (nodeptr)NULL; tr->nodep[i]->next->back = (nodeptr)NULL; tr->nodep[i]->next->next->back = (nodeptr)NULL; tr->nodep[i]->number = i; tr->nodep[i]->next->number = i; tr->nodep[i]->next->next->number = i; } tr->start = tr->nodep[tr->mxtips]; tr->ntips = 0; tr->nextnode = tr->mxtips + 1; for(i = 0; i < tr->numBranches; i++) tr->partitionSmoothed[i] = FALSE; tr->rooted = FALSE; p = tr->nodep[(tr->nextnode)++]; while((ch = treeGetCh(fp)) != '('); if (! addElementLenMULT(fp, tr, p, partitionCounter, partCount)) return FALSE; if (! treeNeedCh(fp, ',', "in")) return FALSE; if (! addElementLenMULT(fp, tr, p->next, partitionCounter, partCount)) return FALSE; if (! tr->rooted) { if ((ch = treeGetCh(fp)) == ',') { if (! addElementLenMULT(fp, tr, p->next->next, partitionCounter, partCount)) return FALSE; while((ch = treeGetCh(fp)) == ',') { n = (tr->nextnode)++; assert(n <= 2*(tr->mxtips) - 2); r = tr->nodep[n]; tr->constraintVector[r->number] = partitionCounter; rn = randomInt(10000); if(rn == 0) randomResolution = 0; else randomResolution = ((double)rn)/10000.0; if(randomResolution < 0.5) { s = p->next->next->back; r->back = p->next->next; p->next->next->back = r; r->next->back = s; s->back = r->next; addElementLenMULT(fp, tr, r->next->next, partitionCounter, partCount); } else { s = p->next->back; r->back = p->next; p->next->back = r; r->next->back = s; s->back = r->next; addElementLenMULT(fp, tr, r->next->next, partitionCounter, partCount); } } if(ch != ')') { printf("Missing /) in treeReadLenMULT\n"); exit(-1); } else ungetc(ch, fp); } else { tr->rooted = TRUE; if (ch != EOF) (void) ungetc(ch, fp); } } else { p->next->next->back = (nodeptr) NULL; } if (! treeNeedCh(fp, ')', "in")) return FALSE; (void) treeFlushLabel(fp); if (! treeFlushLen(fp)) return FALSE; if (! treeNeedCh(fp, ';', "at end of")) return FALSE; if (tr->rooted) { p->next->next->back = (nodeptr) NULL; tr->start = uprootTree(tr, p->next->next, FALSE); if (! tr->start) return FALSE; } else { tr->start = findAnyTip(p, tr->mxtips); } assert(tr->ntips == tr->mxtips); return TRUE; } void getStartingTree(tree *tr) { FILE *treeFile = myfopen(tree_file, "rb"); tr->likelihood = unlikely; if(tr->constraintTree) { int partCount = 0; if (! treeReadLenMULT(treeFile, tr, &partCount)) exit(-1); } else treeReadLen(treeFile, tr, FALSE, FALSE, FALSE); fclose(treeFile); tr->start = tr->nodep[1]; } ExaML-3.0.21/gpl-3.0.txt000066400000000000000000001045131330315463200143700ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ExaML-3.0.21/manual/000077500000000000000000000000001330315463200140205ustar00rootroot00000000000000ExaML-3.0.21/manual/ExaML.backup.odt000066400000000000000000002533111330315463200167470ustar00rootroot00000000000000PKL#F^2 ''mimetypeapplication/vnd.oasis.opendocument.textPKL#F")Thumbnails/thumbnail.pngPNG  IHDRg?|IDATx}|-lKdْ8{#P ZҖQP(he #{ʶlC{IoKۦtzG|(Lar6 C*LW 0t) 0]a C*LW 0t) 0]a C*LW 0t) 0]a C*LW 0t4ðq"_A_RK`CQqrp(@ِ9t;nC~ ׀}r ܋: ( .{d'~] =b$h4|`QL#T"$z @YFIx$)aF#u?1DtP$z1%g7° p# 20pO K1%OI s'ɉ};7t Ve)yz L90198 \v a[nq0S :hy 4f\NjV-c|}|ΖOU-Re>ym(*M{<8ǡ O^oDړv|vF/dWgOI*}qYڂg^-eg| pqmJg3鰿̻o^_Q~ku_|ݝ;}0:gL+eq݇^`~67lh?pdWfԓ ڌ_1a1Qs(K֛;3V5Rտ5)R$mZR ,4V)u-}^탳P/ZЙO?ڐ[o48-MsçΟk/\@ o=;W|uxǟ}1U}^xۺzU|>|]B_hȑr)ƙ=tJǯ(I.LSqյY")!i!YTt݊93IU:QV׾">Ys!!EBz9">w(A¦d8Rc闛o7)BB餞%R%>dp>C]}>|릠r ?n/TJ(~]"A>̓8I7ݳp9qk0x"7߆PLJZTȪDО|~# HQAI HA)>eO@y}^Ҥ@)a -h42pV_B1҄%:H#D  gMB-%. %! D(KQȼID#фǿ#F~`b0GXo}}_5#h2t]L)]kp"ZTc) 0]ayA* zU咿-Fm$)b/\(I H? )Qb(yhc@?/HM`EP\)_u"x+{'PO]H$"|烈Bz:s$`vNt0x=t}7D%iP^:Qk??x|1Xe~wgB?/HAi}'gg]! źoY{7Fg/J95r]{Ǥrs}ŎMގyݫ^oywJ|ǒS4ɻ0ʤq]-G h*CEeRWfVۅnxh8n\.D:qTYt/!S{1d 6Dҵ)RM<6Tj2r#mg;SSPOʦ$uu}k~nv]CCB%qy{!c(HcsuՇTw,-ȣ#G~陵 JADwۚE>/"1ճsOR:BD~hvGL 8T0%h|qh~geΎoV^stE5ow(!%ݍ$k woǼ(_(!w%Uef6Eid.Ƞi3cSVS̜$mHwl-CN/')&dټlN=uh yP 5 %V]DE6"8'2ě h,K&qqy|pV 6 M\,8Qg",ɩiM!.KS($:еfк #tD@lMv4dSAHp@ÐnO6W-rÚHUr[rtM' ?!lגZTȊ;xc_O:R終'ڂ54="C*LT0!+LaH SRaT0!+LaH SRaT0!+LaH UT(I;sP0%=hO Tq?YZt AIl?EQeX%*|5@ 4@E`XmٿXtu?SGCwJ^ uR &O9džշbXk32%yOtU ETwU ZcEO޳ϽTw ?*v15IzwG=q$ec6/>釱y}82LN|mo͉oenJ,Uj ;LWx#Q^Q2+;2F~9 [>Zb^~H8^>ȏO՗.AnܔÐ%Kؤ"DCa.`_lŴ)ˋ)S6׻ZJ4xuˬ10K4:a{}õfݚW{ˎM' CłVPs6FnN%^"4Y1heLM9u "{{;( `AA?WPp>% -IBr? OU4u bїS@dN*tPYL8?f޶훨9G}CD[`/!pc'2Jy Z0v.>+?@2ڷ؝3u~QVBhHc"UQ3`t9IUNRւ\ӓp"Ų7FUtwYzcdmyyOV7]FWY{cFn}׶-eSg2^l?>s΂njPĢ|nե(ČOy'a=._֭e-׭xrwm:_[hC?zs5tȧ>{[ /4ݰjq"^LW1u/#/f,Ț<}aP6by-@ ,_l._V3o{T8,Iסαt'loW&= s5+{y1sRe%>G1Զ9;p"^e0hsM3;jK=n7DCFoh8r(e/À#pf))wc'|ce4mwml7dE<3p g._ Z/gUWG"k,|͈V}0;PӧM+;tz#tLT9)bq^y/,+bN:,.ǟu xmnˈ@*P5ulpe˱Tq}ꑷox3G|&(98&m)j%qf&[}yYϢY(hEy0,j}玼ᶾ}opMwًw]a~̀#!oJ\9hlo{"phB`8 f@gQB6Mu!˰EJ| eBMbL,'͟l˝6mWL[>PUPH NG`ڍJ]d$6]eԨϛږtIRtud)EC_o["(-xGbQmqDP *~DC!&ig5! dY`%` P]!ڊpL;].6>b[ިjnqy(n6:#-lnNriUgV^;Jyd{kØwrxPaAa[CdPs1{$&,Jg}m![lO֗G'woopF']_=s <{]r'Sa ƌ `b۶m R'80F9B@Oc-s91IrnTu9[EQSO?Y3Ǫ}mOwlkHK>o L$glKϟAٻ 1!yŮ=|߽Bt 1%E 954FoX!Fۿ|nE92u o6&M[yk>I܋i9@k>!>n{!&yᏏ<г/55A;:2X|Q~q'DԴ=QҴ<:_ƞ?)Nb~G{O,Ap::cdH%6ے,nlܜ8m\R_ߤ[L3Wܢ0G頠LZ( FWKh1RsI#SI`fD| `lExĔ(Ȕӟ9 q4 %S5+B@ xӁQ:Ťbf϶rgHaU3sRt30K:?~s}bWw߱]Cml_zf'6 d*SVe?/ifjSm135H*Aoȥo39GZu|pt*O@7:0>{-=v)_qHRge%8=紼)3}ZK@".NT:]}n\Y{ネ@Ih~ͽFώܰbŪ8B;a-e`Byb~OZl W8v}/?h=1•7HP8DM  "1^fZZ{S͸}|߅9 r2V}:t.],nHyȸeߎ-@B>sO?QP\r<T[@%*{dZT8Ә;=!QQrT2#.3b:Gg̙`ef=i i_)/UWͩ{\)%-^tӔ@j܆ FCaœ](8 6Ystv ]f!wN_T2a|ϯ̭7\gw894PiBn~X_;6Ƕ?ٜ 嵏|)kB\Xn{ws_ y~ O-ݿ1)_{*wm7WWUGZZzbbԀ@]g=}fIl}l2^ɳUq)s{6&+UgS/posE= 4\6_@J2Q`HS|8oj~ڑ]>~=RQIΉA=ic즺zYF.tHtw(3AMLGff=n鴧MOW4L~͗_x.*>֏9Ҙܴ3gS3{[RQq܀m`̾ro69oe`mN׈sȈ0n.Nd()QdJ!g-|Q4s(RB,ČO DA~4NkPԙdY6 |?:Jibf!u,<қ^o@\FRTev7&QP^?d*ծDܵ׏r#A7tr3s'32ƊkPq2.B:LBG Trh#bO n |8)$V.'X* (׸ˡmLA!*`2e @I{NRU?Dա`!2 ôheլpϥE*\*(Ez!*?0y**bjOMw&Lg!5'D? '͉$K?~!K' T00O 9ֵ p*ȏle)DL?X0$ %3k.K 73 f1o}?>wffv@P:CݺvFш@ yۿ984ow΀ˎ4&{,N,ˑ()䱃ԷtЁ\Z:%sl?|yǏQgػus'4vG:2tj{ݦ1oSeK/>ϊ.?gk¥Elp*evssU-]9 o6gY@@ oWdž.R\:cN\\(҄iRfTYwW=-*m.O`tb7F,(y磷9.4M9}9)F|C/6A\_+Vk.G򱀛ɥ?̂AB4PWQ+",~,QՍ'eJ`1ߋGl!g!u5#f->|Yj5jqiu:cY2ts2a>x\8G2h8P(mVχCC@`,aQ:r[,f"@&1gG\lf+Pn܎R+rI0 0x"Pɠav[ lv00(80P#8ƠK$i  #JbU0vy~?:ng) yAszEIN'ŦaēhAb!R4Snzf0\ E&!}\߈˘MLj44˗i0kւf5(J <[w\oMKM\]4d h4Ƨ(egs24v}Ò*R ǍdG{V^PŎHe3gh>P=u ;Y>flL #muPȎ3[Oben 7E P&W$J8'OO,Kȱi9=M,Y]3,BN#?oCq$ d3fuT6uie3/ib|ߨU %eG:F s.Im83!&s ;NffEDH:; gPwUyB9bKwƱ-5k%m݀"iRRTYƐ(׸d$L67P_/DcqY쮜֚r=cz! ]}.$ѱ(:⾇p˹޳*9u̼xͺQC=;! ?II)(d{rFbM/w| =ѫ%nQ 1zk}c>d*U`6(~Jmfxaps]CLlz<&&_yO Sf1r5/=甂| xLO@y_$L[M_Vw]w 8 8qnpa~҇naIڙoةשQ=R{ſjrJn<䌤NYb%gskҳs"4ExZF~tE#L~DDDEuԳ`Ry}ѣKШ/=%=1qJJN2b$JʦA4;nw:-9p[WpA,#U$WD1:="*Rؽ|.[fuH SѮށiN%#-MSfiq'` Κu #=6ap9A: Xlh :|S*+v T:74210ГN/JX%'i(XW/֧dea./X뺲*/\0w2sn֔Li 15ǽR63;܌p)ƺZu ʕh>(DI9,F .pED!fE*UB* D*u\Oƹ6XixHM=,@[0iOIbQq0Y`񒢴XJ4}B  >a@zb+ GBJC]Ne4rg@HӋj E@ DWb)'&%:vij^/9T&%ɣ;4+>) Sb1He" rf1ӰJ [t=([L#EԼjhbAogia'S`d}^,&~67-I'ה^wulkBAhǎ#4r3@Rnb0YI@~CXmĜ,OVtYl6xY>氙%mV ̕*W3[@]RҮ/>͟Z(`N?Q񜼉ޙth͍T[A uV*cŅ9=24ͦx8́q&<[.+d\ RFCX`~c}u,N#Mk b{\N *0{jtaVi\P@JMw!ŖbXƞ 3an7@طkɆY|ߎgyt.m, ӕ%2dFNCvЦ~m}n'^$"~WlI@ 6[w9CӘD(0ۜy9B!05 ^ e|y P rus 6G$ Px%\RĉWLܥIhƫmZa&j[[*\ EV*W?}=5>o>`'U'] \Y!/3At&eZ4ܠϿIe8iiƎ&DLn3:zm> A[pZ_]&#^cR޴`N-ֵ7յ":^]0cኂc-(8ƔK~T'ʨm[<ϝ"')8z:,Uյ^>qU-t")[?@$s%/?¹Ĭ&%kwږ[ XN[;*-ln8>T*fk6"ce u tp(af͊`*y_m<#KJi\19 VʈR!_%a9u03XJuowzX }ݺE,,T6vwZY;.9vif0D}8K@tCQ_7T%475GiS4Zae$8seӕ!Θo]@'7XFO. bL"ҏn,ȓl촌31 㘻)tRjt?h}("3Cn9zW֔:,X>壵7II1<֯H]LJa~Ʀb@ah*J}lpDTWZ^W]gڙh ߗS4uF^V?n2 FL1)HK}K_^FwGc2eD$/&kfF.H̄Rnȃ,]^0:KxbױG`;p Zf-cl-7Xã"uOq\*L-6'TDǡiB!7B|~'sEQ2!,[~)a^Z͸U9ڇ}-T_\& G^gNVBڊ"XBt[\!H$\X"kÈ!ǣ}eg '$<_w'$hOg8GX~يۿ=[f US̤c~ /frQV":1w2SGa#FM7Ouu{J[D*T I|GTv "DT;q=R">Q1&@UԂS.+WwiGB8oT7f2ng;H`\3Em~QXt j]P 4ZȀ%Lw=lM/HmylT| Oeq)B @UJbrQJoUveC Xy@@F+T߸ؘ̛?btjmZV&O$JZ|irzQсEB/b DT+:Z}ɋ4RnzRC^M~s2Ꚕb Zv\yVnιG3̬:u#9[lUϞ!-iIHlYb)|E7B'v.QYto?fzcnσfc c}m>F~FgI)=:#]&hƱgFܵȬ(veRaQ钆>nV51!+jdQEZ6O{te &#PaPC5ur` ) E^[E9)1MCW^rs&t"QEn  z;[60I<!?ADx6C]~ )BX Ãmuwju5X5Kfg =z(Xm3هB\,E\r{RwL8=FH-ذ8& YtsGVnY݁ъCͻ0 ΉITh]i-2SYa]/ kBfV!l]w_ހ6!gkݠkl5$Ҟ6a6%Ro84)OFZ`@颶́CI3>&hI9&V糺aޅJH`O~s_5'7sbOCL'5]mE\XSS?$_>w=F.eƬم9/SZt`CG] ghL O&L!rRR#5ʿrlSBS&\tLx(~|xpi} ~MA!č.#02#P`ޒe|>Š>;Vg;j,:y{c,4HyD(o.2! ]k:32rJ%T&S4дrN>O1".E%3V_Z.ΏҮ\8j8\3 9TEg0<.7aKCgss6>ns8 .Q t vXZRsQp'@Icly^&|2Y *ϞcVvlj~q! %n?LI8fМ6sEye ՚Dr<$d0~ ʎ Ϟ:WT-Лc& 2tANwkWgD <(ٷ W>B@z=-͟2k7fa|<5)>:6Y!SQC^_`dX`0~j2:Rsȣ#D|8a36;x1<.xt;|$*{\> ʗo&}ju-ΞTvã}gގyt>)@*^س@ 26s+5s9z|7^}'%5BcDsTvx(@O/We`-M-qz_vz*)n`8jYF0 v#ZJTV.eDҘܪk04260lq:3Uu5~K{|BPv{2i[\l}u<>2t| w*Ui4&lY]dz.T׸\^U%YzF.?]ق;ۭ |&"(4326R]vc m;v&מq +*!oƞ檖zE[r{G_kj{z,T"=V(WrzdrcR=4<Z6i&;)1̝;^9H,@!gѡ*e\5fhR0tqD BoZO- 5T[]XGMG TCC)XM/qzяxTWϝ6 GE2d|$Ƶ48X1td&Ԕ;INH0ZFlh:;r/*65S8ՙSܶʊ:Bi]rPo+N9Y9g+bb̾Ŋю#t@yĔ1}l5|{{-)-6wFGm 1.HehN-N!/$H u.LBk[jx NM{b%FO<,^r`oor-x<>f v|su J9 tshXRõ9w92(504޼~:~9$ex@93g,0F'ztE &Wc];F:{ ݝ=-i>!8NkL G&ŧ8q$BC|T6>6UH-6o\\1C =ƥ /xΗR=uss'Ox"rfD ;6޷0P$b`W X O+˕Jly.G,Y)RpD.)v6%H878`k䎩3NgFFk1)S4hgk1pm~Wk :Ghɒ݇A?rQIK\02,M/%6pEFV#i9Ia ~V*-c^ "ш\n#4 G+?!(bc8<S'U#b|RNRm9 .-VBC^v\*[\#5{:(p-vL)Ty%\mQⅈ7$RݻC8nZ~&B*'Ɓ ?JKӪNȾ{&u݉Vu9'8D"9S$J%AZ[y[-K)) `09ttOcHˁ|K?|[uӹsks/s C# bQ >22{\Ӂ.BNB G߾51lhqX'fJu]v~]x%VCH'V#|b.f7Npi|Z@=`68\Nrs=ڻ%쳹J0 ߧwe??xwST0#0JݱRHjlz8Yj2NZ[b>Kt\;tJj^zjo<31|Ȭ`{`QgKQYfr#K;=)Q,E*Յ33|/ kxu82n\&@Zu}c_p'޽c5c_-+dF+(ؔ޿@MJY\rvJbDٶw ](өtRZ&P?~&>^ ۚa?S{'\FH`ΡWY;I;}Ҩ}zffHD\Kz񋾛W7YBrSl![?=9{?)P2Nr|F'>/#Z rep?ؚ łL*8k<:H!fid3s 9Jd{w_)U.] @uV˭ WD$]u]xvƽd _tn'A 0Df0w,1DR@gr8\BP7\rjVr-*j˹L̵:N% @ɜ'reBN(G$ʪTDp^(Q% rZL;=h6[@A?6Hb4LɀmnV bu[W܂^rmݸs'|Sz7,դB5W6t&j|~VUZdt,v: uv?S_@/:ݥR5P6<1:f+02W8͂I75_[S$565K"u B9;ZZ@ O>4`miOVO]r/iR&V)U]2یAÂͰQ-+D*By5mB7051!<~DŲM|b)czu<̨4:RV+46@PlθZb@RB?1|5X-@j5 F'`NW()N`rÖi$ ּ HP@&aׁѲ9N3쉛GCD@mJVJy Z\22Ƭ 3h4Y`;;У0هV*!9x4T ktT'oiAm,O>ADїjfmwʀIBR"0,*"YT@ELRQ(%Ba9| ,L4 AAٱCkS(McTJD<6V)MNL9{,9QP)d05t&:cnSOR*ҰU Հ6֙ȧϸUK1* U<٩\K+^hSc.IF:|u`nzk۷|!\3O<ޙ}u--E $^ hTX"ȧ)wN_X3=56j53V2L\Bn_[I _ʖIgC{}v~/O)DnLηdƦQZKJ$&o}n7nY P2׻c_W ^87, h)bk+f*! \,B )P+fܺQi=4L-9VJ'}RhLTCWN~oy\ZX5,/̻?@&ΝdvG&LRM߾>u)N SNhQN/vvw1L8Gy^-|ڐL*$F:wZ+7;ZpWg՛z("9:fї1Z[k[@g&CITQw/љ Z%\EP jx|:Dzh/ʟ| /Sp0X˨~7-wTlqWO7ܸ}60("%B.,0\ьɎc P/.mR`_oq $Edޙ%/ph@m%mr>z%xbk2DŊ&`0tзC`TR)֩Aު1]:z!Kl7f7Z tĵʔ S٫7:ݬ+abܳm3_XSOӕw%UJ)EJRDs`74ZT%P5RDO=NGW7bߜٝwQ͓up9ʝqx|swme/LPaT vJV߂Y} 8Ѭ7JZ1(`gWU/zdjS# *wnhr1cp1QxBf7NQb K[{frQ3pG%l + 9 [@8Flp`"#ȅPt;<"j7iDv%֊X[s3DL/~# tʎ`=|`j-% 9>BGȿ}(m<6_^= J*[ܽgA!Blߖ(b Ptdy5h5* Ð< [ۍ "Ok#f͔Z.B|$)`V@Riuu#rXeF DA!:KGAmx" 5S۶"H`ηL(<LtT7!_@Ǭr&unM"/=_G}I4L[m[nk\bpH8D-o#X&$k!z#QO"CJQU5l]I|.O<;}ûkU#1ps)u5# 1-]VA %T*;Ԍ~+pc?h|xs@XJZ *[0l7Pd@hZ|ï>鴶" DS1zj5ox\|bfiVHğŕ ŧBE,D˾X[T!kt*rU=3&b7AN$R1NOBLb 9utoo<yͯ x |I*1P"R(<ԉ7~Z`wu_LIC%FsZyHz)Ocɩ3scʙoݹ9N')lkktW|0kfGKŬk7F{j:jDr{dzǶQ@ITJ Ù^p{)lTp%!r'uk";'S `@pyӿ~k8C|.޼t~귉bйTd|nV7+'Zu2pvu^GX8@ ,;?>}_z_ʕO_=IWJp n)TI7r+! dg\|LW+5A]N(\a>) ÷oӠJA( 6`^*j)UtJgol{oOKb$Q(D <[Th.  vy[ȸWC"X,L?0'G!b1:ϻ<:)+!iCdW*LTfAU@,&GFs*Hmdю55BC!SU=ʺʥ5'W nHa-:M(љ,}4"ښLd<J4A|ѬVT(ueR5T*ɤb.>-igGQ:c"tfGWkׯ1it 9w# L2gb?;4jVEB] X(!^ ]YrUAybk- jbݛ)H "*"V,W %*ᴿP%jLE:lT˫ttR?Ƈ1**X:fsbuhQ1º?,(dZ`ǎH(krG{W"MzφR|::ϥ:tRX16w[w5|n?@"RL鰯LbGtzZC [kwb%N<ʎ&R=0L( wlk"r1_rٌP(g1kd`1#/9rqF4d")SmލRҗѵB]qke4D$L> Pb_J4 jTD"Va2I%ÕOE*&Pz:_.z b.1L&͠'P*$\ހNǩpƮ{ :/jJL"`P.Db{lShJXx74|"[XlRX&_Vї}vzT903%Dnw !>R؜$_znit÷Z:%BO܈d`=,P 'yL>p垝ihqئfKEO'L&`. ꑻ榪hĽ .F!LIf{|z #rN\Iތ;phi, ɎL2b9 \, ;Ȥ\ܤA& o]d` H B΀py:P PeswB{,Y_ib|d"g_֡T 6eD=f8RIIhAQJ8*fd*ìR*˯)Tsѿ{ g>{ W7?jG^%ޫKO,Lo;t X940|™pgfٝ;w^qX2 GnB\AkjK2ޥnmVImy&hm;w땒b6y9?xkY A{iO 'C9衽JWܺcgm _ty߱\/Nx<0mtl,eB7tU@٤I] Gn2ů2·N5[7$~{onRĂmwBI+D=`H+?XX\ٽ_&~M D*?[we$Soҷ >&o_[h,Yh(hԫ/96\ $2U,߽G2?uHR"jGGorr쵻]@0*b+ҙcTܞ 3.lPXhPhYA~m4N&p.O rr~Y`T brޖO/H.?gcu:V*%wG藯Nvrr:IPA x\nŊ^_GsPˮO_m[2E[( V {lB33>s଩Jʅ}RW_ Yu…cz~L^vA$0u%Yf\7>AaҦ9M~X`f&]{=MfW0;?={zH+EMk+BxDQ%©-ݞIצQd2YЖW,5!~$nLBKkKŠeTUp&p{!wU+]Jg fh4$,1gӷ&7};==uF fW? 9zG(3wo&hCGNNU!( =Ԟ~H4cP.4ןM vk23tj_hjXZ{co1Y u[GD*T="9Jh^P`bou 8܇~xi=Hl$6W,ȕ*tků;?_y1꺪S. ee1JD-KM!sK KFG/F&MN8I$w=PlMʔL*JgjU w`lcp+щ nH ~x=Z]GSl-zsx 5\l!plkT n9ҁ{t< mŬļP) ` 7؄=tF{0ѻ+ovܺqhPe H6|[fG TwCGcWg{ޠVAW|o4b:(eDFr-[o_{bt|K/_fwuE@sIjkSw?lrL>^&R9R=>Lljo9acGeb>D!(wxe^ܡprI~4©{xx RG7aɊ3M~񹻆n5D-wi񳕲Y㊤~'HE[a?e&^n8/z<`,O)n.ᓍXF%D}E'2~ o-KK!^ӛdPcڞ!]ElQz[/? a3Rx4LY"olr6Q(!v&r=vOc\wC@ n[^xd<6pc?6& < #i`kXh8/^΍y#ZAmm/'}mp]@NXٝxAM^Z= "<ӫx, _uR/&=Յ-Aǿw1I!@ B +&4b~[a)WoW&ϽM %$V܈SQ I26%\ Bղ{q"=D|!+ j׮^kmu͍Hp$강DV |꣎ ^BzcH"#WL:H"HHT>ԃ׹6w{ tkpU$osE@ |T)jX:d4P{˦oؚ;"k<&SQ98՘+3ɁXfo{lQȻ:XK̬[ 2O(*OxWbKޕ%cM*;3՘7GWƋis#4ll8F` ]׆wndUyp!B\+fn,e2V*|R IRr%d $<.[g{ouإ0QiLL!oy=kW|<[,T|ġJ1qpDG Sh\zbrizr|v5umjT"Ւ^ lVGhm_?n_ZYY+&*'M{3#TCm[S;z=WKZ0kىqcsk2wwj xOIW TϿJѽ4/XYxd;&erX8S\fqqv*/N{3gz,ͮl,|5v= [Ũ<y՛ϋWNu8;<#ӝ07*/sج IԓT~> R>ݽ=& IZVh(6$&k5G(.Mq=?9 ;^LLH*26[ ~g")T\鵦Dp}oAPPlr*]cCl`jaay6DSb^;{Z78sIOD|1\k68\ Ʀw֡D,ACuU2ϓ酴&_Xu{lmMɐBAL4v1rJeɥw{ݢ3鮜?44u[s< 5*ﰔ;Zξv\< *qRrfpIO<&oEwu=p,K&KW<o 0O{ >vs:?1Vr &c\ɛ2u'Kx瓱T` \L`@i̕e2ᒑ"99:G`TNC .1\2|)_ADL72)P )GgaTMH;MvgyLϠeQH\Bl=Vt/-D죨YX,)2.6D #zn&B>B1X" ZPnmϬ +HFf*~  ZA|x@'LRlou Ftu877( f>W*A79BѼ۽c谔[RH@͢dIhؑRY5)9=DK1t*\kdzgOw9O0"ӳɉ\"I,F),HFc˩RT<MMfETc1fX)4+ p ][%Bj KNoa4Z^(8k^`zBr$/B^/yE"i{ߐY_]pERȹU\J(L HPdLgɤR"6$?}˻ j])+24vW%ǎ*j]P:;6"JR4o* )yANQ6Ȗ`ZW :<~+~:y6&%Sj3xVg:PuK1bEH4.HL&3vЉ[/\ 8 %2Ziu}21z=+2=roھ{O! uAF3!Yj FTGM|*.98Iɂ%x0$N?`:*\:@e?/R ŋnTeL ,X * FZϔ Z рBt<J ƆDktVJ Vepx,<(E.a1JUt< : SfJ&\SV2럡{D",!`l(X*,iP 拷KR[G_7/=sf>tM:Ͽ0zr[ՙqPőkRk{%޶Ld y+>tN|5G\vxGra%5|7 1B1 !g7>ʪ;Y): N9[Ks ubtgxgZZ; .ulaΨ%!V.$f\fJ YN\\]Y+DiDBI!u*e@O{  "bm I!)@ ȅD9لsI%W<]4hldczErGm(0A@u LȮ]3SmZ\ T(dkJ![R!3"\+UVz&k.\qcw&]XHjL :AwUWĉ=ˏ~rml0CX nF&K)&ah:zݙn:ՠ6lU;;t\~3lin贠/.nVp-箏zkXkgTx]ᄼS-@['ٟ+I5N vֶKDSa}( x!"?Ums̆ ?ꯃg_԰:1gtMr_À $ooDËa_{5蛻?U_`T "+g9Ցmc ~ щ!I H`h*S}㵭;pæA܀;W]6R=lٚ>gG70}|*.}:ݙ {jm[Ȥz-jI1|iH'BH: ރuѻn:K:w$!`tԀ>ZWz߃Ô6 [`+>+QymMх i dgPS5uFGWTT* C[#B| Z)JeDFdRΡ_!"'ApX'qà S}7gBCӿTd`B A!ukqP~Ba(D{o\'ۆ^hd $g6uRTCY[牤t4HB'!|$tڷ~Ť>`w ;3((p:O*$fG:L ։GT U,A=!1cahkl0dY# *n.w:?Ɇ-eFB"a*q>Owz{}yB8Xrp&R^{}O^`ZQK cOWC?_ 䶾^XAFMHh0AX\= ْ' 5O.uh"IưV :V:\Ohy"U`2|㶥Sаb6%bRcj9O%"%!nM  2^ XO1}l][u=76=XHTN ,b:2.}w$UL/w S$2ŗY/hnn,(m;?} N9c{M>2ϖrZ&g#24Ï='Wg7r}v:mPĢ 0\,t>}iSO-;B;NjqBA"ݦ߾Ħas4B+B˓,B`_>Z'\_p6_a>pg<Me tG2S38޼Zaq$os3ˣ+={')"lu֊N!"3yfg8Sp ur] DzpaieApEnp|_3l1r9{ǐBQ+DJYtLO4w7Q4\))0 B>a1ZʆK>6'  <>+S!9a!7LDLI[zvbDl6j͌F"nyv+d|bݙ;o<d=zֵHmw4 |tZ5@]tm2+$K-ͅ*UB&=vDQh<R#UVD_R( ?7VL"? rDǎ۶c^D"Vm/Mv**Xu}k9G8̎^ nk_=ťTZeG:lm{v?諌1)y ޅZqoOwN兯6~uD1I7*}{Q'z1{&H'E#m}Cf/UxnQS.ka>=1-NYW?';x6Џ R{q~܁׀DB̹KC#Εzͦ+)QR% ATX43<->R:x R(5uX#7LH HEpT*H4N1;=#Uiɘ@BU"P+Bd& R=.R4̃u= D8t>ٽ{5¸^wT -:^[kr=09n4jt-[XhE2vL}*5A=kKv %2un“+c'<]1R3>{s0×]Xͩɧs Jx;ۧϩjr8m7n怊G~2엿gM#/gHZo%ڻ7.12W.|741:o"mqr\g'Q*v- !\ ̜gAwDtEjxb$X<[˔L? 'Nj>_ñ1 &9Cfm>0T+U*JdALMNv·'Ǔj3kK" OI{b%r ̍TʙLTFlR,cCG u& 2:5f1U4=aȰF-֣]aA_`zhA?ND/sls2Ο{~/-d2s3WvVK>H"RȄ*gfnܔMT$e>6CnoбCL j{O L"l&`KgdSRg?M|MdSݘe~τD@,xhUop1]=*l RV~0`B \秱;jlyjKnPd lѵ:ōFjza>x%5:Egvgwg{aX4 Tb˲cKKK/vV((QXA$z{ߝ.@vbLg`̙s9+lrSԔ2!V=T| `xyi[:fC) QcʥDA+rWʿ|BTE ܧ *+:rHj_ft3+w|"=V1~,S bWfF9&F[.[W H1L@Y loM?rZ8PX |tc( IeJz*v#Ez%x# ov*1 'ʨ-܈o`ƷsP(R 4-T tAXy8ME![mnh[h\:Xv--%E ߂?(+IQeBd2bP &aK+~Yrx9Pf5f^-'!H0YLLif9Ga!+ h,u5a{lIg Mm fY.̑z5muL,xrL(0am,1rG CA>t cD 6 "| 4,Q>Rc敋ڪ:ZfA&aCd/J2aH"uOZc [g SWS"Cl8Y[:SmQo=_}ˊ77}f>E)w#W^ ;%Cy˿u=ZepuCzWf}@?IQsd4S4X199/|9r3 X{k.Yg[5[af"S(㎆ᚎ{/{{tvAO]X=KcF̭79a_z gd0;/>S`Tr ӣwO^{1Za^wG̔@eQK"Rƌd"ygFX|h$k6Ư2L#kjz߼UAhzj~]/'V Z:9ܙW*5Z #Fpq~I.,h Bfmqnzr#=٤5s#Gxx|s-gC&[YE.jm{Zz/د[aR)bQu]-D:[Df)T_z \qJ%[,ol Gq:^i-&9YPPKK!0O$"lIʠ}JU`eR$叁Ҽ>vGf O" `^bhn#QaU_ȉ@܎ܮx&G> NKז+ʟ\ ں!-GZ-Gǿ~#m _&%*Y*P'"l۩R;eXv8i*GĶ`NbpB=+MX^~nY"-HdfXҸJXv}1-':&H;RXj単0q+rS#@؊%_V8X1$*[{s[m?t-߿KTʛ_}`D/=@+D>:Cd7*wAhM 5f`d7zn9ɮ!s/ %T(`UZ*1f^johMW\ŤSxFN}ǣV^{TӶl R>Na.tJtb.Læ1o2TCt2X!ARPD rk`7.up;Ls9#Zn"ƀ8յ:56řtӧ^T(Mf2ii2D2W_xo1WCc"OgZ.[JN4Rf eݸ4~`{s 0|kQL| x3T._:]Yg37L:U*yp84tK3Z{'_8|8wV}߯mݍ__b}s9weHqYX2Z1MrȞW~/l7`_,f:DbULCL. mXNÓ]5l Mzg Jo}f0 bB s|UsXn(RrQꫛ]/$ZExl\"0 y+.7תsXim$G"e mǞBf}pl(䳄OTF/$ҙuVMYmZ]"UMKX;);{uʅBX0 7DpsRU_1x*EYbY>f 04<BžѩO?tk7BK瞛QİT_ZBПh+l'ͮ|IKPl&.~*n㋥JlQ8RĮ"6t*0Xf[&9:oubI}kdr-@Xr2ɵ{26;<>i7*&iGyK*D, ֶ}lkI^oK+Zn1H~Xpfnl4"(Iij -XfԳHGdfWO?30Ć8$1A ?ljAEA C*{&)2"eB2!Rksq䫝{uC*ʼnJ}ų?~/2%7&ĐXc2ƇΚ.Oȅ]PʨU[,|m;DSOr]QacFHtT3jsP6s*&)^kor<>8][Mz G }a}mOފ#.b1 Bɴ MM`\Bܻ@ɔjwkBӣU*L!9,08"Ww6O\,g2Gh{scy\*=v,_O T]UuTP y|v:Ti.gyiٴ@H$+pjYԙm`-C C6c=Um:=;l6z(.[#WG0,Q}}m`cxGo`\aq֕(0^{G4.wG'jk&oI N ᅑ8XW|LW.Bo V4B| *п2o11vU]}MM[;R[_\YEDv5{n6#~ʙ_&SW~/;۾w>ZeNMM9`qst׉QBp"ihiWItkr 䂋$hT/̵4_݁6_{i6+ͬĪluocfdGo\D#3fU· J#s{ƛ-ܳs}x Ǎ{g^d쑩qdЪ>|g`GLUn_ PW ;r$L981702`ۭJɟ[ܦL2zhjjn nSh6\z/=zns9A@z.(09,YXN.{ &덫'-L#թX޷ BGv_A*qNn.g_|dvaa!d5 XK Ree @taZj`$ƅ ]]Gk1Ckގ=Lenw LΛͦ|:g4ʲlFdYTڻ|vjvVƳ+ cnmzw l,, D㴲xPCPbQ kR gF&{vٳB&q9BFhy TE\L'Q$ȴBcП ,$6ynйvwikHhTI JВ .RIb9X OHJ>u5Y=nԷ;'Ny0s} DZeW|Y6lmsZR̲bˍ&ϕ-v'"յJ 9jG̞ǯo#f9󻤞M0$kʏ@n\Q&l ڌIL8Ͳ0=^Y`s8|`H!0`q]lQiQk(([']j3yPpeD'ټ\j2|?fE:O;0mUNTt kO4M ]T&'sII%P=j3'.-HD=qS8' \D+L\&^| HL>K 1x/OKoMr;#s) 3WQ 1K3EX8zb 4{|nPHUZk\  ͊uj'N旧G3LQÔxXgڸ44O]5ःk׆&~QBAWCQR1;5fGl'1ϟ8.РEsKz${O`PMbvfjݱ2G8&)Hă4T<^@"%f~xRϡÃ_#C{M?9ta.&P}][[2u\N Rكҏ=m]ZHA%л qy%tN,.,/<30/2Iյ9qSū]UTz/ij'o] һؒ( _.*x0j1nll75M 2N!1V0o5O @S'}mKKosaa0}k: 'bas 6Y\G{~KϾケcGK*=~g@Er( ǰlfnnvl`DO1"5BdJĸj&t"^ydG4"=c. M.< B$G!9y_/* Y\ͣL44BN&6s9{L:uf@a<p&T"aK]Vc-S(nUh&<0DѶ.UGRMKKБG_tAȼ@ۮBv|b0$&'Sٜ\*Ns +]f*l&V1`roDP7 +8QJυl QH0G$S^os_ ڡx8ѬWkhI,{Zznj~x.)`B ?13_OzcHcyt\Bx~~Гf0dx#|xucq(Nh}Q#/0,F@h):zpva 334Ծ z֢ |PMf=ʡfd3ˑfo0%VlhhL z)A;o^Z ϭ3x FR+T EDRB|O<|lڿYǂ{`LӓS.=ΠL{;Ṙ7ä:ְ f[mceG4NY\a6gqŌB n WRrʥ@i7DRE:?ܷQ5KV}ģ F6L{jiB3(JT`$(AJ"H嚮ҵ/{m[:ԙ>t49=iJJ2u: LV! |1ɚO][Z Z۷#W /GظP^_XX2z.0^ Jf{bF=ąo@{&br[իH`v(52&nߺs&4]G#g~?;Oxrc?~zx8Q`.7K8h{-jevRW(ᵺ/C]Ǐ80I6O!BiJ7(&I9K{DQy"|QFD 2@UFhaTh|pGc P XB';BnclZK&~/4>T$]1M TPi$ZhH fr, L0!!&L QHkw?w"0ܸeVdVh' ޶ͩX@+fo 0< %_ݽڕ#59Z P}C\aX|$I氻r>EA72ٜP(|`<uÆ|H( J$/GG"e/6RU60YFQH72v[{Pt*hJz-xe,,MK};@R *i %v(?EĀnw^%]4VHqp(0@.vJS"F)+sxum-I;CPU*T' 1E̿@\Gev ɗAg#6+\J朮BX(l9{'9OHґ|8x|F_f#*9w+- Ep2AAJ+-`l,`@&| 1( d"'rqr⸃xSG@ Ek*ɅҘIH7e6Vz嚥8cAK09!M0/%NUPzL k,B<F Vרߘ+D>XL I' XzbԨ^ &Ϭ:a:_YNm2Bx|\\ Uj^]9ѣUȹx:DV*ML@6eŠ^ el0alM3g"jJRoy |e5)B;7waL(;SL2YRҳKcj`Wmu%09m]ť(j21N/tw?%R\Fge /Y; *Fkt 7JL~rsRO$Y , _տam65kVa6#*J5G]Ks!B|gv=׵߷于TCˮvKk!) nT$)pӱL"{bTҶ4pkQc-fe7| @,^}a̗Syأ؇,ƑcBK\U)13s:X`< tҊ75*pzvI\<LjG3#>H!:y)B.a3/"z$,bR%!$ Q _bQ79w5F٠ >Xg\hʴZ1s/n:ds3ᮽ?aXzhl98=p&3y!SDR?UUj +sUe9k0 iI7\2D~NtrD)s#ɢ(h> N4K[vZ3H؟48Z)sjTKCܞk*Y`Bw5_h|s;yNI6!nVЗCpPwɓƘd<䯵)d0BA,2ţ,Tf*kns:]|ե9`;.]^I<={,0^H;Ȥr,\"(2uO.\'Xhu)%YWHg%Y!h8,0ch -h0D(tHg:O2&i//FlN!( yjrtCD"oHsм "zjCP R 6h۳1[yf gwʓp9,)h>J"*J_޺Wjj9|_FD*Q*2neoc l4͊Nm{sk##~b59ZP E̢oq"Tf'BR <1>rXĈ'" #{M 9O7yBI¡q)R?ҿ3 1XM+B4QsC^\%{ͤCTo9+b(1f|rP](T Ɏ]?.d,EXw#`VH%Ox{[1>xzgMFo\σB4eӛH`qkf6pT}K'vUܘܬ]<;}sMfѭ 0,_ݦzeE*DL3 ,qncE4ȳjQ- xS:r8h5=6cjr%'f(Xb^Nlo\^Z4]]Wy,&Q GZ aύe&[rȗCAUCKXI0脬9X⁉l(2߼CAVD FXzu%#f~J6FqQf{tNq NjTs}s4hrBl &$"ʍ0$c"xheI4)g&F ,$^S CP $ 4#n9 Dף2/y.:H!ieFH'?77W lߝJ1QYY~EԽLu)@F(DɰHG/7iWp!_R  dC2T4TwϽo*?;wɣEN݈kFb2\!}WV\Fj6ݹwӏ\a4D0.:B8H?RUeߜ/*Ͳ/|:xI[g>̹|3FX?ր( FB>a0.KmWFe&2 @v2p)ԤJ m{@,l  .*RukҤXne* `+1}++cC\ 9`*YyʯU`OWNi8|+4TnKRωaeщ'?Ǡc\s X䡖)|rrjZݪ^-w(L'#p;WDn"0b\1zE S(L0}9aL1MGpV*.O ]JxTv0*4% E_+S*V! RpW"q]v^~rS ގ,˜2`uR6M,xY:RaI\_щPi1P0Ŧ+H)@۟ov~%UU@sQFIq½m%\%gKd+8- @ǡLjn[iXRQYV?LZ$/.S0Jh?:~'Aj;Xp43:RtN h̎=L!iJbAmɧT^V+]0Homalfy2t}-)e:Bfp(7u:(;B,6ÞF*_kw0Յy¥jgt^Td2&So,OWaAWzjٜޠ9[~bO& J4kL 5䛆vf닥3*x\*K4j-'/\9b\B-_Z^8D0m *te21!UDU-T+;5{}|&zZṳgO|2>л EU.PXLoOZOLqap}{^[k&PNWq~pa'N\`.X::]r?8}СՍFyhh_xY&Y_o_m"[67/|g9Ft~4S93?12/ ˡ:w__H͏&DUHSDpm_z҅' "tc{vvVT! Fx8Hvhph};=j:|iT^Υn;;o\ELpXtTbS0W.,,-#;NzHt}WXчx,B7ݍ(2dKKfOkgKv._ܝd<xbVS)q/4Wן{]+C>78 $/(ξSg|3ozRcd(1HA^::/M /{TߔSi|xt|GE8OC<M䳹d`n-C3O~a7E P{P4"ZXgQ`qޟ D{DSUuiwO7W],c7'xsiRX5L2;Z|S{R`l!P6ح6dH@+HfZ\S9] v7ޕ*u\./:k=|PDQOS"%2@$8 Fo^ ?2"~NPzNhp)V=6-m8-,m>gfoarYg[*׋]?MƉ:47):Fi(<p Xgdg#K6F_ͯ #gw9y1~7קaIoVRV9ybғ_x~ar-Tξk]N2}J e/g^72hql0VWv̬6׺,l5ljoh#"stH n2  Pafʆizbe3᪯rI:ήDh3 e671ϱt jh$Éd"ƻ&&FL >XzX 4erXjhgν=if_.Ne6[9$vwws_>B/i "IX 9u?B҇N?h}^L^ٴUᨱ\- Afah*!KU#iH59u;?w('c1dT82<ɴ' ~s;6M =;JGRP >{O;HGh,}w=I񧟶7tX+s{ ,pIa2צ+iA8?#6NYh\E#֦O̖ju5f0y2)lmjV.8# 9ǖƗbHϞN:]׾;L8nF  BTrl ޜ$FbuX4Ko=kJmnpyL6j7V2 e6"Iɸ>U_6 \U쿼_#B^X`%FdqefwW/]2!- Xxb⪐}/~G#ly] V4p@nj| ²ccX"|z-$ޝb(h eoNB!Spϧs<)& q`"fo gbE mIqΗ(L@$ @r/T`1H.L%A6c΄?͌މuR$Q?W"pcÎt.ot"F'S-+>`HM;6Fsni+(drB[M!LShsK0x"tzN???zȤf4;gL!y@X,4JEy|N!-uuΝhTh]+a1ɮf+PVȰ%'8DGE"f$3F+F٠&?扄|n}(Ǥ1 b>B ,OU7B! wH ?ޔ,0sKׇ7ٺL&sU" D\Ybr!`>pqb\ EؼrLRD1zGw795MUoS4[~ayiI"WrPuuվB&5v1ň7|%ٺ%>b9e65 g65DTg5Y3bCZ#i!EVq,'? iˣG7PH? V7 (4TrQAY,3-Dmh:ls/_>6gSiJ3Ajw+C5$^h 2i`D8Atml?KD| q)'|tJ8r,լtZ.pq*jg@O00E?pA%(*j Wmvs4Ip" Rp:ɯ|\C~%K|R< $C@+c\rۗj Ӣ!wD¦LL"QB=uOOHJN7#O?eBLBNe  HNp+M(~1241eTBTdvm(Jt.*JP`ںp4*t"rRD7RTOt>&x0ř PK\lPKL#F content.xmlvX ﯀HY4+M$IE;XkSE-Ka AhLq2Dxӽÿ~wl}qTԎ =v/~}W``Źco9hkEpϽp[ɧi.&NۡϦ5{go[9+2> |}}>pN}<1C{a~~q4 y:*fzۭүтsSV*z^UώEh]>\;_h\jp7,wG~aܠmZ۴p&H?.:>:oO oNy^T|/(-Q9l3xYիDY!FxQ埣kp?l?\ 4d|ʝx~̠8h5±ѡoYrUpw}{D^ts Z1HLaćԅM('·'ӡS#$6R)n GQhKx^yE&牷/g G\  hYp=3%ĂK%0/ʖ;eZ}mg\a#7q$|x$́ߗ~מxdL~*4'^۸\,WuڛK~ &0O?خe3uqmʑ'Os߿8ʛ/̱8%t:z!cby(\@d`Wz̆|b%Y}.woʛ._`|376Փ+po]cYK} N\M.tcI "vY ei1 gk4B1fM? ߧ7۸g V-ٝiW9e'Ԏ\r79 TCߺ2}H T 3H-=^4\ +?Ma30 z=="m9U 껙#`. /kDQz`9^M~850hDyӔ1π-F~`g.Av>\?4+>a^A/G{nn=͂{<ʂyMk@@^>,aqW nzzgaǾ{=u`r/~S?9p'g2?3}:H}Y.^pwLw85pxp?li;B}Kx ?9jw5w-9DK};:j*ne^Ɨg=Cf[cӛgD㠬UWsj=j{":(@Ԓ10kae/yP6hv{FTڲxx0ö2f3pzPK^AE2=(^7g _ h |A >}kjҧZ=[OTҷ͊7MZ_=..gUS5̊7L={LMyUo7 #gVʥ[um?:(N6{<a??}H!녴xqضsm+ʝ'BƇm/b0&6Kù:/zX6_Ʀ?ݲ#p|5X~o7ÈM۵`r8~ cS?j2&zW_iZ^=WE5mRAhj{yP3i?27V~hLh1q l?¤c]ZaͱOZl7BX5Z} r }`hw:$x~agǪwO$XUS@/$v\_U^ȵ9r9#rNTk$HOhըWx%;=19lgZó@lA?(q8}P){"OYuvP)_ aVгJruNkgكJ߳n͝J0?{9SA57VɁ|`~P sl$g Uq0k<.9$?۾VüYA 9$?[i"g 650?A3gkۖ0{aitG;H?HۙVCwk`.gV\>sH0ޭ*ʾ~ݯnXU:*vgWxvݰ v5Pm0xvrnzP#VYj*Cxu!毷Q>(s6ˀ'@}P.m-sG`L{+sG]O^=W<<:Dsj߃ #lkWdI돰WCV?7yMrן{îγpv=~rk~Ʃ ӼpY*X?zZǩ} T~xh=Qo7Z-ӣʞj;?&N=jtd=ZsWm}(%SkYZ.kg^Ҭ94niiI251iI{5 :BgMKBԀ kZb/&]5-y]S_E3LSg һ\VֆiM/d3QbƬ[L4#7{H&}rKrKV.;_=.d^j5}rKv$eMka-`zj[-X^O)j:!w[}?5ֳKzqdc-h#%.YQywKn,:.LiLmeZacZJΠe z:3j۴ ѶwqVz,*c; M=H;M=v1#@TG~h1z2S@n`Nk[X֌Zeہt&]=yYʒ>RG_FeLa.#fYѩcoK״˭-凭sQ0mm)?cԴTca^|Įp[vh4='F[_V,tR 1q^{{u&qm=Ҵ1.NIkv=l)dcm+ ծ=]hտ8GRdQF7QO;:ݚ[pƌ;h̺!3nki 3/:#+>GËo%+ol[ӛ6m=lz3㶦fgx ζ%5fEъՖbzwTWc*mJXixզ SiSL췳5]vζ;[%ޅgK3R"GL3fA.ʲuSxNˡ79ZNF߁^G۾Hz.=yq~x\ݒɑaܙmthN~ׇi|3_J|B=6G?㱉y/_˶ ؞я71v8xmY8}i ܈(~)SG G7u#~S$_c4j= 3z}/Gb,l *w!=ҩSv96}9Ǜ ܃WBw>I4?fx\*\,Pau ¯N]&aL(g{JscB>)W=> H_~rUR.]~R3?9WC $}£5R.?i왟tF'L I.Ci송$~.7ga?> 69fw-2Ϻ謿pd\HOǀ.c<2R \&L]B7"ة D76) _̻9 @m3C@0@4$F杀i{;Apiolth%"wzd}___\]](F;al&p킨Px VEVp(l`l ܊Fέhu3ahrt8-Wd cV 7bn h}H=m`+=: O~ 2<yRxAe=lN%alDn1&ODZ|E]Z \)-#o"㤮a&X'gі͢ 8Bd>)LNu1iDP}NBDm`1H ";1.?(p% X{IG//Fa89Vm!; Wϊ b_ɟ Z3N8mv;Sr;/p5e7c_pԀ5!s]AVk҆|[199W$ucb.z[=1ݘ% $ēL.Ыã2zǷEJRS}ūKV^pYɸ`VɸP1 ]5o*ću S?2a^ZUASnOOV R?vQrq"DȦR̘1Ru,T G&rV`>NT97g+C&_ l?()~U\dAQӞl <;/W@ 21pyI4Q% 3f>d0up\`X'3&3V #!H#~ 4&{:x>I,(٨ fbuCǒo"M Ag+1W4r^X/&c~?)Hd3b- z${&`м]$60.)\>LCp!b,~Dz jcM 3&1(jBe%"N( + .=K2!i|oXN=Z>5%9Z?us|CګWWzlL%Aօ]t Ҝv8@g ȕ6&~%P-n_odԄb}n\$\xno{-R[:zqe@-n[0֯@5A RT4jJ_>n>ǣPr9k"ee`H Nj!E+7RFN "QIaB]6[D)l6ZIS~T;@ Gܙ ҹ(ĒTKqouBxi&!H$obx{DGĝ)# [ٶF*I@OEwehm eaj BU:d}=4[˜'ΧItGd81Y3>zd^5!t$*ypiԇ@CN"qu:nz3cvz )#2f^4.h({.?NGl-@<&Y fD"oÌQ:`e8ӊ%zr]牶ƙOna;#7JZutaʸ#xeb?`17'NV“ք爇go Hy' ]UI_ZΕpd;>8ֆ)&A$o}VS%!Y8&DʬeQ#m= I!ⰐG[OL] [FwXbR.px$icLٮ0|qGCG; 5*:|fF<:%5`}h+bE@"<_ZNOlx. +.bO?>,X`쀘4qv_pćۃ9;jQץf pl¤)[kp@F$ ދg9DbgQsMRNr` g.$$玘'l=Z@9$ɱ،_H"^Q&6*c@˵ &JH2hMDb<@xT[]%Rlne&wbP0}EnFjH yR<8*y}MK4,+9ųvrdu(-V(Q9#Åe qc8cBac9֒ӣCs2pUύZv֪:E.,z!΍?|=oahv8u,zLb7r+QlQڲtM)z7aOX1P*hPפܖی a9, ÀM?EF=gq[Akv&/R[7>ێJG͸CSk{s^=;ov`A+(+86؛ 0u`!ay'O$*)dЌ2 47oeFٷr gvw"W]Hf*$(" @01F@W0- mEͭMf6*ȋmX1>'.=g!8.(ihYΐ$mCՍG5x w4Fe)G?"ߴ=Ƌ1zxwMCepa] x FQJM1NɈ<  4k^1F_Ωdeq5sfx#em$x&σk?x O'sI %N'vIB%D1x/%}ՂꔨY+JՁFUIz$g { %/M/hqA'4N^.T 3 %RX)gq^>)Fk'Xq-"ASDZeѮ޿+<6\?J {xIBZQ+:q'0`bbDr@[$&Z+%h![2!,~38;zyK2@a2Q̫59-Dc|i𴢫V@ΫȘB+̵ML뮍pQ9"{)"QLbyuaO~rMP2cg1\x6O$J(+2@4"\!i|m$䭴"%C C$ؘ B) "cA)"#R"ݭʉm'iYx)fQ-Wk+'hu.*x igYP884<PgH- A&녘fVuIYXOEVS;[1˲ d\)p[d'ͪ3`H qZpRZ+>"U QPlAce` lm˒Xuδ:@-]U'P qTIEdZ\B 2+AUoresԌ R\ [~Ek U}QIe:s=ha#ɵ5E,|M7ZLZ"aپS2 L=2T/ɂhu|lcEb,Gfnc:DWM1 BPJW%#d:Eq2ޜ\x6`̛sjs]rX,3'3$oiQԱ;(B+c2w2Q$bcwψi䤐>?;ϛNˍ/]pvMErlj&=C u21<+? ֻA9wSTJy2Bn@q>+$ /p8z;T@Eo;Q{8*=N([wzxeJWКʊX`ɽ.80:`^oDGmR@gOYc-f@I'C2pBjqPIuTjeWâɅ&҆bnD17(Q6 A.J(8@ֻʱ`h!}l7v؎n6.fKJ]z2ME> O9dg9f 쵻^IF1͆)cP&b_뽵L|P1pd~|їA]m.3 bFtxG=Oŀ\R!JE3-AOw̗@ctR,Oƨbش@7*y>Ƥ(_ Y *۠O18x{9SuKИG'Vb CX'1MEҗRdL/.KYѹ\S8hpD@{3F{eoj_KLzΔ1.瘰岪ni[ORۍB/Q1psAEmh@}H &첄pR#-gP7F2%U= UkjJ왢̮Xlϸ;?:˺Bu$}{7ctH;) &skqeek|@ <#aL*NNkyKcRxύOFǢv5bߐb׿\40! Ix6ܖJʎ {(\¥n~t屑AsM&hDQZ$q~ yF_٢1&k$X]. ؖ6Bi'Bka$X9Z풯 pZ᪚= Dk1sO6N)B%[Ve6u ՁEe]Ux 3Oԝo5ȲA%9\שTWύ- #ۗ vx\Ľv>;+F3`8'ЯZ8K\Z\,iq QV鿀 '5R#gD!.Ɋ9܈x2 LRӒV WYJe/ d%#sBi2s$Nt]׊ңy9J||TS]8 og_?o{؟; hXdtdw{ivZQkt3 G/ZVP_Fݩ[2Vj5&e>6j?~?9{Yz]hMM0f/y*!<(/?ڟ=Gl(oAU'bwȰI@#itQdxpx-'af37DˇKjqO*;ku'獳z9EHlG<zp5j(<}󊃵ҩ܌{Q,0٢VEJj1 ]< LFs0ir$#JsWt'QtC-6}Q)\@T/sg6:T,s:/dK!R i/鴣 ]qu6EX"m^If'IjE#{.c5C+}Gs+Z{S/uhǦ61sl.̹u!Sp;<Җ"Foh}To ׈8G,P"ܩDWBH(), $G\>J4k+R%qM݄5%ɂZbZh"E3[Ŋ v cFnPRnFz[R[&ŠTPpӇNLÚU$HfD;XNNI͢$˗bMn[dp(`i'khzOϊZrԑ)Yv+L,&V>7H+6s>Z_=;-;J Nfz~ğNJB= yC*oi?*lcY8k0n1F<,'ލ !es "eS[pOzQ!=<i)֪BZsF&QYJV&;dӝSGH@Y|4G5(r'gb۫k(o *"Hbw6kTX@Mz|=r+=9ˏ+ɤ Z =&\Bn?+ NJ ;VҗVR|IKxDMY frC_voh߳}a-_Ÿ,@|<`kKup@O'{|dܢŧ% Sl`8(PsC$A4HN*v7q`W\(hCtȨ6@FpjwFmR WIoN?_dl{fGdfdI$V?}8ct*@^kjQm&&YiPP6S0St :죘a,D zmɽ>de06ɋs.U^'l(MkD c{R{ ov5o@[KgXTc)}/wI(G(;. L\<4{H̡i?a.AuDUn %q :)nW \\1bW*Lv=ܕ/}⹹Y$2b6<{F݆qot G C ?m$$;Pj&k1Vj'ͣ b bqnf?+ә, ZÊ$Z, YaQrmYC+yaKfFYP9%iG)[[/S x)UN21xIUmES($yV@>wON!rǙp)I*0ι(rAkK"&=y.>6sҴ6V1Z}kiE8Qv8FJŽum,ԅj/l7lx 72+,&w+pE dRi3OW!RVa:[6+dav qtq J[\XV-X`$$A܍#;#6Zš3zNۅhUm,z6tumkhm47o;uGcP J-E(HƒI'7hP$'z(Dª6F c^n  V AE[D()۟fѪqI\m{=K\B1G/)tTvh %L)5+tȘ4wɍȩ9|2VE;IۛۋOlc}E\|"NZyBS"ۺKɘ+KBR(`: 5gնP5)xv@5#_-RVhjE8UƨpVdu<XFxRSOŽ|(<~\\I*/YB* 3e7Q1orXVoiu6sdn&1g͑ =<#TjFJk;oi]:q.\(54fFQ;zI M,d1oՁMu~x8?K}'OmA\cR:F>{۝"v?*$kWҔ-Q]A<ȱdwgK5>ҵa=fm"ѬhB cC,*)iQm}81tfeYO.Ulz*ўX탓8v8E4d;7} b<'/u8b),J/11T#SDm$oeٲhn!J" J49wXR%wq& McD5cәn@aˆS2'q8SL|ڽ1 (x8z?ƀB!EMTߙLӒ\1L[So Zڳ-ZlNSRǼAP]|m[k"U`QxL%Ppu: cW1Acn SJ kN_ $(c9jVq H64߾: j8/0Ѹ' LK`"W4)uh4ю1'"3Gvݼ&JFc\)E x8/v= TY]:x `.pn:*Q%b$Qq9|~+n@LL{8j}=:;zyӧ5jV!@gxRM:ȼU 9#r$:sNtQp+iQ6#ju <<a'`HѮ0 )fZ(O<5I k;:k3ifZwv_M*ƫ8=O#yRD $R*ЅL033GYDR,#c[xb`S,t,+pz(xm;Q+-{#I*#oxh:_çbA\ijY2x#͔SaNNqT`I"LD=eX-'{<'ir;Ζk1G .D榔-V"z6UH焰!-`YQ~ܳMYJlfΕs^x@{EUJ3mI&ƞсň0$_"ƶ"`D»丄pj\,s)Si0_6 ^y{٬z罐k6j)Tl]][tŰz`$K%%9 RL2abFs3/$x?,n0sM15NѝxuA)"co`ȻHFŸqd~Et7UAK]l+ET;Koya=m5DХc[Re-BQoFy=O̫й ]=; 6<5`" ci=iRC,F.3#O"Af'+4v.WKȬx>õu͉ه߁yzL3n1F_剡~PM2 n6 =K{ڞ e Hd+! Jx;Dz+2Vqz.q * 88dCXS'qd>ۊEU'Bj.?l |q)dz"ScJ6Y!B$AиvGX,1/攭$PzFrQ$$bK=O+?Rˆ^aL֪LAB"[ž+.bZ[1Mм|--PfD/1-lV߀i=]ٓPz@hkjTPl/}?(.r'MFdr(B=I@aEJg`Y Rp|sirϨ7@_'l:_1␭nv][D'#1Ɋ3*DB E8[z(vɆ1З\}#ϡ7?\jfe2W^Ԋo4e򷫦ll4eNln4e v6Z!Vt6¬t7[KZKNU "h SDD(;U}3SmHz+-o bMa4z B:Vcb-k9h.7FƯ2 $;\x :HڳR+62~c[W}lF | urK]Mm@s˩'V]_`1~w̘qr;,>MґʱaĶT72!j+9 Jry++2J"4z*u:ouwM"ZH6W꜋ׅZ)ZdJƧ#Y;+kUnkFoݮҔTM4|,@ \+ߢRqXq8>yb`&t-qD-CfmDyl| A1ݿlLTǜX$UBJCU#%IM1BA*.7' vi88N$kl5]Έ6#Ew6SLEQT28"jE s)Em17M}$jQD -p/ʼn .h-;Ax'7՞VGZq.L_- 3 1B3O21Z/ $-:߾ L>F:b U]PU/q xnT~UiVZQ@*逵V@{XVTd;I:K!8N׿z]er=K[ĵEpA.M\1TUzg()av|>ƫˏ~Ya-eK/WݔywWnhwq3.E p@ɯ^Oy=A:?"i&"7Pyvgd`VֹPݗtG8 *| (%A.D`NQ1B "@(V-Q`Lw )bZ<[hAqgF%rt"BtTERQႧY+dÜcRub4䍃M! ,`d-mUwUQ%\J%l"Ad9dK$7SEOp\a;TBdc17nZ;e2u> s\ӥKQjFɰ+.|CJ7[C(',G`Y(s\"ޡ&HtQg0YUt3 K &7҉Cԕ|3U_qP 6PNIIspFqkR؈ƙ}Dۨd%߃fڦ̭,!qI ;oJ/K)1 #ߦ*(&@NHG\ԛ0C jZ?3\5:1_J8W,Qw{;Nzg+k,űEP3z)I)BK!7x83QB:UFTS6 {Ck"GvydA#V )'!|5SiX&+&pM)TbEV,7k@M?P3w‚MX+rxNpȑZ[yȡy)EbFgA6 U:PCnfjb*׷v;HyDx ¹cn $2<F+0R~d[R*4;O2VWO;4!7NVo_qUDGsYJ/c4PKQ&TPKL#F settings.xmlZ[s:~?"{%)M!雰Az$9JriA)[ޕ+/bqJsRdӰuySx_cB-0AK }AK]^R%k45b50zu)˞,ԘV,77&mѽ]/ QXUתq~m)JjLS)vX~RbkcpoVݯ|6Ĥ~c ('r+xK}摙|u}U&t՛U>)QAs& uRȧ- bGYre v?7jyVQ <{oO{8_nn7yj>ptqbd?*6'n1mT~OwxHnʜL4QNsIo ΖݻviРڿuݷ9k9z\PM K S≊:oW<#n"PTs' ;(0`i 2ET C*=+ZZbh z<4P [6кtWZ,ꓗP$P@F LS|tlCD G|ٰl(/}SmxiOb*S&[}Q2i8U4X.j L Ftl,PۦఏC^Z:HXH;P v&tE8PSz?0vyTnn>6B7 A? 2?TfAI&Pk%!ƎA]cs>*Ս/`#]5ŕ661iKaA"JPs[(ssk$ !݁yODP9Cƨ+"פ<0Tqv6ϯٿLU"MHPb9H&Jjq~RХ,g\5TOH;|W\27e~ ̒#>Ke7X VxC%p23mPM*- n<e69|ٙsg' -A(p6m=L9xk]XЯ?PKC'PKL#Fmeta.xmlK ;[ ax..jI"C 8{4.9qxMZޅq@jn.c!3//K* o*=gAתK攣UQϩ[%MQ9J“5mۨ%4CuF_@ e){(3'P={z%p<{*oyoUSYV=&:-l5^3^2K歰Mm~6YUV/UVw>Kj)5R4ыM]> Vfb"Q%vd*?CVL !bY=>kg;>)I}Ys|')I}yQhϏA@B8#Gs=h$NɺӌH֝fO̎C`p`Oȑ=hsdO3Z'}^> m,Bhsd|^=9FL,N9`؁^y1y1y,cv{C%6c=r)vR-<J[q#'qYbW|.vyVZ;7bQ{%zB TfѻVOs#u …8)q[ :J٪"EJБI"Yc 4:mE$PMf Z*'%M8 *U b#p-o٢ wF|x'6%?[C] U,W,JXۓ/R1N!.NV2 9#?lf,L@Ը S!7R\vp/ʱXXl dL''C$^a6o*^ Ef+L'>y I;Z>-[@e5]>TJڙ(tl*iT$]x> \K{qd1eOzMZ7A칙 o`Ma7^9큛[w-mJv Jv C wL  c1Jr@܅@L_}h)(m}9m yf{3w6gg6*a njL] Hii_7cݴ_ mi7tgԫ"/?]]>c =x*]G=O[:~5 kHW;TC%m_&dB+ۊVq8ב#}mXTrn .wm2> }& ?׬Rfhs]V7Lx%PἬPzn[c&lՀzʨΔ[|z&XޫVB?S88\8wq8F>)r2gqӓdkHEFA<x 7=~X }WQܪ'5[c'6ҿm#nK *+r.("j[~~Gp3ͥ:/mbgַЎA:p+t # }B~vv8R׳[`Oq\r46k3?0w{ߋOn@8L}}zr&vqFG|äxݶr[pۀ- =~Y568%M5''pmӝx}T2a ϛV? iɛoR:mХm֌V`_p]pl:K&MG#!YBDZLQZ!t^Pj=3:!F!#1H!11bBCR#Ho6燼rsP[T 锵d`m*Ircۍ\}uÝ&,u|& iQ m+x("]ƹmfRRߦM>74s{{/{s3$7={2Qc <KJ8)/pcj Pmt2(ÞeOMjY 1pDAjѽڐLȌZ5OS/+s1PG~2 w6@SS4N'cS lITN+V8**(zڢ%2ʞ :+ BehJ*))7 #m8[G)Nx֤z80qO}dv,WFCl"0ع+yr(&*#< X甽 ޳DzN6DHأR0 v$ɦWrYpEv8={"eoRBԫo31Z2!l=ݮ}A5qCB0|_iodlO؃=_y 5[y4&9IY֤G&sl7.Qܑb6jܴxv-)^V\ٺؐ$PipI A/Juʠ7f Uy,VҚ2'j+؂R9jؠm#NhwNFqNe qH9YkB’I.&I/ Ȁ[|@Pld^j[{o6EEwg+\]e2lgFڙ~^ +e-~2HIj"D`2%1A-2'Rփ+F)4ZMC!2tךV/Y&WaԌW4+ij12/{0c|y/^W=_1:Ɨ _WM7~o΁+xփ̏߼2=ρUa{}@w;#<: 䕁<yyL$I,Wd]VkBTojz6R ډY~41uUg_Ϋioi,k4oO%AmmE#y(y5/$Id ~u ۍԹ(ԔoV ztS]q*'mf\rDdxfvi/V;pc]Cw1G^2Wq7g&F*ZbCOL S$/{^ T]0b9ueͥg٩ѷvԻc  j\'+BD-V *IGƸ6;FG PK4"< :PKL#F manifest.rdf͓n0D|e`9\_X/.%}]'*͡]fh8C;4`kg*|>y&ڸ^jj~ *!eI^eYExE%yL,Ƽ FD>} fy%N:90;:PD LچL(-&)}܂Gm-c1su_5R`""?^v}㧓 Fz{ ?VG5'PK=PKL#FConfigurations2/menubar/PKL#FConfigurations2/toolbar/PKL#F'Configurations2/accelerator/current.xmlPKPKL#FConfigurations2/floater/PKL#FConfigurations2/images/Bitmaps/PKL#FConfigurations2/statusbar/PKL#FConfigurations2/toolpanel/PKL#FConfigurations2/progressbar/PKL#FConfigurations2/popupmenu/PKL#FMETA-INF/manifest.xmlMn0" *" Aź zL%gcDn$"*{$š4S6C*i,RYǯl1J:Oi5ПÔ^e >! 0*|O:920fAt@ܜw%;ĕ]-r 1LVJR&0 D]((NS^aqÃ.eE1b%Vtu?Hm WuG۽t=5.\ɇkEaMttc>[[Žx_Lh~z||ww׸k7`rlc5^(~n\z3d03YgK! AcEVۉ2ENVf4eڠmmwgV4]Hs!`:>(pO}?^*(-lvwNĂG;!ϊϙD"ƄW:?ʡzz4e3+yة~xady dDʝv6(XaZڦ]}W$Ga9c8pA G^|yH$a$Cc&@v 9 riw5+5B;̕#R0_@@pPi|fjq~a;*c)^K8b @}lXf#7|/_3'lߖO!c22!|ԉv̂idCQaa6K'MWP u0v]5{71nN2ncX5!Uh|dwƕ?Փf+?_0@ [{igXWO9a߱_,k WB$46^,U=%K.!l5ļ_Xώq^[[[*)ifvtisϭ|*/`u5h-r "'knd0rrXM),iˡ;ĺ3@dN2>^%BIltM>pٽv1)+be08`fZþWxjx2{ΰWx|xjVWx>G(?7/;K6{7S^}'ZdaM^~֒lܷGY<.zŊק B*D1]xm5a|<g/uҲt5T}ھykg/`e`0>cve辺va/gިl^>7 ]9aŅxfpWGNιi(=}{R {fZk=U_õ^<\%8|n8|d g /vU\O8ÕmYg /~ 3{ lJp.p+eN8_p%NYq"'VfnjrϮķf|v ۻwFo:p"Xˋv_\?} ש>1= OyUz 7#,P?NNp@ٚ+*aGKUPg#cU9 [۰1ۏ,-TiyvmWxޝg"?OE?Oڡܑ_á3?;A͚{&㟝 ~{:Ρe~!93V_]W5~:}6/Ŀx_+}} ]%nyZUn>^!xBV>7yWqLv8:}BW*IL{=ORO&c#65kOimVKOWwH=8wgm/z~\W^?s6QU @?_SIQU}ReeBކyv?yZ_zYژٝhǘidvUE"YFx]x}3+5ʪxm.RVϧwSo'ζS}h8X~]_3T?k]:UD-Kۤ}rZ~vggmpS>=Lw``ZщrUaY96oX_4vU{v=YD`hlEK:fV0qܦ2 ߮G#g*p5k̏O34x\? ]mq/t Òfqݍ/UEX-nTD g׻kYS2G}2>e 򙽢۾(IBS:3{ES~ ic7{֞㺿_h,ti7+ug^<_lX'+z9 [򙽢)4r3DStDFQ% W|]j~R=-eWN{Z's_6`iǿa$_m.3jd7:V3%jMs.nKO3'<]zK^f9aE+E^.B'O2`wc]_kXwxWk;K }T[S#{8,$ aBC4ЂkN@/5RA]/'@]5Oڿ)f͵^<_8qoؽٹ5_{=|_^FXmk#zǏ-x8v+B{~~/]mCwz1wz{E5EB]_UES uO]UOv}Dީ#9ܪ¶w}.ԵMGPbSG a-ЬbGgj:;a==<^u"rg uYšYԂkZ?šL7p%*UMYY=IkkӓGxk,JOBvk8tm~ROQr6b.L4;$U=:i uQ%hғUeXk7ufP-P yCQSh~!z xwPjXGbp].{]yviwZ)f]n(f+5MZ]PV]lhU2lQ2gfMYnzX6 -p5zWY-m Gth1˹$[EvY@vM!?ؠMq_h9DxѶڗ#KwuGׁ@55fԾ[ҺXҾ^O ȗ$tQ ߆|mI&`v6i_ulЮ܂Uc[,֌z,p `Wmj5< -u@)90\^9MN-&[]\ZcfE7<&7 ޔufo7eMb u[]pO;IWB;I-َogzz]Vn1.T{ИQ?(i+nw'8xH@OO}[oXbq҈Tlȋ3nȋ3'K~KmGт xBA}zz+=Hu'[YOToeS?V֓:[ewDNVA˭l*oC1ʛv{8d]77x077kj̸Ow_z\SSme3/l=yf5=n/bLmV8mwTTn|!-oF3ܕZƌu[ 6vL+xrW3lckx6D1bEM@-L"-p:³Y:vCN,s9v4}u5VG0; 0La9  <43xP2W}p]GyCjr0nguxu1S_‰,zt]k?SI! {DM_}]&}ϏE][Fɋ,_'X(/Zu ''H9)Vkc+J]5r.3"J;Jk]<1w+Oz_%ҕ'ȿZZ(istIkd5򮖦s=>;Я`! &ƹFNdHuayTmtl_{Qۋ2_dw 1cXQJ5`4eԒ_G̝B<ƙg!{ԉ{0~,c. !> ?3 ɠ$g]25KG_B8 x޽3[̀b>3יm@ '4,c'm8ޘȕ62..p zAE $µ2+M ˝Mg4L,M1Bj2?ή!   gD.>dPW Bx>ere%l`aQ4ɷAx f&4<M@Ljm8+->7c3TNEf3ǯ#6z(!ꮨ5:y!s+ 3fђ2a~r*2+Zwd6e|pq\XM3#/E aDn2@V-* Tq[Jn TaҶTBx'|cbvft$0?ou?s2n6IԭyշVf:X t+\0_V5r@%rMp&1 j-)hHoԅPT/ +ŞzM4(g15OgG:`s ,zO:Ct#4Ó]C -` G-O-H䏫:@}B~Bt^x"+T9Yߵ-X̚d_;@>ЌQ]ghgI|>'6aC"U¶ʧ =P?( |lMS3ށfۯ%o ?6e`e ㉺ai8,jfzW=v z(Vi 4s':LpܑZ4$Po8=Ac@na ̶ѼQ 'Ң#0*y  Y'(Jn 4+1 耹 LH3%T=LHޚɯĥ5Q7OG|\KJ`џ,z 4"~ZWcЯ$A< mUV@16_K; - bzN̬Yq9|u7n~xn}rYI:zcA?xd"<@CΝR+Ϣ1ģSd|;Ki>>^'O~Ki<7'bu[A'f=D~͎4뉾#m,c:(Ǫbf#6b6>w?/NtI9X]O, 8ug9paӽ'eo 6|#6msE4 zIp={g.鍸>^U6ȁ1},^ LFc3#"Tg [S-Yd`X:+77*˗x`@RI"4kCkhՒO+A35|PrgF9"[ULV+l;S"UI2-άN$":la KT2Q#s` g?5~ŋV\-.ӑ =x}21gẓPȢQ=|'.^C$ ]Ə(ZhRfX"Od-T {*^EwX4/H@ŗ w Y.@LAB\Z@õ?W M(Tc| V9CƝw:vC I# {>n3 O|G'J!㗅p9Y4 q{f`3\ᐟQ@pz).In86l\p ME⫘|+UMJЖ]l ٙ3A!g3ۚTwM5GO|?N_`[Um;dܹ*mĶHǷɂ_ ]|M<@ ͭzV㴻>UapL7qNQՆ+俎08-pE2;`m "qgqA9 .0tsKCg}_[ 5U4%S /!_^]Ƶ>Q'JӥaY~|BwNBwi|lէE\ !\'$zs1k=& vBRH>-ܺ~5p=g#g%Pׅo'Ao &T)RN|/bnjJQI^9lqk >Bܓ:U)QOzS@e<+MS"MIG/Ӵvك|gFt^*#ɩ[ilF٧+XƊm"GyWǝY!ΠR[q"_hXK`@9Rai.Yf v#oāhج!Xjumf-(=n U6/ʼn5c)֦Wrk9Xh6'ftfe)qj|~b6u],›B`(DS2[(2uߓ6ʬÚ1Y pkv0BD|u" iP!p=ON+&iv;'=:``VӸ`K;(YhEB{t}Mh }pwnIY>8K", !z.¨)1} J[i`(/S2r:ƨK݈3k"N3-yK7sF|+bj  OrnɲB>[[:| 5C>AT#mUѹ>)K)]/_VH8T~MV<ŭRga3dC'yG5H 7"941E[y!K;/^ׯկV`*\nnZC 2(eHރ!ә=9ܑ-4;v5iFM|loUHyEp8%9W\K17_u\i<qG 0cL'6a5(WٻdA{?sq-n,ƣ#w䥒| mn%trU ;P;dל鮃T2?elVZn`seU{-04+͑ߘ֝'낶:Nx|džǨBHˑ;jiTYa$@m0QiS)4j*}?M:0;m20B?d0wZ l^@) -Z*fW`.bQ@^ <i^ZY ([嶒lF0yiݔ.\QLY io>TC*,OԘ@xɃ eR޹5S #R($ո2IA<t,!JCv ]#IZi=HkzX;tpN"1Zzܬ(ɂDwOV5i*/Eάy9^F bVp.g'EvaaȰ.Y.ՀRE@J) * Ye%AUru 2`ꖇI*2As؇-16ce'o oA rqDğɝaE d6I{n-ǥxM- m{b^TiR!TQ1q Ճ諐#$&kV[;r*˨ ~mK-T l4gA[Ә:gUk,C)q|+'a?6@i"zAp/sjĹe)R!}qNpꗼ{T1RDK/mުE܇\XyZq@8=̇ 8JLTd,; G$dš(Q ǑzGDbP("f4NsC{^EӛI7f[jjQiR\3n-Y]~dLky򾟼q$\5û) &f"Q?vٝDIWRK8YWLWUu\V nEZtuoQN|lhV.ei'x0݅/3Pl\/,A5" &pGʑ6  -ͷOԢ*GLM-{$PNH& *,L( 7Tأ؟Qng<GrCwLQoqw̌G5Ec3C{A|EQN ͯ,'iWboR'\#)z=ͅ{#&]3(YC^{#>/>񯁅7(-`cB% ^cxz ooͯPAFXo:n3S\1 .k^8HsrK9yrBcW:4Y)w ~KW#z=rUe;RR^Rnn%ciw 53ZkuŊ"+VCg7W-)S-ӬJ}H3,%)E*t}a>tUNj[I~psj|zn @0[JVôZ=t)#S $Js o@t9WR77yZ0 d>F J ;rIIAչΌ&g?0 ceXa|D 8ч*AdYtMCʒO4Ĵf &k\.L#sgRBvuԟU447KE0AYG9@0m~+c0JN5tgc˦ߐ%ilfJ="1]s[h&.-U޹DL,1}!= pf+5iTqXT1Vxi-?V V)8E'#]5Gw~2Fb&$۶e 76ENkbb}OEe!(n*u180N+Xs};]P_sv&rUmJ {y1s[ ?`c;X LLJN]# #z 3~ eP9wONjƿS "_[MԽ2;UޏP̙'+٪GyxP.Kq;N[h!0d|:s;$GQLvw 7H@ԙYb oqD-#Ri"Io fgYC=Z(2z‘Y mڠ;Nhgq`o5v>w4y`z`}NN5VV՗_9v4}uitrJ_ݾi4u !ATLGa]:#jHzj?f ɻwoN:%A]Կ{u@W*'}oȂr '(iMeRmIPȠ"aE)NjiȨX7$7Y}9̈6pFIl O(^VOKwP[ I`LJ{THKLm2u!tpGILgu r7U놝QRoI$(yךVvl*^/7SS滼t? yd:)[`\G5")b9fhɱ v}I0? L>Ń¢Q ]=&TڝаmAhH^KxĕvCw+6Hab+(A=O_ko\kn6zf{_><]ZiFgH?`ӭ#(B#xQD8saer+ﲌD5UT3.+T N['f[yV31?f\ɓɣ2$ΖU˿nW9TfZ+GT‹(+S7޺`KDu' JIL܇D?M:h f%oЁqZ2|%lO>s"*qU:{ܸ"}2OLI G*TNBtR+*.`i(~ْ.eß%jT)g&e,\TXo18c|6_% l·rZoR'KD$ (]\mecGs-d$> 5d*"naCy[WΒRAqLR.y:ʀz'Qق.zˋ;3}0udotuOIɴT&$׫o1˝܅-ܟw4݋R~H}C(>zKJHYy l&Qd#MtS3!\f\NڢI*"FD^X--vf%f"B@7pw贤JBR,Tp$$$ };C9W^\z8`crpٸGruOS6ã9豉E,8Hz z5 6qpp 1 &K"g(ˌO)] Z}=T2Q#Wږ*WFJxYbS1}K.HUvTHq[s rPM㧀WHJ(Qi>)R`kHd3 ԧ"Tł6$K{ PMWF!_bQ“H,޳: g ~LĪc+}(jpz lZ_ }zdX0.ތ5@X&&K~Ě,4iVq٨K-uO(@W&cܖvީnUIOFz@zX#RX&ADF\ gG:;Hnw/e-q'd5@AQ!-Ue 3]WtccPO,U6$sʗ%^&[^G9/dK|ŭ+Hc$ֈ7 7L:3(r<=* 1F*(^Ij'Av};kZ5\{ņw$"^wr/(>\=)^-_(av+*آ`Sw9VNWnI Ւ(sQZuiɆ)_&cOݨ.鎹Z?GSO^` H`c=7i{VzHah C#y}R4u|1 ިz 8fb+1MܵF܍*5޻׫jPN4E#(?Jվ+e+ ]=ո/" T)5(.0i:)J~kɭ, 7Y' WB 5\^\/uf‘9L:YHV&㞊H%r|b.mLhJ=o0ZWiR8g|)J"I=(V,2e"g3r {X(ă7WDƇquP * ( Q! Hb zJV/\0Bqco;`Ǟ*8t@&XVQ5n_Kh7i)} a剤BA`^^*}+}WŖp,r'=Bݞ[o?] gT3A<G7[uEV4 2ZS3쬡(2 gvÈZ k~ԛ=Ѡԟo3UF^\'gx(2<672t|oF cpcyf{l;' a5^Ĭj?up|V>'OraF+av+z';-FQԡ˹mjqS\gitmA'8HFi}1a &6g [GaQmj\. %kYMjqȔFVRԲt#&sWS[oSdeܛ.NuX]û?|09⋺S=9)#`*4SRdG`JiO,-mO-fϫ=V9UShg̻aw@=uM'y.f*$r7ì!-ߑkTMMM#+ QXt)Moh j,uT3bV0@[T r, N4|.'GZbo% $!t="fA ٽ5BkOK֨~#JVl7RNJQU)4;GS_8D<ɖ?2BCK+P.`u{mN]%Ι~@nD0RNDDď؜ڊx߹W2\ձ?WUE)^kN@+\*s2:Wti9[[3j IQ.v VETДNBO gB;b~]t8vJW/*p%-;ыnԓkN\gyX]::qBs[d!y` JKSMTv㋢7l{L? grFdo-/iԽ2Dw2CFQ"pV@-!xOןzajZ&;hQ0ԲNy1kqfNnԟ^ o9X^-({}!.¤-vqP](E+`2nЪh%+bn_Jt5ck ӵBM tm 1/<+` Y7EHiɌKz(_IHy}`08.8oG z8 _yk"oPpqb{÷kJPe~Xf 齉w}mRKеDz+5gJj Wjt_9Qbg(>'.(0)|熅N(&ojPˢB Jg)p1;:qnUS!%P_E{f}Î @\aI* V6ck 6#g08|0s5 j[fyJ`d&*?'y»ױ{!F+):CsFR0R] ^)|.W&[:^3`,OF9pQQ3d.q|d{.(w ɸK첌JPv]i2 TOPVUY{@u:c' Cdz8/zF6}P(Iȃ4镅=-+ {5_V ukD(q+ǻ㲔"fHS)߮jO)\+Ќ}'k # l#]f^k f?TXUBy"9Ktfbl=' )mr%vSn{彔8 lN<aD dIfӝ/\#6OjbIBtċkT~m;)##1m7a '@tIt,l+ySܚwR Wh52 (1N-O(@IW!36QoMVHrjTȼߘywP<4T:]G)f.F/o;hYnyTw+$gwQQʄ;zP`]tSK5e[frT+sjkLz)Y<QEuNuIc-ձpobF j8H#/q9zܥ] M/.IK! /?t^֘ĈPD cßo3ŶT_|ƻA ZBg uFsTf']M`V<}1Td3&Vc3Y{_. :3a_C=}%5*jbt)Š7XkfީQJ(ɨ V6sYUo͑eJh'*az2JșdE :MdmSD%+D _n &b×"H芳K:)flWs7 '<ȥq) 1xS saypދ8u3BޑHۛ*%|InO'M /pyY⎍bt 6( [egu;n[5SUH$_#.laZ} Q^.^e`0/dbI첨y)7jڧx%j(dsDԟ9G8%4-٠Y!CEfwX q+LjP('GۖY7q$Is$fd )Jfl42xr߹@\pHE xWq0)l8_Ʊ6]'p+%ȊlFqi9Zś ?2z\=Jd̰.\=! 3q /㌒4P,eJV Oeaކ.jTYiLڣv BN +8rb#0%9b%yf hIR_x>u( `\4+GO2`VCQq:Yd[~qVѠZGJNj"==Mm%$p ! Q-ϧrgI>@86DJ[rigfS[5`rLk~xy7f1Ǚf Ǒ[ pS$J 63))q ?xc7R7hiI#{Eÿ_7X X@ `vL;vVxݚN㻷qZNx ZѹD±.II: ?Rs +ca?-VDM13ۓX߀ Rәʞ}hn*ݰh5R 3֚QkVAYyZ6sޜ9+h?W 9h"?dO@JNH;PX+  $*OCd ciCD(֌3PSf/ŐXzUtYz{[F=6d&R9y}h&5~Y,W{ VMR)I!hҳ3@d#CUN,"U7H\BĪ@8LNpcUc"y-?4Q %קѱt$Dp*1wǛSf/~z(eÙMmOO7YVC @gAaJݜcp oB?XK%Z @Y5\s&3vdϝ̪r2SӇ+6&om>־Ӥ쉲RK/` *MG mvK;A*4ISX$.ґ횞ӛeUZFCUeR+KądF Q:,qЖ| f5\,T\8? CdNC혈_5)!ZSՄNڱB=[gkd>wPV ׮P*_ݕ~Šg,zq#\YLi{Q;]LxRl0FCIֆY] v8jjN( gzqy#Se/R$7%xV՚%@삓s'U eq?k!Gsɍ+}IjWX=;a54Ш\סRۧLI-zK"\`P}afZKΨk-+H=W T͙iag p}jp. =$z62&^4%t ,!|>EoTV|B㣆)F?wtUR" b1ZxCfj0M0kӅgSĮ\mb0-4GՈq#Tn] 3 i6Gk8ZdDQj@]0Σ?Ys?6LUB?hL`@<9R:Rq:K4!f':qcC&y-R߹*ԘyP 2Y&^Zf2 p9p Q酦r@\ݐ€4NhN_#6Cy0srܷ]ܥҺ1x˪RT5{7&-%/ϣI񊼠~xz!/<˥8>S|CI&EtPKB\PKDJ settings.xmlZmW~w9FXgHG䵀-mtH$_w:suè4O_÷? ={&BƜ]J_a1_F~U_lGy%sI% ^g}|]s$cYg(!:O {yvu݀m?YӘ- zZ.p1/jZ<}Yq6矅ڮ~ 9/l7cʎsY]8mjʅ=`ZX+m$ïGR)р)VmҠqJ"\A9%x"`NS{q2awGußtJэwsf.El)?ںF4ʨ!Gt8 tJ M'l[x?2FNNbŔez:ڢhi$\Aj Ѿ mtm?a"8F]tō_?aE)_{Nov*=EZ _騼cXX 1@,"nM N e?)GJvCm80ClT$F![y@95]SXHs5w̦f"Jufg2ZiR4fX>x{Oe ʥ ׀c"Q$I' 08s3u3O)&K zߜgag36mUA'O':W/!AtoJˬmm%"DeX[ܰKE)I ~iJITX{}K'~tP0Ń< uy48ǻڨbM7ǠwI 3 kѤs uI9jQr^֨6M|GL4?c [gվuCcھSL[nk?>Ni`_i28? Y_Fr 74 2Nޏy%wdxѯNJiν)lAsz6QsO8XnPݼ13OCӗJhPe`@OdJ{~rZCqP!a{AN ˁ 󭵨oej'%<ٛLOQ爮D3 FOc Qs +=tne,RiؖQ!zEd)D-f Co ePo$vFjYu$I}@jҴ*}.o(On'x:f˭ߠCXnZu֠ǩ~[CǼPK&5)PKDJmeta.xmlK ;[?Q&0,ߗI:Ytɹ߽pcX&DQB1ͥj6PJ??K&lrUY26`JK% KLFrlzلz8јD4e rv89X"WCHZ COv8S8W1.Q*1 _,SH%-`FPMG6xr_Mv01 ..8!It_sgdmAoQL$ITfYsUpf/}>iVc}E[?-.Fy3%tG74F8*"|(p*]7`8σl91,tGLmBLw9hdxQ 6d)U/p[f%7 Sޱ(Q ^=7x׮PK2<PKDJ-Pictures/200000020000016B000000D7FFB7454C.epsZi޿#@B;}ʗ]@,+@Fo7g渏=0ϫbshZD,W"EξW7zW)nY˷"Qţ,WH2[aRƵ* v*ſdYeε-u̅bM!n1mHaUǛ?C><{*oyoUSYV=&:-l5^3^2K歰Mm~6YUV/UVw>Kj)5R4ыM]> Vfb"Q%vd*?CVL !bY=>kg;>)I}Ys|')I}yQhϏA@B8#Gs=h$NɺӌH֝fO̎C`p`Oȑ=hsdO3Z'}^> m,Bhsd|^=9FL,N9`؁^y1y1y,cv{C%6c=r)vR-<J[q#'qYbW|.vyVZ;7bQ{%zB TfѻVOs#u …8)q[ :J٪"EJБI"Yc 4:mE$PMf Z*'%M8 *U b#p-o٢ wF|x'6%?[C] U,W,JXۓ/R1N!.NV2 9#?lf,L@Ը S!7R\vp/ʱXXl dL''C$^a6o*^ Ef+L'>y I;Z>-[@e5]>TJڙ(tl*iT$]x> \K{qd1eOzMZ7A칙 o`Ma7^9큛[w-mJv Jv C wL  c1Jr@܅@L_}h)(m}9m yf{3w6gg6*a njL] Hii_7cݴ_ mi7tgԫ"/?]]>c =x*]G=O[:~5 kHW;TC%m_&dB+ۊVq8ב#}mXTrn .wm2> }& ?׬Rfhs]V7Lx%PἬPzn[c&lՀzʨΔ[|z&XޫVB?S88\8wq8F>)r2gqӓdkHEFA<x 7=~X }WQܪ'5[c'6ҿm#nK *+r.("j[~~Gp3ͥ:/mbgַЎA:p+t # }B~vv8R׳[`Oq\r46k3?0w{ߋOn@8L}}zr&vqFG|äxݶr[pۀ- =~Y568%M5''pmӝx}T2a ϛV? iɛoR:mХm֌V`_p]pl:K&MG#!YBDZLQZ!t^Pj=3:!F!#1H!11bBCR#Ho6燼rsP[T 锵d`m*Ircۍ\}uÝ&,u|& iQ m+x("]ƹmfRRߦM>G>gEEXiϣk\GB㵼6O;V-vD }B" @&(t6"{l6NB7]KsTѺak[FN(. Z}PQ5wS_4R'2'6"M<lQ1+zؠbr$'t ub e5ER( S'N.Oq?^D=IᦰشJ9qI?FdJ 03dh;V#hC`H*-EՂʸ-`:\u LjF(gX)nؕG `6n#y;F*M Y)EźBk†)Fr_>5a %qB/Ϋ28oy~˛LWe5Rl,}<֮:(p6 knH?~Md!)6l؈)2_ۢ%[Ҙ?˪Heetu~q*r1j)%Fvg۰\}xH뇳#bN "sb\r;8:(*r*9H/H?c\ƒܨ" kϢ`G`S\c9aUh7P2+|fj[!d>篯u i +&D ' B6۠+BWAK@NvS'6Pkj5חVB`v]U[=!ipWѦO6p/d,):8a2rO ¯`@ȣWz"P%r@vq6rxCs{8zdv_{pDkF\2 g@f ([Mfzjg3o˱׶ ?-<.qyp)O1F}G#W+} BQi4wR^̌*!I~UJwP2jY+ v8fxDj OE'5rYŭ&y M7(5;c^ðz1r`nvd-N H7Pn2|X/u}M; G2m{nfv3CM Ow_`@}[\Jō0q|IT*$od d)XJcӚݜZj*(X}? ]QR=1. o4e>hd}ު|b{,l=3Jvju0]DQ[~?vW(Υeo.!$b<{e_0c|_2_1z /__W 7~o^W<܏%0ye///^8"M^BwwGx"'W, wI.X6'F!iΘT}k5= ZosA;Q8_sL>Qgj-E2 ">5 ]`q Ӛu-^ʜdcEfu>pf 4tz`?DW4baBdt(So -qa]4}{ӷvK<ԺOք-F[=$uy&ڸ^jj~ *!eI^eYExE%yL,Ƽ FD>} fy%N:90;:PD LچL(-&)}܂Gm-c1su_5R`""?^v}㧓 Fz{ ?VG5'PK=PKDJ'Configurations2/accelerator/current.xmlPKPKDJConfigurations2/floater/PKDJConfigurations2/images/Bitmaps/PKDJConfigurations2/statusbar/PKDJConfigurations2/progressbar/PKDJConfigurations2/toolpanel/PKDJConfigurations2/popupmenu/PKDJConfigurations2/toolbar/PKDJConfigurations2/menubar/PKDJ*99Thumbnails/thumbnail.pngPNG  IHDRg?IDATx}xGJ+f[l˲e[ff 'C4^+sJWH!)m 5L'fI%Y wk%Yfgfg~zy84At[w`hRtiRtiRtiRtiRtiRtiRtiRtiRtiRtiRtiRtiRtiRtiRt*4ð0 "_! >R0FF|OxAPFɚw_|FP!C4: " W^*6x9WfO:q5UHCMǃRķ`I"ASKM10k@ BcS X!!a4NC(@@1 P'~ 4CtB 1q1UEY #|9\[_;=̳ @ 8N;߾K?d "g!uϞн҉ˇ{85o2dl_| }OܴU/ɹeŭK|j4*0@BbW{6 g<ɀh>21՟I yC575˯+l[`ŽM|~F=]I"牗V/1>WXˢ?ܹxŊ}:/'ʋ9݀q9?>?-W/~ad !5;m9:{hLŗirvS6ݽ}ҳIm6ǰiD"0OQ@W/[8wFAeW^[{-뿐 l;^}꣧LѦ~j̙>|[;Yf=[6y`Ym>f4YoG mU:)ReU8mXU 3uVf#GW!H.JV̅)=66LuCw8O2?Ѳ3r?<=&;DEL,#V裓^{Ů~Өƞ{#EVƦm?%pSg{o;cX!t }(7ؼsOL!AA~SUׯ'D'kߡ8LGN>]uaT!S o7ЗHW!H:,&9,8u\t! &KG7k"dQpWcѵ)BB]i ֥,J3Izze'B8[5k >t5ڡ6YDrBΝ=Tw*auq F-6X@w6-['/`#=fZetUA*ھOQ{]0"XԨ}ssO g;4#5mzIZ1o~qm뼩smmaز=9ZY^v\Տ+fK%å9o%기C Y_Mᤙ׽[:fZW}@Gu4;HO#6Jadl %v]U)ʝ@ V!:(0.)D`JL/ L2S23zz|DnE>$ˏxFq8^WȰqd]` q55[k<\% WHC#"~â4Ql(BJih_OK>| 0"3mCSgai pOW:4Llrc1k;vB.T`O5-AH @,AݩuUW!flL IzW:DU) f?4+ԦQsW{| IOKRgt^ܒH-9;mBmŻzPC$ 3֟sbEaҬɩzsGMneymEРO=pfPUj3=}h䌈n[~ɈLY`slPry' J(Hm3Cx%/ۻco}@.v9V~ͅuWZ E ,#*O\_}:/X 5z`h=vLKsE mb-VDě1kah p*誂T@<IH1+Dz^@?br)DăEW82Jf'.O@,'m"$U1 +`q8,B y#%ۊ ܉KH$cR?T$" Gce+FW 4EP(K7Ъzx\ bC =]HQ[sfxɉE\wYp25+ iꤿjƌJ <;&7+%KY/pU?󘡫A ӢaEG؂ 6nlרvmgpiyE mI}M&72Jf> q8=A-]AHZ^D{/=w6н> ySaA m/im;=}m-=Ƽ$*u)5H2ꤹf!t!4 ./ >VvXTC?#ϗClL3GbI2̈9c ^ S$44~ gl _/+(K%YQ̠՗4T:x]>"qPWn_`<f e0\۝ׯ^p1 0gޓy:z'PIu@!|/c60cw PpS[J!)18/`?K KH 'sB ?'rifɐНu=)j+Ta6 wlذE0( <ܫ|((8$Hy.M-3Q_>~pƙ;8~~=GxdvÁ=P`r:FO4U:RD3O4egegRQyu AE>s \!ml̼X4~TWY}tǡ~~S?pm;_m̜5έ∌X^{bs/WOu͝ZmQ93-g2G69%M5ǎ-t؏5[JҽG~7?6Fů>3^S~o9|ap73#KwTds>|>cRJlǟxR[}pd軯8U}{ʕG7?pg^~ɜ~nܢFޓO?ƾg/{w^^hAZݥ+/9Rs-ծsW/0 ig+v qo<2`  kϽس޷x![%4GFkG^swn=|>痟|cfȢvo&U+}]]Vdg~-~0 bA_~Y# '2lֺ0.عѬȡ!#D@_wiWK}Hgg-}CG]ޱCD]Ď շGJoRn^yL S]Q/+#Kgi,;]޹rfl 4H\_x-E78Tm]EP;:;JχpYH{OǨk(51 3h3̡ 1/)3:gTB@99M^zW4<5=W@<'+YNaE*FIWK2?pOK 11{JnɔhTJѥ}IX2o_ė Rc&g̦$Ȅ'5 (y#J6Zȱ{\ g}-\.E8&y䚷~־ ݘ}f2&*h Mi4s%ϟWQ]s8JyKS݈ {OPg ^y/w]vb`o]UeZ< }GOLoo)]`o>DeiGvll,?ZB9ξͻNw^>k)LZO+MDD4KZ뽟AKT6X &•H:!!2MBKjN̂-} uԼ)緼4t&'vu Xo6$eP[\ he+n|=x۽g_l=>8l8X$BhYH&`)ȁ.5ֲk.͛w9cBP[3bfm;9 D:<%# 2Xtl)ADjw9vlFɼPu0!Ð>1-vm16kjoùrW,iQ1cQlEG u=tgwO"%r{%s6}r6DSһBEL*>2p(XUWɔKJ 5o/=p R I&h5+TyXcyVyTen}#ӕN.Y v8|f g|qYAI:7v,Qn= IO?Ph| JqE3-7ego}~=SŹ0sփxX w*Yrsك 'v N^^cn~W?nj8t˽?r,Ο[|s%,ECh&*xv.[2t\(Sܹ0ciuMktqaR`_Fn@tϮ<[z!QB`$˷|0vtϧP)m@J 3BQX@۴=v&VS`*ʭQ\"O YK`#,6 FNml+,uYVGcqR޿+)>7f:O *[(qn sĺ"4ɱ>p<<;in;zT,ͲIi)npw+-ohk\'<̲oxļ%bzzR3i@@xmsoAVP󋂂.mB(s=٦T5փTnEӿvݠ?dسO>yC' xׂx?+i֢MZ)a!xXiAj+B51Y% H=T D/ƛ *N) ,qʛo]2ms'\|X[{| O"2Ό#3/_qw2uZ*z]VUKzv&A6bшs͢ MʊO]<~hҠAs<.'>xi:lv&u3"ҩݛ{Mjx罏>tb@C`b'1SO[~Bdr0urpD, T n*??FWj1;Vi6|uϘ;ܑ]ٹ38>>2jGrr봬{ FzۗH㖭X[ yo_ҋ't/>qvʛ{wO}SO޲K.|#uUtWwalBUmv䞺nE*ZtK 2VK N31gڦ追#y| yttzApxGcH!e{FѤ$ Mm9*^-ه6Z0[]z&v8岙*Η0 4_zܠ]\V{ۂ)X؜bnڹHBbJO+=r".Ds~XUYS0ly9 t"tLִ)Q;A1 WmYƽ> 姴qr>t3+%qxd VPPR+@U*}od8 M])z.& js#VÖY6/* ~xxJwlbB3"N8}!-ŨGB]o)3Xl4w<)iMK+*]< ?ñ%;r˕ ImDQ`ql?\Dd$XG i9Ժ؟c:8&%f<^ǒ忣J.^ .bsQo=Q@ϴi2%ҕBSOjdJШ<0ҡdb0uZ(FZө| &?2>~qsQTBI&P;p,4E^hȯ1AGW.EA* SAG] ZϤ俧CDD:oi0MF"wD! 32*#8 Pr >f Cf4qrXybt5ү#2VSQ)wܰ=[\ٝn&L%B媥KRdnw^ɟwsJ D][/]!rp:(E0?kDK9>r+:Ows֬㱍Y {<.O~MKH&.;2ެseby4MArÑJ޽?ߋK[XS?zEov^ض O̙&cw8#D7瘝Kqe tFf1=V,;;oFqo<[_|GB{v W,[<|:Rtiehl_U"ى>6xj#}3;^ǔ&t R EyӘ\!WFuKS#=teXSϾ3n0/7&_ؾ~fhnV^ŚuUJX|%7X*1Ȗ.N.E<:-w>0>$/9.APPGPrf^MKNvLj uҥ0rc`WGׄ6GP@yJPO.l#8ATj_7Dƅ YꪣK7"YAKdЁ*=.rw Cv.KQ6Z+*-`F8QHϐ h@~)_d \/$#`˒yG/l27~x#خ~ ST OeSѿ/KRrFDb}Hf{>j őM| (Ԯ1o Ջac<|L&4J2X@q:-M_: W1LY)ab Fy wTi/ >?$D|)yDٌkj|)B vwh\>S`H%9L冐 9p5T88j7}F%/QoDr Kۇ-N]d$LFq0du4ŤY>ǀvB4&iy.q/9>fz'[Sf6;zNN$ LfC^s9f\O0!9 a(Jb: X5=VR>Q?:iũA+^Q҈_@8x#@qb$!ͱLKM[G-,NC.LDk~<@y=؄ 5Be8d^S?, @֪*oZ931_2{D*3۝APG#Ҫ72jFKqϜ}ֽs!m|Z7 VT"N*E$L)8wtRNc[o릶Wu5Զ5֞Ed P,Xۯ\wNʋˌA{Ϟl1V6Lvx^-r;-GKRJC=gkڲ3SN8]nذ+"Ӥ"l1nfCaMg;ݡ"_EiJtU)QSxl@[ $UUM q |U6pU%F S 6M]n^D\fa Mc1LjJ=r,>-{Mf$ZG & L`oO0 3=#Ù<)]y.' CtZ##=ek:|K"ͭaw]QyLpN}ra=^ =wK/Oݪ*A!XJFjst*Ahagdz}n4w ukHkzji^ZxuWTGW^=`D" Y(친Sw=tM?(҄!)Ç7&^ik290-li>ӣ?[qۉ=լ0U3ؑya>uo< ;OTa6[|ցݻr &Rg.۱+VrDBz ti僳Zos v 8X(&.?(;-[vM6>9v@[ؒ`);D6V%˄(+C/RYM^dfI`wTeI$ƙ6Ejԁt:a5=q ,{ʬ* }i3fyixlrJmNgO]C'K :f]eQ C"cU(u+d$le.!.#:5m1ڰIE,><ΗH{<2<3Kdj:S"WOc?~VjF F: Qe#vu Mhؙw gg0X}$( ArT,ϊP.GCS{xd\XDw #u͞Zt,=M!-.:b!vJdU1ӣG3#@WOe1"HEoǦAy1FGFGu!.t:cn9LYfӳ}./vǝ^Y5Rf B#"iy%KW JN"%9Bl!˟>BʯA|:s6~AcDȍLʈUy}`MDy3+=/eeuvbsa2 x\.5:tX"dD`GOwVv9@qP k14\ayl&(Di 4׹Q>m#>6j;Ӳ2\%(ӃFib >"3g;3RA8las⻷mqgNin:pwkԉ,]0DH=NN@L/,|m଻& ԇ0p\XP9dr(V'qv`OWa$X,R2xtao`ȃ - K̋)Yy.,& ` V~n: katRCdh@m6T+z_YHkn<3S- ^&@trzZjrc|OZ:{ellǮE%@j8w܅^U0[Z}/̢Y1]_^v>M$$%6A*jp}6'p>(ʤ--aᑣ.Drt_`23&$8$_*&,Ij}hi0Z4JiWOWRx}2 =| >5\EajwvT$7l[6r9ymôɃ-5ǜY~C|fs؝e̛̺5 .GP!zXYRrJC}m]C}dЃ0r7-?7:p )NAqߐձl-lw?\1NJ;ggba #d^r0osh/ K'XssFZQSSTmhhTʳx}7eb^2:E(%WJG=C<$8HŐ=<.`)Bo*PGy (LSSlQd hu #9~X&hiN`hQ[`a5:Zb"iRlN9{q14T K5 :00<,A44T%=vhap$.1t9*A,)\eM<} >0EDҫ:1Vvy2:L"fO44X!>*Ǭn@P453n1 UvMn6G"}$H޺{No l>OAnjYF7!!4u\ eNZi3XFr{h ʼnܯ¢d^?%Pwad"=g/XPzLT_= ïlWO/%"LNќ%t!OA<7nbeKNClmWF02e`u!u%t|.s.tu>^~sql]6dS93';V0H*q!nrc3ҠGN,A)h"DJ&;i4lf neJ~rzRedg#u,J+/tO]D*r3N?U[{rvyeUNc{Uַ%VkbP믶,ngexxȧ?ޣ/C4#S{lVi3=|K!6USecN31%F[~ڟXvӊ?m뵚eZةE[& A0FT|%ALI&K"t1.8;T8@ p:N^ ?_< g?dwCl&a4fVa'0FHIbq53fMlLNg17򅃃U(|t.Fjzb?}%r2sr'J4 &sߢy Itp7֥g'Ef>XllDh No5cpOty<`syz;+4AFA6vr@t(NDré( r;Ѹ* E%*3Hx~I.z>} p>y<`J&hkG&e_>%:QB1j2J |"(b$ED@$1>hp(S(! x㩷qyP`x|>&ӄio늈RL"#D_1[0y5}0U8YbWg;x$d\&& {1fhLСN-J8}rKG)tbY(p(OoߠRƦk$dlLRoʴ#] &/;%>0>;*ȥZ O9iGNPOKT|Qgks*B%BBIf#l_s-19z.tºں?~o<}|,o㦉 5|bbmR3Ǐ); `S{Hm;W͆=V]Wb.wigRB4L+p*2>=љAΝPS`^F9bߌɒ¬s aRɂ%_=<'D'J4TmQlc좜Y)1=~!*<w/^Y }QLڏޛF4i=_6ﺛtj:zQGgJovAQZu]M2,=jPI@^W]P]cģtZmݰ%!A|V! ;#tq5TjDxJKyl&E4Ѓ\wgM.1l^_4fj7E$?U44xD:眑s$)l9H&~}33;3 dLJ3)F0h9w< tWM;~^Y+KKSϿķ5`h"1r JG!(]XjS^q7($NdCOٰ&yWg4B0א\}A,EٙnIgGKIEPxѵH8i 2[lN5r~cTsNPH<,r_\^t Inj?чB TnٻsSGDrđV |e{Cg=o*.3SufqvA1Mʷ `ij?xߙ#o_W9VjÇwX_ˤb |vv1UvHb't'b>hjkJm3Y Wz[~o:=3%F믽QZ[ pE 'f=;G$ohx@ܓ0fwvTX{ޥ+--XJ+S7^^5y'0LԎ[ŇK㊵8DkDvtf+U?#wj;~V*" -W1&i.ַo"9h%Ebv٭Uo3jME9тRsQRl ey*ՙ"BJ*j]/}l& %Z5PT]9CqPD~LACYfbmeSɜDk`J$p4~?Lug3T8)͵@r=ԨSz}m-kBLRtIUc=H&guJy:/+3֙\dײW!ܾ$9 8=,b`uFޕ@Pi0wAVco%ܶ{ճyV,2FVIf&#hz}YT16Y,h`q84~p6K/Y 3d#Ra̕\uPѲ~tFBo*PꙓFP(b&;t_/J++%w> E)P$[I(a@*SSSqM }a+.ɠ @$JB>FeRPD1E WqPb"!AQL!cnRu}Ӝ%9F$vGĘtz5L*dR(*Z aD6I$pLsB@#8rY!ШTv;Q`n~Qj*0Ra=\Ӵ4'R& //a&G$fRX%aH`]ጋhtekˋYH&$4PX2TPJLH/^?q3S  c6,Lp+'n{R=~$Y|dbzJ߳c-2`_=O$H(0T}[UgS9|ڦ p~Vx+Zn n8IpR `BeeI۵9G[|"C M-̏]_Ǡ+Ǯ~'h|nK.Gb(̤ҳtFg1ڽ(UlNƇZc:1J3\"//7h59~BMt¹ʎ~Dw A @u_;fE/\5+nb6::\K@mKiݹwO zϝm}iͯkiL)4,*4Տ=ƺ.p'(NT6X|Zgꚫڼk' J2^ʁrRTrjʽrJ H*TnѽmpJ/VT` L, sS%b>.l޴M6t/U䮡u; Œ@( 1U*= k1Q$Xjܫ5c=BSi1&ňp`whfg&D 9v,O'PdRi2 4!OH*&VepqH&Z QRPtۗO OWdhk߲h맯j]'ZgMƃHB(5t=d OuGOY JqΠ|yucgӯk)mY^t7yK9392C6iݸ"uuL+Mx[ߡY!ݾ;ٴ>:~#|Ij=Ŏp=y~H *B_e}T\7P8" uϷID4]VHA3aחZy!`yhYi9xfk;fb |EVh}-Evzo~;`v ewl}9;~r(L^&dXVBpWW=pf3GbiB<54X9/@j1RT6 S&eR)̼V$I뛚rUr01\YY 3x\ʲ[ҋH~&t\@B1>=sTY_Hg<'j88AX<tL6W,j0Im 9 '5rs`{+kaYO#|Ԁ'+hҴAV0в3KkʢX,I#WovmߝJD5cQVs9~š=;MZ.!f^=⫯Էm>>m0HrzӥVH 7uXBb!9x+ HfZ.t͒*Boۙtj.fBƇXfq?H*,di L/P[^x%z1\m(:psֹJ<Ҷ3gϞ )9:}M/Hz,O鋊z{Dc]Po×$ 3k5}RRPixz$SHdU\q+謕O=vx퓍e|\gFoU(HTrZ19: 5&9ob!\?sZoĒ,OmS~;DEuNL>{umaIb!TL.M%So'I3~d'OgjRq-oƬ$`̢_ 2 A(j~A߼= ([XC`yTs9P}ړFR?rN;w'HeNf>ꑨՁw4pX( !J%kݝګ. R_N%SKrt2qdbᖗ/$Ww~d9tJa}5dWq鲆:ziq"%L*",͢{{()b=I[jJh5R"(5?sYc1qߒkyo/I/"R _ 0@.|ʊTcrS-[thO+RyqqF)VMMUv߿''y|չpLǦJ4Ifm{Ahrn9.AY$\ZXqN d"<0)SX熖g.KJ8%$i-Z.d&.|I$4g= :<~MKH0 B|k%Ye]uF q;kj2;?PqA 2>B*&D\͋*&sP˳whԮWLEΝ6٫9x*ܿG?=JF<`26F3^k.ۺTϮzL(1)% aذ_s[wsF):k7mN'1ZZuoYSs+T ǟ`Ƃ͆ *͎*& u?{\f+ZmiI5ۢf.PMs_Pss; 1UOKFqQ}##=x*lkkr.ɖܸ F]*Dc]v; *e[ig*UBtIeM"Oo[_D@(Xė6vm{ dU>wO>\8QR\YӺИQ~NS禦Qo`ȱmڰ)Q Of;%eႳOΐ䱳ZY.߷wsl|Gf̠\|\Z؆Ch6.;Gϭ Ϳ,1s -Bo:و|b: ÅwSIe*ا.G8\k6:&TEr/1@PgÙP ŅyxXRU{O7rW;|H,Z3t* >!FBs +eagg :aχG?|20a眼˯=WXLl?^Ga7OBSm$ny7u!z}> 9k6n>\B\i?9Uz/)ToA*_71PwI<5:E1O/:HI) iyuUH|@ߓKĺ9|oB‰?{Zzj"mQy?{Wc~+feY{QwՎlr7S˺L|i66"[B ~;wy7AٔкSܝR~eE9zv_2]Lљϝflup`lF}>G@N&f0+o4:D5'k0Ha,t"B} gp8$ܱ_:mIp,6_~пFe3kѨF31H>c=a-VEQʆ>P$%XA3=;[RQs|ǽP^߸#6vj];%~:/ӨC=[ Sdpg*`*515(o0yc^\.*ISU[/yt:IK3 X6 2T, HL0uPnQ ?)/)$LRL70pGo3@xm44vh4>-•{niuZRy5G!ܞg*`ovKǦoIEj[гt0g ?}zH$}@1ÃXf0x/ʹ-i٤1vm'߹,7++\sOgaeY-"):SćҞʊ?+mW?:3m5CqO 'j)uAӡp r5'6/rf2>xQ"r lsg:H#6A6$\V87`>w+[60ݫ0GeU9hC++.ڞ҆-eAQ0uڶIPX$)X{bɔ@ hZ xvR80!  ?P(̓Z:@{墩)PXuy1kXOccD$I2M U1 Bbq& "#=`+eb1[SLEg2`y"(5MJјs ΙGJ1.7Mu/( !àUF`ųPDTjHg^, 8rR.i8Hlrj.RR(]Ⱝ,l&_ ͦGzN&i`޻#NxcΛE Xg|yÆǫX]oWiR+|iЮ xұ}7cWm[`w>>m*.I3ntJ/\6W5{nDq}WS=*^#N ENzx|2_\hneC>}ŀ7jhlh`|Y"x+2G75\AntKԾ("t7dcPV?2pPY:Ӊ%J/p*!'9񓩤N,Ly>u*z1UX|`@`tbۃm5_"U 97ܨL^YTrK9IFگ+'O|<7cd[uO>Wյu˕ݸm;P*lھg~duAL(?QqN_hND_tڝamo DCt(=KP$Lmcj7 s̘s}ƝP5~= sx?fBuLc4J<^Z$=Κ꺁k'z{тsFn,PNUVVCpRi0)[Iloڲbme^s"ښLZ]ЬF9{o 2jC> U:Y@gN޸2<\_^}RJWW*TW_C3}:))vڧ!^^!M) {C\Q^<';~\{Yo0 1Pv,*,8J!@87Dv|P8ʸh:bԬs4>=,*T y{ߚvbFfέ$&DcsȨiJU.33hj* ?O\F*8glr~cʹ=;) g I9/p&\:C 㦦0.*Gڼі̴˽KR߮ÏqUϟ3-x}L"zbU05+k L&HU&˨jcraC3 fm%E[s^I?2d3push|;H~IQg@PDy졀iɟPl̴\(h%87O4xʽʥ2-͞?ulh.圞HC|")QVvYmYrwnh|m0L][ r,QCWG'y7!әQj٘i Rߜ?}lh9o<*uUsN'8g Hsnh0UkPhaq̪ C:UTTRN ǝnZ@&T[um]S!,E*-Ee8K 'SԢRg։"25Hkyͬ&ƀkiV*-K䛺6} JeJY EE4rbA2)*pBQ~' EO@%WFA[,`,[VVN;!$ ]\bgp936#QErwΓx0oY~8pV;6pUJ/@/dF$#?imoyL\_\tR5s[7Bު$cY !/Fר\L. Ike=H}9Ay mQ(De+_H:l߹ 'S13>cX"ٴ0J$8("V SzRY*TTY\@ b,ǩltEmE5c04 8Yp0dSߵ!HH@SS 0[Fy|Cg &s*Vҵ@43I.:SI~2aEyXUEInuh|< _HaV1oh8t _2=,M"Db4il*BQ'p` i(Pб1H ϓdϿ6 /9(^İ9 3 K!0}wz:- HQ)bC#. ^4$xM\LjsQi8J\ֈw1;ѓ$wZr/gfJ?!2egPo^ "ǐwx,yE!zr +h#\b?޵HeeɹK7o^_: eh2hhvzgEvp,zsgG_&!Z4L@Wy}E'3`LiYhYKyD|R(@6wݠ\CU+ջܬB OcwXtOYs@皻U=اf#}@@:^N~E||Tѡ#޶U|ttpfV-38lxfUHJ"ý=R!Wzmeo_%:[Z>|߮Lڶl d՜SYB>˶0eAw寸KKzOD>Y?8 4ϒ 6&Kإ}Ⱥݕ5W/~NwΤf,<0Og룣t>G*P,ꎟ<۸I$-V+$y.8ٺ0&1ًa:IQ/ٙiGѿ -Z^OScSs!jk-|bBfgh],qwUXu9 (ͪ |٠^&^߰LQ1$Iy^t+r) TR6t @,50*m}3W}z'& z>4@fHxy,@o&Y)02,E]vߣk &Ц0F l/ [ XOqsF(׼j>(Q:n$@.H&0rxD3!9{Q S|G|,s=>d~ͤ z#QxrP:_fSHM,3|@ly¤@ЀwinWYY_YBɶ bY F$'Xx4 s!rH(" Cc7! <^_Q횓(`}߷Cq ME ^)߻ 66+~ );3Km[: PVO8/ Զ \`!_$UqlXUU;Ezle>U^ĵ@iö́W]>d\ 2t7vED"w=i⾽ۦmm>Ϸ4wspjyVdrjM}g/>}.liy@__YmӚk&|:L@n6Eq(•vulKG?stzn\~6Yz㶇ߨGo-k`R1%5@zmE{§?DE}#O>o~\=Gw6ݷY~cMGgV~X2rv5m\e@@|WLp(μ8I4Uvw=M۶ ,n\,PZ+TTN(`*qWޅ`jb|Hycs>+:wq>!ʦݞb97fSsޘ$ǫV)WN)-6G_zqܨ.\Tw4s~TcTT_X*[~|H>0Sf˕K=Zw< .u˪ٝ)WޘwRp߭:{F*;ow]~wG+*("t%:+gul!D}R4w|Q㯏;&OtD2™!o ,On5Y7)GGg\;G^"H$rk:Kih:䔞@1BO.֕t|^\K#o4?xɅzϥPb K)jɥ+7lԉ n.]|\8:|"E..5(Dpuv~Layng ͎L5wlw !Ien-lZ /B%Օ@ G#QW{ӵQ_'$&:MVɖZ[MdY() ˊ']>J[LdUF#~ZC kfˁ:T+~WrGs4Й HbEuqMot%u744,.fu VkC(^mއ V=Kp.MM~ᱭN/+$usw|izSyǒviɢ FF.,v!d(*_C$S땂HqScLa#:pW6V&z .=8%s&FAD#ڄ24ąĊ4K&S82x^Xr9s?h3c6 콜vtmZ_ y[eSPZ v Q*8.7Y&Q }',ˀ73TON.:!NJ`>JFN-r*ӳO|SgNqXT.8~/f{yE9?\갸f 6x]r!{GX}#ŕi/SqDI s:3T_}M#C<][+w'e>{BF!װnVƔu,e^Bu[0 !P>@e؋=X|Ff9p眷n9^e]Yc. I3ؼpm9[K)F+d J*6VBiM^M61櫯υKl,i{YHEvŲ"NȺb}3Ȫ+^ Bk._0YkϹIRb[O?oJFsjGkc\iGGH+o(lC`g}nxwsc?2ٿ w C_|_vwW=GM GbXT(^1/2<im>(RbN 9039Wx{ aLOWս=sO7ڛ es>붧Z!VŸrAk__ygfNg2U^GPRyӮў2WO D;Л5HGѻ,Nۉix8a[ ꢉ~ >Cy[Ju^>FBop PF ҵ )P> CnjkH#ޠc:\wT5DܐwyӚ21ʁbO=kH\.~iն}mΫW.]5 _>tP?#qy t^fq4;KgR.:x  vŁ`1{{53@aadW֚WΟ6Ut[L̡h¿;ol˯PmAFrJT68Or \)XҳC@OE"Mt]p2GEaHa/1kcSm z0KXI(H»{ndqo߄~~ 񞴪(|tGV8{>S Gsݍ/9? ; ֨Ci졳T՝kϭ-KBe B1WmT], YnD!n5:Xzi/N_QJ{Qme*p: ~JSL}/LV_' (.FV= k K@^)UTO%d\9bوqBJHEKNBCO䕑Ed~,䋡+`"X qPϯ%8V㐈T4[ O EWӃBR^3]I[<\UIzBRҢyΣ֏ ;aKˈwyQWNFX, ¿g0|K8[Kp/F7ԕ`Xќ.\]tv0bt|Po֔vvv2rN)8H#C!ʒH5&'4֒Lȋ2xR%hdbPoimشI"ֻМ'*xлNYOFY5aDx~֑Ly\qT6X *Aڠ MX- U4Hfjj8.͎Dj|{z9/_|~OVH8^V B*N"Hc0K~ќ^9N?>+2Ͽ uG"EQB*wl{Ƞ$}"d"Xh[w_z C 0r k؞ L/Djw=O kvnxh-rpeߤOuZk.N-nz䘏=5:BԻoOnۛ*mxƇӋ[:|BxK$t& ,ҸwwLNM37o1725 g}\v#ѩ5dh%lV0`> ~&|+>L<ꧽ<96,ia<pDޱ,{V!%R Mň@'ڬP.34:n;RP)+^>usC,Z9qrťeb8"1#,32 $1\ #xPn~ٯja+ ||ԞI}R6 ߴgSS91'>yK[(`*Qe}֯fV[;z` r,_d!٫o AH`^Ke2[Kl<*g r y/뺢UˣKɆ2M_|_p[]h[.9=XAN$P/ibDd+KAQs8Op:!O|@Ƃ2EzL^O*;@raogsxoyMJmt6͸8\^<vqPԥ>X^++SRqz|ٻ2;XXPSީӪ 7^Jm osaQ7Dl]Si"KCssHQ<7BT_ ^РxIU39zJyFo^R$b ̄p$XR`rL~jTfڪ,3@Ȭ,L /N,Ej̗.vw)(fVBmMxg&;O^52Yrޢl( Tl63CLeke[b$cQ#("E|IEzeB1La|x@wtuФ)jf9:&<42(c((*+Mc)d$RiD 2m}Ȃ9::.f3D*s}EigXw%R)Th S`65-[K-`{"8, `@BdebdL%l&,#432JۻME9džyVa#gq ~5=Beb DL𴘌%߾p pX,;`=vJuj)!VDJ &ӠW_4 V{2B`رs+ϊP)Pٽgnj*ֶnߪPXr^&ý !1yb1Hpe/б8_CC5}N$KR@\fJl p,&'G ^P[5jx@r֫N Ny.zئ+|aIG'|'q{{ѸeSq.} 'v^)"]/tܞܪ;C:mc̢_?U:V69釄iNJ<٪m#G෧ua)8 WԖTO^>47.mLp(כV&(Pe"~8+t,]>'981_tڱ!_VlbFg ovMV4V"y658kfJ'T,zcBP< /@|FXKw/(=~P!B7E~gw$]bw ~Wi:o,\/=&=yu( 壆hmƛvr ډJ@ivߣ[Pz/C HZ tpGԆi7"BZ8/_ ƺZ/û̓(L&. _+bw.Z#l"9\>/<0W[)yq&H2u%2^$K}١h]V)Z8۶@7ؑuv@@ufFd3/,TڌG%Y,髷VL.h 5|DJ>ֲ*2o)g΢%mΖށ \әI%*S13+D}]ŭ 9E`,BAHWg kqpjzNR4uZ֪:ED÷my/Fb<,W}Peb`Q0U!ގ)='3*{|\Ay\^{K% %IB0b2*c%#f&'0U8vYF'ehlŒd2 p4#U _5PPp<ϒE*1]y{ ]N8`!yLGaf X`HV8tDVwP~?Ƈo8?ApCsaq#ќH'Z<;ዦ2c!U͢!Op\<O. 4D' ,b爆K(Mr6 ԗDI/_`Cv4$3|{)er * ,u d3A/:U&g2dTJP*I)]TT"2 ˆ4I'x/`%dέ^oUzhW^aC0l6"7JBLT tONѡ9HˮBJ(m~sףxwa)k}w>nW?; f _hԝy X&ڡubYO8g6!4ϰvn6L-dJ &C13 ;KmoTra63Ts\A,MN4=YJ$x&սQusLV&_A@م(R8OHWh& \!*8gsܩVۮv^_^Iy?ysnٓaA^ #9#2N w,K"j9Wnl0 ;?w -`XdjkUSوV͝ JB e 1xH aa2r萟e^d x-U#Y|gS3q0bx=oԌt{&c9TVVk=ˤ} bܞ<ѵϥ&2##`(xMZ'Q^EOZtfz e =Z_z0YLWho"+Kig=<5:j!@b#Y,%r '¾$K%5H64m1m3DYQ4=ⷚ0<8eY< Ie+˪T3#+CޖZ;%/prvسiײ7C%R5Qҥ3HFzJR‚>=(5S!^=}^)KFczLux:XHg_ƥZQtA ff=\47Ih$2>Ui00TR&F P!fRV 2u*D7OjK7. &~Z8eم* *Ί?v\9 e0MF-E4" P(y>O<2ffY.i<ѪVА?@O V`qO>k H@`s%|"3}]`9d0J]'$  _|>BGB_Zp@%DK@H>,(PbOE+4qT7pĿdvKiK:˅aY1APB |u\-|WτD202ّ1\g867:69ޮ z-_(7T_]|Hb*,4sK'Fq44iG]+&ϺkL\9p__@-etB&E ňD΋gL-}fT)cϻu^^c_ZsO v =w/qݣ{lL FWǝ3 [ `dzs"ZL_m0л\픪D\VpkJ#$N1oL$h&4&YyBhr1iJM#Ȗ(OF3M3/c)Q2۬D.@<fP?98|6bq(p:Xcl0Ɛ@Z-MD,ɲXs0Hv]XWhP.,$i_ aVlEumO MkK%e.*ʠ-C_:|E@W3NRsy5/$Cyo*6ǀ"BTBehjփy7|v 0o@<6TfzCY`)'`]e)I5 v?:N # u˻䂫S8V@p| dx^Fpl v1m/T4묚*fpVk|^P oSY@5VK{St ?0: M K'IG^(!Z> XO}6Wpw1ͼ *V+[-kn(x 5ͦm e1sk*/UR ' ҪdшyϞE'($ )Zh&T6l*["(X@ )sڻ^^ 4%%RVk\eւ[m0Xp9f:wFAU ܔM3 Ѱ cEэ#!IK,Hٔ*RtbQ yh&GCw4(ӬKUG Y-ꕩ+z[qPH :6I,dT Eb:xkEr&8۲ yEn@`D)z>P$ H%HJBҍG#\$)MR8dwPpT<0m gx+z0)&5 lfk+zSKL "}Vt( x$Jpz;64&?J3p#1@C10drjv 빭{EP~*D t*Uy^sk03]HL-xt_UZdPIy} wT;o"zkx{[U0Xɛ'?~<w[JS01\5PKY/"3sX("Q/ }rUK8,XjRom 8Dg͌}|6 HT,@N?eL̍qX,\g5*8]}c&ffnlyCۮ ^=}ydgNf<1 limĥKKO< vϬě+nT ^,Gah*#3q}3 ѓL&d}=}HLz];XUMJ}[Nԥ[K4RTPp[=̢YoG[3{bYg]sJ&AqXf=֢LwW׷uH(4D?~D`Bp >wmWN_I*0blVjȦI`T:(?~󟇧¥VCŏ\^ox\sc` ?+& '.S$ \QZLgdV2U0=yG(2n FU-z{b)rGsN%\&NH2@2l6@RjӞljaa-d8h+o0_ L z5˞ebagV譙x֭xs .rOVIF++&vRK$?26ާ&YJN19~Ϣ9 Mm[+*+L?Ԗج%%!kY^ jX^u&<)b EoЪқ#jo[:{LŒ@Rxlvkw[$dBt|vY)SL{bv$+3L~C Q,[fbX֤us3W,n+s/Lյ&{jr)Uױh"wޣH\g&2i{|1RTϷ+KQ( )lQ\&A>]۪%5 P']$J}]M:f0aRߴ96qNN0GhNJ!Rղk20T9xM[`$% ֳ\A RZD 3! 'Đt2[9R!"%+s/CA>y|Yf\B_fGG91Ds,&JmTRU/0H%D,VPdY\$Sku`!~~zB a&E<*xUu>>;xD fP &L&%$ã#ד8R?CaYr jN' Y- ϧ:0qHt^ tI}vj/)D̑vOq3wt^Keީ9ԬN"ݬBqCJxj,ļ"RHȄ'd@0H29R:*Eb@,da%`#f8}9{S=O@k}DNC|C~oc=?75#Q/fGR`bqaT_]ݠo~pC}5/{ QZсYj|wב^Be,s|ǣ1H‘T <GTБ?ٷ^^[ p#dgqqda~`ir)_(_jiٜϏ 2)Slj7ѕKvdoH,zJf6#c~b.t/,U60=-@[N&5:nA (f4UQ\=V֯Qz )d| JWl7 &N e%ZI6szjoD^Fhfp۷xd4n.U1Ј/o |B?ؓd\k--g_&'dl7)欴:+jFyΥtau]꠸*U%jQ+j5v Ӷ5c䪦~Yڼ]˥3^ /vR8"A^VmT͵W#ڤA÷<  8uǔZ9Hѕ8{~E]9Ɲ,ǘ,6*8GC[XN\9뫗 FTچцzL  `im^е'b@#XA$gt:]~%gK37yv~hh:_ }׮wj.k-&BN[g|-ܘ;ݪSz—OwL~xt/~h6 ڠ/6Xj`` i6 ڠ/6Xj`` i6 ڠ/6Xj`` i6 ڠ/6Xj`` i6 =,]IENDB`PKDJObject 2/content.xmlZ[o6~_axfFXMضm#*)=$uّN0Ns㡒oEzZ>^pҌ/?݈\Il=Q~<+PTTܺ<3U溶[Y>d?1Rc7S]i14s,0(ӮE R䎙gW?\lר#DzX W]`vv"ڲYM9g|4Xib7%ےL:j% x: P =ij}w j‡fDP.6ز9pNpE66F8NvG0rS-A3h҆wNXS6ӃJq1=edOjegm==X{>=M_+HκYء$3T bYM0_ R::+SQQNj՚q9{1E9Q+ `;ce׈!n^[w%f{ƊO[O|y-t8_j $}_@P͑ hz܊^` [=]î a@ Fnrm0YIJ_F;`c,, NL\=P tƼ ,ʓNhht3-·t`9$EaTE˛ȒX}ɉ!ЌAn4̙p-3^8 'i}.GK|<㻏UH&i1@1Jyjaہ#60\̂8:OD&9#e'nP>biN*gƥ.(^[d]5-.݃AաV4f$m-Mqmw8n <M6UNqk-I- J`I{~yzn`iZ9\Nl?hguo%e:|iJu^]nPFc'V^ 〸[Y蘞7>m} 9(`RI)e)Q N5/(x3k\n7ڹuYŠb@b#4f9="ݝL8Sck"3CͫtUUiU U=B 8@,cXKN:Cl^Ѻt."7 Z$>X@ ezx&GR_)uݜ&iyA3p-KMK|󾆻Dٳ+}w}3/+ tct̻1o!N(ϧrzH;\sP~g]JBj= eX|HSB}=5ghcfvBeHZkېVJ6XTTv6{lrl 3(I.fo!apXzBd$|';bNL 8)be~l^Z 5.nX$ NKm3Jwhv8ڠ0,Tnc&nFD^2!erw $eqsyǎ)c B?i3,X?]Sk|?/> Dpe${az)ˤ>HL;K"?,?+vda i(Aj("ANY}h0/l1e!L?#/=;ѠoDYh0pgjH#3uvԼk i'OPKo~ 13*PKDJObject 2/styles.xmlVM WX^UjU7&{ڞ9", qwNj57f|xӥљiÕ*#&\V!~}xTe +"I*,MIBaM!qLaI&R Ζ=8d[vK;RBMCz/F$Jl;6>Zmj++m6䭣`2⚓E b`e XyL/N[Wg̹Zsu%=rzq=xڢ5]ޢ5'7Cw萯izsno[-܄,XU 2]vI_i(mG!c{>:@+M,0 _r欽|׷A4,E~"8t5.R$ /4LsgӊpƄ8cvϿ%nšoG{v?L9 ?}ƝrL` Xh :C(XUw&P߄åep c@`YԭG>#]w9f9(hf~,MIie}ϝAZb3 Ό:aazox?G9jՌ؁ɠj1LVVi>Ju|̯ !3nߓPK`1PKDJObject 2/meta.xmlAo *OiZ6a&ln W˦`k?*-M#G=UpB*sӈJ9y{}d[,xR5M;}گ`k>Q8HOdd ~­P|PKu#LPKDJObject 1/content.xmlZ[o6~_axfF>,P-WZmv$QKʱ.";raIxT-fCj*e?"^WB]y^/^/e T$(?ksu ARFn*n]Rڙ*TJs]-qn1ӛ).ⴘ 9pEiW"k)r̳[.PLf6HkTa" W= ,+.0 r;u_owAmY,&Yςև3^>}zH,4hmI&5<(پ;vX pr5 3"H(bzOlٜ\8'8osirJC@jIOVm'Zf#H9j_po4iC~j't)`I Aa}ju\1=edOjegm==X{>=M_+HκYء$3T bYM0_R::+SQQNj՚q9{1E9Q+ `;ce׈!n^[w%f{ƊO[O|y-t8߳j $}_@?P͑ hz܊^` [=]î a@ Fnrm0YIJ_F;`c,, NL\=P tƼ ,ʓNjht3-·t`9$EaTE˛ȒX}ɉ!ЌAn4̙p-3^8 'i}.GK|<㻏ULm bD;`c x`)Gl>aq8u6 MrFPA(˻ړSSCY>9omo¢T~Ⱥzok[]iӃC)hJ $IZj7ńlUp"x#Λl֝VZRZBzQ`qsW뗕en~KVC~4]ewKk7ͰtP>˄4puGXCX.6Er 1~+B„q@\M\x,tLO\t9M/80 &J&eD56ރ;thOtZ|3qRua DܺbP1R v1ӑ ea[N&)ʱ5YtUdբ *i*KAJA 8,cXtKN:Cv6>%}nG2˵MF6X ezx&GR)uۜ&iyAn3p-KMK|y_]kي=Vp`d_b1O:ᘷc'n9=$ri.W۹M(?Q.%ypT2z,J>E>a4ƱzsFx2$H-mW[+h{, N zB[ÍwTh.&o!apXzB ,KhI ި)l9m9e4 &ɕykWԸ!cMr&8-M߻m]P8?J"'f1e!z;A9nј80#?^7$b@LYF@01e)P38ynLY };mwCoD ܬ|&8AϘЩmf~D.hh;,=;Qډ>) ]s8cW.ƔH&8A#B)pjǔt QZ)eT]Hѣz>PKOtX+PKDJObject 1/styles.xmlVM WX^UjU7&{ڞ9", qwNj57f|xӥљiÕ*#&\V!~}xTe +"I*,MIBaM!qLaI&R Ζ=8d[vK;RBMCz/F$Jl;6>Zmj++m6䭣`2⚓E b`e XyL/N[Wg̹Zsu%=rzq=xڢ5]ޢ5'7Cw萯izsno[-܄,XU 2]vI_i(mG!c{>:@+M,0 _r欽|׷A4,E~"8t5.R$ /4LsgӊpƄ8cvϿ%nšoG{v?L9 ?}ƝrL` Xh :C(XUw&P߄åep c@`YԭG>#]w9f9(hf~,MIie}ϝAZb3 Ό:aazox?G9jՌ؁ɠj1LVVi>Ju|̯ !3nߓPK`1PKDJObject 1/meta.xmlAo *OiZ6a&ln W˦`k?*-M#G=UpB*sӈJ9y{}d[,xR5M;}گ`k>Q8HOdd ~­P|PKu#LPKDJObjectReplacements/Object 2 pǟݻݐQH"DBbP1JBEjXGhʌ@ǴhV*:RqHGXʈX}vsms=ww73/P5+Betxs+dm*::ᓞl52E9݂Oe2򋷊t[co^@)A[[ˣ CrhU:jooX hޜS/=᪦WMj8Kq̣CQD߈&g|qIzk;3$"]Tq}j)T-!Y@Q7)fMN[3ޣgf1EF+zEF&m %?D- AJ~Sԋ[Aԋ[A|a\- AJYz1}K>5H?*b|j %$W- AIy{0$.b=H|:Yoߒ @J%o&䏍z1}K$L>ɯz1}K$L>ɳzYl$o&-k AI~o~A aI aI;6 aIU aI{u aI aI aHr&omHc9]?e>%+G`Q?%:pOZE^Xh-<#Ft'xx)xx .?[b7 B߁o{)QgW~l`1ŲupY%<RJueg 1頊Y |WFց n߀qׂ+J?'pl.B 8,-:p<6G>np xV%b? >.=e{9%x7X9 ?&m%GӇ%3E|GA\Unhsn__G$*AylѶfZF__k/@ G)`hW`73\^< ~ഭ/sm'NpA-ѻAp .D]u /& Psl^Ltx/ .O`mtXkpELn٘:;㳭i;s;Ss5_j>6Fyq|nMZL3x@=^Zh]qz{3s'4ⱨB@?(LZB|ױmL_~38..~G-u,?w<%(8a MZB|ױmL_c>UIZ^: I񣸪 8YIZ^: IHkFXrv㒴3u,?wy/1u&MVMo5)G4jb] uUX]XUX;tb]wb]źźźź~u=uHl]źU.u.Y]N]f]MXV]d]9Xl];X=X{54Xר&p\붸X׶X׋b]).X{bb][bb]ĺu}JF:]Zu=u"!E덊XX X*E Eu*b]syXWEZuuuǣUXYXW`}E]u}ԴϚ EX׈i]KTUXX׹XׅXUXX-XX_b]b]b]Wź~uĺVĺĺΈu]V11bb]?u-uu6.uG\qźVjb]gjb]oĺnĺĺvhb]źź/|⠇y-a^+!Ny-q^ ;dZG: ^4*V_Gz;伖{!rǸPy:u{!X~6x&ů0{{5汖/Sg⻎ngR|Ω2/i;汖wr/wϤ4_72c-}J ]C|3)~`8.<u{!X~6x&霧͑VmLX˗Yc!ވ%4a^Us&6jn:qNCR ~݉HlBxhVZ:٨5.* ԑmvSfHo%޵~q݄2ɱ؅?1>U5 ̚7N&յhsќ"[]DzRZ``40)XMP M+D0޼[3Y^2FDıдjDRFScmi/4}mLR:/kZ֔GaEcESޱ-ވ,^cym"˱ԗkXѺrM]QkTsC-s![Ns4X4Mimi4Zh]iZjMi55텦|ݯɕrm?CmO%Vn9,Y WO~˱W)>OY?ugjpi6}QƣBa|P| f~>Fu~~D#6F%c3`^.GZE "X\q.uBDsQ:%E_\\8α1碸s˹(;59% c9%;9; p.*q,+sGM J {_wI$6׈Ct >g$igz X~_֮PKNA NxPKDJObjectReplacements/Object 1 pǟ|.wI HB$A!9D$#V ЂTCZ>Pj:VU?8V@-c?Zmq: ?.sv1{WG'NH$4C4Ý~82Ӊ`@έãHnkՠ%t3Q ]]7*}݁L9P(mޖ`jw4X:7z;N?Ԟ={8VmBOT:yUZͪ0EqJͦ_o!i)aC7Ƨ2[Ȥ:o">t~==ڒ7U٠-PG˯o8 )=_LǒwK%M/ K%Mɏ J%M+9/cqSG_Lǒ?8}3wA/_Lǒ7wA򃊤_Lǒ7wAK%o %O~1KKcX ^.H*ӱA]<~#xɻ y]%})A]-A]WlA]㗫A]A]*A]WiA]^AM~S=I2&@&oww!nkC`!ܿ{>q{E Sbapd>\_CDU_p|.pX ^6ȵfhx#8 |<*wIπ7W>n\{=|<6-!p7G0PH18*+pap# x)X׋~x-8 |lc 1 ր.b;go}{`>h,F)rh218h% |xq)qp=O`p 6g6[WY!_<;i!lD 10r ?6cMp8t0"p 38t)g`L\ >1&cJpP[w? ci5h|< .Xl?7M| co TfC#LuR0 :sW{3)X2ck|pL5s1s8^rp8<+Fa O'1!ye4rN_wSM75k džӤś˛+%^UW1~Fej,ϘZ}DIof1pq.R&~^\y}Q_&-rB|S)xEގ>0l(F}=-rB|S)~ط~:1vo9[ JWu4ꆥb3r,'ķ<Et=CQ_W-rB|S)xT+P2Pэic9!7 sgĨg!XNo5lnݹ0eX_cO<;}k'S>5^O||k/mרq_|~5nq_|kq/iF?35_ck|k[5zר ~k( Ʈ8_x@|O_c"HE| W*kvkLShV`טѨѠ1A_N5|Q1R5Fh0׸T5iFkjFk| ΋}|F5x;5J5xkxk WרT~1N_c"˾ E|95V)klP׸M_^E| k<"QE|_ (%A5Fh 1/(ƚw_㕠Gk Q_<$ Ckl ;$ƛ!5N(_cTr׸%W|Gsx/W|a5f׸5,Ƌa5N_cfD|m5^q&"<5副qw4_#_||5拯d'M nbuRN{|6EoTҌjLm ķ#R-AOaj\0g޲+,i+iݶ\6?lt.CfM4E&wNlt>c ?zZ}T?~j4>MMMMGg)$ 1V Q0ͩPG+?E˒-K%umW6]Ӵ*h4킦4VB]/hM*#0"kqM5ZMFM. SFn"ٵ6Ov{d/}:ˮyS*h]oʩcEVUdtuJ*TɌg wAtMU 54톦zEHjOnh7($ԴӴ yr*\U5q[ny_9;\v;Og_>_O}ĞD3oص4=*'S5+i9JKiyާ ݙXq\ bʧp'WxU f'q"# K"D'gKq~8L7of7eм)eޔm~@ϼo~@hySI1e 7̛rc7EæM-Mшy,hySySyS󦞦Ms>P)CuD"aE]e Nn#%r7l0F}=ӎ/JX%w]y/auy*+IK̏h--q5r,'[ վ|-&gJՏWOKXDWp# &epYeVӻUsuzj1orG&OOFeyG'O<7cy#5H^1?ݼżɥ{}ù2 ͧeS#A_J]!c{k&oaǦ;mR k do^ 3\[HF 48b"Y2#v6:%6͛{)lՊn_:PK1vu |PKDJMETA-INF/manifest.xmlV]o0}߯ Tm*}AqJnNoOPK.m PKDJ^2 ''mimetypePKDJe9,+ Mlayout-cachePKDJB\ !content.xmlPKDJ&5) ]settings.xmlPKDJ2< emeta.xmlPKDJO ,-5gPictures/200000020000016B000000D7FFB7454C.epsPKDJ 9 sstyles.xmlPKDJ= }manifest.rdfPKDJ'Configurations2/accelerator/current.xmlPKDJ\Configurations2/floater/PKDJConfigurations2/images/Bitmaps/PKDJConfigurations2/statusbar/PKDJConfigurations2/progressbar/PKDJAConfigurations2/toolpanel/PKDJyConfigurations2/popupmenu/PKDJConfigurations2/toolbar/PKDJConfigurations2/menubar/PKDJ*99Thumbnails/thumbnail.pngPKDJo~ 13*TObject 2/content.xmlPKDJ`1\Object 2/styles.xmlPKDJu#L_Object 2/meta.xmlPKDJOtX+=aObject 1/content.xmlPKDJ`1iObject 1/styles.xmlPKDJu#LlObject 1/meta.xmlPKDJNA NxnObjectReplacements/Object 2PKDJ1vu |zObjectReplacements/Object 1PKDJ.m META-INF/manifest.xmlPKExaML-3.0.21/manual/ExaML.pdf000066400000000000000000013523161330315463200154740ustar00rootroot00000000000000%PDF-1.4 %äüöß 2 0 obj <> stream xZK9"E!@ 6rXA6NzHI'hۖbWb3 6)oo}ꆯ]? 4L |q0|*/.qƋjNjK)뻅\m>1AwLA; `?޾lE1)|B:/ 0*"}C}8'M3Hpq>BzPI e2O npYg(>-PttBAH+5s$RH?̪0AGU1PY3,jnD gfyiRM+ H$_BȘpA%Y sbLfAspes++SxבwqOY aJ]d AY&HKz@6>|RNhcqP³`(M ?Q?ʔX)7G.g?1C*\1%V~'Ut cGeJ6?'Y=s&&fT$M A.rt:7E1A"m7 3t.jǭH ba7uxA@F0J 2C{' ._IUbdyG`(`B' nBO|cĎ2i-a,h-!A>TVɃokV'뉸c`e&͆Xͽl 櫦E=J9_K0=sfWJB%Nk뉈,=y\}Âݴ㉓hŮ0K Ń"JuI/9PRӄ7WC&e i*,niQnsVUHs70DhN1;5z-}M[]Z\A~s30gueo5H/PsЇRQأS!s`UND^_ z,.k\^)tUSh 7BZem0I6FcCEK3}cOPS~ҥP(wNsp(dW›"D{>VŽtrQߧUi׶G{9R^[Dh* dK;5%r{8*ƐC-ƱֳMj{&5$|VcSV7*IaBD7[TzhW kKKvf+.Fdg>M2MBCRPa#&k}PwM) NG$l里AM˦SAٵL 4A7;?,tIUnvŘ$&5'z5Uô}@Ig#.CITfw>d3n*1ZE28jlHX2t2cJ; iA WgUbt (tc Ssm&CoJ nqiT`&-YdnÜmr]SBJ!bV IDjKv*'OKEO65nkAuccȓA.vzU9L k$ rK66g=ǩQ>0U|q+iDN\5 jˁWb3<<%j76Fgf v毒=;CX4?x:T3^.v=Fq#K)4Ewz2LF-0xkdw~,7HDyJ ^C}r_ '9?D&7*xPLTblnN Z<سr]3㓒::Z"t"-@{ue8oƣ6sXȮ5e_}`nevs6,}D=lbߘēOדkyu>qVo[b²:fBNvURⲑc´9AS:o^Ǯ,!SP,u.ӫ/-]5aM_߆i~03|yP endstream endobj 3 0 obj 2966 endobj 4 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 5 0 obj <> endobj 7 0 obj <> stream xZI,7ȳi͔H07n4c ~sߟ$r>,-)1oi5÷ޮoq|OLOg{1|gsNgevgghIWOlɻI>fk#|(0#l 8gsOlFXUFXb ?&UV.{'oADK9d"vwIKȔ(,Ȓ{F&$%a2ˈ:0W Ǭ+奴~ooffeV EYLd6 '-Z5E/$vy02̊&fooKoiDA.6mv)eKK# &I I6O-^I{ԋrŤSJ!A03-0ud1-d3yc^}*}o`hbLM,&=lvVՠ'U6nioޮƂ]_)ƺ%xEgeG0JEv0h`C8T ,- O.fpF|i2 l(ZR2y?;73~?=r~7 JKǿgx.6u, *&eu$} ~܆ːthH_ oV맩 RÑ@be$azHy%pZCAs*[#L+h6:U{3LY?!V5֦:+loD$gܩy$Dh,0L_mEQ IdZ@FS%bcF\6 ͫޞ)7e{+V k$r>` jVTqmʮɿEKO a5/}#y4~/;tz/P5nf=d Vuo Q^/ &J ,BҲ c*فKXX*R+|³!Ok "4lƱ:{3ՙ/Y>~BkClebI -'b dKv*J[/]ppn̆t'w=4縩 ҸA| lmH+x Tm (Zѭ8DrQ({]CC tٟJ*pAv '94YNSҿ3 }َӊUܵ 5{ d8YS ܀k %H+-euw* 3rzgQ]QAi;&nR&֞VǻXIك!pP.E4rŃS]b*v 0x):W4tQpYdĶafBv Wm"HAwER>Xw lag%ҕ*!U$I@r !D[際KQScǭ:-@ ! =t炐#?YY3▵<78LA詆2`]r| :quo㲺R|7 B ԥ(]r.tKG.&qnDjT+gj\P$g2Cf]%R3r@0S$![=19{Q#i]®s;U&-"q] q gZix%erRVN<~s6]Rv># p b-+-.u[G/}(v4%xG.NKJ CDo!K蘮1*f͉b@.l@ x.a2Dq"Z P+A^׀! n,{e4?vr \{WQb'QK:d6RTDǧVrJ}sb QRj>,V8&0[iye)MjYS4}feU)DH[Y/g՗X@ Xc7a> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 10 0 obj <> endobj 12 0 obj <> stream xZI#G_Q3rBP s99͌ ffk噱V<~Mqkkp󠣯<3Fp]+rx1$ S 4rIy4r˔u8w"?N))\l0^`̨tOG -0;Ncrc[ Ut z`&,E<53Df*f'vY(kBG0 W+;F&\b1+.cFD X3ob"m夔Cڀo-1E;b2 Ǹ4+Xd$m6GE^\T0Q}3*4G6f7ܘS)+5QHwt(p+ls  pV6US^`$.[jl%v: t40]aZ,.^sMvYW&9*KTmͩ=*2@% B@AA~ pK!bEg5p۸nR6ԡCTK tN+ NlǏO6!x8սіп=/(?{&RZɈk;;`Ǫ}d̈́ћGD 2u_UxZh:LuT'UqCX)M9RŽdGq"Ay3Qnbh5s)yυnA63![yf6~+bE!=EkF, K6Gq4@^l}ï`pm+Jh:$5Q VPlx?g(WR% aEQ_G% V|#îbVĶåc;kx9+8\aIg[2rEZ._TYP˽h/Ѩd?ڦծ:Vapڢ>*+Z86X37[T I+-%A E"6:؄kOqev\6Hүئ7[v;١m2;` Тf4d(~\5:2,wT\6sT jM:aؘ!mu)YahGuMsS-CC-O@q%mxUu¥| uOh⾻$[D^)rQ77eN !. EŅX O5Ι_Gu/j}GԘRI\*lP_ p*vDBrI4e^nM9IzqB!NO"< ԃd_eqI&B1K9Ędw A4CД.DT VX.[GjF 8@ NNwyu,ȁݶįMƇ.cpiSm{D@-{:bce&u\bGSըrdщXlRQ#/xfjk*ڍ̲km=J+;vqĨ")qA[T!?zX (Q U♯3+yEkj],tD]wzrۆQn7J`=ivdfܕyGi B8* WD5L\#DRD4M%WjmFD)NSeYBTeAl+CZ=q ungI@TҴ vUQRȢ̬1RtݸNJuYݥ jgqQVm]Ce}A?2׹~~{FLfPu46.I"ׇ~{0&uR֡6CvTi"ɨWjȥتE`j?X5o>WTjlg~m_=fݢ͝aO.D/8ԫMiYC]ngڲگKb.usGl@,:{дRW$舫۸=UshoEmPnx -=i& *-*J-7KP[!nQPbؠ'萲$hj؆VSWV.=JGIq81 a Ckn@KQ<2A1JYM̺+]$ \ &_%n0h)jm@?s\kMQR fq?y3 ibovVʑ64M,3o?#e0ݛ]?sWz;:Tx[E:=<љPeﲜ(&iJG_?+y(vmh[#ް#ufVCOjb18XK76(DJ`'}~>-_O_oQG endstream endobj 13 0 obj 2767 endobj 14 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 15 0 obj <> endobj 17 0 obj <> stream xYK6 W\ eA$)۠Pvo-v{/%d9N;cATAOL 6SLfꨚ~}z%sS4~z}z \Ohn AMK,qE6iqڅU"wȪ" ;$8x](o*e >N5j _Ȩ"XJfXzy{NL 9W:Ǩo@`]E!ґ:N ù4omfosYs!ܪ52mzegNiV<uC!ټR.qGe`L|RwR>rݍ.BX`.+g"9 BnwzdVN'y+SF4g6H6 hxˆ<"0=û&mj)>Bw$\߹{U9.ۊ/z*lX޺qPɺN0֘PG htrX5`„2a79*Xڏs$K.lB+SXWxD7/ +N+b+pV7NY8x,e)`/tA3;Ӥ|;Xb_cӘj/,'*do%VO0+ԃO9h1lF"@V˃Aw̼L~]dR9E&uOF&eo1keq-lqI?.&(٫-J)^JME}fxjr,d'RYf־3 IL"#2&545Y0|Ը t㼅d3ʆkRE"4+2 y:CjzHSb SzME7871 z]c![/O|7m[N,Wpej,])yוba m)[Vr ([YaˏC.?2RHg7h"aOR 磜,w܆jMs%7 K$:sa؅x{) :Z7-F0[~XC Y-zW>W7@3#~h> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 20 0 obj <> endobj 22 0 obj <> stream xɊ,_QgCӮ|{37>o"Rfei_Krq}Us㭸?d9|{C=?=7h=| v\}NdgoHTNh>` O -Th spg` M}\H.Kd!81;/TۙGXII뎪qsp1#'ǮP$NOaL]jo=crexN1Uiʬ:=IHBܰ}ԥL NDd=6z!j3+qgv E~㲉v *4fܱc[|\ff"( qYžh؜"5 2 Gjm$,!ÇnKݣ_0_3w#PXՏ+Z@eʤͮCX%ıGn3NteZן[g ,LDC,~ݼ9ʘ$,7Z*!ѹ (ӳA^'6x+K+ D) [EO +S:iU U%Tm*,*k|::BܘҲ9E Ǩ8^apFHfD*<5I䜙Aԕf x6bW9t+BQVv7FgmFHI-F'f[oZprLt| !ʛgF]%"Z SUDKYR=JTWsZ6u O`;v;><]pW<ɶer.'4k/j E# sselKۭl7]{m;]5"H b=*ÄGA-#$@܍ ZZ =[IN"dW&tlgc߁k~ DmJDVMPú* N !VZ` DE`3zA``5ZA 좊rGe*MhcuxWcdknBN^&xõOnl`ܯTt툵r? @ oŋYzxپBhNA\6X3L\^lٳ܅ WpS: E iϥ%ys{ ۜUc;e[n jt~Я+o8_7) avP*- 6~Ucۢ9+'Wv' "@jibNwE*B01{c X(&X.LB@IA6Z0ZKg\7 ,eЂ#$A,XMۯdf7=}Րk,WQĤwb4,$P)uo[EwkǴb"wX9YS=F+9|!CLI XBP) ;Kx*ڝknhR;BFo:04,m,w-J#VɮiNIFZjzHB0U]if٤%Q#=cF?WJ[i43L?\jHh=y/O ^)v5K֓[B$-/cW rd]RG羆rNlޖAqê ctzu5 ]7MXYkЌ$wߐLcŽna4#\CgQCڛ:3򉛆Md)I򟚲Y<aIulg-EhޡujrM ,sC#@C kVů c7fn^>ɔ#أ&zTOrj0ZG:h.ҠUDWnmkI)-e>&uӬ= C'wvia1 &\7+QuۺTOlcS{#8χM? o)s_xrm: URT\h fOogdExWL6wco0Ttc*u8va,v5jztlJձcc!T3/=UGrYoHT-uژ`]{y֋x}mC 4-m*L&=⎫zjY6c/C1ܑwIo :?К01[WKfx"hiu3E$Ϯ(<KtEIގGۂo6jw1b 7p@le& vH ΣjnV)5s44WzZM'V9i:a!LW褺g`{e}:Dclî6S.J* & 4jE[AT]Cdywp& 'j |ug0hfJpo9j+ y}aokOwi@0VN8=E:8(SS L**.~q,9_/4'Ry=L<4J_ H SjHeJU`V -0b/p_$xJӄQHP'KBU9#h6 j$VRZ{sc4J<1q47lޓ`*,c_/x㸕ڠI=T#P5 m:\qh?̗ߪ'cV&/4XsZ&X0e Fۘ FKW)΢-\(rRlO>9pJ+ q0Gkso覉V=;*f[r4-[yd2y;XsJv!}*} z _YJ-M 4/nY, _uÅo@h[ endstream endobj 23 0 obj 3284 endobj 24 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 25 0 obj <> endobj 27 0 obj <> stream xɎ_s*`me ,s$~j%$ E/t˯'ɇS/2N~yRk<__N_ӿ%_U|MrK 9;2$y" N # PK#>Ǻm (vtQzIfH0IIЇ~ 4oyu  0bu^qLO< ">HmG8+ O?MU"(7M88r./~q*%.`W0: x[ae n~v)׼"@9neR$67a'DFh&>&7eQP,Ds(@nCB'+Q,fAU@\*2yᯁ=$GD3侘mV|e ݩ2N8ғRHu&e78p} 7BBx-܆ Jhf*]#?ц9xOy KiBo $KF%Gi[fJ 93γ#%615f,201=|"~'h=b. [|2fO6*4 q; 78R0kG}IBX L};73utܟQx'&Q&mՅX.Ç,aMVA] <t OP+tU'USR 'DؠO.,e{)_r`ZBOIFX_T 0AJw 4HltW7 6>][ۖqŭ1".mJƇQF%$:j6!c$j{>:j0&҇Z'm+Z rdb 3mΠ<>o:()iU5>)g.rb~]AEz(_ &NVdmN%S_Ɯ=֯V@XolpYFֶWvpeJxC܄S/͑>0o] 0ձlڞ-jz,yY9Ud'V~It ABmEZevnHuE)4 zhi bklظE Z,*FzO?N$ۋFîf'fnBj|=z;jYވe؉ٗ8ü8f ISGsy]2!!+ցy/!Mx]+zA/Oħ~ D"4 oZyJKjX_-%Rڕyʈse#< \w]_)Hc+-uCxLx FVm-?b/*4Mqw#2I:4Jq{{q0r.;сVv*;Fs aW"Y*)pxNlDRWy{ɖUdDk39]߷S pH{rll[ /& SfHE]褕y s\3a΀ |_(U^QӼںKS[1įfMQg^:Ov)F# [(2]McWDO(ڐYu=1wAca84a})FC#3^u$'mQA!|0ZlɀwRz&;)CBDq'u =Y<*A;mD{Pz.UaYNPDg2//䷁ŝ) ތ~q+f9]>Qn{[|58Ǝn/ٯ ; }%KmB.=0T]vƯk<gJBFOmzj2㜷~qW^wʡZ P+tjR)mjY㗨5pȠR60{aAwQ{cDK(u/dmWno!ӨMmy0u[9$ p_4םAi)(90tg3$0ݸCU\qe$f%<)~4:_w\S6q;Ƕ tbc۶N};NV$ ^bI{H?5#jf-4f{; ]:E-l ?A ]zd)]R!$ Z^yՉUH~#L#` 6>g.ʒB&y׭5дϥ ƅrN{~wA2;jH)wg!̨2g *=rWMק5M{|FR1fJ&Xgk gU*}~]>H1V玔 ?".B3_mXsg- }{RW!" ۦ:[hQc]=2vdK6m3N[Iq(*S&ז[#\/yJ3w(RINrsA$׎#\  i؃ޥ3H x 6ce+VW4ˊM48ӯ=.y8#tX_Iz`gi$RPҼ)2a9of|t @}~I3"%i"S漃]$Ѭi~VP\֞r;{55l DK;zak+n*֜ t蠁m(lVزݫmW+ݖTXì+5Ĝ?^Fm1픜S2I69ӯ/?|ח endstream endobj 28 0 obj 2978 endobj 29 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 30 0 obj <> endobj 32 0 obj <> stream xZɎ#Wl@-IBZJ֞|0|2iXT%ˋS7;~8GÏ_.oi~/c÷?OK=Mq9Tēw;i 'ɗ۴c"W6;OgRi]shOs[Y,YNXBia n'f=mJ9EFҼITB?}|}4VzI#(|0SM[Qqrktcqyo_Xo]U@qWa&s!8fm %7|f̲BJ%+ /b'O֛.i8,c툺O}z0# y , H92Q7(jzl/mW!zG H̆==*L1'c`~S&dd{^27!ekIcCǘWDxJ4jLnꁗ p=ƴxkeu,CF0LJs5y8FU/Ƀ1dאn~Q@!@Xu4kz}N 3g;3 ULkic!AGzzQ}7|tu5Xcɾ*-^5uUbV!Rw 4;g|&`[,n]iz=іQO)[a9G/m8qy3ՙyo1yW75$sA޼XۣTO7XSQiHهm˄toH4F6ҹoM->ަѵD-:d}Ԏ r'D S+Z=fbk=Bv̑;+(6i!B2n5 ŏ@ NTO7ds5~%Ll\Ov%>ŵ,83KUQArm]VaKz$E}wǭ- zul]6i1JP rU74}F d ,~3'mR&Q(d[ќ^#*Gdҥt*];'ィT$!%KrAzs;~1R]Ww6 :OQk/ҠsIw=-VڪWI6t>Ί!q^a*-lKoLH.1 h%krFmXJ0'ˤ^,1Zq&PAņ~g/fN6m _u y r9g$vɳ]JwpRG?s1K۵jBIcv.kǪRхּչ*Nm7S56W4 V@h"`'Y_~f_7nO2%W IU18SE#2"oHO`\#uQ yDղa^f}aVz> ;>. bܴV4\iQX<"lvhqj ~uJzWns6rgBxh]w@!˪']O dⱔQfuYZHq|v*/鸿+zD>(ը0y>̚,?d˦uyh`d:鉶$VPIpҖ=RWsglri/g<:у#!s\:,֛X%|(J7YFYgdҨ'fL;<5fWD&If}R&k&sQ̚Tk+J,p9~Gq+'huP|/rIL!Aij@VV╔BO m@^?ES;7Zm$tZg7Έ:HC%Ӓ86]$c&m<'~5>8د_n9?cYm>kF;4#md)-D[Ivs:/];G@ 6CmEF }iˣRIXo}PURzΪ[ z>o}^XO8H)\xP_l1PBXʸǑхDhT]%clȶlWPVKA\vt= lE nIe@D9`BxAhHkx5CN a3t:ʸWFafj]&l9L}dN]櫺KK] (:K*k.e6&q0.ezUEd{58]2bK.馁Ci$=lRо)__7U0`ҳ|Lx^6#`iSΘg<\~;|Gu endstream endobj 33 0 obj 2853 endobj 34 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 35 0 obj <> endobj 37 0 obj <> stream xɊ,_QgCӮյ|{9R2jƦ!;KK(MN_*m1Ï|_:#=D_?|{C^ϿŜ=?\yF]U(ZcDSA9]pe&<+VfAݖGWa^|]C5x2z.aIrxNH' 'K@6p!*`vĐ`q1mID$PD#˻( [Oa sg=#\AObxc L#?W7mO@ P!n&F$גYR[juvOfdYL"q)PAֳPp'%dS@` Dс:aj[Rq) GqzA yҙVeJA%ri_*L܋h3~L+R jwPbY{~n\ꀙL-cRYs`cp3Ӓ1l2PFaV,J~"@dPnyK ›[~W>o̸,8Ob5,U > n3Ñyea `v-&O![R@wd#42-eTxf)vZ ܯS&wˀ).ks )um#am0Ԓ‰L-GgMy[0Qn݉@{(  ( <vʛ0K8:]fZ*+jdV"?EB+6HUخ*.}tK /} Hq1Gw6oRUaOQO-{-`f0kFx@$4]#9 6*pCo--3:/ӌ>i,J||S ܸ«);%Q"\jρx2NrjLi-5o Ռ1{\,f^һ6L:1oe`;Ap8vlˬ͂+R[0`H!=e Qǔ^(IF2}H6nXVZ4kkٻtL2obQ.fdn9 4fb̼CP{"] s/'ZC2nr 2FS5q쟔VGn6{RDžZC!c; .6`cqr4+cHm{!>Q`5Ylqcp_> YPƏgio<­qHã--(MU?St^">Ϝdj44e]~]S45J+C+Z.P~?;u߇o_?l:u_y endstream endobj 38 0 obj 2373 endobj 39 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 40 0 obj <> endobj 42 0 obj <> stream xYɎ#7 WnJ@m-H99e$!)b'`[ E>lvӧ)]ʰOfB:]_v{]Y#${h/bFsa.O?,0afΆџ'5E ކ@S6Ɏ&/8UD+00ӔƢʾ(M!~Gk#/3"Dx s ZX3_3[%LpS)EYͧstWbǨD)!_@O#b',%W+1U1 8?놶̳ XQAWa(#5-^(`K+\ilw^+'a̕~x? $E?if_ $"fF >ð'|\k^ƒ[&Apv3Hỏ!0;! شҡf(u:EOp3;ftf.u\V[3P617kтāz65c|~?Z ,yX<| K)fl*OQ}/jddElt ԊpjuhP_scjTªk E^ )K}E:͚ 8 E D _A 3, nb.1W}kcrƄIղe:P*ˍTySANDxQT#u{pz幌bV28UwR`bgex>!)Pb ;=Ե/4ңYSB0$3bMG,?Gc=@џkmG\5~5(һtMvhhfiE6[r}}[HK:=Ne3u.3Fy7=ંgUs666|!Q <4әgrA\2ޭꈘ"M V 6 kĩܨ3cg13E5OKoR|_5xvV<PJ@v Gxtav;}-IY9|AЈ};q45K^ZI'aUW^gfqV1C:uoA7!g-n5Do[br9~2Ϲ4ҶYE2Oڪsbt)•tlP_c=o-Mѷ$$ZwFh8`ֈ(`4򝙢#H9ῐ5=HHjGב. UM}k~T9 jxi__XSd[ayoq> stream JFIF(#(#!#-+(0<dA<77<{X]Id/,  #=''x:1}'l g bkCb`.Zu<ޘ^Xͼ766666669MaOѝ4 ******* b?\g@c^k_Fl6gsqo漭D+B5%菠$ 9әkε=sm z \FJ.st:c`y9serݥ=;y<39ӎp;θu Ƶ?S{Pzsw _ y-YNYl`B6rW!pZ {y}] l¾.#`Xɿ@C>%û, U!p\ JͥN354P.9;fsO5Զ'ʀ\knJ^>FhsɿH.9Bb5)zfޣ`<9+3;!p@ v3 !p1\F?ހ|B6@c&!pZ\] |.Z\plgNt @9+4.Wf'NT46B6wz( `H->o\+㮻b/^=0jn!nrRGя==I"h\.<#Tl#nFc.??#`!p΀9@r7W9x%`B#p e c!p9+fWOF#`5 `fvB!*6@'݀!pc5!pol S3\O[ϫb6ζ'F6l 9D\zK8k淚;ڀ#`@K2y^_W||76y!p;yoog4;l@Ϟ% g;%PFxzX*vV>}sc|y\F 6\^}FOǗֆJyXBJ}%\Rz!p T(t sF6B<*l#`JBB”'F4@g\v6#dk!pf1_vǥ9@jAloVg%{PlVǞrԵF).kF6yp.:J#`¶*z6yݨ Ja3NtbRr7\F6KՍú5+:yw?=whv\z.#`Mx1>}OJKˠT] }4 Μ9Β;tsFk1.k18I=ck o'7:c\n}7:clss:ms:lX9sXz''q?Ϭ<;Ϩ<˗zaפy=~g7?Wy=xR-7}'Ո_oחqio 5/WP1>*%w>y=?y7PWȻ#_/:!=zfմz<<m r7c\7ct7t7oDoxyoƸcƸ{k\@ s:8Ruy9C}9~§ j,Y&/;sڑLŜȽ5*J>+j,YPLs9̌̚d&4ɦM2iLd&4ɦM2iLd&y:bfMf`-^5wuk,%oyVn֧J@ɪ}æ-I Ne˼똴aq*-͈@D|Z)| *"jc^Uw7VO֮18TN*[g-)lƶIS-aOex*{Χ4i4ip4i4iIM&M4i4iIM&M4i4iIM&M4i4iIM&M4i4iIM&M4i4iIM!DHIM&M4BzJ*\E`x~i-uzJ55ԙ In, *zQDgM5W_8V*z%/Cz$V&! cr8gsZ+;§,d`L e#_>mFHY!!E2]8*K%EOVTV %YҳZ*sJMy Ft0r ~ڷHD!03O-[ONm&شGczBl/l41(qh ecyqf櫏to>>}!@ҭTP:M[! [g.^an61WԭT~IvU}uohl= 6NBːFfU׭X QbCT/YN 7e*+l t=4j}`)'zloW[ge1Wd80C\f Eb /H&SsL1tQ*ӧJd#uT:3iƧ,3?dYaIbQsXMYx".7UbU+tJtԃC>5"xUb `Mc/Q Ld1* v7ƬS 9IhZ Z),)%@vNr 5 H0^FKG>>mpcU"s5>6O92<~2ΔFf"Ҹw z ;t]" 7~6 .}6`~ fIf|?voӑpHPcklcm8ߚoiD Pxٱn}m/?lS=䪷vUzoɛvkh;T8zf*Z;'餤e7ˁ&dدU_В2Ȏ;UmYrhoM[gg.`˰p(g*hKY%*l.JVf3_<7Q 7 WJ~3iQ^T MU006_sq8Z( 4T+ *SiO)n;o'he*;,fH?Ŧ3)vq,EцB 1 -;;zlBRi?Ptһ-NQAv12%DSO_uA\^B[E$ePK2zBzU"3S.ʎrflU&8(m׀cJ̉X׾4=G6Jؖ̽;tžN]5SuCPS)>]54iU񢂘(1QPT(ٗUO%oF`KWVwn>N_~(zɠ*-VXHGC5 ,؄[{:vvod/*wj6/Qz.nOy}zڻ{;\V1j`7 a[G91ʝ4qPQ*9)EMÂڏ I`|wMȸYQ^шIX0IX ծtVpAtO.S[pݩ/~|TXE[gaBS\GةݩGGbM,:3 RŚ%&IS~\4ja5ݱZG步 f{E`̯p㡲(-8%,/hO%p>qkl;ˮ#dtSW= *,-SSGz:>:~jG eO 󩲏CXlYTޚm=PHZmu{MbՏE=zrۥeJT?Ӥ?tOmF4O:TYN\*c*lLuntՃ*6)W`L)0XZU Uv=%N[BYH ZXK a,%aÅ8ZЀxZXqzJ4G[g}jΦLJpʼnAY#NoʶϠMqHM&XPaPZ8&%*lVdi`~2yP=%K|˃߸/"e@8m5L*S4OeR*w[UwCMBX)*cBi/2f<0XJe[go'UzJe[g>_l;mtT/U} TΫB@ AiHsS_lﰼeh:RPvRÆb|lVuR8*;__]{vlKl)UUf\2!)%X"*l iBTԗ/R^Iz%Kԗ/R^Iz#f%Kԗ/R^Iz%Kԗ/R^HٴIz%Kԗ/R^Iz%Kԗ/R6m/R^Iz%Kԗ/R^Iz%Kԍ ԗ/R^Iz%Kԗ/R^Iz#f%Kԗ/R^Iz%Kԗ/R^HٰIz%Kԗ/R^Iz%Kԗ/R6l/R^Iz%Kԗ/R^Iz%KԍM$CC/yk>jæ Wy8MBi$=5O -@fք104G Mcj( φc\V s&11>an`56 na \aᘀ X/@ׄ232 \f ,W ef8ea` k,x˜p˘ @&\c\jsvZF?)TN ʭAtg X!Q5ڽUm'*пQeCk~V FQeCQ~)5nR('qt !S—3W;djTGz}O[[Zv;]-l]:VW)|Wcے5͵Ӫo¾[7 <^#bvV};$*)oE>?Lڏce ,^U_aoGWTtף+můRʻuE67_gSߠ||ա[ ʵ_>>KE3P\Ll) heL-ɴ X7G(lȭS{!`9 5+i pxv< ^A 0CYjҢ`ds JrgPX:6PSkBJ۟x3!12q0@APQ a"`pBb3rR?N }0FH\u'OOSI?kX8-Q [űl[űl[űl[űl[űl[űl[űHbض-bض-bض-bض-bض-bض-bض-bؤEl[űl[űl[űl[űl[űl[űl[űlR"ض-bض-bض-bض-bض-bض-bض-bض)l[űl[űl[űl[űl[űl[űl[űl[-bض-bض-bض-bض-bض-bض-bض-D[űl[űl[űl[űl[űl[űl[űl["-bض-bض-bض-bض-bض-bض-bض)E?W? ): < 7.}G EEX6A|aאMyאMyCXuXdٟqhUq! z! +觹Uq˦OG)~Ȝ?HU 2DfyC,D"?iO~?i60BB\qʥ_-ANEq80J*TRjTQ RI)&O Qai4bjIG*TRKI$TRJ*TRJ^;lЧt0Ӿ{wT*Wv:Qv(]]9FBU'2$J5Wl+ Pf1^ RpH-b؋TKK SsBJŹԡB(5ӒudF2!t낉T^&n]0*ZU MUJBt*aeCƦn& L\=Ɔj'BbĽp^^vuʉWNV$'}];L:B dB (PB (PB (PB (PB (PB (Mh!(PB 'i^J_u!Rl[DXŷ S43C(vXw2^΄DԸJPrn{kCO#!.>r\^;\}қ408phw{L{LϦϪ"IͲ;O}} pR0qpS%jYjo*:xas%G󷐲"N5^OoB6E" KR#{;%O+ę쮣OpYԻF7BQ+`K$R%:l׍6't_&Ucu3E{.Xw%ڔ~9GJc{#CO#'*|u9z^ӞkױNs2yZ85fj\\:s0G9 NdCS߰"yaװfnC/D;W {%YFoMS*W%ï9RNQ!*seZ/+L!fTIHE4qQz >j-yu⨜xeױ". APH >O > 4$#CR D<Ua׊ʕQ)/ ZfmFD&.Z`FeBEE (XPeC6QFxXp *;}RAeAVtQ C:ZsEIlC`ï8z3/5f4!׋_C~YGXIL}jH5uqʕ>Ten=5^5FPB> C1%0Mx뇹[9( pKPl*ed꧘pʟ$KU !Ԡ5⦼xG3 rVz$X: T3( IWHe&p^,:v61kïq닅NfxŠDib^ahguï /.(2MFYI$BʊTt #O&5QcQIAYIO׋%V_"Ba(Ba.)%aWi:0*)!4APŇ^Ll'EDBHh邍๪:Oc,C@B%1HB|GxkĦCg(!4ScLhS z)觢~cO׋zO|$,1UwL%_R"UGw駜a׋EƎ/Fd |\TBMjYE8[냯ǣDZrj㊝:(DCsD*3 \&NxITŃ:a1X CŇ:SOM?W'Sxï4R*K|< f%u~>}z)f"AN,HujPRrJL̄3( 18UN6W'QQ0H2!e\W_1_1W1a,:  T|V +HR:+JI:&k|=ql$**}FgeAtʴHcpQ *#y-B-B-B-B-B-B-B-BZZZZZZZZ P P P P P P P !jjjjjjjjB-B-B-B-B-B-B-B(ZZZZZZZQ P P P P P P P PfB-B-B-B-B-B-B-BBH?=TB/EOaȗ$K 0e~xE?< D_>񮄈!?UB}YVJEE"Q"BЄH,^HWDC yASD1zq}"R%/B=M0b/cSR%"&N$'D<U"{ :AsxCkaD:CeE |EB!O1"OL8ZEbM܋EDz T39:E3/ǥ)ufdjd#=Ƀa"Abft%>Dz'I^D)1gAbS2|Ș*DU UffU fO:'WNRc apRTŰfZu] I Sa%y OKBHPe\C2M*$ȕP]HTMHQG)T*fiBUB* ) FDt>V(Ej"Pl7Qy*o?,1!QAa0@Pq `p?!j(A+J2K Q'@&Ǫ`JppĐFfhh?|!E+Ӻxk5z1ʘa/Gd7 n+ ]w%kJwJwx}ϵY;);@ 㫓r쫕ƉgnOHڡQeSpuW D4F/>< :xQ1U8IiM1R)HsQ*Gy*UpЁFa90J!P~Ο0z<P/GJ4^E @^J<P^-Ը Թ㴢21P0~VP$P"Vhcھ܂jGh^o+L>Z,Pkۇ`U/< S)AXf\Q,@VS (qQ8-5X&&p{ r uprBc[snoY㡡ri1p9dc'mAQ7H+bf;0|UU</vq Qת51:ۄ`Wzi :El/. sv(:i0 ybq Bn3qUWU˭ 6M%oYЕ{*"ҧx./{mѨ_eXT׼&77MO\ ^ƐkLiF388B qw`"ikQR^`ꎨS\.E؈VƳNmkٿ/8(ؔlJ6%FģbQ(ؔlJ6%FģbQ(ؔlJ6%FģbQ(ؔlJ6%FģbQ(ؔlJ6%FģbQ(ؔlJ6%3 FģbQ(ؔlJ6%FģbQ(ؔlJ6'~Sz_>q:=êxJT25P)صGL|<›N_zݨUZ97.gp(k^I_` -1V> F/8gPe9y'92d%qǼ=19y{c?ɟg3L&?ɟg3GꕷMdoFZ=g9yu_TVO! Dp(&lޣ쏙]-7 &mfX.!Y&GYv)=|u]v&Իe>YO&>rҍ4 ON׋ MaUEa([˸: R9Kx6"hiKl&AITt|+uO ]vWoKθ<êy/K窕tĦ缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦缦/êy/Kj Z& (g+9Y6['+9YVrg+9YVrg+9YVrg+9YVrg+9YVrg+9YVrENŁiVrJWDj0˪YVa=s. X$1 6c{ TKB8& P{ @29o=s~S3|J9<ȡ[wc7xl>ܽ6Uq+|~z^_~xVQ X/XplȆxOOuN@Yfhk3!ף4E^3ǖ%̎Y_0Z+s%Кyb(]+i0HMڥW⿨sH6Yt -t};/Xm(e&ΖJkH)ᤰahSjYb1L6뢱R.&5jTQ4"Jh)uN(Z.`|y27;@YZ uNt5 }UKު]n]?!\L & @u,JɟbVݯ9NVK׉Z;iRJOC̎Y#)cdIX+vA]vk u뛚"p%9*B84AƮ1lP#x@ԅ/{;s;@+{ޡߺ+x7m\gS z@!уzuNf{_{ީߺnPWڠ;TBmkX:^u@~AA;Qڎvt1(aW[V@-Ce䠵-C`6/{7j<[.2 AC2noAH_`2 喨'njQ΀A%.ͩ7/oWM|_ޗX9%uYfIZ1kF7p؀Cezka/e 8²y9ui-ŧ`L]:l Xg%]ݕ2&mV+>lW Nz\ZJ K*-MAb C3nBqBق%kr j9f'/q{STkΫ~tZ^P0#Σt=8|OKNˇg\K=h7 r*3ZX?uO%{>X vћ|8%g`TG3y:c#c*--tE]%Ʌ!@jW{r8=dkbX'K-*)RqἣBP@vSz_ց@7%O|8(|tB>t(i:Nfϋغ!0yv3cn9/XEnZL^Qv,juMm,B.g>g`T^p+f nZlkxGLGMOiFrCmV0h9e nSLNC eYP) 2CeT,م3z&Z"|{%%"uj5& :J4(Yѹ^\+(YWuO%|4!@ s9Oi%KO7e8L NA0NSb'))9= TNCr+f~rC02Q ).R 6]96 ީ/D3kJzj]1f?2b?d'6# ⾽/{?OFeP{*)f&P"Mkؗ7uc4uNn0CUȟ(-ڄk;0m{bo}TnV"}YS 0ZXkN Sj"aw }Φ:S:l_gK]?OZ!!^(p*o<QUk> 1vBV4(GgKSϪy/K?O%{߈3K%Ϫy/K>u+-` MEܮ̋O_ j.,΢؞/z}Sh<ĵ/GVoV#Qʜ=3̜"z[֐Af5#K9Z¡gWpelsq?ݟơ/e7\)T rjfzB KJ)op-'Å$ʉ Nap,}p4Xod"{˭"nij( &exBqX@oQ[ I7+im8Yty/Kz?T^2gK?O%Sz_T^p AAWx FZ^|P4ZЂ¥_ai[kxYU겠R^4xG[ Vu=dkj&tG|'_1<TSuX?Qq#"BY\Fa"KN(4{Uȟ, ڀBQVP`Z}'Oq>}'Oq\&>}'Oq>}'Oyq>}'Oq>}'@Aϸq>}'Oq>} Ƽϸq>}'Oq>} *^gOq>}'Oq>}DOq>}'Oq>}u}'Oq>}'Ok ~Rz!= "XcA85V]# [!fsPU0>EJ9F750q]?DP D\=AP5lK)u%Isvd.ZŽ6 ;Z`Ko)xVJ˂ҢRb+fIE'5*o. Q5 b0! %Kɓtq d*& aN̈  \LmL *G.Ar`@B\LkbK&ln&A[@iڌ fvg3o6 fA3`fH@6?YIm@ qsKGe66ԩCc @%7ځ}Z=,N5 ˂e.Ri܅@)#IC 6 .|#; :5b2³&rT~;mjNT?pF j&dc*khqWZz͎e\UEi%`+oBa20!r ٬oX9N8EYz |BhT/^3b#] Z'9_ /R; -瘹h75X`FXL&ECқ/ NuRV U A, 5}Kdx-dS7F%b 1zAX3!l.r_MU q:XsVfB 0zFBq=s@OYsh=w`˲Poa>!iNpP9vl[M<ð/e|YAG`;3/'ŕ'>ˑuHsX(9~ À+''>Dڎis /XwTm9^p[ aUfhwz yZ AͰ+@[\#!̷\j;!S|b!Q\h<yz2-N(RxO(H]it2"WxM핋lTvWN2Kedm8D~)bo %.ScT ׌zDn^*j']r-zp .y TU]w +sf&" ZzIR nx.lԩuPyAgL?!U68E@mxxԮ'H x@=XMJxnZ*(,|I7.t.eD^%ނ^: M+i^xt'8؁*tзA.r+x.qqdkDg'\ 4؇z3pKXM(@-DZ؎iukT@tő82 _u|=NB5 %v.̓RVvkn.u5Y؊ӌσ+7B' &$[| "G):1M 4'<"9 MVQhRÇx%LK Qypޣa*b~VlMg+h㯣c<p?)7lzhg?0hB@ ?o 2ӠU ?G7???/97c?評??W8~<?A.V{Eك?wwu@_,gGŻr& )X%gr u71P>2w1#+ Y? >_v(&~>Tw__Cck?ĺAt, !1QAaq 0@P`p?>:7_0T/;`#+(eWxǢY|e8_ i K.ę8 SOe),(mٓQXi7aS2,&n*v#Mi#r۲2ylO`P@-wO9ؼbv/9ؼbv/9ؼbv/9ؼ+hv/9ؼbv/9ؼbv/9ؼbv/9ؼV.ڼbv/9ؼbv/9ؼbv/9ؼbd?;W^sy;^sy;^sy;^syG?v/9ؼbv/9ؼbv/9ؼbv/9ؼV#L^sy;^sy;^sy;^sy;^sy;^sy;^sy;^syF;^sy;^sy;^sy;q *ôun)e]iFzAOg'5FXo@Y VdZ(yaMU(&}h#>@@m4{e,C[mn62PV*SЮlj-]E *jg5AnUݟy\+>3h)fRKd2VUktTf fC52 Lm!eJ:+陰 L [u*8)l&7 Djt5.׬h1^@e,;{4:{Sc'1az-BJ)hZyMrv Vυ QFwP@qlP+XBߐ cZ{v1KY:A>\qBFfx iuAv!o08hCE@9F vK+ -xe A}Fk.v)H:[98m v208&N;LJ]QЏh՞ *fp֛(C&6Is~":H#O3L~I7~2Vjvg6ol)oeN9 jQZjݷ~(*kDRǔ5 үG3M;oB#%|G-9abtQ7(k~ѳѳѳo9 3o9 3o9 3"ۧYq ~Eyhd4EДl{9ٟ \ʜaW BRgQV/jvg ( bONS0D^lddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddb'5;32@ dɈ_tm2h.H'䈈}]񈈈}"%V* idɝRn5;3}!_8ߧ}F9b#5@H,މo josf-$%R/ZKCfYV!nJ jP}5;CK_jvg]F(KC'5 ?$Y@>:mBѺ"XLz!"P=C8] @,pmJ(h5XprLTU`M>p, ]qJ9<Հ#$$a 1.E{oY`!{HRP@L%KcC8:g0~iiq&i(~eYɺh ;3ɠ\!A-؆\2 1=KIn0]jͨZ: dJ U#NZ;@ʏTnn0:,@i:4J5g"W0WŪxr_"}ߒQi͐iy@3`ƿZwRC5f`SSE׵B=>HؘєpS|``msb7nJm O4A%~f99|D Vv ^5*%-Nc]Ӷ!B/7I4^Z Ip"c3xh ة|*,5](/8Ɏ C(.wCSc쇟8)u_)CTrl4pJ<_1T|aL~來(Y bX>=GuQ|fð"eXz9C& m̀:˂6r'>?#-ٟ̌Ėt^gPhCMA49d!vg]3g˱eYr j0M{͏EϚG:N Y%-q\p V93 E͋O8J-u_3ٟ"cr-f^/qOiCsQn v #c~{@aVjd7>u@w,N/|ͻN;aLv/jrVw;3\Q0%bqQmK75E{z hգk @%2pqeƴnz [!XN%8=F1ݼfetNs-8Ҏ 'rS:s/~7"e Vjܾ}[@D*(cg «kvHqQksV4]]T$fe{3qbϳ%:YI(@6]6yqM ڃ aMq?]IqD{ bz]V[ON@fߩe@ZY_.-e#Ao Qȟ%ZC &HliA5TCYi#数`*HjCX< 5H߄2%ݜ/ʠx\wE؍r^& hX 84VzC%BVW)n1xLQ5kM>%$mO( bfI/)0`PBpefwIfǕ@g|rm 75D2 ڝGZ7c_IX 4ܟ 2yA7TM~~prnԔjq N>;>4S#7vnob7z|;/'u`'AAsIo[klB;3jWÜےխ4>ٶ_k!F@}~hTn/ڍ Gc:v>ٟ%4Xۡ=ã9j+DٮD@#.f~ Eh8\FoyDV,Ɔ#eⷠTpX X7zXX6%Z'2%Dtޫz* FL7fü&mQl39OmN#$ {L,(x,JHQ+-m֯؆GZ!?*u\Wk˰.: H'Ylqɟ( hF5$NƮlDR{6`>}X -J 7` \Evejf( &%"/Z *PL{GpPN]]Tud 4`&E^}o ABR HQ|f"ny@ӊņw[l]i. Fx O_1> 3jD狋+WUNAyBR^MiXԙ#*jZ UWEXX!<Raʹ«xq0hSMJ P6Vn v "E#ֹ=w >/jE2u96F<+9!Y[%hRXptbyCHr}.}~cJ(+ /u;3UCrAus H&M3.|i~"c4׸ `tP,1"}ȥy@6`F0nV0Pl+%&;]:o%T74j+h`+Cƴ( (R"/YT3FY{l5U 7cuHj[|&ETݹU;;-2 gY=kh"0pA]aUEjC"#}P)ޢ1膟S?P*>ћ9X_ۋ b#5͵#z^?p,JeҫG*<%⑧H hvNoPѰXB[VR8AMeYT;DQs5kѦg]GOgt6T^X~w?1 A.8&DhM?S8nN +ѷoԆ*P^'aq7PӰ~}klhj!.(!r@xpBU@!~2 _ɞ(Q[<#Ɲʧ.S"aV0pc(˯"$<T (A[B$ڌuAśaUګLJSģ5 h"/P- Mq9j"_KX'6vb~;*h硿@f~E Y!I e\ƣ^NSh<_Йar?vg&fCFC꭭6OS: z-iX])?iMJ>B&Mˇ0"{+]"̭nƋOh10U(.?jvgM޹$}rf~GOg?s͗@P+gqK$5&D&`!Qfk *l dT5ay:*8[*RK5_[t!8Ҩ>񡨡gr"0) ٟ݂VyG"Y uYU}t/W@jE%5>ٟ3ᶺs,rTr?sR>Aұ=!(7ΧS;@(M'{al7Dpa9{b`10~y+38{Il߁h`xODAS^10t )ʵK|ʖN4.舠&]'w~g!=z>PNI5BdSlbزYd B4 xFbA+R3)9P"A 21T^3LMY҅!mQ2&3CSz2R:Ei7UihLMyZE+~P K-.kLPV a#@rq6?=%Zwvo2iJ kPqH4Rn4!<j44f~||N0T$TYAl*h6*k +(̸, kA{=Pb::=j@kz*,ЛDeP6 lϴ q+OЖ`i<UT\6l*l6V%q 7&g8/tJ`vgLo||&'gf~A&B-: U6}A6yBrS-5QtFKˈ5gT=F  5PQr,yJU%wЊin|vx9_;3E;Bcj 6eոXҬ;l@SxN-o|!Z8tk57egQ @?YgϞXUJ=vr~0h斾{-Zr~ V:/J HX<^qGnb=!+FBENe2#lp`H)DBgBpíUv΢z\꼠f) ` T;3GCW=IV%Qy%CW O_/h*٩eҩЄi28jn<Ƈ :\}ovgMgٟ7;3u;3&Xڝ5;3&Xf~A@Ug׌lx[(q ^ ذ h]5/e^-wD_O`"q~ҕ;z .곹'*HTkk[MVTE%SEQl#`o-h`9dnk ].ܹviBwN5uJ@8˖((GDi2_x*"B2>-]: eX.JH< !h`oX[H܉ҰKԡ.w\NaoBYb)ǔU~`])\"]CX ;KR,mhNl,9U6`:8ˡTb!]m,(hihh$+K&ɠˠb*6-DT}u éjU? lWDAi;:z;3&5f~~vgLf~i/z[S?+jvg5E몿 ~Cê -`ֿ!j~CWZ!~Aw &K܋qii9.<łrx؊໱X-qnMZwسgcyN.ݟxvcmWPٯ ov~uNyJ7]su{./!CA`՜iUPˬ%2$-[[) NSɭ8"*Ek`JXJuD>ˍIDJ9D)=85eUbDyB<@ D>˭"h`)]6A )=m7@V )UmZPW"@Va |XAnjoLtb%k`J)A+H23B;5XH*'APDʳɉ":$Cu20];A -b)pRt 2{+U/ hyE5qDPULH9APEv)q@ZttҜQŃ`5Xښ?36-5VUA dN0t!+FɴkF~ SCv$"@ÛA϶Z;B3JfC 9GKkryJrwj2}:]Ծ='@> ɮS<6}6qv&9, [Mk(Nf\CFVgߜV]3_ t_Ӥ n4s_:f1x ,AMG~-pw`*yP4 n?* X"AWşBD4}"B[AU %׭?K]TVƈF*ӳW=m!Po5n%ߨ?⚋ޒ;KrGlh^l?.#jGD\ lxhЂ_7ײM.D8KPڼV"~# ?t}~ tv*].)?`GۿBQ-e9aH+M یjj-\OWsB~=(]kZӴ q3t\Q{`{(!b sXd<`IȪy[Ȕc+f-de0os&_F ZԴ8z K\nnZ`5InД[$>d}-|v6g&We`x,mj^^,ѵSR+}9Remѩ%P{ar`Yat Sr:ĿV= 7= 7K]mLʲ|CLUZM_X֍P]Ps>Ī+&^8* lW8> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 46 0 obj <> endobj 48 0 obj <> stream xZI# _svR 0 5ܒ-tIqQ-{z`TE0F|G!;W|u?zo|I>q |>m82@#m􂞈6|m /DDžlh JթJbhc$&bt+27N-#, a6PWRKՓX1>mRí/vN;OvxnM3pGʔ}Ъ?Pfkw3kqo|7Wyq;eb_q>{^R13 :ə ==O,r~b ؘg<2/b|i6 r5"MI!&+&>wKjp6Nif+{p /EVr xbo.=cXaǘt7^LHzݭSEpL;[D@WdQX X՜#% ,gqM׻Olpƺy*C 1I{|Ln}?q ,9 A`(@Ē5ptWSۉn.b!rBi\-8[,å5N J'#9'>MTgX\fx:45&i4νS\Zs'0e8>&lDF:aG]*KOY:6(ѐ*,a[ %5n-HwVx.k4Vv^ O+~2墊 g{l:Utr19XWL1( o(\\ǐO"L 6>|vydZxVW,"Tu&0Bi]ժlobث ŶsH #ReyMUP29yێ@&J :Q6vUTaZU^4ja*B6yme8t$+mZWqr-JulHEF{eaOtºt&p*U6yw&_+.Քe)WR"Uj A*z]p,7Y 6&:R4vZ;q8]Ь^{v."MzVkWGzbLE8FFl:9ܞZsG;ԛ2 atK F ht}UIVƴVnL7I8-o2hέEO?U:xw*2g`Y5U> e fU 27{}ӼLfo[;މ;q|{K9wԭMA=ըSa}6{aUv3e73ܘpishh?U l;eE3NSXQTإM8㪭bLV?tחP-kvEZgN\THcK@WZ,mʙbcUn{EBI~3٧/"6_oɍR\øjpgDTr.9sjصO9Bq朆wɤ%m'&BRgyt5߱'LZv?'w?p3 endstream endobj 49 0 obj 2808 endobj 50 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 51 0 obj <> endobj 53 0 obj <> stream xZK$7 ϯs`z,iG %99ǒ,YGwo6eezZ6;`hݐ>7u ~{y{d!?na(.'w <9Fx:zD_c,h1 w| S+B.` i¡:Bxcyisč|[nY,|CR eM k`aW~zql! cN ]J3?*{&Rɢ@s`e"i|pKGg` ›A,=hzAoW0xk)^?AK.sLLRh#P [vN'[hnxF6˸E9x|GS4v.N;6&h_\/pd}i&oxR7*'_)msXcpFsj:Ĵ[z+y}uT;˳M J>sxWO*]dUy[+w[ 12͆z4,1rш@31,I͵W H&2jɉp2#r\{BT$TUՆ7A`K:Ƕgp(q#p[mtIXƍ4ONAd˜ǸVSk>xwd`j8Ǔ^8=G!ыBbf77r$E/6Wq&}tv5U\|fYgKW4 3>HIDFrNCxÇsbgl)xAw(oi䈹1f$!SaL9px fΚx[,cDAd8EbSAgB "S7ظBzC:aΊPˑ:Yk њ3d"1D_;A"necB!WR Bͣ!:m44ORHB2Ge%ϒZ#ꩆǾ,TSb:ҐkENCx\AV?V uڃk̭GZU8YYU7p{]ZqQTu%^C2lM*6 ~dɮz]:0(rR!X3j:!/R/Nw4zRQ$tVBZY%O̍zŭ}\+Ve$Ĭmlj̝[I;3U_K3E8&-b\ lKɤbֲYqe֣[n81 4"~h`֧flܕ yMFC9y/jxrqEa;h2*·k<אpVWNn@'V@ßfִxG#=/T !Šv'AmfuR@](a%G諿 ¢_`t&vx7d.]USoS1JuC08ON-iܵt Xʾu(DޅG,srCW`_W7uCWAGXyuqmSv QFoVzC*f̶2 DAھY=~qZnK=RRe5qup'(^$8먛~Tg"M8 (NhgA|z> ~᷿b._u endstream endobj 54 0 obj 2308 endobj 55 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 56 0 obj <> endobj 58 0 obj <> stream xZK# 9{K`M9@MHa2]%Q'#Ejz7~;L_4=|۟pw{;v|1?<4'qdNcϿ|ealzO2TGS9z뗹>ڨuhsm(F>[@qGے0xǃU6Y;z2>@zw1w;`DζaVt̬&)݀2 R?$R6h 4Ԧcά׽_Q }>}wfጆko8w+mi{~9b Ϭ,l)Ffܷ#"ed.g2wsٝ&0COQV)?K( EÞK }/ _eu^(5*8O_'XxY9 '|,UUtbL!)W!( ئbCV省L֖IB30#ӵ-u.AsJ1(ٴmW5V]Qb[pp!m_ ]mV7EvydVWdBq Vřau޾竼,ocoNwרH+bv*j&.~RnN(mrLz o:,pkQ^R V#f/"e D/ iQ#F-tm-ʝ6ľUsvg6E-p{xSjn rsƦ9^0;|c $818V1* %^Z`I38O 5+/%N„K >1XǃvQ`kǧ^QB/͚nƈr5nE힬K?! W- -Bϸ<ƶ#OF{y^ٕU9[sg2}lF;-j`Fuyת!=3AK+Va;XLvM9kyaiAT)8$]iZLTJ3"xke7}8>æS $َM9 ے߼ n/Gn^/z;h '~`ˊxBhγ"l,9CH%'Lǃe}=Oav p J^*2dKIyKVKM/Ső}Y1,aܖR* ZKRɳg)wnNɽ3+ZԴu}fQ+:%hHuI9|>%1/ϒY]1zqqOzavwiw1s\liaM+դYV9 -ank`xﰑֿchGԌaHuC#q$@ :Q xKI@ \Gw{un#w*!(r"Β Km.^8HEes5QXg(h.wZIŠMz:JL3Y[](鲐B]ʕH~%ݺV壬#bIlR5ZI }-|ڔ41Y5Aď]uh۔pE =\=[Һ N 6)- .*X`t=اtcRe<+3?]8T_qU{f{#y*?Es忇>× }: endstream endobj 59 0 obj 2880 endobj 60 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 61 0 obj <> endobj 63 0 obj <> stream xZI+ ϯ9u] @ r|K[S$Kz1@C] dqȞN}4T>:V9smO_Ԗo?]ϟ?=>߾.9_escmc;c;<=] 4L G;y %x9|kcRjx1D.}QnQw.KXg.=9ɧ̔jvusSrD8zf \٭Cz\qqݍGIt:. [QPkL㘍yQ+h;hLÂpŎXh umOm(0B:hp57m@$UWd CO@Q =¤%5R E,K6yC6.'C~pf*F}晱G4PQ;,ťNK FqCL`82F,7)kiU(N4v ܱDZQ`IHR[s9\k 8fs1R*W4q-,孩H&M~R[wȍx'So/ Vc܁^SV2/&8 |˜43b*-_ fդ:$hxixK^٘!"MI1l@`hy!-/ $9fe֚yeءhjk=a*徨۲ͯ`C9>֮[Cȝ`5#Zq@9M$4`֐T罃0^]޽2t*eo@Sc:Ƭ.R1Líh֞'kI0P*qo4paAJ}԰"A ^$U"lOƔ}m)4ft˝QuhPwYc-5`dI#3t6aɐݹm~YIqt'b"VEc1d 17/)bIKs2}D+^c$ q+7Ct* Cr G9> mL60.hn۠ߡ*^AQ(Mst/CeEi cc{k@ίK*@o3yD[0Rh7m][NMooMa隑;ZZ|躃혮(D{ O9nŷeʭd2wo[DODZt'(Aj0u9vL;!-{_8,j_qS$i+F[%ƬW_8b<\E3UbᦔZ1 H ߜ[49=UQ *W (\1$I4˪t3tȶ8Q;|~-'c0M4/]'k{XtoqUHuvq ~=}ySΧ_s-׷J endstream endobj 64 0 obj 2352 endobj 65 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 66 0 obj <> endobj 68 0 obj <> stream xZK$zV *o|0^aPBnl̚jx~՞ɺS.o/jN?~z8jӷ;^l/f e>-t1~>I9~s8v/^/O^+Z>p7Dh ^=C}xvh_\6j53wwb1i]mwh۶D]U8&hii[ RtJ/ՕИr<X}-G|J˸$jf*Fk/̑Mwc-سJDš qkW֦ak]]0M5-c gbBXRl{(F2bYwJ]>K97L y)/b}1[vEZKU͞5\7Vs!~w+nSYv0C"%Yc 6`ѾNKyαj̀y$喓bXIN8vsLuk^.aO l Ʊ 9ԵrU+ @%m 8UP6 "S̍1*P\HA\3:-6Oa_E'>QKz _*GQNX:36(iRZ{ TsXe[țc'?~O'&Sh@ 2 {ZwC>ҋG/dا9$A_EJ @VBjnc>#[ 36`i[+*jHEla%F Zq%'v>*ХIϔ]01= vmL)ƈZUHGI aիۀ֌mHƬRJ<* 3etuEXxtP\=3vC:.V46Z&'vԝȐUlώlݢڟ]N/] 1ҭi Z Ƴ7܉PSp^F\ Q!C +Q>b(wB xJOMIgl7tksRliah>] rru4vPv&AhM DZE=XԖ!Tj(vw"oJYz9U%-zCZl\2ȯ\1<$4rʞઋ|`WbBV`3AMB@ ${|C6{O{8Ntbp].WD, oɭ#bz#Y3ñ')1R(42qHN1Ck'mU1 C?<ĿuÏc>62?CfMQXfc N SNS+rn"t5T'w#noi(1 |.ھGҐZM㧌Tuӯo1O<}{˿.Y endstream endobj 69 0 obj 2657 endobj 70 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 71 0 obj <> endobj 73 0 obj <> stream xZKk:оzv]ҐE]e;TΣ{ dBGG*^_=dsz2/Ywŝ~/8ӏ_/ŝ)x3ޮMHkGz N7u Jgٽ{|CF=,_%rpcAǟ^?^OYyd?nN g5N >1}@ dl,Ǚ$BION "S'IKȉIƁFCѳ^&y0|v[2D HMo<G8{t^N)-fw@< U,Ǻ0Ț/6]V5W>&__뷥QOo1\mYB'.b2eBGK$ʀ:oOY |D;MDe b8-mDj7 r]XM89nB,k*`RZMhW7^xHhb=tL.@`bqg `ZroǢyh61QZ:_,KQF(oC;­ 'gٷz3esN;6*X_YX`InC(՚Y6j557݄#}ۛ͞`yW6a Y|{UEyb͈gvU"'Lz+='^[-)mn0$}0gx]9ϩ'xIFr M4 ~7"ҩldWO++T\Xҹ:`pҬ 3s #lޑ[D‘7y3/C8׺W)+j/Rgι_>M+oPP܏)[)A4dҡ`A@ f#m!30'Hй\L 5#Dڀ5^.4nX̒ht;XnH2 /f Kp0(C@5Ӭ 0HNv\Vi>h;+K=oUZ$rE[V5 P{CCBtmTo{Jc,< Xu!sK8`U{kjGKrޯ^+8RrAk4k]\sMEN)5t+5Rb zy_)}wт>zal( N6)xPeTUX]@P?+\54 Ab"B!_PwK9І76zwA 'ۊzB$JTE0J,zڐRbTsP]qX:yF?0z Tv{: rέb8$XqLnɐ$[mU)qC٪jsI\(;q LہI)J@h뭔Pvᆦ搂4%XzFR$z˪V/j u0;ߵm&=ے%)[bj"t6rA@ָ{CD[:X(j$% Etm^'^^ fZ! +d&m?Э?-6߮s3Xd9 ^N{omjNStB]}<!jmЊIԄIFAQx.#qFg!z3sh (o]AvMCV2vD%{0A| GlVێ7rQvsN't)`WJdr\A5INEN="+S'84rjʺ;$hړ D0^eYi%L&+Y oZtp8- 咽øfEVE6(B ՈKj6Pl U9:|c=tf苇F{VF ;Vwo}7XeesIP / hG bvkw996G媀S6Moc$rl 4[9 rk5ZSȃsz*eZ@D +|VEPEȈCL'( *fiXS&b3Bn/Pf,t;4F TT"=9;rAutײp7onȪ*ESH17K}+ ; ZmFaS}]q5K[rTuPw yLҐ ]/1|M~9ݬo\G6;bs*PsHtYKA1+ڕ_ʣ9|-$ r-D}2;xs(ƹv[ &: |w7t*E¢Yȡ3"q{n cˊTa>&nѤTÂb't&)9)zh%ɚcKZ!@ǖ~OdFǦZT'p\E^(ӷ?9Ͽ}˿RiI endstream endobj 74 0 obj 2612 endobj 75 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 76 0 obj <> endobj 78 0 obj <> stream x[Ko#7WY|=[6m7Y3HU_l%cc0VS]7>Rw/{ڗF?wطnoO/P /L{& ƒO}>z+ȅC| {GC~24W:13>"=tSr4%4eR5ژjČSCeT?fC邒{fqJ]=UV<{T = CD=>(,2m+Ij3m) MRÊ88L7زWC}; %=q2G 8 [:ӹa7goi6KXTE]\>+|t,ˉ6Q},'+DP)Yp۵άceqH|E CGy*eW51?),Pؑ- ;t my Xn{֏v(&P;{gf]mNZz% ,5.A[luY8-iSqXש UJ\y/B,(ZU^l6IA&ϚN:hJ'IqדIe,GBVT\{?Fo }9 Cq vN˳w,BTo`ha@ RυbwwY0,uG1aA i2k$_URVrhdKdžhS}uƮݓVH[$Ŕ:try5ƕcjXOםVhQ*E9Sn0"WbRy]zǙ(Hku I-3Y]QYʋxWiCXcoSScy½O۬9@h-IE6]u)|a8t!rBy-L/X҂xL~{f9V5Ҋ603:]N6FO*$l:i) H^ [K(%z23Dۺ3eZ:A-{dɚ D{O'ۧeզ(n9Z'Z>/ȵID猧x75h!\p3-u˸8y v1p^b?mYF1OhviRi]>nՅW 77bmnGB)#޶?[ake;Er:1v-bg05Tegu=mx^ebl ±F8幃YgiOI3l)v6?0 2cP%CSG) 3tM*SfƘlC>h ~vKpqb*\'9!: {W@oHTGN/4=fLJg-[X ~I%n}y`Q ? j}y\a/V'xӗ<'[,tL\zW{*og#1ee.Dy> %hN(|H9zSzQ8c/[tG.lz{u5Gq jIb^żwzп`_trmU=U8=*g^á?ؗvϞA*V「2g|cC 9DX:߻_۹|Ͽ@d4²}h _zZ*Ҁz#[- EʒfbtIj.Sc +A0 5Pct 5FW.Z1ڢxo%GH]͉-6z?mI2Mi4AGkOiU>%[^LnYoN|U[oAD}c&7QX 6e2RD)6m>z=2|c$8Gr#a$IV0e2EJ?WOЙ$HxYQ:6*#d6siоUF|k% e}{=l OpUaAw"Y}D^pGAeZu/1ЈGb%j1q _jT*F2@|OY8eTaK{//"' ̃#:gM߉CXTef"PGܟXZjM?Gdʨa Ng(V$rQ\H+Z UHF䨉4OAh"ڝy$Y""]!:J/pAlI55Bna8^,]6儸xLFӺ3d'V4ļEBlJYX*> QW Ix4Y7b-CǬK W5 %WPg"J!҆",i(iB jY j(VQAn~T+{$SXdZ:.VNz6gxHuWNyֽ=Cv.׽l^u3"{^uo)bPbME/{Cm!v Įv fEbv}07D݋G < SvdHY1;eIavRN;0;fyfI)fފ=j7Z=nD{7ףsCn궯3nHɐbTXs`H=i0Zc>F(@X=!;CI8zZukĆ֓B'Ven VW_l%X]w'ҽbdIz0x 7brgѐ&CQu eh=WueZZ `֣ GR-GR\h=j[6nCY! ]!yKN ;Z,5 )VHXVDV`xWX]V"wT{Squ֜NձV=݋n naįyh%d. {vV?@Q q?ZLnG 0; pYC 5Ҭw6ͺY5Q=4v?DԄعcFiRlMKe~1 Hu*&k#7fw?JX?~ rOaT_~'V^~|~c]NQ6f 3oEԢpݱPsLq˦]xNd^|+3U hʥa'sMDuMBVpI̔s232232Gs,zunh>wMNg}{{AՆCз<rԧ q9@_ly5 fǮBH/ž.oy*t7YмEFͨl[dk\|NyEv5r˳o˟i] endstream endobj 79 0 obj 4247 endobj 80 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 81 0 obj <> endobj 83 0 obj <> stream x\I#ׯـ4܂ P20{c|\rJ- L3Exw>|W϶%l S'&vr^lG; wwo3y&e\íLUmޖJ0O>>{ǟ|%DU63\Qi˼e^PڵC[uDb$]ᵺ"ny !4ZJ̰sSՆƉKT{$7m)#&V5؋tT 26M#mjH ONPXf#TxaęZF,I"n! T5HGu}cy4}q(լ½94~Ia/ܴ-Qou, k.LSnt,ukHzY .jb$yϭ' D{ju3j-N&~]d]_ƱΎg[0ynɚ,MmV^&9BUK6\hФ33d7hiS3޷7Aﲐ |K=ڋ>L2s2ꁚ3)F|\}3ƓKX4U+W"r=T_? w "-3R6f95Мjer;f<$==e јX,v ԇg5f^tuΪN49LS2uDԵXv$R +'C.nm#g7j<48Yu6y` XJ<%{Sƞz)HWC[6iSPJN)QhڔKHQtg"w`>uuA:}oۜ6\ 4TW-nY`@Y!t]gy5B I?nUݨt7z ŭzpVp>'QOg-pw悲(վ03l)s°i~Q++պ֏B/WުCa<'w|*;/̀S0JIXR{{N:Zj z)t]+q؟&OL;Qv]V^P4:Mt82]%mkfStbXSQady5uA}g{cwQɾθ]wF;~\2/$S3O('nEιj-B+)%ZdT\Kl;ny:kr܊V,ZqAau6̪M : G+,<xN)G&9 %_IZr%LI/Y)yF>JV=gygIZ{S:q@E9 ;âx>G+J.C9o!WJ\Gбtu_@'; :@*'!q }d굕uɁ|D"t7.\|(I|܂2]QmnH$|$Gna _!=SHvZ~B$=5T؇\5cZ\ 9ثּsox>ٽ @O޲ 0A;ǔ! e9S嘆a^Ÿjs8'=|%x|;J+Թ9Y!^^✧:gQcDdGUxuuů|b^WN T+2K8>wDPgbS. 9"Z XZ) Qa #he 'heV~Mz =1h)TުdF.8q781W%&϶E[W۵j(R<"{V@k)BI}Z9dv eٲb9jy0((l@xhw?Z '~4-EV;sN[\e+kkGHle+W[l}e}"(EWЗfOE_ +)^Ib/Ͱi*$n+&j+y]Wt+YdaF W2G6쥈@HӰ*}^$HLp,Kj0b/7ejF{TJE}X_D3"ۀ(BE"Kϗ}ḿ/)TK}_%iKz`! yM`PiV&UxC`0Li# IXPtŒZK[k}z "R@`OA`MA`M:A`r jO>.hB_ "K'LYb/}+`/HK0bQW]+Yx} +4,~Q}&kxJHPKpp^A+Ғ@W0+^b5`BWmb, q yq9" J`%&1xаc#`/X+2(؋20Wʇc"<?*/#epGb b@`hS !^> +AS&EdgA d-s˹k|/|72 8c( rSQA(ڵop$gx$^}챫\#[Z˓[AHh6-;],v}'"5N,#EE3'Zl[_ ]_%iꂥi-|FwW޵$us8S-q:x:_"~txO endstream endobj 84 0 obj 5014 endobj 85 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 86 0 obj <> endobj 88 0 obj <> stream x[K sÒmQ@UumvK6N7)=CeY("?RO>rJrr?OiM?=]<2/=}QNy~Mi>?gxI粼Lr^cXzr3gh\^s:ܠc6"4rLwNJ/+RϹi 9|uq#N@'w`2!3뎿UE_qq&$"0}mb7˙{8VAҏ&~O۔kt8AД k} $li)`O3[Rٙ;1&хk:~+7&4m7@; hΦM㮶'֑AzF&M[Da M`H$ $F{r5lEIx[QEP|mNj dCtRuy~CX{3@P]PhKbb}iUC"WRV,HrHs0\),G,: 82# +%t3VF !"g'ձ"CD34  co~ 3fȖ Y DC>{l%$byGm[x3ky&C8pJdƇFQ)U^H uIS+*E'z!ewsu6rGx#?qP^Q8 㷇kҜSVD̰>ӪpݘyXx}#Q'S ^mAhPAu3~#iYcqfo1']3n;dtY}^^s]6wz)A֧<|@/YD|(慣Zey8UPM|?0V.f[s0GYφ.8\Btb58hX`s2I>Ru͑PX ǘ5v= qE-4&V^F3u^,VG~[哽U`b^ܦm?t D|bdmaIK R >T MwecОZ|_񦛚ý vF:IjdP* LVy6)sH,%'%a2 xѲWobVzMHsZN˚C^5J|)/14_Sot'eCo_8z)O"t&Y=9wYv&^uQS(TjVJ U~/uO5g:bBdeVNQu 8AˆnUqcFwONuz-*_u4##9#\n S0&V`U0TTlZah& Qކ\֡!4tLDʔħy^>9UHǗN[!n($'$PĝL֖*u{+ $bG8fna$ cW8 \YݠdMDBn%7ܯyhX}͇#gm>ն*F*JxTgu *a~4~?^vR,/)n$!e(#JibT?`-G95#%˂¿"T<-Vm^ey\ka8x]]ƅ:=-rAAڔGiQ1PNeBL,'Zbi?B (O1֎*t$a[|#y$ ]3I^#q,M_?ؤ?~9}k>w_OR endstream endobj 89 0 obj 3355 endobj 90 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 91 0 obj <> endobj 93 0 obj <> stream xˊ$_QgC4]7`|5;>EHTfw 0LvR ;B2_O%Nӷ=O_9}!]o<}Lߟ?Ys3 99< y76 Woyx}{:&ĸ8.s?_~ >+>lv }\ 7onѷ l K#5)+[^h'%{baB.g$? - J,2O$4?W Px*mUhXZ82oڲ$ -2r )?b yi?7@IERppw?KX^P5Q+'Z)gr] ëu"-%:14H!183 =( xtǒ~# ߑ;7ҤR̊A4(:R{%e[Ou\y|4QPX@΃xmtEqMGcCiaYChY* CZ3:bEn?N=$ @cXa$,n104-JұKfjdmDb,È8ʶj"qT5Ժi{_Ba=`؍Ǭ PT#U c4bh9;Bx ƾ\9wD$}PJkD}RN7J^b0Zdvsw Ln8xhp0!(x! ]dL̘HB$=v̀|A3_L'2hEvt~ 6C@ #~kq(Ba}ئ4|Dpb{fW>bpAF9?ʹo6&;[LVke|ga^\(v<8'7w[ğt; FD6 r)"KMn-X5ECQ%~ J "/6K#+ȣQFQT3"b7ˀrB J7@݀Wq̊Kl,YMuMX׹99E<됧\ KzK2Cvȱqۃ`Jg ? 0).s?!lS?۴%xM`K2l.y_vn{lKsӲUs"p4eWkcY u~ ~N=BN>R:E\jQsek1˖{<22\±F>#QDjKAˊGRr"ia"Cq簩rUl+'j*@tEYVia,|Ϲ E^!c)kȔ@ wN|r?,׊V Z!ku:UВ>ެsTUEFĈ7ŅYN-q̻$+6&IZyߪ de@ 8C~5I'պ%W s]]oRWlC+swә<.>qC鵡/%`k ԴLP?UWfj?WU2ĭKA%A&œVZnނ&o #WhG1hAd뇉eu"%@c9`e}g@DѦA>U{V4WzPFi=:tEl^~8獗쳱zOw1e-uqcAjљܭd/IohЇtZ^Һ!ar5dۏ(t F'3@+VѠ1!*E-ӘwR[DHdyB07n0d{qKc45'k8 i&3ӘkF h3| ߀(OufuD-W>}eTQ6H 7HZ~垴;Nr9nl% I7]]X߽|BG۹fpt!u6FFXq8,²0CrUWc]Fxo0,7Ay҄6lO }}A mW~`*&,6MkhTv3iTo=vxh6OChq<njUVf@ΗvvC6 b7ץ7;eimG'7Jq0!BݕAo USM{WX]yi~8!E{LWO2]ͩ@!'wmGb<$+;c\]9 =n#PM)' dy)UL/#ܱl6,ҧXj ō tM0=/T+eg1 Ct[ֶ[kֶ?*pWLNf"!p-XI/1gID-hs`MEܜ戯[&N%۵K>c3R窬~Sޗa鸥b[/z\5əH׵KpǴѼHSw'1yZ Hu-F ѳQ\pZ@for%A;wI/F|^Ufz-O_޾xzT endstream endobj 94 0 obj 2704 endobj 95 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 96 0 obj <> endobj 98 0 obj <> stream xɎ+>_scqiЀ^<@FNIlOmz&><_Hbm^˯C/ߺj_~zDzç{: '/o/7X .3Np`$OCc>iAwX h܌δ $yTbD,% y|frJna1_L s$ puNlӞl'Io%.ͅb'}ua&::ЕOd#KD=IȱP"@RpLX $‡JaJ ZG-Zpz P;yQ݉BT}dk"ڼ= >{dgU"5 ,>YFUǴ* î8o^I`jB /d&_ s5ZDؠ >!gcI$~\^Xx;P{S;2#Jq(A4eT$Q5x(;pHٍՋɉ3βA==x p'a8;Q[D }vt؋sPz-W+A6q{my *Ԇu.Z@q'^oDm%Km[%&9}xЇ;D*8rIQnDx]W1*z֦\)L%֜9}L y!'\%93]Q EHɦPX!^$[ƀf-lo5P3k.I($q#,y{n*1/},N_VA.Vc\Q{ǐ H йB.W˘&(C.%IQkRT\S}|v(LG>ZYE8|Ex()e;k-oI{Q$Dž@L T3zZft1X֍-֌ .Eu jPӓ&qhj&ŏD|v+o[BRӨNeY|U\-':Lh軨pڌ0|ό˼cSI[Z ޫϱUem3X.^tlz+}B}ǰy_2!h:W{Os.i7鬙xN`tm_{1#`Mu? iۊHC]׺e-]R¼FQcRW1!+\ESR(N hU._Λ54A|v6{0N}ɥ e>KFz=^F6vI++)D6BhahgeXR},yi'M u=:^̤B[/%YhAf D }zkֿ֨~sk0hW8>I>3҄u7<͸{M0e6Ok#{$+ .UV.\"YXqfB9ZO JewX0n&R :mcPCUYZՏ~#׆lqNIsTi ?Ɠ77z=: ` 'úҵ:nWӺ:ex€y*DkZop?QB2-ٶ[kaSLmn[j3g}kow%Ʀa,2訛>M+jpQB.yA#{):_SCPiƫ( 5 W*EG7h:ׂ_g|u  X)!4YμRgq_=r:6q5(In'_eZ~=|z{0p鿇O_?/ނ endstream endobj 99 0 obj 3306 endobj 100 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 101 0 obj <> endobj 103 0 obj <> stream x$1߯lv^Ù% dͪbU%OXfz57YwH~Kv0{8?n'wtH<&{iWx\#0 0 qLw,r_AZ>~zXNߧ~7YB\{ٮK/BVgͺ6İ2!YyYU+ʬ`Z>zFF@; v ]I0JNE])(z4zn%!3ї; +G<=21`C&Ɏ{`+ڭOuKuuYoxݱRȏ¥Aa$xEEviS (̆yG w"n BbIdzZa"ݵͪ- "KTZĚ;zEvUnX5՛UtOmpn腮F(hpnLz\[-܊C#s[nLtdwc0sCA+&M#}XKF? k)c`4s5|d !EGd >U}"kxFpUګ-˾sv|iͯ#Sܱݗc=>r?[<?"ȧubtխG qiC.\[qh ҆/>vE,Y0nRz\:BF2$YsG<3:/e ܆"s1p1h(kP)+lnj `V~e;]2,cm,p bjݖC>U~Ti*CJ>Dt*V!V0کer gB9񂢘<BLPZ xtEabj"䍘-e Uܼ`^?.K!ǪڹVxSۺXTQ'f'dw\RXg-"-Xk[.ECMv& ek6JQ=T<:up[198MsY!" P(:=IJTf|qV.^84Aև6QW vj5YP Q(*Qr:[CQe]tL]`j+@)_ZDRu!Xy,P qb옰Ƭ_kKMom"&@ׄO)׼xE{9 mͭoh>tawmFQgX=!?\ JVNcSû-D7ϪKoHEO~$=D!1 @tH:f 5gy?My GyESESlKڶZXzkT W*E#Hok[4y]>EǢQ'jsodzk)5nw5h, ;M9s2I:zǦ~^YHqN~YS7wκ4*WZjC;]Fl7P ~&ˤn2)mIkQgjGQ#woBۤn2iFzZgFU'Y}*{f$0^gS6ox+f*&Hrg tyGv5d;ۛ=\3?%"ջ>at.𘮧_'ڒJyeꤒ++,.ϵ:"HmZ,K,U~Ak*[D]NX[7PUrKYvfw|yф pxry[bm.z.@"' ^M6V2*)LHff@,RWi/ Őa1hCVnj\GwVX ߲~֑3Ozz96N8`W: )AמҭЅvZ{fk vVͅ~PPzDj ̹ikUk3fͽ.+N{g:Vӊ"GmgbI'p^`Ƀ +rl.6E, (}yGݼO,$]IňYtV:wRwKZsq*.7ɼ Ec;ظ0[٪8i_ Xmlq s %;<4Bێ|H[t<|.q4[k{DkN+.Rfn|XJC JFnczd|! G$Rӯx dDjv\)~X#J^Q7~"G)Qʂp]@Ԟ~$9kJLӆlΕPpgK&JNkNTJLFf=`aiXHC@ w3LE0Fќ!uM3Un\D׎FEs }$NrcWJ- %3E[`oXσV4E!\qEm)ćatϬM9Cd bU RW 26\1+FN尫9up+j H¹;>mse%҂7N{S$ajV>A:#)h 7 DBS;Y5{TR9:W@viU&R5'`D]?/2r_5pXt endstream endobj 104 0 obj 2912 endobj 105 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 106 0 obj <> endobj 108 0 obj <> stream xWK69=*=, nOrҐÒ[vrO{w ӶUϯ>Iÿ/¿?|Uz?-*^nz@&eu I9P&5zRWbe\t $Q?SL.뚾 l$ o3mk'ϣyN 8s]|0GNsǶO!m__v[VN9-ڎH .j{ÌkdNcݕ7)꼆IRC-0/2~~0 T[(/6gT+fryS ca%.~_K'z)}g\v0Fc7i t/\.o0LU@jCfnӓVs(1k+'($> QYb"$׀L2._u|:-$*jQԙp_9Ѹ?28$ߜc/=ex#TFxMqfP#ZM'zy(պ1D9#(,*G tsE!mȖ +!H_]0qWBǴ|PYAӳ7oK@ Yo,CP5 8Vo>H@p9j#Y]TN<;zzaVUmi͚%?>p *5VǾQMb"AКnM&GÏndL>Q*9Lyc kڻ 'IJgaF`wr[QnE 8m_%gG0Ӟp/xT.t6|^^ /w5lo@e endstream endobj 109 0 obj 1232 endobj 110 0 obj <> /Length 8 /Filter/FlateDecode >> stream x endstream endobj 111 0 obj <> endobj 127 0 obj <> stream PKDJ^2 ''mimetypeapplication/vnd.oasis.opendocument.textPKDJ layout-cachecd`d(Pgd`e`P```N#ƀK1No` ~Yn@\ |P5P-cœ2h&ze $  \!DM Y20$ ;# n1TPKe9,+PKDJ content.xmlvH(@HIK#("3"PK$$2@ z9Vܻ]g՗;^wb UwU$3s{=3׸eAޫ<07mǛ:]ۿ3b?Z̘G텧W; O=khtϙ':M?}JsoU~NHe|65TNm֝,5W}>tc>[[Žx_Lh~z||ww׸k7`rlc5^(~n\z3d03YgK! AcEVۉ2ENVf4eڠmmwgV4]Hs!`:>(pO}?^*(-lvwNĂG;!ϊϙD"ƄW:?ʡzz4e3+yة~xady dDʝv6(XaZڦ]}W$Ga9c8pA G^|yH$a$Cc&@v 9 riw5+5B;̕#R0_@@pPi|fjq~a;*c)^K8b @}lXf#7|/_3'lߖO!c22!|ԉv̂idCQaa6K'MWP u0v]5{71nN2ncX5!Uh|dwƕ?Փf+?_0@ [{igXWO9a߱_,k WB$46^,U=%K.!l5ļ_Xώq^[[[*)ifvtisϭ|*/`u5h-r "'knd0rrXM),iˡ;ĺ3@dN2>^%BIltM>pٽv1)+be08`fZþWxjx2{ΰWx|xjVWx>G(?7/;K6{7S^}'ZdaM^~֒lܷGY<.zŊק B*D1]xm5a|<g/uҲt5T}ھykg/`e`0>cve辺va/gިl^>7 ]9aŅxfpWGNιi(=}{R {fZk=U_õ^<\%8|n8|d g /vU\O8ÕmYg /~ 3{ lJp.p+eN8_p%NYq"'VfnjrϮķf|v ۻwFo:p"Xˋv_\?} ש>1= OyUz 7#,P?NNp@ٚ+*aGKUPg#cU9 [۰1ۏ,-TiyvmWxޝg"?OE?Oڡܑ_á3?;A͚{&㟝 ~{:Ρe~!93V_]W5~:}6/Ŀx_+}} ]%nyZUn>^!xBV>7yWqLv8:}BW*IL{=ORO&c#65kOimVKOWwH=8wgm/z~\W^?s6QU @?_SIQU}ReeBކyv?yZ_zYژٝhǘidvUE"YFx]x}3+5ʪxm.RVϧwSo'ζS}h8X~]_3T?k]:UD-Kۤ}rZ~vggmpS>=Lw``ZщrUaY96oX_4vU{v=YD`hlEK:fV0qܦ2 ߮G#g*p5k̏O34x\? ]mq/t Òfqݍ/UEX-nTD g׻kYS2G}2>e 򙽢۾(IBS:3{ES~ ic7{֞㺿_h,ti7+ug^<_lX'+z9 [򙽢)4r3DStDFQ% W|]j~R=-eWN{Z's_6`iǿa$_m.3jd7:V3%jMs.nKO3'<]zK^f9aE+E^.B'O2`wc]_kXwxWk;K }T[S#{8,$ aBC4ЂkN@/5RA]/'@]5Oڿ)f͵^<_8qoؽٹ5_{=|_^FXmk#zǏ-x8v+B{~~/]mCwz1wz{E5EB]_UES uO]UOv}Dީ#9ܪ¶w}.ԵMGPbSG a-ЬbGgj:;a==<^u"rg uYšYԂkZ?šL7p%*UMYY=IkkӓGxk,JOBvk8tm~ROQr6b.L4;$U=:i uQ%hғUeXk7ufP-P yCQSh~!z xwPjXGbp].{]yviwZ)f]n(f+5MZ]PV]lhU2lQ2gfMYnzX6 -p5zWY-m Gth1˹$[EvY@vM!?ؠMq_h9DxѶڗ#KwuGׁ@55fԾ[ҺXҾ^O ȗ$tQ ߆|mI&`v6i_ulЮ܂Uc[,֌z,p `Wmj5< -u@)90\^9MN-&[]\ZcfE7<&7 ޔufo7eMb u[]pO;IWB;I-َogzz]Vn1.T{ИQ?(i+nw'8xH@OO}[oXbq҈Tlȋ3nȋ3'K~KmGт xBA}zz+=Hu'[YOToeS?V֓:[ewDNVA˭l*oC1ʛv{8d]77x077kj̸Ow_z\SSme3/l=yf5=n/bLmV8mwTTn|!-oF3ܕZƌu[ 6vL+xrW3lckx6D1bEM@-L"-p:³Y:vCN,s9v4}u5VG0; 0La9  <43xP2W}p]GyCjr0nguxu1S_‰,zt]k?SI! {DM_}]&}ϏE][Fɋ,_'X(/Zu ''H9)Vkc+J]5r.3"J;Jk]<1w+Oz_%ҕ'ȿZZ(istIkd5򮖦s=>;Я`! &ƹFNdHuayTmtl_{Qۋ2_dw 1cXQJ5`4eԒ_G̝B<ƙg!{ԉ{0~,c. !> ?3 ɠ$g]25KG_B8 x޽3[̀b>3יm@ '4,c'm8ޘȕ62..p zAE $µ2+M ˝Mg4L,M1Bj2?ή!   gD.>dPW Bx>ere%l`aQ4ɷAx f&4<M@Ljm8+->7c3TNEf3ǯ#6z(!ꮨ5:y!s+ 3fђ2a~r*2+Zwd6e|pq\XM3#/E aDn2@V-* Tq[Jn TaҶTBx'|cbvft$0?ou?s2n6IԭyշVf:X t+\0_V5r@%rMp&1 j-)hHoԅPT/ +ŞzM4(g15OgG:`s ,zO:Ct#4Ó]C -` G-O-H䏫:@}B~Bt^x"+T9Yߵ-X̚d_;@>ЌQ]ghgI|>'6aC"U¶ʧ =P?( |lMS3ށfۯ%o ?6e`e ㉺ai8,jfzW=v z(Vi 4s':LpܑZ4$Po8=Ac@na ̶ѼQ 'Ң#0*y  Y'(Jn 4+1 耹 LH3%T=LHޚɯĥ5Q7OG|\KJ`џ,z 4"~ZWcЯ$A< mUV@16_K; - bzN̬Yq9|u7n~xn}rYI:zcA?xd"<@CΝR+Ϣ1ģSd|;Ki>>^'O~Ki<7'bu[A'f=D~͎4뉾#m,c:(Ǫbf#6b6>w?/NtI9X]O, 8ug9paӽ'eo 6|#6msE4 zIp={g.鍸>^U6ȁ1},^ LFc3#"Tg [S-Yd`X:+77*˗x`@RI"4kCkhՒO+A35|PrgF9"[ULV+l;S"UI2-άN$":la KT2Q#s` g?5~ŋV\-.ӑ =x}21gẓPȢQ=|'.^C$ ]Ə(ZhRfX"Od-T {*^EwX4/H@ŗ w Y.@LAB\Z@õ?W M(Tc| V9CƝw:vC I# {>n3 O|G'J!㗅p9Y4 q{f`3\ᐟQ@pz).In86l\p ME⫘|+UMJЖ]l ٙ3A!g3ۚTwM5GO|?N_`[Um;dܹ*mĶHǷɂ_ ]|M<@ ͭzV㴻>UapL7qNQՆ+俎08-pE2;`m "qgqA9 .0tsKCg}_[ 5U4%S /!_^]Ƶ>Q'JӥaY~|BwNBwi|lէE\ !\'$zs1k=& vBRH>-ܺ~5p=g#g%Pׅo'Ao &T)RN|/bnjJQI^9lqk >Bܓ:U)QOzS@e<+MS"MIG/Ӵvك|gFt^*#ɩ[ilF٧+XƊm"GyWǝY!ΠR[q"_hXK`@9Rai.Yf v#oāhج!Xjumf-(=n U6/ʼn5c)֦Wrk9Xh6'ftfe)qj|~b6u],›B`(DS2[(2uߓ6ʬÚ1Y pkv0BD|u" iP!p=ON+&iv;'=:``VӸ`K;(YhEB{t}Mh }pwnIY>8K", !z.¨)1} J[i`(/S2r:ƨK݈3k"N3-yK7sF|+bj  OrnɲB>[[:| 5C>AT#mUѹ>)K)]/_VH8T~MV<ŭRga3dC'yG5H 7"941E[y!K;/^ׯկV`*\nnZC 2(eHރ!ә=9ܑ-4;v5iFM|loUHyEp8%9W\K17_u\i<qG 0cL'6a5(WٻdA{?sq-n,ƣ#w䥒| mn%trU ;P;dל鮃T2?elVZn`seU{-04+͑ߘ֝'낶:Nx|džǨBHˑ;jiTYa$@m0QiS)4j*}?M:0;m20B?d0wZ l^@) -Z*fW`.bQ@^ <i^ZY ([嶒lF0yiݔ.\QLY io>TC*,OԘ@xɃ eR޹5S #R($ո2IA<t,!JCv ]#IZi=HkzX;tpN"1Zzܬ(ɂDwOV5i*/Eάy9^F bVp.g'EvaaȰ.Y.ՀRE@J) * Ye%AUru 2`ꖇI*2As؇-16ce'o oA rqDğɝaE d6I{n-ǥxM- m{b^TiR!TQ1q Ճ諐#$&kV[;r*˨ ~mK-T l4gA[Ә:gUk,C)q|+'a?6@i"zAp/sjĹe)R!}qNpꗼ{T1RDK/mުE܇\XyZq@8=̇ 8JLTd,; G$dš(Q ǑzGDbP("f4NsC{^EӛI7f[jjQiR\3n-Y]~dLky򾟼q$\5û) &f"Q?vٝDIWRK8YWLWUu\V nEZtuoQN|lhV.ei'x0݅/3Pl\/,A5" &pGʑ6  -ͷOԢ*GLM-{$PNH& *,L( 7Tأ؟Qng<GrCwLQoqw̌G5Ec3C{A|EQN ͯ,'iWboR'\#)z=ͅ{#&]3(YC^{#>/>񯁅7(-`cB% ^cxz ooͯPAFXo:n3S\1 .k^8HsrK9yrBcW:4Y)w ~KW#z=rUe;RR^Rnn%ciw 53ZkuŊ"+VCg7W-)S-ӬJ}H3,%)E*t}a>tUNj[I~psj|zn @0[JVôZ=t)#S $Js o@t9WR77yZ0 d>F J ;rIIAչΌ&g?0 ceXa|D 8ч*AdYtMCʒO4Ĵf &k\.L#sgRBvuԟU447KE0AYG9@0m~+c0JN5tgc˦ߐ%ilfJ="1]s[h&.-U޹DL,1}!= pf+5iTqXT1Vxi-?V V)8E'#]5Gw~2Fb&$۶e 76ENkbb}OEe!(n*u180N+Xs};]P_sv&rUmJ {y1s[ ?`c;X LLJN]# #z 3~ eP9wONjƿS "_[MԽ2;UޏP̙'+٪GyxP.Kq;N[h!0d|:s;$GQLvw 7H@ԙYb oqD-#Ri"Io fgYC=Z(2z‘Y mڠ;Nhgq`o5v>w4y`z`}NN5VV՗_9v4}uitrJ_ݾi4u !ATLGa]:#jHzj?f ɻwoN:%A]Կ{u@W*'}oȂr '(iMeRmIPȠ"aE)NjiȨX7$7Y}9̈6pFIl O(^VOKwP[ I`LJ{THKLm2u!tpGILgu r7U놝QRoI$(yךVvl*^/7SS滼t? yd:)[`\G5")b9fhɱ v}I0? L>Ń¢Q ]=&TڝаmAhH^KxĕvCw+6Hab+(A=O_ko\kn6zf{_><]ZiFgH?`ӭ#(B#xQD8saer+ﲌD5UT3.+T N['f[yV31?f\ɓɣ2$ΖU˿nW9TfZ+GT‹(+S7޺`KDu' JIL܇D?M:h f%oЁqZ2|%lO>s"*qU:{ܸ"}2OLI G*TNBtR+*.`i(~ْ.eß%jT)g&e,\TXo18c|6_% l·rZoR'KD$ (]\mecGs-d$> 5d*"naCy[WΒRAqLR.y:ʀz'Qق.zˋ;3}0udotuOIɴT&$׫o1˝܅-ܟw4݋R~H}C(>zKJHYy l&Qd#MtS3!\f\NڢI*"FD^X--vf%f"B@7pw贤JBR,Tp$$$ };C9W^\z8`crpٸGruOS6ã9豉E,8Hz z5 6qpp 1 &K"g(ˌO)] Z}=T2Q#Wږ*WFJxYbS1}K.HUvTHq[s rPM㧀WHJ(Qi>)R`kHd3 ԧ"Tł6$K{ PMWF!_bQ“H,޳: g ~LĪc+}(jpz lZ_ }zdX0.ތ5@X&&K~Ě,4iVq٨K-uO(@W&cܖvީnUIOFz@zX#RX&ADF\ gG:;Hnw/e-q'd5@AQ!-Ue 3]WtccPO,U6$sʗ%^&[^G9/dK|ŭ+Hc$ֈ7 7L:3(r<=* 1F*(^Ij'Av};kZ5\{ņw$"^wr/(>\=)^-_(av+*آ`Sw9VNWnI Ւ(sQZuiɆ)_&cOݨ.鎹Z?GSO^` H`c=7i{VzHah C#y}R4u|1 ިz 8fb+1MܵF܍*5޻׫jPN4E#(?Jվ+e+ ]=ո/" T)5(.0i:)J~kɭ, 7Y' WB 5\^\/uf‘9L:YHV&㞊H%r|b.mLhJ=o0ZWiR8g|)J"I=(V,2e"g3r {X(ă7WDƇquP * ( Q! Hb zJV/\0Bqco;`Ǟ*8t@&XVQ5n_Kh7i)} a剤BA`^^*}+}WŖp,r'=Bݞ[o?] gT3A<G7[uEV4 2ZS3쬡(2 gvÈZ k~ԛ=Ѡԟo3UF^\'gx(2<672t|oF cpcyf{l;' a5^Ĭj?up|V>'OraF+av+z';-FQԡ˹mjqS\gitmA'8HFi}1a &6g [GaQmj\. %kYMjqȔFVRԲt#&sWS[oSdeܛ.NuX]û?|09⋺S=9)#`*4SRdG`JiO,-mO-fϫ=V9UShg̻aw@=uM'y.f*$r7ì!-ߑkTMMM#+ QXt)Moh j,uT3bV0@[T r, N4|.'GZbo% $!t="fA ٽ5BkOK֨~#JVl7RNJQU)4;GS_8D<ɖ?2BCK+P.`u{mN]%Ι~@nD0RNDDď؜ڊx߹W2\ձ?WUE)^kN@+\*s2:Wti9[[3j IQ.v VETДNBO gB;b~]t8vJW/*p%-;ыnԓkN\gyX]::qBs[d!y` JKSMTv㋢7l{L? grFdo-/iԽ2Dw2CFQ"pV@-!xOןzajZ&;hQ0ԲNy1kqfNnԟ^ o9X^-({}!.¤-vqP](E+`2nЪh%+bn_Jt5ck ӵBM tm 1/<+` Y7EHiɌKz(_IHy}`08.8oG z8 _yk"oPpqb{÷kJPe~Xf 齉w}mRKеDz+5gJj Wjt_9Qbg(>'.(0)|熅N(&ojPˢB Jg)p1;:qnUS!%P_E{f}Î @\aI* V6ck 6#g08|0s5 j[fyJ`d&*?'y»ױ{!F+):CsFR0R] ^)|.W&[:^3`,OF9pQQ3d.q|d{.(w ɸK첌JPv]i2 TOPVUY{@u:c' Cdz8/zF6}P(Iȃ4镅=-+ {5_V ukD(q+ǻ㲔"fHS)߮jO)\+Ќ}'k # l#]f^k f?TXUBy"9Ktfbl=' )mr%vSn{彔8 lN<aD dIfӝ/\#6OjbIBtċkT~m;)##1m7a '@tIt,l+ySܚwR Wh52 (1N-O(@IW!36QoMVHrjTȼߘywP<4T:]G)f.F/o;hYnyTw+$gwQQʄ;zP`]tSK5e[frT+sjkLz)Y<QEuNuIc-ձpobF j8H#/q9zܥ] M/.IK! /?t^֘ĈPD cßo3ŶT_|ƻA ZBg uFsTf']M`V<}1Td3&Vc3Y{_. :3a_C=}%5*jbt)Š7XkfީQJ(ɨ V6sYUo͑eJh'*az2JșdE :MdmSD%+D _n &b×"H芳K:)flWs7 '<ȥq) 1xS saypދ8u3BޑHۛ*%|InO'M /pyY⎍bt 6( [egu;n[5SUH$_#.laZ} Q^.^e`0/dbI첨y)7jڧx%j(dsDԟ9G8%4-٠Y!CEfwX q+LjP('GۖY7q$Is$fd )Jfl42xr߹@\pHE xWq0)l8_Ʊ6]'p+%ȊlFqi9Zś ?2z\=Jd̰.\=! 3q /㌒4P,eJV Oeaކ.jTYiLڣv BN +8rb#0%9b%yf hIR_x>u( `\4+GO2`VCQq:Yd[~qVѠZGJNj"==Mm%$p ! Q-ϧrgI>@86DJ[rigfS[5`rLk~xy7f1Ǚf Ǒ[ pS$J 63))q ?xc7R7hiI#{Eÿ_7X X@ `vL;vVxݚN㻷qZNx ZѹD±.II: ?Rs +ca?-VDM13ۓX߀ Rәʞ}hn*ݰh5R 3֚QkVAYyZ6sޜ9+h?W 9h"?dO@JNH;PX+  $*OCd ciCD(֌3PSf/ŐXzUtYz{[F=6d&R9y}h&5~Y,W{ VMR)I!hҳ3@d#CUN,"U7H\BĪ@8LNpcUc"y-?4Q %קѱt$Dp*1wǛSf/~z(eÙMmOO7YVC @gAaJݜcp oB?XK%Z @Y5\s&3vdϝ̪r2SӇ+6&om>־Ӥ쉲RK/` *MG mvK;A*4ISX$.ґ횞ӛeUZFCUeR+KądF Q:,qЖ| f5\,T\8? CdNC혈_5)!ZSՄNڱB=[gkd>wPV ׮P*_ݕ~Šg,zq#\YLi{Q;]LxRl0FCIֆY] v8jjN( gzqy#Se/R$7%xV՚%@삓s'U eq?k!Gsɍ+}IjWX=;a54Ш\סRۧLI-zK"\`P}afZKΨk-+H=W T͙iag p}jp. =$z62&^4%t ,!|>EoTV|B㣆)F?wtUR" b1ZxCfj0M0kӅgSĮ\mb0-4GՈq#Tn] 3 i6Gk8ZdDQj@]0Σ?Ys?6LUB?hL`@<9R:Rq:K4!f':qcC&y-R߹*ԘyP 2Y&^Zf2 p9p Q酦r@\ݐ€4NhN_#6Cy0srܷ]ܥҺ1x˪RT5{7&-%/ϣI񊼠~xz!/<˥8>S|CI&EtPKB\PKDJ settings.xmlZW8߿gtOqD> (oiCtT` 8 n!{6~ _X%svU(}r 'ElvUe߾4H (KS(K lgy}Uq$cYc(!O {V{fmhWRiX\.gKjh>/8Ƴڬ~͊sHoc缸pjʅg=<˖4V$Ѻ9>֢]e)&vuֻ7j٬p}yyQR|O[dvv;$|Vp+gb.`Η}H}،7B)ApDFeKI9&O&4f~Nf@xT~߈*?r>p}R=\Q,㐒G!k% @a W' ]|>< [sJK-晪s%mhh^/>e/V%" ;1^oP&?^X72SaȔV&qeae9(S 5ɐP XLL6ҜBp+[?CA7=I8iJ@3= $$ߏ5@a4k /|3,lv4ZU7-M;>! @/5QZGAxT,2F~E(JϦ/cmR$._VKy]i#""xcZa; NԕГ ?D,rJXRӵ-6X3N Ƒʄ78~f-p][ ;c`|2QiDpdK}OǏ|!m߷Lx֧XA1eέ4Z*BCI4 " +5xZO/uWyIwPs/fH?b_r^2k-[Q;TZlb=ڥ0YyJGiVc}E[?-.Fy3%tG74F8*"|(p*]7`8σl91,tGLmBLw9hdxQ 6d)U/p[f%7 Sޱ(Q ^=7x׮PK2<PKDJ-Pictures/200000020000016B000000D7FFB7454C.epsZi޿#@B;}ʗ]@,+@Fo7g渏=0ϫbshZD,W"EξW7zW)nY˷"Qţ,WH2[aRƵ* v*ſdYeε-u̅bM!n1mHaUǛ?C><{*oyoUSYV=&:-l5^3^2K歰Mm~6YUV/UVw>Kj)5R4ыM]> Vfb"Q%vd*?CVL !bY=>kg;>)I}Ys|')I}yQhϏA@B8#Gs=h$NɺӌH֝fO̎C`p`Oȑ=hsdO3Z'}^> m,Bhsd|^=9FL,N9`؁^y1y1y,cv{C%6c=r)vR-<J[q#'qYbW|.vyVZ;7bQ{%zB TfѻVOs#u …8)q[ :J٪"EJБI"Yc 4:mE$PMf Z*'%M8 *U b#p-o٢ wF|x'6%?[C] U,W,JXۓ/R1N!.NV2 9#?lf,L@Ը S!7R\vp/ʱXXl dL''C$^a6o*^ Ef+L'>y I;Z>-[@e5]>TJڙ(tl*iT$]x> \K{qd1eOzMZ7A칙 o`Ma7^9큛[w-mJv Jv C wL  c1Jr@܅@L_}h)(m}9m yf{3w6gg6*a njL] Hii_7cݴ_ mi7tgԫ"/?]]>c =x*]G=O[:~5 kHW;TC%m_&dB+ۊVq8ב#}mXTrn .wm2> }& ?׬Rfhs]V7Lx%PἬPzn[c&lՀzʨΔ[|z&XޫVB?S88\8wq8F>)r2gqӓdkHEFA<x 7=~X }WQܪ'5[c'6ҿm#nK *+r.("j[~~Gp3ͥ:/mbgַЎA:p+t # }B~vv8R׳[`Oq\r46k3?0w{ߋOn@8L}}zr&vqFG|äxݶr[pۀ- =~Y568%M5''pmӝx}T2a ϛV? iɛoR:mХm֌V`_p]pl:K&MG#!YBDZLQZ!t^Pj=3:!F!#1H!11bBCR#Ho6燼rsP[T 锵d`m*Ircۍ\}uÝ&,u|& iQ m+x("]ƹmfRRߦM>G>gEEXiϣk\GB㵼6O;V-vD }B" @&(t6"{l6NB7]KsTѺak[FN(. Z}PQ5wS_4R'2'6"M<lQ1+zؠbr$'t ub e5ER( S'N.Oq?^D=IᦰشJ9qI?FdJ 03dh;V#hC`H*-EՂʸ-`:\u LjF(gX)nؕG `6n#y;F*M Y)EźBk†)Fr_>5a %qB/Ϋ28oy~˛LWe5Rl,}<֮:(p6 knH?~Md!)6l؈)2_ۢ%[Ҙ?˪Heetu~q*r1j)%Fvg۰\}xH뇳#bN "sb\r;8:(*r*9H/H?c\ƒܨ" kϢ`G`S\c9aUh7P2+|fj[!d>篯u i +&D ' B6۠+BWAK@NvS'6Pkj5חVB`v]U[=!ipWѦO6p/d,):8a2rO ¯`@ȣWz"P%r@vq6rxCs{8zdv_{pDkF\2 g@f ([Mfzjg3o˱׶ ?-<.qyp)O1F}G#W+} BQi4wR^̌*!I~UJwP2jY+ v8fxDj OE'5rYŭ&y M7(5;c^ðz1r`nvd-N H7Pn2|X/u}M; G2m{nfv3CM Ow_`@}[\Jō0q|IT*$od d)XJcӚݜZj*(X}? ]QR=1. o4e>hd}ު|b{,l=3Jvju0]DQ[~?vW(Υeo.!$b<{e_0c|_2_1z /__W 7~o^W<܏%0ye///^8"M^BwwGx"'W, wI.X6'F!iΘT}k5= ZosA;Q8_sL>Qgj-E2 ">5 ]`q Ӛu-^ʜdcEfu>pf 4tz`?DW4baBdt(So -qa]4}{ӷvK<ԺOք-F[=$uy&ڸ^jj~ *!eI^eYExE%yL,Ƽ FD>} fy%N:90;:PD LچL(-&)}܂Gm-c1su_5R`""?^v}㧓 Fz{ ?VG5'PK=PKDJConfigurations2/popupmenu/PKDJConfigurations2/toolpanel/PKDJConfigurations2/progressbar/PKDJConfigurations2/statusbar/PKDJ'Configurations2/accelerator/current.xmlPKPKDJConfigurations2/floater/PKDJConfigurations2/images/Bitmaps/PKDJConfigurations2/menubar/PKDJConfigurations2/toolbar/PKDJ*99Thumbnails/thumbnail.pngPNG  IHDRg?IDATx}xGJ+f[l˲e[ff 'C4^+sJWH!)m 5L'fI%Y wk%Yfgfg~zy84At[w`hRtiRtiRtiRtiRtiRtiRtiRtiRtiRtiRtiRtiRtiRtiRt*4ð0 "_! >R0FF|OxAPFɚw_|FP!C4: " W^*6x9WfO:q5UHCMǃRķ`I"ASKM10k@ BcS X!!a4NC(@@1 P'~ 4CtB 1q1UEY #|9\[_;=̳ @ 8N;߾K?d "g!uϞн҉ˇ{85o2dl_| }OܴU/ɹeŭK|j4*0@BbW{6 g<ɀh>21՟I yC575˯+l[`ŽM|~F=]I"牗V/1>WXˢ?ܹxŊ}:/'ʋ9݀q9?>?-W/~ad !5;m9:{hLŗirvS6ݽ}ҳIm6ǰiD"0OQ@W/[8wFAeW^[{-뿐 l;^}꣧LѦ~j̙>|[;Yf=[6y`Ym>f4YoG mU:)ReU8mXU 3uVf#GW!H.JV̅)=66LuCw8O2?Ѳ3r?<=&;DEL,#V裓^{Ů~Өƞ{#EVƦm?%pSg{o;cX!t }(7ؼsOL!AA~SUׯ'D'kߡ8LGN>]uaT!S o7ЗHW!H:,&9,8u\t! &KG7k"dQpWcѵ)BB]i ֥,J3Izze'B8[5k >t5ڡ6YDrBΝ=Tw*auq F-6X@w6-['/`#=fZetUA*ھOQ{]0"XԨ}ssO g;4#5mzIZ1o~qm뼩smmaز=9ZY^v\Տ+fK%å9o%기C Y_Mᤙ׽[:fZW}@Gu4;HO#6Jadl %v]U)ʝ@ V!:(0.)D`JL/ L2S23zz|DnE>$ˏxFq8^WȰqd]` q55[k<\% WHC#"~â4Ql(BJih_OK>| 0"3mCSgai pOW:4Llrc1k;vB.T`O5-AH @,AݩuUW!flL IzW:DU) f?4+ԦQsW{| IOKRgt^ܒH-9;mBmŻzPC$ 3֟sbEaҬɩzsGMneymEРO=pfPUj3=}h䌈n[~ɈLY`slPry' J(Hm3Cx%/ۻco}@.v9V~ͅuWZ E ,#*O\_}:/X 5z`h=vLKsE mb-VDě1kah p*誂T@<IH1+Dz^@?br)DăEW82Jf'.O@,'m"$U1 +`q8,B y#%ۊ ܉KH$cR?T$" Gce+FW 4EP(K7Ъzx\ bC =]HQ[sfxɉE\wYp25+ iꤿjƌJ <;&7+%KY/pU?󘡫A ӢaEG؂ 6nlרvmgpiyE mI}M&72Jf> q8=A-]AHZ^D{/=w6н> ySaA m/im;=}m-=Ƽ$*u)5H2ꤹf!t!4 ./ >VvXTC?#ϗClL3GbI2̈9c ^ S$44~ gl _/+(K%YQ̠՗4T:x]>"qPWn_`<f e0\۝ׯ^p1 0gޓy:z'PIu@!|/c60cw PpS[J!)18/`?K KH 'sB ?'rifɐНu=)j+Ta6 wlذE0( <ܫ|((8$Hy.M-3Q_>~pƙ;8~~=GxdvÁ=P`r:FO4U:RD3O4egegRQyu AE>s \!ml̼X4~TWY}tǡ~~S?pm;_m̜5έ∌X^{bs/WOu͝ZmQ93-g2G69%M5ǎ-t؏5[JҽG~7?6Fů>3^S~o9|ap73#KwTds>|>cRJlǟxR[}pd軯8U}{ʕG7?pg^~ɜ~nܢFޓO?ƾg/{w^^hAZݥ+/9Rs-ծsW/0 ig+v qo<2`  kϽس޷x![%4GFkG^swn=|>痟|cfȢvo&U+}]]Vdg~-~0 bA_~Y# '2lֺ0.عѬȡ!#D@_wiWK}Hgg-}CG]ޱCD]Ď շGJoRn^yL S]Q/+#Kgi,;]޹rfl 4H\_x-E78Tm]EP;:;JχpYH{OǨk(51 3h3̡ 1/)3:gTB@99M^zW4<5=W@<'+YNaE*FIWK2?pOK 11{JnɔhTJѥ}IX2o_ė Rc&g̦$Ȅ'5 (y#J6Zȱ{\ g}-\.E8&y䚷~־ ݘ}f2&*h Mi4s%ϟWQ]s8JyKS݈ {OPg ^y/w]vb`o]UeZ< }GOLoo)]`o>DeiGvll,?ZB9ξͻNw^>k)LZO+MDD4KZ뽟AKT6X &•H:!!2MBKjN̂-} uԼ)緼4t&'vu Xo6$eP[\ he+n|=x۽g_l=>8l8X$BhYH&`)ȁ.5ֲk.͛w9cBP[3bfm;9 D:<%# 2Xtl)ADjw9vlFɼPu0!Ð>1-vm16kjoùrW,iQ1cQlEG u=tgwO"%r{%s6}r6DSһBEL*>2p(XUWɔKJ 5o/=p R I&h5+TyXcyVyTen}#ӕN.Y v8|f g|qYAI:7v,Qn= IO?Ph| JqE3-7ego}~=SŹ0sփxX w*Yrsك 'v N^^cn~W?nj8t˽?r,Ο[|s%,ECh&*xv.[2t\(Sܹ0ciuMktqaR`_Fn@tϮ<[z!QB`$˷|0vtϧP)m@J 3BQX@۴=v&VS`*ʭQ\"O YK`#,6 FNml+,uYVGcqR޿+)>7f:O *[(qn sĺ"4ɱ>p<<;in;zT,ͲIi)npw+-ohk\'<̲oxļ%bzzR3i@@xmsoAVP󋂂.mB(s=٦T5փTnEӿvݠ?dسO>yC' xׂx?+i֢MZ)a!xXiAj+B51Y% H=T D/ƛ *N) ,qʛo]2ms'\|X[{| O"2Ό#3/_qw2uZ*z]VUKzv&A6bшs͢ MʊO]<~hҠAs<.'>xi:lv&u3"ҩݛ{Mjx罏>tb@C`b'1SO[~Bdr0urpD, T n*??FWj1;Vi6|uϘ;ܑ]ٹ38>>2jGrr봬{ FzۗH㖭X[ yo_ҋ't/>qvʛ{wO}SO޲K.|#uUtWwalBUmv䞺nE*ZtK 2VK N31gڦ追#y| yttzApxGcH!e{FѤ$ Mm9*^-ه6Z0[]z&v8岙*Η0 4_zܠ]\V{ۂ)X؜bnڹHBbJO+=r".Ds~XUYS0ly9 t"tLִ)Q;A1 WmYƽ> 姴qr>t3+%qxd VPPR+@U*}od8 M])z.& js#VÖY6/* ~xxJwlbB3"N8}!-ŨGB]o)3Xl4w<)iMK+*]< ?ñ%;r˕ ImDQ`ql?\Dd$XG i9Ժ؟c:8&%f<^ǒ忣J.^ .bsQo=Q@ϴi2%ҕBSOjdJШ<0ҡdb0uZ(FZө| &?2>~qsQTBI&P;p,4E^hȯ1AGW.EA* SAG] ZϤ俧CDD:oi0MF"wD! 32*#8 Pr >f Cf4qrXybt5ү#2VSQ)wܰ=[\ٝn&L%B媥KRdnw^ɟwsJ D][/]!rp:(E0?kDK9>r+:Ows֬㱍Y {<.O~MKH&.;2ެseby4MArÑJ޽?ߋK[XS?zEov^ض O̙&cw8#D7瘝Kqe tFf1=V,;;oFqo<[_|GB{v W,[<|:Rtiehl_U"ى>6xj#}3;^ǔ&t R EyӘ\!WFuKS#=teXSϾ3n0/7&_ؾ~fhnV^ŚuUJX|%7X*1Ȗ.N.E<:-w>0>$/9.APPGPrf^MKNvLj uҥ0rc`WGׄ6GP@yJPO.l#8ATj_7Dƅ YꪣK7"YAKdЁ*=.rw Cv.KQ6Z+*-`F8QHϐ h@~)_d \/$#`˒yG/l27~x#خ~ ST OeSѿ/KRrFDb}Hf{>j őM| (Ԯ1o Ջac<|L&4J2X@q:-M_: W1LY)ab Fy wTi/ >?$D|)yDٌkj|)B vwh\>S`H%9L冐 9p5T88j7}F%/QoDr Kۇ-N]d$LFq0du4ŤY>ǀvB4&iy.q/9>fz'[Sf6;zNN$ LfC^s9f\O0!9 a(Jb: X5=VR>Q?:iũA+^Q҈_@8x#@qb$!ͱLKM[G-,NC.LDk~<@y=؄ 5Be8d^S?, @֪*oZ931_2{D*3۝APG#Ҫ72jFKqϜ}ֽs!m|Z7 VT"N*E$L)8wtRNc[o릶Wu5Զ5֞Ed P,Xۯ\wNʋˌA{Ϟl1V6Lvx^-r;-GKRJC=gkڲ3SN8]nذ+"Ӥ"l1nfCaMg;ݡ"_EiJtU)QSxl@[ $UUM q |U6pU%F S 6M]n^D\fa Mc1LjJ=r,>-{Mf$ZG & L`oO0 3=#Ù<)]y.' CtZ##=ek:|K"ͭaw]QyLpN}ra=^ =wK/Oݪ*A!XJFjst*Ahagdz}n4w ukHkzji^ZxuWTGW^=`D" Y(친Sw=tM?(҄!)Ç7&^ik290-li>ӣ?[qۉ=լ0U3ؑya>uo< ;OTa6[|ցݻr &Rg.۱+VrDBz ti僳Zos v 8X(&.?(;-[vM6>9v@[ؒ`);D6V%˄(+C/RYM^dfI`wTeI$ƙ6Ejԁt:a5=q ,{ʬ* }i3fyixlrJmNgO]C'K :f]eQ C"cU(u+d$le.!.#:5m1ڰIE,><ΗH{<2<3Kdj:S"WOc?~VjF F: Qe#vu Mhؙw gg0X}$( ArT,ϊP.GCS{xd\XDw #u͞Zt,=M!-.:b!vJdU1ӣG3#@WOe1"HEoǦAy1FGFGu!.t:cn9LYfӳ}./vǝ^Y5Rf B#"iy%KW JN"%9Bl!˟>BʯA|:s6~AcDȍLʈUy}`MDy3+=/eeuvbsa2 x\.5:tX"dD`GOwVv9@qP k14\ayl&(Di 4׹Q>m#>6j;Ӳ2\%(ӃFib >"3g;3RA8las⻷mqgNin:pwkԉ,]0DH=NN@L/,|m଻& ԇ0p\XP9dr(V'qv`OWa$X,R2xtao`ȃ - K̋)Yy.,& ` V~n: katRCdh@m6T+z_YHkn<3S- ^&@trzZjrc|OZ:{ellǮE%@j8w܅^U0[Z}/̢Y1]_^v>M$$%6A*jp}6'p>(ʤ--aᑣ.Drt_`23&$8$_*&,Ij}hi0Z4JiWOWRx}2 =| >5\EajwvT$7l[6r9ymôɃ-5ǜY~C|fs؝e̛̺5 .GP!zXYRrJC}m]C}dЃ0r7-?7:p )NAqߐձl-lw?\1NJ;ggba #d^r0osh/ K'XssFZQSSTmhhTʳx}7eb^2:E(%WJG=C<$8HŐ=<.`)Bo*PGy (LSSlQd hu #9~X&hiN`hQ[`a5:Zb"iRlN9{q14T K5 :00<,A44T%=vhap$.1t9*A,)\eM<} >0EDҫ:1Vvy2:L"fO44X!>*Ǭn@P453n1 UvMn6G"}$H޺{No l>OAnjYF7!!4u\ eNZi3XFr{h ʼnܯ¢d^?%Pwad"=g/XPzLT_= ïlWO/%"LNќ%t!OA<7nbeKNClmWF02e`u!u%t|.s.tu>^~sql]6dS93';V0H*q!nrc3ҠGN,A)h"DJ&;i4lf neJ~rzRedg#u,J+/tO]D*r3N?U[{rvyeUNc{Uַ%VkbP믶,ngexxȧ?ޣ/C4#S{lVi3=|K!6USecN31%F[~ڟXvӊ?m뵚eZةE[& A0FT|%ALI&K"t1.8;T8@ p:N^ ?_< g?dwCl&a4fVa'0FHIbq53fMlLNg17򅃃U(|t.Fjzb?}%r2sr'J4 &sߢy Itp7֥g'Ef>XllDh No5cpOty<`syz;+4AFA6vr@t(NDré( r;Ѹ* E%*3Hx~I.z>} p>y<`J&hkG&e_>%:QB1j2J |"(b$ED@$1>hp(S(! x㩷qyP`x|>&ӄio늈RL"#D_1[0y5}0U8YbWg;x$d\&& {1fhLСN-J8}rKG)tbY(p(OoߠRƦk$dlLRoʴ#] &/;%>0>;*ȥZ O9iGNPOKT|Qgks*B%BBIf#l_s-19z.tºں?~o<}|,o㦉 5|bbmR3Ǐ); `S{Hm;W͆=V]Wb.wigRB4L+p*2>=љAΝPS`^F9bߌɒ¬s aRɂ%_=<'D'J4TmQlc좜Y)1=~!*<w/^Y }QLڏޛF4i=_6ﺛtj:zQGgJovAQZu]M2,=jPI@^W]P]cģtZmݰ%!A|V! ;#tq5TjDxJKyl&E4Ѓ\wgM.1l^_4fj7E$?U44xD:眑s$)l9H&~}33;3 dLJ3)F0h9w< tWM;~^Y+KKSϿķ5`h"1r JG!(]XjS^q7($NdCOٰ&yWg4B0א\}A,EٙnIgGKIEPxѵH8i 2[lN5r~cTsNPH<,r_\^t Inj?чB TnٻsSGDrđV |e{Cg=o*.3SufqvA1Mʷ `ij?xߙ#o_W9VjÇwX_ˤb |vv1UvHb't'b>hjkJm3Y Wz[~o:=3%F믽QZ[ pE 'f=;G$ohx@ܓ0fwvTX{ޥ+--XJ+S7^^5y'0LԎ[ŇK㊵8DkDvtf+U?#wj;~V*" -W1&i.ַo"9h%Ebv٭Uo3jME9тRsQRl ey*ՙ"BJ*j]/}l& %Z5PT]9CqPD~LACYfbmeSɜDk`J$p4~?Lug3T8)͵@r=ԨSz}m-kBLRtIUc=H&guJy:/+3֙\dײW!ܾ$9 8=,b`uFޕ@Pi0wAVco%ܶ{ճyV,2FVIf&#hz}YT16Y,h`q84~p6K/Y 3d#Ra̕\uPѲ~tFBo*PꙓFP(b&;t_/J++%w> E)P$[I(a@*SSSqM }a+.ɠ @$JB>FeRPD1E WqPb"!AQL!cnRu}Ӝ%9F$vGĘtz5L*dR(*Z aD6I$pLsB@#8rY!ШTv;Q`n~Qj*0Ra=\Ӵ4'R& //a&G$fRX%aH`]ጋhtekˋYH&$4PX2TPJLH/^?q3S  c6,Lp+'n{R=~$Y|dbzJ߳c-2`_=O$H(0T}[UgS9|ڦ p~Vx+Zn n8IpR `BeeI۵9G[|"C M-̏]_Ǡ+Ǯ~'h|nK.Gb(̤ҳtFg1ڽ(UlNƇZc:1J3\"//7h59~BMt¹ʎ~Dw A @u_;fE/\5+nb6::\K@mKiݹwO zϝm}iͯkiL)4,*4Տ=ƺ.p'(NT6X|Zgꚫڼk' J2^ʁrRTrjʽrJ H*TnѽmpJ/VT` L, sS%b>.l޴M6t/U䮡u; Œ@( 1U*= k1Q$Xjܫ5c=BSi1&ňp`whfg&D 9v,O'PdRi2 4!OH*&VepqH&Z QRPtۗO OWdhk߲h맯j]'ZgMƃHB(5t=d OuGOY JqΠ|yucgӯk)mY^t7yK9392C6iݸ"uuL+Mx[ߡY!ݾ;ٴ>:~#|Ij=Ŏp=y~H *B_e}T\7P8" uϷID4]VHA3aחZy!`yhYi9xfk;fb |EVh}-Evzo~;`v ewl}9;~r(L^&dXVBpWW=pf3GbiB<54X9/@j1RT6 S&eR)̼V$I뛚rUr01\YY 3x\ʲ[ҋH~&t\@B1>=sTY_Hg<'j88AX<tL6W,j0Im 9 '5rs`{+kaYO#|Ԁ'+hҴAV0в3KkʢX,I#WovmߝJD5cQVs9~š=;MZ.!f^=⫯Էm>>m0HrzӥVH 7uXBb!9x+ HfZ.t͒*Boۙtj.fBƇXfq?H*,di L/P[^x%z1\m(:psֹJ<Ҷ3gϞ )9:}M/Hz,O鋊z{Dc]Po×$ 3k5}RRPixz$SHdU\q+謕O=vx퓍e|\gFoU(HTrZ19: 5&9ob!\?sZoĒ,OmS~;DEuNL>{umaIb!TL.M%So'I3~d'OgjRq-oƬ$`̢_ 2 A(j~A߼= ([XC`yTs9P}ړFR?rN;w'HeNf>ꑨՁw4pX( !J%kݝګ. R_N%SKrt2qdbᖗ/$Ww~d9tJa}5dWq鲆:ziq"%L*",͢{{()b=I[jJh5R"(5?sYc1qߒkyo/I/"R _ 0@.|ʊTcrS-[thO+RyqqF)VMMUv߿''y|չpLǦJ4Ifm{Ahrn9.AY$\ZXqN d"<0)SX熖g.KJ8%$i-Z.d&.|I$4g= :<~MKH0 B|k%Ye]uF q;kj2;?PqA 2>B*&D\͋*&sP˳whԮWLEΝ6٫9x*ܿG?=JF<`26F3^k.ۺTϮzL(1)% aذ_s[wsF):k7mN'1ZZuoYSs+T ǟ`Ƃ͆ *͎*& u?{\f+ZmiI5ۢf.PMs_Pss; 1UOKFqQ}##=x*lkkr.ɖܸ F]*Dc]v; *e[ig*UBtIeM"Oo[_D@(Xė6vm{ dU>wO>\8QR\YӺИQ~NS禦Qo`ȱmڰ)Q Of;%eႳOΐ䱳ZY.߷wsl|Gf̠\|\Z؆Ch6.;Gϭ Ϳ,1s -Bo:و|b: ÅwSIe*ا.G8\k6:&TEr/1@PgÙP ŅyxXRU{O7rW;|H,Z3t* >!FBs +eagg :aχG?|20a眼˯=WXLl?^Ga7OBSm$ny7u!z}> 9k6n>\B\i?9Uz/)ToA*_71PwI<5:E1O/:HI) iyuUH|@ߓKĺ9|oB‰?{Zzj"mQy?{Wc~+feY{QwՎlr7S˺L|i66"[B ~;wy7AٔкSܝR~eE9zv_2]Lљϝflup`lF}>G@N&f0+o4:D5'k0Ha,t"B} gp8$ܱ_:mIp,6_~пFe3kѨF31H>c=a-VEQʆ>P$%XA3=;[RQs|ǽP^߸#6vj];%~:/ӨC=[ Sdpg*`*515(o0yc^\.*ISU[/yt:IK3 X6 2T, HL0uPnQ ?)/)$LRL70pGo3@xm44vh4>-•{niuZRy5G!ܞg*`ovKǦoIEj[гt0g ?}zH$}@1ÃXf0x/ʹ-i٤1vm'߹,7++\sOgaeY-"):SćҞʊ?+mW?:3m5CqO 'j)uAӡp r5'6/rf2>xQ"r lsg:H#6A6$\V87`>w+[60ݫ0GeU9hC++.ڞ҆-eAQ0uڶIPX$)X{bɔ@ hZ xvR80!  ?P(̓Z:@{墩)PXuy1kXOccD$I2M U1 Bbq& "#=`+eb1[SLEg2`y"(5MJјs ΙGJ1.7Mu/( !àUF`ųPDTjHg^, 8rR.i8Hlrj.RR(]Ⱝ,l&_ ͦGzN&i`޻#NxcΛE Xg|yÆǫX]oWiR+|iЮ xұ}7cWm[`w>>m*.I3ntJ/\6W5{nDq}WS=*^#N ENzx|2_\hneC>}ŀ7jhlh`|Y"x+2G75\AntKԾ("t7dcPV?2pPY:Ӊ%J/p*!'9񓩤N,Ly>u*z1UX|`@`tbۃm5_"U 97ܨL^YTrK9IFگ+'O|<7cd[uO>Wյu˕ݸm;P*lھg~duAL(?QqN_hND_tڝamo DCt(=KP$Lmcj7 s̘s}ƝP5~= sx?fBuLc4J<^Z$=Κ꺁k'z{тsFn,PNUVVCpRi0)[Iloڲbme^s"ښLZ]ЬF9{o 2jC> U:Y@gN޸2<\_^}RJWW*TW_C3}:))vڧ!^^!M) {C\Q^<';~\{Yo0 1Pv,*,8J!@87Dv|P8ʸh:bԬs4>=,*T y{ߚvbFfέ$&DcsȨiJU.33hj* ?O\F*8glr~cʹ=;) g I9/p&\:C 㦦0.*Gڼі̴˽KR߮ÏqUϟ3-x}L"zbU05+k L&HU&˨jcraC3 fm%E[s^I?2d3push|;H~IQg@PDy졀iɟPl̴\(h%87O4xʽʥ2-͞?ulh.圞HC|")QVvYmYrwnh|m0L][ r,QCWG'y7!әQj٘i Rߜ?}lh9o<*uUsN'8g Hsnh0UkPhaq̪ C:UTTRN ǝnZ@&T[um]S!,E*-Ee8K 'SԢRg։"25Hkyͬ&ƀkiV*-K䛺6} JeJY EE4rbA2)*pBQ~' EO@%WFA[,`,[VVN;!$ ]\bgp936#QErwΓx0oY~8pV;6pUJ/@/dF$#?imoyL\_\tR5s[7Bު$cY !/Fר\L. Ike=H}9Ay mQ(De+_H:l߹ 'S13>cX"ٴ0J$8("V SzRY*TTY\@ b,ǩltEmE5c04 8Yp0dSߵ!HH@SS 0[Fy|Cg &s*Vҵ@43I.:SI~2aEyXUEInuh|< _HaV1oh8t _2=,M"Db4il*BQ'p` i(Pб1H ϓdϿ6 /9(^İ9 3 K!0}wz:- HQ)bC#. ^4$xM\LjsQi8J\ֈw1;ѓ$wZr/gfJ?!2egPo^ "ǐwx,yE!zr +h#\b?޵HeeɹK7o^_: eh2hhvzgEvp,zsgG_&!Z4L@Wy}E'3`LiYhYKyD|R(@6wݠ\CU+ջܬB OcwXtOYs@皻U=اf#}@@:^N~E||Tѡ#޶U|ttpfV-38lxfUHJ"ý=R!Wzmeo_%:[Z>|߮Lڶl d՜SYB>˶0eAw寸KKzOD>Y?8 4ϒ 6&Kإ}Ⱥݕ5W/~NwΤf,<0Og룣t>G*P,ꎟ<۸I$-V+$y.8ٺ0&1ًa:IQ/ٙiGѿ -Z^OScSs!jk-|bBfgh],qwUXu9 (ͪ |٠^&^߰LQ1$Iy^t+r) TR6t @,50*m}3W}z'& z>4@fHxy,@o&Y)02,E]vߣk &Ц0F l/ [ XOqsF(׼j>(Q:n$@.H&0rxD3!9{Q S|G|,s=>d~ͤ z#QxrP:_fSHM,3|@ly¤@ЀwinWYY_YBɶ bY F$'Xx4 s!rH(" Cc7! <^_Q횓(`}߷Cq ME ^)߻ 66+~ );3Km[: PVO8/ Զ \`!_$UqlXUU;Ezle>U^ĵ@iö́W]>d\ 2t7vED"w=i⾽ۦmm>Ϸ4wspjyVdrjM}g/>}.liy@__YmӚk&|:L@n6Eq(•vulKG?stzn\~6Yz㶇ߨGo-k`R1%5@zmE{§?DE}#O>o~\=Gw6ݷY~cMGgV~X2rv5m\e@@|WLp(μ8I4Uvw=M۶ ,n\,PZ+TTN(`*qWޅ`jb|Hycs>+:wq>!ʦݞb97fSsޘ$ǫV)WN)-6G_zqܨ.\Tw4s~TcTT_X*[~|H>0Sf˕K=Zw< .u˪ٝ)WޘwRp߭:{F*;ow]~wG+*("t%:+gul!D}R4w|Q㯏;&OtD2™!o ,On5Y7)GGg\;G^"H$rk:Kih:䔞@1BO.֕t|^\K#o4?xɅzϥPb K)jɥ+7lԉ n.]|\8:|"E..5(Dpuv~Layng ͎L5wlw !Ien-lZ /B%Օ@ G#QW{ӵQ_'$&:MVɖZ[MdY() ˊ']>J[LdUF#~ZC kfˁ:T+~WrGs4Й HbEuqMot%u744,.fu VkC(^mއ V=Kp.MM~ᱭN/+$usw|izSyǒviɢ FF.,v!d(*_C$S땂HqScLa#:pW6V&z .=8%s&FAD#ڄ24ąĊ4K&S82x^Xr9s?h3c6 콜vtmZ_ y[eSPZ v Q*8.7Y&Q }',ˀ73TON.:!NJ`>JFN-r*ӳO|SgNqXT.8~/f{yE9?\갸f 6x]r!{GX}#ŕi/SqDI s:3T_}M#C<][+w'e>{BF!װnVƔu,e^Bu[0 !P>@e؋=X|Ff9p眷n9^e]Yc. I3ؼpm9[K)F+d J*6VBiM^M61櫯υKl,i{YHEvŲ"NȺb}3Ȫ+^ Bk._0YkϹIRb[O?oJFsjGkc\iGGH+o(lC`g}nxwsc?2ٿ w C_|_vwW=GM GbXT(^1/2<im>(RbN 9039Wx{ aLOWս=sO7ڛ es>붧Z!VŸrAk__ygfNg2U^GPRyӮў2WO D;Л5HGѻ,Nۉix8a[ ꢉ~ >Cy[Ju^>FBop PF ҵ )P> CnjkH#ޠc:\wT5DܐwyӚ21ʁbO=kH\.~iն}mΫW.]5 _>tP?#qy t^fq4;KgR.:x  vŁ`1{{53@aadW֚WΟ6Ut[L̡h¿;ol˯PmAFrJT68Or \)XҳC@OE"Mt]p2GEaHa/1kcSm z0KXI(H»{ndqo߄~~ 񞴪(|tGV8{>S Gsݍ/9? ; ֨Ci졳T՝kϭ-KBe B1WmT], YnD!n5:Xzi/N_QJ{Qme*p: ~JSL}/LV_' (.FV= k K@^)UTO%d\9bوqBJHEKNBCO䕑Ed~,䋡+`"X qPϯ%8V㐈T4[ O EWӃBR^3]I[<\UIzBRҢyΣ֏ ;aKˈwyQWNFX, ¿g0|K8[Kp/F7ԕ`Xќ.\]tv0bt|Po֔vvv2rN)8H#C!ʒH5&'4֒Lȋ2xR%hdbPoimشI"ֻМ'*xлNYOFY5aDx~֑Ly\qT6X *Aڠ MX- U4Hfjj8.͎Dj|{z9/_|~OVH8^V B*N"Hc0K~ќ^9N?>+2Ͽ uG"EQB*wl{Ƞ$}"d"Xh[w_z C 0r k؞ L/Djw=O kvnxh-rpeߤOuZk.N-nz䘏=5:BԻoOnۛ*mxƇӋ[:|BxK$t& ,ҸwwLNM37o1725 g}\v#ѩ5dh%lV0`> ~&|+>L<ꧽ<96,ia<pDޱ,{V!%R Mň@'ڬP.34:n;RP)+^>usC,Z9qrťeb8"1#,32 $1\ #xPn~ٯja+ ||ԞI}R6 ߴgSS91'>yK[(`*Qe}֯fV[;z` r,_d!٫o AH`^Ke2[Kl<*g r y/뺢UˣKɆ2M_|_p[]h[.9=XAN$P/ibDd+KAQs8Op:!O|@Ƃ2EzL^O*;@raogsxoyMJmt6͸8\^<vqPԥ>X^++SRqz|ٻ2;XXPSީӪ 7^Jm osaQ7Dl]Si"KCssHQ<7BT_ ^РxIU39zJyFo^R$b ̄p$XR`rL~jTfڪ,3@Ȭ,L /N,Ej̗.vw)(fVBmMxg&;O^52Yrޢl( Tl63CLeke[b$cQ#("E|IEzeB1La|x@wtuФ)jf9:&<42(c((*+Mc)d$RiD 2m}Ȃ9::.f3D*s}EigXw%R)Th S`65-[K-`{"8, `@BdebdL%l&,#432JۻME9džyVa#gq ~5=Beb DL𴘌%߾p pX,;`=vJuj)!VDJ &ӠW_4 V{2B`رs+ϊP)Pٽgnj*ֶnߪPXr^&ý !1yb1Hpe/б8_CC5}N$KR@\fJl p,&'G ^P[5jx@r֫N Ny.zئ+|aIG'|'q{{ѸeSq.} 'v^)"]/tܞܪ;C:mc̢_?U:V69釄iNJ<٪m#G෧ua)8 WԖTO^>47.mLp(כV&(Pe"~8+t,]>'981_tڱ!_VlbFg ovMV4V"y658kfJ'T,zcBP< /@|FXKw/(=~P!B7E~gw$]bw ~Wi:o,\/=&=yu( 壆hmƛvr ډJ@ivߣ[Pz/C HZ tpGԆi7"BZ8/_ ƺZ/û̓(L&. _+bw.Z#l"9\>/<0W[)yq&H2u%2^$K}١h]V)Z8۶@7ؑuv@@ufFd3/,TڌG%Y,髷VL.h 5|DJ>ֲ*2o)g΢%mΖށ \әI%*S13+D}]ŭ 9E`,BAHWg kqpjzNR4uZ֪:ED÷my/Fb<,W}Peb`Q0U!ގ)='3*{|\Ay\^{K% %IB0b2*c%#f&'0U8vYF'ehlŒd2 p4#U _5PPp<ϒE*1]y{ ]N8`!yLGaf X`HV8tDVwP~?Ƈo8?ApCsaq#ќH'Z<;ዦ2c!U͢!Op\<O. 4D' ,b爆K(Mr6 ԗDI/_`Cv4$3|{)er * ,u d3A/:U&g2dTJP*I)]TT"2 ˆ4I'x/`%dέ^oUzhW^aC0l6"7JBLT tONѡ9HˮBJ(m~sףxwa)k}w>nW?; f _hԝy X&ڡubYO8g6!4ϰvn6L-dJ &C13 ;KmoTra63Ts\A,MN4=YJ$x&սQusLV&_A@م(R8OHWh& \!*8gsܩVۮv^_^Iy?ysnٓaA^ #9#2N w,K"j9Wnl0 ;?w -`XdjkUSوV͝ JB e 1xH aa2r萟e^d x-U#Y|gS3q0bx=oԌt{&c9TVVk=ˤ} bܞ<ѵϥ&2##`(xMZ'Q^EOZtfz e =Z_z0YLWho"+Kig=<5:j!@b#Y,%r '¾$K%5H64m1m3DYQ4=ⷚ0<8eY< Ie+˪T3#+CޖZ;%/prvسiײ7C%R5Qҥ3HFzJR‚>=(5S!^=}^)KFczLux:XHg_ƥZQtA ff=\47Ih$2>Ui00TR&F P!fRV 2u*D7OjK7. &~Z8eم* *Ί?v\9 e0MF-E4" P(y>O<2ffY.i<ѪVА?@O V`qO>k H@`s%|"3}]`9d0J]'$  _|>BGB_Zp@%DK@H>,(PbOE+4qT7pĿdvKiK:˅aY1APB |u\-|WτD202ّ1\g867:69ޮ z-_(7T_]|Hb*,4sK'Fq44iG]+&ϺkL\9p__@-etB&E ňD΋gL-}fT)cϻu^^c_ZsO v =w/qݣ{lL FWǝ3 [ `dzs"ZL_m0л\픪D\VpkJ#$N1oL$h&4&YyBhr1iJM#Ȗ(OF3M3/c)Q2۬D.@<fP?98|6bq(p:Xcl0Ɛ@Z-MD,ɲXs0Hv]XWhP.,$i_ aVlEumO MkK%e.*ʠ-C_:|E@W3NRsy5/$Cyo*6ǀ"BTBehjփy7|v 0o@<6TfzCY`)'`]e)I5 v?:N # u˻䂫S8V@p| dx^Fpl v1m/T4묚*fpVk|^P oSY@5VK{St ?0: M K'IG^(!Z> XO}6Wpw1ͼ *V+[-kn(x 5ͦm e1sk*/UR ' ҪdшyϞE'($ )Zh&T6l*["(X@ )sڻ^^ 4%%RVk\eւ[m0Xp9f:wFAU ܔM3 Ѱ cEэ#!IK,Hٔ*RtbQ yh&GCw4(ӬKUG Y-ꕩ+z[qPH :6I,dT Eb:xkEr&8۲ yEn@`D)z>P$ H%HJBҍG#\$)MR8dwPpT<0m gx+z0)&5 lfk+zSKL "}Vt( x$Jpz;64&?J3p#1@C10drjv 빭{EP~*D t*Uy^sk03]HL-xt_UZdPIy} wT;o"zkx{[U0Xɛ'?~<w[JS01\5PKY/"3sX("Q/ }rUK8,XjRom 8Dg͌}|6 HT,@N?eL̍qX,\g5*8]}c&ffnlyCۮ ^=}ydgNf<1 limĥKKO< vϬě+nT ^,Gah*#3q}3 ѓL&d}=}HLz];XUMJ}[Nԥ[K4RTPp[=̢YoG[3{bYg]sJ&AqXf=֢LwW׷uH(4D?~D`Bp >wmWN_I*0blVjȦI`T:(?~󟇧¥VCŏ\^ox\sc` ?+& '.S$ \QZLgdV2U0=yG(2n FU-z{b)rGsN%\&NH2@2l6@RjӞljaa-d8h+o0_ L z5˞ebagV譙x֭xs .rOVIF++&vRK$?26ާ&YJN19~Ϣ9 Mm[+*+L?Ԗج%%!kY^ jX^u&<)b EoЪқ#jo[:{LŒ@Rxlvkw[$dBt|vY)SL{bv$+3L~C Q,[fbX֤us3W,n+s/Lյ&{jr)Uױh"wޣH\g&2i{|1RTϷ+KQ( )lQ\&A>]۪%5 P']$J}]M:f0aRߴ96qNN0GhNJ!Rղk20T9xM[`$% ֳ\A RZD 3! 'Đt2[9R!"%+s/CA>y|Yf\B_fGG91Ds,&JmTRU/0H%D,VPdY\$Sku`!~~zB a&E<*xUu>>;xD fP &L&%$ã#ד8R?CaYr jN' Y- ϧ:0qHt^ tI}vj/)D̑vOq3wt^Keީ9ԬN"ݬBqCJxj,ļ"RHȄ'd@0H29R:*Eb@,da%`#f8}9{S=O@k}DNC|C~oc=?75#Q/fGR`bqaT_]ݠo~pC}5/{ QZсYj|wב^Be,s|ǣ1H‘T <GTБ?ٷ^^[ p#dgqqda~`ir)_(_jiٜϏ 2)Slj7ѕKvdoH,zJf6#c~b.t/,U60=-@[N&5:nA (f4UQ\=V֯Qz )d| JWl7 &N e%ZI6szjoD^Fhfp۷xd4n.U1Ј/o |B?ؓd\k--g_&'dl7)欴:+jFyΥtau]꠸*U%jQ+j5v Ӷ5c䪦~Yڼ]˥3^ /vR8"A^VmT͵W#ڤA÷<  8uǔZ9Hѕ8{~E]9Ɲ,ǘ,6*8GC[XN\9뫗 FTچцzL  `im^е'b@#XA$gt:]~%gK37yv~hh:_ }׮wj.k-&BN[g|-ܘ;ݪSz—OwL~xt/~h6 ڠ/6Xj`` i6 ڠ/6Xj`` i6 ڠ/6Xj`` i6 ڠ/6Xj`` i6 =,]IENDB`PKDJObject 2/content.xmlZ[o6~_axfFXMضm#*)=$uّN0Ns㡒oEzZ>^pҌ/?݈\Il=Q~<+PTTܺ<3U溶[Y>d?1Rc7S]i14s,0(ӮE R䎙gW?\lר#DzX W]`vv"ڲYM9g|4Xib7%ےL:j% x: P =ij}w j‡fDP.6ز9pNpE66F8NvG0rS-A3h҆wNXS6ӃJq1=edOjegm==X{>=M_+HκYء$3T bYM0_ R::+SQQNj՚q9{1E9Q+ `;ce׈!n^[w%f{ƊO[O|y-t8_j $}_@P͑ hz܊^` [=]î a@ Fnrm0YIJ_F;`c,, NL\=P tƼ ,ʓNhht3-·t`9$EaTE˛ȒX}ɉ!ЌAn4̙p-3^8 'i}.GK|<㻏UH&i1@1Jyjaہ#60\̂8:OD&9#e'nP>biN*gƥ.(^[d]5-.݃AաV4f$m-Mqmw8n <M6UNqk-I- J`I{~yzn`iZ9\Nl?hguo%e:|iJu^]nPFc'V^ 〸[Y蘞7>m} 9(`RI)e)Q N5/(x3k\n7ڹuYŠb@b#4f9="ݝL8Sck"3CͫtUUiU U=B 8@,cXKN:Cl^Ѻt."7 Z$>X@ ezx&GR_)uݜ&iyA3p-KMK|󾆻Dٳ+}w}3/+ tct̻1o!N(ϧrzH;\sP~g]JBj= eX|HSB}=5ghcfvBeHZkېVJ6XTTv6{lrl 3(I.fo!apXzBd$|';bNL 8)be~l^Z 5.nX$ NKm3Jwhv8ڠ0,Tnc&nFD^2!erw $eqsyǎ)c B?i3,X?]Sk|?/> Dpe${az)ˤ>HL;K"?,?+vda i(Aj("ANY}h0/l1e!L?#/=;ѠoDYh0pgjH#3uvԼk i'OPKo~ 13*PKDJObject 2/styles.xmlVM WX^UjU7&{ڞ9", qwNj57f|xӥљiÕ*#&\V!~}xTe +"I*,MIBaM!qLaI&R Ζ=8d[vK;RBMCz/F$Jl;6>Zmj++m6䭣`2⚓E b`e XyL/N[Wg̹Zsu%=rzq=xڢ5]ޢ5'7Cw萯izsno[-܄,XU 2]vI_i(mG!c{>:@+M,0 _r欽|׷A4,E~"8t5.R$ /4LsgӊpƄ8cvϿ%nšoG{v?L9 ?}ƝrL` Xh :C(XUw&P߄åep c@`YԭG>#]w9f9(hf~,MIie}ϝAZb3 Ό:aazox?G9jՌ؁ɠj1LVVi>Ju|̯ !3nߓPK`1PKDJObject 2/meta.xmlAo *OiZ6a&ln W˦`k?*-M#G=UpB*sӈJ9y{}d[,xR5M;}گ`k>Q8HOdd ~­P|PKu#LPKDJObject 1/content.xmlZ[o6~_axfF>,P-WZmv$QKʱ.";raIxT-fCj*e?"^WB]y^/^/e T$(?ksu ARFn*n]Rڙ*TJs]-qn1ӛ).ⴘ 9pEiW"k)r̳[.PLf6HkTa" W= ,+.0 r;u_owAmY,&Yςև3^>}zH,4hmI&5<(پ;vX pr5 3"H(bzOlٜ\8'8osirJC@jIOVm'Zf#H9j_po4iC~j't)`I Aa}ju\1=edOjegm==X{>=M_+HκYء$3T bYM0_R::+SQQNj՚q9{1E9Q+ `;ce׈!n^[w%f{ƊO[O|y-t8߳j $}_@?P͑ hz܊^` [=]î a@ Fnrm0YIJ_F;`c,, NL\=P tƼ ,ʓNjht3-·t`9$EaTE˛ȒX}ɉ!ЌAn4̙p-3^8 'i}.GK|<㻏ULm bD;`c x`)Gl>aq8u6 MrFPA(˻ړSSCY>9omo¢T~Ⱥzok[]iӃC)hJ $IZj7ńlUp"x#Λl֝VZRZBzQ`qsW뗕en~KVC~4]ewKk7ͰtP>˄4puGXCX.6Er 1~+B„q@\M\x,tLO\t9M/80 &J&eD56ރ;thOtZ|3qRua DܺbP1R v1ӑ ea[N&)ʱ5YtUdբ *i*KAJA 8,cXtKN:Cv6>%}nG2˵MF6X ezx&GR)uۜ&iyAn3p-KMK|y_]kي=Vp`d_b1O:ᘷc'n9=$ri.W۹M(?Q.%ypT2z,J>E>a4ƱzsFx2$H-mW[+h{, N zB[ÍwTh.&o!apXzB ,KhI ި)l9m9e4 &ɕykWԸ!cMr&8-M߻m]P8?J"'f1e!z;A9nј80#?^7$b@LYF@01e)P38ynLY };mwCoD ܬ|&8AϘЩmf~D.hh;,=;Qډ>) ]s8cW.ƔH&8A#B)pjǔt QZ)eT]Hѣz>PKOtX+PKDJObject 1/styles.xmlVM WX^UjU7&{ڞ9", qwNj57f|xӥљiÕ*#&\V!~}xTe +"I*,MIBaM!qLaI&R Ζ=8d[vK;RBMCz/F$Jl;6>Zmj++m6䭣`2⚓E b`e XyL/N[Wg̹Zsu%=rzq=xڢ5]ޢ5'7Cw萯izsno[-܄,XU 2]vI_i(mG!c{>:@+M,0 _r欽|׷A4,E~"8t5.R$ /4LsgӊpƄ8cvϿ%nšoG{v?L9 ?}ƝrL` Xh :C(XUw&P߄åep c@`YԭG>#]w9f9(hf~,MIie}ϝAZb3 Ό:aazox?G9jՌ؁ɠj1LVVi>Ju|̯ !3nߓPK`1PKDJObject 1/meta.xmlAo *OiZ6a&ln W˦`k?*-M#G=UpB*sӈJ9y{}d[,xR5M;}گ`k>Q8HOdd ~­P|PKu#LPKDJObjectReplacements/Object 2 pǟݻݐQH"DBbP1JBEjXGhʌ@ǴhV*:RqHGXʈX}vsms=ww73/P5+Betxs+dm*::ᓞl52E9݂Oe2򋷊t[co^@)A[[ˣ CrhU:jooX hޜS/=᪦WMj8Kq̣CQD߈&g|qIzk;3$"]Tq}j)T-!Y@Q7)fMN[3ޣgf1EF+zEF&m %?D- AJ~Sԋ[Aԋ[A|a\- AJYz1}K>5H?*b|j %$W- AIy{0$.b=H|:Yoߒ @J%o&䏍z1}K$L>ɯz1}K$L>ɳzYl$o&-k AI~o~A aI aI;6 aIU aI{u aI aI aHr&omHc9]?e>%+G`Q?%:pOZE^Xh-<#Ft'xx)xx .?[b7 B߁o{)QgW~l`1ŲupY%<RJueg 1頊Y |WFց n߀qׂ+J?'pl.B 8,-:p<6G>np xV%b? >.=e{9%x7X9 ?&m%GӇ%3E|GA\Unhsn__G$*AylѶfZF__k/@ G)`hW`73\^< ~ഭ/sm'NpA-ѻAp .D]u /& Psl^Ltx/ .O`mtXkpELn٘:;㳭i;s;Ss5_j>6Fyq|nMZL3x@=^Zh]qz{3s'4ⱨB@?(LZB|ױmL_~38..~G-u,?w<%(8a MZB|ױmL_c>UIZ^: I񣸪 8YIZ^: IHkFXrv㒴3u,?wy/1u&MVMo5)G4jb] uUX]XUX;tb]wb]źźźź~u=uHl]źU.u.Y]N]f]MXV]d]9Xl];X=X{54Xר&p\붸X׶X׋b]).X{bb][bb]ĺu}JF:]Zu=u"!E덊XX X*E Eu*b]syXWEZuuuǣUXYXW`}E]u}ԴϚ EX׈i]KTUXX׹XׅXUXX-XX_b]b]b]Wź~uĺVĺĺΈu]V11bb]?u-uu6.uG\qźVjb]gjb]oĺnĺĺvhb]źź/|⠇y-a^+!Ny-q^ ;dZG: ^4*V_Gz;伖{!rǸPy:u{!X~6x&ů0{{5汖/Sg⻎ngR|Ω2/i;汖wr/wϤ4_72c-}J ]C|3)~`8.<u{!X~6x&霧͑VmLX˗Yc!ވ%4a^Us&6jn:qNCR ~݉HlBxhVZ:٨5.* ԑmvSfHo%޵~q݄2ɱ؅?1>U5 ̚7N&յhsќ"[]DzRZ``40)XMP M+D0޼[3Y^2FDıдjDRFScmi/4}mLR:/kZ֔GaEcESޱ-ވ,^cym"˱ԗkXѺrM]QkTsC-s![Ns4X4Mimi4Zh]iZjMi55텦|ݯɕrm?CmO%Vn9,Y WO~˱W)>OY?ugjpi6}QƣBa|P| f~>Fu~~D#6F%c3`^.GZE "X\q.uBDsQ:%E_\\8α1碸s˹(;59% c9%;9; p.*q,+sGM J {_wI$6׈Ct >g$igz X~_֮PKNA NxPKDJObjectReplacements/Object 1 pǟ|.wI HB$A!9D$#V ЂTCZ>Pj:VU?8V@-c?Zmq: ?.sv1{WG'NH$4C4Ý~82Ӊ`@έãHnkՠ%t3Q ]]7*}݁L9P(mޖ`jw4X:7z;N?Ԟ={8VmBOT:yUZͪ0EqJͦ_o!i)aC7Ƨ2[Ȥ:o">t~==ڒ7U٠-PG˯o8 )=_LǒwK%M/ K%Mɏ J%M+9/cqSG_Lǒ?8}3wA/_Lǒ7wA򃊤_Lǒ7wAK%o %O~1KKcX ^.H*ӱA]<~#xɻ y]%})A]-A]WlA]㗫A]A]*A]WiA]^AM~S=I2&@&oww!nkC`!ܿ{>q{E Sbapd>\_CDU_p|.pX ^6ȵfhx#8 |<*wIπ7W>n\{=|<6-!p7G0PH18*+pap# x)X׋~x-8 |lc 1 ր.b;go}{`>h,F)rh218h% |xq)qp=O`p 6g6[WY!_<;i!lD 10r ?6cMp8t0"p 38t)g`L\ >1&cJpP[w? ci5h|< .Xl?7M| co TfC#LuR0 :sW{3)X2ck|pL5s1s8^rp8<+Fa O'1!ye4rN_wSM75k džӤś˛+%^UW1~Fej,ϘZ}DIof1pq.R&~^\y}Q_&-rB|S)xEގ>0l(F}=-rB|S)~ط~:1vo9[ JWu4ꆥb3r,'ķ<Et=CQ_W-rB|S)xT+P2Pэic9!7 sgĨg!XNo5lnݹ0eX_cO<;}k'S>5^O||k/mרq_|~5nq_|kq/iF?35_ck|k[5zר ~k( Ʈ8_x@|O_c"HE| W*kvkLShV`טѨѠ1A_N5|Q1R5Fh0׸T5iFkjFk| ΋}|F5x;5J5xkxk WרT~1N_c"˾ E|95V)klP׸M_^E| k<"QE|_ (%A5Fh 1/(ƚw_㕠Gk Q_<$ Ckl ;$ƛ!5N(_cTr׸%W|Gsx/W|a5f׸5,Ƌa5N_cfD|m5^q&"<5副qw4_#_||5拯d'M nbuRN{|6EoTҌjLm ķ#R-AOaj\0g޲+,i+iݶ\6?lt.CfM4E&wNlt>c ?zZ}T?~j4>MMMMGg)$ 1V Q0ͩPG+?E˒-K%umW6]Ӵ*h4킦4VB]/hM*#0"kqM5ZMFM. SFn"ٵ6Ov{d/}:ˮyS*h]oʩcEVUdtuJ*TɌg wAtMU 54톦zEHjOnh7($ԴӴ yr*\U5q[ny_9;\v;Og_>_O}ĞD3oص4=*'S5+i9JKiyާ ݙXq\ bʧp'WxU f'q"# K"D'gKq~8L7of7eм)eޔm~@ϼo~@hySI1e 7̛rc7EæM-Mшy,hySySyS󦞦Ms>P)CuD"aE]e Nn#%r7l0F}=ӎ/JX%w]y/auy*+IK̏h--q5r,'[ վ|-&gJՏWOKXDWp# &epYeVӻUsuzj1orG&OOFeyG'O<7cy#5H^1?ݼżɥ{}ù2 ͧeS#A_J]!c{k&oaǦ;mR k do^ 3\[HF 48b"Y2#v6:%6͛{)lՊn_:PK1vu |PKDJMETA-INF/manifest.xmlV]o0}߯ Tm*}AqJnNoOPK.m PKDJ^2 ''mimetypePKDJe9,+ Mlayout-cachePKDJB\ !content.xmlPKDJz$A6) ]settings.xmlPKDJ2< emeta.xmlPKDJO ,-6gPictures/200000020000016B000000D7FFB7454C.epsPKDJ 9 sstyles.xmlPKDJ= }manifest.rdfPKDJConfigurations2/popupmenu/PKDJ>Configurations2/toolpanel/PKDJvConfigurations2/progressbar/PKDJConfigurations2/statusbar/PKDJ'Configurations2/accelerator/current.xmlPKDJ?Configurations2/floater/PKDJuConfigurations2/images/Bitmaps/PKDJConfigurations2/menubar/PKDJConfigurations2/toolbar/PKDJ*99Thumbnails/thumbnail.pngPKDJo~ 13*TObject 2/content.xmlPKDJ`1]Object 2/styles.xmlPKDJu#L_Object 2/meta.xmlPKDJOtX+>aObject 1/content.xmlPKDJ`1iObject 1/styles.xmlPKDJu#LlObject 1/meta.xmlPKDJNA NxnObjectReplacements/Object 2PKDJ1vu |zObjectReplacements/Object 1PKDJ.m META-INF/manifest.xmlPK endstream endobj 128 0 obj 102883 endobj 130 0 obj <> stream xUoU?wvg ç'6شe3DidwvmƏ: $&!DF1wy F h$4;Opgg9wϙ;܌ HY!/H]b@6\t2;+Ќ18ᴡO nFⅻO{~KhW2 ]Q{xYk .@dhSSO:_g3XcgsF+hO@/+5x@.MhpdA'H9\o /98 o%`.$H.fעxP|k( 6'*뙧AݯqFo2>BdLPbjX֤s)zʂQUbA-܊*s-G?%&6{VDeؑ(mdؘ* .QJ]-`kzP)seU-ҩ K淸+[`eyu5 3U跼u mbކ1Cr~tb[o+4![-j\N zb}6m`LWڿX/I~ha0(q&qjELվ_bDS-,("[2"{6klPP=++C7(Xݶ 2U;O$I@vQkLqr"wb1%B &fc C l0!"]}(Ptٴh%g?%bmRV vr޴8!;B/!u݂*xrl nbEv-dۮOmok}dFC_6}@Ƽ84`f.3yB_]O;x WVaw.W;qy$7Nm6ٴAl|@%Zĉ§v!n a=|`'qD &B`7yp?ٝC[I\&?/cR٤=z*"a2DôL8mt@/L'1iKskc2 UكoA+4Qfq8 aƑmL#ށa0n G4h0xN HAq 9; VՈzھj:C\e+A%^2̹(sv.g7=|̣V cm& ˫cXebL踪> endobj 133 0 obj <> stream x]AO 96&f&=?´؁L)VM<@x7kQ13.qe0H|pPewMJ oKƹ16ү-78=8Y;{@ޯ~Mg j[8=O6=u.;"_mKd USU-4[? }Xd-ISSNc2K2{?'ŴSe}~my endstream endobj 134 0 obj <> endobj 135 0 obj <> stream xyixTǕh]zQ7ۺRKnqmH-- aVܒFj!u‗ F@l{C<&\DdL2obHʼna&L-7ˋNU_ |3}ǻ[uluT:ձ! CۃH@N+1F"x! !-yV"d=6 D07`\8=`aO;BCuZQ;dknp0>ca<=thC` F葉Pd?$!cxVO2$MfooQ:MnJC 4jZ-E:z 'HA?Zʍq)=?K+.C|ol8g"8/zo{^N4o؎Nb &}x]BWS ]l6~20sl<zWfE/SQojFgУK3:tF=ME9!a/ Dm+907fx=Ůc9/Q̣'(hy)~.<b~zѿM!/Z[|M keujk*WT]e%ŎBnJZ&!Ijxe0*k}T8ZNb%AEvEl2p)'8ENlQ}y, ʅ&Q>A]t`BshAYll}ӆF1T^ RJ4.Y)4fHUآhnʵDIT4ƈ0]v~Ȍmt& Iyrbu*bRj28Wu+'hɵ[x:>N~xFF` $ڔ{ng Jz/X,݁I+jLJʁMp-vq2*Ժ(V R8)DdB?$\aMjEPC4̓gh(˔Vgb{Ty Aآ&}[(ib~ǺTDS48J)&2<9ؔ0;gJ![5F8WbHvE >rCW`:;Qa{b{gF5$A 긢;Ԉ܄8rH'\-| *"p8ŒP/p.Z3R9ԤmJyr[i4쉧N :[7PCQėY 1$"wڈ{UgP{shMqs.uBNj;m daR'wO墪m "GX',4'e( ImxRSnACJA .i?9-ǻ [ N3il.Zb%H2Ȁhꂁ瞓:@E F[a44$p8.)KwB޿XBXТ)M5OJfI|VT8է.\(hMc{j>Ȭ^V€M 0 4Ч zO2_ ;s!9lҘF%&99h3h&˳,%s+5̇7S|_KMgO-(ᡖE0|9_:tW~N'Lv}_ L93[%M,OY:@wx8+m1ayw kGg!WDA5h\*=p60i_D<k_^mVam˘k?pwJuYOFm$.6Ko@$|R}8.4=53V+))kpg8edX;,^FpޤY hMuRvnaySroJRbSr ŕꊵEk؄TnbGh©p82<{WcˁKbuI6'YWs㫴b]RR%9;WUV9=hgRI+7 w9K5h4h(a z]M82_kP&= 3pZZfYVvd1kMӘ~Ym{s W(+ a(k9]d㔠euI$Z.Ho3`!j05<ϰzXgO ;gWouXZZi$ ZkN X&̫&0V%jAY\7#*s:K, +|M#ᲱfZDK B (0v,TnPn/^>qQvXޅSj2ȺX(N221Ƿ'V>ƒIOեX-pͧ2X‡o$eM&#-G<+%K\2ƇlJz9ſbK.ֿ|Eʊ3}=Gr*bVb0˪ q" 7.f>x*p$T} 崴T4X)brZ2fD2(TTtL@{yC!_oM>֣܃5&[_zGpK|%~Js j_C%s沑PA]CXZQSVSXuW븺:lݫuԱ=u:0Jź+u:M) 5W'szQbM΅CQ,ZK*="3rtWV lh`X~w< 9s;N${miڮU=Lދ{۪ʺxG %+kҷԅ=%ݾeGtZs}A'lkwلM2,iU]+/` h9On- DFZz22*' H1AOKsJRCadwPg\m8Yynͯ.+tc}a_F3drr|baqR.KOUXaJdt"K6Φ57iIAwa;] -XrN.̬cĪn˪ڰziXvW?Okg~tUuM;{Wx2]Բ˼þGuv8G1jmI94SXmIIggiG Q/ZrxFk_W&· mWį{j[<.wzGoa;4 5U*zw>0bHrf_Ŧ"?7`lߛޚ5SGa6%cB5Q㭟w}$5i墨ye3(A~:Iov:HhW b~.w|i24Ui _it[tZUdAn|7,9h3Taq(,|0*Cu@nyYh P^zd½*liu*lDa &fǜF~(Qa(fVVaSa_Wa rZ{֡W*Gy<T **lD/ <<JJZ X6>n&P0&v]段=mbV!,, GFƆB99 ٢4'"aլXhWH+X,~\Ayx]C?G펄Cѱzhl`x IgkzMږ)@GAHhLLbfc[ }cݷ-<9i[(v 46Q%hB/AXB!4 }+ G@mh\EOX!JG!Cs=H52=o v'Vȟ=oF㠷@r-C5NOG9 ^ 'ȱ#s!ϧXPoPb/6S-1;9FuG7ꠒG1:80c0Nhp5Wisϝcakk']`竫mtWV.uﻫ_6Zhxex8_.w/z?γc_bIpO']^KIFygfjZjAoej3gl,Fg<鎝xv,? | œ|+ 38L ^?,: -˳Gv}{)| ˧L>b/W^{ :s83 lkĩp|ܳŶex6thmǽ ~\)&ٯhWPoi)԰]ಾve,@ }X43SB - ѝKP aFcJDQ:c;EU(a'&-w:cTa@d" , ` endstream endobj 136 0 obj 6751 endobj 137 0 obj <> endobj 138 0 obj <> stream x]Mo0 CElBh8Cc41]nvHn5!} Xa^8$˅6*"ػ$nLҷ_ꠧ3%GŸ:# dRUB<!%׺1m²?@g5i]I)e%ʦ_.+rg4R)wE9'#o3-qEyϚ r|B'K5\#m̤90cL߿fo]a۸q u>G3 uCox:4 endstream endobj 139 0 obj <> endobj 140 0 obj <> stream xݼ xSǵ(05P*0~ +'ASTjIzd$$&%ZlvG3#3+;'7'>››^a1]/%&r!3e[B .WsmImWO t<l_"OEcym!racX%]Tta[}>+w2y)L^IԼ=eal)%Gudb#E`:Fwn7aO5?|^cN'cp6o6QЋN}#_"=vXχEZYBƆիC+W,_V6$PS]x\Y//+-Yh^דp;l&ƈJ9 ] Ya> 泸sa;ӄ vJ)#MJma]8c۬ڱVb\s3,c(\M{0>5Κ͉]oh >9WEJ΁ɹfjnRDMUaҾ)+쭩f%kګ#U`M/}d>ifĖ*ԫ=GZ)M]LPBXC)1LV;[F+I`̚;8R"lPšLpH(!@au_ `..7A js5]Q:ԩ*8MŢȧ*hvD|7d{`̡aB &q8 "dtr6;7rGrṬ}p[lPLāɳ&p2W%Jf4xGrl}L[=Ƙ; ּ6L )gA#Zcdl؎9k;ǜjAM2:kXl9'{7qwyX{3qbA/YqV 8 _ը`|1Dࣤ?B#Zj9[~^kS )?Q9>VLQMf񓧫@GJ6W HEQGyp( pi溜,YB)pJ9J$T^-\^_ Z|Vot:W EX3cX=?H<ыuY%ȡ TA)AvZY[8 ǚº1{b 'l$4X,UW3x}W Yv *l|;CZA;!Sxjj3=T25ӏ FI@!S$$g' I.z|`$`qtA+I=JG& c tqHwn͘Vnn# 5]5,ڲ3tf0̶'*lV8UW@`U,$IAWQWKJjCU} ; %%U(ZaNxLТtAc06q|c< xGO.x=/U]U\Z(xbbGe߿y)K6VZJC= 5+kp_5Pm-UTlykD>b햲7n:tZ,Snl*k z&@,TFx[#AC+WqV{h 8_aq ELE*uv7w`Ip}k鶥[Wvp]_}AOmW4޷*v<ֻ`õg:ywǷ/zpyŶ5/5 0!ߔ0|0$ڕ k2!^T'$a$` U@OYyAYG55dQcD8RPq&7l3cb jJTCVd/)_ 48*I%UEQ#0a}[FWfT-/̎r_{IW<{ypM [Zys~١o-9Y3CNd9ԜٛI5n&;6'&P;tW8vN6QMMԔ;t.iHvFUT8N7yDQ όK{ﯫ;paK׹^Y#lxeN%+]GoLK󛿂'ӯrpƒW>PVoO7ޅkg,I"rl"Ig %P'?+Aʤ=WVvk"{ .eTNS QI*YũU65gjS-z۸#98i%0WPk˥_ŷzĪcg?*?;酣oq.;LYX#y%33)gǺ1JRK8duvCj -L<"10kP. TK 1@iB,$ y|'{#ˣ–=ǿS>d [h2n\^ m3;Q'(G[#X+"`;h-`1@KwEe9ߜ[wiԳբ`]:x|S^欪Oys?}=3+^"ZTGq5|Gcc r㱧ci,K qR0V$9%ީqs15Tg9`hkzɢu,zO٤c:nc˅Gm+L8fe "'!"jy:/m#$< <.x@끷|=`<f@lw{ah:088'f F FjTieoC?xA:d# +l%Tp Ѕ֠7lct:BJwMIf= ]ٟ܄.'ߛPTp'aߧ^S2I*_\aevBkRJh qk͌p%I&uKtըl&iʹ$LofL$LjcȩQĊBwMYi J~|5jE1s7KY?w]5UZ縉8sf IFq;_V+rk`'3~f\&\;$DDP i!,pDY) Ạ p)O<T%pl2[*nVqxU6O)uR}̗@-$@!rRREWKwXp G=qlQQ: W=%S<&#iޓV\H@#quQ!Š| G ' o3hf =mcnjC L[ j`1R88:"G?Sj$&?[b`TTb)V)X`nT2oӝ4dA2PD0iQ )uLan|ܩ24DZnDnM%dA$qjF]SMzh2k>zMRY]i6W.G֭r:"7,0)զьZeHǍa#g,IiwpJVL(am^v^0ܐdx aCBv@KGѫ h0ys|^۝i2q !67}t9t蘩&pݻS 㣥lϪ? =]˷-r4-tk].̶ܻ^^T02ft/?v#ni$*iMپ&Gs '42LD'q2bx2ok ?|{1Wߢ~6yLH1V9R`]$%@6Y'L.=w4{.j]-$xg`xZ?!*ޙ| M`#[ۅO'6?'A8'`}?[h+{;Ll=y}{cб{D`[LrV1Y]k!ەGeG]aQ5hYMqReJē%l. IB/kp9T@x9L9LOTw(]t)Ӻ@)6,1(u]ʮͬee;8@3!苸9'\Y8OWuUhy%l-+=Yui::,ey"+M_5־Ƿ-Lo?ЩҾSl^q"LU88iKږ4uqTS+)KdqXff%6= '/gslxӜAF LHB(rsQ_XlEihx]TGBvdK &g`ho']@׍?hOɆ`~Z/AcW?ێ{{qd+u۪kW亗V ȣiO_~}g6fn:l1To/.3))אI4EO 0 T'z]3kKNI `&&c/N;~ǗtXX`wu}LJq\pP1 ac~1B = 鿲 B{U>xV~acpjG;L:9q/[A$etJAqDŽ:8$UcO{^R}nG绀mNc$Y5Z[^WX|E,F6fe1Vn{Ez)kӫ'ޏ)`My_ƫعM=B6JgJK듓wÄB" Nt'"~QP.|u!.V3N~c$L~bgs>fWPK:Pl4J+N P@9Zfh2iuchHRq4%A xFA5#T/ fKr՟sz DȩN :4 >魄hhg?0`< }"s^g_DZׇx]LgS045֦_N!ز>mz3;݅Ƕmhz飰#fpװ_lGkӻiKBF'.[4dR@mV*{Gj笯ZXYemHgtr;hXۭs '[A\1J(Ic_-$v(yC+;fεA9FZs >3^x1KYw&YoY^{q:Ju,Q e|ɐǩ8$4u<gDaqBD`wl"+ "#׳UV :LV:8lI 3|2ɗx=Ml2"`WlʄM6&ps5Jڏگy=Yk4˚IH5]N B6*Z\hŚ19b}zw$"2f*U0Ƚ.=:/X3X9=r Mo}|GmUl(Y[woµ;[zW.NڙU@\&ڝC&rB.O9u03?vIFa#1 fXLlܐ %$Byr%8nw'|z~edl9&.b3]]*x^eχD{ë( b*}L_f|twwU/^<8`H57Nr_+yË[ɓݖWenv;uK^EkyYD8ӽ==NLlyfgs?ܴݱbƶѕ+G=g;gbv8ۿ'/ȩkq*hEh֥_YH8AgAjۜvLqjSf:ng4Ö۵";vLɑ2*ihH_K{`s zymhZ R3ٷ]5EDVg*6+w_(!SS 7>S70ԕ9] W.ھ-fG'e#ߊuN;#ψ"L|WX^VlwE$~$ g"=׊"w? .z1 QHA%B8!E?!cgE8.B |@+£[=ie/ Q "%z:$2D8"D7/DZ N+" 3aSQ5UNt A0· (h SvPqivFw'ofoR4oT3T)<0 5X;k7S349JI'?FSIhIIIIדMR2IҚ!$H+hì뤣iΊ[_4[0aaC S^l7s,^fmbŀbwNC.ͥsrI556b+X4mA˸$6B*۲W6q,ZrØbĠZ%QXS@9NhrEt-.7Ock`~dyz<88/ם%yp%;Gv%)TyɓtAkֱ>F7w.7t &C7 N7nr?fY/#7Ut')| kCnsX&,_g~ ƃnd0]鳴'>rÏݿp nx ܰհM3Rܔw;nx ؖ/+n:ۚ F 1|N9.g1.t zw *޷/ e_te L,K`t%TĻ^^rAե/$ݢ"Tn Lѡ{!,lKu0ΛS_\y^s9qǮ rGx(m=3<`eZb,5GeI DЩB̞uF[E(%><3])cRĜ>쌊6.U&ϳjqWTjTʟݼaAkCNN&>HbvJ>̧32 Z6S˩fQi2VgHkI@IH%--ݛNK[ 9m{ѐIMiSsQ'vkntKp2y5]4:# G~y5JF.V97yWaQp^?o0Th[ؗݰls_Sr]fʌ0W^D5Jqmσ]U"T'Ҍ.8;'oo<s}l0GN#soBW{ǧ?9/ŗnrw#%h/k{{ ~]5{Vobg{73?pGPO?_+Ir%~?|g~ߢ0aEћ,οο"_SL-Y뇯06 \y9{YeJ?!C!ndiP؂o|?RԖ2R(%Ǧ`v c6Ci{~3m|%%/#;a%6.R+ 0be?vc~F?hҋB9Rh9Ugw9n^E~fr۝VX>j2Dnm|881y-(Yąu򞣩\byS^uײT_tqcS;8W/f]rqyRڣZjOig6{W2eP!ed\5ȭpl: s8v=c1cnt믏|ٽ9ơJ-U C~Γ./NR`;w8Su<^x'V[M۟~y __ܹkӕ"KZ;lDFPu RuooG+zmw3+7$ lCJ . w*y2̵ E8kԒdb{|iv V/,ߨRzSWc|=d-B&)e "]R/ũkyX#&1}n/&{. e»)V+T!%'°RZB9%1?-M aG8#9*-(AJٶ aɟ>ӽAԾ;djS)sVtmVbW/K 7Ezh;R7#c@c=Hqs;jֲ}gƈl02bƇ, YE߭~Q]= Gic/a/Bsz'6u=;v[69N>9'?5%R)xn ĬP@?ykTwm嵶kG=wM4~ۿOloO^6ɓd ?WnƦWT?OL cxeP?̱ͼKF/q%K€WO܋χs0_ =_xa\sߣ߻=}zixSt٣glWΜ?a q8ھz,c3Ǹ/__GQ8z(]PCq3SyJ(%Cbc/QUvLkw}`m]Kւ(LBWk3T/Z3so ! mAp%p-@G`)47A()F `*um:^VuGuWt3:u%84G- %?װ媻YUVօpj[ªäe]9G>0Yl n [ E@C#; \CC b+Q !LF! !0 @Fl@xhs;䊰Gx2pa 5j endstream endobj 141 0 obj 13764 endobj 142 0 obj <> endobj 143 0 obj <> stream x]n0E|";`'R!eчLR ,̥؞FCoԩMkw 5#[hƕK'i=ܯ]-IϮCɪ/|q}]*KR5tuP*Y}>)J5tBϔ,TݮL7)SYchtـsxΜ-s1[avy.Kx˼]fͼK1p!;/"Lرc wi;f;o f[x[vwr/Čr/-7[Ʌxf0 cofẉ0ߌ['uK q>;ql%3N xBMd&y[OK%7Dv endstream endobj 144 0 obj <> endobj 145 0 obj <> stream xX{P[Wzνzѕ%$l $q1`˕P%@J %ɦ+7ud3۝L3iiL:I;dtYlꚵn2;W kۙ}ܫK:y<[`XpN͆zB? ESin!})NV773GON-DA4 ?|-DyR PXl)r+ƧB/(fE^7;ȇBD<UTHF?o`~iѱIVTߡ< (u` z:^|ٿ,4Ig}B #q(^W1,<Gᩯp iS/½[% ^?Fl\1x /i `>B)*aބ 0zN:Ϯ N:QGZ;>8߆N85,7 bMߐ0ǚP-w2/3#03gNp) KN76:2<<8wW]]Ύm4iuklջ;&cyIN[Q !`s 'VEE/5C6ACȳYG䂒YӉӷi:uMڠƹyN|sKd|ȇYhE#c2.89虏fA[#56XC2)O,v"L{"|VdPX.䯱KARTuj%nѶydIA0fXw&Xh-KQ9<"x[R}qn$Ҭ'WmFB22>Jz<`&0s:>eK& ׇVK1G.%{z⡀Od.B?`*xJ X,d ?Idą!_`p_dT&)5ɺyeD7̻gB$ӝt+xXg V_0pUXhBM2:)4;0@Uaʣͻg>Z(X[?.$!y܋qb.iDKic#>D6KENV9w&ʦ@}CWab#gwQn*wACO43D7"~hX!U g"Loȉdԝ 3d`ˉ1֏:8|W^EY_\Bivq>b5mLCpK֣&JNš7eO`0MQccPɁBC*X3 cЍZӞ||QNtz}tm5þF ig͟'I^bPe`r*g/؞ݰ6LRέ킙HxfTCeбұRX!z ;~xRZR4Է3ͥ,ȫNȎhg#9QվmkA_m\-CMzXU >4_Uh e?}W~f~\pCҏ by%˽ʓ&W3'ǒr3ROs5m6mpwmbMO/+ x?9zMM1uf uu~90<~iߜ]_Z< eآjP쨷x NvL/;;OsvO; (& $@cB$ / 0l Et(~`T~Siv:Y\i0\VgnZ{זr_Pf<`\nw[\!w>X'&toV b5`M9vDZ$6urI=మLHVnhk+6kv:Av%*~G.u%i0՗nf;\[Xś صV%{6(B?l`=ǛN,?rû5;+y1 U9W3;LO?dyi6P/o5knܦ2nq',*uJ}jؤ߹ow9qiTD[eeDGǑ#=c?ξAIe%,: P}¹,鬬ZK7-YZ a*gaFR) %p2{.sI.S+uBAx.?c=XIi7IۙfZ'x o?|㡻u&Td-O\:mw2WȭW)zO_RBt A?\#=> {8?1T^xd26MsS9!qsSvQNRHqH*\o{sw Kkk: GfCɻfd$JsH$?Jv"sHn׸?I(Sgm7ܒޮ `3T:D06ǍG7̥\]7ME$p*LP9bwOR;Lґ7J#\4Nu8N8aSk:N>#MDŽRq)"fjnѬKE"uBӑ0HLD쮘#/67za q<'! 1(j PH C8 B R0Zvq|CJ"8Gplf?Zuu(҃pјoCYpbqh?)šϡtDBbhK-g8fH=vb)D(IԬz$?$QuIEf/&XE%Y͘{ 5F$-dIkIZ_q#N=-)w8QwbœRanmm)==.V%ݼs@ROQYT:|n?;l<%K,joxBR#>ϠnvY~BsR ߰lm<Ҝ=9G7;Kgj}JZZq{D]Bg5pcHm̏،ݞZ.nj&×ŜDOz(~rs 99{=Yް_q3x׉:nŻ\I<^#[פWW[l2acpy,\M a>`ˌenv9˚Ͻk5kS Dti`~)Jwqz|zǘC {]x܃̋癔bYs=1u;bW5i8GP)0^kƔ`8({Uk!^2Acm>::8pXBOQcq={TGzȳaT<atLנcshWV{D{Jj2$Kڷ^5ހHNzu"||ٳеO>1 H/A?JKJjE8^zé,51XS$TXL"6-^*iQ**?? endstream endobj 146 0 obj 4261 endobj 147 0 obj <> endobj 148 0 obj <> stream x]n <ƽXHH>tQ>Vƚ&T[h,)Jw+j0vajꚰ1twҮނ`Hw_Mvx lA5 XEW9˪}1lG_ꁖ.Q0{ H;9\ŪM*fyrq:&~|8>c:&T-!ny4{Z|R y endstream endobj 149 0 obj <> endobj 150 0 obj <> stream x |U?~oݪӝ}l@HbBJ'@ B (tHUm 2 B"BT`0*"2(*0010QQMy>gTH uݵl9F2 ww1lA:2 89.L)G9zjμLBzFWzJ+OEhY?.,Ԫ pS9aѝjJ8ϫ)+=8/]T{#ju|O+u7D+"ޯV\OyBB%\Lp(shdh2[6  P#cb 48aHbRM)Cӆ >ro;.+{r'Mɿ`jᴢ3+pjGG:jCn8wÕVn?Zʛ(^ k%tZ6Gx"J8.D`tG|/q4%|=N% Enx8zEv>GJx z'mc sl@;Rʼnk2n)WWVxx;>«) h;>|ECH! 2XǡVT#V k@=5}!)̅h.: 0 n&7VtN&gj>O@t Jx1N_KB |a6<G06i^Mn:n'Ap/pP ICsh)ڋ!mpos 'P.6|;őC9Umug^_? HF7?0);kwԬqpm 8gpgcX)٧U?,zlC@lBk+ (m e:Nvބl';Ov&# uՓxX?Z'BFv<׌VH3e Eՙr&Eb3Ƴ"]0~ts_u"jӲۺ?j AȈǺKNxxab8lCK.+~ddT <%y8I4NNڧNg-m>6 SO,W_QqL HO!l_ 6ryqv?̻M4~aR,K~~0bxPy@ٍwPZPܧ3l'XyQ50\j&9$[Ȓ'bTb2]( ER\l7טeGfSxaWI,1ʘ/mCڡy4|Iݯvm7,?֚baw\P1@'ă&Pv fY2Fə5~dgJ=]/.dwurXrxrD5&wGUw;*?,?2&nƸƴ+DE41  "$ar\R;/ 5R| ؕrAqi a $Sɺ=3׮yLǮ/s*.]s"-^WҊoki^p` 4r1ߧP9 3 uK *db Y@HkC7P:Em((=ho|yw~`q|ӃtG[;hFXt/zmᰄyX%6- %BpIڣ_ou']_ xrTA.,\Ob xnZ$&qkV( Eg9+t]ŏ k Mإ0a pc\cBCfQjp W Ay H+&J 5h /=27wi_hGp|ׇoA wW wPjr`v1 J9;$E8Y]QdzV2 SPP†8ߎ0}}1X%).iSp a*C iJw԰XYέ4Tyl$~8D' ѤH*=\yX^'q=ڎ=]{2<-mQmYpK"_],Dt!]Q}ڂ v[WaN%[D`\&|D,.j|ɕVy 0(4=@tȁV$\0*Ib]J4vuL}H]/9&?6恘Vx~>P|aTgW5n}no{۹m{egwG^}/;g=d/ |;ȈXdWag ӘqQNet.勎NFk.ddO^sO3ck|k|]c+;WZ(Dxm 6)XaFRρFdCa9YLGם©˧t]@ Dx..ϔh, % :Xϔ>l3QSɟRW͑깅Jnsi"l ($( ܦJRbZKVk dBx/%%u7Q@MA.{.u9(:G_t?Ewo9뇆znڢrFy4g;)_t2| _fp?3fTN76ΎpDgvOg>bDhO<@Mz+q zxpc22iLYf\jZf^fYf]f[f_h d 4ťPo{}~O5ozMCxϰwΑ ۴wN/9q&ƆBwPAdqvHƬ0Fi 5s [J—*!sc} 5x{9z]=zsG~{XD"S,QPKA0=%j@m29=K-]r֖[D'-k>3~ONo'Wp[ t>FF'!o;\N=̑6 C6^Jttj6ΟoB^;Ta`xA$՘ G=0b!SGwtp0z. ,%N nWE 0MDAp_+ܷoˢʲ ]I^zJ_d"ئ%4YE؍/'Ѡ| o/c^@&F$l#K %tYQ&iEN-[0ڲܲnk 33X=G}:z⹥իǖ>Ǎk}+*ma+x.@2Ѭx{Ad;4 !nEVdFbVn4*flCFl1Y&E h%hKˌ}2=+ApM[K@ .HDmN3(Sۯ=[ @c0uܦl[z߁x%[')6yzt9݁wLacA+98 =|rp؀ $ƋO:N;Eh:xA^ظȞfu}R㻚7ڵyW].}[@{~{s7s;GΞv!,A/z[l<㑳ڐ/n11:|uh~MaJFA a^A'#dJm 9:ul37ri@Jv/VOS75 ۵76tۺw\|;o|##݁ن"Byi4U#ύ ޜNa?,  H C'#XnHd5|elRh~2D?$ )QCP]EzQE7214cpdYTdR鑈& ߨT3YifGK 2A\Jn^CER[nz{@#q*&$;]bs鿻N `L[e;uG@zk{Ȗ p4Fe/{8/w72V RDMd?LJ7%[ $w?N3-nK*E\>P r!D2ЏK<RS5ܽdD\&.1,],/* -h m"GI-h7$OO OOv{̿$˯Z:71=a1i`8Oqv|~/j!sJ+iKYDtt1'/‰H fr`* Mۤ}^=닼3En.4[mvrHL_0 8k$'K(>[ %*bRKW*~P)H/%KC.Wx-Y -VE#B'&/]na2n֡veT!yJ5at/hy9p'}k0zI A N\}of8#t}7~$ P`cJ?i4Ȍ`ꪼI5Mv15$"KUBڧX/U_yi +3O]a;Ўh֎q  ^C:+ U$f,9u5[6J9jʧm&x>E bivQS{s4jjkxAlZ]ټ=˦N?>FF%;G8V4ΔDɓD aQ c!v {בab4E=J&\A0JVc KqI4ObyXi:)4%liqYcEi8n2;;u/w×:i aDx4t&e B\R ERL5 7&)4 uϮѰ!Oqʠlh!pPX$-⦤М֙k!=0EÆ+ePt}{ fZԈjᄇ"Aey/M 5e_郻v2gF+aL̀̀茆Vb:lRP(&Oaf0UI=ݡ`h>ǿ zjj BP1B ϐ_? yxiWFfTZ6<Q㰖:nBlGxW(R=豐 bVױο`(&K4o]lflv2I+ϵ + U"P"FFVu,# @sGڅXVDayOOh@t#FIvȓx@Acy%|Y }>cLQҸmgίkof`7h *~7a #_h2F% Zϙd{kY_Oy K =0ɒ?7P( C\6inPXEђ{D:Ϲ d1<  4C)V~LaW s Z:N<*>jxyOS/WbMt!ߺS!^-XjVe#t9dh&AӱD|4ˡnsļrh|}GǬzm-z= !ơxp4׻91f;ߌ6nݛ 19v@7}{6׬"ēYn2 K>-_Y᦭K?|η[4 ~R}ODמzD.lLj~".&Y 7 l:v_7_E4T"Ot~ 1ϰO/ы8:[;1,I.l7%jDㅙ^Dd$[' Y x>^UiJũh~0\pbT$VpU|-w1XhK-b9py0п llf u'"FX̭&1UQ\z"?gPJO׿B}dt{Bf5l>5vjy$ ך׾<" 7ڧw[WܵO<4w?؈yl7liKcP؈Lڈ!H 遍гFދeڈpu aDa( !vȑ'=flnunQ+l è\T$Hg:_{Mե1ri|PdX/4x|ڀ! +њ+CVA{B`  Co׊l^ʭNŚ;O,ZrrƧؙu[E[[Bq-9 [2)7nUw6t//_6ҽPk8 u\`ۤ[GG`YK, q8UhM%~ė~h>`_c n58[mk\+Za^ok>e64O}Xm=8.'gT$Aݭ 3.oV|g{[+=hjћ_ض텘L+&a A3ц *V?ն}!44/EECbA@OgC;~-09;.8+huga҆"o5AI?Ollמ>݆ooǎ3vl'؟)dv[8㏽c:AW3^c6 {;6ЄZ!H4 uńZe80;kdH2ۻ=IF>[űDsKQ1ܺvzݻ]+7qŃOh_~ Wܴi媍[[>ikQoo8駧7KVl73Z{Ĉh;Ix6=gl8Ō%ʶ1Tv.ۀqmv=^b8}A_fT˞6Y׶>,muȓy܃!ey%̏G5~ٚ6" 6csh0  A~_Azɤ ~YR݉],/QdhhP[,؅}3g7;^3$Q4qgeQq7Wg=>k҂\2N y܋mh'n(Zb YS].8 #P8T9fό(N=⇹-Rqٿ9!Q6IvSi` "LAPg?,"%x91os+)e<ԑ7&eRgŦib#Lk4Ŧ%Mh5 ۤVV))R < F89rfkpj땚FNhmt@z -}Ijݘ=Kwxvք Z֎'`'nӶhwrqvRws+2 is{^sA#+e--P%Y& [)rw s ˕009P>/ WEl%$d$bB`]RfQHAU*E1JQHƧ }| ݿ@x"_!S4dJn-S& H*6[*9-%\.Wʍ !X-" aذPYpM>~Zqe 6_ e=2#q\[> p`v| Q,Opf R7X),X5!yҾn'+9v.;"H0:{Ne@ ) ""b++I+NzxZS!vhk\˟wv}-^M¨oGH ^J7Q 3gu#CC;Z&X$X U[גN5~v"nFh2|=ጐ,I"8RSXih,ı*qLU[_gi@i2cDd^_l ek5>%#]z\(:sqpTc87Ӊz#TgEX}$w}҇ZvG(>>>Kϟh͒"E;P\2ȉ@A[WF4IҌLD׀ g+38,`!] !> 8ryXNN]^A>+QGfEnv3vE/&(Gd5'F 6/ě'} 0y͚_^~O.ҕOwشnjBݯ=qzw}8x'O^c0ٓgOݵ\~h7>:"m (mOyB ނnoUcUiVnkr򫲡qMu\fp k[?$u&Գ06~*lxZeOj2uqa; + *,Ua[f~z휝>Z>4cb>?F[q)9yX[MY7Y7*wccn$%6m`^Iv'6H8{.ﳁ] 'ɶѶm2ylXbH?Ↄ.k ]r3Eܳ3IۅETăL8;fz!*#p(puhuoaٚIw ?7pdv];1*sɆxBq(u`DL?Al+"&PJ+FZ2ykQ|[:71-{hoI5υ-˶'vzYieeӶzC/um)*=}zY9kfk/qqOW67\ռK/93\iʟn-˾_|楗pzS `_'1x"$-6= $R3 ,KE.g]lgd4}8y>c*,T}_Eq_Fڸ!t߿N迢&W=-ZaH/h2ZXߟ_b8,]0şGK@wsu<ޥ熣@{Fh8;>n{'[D&=';nh;'`?zY؀#m}uO SQ=.C.30FIB*}ۏ. cW[oq6vZ^|үǠMtZ\Top};IiG؊%{[\*}Pp7lEwjPE9GmLn7A49[SmICHR9̯AC%RT׃HarSk{J(=U@I鈬:a!?*QR穭)o,aʫٍ JүCl^c9daUCeMc3;N% X); |ZaR_g:gRMZ=@* 5SS`Z*Eha%7:P5T4UÄֱFIPg5+y`l*GHE)Jg,0t+bAuM^JRk=tk.5u벭6,TD:Q/] WUTQC+0hiy9\]u@W:NTSȘUD- =|_;R J]oyU}\yH҃z*HyX5ujT:sn(QtF1freVt@e0ϢX1jim-,<;L^T60LZwX]%TsmZGW5SUR:zX+ew`V(T>78, 35!K͞WN]8= K͙L)5Nʘ Q SТ #Xfr%Y3 NU9ssZNirƫ/oJ39-ºzɚJU0vfd'(9y0&Wf9cf L͂1y9y0K,`;% gT‚qY3 &%0`@eMJC*NU3s deLmtMdO7.0gJddf+cs3r&'2&g&tvzš 2rԩYcs1 kl!k I2rNɛu4|S$('d) (ct)=LϙfL.R}Nf0 I祗^u@+ฬ\p*%.(ڂue-*6P.n527f_ W!,bQGn2 Hw <+Sj3YXUV:5zSKdЋ" |eРa4(UEaCe8H>8HAA7qɗ}1:(?+>{`%E? +)AXIҋ~{`%FXIXI郕.~p 98 .)^ #?6dRk 2)^Ȥ~Ȥ\ B&LJaFS(:Rz9!H##/:R:R[(=G!Q|;QQo@kfAIo\%-* <Ȣ$rƢT:TJԀT4xNAJBEЦûyP)jpKE=cճ3|{,wuXϬ0КQ }\WE-eyXRƑ Tg- VA;޵LeE5wQXְYST4_Pz6x5AyoG$x{/Ю[N1<'h>9tM{TH-T?HbhSzVZFw'@A-\G 5qCJJᨯԾi ^wZ!?{y; ;j`Wg Հ/Z(gll^b4U{/_s,^'xkKM1ݞ]5Lլw3 ^ZA)CQq=v}#:-{zm/D1Ѿ컞U}J)lg4;>T-3$xWsPFe@%: ^gr㡮U62&=ZAw H3y}*Tk۹INǢ]VB&ij`^ˡόΑ$B26Ƨ?jͧ26w9KH: ԕˆ53꠯/7=A5o~m}kWb}}@~*㹔Q0ti豤[Yâ|?.X$Qb?I}[_*آNe^h,ZҘ/3|h)v}s\+'^ +e:Zy\~U7Jvꘟ-e~w\ߕk< L WuaTP/F2}^_f^ӇF:[uy"&jJJGwf+yx}{i0K||w9L}u=*}$Ww3սͷ(r׃==X,.՘U)=^nliÊIM@Yl)(F|ұ [elσh,4͑Mʦ1{2\ͅ,o;c,\x<(T/zCQZtJ za3( g0 ;GO`y%WF2#1E^n*gY6 u^&tw>M[ Lޖ Lq?ukS6ūez;JW:TE=3OeKe•B 7vƳ( 4_6C&kGHcq}2ɋR>͔$2F뫝Y3x_T.k=szx땵>nMX#0kצ2sA4˅ >2~W>z ̅בtX =k$^ʧXX)=o}ߡ囻1{R8Gz [}Wĵ24/jE}qgB_ ^xz͊=*>}4?fGAol߯|[Ǩ4|c|74(lzJbr Ir~kط?s~'h&οvn\vcW)7 Fƒ-ZȥX24rt^&L[#FO3y|B>>7U禒>L>L>L"hOy?ýK?5{h{ɩSɉ߅'4[F#ȯ4r;.p^ yW#o oIFy]#iU5rX#/i䐝\+H/ yY‹//2Vxa*y2-dF>< yXrTCx*9ȓ@B#5Avj-)q yBC#5 5l{$HVNj "[ma<--faFZ̤:5͛,dI3&TNրĒvSZiVidr,ӈOWFSNdFkd,4 iHeR]&w_&HFE42מ)̝J4Ry/'h\#eґ2Dfi6H E(Lf(d0=id<-Tl'upFdF&ۄ& waiFapj&)7d$IF!L$q,$$bdPCKd`\00ŒFaIF5e%g$2 IC5rg 8 H`9 Ih:Fӈ84b^v/F&6F5"A3I#' 7yD#sC܎Wߏ aB- endstream endobj 151 0 obj 17548 endobj 152 0 obj <> endobj 153 0 obj <> stream x]͎@~ 7 Bg8Ga`,c}\]lcmLfߧwqx/vסC]җ||xݘfj6> endobj 155 0 obj <> stream x{ \T;˙}EᲃlFI㠀#* 0 ̄@.I Qc"IMib5di4m.b_|^m\{Y~q{9};}dDFn]O? B?(e~ƿwW߻~5;[~J|N'L<&ߡ3p\T߇]6W>ݮu-R tޚ{ܟG 7}`37 #A{=~ڽ 0{ FdXmظ)S%%K)i?.+D$BT2χ'-GGiMfP[|-RHhGU/mAo$_`'( M E(&Dmp&{6ȉiF5iFs4^oBPv(h/f耰{JNPZa(mG/{nۀMtJ[-*Ti73ðiGv.C9-P4B(F0ϡffNk"(z*6U@91z,h+o@Ν?g}xp]ʥ̌hhq8e7f8u5~]_mk~eש\#G|C;߈]/}]||˗ZA]GQ6BewLE0La( 6j4ZA92mzA-r!g_).)Sg/!+Cq-_Z_-,mvNFGFFF(]]R/wcjPb~-I7fBcqqqQh:=K%:;OTRGR7KZ7)Ek;kJ2Uğ浝z^tsc磎Y{6̝]{\m/Ө rd&guZp0ϋLb&^o-(;mUX%FlC&zȲę,`fVeYӧPF\3GW͋[يmonm7.p`^gW8/qg"HD;r~⴨[8U0U%Jr`h8kje_.Vu2T2 X~q섰WVTrG :n1h2Eɨ>l )q|L8%9u8$b´451Li(qcK25n1&̧i Ӧ%Ҹ,8%=z9G3ӥxhZΝ;sٴiG?xSwr u[u#3A{)kg/>._+MVq!nCs7[`Kt XZ`!7w>cp-?1/VbZ;6)uJ,wB̤_ Mu E<15-OOkt>;*Jx UBpO1ǥ5Eqk4K\njJk388Öa֧2i>2/ .6*jŪ =b뻐mW(k#>8(9愺[oMX&a(~(a{8gl};vu\0%vscd0b1=>Hysq=kbhvS$lM]A!4-ux:t~O۞v mOee=}(eMݿ8-ZŇ!Ow!Xy1Ξx1.^b(67@Qe72z<"B0 BZd '_i,\"` 6C{,m@5 ֩fzD80m-_VI-09Jo3(_E3`hcmTqBʹ%!/Uɲx;I^XsmEsWpZ%1BJ/?8|%oaf1ek{ 3\F_}CzЛsE)NPXk䒤1YEu 5vN/I2$%@P 7/ %fDD#cصixq FϟerҙQVpnhSfqiQoNʿ9},mIͱB.X14_V##juZ1Wu:-"28`b MTv'q#ĩ|̌?VoM2(:I SJ6d'10tCu1yP{~ !#dDYDE*Lx&1y` gOjzvyV^دD:>=Td0HnNDṈ(7gt.1IyJ_E*M4 Uàyrn~pqKa4 daq4+\||/n~dî5xX9V(8nvAӣL#H̢Z[M<&e(~Iast NK7%fќN^~0}UtK6%;Kc7ÎA#χ|.O#>/ݗ˼7}Q-;vD?jՑ9:v~iHlObb>n;o<|eZw>0XoXSmC_y{x,;Srg_)cз&;υs櫟VNrܹsJyȌDnYN8ס<ҽ% rnǏD[=q=jG\CPVz?k}E:"/2JE_Hp8o!5C09Olj'D ^3r>c3Л j ȍ抃˸H%r3quM!x@r80GWy8lJJoJTT|q4Q6)=4; Pss՞_*'w0݇톊-?~`pGv&8p=N|dFv1*:JkM HĘ/S]XRԬJmGOf1 |HRT3g(W OhLG&2 QQBT ңŞ4MAs-ڴqpf¥A|'~B3W:7d+4jWG vPzұdgԋi; ` dOJӢ;Ldi%)v#1$-J_)itdOHKϤ1'ERk+,us^yٙsuSGG6gAp U纅"Ұ_T`K`ٞcN>9SRG`wjkU-kw{/?zTiFJYzQJ67F&9"~uVV?O?NJ7.OVs&YLn6H?q j* ˄NܮmRj|+{>S0-(.>\B~>W$%:y6zBAMgNqrIT7_~cOc> *}^~ y=߆qXЀx=LUVMXq,EOL#5^gCio&t$I35Ɣn=OY>"m_=A Ǐt'8 aς\y;q~c\|b}&nKy|Ry1u?kW%>5>;OG <\gcq]k?$bonJߘGpqC)~UxKDh~hN?, 炑6e Y u m_vl?~m/_x4;0Gvp46ܿ?|BS[3FM)5G΅rH/ hJ \o I4.O3' h5#o7Z^N+fEl W |bf+ o4(۩ͥ!>c[އcv%`'SrE9Cɒ \pyz1\mhzsj ~yZZHcLWaBedʖphO"  teY8C@*K\n0[) ը[(嚅*RmhBMRI\Lߎڹv{vMQ/n؆ wwij{~8rÚc1s9M^k5d 9L2+!\PyNm'֑/ ۴wC>0XBo;M\uX©1_e|ӿc;$]^ ꫗!nP*Dmxѻ,MP8uH#]]hktY)3gC>N[ *e]DNZȫ!`}Rg+SPw<z赎/}k{#n_'2 ߟp߾Ý}Nj;z9VC+O{z]%t]GZcصV"cuMvS( 2.AKʵWjw>eМrF. Cz6Vӛͦfs5555ӇC!}h{Mϸϴϼo'MOy秿f|o2e~k;wLߙO3B~Jϖ?װV2XO{ ΚZ2nֶWw[;os6wwd43[(e Ns mއQ#40 q9ALJNs:"&''CRxW78Bhh-N"ɆD-SS'TC]sxjHd0ugE͊3+-S55J_grԾ,ϫ-yݡS#Co[_[ExĜT.Kiy[[2|eܴLfWk(BudO[J%Tj4p0MYϜ=sN`=4#:PlL:9\cӨcT:֡Ԙ_c*SǦ"ulF7ݮ(Ա o>`3(eH3g̘%J@Γz Ү. H . WlC:]k|=|WU6yָNWO' z=Gvy$ it`>OČt&Oof̺QyLO_g0/),t|_Aivx z< GxVOo @f ]΀zJ{=*)!Lx}"$q k+uuj. u=ݮ޵r({zo@zWGXށ-9IA8k ļ DXr AʞH/$5%W kq==AW%eSlkSs%a`^`PȄ y涮>7dnbUD `'u{(ׄH3/GY*X?t(c:@=l'|yRu-Hg(.06P|Jq8W8P0n= !R<.Qd&蕺}Iٖ~O (DM|ono+r訃z.W/ܞѡ*lj #DOrL$L`{Bty=]7 eC0A %9O/4uq?LCH*uT&2L/$ t@eY\~?C(d: atR+==dB.lnǭ&0Հz5SUK|%j[{|G3 `vJTeTQW*JʥFLJ-mQD&΍vDz|'.ȧZ2d>~D./S2IK&飔LYڴ]Z#TG$TI:"Ց#2iu$}G/|U #>څta `h .\xz A;j Aԋu P6jC9pɾ(VX!&EB(fP/Q)ꂗa؝nXIqNXMp Fk`_mŠyH(=5 $.r8 JթoYUHkU#>FLfqkbhg UQT/:\{AI`x`OEBN3ӪhXKuhBZOaM'g~FwY@/ABL* w5n&]ѡ FRhuէ͓;̳6 jeLka0Z(g ^7/=|u0,=T+R)6sǴUS0jP1j.C4QaSP@W++a^j2ѽnv 0`K0/h fPIH>0R=){0w(A_)ưL茟y0!j܌ VxdOTonE&:Y fsx` }LyڡnOE$"`wU糐EAVAU:Q:$9ZE]a s4}]B΢vʡ'}RyJ%V1xʚw-6(0tԹE"cQXWFXT!0amW$ƳQNXlhk4\⺆>},I5?GAhtLԵR ENehtw|FH ePˈ^3(ꉐFDŽ` PvC8.OCy QITb:~ &\і껋^%q8bq% 74Ȑ\=ZNEr :La.j] zXYxVecu*kbMDHwjv `-Wmn"TOa. "d~=N9T1_,gJ}bKUl|C~Zw=C=Qe̞jT ǥ ׀Įrkm3wdF#μXY (Qx![}ٺrZRrVYMvZ>T%v+gȪs W%>V+4j7G1XEaXJ]bDWP䊓{ʄקCC+u M/Ueg)/0' T(t. ˄J@u_Qh%AGn&kIX ]O"AW^]?L>~~J-p#:uX?$]W"W w+ W"JdҾRϧD/|J}ԾR[O}e߫wRIu]t5+EH_D]Y|]&/e"ugϳD>$}n]&Lge"LMQH~#2Y#rEHU{Gg;"wt-m(YQ|:>W>^LJDt|w4:4+;P@zW ~sUޅ67 XꇹRKFԌ&7;.}KƇ333ft,>=COe' a|H_+x`82..6g⇢a eώneVـw] 6] NH_Wdeoے{e- i&*b);dYƛdQe2^oC/C2\"7 2u-xC2A7qbg`,$nwxm,^-׸pxKpgAfc&n7ca{ɸe[e2իn6*f-$& ;fqE6^n.থ/M2^ln;Bcnq pQk x1PFƋm \mU2\h+eІ+d\.2/A\ p 9śe|ӏq Jqp9l(Y%x<È e/<t+V1' g'Lƙf1c&N7ƋpX"8R_)>%KQ`i+B'qCfSaa8$dS8!.&dx;Jqlq.`-APm *c> endobj 158 0 obj <> stream x]n0E|"W"!E*Rb,C}=3wc{:WzXW;5,tgaq۠=D76;6]m ,76/vS7]_lv7(j7|z碃ԘfU疇eݻj@(KVifӴ`}/ \de{ka%׾lJ HqrDK3' qJ)ϟș!#*@>™dF7>12'?> endobj 160 0 obj <> stream x} |EwUWwOwϝdr@@ rI2!$L@v[V]QeEȪ "* Fc] I=U=L"4S]Sǟ672U gMӫO##CjT9籿C=ʺM4!~$ٳqi]5<^vվX 2n9pclz`}ǒHSڜP&@6nYOµjrG~Z48K뛍V_@N2gsu'\Gk&h# $Y1OP L28uдaóFuY1cǡu3ǡm$ :KJϫj:\ MK@#P5 :>ѫa0fQZ_ υ\.q>~5zuj\~_fRp P>F<@8G|%<ވ/ /S.{N_ <Q_/q\es,8^^!3mD:^?D_ /Tm)np =G}bqdp .$>Sb!BgN+<sp|_ tF2si\/Џ`1Xa fr˸ | (ngT6%G9-q8WPAaɆJ0xFS$1S};ǭ /E/qmbZZC^$ȠG 4%׶;>?+qXZKfPQyy؅ 3aVNv>yz)3|?ق|9m&4܆]HUjMzoG ( =%&GGOv G';2CD{b$Cmb*s& $,1NAkx| G vrJrH@futsYxSB2=Jk+5pJ{|)C0f0R子c̙Ql"m]Y(ձtsss3WEAyaD0xD:`A6Zѣ 0`\G#6sLzAC[нq-/٭CH(|2B%Έr$#ȢA DqD_??SF_y2Np6D;/ wiu}]ǍhqIpvߎguE`DxYl9aW'y1zA"Ͳ8. 9 NE p\׹Gg< f,HK2U8Oج6'^^ؒrzk꽉$>>ȊLL_P_p]'lߒ/=6<5,\dN'7I=r`lK<'spߌ'_ lI^ sӽ W%єzCu^cӱ=6r_L$ Ip"EGDSFA 8W#bќNjYIy:JV9s١ s2P\2R9..ϵڕhXqYd2g2$E i\n [Z(WYn"@Bq+Cfw3YSuNۥNuO:]oc"F=DD[Q`@6Ѓ^x@D:S<D,q^AiH`;3 eȺܰs9ER68T.sr3:nw;kG8{(0(XBP砑8R!*Ťo7u6 ]Fqy ĉ "p8^iKN"ߢܛ>JCcONyȼGT%<'}&q}jxhTEUOu9J͇9,Pǎ0>1iP 8[o:#L$Wۣ~S 6l;>њZ>VkB$r,},7IyȟSR'+Y1'>Oa'#7P W 14-f(O:w';Pǡ:ِ; HFm2HFh€hS9iMt%ݘnJ7y284ϼèOqmuy"LqFds,:qtI (nRA4_z-[6yXѾ|mdiSG5mb?C`gX(OFm6cl y Llq:  !EЀBe>{$٬$8v^j7`oC GkӾójo凫≝qܚ]v 5GdoA6nq׺nYEPڣ)꓿HrPf N\`e \P^Y EW8cm6I[Em+,Vco5؎8v& RV d**8,ȚJ,}&uT~ԵTaT胔'_ * pN4V;5xahVt7 *fe n]lݯngWB3y[ xv1*A1u`s!?Һ=dQ81ۢ^yY:̄ġ}y:j{֟g\㷔'G(C(܅nJ~ܶ⣅Nx{E.["Fi/k_}U~o a>Ȋ1θ^z̲Kd5lg=AkAv˅P r~^pmEeGQb=6jG#vH8bY/5!RKm69J"#Ж͡k}~{7.`Ok4>-Z}`dej@&.| ] B89˄F,)VI}~hc4X q;m$n/ze=/ Aq$́qaC"x,CvpOv؞;d‡nܙ/?:k/'Y`4s,VbS($QrgLFJ1yxeiL1Nɘ9f+M93몬Z-0TcUYiQI2F 1c32dcqJ+\㜔0Hs {Tpb YQ]Ă>FQedmfu'?վmېګs]4WΛ{D_9]^"pSa>vf/h\19IWjf,)nKMnAu},AMfE9AFjʈ%BDw\p!Bڟ~~fmuuU_;0#Z.mV Y|!^71ߣ&';M{ ƽhj6`67J`az8mCL훖|; !n%õ4m%^}kZ ݝa"%Y1\lT\xDxd\DDxrT^Ӛ%<4bDě!GdCoRrCrs7XtیUOBLdLTttLLtl#'Q>1#!'`j?;JpTS,ҾbҞ_ɒ@u=/:^N1BQ6EMh%֢`sh0eT0~h,3}(si Elq)(#niT`ee63r|Izè3 mmZހ1xQt|m;{L[vr¯ݦG9|_Oqo7?b6ąe{ <>s7OҖU]]湮[ץ A!'L`{Qh>`(7#2RGֹ]c3/u\e+"l0a)c,qc;ley̑UpT8c$^Tಮ{禌4nmvw{;ﴷ@ZUAU;>}C~v6m~{p[WP- * ;Ca@@ $$d#cxpEu~b@ QFI${h+b?!!sϟsO6_۟Io^^MZ1-/zv[]riKOIԡ6k_^ Afഢ%d6 *G(x*Ne b 7rzjJ틿'z ?O1Ceb_P*r4Ax>lOȦDF[D;1)$:(q`L66 tJ dop@|hXB׸U[~8$hѷܸwy~5sgWWϞ[mZi[{={x!O{xYrF9xC]{ uxpDl񶷏Baf;>;WE0gCnOA^6+~e׼u[j&ٹ/ópFaMmo:C5iF;AX:J ͡H*%1<j*érY;g?6RÕʛ*ؿŖo/ I?hޤO/_BuBR}hЄfr/g-AT ԡ/Qp}(6fF{ kO<6q8=/J4-Akɫ(Fv 0ƊA}Nt,C)a4S8 }q%:$ve"hB%l\zOz4;P> hp %#djV>hBh=:bwqLv&>5apKxx|RT%m$BIR+R}L7N ͏Y޵Y߶IC&4|{aΰ氷i~M\1)oCN9S.y/a6(- -BM#m#!bmA#CmmG|ḧy (ܡ96Ar|[@km;Jrh5ۜ<:o[P oۑ4 }T5+3sZTZݮ4&]klT+h/Z[kӕo ͡C+]z\^ѦԻխ64-mՍ 5j3i T/v=m4Y#FaA]<TȨҽwu;+d(KtQ=rP{nY~EK[jCSUZ=Mj^{L`mQay.UgGʰoSZ ^ťZ]&W"Sן[L ^ꆹaivX TGu5/U[@k0S5\j 0@O_; OS t|@nHRXz=5 .OԴ5}.姮4Rdi:R*mq32 6jil,i{|LS":C.J t9ijZaO #ΙiUnnV75eȶPAvfc-fzT'MU/t:O#]P;ZQ*ڳV[c=>PWKk3[jlT~%>4]MVE\0QTߧM-0 ꪭe+EG |5Z:Q۰@UD-UDtDo(I&`s5^L^j^sR!V7X_RAR 6nexZkjR&ѹ$ILdT(6bOCc}1UePzR./Pt7 ^Uۚk 0~Vڨ\j#+-E0fBM3>SAݍuIjaYi:ʼxZ^Q68 _MʛIiŕʦWУ"rZVR槩3+ MS*%ptb"u+-TKW26O`%6b$̛P\R\9+M),,\UTO^WO(/V4liqiaR0&Ϫ(.T*fRY_05bJ `*\ `wʄc&@§ 54[:P#*eWnvØpw5gJi1̵4Coʇ s3Ck!ڠG u1jn6Vf8@jT]Y:/px~3^8G}F :6Vϯ'*k4ʀ1O~nV&t1AR h@Qɻ-TW?("xԳ cڦhe#}PI:z-]j5 [=M[W@wP^{q}(cw51Y/{?ⅮkbzTϞZfik=ͯw][l07-~_gUVb4tI+~>E{ahowݖsuK $9:}{_50_¼,Q'AI{x읁ʿW~:cL50C খlS}[fH{s pƨ2YlE_2M^khc:mLiAڡ&O]JPK#g,:TjWmKE_V׻%LMi7Ա_;hZvso*УWras2fY=,2 8J7+ Tf\as[aYN뾉}Ə D4s+J#oKeԟ[٩~KjdvsGʴ6HVȠ.XhdWJϊjT_AX'3bYn9R\LGߝxK뻑kD4Wz⬋ŕ^; K97[E`%lUl|EaRϺPY &Y3%K5wOm~?bxpL~OnC^.Q=#\SYWٷϣYҥ$.kY&hfzŤI.XW~W'Q؃=Z#Rla !*'+#եWU?Hj*`RU%pd{V Tqd\|<>Obx%)24iTҞw(m]ӫ)пhѱh&MʠMiO%]GGL;ᚶE|0Gy9媘l*\UIy@ѣ1|Dۥ~>uU0TF298*aWt.~Ә<ؚunK ṾƁ ]sEW%3鑮'NatZ^*~Y|Py[ *[%ܩd)b( t<&26֏Jʳ*2ɋrfcvѕkb֡PW$UzO9@;=NZ۽n%AҝH5{Z෩<&z߻ ]y jԯ?lʋHJW)d; YY_(V`gTpZ4ʷcWVzv{h0L H@EoS~wjIYN0vXu,@CzMzk>1x %ioNoxytfi=srQ/-WZy/"Kg(a ,KXG&t}m57u^T\ 9˿_K50 S<ۊuYL}~Z>Jm4꿫@e Z&k{ttNū~޵oRG^ Ay?HNA}|MO{mb;,l_IƾzwWRdܾrja_IR=Jʷ{+u1zҥw\GmK 껻tݍ-U$߽ˤ0&2)ŻLJ]Z߹ˤ]&߶ˤLlIa2T'3nuiޑrQo#{G{@#;6ڽ@dtF掏=v|wi~|f~;>JЎϷ;;4owޝCo2\'VPS:ï-p/_!'.\f[! pgDp59/mU<=x84E99݉bHv`pvv0dvEv;[VvE A<6a# =!xl g'ܣwH tt!/l];a+yap94u>M4ҩ*^A*"$_jo98B#5Y<9O;St(/,|rGF>$uCF{9w;;oG Ԓ#[[ⅷjɛo$ ov7_II^-Lx=v&FNWIj$$Wɉ;M‰߇ /")D}y)ȋa 4'/w^]<]2yN#֒ۄy&<4r‘N1“'YCvhrqpN?h&r&;4<B~yX#"CQ=<t${ko'y?Cמ7=ܯ]FvjW ١,vlmN~+jk'Cē𵹓/ܫM<.l= > endobj 163 0 obj <> stream x]͎0<Hd"e5 H ,m.}ŷvqXoqaQacMu a,Q-Jk;eZ{|ܖp=i*mST_c0^ӏ1]+\øXUiRV=xXiɿcȵJ76]x Ūj߯0=ylcڭaM5o7ak[n#+M5LL 7Mۀo N2艦#= 5ka7}-C&24wG =k0пF C-&K8I c_ Ood~?H&bYAl>Cp3$,괬!'Y3bǘKZ 5ӌU  endstream endobj 164 0 obj <> endobj 165 0 obj <> stream xct].vVl6WlcvرӱmwlN:fǺ9}~qkΪjV.sWcg +3scS?fn/+~+WPw!9Z[K3 +gWK @lo?.n&/tu2W\s/>+~!]c g _ eVp2r1MiԬ__yc//h h0v7>ۯ:,]`QLQ_t/9X̬GKɹi!^\4_H#u]M]ݾTp?o O, +gWߚ4W-\\_j~팿Z+:,,_}icnOKۛ;xcK4L_Gj hz*fk`l/ה8XJV_c;+[ޚVpp3viW㯮j+ڴr U{7̀ζV@%fj_M?S`aMDA᫥K  =ͣ'@_+*no`feoՈ_il6'dpsp7 u{+'7k6usv߶Jͭj zMqG g1ҥ6_r|WDtlN;OM2v5x¯-+hs^1\=k(ٺm:TuQ)0oKXa5APCR-^>coBeJqVzo7oN=:~~7I"!};/ݼӓAN|^h8̦]BwQ*AA-=As=[D Y^&pqݺ2rPf/m1}߁* iCkl39{;Nj#מ%Pёy 42y$0"l[I0tUu^=zOn&{8\BV/x$m;UoY~\*x{q!҅q(~:!=s:M\{m S:u_[KڅPI"%-SOCjv +;yAu9/$8z!R|շSK:D"ӏEOҍey 3֪/I~=tZ\ov^n1xѴg<hŃZ 9 AhW{&; +|=19@*|,v *+ֿ#J|)EAm .K;U]L$M2Nm|SH>c`%b$B*t^*·;* x#Mx2&bTj_bBѮzqEOK:j Nkx'YEd?Oyջӡz:NBYWlLoiètus[Ta-p 13>=pg;gP@| kMCq(gB YEE>'Us$q|I$MhouP|[{A~ZPއ"D7?m1{%P~SCDݍŃ !*4ytVNF)U\w o嗜ߔX-?PlTeh|(ޜ;Zf(uX)átFT?:.G#FOt޸1]&4 e 105$C1!6lxEi6/wږocmcn%+!!:JXNonuS^qg2$ gtHa5R1 5 k Ι{Pd 6L0$7[tvԕ P/'LHz`׿oTge͟㚛2# Dۄtj} =h vⲘgz?g^!Y0a"H0Oz 5Zt Ih-Y6(]} *ֱqr@2 }CU,+[xmaϾ!p־2 $8WQ"?޻9a[#Rdk\ha(rՙAL|LUDrUWry^Gv'>\+)iI=Ismv^AiT CQQGc7yKڟ~`g|^mAmQǚF3HMaiD3#qLcX]NjH\&A:2(?4DW^McrD~?Y,(U'/W%g`e1Xwy}QRa_A0/VCdAt]SE 8LX3v20m~/ǨrZ0<"=u|P3Cz 寧bD<iIwR&^V|}a~~-Yros;(߰NA,ߑ@W5K! WFhe`i*l(BOI\V5~9c q/5!$.VGS\F)LHSQXTv&Qb>ѳb7^jy/\Ÿ L)"ѵpH얷1[BKYֈSRt9PϓJ6O_Bўrxo=]o253k\nو~Pacc(_"IFlzEIETVPR]CٛhrF3BH8mA43 A-ЉmStm0z4ÍcD~Jc+Lp ڏA n7M3j,fu0Ym\F\/g&܌(7rJ6H~T$ˊ׾[5͝ӫ^ &?0ᴝF෢dlU%P5p6){WZao 3a@¬ipvy[LYvtg(hګ补"w致 t]D ]q@wXXqtd~0l\'\V7͑L79#IN&^fUO˔FNT%K Z Hh :JbŦ,mw%Eg؀Ma9v,L s%q3|>3#vDžz՞[͂}dLХ; +ᕃ!4TEFʻ?)ߖ34Y{$#Nƌkkhq]k~e $#Kl"mmGXߓ c%0ۭ7 S\8FmH=Edޘ0ftȠ.fW\MPBW~\MRJIt"JTs"ai>'&FGKr$vd2Sb[uu`1q'x-Re1q>{&μ6jUzRIM3LNq*O gJ|dI*qN[~C2i: p8 Cm qvn_^5N7oTJ0~z멛mt}VJZȵjQYt%ZtD&\VBVEwy&CX2E,>zgGh?ÜT7h/[r $yk"'/D1)AQۅQK>N/NilY:c+= D/46 TfkQ;kzs@e3t#xl. DR+_*NnVl#겵3v]%&˽t' ^g GZq(g0o0z{h9xAE)9\l*HG&8UZlUjƩ2H&pYӈ'hb !IOu{P#G3ѝz|,9v tDaPcC~Mm8ATY%%c )f~(<KA#S14AiqQS1#! j~HR# PXf` lHV3(Xjtи591 Y-l3gs1 ŹWn ! %xp}OUTYV<*ETwGe@A\x].}m:h3±hz++vLN%@|A>4YNgYFbO ){+P &ƨH;۞ysY~f3s,7f2<3"zxp)d[Tʜw|EK'G'C(X&tԬsbū"q`{M-2@@xNmfllhWiFg ˱4#z礕 v^ݮ Ks;Bn-iG?5>˞AEbǏ\9M4:e*:8Ft06!~B8J/nٟÝѠk]/-42@,>χ_v~).}1Z"c^=`rđ4292%aA _OĸE>D&9o5;Ϗc6.7W?w(ff*6瘪>gH'ҼSA4xR>LsBm٠ɤ\vKn`.Խryl!C$E03C-#xjɏ=R\Jh}6{;aK@95D) M/4Bb9-wޓ"l6 @mf;ඟ@KE.깃 ʠ$eܠ|[nf0ƑF !L8S5 ,Bp~5}: ⼥0w '?tw5hx a{A.< 6/rZuٜjĞOICj֟&v_#ݞ7}5щz}r])-BHm7ʼnt,DRq't^ÍPDI!΂6GRG+)i؞0_G;)8t4\Nh=5FI6;zX ꠣbe4V(ϤNޝ#DH%.aF~_SճwWD| k!{Ү朼na~7(F#DN"WƮb|F&Q:jKw>R(ʩO7nɉrAOt #!l'Ю_^d0eDz%59l%lpts0,zvyL WdWF31Mܙ}h)b?nƄ۟jMAh_:MvbGFg_FఴSkUPAsnk$=fg%^.c_^qb*)w1R.XCd.fw_Na bꁽ㟲Ğ}Rq"Cٌ\:9>m(u$fZC AXHv1)%Y~Y-j gvds hIBjBJ8k֗ O:N@+e_fe=]j[KkcH@Q2;Gae=i9uu֍Cxkf͜)2\RG`6HA-842*ͤ+wSK@:bux2{L^cBh+1Fa:?j\L N~MKzLHkUۈ@Z6vg=ogEX'E6si DC#ԹA_RM1OTXuǾÛQ2^}˵8-gry" (u2E6Dqnr|v.-mh|?PrܚVkSق9wiha>Il cJ4[,c Hqvo.dSڈB)P 0g%3$f-/RXb4o\@Vr|R-BB}Ihb'D6KT% &jt&>P &@{Yw[SL GJgdžgN6hq sem 3ḶJZrDa=m4s;EQ(ed=8Pϰ|U{[xhG%xܜ2>Ku@ԋa~6C,F3捝e!Ih#EFCut٪ C CgARf̼·)6sυFk:ICW1G_}]Cl>Z{Il6G U:Uշ:QvC0Qyx$0ڙLAUG?M\Jyf<՗:v4ɪE.6ȩ@7b|wQD># ^MnmonPJI+inGmNߖ?4@Uwڴ@{!13e@s7M lBA Y\X\ ~$Ǭ(sV>nR&SK K}UzO%r\jhAJ 6oqyuFU'm/ .I<B,m~wsMbG,ЩYD'{4`BCxlDQ Bﭒεdj5!)?{{PABq ( W֞Z @!<i9b\ t; ;Ȑٴ:}w]m *>f=[R;frC 1 o@:ngq~\yJ78>SVSc9)]Ioͷʱ6}ByT{TֻR:Q ñRiw_*9}{uaD!4QO]>ZɄdAM^L7Nӳ5՘$:mIkv 3Z+;cT2յ y jv0fQ`xp \ŜQ3+072Nȥ]"cvi,Xw*%duqfZ#S9ۥf}m!%]2'tN9/Uzo'%F6;CaxFOzgZ>P$xk_7(ku=>G̝ E=UppLng`~Yfe\;Xg5Hg. BB3s+XUbޜc DEqeT!) KSKhmuUL[6cφJ&gߑ-ŧг-TJ4? i=V,fPX+Eil0n~2i*<xJ ԇ*%whq%nnb$Y 0ZZlqkpĜcKڎlDQeRN v~umR%V,*Tmv(Ouٍ|D蝋PѡOrlo<24u<#?Abʶ eNBFb),Ȯ7I<AFۍ1[֣x=|nR&ڕفYrʏЈ8}H+%m{D7Y1N8&O"_Y lslz(f%CA4\0n"[[Bz٦YƦ%)w> { qeT 1tl,Y`kB 20@}Sǃ̞{=8T:5M: DI`X"d/_lދ:7y\8g[Yn5%@xҠ\p}('<Ҷf`WvFڱ)l#c>WuzHZ"h1]+k^@H|EO#t62&yiSLQhm#E|(^=XUXa=N9&,mԠ *v\[y6Miю` i] x1K6.Cs|=\vj_4[wZGf L  C.\\"ۅ$G^0KN' ݈@`tg{ ?Qn%.2&͕ƜP 諜%"8ێ).L5B٩eAlP DqI"=#zlh,+׶l_i-gZ<т.39657KȜ(-x%aOZi3Xnݍ c4:+)dߨ֧. ^D.]⼯CRAm?Շr~lELt$Th0F'L NR߉&EW 0m?^'ӓX IVlɸacVOD.ɄP`f6}fojo Fy`% mMYqp ]|wVmWmVy9# !wո({ JXyH.&21𩈁J NAk{" }^#gLLE2#0KUNu]7'iL&# +1ӍIJ{'Fg5cnQ0Icb'ζ )]E|,!$M0u;I&"Yߐ!FYlE)^^(OEY*F2o&8㎉\Ea .3 aKߨ.cJWa~rs^ {JI.WvZgEӿB<"~8TQO}8֧MΐlCyiEc8QCهTSs.VE̅B&!;ɟ =\WY:^HNMAFB+fƻ=RSYe.q 7$Yw@#aΉT2ZJ|; A/orծ Cv$T@+#6ly~}.߸xe h^$TQ%?&'.n:h(BRc$BQj͎3-N[$aa1ni|SPaϷR$ۿ۴ܻEgDy$+p.=h3r«[R..wϐHϡu;i/ J՝t|*[ deC5u^bC/e1%˃k@cX :kPowy+ #e'pkSo2gA6̎͡`9U7 (S}!.od A y`12"U /1ffUcp:/dOǎ\Iă|*L?Ҽ9CrL$qIK2Q Wζ2SZ6sY#C :"|PrQ n,X-rdcMԥO,M-)qYw}8e@0z`/L5UrF;Z7 6|㉬ɾ_kNnY|gz}YQXq8ЩA -,kxPmՁLr<ˆs, G twjG'R)n¸nr3o⇢mI&In\JQ7yEiίT"cTdısqF1:-3][ؔd햰|vf |~U׌B*c^]QdMo ,T+[@H HnkA~sn$2suI_$%9T$ƗUX:p{ o-5 S(L /?@QDsQg-Hr6i/";>kaLMNtf?@0 nKunbL"fc?^Qڝ}E vA^߃Tܚ5x Zy~<,Xj['}4%v3%nEI~V{݋$ZF4^ka^%,9ځsEEh׶D*HTtTȫe`m,vc7z3mx :WR;HdH}F&VC!1Wa!#LewVWrpgڀwk${)$#6V=Vd) N ָ5}b=t!)o儰uSciz6b:-43]_i11q THЊKQ]{ th3T9g;܉lY-ݏU4oa}8O^V" n_鱦3(ΡW(OxmV&Xt7QS6! ISql~T09`FHb&S4hG3]S8ߍB%KQ:Z_idնߗem&"jw|-H5PܔG?բyyɁ>YXmVd!Uf!ѧc_,G 3%FLAA.Wj?Ys4t4E n=oGK~:>ԵrVfHS#\߭[XE+AʋmcwYkh|ЕvُLu )t)Vc1A9GRam&0rZ幣PF}, ;a5e+z$I-q8ShI_W)ZGZrÆEϦpmrxRYI^+K2-Jeɧm+Qw"Kّ|*uKVe_^95jܵj`D'svTZ8cI;_gʉlNZ )nzlVMe:tz?+qú0\8f&P_m'JU53pݣtʁ[ $.Ȩ<ǎ=='+%8rAZ|RSa2]=SkU2g ''X2x=ju kgg{ˊ͊e_ g,WP3.}l¤YčqE[oa1w_ݤo~tJ ?{Ĥ&fD(Qnk*3X>KRgB&@ )ƦFv=LGǤޓu0gIDۏ \^Fh6|nnxAv= Qy"'V6xј w3|sz'P-Y U.,n.nI&zBgR>uȠ'C?9 5z-LAx>+_j8'1$i\5[`_#~\6?e=0h5;OkޣcVUɜ "b^O3r0]!‘oŘz"@HO帶2h@( !?V0OHqbD2{f|'!3?af$ K^J@$YmX*hƽ9a?,O< r2.p]'AoaG-Ƶyfx/-%Y#E[ ۉ[:'7x Q5y0^U(aCq'e_'.`ɿͧHyi~.w cyc t4A/\+hmԆwN4x ߴ! =G1bBlJnjgc\pmbmr)M6ZD1iU8bt[oKƿrTg0-ȏpY'lWzoR^ju-VWM{swڈ=gbdqd GS_*#.F,hpgD_:*o, C3& VuALkFBUC *;iݬh:}ᣂp%y3tz&wf沓< %?S\vVvI8Gz٪' 0&C@vq)>O~Im3BnrĈQya TD8b[YsyL8"cvnqk\z;rec!t9J1?'J~,n^|i\H 8$l&*k708Rh@#Pvⓚ@BO}RTX l%WgE ]m:ke2m3,G[< [_;v2@1"V7X_}Ħaޣj &֐*')crPnY3mzY&%%`d=fFӲ'8IOI(m&ff-s7Wʋ3L9P{rszZ55`WA1J;-)6Jsh/@[hv_|9<2{P^K#\תu2mT7TTY׻fq9A?7Ze>KWce{}Bf0Gx9)fBYSháq 7}v\ | 0Nv90=. B_q~h'hOFMKW(:S r` ,,(:-+~_M x1 u|kE1bA X15 2fam N|M..m9= )\ZNO+cÙ3IFᰒ\Shr膲˿u BOFTjNn|s#fW4Cϙd"Mr"\R[&@T8[miObVڟ;VB ]w6OVA F1ZYBΜڢns/둖$~n#cNإE9s'Z0,_ٞ'd8(kTϕ9:2 2rkqgn#w&"\i9n@DzF<[S&ҽP+ Fɼ^~9> zG5e|օ$d^b&Wf9X;/ßH9q^冠a@~tz@]UP;_—r|T &o(m7)1J4/۶ ysR+_jԻٵ] 0!R?RJ ]k s?R%M$cF* KZp=RH`boD|M0fnֵ1)ݻM.)WӾ kñRxI~b ~X9it≱ɤ~\=ےN0Q @]S(="C k%, ᚓv/R?DCLХR2b"~RoZ2$ .Dw$m2x|O&?zK{T1ǟ;Rg[95FZ]+jf͸`Qx#o=G47%lT$-Ǽ73Ne,EE-:ͽ5ޭИЭB)ym@5\L[~ɾ!r&-8_JûYs.bV1> _C]Y?syEXDx#K[ 0a&S:wSGmǘ,:Aep`T" =oRG)EGg I̥h'Yjj]X*tPFUg1mXu KP:2M?}+Z4gD%ݿ!3#>,&730o~vtQur{&)O|ESHY OCR p9`DTxAq\ >_h񐕰X%T/ V%A+H5Cu1Y rPZM?w^;V2su~w?1]Jw=M -N8l6㳹_9PY-Du?Y>zrl;wUMu[6vu:!My⏇k7="pp \T1fxWhQPh<ID3H?@:7\:ϳѐ.pAARLKU`K{ 7rV]^5Zh.pHQǗW X F"MW$A"=ɼ|)DR-@7w8 RKMձ7wt;&>l/+ |37v4"A7zS21m.ؽXPBX{(+8g[6%$1LZH{ho L )IKPec[0b^9rCk^$x?wME˽œYW8r4!G2Z qLVݔwu:E@S G~ZiD-u3T+le#i^LLH ,t- 2 &us)xǯfo"8 *SvzvCye([iDL\T?dY4%K@np(չX/S2۬*o:P*Go!ﳬ ƷtfVs|큉պf%aCK@ZC,65KEVi":2dQKl#Xۃ0-JE (p+kE!RPi,q:yFlӓ,ԭPS&j=3ٽp AYv٢N(<9D @3:b_ SMK̝PNc}/4@Z '2eh'}G7;FB` J}V?Aߣd-wY̊ק;5iaYAՆojg*rFIوBX<"Bd^Kyגʣ:q7Npc+*Myz)RkBŅvpf[ biYbm(&"-Cp,cبR=+ۡl(I;L۝Cxk6b|TOQnFF+]Ri/UFTrsw&&`A)c!kY c/([YCsŲ`m'WvaݫCJOGڬMVPM*t" iMWN7la| '48k`$($#w;Ff3yP<ᖓ<HsAZ'ĒAi]ܱlN\V(iu{ Үbg9[/խDs`X0h;HߜN݅z9w7 i7w~&87Ƒ¨vwk)[r%TkuӁ[s[jY, :|*j@nCk2L;y5r h+GM-iB.n[h&E&_ hskuhL-ђa|R8_wɊKۆ>چ\x\NၺXX5!V6z3ef-X)0|>q释1jFb56t Sedi44cU7'Ц\a'+M`Hp"릵%-M}+ HWIIbYh\џ4 gu= ~ծiKtgDNNc񁉢ey8X'cp}4Ha2UDl܉Җ` )+v!A ^zoOɉh>1"j$E,DMѐHENʐЭ~2]V^Y}Ǧ΍;Ox6OQ)!$"pxn;*T~_SM%Zdkk曑2\V۶ByKiO+mdx3:1$$&RB(˨7}n/OaP:+fFEegB&P; ~\yĹ|6L[J螓!݊W~>tsLCNYe] 2_\ms#XX/=.q5l,sa 00=Mv/U KN]CwFcQDCl\7vHSVQ`ֿ ([ʇEB&0wf!(0W$m+ J/Ǟp1HA^2bƓeժZ^Ҡp( ƪ1 +j/RpTI1b.[߂P6b6FN`KL g/)lfYbt.w.o񇻏,]G#v TЄ# fKMٳY&N2gV"_\jo$4?ā5GEdOFXd`@vN^>੃pZCIXSi*_ /(IWʭӜX5oDϰU*0xXG4S_!8:ژWJ>Kgt_ quϢ;1\f$XlWA0Dxk6!6+ކE.MDlAl&U` ,-/.TXLzˋR2$ꚉLesXy}'ۈm ?Ǭ5MB4d`.Iáԛ$(7T_9?ps;q@fKt}۷1~0mLt5v+ q}tsMYιRwl*+p~; NYb;1ĨAȔYv K+g؀XdALOЁx1J;FTA}+"Pt`Dž89'8khdGys q$LWN7)Q@FGRқ]*qK{%>AчU& ~`vݜ'%J¿zf&VU ) 1:v( loQjyo/]\S0p8HdDyK[LD>A<1, .jD?:?XEeɼH\t ῨsA|͙,sgűњ( ޹6%exW?x)LM?|~~gP(BbB%v6i:ou=?Q:nxHhdO9: aE9@括t!wP*k]ʶTɨ_dp>YY% ;x]:>;{hG+I &0PW.j0bOW}gfdKR ?.>֧\ tz@*atg? wn}7x C1"G߇a h;:t)ćLp©^ !dA4^f.*Ye;/6R*'1~E }qܖN<7~:㺟\MoBI9qDz>k3HL9cpƑ&:>.MSNbm{] l `9`JJGi$KSI-Bg˖6=0SX[hbjkZT 5l$r(-MnJC:t/[>"dҴU KUQL_ETR;P}ږdtI?i0ԉVn8'D@~pvXI`6nlDU>-q?(1m4cޣ${0ˢNط[]rm!xB s9FsKO~Y0]ّT \z'51h in8mUJ@aFe)ӧ +EY'.4&~bOe!Hr"btdZ9a?^Bx?[9-Z.)U3˴fyFp p;;8}Po9ָ)9w.N-R^wRzQk8?kƋ+/h! Ľ6 Y `'|3&|EYU1h,YPOEeB᥈pT mkx L,VެW~1(%XϗẐűk9p]?ۖXFVުNÈR5T4 v:Ua*[Vk? Ƞ' U%L \؎m㞧*1 _ueߣt839p62hpB@6"\ևvf[.pvbٟHa/\dd9arYvQ$3:I_r? :^#@_(KtumZ#u=S{bR' "[D_a4٠ßu<6S hlۊ.c=kjך;Nv }a-KYvb3x@8uU/+SQA;H'#T2Q)x $n $ D`Qc7z$wĔ l$0!I&{{$IBYb,&+w-pSse(;q ,="q!?H0EpE ?v<~!}|$B.FT ԑ0tjxL.;I<_MC@'t'!#9-;霸AT2b eSm@s6HSUX_W[k36رJThp?媒m cZr"+t0(ē5tzYl95^J@?apa̬Fy<1/G;6`k: F Xi$FJ?s #K?-HT}oԦc#El/bDy}X ?oJbQTx8W6T%שt%pKfRJ%tڗgܑ#p`A?9hBW~=);k~~!;%x }=a}N kkv^.P)XB&"WByK;zh 7w_jb'@{8PvKW!vk}ng1 .IT4H"lf邺l:+%TR==Cg~~wUZU^lK_OOdrK$,]'\sS[-[4Wh9Zn{il7!)|HJh$='ՐT]'>3UV )[!}tRE G.aq qTMJ|Q"a&F\Qs}\Q"wFo |k`PXg ^* rL2Ҡ7Hv)nܴ9F 3A B+1sڰ5hVJޡT$,UVc%W+:(?rO]t\&_L4:uO@&PN] CNQ #-Skoڈ[LPBBWۻޒ8BjcɟTwL5Qѫ)_;I}\T\1,AQYx\K5pܒ ZL~2tʹ9DgvwʘQYSTsAk_sDf;R?uͻ!F Rsfʪð(yR=KyzxMutI c+wS yjP?*2췩a\j CxOo+#}o@ֈ#QPhiT_ SRz!M'[T+(u6pD+CW2\1hJL-Ԍ4Çೄ:'׽'Ph7AXZSvkw貾 + ܟf?Q"1E2(柝Hdxs-(yI+:u7ǽQ~U'2|)AG8\?ee%go;$y}+S_]# 8Ϭ1l37!r:ựQ82, ۰7Rh2qcEwziNqۿ<}]^eieYgMg ءVOY5:kE<2}T׆DExU΅>3/?¿=H!C9a5%U5;nyQW|mzhY[ ;.qK7U\OMCV VVFeVw!eKX5)ˈfrwqKB:Mۍ7{=asjFIjx4ֶ *; hC``jZ=7εKpT UUBM#`|Uaeyvo鬧9Q3, "Mwdrk:'''{3 VlA% ΛR]f0;8PZ4?*@=k~飝$ -~7us$BAXa\k{CB23}`,B_2Ыծ?5?"`>I/u2UG,X>2J+:I3ɰm jʓGq:G P;vvX3%%@ۮ?ıےx=˞8fK* (Zt+J iBx`/G*Mn7Tv*U@D6xvm3 WӅsUgbP7eO#WDJ}1sBp"=f< ˜$Xj,@nS-u=}"$ې#+nJV;ne+#g:2?WГJ4P`#ïTAfG@u`&!8cz-$@E:k]eܸw53?P]}BCLԸq'; E͚k/-`y<-{"90M_։7[ Cwt wNƖ_H֠1S?^}̱BOY6]tlY_.q$gz7< AAUS{E=_sYaɩ'bZퟔ ' )0zll$Xmjl[mlcFls3zF4D$qLLlHwB߂bF{-{-@` nI嗧57ZF;o"p:^Ld"?-h: ! 5S™|Q *BˊtF+usB-UKAZBe-,+K{`1׮kA#ڳ݊躢z⧳6CÍLi8''vQ@$=>~DQ^0CmP}K(Ww.C̏5ؚ-ĵ+e<9*$eM˸vBnQ;1aNY.I-VCQ7TF|N̏Ϋ/ Z=um A?,i: :>Js_{3gc?Ov.lC{le`EN\dI-=/7%"gN!tWG>1CsTqMߎIbHjL l_l."VI 3]aЙ4к 0X6`]dʶ"H;TE *ޯ/|IYhػ&Kiٳi8zڇ(`&_!E;sd@)7jMpG9Cxՠ&Oa{K@=!o%l3t&4|s[B Cwޚy<PJ/{v;Y s_:+hU^aC%FR+Vu0G"xD*tz3aX36dɆ6tr4%y[kvCB.8pȺMr@Ybc8]Q: mٯ )8t `{r7itXoVeL@Q`8Ф/[,^?d=mul<J)hE3 ?zlV Ă C4kxdx˒KTsw[?TEM?X +;Ws5Ԁ EЭO֨**IQ9J1bLZM+Ʀv>vb#Uy/Pcnxϓʘ*;d2go&`Dc3F"qcq@hi fۖx"~U\l\!qa kc?}A[Oχu{նUl˗uB n()Ču@ }SU|=`hkeNJ= 9I멷RKOO|Sӟ3v] I4qL>er*&__<_I#L .k=< zNVIY"lEԘAz2LO&_LrAɌ6E 1QeYTˁ4MUA9l0o[ %t8~Qo2׫V!d͘m SJK*=dȝzǸ;Kḻa2*x>e!2QM"&?qa Pq>734 \MvGرxB`|«C6tիQ8|{׌S͋:TkZ D^ 2{"fGbD*(G8wqtMџ/@/sKQ 4_aZ?O0ol{0=׾ HAJZXK4Yo{̿<6'؉ *rX=υO?Nt@~8!끫\$O<{To(9JyZ]uTT1lni?gNRyO# "*}N tOt[?]cZ0!ͫrbrհsaq-051<s(ˡ&A( trd3O2m;[Ikā婨r쇵]芰Z_t "d~?ZïQ`I3~ݞ0aZl@D!K^VWJ@tu38^(*9aOPHT-3F+Y3FS 䨪:#ӱ\xx9O5|iH7ŝC"%>?L gz (>wuUl1Gz՘.Չ+/CՔ ;LxZ &ѿyt2بS&c5ӽҔ[-FGj@KvaH%WkhIJOAdXܜ#+syxȴeȜ2 lBgzɰncvw#J -My=Z%DmPiO}6ה޻PERF~q(Dz\8?{]#io&Ʃd_i$PƱAH%\Z:׍Z;7rբ}0]& Sn"O1^/FWCeKX%qLA6w; z"]$%8G&Lcޅ&r<"Lc{+JFR<~1-8Efm ),G9h'1 I7 +%:yDU.d ϗrB֝ai A _"xBW k>RE`]WBH#h]@}N=U%꧐&7lcv'nAkTC\t0jTZ V\YHb*N7-+nhȰ8R'&d́_kᆶW&f)JT9SP[baX E` &K2ɇrS78-y/Tg+s@>ەdJJ|[ Кw#ҲHN^!LJ?vM`ǦۉmHHQFG]F2ַ+|nuaN;D-І,FJVpxېg*aU_#'BWMyV ᴛĖE8d^(rzADӘ w{]:G_B]|4N;I0^cr*|VhY4t'zR[TS/&˺r 2) +w$3nj(\qQ$7 4-Ifh/cgMNNKgNBP(?=c HCuaJpYjxF;N ȗ;Lx]-UY݄16Z& v"e6ك7r!8Ш*?z`jmH~*\ hSg~5hC`lXXZǻ;Kje % C, tGB_f$MwP DԖ/2EX́ULK'=gw"ȱ5/CN!AA泤l6wqBe.nb}zJzPdjhNe+!\؇M+)M)6Lw0SPY '>RTځ8 [ќ{*H;Uؒ p $ ^U4|93F~XKj7j*;ʒeM_u-6+bYs6㎎AJry{ o8vInq;b/78klpjG&?KU@&%zV@*XrlcnʰMN3ˠzJLB98nkUdSa8З~ՈsWW)6$Tj:(ϘCk{Jۖ;FJjA)1t=ZFKd[[=G~M;?zo=B}V*}qS4V>Ryn2)/ֳQ9'/_3Ɛ2ݑQ{˷U'>x\m ~CD ڣILc"x(KB 1j eLJ٢sqvvQȥ-S9n*c9Iۢ41GIy]uBܨ8bSC3n8] {Ud =R)7mg&&v"Tt@sS h$x 'hG-L\ݝL\ar<\ endstream endobj 166 0 obj 39812 endobj 167 0 obj <> endobj 168 0 obj <> stream x]n8ཟBvQXO HYi@#WGt>R4uwϷ?oytnW/^}cZNy:Շo|v/yUjNi%]O| _sՖ㆔_cs^mzWmasM]ǧôڶcsS1疹EYY٘ w#rbNsmܳGn@?@?@?@?~_~_~_~_~_~_~_~_W~_W~_W~_W~_W~_W~_W~_W~_ᷚs~7~7~7~R~7~7~7~9w~w~w~w~w~w~w~tF8#Hg3ٶ l+ڲr Y,h6;сDt8. Pi|Fv +KdDTguNm-^F ̸>-AāNą,ua`ʼnALt&8eM<#art˄F{ǁN tޮLvqpvvΙK2=n=azf1OOg$@;<) bwW<}ynS~y.XG) 3,ud@ژ4͛rPvc1Kzp endstream endobj 169 0 obj <> endobj 170 0 obj <> stream xctl 6'vINl۶m۶m۶mض;'}gwf_w^{zzv^MB(D#`lgh"jgL@KOB"hblag+ll PrڹN&NoG @ hgh`mp03w7`0ڻZ[8 [#Zj 5@FI/Ę_[S c[g olc~*TEeeDd"JʊB"E 1qeoes ' 2S#]Co-7-@Ʉ^NFvN.ߨ5;\Mmm ;"-t3od['ɿ4(*`aeddaQ2:Q- ? vEwr?)?߬ ,ߚXKNbFo~uv40rs1uVw ?i0D-J1DzFfF68ߝ6pr6qV{$-߷6t ?.+&[(&10!ko@YE]e luG*[8/6fo%w, g5,h$jnb98;AD`_M55qrp0k4ހFP@0&LO$o`a-[91Hw=-==÷뿎t(~更^4&z++3Z8HXXYJ#Go⻵&&&F)ALA T+.P0՟X(NYɿؠaǓnu_WK[jdX63͆(-k">]Y=^ :O$6ŭtawa'V&9.7±xtkn?Sq9 % ϏR&rN:kqU{ ;b^e9DPj3otFhm@^hz)ARØ0wr6% ,ZEs۳E BH fNIWǜS#]Vu_mˑ:sv/S% pnicT ȴgl3pDhM3?=/.IDGj眔]ľăm φf@+jOԎpF >TD#\ap $Ԉ*}7L &AJ4ڝ1U, d5Ca@2 \Z/C"Ŀ!;eΪ+Ck+h\8hJ^l!TCL%syFG4F,TOzT]2o⛍ r+5 ?L@R TwLfٮÈ2a&Lӡ8nSr\yJf+f"yN%0aiVśfrQGe*Uw(Ee+pP`ٱRop7Oxˁa1b'{B[ɶHu]8 2BfX@k;Ri Ny< y/#XS#' P$=_dp%ᢧ=EQY$Hnf?af%q芎E;fBsp&-|do&*4WOO@8[@Al4iJe6S\Y7r`FBk}ssʆ؉"ּB~S%6J%KL5D `anmr(,t:\eQ_Uc%|㵗Bty5c^!?p8M4Wls'++t&Z w^4JxO''%tm;oje+5&8 {gЭq)ĔT I9Cao2<35av=(hS^nZ-M-^]oj^SKN /ѡ`OfOUyM@O!E\K8?2~ހǏ6O#щ^rA K$DKxœFt ꜠Sz`Q?c"Fe!nXm2nN*;Ѹt9hTxN3.x#]PRP4qoTyٙaJقxq\:(KgLa6zLIYy'xvnn@a,UpȈ##BRxcOQci%EI*9qb]ɕJ<;g'qRc%h|m뭁l "$ 5׼)H,6Z%G2ʲ,R=]G!Z ͫ + GINwG氿?ƓBӼ01PRy,AZ>0+ 3`)/2|Evv oFa~ݡ W)" :xf"wq9TT9;Ӻ7q`JۆZ|pK g!ۈAK"#>b!*}%mIAP{lBF@O8i$wqYFZYe&at 0;AS)sw8'vM9b"+FG/ˆ m fQgq$ YZ/&qyXia:Q-pYEQ;[^o[t+~'%Eu6ΐK$n\`Eu"!1KBjNgP)/HFAEKzPHJYo ND_QHBzԥ0{w"8O_"یzҫ\3*H:KGYbw\WA8A,%]myv\l/}lMnͷqtIS}K?Cmpc%v" LOT ;Pt +/7 vLJc}E lVu`WxE'3ok)u3gV59υ4IUKUq;-}er8eaLED^p{@^ӄnm=OSFA'} ^ɴewh "̹g(p9{tk& `k>i`jjTVc$ܰs46 dqz#91o 2b8ijv5ڊǠ$r_^96̦;sʺ[؞sa~gޒs(EzKb~p{Q.T){\_x-yX6ܡܖzWy% sY{]N׈˛*>.n` ^HvRr'.Lܽ}lI֖þ ݜ~9{P+$;SkN?Esi }޺ RaWCצ.t]T1%PeԾ [3Z$rքq,xJ hdDV*lx_aod`vDWG^@"qA=:LjpA$V+?E4;} ESj^jO̝1n5P*ҘRۋ}T)?`'xhkC. ѥ>2gj %z.8酂;~}1)[ .sڳ1srH3ɰx0<1z,"J m:(?fj!Ho{,Vsvw4~U&2/Dqf[ĵb* ɀo\s<`-b7sᣀ t$ Y$aqoc0(EqZ` p&uoXwvE\p=x4eoY!O:]` Z̨sHBYOQF&Slh[3-GM&mtgCbznᝡT 겹&*`Red=zPX"9䥭zO@=AQJoKRd^hlٙQ)`$<_ԣmK)Cv{!܀*{rFn rёD=P% Wš7DF'7|{ v^9?ktjCͧrrV0K m*TUN*.rnI YYc \iXgI&?^ryb'.B,hjFn@"* GnA%RH㱠+c>xِeV" T K)?o 72wj!5X}b J_xEQAMK`n.ׄ7R2QH u!H@1}pʢ A~D "Y^zih{ +SMۉKDu` " nA`, wey ҒH~KAc7;XdC:Pڡ`A~Gl#sbRm zW\GZ$ًICcG9=DJ@W_n9u"<7 +%aYC@pP$cqT{ch~ ! e`uߡ~IWkmNwZ.N~ Uކ~eJ;=m͝= d?ACPIpR%M,=WcDƅ,-\ yKhdIb#p_Euj`#qDpYƃΡ7`@D)N+?X|h~%jML,_[P]V2h=S둀_XEřfd FUօ0;${`iz`~r8E-mт=t蝻~ ?Vk5%=ЃS>Vt*M?q)0 @CsNn-!`-jY> oNU9cG, n6 &2_NE`dqkᨍLW<]T*y  TvZ lh***#珙8,hWwq%rڂ)W_tJb\eꬌ鑍Ji ^s)RSHڗnjC*s&:/'z]xs)Q@.'|)Ϛm%5 V<S= ,}Y$?!gELK9p5и{@H:6}䶷^Fr]Nߋο6BӇâ^!ߌaH[ЧwK*T%l( 4W=k7E"a籜Dsoe/Qk> Wo$)r<8j/buDt]HzQ8qìYCh 8qrP튥O@f-BdAv޶h'G$h?]]sT "KR= F&M<=OԴkǒ@xeԻAus$?7J8iн537ʆ.x{s}.N_|o"|g(1"dTAiV%_g2zq3  %``o{2&l0RB_F8"8 uYR:5<믴ZLjzkcG%S0"C1{m:v6e}Z-[Q+L> J_l RK}U8zi >y>xR.d7ɶ^R^19GYm| H[mNemk^SsD JY^Sv[ߥeco_~Uz*]wWY-iXxe&dF@vU P׸y/;}碵f҅1^7goƍI]kFL6,,يpi b\,n$:{^@!W)wv<`Q: ߠ A`c~2k{z6WYи]:i67<ĪMI=!<ܙϷ@?j͌GMs}9hmq>lxƘH/hfVI℺G?ȷW:$4YmO ]jƱL)D#׾lWĞ#pdw7Ņ^gr[/pW/:hz.kj?U5U)V.'OL{A5#YRP*q. Gu e6ၚ >v٭bELc~KF4uidY:L'˯gg7GQ'bI=fM7^Pkn ^* [>qLC-vSNW:YNj&4?3hG(Iu6396Ab %O%E|=[,ъhY_Ra$7|Wsʘ)ۉQI_5?Ho#, |&JLY,Ss`u i{6SCo1Jr ~`P'HR Uس=L5(cU >V,pȫS x?;$2i2 qbQDx;חہt|9z[sF<3S6kަ#Wsmǟ.XnE; @=VKjS۰K\&iU-3Cjo4ojU/!Nԯ}HahZuqNfcƦ"}ک#'Q^[yKX sc@OvYIO(Pa (z*-`r@(n, ՄV(AT b91B 1&2F$!Z Pgr@I,@_MAoVc8&$9#M0!M1̫7D(o5YwJBP/ HKxy.*[Ajs1*sn+=E`i,:^N͓#yuFz, ry#ēN"2>,ܥl Eniqj\vGvi`aM!=ۋ}:dvg=f!ӵqK&0"OܓC2BSH'[-#xf3pH?..zoJK'{caISFj\@T |V1#w/xR+yHO_?Hnd] L*TwGv"X\ks^IއK$2^@>*>;ܧ0OdtX8Ru5`;G]u˕ tI&qc|58}~G]6vJֳeP}Fk&V0VPANN=ii֝{?Iu6T.* ÒJU ¢keW_t W*؎<MscaՂ#k z􋁣vߎ5|ğ,\}>Foo\{9?EYJx ŵ (R!ޗ#j(f:_͂qN6yIWb]%b~ :}PX>R{V I9Qz_m\/ ExI7,Nϟ$Q(KI:v>1(_Mܸ_2{Y#(]B\RdX~QZGF O6E}1`@c]mvF[N>֊˾ˠP&]"k{jF_y ? JU'Y5VL^oX[[,堏 "TdTYT%[_ oBnQG6^9 ={.[h]ygԲ& .v)(؇<ݝC~1t#9(P]W>y)cȳLY|ě,Clt ?5R& 4ePl=3%wS$ւ5`ܥdAB5qRih/3CHEZhoVX8_>TAQ*uqs Y.V^ aKA| e,9uGD%3->fp 727oIYB'&GׅUJHX}|*ar$溍G`F9`gPpOϪycbEkҸ^:It*~s֛JL@Kt`S栳ϯoee3<)C_-qiPU󰫜mfos`l<žҴg}Xq4^x:im2*DT<ж#a?Sk ȩ3aYlYj/fz57Ԍ5ߵlia;XͦdPJscEB=KDfe *S> Ȝ&)Ecɟ1q#K"p7"ɢ{"PA֏+ОbĤw麎Ȉ/Oz _K[ XN R9N a/~DQ~qi%wֳ6.iJE ]LNd_$V}7\p/W`~qbVbr%c f0P |*qmK BHV,"m Ֆ'P[DL/Hk=]QԙZ[oM9{uxh+"N~mB7%=C+AT!qWOD+#82eVN<\uN:0^/McC3|Siڶ/‚M}"ϽLUTr< W2(G`3Hu@Q%sA^(˦ɻD,,}dyɵm, 7D;WP(ϡi!'67'kўϖ\o&&"r|ւ>B,i=5l߮<Ok>Ny!.(p]*m+A#ZEtM;}/d8;cF`g}u^Zߡ(]wr(%*T*$H\A97A-w.b ޫ[= 3cES+2.O6FSGѮ9(x[%_)1 'Ws>Wuwj~_ny'UM8NZoڤQ٩_9#.^ gTz56|B=qwaik3[hNA vE1B ȯ"DŽ]pZ4`o^'5`ٝS 'Ņ c%6`2&'d\zV]ln6?߂Ϧ3(6SyòձDvmZp_3Ol :uu^͉KtAdPx (ܯSa29<ΘP3,Iݧ%nrT(]TshPlVBTԥ-Mnas y ,,,An^ΜakΆbtHc)HXc>sb?N ?bBc@~.DB>u7킚,r.P^ew?7͖:ug5b9q{Kh@*+,>x))# BAz|ghKJ"{7#C0\e(Ta.!L 1r,_O]w!:AL*IOkE`9$q){>!Vy_!Bcfyo))O/ͮDԚi*ŋʼn&p-nNB ;.`k[޾oȹ2m)b,XBA! bʂٓk̝ᾫg&_b."0Rd7Y:BEe0i6̐sy#V!*\a{貖1QnOy"HLDd@+e '* Ӥ/~FBTↅz5TYj-yB8 hw|qv"yVXah:@E{6 Uâgxh%ɓAGC05Xs}?<"tzYV3K,)j^}G]Eve[ju?G3iϫmOTv$+E1AGo#՞* e@h,H.,?S6M3UMUN.42˱B[&5{Ճj7k׈Ѽ/F ږ^}Rx^RF!0KP0m~dK5?)&Dߩn'UIj*y$"*:s"F*%Xy*awuZ\Kb$y%q<6ܾ,lKI;kN8煆uRzlCDBc@̑ٲl lWFs +<@\0Z63k{i^U8>QevU 8Vp@ImiӺT[yrH6)r^2!m ]#8H*!:" e|mI&x5vM;XԴ Jpb]|Q="Qeڛ,\m%dDΦV=w 88//C`#;ڢE>_!;:œg IZOmXM"A;&SE%vH`8ޭ+̿3 LtUj)"x0EA5%tS%oky, ܸO J>YWED%#LhLe YYKo# RF工,VxJg& ՄD!yUtc`o56P׽OOu (Zq]xCf*'xaRnWrҨbHEwG4 PW¶1=/v;I/C~rJ']b< &I {QR [}!m rOij-*gL˼Vr 21hM# /w23i73l YIrIZiyQɻI.I'96lr_YF؂#~w6tN >%C?HOsVo_E~3=>90e>\+V90cB8IEvP_VkD\Y+?/y:wL)X ŵp>#iFUqD,t#$ΏPc< jGQ0p(ڠ0n!ľ;>t4'Ù?.rI a+]AXv`Y:$N N ny@5:pYW|W Cv'f EorY iBDwN;?l;3II3t/@M+\+x^lLt{AkPspJF+lHNo)c%vztN" 0@=M+0p'M D:1u{hN`v`Ǎ8a #G!-q?lZ1OR*Yݤb2j #~YCTj๿پ Pч]JF,/yx_.GP8M'JIYnlB( ,)(1W uSwFh;RTDUCYh?1Yz.& $q/ܕ<4' V(~m[JE(:3NǡĹ-/#B%Rܠm]JkAj@Pt|ڰhHJ2ZjM=,!_[w^1SK@r(?9@HiȃrN-n㲥OSO JƁgjdYO%c qwA@-V{֗q%(=lMvjI3p 6`$Z{#͠7$O̍X )Dʜx_x[OKRcckW;B] չ !kwzdՅ~;\Oyt8?`u"em ZC=%A+1͖+}#I iE]JZ:Gg"@Sګc@Dh~6z[O 7W9=/Tq4ѐXtJ`KBLiҷ/ϷS6K>SStv)WsqG%M#7Z5븸:9Ua ͅ@=<LSCq>afUUSoB9W)m)wê)v 9(ȸr?QG+Jt5|~[9mx<G#pDæ'ReQOf$830bZC<$/6Xx'~dVfLeȑ|$ZݞXz֥8Pid6a+8;@Tssa4 lϟxAY#E =2^dX-´*.mg_I|Eˍ}}]7 dF% /)(6B+1 U8%"Z[;@/ ">R)c{w+ǎ_dz5^)Ne #,1}ஓz#ŢPebr߷?PmB;ƫo ڥKV-C߁,v3JML"3q)"6{'G4h 0YF> poW>yXGz{OtD! 20-GL'V`[{+8lX;#`n,>D* ! dt]LNfׇ+v4zs qIƑ6dG&qxz@o_ ORk׀.+Ћ颧{yXӉ'2 ߖ:1޵YOOe!KczɰyQq#M @aSLXW73l:@P#@|o'2NԄҵ4czSGJʯ+Y{ep-ڨ]+V־S6sX HS$jv@^j4W3FQ;(J=\T"3_p,_4Sw$oXeEſӖ8E~8 8+4 Dy;68"J\'f:o~ Z7کt](uW|{+?',zs:glCxߤT|qO S˃q^Ңǟ٘NS%В2ؗfd X7gv,9xhW.lag ].~q}J]?cx _Dih1!e(v!FV ӏq 7X*6q3crQdhG8pߞ 3ceJTf%&MDiKY t:~=-ox|L,#3/4\JA^?Az]5h@Y/ʝtIXFF6}5GԷmJ5tlBfZ,:I-]cuJDƧw%ms&%g`ͧmMNlx;}~s%uKta*`C~ZZ?DC~=lY3qJݢ}M[8f9:ځ6N2 =[1$؟@eiLC8<׊ZS6U_3Lg3avA[04춅#Óp *#3k*I!MyJ 9AJyhtwRLz`$4qƾ8rޛMA( DPyXJM A.җa`S 'fe`fRDt冪OX}0~=m~~{.I*6:{o~v&vFËS՞b?`(Oaފ*?bi_a4ո4sA(k"D1]Ej"t}YI,*rA[\Zp2gpmN^KЬ𖸇UN'Q@xF ;q [/oKG-ou@gk4y1_ ȩ?֤Ū_To  h9IC@mh\KEfռ5w+XDsYv(L+aJ=WRN޷i0%a8& GQGɫAPjg3ps5C9| hh_ey*Ukp'9dݶ3"`Ne8? i+M0nm,_OuNǧQSwڜCJkK>ipADR L׈cfKMHb%Oc `ЇM?~kyڻ7t,^ut!5 J5$ s tNieRuz i_?ɓJ= ݑ=Z ϼAf[<@AC2YmWիj;M*#{ȷK~S(58捹Rn#$Te?T 1MY^9r+%[OwΝhyYf4ĸ0vk._]YQ's*@_p4q~"4N;PNBg}o݅{<X8fwN'I dP›lc%!KPo@s8DXE A*g);(]A,xAeih9z`t66bPP'EUy&*ɮPq 2eFh@o?l0=(LraK$=;!~C0x)FוؘYt}QdL~zi偮i'y`(G{cK 8X+F~Q*c (5-i]jmn^'L"kS4N'7Ro'6~baqr3)a(Y |FD5h̕u#)k O@來K?HAk[ *X-ng2۱a]]+j0Y.C,C XSz%s`Zmz 'n>|1y`Aj92b3۬mD k $H|;œ!MBGPFvC:K B Qukct!TyIspSEV0FפP@x >sc JIrK=:MHa>]MeI8NJ̖7эªXPU|4uR<9?,ڡɦ|x8Ҷxsź5qEh; |wlNǚ er<'r,b+M-Y #ItsE':(2ۥ;e~=”'2Vb^Z>.[Fn@6&Y3w @9p3B)|Ё$zY۴ qb+sT"fkƼ&いJ]LM/LpKG7_XiX: #l`"dIbF}- b:T(WP=iF.qZlѺS8B6+sA5*u۽yYKyDa)r&P¯ ]Fϵ[QMFڽ^y.44=E}*1AxwJ7-cXfb4M^C@;7I`%E8aAIv졤p' )0R-:d|ƶЃx{_Ue'K!@#Hb^2*`ҡ֊.'wMh|,̩$x!Ar6z bAy(n}ϖHU?L)O9*d3o& m!pf"Zن2q<MS phB.J 0mT55IE ap ~o-ҟ|j繗\nr90  ]t>Bե;5bk!w|=fY{L7Vi5Ѻ7VXɅzpB&kx=aJGg /!W42tQZ1|>f(X9]_cO焾$Ѓܔ-黶+eW6FVtb/F;hyM+ν"^ANe'IҪU= %h5$3XeY L R]]|j`2 Iqc z'*A }}Uj4L,=D6ьpV [q7k8 nyA 7~NBy^3.ѧEem(׌g1u^F 5Xc)[H{rs9Xf#>TJ"|6OfɌmo2 _om5@JƟ(~o~,Q wSmW ERJ>? w(_?K$,N7*7'%2)Qԭ?*Ǖs'Ԕ7I}sS"O,zs"]8 0kɟ8sz9kt\ԮwU|`—I*1y !Lд^P%ZHAb` Qva_p_nuq{H`InFym=</Q{uC*?NQq>S,ף zbvv lo#<- I͗$BS,S zNtUJ0lń%Or6ydN06,kr͸ $(oQ7m8͇b{.O UͼW w։h@o%ލ:Oܼ]|$z|h/5SQٟOi؊:bWw2%ԤBXm̷w Ԋ)x*\Op# B7Bt p3kM UZɿ&Nc Tl"qu1Šʔqht];ӂ̂AfQLjf>x1gmCWW,]ȕtUչDߙ"w*ye~ o"\?\hS>,jEʽcś7o jP丏qB%8ERn : tqaX^ X&딚"ZȩZh J8p񈴓fs$K;}-<'כ2J hI{Q0kWA:ɑk`x.y{l9e@9տI*1"cR i:+:[M=SWF8n^8 G96vV0a$U :{yK?#?7z-qmHkoO RHxP6h,nw2bB\V] tZb:dT G'ug\g .z5($`w/i;wAo`׆5 4Un[>0!1^,ã& 0eL- S~-:Ylj.]n[Ǭ+ AL8sl+WLݳۮaPzIו_}o OKo~zM1=_!5~TcYb\>{0ShJinք{Drv4{=xڟ.vf%A-IW0@Aаz0%+,af]}`k.{'ȃ{!GmD\;;.ءKj)a3kTJ'.R4+ IGJp=91 Lip [qzz͂fC3?%t3Il `ը'r&!}Ha}CbC~*xKXorJpkobb9dfT"·dIvkO3] D>rɏAf}Y71Hj m@5[gN~ab6$ĵMɇ$d۬F$j6Cu`_|Gi֒"W6ޔ&Q )G]2N7b\ i P$Z. ͿEQi耠[ S,ӴR!\ w=YX;2cs!>[ЌFuBb06=X}Z1(OKjPG*PJߑy*ݼj|2tb!` ONq4zƔ-&= H6wk&iMz!q/))"vd:`?  :f7J×b+}º$o d:y=e<*%Wfmc l`0u+P8Ipne{R{etWZka|4I"e-,8M@1!' { ;vSZ @1XnA6WDIϽJQ^8;AWS /CIl`ʠM/MT[ L `*g\ ̦%{3<mEbamf '`o{= }tjBu?qO,y k$qY+i[\B3 ;mŀ+Ud֪x/TC칍?KNW혿,!2zDKYf?P5}P"e78a%]Tt?mTcSܩ;R>YɮH3MZ3-O{L?Q[pB %g7h$&Q otT41~) 쎜2@pDȐdw i8[ Er[.5_~gcAVųe QO^|M?DMD 4B+l?k,E_Q jud.e=xb[T(2sJ!]1ُ9+[ZyInP)͊f)[ɬN+m[+)2`bkcNk4)ÐyPf_Rb։E \L/,AiT+ђgs{vT=IuƶLZ.[Y?/ V ''-cTM(m)Jv̰)\Q waKV R}k"0P.t$s${b6C'? $\|K(OI}_UBFsz~5 5?ΜivYu:$L[Q89pI7BPG4^=qziq!88:@oX0(-1]C-ŕu Tsl9ζFo MND>!;,+*c{aKzey+j{c[Pn0A]j0`REuR%mgJB1jn]q6Oznv6.gRעW\c*Ew^ͦ6WdFpaz2T+dޒe y8kv <`>z5elWp?m;q gԈRuRe|} '?!9D#^cD`Oy5ۥFz@:,DQ5*~( jrs0wքRTvF& >j.籸J:ۋ](Rdrap_E^O[qҐs" Í>cb$nɲpoɦs*~7Ey=z`32鉲n F_|gv'AD̕hҪX\Kf?-r+21V& ~<5|]yC{XTߪ2JIBmrr"&oY&c):]!HM]A``\lFv+F ĠmIYG4|8NB?g Tg..f2F" ҏr9Ig6l9~0) |>G>U&χ0N}¤'ӠRB{hE\P5, [GvNx&*IjDv`*N"i#8#Qi(vt![I d(k,]/ sB#q,[K(j^U-Hla4ro& |2c&Ҏ 1Ys1 [M]22 O7[pŲ֫eu0*f=^K.~ol+nm7`?(4YuTYV1C/6܌WG!U}51> (^Fcw.0ϗ|>@WmoU(;YxaVg7nIO(v} Cܷhiɭmi<% T)7Ðty0ΖkNvp3hLmVC(WEfi=30go#.]_yY jjT'1bp\qw%&c$҄r9}k%oo(^ H`jIrm:oZFPBG?6Q.,L,[c> D/"jko#]wAz7&V3,٠zԖ"jJ{(9t?? *|Do jK\J{P' @. E7[ V٩>l4穮(@o+<[CyTo_Bla&V+W"a+WVۊd> (,)s>Ҳx6 Zրe5DC Ygh9> M/aOB)4&Ivd![Ԇ{Ռɾm" 191cF@t~Cɢm7dZdzyV0Kv6jDPEV8 \b(pT>Bɧ{/Ey$2mC |8i ,D&.zyTBD߈  A ZFIev+rbķ]:F4#vI-_ E ]Y2Ɓ2. y"K攏h:& 9ȣ HY}Bv큝='xȳHtQG1>J'%bu46\4 ʛrgώXC))[ܳR5Z"Cg;ޟ N B[o5u5݆36p6FoJ\S׸BcT{lN?u+UEv+ 2`cU{Te׌vH}{1WciH~ u<)<@iP#~|%J_!2_?{B䖕I<1i,y/]mavo@0]#( 14{9̮Fgu{5 JDd.S5FiB0E0Xl{Z L,;ZM>0&o]t@@ G̓F6_Qa0".rh Cd(2[_A< {^]}ax cɖ&OXb8ϒYgDrT&`aװf*Ԫ4o{. d  S$s2&,%nUTNejʗL *X#PW~TQ,1wSk)@Slq.H3˃41a ( Qu`qvό=9M69~NdmLaBKOPY:|U;sq_ҐI?" VJ;ohw߬YdݕwiS6ٺvIPr%7i#a~P}$,,HF3ORk"o}Xr(,j}+n},ψ[n ŤRe4yÊCZnkh0;eE:EAkZ])$ I$s{C wNc0;e:ZޞvR,9\MG'RzG} @<8UMGU2SJifZ ɐ=e$݉䡖ryE`iLJJJwrln|1di~!-EE<%}»DDtl2K 8"CdZfd؅B`[K1FVV&7gKލ T${3# D@D `Ƙ j2hH>dA'v[ 1H_J<-O==Q4hW>P!?L](b&#i.;S^h|Q /[:/m3>N"3p +f:<  "x~P8(x8R<8SJgK;0uLXmvg}0P E};fC1bWuCZ+(Dk{.yby]c*p 5>h/ o|u d5`vSg4f,s΢ziclPy`(95Kj3~ АrA3[|k,>-9y}eQ5騱7+-Ԁ9{1\DJs@7?dDzsAGn,&f */ND?wIv2x%#:|mŇR/۴ MZ=g0xӺ ELI"~!ӊyh(G bkNPN5MՀr̊PkEᜏuGNj:FccKaD*u3J;-Ofe#t޹]}vS3W8 `nH4=}~Ϝ![ލvǙoUY+u6Z=uҤu/w3X*1`sͼk*;]zT^n8޻,nhҿ^& uz#Iqpɽ,Ci&luKa%X䄕걂*6>JO{ēiPy=_a-,3bN8:2O]tSQ}K_zQ8(j|e>s>tt.0喙[ra,R5`eW`L֞ F!5M$!~Lq;uAMF$v'MXo}d}?|wD'szȄKfĈa:~RDx!]m][O`:P,}s*X$o"8f@% 5Mf=BXxZWޔ[Q7fXt q!oWگ~l[uMP4.b]}i;H|y~(`sw -a${Պ>~j)Ys7S\8h F64^IN^QCggUL߲,]ڣȲ"š_ |` , SE8NcܹV,7*?aLO-'nǤ"~|u;… Oj(?~){")iPĬ i) ٱnj }c1ٽ+F]Wc;)) ڕ&/,nDeloK:Ao8f~~Cf]&S)qv# !yOۿ Ҏ;WO % ܐDgXZza9y=r߼|8A9=|H[LchcKݣio gC ?˖Iuf-m߈T!SEA0TY\#vޱevJ. %%(X[O$}{-=|FH:qge /6݆QFݍMџpbM\}ڨ1jA@8A00U20zpѪyX?(5‘X&-4A ~@c]SNTQTֱDSM4e~'qIЍw*NwRcXz_Dn,MO)م Af^?杙Sne)b4NKe-u׎y*}ҡ1Wo)֏-ӏ 3] ^N;whP3Q1|dZBn$DMqT͈T񘀤$>'; D=*$aJoVzHaRT +qU)m9% 0bv)Ӷ+ރIi=/T{d/!hb@ Hp,-6TAIoKe˰|3ìܜ{>& v|Fo\wGNK Oו)(P )\1*d ~.P텹=Wţc Vͅʵٺ" O-"5}OϮI)s)Euؾ=p~+6ڐukOÇr&ƕ*{d(0kzzծU KI/oz01okwrڳ *ٷIq(;} )P}r)^oUg!.Ă^l MY#E o@g iMHҽ dPh[@RWmlD+Z\+󙞲qw/,tŝD5oRDTFٞ?fP?-rǗZ6Lr{`Ka 0YKNdӥHn:-Ga˫A, WEN10F BZ^D:Zڦ9TA,7nET?B1W~ Q3%&>+wL Q_zoWV4-lUe 7h:^aCeA&^ Xٹ8 |SvY),ioAPzԳ?]-􄭬}#D𤋮t `A({]죲foC9ɫ 5h7BS_n]C&[x/VLcr{LBE"r3!J$9JBȥBd~Q:VJTaN_%1ZYEbq:F“~*<.[gd=QL_~QEZ ̒ e?TvLuB$~LE5-`^hvQl6ikOM1$sHhCqr rF}Z>nv<YA|^[y ZE%&+~MK #{Ͷpրp|ώndeb{ El0~m ,xzYyN5FwizӔjKtn;ܤ}1yLux[*o֊g~*3K\(d֣`ay[B/j7(Xx){ZaPd|_{>s,\_ebW2"sϳ$IY#v*l>XIuf.9U؉b!"Gyb m^h $9Ѣ8LOv]!j;=FLꤲZujnRl]dę-83ctܪ`sy\PVP__%7\v@)&{X}"2+Yc:Y~j .|c=ɏ:9l_)v)YqQN _Y kulKzr1zB$OT?i< 9b # /Ѝs!t xXuuE>O63o NQ_x}$Zl ™8`hC$lA F~u!K<7IzPCiJ>aˣck4PN0d~ExV&ȷ8gԻqWħTk}y5LٶWfǜcgT/٢Uف1◻=AEc~Ix7$" 3nm.hZ4Fy\&?&kl 4QMch6%h8alI0cqS<{ݡ*3J9R]-۷/eCEH* *L/7M~2(Y~!DsvQŐhlzo򡣩Lzjk!]յR 1KP()B%Wd7Q '8,ENnxH5&Q'PD@G{baBu'sG*hI"a=Ǿ.C ` ɳSڳ2@!ϧPj1E-Pat/wRN'&n~>ҌqqYR\,8amQ-Ԣn1V\(dy[:ք`R0)j./_C {U)sY-xYYŽCĐ1ڵ|R6M&S#UHN}3N'e3|``M$Pqͭz?@>sG52nϵ0x~=Q @~NI߷V 6"iJ6}оW>X(&:lrG$"\ΚLg}5_hć8G/kEz| U|):3"[ X]Mse<.A 霓ɎE R/mQikbƵCM;XlREL ГRpg!?EC09nn?u"7-om܋7"1_g3gM}OT'P `C_J !){)G\$Yi68eO4yaW;#lUf\,b9gT^NP:-+'׆N"D盇͐],쉂tg26C۱tƭ9 U0_B߮Ax;e-n~㳠O8TzD,ZxW>g,L\~:ڛR0` endstream endobj 171 0 obj 39050 endobj 172 0 obj <> endobj 173 0 obj <> stream x]n8ཟBvQXO HYi@#WGt>R4uwϷ?oytnW/^}cZNy:Շo|v/yUjNi%]O| _sՖ㆔_cs^mzWmasM]ǧôڶcsS1疹EYY٘ w#rbNsmܳGn@?@?@?@?~_~_~_~_~_~_~_~_W~_W~_W~_W~_W~_W~_W~_W~_ᷚs~7~7~7~R~7~7~7~9w~w~w~w~w~w~w~tF8#Hg3ٶ l+ڲr Y,h6;сDt8. Pi|Fv +KdDTguNm-^F ̸>-AāNą,ua`ʼnALt&8eM<#art˄F{ǁN tޮLvqpvvΙK2=n=azf1OOg$@;<) bwW<}ynS~y.XG) 3,ud@ژ4͛rPvc1Kzp endstream endobj 174 0 obj <> endobj 175 0 obj <> endobj 176 0 obj <> /ExtGState<> /ProcSet[/PDF/Text/ImageC/ImageI/ImageB] >> endobj 1 0 obj <>/Contents 2 0 R>> endobj 6 0 obj <>/Contents 7 0 R>> endobj 11 0 obj <>/Contents 12 0 R>> endobj 16 0 obj <>/Contents 17 0 R>> endobj 21 0 obj <>/Contents 22 0 R>> endobj 26 0 obj <>/Contents 27 0 R>> endobj 31 0 obj <>/Contents 32 0 R>> endobj 36 0 obj <>/Contents 37 0 R>> endobj 41 0 obj <>/Contents 42 0 R>> endobj 47 0 obj <>/Contents 48 0 R>> endobj 52 0 obj <>/Contents 53 0 R>> endobj 57 0 obj <>/Contents 58 0 R>> endobj 62 0 obj <>/Contents 63 0 R>> endobj 67 0 obj <>/Contents 68 0 R>> endobj 72 0 obj <>/Contents 73 0 R>> endobj 77 0 obj <>/Contents 78 0 R>> endobj 82 0 obj <>/Contents 83 0 R>> endobj 87 0 obj <>/Contents 88 0 R>> endobj 92 0 obj <>/Contents 93 0 R>> endobj 97 0 obj <>/Contents 98 0 R>> endobj 102 0 obj <>/Contents 103 0 R>> endobj 107 0 obj <>/Contents 108 0 R>> endobj 129 0 obj <> endobj 112 0 obj <> >> endobj 113 0 obj <> >> endobj 114 0 obj <> >> endobj 115 0 obj <> >> endobj 116 0 obj <> >> endobj 117 0 obj <> >> endobj 118 0 obj <> >> endobj 119 0 obj <> >> endobj 120 0 obj <> >> endobj 121 0 obj <> >> endobj 122 0 obj <> >> endobj 123 0 obj <> >> endobj 124 0 obj <> >> endobj 125 0 obj <> >> endobj 126 0 obj <> >> endobj 177 0 obj <> endobj 178 0 obj < /Creator /Producer /CreationDate(D:20170717103743+02'00')>> endobj xref 0 179 0000000000 65535 f 0000371431 00000 n 0000000019 00000 n 0000003056 00000 n 0000003077 00000 n 0000003256 00000 n 0000371604 00000 n 0000003296 00000 n 0000006173 00000 n 0000006194 00000 n 0000006373 00000 n 0000371801 00000 n 0000006414 00000 n 0000009254 00000 n 0000009276 00000 n 0000009456 00000 n 0000371968 00000 n 0000009497 00000 n 0000011401 00000 n 0000011423 00000 n 0000011603 00000 n 0000372116 00000 n 0000011644 00000 n 0000015001 00000 n 0000015023 00000 n 0000015203 00000 n 0000372264 00000 n 0000015244 00000 n 0000018295 00000 n 0000018317 00000 n 0000018497 00000 n 0000372431 00000 n 0000018538 00000 n 0000021464 00000 n 0000021486 00000 n 0000021666 00000 n 0000372598 00000 n 0000021707 00000 n 0000024153 00000 n 0000024175 00000 n 0000024355 00000 n 0000372746 00000 n 0000024396 00000 n 0000026493 00000 n 0000026515 00000 n 0000063707 00000 n 0000063887 00000 n 0000372894 00000 n 0000063928 00000 n 0000066809 00000 n 0000066831 00000 n 0000067011 00000 n 0000373042 00000 n 0000067052 00000 n 0000069433 00000 n 0000069455 00000 n 0000069635 00000 n 0000373190 00000 n 0000069676 00000 n 0000072629 00000 n 0000072651 00000 n 0000072831 00000 n 0000373357 00000 n 0000072872 00000 n 0000075297 00000 n 0000075319 00000 n 0000075499 00000 n 0000373505 00000 n 0000075540 00000 n 0000078270 00000 n 0000078292 00000 n 0000078472 00000 n 0000373653 00000 n 0000078513 00000 n 0000081198 00000 n 0000081220 00000 n 0000081400 00000 n 0000373801 00000 n 0000081441 00000 n 0000085761 00000 n 0000085783 00000 n 0000085963 00000 n 0000373949 00000 n 0000086004 00000 n 0000091091 00000 n 0000091113 00000 n 0000091293 00000 n 0000374097 00000 n 0000091334 00000 n 0000094762 00000 n 0000094784 00000 n 0000094964 00000 n 0000374264 00000 n 0000095005 00000 n 0000097782 00000 n 0000097804 00000 n 0000097984 00000 n 0000374412 00000 n 0000098025 00000 n 0000101404 00000 n 0000101426 00000 n 0000101607 00000 n 0000374595 00000 n 0000101649 00000 n 0000104636 00000 n 0000104659 00000 n 0000104840 00000 n 0000374745 00000 n 0000104882 00000 n 0000106189 00000 n 0000106212 00000 n 0000106393 00000 n 0000375146 00000 n 0000375395 00000 n 0000375644 00000 n 0000375854 00000 n 0000376062 00000 n 0000376227 00000 n 0000376400 00000 n 0000376567 00000 n 0000376730 00000 n 0000376915 00000 n 0000377076 00000 n 0000377216 00000 n 0000377401 00000 n 0000377564 00000 n 0000377739 00000 n 0000106435 00000 n 0000209374 00000 n 0000374895 00000 n 0000209399 00000 n 0000210922 00000 n 0000210945 00000 n 0000211139 00000 n 0000211431 00000 n 0000211595 00000 n 0000218435 00000 n 0000218458 00000 n 0000218663 00000 n 0000219033 00000 n 0000219271 00000 n 0000233124 00000 n 0000233148 00000 n 0000233346 00000 n 0000233834 00000 n 0000234179 00000 n 0000238528 00000 n 0000238551 00000 n 0000238750 00000 n 0000239071 00000 n 0000239260 00000 n 0000256897 00000 n 0000256921 00000 n 0000257118 00000 n 0000257800 00000 n 0000258313 00000 n 0000270353 00000 n 0000270377 00000 n 0000270585 00000 n 0000271033 00000 n 0000271342 00000 n 0000286063 00000 n 0000286087 00000 n 0000286289 00000 n 0000286855 00000 n 0000287267 00000 n 0000327195 00000 n 0000327219 00000 n 0000327415 00000 n 0000328361 00000 n 0000329330 00000 n 0000368496 00000 n 0000368520 00000 n 0000368715 00000 n 0000369661 00000 n 0000370629 00000 n 0000370753 00000 n 0000377916 00000 n 0000378016 00000 n trailer < ] /DocChecksum /AC3725C0C33D449196D2E5E3A378B4F2 /AdditionalStreams [/application#2Fvnd#2Eoasis#2Eopendocument#2Etext 127 0 R ] >> startxref 378290 %%EOF ExaML-3.0.21/parser/000077500000000000000000000000001330315463200140375ustar00rootroot00000000000000ExaML-3.0.21/parser/Makefile.SSE3.gcc000066400000000000000000000022041330315463200167440ustar00rootroot00000000000000# Makefile August 2006 by Alexandros Stamatakis # Makefile cleanup October 2006, Courtesy of Peter Cordes CC = gcc CFLAGS = -fomit-frame-pointer -O2 -D_GNU_SOURCE -msse -funroll-loops #-Wall -Wunused-parameter -Wredundant-decls -Wreturn-type -Wswitch-default -Wunused-value -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wimport -Wunused -Wunused-function -Wunused-label -Wno-int-to-pointer-cast -Wbad-function-cast -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wstrict-prototypes -Wpointer-sign -Wextra -Wredundant-decls -Wunused -Wunused-function -Wunused-parameter -Wunused-value -Wunused-variable -Wformat -Wformat-nonliteral -Wparentheses -Wsequence-point -Wuninitialized -Wundef -Wbad-function-cast LIBRARIES = -lm RM = rm -f objs = axml.o parsePartitions.o all : clean parse-examl GLOBAL_DEPS = axml.h globalVariables.h ../versionHeader/version.h parse-examl : $(objs) $(CC) -o parse-examl $(objs) $(LIBRARIES) axml.o : axml.c $(GLOBAL_DEPS) parsePartitions.o : parsePartitions.c $(GLOBAL_DEPS) clean : $(RM) *.o parse-examl dev : parse-examl ExaML-3.0.21/parser/Makefile.check.warnings000066400000000000000000000022041330315463200204000ustar00rootroot00000000000000# Makefile August 2006 by Alexandros Stamatakis # Makefile cleanup October 2006, Courtesy of Peter Cordes CC = clang CFLAGS = -fomit-frame-pointer -O2 -D_GNU_SOURCE -msse -funroll-loops -Weverything -Wno-padded #-Wall -Wunused-parameter -Wredundant-decls -Wreturn-type -Wswitch-default -Wunused-value -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wimport -Wunused -Wunused-function -Wunused-label -Wno-int-to-pointer-cast -Wbad-function-cast -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wstrict-prototypes -Wpointer-sign -Wextra -Wredundant-decls -Wunused -Wunused-function -Wunused-parameter -Wunused-value -Wunused-variable -Wformat -Wformat-nonliteral -Wparentheses -Wsequence-point -Wuninitialized -Wundef -Wbad-function-cast LIBRARIES = -lm RM = rm -f objs = axml.o parsePartitions.o all : parse-examl GLOBAL_DEPS = axml.h globalVariables.h ../versionHeader/version.h parse-examl : $(objs) $(CC) -o parse-examl $(objs) $(LIBRARIES) axml.o : axml.c $(GLOBAL_DEPS) parsePartitions.o : parsePartitions.c $(GLOBAL_DEPS) clean : $(RM) *.o parse-examl ExaML-3.0.21/parser/USAGE000066400000000000000000000001001330315463200146150ustar00rootroot00000000000000./parser -m DNA -s ../testdata/49 -q ../testdata/49.model -n 49 ExaML-3.0.21/parser/axml.c000066400000000000000000001746331330315463200151620ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifdef WIN32 #include #endif #ifndef WIN32 #include #include #include #include #endif #include #include #include #include #include #include #include #include #ifdef _FINE_GRAIN_MPI #include #endif #ifdef _USE_PTHREADS #include #endif #if ! (defined(__ppc) || defined(__powerpc__) || defined(PPC)) #include /* special bug fix, enforces denormalized numbers to be flushed to zero, without this program is a tiny bit faster though. #include #define MM_DAZ_MASK 0x0040 #define MM_DAZ_ON 0x0040 #define MM_DAZ_OFF 0x0000 */ #endif #include "axml.h" #include "globalVariables.h" #define _PORTABLE_PTHREADS /***************** UTILITY FUNCTIONS **************************/ void myBinFwrite(const void *ptr, size_t size, size_t nmemb) { size_t bytes_written = fwrite(ptr, size, nmemb, byteFile); assert(bytes_written == nmemb); } void *malloc_aligned(size_t size) { void *ptr = (void *)NULL; int res; #if defined (__APPLE__) /* presumably malloc on MACs always returns a 16-byte aligned pointer */ ptr = malloc(size); if(ptr == (void*)NULL) assert(0); #ifdef __AVX assert(0); #endif #else res = posix_memalign( &ptr, BYTE_ALIGNMENT, size ); if(res != 0) assert(0); #endif return ptr; } void printBothOpen(const char* format, ... ) { FILE *f = myfopen(infoFileName, "ab"); va_list args; va_start(args, format); vfprintf(f, format, args ); va_end(args); va_start(args, format); vprintf(format, args ); va_end(args); fclose(f); } void printBothOpenMPI(const char* format, ... ) { #ifdef _WAYNE_MPI if(processID == 0) #endif { FILE *f = myfopen(infoFileName, "ab"); va_list args; va_start(args, format); vfprintf(f, format, args ); va_end(args); va_start(args, format); vprintf(format, args ); va_end(args); fclose(f); } } boolean getSmoothFreqs(int dataType) { assert(MIN_MODEL < dataType && dataType < MAX_MODEL); return pLengths[dataType].smoothFrequencies; } const unsigned int *getBitVector(int dataType) { assert(MIN_MODEL < dataType && dataType < MAX_MODEL); return pLengths[dataType].bitVector; } int getStates(int dataType) { assert(MIN_MODEL < dataType && dataType < MAX_MODEL); return pLengths[dataType].states; } unsigned char getUndetermined(int dataType) { assert(MIN_MODEL < dataType && dataType < MAX_MODEL); return pLengths[dataType].undetermined; } char getInverseMeaning(int dataType, unsigned char state) { assert(MIN_MODEL < dataType && dataType < MAX_MODEL); return pLengths[dataType].inverseMeaning[state]; } partitionLengths *getPartitionLengths(pInfo *p) { int dataType = p->dataType, states = p->states, tipLength = p->maxTipStates; assert(states != -1 && tipLength != -1); assert(MIN_MODEL < dataType && dataType < MAX_MODEL); pLength.leftLength = pLength.rightLength = states * states; pLength.eignLength = states; pLength.evLength = states * states; pLength.eiLength = states * states; pLength.substRatesLength = (states * states - states) / 2; pLength.frequenciesLength = states; pLength.tipVectorLength = tipLength * states; pLength.symmetryVectorLength = (states * states - states) / 2; pLength.frequencyGroupingLength = states; pLength.nonGTR = FALSE; pLength.optimizeBaseFrequencies = FALSE; return (&pLengths[dataType]); } double gettime(void) { #ifdef WIN32 time_t tp; struct tm localtm; tp = time(NULL); localtm = *localtime(&tp); return 60.0*localtm.tm_min + localtm.tm_sec; #else struct timeval ttime; gettimeofday(&ttime , NULL); return ttime.tv_sec + ttime.tv_usec * 0.000001; #endif } double randum (long *seed) { long sum, mult0, mult1, seed0, seed1, seed2, newseed0, newseed1, newseed2; double res; mult0 = 1549; seed0 = *seed & 4095; sum = mult0 * seed0; newseed0 = sum & 4095; sum >>= 12; seed1 = (*seed >> 12) & 4095; mult1 = 406; sum += mult0 * seed1 + mult1 * seed0; newseed1 = sum & 4095; sum >>= 12; seed2 = (*seed >> 24) & 255; sum += mult0 * seed2 + mult1 * seed1; newseed2 = sum & 255; *seed = newseed2 << 24 | newseed1 << 12 | newseed0; res = 0.00390625 * (newseed2 + 0.000244140625 * (newseed1 + 0.000244140625 * newseed0)); return res; } static int filexists(char *filename) { FILE *fp; int res; fp = fopen(filename,"rb"); if(fp) { res = 1; fclose(fp); } else res = 0; return res; } FILE *myfopen(const char *path, const char *mode) { FILE *fp = fopen(path, mode); if(strcmp(mode,"r") == 0 || strcmp(mode,"rb") == 0) { if(fp) return fp; else { if(processID == 0) printf("\n Error: the file %s you want to open for reading does not exist, exiting ...\n\n", path); errorExit(-1); return (FILE *)NULL; } } else { if(fp) return fp; else { if(processID == 0) printf("\n Error: the file %s you want to open for writing or appending can not be opened [mode: %s], exiting ...\n\n", path, mode); errorExit(-1); return (FILE *)NULL; } } } /********************* END UTILITY FUNCTIONS ********************/ /******************************some functions for the likelihood computation ****************************/ /***********************reading and initializing input ******************/ static void getnums (rawdata *rdta) { if (fscanf(INFILE, "%d %d", & rdta->numsp, & rdta->sites) != 2) { if(processID == 0) printf("\n Error: problem reading number of species and sites\n\n"); errorExit(-1); } if (rdta->numsp < 4) { if(processID == 0) printf("\n Error: too few species\n\n"); errorExit(-1); } if (rdta->sites < 1) { if(processID == 0) printf("\n Error: too few sites\n\n"); errorExit(-1); } return; } boolean whitechar (int ch) { return (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r'); } static void uppercase (int *chptr) { int ch; ch = *chptr; if ((ch >= 'a' && ch <= 'i') || (ch >= 'j' && ch <= 'r') || (ch >= 's' && ch <= 'z')) *chptr = ch + 'A' - 'a'; } static void getyspace (rawdata *rdta) { size_t size = 4 * ((size_t)(rdta->sites / 4 + 1)); int i; unsigned char *y0; rdta->y = (unsigned char **) malloc(((size_t)rdta->numsp + 1) * sizeof(unsigned char *)); assert(rdta->y); y0 = (unsigned char *)calloc(((size_t)(rdta->numsp + 1)) * size, sizeof(unsigned char)); /* printf("Raw alignment data Assigning %Zu bytes\n", ((size_t)(rdta->numsp + 1)) * size * sizeof(unsigned char)); */ assert(y0); rdta->y0 = y0; for (i = 0; i <= rdta->numsp; i++) { rdta->y[i] = y0; y0 += size; } return; } static boolean setupTree (tree *tr, analdef *adef) { nodeptr p0; int tips, inter; if(!adef->readTaxaOnly) { /*tr->bigCutoff = FALSE;*/ tr->patternPosition = (int*)NULL; tr->columnPosition = (int*)NULL; /*tr->maxCategories = MAX(4, adef->categories);*/ /*tr->partitionContributions = (double *)malloc(sizeof(double) * tr->NumberOfModels); for(i = 0; i < tr->NumberOfModels; i++) tr->partitionContributions[i] = -1.0; tr->perPartitionLH = (double *)malloc(sizeof(double) * tr->NumberOfModels); for(i = 0; i < tr->NumberOfModels; i++) { tr->perPartitionLH[i] = 0.0; } if(adef->grouping) tr->grouped = TRUE; else tr->grouped = FALSE; if(adef->constraint) tr->constrained = TRUE; else tr->constrained = FALSE; tr->treeID = 0;*/ } tips = tr->mxtips; inter = tr->mxtips - 1; if(!adef->readTaxaOnly) { tr->yVector = (unsigned char **) malloc(((size_t)tr->mxtips + 1) * sizeof(unsigned char *)); /* tr->fracchanges = (double *)malloc(tr->NumberOfModels * sizeof(double)); tr->likelihoods = (double *)malloc(adef->multipleRuns * sizeof(double));*/ } /*tr->numberOfTrees = -1; tr->treeStringLength = tr->mxtips * (nmlngth+128) + 256 + tr->mxtips * 2; tr->tree_string = (char*)calloc(tr->treeStringLength, sizeof(char)); tr->tree0 = (char*)calloc(tr->treeStringLength, sizeof(char)); tr->tree1 = (char*)calloc(tr->treeStringLength, sizeof(char));*/ /*TODO, must that be so long ?*/ if(!adef->readTaxaOnly) { /*tr->td[0].count = 0; tr->td[0].ti = (traversalInfo *)malloc(sizeof(traversalInfo) * tr->mxtips); tr->td[0].executeModel = (boolean *)malloc(sizeof(boolean) * tr->NumberOfModels); tr->td[0].parameterValues = (double *)malloc(sizeof(double) * tr->NumberOfModels); for(i = 0; i < tr->NumberOfModels; i++) tr->fracchanges[i] = -1.0; tr->fracchange = -1.0; tr->constraintVector = (int *)malloc((2 * tr->mxtips) * sizeof(int));*/ tr->nameList = (char **)malloc(sizeof(char *) * ((size_t)tips + 1)); } if (!(p0 = (nodeptr) malloc(((size_t)tips + 3 * (size_t)inter) * sizeof(node)))) { printf("\n Error: unable to obtain sufficient tree memory\n\n"); return FALSE; } tr->vLength = 0; tr->h = (hashtable*)NULL; return TRUE; } static void checkTaxonName(char *buffer, int len) { int i; for(i = 0; i < len - 1; i++) { boolean valid; switch(buffer[i]) { case '\0': case '\t': case '\n': case '\r': case ' ': case ':': case ',': case '(': case ')': case ';': case '[': case ']': valid = FALSE; break; default: valid = TRUE; } if(!valid) { printf("\n Error: Taxon Name \"%s\" is invalid at position %d, it contains illegal character %c\n\n", buffer, i, buffer[i]); printf(" Illegal characters in taxon-names are: tabulators, carriage returns, spaces, \":\", \",\", \")\", \"(\", \";\", \"]\", \"[\"\n"); printf(" Exiting\n"); exit(-1); } } assert(buffer[len - 1] == '\0'); } static boolean getdata(analdef *adef, rawdata *rdta, tree *tr) { int i, j, basesread, basesnew, ch, my_i, meaning, len, meaningAA[256], meaningDNA[256], meaningBINARY[256], meaningGeneric32[256], meaningGeneric64[256]; boolean allread, firstpass; char buffer[nmlngth + 2]; unsigned char genericChars32[32] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V'}; unsigned long total = 0, gaps = 0; for (i = 0; i < 256; i++) { meaningAA[i] = -1; meaningDNA[i] = -1; meaningBINARY[i] = -1; meaningGeneric32[i] = -1; meaningGeneric64[i] = -1; } /* generic 32 data */ for(i = 0; i < 32; i++) meaningGeneric32[genericChars32[i]] = i; meaningGeneric32['-'] = getUndetermined(GENERIC_32); meaningGeneric32['?'] = getUndetermined(GENERIC_32); /* AA data */ meaningAA['A'] = 0; /* alanine */ meaningAA['R'] = 1; /* arginine */ meaningAA['N'] = 2; /* asparagine*/ meaningAA['D'] = 3; /* aspartic */ meaningAA['C'] = 4; /* cysteine */ meaningAA['Q'] = 5; /* glutamine */ meaningAA['E'] = 6; /* glutamic */ meaningAA['G'] = 7; /* glycine */ meaningAA['H'] = 8; /* histidine */ meaningAA['I'] = 9; /* isoleucine */ meaningAA['L'] = 10; /* leucine */ meaningAA['K'] = 11; /* lysine */ meaningAA['M'] = 12; /* methionine */ meaningAA['F'] = 13; /* phenylalanine */ meaningAA['P'] = 14; /* proline */ meaningAA['S'] = 15; /* serine */ meaningAA['T'] = 16; /* threonine */ meaningAA['W'] = 17; /* tryptophan */ meaningAA['Y'] = 18; /* tyrosine */ meaningAA['V'] = 19; /* valine */ meaningAA['B'] = 20; /* asparagine, aspartic 2 and 3*/ meaningAA['Z'] = 21; /*21 glutamine glutamic 5 and 6*/ meaningAA['X'] = meaningAA['?'] = meaningAA['*'] = meaningAA['-'] = getUndetermined(AA_DATA); /* DNA data */ meaningDNA['A'] = 1; meaningDNA['B'] = 14; meaningDNA['C'] = 2; meaningDNA['D'] = 13; meaningDNA['G'] = 4; meaningDNA['H'] = 11; meaningDNA['K'] = 12; meaningDNA['M'] = 3; meaningDNA['R'] = 5; meaningDNA['S'] = 6; meaningDNA['T'] = 8; meaningDNA['U'] = 8; meaningDNA['V'] = 7; meaningDNA['W'] = 9; meaningDNA['Y'] = 10; meaningDNA['N'] = meaningDNA['O'] = meaningDNA['X'] = meaningDNA['-'] = meaningDNA['?'] = getUndetermined(DNA_DATA); /* BINARY DATA */ meaningBINARY['0'] = 1; meaningBINARY['1'] = 2; meaningBINARY['-'] = meaningBINARY['?'] = getUndetermined(BINARY_DATA); /*******************************************************************/ basesread = basesnew = 0; allread = FALSE; firstpass = TRUE; ch = ' '; while (! allread) { for (i = 1; i <= tr->mxtips; i++) { if (firstpass) { ch = getc(INFILE); while(ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r') ch = getc(INFILE); my_i = 0; do { buffer[my_i] = (char)ch; ch = getc(INFILE); my_i++; if(my_i >= nmlngth) { if(processID == 0) { printf("Taxon Name to long at taxon %d, adapt constant nmlngth in\n", i); printf("axml.h, current setting %d\n", nmlngth); } errorExit(-1); } } while(ch != ' ' && ch != '\n' && ch != '\t' && ch != '\r'); while(ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r') ch = getc(INFILE); ungetc(ch, INFILE); buffer[my_i] = '\0'; len = (int)strlen(buffer) + 1; checkTaxonName(buffer, len); tr->nameList[i] = (char *)malloc(sizeof(char) * (size_t)len); strcpy(tr->nameList[i], buffer); } j = basesread; while ((j < rdta->sites) && ((ch = getc(INFILE)) != EOF) && (ch != '\n') && (ch != '\r')) { uppercase(& ch); assert(tr->dataVector[j + 1] != -1); switch(tr->dataVector[j + 1]) { case BINARY_DATA: meaning = meaningBINARY[ch]; break; case DNA_DATA: case SECONDARY_DATA: case SECONDARY_DATA_6: case SECONDARY_DATA_7: /* still dealing with DNA/RNA here, hence just act if as they where DNA characters corresponding column merging for sec struct models will take place later */ meaning = meaningDNA[ch]; break; case AA_DATA: meaning = meaningAA[ch]; break; case GENERIC_32: meaning = meaningGeneric32[ch]; break; case GENERIC_64: meaning = meaningGeneric64[ch]; break; default: assert(0); } if (meaning != -1) { j++; rdta->y[i][j] = (unsigned char)ch; } else { if(!whitechar(ch)) { printf("\n Error: bad base (%c) at site %d of sequence %d\n\n", ch, j + 1, i); return FALSE; } } } if (ch == EOF) { printf("\n Error: end-of-file at site %d of sequence %d\n\n", j + 1, i); return FALSE; } if (! firstpass && (j == basesread)) i--; else { if (i == 1) basesnew = j; else if (j != basesnew) { printf("\n Error: sequences out of alignment\n"); printf("%d (instead of %d) residues read in sequence %d %s\n", j - basesread, basesnew - basesread, i, tr->nameList[i]); return FALSE; } } while (ch != '\n' && ch != EOF && ch != '\r') ch = getc(INFILE); /* flush line *//* PC-LINEBREAK*/ } firstpass = FALSE; basesread = basesnew; allread = (basesread >= rdta->sites); } for(j = 1; j <= tr->mxtips; j++) for(i = 1; i <= rdta->sites; i++) { assert(tr->dataVector[i] != -1); switch(tr->dataVector[i]) { case BINARY_DATA: meaning = meaningBINARY[rdta->y[j][i]]; if(meaning == getUndetermined(BINARY_DATA)) gaps++; break; case SECONDARY_DATA: case SECONDARY_DATA_6: case SECONDARY_DATA_7: assert(tr->secondaryStructurePairs[i - 1] != -1); assert(i - 1 == tr->secondaryStructurePairs[tr->secondaryStructurePairs[i - 1]]); /* don't worry too much about undetermined column count here for sec-struct, just count DNA/RNA gaps here and worry about the rest later-on, falling through to DNA again :-) */ case DNA_DATA: meaning = meaningDNA[rdta->y[j][i]]; if(meaning == getUndetermined(DNA_DATA)) gaps++; break; case AA_DATA: meaning = meaningAA[rdta->y[j][i]]; if(meaning == getUndetermined(AA_DATA)) gaps++; break; case GENERIC_32: meaning = meaningGeneric32[rdta->y[j][i]]; if(meaning == getUndetermined(GENERIC_32)) gaps++; break; case GENERIC_64: meaning = meaningGeneric64[rdta->y[j][i]]; if(meaning == getUndetermined(GENERIC_64)) gaps++; break; default: assert(0); } total++; rdta->y[j][i] = (unsigned char)meaning; } adef->gapyness = (double)gaps / (double)total; /*myBinFwrite(&(adef->gapyness), sizeof(double), 1);*/ printf("gappyness: %f\n", adef->gapyness); /*for(i = 1; i <= tr->mxtips; i++) { int len = strlen(tr->nameList[i]) + 1; myBinFwrite(&len, sizeof(int), 1); myBinFwrite(tr->nameList[i], sizeof(char), len); printf("%d %s\n", len, tr->nameList[i]); } */ return TRUE; } static void inputweights (rawdata *rdta) { int i, w, fres; FILE *weightFile; int *wv = (int *)malloc(sizeof(int) * (size_t)rdta->sites); weightFile = myfopen(weightFileName, "rb"); i = 0; while((fres = fscanf(weightFile,"%d", &w)) != EOF) { if(!fres) { if(processID == 0) printf("error reading weight file probably encountered a non-integer weight value\n"); errorExit(-1); } wv[i] = w; i++; } if(i != rdta->sites) { if(processID == 0) printf("number %d of weights not equal to number %d of alignment columns\n", i, rdta->sites); errorExit(-1); } for(i = 1; i <= rdta->sites; i++) rdta->wgt[i] = wv[i - 1]; fclose(weightFile); free(wv); } static hashNumberType hashString(char *p, hashNumberType tableSize) { hashNumberType h = 0; for(; *p; p++) h = 31 * h + (hashNumberType)*p; return (h % tableSize); } static void addword(char *s, stringHashtable *h, int nodeNumber) { hashNumberType position = hashString(s, h->tableSize); stringEntry *p = h->table[position]; for(; p!= NULL; p = p->next) { if(strcmp(s, p->word) == 0) return; } p = (stringEntry *)malloc(sizeof(stringEntry)); assert(p); p->nodeNumber = nodeNumber; p->word = (char *)malloc((strlen(s) + 1) * sizeof(char)); strcpy(p->word, s); p->next = h->table[position]; h->table[position] = p; } static stringHashtable *initStringHashTable(hashNumberType n) { /* init with primes */ static const hashNumberType initTable[] = {53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; /* init with powers of two static const hashNumberType initTable[] = {64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648U}; */ stringHashtable *h = (stringHashtable*)malloc(sizeof(stringHashtable)); hashNumberType tableSize, i, primeTableLength = sizeof(initTable)/sizeof(initTable[0]), maxSize = (hashNumberType)-1; assert(n <= maxSize); i = 0; while(initTable[i] < n && i < primeTableLength) i++; assert(i < primeTableLength); tableSize = initTable[i]; h->table = (stringEntry**)calloc(tableSize, sizeof(stringEntry*)); h->tableSize = tableSize; return h; } static void getinput(analdef *adef, rawdata *rdta, cruncheddata *cdta, tree *tr) { int i; INFILE = myfopen(seq_file, "rb"); getnums(rdta); /*myBinFwrite(&(rdta->sites), sizeof(int), 1); myBinFwrite(&(rdta->numsp), sizeof(int), 1); printf("%d %d\n", rdta->sites, rdta->numsp);*/ tr->mxtips = rdta->numsp; rdta->wgt = (int *) malloc(((size_t)rdta->sites + 1) * sizeof(int)); cdta->alias = (int *) malloc(((size_t)rdta->sites + 1) * sizeof(int)); cdta->aliaswgt = (int *) malloc(((size_t)rdta->sites + 1) * sizeof(int)); tr->model = (int *) calloc(((size_t)rdta->sites + 1), sizeof(int)); tr->initialDataVector = (int *) malloc(((size_t)rdta->sites + 1) * sizeof(int)); tr->extendedDataVector = (int *) malloc(((size_t)rdta->sites + 1) * sizeof(int)); if(!adef->useWeightFile) { for (i = 1; i <= rdta->sites; i++) rdta->wgt[i] = 1; } else { assert(!adef->useSecondaryStructure); inputweights(rdta); } if(adef->useMultipleModel) { int ref; parsePartitions(adef, rdta, tr); for(i = 1; i <= rdta->sites; i++) { ref = tr->model[i]; tr->initialDataVector[i] = tr->initialPartitionData[ref].dataType; } } else { int dataType = -1; tr->initialPartitionData = (pInfo*)malloc(sizeof(pInfo)); tr->initialPartitionData->optimizeBaseFrequencies = FALSE; tr->initialPartitionData[0].partitionName = (char*)malloc(128 * sizeof(char)); strcpy(tr->initialPartitionData[0].partitionName, "No Name Provided"); tr->initialPartitionData[0].protModels = adef->proteinMatrix; tr->initialPartitionData[0].protFreqs = adef->protEmpiricalFreqs; tr->NumberOfModels = 1; if(adef->model == M_PROTCAT || adef->model == M_PROTGAMMA) dataType = AA_DATA; if(adef->model == M_GTRCAT || adef->model == M_GTRGAMMA) dataType = DNA_DATA; if(adef->model == M_BINCAT || adef->model == M_BINGAMMA) dataType = BINARY_DATA; if(adef->model == M_32CAT || adef->model == M_32GAMMA) dataType = GENERIC_32; if(adef->model == M_64CAT || adef->model == M_64GAMMA) dataType = GENERIC_64; assert(dataType == BINARY_DATA || dataType == DNA_DATA || dataType == AA_DATA || dataType == GENERIC_32 || dataType == GENERIC_64); tr->initialPartitionData[0].dataType = dataType; for(i = 0; i <= rdta->sites; i++) { tr->initialDataVector[i] = dataType; tr->model[i] = 0; } } if(adef->useSecondaryStructure) { memcpy(tr->extendedDataVector, tr->initialDataVector, ((size_t)rdta->sites + 1) * sizeof(int)); tr->extendedPartitionData =(pInfo*)malloc(sizeof(pInfo) * (size_t)tr->NumberOfModels); for(i = 0; i < tr->NumberOfModels; i++) { tr->extendedPartitionData[i].partitionName = (char*)malloc((strlen(tr->initialPartitionData[i].partitionName) + 1) * sizeof(char)); strcpy(tr->extendedPartitionData[i].partitionName, tr->initialPartitionData[i].partitionName); tr->extendedPartitionData[i].dataType = tr->initialPartitionData[i].dataType; tr->extendedPartitionData[i].protModels = tr->initialPartitionData[i].protModels; tr->extendedPartitionData[i].protFreqs = tr->initialPartitionData[i].protFreqs; } parseSecondaryStructure(tr, adef, rdta->sites); tr->dataVector = tr->extendedDataVector; tr->partitionData = tr->extendedPartitionData; } else { tr->dataVector = tr->initialDataVector; tr->partitionData = tr->initialPartitionData; } getyspace(rdta); setupTree(tr, adef); if(!getdata(adef, rdta, tr)) { printf("Problem reading alignment file \n"); errorExit(1); } tr->nameHash = initStringHashTable(10 * (size_t)tr->mxtips); for(i = 1; i <= tr->mxtips; i++) addword(tr->nameList[i], tr->nameHash, i); fclose(INFILE); } static unsigned char buildStates(int secModel, unsigned char v1, unsigned char v2) { unsigned char new = 0; switch(secModel) { case SECONDARY_DATA: new = v1; new = new << 4; new = new | v2; break; case SECONDARY_DATA_6: { int meaningDNA[256], i; const unsigned char allowedStates[6][2] = {{'A','T'}, {'C', 'G'}, {'G', 'C'}, {'G','T'}, {'T', 'A'}, {'T', 'G'}}; const unsigned char finalBinaryStates[6] = {1, 2, 4, 8, 16, 32}; unsigned char intermediateBinaryStates[6]; int length = 6; for(i = 0; i < 256; i++) meaningDNA[i] = -1; meaningDNA['A'] = 1; meaningDNA['B'] = 14; meaningDNA['C'] = 2; meaningDNA['D'] = 13; meaningDNA['G'] = 4; meaningDNA['H'] = 11; meaningDNA['K'] = 12; meaningDNA['M'] = 3; meaningDNA['N'] = 15; meaningDNA['O'] = 15; meaningDNA['R'] = 5; meaningDNA['S'] = 6; meaningDNA['T'] = 8; meaningDNA['U'] = 8; meaningDNA['V'] = 7; meaningDNA['W'] = 9; meaningDNA['X'] = 15; meaningDNA['Y'] = 10; meaningDNA['-'] = 15; meaningDNA['?'] = 15; for(i = 0; i < length; i++) { unsigned char n1 = meaningDNA[allowedStates[i][0]]; unsigned char n2 = meaningDNA[allowedStates[i][1]]; new = n1; new = new << 4; new = new | n2; intermediateBinaryStates[i] = new; } new = v1; new = new << 4; new = new | v2; for(i = 0; i < length; i++) { if(new == intermediateBinaryStates[i]) break; } if(i < length) new = finalBinaryStates[i]; else { new = 0; for(i = 0; i < length; i++) { if(v1 & meaningDNA[allowedStates[i][0]]) { /*printf("Adding %c%c\n", allowedStates[i][0], allowedStates[i][1]);*/ new |= finalBinaryStates[i]; } if(v2 & meaningDNA[allowedStates[i][1]]) { /*printf("Adding %c%c\n", allowedStates[i][0], allowedStates[i][1]);*/ new |= finalBinaryStates[i]; } } } } break; case SECONDARY_DATA_7: { int meaningDNA[256], i; const unsigned char allowedStates[6][2] = {{'A','T'}, {'C', 'G'}, {'G', 'C'}, {'G','T'}, {'T', 'A'}, {'T', 'G'}}; const unsigned char finalBinaryStates[7] = {1, 2, 4, 8, 16, 32, 64}; unsigned char intermediateBinaryStates[7]; for(i = 0; i < 256; i++) meaningDNA[i] = -1; meaningDNA['A'] = 1; meaningDNA['B'] = 14; meaningDNA['C'] = 2; meaningDNA['D'] = 13; meaningDNA['G'] = 4; meaningDNA['H'] = 11; meaningDNA['K'] = 12; meaningDNA['M'] = 3; meaningDNA['N'] = 15; meaningDNA['O'] = 15; meaningDNA['R'] = 5; meaningDNA['S'] = 6; meaningDNA['T'] = 8; meaningDNA['U'] = 8; meaningDNA['V'] = 7; meaningDNA['W'] = 9; meaningDNA['X'] = 15; meaningDNA['Y'] = 10; meaningDNA['-'] = 15; meaningDNA['?'] = 15; for(i = 0; i < 6; i++) { unsigned char n1 = meaningDNA[allowedStates[i][0]]; unsigned char n2 = meaningDNA[allowedStates[i][1]]; new = n1; new = new << 4; new = new | n2; intermediateBinaryStates[i] = new; } new = v1; new = new << 4; new = new | v2; for(i = 0; i < 6; i++) { /* exact match */ if(new == intermediateBinaryStates[i]) break; } if(i < 6) new = finalBinaryStates[i]; else { /* distinguish between exact mismatches and partial mismatches */ for(i = 0; i < 6; i++) if((v1 & meaningDNA[allowedStates[i][0]]) && (v2 & meaningDNA[allowedStates[i][1]])) break; if(i < 6) { /* printf("partial mismatch\n"); */ new = 0; for(i = 0; i < 6; i++) { if((v1 & meaningDNA[allowedStates[i][0]]) && (v2 & meaningDNA[allowedStates[i][1]])) { /*printf("Adding %c%c\n", allowedStates[i][0], allowedStates[i][1]);*/ new |= finalBinaryStates[i]; } else new |= finalBinaryStates[6]; } } else new = finalBinaryStates[6]; } } break; default: assert(0); } return new; } static void adaptRdataToSecondary(tree *tr, rawdata *rdta) { int *alias = (int*)calloc((size_t)rdta->sites, sizeof(int)); int i, j, realPosition; for(i = 0; i < rdta->sites; i++) alias[i] = -1; for(i = 0, realPosition = 0; i < rdta->sites; i++) { int partner = tr->secondaryStructurePairs[i]; if(partner != -1) { assert(tr->dataVector[i+1] == SECONDARY_DATA || tr->dataVector[i+1] == SECONDARY_DATA_6 || tr->dataVector[i+1] == SECONDARY_DATA_7); if(i < partner) { for(j = 1; j <= rdta->numsp; j++) { unsigned char v1 = rdta->y[j][i+1]; unsigned char v2 = rdta->y[j][partner+1]; assert(i+1 < partner+1); rdta->y[j][i+1] = buildStates(tr->dataVector[i+1], v1, v2); } alias[realPosition] = i; realPosition++; } } else { alias[realPosition] = i; realPosition++; } } assert(rdta->sites - realPosition == tr->numberOfSecondaryColumns / 2); rdta->sites = realPosition; for(i = 0; i < rdta->sites; i++) { assert(alias[i] != -1); tr->model[i+1] = tr->model[alias[i]+1]; tr->dataVector[i+1] = tr->dataVector[alias[i]+1]; rdta->wgt[i+1] = rdta->wgt[alias[i]+1]; for(j = 1; j <= rdta->numsp; j++) rdta->y[j][i+1] = rdta->y[j][alias[i]+1]; } free(alias); } static void sitesort(rawdata *rdta, cruncheddata *cdta, tree *tr, analdef *adef) { int gap, i, j, jj, jg, k, n, nsp; int *index, *category = (int*)NULL; boolean flip, tied; unsigned char **data; if(adef->useSecondaryStructure) { assert(tr->NumberOfModels > 1 && adef->useMultipleModel); adaptRdataToSecondary(tr, rdta); } if(adef->useMultipleModel) category = tr->model; index = cdta->alias; data = rdta->y; n = rdta->sites; nsp = rdta->numsp; index[0] = -1; if(adef->compressPatterns) { for (gap = n / 2; gap > 0; gap /= 2) { for (i = gap + 1; i <= n; i++) { j = i - gap; do { jj = index[j]; jg = index[j+gap]; if(adef->useMultipleModel) { assert(category[jj] != -1 && category[jg] != -1); flip = (category[jj] > category[jg]); tied = (category[jj] == category[jg]); } else { flip = 0; tied = 1; } for (k = 1; (k <= nsp) && tied; k++) { flip = (data[k][jj] > data[k][jg]); tied = (data[k][jj] == data[k][jg]); } if (flip) { index[j] = jg; index[j+gap] = jj; j -= gap; } } while (flip && (j > 0)); } } } } static void sitecombcrunch (rawdata *rdta, cruncheddata *cdta, tree *tr, analdef *adef) { boolean tied; int i, sitei, j, sitej, k; int *aliasModel = (int*)NULL, *aliasSuperModel = (int*)NULL, undeterminedSites = 0; if(adef->useMultipleModel) { aliasSuperModel = (int*)malloc(sizeof(int) * ((size_t)rdta->sites + 1)); aliasModel = (int*)malloc(sizeof(int) * ((size_t)rdta->sites + 1)); } i = 0; cdta->alias[0] = cdta->alias[1]; cdta->aliaswgt[0] = 0; if(adef->mode == PER_SITE_LL) { assert(0); /* tr->patternPosition = (int*)malloc(sizeof(int) * rdta->sites); tr->columnPosition = (int*)malloc(sizeof(int) * rdta->sites); for(i = 0; i < rdta->sites; i++) { tr->patternPosition[i] = -1; tr->columnPosition[i] = -1; } */ } i = 0; for (j = 1; j <= rdta->sites; j++) { int allGap = TRUE; unsigned char undetermined; sitei = cdta->alias[i]; sitej = cdta->alias[j]; undetermined = getUndetermined(tr->dataVector[sitej]); for(k = 1; k <= rdta->numsp; k++) { if(rdta->y[k][sitej] != undetermined) { allGap = FALSE; break; } } if(allGap) undeterminedSites++; #ifdef _DEBUG_UNDET_REMOVAL if(allGap) printf("Skipping gap site %d\n", sitej); #endif if(!adef->compressPatterns) tied = 0; else { if(adef->useMultipleModel) { tied = (tr->model[sitei] == tr->model[sitej]); if(tied) assert(tr->dataVector[sitei] == tr->dataVector[sitej]); } else tied = 1; } for (k = 1; tied && (k <= rdta->numsp); k++) tied = (rdta->y[k][sitei] == rdta->y[k][sitej]); assert(!(tied && allGap)); if(tied && !allGap) { if(adef->mode == PER_SITE_LL) { tr->patternPosition[j - 1] = i; tr->columnPosition[j - 1] = sitej; /*printf("Pattern %d from column %d also at site %d\n", i, sitei, sitej);*/ } cdta->aliaswgt[i] += rdta->wgt[sitej]; if(adef->useMultipleModel) { aliasModel[i] = tr->model[sitej]; aliasSuperModel[i] = tr->dataVector[sitej]; } } else { if(!allGap) { if(cdta->aliaswgt[i] > 0) i++; if(adef->mode == PER_SITE_LL) { tr->patternPosition[j - 1] = i; tr->columnPosition[j - 1] = sitej; /*printf("Pattern %d is from cloumn %d\n", i, sitej);*/ } cdta->aliaswgt[i] = rdta->wgt[sitej]; cdta->alias[i] = sitej; if(adef->useMultipleModel) { aliasModel[i] = tr->model[sitej]; aliasSuperModel[i] = tr->dataVector[sitej]; } } } } cdta->endsite = (size_t)i; if (cdta->aliaswgt[i] > 0) cdta->endsite++; #ifdef _DEBUG_UNDET_REMOVAL printf("included sites: %d\n", cdta->endsite); #endif if(adef->mode == PER_SITE_LL) { assert(0); for(i = 0; i < rdta->sites; i++) { int p = tr->patternPosition[i]; int c = tr->columnPosition[i]; assert(p >= 0 && (size_t) p < cdta->endsite); assert(c >= 1 && c <= rdta->sites); } } if(adef->useMultipleModel) { for(i = 0; i <= rdta->sites; i++) { tr->model[i] = aliasModel[i]; tr->dataVector[i] = aliasSuperModel[i]; } } if(adef->useMultipleModel) { free(aliasModel); free(aliasSuperModel); } if(undeterminedSites > 0) printBothOpen("\nAlignment has %d completely undetermined sites that will be automatically removed from the binary alignment file\n\n", undeterminedSites); } static boolean makeweights (analdef *adef, rawdata *rdta, cruncheddata *cdta, tree *tr) { int i; for (i = 1; i <= rdta->sites; i++) cdta->alias[i] = i; sitesort(rdta, cdta, tr, adef); sitecombcrunch(rdta, cdta, tr, adef); return TRUE; } static boolean makevalues(rawdata *rdta, cruncheddata *cdta, tree *tr, analdef *adef) { int i, model, modelCounter; size_t j; unsigned char *y = (unsigned char *)malloc(((size_t)rdta->numsp) * ((size_t)cdta->endsite) * sizeof(unsigned char)); /* printf("compressed data Assigning %Zu bytes\n", ((size_t)rdta->numsp) * ((size_t)cdta->endsite) * sizeof(unsigned char)); */ { for (i = 1; i <= rdta->numsp; i++) for (j = 0; j < cdta->endsite; j++) y[(((size_t)(i - 1)) * ((size_t)cdta->endsite)) + j] = rdta->y[i][cdta->alias[j]]; /* printf("Free on raw data\n"); */ free(rdta->y0); free(rdta->y); } rdta->y0 = y; if(!adef->useMultipleModel) tr->NumberOfModels = 1; #ifdef _DEBUG_UNDET_REMOVAL for(i = 0; i < cdta->endsite; i++) printf("%d ", tr->model[i]); printf("\n"); #endif if(adef->useMultipleModel) { tr->partitionData[0].lower = 0; model = tr->model[0]; modelCounter = 0; i = 1; while((size_t) i < cdta->endsite) { if(tr->model[i] != model) { tr->partitionData[modelCounter].upper = (size_t)i; tr->partitionData[modelCounter + 1].lower = (size_t)i; model = tr->model[i]; modelCounter++; } i++; } if(modelCounter < tr->NumberOfModels - 1) { printf("\nYou specified %d partitions, but after parsing and pre-processing ExaML only found %d partitions\n", tr->NumberOfModels, modelCounter + 1); printf("Presumably one or more partitions vanished because they consisted entirely of undetermined characters.\n"); printf("Please fix your data!\n\n"); exit(-1); } tr->partitionData[tr->NumberOfModels - 1].upper = (size_t)cdta->endsite; for(i = 0; i < tr->NumberOfModels; i++) tr->partitionData[i].width = tr->partitionData[i].upper - tr->partitionData[i].lower; model = tr->model[0]; modelCounter = 0; tr->model[0] = modelCounter; i = 1; while((size_t) i < cdta->endsite) { if(tr->model[i] != model) { model = tr->model[i]; modelCounter++; tr->model[i] = modelCounter; } else tr->model[i] = modelCounter; i++; } } else { tr->partitionData[0].lower = 0; tr->partitionData[0].upper = (size_t)cdta->endsite; tr->partitionData[0].width = tr->partitionData[0].upper - tr->partitionData[0].lower; } tr->rdta = rdta; tr->cdta = cdta; tr->originalCrunchedLength = tr->cdta->endsite; for(i = 0; i < rdta->numsp; i++) tr->yVector[i + 1] = &(rdta->y0[(tr->originalCrunchedLength) * ((size_t)i)]); return TRUE; } static void initAdef(analdef *adef) { adef->useSecondaryStructure = FALSE; adef->bootstrapBranchLengths = FALSE; adef->model = M_GTRCAT; adef->max_rearrange = 21; adef->stepwidth = 5; adef->initial = adef->bestTrav = 10; adef->initialSet = FALSE; adef->restart = FALSE; adef->mode = BIG_RAPID_MODE; adef->categories = 25; adef->boot = 0; adef->rapidBoot = 0; adef->useWeightFile = FALSE; adef->checkpoints = 0; adef->startingTreeOnly = 0; adef->multipleRuns = 1; adef->useMultipleModel = FALSE; adef->likelihoodEpsilon = 0.1; adef->constraint = FALSE; adef->grouping = FALSE; adef->randomStartingTree = FALSE; adef->parsimonySeed = 0; adef->proteinMatrix = JTT; adef->protEmpiricalFreqs = 0; adef->useInvariant = FALSE; adef->permuteTreeoptimize = FALSE; adef->useInvariant = FALSE; adef->allInOne = FALSE; adef->likelihoodTest = FALSE; adef->perGeneBranchLengths = FALSE; adef->generateBS = FALSE; adef->bootStopping = FALSE; adef->gapyness = 0.0; adef->similarityFilterMode = 0; adef->useExcludeFile = FALSE; adef->userProteinModel = FALSE; adef->externalAAMatrix = (double*)NULL; adef->computeELW = FALSE; adef->computeDistance = FALSE; adef->thoroughInsertion = FALSE; adef->compressPatterns = TRUE; adef->readTaxaOnly = FALSE; adef->meshSearch = 0; adef->useCheckpoint = FALSE; adef->leaveDropMode = FALSE; adef->slidingWindowSize = 100; #ifdef _BAYESIAN adef->bayesian = FALSE; #endif } static int dataExists(char *model, analdef *adef) { /********** BINARY ********************/ if(strcmp(model, "BIN\0") == 0) { adef->model = M_BINGAMMA; return 1; } /*********** DNA **********************/ if(strcmp(model, "DNA\0") == 0) { adef->model = M_GTRGAMMA; return 1; } /*************** AA GTR ********************/ if(strcmp(model, "PROT\0") == 0) { adef->model = M_PROTGAMMA; return 1; } return 0; } /*********************************************************************************************/ static void printVersionInfo(void) { printf("\n\nThis is the parse-examl version %s released by Alexandros Stamatakis, Andre J. Aberer, and Alexey Kozlov in %s.\n\n", programVersion, programDate); } static void printREADME(void) { printVersionInfo(); printf("\n"); printf("\nTo report bugs use the RAxML google group\n"); printf("Please send us all input files, the exact invocation, details of the HW and operating system,\n"); printf("as well as all error messages printed to screen.\n\n\n"); printf("parse-examl\n"); printf(" -s sequenceFileName\n"); printf(" -n outputFileName\n"); printf(" -m substitutionModel\n"); printf(" [-c]\n"); printf(" [-q]\n"); printf(" [-h]\n"); printf("\n"); printf(" -m Model of Nucleotide or Amino Acid Substitution:\n"); printf("\n"); printf(" For Binary data use: BIN\n"); printf(" For DNA data use: DNA\n"); printf(" For AA data use: PROT\n"); printf("\n"); printf(" -c disable site pattern compression\n"); printf("\n"); printf(" -q Specify the file name which contains the assignment of models to alignment\n"); printf(" partitions for multiple models of substitution. For the syntax of this file\n"); printf(" please consult the manual.\n"); printf("\n"); printf(" -h Display this help message.\n"); printf("\n"); printf("\n\n\n\n"); } static int mygetopt(int argc, char **argv, char *opts, int *optind, char **optarg) { static int sp = 1; register int c; register char *cp; if(sp == 1) { if(*optind >= argc || argv[*optind][0] != '-' || argv[*optind][1] == '\0') { return -1; } } else { if(strcmp(argv[*optind], "--") == 0) { *optind = *optind + 1; return -1; } } c = argv[*optind][sp]; if(c == ':' || (cp=strchr(opts, c)) == 0) { if(argv[*optind][++sp] == '\0') { *optind = *optind + 1; sp = 1; } printf("\n Error: illegal option -- %c\n\n", c); return('?'); } if(*++cp == ':') { if(argv[*optind][sp+1] != '\0') { *optarg = &argv[*optind][sp+1]; *optind = *optind + 1; } else { *optind = *optind + 1; if(*optind >= argc) { if ( c != 'h') { sp = 1; printf("\n Error: option -- %c requires an argument\n\n", c); return('?'); } else return ( c ); } else { *optarg = argv[*optind]; *optind = *optind + 1; } } sp = 1; } else { if(argv[*optind][++sp] == '\0') { sp = 1; *optind = *optind + 1; } *optarg = 0; } return(c); } /*********************************************************************************************/ static void analyzeRunId(char id[128]) { int i = 0; while(id[i] != '\0') { if(i >= 128) { printf("\n Error: run id after \"-n\" is too long, it has %d characters please use a shorter one\n\n", i); assert(0); } if(id[i] == '/') { printf("\n Error character %c not allowed in run ID\n\n", id[i]); assert(0); } i++; } if(i == 0) { printf("\n Error: please provide a string for the run id after \"-n\" \n\n"); assert(0); } } static void get_args(int argc, char *argv[], analdef *adef, tree *tr) { boolean bad_opt =FALSE; char *optarg = (char*)NULL, model[2048] = ""; int optind = 1, c, nameSet = 0, alignmentSet = 0, modelSet = 0; run_id[0] = 0; seq_file[0] = 0; model[0] = 0; weightFileName[0] = 0; modelFileName[0] = 0; /*********** tr inits **************/ #ifdef _USE_PTHREADS NumberOfThreads = 0; #endif tr->bootStopCriterion = -1; tr->wcThreshold = 0.03; tr->doCutoff = TRUE; tr->secondaryStructureModel = SEC_16; /* default setting */ tr->searchConvergenceCriterion = FALSE; tr->catOnly = FALSE; tr->multiStateModel = GTR_MULTI_STATE; tr->useGappedImplementation = FALSE; tr->saveMemory = FALSE; /********* tr inits end*************/ while( !bad_opt && ( ( c = mygetopt(argc,argv,"q:s:n:m:hc", &optind, &optarg ) ) != -1 ) ) { switch(c) { case 'c': adef->compressPatterns = FALSE; break; case 'h': printREADME(); errorExit(-1); break; case 'q': strcpy(modelFileName,optarg); adef->useMultipleModel = TRUE; break; case 'n': strcpy(run_id,optarg); analyzeRunId(run_id); nameSet = 1; break; case 's': strcpy(seq_file, optarg); alignmentSet = 1; break; case 'm': strcpy(model,optarg); if(dataExists(model, adef) == 0) { printf("\n Error: model %s does not exist\n\n", model); errorExit(-1); } else modelSet = 1; break; default: errorExit(-1); } } if(!adef->useMultipleModel && !modelSet) { if(processID == 0) { printREADME(); printf("\n Error, you must specify a data type for unpartitioned alignment with the \"-m\" option\n\n"); } errorExit(-1); } if(!nameSet) { if(processID == 0) { printREADME(); printf("\n Error: please specify a name for this run with -n\n\n"); } errorExit(-1); } if(!alignmentSet) { if(processID == 0) { printREADME(); printf("\n Error: please specify an alignment for this run with -s\n\n"); } errorExit(-1); } strcat(infoFileName, "RAxML_info."); strcat(infoFileName, run_id); if(processID == 0) { int infoFileExists = 0; infoFileExists = filexists(infoFileName); if(infoFileExists) { printf("\n Error: output files with the run ID <%s> already exist... exiting\n\n", run_id); exit(-1); } } strcat(byteFileName, run_id); strcat(byteFileName, ".binary"); if(filexists(byteFileName)) { printf("\n Error: binary compressed file %s you want to generate already exists... exiting\n\n", byteFileName); exit(0); } byteFile = fopen(byteFileName, "wb"); if ( !byteFile ) printf("%s\n", byteFileName); return; } void errorExit(int e) { #ifdef _WAYNE_MPI MPI_Finalize(); #endif exit(e); } /***********************reading and initializing input ******************/ /********************PRINTING various INFO **************************************/ void getDataTypeString(tree *tr, int model, char typeOfData[1024]) { switch(tr->partitionData[model].dataType) { case AA_DATA: strcpy(typeOfData,"AA"); break; case DNA_DATA: strcpy(typeOfData,"DNA"); break; case BINARY_DATA: strcpy(typeOfData,"BINARY/MORPHOLOGICAL"); break; case SECONDARY_DATA: strcpy(typeOfData,"SECONDARY 16 STATE MODEL USING "); strcat(typeOfData, secondaryModelList[tr->secondaryStructureModel]); break; case SECONDARY_DATA_6: strcpy(typeOfData,"SECONDARY 6 STATE MODEL USING "); strcat(typeOfData, secondaryModelList[tr->secondaryStructureModel]); break; case SECONDARY_DATA_7: strcpy(typeOfData,"SECONDARY 7 STATE MODEL USING "); strcat(typeOfData, secondaryModelList[tr->secondaryStructureModel]); break; case GENERIC_32: strcpy(typeOfData,"Multi-State"); break; case GENERIC_64: strcpy(typeOfData,"Codon"); break; default: assert(0); } } /************************************************************************************/ static int iterated_bitcount(unsigned int n) { int count=0; while(n) { count += n & 0x1u ; n >>= 1 ; } return count; } static char bits_in_16bits [0x1u << 16]; static void compute_bits_in_16bits(void) { unsigned int i; for (i = 0; i < (0x1u<<16); i++) bits_in_16bits[i] = iterated_bitcount(i); return ; } unsigned int precomputed16_bitcount (unsigned int n) { /* works only for 32-bit int*/ return bits_in_16bits [n & 0xffffu] + bits_in_16bits [(n >> 16) & 0xffffu] ; } static void smoothFreqs(const int n, double *pfreqs, double *dst, pInfo *partitionData) { int countScale = 0, l, loopCounter = 0; for(l = 0; l < n; l++) if(pfreqs[l] < FREQ_MIN) countScale++; /* for(l = 0; l < n; l++) if(pfreqs[l] == 0.0) countScale++;*/ if(countScale > 0) { while(countScale > 0) { double correction = 0.0; double factor = 1.0; for(l = 0; l < n; l++) { if(pfreqs[l] == 0.0) correction += FREQ_MIN; else if(pfreqs[l] < FREQ_MIN) { correction += (FREQ_MIN - pfreqs[l]); factor -= (FREQ_MIN - pfreqs[l]); } } countScale = 0; for(l = 0; l < n; l++) { if(pfreqs[l] >= FREQ_MIN) pfreqs[l] = pfreqs[l] - (pfreqs[l] * correction * factor); else pfreqs[l] = FREQ_MIN; if(pfreqs[l] < FREQ_MIN) countScale++; } assert(loopCounter < 100); loopCounter++; } } for(l = 0; l < n; l++) dst[l] = pfreqs[l]; if(partitionData->nonGTR) { int k; assert(partitionData->dataType == SECONDARY_DATA_7 || partitionData->dataType == SECONDARY_DATA_6 || partitionData->dataType == SECONDARY_DATA); for(l = 0; l < n; l++) { int count = 1; for(k = 0; k < n; k++) { if(k != l && partitionData->frequencyGrouping[l] == partitionData->frequencyGrouping[k]) { count++; dst[l] += pfreqs[k]; } } dst[l] /= ((double)count); } } } static void genericBaseFrequencies(tree *tr, const int numFreqs, rawdata *rdta, cruncheddata *cdta, int lower, int upper, int model, boolean smoothFrequencies, const unsigned int *bitMask) { double wj, acc, pfreqs[64], sumf[64], temp[64]; int countStatesPresent = 0, statesPresent[64], i, j, k, l; unsigned char *yptr; for(l = 0; l < numFreqs; l++) { pfreqs[l] = 1.0 / ((double)numFreqs); statesPresent[l] = 0; } #ifdef _DEBUG_UNDET_REMOVAL printf("bounds %d %d\n", lower, upper); for(j = lower; j < upper; j++) { for(i = 0; i < rdta->numsp; i++) { unsigned int code; yptr = &(rdta->y0[((size_t)i) * (tr->originalCrunchedLength)]); code = yptr[j]; printf("%c", inverseMeaningDNA[code]); } printf("\n"); } printf("\n\n"); #endif for(i = 0; i < rdta->numsp; i++) { yptr = &(rdta->y0[((size_t)i) * (tr->originalCrunchedLength)]); for(j = lower; j < upper; j++) { unsigned int code = bitMask[yptr[j]]; switch(numFreqs) { case 2: switch(code) { case 1: statesPresent[0] = 1; break; case 2: statesPresent[1] = 1; break; default: ; } break; case 4: switch(code) { case 1: statesPresent[0] = 1; break; case 2: statesPresent[1] = 1; break; case 4: statesPresent[2] = 1; break; case 8: statesPresent[3] = 1; break; default: ; } break; case 20: if(yptr[j] >= 0 && yptr[j] < 20) statesPresent[yptr[j]] = 1; break; default: assert(0); } } } for(i = 0, countStatesPresent = 0; i < numFreqs; i++) if(statesPresent[i] == 1) countStatesPresent++; for (k = 1; k <= 8; k++) { for(l = 0; l < numFreqs; l++) sumf[l] = 0.0; for(i = 0; i < rdta->numsp; i++) { yptr = &(rdta->y0[((size_t)i) * (tr->originalCrunchedLength)]); for(j = lower; j < upper; j++) { unsigned int code = bitMask[yptr[j]]; assert(code >= 1); for(l = 0; l < numFreqs; l++) { if((code >> l) & 1) temp[l] = pfreqs[l]; else temp[l] = 0.0; } for(l = 0, acc = 0.0; l < numFreqs; l++) { if(temp[l] != 0.0) acc += temp[l]; } wj = ((double)cdta->aliaswgt[j]) / acc; for(l = 0; l < numFreqs; l++) { if(temp[l] != 0.0) sumf[l] += wj * temp[l]; } } } for(l = 0, acc = 0.0; l < numFreqs; l++) { if(sumf[l] != 0.0) acc += sumf[l]; } for(l = 0; l < numFreqs; l++) pfreqs[l] = sumf[l] / acc; } if(countStatesPresent < numFreqs) { printf("Partition %s number %d has a problem, the number of expected states is %d the number of states that are present is %d.\n", tr->partitionData[model].partitionName, model, numFreqs, countStatesPresent); printf("Please go and fix your data!\n\n"); } if(smoothFrequencies) { smoothFreqs(numFreqs, pfreqs, tr->partitionData[model].frequencies, &(tr->partitionData[model])); } else { boolean zeroFreq = FALSE; char typeOfData[1024]; getDataTypeString(tr, model, typeOfData); for(l = 0; l < numFreqs; l++) { if(pfreqs[l] == 0.0) { printBothOpen("Empirical base frequency for state number %d is equal to zero in %s data partition %s\n", l, typeOfData, tr->partitionData[model].partitionName); printBothOpen("Since this is probably not what you want to do, RAxML will soon exit.\n\n"); zeroFreq = TRUE; } } if(zeroFreq) exit(-1); for(l = 0; l < numFreqs; l++) { assert(pfreqs[l] > 0.0); tr->partitionData[model].frequencies[l] = pfreqs[l]; } } } static void baseFrequenciesGTR(rawdata *rdta, cruncheddata *cdta, tree *tr) { int model; size_t lower, upper; int states; for(model = 0; model < tr->NumberOfModels; model++) { lower = tr->partitionData[model].lower; upper = tr->partitionData[model].upper; states = tr->partitionData[model].states; switch(tr->partitionData[model].dataType) { case GENERIC_32: switch(tr->multiStateModel) { case ORDERED_MULTI_STATE: case MK_MULTI_STATE: { int i; double freq = 1.0 / (double)states, acc = 0.0; for(i = 0; i < states; i++) { acc += freq; tr->partitionData[model].frequencies[i] = freq; /*printf("%f \n", freq);*/ } /*printf("Frequency Deviation: %1.60f\n", acc);*/ } break; case GTR_MULTI_STATE: genericBaseFrequencies(tr, states, rdta, cdta, lower, upper, model, TRUE, bitVector32); break; default: assert(0); } break; case GENERIC_64: assert(0); break; case SECONDARY_DATA_6: case SECONDARY_DATA_7: case SECONDARY_DATA: case AA_DATA: case DNA_DATA: case BINARY_DATA: genericBaseFrequencies(tr, states, rdta, cdta, lower, upper, model, getSmoothFreqs(tr->partitionData[model].dataType), getBitVector(tr->partitionData[model].dataType)); break; default: assert(0); } } return; } // #define OLD_LAYOUT int main (int argc, char *argv[]) { int model; rawdata *rdta; cruncheddata *cdta; tree *tr; analdef *adef; /* get the start time */ masterTime = gettime(); /* get some memory for the basic data structures */ adef = (analdef *)malloc(sizeof(analdef)); rdta = (rawdata *)malloc(sizeof(rawdata)); cdta = (cruncheddata *)malloc(sizeof(cruncheddata)); tr = (tree *)malloc(sizeof(tree)); /* the initialization below is required for the hash tables that are used */ compute_bits_in_16bits(); /* initialize the analysis parameters in struct adef to default values */ initAdef(adef); /* parse command line arguments: this has a side effect on tr struct and adef struct variables */ get_args(argc,argv, adef, tr); /* parse the phylip file: this should probably be re-done, perhaps using the relatively flexible parser written in C++ by Marc Holder */ getinput(adef, rdta, cdta, tr); printBothOpen("Pattern compression: %s\n", (adef->compressPatterns)?"ON":"OFF"); makeweights(adef, rdta, cdta, tr); makevalues(rdta, cdta, tr, adef); for(model = 0; model < tr->NumberOfModels; model++) { tr->partitionData[model].states = getStates(tr->partitionData[model].dataType); tr->partitionData[model].maxTipStates = getUndetermined(tr->partitionData[model].dataType) + 1; tr->partitionData[model].nonGTR = FALSE; partitionLengths *pl = getPartitionLengths(&(tr->partitionData[model])); tr->partitionData[model].frequencies = (double*)malloc(pl->frequenciesLength * sizeof(double)); } baseFrequenciesGTR(tr->rdta, tr->cdta, tr); { int sizeOfSizeT = sizeof(size_t), version = (int)programVersionInt, magicNumber = 6517718; size_t i, model; /* NEW, we firstly write, how many bytes size_t comprises */ myBinFwrite(&(sizeOfSizeT), sizeof(sizeOfSizeT), 1); //error checking for parser! myBinFwrite(&version, sizeof(int), 1); myBinFwrite(&magicNumber, sizeof(int), 1); //error checking for correct parser end myBinFwrite(&(tr->mxtips), sizeof(int), 1); myBinFwrite(&(tr->originalCrunchedLength), sizeof(size_t), 1); myBinFwrite(&(tr->NumberOfModels), sizeof(int), 1); myBinFwrite(&(adef->gapyness), sizeof(double), 1); myBinFwrite(tr->cdta->aliaswgt, sizeof(int), tr->originalCrunchedLength); for(i = 1; i <= (size_t)tr->mxtips; i++) { int len = strlen(tr->nameList[i]) + 1; myBinFwrite(&len, sizeof(int), 1); myBinFwrite(tr->nameList[i], sizeof(char), len); } for(model = 0; model < (size_t)tr->NumberOfModels; model++) { int len; pInfo *p = &(tr->partitionData[model]); myBinFwrite(&(p->states), sizeof(int), 1); myBinFwrite(&(p->maxTipStates), sizeof(int), 1); myBinFwrite(&(p->lower), sizeof(size_t), 1); myBinFwrite(&(p->upper), sizeof(size_t), 1); myBinFwrite(&(p->width), sizeof(size_t), 1); myBinFwrite(&(p->dataType), sizeof(int), 1); myBinFwrite(&(p->protModels), sizeof(int), 1); myBinFwrite(&(p->protFreqs), sizeof(int), 1); myBinFwrite(&(p->nonGTR), sizeof(boolean), 1); myBinFwrite(&(p->optimizeBaseFrequencies), sizeof(boolean), 1); /* later on if adding secondary structure data int *symmetryVector; int *frequencyGrouping; */ len = strlen(p->partitionName) + 1; myBinFwrite(&len, sizeof(int), 1); myBinFwrite(p->partitionName, sizeof(char), len); myBinFwrite(tr->partitionData[model].frequencies, sizeof(double), tr->partitionData[model].states); } #ifdef OLD_LAYOUT myBinFwrite(rdta->y0, sizeof(unsigned char), (tr->originalCrunchedLength) * ((size_t)tr->mxtips)); #else /* Write each partition, taxon by taxon. Thus, if unpartitioned, nothing changes. */ size_t mem_reqs_cat = 0, mem_reqs_gamma = 0, unique_patterns = 0; for(model = 0; model < (size_t) tr->NumberOfModels; ++model ) { pInfo *p = &(tr->partitionData[model]); size_t width = p->upper - p->lower; unique_patterns += width; //multiply partition width with number of states we need to store in each CLV entry mem_reqs_cat += (size_t)tr->partitionData[model].states * width; for(i = 0; i < (size_t)tr->mxtips; ++i) { myBinFwrite(rdta->y0 + sizeof(unsigned char) * ( (i * tr->originalCrunchedLength) + p->lower ) , sizeof(unsigned char), width); } } printBothOpen("\n\nYour alignment has %zu %s\n", unique_patterns, (adef->compressPatterns == TRUE)?"unique patterns":"sites"); //multiply CLV vector length with number of tips and 8, since b bytes are needed to store an inner conditional probability vector mem_reqs_cat *= (size_t)tr->mxtips * sizeof(double); //mem reqs for gamma are 4 times higher than for CAT mem_reqs_gamma = mem_reqs_cat * 4; //now add the space for storing the tips: mem_reqs_cat += (size_t)tr->mxtips * unique_patterns * sizeof(unsigned char); mem_reqs_gamma += (size_t)tr->mxtips * unique_patterns * sizeof(unsigned char); printBothOpen("\n\nUnder CAT the memory required by ExaML for storing CLVs and tip vectors will be\n%zu bytes\n%zu kiloBytes\n%zu MegaBytes\n%zu GigaBytes\n", mem_reqs_cat, mem_reqs_cat / 1024 , mem_reqs_cat / (1024 * 1024), mem_reqs_cat / (1024 * 1024 * 1024)); printBothOpen("\n\nUnder GAMMA the memory required by ExaML for storing CLVs and tip vectors will be\n%zu bytes\n%zu kiloBytes\n%zu MegaBytes\n%zu GigaBytes\n", mem_reqs_gamma, mem_reqs_gamma / 1024 , mem_reqs_gamma / (1024 * 1024), mem_reqs_gamma / (1024 * 1024 * 1024)); printBothOpen("\nPlease note that, these are just the memory requirements for doing likelihood calculations!\n"); printBothOpen("To be on the safe side, we recommend that you execute ExaML on a system with twice that memory.\n"); #endif } fclose(byteFile); printBothOpen("\n\nBinary and compressed alignment file written to file %s\n\n", byteFileName); printBothOpen("Parsing completed, exiting now ... \n\n"); return 0; } ExaML-3.0.21/parser/axml.h000066400000000000000000001057511330315463200151620ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses * with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #include #include #include "../versionHeader/version.h" #ifdef __AVX #define BYTE_ALIGNMENT 32 #else #define BYTE_ALIGNMENT 16 #endif #define MAX_TIP_EV 0.999999999 /* max tip vector value, sum of EVs needs to be smaller than 1.0, otherwise the numerics break down */ #define smoothings 32 /* maximum smoothing passes through tree */ #define iterations 10 /* maximum iterations of iterations per insert */ #define newzpercycle 1 /* iterations of makenewz per tree traversal */ #define nmlngth 256 /* number of characters in species name */ #define deltaz 0.00001 /* test of net branch length change in update */ #define defaultz 0.9 /* value of z assigned as starting point */ #define unlikely -1.0E300 /* low likelihood for initialization */ #define SUMMARIZE_LENGTH -3 #define SUMMARIZE_LH -2 #define NO_BRANCHES -1 #define MASK_LENGTH 32 #define GET_BITVECTOR_LENGTH(x) ((x % MASK_LENGTH) ? (x / MASK_LENGTH + 1) : (x / MASK_LENGTH)) #define zmin 1.0E-15 /* max branch prop. to -log(zmin) (= 34) */ #define zmax (1.0 - 1.0E-6) /* min branch prop. to 1.0-zmax (= 1.0E-6) */ #define twotothe256 \ 115792089237316195423570985008687907853269984665640564039457584007913129639936.0 /* 2**256 (exactly) */ #define minlikelihood (1.0/twotothe256) #define minusminlikelihood -minlikelihood /* 18446744073709551616.0 */ /*4294967296.0*/ /* 18446744073709551616.0 */ /* 2**64 (exactly) */ /* 4294967296 2**32 */ #define badRear -1 //#define NUM_BRANCHES 1 #define TRUE 1 #define FALSE 0 #define LIKELIHOOD_EPSILON 0.0000001 #define AA_SCALE 10.0 #define AA_SCALE_PLUS_EPSILON 10.001 /* ALPHA_MIN is critical -> numerical instability, eg for 4 discrete rate cats */ /* and alpha = 0.01 the lowest rate r_0 is */ /* 0.00000000000000000000000000000000000000000000000000000000000034878079110511010487 */ /* which leads to numerical problems Table for alpha settings below: */ /* */ /* 0.010000 0.00000000000000000000000000000000000000000000000000000000000034878079110511010487 */ /* 0.010000 yielded nasty numerical bugs in at least one case ! */ /* 0.020000 0.00000000000000000000000000000044136090435925743185910935350715027016962154188875 */ /* 0.030000 0.00000000000000000000476844846859006690412039180149775802624789852441798419292220 */ /* 0.040000 0.00000000000000049522423236954066431210260930029681736928018820007024736185030633 */ /* 0.050000 0.00000000000050625351310359203371872643495343928538368616365517027588794007897377 */ /* 0.060000 0.00000000005134625283884191118711474021861409372524676086868566926568746566772461 */ /* 0.070000 0.00000000139080650074206434685544624965062437960128249869740102440118789672851562 */ /* 0.080000 0.00000001650681201563587066858709818343436959153791576682124286890029907226562500 */ /* 0.090000 0.00000011301977332931251259273962858978301859735893231118097901344299316406250000 */ /* 0.100000 0.00000052651925834844387815526344648331402709118265192955732345581054687500000000 */ #define ALPHA_MIN 0.02 #define ALPHA_MAX 1000.0 #define RATE_MIN 0.0000001 #define RATE_MAX 1000000.0 #define INVAR_MIN 0.0001 #define INVAR_MAX 0.9999 #define TT_MIN 0.0000001 #define TT_MAX 1000000.0 #define FREQ_MIN 0.001 /* previous values between 0.001 and 0.000001 TO AVOID NUMERICAL PROBLEMS WHEN FREQ == 0 IN PARTITIONED MODELS, ESPECIALLY WITH AA previous value of FREQ_MIN was: 0.000001, but this seemed to cause problems with some of the 7-state secondary structure models with some rather exotic small toy test datasets, on the other hand 0.001 caused problems with some of the 16-state secondary structure models For some reason the frequency settings seem to be repeatedly causing numerical problems */ #define ITMAX 100 #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d); #define SIGN(a,b) ((b) > 0.0 ? fabs(a) : -fabs(a)) #define ABS(x) (((x)<0) ? (-(x)) : (x)) #define MIN(x,y) (((x)<(y)) ? (x) : (y)) #define MAX(x,y) (((x)>(y)) ? (x) : (y)) #define NINT(x) ((int) ((x)>0 ? ((x)+0.5) : ((x)-0.5))) #ifdef _USE_FPGA_LOG extern double log_approx (double input); #define LOG(x) log_approx(x) #else #define LOG(x) log(x) #endif #ifdef _USE_FPGA_EXP extern double exp_approx (double x); #define EXP(x) exp_approx(x) #else #define EXP(x) exp(x) #endif #define LOGF(x) logf(x) #define PointGamma(prob,alpha,beta) PointChi2(prob,2.0*(alpha))/(2.0*(beta)) //#define programName "the phylip file parser for ExaML" //#define programVersion "2.0.1" //#define programDate "June 3 2014" #define TREE_EVALUATION 0 #define BIG_RAPID_MODE 1 #define CALC_BIPARTITIONS 3 #define SPLIT_MULTI_GENE 4 #define CHECK_ALIGNMENT 5 #define PER_SITE_LL 6 #define PARSIMONY_ADDITION 7 #define CLASSIFY_ML 9 #define DISTANCE_MODE 11 #define GENERATE_BS 12 #define COMPUTE_ELW 13 #define BOOTSTOP_ONLY 14 #define COMPUTE_LHS 17 #define COMPUTE_BIPARTITION_CORRELATION 18 #define THOROUGH_PARSIMONY 19 #define COMPUTE_RF_DISTANCE 20 #define MORPH_CALIBRATOR 21 #define CONSENSUS_ONLY 22 #define MESH_TREE_SEARCH 23 #define FAST_SEARCH 24 #define MORPH_CALIBRATOR_PARSIMONY 25 #define SH_LIKE_SUPPORTS 28 #define M_GTRCAT 1 #define M_GTRGAMMA 2 #define M_BINCAT 3 #define M_BINGAMMA 4 #define M_PROTCAT 5 #define M_PROTGAMMA 6 #define M_32CAT 7 #define M_32GAMMA 8 #define M_64CAT 9 #define M_64GAMMA 10 #define DAYHOFF 0 #define DCMUT 1 #define JTT 2 #define MTREV 3 #define WAG 4 #define RTREV 5 #define CPREV 6 #define VT 7 #define BLOSUM62 8 #define MTMAM 9 #define LG 10 #define MTART 11 #define MTZOA 12 #define PMB 13 #define HIVB 14 #define HIVW 15 #define JTTDCMUT 16 #define FLU 17 #define STMTREV 18 #define AUTO 19 #define LG4M 20 #define LG4X 21 #define GTR 22 /* GTR always needs to be the last one */ #define NUM_PROT_MODELS 23 /* bipartition stuff */ #define BIPARTITIONS_ALL 0 #define GET_BIPARTITIONS_BEST 1 #define DRAW_BIPARTITIONS_BEST 2 #define BIPARTITIONS_BOOTSTOP 3 #define BIPARTITIONS_RF 4 /* bootstopping stuff */ #define BOOTSTOP_PERMUTATIONS 100 #define START_BSTOP_TEST 10 #define FC_THRESHOLD 99 #define FC_SPACING 50 #define FC_LOWER 0.99 #define FC_INIT 20 #define FREQUENCY_STOP 0 #define MR_STOP 1 #define MRE_STOP 2 #define MRE_IGN_STOP 3 #define MR_CONSENSUS 0 #define MRE_CONSENSUS 1 #define STRICT_CONSENSUS 2 /* bootstopping stuff end */ #define TIP_TIP 0 #define TIP_INNER 1 #define INNER_INNER 2 #define MIN_MODEL -1 #define BINARY_DATA 0 #define DNA_DATA 1 #define AA_DATA 2 #define SECONDARY_DATA 3 #define SECONDARY_DATA_6 4 #define SECONDARY_DATA_7 5 #define GENERIC_32 6 #define GENERIC_64 7 #define MAX_MODEL 8 #define SEC_6_A 0 #define SEC_6_B 1 #define SEC_6_C 2 #define SEC_6_D 3 #define SEC_6_E 4 #define SEC_7_A 5 #define SEC_7_B 6 #define SEC_7_C 7 #define SEC_7_D 8 #define SEC_7_E 9 #define SEC_7_F 10 #define SEC_16 11 #define SEC_16_A 12 #define SEC_16_B 13 #define SEC_16_C 14 #define SEC_16_D 15 #define SEC_16_E 16 #define SEC_16_F 17 #define SEC_16_I 18 #define SEC_16_J 19 #define SEC_16_K 20 #define ORDERED_MULTI_STATE 0 #define MK_MULTI_STATE 1 #define GTR_MULTI_STATE 2 #define CAT 0 #define GAMMA 1 #define GAMMA_I 2 typedef int boolean; typedef struct { double lh; int tree; double weight; } elw; struct ent { unsigned int *bitVector; unsigned int *treeVector; unsigned int amountTips; int *supportVector; unsigned int bipNumber; unsigned int bipNumber2; unsigned int supportFromTreeset[2]; struct ent *next; }; typedef struct ent entry; typedef unsigned int hashNumberType; typedef unsigned int parsimonyNumber; /*typedef uint_fast32_t parsimonyNumber;*/ #define PCF 32 /* typedef uint64_t parsimonyNumber; #define PCF 16 typedef unsigned char parsimonyNumber; #define PCF 2 */ typedef struct { hashNumberType tableSize; entry **table; hashNumberType entryCount; } hashtable; struct stringEnt { int nodeNumber; char *word; struct stringEnt *next; }; typedef struct stringEnt stringEntry; typedef struct { hashNumberType tableSize; stringEntry **table; } stringHashtable; typedef struct { unsigned int parsimonyScore; unsigned int parsimonyState; } parsimonyVector; typedef struct ratec { double accumulatedSiteLikelihood; double rate; } rateCategorize; typedef struct { int tipCase; int pNumber; int qNumber; int rNumber; //double qz[NUM_BRANCHES]; //double rz[NUM_BRANCHES]; } traversalInfo; typedef struct { traversalInfo *ti; int count; int functionType; boolean traversalHasChanged; boolean *executeModel; double *parameterValues; } traversalData; struct noderec; typedef struct epBrData { int *countThem; int *executeThem; unsigned int *parsimonyScores; double *branches; double *bootstrapBranches; double *likelihoods; double originalBranchLength; char branchLabel[64]; int leftNodeNumber; int rightNodeNumber; int *leftScaling; int *rightScaling; parsimonyVector *leftParsimony; parsimonyVector *rightParsimony; //double branchLengths[NUM_BRANCHES]; double *left; double *right; int branchNumber; } epaBranchData; typedef struct { epaBranchData *epa; unsigned int *vector; int support; struct noderec *oP; struct noderec *oQ; } branchInfo; typedef struct { boolean valid; int partitions; int *partitionList; } linkageData; typedef struct { int entries; linkageData* ld; } linkageList; typedef struct noderec { branchInfo *bInf; // double z[NUM_BRANCHES]; #ifdef _BAYESIAN //double z_tmp[NUM_BRANCHES]; #endif struct noderec *next; struct noderec *back; hashNumberType hash; int support; int number; char x; } node, *nodeptr; typedef struct { double lh; int number; } info; typedef struct bInf { double likelihood; nodeptr node; } bestInfo; typedef struct iL { bestInfo *list; int n; int valid; } infoList; typedef struct { int numsp; int sites; unsigned char **y; unsigned char *y0; int *wgt; } rawdata; typedef struct { int *alias; /* site representing a pattern */ int *aliaswgt; /* weight by pattern */ int *rateCategory; size_t endsite; /* # of sequence patterns */ double *patrat; /* rates per pattern */ double *patratStored; } cruncheddata; typedef struct { int states; int maxTipStates; size_t lower; size_t upper; size_t width; int dataType; int protModels; int autoProtModels; int protFreqs; int **expVector; double **xVector; size_t *xSpaceVector; unsigned char **yVector; char *partitionName; double *sumBuffer; double *gammaRates; double *EIGN; double *EV; double *EI; double *left; double *right; double *frequencies; double *tipVector; double *substRates; double *perSiteRates; double *wr; double *wr2; unsigned int *globalScaler; double *globalScalerDouble; int *wgt; int *rateCategory; int *symmetryVector; int *frequencyGrouping; boolean nonGTR; boolean optimizeBaseFrequencies; double alpha; int gapVectorLength; unsigned int *gapVector; double *gapColumn; int numberOfCategories; } pInfo; typedef struct { int left; int right; double likelihood; } lhEntry; typedef struct { int count; int size; lhEntry *entries; } lhList; typedef struct List_{ void *value; struct List_ *next; } List; #define REARR_SETTING 1 #define FAST_SPRS 2 #define SLOW_SPRS 3 typedef struct { int state; unsigned int vLength; int rearrangementsMax; int rearrangementsMin; int thoroughIterations; int fastIterations; int treeVectorLength; int mintrav; int maxtrav; int bestTrav; int Thorough; int optimizeRateCategoryInvocations; double accumulatedTime; double startLH; double lh; double previousLh; double difference; double epsilon; boolean impr; boolean cutoff; double tr_startLH; double tr_endLH; double tr_likelihood; double tr_bestOfNode; double tr_lhCutoff; double tr_lhAVG; double tr_lhDEC; int tr_NumberOfCategories; int tr_itCount; int tr_doCutoff; } checkPointState; typedef struct { double EIGN[19] __attribute__ ((aligned (BYTE_ALIGNMENT))); double EV[400] __attribute__ ((aligned (BYTE_ALIGNMENT))); double EI[380] __attribute__ ((aligned (BYTE_ALIGNMENT))); double substRates[190]; double frequencies[20] ; double tipVector[460] __attribute__ ((aligned (BYTE_ALIGNMENT))); double fracchange[1]; double left[1600] __attribute__ ((aligned (BYTE_ALIGNMENT))); double right[1600] __attribute__ ((aligned (BYTE_ALIGNMENT))); } siteAAModels; typedef struct { boolean useGappedImplementation; boolean saveMemory; siteAAModels siteProtModel[2 * (NUM_PROT_MODELS - 2)]; boolean estimatePerSiteAA; int *resample; int numberOfBranches; int numberOfTipsForInsertion; int *inserts; int branchCounter; parsimonyNumber **parsimonyState_A; parsimonyNumber **parsimonyState_C; parsimonyNumber **parsimonyState_G; parsimonyNumber **parsimonyState_T; unsigned int *parsimonyScore; int *ti; unsigned int compressedWidth; int numberOfTrees; stringHashtable *nameHash; pInfo *partitionData; pInfo *initialPartitionData; pInfo *extendedPartitionData; int *dataVector; int *initialDataVector; int *extendedDataVector; int *patternPosition; int *columnPosition; char *secondaryStructureInput; boolean *executeModel; double *perPartitionLH; traversalData td[1]; int maxCategories; double *wr; double *wr2; // double coreLZ[NUM_BRANCHES]; int modelNumber; int numBranches; int bootStopCriterion; int consensusType; double wcThreshold; branchInfo *bInf; int multiStateModel; // boolean curvatOK[NUM_BRANCHES]; /* the stuff below is shared among DNA and AA, span does not change depending on datatype */ double *fracchanges; /* model stuff end */ unsigned char **yVector; int secondaryStructureModel; size_t originalCrunchedLength; int fullSites; int *originalModel; int *originalDataVector; int *originalWeights; int *secondaryStructurePairs; double *partitionContributions; double fracchange; double lhCutoff; double lhAVG; unsigned long lhDEC; unsigned long itCount; int numberOfInvariableColumns; int weightOfInvariableColumns; int rateHetModel; double startLH; double endLH; double likelihood; double *likelihoods; node **nodep; nodeptr nodeBaseAddress; node *start; int mxtips; int *model; int *constraintVector; int numberOfSecondaryColumns; boolean searchConvergenceCriterion; int ntips; int nextnode; int NumberOfModels; int parsimonyLength; int checkPointCounter; int treeID; boolean bigCutoff; // boolean partitionSmoothed[NUM_BRANCHES]; // boolean partitionConverged[NUM_BRANCHES]; boolean rooted; boolean grouped; boolean constrained; boolean doCutoff; boolean catOnly; rawdata *rdta; cruncheddata *cdta; char **nameList; char *tree_string; char *tree0; char *tree1; int treeStringLength; unsigned int bestParsimony; double bestOfNode; nodeptr removeNode; nodeptr insertNode; /* double zqr[NUM_BRANCHES]; double currentZQR[NUM_BRANCHES]; double currentLZR[NUM_BRANCHES]; double currentLZQ[NUM_BRANCHES]; double currentLZS[NUM_BRANCHES]; double currentLZI[NUM_BRANCHES]; double lzs[NUM_BRANCHES]; double lzq[NUM_BRANCHES]; double lzr[NUM_BRANCHES]; double lzi[NUM_BRANCHES]; */ int mr_thresh; unsigned int **bitVectors; unsigned int vLength; hashtable *h; } tree; /***************************************************************/ typedef struct { int partitionNumber; int partitionLength; } partitionType; typedef struct { // double z[NUM_BRANCHES]; nodeptr p, q; int cp, cq; } connectRELL, *connptrRELL; typedef struct { connectRELL *connect; int start; double likelihood; } topolRELL; typedef struct { int max; topolRELL **t; } topolRELL_LIST; /**************************************************************/ typedef struct conntyp { // double z[NUM_BRANCHES]; /* branch length */ node *p, *q; /* parent and child sectors */ void *valptr; /* pointer to value of subtree */ int descend; /* pointer to first connect of child */ int sibling; /* next connect from same parent */ } connect, *connptr; typedef struct { double likelihood; int initialTreeNumber; connect *links; /* pointer to first connect (start) */ node *start; int nextlink; /* index of next available connect */ /* tr->start = tpl->links->p */ int ntips; int nextnode; int scrNum; /* position in sorted list of scores */ int tplNum; /* position in sorted list of trees */ } topol; typedef struct { double best; /* highest score saved */ double worst; /* lowest score saved */ topol *start; /* starting tree for optimization */ topol **byScore; topol **byTopol; int nkeep; /* maximum topologies to save */ int nvalid; /* number of topologies saved */ int ninit; /* number of topologies initialized */ int numtrees; /* number of alternatives tested */ boolean improved; } bestlist; typedef struct { int categories; int model; int bestTrav; int max_rearrange; int stepwidth; int initial; boolean initialSet; int mode; long boot; long rapidBoot; boolean bootstrapBranchLengths; boolean restart; boolean useWeightFile; boolean useMultipleModel; boolean constraint; boolean grouping; boolean randomStartingTree; boolean useInvariant; int protEmpiricalFreqs; int proteinMatrix; int checkpoints; int startingTreeOnly; int multipleRuns; long parsimonySeed; boolean perGeneBranchLengths; boolean likelihoodTest; boolean permuteTreeoptimize; boolean allInOne; boolean generateBS; boolean bootStopping; boolean useExcludeFile; boolean userProteinModel; boolean computeELW; boolean computeDistance; boolean thoroughInsertion; boolean compressPatterns; boolean useSecondaryStructure; double likelihoodEpsilon; double gapyness; int similarityFilterMode; double *externalAAMatrix; boolean readTaxaOnly; int meshSearch; boolean veryFast; boolean useCheckpoint; boolean leaveDropMode; int slidingWindowSize; boolean writeBinaryFile; boolean readBinaryFile; #ifdef _BAYESIAN boolean bayesian; #endif } analdef; typedef struct { int leftLength; int rightLength; int eignLength; int evLength; int eiLength; int substRatesLength; int frequenciesLength; int tipVectorLength; int symmetryVectorLength; int frequencyGroupingLength; boolean nonGTR; boolean optimizeBaseFrequencies; unsigned char undetermined; const char *inverseMeaning; int states; boolean smoothFrequencies; const unsigned int *bitVector; } partitionLengths; /****************************** FUNCTIONS ****************************************************/ extern void computePlacementBias(tree *tr, analdef *adef); extern int lookupWord(char *s, stringHashtable *h); extern void getDataTypeString(tree *tr, int model, char typeOfData[1024]); extern unsigned int genericBitCount(unsigned int* bitVector, unsigned int bitVectorLength); extern int countTips(nodeptr p, int numsp); extern entry *initEntry(void); extern void computeRogueTaxa(tree *tr, char* treeSetFileName, analdef *adef); extern unsigned int precomputed16_bitcount(unsigned int n); extern size_t discreteRateCategories(int rateHetModel); extern partitionLengths * getPartitionLengths(pInfo *p); extern boolean getSmoothFreqs(int dataType); extern const unsigned int *getBitVector(int dataType); extern unsigned char getUndetermined(int dataType); extern int getStates(int dataType); extern char getInverseMeaning(int dataType, unsigned char state); extern double gettime ( void ); extern int gettimeSrand ( void ); extern double randum ( long *seed ); extern void getxnode ( nodeptr p ); extern void hookup ( nodeptr p, nodeptr q, double *z, int numBranches); extern void hookupDefault ( nodeptr p, nodeptr q, int numBranches); extern boolean whitechar ( int ch ); extern void errorExit ( int e ); extern void printResult ( tree *tr, analdef *adef, boolean finalPrint ); extern void printBootstrapResult ( tree *tr, analdef *adef, boolean finalPrint ); extern void printBipartitionResult ( tree *tr, analdef *adef, boolean finalPrint ); extern void printLog ( tree *tr, analdef *adef, boolean finalPrint ); extern void printStartingTree ( tree *tr, analdef *adef, boolean finalPrint ); extern void writeInfoFile ( analdef *adef, tree *tr, double t ); extern int main ( int argc, char *argv[] ); extern void calcBipartitions ( tree *tr, analdef *adef, char *bestTreeFileName, char *bootStrapFileName ); extern void initReversibleGTR (tree *tr, int model); extern double LnGamma ( double alpha ); extern double IncompleteGamma ( double x, double alpha, double ln_gamma_alpha ); extern double PointNormal ( double prob ); extern double PointChi2 ( double prob, double v ); extern void makeGammaCats (double alpha, double *gammaRates, int K); extern void initModel ( tree *tr, rawdata *rdta, cruncheddata *cdta, analdef *adef ); extern void doAllInOne ( tree *tr, analdef *adef ); extern void classifyML(tree *tr, analdef *adef); extern void doBootstrap ( tree *tr, analdef *adef, rawdata *rdta, cruncheddata *cdta ); extern void doInference ( tree *tr, analdef *adef, rawdata *rdta, cruncheddata *cdta ); extern void resetBranches ( tree *tr ); extern void modOpt ( tree *tr, analdef *adef , double likelihoodEpsilon); extern void parsePartitions ( analdef *adef, rawdata *rdta, tree *tr); extern void computeBOOTRAPID (tree *tr, analdef *adef, long *radiusSeed); extern void optimizeRAPID ( tree *tr, analdef *adef ); extern void thoroughOptimization ( tree *tr, analdef *adef, topolRELL_LIST *rl, int index ); extern int treeOptimizeThorough ( tree *tr, int mintrav, int maxtrav); extern int checker ( tree *tr, nodeptr p ); extern int randomInt ( int n ); extern void makePermutation ( int *perm, int n, analdef *adef ); extern boolean tipHomogeneityChecker ( tree *tr, nodeptr p, int grouping ); extern void makeRandomTree ( tree *tr, analdef *adef ); extern void nodeRectifier ( tree *tr ); extern void makeParsimonyTreeThorough(tree *tr, analdef *adef); extern void makeParsimonyTree ( tree *tr, analdef *adef ); extern void makeParsimonyTreeFastDNA(tree *tr, analdef *adef); extern void makeParsimonyTreeIncomplete ( tree *tr, analdef *adef ); extern void makeParsimonyInsertions(tree *tr, nodeptr startNodeQ, nodeptr startNodeR); extern FILE *myfopen(const char *path, const char *mode); extern boolean initrav ( tree *tr, nodeptr p ); extern void initravPartition ( tree *tr, nodeptr p, int model ); extern boolean update ( tree *tr, nodeptr p ); extern boolean smooth ( tree *tr, nodeptr p ); extern boolean smoothTree ( tree *tr, int maxtimes ); extern boolean localSmooth ( tree *tr, nodeptr p, int maxtimes ); extern boolean localSmoothMulti(tree *tr, nodeptr p, int maxtimes, int model); extern void initInfoList ( int n ); extern void freeInfoList ( void ); extern void insertInfoList ( nodeptr node, double likelihood ); extern boolean smoothRegion ( tree *tr, nodeptr p, int region ); extern boolean regionalSmooth ( tree *tr, nodeptr p, int maxtimes, int region ); extern nodeptr removeNodeBIG ( tree *tr, nodeptr p, int numBranches); extern nodeptr removeNodeRestoreBIG ( tree *tr, nodeptr p ); extern boolean insertBIG ( tree *tr, nodeptr p, nodeptr q, int numBranches); extern boolean insertRestoreBIG ( tree *tr, nodeptr p, nodeptr q ); extern boolean testInsertBIG ( tree *tr, nodeptr p, nodeptr q ); extern void addTraverseBIG ( tree *tr, nodeptr p, nodeptr q, int mintrav, int maxtrav ); extern int rearrangeBIG ( tree *tr, nodeptr p, int mintrav, int maxtrav ); extern void traversalOrder ( nodeptr p, int *count, nodeptr *nodeArray ); extern double treeOptimizeRapid ( tree *tr, int mintrav, int maxtrav, analdef *adef, bestlist *bt); extern boolean testInsertRestoreBIG ( tree *tr, nodeptr p, nodeptr q ); extern void restoreTreeFast ( tree *tr ); extern int determineRearrangementSetting ( tree *tr, analdef *adef, bestlist *bestT, bestlist *bt ); extern void computeBIGRAPID ( tree *tr, analdef *adef, boolean estimateModel); extern boolean treeEvaluate ( tree *tr, double smoothFactor ); extern boolean treeEvaluatePartition ( tree *tr, double smoothFactor, int model ); extern void meshTreeSearch(tree *tr, analdef *adef, int thorough); extern void initTL ( topolRELL_LIST *rl, tree *tr, int n ); extern void freeTL ( topolRELL_LIST *rl); extern void restoreTL ( topolRELL_LIST *rl, tree *tr, int n ); extern void resetTL ( topolRELL_LIST *rl ); extern void saveTL ( topolRELL_LIST *rl, tree *tr, int index ); extern int saveBestTree (bestlist *bt, tree *tr); extern int recallBestTree (bestlist *bt, int rank, tree *tr); extern int initBestTree ( bestlist *bt, int newkeep, int numsp ); extern void resetBestTree ( bestlist *bt ); extern boolean freeBestTree ( bestlist *bt ); extern char *Tree2String ( char *treestr, tree *tr, nodeptr p, boolean printBranchLengths, boolean printNames, boolean printLikelihood, boolean rellTree, boolean finalPrint, int perGene, boolean branchLabelSupport, boolean printSHSupport); extern void printTreePerGene(tree *tr, analdef *adef, char *fileName, char *permission); extern int treeReadLen (FILE *fp, tree *tr, boolean readBranches, boolean readNodeLabels, boolean topologyOnly); extern void treeReadTopologyString(char *treeString, tree *tr); extern boolean treeReadLenMULT ( FILE *fp, tree *tr, analdef *adef ); extern void getStartingTree ( tree *tr); extern double treeLength(tree *tr, int model); extern void computeBootStopOnly(tree *tr, char *bootStrapFileName, analdef *adef); extern boolean bootStop(tree *tr, hashtable *h, int numberOfTrees, double *pearsonAverage, unsigned int **bitVectors, int treeVectorLength, unsigned int vectorLength); extern void computeConsensusOnly(tree *tr, char* treeSetFileName, analdef *adef); extern double evaluatePartialGeneric (tree *, int i, double ki, int _model); extern void evaluateGeneric (tree *tr, nodeptr p, boolean fullTraversal); extern void newviewGeneric (tree *tr, nodeptr p, boolean masked); extern void newviewGenericMulti (tree *tr, nodeptr p, int model); extern void makenewzGeneric(tree *tr, nodeptr p, nodeptr q, double *z0, int maxiter, double *result, boolean mask); extern void makenewzGenericDistance(tree *tr, int maxiter, double *z0, double *result, int taxon1, int taxon2); extern double evaluatePartitionGeneric (tree *tr, nodeptr p, int model); extern void newviewPartitionGeneric (tree *tr, nodeptr p, int model); extern double evaluateGenericVector (tree *tr, nodeptr p); extern void categorizeGeneric (tree *tr, nodeptr p); extern double makenewzPartitionGeneric(tree *tr, nodeptr p, nodeptr q, double z0, int maxiter, int model); extern boolean isTip(int number, int maxTips); extern void computeTraversalInfo(nodeptr p, traversalInfo *ti, int *counter, int maxTips, int numBranches, boolean partialTraversal); extern void newviewIterative(tree *tr, int startIndex); extern void evaluateIterative(tree *); extern void *malloc_aligned( size_t size); extern void storeExecuteMaskInTraversalDescriptor(tree *tr); extern void storeValuesInTraversalDescriptor(tree *tr, double *value); extern void myBinFwrite(const void *ptr, size_t size, size_t nmemb); extern void myBinFread(void *ptr, size_t size, size_t nmemb); extern void makenewzIterative(tree *); extern void execCore(tree *, volatile double *dlnLdlz, volatile double *d2lnLdlz2); extern void determineFullTraversal(nodeptr p, tree *tr); /*extern void optRateCat(tree *, int i, double lower_spacing, double upper_spacing, double *lhs);*/ extern unsigned int evaluateParsimonyIterative(tree *); extern void newviewParsimonyIterative(tree *); extern unsigned int evaluateParsimonyIterativeFast(tree *); extern void newviewParsimonyIterativeFast(tree *); extern unsigned int evaluatePerSiteParsimony(tree *tr, nodeptr p, unsigned int *siteParsimony); extern void initravParsimonyNormal(tree *tr, nodeptr p); extern double evaluateGenericInitravPartition(tree *tr, nodeptr p, int model); extern void evaluateGenericVectorIterative(tree *, int startIndex, int endIndex); extern void categorizeIterative(tree *, int startIndex, int endIndex); extern void fixModelIndices(tree *tr, int endsite, boolean fixRates); extern void calculateModelOffsets(tree *tr); extern void gammaToCat(tree *tr); extern void catToGamma(tree *tr, analdef *adef); extern void handleExcludeFile(tree *tr, analdef *adef, rawdata *rdta); extern nodeptr findAnyTip(nodeptr p, int numsp); extern void parseProteinModel(analdef *adef); extern void computeNextReplicate(tree *tr, long *seed, int *originalRateCategories, int *originalInvariant, boolean isRapid, boolean fixRates); /*extern void computeNextReplicate(tree *tr, analdef *adef, int *originalRateCategories, int *originalInvariant);*/ extern void putWAG(double *ext_initialRates); extern void reductionCleanup(tree *tr, int *originalRateCategories, int *originalInvariant); extern void parseSecondaryStructure(tree *tr, analdef *adef, int sites); extern void printPartitions(tree *tr); extern void compareBips(tree *tr, char *bootStrapFileName, analdef *adef); extern void computeRF(tree *tr, char *bootStrapFileName, analdef *adef); extern unsigned int **initBitVector(tree *tr, unsigned int *vectorLength); extern hashtable *copyHashTable(hashtable *src, unsigned int vectorLength); extern hashtable *initHashTable(unsigned int n); extern void cleanupHashTable(hashtable *h, int state); extern double convergenceCriterion(hashtable *h, int mxtips); extern void freeBitVectors(unsigned int **v, int n); extern void freeHashTable(hashtable *h); extern void printBothOpen(const char* format, ... ); extern void printBothOpenMPI(const char* format, ... ); extern void initRateMatrix(tree *tr); extern void bitVectorInitravSpecial(unsigned int **bitVectors, nodeptr p, int numsp, unsigned int vectorLength, hashtable *h, int treeNumber, int function, branchInfo *bInf, int *countBranches, int treeVectorLength, boolean traverseOnly, boolean computeWRF); extern int getIncrement(tree *tr, int model); extern void fastSearch(tree *tr, analdef *adef, rawdata *rdta, cruncheddata *cdta); extern void shSupports(tree *tr, analdef *adef, rawdata *rdta, cruncheddata *cdta); extern FILE *getNumberOfTrees(tree *tr, char *fileName, analdef *adef); extern void writeBinaryModel(tree *tr); extern void readBinaryModel(tree *tr); extern void treeEvaluateRandom (tree *tr, double smoothFactor); extern void treeEvaluateProgressive(tree *tr); extern void testGapped(tree *tr); extern boolean issubset(unsigned int* bipA, unsigned int* bipB, unsigned int vectorLen); extern boolean compatible(entry* e1, entry* e2, unsigned int bvlen); extern int *permutationSH(tree *tr, int nBootstrap, long _randomSeed); extern void updatePerSiteRates(tree *tr, boolean scaleRates); extern void restart(tree *tr); ExaML-3.0.21/parser/globalVariables.h000066400000000000000000000211201330315463200172750ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifdef _USE_ZLIB #include #endif #ifdef _FINE_GRAIN_MPI int processes; double *globalResult; #endif int processID; infoList iList; FILE *INFILE; #ifdef _USE_ZLIB gzFile byteFile; #else FILE *byteFile; #endif char run_id[128] = "", seq_file[1024] = "", weightFileName[1024] = "", modelFileName[1024] = "", byteFileName[1024] = "", infoFileName[1024] = "", secondaryStructureFileName[1024] = "", excludeFileName[1024], proteinModelFileName[1024]; char *protModels[NUM_PROT_MODELS] = {"DAYHOFF", "DCMUT", "JTT", "MTREV", "WAG", "RTREV", "CPREV", "VT", "BLOSUM62", "MTMAM", "LG", "MTART", "MTZOA", "PMB", "HIVB", "HIVW", "JTTDCMUT", "FLU", "STMTREV", "AUTO", "LG4M", "LG4X", "GTR"}; const char inverseMeaningBINARY[4] = {'_', '0', '1', '-'}; const char inverseMeaningDNA[16] = {'_', 'A', 'C', 'M', 'G', 'R', 'S', 'V', 'T', 'W', 'Y', 'H', 'K', 'D', 'B', '-'}; const char inverseMeaningPROT[23] = {'A','R', 'N', 'D', 'C', 'Q', 'E', 'G', 'H', 'I', 'L', 'K', 'M', 'F', 'P', 'S', 'T', 'W', 'Y', 'V', 'B', 'Z', '-'}; const char inverseMeaningGeneric32[33] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', '-'}; const char inverseMeaningGeneric64[33] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', '-'}; const unsigned int bitVectorIdentity[256] = {0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 ,19 ,20 ,21 ,22 ,23 ,24 ,25 ,26 , 27 ,28 ,29 ,30 ,31 ,32 ,33 ,34 ,35 ,36 ,37 ,38 ,39 ,40 ,41 ,42 ,43 ,44 ,45 ,46 ,47 ,48 ,49 ,50 ,51 , 52 ,53 ,54 ,55 ,56 ,57 ,58 ,59 ,60 ,61 ,62 ,63 ,64 ,65 ,66 ,67 ,68 ,69 ,70 ,71 ,72 ,73 ,74 ,75 ,76 , 77 ,78 ,79 ,80 ,81 ,82 ,83 ,84 ,85 ,86 ,87 ,88 ,89 ,90 ,91 ,92 ,93 ,94 ,95 ,96 ,97 ,98 ,99 ,100 ,101 , 102 ,103 ,104 ,105 ,106 ,107 ,108 ,109 ,110 ,111 ,112 ,113 ,114 ,115 ,116 ,117 ,118 ,119 ,120 ,121 ,122 , 123 ,124 ,125 ,126 ,127 ,128 ,129 ,130 ,131 ,132 ,133 ,134 ,135 ,136 ,137 ,138 ,139 ,140 ,141 ,142 ,143 , 144 ,145 ,146 ,147 ,148 ,149 ,150 ,151 ,152 ,153 ,154 ,155 ,156 ,157 ,158 ,159 ,160 ,161 ,162 ,163 ,164 , 165 ,166 ,167 ,168 ,169 ,170 ,171 ,172 ,173 ,174 ,175 ,176 ,177 ,178 ,179 ,180 ,181 ,182 ,183 ,184 ,185 , 186 ,187 ,188 ,189 ,190 ,191 ,192 ,193 ,194 ,195 ,196 ,197 ,198 ,199 ,200 ,201 ,202 ,203 ,204 ,205 ,206 , 207 ,208 ,209 ,210 ,211 ,212 ,213 ,214 ,215 ,216 ,217 ,218 ,219 ,220 ,221 ,222 ,223 ,224 ,225 ,226 ,227 , 228 ,229 ,230 ,231 ,232 ,233 ,234 ,235 ,236 ,237 ,238 ,239 ,240 ,241 ,242 ,243 ,244 ,245 ,246 ,247 ,248 , 249 ,250 ,251 ,252 ,253 ,254 ,255}; const unsigned int bitVectorAA[23] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 12 /* N | D */, 96 /*Q | E*/, 1048575 /* - */}; const unsigned int bitVectorSecondary[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255, 0, 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 0, 257, 514, 771, 1028, 1285, 1542, 1799, 2056, 2313, 2570, 2827, 3084, 3341, 3598, 3855, 0, 272, 544, 816, 1088, 1360, 1632, 1904, 2176, 2448, 2720, 2992, 3264, 3536, 3808, 4080, 0, 273, 546, 819, 1092, 1365, 1638, 1911, 2184, 2457, 2730, 3003, 3276, 3549, 3822, 4095, 0, 4096, 8192, 12288, 16384, 20480, 24576, 28672, 32768, 36864, 40960, 45056, 49152, 53248, 57344, 61440, 0, 4097, 8194, 12291, 16388, 20485, 24582, 28679, 32776, 36873, 40970, 45067, 49164, 53261, 57358, 61455, 0, 4112, 8224, 12336, 16448, 20560, 24672, 28784, 32896, 37008, 41120, 45232, 49344, 53456, 57568, 61680, 0, 4113, 8226, 12339, 16452, 20565, 24678, 28791, 32904, 37017, 41130, 45243, 49356, 53469, 57582, 61695, 0, 4352, 8704, 13056, 17408, 21760, 26112, 30464, 34816, 39168, 43520, 47872, 52224, 56576, 60928, 65280, 0, 4353, 8706, 13059, 17412, 21765, 26118, 30471, 34824, 39177, 43530, 47883, 52236, 56589, 60942, 65295, 0, 4368, 8736, 13104, 17472, 21840, 26208, 30576, 34944, 39312, 43680, 48048, 52416, 56784, 61152, 65520, 0, 4369, 8738, 13107, 17476, 21845, 26214, 30583, 34952, 39321, 43690, 48059, 52428, 56797, 61166, 65535}; const unsigned int bitVector32[33] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648u, 4294967295u}; /*const unsigned int bitVector64[65] = {};*/ const unsigned int mask32[32] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648U}; const char *secondaryModelList[21] = { "S6A (GTR)", "S6B", "S6C", "S6D", "S6E", "S7A (GTR)", "S7B", "S7C", "S7D", "S7E", "S7F", "S16 (GTR)", "S16A", "S16B", "S16C", "S16D", "S16E", "S16F", "S16I", "S16J", "S16K"}; double masterTime; double accumulatedTime; int partCount = 0; int optimizeRateCategoryInvocations = 1; partitionLengths pLengths[MAX_MODEL] = { /* BINARY */ // {4, 4, 2, 4, 2, 1, 2, 8, 2, 2, FALSE, FALSE, 3, inverseMeaningBINARY, 2, FALSE, bitVectorIdentity}, //eiLength changed from 2 -> 4 {4, 4, 2, 4, 4, 1, 2, 8, 2, 2, FALSE, FALSE, 3, inverseMeaningBINARY, 2, FALSE, bitVectorIdentity}, /* DNA */ {16, 16, 4, 16, 16, 6, 4, 64, 6, 4, FALSE, FALSE, 15, inverseMeaningDNA, 4, FALSE, bitVectorIdentity}, /* AA */ {400, 400, 20, 400, 400, 190, 20, 460, 190, 20, FALSE, FALSE, 22, inverseMeaningPROT, 20, TRUE, bitVectorAA}, /* SECONDARY_DATA */ {256, 256, 16, 256, 256, 120, 16, 4096, 120, 16, FALSE, FALSE, 255, (char*)NULL, 16, TRUE, bitVectorSecondary}, /* SECONDARY_DATA_6 */ {36, 36, 6, 36, 36, 15, 6, 384, 15, 6, FALSE, FALSE, 63, (char*)NULL, 6, TRUE, bitVectorIdentity}, /* SECONDARY_DATA_7 */ {49, 49, 7, 49, 49, 21, 7, 896, 21, 7, FALSE, FALSE, 127, (char*)NULL, 7, TRUE, bitVectorIdentity}, /* 32 states */ {1024, 1024, 32, 1024, 1024, 496, 32, 1056, 496, 32, FALSE, FALSE, 32, inverseMeaningGeneric32, 32, TRUE, bitVector32}, /* 64 states */ {4096, 4096, 64, 4096, 4096, 2016, 64, 4160, 64, 2016, FALSE, FALSE, 64, (char*)NULL, 64, TRUE, (unsigned int*)NULL} }; partitionLengths pLength; #ifdef _USE_PTHREADS volatile int NumberOfJobs; volatile int jobCycle = 0; volatile int threadJob = 0; volatile int NumberOfThreads; volatile double *reductionBuffer; volatile double *reductionBufferTwo; volatile char *barrierBuffer; #endif ExaML-3.0.21/parser/parsePartitions.c000066400000000000000000001033271330315463200174000ustar00rootroot00000000000000/* RAxML-VI-HPC (version 2.2) a program for sequential and parallel estimation of phylogenetic trees * Copyright August 2006 by Alexandros Stamatakis * * Partially derived from * fastDNAml, a program for estimation of phylogenetic trees from sequences by Gary J. Olsen * * and * * Programs of the PHYLIP package by Joe Felsenstein. * * This program is free software; you may redistribute it and/or modify its * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 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. * * * For any other enquiries send an Email to Alexandros Stamatakis * Alexandros.Stamatakis@epfl.ch * * When publishing work that is based on the results from RAxML-VI-HPC please cite: * * Alexandros Stamatakis:"RAxML-VI-HPC: maximum likelihood-based phylogenetic analyses with thousands of taxa and mixed models". * Bioinformatics 2006; doi: 10.1093/bioinformatics/btl446 */ #ifndef WIN32 #include #include #include #include #endif #include #include #include #include #include #include #include #include "axml.h" /*****************************FUNCTIONS FOR READING MULTIPLE MODEL SPECIFICATIONS************************************************/ extern char modelFileName[1024]; extern char excludeFileName[1024]; extern char proteinModelFileName[1024]; extern char secondaryStructureFileName[1024]; extern char seq_file[1024]; extern char *protModels[NUM_PROT_MODELS]; static boolean lineContainsOnlyWhiteChars(char *line) { int i, n = strlen(line); if(n == 0) return TRUE; for(i = 0; i < n; i++) { if(!whitechar(line[i])) return FALSE; } return TRUE; } static int isNum(char c) { return (c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6' || c == '7' || c == '8' || c == '9'); } static void skipWhites(char **ch) { while(**ch == ' ' || **ch == '\t') *ch = *ch + 1; } static void analyzeIdentifier(char **ch, int modelNumber, tree *tr) { char *start = *ch, ident[2048] = ""; char model[128] = ""; char thisModel[1024]; int i = 0, n, j; int containsComma = 0; while(**ch != '=') { if(**ch == '\n' || **ch == '\r') { printf("\nPartition file parsing error!\n"); printf("Each line must contain a \"=\" character\n"); printf("Offending line: %s\n", start); printf("ExaML will exit now.\n\n"); exit(-1); } if(**ch != ' ' && **ch != '\t') { ident[i] = **ch; i++; } *ch = *ch + 1; } n = i; i = 0; for(i = 0; i < n; i++) if(ident[i] == ',') containsComma = 1; if(!containsComma) { printf("Error, model file must have format: DNA or AA model, then a comma, and then the partition name\n"); exit(-1); } else { boolean found = FALSE; i = 0; while(ident[i] != ',') { model[i] = ident[i]; i++; } /* AA */ for(i = 0; i < NUM_PROT_MODELS && !found; i++) { strcpy(thisModel, protModels[i]); if(strcasecmp(model, thisModel) == 0) { tr->initialPartitionData[modelNumber].protModels = i; tr->initialPartitionData[modelNumber].protFreqs = 0; tr->initialPartitionData[modelNumber].dataType = AA_DATA; found = TRUE; } strcpy(thisModel, protModels[i]); strcat(thisModel, "F"); if(strcasecmp(model, thisModel) == 0) { tr->initialPartitionData[modelNumber].protModels = i; tr->initialPartitionData[modelNumber].protFreqs = 1; tr->initialPartitionData[modelNumber].dataType = AA_DATA; found = TRUE; if(tr->initialPartitionData[modelNumber].protModels == AUTO) { printf("\nError: Option AUTOF has been deprecated, exiting\n\n"); errorExit(-1); } if(tr->initialPartitionData[modelNumber].protModels == LG4M || tr->initialPartitionData[modelNumber].protModels == LG4X) { printf("\nError: Options LG4MF and LG4XF have been deprecated.\n"); printf("They shall only be used with the given base frequencies of the model, exiting\n\n"); errorExit(-1); } } strcpy(thisModel, protModels[i]); strcat(thisModel, "X"); if(strcasecmp(model, thisModel) == 0) { tr->initialPartitionData[modelNumber].protModels = i; tr->initialPartitionData[modelNumber].protFreqs = 0; tr->initialPartitionData[modelNumber].optimizeBaseFrequencies = TRUE; tr->initialPartitionData[modelNumber].dataType = AA_DATA; found = TRUE; if(tr->initialPartitionData[modelNumber].protModels == AUTO) { printf("\nError: Option AUTOX has been deprecated, exiting\n\n"); errorExit(-1); } if(tr->initialPartitionData[modelNumber].protModels == LG4M || tr->initialPartitionData[modelNumber].protModels == LG4X) { printf("\nError: Options LG4MX and LG4XX have been deprecated.\n"); printf("They shall only be used with the given base frequencies of the model, exiting\n\n"); errorExit(-1); } } /*if(found) printf("%s %d\n", model, i);*/ } if(!found) { if(strcasecmp(model, "DNA") == 0) { tr->initialPartitionData[modelNumber].protModels = -1; tr->initialPartitionData[modelNumber].protFreqs = -1; tr->initialPartitionData[modelNumber].dataType = DNA_DATA; tr->initialPartitionData[modelNumber].optimizeBaseFrequencies = FALSE; found = TRUE; } else { if(strcasecmp(model, "DNAX") == 0) { tr->initialPartitionData[modelNumber].protModels = -1; tr->initialPartitionData[modelNumber].protFreqs = -1; tr->initialPartitionData[modelNumber].dataType = DNA_DATA; tr->initialPartitionData[modelNumber].optimizeBaseFrequencies = TRUE; found = TRUE; } else { if(strcasecmp(model, "BIN") == 0) { tr->initialPartitionData[modelNumber].protModels = -1; tr->initialPartitionData[modelNumber].protFreqs = -1; tr->initialPartitionData[modelNumber].dataType = BINARY_DATA; tr->initialPartitionData[modelNumber].optimizeBaseFrequencies = FALSE; found = TRUE; } else { if(strcasecmp(model, "BINX") == 0) { tr->initialPartitionData[modelNumber].protModels = -1; tr->initialPartitionData[modelNumber].protFreqs = -1; tr->initialPartitionData[modelNumber].dataType = BINARY_DATA; tr->initialPartitionData[modelNumber].optimizeBaseFrequencies = TRUE; found = TRUE; } else { if(strcasecmp(model, "MULTI") == 0) { tr->initialPartitionData[modelNumber].protModels = -1; tr->initialPartitionData[modelNumber].protFreqs = -1; tr->initialPartitionData[modelNumber].dataType = GENERIC_32; found = TRUE; } else { if(strcasecmp(model, "CODON") == 0) { tr->initialPartitionData[modelNumber].protModels = -1; tr->initialPartitionData[modelNumber].protFreqs = -1; tr->initialPartitionData[modelNumber].dataType = GENERIC_64; found = TRUE; } } } } } } } if(!found) { printf("ERROR: you specified the unknown model %s for partition %d\n", model, modelNumber); exit(-1); } i = 0; while(ident[i++] != ','); tr->initialPartitionData[modelNumber].partitionName = (char*)malloc((n - i + 1) * sizeof(char)); j = 0; while(i < n) tr->initialPartitionData[modelNumber].partitionName[j++] = ident[i++]; tr->initialPartitionData[modelNumber].partitionName[j] = '\0'; } } static void setModel(int model, int position, int *a) { if(a[position] == -1) a[position] = model; else { printf("ERROR trying to assign model %d to position %d \n", model, position); printf("while already model %d has been assigned to this position\n", a[position]); exit(-1); } } static int myGetline(char **lineptr, int *n, FILE *stream) { char *line, *p; int size, copy, len; int chunkSize = 256 * sizeof(char); if (*lineptr == NULL || *n < 2) { line = (char *)realloc(*lineptr, chunkSize); if (line == NULL) return -1; *lineptr = line; *n = chunkSize; } line = *lineptr; size = *n; copy = size; p = line; while(1) { while (--copy > 0) { register int c = getc(stream); if (c == EOF) goto lose; else { *p++ = c; if(c == '\n' || c == '\r') goto win; } } /* Need to enlarge the line buffer. */ len = p - line; size *= 2; line = realloc (line, size); if (line == NULL) goto lose; *lineptr = line; *n = size; p = line + len; copy = size - len; } lose: if (p == *lineptr) return -1; /* Return a partial line since we got an error in the middle. */ win: *p = '\0'; return p - *lineptr; } static void nonContiguousError(analdef *adef) { if(adef->compressPatterns == FALSE) { printf("\nError: You are not allowed to use interleaved partitions, that is, assign non-contiguous sites\n"); printf("to the same partition model, when pattern compression is disabled via the -c flag!\n\n"); exit(-1); } } void parsePartitions(analdef *adef, rawdata *rdta, tree *tr) { FILE *f; int numberOfModels = 0; int nbytes = 0; char *ch; char *cc = (char *)NULL; char **p_names; int n, i, l; int lower, upper, modulo; char buf[256]; int **partitions; int pairsCount; int as, j; int k; f = myfopen(modelFileName, "rb"); while(myGetline(&cc, &nbytes, f) > -1) { if(!lineContainsOnlyWhiteChars(cc)) { numberOfModels++; } if(cc) free(cc); cc = (char *)NULL; } rewind(f); p_names = (char **)malloc(sizeof(char *) * numberOfModels); partitions = (int **)malloc(sizeof(int *) * numberOfModels); tr->initialPartitionData = (pInfo*)malloc(sizeof(pInfo) * numberOfModels); for(i = 0; i < numberOfModels; i++) { tr->initialPartitionData[i].protModels = adef->proteinMatrix; tr->initialPartitionData[i].protFreqs = adef->protEmpiricalFreqs; tr->initialPartitionData[i].dataType = -1; } for(i = 0; i < numberOfModels; i++) partitions[i] = (int *)NULL; i = 0; while(myGetline(&cc, &nbytes, f) > -1) { if(!lineContainsOnlyWhiteChars(cc)) { n = strlen(cc); p_names[i] = (char *)malloc(sizeof(char) * (n + 1)); strcpy(&(p_names[i][0]), cc); i++; } if(cc) free(cc); cc = (char *)NULL; } for(i = 0; i < numberOfModels; i++) { ch = p_names[i]; pairsCount = 0; skipWhites(&ch); if(*ch == '=') { printf("Identifier missing prior to '=' in %s\n", p_names[i]); exit(-1); } analyzeIdentifier(&ch, i, tr); ch++; numberPairs: pairsCount++; partitions[i] = (int *)realloc((void *)partitions[i], (1 + 3 * pairsCount) * sizeof(int)); partitions[i][0] = pairsCount; partitions[i][3 + 3 * (pairsCount - 1)] = -1; skipWhites(&ch); if(!isNum(*ch)) { printf("%c Number expected in %s\n", *ch, p_names[i]); exit(-1); } l = 0; while(isNum(*ch)) { /*printf("%c", *ch);*/ buf[l] = *ch; ch++; l++; } buf[l] = '\0'; lower = atoi(buf); partitions[i][1 + 3 * (pairsCount - 1)] = lower; skipWhites(&ch); /* NEW */ if((*ch != '-') && (*ch != ',')) { if(*ch == '\0' || *ch == '\n' || *ch == '\r') { upper = lower; goto SINGLE_NUMBER; } else { printf("'-' or ',' expected in %s\n", p_names[i]); exit(-1); } } if(*ch == ',') { upper = lower; nonContiguousError(adef); goto SINGLE_NUMBER; } /* END NEW */ ch++; skipWhites(&ch); if(!isNum(*ch)) { printf("%c Number expected in %s\n", *ch, p_names[i]); exit(-1); } l = 0; while(isNum(*ch)) { buf[l] = *ch; ch++; l++; } buf[l] = '\0'; upper = atoi(buf); SINGLE_NUMBER: partitions[i][2 + 3 * (pairsCount - 1)] = upper; if(upper < lower) { printf("Upper bound %d smaller than lower bound %d for this partition: %s\n", upper, lower, p_names[i]); exit(-1); } skipWhites(&ch); if(*ch == '\0' || *ch == '\n' || *ch == '\r') /* PC-LINEBREAK*/ { goto parsed; } if(*ch == ',') { ch++; nonContiguousError(adef); goto numberPairs; } if(*ch == '\\') { ch++; skipWhites(&ch); if(!isNum(*ch)) { printf("%c Number expected in %s\n", *ch, p_names[i]); exit(-1); } nonContiguousError(adef); l = 0; while(isNum(*ch)) { buf[l] = *ch; ch++; l++; } buf[l] = '\0'; modulo = atoi(buf); partitions[i][3 + 3 * (pairsCount - 1)] = modulo; skipWhites(&ch); if(*ch == '\0' || *ch == '\n' || *ch == '\r') { goto parsed; } if(*ch == ',') { ch++; nonContiguousError(adef); goto numberPairs; } } printf("\nError: You may be using \"/\" for specifying interleaved partitions in the model file, while it should be \"\\\" !\n\n"); assert(0); parsed: i = i; } fclose(f); /*********************************************************************************************************************/ for(i = 0; i <= rdta->sites; i++) tr->model[i] = -1; for(i = 0; i < numberOfModels; i++) { as = partitions[i][0]; for(j = 0; j < as; j++) { lower = partitions[i][1 + j * 3]; upper = partitions[i][2 + j * 3]; modulo = partitions[i][3 + j * 3]; if(modulo == -1) { for(k = lower; k <= upper; k++) setModel(i, k, tr->model); } else { for(k = lower; k <= upper; k += modulo) { if(k <= rdta->sites) setModel(i, k, tr->model); } } } } for(i = 1; i < rdta->sites + 1; i++) { if(tr->model[i] == -1) { printf("ERROR: Alignment Position %d has not been assigned any model\n", i); exit(-1); } } for(i = 0; i < numberOfModels; i++) { free(partitions[i]); free(p_names[i]); } free(partitions); free(p_names); tr->NumberOfModels = numberOfModels; } /*******************************************************************************************************************************/ void handleExcludeFile(tree *tr, analdef *adef, rawdata *rdta) { FILE *f; char buf[256]; int ch, j, value, i, state = 0, numberOfModels = 0, l = -1, excludeRegion = 0, excludedColumns = 0, modelCounter = 1; int *excludeArray, *countArray, *modelList; int **partitions; printf("\n\n"); f = myfopen(excludeFileName, "rb"); while((ch = getc(f)) != EOF) { if(ch == '-') numberOfModels++; } excludeArray = (int*)malloc(sizeof(int) * (rdta->sites + 1)); countArray = (int*)malloc(sizeof(int) * (rdta->sites + 1)); modelList = (int *)malloc((rdta->sites + 1)* sizeof(int)); partitions = (int **)malloc(sizeof(int *) * numberOfModels); for(i = 0; i < numberOfModels; i++) partitions[i] = (int *)malloc(sizeof(int) * 2); rewind(f); while((ch = getc(f)) != EOF) { switch(state) { case 0: /* get first number */ if(!whitechar(ch)) { if(!isNum(ch)) { printf("exclude file must have format: number-number [number-number]*\n"); exit(-1); } l = 0; buf[l++] = ch; state = 1; } break; case 1: /*get the number or detect - */ if(!isNum(ch) && ch != '-') { printf("exclude file must have format: number-number [number-number]*\n"); exit(-1); } if(isNum(ch)) { buf[l++] = ch; } else { buf[l++] = '\0'; value = atoi(buf); partitions[excludeRegion][0] = value; state = 2; } break; case 2: /*get second number */ if(!isNum(ch)) { printf("exclude file must have format: number-number [number-number]*\n"); exit(-1); } l = 0; buf[l++] = ch; state = 3; break; case 3: /* continue second number or find end */ if(!isNum(ch) && !whitechar(ch)) { printf("exclude file must have format: number-number [number-number]*\n"); exit(-1); } if(isNum(ch)) { buf[l++] = ch; } else { buf[l++] = '\0'; value = atoi(buf); partitions[excludeRegion][1] = value; excludeRegion++; state = 0; } break; default: assert(0); } } if(state == 3) { buf[l++] = '\0'; value = atoi(buf); partitions[excludeRegion][1] = value; excludeRegion++; } assert(excludeRegion == numberOfModels); for(i = 0; i <= rdta->sites; i++) { excludeArray[i] = -1; countArray[i] = 0; modelList[i] = -1; } for(i = 0; i < numberOfModels; i++) { int lower = partitions[i][0]; int upper = partitions[i][1]; if(lower > upper) { printf("Misspecified exclude region %d\n", i); printf("lower bound %d is greater than upper bound %d\n", lower, upper); exit(-1); } if(lower == 0) { printf("Misspecified exclude region %d\n", i); printf("lower bound must be greater than 0\n"); exit(-1); } if(upper > rdta->sites) { printf("Misspecified exclude region %d\n", i); printf("upper bound %d must be smaller than %d\n", upper, (rdta->sites + 1)); exit(-1); } for(j = lower; j <= upper; j++) { if(excludeArray[j] != -1) { printf("WARNING: Exclude regions %d and %d overlap at position %d (already excluded %d times)\n", excludeArray[j], i, j, countArray[j]); } excludeArray[j] = i; countArray[j] = countArray[j] + 1; } } for(i = 1; i <= rdta->sites; i++) { if(excludeArray[i] != -1) excludedColumns++; else { modelList[modelCounter] = tr->model[i]; modelCounter++; } } printf("You have excluded %d out of %d columns\n", excludedColumns, rdta->sites); if(excludedColumns == rdta->sites) { printf("Error: You have excluded all sites\n"); exit(-1); } if(adef->useSecondaryStructure && (excludedColumns > 0)) { char mfn[2048]; int countColumns; FILE *newFile; assert(adef->useMultipleModel); strcpy(mfn, secondaryStructureFileName); strcat(mfn, "."); strcat(mfn, excludeFileName); newFile = myfopen(mfn, "wb"); printBothOpen("\nA secondary structure file with analogous structure assignments for non-excluded columns is printed to file %s\n", mfn); for(i = 1, countColumns = 0; i <= rdta->sites; i++) { if(excludeArray[i] == -1) fprintf(newFile, "%c", tr->secondaryStructureInput[i - 1]); else countColumns++; } assert(countColumns == excludedColumns); fprintf(newFile,"\n"); fclose(newFile); } if(adef->useMultipleModel && (excludedColumns > 0)) { char mfn[2048]; FILE *newFile; strcpy(mfn, modelFileName); strcat(mfn, "."); strcat(mfn, excludeFileName); newFile = myfopen(mfn, "wb"); printf("\nA partition file with analogous model assignments for non-excluded columns is printed to file %s\n", mfn); for(i = 0; i < tr->NumberOfModels; i++) { boolean modelStillExists = FALSE; for(j = 1; (j <= rdta->sites) && (!modelStillExists); j++) { if(modelList[j] == i) modelStillExists = TRUE; } if(modelStillExists) { int k = 1; int lower, upper; int parts = 0; switch(tr->partitionData[i].dataType) { case AA_DATA: { char AAmodel[1024]; strcpy(AAmodel, protModels[tr->partitionData[i].protModels]); if(tr->partitionData[i].protFreqs) strcat(AAmodel, "F"); fprintf(newFile, "%s, ", AAmodel); } break; case DNA_DATA: fprintf(newFile, "DNA, "); break; case BINARY_DATA: fprintf(newFile, "BIN, "); break; case GENERIC_32: fprintf(newFile, "MULTI, "); break; case GENERIC_64: fprintf(newFile, "CODON, "); break; default: assert(0); } fprintf(newFile, "%s = ", tr->partitionData[i].partitionName); while(k <= rdta->sites) { if(modelList[k] == i) { lower = k; while((modelList[k + 1] == i) && (k <= rdta->sites)) k++; upper = k; if(lower == upper) { if(parts == 0) fprintf(newFile, "%d", lower); else fprintf(newFile, ",%d", lower); } else { if(parts == 0) fprintf(newFile, "%d-%d", lower, upper); else fprintf(newFile, ",%d-%d", lower, upper); } parts++; } k++; } fprintf(newFile, "\n"); } } fclose(newFile); } { FILE *newFile; char mfn[2048]; strcpy(mfn, seq_file); strcat(mfn, "."); strcat(mfn, excludeFileName); newFile = myfopen(mfn, "wb"); printf("\nAn alignment file with excluded columns is printed to file %s\n\n\n", mfn); fprintf(newFile, "%d %d\n", tr->mxtips, rdta->sites - excludedColumns); for(i = 1; i <= tr->mxtips; i++) { unsigned char *tipI = &(rdta->y[i][1]); fprintf(newFile, "%s ", tr->nameList[i]); for(j = 0; j < rdta->sites; j++) { if(excludeArray[j + 1] == -1) fprintf(newFile, "%c", getInverseMeaning(tr->dataVector[j + 1], tipI[j])); } fprintf(newFile, "\n"); } fclose(newFile); } fclose(f); for(i = 0; i < numberOfModels; i++) free(partitions[i]); free(partitions); free(excludeArray); free(countArray); free(modelList); } void parseProteinModel(analdef *adef) { FILE *f; int doublesRead = 0; int result = 0; int i, j; double acc = 0.0; assert(adef->userProteinModel); printf("User-defined prot mod %s\n", proteinModelFileName); adef->externalAAMatrix = (double*)malloc(420 * sizeof(double)); f = myfopen(proteinModelFileName, "rb"); while(doublesRead < 420) { result = fscanf(f, "%lf", &(adef->externalAAMatrix[doublesRead++])); if(result == EOF) { printf("Error protein model file must consist of exactly 420 entries \n"); printf("The first 400 entries are for the rates of the AA matrix, while the\n"); printf("last 20 should contain the empirical base frequencies\n"); printf("Reached End of File after %d entries\n", (doublesRead - 1)); exit(-1); } } fclose(f); /* CHECKS */ for(i = 0; i < 20; i++) for(j = 0; j < 20; j++) { if(i != j) { if(adef->externalAAMatrix[i * 20 + j] != adef->externalAAMatrix[j * 20 + i]) { printf("Error user-defined Protein model matrix must be symmetric\n"); printf("Entry P[%d][%d]=%f at position %d is not equal to P[%d][%d]=%f at position %d\n", i, j, adef->externalAAMatrix[i * 20 + j], (i * 20 + j), j, i, adef->externalAAMatrix[j * 20 + i], (j * 20 + i)); exit(-1); } } } acc = 0.0; for(i = 400; i < 420; i++) acc += adef->externalAAMatrix[i]; if((acc > 1.0 + 1.0E-6) || (acc < 1.0 - 1.0E-6)) { printf("Base frequencies in user-defined AA substitution matrix do not sum to 1.0\n"); printf("the sum is %1.80f\n", acc); exit(-1); } } void parseSecondaryStructure(tree *tr, analdef *adef, int sites) { if(adef->useSecondaryStructure) { FILE *f = myfopen(secondaryStructureFileName, "rb"); int i, k, countCharacters = 0, ch, *characters, **brackets, opening, closing, depth, numberOfSymbols, numSecondaryColumns; unsigned char bracketTypes[4][2] = {{'(', ')'}, {'<', '>'}, {'[', ']'}, {'{', '}'}}; numberOfSymbols = 4; tr->secondaryStructureInput = (char*)malloc(sizeof(char) * sites); while((ch = fgetc(f)) != EOF) { if(ch == '(' || ch == ')' || ch == '<' || ch == '>' || ch == '[' || ch == ']' || ch == '{' || ch == '}' || ch == '.') countCharacters++; else { if(!whitechar(ch)) { printf("Secondary Structure file %s contains character %c at position %d\n", secondaryStructureFileName, ch, countCharacters + 1); printf("Allowed Characters are \"( ) < > [ ] { } \" and \".\" \n"); errorExit(-1); } } } if(countCharacters != sites) { printf("Error: Alignment length is: %d, secondary structure file has length %d\n", sites, countCharacters); errorExit(-1); } characters = (int*)malloc(sizeof(int) * countCharacters); brackets = (int **)malloc(sizeof(int*) * numberOfSymbols); for(k = 0; k < numberOfSymbols; k++) brackets[k] = (int*)calloc(countCharacters, sizeof(int)); rewind(f); countCharacters = 0; while((ch = fgetc(f)) != EOF) { if(!whitechar(ch)) { tr->secondaryStructureInput[countCharacters] = ch; characters[countCharacters++] = ch; } } assert(countCharacters == sites); for(k = 0; k < numberOfSymbols; k++) { for(i = 0, opening = 0, closing = 0, depth = 0; i < countCharacters; i++) { if((characters[i] == bracketTypes[k][0] || characters[i] == bracketTypes[k][1]) && (tr->extendedDataVector[i+1] == AA_DATA || tr->extendedDataVector[i+1] == BINARY_DATA || tr->extendedDataVector[i+1] == GENERIC_32 || tr->extendedDataVector[i+1] == GENERIC_64)) { printf("Secondary Structure only for DNA character positions \n"); printf("I am at position %d of the secondary structure file and this is not part of a DNA partition\n", i+1); errorExit(-1); } if(characters[i] == bracketTypes[k][0]) { depth++; /*printf("%d %d\n", depth, i);*/ brackets[k][i] = depth; opening++; } if(characters[i] == bracketTypes[k][1]) { brackets[k][i] = depth; /*printf("%d %d\n", depth, i); */ depth--; closing++; } if(closing > opening) { printf("at position %d there is a closing bracket too much\n", i+1); errorExit(-1); } } assert(depth == 0 && countCharacters == sites); if(closing != opening) { printf("Number of opening brackets %d should be equal to number of closing brackets %d\n", opening, closing); errorExit(-1); } } for(i = 0, numSecondaryColumns = 0; i < countCharacters; i++) { int checkSum = 0; for(k = 0; k < numberOfSymbols; k++) { if(brackets[k][i] > 0) { checkSum++; switch(tr->secondaryStructureModel) { case SEC_16: case SEC_16_A: case SEC_16_B: case SEC_16_C: case SEC_16_D: case SEC_16_E: case SEC_16_F: case SEC_16_I: case SEC_16_J: case SEC_16_K: tr->extendedDataVector[i+1] = SECONDARY_DATA; break; case SEC_6_A: case SEC_6_B: case SEC_6_C: case SEC_6_D: case SEC_6_E: tr->extendedDataVector[i+1] = SECONDARY_DATA_6; break; case SEC_7_A: case SEC_7_B: case SEC_7_C: case SEC_7_D: case SEC_7_E: case SEC_7_F: tr->extendedDataVector[i+1] = SECONDARY_DATA_7; break; default: assert(0); } numSecondaryColumns++; } } assert(checkSum <= 1); } assert(numSecondaryColumns % 2 == 0); /*printf("Number of secondary columns: %d merged columns: %d\n", numSecondaryColumns, numSecondaryColumns / 2);*/ tr->numberOfSecondaryColumns = numSecondaryColumns; if(numSecondaryColumns > 0) { int model = tr->NumberOfModels; int countPairs; pInfo *partBuffer = (pInfo*)malloc(sizeof(pInfo) * tr->NumberOfModels); for(i = 1; i <= sites; i++) { for(k = 0; k < numberOfSymbols; k++) { if(brackets[k][i-1] > 0) tr->model[i] = model; } } /* now make a copy of partition data */ for(i = 0; i < tr->NumberOfModels; i++) { partBuffer[i].partitionName = (char*)malloc((strlen(tr->extendedPartitionData[i].partitionName) + 1) * sizeof(char)); strcpy(partBuffer[i].partitionName, tr->extendedPartitionData[i].partitionName); partBuffer[i].dataType = tr->extendedPartitionData[i].dataType; partBuffer[i].protModels= tr->extendedPartitionData[i].protModels; partBuffer[i].protFreqs= tr->extendedPartitionData[i].protFreqs; } for(i = 0; i < tr->NumberOfModels; i++) free(tr->extendedPartitionData[i].partitionName); free(tr->extendedPartitionData); tr->extendedPartitionData = (pInfo*)malloc(sizeof(pInfo) * (tr->NumberOfModels + 1)); for(i = 0; i < tr->NumberOfModels; i++) { tr->extendedPartitionData[i].partitionName = (char*)malloc((strlen(partBuffer[i].partitionName) + 1) * sizeof(char)); strcpy(tr->extendedPartitionData[i].partitionName, partBuffer[i].partitionName); tr->extendedPartitionData[i].dataType = partBuffer[i].dataType; tr->extendedPartitionData[i].protModels= partBuffer[i].protModels; tr->extendedPartitionData[i].protFreqs= partBuffer[i].protFreqs; free(partBuffer[i].partitionName); } free(partBuffer); tr->extendedPartitionData[i].partitionName = (char*)malloc(64 * sizeof(char)); switch(tr->secondaryStructureModel) { case SEC_16: case SEC_16_A: case SEC_16_B: case SEC_16_C: case SEC_16_D: case SEC_16_E: case SEC_16_F: case SEC_16_I: case SEC_16_J: case SEC_16_K: strcpy(tr->extendedPartitionData[i].partitionName, "SECONDARY STRUCTURE 16 STATE MODEL"); tr->extendedPartitionData[i].dataType = SECONDARY_DATA; break; case SEC_6_A: case SEC_6_B: case SEC_6_C: case SEC_6_D: case SEC_6_E: strcpy(tr->extendedPartitionData[i].partitionName, "SECONDARY STRUCTURE 6 STATE MODEL"); tr->extendedPartitionData[i].dataType = SECONDARY_DATA_6; break; case SEC_7_A: case SEC_7_B: case SEC_7_C: case SEC_7_D: case SEC_7_E: case SEC_7_F: strcpy(tr->extendedPartitionData[i].partitionName, "SECONDARY STRUCTURE 7 STATE MODEL"); tr->extendedPartitionData[i].dataType = SECONDARY_DATA_7; break; default: assert(0); } tr->extendedPartitionData[i].protModels= -1; tr->extendedPartitionData[i].protFreqs= -1; tr->NumberOfModels++; if(adef->perGeneBranchLengths) { /*if(tr->NumberOfModels > NUM_BRANCHES) { printf("You are trying to use %d partitioned models for an individual per-gene branch length estimate.\n", tr->NumberOfModels); printf("Currently only %d are allowed to improve efficiency.\n", NUM_BRANCHES); printf("Note that the number of partitions has automatically been incremented by one to accomodate secondary structure models\n"); printf("\n"); printf("In order to change this please replace the line \"#define NUM_BRANCHES %d\" in file \"axml.h\" \n", NUM_BRANCHES); printf("by \"#define NUM_BRANCHES %d\" and then re-compile RAxML.\n", tr->NumberOfModels); exit(-1); } else*/ { tr->numBranches = tr->NumberOfModels; } } assert(countCharacters == sites); tr->secondaryStructurePairs = (int*)malloc(sizeof(int) * countCharacters); for(i = 0; i < countCharacters; i++) tr->secondaryStructurePairs[i] = -1; /* for(i = 0; i < countCharacters; i++) printf("%d", brackets[i]); printf("\n"); */ countPairs = 0; for(k = 0; k < numberOfSymbols; k++) { i = 0; while(i < countCharacters) { int j = i, bracket = 0, openBracket, closeBracket; while(j < countCharacters && ((bracket = brackets[k][j]) == 0)) { i++; j++; } if(j == countCharacters) { assert(bracket == 0); break; } openBracket = j; j++; while(bracket != brackets[k][j] && j < countCharacters) j++; assert(j < countCharacters); closeBracket = j; assert(closeBracket < countCharacters && openBracket < countCharacters); assert(brackets[k][closeBracket] > 0 && brackets[k][openBracket] > 0); /*printf("%d %d %d\n", openBracket, closeBracket, bracket);*/ brackets[k][closeBracket] = 0; brackets[k][openBracket] = 0; countPairs++; tr->secondaryStructurePairs[closeBracket] = openBracket; tr->secondaryStructurePairs[openBracket] = closeBracket; } assert(i == countCharacters); } assert(countPairs == numSecondaryColumns / 2); /*for(i = 0; i < countCharacters; i++) printf("%d ", tr->secondaryStructurePairs[i]); printf("\n");*/ adef->useMultipleModel = TRUE; } for(k = 0; k < numberOfSymbols; k++) free(brackets[k]); free(brackets); free(characters); fclose(f); } } ExaML-3.0.21/testData/000077500000000000000000000000001330315463200143145ustar00rootroot00000000000000ExaML-3.0.21/testData/140000066400000000000000000004577141330315463200145650ustar00rootroot00000000000000 140 1104 Seq1 MDFIDTESSSESDSELHRQLLL-----QQRDETDTVLRELVQGGCNRKRRASSTCTVPQTVPKAMRLYSSNFFCLTSKNRKLSALAAFKKMYNASYYEVAREYKSDKTQSYEWVLGCSPERVSALNCLKGVTEFILYD-YSALFYLEFYCSKNREGVRRLLNVDTDSILLLNPPNKRSVLAALFYQKLVLAHGD--FPDWCR-D-ILSNFELSQMIQWALDNKHHDEGSIAYHYAIHAEQDNNAKLWLQSNQQAKYVRDAATMVRHFVKGRLHSITMSEHIAAQDGWKKILVFLTFQHINFKEFISILCMWLKGPKKSCITIAGVPDSGKSMFAYSLIKFLNGSVLSFANSKSHFWLQPLTECKAALIDDVTLPCWDYVDTFLRNALDGNAICDCKHRAPVQTKCPPLLLTSNYDPRLHYLNSRIQFLLFNRVIPLYG-TQPRFYIEPADWRSFFQKYSEDLQLYDGEGELLQKLLQLQERESQLLEETHTLKEMEEYWRKQQIILTYAATKGLKYLGLTRVPSQVVSEHMAKDAILMQMLITSISKSRFSDLDFNLDFMPQTVKKVPKLGAKTVRVTYGGDPDTETEYVYWG-RLLKH-DPLTDRWEECSGVDLAGIYYKSYTSVWSNEAALHRTAVERLIDDAVDPVGLCFEGYTHQVKTIRRRLYATNLR-YQRVSSTWHWFDSKEDRDNFAKNFTGA---NVPPLYIPSQVTVSPYSTDDYVTPTEHLYHLQTRLITVGNPYFVIAVPKVSANQYRCFRLQLPDPNGFPLPSNNLYDPEHRLVWQLVGLEIDRGQPLGVGLVAAPAFNRGRDAEANSRADNRISCAEPKHNQMLIVGCAPAVGQHWGLGTKCTKCPPIELVNSNIQDGDMSDIGFGAMDFNALGLNRSDVPMELAASVAKYPDWIKMHTDAHGDSCFYYVTREQIYARRYWQQSGYMACPSGSVITSDTNLFNRPYWLSRAQGTNNGILWNENLFVTVLDNSRNVIMKIYDWKNYYECVRHVEEYGISAIVRLCRVTLTAENLGSIYRMNPDILKKWGIQ-EAPLAEDKYSQAITCPPNNAPDPYKTENYWTVDCRERLSDDLLRYPLGRKFLQLPRRKR Seq2 MDFITIESSQCEEEESHVQLL-------QDFEIIPKR--VAGHYTRKRRRTRSPGDPKKTVPKTIRQYNRPHKCLVSKNKTLTALAVFKELYTASFTEVTRTFKSDKTQSYEWVLGCSHIALEAVKVLIHNTEHVILD-HLGVYYVGFTVSKSREGLLRFLNIFTENVVLSNPPNKRSVLSALFFDKLVQVSGD--KPQWMI-D-IITSFELSKMIQWALDNNMYDEGAIAYNYALLADTDLNAQLWLKHNSQAKYVRDAATMCRHYRRGQMQAIGVMEHLATRG-WKRIIVFLRYQHVDHHTFINDLKYWIVNPKRSTIAIVGIPDSGKSMFGMSLIQFLDGRVLSFSNHKSHFWLQPLSETRYALVDDVTWPAWDYMDVYMRNALDGNPICDCKHRAPIQTKCPPLLLTSNYDPRERYLLSRITFMSFNRSIPCIG-GQPRFLISPADWRSFMLKFRKELDI---TGELRESLERLQRREAEILEDPTDLQTITEYWKKQHLLLYAAGQKGYKQLGLQRVPPLHVSEQEARDGILMVVLLRSLLGTPHALRTWSLEWGPRLFRTPPKFGPHTVRVFYCNDPSTETEYPYWD-SYLFY-DPTTGEWTEGIGYDNVGIWHRGYHMIWRDEARRVGTRLDRLIAEAKDPPGLCFVGRTGQLKTIRYRVQTGPYN-VTRISTTWHWFNDSHQREVFARAFVV-APALPSALYIPNAAPLPLFTTDDFVSPTDYVYHVNTRLLMVGNPYFRAAVPKVSGNQYRVFRLKLPDPNDQFDLPDGLFDPEFRYVWQLVGLEVCRGQPLGVGISAAPAFNKGRDVESPARLDNRVSVGDPKQNQMLIVGCAPAYGQHWGKATPCTQCPPIELISSTLQDGDMCDIGFGCMDFAALAANTSDIPLELINTVSKYPDWIRMHNDPKGDCCFFLMRREQLYARHMWQHSGYMCVPSGSVYTSDTQLFNRPYWLSKAQGPNNGVCWGDDLFITVLDNTRGGVMNIYKPSDFREYVRHVEEYELSCVLRLCKVPLSPDVLASLYRAVPHVLGRWGISEYPQAPEDKYSQATRCDTPTPVDPWADMTFWTVDCTSRISPELPRFPLGRKFLALPGKRR Seq3 MTDPNSKGFGDWCLLDISDLLDQGN-SLELFHQQECEQSEEQLQKLKRKY-LSPSPRLESIKSKRRLFDSGLELLRSSNKKATLMAKFKESFGVGFNELTRQFKSHKTCCKDWVYAVHDDLFESSKLLQQHCDYIWVR--MSLYLLCFKAGKNRGTVHKLILNVHEQQILSEPPKLRNTAAALFWYKGCMGSGAGPYPDWIAQQTILGHFDFSAMVQWAFHNHLLDEADIAYQYARLAPEDANAVAWLAHNNQAKFVRECAYMVRFYKKGQMRDMSISEWIYTKGHWSDIVKFIRYQNINFIVFLTALKEFLHSPKKNCILIYGPPNSGKSSFAMSLIRVLKGRVLSFVNSKSQFWLQPLSECKIALLDDVTDPCWIYMDTYLRNGLDGHYVSDCKYRAPTQMKFPPLLLTSNINVHGEYLHTTIKGFEFPNPFPMKADNTPQFELTDQSWKSFFTRLWTQLDLEEEFQCLSERFNALQDQLMNIYEAEQTLQAQIKHWRKEPVLLYYAREKGVTRLGYQPVPVKAVSETKAKEAIAMVLQLESLQTSDFAHEPWTLDTSIETFRSAPHFKKGPLPVEVIYDNDPDNANLYTMWTYVYYMDAD-DKWHKARSVNHIGIYYKNYYVLFADDAKRYTGRLGRLLEEARDPPVIIVKGAANTLKNVRNRAKIKYMGLFRSFSTTWSWFSSYTQRRDFDEAVRYPWHSANGKVYLPPSTPVRVQSTDEYIQRTNIYYHAFSRLLTVGHPYFKLEVPKVSGNQHRVFRLKLPDPNRFALPDMSVYNPDERLVWACRGLEIGRGQPLGVRSTGHPYFNKVKDTENSNAYDDRQDTSDPKQIQMFIVGCTPCIGEHWDKAVPCGLCPPIELKNTYIQDGDMADIGFGNMNFKALQDSRSDVSLDIVNETCKYPDFLKMQNDIYGDACFFYARREQCYARHFFVRGGYFPTVSGSLVSSDAQLFNRPFWLQRAQGHNNGILWANQMFITVVDNTRNTNFSIYNADQFREYQRHVEEYEISLILQLCKVPLKAQVLAQINAMNSSLLEDWQLGFVPTPIQDTYSLATRCPPKEKEDPYKGLHFWDVDLTERLSLDLDQYSLGRKFLFQAGKRK Seq4 MADPKGSGFGDWCILDISDLIDQGN-SLELFHQQECKQSEEQLQKLKRKC-LSPSPRLQSIKSKRRLFDSGVELLRSSNKKATLMAKFKAAFGVGFNELTRQFKSHKTCCNHWVYAVHDDLFESSKLLQQHCDYLWVR--MSLYLLCFKAGKNRGTVHKLMLNVHEQQILSEPPKLRNTAAALFWYKGCMGSGVGPYPDWIAQQTILGHFDFSQMVQWAFDNQLVDEGDIAYRYARLAPEDANAVAWLAHNSQAKFVRECAAMVRFYKKGQMRDMSMSEWIYTKGHWSDIVKFLRYQEVNFIMFLAAFKDFLHSPKKNCILIHGPPNSGKSSFAMSLIRVLKGRVLSFVNSKSQFWLQPLSECKIALIDDVTDPCWLYMDNYLRNGLDGHYVSDCKYKAPMQTKFPPLLLTSNINVHEEYLHSRIKGFAFPNPFPMKSDDTPQFELTDQSWKSFFERLWTQLELEDEFQCLSERFNALQDLLMNIYEAEQTLEAQIKHWRQEAVLLYFARQRGVTRLGYQPVPVKAVSEAKAKEAIAMVLQLQSLQTSEYASETWTLDTSIETFRSAPHFKKGPVPVEVIYDNDADNANLYTMWTYVYYME-D-DVWHKARSVNETGIYYKYYYVLFADDARKYTGRLGRLLEEALDPPVILVRGEANTLKCFRNRAKIKYMGLYRSFSTTWSWFSSYNQRRDFDDVVRYPWHSANGKVYLPPSTPVRVQSTDEYIQRTNIYYHAFSRLLTVGHPYFKLEVPKVSGNQHRVFRLKLPDPNRFALADMSVYNPDERLVWSCRGLEIGRGQPLGVGSTGHPLFNKLKDTENSNSYDDRQDTSDPKQIQMFIVGCTPCIGEHWDKAIPCRLCPPIELKTTYIEDGDMADIGFGNLNFKNLQESRSDVSLDIVNETCKYPDFLKMQNDVYGDACFFYARREQCYARHFFVRGGYYPTVSGSLVSSDAQLFNRPFWLQRAQGHNNGILWANQMFITVVDNTRNTNFSIYTAEQFREYQRHVEEYEISLILQLCKVPLKAEVLAQINAMNSSLLEDWQLGFVPTPIQDTYSLATRCPPKEKEDPYKGLKFWDVDLTERLSLDLDQYSLGRKFLFQAGKRK Seq5 MADSKGSGFGDWCILDISDLLDQGN-SRELFHQQECKQSEEQLQKLKRKY-LSPSPRLESIKSKRRLFDSGLELLRSSNQKATLLAKFKQAFGVGFNELTRQFKSYKTCCNHWVYAVHDDLFESSKLLQQHCDYIWVR--MSLYLLCFKAGKNRGTVHKLILNVHEQQILSEPPKLRNTAAALFWYKGCMGPGVGPYPEWIAQLTILGHFDLSVMVQWAFDNNLFEEADIAYGYARLAPEDSNAVAWLAHNNQAKYVRECAMMVRYYKKGQMRDMSMSEWIYTRGQWSSIVKFLRYQEINFISFLAALKDLLHSPKRNCILFHGPPNTGKSSFGMSLIKVLRGRVLSFVNSKSQFWLQPLGECKIALLDDVTDPCWVYMDQYLRNGLDGHFVSDCKYRAPMQTKFPPLILTSNINVHAEYLHSRIKGFEFKNPFPMKADNTPQFELTDQSWKSFFTRLWTHLDLEDEFQCLSERFNALQEQLMNIYEAEQTLKAQILHWRKEAVTLYFARQKGINRLGYQPVPALAISEARAKEAIYMVLQLESLQKSAFALEPWTLDTSTETFKSAPHFKKGPVPVEVIYDKDEANANLYTMWTFVYYMDSD-DVWHKTTSVNQTGIYYKHYYVLFADDAKRYSGRLGRLLEEARDPPVILVRGDANTLKCFRNRARNKYRGLFRSFSTTFSWFSCLTQRRDFDDAVKYPWHSANGKVYLPPSTPVRVQSTDEYIQRTNIYYHANTRLLTVGHPYFTLEVPKVSGNQHRVFRLKLPDPNRFALADMSVYNPDERLVWACRGLEIGRGQPLGVGSTGHPYFNKVKDTENSNSYDDRQDTSDPKQIQMFIVGCTPCIGEHWDKAEPCGLCPPIELKNTYIQDGDMADIGFGNINFKALQHSRSDVSLDIVNETCKYPDFLKMQNDVYGDACFFYARREQCYARHFFVRGGYFPTVSGSLVSSDAQLFNRPFWLQRAQGHNNGILWANQMFVTVVDNTRNTNFSIYNADNFREYQRHVEEYEISVILQLCKVPLKAEVLAQINAMNSSLLEEWQLGFVPTPIQDTYSLATRCPPKEKVDPYKGLNFWDVDMTERLSLDLDQYSLGRKFLFQAGKRK Seq6 MADHKGSGLSEWCILDISDLLDQGN-SLELFHQQECEQSEEQLQKLKRKY-LSPSPRLQSIKSKRRLFDSGVELLRSSNTKATLMAKFKEAFGDGFNELTRQFKSYKTCCNYWVYAVHD-VYESSKLLQQHCDYIWVR--ITLYLLSFKAGKNRGTVHKLMLNVQEQQILSEPPKLRHTAAALFWYKGGMGTGTGSYPDWIAHQTILGHFDFSVMVQWAFDNNHFEEADIAYGYAKLAPEDANAVAWLAHNSQAKFVRECAAMVRFYKRGQMREMTMSEWIYTRGHWSSIVKFVRYQGINFITFLAALKDFLHSPKRNCLLIYGPPNTGKSTFAMSLIQVLKGRVLSYVNSKSQFWLQPLGDCKIALLDDVTDPCWLYMDTFLRNGLDGHVVSDCKYKAPMQIKFPPLLLTSNINLHEEYLHSRVRGFEFPNPFPMKPDNTPEFELTDQSWKSFFARLWTQLELEDEFQCLSERFNVLQDQLMNIYEAEQTLEAQIAHWRKEAVLLYFARQKGITRIGYQPVPPLAVSEAKAKQAIGIMLQLQSLQKSEFADEPWTLDTSIETYKNAPHFKKGATPVEVIYDKQPDNANVYTMWKHIYYTDAD-DKWHKTTSVNQTGIYYRHYYVVFADDARRYTGRLGRLLDEAIDPPVILVRGEANTLKCFRNRARVRYRGLFKYFSTTWSWFTSAGQRKDFDETVKYPWQSATGKVYLPPSTPVRVQSTDEYIQRTNIYYHANTRLLTVGHPYFTLQVPKVSGNQHRVFRLKLPDPNRFALADMSVYNPDERLVWACRGLEISRGQPLGVGSTGHPYFNKVKDTENSNSYDDRQNTSDPKQIQMFIVGCTPCIGEHWEKAIPCGLCPPIELKNTVIEDGDMADIGFGNMNFKTLQQNRSDVSLDIVNEICKYPDFLKMQNDVYGDACFFYARREQCYARHFFVRGGYFPTVSGSLVSSDAQLFNRPFWLQRAQGHNNGILWANQMFVTVVDNTRNTNFSIYKSTQFREYLRHVEEYEISLILQLCKIPLKADVLAQINAMNSSLLEEWQLGFVPTPIHDTYSLATRCPPKEK-DPYAKFNFWNVDLTERLSLDLDQYSLGRKFLFQAGKRK Seq7 MADSKGSGLSDWCILDVSDLLDQGN-SLELFHQQECEQSEEQLQILKRKY-LSPSPRLESIKSKRRLFDSGLELLRSSNIKATLMAKFKESFGVGFNELTRQFKSYKTCCNDWVYAVHDDLFESSKLLQQHCDYIWVR--MTLYLLCFKAGKNRGTVHKLMLNVQEQQILSEPPKLRNTAAALFWYKGGMGSGAGTYPDWIAHQTILGHFDFSAMVQWAFDNNYLEEPDIAYQYAKLAPEDSNAVAWLAHNQQAKFVRECAAMVRFYKKGQMKEMSMSEWIHTKGHWSDIVKFLRYQDVNFITFLAAFKNFLHAPKHNCILIYGPPNSGKSSFAMSLIKVLKGRVLSFVNSKSQFWLQPLGESKIALLDDVTDPCWVYIDTYLRNGLDGHFVSDCKYKAPVQIKFPPLLLTSNINVHGEYLHSRIKGFEFPHPFPMKPDNTPQFQLTDQSWKSFFERLWTQLDLEEEFQCLSERFNVLQDQLMNIYEAEHTLETQIAHWRREAVLLYYARQKGITRLGYQPVPTLAVSEAKAKEAIGIMLQLQSLQKSEYASENWTLDTSAETYNNVPHFKKGPVPVEVIYDKEPENANVYTMWKYVYYMDPE-DVWHKTTSVNQTGIYYKHYYVLFADGARMYRGRLGRLLEEALDPPVIICKGGANTLKCFRNRARHKYTGLFKAFSTTWSWFTSTNQRKDFDETVKYPWQAAHGKVYLPPSTPVRVQSTDEYIQRTNIYYHANTRLLTVGHPYFKLEVPKVSGNQHRVFRLKLPDPNRFALADMSVYNPDERLVWACRGLEISRGQPLGVGSTGHPYFNKIKDTENSNNYDDRQNTSDPKQIQMFIVGCTPCVGEHWEKALPCGVCPPIELKNTFIEDGDMADIGFGNMNFKTLQQNRSDVSLDIVNETCKYPDFLKMQNDVYGDACFFYARREQCYARHFFVRGGYFPTVSGSLVSSDAQLFNRPFWLQRAQGHNNGILWANQMFVTVVDNTRNTNFSIYDSQKFREYLRHVEEYEISLILQLCKVPLKAEVLAQINAMNSSLLEDWQLGFVPTPIHDTYSLATRCPPKEK-DPYDGLSFWTVDMTERLSLDLDQYSLGRKFLFQAGKRK Seq8 MADPKGSGLGDWCILDVSDLLDQGN-SLELFHQQECKQSEEQLQILKRKY-LSPSPRLELMKSKRRLFDSGLELLRSSNRKATLMAKFKDAFGVGFNELTRQFKSYKTCCNHRVYAVHDDLFESSKLLQQHCDYIWVR--MTLYLLCFKAGKNRGTVHKLLLNVQEQQILSEPPKLRNTAAALFWYKGGMGSGAGKYPDWIAQQTVLGHFDFSVMVQWAFDNNHVDEADIAYQYARLAPEDSNAVAWLAHNSQAKFVRDCAAMVRFYKNLQMREMSMSEWIYTRGHWSSIVKFLGYQGVNFIMFLAALKNFLHAPKQNCILIHGPPNSGKSSFAMSLIKVLKGRVLSFVNSRSQFWLQPLGECKIALIDDVTDPCWLYMDTYLRNGLDGHFVSDCKYKAPVQTKFLPLLLTSNINVHEEYLHSRIKGFEFPNPFPMKSDNTPQFELTDQSWKSFFERLWTQLELEEEFQCLSERFNVLQDQLMNIYEAEHTLETQIAHWRREAVLLYVARQKGITRLGYQPVPPLAVSEGKAKEAIGIMLQLQSLQKSEYASEPWTLDTSAETYRNAPHFKKGPIPVEVIYDKESGNANVYTMWKFVYYMDPE-DVWHKTTSVNHNGIHYKHYYVLFADGARTYRGRLGRLLEEALDPPVILCKGGANTLKCFRNRTRGKYTGLFRAISTTWSWFSSDGQRKHFDETVKYPWHSANGKVYLPPSTPVRVQSTDEYIQRTNIYYHANTRLLTVGHPYFKLEVPKVSGNQHRVFRLKLPDPNRFALADKSVYNPDERLVWGCRGLEISRGQPLGVGSTGHPYFNKVKDTENTNNYDDRQNTSDPKQIQMFIVGCTPCVGEHWEKALPCGICPPIELKNTFIEDGDMADIGFGNMNFKTLQQNRADVSLDIVNETCKYPDFLKMQNDVYGDACFFYARREQCYARHFFVRGRYFPTVSGSLVSSDAQLFNRPFWLQRAQGHNNGILWANQMFVTVVDNTRNTNFSIYDSQKFREYLRHVEEYEISIILQLCKIPLQAEVLAQINAMNPSLLEDWQLGFVPTPIQDTYSLATRCPPKEK-DPYEKLTFWNVDLTERLSLDLDQYSLGRKFLFQAGKRK Seq9 MADPKGSGLDDWCIVDISELLDQGN-SRELFHQQESKESEEHLQKLKRKY-LSPSPRLESIKSKRRLFDSGLELLRASNNKAILMAKFKEAFGVGFNDLTRQFKSYKTCCNHWVYAVHDDLLESSKLLQQHCDYVWIR--MSLFLLCFKVGKNRGTVHKLMLNVHEKQILSEPPKLRNVAAALFWYKGAMGSGTGPYPDWMAHQTIVGHFDMSVMVQWAFDNNYLDEADIAYQYAKLAPEDSNAVAWLAHNNQARFVRECASMVRFYKKGQMKEMSMSEWIHTRGHWSTIAKFLRYQQVNFIMFLAALKDMLHSPKRNCILIYGPPNTGKSAFTMSLIRVLRGRVLSFVNSKSQFWLQPMSECKIALIDDVTDPCWLYMDTYLRNGLDGHYVSDCKHKAPIQTKFPALLLTSNINVHNEYLHSRIKGFEFPNPFPMKADNTPEFELTDQSWKSFFTRLWNQLELEDEFQCLSDRFNALQDQLMNIYEAANTLESQIEHWRKEAVLLYFARQNGVTRLGYQVVPTLAISEAKAKQAIGMVLQLQSLQKSQFGSEPWSLDTSGETFRSAPHFKKGPVSVEVIYDNDKDNANAYTMWKHIYYQD-DDEQWHKSASVNHTGIYYRNYYVLFADDATRYTGRLGRLLDEALDPPVILVRGDPNTLRCFRNRAKQKFTGLYRAFSTAWSWFFSFNQRRDFDQTVKYPWQAASGKVYLPPSTPVRVQSTDEYVQRTNIYYHAYSRLLTVGHPYFKIKVPKVSGNQHRVFRLKLPDPNRFALADMSVYNPDERLVWACRGIEIGRGQPLGVGSVGHPLFNKVGDTENPNSYDDRQNVSDPKQLQMFIIGCAPCMGEHWDRALPCGSCPPIELKNTVIEDGDMADIGYGNLNFKALQENRSDVSLDIVNEICKYPDFLKMQNDVYGDSCFFYARREQCYARHFFVRGGYFPTVSGSLVSSDAQLFNRPFWLQRAQGHNNGICWFNQLFVTVVDNTRNTNFSIYTSQKFQEYLRHVEEYEMSLILQLCKIPLTAEVLAQINAMNSNILEEWQLGFVPAPIHDTYSAATRCPPKEREDPYKNFNFWNVDLTERLSLDLDQYSLGRKFLFQAGKRK Seq10 MADPKGSGLEDWCIVDISELLDQGN-SRELFHQQESKESEEQLQKLKRKY-LSPSPRLESIKSKRRLFDSGLELLRASNNKAILMAKFKEFFGVGFNDLTRQFKSYKTCCNAWVYAVHDDLLESSKLLQQHCDYIWIR--MSLFLLCFKVGKNRGTVHKLMLNVHEKQIISEPPKLRNVAAALFWYKGAMGSGAGPYPDWIAQQTIVGHFDMSAMVQWAFDNNYLDEADIAYQYAKLAPEDSNAVAWLAHNNQARYVREVASMVRFYKKGQMKEMSMSEWIHTRGHWSTIAKFLRYQQVNFIMFLAALKDMLHSPKRNCILIYGPPNTGKSAFTMSLIHVLRGRVLSFVNSKSQFWLQPMSECKIALIDDVTDPCWIYMDTYLRNGLDGHVVSDCKHKAPMQTKFPALLLTSNINVHNEYLHSRIKGFEFPNPFPMKADNTPEFELTDQSWKSFFTRLWNQLELEDEFQCLSDRFNVLQDQLMNIYEAANTIESQIEHWRKEAVLLYFARQKGVTRLGYQYVPPLAVSESRAKQAIGMMLQLQSLQKSEYAKEPWSLDTSAETFRSPPHFKKGPVSVEVIYDNDKDNANAYTMWRYVYYVD-DDDQWHKSPSVNHTGIYFRHYYVLFADDASRYTGRLGRLLDEALDPPVILVRGEPNTLKCFRNRAKLKYAGLYKAFSTAWSWFFSFEQRKDFDKTVKYPWQAASGKVYLPPSTPVRVQSTDEYVQRTNIYYHAYSRLLTVGHPYFKIKVPKVSGNQHRVFRLKLPDPNRFALADMSVYNPDERLVWACRGIEIGRGQPLGVGSVGHPLFNKVGDTENPSSYDDRQNVSDPKQLQMFIIGCAPCLGEHWDKAIPCGSCPPIELINSAIQDGDMADIGYGNLNFKALQQNRSDVSLDIVNETCKYPDFLKMQNDVYGDSCFFYARREQCYARHFFVRGGYFPTVSGSLVSSDAQLFNRPFWLQRAQGHNNGICWFNQLFVTVVDNTRNTNFSIYKAESFQEYLRHVEEYELSLILQLCKVPLTAEVLAQINAMNANILEEWQLGFVPAPIHDTYSAATRCPPKEREDPYKNMKFWDVDLTERLSLDLDQYSLGRKFLFQAGKRK Seq11 MADPKGSGLDDWCIVDISELLDQGN-SRELFHQQECKDSEEQLQKLKRKY-ISPSPRLESIKSKRRLFDSGLELLRASNHKAILLAKFKEAFGIGFNDLTRQFKSYKTCCNDWVYAVHEDLLESSKLLQQHCDYIWIR--MSLFLLCFKAGKNRGTVHKLMLNVHEKQILSEPPKLRNVAAALFWYKGAMGSGAGPYPNWMAQQTIVGHFDLSEMIQWAFDHNYLDEADIAFQYAKLAPENSNAVAWLAHNNQARFVRECASMVRFYKKGQMKEMSMSEWIYARGHWSSIAKFLRYQQVNVIMFLAALKDMLHSPKHNCILIHGPPNTGKSAFTMSLIHVLKGRVLSFVNSKSQFWLQPMSETKIALIDDVTDPCWVYMDTYLRNGLDGHYVSDCKHKAPIQTKFPALLLTSNINVHNEYLHSRIKGFEFPNPFPMKPDNTPEFELTDQSWKSFFTRLWKQLELEDEFQCLSKRFNALQDQLMNIYEAPDTLESQIEHWRKEAVLLYFARQHGISRVGYQPVPVLAVSEAKAKQAIGMVLRLQSLQKSEYGSEPWSLDASAETFRSPPHFKKGPISVEVIYDKDKDNANAYTMWRFVYYQD-DDDKWHKSASVNQTGIYFRHYYVLFADDASRYTGRLGRLLDEALDPPVILVRGEPNTLKCFRNRAKQRYTGLYKSFSTAWSWFISFSQRKDFDETVKYPWQAASGKVYLPPSTPVRVQSTDEYVQRTNIYYHAYSRLLTVGHPYFKIKVPKVSGNQHRVFRLKLPDPNRFALADMSVYNPDERLVWGCRGIEIGRGQPLGVGSVGHPLFNKLGDTENPNSYDDRQNVSDPKQLQMFIIGCAPCLGEHWDRALPCGSCPPIELKNTAIQDGDMADIGYGNLNFKALQENRADVSLDIVNETCKYPDFLKMQNDVYGDSCFFYARREQCYARHFFVRGGYFPTVSGSLVSSDAQLFNRPFWLQRAQGHNNGICWFNQLFVTVVDNTRNTNFSIYDSQKFQEYLRHVEEYEISLILQLCKVPLTAEVLAQINAMNSNILEEWQLGFVPAPIHDTYSAATRCPPKEREDPYKDLNFWNVDLSERLSLELDQYSLGRKFLFQAGKRK Seq12 MAESKGSGFGDWCILDISDLLDQGN-SRELFHQQECQESEEHLQKLKRKY-LSPSPRFESIKSKRRLFDSGLELLRANNNRAILMAKFKEAFGVGFYDLTRQFKSYKTCCNAWVYAVHDDLLESSKLLQQHCDYVWIR--MSLFLLCFKVGKNRGTVHKLMLNVHEKQILSEPPKLRNTAAALFWYKGCMGSGGGPYPDWIAQQTILGHFDLSEMIQWAFDNNHMDESDIAYQYAKLAPENSNAVAWLAHNNQARFVRECAAMVRFYKKGQMKEMSMSEWIYARGHWSTIAKFLRYQQVNFIMFLAALKDLLHAPKRNCILIYGPPNTGKSAFTMSLIRVLKGRVISFVNSKSQFWLQPLSECKIALLDDVTDPCWIYMDTYLRNGLDGHVVSDCKHKAPIQTKFPALLLTSNINVHNEYLHSRIQGFEFPNPFPMKADNTPQFELTDQSWKSFFTRLWQQLELEEEFQCLSERFNVLQDQLMNIYEAAETLESQIEHWRKEAVLLYFARRKGVTRIGYQPVPTLAVSEAKAKEAIGMVLQLQSLQKSEYGTEPWSLDTSAETYRSAPYFKKGPMPIEVIYDKDADNANLYTMWKFVYYVD-EDDNWHKSESVNHTGLYFRHYYVLFADDARKYTGRLGRLLEEALDPPVILVRGEPNTLRSFRNRAKHMYRGLFSSFSTAWSWFVSFNQRKHFDDTVRYPWQAASGKVYLPPSTPVRVQSTDEYVQRTNIYYHAYSRLLTVGHPYFKLEIPKVSGNQHRVFRLKLPDPNRFALADMSVYNPDERLVWGCRGIEIGRGQPLGVGSVGHPLFNKVGDTENPNSYDDRQNVSDPKQLQMFIIGCAPCIGEHWDKALPCGSCPPIELINSVIEDGDMADIGYGNLNFKALQQNRSDVSLDIVNETCKYPDFLKMQNDVYGDSCFFYARREQCYARHFFVRGGYFPTVSGSLVSSDAQLFNRPFWLQRAQGHNNGICWFNQLFVTVVDNTRNTNFSIYNSANFKEYLRHVEEYEISLILQLCKIPLKAEVLAQINAMNSNILEEWQLGFVPAPIQDTYSLATRCPPKEKVDPYKNLHFWNVDLSERLSLDLDQYALGRKFLFQAGKRK Seq13 MADPKGSGFNDWCILDISDLLDQGN-SRELFHLQECQESEEQLQKLKRKY-LSPSPRFESIKSKRRLFDSGLELLRASNNKAILMAKFKEAFGVGFNDLTRQFKSYKTCCNAWVYAVHDDLIESSKLLQQHCDYVWIR--MSLFLVCFKAGKNRGTVHKLMLNVHEKQILSEPPKLRNVAAALFWYKGSMGSGVGSYPDWIAHQTILGHFDLSDMVQWAFDNNYLDEADIAYQYAKLAPDNSNAVAWLAHNNQAKFVRECASMVRFYKKGQMKEMSMSEWIYTKGQWSTIVQFLRYQQVNFIMFLAALKDLLHSPKRNCILFYGPPNTGKSAFTMSLIKVLKGRVLSFCNSKSQFWLQPLSECKIALLDDVTDPCWVYMDTYLRNGLDGHYVSDCKHKAPMQTKFPALLLTSNINVHNEYLHSRIKGFEFPNPFPMKADNTPQFDLTDQSWKSFFTRLWHQLDLEDEFQCLSERFNVLQDQLMNIYEAAQTLEAQIEHWRREAVLLYFARQKGVTRLGYQPVPALMVSEAKAKEAIGMVLQLQSLQKSEFGKEPWSLDTSTETYKSPPHFKKGPMPIEVIYDKDADNANAYTMWRYIYYVD-DDDKWHKSASVNHTGIYFRHYYVLFADDARRYTGRLGRLLEEALDPPVILVRGDANTLRSFRNRAKHMYTGLFSSFSTAWSWFISNSQRKHFDDAVRYPWQAASGKVYLPPSTPVRVQSTDEYVQRTNIYYHAYSRLLTVGHPYFKLQIPKVSGNQHRVFRLKLPDPNRFALADMSVYNPDERLVWACRGIEIGRGQPLGVGSVGHPLFNKVGDTENPNSYDDRQNVSDPKQLQMFIIGCAPCIGEHWDKALPCGSCPPIELINSVIEDGDMADIGYGNLNFKALQQNRADVSLDIVNETCKYPDFLKMQNDVYGDSCFFYARREQCYARHFFVRGGYFPTVSGSLVSSDAQLFNRPFWLQRAQGHNNGICWFNQLFVTVVDNTRNTNFSIYNSQKFTEYLRHVEEYELSLILQLCKVPLKAEILAQINAMNSNILEEWQLGFVPAPIQDTYSLATRCPPKEKVDPYKNLHFWDVDLTERLSLDLDQYSLGRKFLFQAGKRK Seq14 MADNKGSGLHEWCLLDVSDLISQGN-SRELFQQQELEESNALLQSLKRKY-ISPSPQLESIKTKRKLFDSGVELMRCSNLKATLLSKFKNAFGVSFVELTRQFRSNKTCCNDWVYGVNYDLFESSKLLQQHCDYIWVT--MFLYLLCFKAGKNRQTVIRLLLYVAEEQILSEPPKLRSTVSALFWYKGSSNAATGSYPKWIIEQTLIGHFDMSTMVQWAFDNDLTEEADIAFQYAKLAPDDVNATAWLAHNNQARFVRECANMVRYYKKGQMREMSMSAWIHFKGQWSTIVKFIRYQGINFISFLSALKDFLHGPKKNCLLIYGPPNTGKSAFTMSLIKVLHGRVISFVNSKSHFWLQPMSEAKIALLDDATDPCWIYMDTYLRNGLDGHLVSDCKHKAPIQIRFPPLLITSNINAMAEYLHSRLVAFEFPNPFPMKDDDTPEFELTDQSWKSFFKRLWRQLDLEDEFRCLKKRFDVLQDLLMNIYEGSDTLESQIEHWRREAVLLYYARQNGVLRLGYLPVPPLATSEAKAKQAISMVLQLQSLQQSPYGTEKWTLDTSIETFKNTPHFKKGPINVEVIYDGDPDNANLYTMWKYVYYMD-DNDQWQKTESANHTGIYYKHYYVLFADDANRYSGRLGRLLEEALDPPVILLRGGANTLKCFRNRAKLRYRGHYKAFSTSWSWFTSFKQRSGFLDLVRFPWLPASGKVYLPPSTPVKVQSTDEYIQRTNIFYHAYSRLLTVGHPYFVLEVPKVSGNQHRVFRLKLPDPNRFALADMSVYNPEERLVWGCRGVEIGRGQPLGVGTSGHPLFNKVNDTENPVSYDDRQNTSDPKQIQMFIIGCAPCIGEHWEVAERCGRCPPIKLVNSVIQDGDMADIGYGNLNFRTLQQSRSDVSLDIVNETCKYPDFLKMQNDVYGDSCFFFARREQCYARHFFVRGGYFPTVSGSLVSSDAQLFNRPFWLQRAQGHNNGICWANQLFITVVDNTRNTNFSIYDANKFREYQRHVEEYEISLILQLCKIPLKADVLAQINAMNPSLLEEWQLGFVPAPLQSTYSLATPCAPKEREDPYAPYTFWNVDLSERLSLELDQYSLGRKFLFQAGKRK Seq15 MADNKGSGLSDWCLLDVSDLLNQGN-SRELFQQQELEDSETLLQSLKRKY-ISPSPQLESIKSKRKLFDSGVELMRCSNLKATLLAKFKSAFGVSFAELTRQYKSNKTCCNDWVYGVNNDLFEGSKLLQQHCDYIWLT--MYLYLLCFKAGKNRHTVIRLLLHVAEEQILSEPPKLRSTVAALFWYKGSSNSGTGSYPKWIVEQTLIGHFDMSTMVQWAFDNNLTEEADIAFQYAKLAPDDVNATAWLAHNNQARFVREVAAMVRFYKKGQMREMSMSAWIHFRGHWSSIVKFIRYQGINFISFLSALKDFLHAPKKNCLLIYGPPNTGKSAFTMSLIKVLNGRVISFVNSKSHFWLQPMSECKIALLDDATDPCWVYMDTYLRNGLDGHLVSDCKHRAPMQIKFPPLLITSNINAMAEYLHSRLVAFEFPNPFPMKDDDTPEFELTDQSWKSFFTRLWTQLELEDEFRCLRERFDVLQDQLMNIYEASDTLEAQIEHWRKEAVLLYFARQNGVLRLGYQPVPPLATSEAKAKEAIGMMLQLQSLQKSAYASEKWTLDTSIETFKNTPHFKKGPVNVEVIYDGDPDNANLYTMWKYVYYLDSE-DRWQKTESANHTGIYYKHYYTLFADDAKKYTGRLGRLLEEARDPPVILIRGEANTVKCFRNRAKQKYKGLCKAFSTTWSWFTSHTQRSSFLKVVKFPWLPASGKVYLPPSTPVRVQSTDEYVQRTNIFYHAYSRLLTVGHPYYVLEVPKVSGNQHRVFRLKLPDPNRFALADMSVYNPEERLVWACRGLEIGRGQPLGVGTTGHPLFNKVNDTENPLNYDDRQNLSDPKQIQMFIIGCTPCVGEHWDVAPKCGICPPIQLVNTVIQDGDMADIGYGNLNFKALQENRSDVSLDIVNETCEYPDFLKMQNDVYGDSCFFFARREQCYARHFFVRGGYFPTVSGSLVSSDAQLFNRPFWLQRAQGHNNGICWANQLFITVVDNTRNTNFSIYDANKFREYQRHVEEYEISLILQLCKIPLKSEVLAQINAMNPSLLEEWQLGFVPTPLQSTYSLATPCPPKEKEDPYAPYTFWNVDLTERLSLDLDQYSLGRKFLYQANKRK Seq16 MADDKGSENDNWCLLDISDLVDQGN-SRELLHQQQCNDSELQVQKLKRKY-LSPSPRLESIKSKRKLFDSGLELMRCSNVKATLLCKFKLAFGVSFSELTRQYKSNKTCCNDWVYGIRDELYEGSKLLQQHCDYIWVY--MSLFLLCFKAGKNRTTVHRLLLDVQEQQILSEPPKLRSTVAALFWYKGSFGSKAGAYPQWIVQQTMVGHFELSTMVQWAFDNNLTDEADIAYKYANMAFEDVNAAAWLAHNNQARFVRECASMVRFYKRGQMREMSISEWIHHKGHWSSIVKFIRYQEINFICFLAALKDFLHSPKRNCLLIYGPPNTGKSAFTMSLIKVLGGRVISFVNSRSQFWLQPLSECKIALLDDATDPCWTYMDTYLRNGLDGHMVSDCKHKAPMQTKFPPMLVTSNINVLEEYLHSRIVGFKFPNPFPLKPDNTPEFELTDQSWKSFFERLWSQLDLEEEFQCLSERFNALQDELMNIYEAKETLQAQIDHWRQEAVMMYYGRKKGYMRLGYQPLPPLAVSEHKAKEAIAMVLHLQSLQHSPFSEEKWTLDASAETFRNAPYFKKGATNVEVIYDNNEENANLYTLWKYVYYLDGD-DMWQKTTSVNHTGIYFRHYYVRFADDAARYTGRLGRLLAEAVDPPVILVRGDANTLKCFRNRAKQRYWGLYKSFSTTWSWFLSTTQRSHFEKTVRYPWLPASGKVYLPPSTPVRVQSTDEYVERTNIYYHAYSRLLTVGHPYFKVEVPKVSGNQHRVFRLRLPDPNRFALADMSVYNPDERLVWACRGLEIGRGQPLGVGSSGHPLFNKLGDTENPNNYDDRQNVSDPKQLQMFVIGCAPCIGEHWDRAIACGSCPPIELKNTYIEDGDMADIGYGNLNFQTLQQSRADVSLDIVHETCKYPDFLKMQNDVYGDSCFFYARREQCYARHFFVRGGYFPTVSGSLVSTDAQLFNRPFWLQRAQGHNNGICWANQLFLTVVDNTRNTNFSIYDPNKFREYQRHVEEYEISLILQLCKIPLTAEVLAQINAMNPALLEDWQLGFVPAPIHDTYSLATRCPAKEKEDPYGKYTFWEVDLTERLSLDLDQYSLGRKFLFQAGKRK Seq17 MEDNKGTGCSDWFLVDISDLIDQGN-SRELLCQQETEESEQQVQLLKRKY-FSPSPRLQSIKSKKRLFDSGLELLKSSNVKATLMGKFKDAFGVGFNELTRQYKSNKTCCKDWVYCVQDDLLEASKLLQKHCNYIWMH--MTLYLLCFNAGKSRETVCRLLLQIDDMQALLEPPRLRSVLSALFWYKGSMNPNVGTYPDWIVAQTMISHFSLSRMVQWAFDNEHLEEADIAYNYAKLAETDSNAKAFLDSNSQANFVRQCALMVRHYKRGQMRDMSMSCWIHTRGHWSEIVKFIRYQNLNFIMFLDKFRTFLKNPKRNCMCFYGPPDSGKSMFTMSLINVLKGRVLSFANSRSQFWLQPLSETKLALLDDATQECWNYIDTFLRNGVDGNYVSDIKHRAPLQIKFPPLMITTNMNILKEYLHTRIEFFEFPNKFPFDNNNKPQFHLTDQSWKSFFERLWTQLELEDEFHCLSERFTALQDKLMDIYEGLETLEVQIEHWRQEQVLLNFARRNGILRLGYQPVPSLATSETKAKDAIGMVLMLQSLQNSKYAEETWSLQTSLETVRSPPCFKKEPQTIEVVFDGDPENRMIYTVWNWIYFQNTE-DIWQKVKGVDYEGAFYKHYYIKFENDANRFHGRLGRLLDEAKDPPVILLRGEANQLKCYRFRARKKHKGNYKYFSSTWSWFTSTHQREMFLDTMKLPWLPATGKVYLPPSTPVRVLSTDEYVERTNIFYHATSRLLTVGHPYFKVEVPKVSGNQFRAFRMLFPDPNRFALADMSVYNPDERLVWACAGIEINRGQPLGVGTTGHPLFNKVKDTENTNSYDDRQNISDPKQVQMFVIGCTPCLGEYWDRALPCGKCPPIELKNSFIEDGDMIDIGFGNINNKTLSVNKSDVSLDLVNEIAKYPDFLTMANDVYGDSCFFFARREQCYARHYFTRGGYYPTVSGSLVSSDAQLFNRPFWLKRAQGHNNGILWGNQMFVTVADNTRNTNFTIYDANNIREFLRHVEEYQISVILQLCKVSLQPDVLAQINAMNSGILEDWQLGFVPTPVHDTYSAATKCAPKEKEDPFAQYFFWRVDMTEKLSLDLDQYPLGRKFLFQTTKRK Seq18 MSDNKGTCCSAWLSLDISDLIDQGN-SRELFCQQESEESEQQTQLLKRKY-ISPSPQLESIKPKRRLFDSGLELLKHSNVKAVLMAKFKEAFGVGFAELTRQYKSNKTCCRDWVYAVNDDLIESSKLLLQHCAYIWLH--MCLYLLCFNVGKSRETVCRLLLQVSEVQLLSEPPKLRSVCAALFWYKGSMNPNVGAYPEWILTQTLINHFDLSTMIQFAYDHEYFDEATIAYQYAKLAETDANARAFLQSNSQARLVKECATMVRHYMRGEMKEMSMSTWIHRKGQWSDIVRFIRYQDINFIEFLTVFKAFLQNPKQNCLLFHGPPDTGKSMFTMSLISVLKGKVLSFANCKSTFWLQPIADTKLALIDDVTHVCWEYIDQYLRNGLDGNYVCDMKHRAPCQMKFPPLMLTSNIDITKDYLHSRVKSFAFNNKFPLDANHKPQFELTDQSWKSFFKRLWTQLDLEDEFQCLSARFNALQETLMDLYEGREDLQSQIDHWRQEQILLHYARKNGVMRLGYQPVPPLATSEQKAKDAIGMVLLLQSLQRSAYGQEPWTLQTSLEAVRSPPAFKKGPQNIEVVYDGDPDNVMSYTIWNFIYYQTVN-D-WEKVQGVDYFGAYYKTYYINFDKDAARYHGRLARLLAEAKDPPLMLLRGDANVLKCYRFRERKKKRGLVKYYSTTWSWFDTYEHRQQFIRTMKLPWLPASGKVYLPPATPVRVQSTDEYVERTNIFYHAISRLLTVGHPYYRIEVPKVSGNQYRAFRISLPDPNRFALADMSVYNPDERLVWACRGIEIGRGQPLGVGTSGHPLFNKVRDTENSSNYDDRQNTSDPKQVQMFIIGCIPCLGEHWDKAKVCGLCPPIELRNTVIEDGDMFDIGFGNINNKELSFNKSDVSLDIVDETCKYPDFLTMANDVYGDACFFFARREQCYARHYYVRGGYYPTVSGSLVTSDAQLFNRPFWLQRAQGHNNGILWGNQIFVTVADNTRNTNFTIYNANNIREYLRHVEEYQISLILQLCKVPLVAEVLSQINAMNSGILEDWQLGFVPTPVHDIYSKATKCEPTEKEDPFAKYSFWKVDLTERLSLDLDQYPLGRKFLFQAGKRR Seq19 MSDDKGTGCSDWFVLDISDLIDQGN-SRELLCQQESEESEQQIHWLKRKY-ISSSPRLQCIKSKRRLFDSGLELLKCNNVKAMLLAKFKEAFGVGFMELTRQYKSSKTCCRDWVYAVQDELLESSKLLIQHCAYIWLH--MCLYLLCFNVGKSRETVLRLLLQVSEIQIIAEPPKLRSTLSALFWYKGSMNPNVGEYPEWIMTQTMINHFDLSTMVQYAYDNELSEEAEIAWHYAKLADTDANARAFLQHNSQARLVKDCAIMVRHYRRGEMKEMSMSSWIHKKGHWSDIVKFVRYQDINFIQFLDSFKSFLHNPKKSCMLIYGPPDTGKSMFTMSLIKVLKGKVLSFANYKSTFWLQPVADTKIALIDDVTYVCWDYIDQYLRNALDGGVVCDMKHRAPCQIRFPPLMLTSNIDIMKEYLRSRVQAFAFPHKFPFDSDNNPQFKLTDQSWKSFFERLWRQLELEDEFQCLSERFNALQENLMDIYEGRDDIETQILHWRQEQVLFYFARKHGVMRL?YQPVPPLATSETKAKDAIGMVILLQSLQKSAYGKEPWTLQTSLETVRSAPCFKKGPQNIEVMFDKDPENIMVYTVWTYIYYQTLD-DTWNKVEGIDYHGAYYKVYYIQFEVDAARFTGRLERLLEEARDPPVILLRGDANKLKCFRFRAKKKYQDLVKYYSTTWSWFSSNTERELFIKIMKLPWLPTTGKVYLPPTPPVRVQSTDEYVERTNVFYHAMSRLLTVGHPYFSIEVPKVSGNQYRAFRVTFPDPNRFALADMSVYNPEERLVWACVGLEIGRGQPLGVGTSGHPLFNKVKDTENNSNYDDRQNTSDPKQVQMFVVGCVPCLGEHWDRALVCGKCPPLELKNTVIEDGDMFDIGFGNINNKALSVTKSDVSLDIVNETCKYPDFLTMANDVYGDACFFFARREQCYARHYFVRGGYFPTVSGSLVTSDAQLFNRPFWLRRAQGHNNGILWGNQMFITVADNTRNTNFTIYNSQNIREFLRHVEEYQLSIILQLCKIPLKAEVLTQINAMNSGILEDWQLGFVPTPVQDIYSKATKCQPKDKEDPFGKYTFWNVDLTEKLSLDLDQYPLGRKFIFQAGKRK Seq20 MSDEKGTGCSEWFDLDISDLIDQGN-SRELLCQQESEESEQQIHWLKRKY-ISSSPRLQSIKSKRRLFDSGLELLKCSNVKAMLLAKFKEAFGVGYMELTRQYRSSKTCCRDWVYAVQDELLESSKLLIQHCAYIWLH--MCLYLLCFNVGKSRETVLRLLLQVSEVQIIAEPPKLRSTLSALFWYKGSMNPNVGEYPEWIMTQTMISHFDLSTMVQYAYDNELTDEAEIAYHYAKLADTDANARAFLQHNSQARLVKDCAIMVRHYRRGEMKEMSMSAWIHKKGHWSDIVKFIRYQEINFIQFLNAFKLFLHNPKKSCLLFYGPPDTGKSMFTMSLIKLLKGKVLSFANYKSTFWLQPVADTKVALIDDVTYVCWDYIEQYLRNALDGNTVCDMKHRAPCQIRFPPLMLTSNIDIMKEYLYSRIQAFAFPHKFPFDSDNKPQFKLTDQSWKSFFERLWRQLDLEDEFQCLSERFNALQENLMDIYEGRDDIETQIMHWRQEQVLFYFARQHGVMRLGYQPVPPLATSEAKAKDAIGMVILLQSLQKSQYGKEPWTLQTSLETVRSAPCFKKGPQNIEVMFDNDPENLMVYTVWSHIYYQTLD-DTWKKVEGVDYHGAYYKNYYIQFEIDAARFNGRLERLLEDARDPPVIVLRGDANKLKCFRFRAKKKYRDLVKYYSTTWSWFTSNTERQLFINIMKLPWLPATGKVYLPPTPPVRVQSTDEYVERTNVFYHAMSRLLTVGHPYFKIDVPKVSGNQYRAFRVTFPDPNRFALADMSVYNPEERLVWACAGLEIGRGQPLGVGTSGHPLFNKVKDTENNSGYDDRQNTSDPKQVQMFIVGCVPCLGEHWDRAPVCGKCPPLELKNTVIEDGDMFDIGFGNINNKVLSVTKSDVSLDIVNETCKYPDFLTMANDVYGDACFFFARREQCYARHYFVRGGYFPTVSGSLVTSDAQLFNRPFWLRRAQGHNNGILWGNQMFITVADNTRNTNFTIYNTQNIREFLRHVEEYQLAIILQLCKVPLKAEVLTQINAMNAGILEEWQLGFVPTPVHDIYSKATKCAPKDKEDPFGKYTFWNVDLTEKLSLDLDQYPLGRKFIFQAGKRK Seq21 MTDDNKGGCSQWCILEISDLIDQGN-SRELLCQQESEESEQQIQLLKRKY-LSSSPRLQSIKSKRRLFDSGLELLKCSNVKAMLLAKFKEAFGVGYMDLTRQYKSSKTCCRDWVYAVQDELIESSKLLLQHCAYIWLQ--MCLYLLCFNVGKSRETVSRLLLQVAEVQMLAEPPKLRSMLSALFWYKGSMNPNVGEYPEWILTQTMINHFDLSTMIQFAYDNEYLQEDEIAYHYAKLADTDANARAFLQHNSQARFVKECAIMVRHYKRGEMKEMSISTWVHRKGHWSDIVKFIRYQDINFIRFLDIFKSFLHNPKKNCILIHGPPDTGKSMFTMSLIKVLKGKVLSFANCRSNFWLQPLADTKLALIDDVTFVCWDYIDQYLRNGLDGNVVCDLKHRAPCQIKFPPLLLTSNIDVMKEYLHSRIQSFAFPNKFPFDNNNMPQFRLTDQSWKSFFERLWHQLDLEEEFQCLSERFNVLQENLMDIYEGQEDIETQIKHWRQEQVLFYYARKNGVMRVGYQPVPPLATSEAKAKDAIGMVLLLQSLQKSPYGKEPWTLQTSLETVRSPPCFKKGPQNIEVMFDNDPENLMSYTVWSFIYYQNLD-DTWNKVEGVDYHGAYYKVYYIQFEVDAARFGGRLTRLLEEARDPPVILLRGEANKLKCFRYRAKKRYGSLVKYYSTTWSWFNTYDERELFIQKMKLPWLPTTGKVYLPPTPPVRVQSTDEYVERTNIFYHAMSRLLTVGHPFYRIEVPKVSGNQYRAFRVTLPDPNKFALADMSVYNPEERLVWACAGLEIGRGQPLGVGTTGHPLFNKLRDTENNSSYDDRQNTSDPKQVQMFVVGCVPCIGEHWDRAPVCGLCPPLELKNTVIEDGDMVDIGFGNINNKVLSFNKSDVSLDIVNETCKYPDFLSMANDVYGDACFFFARREQCYARHYFVRGGYFPTVSGSLVTSDAQLFNRPFWLRRAQGHNNGILWGNQIFVTVADNTRNTNFSIYNSQNIREYLRHVEEYQLSFILQLCKIPLKAEVLTQINAMNSGILEDWQLGFVPTPVHDIYSKATKCVEKEKEDPFAKYTFWNVNLTEKLSLDLDQYPLGRKFIFQSGKRK Seq22 MTDDTKGGCSDWFVLDISDLIDQGN-SRELLCQQQSEESEQQIHLLKRKY-FSSSPRLQSIKSKRRLFDSGLELLKCSNVKAMLLAKFKEAFGVGFMELTRQYKSCKTCCRDWVYAVQDELIESSKLLLQHCAYIWLQ--MCLYLLCFNVGKSRETVFRLLLQVAEVQILAEPPKLRSTLSALFWYKGSMNPNVGEYPEWIMTQTMINHFDLSTMIQYAYDNDLINEDEIAYNYAKLADTDANARAFLQHNSQARFVRECALMVRYYKRGEMKDMSISAWIHNKGHWSDIVKFVRFQDINFIRFLDVFKSFLHNPKKNCLLFYGPPDTGKSMFTMSLIKVLKGKVLSFANYKSNFWLQPLADTKIALIDDVTHVCWDYIDQYLRNGLDGNFVCDLKHRAPCQIKFPPLLLTSNMDIMKEYLHSRVHAFAFPNKFPFDSNNKPQFRLTDQSWKSFFERLWKQLDLEDEFQCLSDRFNALQENLMDIYEGRDDLETQIMHWRQEQILFHYARKNGVMRLGYQPVPPLATSEAKAKDAIGMVILLESLQQSAYGKESWTLQTSLETVRSPPCFKKGPQNIEVMFDNDPENLMVYTAWSFIYYQTVD-DTWNKVEGVDYYGAYYKVYYIQFEGDAARFSGRLKRLLDEARDPPVIVLRGDANKLKCYRYRAKKKHGNLVKYYSTTWSWFQSNTERELFLKTMKLPWLPATGKVYLPPTPPVRVQSTDDYVERTNVFYHAMSRLLTVGHPYYKIEVPKVSGNQYRAFRVRLPDPNKFALADMSVYNPEERLVWACAGLEIGRGQPLGVGTTGHPLFNKLRDTENNSNYDDRQNTSDPKQVQMFVVGCVPCMGEHWDKAPVCGQCPPLELKNTVIEDGDMFDIGFGNINNKVLSTNKSDVSLDIVNEICKYPDFLTMANDVYGDACFFFARREQCYARHYFVRGGYFPTVSGSLVTSDAQLFNRPFWLRRAQGHNNGILWGNQMFITVADNTRNTNFSIYNSQTLREYLRHVEEYQLSIILQLCKVPLKAEVLTQINAMNSGILEEWQLGFVPTPVHDLYSKATKCVEKEKEDPFAKYTFWNVDLTEKLSLDLDQYPLGRKFIFQSGKRK Seq23 MDDDKGTGCSGWFMLDVSDLINQGN-SRELLCQQQSEECEQQIQYLKRKY-FSPSPRLQSMKSKRRLFDSGLELLRCNNVKAVLLGKFKDAFGVSYNELTRQFRSNKTCCKHWVYAAKDELIDASKLLQQHCTYLWLQ--MSLYLCCFNVGKSRETVMRLLLQVNENHILSEPPKIRSMIAALFWYKGSMNPNVGEYPEWIMTQTMIHHFDLSEMIQWAYDQDYVDECTIAYQYARLADSNSNARAFLAHNSQAKYVRECAQMVRYYKRGEMRDMSISAWIHHCGHWQDIVKFLRYQGLNFIVFLDKFRTFLKNPKKNCLLICGPPDTGKSMFSMSLMKALRGQVVSFANSKSHFWLQPLADAKLALLDDATEVCWQYIDAFLRNGLDGNMVSDMKHRAPCQMKFPPLIITSNISLKKEYLHSRIYEFEFPNKFPFDANDTPLFKLTDQSWASFFKRLWTQLELEEEFQCLSERFSALQEKLMDLYEGVEDLETQIQHWRQEQVLFYYARRHGILRLGYQPVPTLATSESKAKDAIAMGLLLESLQKSQYAEEPWTLETSLETVKSPPCFKKGPKSVEVYFDGDPENVMSYTVWSYIYYQT-DDESWEKVEGVDYTGAYYKTYYIKFETDAKRYSGRLAQLLDAAKDPPVILLRGAANTLKCYRYRFRKKHAGSFQFISTTWSWFHTDREREKCLQQMKLPWLPTSGKIYLPPTPPVRVQNTDEYVERTDIYYHAISRLLTVGHPYFKIEVPKVSGNQFRAFRVTFPDPNKFALGDMTIHDPEYRLVWACKGLEIGRGQPLGVGTTGHPLFNKLHDTENPTERDDRRNVSDPKQVQMFIIGCIPCLGEYWDKAPVCGLCPPLELKNGVIEDGDMFDIGFGNINNKTLSFNRSDVSLDIVNEICKYPDFLTMSNDVYGDSCFFCARREQCYARHNFVRGGYFPTVSGSLVTSDAQLFNRPFWLKRAQGHNNGILWNNQMFVTVADNTRNTNFSIYDAKKIREFMRHVEEYQLSFILQLCRIPLEAEVLTQINAMNHGILENWQLGFVPTPVHDTYSKATKCPDTQKEDPFGQYTFWNVDMSEKLSLDLDQYPLGRKFLFQSGKRR Seq24 MDDDKGTGCSTWCLLDVSDLINQGN-SRELLCQQESEECEQQIQYLKRKYNISPSPRLQSLKSKRRLFDSGLELLRCKNAKAVLLHKFKEGFGISYNELTRQFKSNKTCCKHWVYGAKEELIDASKLLQQHCSYIWLQ--MSLYLCCFNVAKSRETVVKLLLQIHENHILSEPPKNRSVPVALFWYKGSMNPNVGEYPEWIVTQTMIQHFDLSRMIQWAYDNDHLDECSIAYNYAKLADTDSNARAFLAQNSQAKHVRDCAQMVKHYKRGEMREMTISAWVHHCGQWQDIVKFLRYQGLNFIVFLDKFRTFLQNPKKNCLLIYGPPDTGKSMFTMSLMKALRGQVISFANSKSQFWLQPLADAKIALLDDATEVCWQYIDMFLRNGLDGNVVSDMKHRAPCQMKFPPLIITSNISLKKEYLHSRIYEFEFPNRFPFDSDDKPLFKLTDQSWASFFKRLWIQLGLEDEFQCLSERFSALQDKLMDLYEGLEDLETQIQHWRQEQILLYYARKRGIMRLGYQPVPPLATSEIKAKDAIAIGILLESLQKSKYADEPWTLETSLETIRSPPCFKKGPKTVEVYFDGDPENVMPYTVWSYIYYQT-DEDTWEKVEGVDYTGAYFKNYYIKFEADAKRFSGRLAQLLDAAKDPPVILLRGGANTLKCYRYRFRKKHAGKFYYVSTTWSWFHSNHEREKCIQEMKLPWLPASGKIYLPPTPPVRVQSTDEYVERTDIYYHATSRLLTVGHPYFKIDVPKVSGNQFRAFRVTFPDPNKFALADMTIYDPDYRLVWACAGLEIGRGQPLGVGSTGHPLFNKLRDAENSSERDDRRNISDPKQVQMFIIGCTPCLGEYWDTAPVCGLCPPLELKNSVIEDGDMFDIGFGNINNKTLSFNRSDVSLDLVNEVCKYPDFLTMSNDVYGDACFFCARREQCYARHYFVRGGYFPTVSGSLVTSDSQLFNRPFWLKRAQGHNNGILWNNQMFVTVADNTRNTNFSIYDATKIREFTRHVEEYQLSFILQLCRIPLKAEVLTQINAMNSDILENWQLGFVPTPVHDTYSKATKCPDTQKEDPFGKYSFWNVDMTEKLSLDLDQYPLGRKFLFQIGKRK Seq25 MADDKGTGCSDFIY-DISDLINQGN-SRELLCQQEREESELQVQYLKRKC-FSPSPRLQSMKSKRRLFDSGLELLRSSNSRATLLSKFKDSFGVSFTELTRQYKSNKTCCHHWVYAAKDDLIDASKLLQQHCFYIWLQ--MSLYLCCFNVGKSRDTVVRLILQVHENHILSEPPKNRSIPAALFWYKGSLNSNVGEAPDWILSQTMIQHFDLSRMIQWAYDNDHIDESIIAYQYAKLADIDSNAKAFLAHNSQVKYVKECALMVRYYKRGEMKEMSISAWIHHCGNWQHIVRFIRYQNLNFIMFLDKFRTFLKNPKKNCLLIYGPPDTGKSMFAMSLIKLLKGSVVSFANSKSQFWLQPLADGKIGLLDDATDVCWQYIDSFLRNGLDGNLVSDIKHKAPCQMKFPPLIITSNINLLKEFLHSRVTQIDFPNKFPFDSDNKPLFELTDQSWASFFKRLWTQLELEDEFHCLSARFTVLQEKLMDIYEGVEDLDTQIQHWRQEQIIYHYARRHGVTRLGYQPVPSLASSEAKAKDAISMVLLLESLKKSKYADEQWTLQTSLEAVRSPPCFKKGPKNIEVVFDGDPENLMSYTVWTYIYYLT-DEDIWEKVEGVDYTGAYYKVYYLKFENDAKRYGGRLTRLLADAADPPVILLRGDANTLKCYRYRFRKKHAGGFRFVSTTWSWFYSESQREKFIQTMKLPWLPASGKIYLPPTPPVRVQSTDEYVERTDIYYHATSRLLTVGHPYFKIEVPKVSGNQYRSFRVTFPDPNKFALADMSVYDPDYRLVWACKGLEIGRGQPLGVGTTGHPLFNKVRDTENSSNYDDRQNTSDPKQVQMFIIGCTPCLGEYWDKAPVCGLCPPLELKNSVIEDGDMFDIGFGNINNKTLSFNRSDVSLDIVNETCKYPDFLTMSNDVYGDSCFFFVRREQCYARHYFVRGGYFPTVSGSLVTSDAQLFNRPFWLQRAQGHNNGILWGNQMFVTVADNTRNTNFTIYDSANIREYLRHVEEYQLSFILQLCKVPLNAEVLTQINAMNSGILENWQLGFVPTPVHDTYSKATKCPETEKEDPFGQYTFWNVDMTEKLSLDLDQYPLGRKFLFQAGKRK Seq26 MADDKGTGCSEWFIDNISNLLNQGN-SRDLLRQQEFEESAEQVQKLKRKY-FSPSPRLQSMKSKRRLFDSGLELMRCNNSRAKLLSKVKEYFGVGFYELARQYKSDKTCCKDWVYGVREELVESAKLLLNHCSYVWIN--MTLYLLCFNHAKSRETVGRLLLDVQLLQLICEPPKLRSVVSALYWYKGSMDSSVGAYPDWIVNQTMISHFDLSEMIQWAYDSDLTDEADIAYLYAKMANSDSNARAWLAHNNQARYLRECAQMVRHYRRGEMRDMSMSEWIHHRGHWSEIVKFIRFQEINFIIFLDAFKQFIHGPKKSCLLIHGPPDCGKSMFAMSLLKVLKGKVISFVNAKSQFWLSPLSECKIGLLDDATDPCWQYIDTYLRNGLDGNVVSDCKHKTPMQIRFPPLLITSNYNIKANFLYSRIAIFEFKHKFPFKEDGTPVFQLTDQSWKSFFERLWTQLELEDEFQCLNARFNVLQEMLMDIYEGKEDLETQIEHWRQEQALLFFARKHSIMRLGYQPVPPMAVSETKAKQAIGMMLTLQSLQKSPFGKEKWTLNTSLETYNAPPCFKKGPYNIEVIFDGDPENLMVYTAWKEIYFVDSD-DMWQKVQGVDYAGAYYKQYYVTFADDAVRYLGRLGRLLEEASDPPVILLRGDPNILKCYRYRDKKRKLGLVKHYSTTWSWFTSNSTRSQYVKIMKLPWLPATGKVYLPPSTPVRVQSTDEYIQRTDIYYHANSRLLTVGHPYFKILVPKVSGNQYRAFRLLLPDPNRFALVDMNIYNPEERLVWACRGLEIGRGQPLGVGTTGHPLFNKVKDTENANNYDDRQDTSDPKQVQMFIIGCTPCMGEYWDAAKPCGKCPPLELINSVIQDGDMIDIGFGNINNKTLSVNRSDVSLDIVNDICKYPDFLKMANDIYGDACFFYARREQCYARHFFVRGGYFPTVSGSLVSTDAQLFNRPFWLQRAQGHNNGICWENQLFITVADNTRNTNFTIYDSTKVREFLRHVEEYEISIILQLCKVPLEPEVLAQINAMNSSILENWQLGFVPTPIHDTYSQATRCPAPER-DPYEQYNFWTVDLTEKLSLDLDQYSLGRKFLFQAGKRK Seq27 MADDKGTGCSEWFLDNISELIDQGN-SRDLFRLQEFEESAEQVQMLKRKY-FSPSPRLQSLKSKRRLFDSGLELMRCSNSRARLLSKVKEYFGVGFYELARQYKSNKTCCRDWVYGVREELLEGAKLLLNHCSYVWIN--MSLFLLCFNNAKSRETVGRLLLDVQLLQLICEPPKLRSVVSALYWYKGSMDSSVGTYPDWIVNQTMLTHFDLSQMIQWAYDTDLTDEADIAYGYAKMAESDSNARAWLAHNSQAKFVRECAQMVRHYRRGEMRDMSISEWIHYRGHWSEIVKFIRFQEINFILFLDAFKQFLHGPKKSCLLIYGPPDCGKSMFAMSLIRVLKGRVISFVNAKSQFWLSPLAECKIGLLDDATDPCWQYIDAYLRNGIDGNIVSDCKHKTPLQIRFPPLLITSNYNIKDNYLYSRIVIFEFKHKFPFKEDGSPEFLLTDQSWKSFFKRLWSQLELEDEFQCLNDRFNALQDKLMDIYEGKDDLETQIEHWRQEQVLYFYARKKGILRIGYQPVPTLAVSETKAKEAIGMMLTLESLQKSPFGKESWTLNTSLETFRTPPCFKKGPINIEVRFDGDPENIMLYTAWTHIYFLDAE-EHWQKVKGVDYLGAFYKHYYIHFNDDALRYLGRLGRLLAEASDPPVILLRGDPNILKCFRYRDKKNRKGLVKCYSTTWSWFTSEQNRAEYINSMKLPWLPTTGKVYLPPSTPVRVQSTDEYIQRTDIYYHANSRLLTVGHPYFKILVPKVSGNQFRAFRLLLPDPNRFALVDMNVYNPEERLVWACRGLEIGRGQPLGVGSTGHPLFNKVKDTENSNNYDDRQDTSDPKQVQMFIIGCAPCIGEHWDAAKPCGKCPPLELVNTVIEDGDMVDIGFGNINNKTLSANKSDVSLDIVNNICKYPDFLKMANDIYGDSCFFYARREQCYARHFFVRGGYVPTVSGSLVSTDAQLFNRPFWLQRAQGHNNGICWENQLFVTVVDNTRNTNFTIYDSGKIREFLRHVEEYELSVILQLCRVPLEPEVLAQINAMNPNILENWQLGFVPSPIHDTYSQATRCPAPEK-DPYEQYTFWPVDLTEKLSLDLDQYSLGRKFLFQAGKRK Seq28 MADDKGTGCSEWFLDNISELIDQGN-SRDLLRQQEFEESAEQVQKLKRKY-FSPSPRLQSLKSKRRLFDSGLELMRCSNSRARLLSKVKEYFGVGFYELARQYKSDKTCCRDWVYGVREELLEGAKLLINHCSYVWIN--MSLFLLCFNNAKSRETVGRLLLDVQLLQLICEPPKLRSVVSALYWYKGSMDSSVGTYPDWIVNQTMLTHFDLSEMIQWAYDTDLTDEADIAYGYAKMAESDSNARAWLAHNSQAKFVRECAQMVRHYRRGEMRDMSISEWIHYRGHWSEIVKFIRYQGINFILFLDAFKQFLHGPKKSCLLIYGPPDCGKSMFAMSLIRVLRGRVISFVNAKSQFWLSPLAECKIGLLDDATDPCWQYIDTYLRNGIDGNIVSDCKHKTPLQIRFPPLLITSNYNIKDNYLYSRIVIFEFKHKFPFKEDGSPEFLLTDQSWKSFFKRLWNQLDLEDEFQCLNDRFNALQDKLMDIYEGKDDLETQIEHWRQEQVLYYYARKKGVLRLGYQPIPTLATSETKAKEAIGMMLTLESLQKSPFGKEPWTLNTSLETYRTPPCFKKGPVNIEVRFDEDPENIMLYTSWTYIYFLDAEDQ-WQKVKGVDYLGAFYKHYYINFNDDALRYLGRLGRLLAEASDPPVILLRGDPNVLKCFRYRDKKNKKGLVKCYSTTWSWFTSQQHRAQYISSMKLPWLPATGKVYLPPSTPVRVQSTDEYIERTDIYYHANSRLLTVGHPYFKIQVPKVSGNQFRAFRLLLPDPNRFALVDMNVYNPEERLVWACRGLEIGRGQPLGVGSTGHPLFNKVKDTENANNYDDRQDTSDPKQVQMFIIGCAPCIGEHWDAAKPCGKCPPLELVNTVIEDGDMVDIGFGNINNKTLSANKSDVSLDIVNNICKYPDFLKMANDIYGDSCFFYARREQCYARHFFVRGGYVPTVSGSLVSTDAQLFNRPFWLQRAQGHNNGICWENQLFVTVVDNTRNTNFTIYDSTKIREFLRHVEEYELSVILQLCKVPLVPEVLAQINAMNSNILENWQLGFVPTPIHDTYSQATRCPAPEK-DPYEQYNFWQVDLTEKLSLDLDQYSLGRKFLFQAGKRK Seq29 MAD-KGIGCSTWCLIDISDLLDELGNPQELLCLQEREESDLQLQQLKRKY-FSPSPQLESIKSKRRLFDSGLELLQCSNARATLLSKFKAAFGVSFTELTRRYKSDNTCCRDWAYGL-QDIIEGSKLFQQHCEYIWLH--ISLYLLCFKTGKSRNTVKNLLLNVGDAQLIADPPQIRSVVAALFWYKESMNKNVGEYPEWIANQTLLSHFDLSRMIQWAYDNEYTEDSDIAYHYAKLADEDSNARAFLAHNSQAKFVRECGQMVRHYKRGEMKNMSMSAWIYTRGHWSDIVKFIRFQQINFIMFLDVFKQFLASPKRNCLLIYGAPDCGKSMFCMSLIKALKGKVISFVNARSQFWLSPLVESKIALLDDATECCWNYIDNYLRNGIDGNMVSDCKHKNPVQIRFPPLLITSNNNIMSDYLHSRIKAFEFVNKFPFKDDGSPLFELTDQSWKSFFQRLWRQLDLEDEFQCLSDRFNALQDKLMTIYEASESLKDQIEHWRQEQVLFHYARQRGVLRLGYQPVPALTISEAKAKEAIAMVLHLEALQRSPYKNEKWTLNTSVETFRTPPCFKKGPKTIEIVYDGNPENTMLYTIWTHIYFED-DEGNWQKTEGLDYHGAYFKQYYIRFAQDARRFSGRLARLLDDARDPPVILLKGQANTLKCYRYRAKEKYKGYYDCFSTTWSWFTSKSQRQMFLSIMKLPWLPANGKVYLPPSTPVRVQSTDEFVQRTNIFYHANSRLLTVGHPYFDVLVPKVSGNQFRAFRLKLPDPNRFALADMSVYNPDERLVWGCRGLEIGRGQPLGVGTTGHPLFNKVLDTENPNKYDDRVNTSDPKQIQLFVLGCTPCLGEHWDTALPCGGCPPLELKNTVISDGDMVDIGFGNMNFKALSVTKSDVSLDIVDSTCKYPDFLKMSNDVYGNSCFFYGRREQCYVRHMFVRGGYFPTVSGSLVSTDAQLFNRPYWLQRAQGHNNGICWSNELFLTVCDNTRNTNFNIYDSQKIREYTRHVEEYEISLILQLCKIPLEAEILAQINAMNPNILEDWQLGFVPTPIQDAYSKATPCQPKEREDPWAPYTFWVVDLTEKLSLDLDQYSLGRKFLFQAGKRK Seq30 MADNRGIGCSNWF-SDLSDLIDEQGISRDLFRQQGSEEFEQQIQDLKRKY-FSPSPRLEAIKCKKRLFDSGLELLKCSNLRATMLSKFKNSFGVGFMELCRKFNSNKTCCRDWVYGVKEELLEGCKLLQEHCGYIWLH--MSLFLLCFKTGKSRDTVVRLLLSIHKEQLLTEPPKLRSVMAVLYWYKGSMNPNIGEYPDWIVQQTMISHFELSPMVQWAYDNDYIEDSDIAYNYAKLADEDINARAFLAHNNQAKIVRDCAWMVRHYKRGEMRYMSISKWIWYKGHWSNIVKFVRFQGINFIMFLDAFKHFLLSTKKNCILFYGPSDCGKTMFCMSLIKALGGRVISFANAKSQFWLQPLTESKIAMLDDATEACWNYLDTYLRNGLDGNWVSDCKHKAPIQIRFPPLLITSNYDILKNFLVSRIKIFEFKNKFPFNEDGTPMFELTDQSWKSFFQRLWKQLDLEDEFQCLNQRFNALEDQLMDIYEGSDKLEDQIKHWRKEQILLHYARRRGIMRLGYTPVPSLAASETKAKDVIYMVLQLEKLRDSPYKDEPWTLNTSLETYRAPPCFKKGPQNVEVIFDADPENIMLYTSWQFIYFEDTD-GHWQKTEGIDYAGLYYRHYYVEFKVDARRFSSRLKRLLDEALDPPVILLRGEPNTLKCYRYRVKDKLRGSFDKISTTWSWFVSEDQREKFINVMKLPWLSTTGKVYLPPSTPVRVQSTDSYIQRTNIYYHANTRLLTVGHPYFEVLVPKVSGNQYRAFRVHLPDPNRFALADMSVVNPDERLVWAVRGMEIGRGQPLGVGTSGHPLFNKVKDTENPNGYDDRVNTSDPKQIQMFVLGCIPCLGEHWDKALPCGACPPLELKNTIIEDGDMGDIGFGNLNFKTLSVTKSDVSLDIVNEICKYPDFLKMANDVYGNACFFYARREQCYARHMFCRGGYTPTVSGSLVSTDAQIFNRPFWLQRAQGHNNGICWGNQIFLTVIDNTRNTNFCIYNTANFREYLRHVEEYELSFILQLCKVPLEPEVLAQINAMNADILEDWQLGFVPSPINDTYSAATRCTPKEKADPFAGYHFWDVDLSEKLSLDLDQYSLGRKFLFQANKRK Seq31 M-EGK-KSFTSPFIIDIS-FIDEGN-TAQLFAQHQALDAAQEISAVKRKL-PLTGS-------KKGKLDSGYAWVNASSEKGAKLAIFKQTYGVTFASLTRVFKSDKTCCHNWVFSASEEVIEGSKQLRQYCDFYYASGHCVLYLLDFKASKNRETVIRLFLAVPDHCILSDPPKLKHVPAALFWLKTSNQPHVGQLPNWICQQTMLNYFELRKMVQWALDHNLTDDSMIAYNYAQLAEEDENANAWLNSNSQARYLKECALMTRHFLRAQRLEMTMAKWLTRCGDWKAIIKFLKYQNVNIVNFLSMFRDFMNSPKKNCLVICGAPNTGKSIFAMSLMQFLQGKTISFANHKSHFWLQPLADCKFAVLDDATLPCWSYLDIYCRNALDGNYVCDSKHKNPVQIKIPPLLITTNYNILQEYLHSRLLFLEFNNAFPLDEEGNPQFDLNDQNWKSFFIKLRRQLDLEEEV*RLEARFEEVQEKLLELLENPETLDEQIEYWKWENIYYNAARRKGIHKLGFSPVPSLQASEHGAKEAIGMKLQLTNLKSSGFGSEKWTLDTSSMTYLAPPTFKKLSKPVTVTFDSNSQNAVRYTCWSHVYYLN-DNDMYVKSYSVDVHGVYYKQYYVNFEKDARKYRSHERLHSAVKKDPYVILVRGKPNQLKCWRWRLHNRARRVFRCFSTTFSWFDTRQDRELFLHRV-TFWTPSTGRVYLPPSTPLKVLHTDDFVRRTSLFYHVKSRLLTVGNPYYKILVPKVNASQYRVFRVRLPDPNKFALSEPHIYDPDERLVWKLLGMQIGRGQPLGISSTGHPFFNKFLDTENPMAQDDRQNTSDPKQIQMFIVGCTPCNGEYWEKALPCGACPPIELKSVLIQDGFMCDIGLGAMNFKTLQDTKSGGSLDIVAEPCYYPDFLKMTDDSYGNSCFFYGKREQLYSRHYFVRGGYFTTPSGSLVTSESQILNRPYWLQRAQGTNNGICWNNQVFVTVVDTTRGTNFTIYDQNKFKQYSRHVEEFELSFIFELGVVVLSPEVLAHLHNMDKNILDDWNLGVVAPPLEDQYSQATKCPPTEKEDPYKGLTFWNVDLTDKFSSDLSQHSLGRKFLFQSNKKR Seq32 M-DPNLK-GQ-SFLDDLSDLIDQGN-SAELFAQQEAFAFQEHIRTTKRKLKLSFTSQ--SNAPKRRVLDSGYNLLAASSHRAVQLAIFKEKFGISLNSLTRIFKNDKTCCSNWVFGAREELLAASQILQRVCDSIMLLGFMGLYLLEFKNAKSRDTVRHLFLQVENNDMLLEPPKIKSLPAATFWWKLRHSSAAGNLPDWIARQTSITHFDLSAMVQWAYDHNFVDEAQIAYYYARLASEDSNAAAFLRCNNQVKHVKECAQMTRYYKTAEMREMSMSKWIKKCGDWKQIINFIKYQNINFLSFLACFRDLLHSPKRNCLVIVGPPNTGKSMFVMSLMRTLKGRVLSFVNSKSHFWLQPLNAAKIAILDDATRPTWSYIDTYLRNGLDGTPVSDMKHRAPMQICFPPLIITTNVDVAKDYLHSRLMSFEFANAFPLDENGKPALILNELSWKSFFERLWNQLDLEDEFRCLQARFDAVQEQLLEIYEDTSSLDVQITYWRHEQALYYYARRQGILRLGIYQVPPTGVSEKKAKDAIKMTLFLKSLQKSEFAAQPWSLETSLERFLAAPTFKKRGQHVTVIYDKDSMNAMEYTLWTEIYAVD-DNDQWHKYTSVDYDGIYFKNYYVSFADDAALYKGRLAELISAAYDPPVLLLQGCANTLKSFRRRTTQSYPHTFLCMSTSWTWFVNSEQRTLFLATVKIPWLPSQGKLYLPPPTAVQYLDTDDFVTRTDTFYHTNTRLLFVGHPYFKVLVPKVSGSQFRVFRLKFPDPNKFSFPDPNVYNSDQRLVWALRGIEICRGQPLGIGVTGHPSFNKFKDAENNNNKDDRVNMADPKQVQMFIVGCTPCDGEHWDVAQACGACPPIELKNTIIEDGEMCDTGFGNMNFQKLQASKSGAPLDIVNQIVKYPDFLKMGSDPHGNSMFFYAKREQMYVRHLWSRGGYFGSPSGSLVSSDQQIYNRPFWIQRAQGRNNGICWNNQLFVTAVDSTRGTNFTIYTAAEFKHYLRHVEEWEVSLVLQLCIVDLTPEALAHINGMDPRIIESWNLGFIHAPIEDQYSIATRCDAAATEDPYAKYTFWDVDLTERFSMNLDQYSLGRKFLFQIGKRR Seq33 M-DPNEK--VLSFIDDLSDLIDQGN-SAELFAQQEALAVQEHIRASKRKLKLSFTSH--SNAPKRRKLDSGYNFLRAGSRRATQLAIFKDKFNISFNSLTRPFKNDKTCCNNWVFGARDELLEASKLLQRHCDYLMLLGFMALYLLEFKHAKSRETIRHLFLQIEKEEMFLEPPKLKSLPAATFWWKISHSASAGELPDWIARQTSLSHFDLSQMVQWAYDHNYTDEPTIAYNYARMASEDSNAAAFLRCNSQVKFVKECAQMTKYYKTAEMREMSMGKWIKRAGDWKDIINFLKYQGINFLSFLASFKDLLHGPKRNCLVIVGPPNTGKSMFVMSLMKALKGRVLSFVNSKSHFWLQPLNAAKIAVLDDATKATWSYIDTYLRNGLDGTPVSDMKHRAPIQICFPPLLITTNVQVMKDYLHSRLMCFEFPNPFPLNEAGQPALILNELSWKSFFARLWRQLDL-EDFRCLQARFDAVQDQLIDIYEDTRSLEVQVTYWRREQALFYYARQQGITRLGLYQVPLTSVSERKAKEAIKMSMYLTSLQKSPFAQLSWSLETSPEMFFAPPTFKKKGSHVTVVYDKDSNNAMEYAVWGEVFYVD-ETDTWHKAQSVDYDGVYYKVYYVHFADDAAHYSRRLAQLIESANDPPVLLLQGCANTLKCFRRRTSHAHPHKFLCMSTSWTWFSDYEQRRCFLAGVKLPWLPSSGKLFLPPPTPVNILNTDDFVTRTDTFYHASSRLLNVGHPYFEVIVPKVSGSQFRVFRLQLPDPNKFTFQTPNVYNPEQRLVWALKGIEICRGQPLGIGVTGHPSFNKFRDAENLNNNDDRVNTADPKQVQLFIVGCTPCEGEHWDVAESCGACPPLQLVNTLIQDGEMCDIGFGNINNKALQATKSDAPLDIVDQIVKYPDFLKMSSDLQGNSMFFYAKREQLYLRHLWARGGYFGGPSGSLVSSDQQIFNRPFWIQRAQGNNNGVCWHNQLFVTAVDSTRGTNFTIYKSTDFNHYLRHVEEWELSCIMQLCIVDLKPETLAHLHNMDPRILETWNLGFIQPPIEDQYSLATKCETAEKEDPYAKYKFWDVNLTERFSSNLEQYSLGRKFLFQIGKRR Seq34 M-DP--K-TVLDFIEDISDLIDQGN-SAELFAQQQAFDFHKDICTTKRNLKRSLTSQ--SNAPKRRLLDSGYNLLRAGSRRAAYLGVFKEKFTISFTALTRIFKNDKTCCRNWVYRAREELLEASKILQKCCDFILLLGFLALFLLEFKTAKSRETVQRLFLQVEKEDMLLEPPKLKSLPAATFWWKIQHSNNSGTLPDWIARQTMISHFSLSVMVQWAYDHNYTEESTIAYHYAKLASEDSNAAAFLKCNNQVKHVKECAQMTRYYKTAEMTEMSMGQWIKKCGDWKQICKFLKFQNVNFLSFMSALKDLLHRPKRNCMVICGPPNTGKSMFVMSFMKALQGKVLSFVNSKSHFWLQPLRGAKVAVLDDATRATWTYFDTYLRNGLDGTPVSDMKHRAPLQICFPPLVITTNVNVMQDYLHSRIVCFEFPNTFPLDEAGNPLLLIDELSWKSFFERLWTQLDLEEDFRCLEARFDAVQDQLLQVYEDSNTLELCLQYWRRENALYYYARQQGKTRLGLYTVPPTRVSEQKAKDAIKMYLCLESLQKSEFANQRWSLDTSIETFKAPPTLKKRGQHVTVIYDQNAMNSMVYTLWKEVYYVD-ETETWHKTSSLDYDGIFYKIYYVNFQDDAALYSSRLAQLIDAAYDPPVLLLQGAANTLKCFRRRATQAHPHKFLCMSTSWTWFSNSEQRNCFLASVRLPWVPNSAKLYLPPPTPVQFLDTDEFVTRTDIFYHTSTRLLFVGHPYFTVVVPKVSGSQFRVFRLKFPDPNKFSFPTQDIYNPEQRLVWAVRGIEICRGQPLGVGVTGHPSFNKFKDAENLNQNDDRVNVCDPKQVQLFIVGCVPCDGEHWDKAQACGDCPPIELKNTKIQDGEMCDTGFGNMNFAALQASKSGAPLDIVDQIVKYPDFLKMGNDPYGNSMFFYAKREQMYVRHLWARAGYIGSPSGSLVSSDQQIYNRPFWIQRAQGSNNGMCWNNELFVTAVDSTRGTNFSIYTATKFKHYLRHVEEWDLSLIMQLCIVNLTPESIAYLHNMNESIIENWNLGFIQPPIEDHYSLATRCDTQVKEDPYKDLKFWDVDLTEKFTTNLNQHSLGRKFLFQIGKRR Seq35 MAEDKGTVSGSWYLDDDPEFISEGNSSELLHNNHMLAKDGEQIQLLKRKY-MSPSPRLALVSSKRRLFETKDKILKSKNQKATALAQFKEAFGVSFTDLTRSFISNKTCTQHWVFGPNSDILDGTGLLEPHCTFLLKCGPIILLLIEFKASKCRDTVQNLLMRVEHHQMLLEPPKIRSQLTAFFFYKKTMAGGCGKLPDWLTRLTVLSHFELSRMVQWAYDNDMLEDSEIAYYYAQHADVDSNAAAWLKTNNQAKYVRDCGNMVRLYKQQEMKNLTMSEYIYKRGDWKHIFKLLRYQDVNMIQFLTSFRDLLSCPKRQCLVIYGPPDTGKSYFLYSLISFLKGKVISFTNSKSHFWLQPLLNAKVALLDDATKACWNYMDCYMRTALDGNAVSDSKFKAPVQVRLPPLLISTNVELPLLYLHSRTMCYCFAKPCLYDDEGNPLFNLTDRHWKGFFLHLEQQLGL-SEFRCLAEHLDACQEQMLELIEDSQELEDQIDYWKRENLLLFAAKEAGLSRLGYEPVPPTKVSEGKAKNAIMMSISLQSLQSSEFGRDPWTLQTSLEVFMSNPCFKKNGEHVEVLFDGDKNKAVIFVKWGEVYVQDLLG-AWHKCPSVVYEGIYYRTFYLRFEEEAAKYAEGGGHTSTAPGHYPVLIGKGRPNCLKCWRNRFGVSHKGLFLDCSSTFSWFETEQQLQTFVDTVRPTWNNSS-KVYLPPTQPIRVLSTKEYVQTTGYYYHGQSRLITVGHPFYKIVVPQVSANQLRAFRIKLPDPNKFVFADPNFYNPEHRLVWLLKAIEIGRGGPLGVGCTGHPFFNKI-DTENPNKYDDRMHTSDPKHCQMFVVGCKPCIGSHWGLAKSCEHCPPIQLVNSFIEDGDMGDIGLGNMDFLSLQEDRSCAPLEIVTKKCKFPDFLKMQAEASGDSMFFYGRKESLYARHMFSRVGYFATPSGSLNASDSQLFNRAYFLRNSQGPNNGVLWNNEMFVTTMDNSRNTNFTIYDATRIKYYMRHVEIYELMFVLEVGKIELNGTVLAHINAMNPSVIDSWNLGFVPMPTEDTYSLATKCVP-EK-DPYDGYSFWEVDCTEKMTMELDQYPLGRKFLAQR-KKR Seq36 MEDKDNKYNAIDFIDDISDLIDEGN-SLALLNKQQLEDDTQQLKILKRKYFSPSSPRLQQLK-RRLVFDSGLGLLHSSNREATAYAKFKATFDVGYKELTRPFISNKSCCCSWIFGVVAEILEAAKLLQPHCEYLQIIGVTVMMLFQFYAAKCRDTVINLLLHVREWQIITNPPKHRSVAVALYFYKTSMSNVSGAMPEWIKKQTLVNHFEFATMVQWAYDNNIRDEAEVAYGYASLADDDTNAAAWLKCNNQFKYVKDCVQMVAMYKRYEMRNMTIGQWLVKCGNWKNIINFLKYQEISIVAFLTTLRYFLQGPKKNCLAIWGPPDTGKSMFCYSLIKYTQGKVVSFVNSRSQFWLQPLVDGKIGLIDDATFACYQYMDVYMRNGLDGNAVSDVKHKAPIQLKLPPLLLTSNIEVHAEYLHSRIQEYKFPNKLRLDANGNPIITITDADWKSFFSKLWKQLDL-DDFRCLVDRFDAVQDRLLGIYEGRTDIDGQIVHWRQEYVLLHYARKNGISNLGIQKVPSLATSESKAKQAILMGIVLKSLKNSAFGNEQWTLDTSYELFMTPPTFKKQGKTIEVWYGNNEDNAVPYTLWTAIYYQDAQ-DNWYKARGVSADGLYYKHFYVRFADEATQFRSRLARLQDEARDPPVILIKGPANTTKCWRYRMKQNYRALFESISTAFSWFRNNSQRERFLHTVKLPWLPQTGKIYLPPAPPVRSLTTDEYVVETSVFFHASSRLVTVGHPYFTVEVPKVSGNQFRAFRLRLPDPNKFALIDKQLYNVEERLVWRLRGIDIGRGGPLGIGSTGHPLFNKLKDTENPNGYDARQNVSDPKQTQLFVVGCTPCKGEHWDVAPACGTCPPLQLVSSVIQDGDMCDIGFGAMNFAALQADHSGVPLDIVADTCKWPDFLGMANDRFGDGMFFFGRREQVYARHYFTHNGYFATPSGSLASSDSQLFSRPYWIERAQGANNAVLWNNNVFVTLVDNTHNVNFTIYDSAKYKHYLRHVEEFEISLIVQLCKVSLTPDVLAHIHLMNPSILDEWQLGI-AAPIETTYSLATMCPPKEKEDPYDKMSFWVVDLSDRMSSELGAYPLGRRFLHQTGKRR Seq37 MEDKDTKANACEFIEDISELIERGN-PQALLNRQQLEEDSQLLTVLKRKYVSPSSPRLEAL-SKRRLFDSGLGILHSSNRQATALTKFKNVFGVGYKEITRPFQSNKSCCHSWVFGVVAEMLEAAKLFKVHCDYLQIIGVTVLCLFEFSSSKCRDTVQKLILNVQEHQIITDPPRHRSVPVALFFYKQSMSNTSGTMPDWLKRQTMLNHFELSHMVQWAYDNNIWDEAELAYQYACLADVEPNAAAWLKSNQQYKYVSDCAKMVRMYKKYEMQQMSMAQWIKKCGDWKKIINLLKYQEISVIAFLTSFRMFLKGPKKNCIALWGPPDTGKSMFCYSLIRYVKGKVVSYANSKSQFWLQPLTDAKLGLIDDATFPCFQFMDVYMRSALDGNEVSDCKHRVPVQIKLPPLLVTSNIDMHSEYLQSRITSFKFPHKLPLDTNGNPIFIITDTDWKCFFSKLEQQLDL-EDFRCLVERFDAVQEKLLGLYEGRSDLESQIQHWRQEHVLLNYARRQGIQTLGLQKVPPLAASESKAKTAIMMQLVLKSLKKSQYGQEPWTLDTSHELFTTAPTFKKGGVTVEVLFDNEEEKAMPYTLWRLIYYQDAD-ELWHKTHGVDADGLYFKHYYVHFTKEAVKYPSRLARLQAEAWDPPILLVKGPSNTLKCWRYRCRIKYRGLFQCISTAFTWFTNTSQREKFIQTVKLPWLPQSGKLYLPPSQPVKILPTDEYVVETSIFFHASSRLLTVGHPYFTIVVPKVSGNQFRAFHILLPDPNKLALVDSNIYNAEERLVWKLRGLDIGRGGPLSVGSSGHPLFNKLKDTENPNSYENRQSVSDPKQTQLFVVGCTPCLGEHWDAAKPCGACPPLELVSSIIEDGDMCDIGFGAMNFATLQEDHSGVPLDIVASKCKWPDFLRMANDTYGNQMFFFGRREQLYARHFFARDGYYATPSGSLVSSDSQLFGRPYWIQKAQGPNNSVCWRNNLFITLVDNTHNVNFTIYAATSYKHYLRHVEEFEIALILQLCKVPLTADVLAHIHVMDPAIIEDWQLGFVPPPIGDTYSLATRCPPKEKQDPYDKLSFWKVDLTERLSSDLDRYPLGRRFLSQTGKKR Seq38 MAEGGERLDAGWFVVNVSDLIDN-EGHAGVLNQQLLEESEQQTAYLKRKYCTPSSPRLQAVHSKRRLFDSGI-LQGSNQEATIL-AKFKGCFGVSLKELTRPYKSSKTCCNEWVFGIREELLTASKLLQPHCDFFLADGYVCLYLITFKAAKNRETITKLFLNCYDYQLRADPPKNRSVAVALFFYKLGLSGGCGDFPPWLAKQLLVSHFELSKMVQWAYDNDHTDESEIAFHYACLADEDSNAAAWLKSNAQAKYVADCSKMVRHYKKQEMRNMSMSQWIYRCGDWTVVAKYLKYQGVSFLGFLTALRHLFEGPKKQCLLIYGPPDTGKSWFCFSLLNFLRGKVVSYQNSRSHFWLSPLADCKVGMLDDATHACFQFIDVNMRSAFDGNYVSDCKHKAPIQIKLPPMLVTSNVNLPGEYLHSRVTGFEFPRKFPIDQDGSPVFSLTHSVWKAFFKRLHHQLGLEDEFRCLARRFDVLQEVMLHHYEGSKKLTDQCNYWRRESALLHYARKNRITRLGITPVPSLATSENSAKKAIRMSLLLSSLCNSPYKDEPWTLDTSIELWECPPCFKKGGFTVDVLFDNDPGNVFPYTAWAYIYYQN-QNDEWIKVPGVDYDGLFYKRYYQTFAKDALRFEPEPGRSQEQNRPFPVILVKGDGNASKCWRRRLRLRYSGLFESISTGFSWFNSDGQRDHFLKNIKIPWIQSQGKLYLPPPKPVKVIHTDDFVRPTAIYYYGSTRLLTVGNPYFTIIVPKVSGNQYRAFRLKLPDPNKFALTDPTVYNPDERLVWRLTGIEIGRGGPLGFGTTGNFLFDRLQDTENPNNTDDRQNVSDPKQTQLFVVGCTPCKGEHWDQAPRCGDCPPLKLVSSIIEDGQMCDVGFGAMNFKVLQFNKSGVPIDIVDTVCKWPDFLQMNNEKYGNSCFFFGRREQVYCRHMFVRGGYVGTPSGSLVTSDSQIFNRPYWIRQAQGHNNGVIWNNNLFVTVVDNTRNTNFTIYKSEEMRNYVRHVEEYELTIIVQLCIVPLEPEVLTHLNTMDPTILENWNLGVIPPPLESNYSLATMCPPKKKEDPYDALNFWTIDMTEKLSLDLEQFSLGRRFLYQYTKKR Seq39 M-DAVNK-G-WCFIE----FLDDRGNHLALFTQQLFSEDDQHIAALKRKYAATPSPRLHSCQSRRRLFDSGIGLLRMSNRVAASLARFKDAFSVSFSDLTRSFKSDKTCSVNWVFGAREPLLEALLVLKPQCDYFQTVRRVDIILFEFKVGKSRNTLRKQMLGLDEKLIMADPPNHRSTLAALFFYKKVLFGAAGQTPAWIAQQTILEHFDFSKMVQWAYDNQLIEESEIAYRYACEAETDANAQAWLKCTNQVKHVRDCCAMVRLYKRQEMRDMTMAQWVRKCGDWKTIAGFLRYQEVNMVLFLTALRHMFKGPKKHCLVISGPPDTGKSYFCNSLNTFLHGRVISFMNSKSQFWLQPLVDAKMGFLDDATNACWTFMDIYMRNALDGNPMQDMKHRAPLQLKLPPLLITTNVDVMHNYLHSRLQCFAFEKPMPLNNDGHPQFPLHAANWKSFFTRLAKQLGIEEEFRCLEARFDAVQEQILSLYEGSTDLADHVKYWRAEGALEYCARQSGRNKLGLHSVPSSVGAESKAKKAIHMQMVLSSLQDSSFGSEPWTMDTSLEMYERTSTFKKKGSEAEVTFGSDPDNSVSYMVWGCVYTQD-EDGQWHKHMSVDYYGVYYRVYYHQFDEDSKTFSCQRRVPNPVHCDPPVILLKGPTNTLKCWRNRLRRRHFRPFIKISTAFSWFLDSQQRDVFLKTVPIPWTPQNGKLYLPPTAPVRVQNTDEYVVPTGLYCHAMTRLLTVGHPYFKVTVPKVSGNQYRVFRLKFPDPNRFALPRDDFYNPEERLVWRLRGLEISRGGPLGIGTTGHPLFNKLGDTENPNKYDNRQNTSDPKQTQMFIVGCVPCTGEHWDVARACGDCPPIQLVNSTIEDGDMCDIGFGNMNFKALQQDKSGAPLDIVATKCKWPDFLKMTNEVYGNSLFFFGRREQLYARHYFTRNGYFGTPSGSLVSSDGQLFNRPFWLQRAQGNNNGVCWSNELFVTMVDNTRNTNFTIYDSQNFKQYLRHVEQFELSLILQVCKVPLQPNVLAHINTMNPDILEDWNLGFVPPPITDDYSLATRCPPKEKEDPYKGLVFWEVDLTERFSQDLDQFPLGRKFLFQTGKRR Seq40 M-D-NDK-YRWAFLD----FLDQGN-SLALLTSQLFEQDEQHITALKRKYVTTPSPRLNAVTSRRRLFDSGVGLLRANNVYNACLARFKEAFGVGFTDLTRSFKSNKTCSQHWVFGAPETLIEAAKQLGEQSLFLQHQKRVDLFLFQFKAEKCRLTLTKQVLGVAERLVLAEPPNCRSNLAAFYFYKKTLGKEPGSSPEWIVKQVLIEHFDFSKMVQWAYDNNYVEESEIAYNYALEAETDSNAESWLKTTSQVKYVKDCAQMVRMYKRQQMREMSNTQWIRKCGDWKVIAAFLRYQEVNLVMFLSALRNMLKGPKRHCLVITGPPDTGKSYFCTTLVSFLKGRVISFMNSKSQFWLQPLADAKIGFLDDATHTCWTYMDTYLRNALDGNPVQDMKHRASIQLKLPPLLITSNIDVMNMYLHSRLQSFEFTKRMPLDSKGQPEFVLSAANWASFFTRLAKQLGLEEEFRCLQDRFDALQEQILNLYEGSSLLQDQITFWRKEGALEFFARKQGFTRLGLHVVPSQASAEAKAKGAISMSLYLTSLQESPYGSEKWTMETSREMFEQTETFKKGGVHVQVYYDCDKKNEVSYVLWTSVYVQN-EEGFWQKHSSVDYYGVYFKSYYHNFEKDSVKYLGRYGRLIADARDPPIVLVKGPTNALKCWRNRLRRRFHKPFQNVSTAFSWFLDEHQRSVFLETVPLPWLP-NGKLYLPPTAPVKVQSTDEYVIPTTLYCHANTRLLTVGHPYFKVTVPKVSGNQYRVFRLKFPDPNKFALQQLDIYNPEERLVWRLRGIEIGRGGPLGIGTTGHPLFNKLGDTENPTKYDNRQNTSDPKQTQMFIVGCVPCTGEHWDVARPCGDCPPIQLVNSVIQDGDMCDIGFGNMNFKTLQEDKSGATLDIVSTMCKWPDFLRMTNEIYGDQMFFFGRREQVYARHYFTRNGYFGTPSGSLVSSDGQLFNRPFWLQRAQGNNNGICWNNELFVTLVDNTRNVNFTIYDSQNFKQYLRHVEQFELSVIVQLCKVPLEPSVLAHINVMNPNILEDWNLGFVPPVISDDYSLATRCPPKEKEDPYKDLSFWEVDLTERFSQDLDQFPLGRKFLFQTGKRK Seq41 MAD-KGTGCSGWYIVETNSFIDQGN-SLSLFHEQLFLSSEEQIACLKRKYAATPSPRLESVSSRRKLFDSGIGLLKSSNIYATCLSKFKTAYGCSFAELTRQFKSDKTCSPHWVFGAPEQLVEASKLLPQHCEYAQLSSKVLLFLFEFKASKNRETVRKLLLGVQECLIIAEPPKERSVLSALFFYKKVMFQGSGQLPEWVAKQTLVEHFDLSRMIQWAYDNDYAEESAIAYNYALYAEADANAEAFLKSNCQAKYVKDCATMVRLYKRQEMRDMSMSQWVKKCGDWKVIAAFLRYQEVNVVLFLAALRHLFLGPKKHCLVIYGPPDTGKSYFCTTLVGFLKGKMISFMNSKSQFWLQPLVDSKIGFLDDATTACWQYMDVFMRNALDGNPISDMKHRAPTQIKLPPLLITTNVNVQANFLHSRLQFFAFNKPMLFDDSGNPQYPLSKANWRSFFTRLGKQLGIDDEFRCLTERFDAVQDQILNLIEGSTALADHVLYWRKEGVLQYYARKHNMNRLGLHALPCQLGAETKAKKAIQMGMLLRSLLDSKYGSEPWTVETSLELYEQTDTFKKGGQTIEVHYDNDPENSVAYTLWKYLYKQD-EAGQWHKLEGVDYAGLYYHVYYEEFCEDSDRYFGGYPEVLGRSGDPPILLLTGPANCLKCWRNRVKRRPHRLYKRMSTCFSWFTDALQREQFLRTVPLPWMQPSGKLYLPPAKPIRVQSTDEYLQPTSFYCHASTRLLTVGHPYFKVVVPKVSGNQYRVFRLKLPDPNKFALAQQDLYNPDERLVWRLRGLEIGRGGPLGVGTTGSPLFNKLGDTENPNKYDNRQNLSDPKQTQMFIVGCAPCTGEHWDIAKPCGDCPPIQLVNTVIQDGDMCDIGFGAMNFKTLHDDKSGVPLDIVNSACKWPDFLKMTNEVYGDRMFFFGRREQVYARHYFVRNGYFATPSGSLLSSDGQLFNRPFWLQRAQGNNNGICWGNDLFITLVDNTRNVNFTIYAATNFSQYLRHVEQFEISCIFQICKVPLDADVLAHLNVMNPDILEDWNLGFVPPPIHDEYSLATRCPPKEKDDPYKDYTFWTVDLTERFSQELDQFPLGRKYLYQSGKRR Seq42 MADKGTD-GNNWYIVNISNLIDQGN-SLALYNAQINEDCDNALAHLKRKYNKSPSPQLQAVHSKRRLFDSGIFLLQSSNRRATMLAKFKEWYGVSYNEITRIYKSDKSCSDNWVFRAAVEVLESSKVLKQHCTYIQVK--SALYLVQFKSAKSRETVQKLMLNIQEYQMLCDPPKLRSVPTALYFYKHAMLTESGQTPDWIAKQTLVSHFELSRMVQWAYDNNYVDECDIAYHYAMYAEEDANAAAYLKSNNQVKHVRDCSTMVRMYKRYEMRDMSMSEWIYKCGDWKPISQFLKYQGVNILSFLIVLKSFLKGPKKNCIVIHGPPDTGKSLFCYSFIKFLKGKVVSYVNRSSHFWLQPLMDCKVGFMDDATYVCWTYIDQNLRNALDGNPMCDAKHRAPQQLKLPPMLITSNIDIKQEYLHSRIQCFNFPNKMPILDDGSPMYTFTDGTWKSFFQKLGRQLELEEEFRCLVARFDALQEAILTHIEQESTLESQIQYWRKENAIMHYARKQGLTKLGLQPLPTLAVTEYNAKQAIQIHLTLQSLLKSPFASERWTLDVSAELINTSPCLKKGGYDVAVWFDNDRQNAMLYTNWDFLYYQDMN-EQWHKVKGVDYDGLYFRAYFTLFSSDAQRFLSRLGLLQAEARDPPMILLKGTANSLKCWRYRKVNSNCCNFLFMSTVWNWFDSTDQRDAFVKHNLFPWLSTTGKVYLPPAQPVRVLETDEYITGTSLYFHAGTRLLTVGHPYFKVLVPKVSGSQFRVFRFNLPDPNRFALIDNGFYDSDERLVWKLRGIEIGRGGPLGIGTTGHPLYNKFGDTENPNGYDNRQDVSDPKQTQMFIIGCTPAIGEHWDKAEPCGDCPPIELVNSYIQDGDMCDIGFGAFNFKALQADKSSAPLDVIATVCKWPDFLKMGKDIYGDSLFFFGRREQLYARHFFVRAGYVGTPSGSLVSSESQLFNRPYWLNRAQGTNNGICWDNQLFVTLVDNTHNTNFTIYKASDFKQYLRHIEEFEMEFIFQLCKVPLTADVMAHLNVMNPNILDNWQLNFVPPPIEDQYSRATRCPATEKEDPYKDLSFWVVDLSERFSSELSQFSLGRRFLYQSGKRK Seq43 MADKGTE-GSSWYIVNVSNLIDQGN-SLALYNAKITDDCDNAIAHLKRKYNKSPSPQLQAVNSKRRLFDSGIFLLQTSNRRATMLAKFKDWYGVSYNEITRVYKSDKSCSDNWVFRAAVEVLESSKVLQQHCTYIQVK--SALYLLQFKSAKSRETVQKLMLNIQEFQILTDPPKLRSVPTALYFYKQAMLTESGQTPDWIAKQTLVSHFELSKMVQWAYDNNLLEECDIAYHYAMYADEDANAAAYLKSNNQVKHVRDCSTMVRMYKRYEMRDMSMSEWIYKCGDWKPISQFLKYQGVNILSFLIVLKSFLKGPKKNCIVIHGPPDTGKSLFCYSLVKFLKGKVVSYVNRSSHFWLQPLMDCKVGFMDDATYVCWTYIDQNLRNALDGNPMCDAKHRAPQQLKLPPMLITSNIDVKQEYLHSRVQCFSFPNKMPFLDDGSPMYTFTDATWKSFFQKLGRQLELEEEFRCLVARFDALQEAILTHIEQDDTLESQIRYWRKENAIMHFARKQGLTKLGLQPLPTLAVTEYNAKQAIQIHLTLQSLLKSPYGSERWTLEVSAELINTAPCLKKGGYDVSVWFDNDRYNAMVYTNWDYLYYQDVN-EIWHKVKGVDYDGLYFRAYFTLFSTDAHRFLSRLGQLQAEARDPPMILLKGTANSLKCWRYRKQNSSNCGFLFMSTVWNWFKSPGQRDSFVKHNLFPWLSAKGKVYLPPAQPVRVLETDEYITGTSLYFHAGTRLLTVGHPYFKVLVPKVSGSQYRVFRFYLPDPNRFALIDNGFYDSDERLVWRLRGIEIGRGGPLGIGTTGHPLYNKFGDSENPNGYDNRQDVSDPKQTQMFIIGCTPAIGEHWDKAEPCGDCPPIELVNTYIEDGDMCDIGFGAFNFKALQQDKSSAPLDVVATMCKWPDFLKMSKDVYGDSLFFYGRREQLYARHFFVRAGYIGTPSGSLVSSESQLFNRPYWLNRAQGTNNGICWDNQLFVTLVDNTHNTNFTIYKAGDFKQYLRHIEEFEMEFIFQLCTVPLTADVMAHLNVMNPNILDNWQLNFVPPPIEDQYSRATRCPSTEKEDPYKDLSFWGVDLTERFSSELSQFSLGRRFLYQSGKRK Seq44 MADKGTE-GSSWYFVNISNLIDQGN-SLALYNTQITDACENAIAALKRKYTKSPSPQLQAVKSKRRLFDSGICLLQDNNRRATMLAKFKDWYGVSYTEITRLYKSDKSCSDNWVFKAPVEVLESSKVLQQHCQYIQVK--SALYLLQFKSSKSRETVYKLLLNIQEFQILADPPKLRSVPAALYFYKHALLTECGQTPDWIAKQTIVSHFELSRMVQWAYDNNHLEECDIAYHYALYADEDANAAAYLKSNNQVKHVKDCSTMVRMYKRYEMREMSMSEWIHKCGDWKPISHFLKYQGVNILSFLIVLKSFLKGPKKNCILIHGPPDTGKSLFCYSLIKFLRGKVVSYVNRTSQFWLQPLMDGKIGFLDDATYVCWTYIDQNLRNALDGNPMSDAKHRAPQQLKLPPMLITSNINVKQEYLHSRVQSFEFPNKMPFLDDGSPLYTFTDATWKSFFEKLGRQLDLEEEFRCLVARFDALQEEILTHIEGNTTLESQIKYWRKENAIMHYARKQGLTKLGLQPLPSLLASEYNAKQAIQIQLTLLSLLKSPYASEPWTLEVSAELINTPPVLKKGGYDVTVWFDDDRNNTMVYTNWTALYYQDAN-EIWHKVKGVDYNGLFFRAYFTLFSTDAERYLSRLGQLQADARDPPMIMLKGHANSLKCWRYRKLTSNSCGFLYMSTVWNWFTSTDQRDYFVKHHFFPWLSTTGKVYLPPAQPVRVLETDEYITGTSLYFHAGTRLLTVGHPYFKVLVPKVSGSQYRVFRFQLPDPNRFALIDNGFYDSDERLVWRLRGIEIGRGGPLGIGTTGHPLFNKYGDTENPNAYDNRQDVSDPKQTQMFIIGCIPAIGEHWDKAEACGDCPPIELVNTYIEDGDMCDIGFGAFNFKALQDDKSSAPLDVVGTLCKWPDFLKMSKDIYGDSLFFFGRREQLYARHFFVRAGYFGTPSGSLVSSESQLFNRPYWLNRAQGTNNGICWDNQLFVTLVDNTHNTNFTIYKANDFKQYLRHIEEFEMEFIFQLCRVPLTADVMAHLNVMNPNILDNWQLNFVPPPIEDQYSRATRCPPAEREDPFKDLSFWTVDLSERFSSELSQFSLGRRFLYQSGKRK Seq45 MADPNKGH-SEWYVVIVSNLIDEGN-SLALYNEQLTEDCNRAILALKRKLTKTPSPRLEAVQSKRRLFDSGLGIFRSTNRKATLLAKFKEYFGVAYGDLTRPFKSDRSCCENWVCAAAEEVIEASKVMQQHCDFLQVI--YALYLVKFKTAKSRDTIMKLFLNVQEQQLMCDPPKSRSTPTALYFYRRSFGNASGPFPDWLAKLTMLDHFELAQMIQFAYDNNLTTESEIAYKYALLADSDANAAAFLKSNQQVKYVRDCYAMLRYYKRQEMKDMSISEWIWKCGNWKLIAQFLRYQEVNFISFLCALKTLFKGPKRNCLVFWGPPDTGKSYICSSLTRFMQGKVVSFMNRHSQFWLQPLQDCKLGFLDDATFQCWQYMDVNMRNALDGNHISDLKHKAPLQIKLPPLLITTNVDVENEYLKSRLVFFKFPNKLPLKENDEVLYEITDASWKCFFIKFASHLELGDEFRCERS-DALQEQI-LNLYEDSKDIQAQIQYWRKLYVTYYYARKEGYSHLGLQPLPALQVSEYKAKQAIEMGLLLTSLSKSQYASELWGLDTSAELLLTPPTFKKKGYTVNVWFDNNENNTFPYTNWEYIYYQD-DIEQWHRTRGVDYNGLYFRAYFLLFDSDAQTYISRLARLQGEARDPPILLIKGLANSLKCWRYRLKKY-TRYFKCMSTVFRWFNDTTQRDVFMKLVTLPWLQTAGQLYLPPSKPVRVLSTDEYVQPTNLVFHTGTRMLIVGHPYFNITVPKCSGNQFRVMRLLFPDPNKFAMIDRAVFNPEERLVWRLEGLEIGRGGPLGIGTSGHPLFNKYGDTENPAAYDNRMDVSDPKQMQLFIVGCKPATGEHWDIAKPCGSCPPIKLTQSIIQDGEMCDTGFGNANFITLQEDKSGVPLDITNEICKYPDLLKMTKDIYGDAVFFFGKREQIYSRHYFVRGGYFPTPSGSVASSDNQLFNRPYWLHRAQGANNGICWGNQLFITIVDNTRNTNLSIYKQEDFRQYLRHTEEYEVELILRLCKVPLNPDVLAHLNVMDKNILEDWQLSFVPPPIEDAYSQATMCPNTEREDPYKQYTFWTIDLQERFSNELSQFSLGKRYLYQYGKRK Seq46 MAELKGTI-NELFDNTISNLIDQGN-SHALLNAQLSEEYDKDLVTVKRKFYATPSPRLSAVQSKRRLFDSGI-LLHSNNRRAALLCKFKEKYGIPFNEITRTFKSNKSCTQNWIFACAEDLIEASKTMQNHVSYLQMI--SALYIICFKAAKSRETVVKLILNTKEEQVLCDPPKIKSMAAALYCYKKVIADTCGDFPDWIATHTVINHFKFSDMVQWAYDNDMLDEAAIAYNYACYASENENAAAFLQTNSQLKYVKECCAMVRLYKKQEMRNMTMPEWIKSCDDWKVIVRYLKYQNINFLEFLLALKLLLKGPKKMCLVIYGPPDTGKSYFCYQFIQFMRGKVVSFMNKNSHFWLMPLLDSKIGFLDDATQCCWMYLDTHMRNAFDGNAVSDVKHKNLQQIVLPPMLITTNCDVCRDYLRSRLTCFNFPNKLPLYENGEPKFKFTDNCWTSFFSKFWKHLDLDPDFSCLSARFLAQQDIQLNLIEDSKNLKDHIDYWRKEQVLAFYAKKENMSRLGLQPLPPAKVSEQKAKDAIRIQLLLQSLYKSDFGSEPWTLECSLEMLNAPPCFKKQPFTVTVQFDNDPKNVYPYICYEYIYYQD-DRDKWHKVKGVDHNGLYFSVYFKLFQPDATVYLSRLRRLQEEARDPPVLIITGQQNNLKCWRYRFSQKYADLYECCSSAWKWFKNPEQRLSFLNTVGLPWSSTSGKLYLPPSTPVRVLSTDEYVKETDVYFHARSRLLIVGHPYYDIKVPKVSANQYRVFRCELPDPNKFALIDTTLYNSDERLVWKLVGIEVGRGGPLGVGSTGHPLFNKVGDTENPSFYDERQNLSDPKQTQLLIVGCKPAVGEYWDLAEPCGKCPPIQLVNSYIQDGDMGDIGFGNANFPKLQQDRAGVPLDIVDSISLWPDLLKMTKDVYGDHVFFYAKQEQLYARHLFTHAGYFTTPSGSLNTSSSQLFNRPYWIRRAQGTNNCICWGNEVFVTVFDNTRNINFNIYSKDDFNQYSRHTEEYELEFIFQLCKVGLDADILAHLNVMDPRILENWQLAYVPPAIGDTYSDATKCSSAEVVDPYKEYTFWNVNLTEKFSSELDQYALGRKFLFQTGKRK Seq47 MADHKGTLDGSWCLIVVSNLLD------SIIQGN-SEESDRCIQELKRKLNVTPSPRLSAVASKRRLFDSGVVILRSNNIRATVLCKFKDKFGVSFNELTRSFKSDKTCTPNWVIGIREDLRDACKLLQQHVEFLEMI--SVLLLVEFKVTKNRETVLKLMLNAKEEQILCEPPKLKSTAAALYFYKKIITDTCGTLPSWVSRLTIVEHFSLSEMVQWAYDNDFTEEASVAYNYACYATENTNAAAFLASNMQVKYVKDCVAMVRMYKRQEMKSMTMSEWISKCEEWKEIVQFLKYQGVNFLEFLIALKQFFKCPKKMCIVIYGPPDTGKSMFCFKLVQFLKGQVVSYINKSSQFWLMPLQDAKIGLLDDATHNCWIYLDTYLRNAFDGNTFCDIKHKNLQQTKLPPMIITTNVNVTTDYLRSRLTCFNFPNKLPMSDKDEPLFTISDKSWTCFFRKFWNQLELDA-FCCLSTRFAAQQEIQLTLIEESYDLKDHLAYWRLENVIAYYARKEHITKLGLQPLPTLAVTEYKAKEAINIQLLIQSLLKSEFALERWTLETSAETINSSPCFKKVPFIVNVWFDNDERNSFPYTCWDFIYYQD-DQNKWHKTEGVDHNGCYYFVYFTLFQPDAVKYYSRLGRLQEEARDPPLVLFTGQQNNLKCWRNRCTTKYASLFLCFSSVWKWFKSDAQRQVFLNTVHIPWSAVPGKVYLPPSAPVRVLRTDEYVQETDVYFYTSTRLLIVGNPYFTITVPKVSANQYRVFRCKLPDPNKFALVDKNLYNSDERLVWKLVGLEVGRGGPLGVGSTGHPLLNKIGDTENPSFYDERQNVSDPKQSQILIVGCAPATGEYWDLAKPCGAAPPIQLVNTVIQDGDMGDIGFGAANFPKLMQDRAGVPLELIDSISIWPDFLKMTKDIYGDSVFFFGKREQCYARHLFARAGYFTTPSGSLNTSDSQLFNRPYWLRRAQGTNNGICWGNELFITVFDNTHNVNFTIYNNADFKQYLRHTEEYEIELVFQLCKVNLTADVLAHLHVMNPRILEEWQLAFVPPAIEDTYSMATKC-P-EEDDPYKAYSFWTLDMTERFSSDLSQFSLGRKFLYQTGKRR Seq48 MTD-RGT-NDDWYIVDISDLLDQGN-SLELFHLQEHLQNEQDLNTLKRKYLNSPSPRLESIKARKQLFDSGIEILKCSNTRSALLAKFKDTVGVSFTDLTRAYKNNKTCCSYWVWGVTSTSVDVVKVFQVQCNYMHVENKFLIVLAGFKAQKSRETVLNLVLNVQSNYIMAEPPKNRSMAAALYWYRRSMSPAVGEMPDWMAQQTLLNHFELSQMVQWAYDNGYTDESDIAYYYAILAEEDENAKAFLASNAQAKYVKDCARMVSHYKRAEMSSMSMSAWIYKRGDWKHIVKFLRFQEVEFISFMIAFKELLSGPKKNCLVIYGPPNTGKSMFCMSLLRVLKGKVISYVNSKSQFWLQPLASTKIALLDDATKPAWDYIDLFLRNALDGNPICDLKHKAPQQIKCPPLMITSNINVKADYLHSRITCFEFKQPFPFDENGQPAFSLTDINWKSFFERFWSQLDLEDELRLLNNRLDWLQEQLLTLYEDSKDIEDQIMQWRQEQVLFHYARKKGIMRLGLQVVPSLAASQDKAKTAIEMTLYLSGLRDSQYGSEQWSLDTSREIFLAPPTFKKGGQTIEVIYDEDPNNSTRHTVWRHIYYQNGD-NRWRKAASVDVHGVFYKNYYVDFQEEANRYQSRLRRLIQEARDPPIICLKGGPNQLKCLRYRIKASNSSDFESISTTWHWFISTEQRDRFLDKVVVPWLPAQNKFYLPT-QPIKILSSDDYVSRTNIFYHATSRLLIVGHPLYTMTVPKVSPNQYRVFRVRFPDPNRFAFGDKDIFDPEERLVWGLRGIEIGRGQPLGVGISGNPLLNRFDDAENPSRYDNRQNVADAKQTQMFLIGCTPATGEHWSIARRCGDCPPIELVNTVIEDGDMFDIGLGAMDFGSLQANKADAPLDIAGTVCKYPDYIKMGQEVHGNSLFFFARREQMYLRHVFTHAGYFVAPSGSLVSSDVQIFNRPYWLQRSQGQNNGICWRNELFVTVADNTRGTTMNIYDSADYNEYTRHVEEYELSFIVQLCKVKLTPENLAFLHNMDPTIIDSWQLTV-SQPIEDKYSLATKCPPPTP-DPYKDLRFWDVDLSERMSEQLDQFPLGRKFLYQSGKRR Seq49 MADNKGT--NDWFLVDLSDLLDQGN-SLELFHKQESLESEQELNALKRKLLYSPSPRLETIRYRRQLFDSGLEILKASNIRAALLSRFKDTAGVSFTDLTRSYKSNKTCCGDWVWGVRENLIDSVKLLQTHCVYIQLENRFLFLLVRFKAQKSRETVIKLILPVDASYILSEPPKSRSVAAALFWYKRSMSSTVGTTLEWIAQQTLINHFELCKMVQWAYDNGHTEECKIAYYYAVLADEDENARAFLSSNSQAKYVKDCAQMVRHYLRAEMAQMSMSEWIFRKGNWKEIVRFLRFQEVEFISFMIAFKDLLCGPKKNCLLIFGPPNTGKSMFCTSLLKLLGGKVISYCNSKSQFWLQPLADAKIGLLDDATKPCWDYMDIYMRNALDGNTICDLKHRAPQQIKCPPLLITSNIDVKSDYLHSRISAFKFAHEFPFKDNGDPGFSLTDENWKSFFERFWQQLELEDELRLLSSRLDLLQEQLMNLYEDSKLIEDQIKQWRQEQVLFHFARKNGVMRIGLQAVPSLASSQEKAKTAIEMVLHLESLKDSPYGTEDWSLDTSRELFLAPPTFKKSGSTLEVTYDNNPDNQTRHTIWNHVYYQNGD-DVWRKVSSVDAVGVYYKNYYVLFAEEASKYSSRLRRLLQEAWDPPVVCVKGGANQLKCLRYRLKASTQVDFDSISTTWHWFIDEAQREKFLERVALPWLPAQNKFYLPP-QPIRILSTDEYVTRTNLFYHATSRLLLVGHPLFTVTIPKVSPNAFRVFRVRFADPNRFAFGDKAIFNPEERLVWGLRGIEIGRGQPLGIGITGHPLLNKLDDAENPTNYDSRQNTADAKQTQMFLVGCTPASGEHWTSSR-CGDCPRVQMIESVIEDGDMMDIGFGAMDFAALQQDKSDVPLDVVQATCKYPDYIRMNHEAYGNSMFFFARREQMYTRHFFTRGGYVGTPSGSMVSSDVQLFNRSYWLQRCQGQNNGICWRNQLFITVGDNTRGTSLSIYSNANFNDFLRHTEEFDLSFIVQLCKVKLTPENLAYIHTMDPNILEDWQLSV-SQPLEDQYSLAAKCPPEP-QDPYSQYKFWEVDLTERMSEQLDQFPLGRKFLYQSGKRR Seq50 MAE--GTGSSGWFLVTIGDLIDQGN-SLELFHQQETAEVLAEIAQLKRKYCDSPSPRMQSVSVKKRLFNEAVSVFTQSSSRIAQLAIFKEAHTVSFAELTRPFKSDKTVCGDWVSGVHCALGDSLKSLRSHCMFFLYDSTSILLLLRFKSQKSRDTVTSLLLGVDHIQVMLDPPKTRSVPAALFWYKRAMVTAVGPFPEWITQQTQVNHFELSTMIQWAYDNHITEESKIAYQYALLADSDENAKAFLASNAQAKYVKDCAAMVRLYFRAEMQEMSISAWIHYRGDWKEIVRFLRFQGIEYIPFMISMKKFLKGPKKNCIVIYGPPNSGKSYFCMSLLRLMGGKVISFANSKSHFWLQPLADAKIGLLDDATKPCWDFIDTYLRNALDGNPISDCKHRAPTELKCPPLLVTTNVDVMGDYLHSRIVFLRFMNKMPLKSDGTPGYNLDDKNWKSFFTRFWETLELEEELRLLSQRLDSVQEQLLNLYEESQSLQDQIAHWRKEQVILHFARKHGIRRLGMTYVPTLAATQHNAKQAIEIVLFLESLQRSQYGQEPWTLDTSKERFKSPPCFKKGAQTVEVIYDGNKDNNFRYTVWKFIYFWD-ESGDWHKVPSVDEKGVYYNIYYVDFETDAARFGGRVRQLISEARDPPVICLKGGNNQLKCLRYRLKAKHRTLFDCISTTWSWFKDEAQRERFLEEVPIPWLSQQSKFYVPP-QPIKILSTDEYVSRTNIFYHASTRLLTVGHPYYTVVVPKVSPNQYRVFRVRLPDPNKFAFNDKQLYDPEERLVWAVRGVEVGRGQPLGVNVTGNPLFNRYDDVENSSRYDNRQNIADPKQTQLFILGCVPATGEHWTQAQRCGDCPPIELINTVIEDGDMSDIGLGAMDHRLLQVSKAEVPMELVNSVSKYPDYIKMLKDPFGDSLFFYARGEQMYARHFFSRAGYMVTPSGSLVSSDSQVFNRAYWLQRAQGMNNGICWNNQMFVTIVDNTRGTVMNIWANNAFKSYLRHVEEFELQFIVQLCKVRLSPENLAFLHKMQPSIIDNWQLSITA-PLEDQYSLATKCPPQE-DDPYKNYKFWDVDLSEKMSDQLDQFPLGRKFLNQSGKRK Seq51 MAE--GT-DCGGFLDTVSSLLDQGN-SLEPFQHHEATETLKSIEHLKRKYVDSPSPRLQAFAVKKRLFDEAASANTARVKH-LLL--FRQAHSVSFSELTRTFQSDKTMSWDWVADIHVSVLESLQSLRSHCVYVQYDASSLLLLLRFKAQKCRDGVKALLLGVQDLKVLLEPPKTRSVAVALFWYKRAMVSGVGPMPEWITQQTNVNHFQLSVMVQWAYDNHLQDESSIAYKYAMLAETDENARAFLASNSQAKYVRDCCNMVRLYLRAEMRQMTMSAWINYRGDWKVVVHFLRHQRVEFIPFMVKLKAFLRGPKKNCMVFYGPPNSGKSYFCMSLIRLLAGRVLSFANSRSHFWLQPLADAKLALVDDATSACWDFIDTYLRNALDGNPISDLKHKAPIEIKCPPLLITTNVDVKSDYLFSRICVFNFLQELPIR-NGTPVYELNDANWKSFFKRFWSTLELEDELRLLSQRLDSIQEELLSLYEESTSLESQLQHWRKEQVLLHFCKKHGIRQLGYTPVPSLLTSQECAKQAIEMVLYIESLLRSPYSDEPWTLDTSRERFESPPTFKKNPAIVEVYYDGDRGNNNEYTLWGIFIIGNAD-GEWVKTESVDYRGIYYYVYYVDFSTDAGRFNRRLRELITEASDPPVICLKGGHNQLKCLRYRLKSKHSSLFDCISTTWSWFADSEQRDKFLSRVPLPWLSTQNKFYLPP-QPVKIPSTDEYVTRTNVFYYASSRLLTVGHPYYTMLVPKVSPNQYRVFRIKLPDPNKFAFGDKQLYDPEERLVWCLRGIEVNRGQPLGVSVTGNPIFNKFDDVENPTKYDYRKSMADPKQVQLLMLGCVPATGEHWAQAKQCTDCPPIELVNTVIEDGDMCEIGFGAMDHKTLQASLSEVPLELAQSISKYPDYLKMQKDQFGDSMFFYARREQMYARHFFSRAGYCITPSGSLVSSDSQVFNRAYWLQKAQGMNNGVCWDNQIFVTVVDNTRGTILSLGKTVHFSSYLRHVEEYELQFVLQLCKVKLTPENLSYLHSMHPTIIDNWQLSVSAQPLEDQYSIATKCPPKE-NDPYKNYKFWEVDLSEKLSDQLDQYPLGRKFLNQSGKRK Seq52 MAARKGTTEDGGWVLNVSDLVDQG-LSLQLFQQQELTECEEQLQQLKRKFVQSPSPQLASIKVKKQLFDSGIQLFKVRDKRAFLYSKFKSSFGISFTDLTRVYNSDKTCSSDWVYHVSDDRREAGKLLQDHCEYFFLH--CTLLLLCLFVPKCRNTLFKLCFHISNVQMLADPPKTRSPAVALYWYKKGFASGTGELPSWIAQQTLITHFDLSEMVQWAYDNDLKDESEIAYKYAALAETDENALAFLKSNNQPKHVKDCATMCRYYKKAEMKRLSMSQWIDERGDWKEVVKFLRHQGIEFILFLADFKRFLRGPKKNCLVFWGPPNTGKSMFCMSLLSFLHGVVISYVNSKSHFWLQPLTEGKMGLLDDATRPCWLYIDTYLRNALDGNTFSDCKHKAPLQLKCPPLLITTNVNVCGDYLRSRCSFFHFPQEFPLDDNGNPGFQLNDQSWASFFKRFWKHLDLED-LRLLSEALDLLQEELLSLYENSQSLADQSRHWRKEQVLLYYARGKGIMRIGMQPVPPQSVSQAKAKQAIEQSLYIDSLLHSKYANEPWTLDTSRERLVAEPTFKKGGKQIDVRYGDSEENIVRYVLWLDIYYQD-EFDTWEKAHGLDHKGLSYQVYYVDFEEEANKYGGRLGRLLQEAYDPPVLVLAGDPNSLKCIRYRLSHKHRGLYLGASTTWKWFLSDQQREDFMDRVTFPWLPAQNKFYLPP-QPSKVLSTDEYVSRTNIFYHASSRLLTVGHPFYEVIVPKVSPNQYRVFRLLLPDPNNFAFGDKSLFDPEERLVWGLRGLEIGRGQPLGISVTGHPTFDRYNDVENPNKNDSRVNMGDPKQTQMFMIGCKPALGEHWSLTRWCGQCPPIELRNTTIEDGDMVDIGFGAMDFKALQHYKSGVPIDIVNSACKYPDYLKMANEPYGDRCFFFVRREQLYARHIMSRSGYFSTPSGSLVSSEGQLFNRPYWIQRSQGKNNGIAWGNQLFLTVVDNTRGTPLTIYVPSSYRTYLRHVEEYEVSIIVQLCKVKLSPENLAIIHTMDPNIIEDWHLNVTP-PLDDTYSLATKCPPKT-NDPFADFKFWEVDLKDKMTEQLDQTPLGRKFLFQTNKRK Seq53 MADKKGT-DLSDWVLDISDLVDQG-LSLQLFRLQEQKESDEQLQQLKRKYIASPSPQLEAVKAKKQLFDSGIDLFRAKNSRVFALGKFKETYGLSFMDLVRVFQSDKTCSLDWVLYMNPERSEAAKLLQDHCAYIFFT--AALMLLCFKYQKSRETVMKLLFDCSAQQILAEPPKTRSTAAALYWYKKSLIAGAGAFPEWIAKQTLINHFDLSAMVQWAYDNDLYEECEIAYQYASLADTEENAAAFLKSNSQAKHVRDCATMCRYYKRAEMQRMTMSEWISRQGDWKDIVKFLRYQDLEFTSFLSAFTKFLKGPKKNCLVFWGPPNTGKSMFCMSLMQFLKGKVLSFVNSKSQFWLQPLADAKVALLDDATAPCWTYFDTFLRNALDGNPICDAKHKAPYQVKCPPLMVTTNVDVIGDYLRSRLSAFCFATEFPFKEDGSPGFCLSDQSWASFFTRFWSRLELEDELRLISKALDSIQEQLLTLYEDSADLTDQIEHWRREQTLYHYARRQGWMRIGMNPVPSLAASQSKAKSAIEQELLLQSMQKSAFAREPWTLDTSRERLLTEPCFKKGGRQVEVRYDNDRDNTSRHVLWDFIYFQ-GDNDEWHKTPGLDARGLYYKTYYVDFEEEAKKYTTRLGRLLLDARDPPLLVLKGDPNSLKCVRYRLKGKYSSLFCWVSTTWSWFKDLEQREVFVKTVKLPWLPAQNKFYLPP-QPTRVLHTDEYVTRTRIFYHASSRLLTVGHPFYEVIVPKVSPNQYRVFRLRLPDPNNFAFGDKSLFNPEERLVWALRGLEIGRGQPLGVGVSGNPTFDRYADVENPNKNDPRVNMADPKQTQMFMVGCKPALGEHWIKARWCQQCPPIELKNSTIEDGDMVDIGFGAMDFRNLQQNRSAVPLDIADTQCKYPDYIKMANEPYGDRCFFFVRREQLYARHLSTRSGYFSTPSGSLVSSEAQLFNRPYWIQRSQGQNNGIAWENQLFITVADNTRGTPLTIYKAGSYKTYLRHVEEFDISVILQLCKVHLTPENLATIHTMDPNIIESWHLNVNP-PLDDTYSLATKCPPKEREDPYANMKFWEVDLRDKLTEQLDQTPLGRKFLFQTNKRR Seq54 MADKKGT-DLSDWVLDISDLVDQG-LSLQLFRLQEQTESDEQLQQLKRKYFHSPSPRLQAVKAKKQLLDSGIDLFRAKNRRLFSLGKFKETYGLSFMDLVRVFQSDKTCSLDWVLYLHEERSEAAKLLQDHCSYVFCN--TTLMLLSFKSQKSRETVLKLLFDCKGEQFLAEPPKTRSTAAALYWYKKSVVSGTGILPEWIARQTLINHFDLSAMVQWAYDNDVYEECEIAYRYACLGETEENAAAFLKSNNQAKHVRDCATMCRYYKRAEMQRMSISEWIHRQGDWKDVVRFLRYQGLEFMEFLGAFTKFLKGPKRNCLVFWGPPNTGKSMFCMSLLRFLRGKVISYVNSKSQFWLQPLADAKVALLDDATVPCWNYFDVYLRNALDGNPVCDAKHKAPYQIKCPPLMVTTNVDVLADYLRSRLSAFCFATEFPFKEDGSPGFLLNDQSWASFFTRFWLRLELEDELRVISKALESVQEQLLTLYEDSTDLTDQIKHWRREQALYYCARRQGITRVGMNVVPSLAASQQRAKSAIEQELLLQSLLDSDFADEPWSLDTSRERLLADPCFKKGGQQVELRYDRDRDNTSRHVLWKDIYFQ-GEEDTWRKTHGVDEKGLFYKTYYVEFEKEAAKFGTRLGRLLHDARDPPVLVLRGDANSLKCIRYRLKGKYSDLFCRVSTTWTWFRDLSQRDTFERTVRLPWLPAQNKFYLPP-QPTRVLHTDEYVTRTRIFYHASSRLLTVGHPFFEIIVPKVSPNQYRVFRLRLPDPNNFAFGDKSLFNPEERLVWALRGLEIGRGQPLGVGVSGNPTFDRYTDVENPNKNDPRVNMADPKQTQMFMVGCKPALGEHWVKARWCQQCPPIELTNTPIEDGDMVDIGFGAMDFRTLQQNRSAVPLDIIDTQCKYPDYIKMANEPYGDRCFFFVRREQLYARHLLTRSGYFSSPSGSLVSSEAQLFNRPYWIQRSQGQNNGIAWENQLFITVADNTRGTPMTIYKAGSYKTYLRHVEEFDISVILQLCKVHLTPENLATIHTMDPNIIESWHLNVNP-PLDDTYSLATKCPPKEKEDPYAHLKFWEVDLRDKLTEQLDQTPLGRKFLFQTNKRR Seq55 MADKKGT-DLSDWVLDISDLVDQG-LSLQLFRLQEQTESDEQLQQLKRKYLASPSPRLQSVKAKKKLWDSGIELLRSKNRRLFSLGKFKETYGLSFLDLVRVFQSDKTCSMDWVLYLNEERAEAAKLLQDHCSYVFLT--VSLMLLSFKSQKSRETVSKLLFDCRGEQFLAEPPKTRSTAAALYWYKKSTVSGAGMLPDWIAKQTLINHFDLSAMVQWAYDNDLYEECEIAYQYACCAETDENAAAFLKSNSQAKHVRDCATMCRYYKRAEMQRMSISEWIHRQGDWKEVVKFLRHQGLEFIEFLSAFTKFLKGPKKNCIVFWGPPNTGKSMFCMSLLNFLKGKVISYANSKSHFWLQPLADAKLALLDDATAPCWNYIDTFMRNALDGNPVCDAKHKAPFQIKCPPLLVTTNVDVLGDYLRSRLSAFCFAAEFPFNEDGSPGFHLNDQSWASFFERFWPRLELEDELRVISLALESVQEQLLTLYEDSPDLRDQIKHWRREQVLYYCARRRGITRVGMAVVPPLAAAQQRAKAAIEQELLLQSLLESDFAGEPWTLDTSRERLLTEPCFKKDGEQIEVRYDNDRENMSSHVLWTAIYYQ-SDDDKWRKTQGVDARGLFYKTYYVDFEQEAKKYG--AGPEGSLQQDPPVLVLAGDANSLKCVRFRLKGKHSSLFCRVSTTWTWFRDNNQREIFEKTVRLPWLPAQNKFYLPP-QPTRVLHTDEYVTRTRIFYHASSRLLTVGHPFFEIIVPKVSPNQYRVFRLRLPDPNNFAFGDKSLFNPEERLVWALRGLEIGRGQPLGVGVSGNPTFDRYSDVENANKNDPRVNMADPKQTQMFMVGCKPALGEHWVKARWCQQCPPIELKNTPIEDGDMVDIGFGAMDFKNLQQNRSAVPLDIIDTHCKYPDYIKMANDPYGDTCFFFVRREQLYARHLLARSGYFSSPSGSLVSSEAQLFNRPYWIQRSQGQNNGIAWENQLFLTVADNTRGTPLTIYKAGSYKTYLRHVEEFDISVILQLCKVQLTPENLATIHTMNPDIIESWHLNVNP-PLDDTYSLATKCPPKEREDPYAHLKFWEVDLRDKLTEQLDQTPLGRKFLFQTNKRR Seq56 MADKKGT-DLSDWVLDISDLVDQG-LSLQLFRLQEQTESDDQLQQLKRKYIASPSPRLQAVKAKKQLVDSGVDLFKSKNRRLFALGKFKENFGISYMDLVRVFQSHKTCSMDWVLYLHDERSEAAKLLQDHCAYIFFT--VTLMLLAFTSQKSRETVFKLLFDCKEEQFLAEPPKTRSTAAALYWYKKSLLAGAGIFPEWIAKQTLINHFDLSVMIQWAYDNNITEESEIAYQYAMFADTDENAAAFLNSNNQAKHVRDCATMCRYYRRAEMQRMTMSEWIHKQGDWKEVVKFLRYQGLEFVEFLSAFTKFLKGPKRNCLVFWGPPNTGKSLFCMTLLKFLRGKVISYVNSRSQFWLQPLADAKVALLDDATVPCWNYFDTFLRNALDGNPVCDCKHKAPFQIKCPPLLVTTNLNVKGDYLHSRLSAFCFANEFPFKEDGSPGFNLNDQSWASFFKRFWLRLELEDELRVVSKALECVQEQLLHLYEDSAELRDQIMHWRREQALYYCARKQGITRIGMNPVPTLAAAQQKAKSAIEQELLLQSLLDSKYADEPWTLDTSRERLLVEPCFKKGGQQVEVRFDCDRENVSRYVLWTDIYHQ-TEQDQWRKTKGADNRGLFYKVYYVDFEDEAKKFGDRLGRLLLDARDPPVLVLKGDPNSLKCTRYRLKGKYSHLFCRASTTWQWFTDTAQRDLFEKAVKLPWLPAQNKFYLPP-QPSRVLHTDEYVTRTRIFYHASSRLLTVGHPFFEIIVPKVSPNQYRVFRLRLPDPNNFAFGDKSLFNPEERLVWALRGLEIGRGQPLGVGVSGNPTFDKYNDVENPNKVDPRMNMADPKQTQMFMVGCKPALGEHWVKAKWCQQCPPIELKNSPIEDGDMVDIGFGAMDFRNLQQNRSAVPLDIVDTQCKYPDYIKMANEPYGDRCFFFVRREQLYARHLLTRSGYFSSPSGSLVSSEAQLFNRPYWIQRSQGQNNGIAWENQLFVTVADNTRGTPLTIYTANSYKTYLRHVEEFEISVILQLCKVQLTPENLATIHTMDPAIIESWHLNVNP-PLDDTYSLATKCPPKEKEDPFKGLKFWEVDLRDKLTEQLDQTPLGRKFLFQTNKRR Seq57 MVD-KGT-EESDWVLSLADFVDEG-LSLELFRQQEADREEEHLLQLKRKYIRSPSPRLESIKAKKQLKDSGLGLFKSKNQRAVLFAKFKECFGLSFTDLTRNFKSDKTCTADWVIYISEARAEAGKLLQDHCEYVFVS--CALCLLSFKAQKNRETVLKLLFGVRDCQLMAEPPRTRSAAAALYWYKRGMSNCAGQLPEWIAKQTLLGHFDLSQMVQWAYDNDLVEESEIAYQYALLGEEDENAAAFLNSNNQTKHVKDCAVMCRYYKKAERESMSMSEWIHRSELWREIVKFLRHQTVSFVSFIAAFKRFLRGPKSNCIVIWGPPNTGKSLFCMTLLKFLKGRVISFVNSKSQFWLQPLADAKIGLLDDATRPCWDYFDAYMRNALDGNPICDCKHKAPSQIKCPPLLITTNLNVMGDYLRSRLSSFCFPTEFPFHDDGSPGFILNDESWASFFARFWTHLELEDELRLLRQALDSVQEELLNLYEDSSDLTDQVTHWRREQVILHYARKNAITRVGMTFVPPQNVSQQKAKEAIEQELYLQSLLGSDYSNERWTLDTSREVLLAPPCFKKGGRPVDVRFDGDPENVTQYTLWGHIYYQNAE-DVWQKTKGVDDTGLYYRVYYVVFKDEAKRYGTRLERLVLEARDPPVVVFKGEPNSLKCLRFRLRKGYFHLFQKVSTTWSWFDSSEQRESFLRQAPIPWLPAQNRFYLPP-QPSKVLNTDDYVTRTSIFYHAGSRLLTVGHPLYHVIVPKVSANQYRVFRIRLPDPNNFAFGDKAIFDPEERLVWAVRGLEIGRGQPLGVCVSGNPLFDKNNDVENPTKYDNRVNVADPKQTQLFMIGCKPAIGEHWGQARRCGHCPPIELKNTTIEDGDMIDIGLGAMDFRVLQQNKAGVPLDISNSECKYPDYIKMANDPYGDNLFFYVRREQLYARHMFTRSGYFSTPSGSLVSSEAQLFNRPYWIQRSQGQNNGIAWQNQLFITVVDNTRGTSLNIFNPADYRCYMRHVEEYEISLILQLCKVKLTPENLAFIHTMNPDIIEDWHLNVNP-PIDDVYSLATKCPPKTREDPYGLYRFWEVDLKDKMTEQLDQTPLGRKFLFQTGKRK Seq58 ?ETKIKTLG-CSYIV-TEDFVDAGE-HLSLLQTQMRASDAQQIASLKRKYVKSPSPKLEQCKARKQLFDSGISDERSRVLYMYRR--FNDMYGVKYTDLIRAFKSDKTMSANWVYVPLLEDGKAAATLQQQCSWYFME--IQLFNVEFNAQKCRATVIKLFFNFSSKRLMADPPKLRSAPACLFWYQKVLKKVGGELPDYIHTQCALGSFELTKMVQWALDNNLTEESSIALKYAMLAEEDENAQAFLKSNNQPKLVKDCCTMVRMFQTALMRDMSISQYVDHR--WRSIVHFLRYQGVQFLSFMIDLKNLLHHPKKCTIVVCGPPNTGKSYFVLSFVKFMNGCVISFVNYGSHFWLTPLRTARIGMIDDATNSFWKYCDTYMRTLLDGNDVSDCKHRNPIQLRCPPLVITTNEDIKNDYLQTRLRFLYFNKPFPLHDRGDPVYKIESLQWASFFRKFWRHLDLLEELRLLQHRLDYTQEKILTLYEDSTDINDHISLWRHENVLFHTMRKRGIVRVMGRSIPSLQASEKSAKHAIMMQLQLEDLAKSPYGLEPWSLETTLERYLAPPTFKKGGVHVNVTFDNEESNSAEYVMWTYIYVTD-ENGDWHKTQGVDRTGIYYHIYYVYFEDEAAQHHRSSAERPGPTPQFYLIGCRGPVNTLRCYRFKLKKRPNPDITYISTTFNWFTSKEHRDEFYVAARPPWLPAQNRFYLPPA-PVRILSTEDYVHRTDVYVHASTRLLTVGHPYYTVKVPKVSSSQYRAFRCRFPDPNNFAFGDTSIFNAEERLCWALRGIEVGRGQPLGIGATGHPYTNRFQDVENPFNPDDRLNVADPKQTQLIIVGCRPAQGEHWDAAPWCNRCPPLELRSTVIEDSDMVDIGLGNLNFESLQDNKADAPLDIVRSICKYPDFLKMSEDPYGDEMFFFTRREALYARHMFQRSGYYISPSGSLVTSEQQLFNRPYWLRSAQGHNNGILWHNEAFVTVVDTTRGTNFNVFKNGKFSEFLRHCEEYQLSFILQLCKVSLTPENLAYIHTMDQSIIEAWHLSVNA-PLEDKYSLATKCTTSES-DPYSKYRFWDIDLTDRITEQLDQTPLGRKFRFQGGLKR Seq59 MAMKTKREARCSYIL-VEDLVDQGN-SLSLFHAQTVEEYEGEIQSLKRKFILSPSPRLAGVKARKSLFDSGIDLFQSRQRCTHMYSKFKAVYGVSFTDITRPFKSDKTTSQHWVYYLAFDSEISAMLLRQQCQFLYID--IILFFLEYNVQKSRTTVYNWFFHYNENRMLANPPRTRNMPAALFFYHRFMGTGGGAMPEIIVNQCVVSNFELSRMVQWALDNDLQDEHMLALEYALLAESDGNARAFLKQNNQPMIVKNCSIMVRHYKTALVAKMSISQYVNKRNSWRGIVHFLRYQGQEFLPFMCKMHNFLHHPKKSTLVLCGPSDTGKSYFANGLNKFLDGHVLSFVSNGSHFWLSPLRGARCCLIDDATLTFWRYADQNMRALLDGYEISDAKHRNPMQTRAPPLIITTNEDIMRLYLQTRTMYVYFNKPFPLKGNGQPLYYIDGYTWNSFFRKFWRHLNL-EDIRLLLERLDYIQEQILTLYEDSVDLEDHIRLWRRENAIWYVLRQEGHARVGGRAVPAMTVSEANAKFAIEMQIKLESLKASPYAAEGWSLETTKERYLAEPTFKKLGQPVTLMFDNDPENLTEVVLWKWVYYITP-TDEWYKARGIDDTGIYYKMYYVRFDMEAENFKKTAGVAPAEGH-Y-LVGAKGPVNSLRCLRYKWKNKYSGDIMYLGTTFTWFSNETKREKFLKSVKIPWLPGPNRFYLPP-QPIRTLNTEEYVRRTSTFLHAATRLLTVGHPFYKEVVPKVSSNQFRAFRVRFPNPNTFAFCDKSLFNPDERLVWGIRGIEVSRGQPLGIGVTGNPFFNKFDDAENPYNGDSRLSIADPKQTQLLIVGAKPAKGEYWDVAATCDKCPALELKSSYIEDADMSDIGLGNLNFSTLQRNKSDAPLDIVDSICKYPDYLQMIEELYGDHMFFYVRREALYARHIMQHAGYFMTPSGSLVATEQQLFNRPFWLQRSQGHNNGILWHNEAFVTLVDTTRGTNFTIYNNSKFFEFLRHTEEFQLAFILQLCKVDLTPENLAYIHTMDPSIIEDWHLAVTS-PLEDHYSIATKCADDTS-DPYKDLKFWEVDLRDRMTEQLDQTPLGRKFLFQTGKRR Seq60 MEDLEEGGCSGWF-DSIADMFDQGN-SLELFHTQEKEETRTQIQALKRKYI-PSSPRLRAIPSRRLFEDSG-NLLQSHNRVARLLAVFKEAYGVSYKELTREYKSDKTCNPDWVYSLSEPILNAARTLQGICEYVFMQATVALLTVRFKCSKSRETVRKQMFHSDPLLCLCDPPKVQSVPAALYWYKSSMYSGTGEAPEWIKRQTMITCFDLSEMVQWAYDNNYEDESQIAFEYARTATESPNANAWLASNAQAKHVRDCATMVRHYKRAEMKAMSMSQWVWKCGTWTPISLYLASEGVEVIRFLSAMKSWLRGPKKNCLVFYGPPNTGKSLFTMSLIKFLRGRVISFANSKSHFWMQPLAEAKVVLLDDATRATWDYVDTYMRNAMDGNPLSDCKYRTPVQVKCPPMLVTTNEDVHLNYLHSRIQVFHLKEPMPIDTAGNPEYSFSNRHWKAFFEKLQKPLDLEGDFSCIHSRLAAVQEELMCMYEGEETLEAQLKHWRKEQVLLHAARQHGHNKIGLQAVPPLSVTQQNAKNAIEMHLLLQSLAETPYAREAWTLQTSREMYMAGPTFKKDGTIVEVIFDGDKTNMMTYTKWGKIYFADPN-GNWSRTTSTDINGIYFKEYYVRFKEEAKRYSRPSRGHCRDPRTACLLIIKGSSNQVKCLRFRLKSWHHSLFSYISTTWQWCEDSAQMDRFLCTVKIPWLPNNQKLYLPPA-PVRILSTDEFTTRTDIYYYASSRLLTVGNPYYTVTVPKVSPNQYRVFRCKLPDPNRFAFGEKSVYDPEQRLAWCIRGVEIARGQPLGIGITGHPLYNRLEDVENPGKYDNRQNVGDPKQTQMFIVGCVPAQGEHWSRALTCGDCPPIQRMSGMIEDGDMGDIGYGNLDFRVLQENKSEVPLEVVDSICKYPDYLGMSKETHGNSCFFYARQARLYSRHFFNRAGYSGTPSGSLVSSDAVLFNRPYWLERAQGQNNGILWNNDLFVTVLDNTRGTHFSIYTASNYKQYTRHVEEFELEFIFQLVKINLSTEVLAYLHGMDPSILDNWNLTL-G-PLADKYSLATKCEVTKP-DPYKGRIFWNIDLTERLTADLDQFSLGRKFLYQHAKRR Seq61 MASQRGTLGGIDFIDSVSNLFDPGN-PLQLLQQQEAAEDERLVALIKRKHLTTPSPKLDAM-AKKKLFDSGVGILRAANRRVCMLARFKEVYGVSVTDLTRQFKSDKTCCKNWVFGLCEPYYITLTVLPDHCCYSHMQGGIALMLCDFKAMKNRDTVIKLIVPVSDDLIMVQPPNVRSPAAALYWVQRAQSNASGEYPSWITKQTMLSHFDFSNMVQWAYDQGYTEESKIAYHYAQLAEEDKNAMAWLSSAAQAQHVKHCAQMVRYYMQAQTAEMTMAQYIHERGDWKHIIAFLRHQDIEIIPWLRTTRDWLKGPKRNCVCYHGPPDTGKSMFGMSLMRFMRGAIISYVNSRSHFWLQPLVSAKVAMLDDATDACWQYIDTNLRNLLDGNPLSDLKHRAPIQATCPPLLITSNIDITQDYLRSRVKCFAFHCPLPVGEDGMPTLVLTEASWKCFFRKFASTLEV-EEFRCLRDRLDVLQDQILGHYEQSTCLQDHVQYWRRESSLLFYARGKGVKTLGYLPVPVQQVSQDRARQAIQLHLATQSLAKSKYKDEPWTLDVSRENYMSEPTFKKGGTQVEVIYDGDEDNVMLYTSWEHIYIQD-DDGSWYKRKGVCVEGLYYKTFYVNFEEELGKYGAGFRPQPPTAVVAPVIIIAGPPNALKCQRYRLQNQHYRHFAQVTTTYHWFVDTAQRETFLNTGALSWIPSPQAVYVAPA-PVTIPSTEDFITRTPYFYHANSRLLTVGNPFYKILVPKVSGNQYRVFRIRFPDPNKFALPDPNVFNPDERLVWGLRGIEVGRGGPLGMEVTGNLGFGRNADVENPNQATKRFNVGEPKQNQLLIVGCSPAWGEFWDSTPACGDCPALELKSTRLQDGTMTDIGFGHMNFKSLQDDKSGVPLEIVNSVCVYPDFYKMSKDPYGNSCFFSVRKEQMYIRHYFSRVGYMGTPSGSIVSTEGQVLNRPYWLLKAQGRNNGMLWGNQCFVTVVDNTRSLNFLIFQADEFANYLRHTEEYEIACIVQLCKVRLDPETLSILNTMDPEILEEWQIGVNP-PVNDRYSLATHCKAKEKEDPYAGLAFWNLDFTESLSPDLDQFPLGRRFLTQAGKRR Seq62 MTDKSG---E-YFLLNGVDFIDG-NTLAEYNRKEADRHKRDLEQLKRRHVR-RPVGGSPSSSSKRRCL-GL-ELLRSANRQATFLGKFKDTYGISFTELTRPFKSDKTCCEDWVYGISGPLYEGAKLLEGHVIYMQLTGLLLLMLLRLKHAKSRATLRRLLFNISEMQLLAEPPKTRSVPVALFWYKGTLSSLSGTCPEWIHRQTLINHFDLSSMIQWAYDYDYDDECTIAYQYARLAETDANANAWLNSPAQARYVKDTATMVKYYKRAQMREMTMGEWIKHRGDWKKIVQFIRFQGIEFPLFFGALKKFLHGPKHNCIVIWGPPDTGKSMFCMNLIKLLGGKIISFANSKSQFWLQPLADAKVGLLDDATGVCWDYIDQYLRNALDGNPISDLKHRAPTQMKCPPLLITTNLDITANYLVSRVACFKFSEPFPFTDRDTPTYPLTECNWKALLERLWKQLDFQEEFKCLLDRLNAVQSKILDLYEAENTLSSQQEHWRQEQILYYACRSKGILRLGYQPIPTTSVSQTKAKAAISMCLFLAKLKDSAFASEAWTFETSQERLAAPPCFKKGGYTVEVTFDEEIENKMLYTAWKYIYYLDMC-DNWCKSEGLDINGLYYKIYYVNFADEAQLYTQSSVVVPSISGAYPVTVFRGNVNQLKCWRGRIRDKYHMYFKDISTTWKWFHSAVQRERFRCFVPVPWLPNNDKVYLPPT-PARILNTEDYVTRTSLYYHANSRLLTIGHPYFKLKVPKVSGNQYRVFRIQLPDPNRFALTDKSIFDPEERLVWGCRGLEVSRGLPLGVGLSGHPYFNRKADNENPDPIDTRQNMADVKQSQVIMVGCVPQMGEHWQAALPCGECPPLELVSTIIEDGDMADLGFGAMDFKNLQHTKADAPLDLVDTISKYPDYIKMNQDIFGDMLFFYARREQCFTRHFMSRTGYYGTPSGSLVSSDAQLFNRPYWLQRAQGHNNGIAWQNQLFVTILDNTRGTNMTVYDDNDYAQYLRHAEEFELSFVFQLCKVQLTTEALAHIHTMNPKILEDWHIGLRPPPVEDQYSLATRCVPAENDDPYKTKKFWVVDLSTRFSTELDQFPLGRRFLFQSGKRK Seq63 MEGDIDSSRGGGFILDLINDSLQGN-SQALLHQQIMREDNRQVQDLKRKYVSPKSPRLRAISAKRRLFDSGLELMRASNQRATQLALFKKGYGISLTELTRVFKSNKTCNPDWVFGVHHNTYSDLVRLEKHCEYVQCSGYIVLMLLRFTAHKNRNTLIKLMLSVSDIQILADPPKIRSVPAALYWYRNSMSTAVGPLPDWVARQTLVQHFVLSTMVQWAYDNDHTEESDIAYHYALLADEDTNAAAWLGTNSQAKHVRDCAVMVKHYRRAIMSAMSMSEWI-NRGDWKNIGNFLRYQGIEVITFIGALRDMLKGPKRTCMCIVGPPDTGKSAFCLSLLDFFGGRVLSFTNYKSQFWLQPLADTRIALIDDATKSTWDYIDEYMRNALDGNAICDLKHKNPLQIRCPPLLITSNINIKHNYLYSRIHIVEFKHAFPFNEEGEPVYQLTKGNWKSFFKRLWLRLDLEDEFRCLKKRLDAIQDELLTIYEGSELISVQVQHWRKENVLMHYAKKSGVTRLGLQPVPSLRVSAEKAKQAIEMQLTLQTLQDSPYATEQWTLDTSYERWTTEPCFKKGPTTVEVYFDGDRANAMHYTMWSKVYYTDVN-EKWQKTKSVDNDGLWFKRYYVRFSDEAAKYGPQPFLREAGDSSPSVIVLAGPCNTLKCFRYRAKNLHRGLFERISTTWYWFSGNSQRAEFLNRVRLPWVSNSQKLFLPP-NPVKVLHTDTYIKRTSVFCHAASRLLTVGNPFFTVKIPKVSSNQFRVFRVTLPDPNQFAFAERPAHDPEERLVWGLRGMDVGRGQPLGIGVTGHPLFNRYTDNENPGKYDSRQNVADAKQTQVLIVGCSPALGEHWSAARPCGECPPLELKNTYIQDGDMMEIGYGAMDHRGLSQNKSDAPLDTVFSITKYPDYLKMSKEASGDSMFFFARREQEYIRHFFSREGYYGAPSGSLTSTDSQIFNRPYWLQRSQGLNNGICWLNQLFVTVGDTTRGTNMTIYDSSKFTTYLRHTEEFELSFIFQLCIVPLTPDVLAHLHSLNSHILDKWNIGLQA-PLEDRYSLATRCPPS-PEDPYAGYSFWLVDLSEKFSQDLDQFPLGRKFLAQSSKRK Seq64 MDAEEAGEGSSWFLQE--DLIDQGN-SLLLFQQQEAQADEQHLSVFKRKYC-SPSPRLGAIQVKRRLFDSGLDILRSANRKATMLGLFKDAFGVPYGELTRQFRSDKTGCFDWVYAVREPFFESGKQLRQHCRYTHVTGTVLLMLVSFNNQKCRDTVNKLIFNVHELLLMLEPPKIRSVAAAMYWYKQSLTNATGELPEWIKKLILINHFDFSQFVQWAYDNEYQEEHEIAYNYASIADEDSNAAAWLGLTGQAKVVKDVATMVRYYRRAEMNRMSMSNWIHNRGQWQPIVNFLKYQGVAMVTFINALKSFLKGPKKNCLVIWGPPNTGKSWFCMSLMHFLGGRVLSHVNSNSHFWLQPLGDAKVALLDDATTVVWDYFDRYMRNACDGNPISDMKHKAPVQIKCPPLLITSNIDVKADYLHSRLVTFHFPNLFPFEDDGSPVYQFNDENWNSLFTRLWRALDLEDEFRCLRQRLDAVQEKLMNLLEGSSDLSSQICYWRKENVLLYYAREKGLSRLGLQMVPHKAVSQSQAKQAIHMELILLSLQGSSYEQEPWTLDCSWERWLQAPCLKKDPVIVEVVYDGNSENANWYTLWGLIYYQ-TFEGDWMCTRGCDHSGLYYKRYYVHFIDDAARYGNDPAPVPLEAAFAPIVIFQGGTNQCKCYRWRLKKRHRSLFVAITTTYFWFSSDLQRRLLLATVPPPWSSNSQKVYLPPT-TLKAVSTDTYVTRLGIYYHGHSRLLTVGHPFYTMRVPKVSANQFRVFRVILPNPNKFALPDSNVFDPDERLVWAVKAMEICRGQPIGPQVTGHPLFNRFEDVENPAVYDKRQNMADYKQIQMVVLGCRPALGEHWGKTRSIGDCPAIELFHTTIEDGDMVDIGLGNLDFAQLQADKSGAPLDIVQSICKYPDTLKMAQEITGDTMFFSARREQSYLRHMMTRAGYCGVVSGSLFSSDAQIFNRPFWLNQAQGLNNGIAWNNQLFVTAVDNTRATNFTIYDAGSFNAYLRHVESYELQFVFELCKVKLTPENLTILHQQDPGILKGWELGVTP-PLEDTYSVATKCPEEVQEDPWGRFAFWRVDLSERFSLDLDQFPLGRRFLALSAKQR Seq65 MDEKPGS-GGTSFILSDEDLVDRGN-HLELFQTQEKEAGEKQISILKRKFCLSPPGLAGIRVVRRRLFTGGPDVVQDFNMAATIQKLFKTLYVATFGEITRIFQSNKTNNQQWVYGVPELLYTASFLLNNHCNYLLANGSLSLYLAVFNVGKSRDTVCKLVLNTTNQNLLLQPPKVRGLCSALFWYKLSLSPATGSTPDWIQQQTNVANFDFGTMVQWAYDHHLTEECKIAYQYAKCAGSDVNAKAFLASTNQARLVKDCCTMVRHYLRAEEQALSISAYIKKRGSWLSIMNLLKFHGIEPIHFVNALNPWLKGPKHNCIAIVGPPNSGKSLLCNSLITFLGGKVLTFANHSSHFWLAPLSDCRVALIDDATHACWRYFDTYLRNVLDGYPVCDRKHKSAVQMKAPPLLLTSNIDVHADYLQSRVKSFYFTEPCCASDNGEPLFVITDADWRNFFERLWERLDLEDELTCASEHLLAAQETQMTLIEDSTSLRDHETYWRREHGLLYAARKKGLTRLGCVPVPPCSVSAEKAKQAICMQLITRELINSQWANEPWSLDLSWDRYQANPCLKKGARVVEVEYDGNSTNKTWYTTWTVVLTRKTEEEGWEAATGADEKGLYYRVYFETFDIDASRWTTPRFSLLTKTGGQPCLILSGNGNQTKCFRFRCKKHFRRHYEHVTTTW-WFKNSCQRQDFLKTVPLPW-QPGQRLYLPPT-PVKVLCSEQYIRRRDVFYHGETRMLSVGHPFFGKSIPKVSPNQYRVFRVALPDPNQFALPDRALYDPSERMVWAVVGLQVSRGQPLGGSVAGHSYFNAFLDAENVSKKDDRKQAGDVKQQQVLLLGCTPAVGEYWTEARPCGSCPPIELKNKPIEDGDMMDIGFGAANFKELNATKSDLPLDIANDICLYPDYLKMTEEAAGNSMFFFARKEQAYVRHIWSRGGFFPVPSGSLVSTDGQLFNRPYWLFRAQGMNNGICWNNQLFVTVGDNTRGTTLTIYDTSKFNVYQRHVEEYKLAFVFQLCSVELTADTISHLQGLMPSILETWDINLQP-PLEDTYSPATKCSPSKPEDPYSGLKFWEVNLKEKLSLDLDQFPLGRRFLAQQGKKR Seq66 MAETAGS-GGGAYICSDEDLVDPGN-HLELFQTQEKEAGERQISLLKRKFCLSPPGLAGIRVVRRRLFDAGGRPASDGNMAAVMHKLFKTLYIAGFGEITRVFQSDKTNNNQWVHGASEVLYAASFILSKHCSYLQASGSMSLFLAVFNVGKSRETVRKLILNTPCSRLLLQPPKIRGLCPALFWFKLGLSPATGTTPDWIKQQTNVAYFDFGTMVQWAYDHRLTEECKIAYQYAKCAGTDLNAKAFLASTNQARLVKDCCTMVKHYLRAEEQSLTISAFIKRRGSWLSIMNLLKFQGIEPINFVNALKPWLKGPKHNCIAIVGPPNSGKSLLCNTLMSFLGGKVLTFANHSSHFWLAPLTDCRVALIDDATHACWRYFDTYLRNVLDGYPVCDRKHKSAVQLKAPPLLLTSNIDVHADYLQSRVKTFYFKEPCPASDTGEPLFFITDADWKNFFERLWERLDLEDEFTCASDHLLAAQETQMQCIEDSRLLQDHACYWRREKLLLYAARTKGLKTIGCVPVPPCSVTAEQAKQAICMQLIVEELLHSPWAKEPWSLDLSWERYQAAPCLKKGARVVEVEYDGNSSNKTWYTAWSTVYVRGTEEEGWETAVCADGQGIYY-VYFETFETDARRWEPERFSILSKPGGQPCLILSGNGNQAKCYRFRCKRYFREHYQHITTTW-WFKDSSQRGVFLKRVPLPW-QPSQRLYLPPT-PVKVLCSEQYIRRKDVFYHGETRMLTVGHPYYGKTIPKVSPNQYRVFRILLPDPNQFALPDKAMYDPSERLVWAVVGVQVSRGQPLGGSVSGHSYQNTLIDAENVSKKDDRKQGGDVKQQQILLLGCTPAIGEYWTTARPCGSCPPIELKNKPIEDGDMMDIGFGAANFKELNATKSDLPLDIAKDICLYPDYLKMTEEAAGNSMFFFARKEQVYVRHIWSRGGLFGVPSGSLVSTDGQLFNRPYWLFRAQGMNNGICWLNQLFVTVGDNTRGTTLTIYDTSKFNVFQRHVEEYKLAFVFQLCSVTLSPETVSHLQGLMPSILEHWDINMQP-PLEDTYSPATKCTPMGPEDPYAGLKFWEVNLKERLSLDLDQFPLGRRFLAQQGRKR Seq67 MDKENAG-GGDSFILD-EDLLDPGN-HLELFQTQEKEAGERQISILKRKLCLSPSWACCHKVVRRRLFDPGGASSAEPNMAACIQKLFKTLYIASHGEITRVFQSNKTVNHQWVYGVSEVLYSASFLFGKQCNCLQTSGSISVYRCMFNVAKSRDTVQKLMLNVTAGNLLLQPPKIRGLGPALFWFKLTLSPATGTTPEWIQQATNVASFDLGTMVQWAYDHGFTEESKIAYEYALCAGSDCNAKAFLASTSQARLVKDCCTMVRHYLRAEVQALTMSGYIKRRGSWLSIMNLLKYHGIEHIQFVNALKPWLKGPKYNCITIVGPPNSGKSLLCNSLIAFLGGKVLTFANHHSHFWLAPLADCRVALIDDATTACWRYFDTHLRNVLDGYPFGDRKHNTAVQMKAPPLLVTSNIDVHAEYSHSRVKPFYFKEPCPASDNGEPMFSITDADWKHFFERLWGRLDLEDEVTCAKEQLLAAQETQMTLIEDSTDLKDHIDSWRREHGLLYAARHKGLIWLGLNPVPPCSVKCLEARQAIEMQLLGNSLKESPWCNEPWSLDLSWGRYQAPPTLKKGARLVEVEYDGSSTNKTWYTAWNSLYLRKPDEEGWETATGADADGLFYRVYYELFERDAARYKEPRFSLFGSSGGLPCLLISGTGNQVKCYSFRVKRWHRDKYHHCTTTW-WFKDQSQRSMFLQQVPLPW-QPGQALYLPPT-PVKVLCSEQYINVRDIFYHGETRMLTSG-SILHTTVPKVSPNQYRVFRVALPDPNQFALPDKALHNPSERLVWAVVGVQVSRGQPLGGEVRGHSYFNTFLDAENVSKKDDRKQAGDTKQQQVLMLGCTPAIGEYWTKARPCGSCPPIELKLSFIEDGDMMDIGFGAANFKELNATKSDLPLDIANSICLYPDYLKMTEEAAGNSMFFFARKEQVYVRHIWTPWGFFASPSGSLVSTDGQLFNRPYWILRAQGMNNGVCWNNTLFVTVGDNTRGSTLTIYDTSKFNVYQRHVEEFKLAFILELCSVELTPETVSSLQGSMPSILENWEINLQP-PLEDIYSPATKCSPSKPEDPYSAHKFWEVNLKEKLSLDLDQFPLGRLVLQFDCICF Seq68 MSDEPGSGKGSEFILDLEDFVDQGN-HRELFQTQEKEAGEKAIQKLKRKLALSPPGLAAISLVKRRLFIGPKAILKSKNSAACKLKLFKTIFACSFCDLTRVFQSNKTTNLQWVYGPSETMYEASFLLKKACSYVLAVGTIALILACFNNAKSRDTVQKLFLNVHHEQLLMQPPKIRGVCAALFWFRLTFSPATGTLPQWIRTQTIAAEFDFGTMVQWAYDNSYCEESKIAYEYAMLANCDTNAKAFLASNNQAKMVKDCATMVRHYKRAEVQAMTMSEYIKRRGSWLPIMNLFKFQGIEPIRFVNSMRQWLRGPKKNCICIVGPPNSGKSLLCNSLISFLGGRVLTFAMHKSHFWLAPLSEARVALIDDATYACWKYFDTYLRNALDGYPICDRKHKTAVQMKAPPLLVTSNIDVHADYLHSRIVSFYFKETCT-TANGEPMFSITNADWKIFFERLWGRLELEEEFACASERLRAAQEQQMLLIEDSTKLCDHILFWRTENGLLYAARQKGITTLNGFPVPALAVSSSKAKQAIEMQLLLTELLNTTWGRDAWTLDTSYERYLLEPTLKKGPRVVEVMYDNDPANRMCYTAWSLLYMRTPA--GWLFATGADECGLYYRHYYDFFGRDAARYDPNKFSLFKTSGGQQCLLLSGSGNQAKCFRFRMKKGHRHKYVHCTTTW-WFDSPTQRELFLKTVPIPW-QAGQKLYLPPT-PVKTLCSETYVSRRDIYYHAETRLLTVGHPFYK-TVPKVSPNQYRAFMIQLPDPNQFALPDRTLYDPGEKLVWGLIGLQVSRGQPLGGAISGHTTFNALLDAENVSRRDDRKPAGDAKQQQVLLVGCTPAVGEYWAKARPCGSCPPLELKHKPIEDGDMMDIGFGAANFKELNSSRSDLPLDIVNEICLYPDYLRMTEETAGNSMFFFARKEQVYVRHVWARGGFIGAPSGSLLSTDGLIFNRPYWLYRAQGMNNGICWNNTVFVTVGDNTRGTNLTIYETGKINVYHRHVEEYKLAFIFQLCSVQLTPETVSSLQGLMPSILENWEINVQP-PLEDTYSPATKCPAS-K-DPYEGLRFWKIDLKEKFSLDIDQFPLGRRFLAQQGKRR Seq69 MSDEPGSGKGSEFILDLEDFVDQGN-HRELFQIQEKEAGDKAIQKLKRKLALSPPGLAAITLVKRRLFIGPKAILKSKNSAACKLKLFKTIFACSYSDLTRVFQSNKTTNLQWVYGPSETMFEASFLLKKACSYLLSVGTVALFLACFNNAKSRDTVRKLFLNVHPEQLLMQPPKIRGVCAALFWFRLTFSPATGTLPQWIRTQTIAAEFDFGTMVQWAYDNSYCEESKIAYEYAMLANCDSNAKAFLASNNQAKMVKDCATMVRHYKRAEVQAMSISEYIKRRGSWLPIMNLFKFQGIEPIRFVNSMRQWLRGPKKNCICIVGPPNSGKSLLCNSLISFLGGRVLTFAMHKSHFWLAPLSEARVALIDDATYACWKYFDTYLRNALDGYPICDRKHKTAVQMKAPPLLVTSNIDVHADYLHSRIVSFYFKETCT-TANGEPMFSITNADWKIFFERLWGRLELEEEFTCASDRLRAAQEQQMLLIEDSTKLSDHVLFWRTENGLLYAARQKGITSMNGFPVPALAVSSTKAKQAIEMQLLLTELMHTTWGRDAWTLDVSYERYLMEPTLKKGPRVVEVMYDNDPANRTWYTAWSLLYMRTPA--GWLFATGADECGLYYRHYYDFFGRDAARYDPNQFSLFKSSGGQQCVLLSGSGNQAKCFRFRLKKGHRDKYLHCTTTW-WFDSPTQRELFLKTVPIPW-HAGQKLYLPPT-PVKTLCSESYVYRKDIYYHAETRLLTVGHPFYK-TVPKVSPNQYRAFMVQLPDPNQFALPDRTIYDPTEKLVWGLIGLQVSRGQPLGGAISGHTSFNALLDAENVGRRDDRKAAGDAKQQQVLLVGCTPALGEYWDTARPCGSCPALELKHKPIEDGDMMDIGFGAANFKELNSSKSDLPLDITNEICLYPDYLRMTEETAGNSMFFFARKEQVYVRHVWSRGGFIGAPSGSLLSTDGLIFNRPYWLYRAQGMNNGICWNNTVFVTVGDNTRGTNLTIYDSAKINVYHRHVEEYKLAFIFQLCSVQLTPETVSSLQGLMPSILQNWEVNVQP-PLEDTYSPATKCSPT-K-DPYDGLKFWKIDLKEKFSLDIDQFPLGRRFLAQQGKRR Seq70 MANDKGSALGCSYLLQDEDFLDQGN-HLEVFQALEKKAGEEQLLNLKRKV-LGSSEASETPGAKRRLFENEANLVKSKNATVFKLGLFKSLFLCSFHDLTRLFKNDKTTNQQWVFGIAEVFFEASLLLKKQCSFVQMQGTCAVYLLCFNTAKSRETVRNLMLNVREECLLMQPPKIRGLSAALFWFKSSLSPATGALPEWIRAQTTL-HFDFGTMVQWAYDHKYAEESKIAYEYALAAGSDSNARAFLATNSQAKHVKDCATMVRHYLRAETQALSMPAYIKTRGSWKSILTFFNYQNIELITFINALKLWLNGPKKNCLAFIGPPKTGKSMLCNSLIHFLGGSVLSFANHKSHFWLASLADARAALVDDATHACWRYFDTYLRNALDGYPVSDRKHKAAVQIKAPPLLVTSNIDVQAEYLHSRVQTFRFEQPCT-DESGEQPFTITDADWKSFFVRLWGRLDLEEDFTCACERLHVAQETQMQLIEASDKLQDHILYWRTENTLLYAARKKGVTVLGHCRVPHSVVCQERAKQAIEMQLSLQELSKTEFGNEPWCLDTSWDRYMSEPCFKKGARVVEVEFDGNASNTNWYTVYSKLYMR-TE-DGWQLAKAADGTGLYYRIYYSRFGEEAARFDADGFHLL-KAGQSCFALISGSANQVKCYRFRVKKNHRHRYENCTTTS-FFGSPGQRQDFLKHVPLPW-QQGQKLYLPPT-PVKVLCSETYVQRKSIFYHAETRLLTVGHPYYK-TVPKVSANQFRVFKIQLPDPNQFALPDRTVHNPSERLVWAVIGVQVSRGQPLGGTVTGHPTFNALLDAENVNRKDDRKQTGDAKQQQILLLGCTPAEGEYWTTARPCGACPPLELKNKHIEDGDMMEIGFGAADFKTLNASKSDLPLDIQNEICLYPDYLKMAEDAAGNSMFFFARKEQVYVRHIWTRGGHFGSPSGSLVSTDNQIFNRPYWLFRAQGMNNGIAWNNLLFLTVGDNTRGTNLSIYDTGKFNLYHRHMEEYKLAFILELCSVEITAQTLSHLQGLMPSVLQNWEIGVQP-PLEDTYSPATKCIPP-KEDPYAGLKFWSIDLKEKLSLDLDQFPLGRRFLAQQGKRK Seq71 MANDKGSGLGCSYLLQDEDFVDQGN-HLEVFQALEKKAGEEQILNLKRKV-LGSSEASETPGAKRRLFE?EANLVKSKNATVFKLGLFKSLFLCSFHDITRLFKNDKTTNQQWVFGLAEVFFEASFLLKKQCSFLQMQGTCAVYLICFNTAKSRETVRNLMLNVREECLMLQPAKIRGLSAALFWFKSSLSPATGALPEWIRAQTTL-NFDFGTMVQWAYDHKYAEESKIAYEYALAAGSDSNARAFLATNSQAKHVKDCATMVRHYLRAETQALSMPAYIKARGSWKSILTFFNYQNIELITFINALKLWLKGPKKNCLAFIGPPNTGKSMLCNSLIHFLGGSVLSFANHKSHFWLASLADTRAALVDDATHACWRYFDTYLRNALDGYPVSDRKHKAAVQIKAPPLLVTSNIDVQAEYLHSRVQTFRFEQPCT-DESGEQPFNITDADWKSFFVRLWGRLDLEEDFTCACERLHVAQETQMQLIESSDKLQDHILYWRTENTLLYAARKKGVTVLGHCRVPHSVVCQERAKQAIEMQLSLQELSKTEFGDEPWSLDTSWDRYMSEPCFKKGARVVEVEFDGNASNTNWYTVYSNLYMR-TE-DGWQLAKAADGTGLYYRIYYSRFGDEAARFN-DGFHLL-KAGGSCFALISGTANQVKCYRFRVKKNHRHRYENCTTTW-FFGSPSQRQDFLKHVPLPW-QQGQKLYLPPT-PVKVLCSETYVQRKSIFYHAETRLLTIGHPYYK-TVPKVSANQYRVFKIQLPDPNQFALPDRTVHNPSERLVWAVIGVQVSRGQPLGGTVTGHPTFNALLDAENVNRKDDRKQTGDAKQQQILLLGCTPAEGEYWTTARPCGACPPLELKNKHIEDGDMMEIGFGAANFKEINASKSDLPLDIQNEICLYPDYLKMAEDAAGNSMFFFARKEQVYVRHIWTRGGHFGSPSGSLVSTDNQIFNRPYWLFRAQGMNNGIAWNNLLFLTVGDNTRGTNLTIYDSSKFNVYHRHMEEYKLAFILELCSVEITAQTVSHLQGLMPSVLENWEIGVQP-PLEDTYSPATKCIPA-KEDPYAGFKFWNIDLKEKLSLDLDQFPLGRRFLAQQGKKK Seq72 MADKSGRGGCSFVLDFDAEFIDQGN-TLALFQSQVAQAGKQKVNYLKRKLHLESRAVLQPVAAKRRLFCSSSEILKSKNSAACKLAVFKFVYAASFCDLTRPFKNDKTTNYQWVFGVSEELFEASKLLGRSCTYLHATGSVALLLLSFHVAKSRETVTNLLLNLRAEHMMLQPPKLRGVTSAMFWYKMTLSPNTGQLPRWIEQQILITEFDFSHMVQWALDNEMMDESSIAFHYAQMADHDSNARAWLGLSNQAKIVKDVCTMVHHYQRAIMRSMTMSAYVHKMGSWLVIMQFLKFHGIEPIRFVNALRPWLQGPKKNCLAFIGPPDTGKSLFTNSLMSFLKGKVLNFANSASHFWLAPLTEAKVALIDDATHACLKYCDTYLRNFFDGYSVCDRKHKNAVQIKAPPMLLTSNIDIQAEYLKSRVTCFYFNDKCPLNEDGKPLFQITDPDWKSFFERLWQRLELEEEFICAAERLSAAQETQMTLLEPSFDLKDHISYYRTENTIFYAARKKGLTSLGHCPVPTLATAAANAKAAIEMQLLLKDLLRSPFAKNDWSLDVSHERYKAPPTLKRKPRIVEVIFDKDPQNKTWYTLWDEVYVC-TV-DGWTLTTSADATGIFVRQYYELFGEDAQRFQRAGEFDLLKGGCRPCCLIEGNGNKVKCLRFRLKKSHRSRFLDITTTF-WFTDTTQRDLFLGSVSIPWQQQGQRLYFPP-NPVKVLCTESYVKRTSIFYHGETRLLTVGHPYWQ-NIPKVSGNQYRVFRVQLPDPNQFALPDKNLHNPAERLVWAILGLQVSRGQPLGAPVTGNQLFNVWTDAENVTAKDDRKQLGDVKQTQMLLIGCTPAIGEYWGKAIPCGDCPPIELKNKPIEDGDMMDIGFGACDWKDFSQNLSDVPLDLINSKSLYPDYLKMAEDSLGNSCFFYARREQVYVRHVYSRGGFMGTPSGSLVSTDGQLFNRPYWLYQAQGLNNGVCWDNELFITVGDNSRGGVFTIYNSANMNIYCRHVEEYKLAVILELCSVELTSETVAYLQTVNPSVLEKWEVGVNP-PLEDTYSKAIKCAAA-K-DKYENLSFWNIDLREKLSADLDQYPLGRRFLAQNGNKK Seq73 MDNTPGTGSSDWVLLDLVDFIDDSDFYRRLQVEQQREDDQRAAHVLKRKFLDSPSPRLEAIRARRKLYDSGHGLMQAGKPRNVLLALCKDAYGCSFSDLTRSYKSDKTVCGDWVAGVPCSLEEAITLLKPHSDYTHVNGLLLLLLVRWKTAKCRETVQKLLMSVEKHQMVLEPPKIRHPATAMFWYKRTLANASGETPEWILKQVSLQEFSLSAMVQWAYDNGLEGESEIAYGYAQLAEEDTNAEAFLRSNAQAKHVKDCAIMVRHYRRAEMCKMNIAQWIKLRGDWRPIMKFLKFQKVEILAFLTFMRHFLRGPKRNCMVLLGPPNTGKSLFGMSLMHFLGGKIISHVNSGSHFWLQPLLECKVAMLDDATTSTWDYMDIYLRNMLDGNTVCDAKHKAPMQLKCPPLIVTTNVDVTANYLHSRLKVFTFPNLCPLNCRGDPEFQLTPENWKAFLEKCWTSLGLDLLLRCLCSRLDVLQEQQMELIDDSGCLKDIISYYRREAVLLFAANVRDIKKVGLTVVPPKQVCEANAKQAIEMHLVLCSLSESTYGQEPWYLQVSHDMYMLRPTFKKNGKRVLVTFDGDESNLMEYMCWEAVYKQRQNGQ-WSCVKSVSHEGIYYRDMYVDFAREAAKYDNWGSKRPGTCPDIPTLLISGGPNQVKCLRYRLRRHHRKAYRSCSTTWSWFYSEAQRVNFQKTVRLPWLPSTDKLFLPPPAPVKILSTDAFVTRLDIFYHAGTRQLLVGHPYFKLIAKKVSGNQYRAARFTLPDPNRFALQDPTIYDPDERLVWACRGLQVGRGLPLGGGTTGHPYYNKAKDTENPNSGDNRQNVSDPKQVQMVFVGCSPCVGEHWDKVTSTGDCPAIELVSSHIQDGDMCDIGFGAINNKTLQESRSEVPLDIVSSICKHPDILQMSNDPFGNSMWFFAKREQMYVRHMWARRGYSATPSGSLITSDGQLFNRPYWIQTAQGKNNGICWGNEVFVTVADNTRSTNITIYEADHFKIYTRHMEEYEFSFIFQLCKVPLTPEVLAQLNNMNSKIIEKWNVGFATAALAEHYSLATKCEDTEE-DPYEGESYWNIDLSEAFSSELDSFPLGRKFLYQASKRA Seq74 MASQDSTGSGG-FILEYMDFIDDDGGRHLNALLAEDDARAVQAVMSKIGH-SREYSSGGKESSHRKRTRSPDSLIRSGKARAAMLGIFKDSFGVRFTDITRHFKSDKTVCRDWVVGVACSVSDAVPLVRPHTVYSHTTGNMALGLVRWKTAKCRDTCCKLLLTVENKQLLLEPPQTQNAGAALFWYKKSISRGSGETLEWIARQVSLSSFCLSRMVQWAYDCGYTNESTIAYEYAKLADDDSNAEAFLKCNNQARYVRDCCKMVTLYARAEMAKMSMNEWIGRRKEWRVIVQFLKVQKVEFIPFLMQFRKFLKGPKNNCLCFYGPSNTGKSMFCMSLLEFLKGRTISYVNSKSQFWLQPLGDSKIGLLDDATLPVWDYMDVYLRNLLDGNVFCDAKHKAPSQIKAPPLLVTSNYNIKEYYLVNRVHVITFPTVCQTDYKGDVSVKLESHHWKSFFRRWWPLLDSNDGFRCLTNHLDVLQETQMEIFENSGNISDAVEYWRKEHSLLFLARRNGHVKVGHQMVPPAHVSESSAKDAIGMQLLLEGLQKTEYSTLTWTLETSKDMYMSPPTFKKGGTTVTVTYDESGYNCMDYTYWKYVFFQ--DGDTWTRGQGCNEKGLAY-CYYVTFAEEAVKYASGRWKQSPYCTEVPALIIRGPPNNVKCYRYRLKQKYPDIFVSCSSTWTWFANTHKREYFLNGIHMP-------LQLPPPGALRVLHTDEFIVRTNAFYHAMTRLITIGNPYYSVIAEKVSPHQYRVFRIQLPDPNQLALVDASVYDPKERLVWLLRGFDIGRGGPLGVGATGHPLFDKLKDAENPNNADSRQNVCDPKSMQMIIVGCTPAVGHYWDKADACGACPALVLKNSPLEDGDMIDLGFGSMNNKALNESHSAVPLDIVNSITKHPDMLKMAAEPYGNSCWFCLVREQMFARHLWARNGYLCTPSGSLVSSDTQVFNRPFWLQRAQGRNNGACWHNELFVSIADNTRGTNFNIYKGDDFKQYVRHCEIFELTFIIQLGKVSLTAEAVAHLQGMDASILEEWNIGFQGTAAEEKYSLATKCPTPKVQDRYDGLSFWTVDVSKTLSKDLENYPLGRKFLYQAGKRK Seq75 MAHAEGTGAGGWFVVDLVDFI-Q-EVPLELFVQQTANDDAAAVQALKRKFVGSPSPRLDAIKARRRLFDSGYGLFKGSNVRAAILSKFKDLFGLSFYDLVRQFKSDKSICGDWVFGVYYAVAEAVKLIQPQCIYAHIQGMVVLLLVRFKCGKSRETVAKYMLNVPEKHMLIEPPKIRSGPCALYWYRTAMGNACGETPEWIVRQTVVGHFSLSVLVQWAYDNDIQDESDLAYEYAKLGNEDANAAAFLASNCQAKYIKDAMTMCRLYRRAEQARMSMAQWIVHRGDWKHIVKFLRYQRVEFITFISAFKLFLKGPKKSCLVFYGPSDTGKSLFCMSLLQYLGGAVISFVNSSSHFWLSPLADAKIGLLDDATGQCWTYIDVYLRSILDGNPISDRKHRTLTQLKCPPLMITTNVDPLADYLRSRITVFKFMNKCPVTASGEPVYTLNNETWKSFFQRSWARLELEEEFRCLADRLDACQEMLIDLYEDSNKLEDQLLHWRREHAILFRAREAGHTSVGHQVVPPLSVTKTKACQAIAVHLSLQSLNNSDFKYEPWTLDTSMDMWNTPPCWKKKGCTVTVKFDNSDCNEMDYVSWGHIYVNKEDTDTWYKVPGIDYAGLYYKHYYVAFAKEALKYCPKRPRDNSDSNNTPVIHLQGEANKLKCFRYRLHKFVPTLLVGATSTWHWYSSVEQRNLFLSRVTIPWRHGDGKTYLPPT-PVKVMSTDRYVTRTSLFYYGGSRLLTVGHPYYKANIPKVSGYQYRVFRVKLPDPNKFALPDTALYNPDERMVWACRGVEVGRGQPLGVGTSGHPLYNRLDDTENTPLLDRRDNVSDYKQTQLLIIGCKPPIGEHWAKGTVCGDCPPLQFVNSTIQDGDMVETGYGAMDFANLQESKSEVPIDICTGICKYPDYLQMAAEPYGDCMFFCLRREQMFARHFFNRHGYAPTPSGSMVTSDSQLFNKPYWLQRAQGHNNGICWFNEVFVTVVDTTRSTNITIYQASNFKEYLRHTEEYDLQFIFQLCKIRITPEIMAYLHGMNESLLDDWNFGVLPPPLDDTYSRAITCAPDPK-DPYDGLAFWEVDLKDKLSMDLDQFPLGRKFLLQLGKKK Seq76 MADTEGTGAGGWFMVDLVDFI-Q-EVPLELFVQQTAEDDAAIVQAVKRKFVCSPSPRLDAIKARRRLFDSGYGLFKCSNVRAAILSKFKDLFGLSFYDLVRQFKSDKSICGDWVFGVYYAVAEAVKLLQPQCLYAHIQGMVVLMLLRFKCGKSRETVAKYMLNVPEKHMLIEPPKIRSGPCALYWYRTAMGNASGETPEWIVRQTVVGHFSLSMLVQWAYDNDIQEESDLAYGYAQLGNTDPNAAAFLASNCQAKYIKDAMTMCRLYRRAEQSRMSMAQWIAHRGDWKHIVKFLKYQNVEFISFISAFKLFLKGPKKSCLVFYGPSDTGKSLFCMSLLQYLGGAVISYVNSSSHFWLSPLADAKIGLLDDATAQCWTYIDVYLRSILDGNPTSDRKHRTLTQLKCPPLMITTNVDPLADYQRSRITVFKFLNKCPVTNSGELVYTLNNETWKSFFQRSWARLELEEEFRCLADRLDACQETLIDLYEDSNKLEDQLLHWRLEHAILFRAKEAGHAKVGHQVVPPLHVTKSKACQAIAVHLSLQSLNDSDFKHEPWTLDTSMEMWNTPPCWKKKGRTVTVRFDKSDCNEMDYVSWGHIYVYTEETRTWHKVSGVDYAGLYYKQYYVEFVKEAQKYCTNATRDTVNRYHTPVIHLQGEPNKLKCFRYRLHKSVPTLFVRATSTWHWYASIEQRELFLTRVTIPWRPGDGKTYLPPT-PVKVISTDRYVTRTNLFYYGGSRLLTVGHPYYKATIPKVSGYQYRVFRIRLPDPNKFSLPDTSLYNPDERMVWACRGIEVGRGQPLGVGTSGHPLYNRLDDTENTPLLDRRDNVSDYKQTQLIIIGCKPPIGEHWAKGTVCGDCPPLQFVNSTIQDGDMVETGYGAMDFATLQESKSEVPIDICTATCKYPDYLQMAAEPYGDCMFFCLRREQMFARHFFNRHGYAPTPSGSLVSSDSQLFNKPYWLHRAQGHNNGICWFNELFVTVVDTTRSTNITIYTASNFKEYLRHTEEYDLQVILQLCKIHLTPEIMAYLHSMNEHLLDEWNFGVLPPPLDDTYSRAITCAPAPK-DPYDGLVFWEVDLKDKLSTDLDQFPLGRKFLLQLGKKK Seq77 MADHEGTRAGGWFLVDLVDFIVQ-EVPLALYVHQNAQDDAAAVQALKRKFTYSPSPRLDAIKARRRLFDSGYGLLKASNIRATILSKFKELFGLSYYDLVRQFKSDKSTCGDWVFGVYHAVAEAVKLLQPHCVYAHIQGMVVLALVRFKCGKNRESVAHCMLNIPDRHMLIEPPKIRSGPCALYWYRTAMGNASGETPEWIVRQTVIGEFSLSTLVQWAYDNDITDESQLAYEYALLGNEDPNAAAFLASNCQAKYIKDAITMCKHYKRAEQARMTMAQWIKYRGDWRHIVKFLRYQNVEFITFMSAFKHFLKGPKKSCMVFYGPSDTGKSLFCMSLLHYLGGAVISFVNSSSHFWLSPLVDAKVGLLDDATMQCWTYIDVYLRSILDGNAISDRKHRNLTQLKCPPLMITTNVDPLADYLKSRIVVFRFLNKCPMNANGEPVYTLNNETWKSFFQRSWARLDLEEEFRCLADRLDACQERLIDLYEDSNKLQDQLSHWRLEYAILYKARQAGLTSVGHQVVPPLNVTKEKASQAITIHLSLQSLNASAYKDEPWTLHTSLDMWNAPPCWKKKGHTVTVKYDGEDQKAMEYVSWGEIYIQCPETDMWYKVAGVNATGLYYRHYYVNFTKEAKHYGTERLGIAHCCNTAPVIHLQGEANKLKCFRYRLKQTVPDLYLRASSTWHWYSSAEQRAQFLARVHIPWRPGDGKVYLPPT-PVKVLSTDRYVQRTNLYYYGGSRLITVGHPYYKANIPKVSGYQYRVFRVRLPDPNKFGLPDASLYNPDERLVWACRGIEVGRGQPLGVGTSGHPLYNRLDDTENASLLDSRDNISDYKQTQLLIIGCKPPIGEHWAKGTVCGDCPPLQLLNTTIEDGDMVETGYGAMDFSKLQESKSEVPIDICDSTCKYPDYLQMAAEPYGDCMFFCLRREQMFARHFFNRQGYAPTPSGSMVTSDSQLFNKPYWLHRAQGHNNGICWFNELFVTVVDTTRSTNLTIYSSTRFKEYLRHTEEYDLQFIFQLCKIHLTPEIMSYLHNMNDTLLDEWNFGVIPPPLDDTYSRAITCAPEPK-DPYDKLSFWDVDLKERLSTDLDQFPLGRKFLLQLGKRK Seq78 MADAEGTGAGGWFMVDLVDFIDQ-EVPLELFVQQNARDDAAAVQALKRKYTYSPSPRLNAIRARRRLFDSGYGLLKTSNLRATLLSKFKELYGLAFGELVRQFKSDKSVCGDWVFGVYHAVAEAIKLIQPVCLYAHIQGMVILMLIRFKCSKSRETVAKCILNVPDKQMLIEPPKIRSAPCALYWFRTAMGNASGETPEWITRQTVVGHFSLSVLVQWAYDNDIVDESDLAYQYALLGNDDPNAAAFLASNCQAKYIKDAITMCKYYKRAEQKRMSMAQWIAHRGDWRPIVRFLRYQKIEFVTFMSALKMFLRNPKKSCIVIYGPSDTGKSLFCMSLLKFLGGAVISYVNSTSHFWLSPLTDAKVGLLDDATYPCWVYIDTHLRSVLDGNQISDRKHKNLTQIQCPPLFITTNINPLEDYLHSRIAVFHFMYKCPLDDKGDPVYQFNNENWKSFFQRSWAQIEGEEEFRCLADRLDACQEKLIDFYEDSDKLDDQVKHWRLEHAILFKARQAGLTQLGHQVVPALSVTKGKAHLAIEVHLALKSLYASVYKDEPWTLSTSLDMWNAKPCWKKKGRTVTVKFDCEDSKIMEYVSWGYIYVQ-TDTEQWCKVQGVSYEGLYYRHYYVVFADEAKKYSTK-GRHVCDGGAAPVIHLRGEPNKLKCLRYRLRGSVPHLFVKASSTWHWYANIEQRTEFLQRVTIPWRPGDGKVYLPPT-PVKVLSTDTYVTRTNLFYYGGSRLLTVGHPYCRATIPKVSGYQYRVFRVKLPDPNKFTLPDATLYNPDERMVWACRGIEVGRGQPLGVGTSGHPLYNRLDDTENTSLLDSRDNISDYKQTQLLIVGCKPPIGEHWTKGTLCTECPPLEFKNTTIQDGDMVETGYGAIDFKSLQESKSEVPLDICTSTCKYPDYLQMAAEPYGDCMFFCLRREQMFARHFFNRHGYAPTPSGSMVSSDSQLFNKPYWLQRAQGHNNGICWFNELFVTVVDTTRSTNFTIYKATNFREFLRHTEEFDLQFIFQLCKIQLTPEIMAYLHNMNKDLLDDWNFGVLPPPLDETYSRAITCSPSPKVDPYAQMTFWTVDLKDKLSTDLDQFPLGRKFLLQAGKRK Seq79 MADVEGTRAGGWFMVDLVDFI-Q-EVPLELFVQQNAQDDAAAVHALKRKYIHSPSPRLDAIRARRRLFDSGYGLLKARNLRATLLSKFKELYGLAFGELVRQFKSDKSTCTDWVFGVYYAVAEALKLIQPLCHYAHIQGMVQLMLIRFKCGKSRDTVAHCILNVSEKQMLIEPPKIKSTPCALYWYKTAMGNASGETPEWIVRQTVVGHFSLSVMVQWAYDHDITDESQLAYEYALLGHEDPNAAAFLASNCQARYIKDAITMCRHYKRAEQARMSMAQWIAHRGDWKPIVRFLRFQKIEFMTFMGAFKMWLKGPKRSCIVIHGPSDTGKSLFCMSLVQFLGGAVISYVNASSHFWLSPLADAKVGLLDDATHPCWVYIDTHLRSVVDGNLISDRKHRNLAQLKCPPLLITTNINPLEDYLHSRMAVFSFMYKCPLDDNGDPVYKFNNENWKSFFQRSWARLEVEEEFRCLADRLDACQETLIDLYEDSNKLEDQIKHWRLENAILFKARQAGLTHLGHQVVPTLNVTKGKAHQAIAVHLSLQSLYASEYKDEPWTLNTSLDMWNTQPCWKKKGRTVTVKYDCEDSKKMEYVNWGHIYVQSPHTEQWHRVHGVSYDGLYYKQYYVQFAQEARKYSTE-TRNFSDGDTAPVIHLRGDANKLKCLRYRLRSSVPHLFVNASSTWHWYANEDQRAKFLQRVTIPWRPGDGKVYLPPT-PVKVISTDAYVTRTNLFYYGGSRLLTVGHPYCRSTIPKVSGYQYRVFRVKLPDPNKFALPDGTLYNPDERMVWACRGIEVGRGQPLGVGTSGHPLYNRLDDTENTAYLDSRDNISDYKQTQLLIIGCKPPIGEHWARGTFCNECPPLEFKNTTIQDGDMVETGYGAIDFKALQENKSEVPLDICNTTCKYPDYLQMAAEPYGDCMFFCLRREQMFARHFFNRHGYAPTPSGSMVSSDSQLFNKPYWLQRAQGHNNGICWFNEMFVTVVDTTRSTNFTIYKASNFKEFLRHTEEYDLQFIFQLCKIQLTPEIMAYLHNMNKALLDDWNFGVLPPPLDDTYSRAITCAPAPKEDPYADMSFWTVDLKDKLSTDLDQFPLGRKFLLQSGKR- Seq80 MADSEGTRAGGWFLVDLVDFI-Q-EVPLALFVQQNAQDDAATVQALKRKYTCSPSPRLDAIRARRRLFDSGYGVFKVSNLKAKLLYKFKDLFGLAFGELVRNFKSDKSICGDWVFGVYHAVAEAVKLIQPICVYAHIQGMVILMLVRYKCGKSRETVAHSMLNIPERQMLIEPPKIRSAPCALYWYRTAMGNASGETPEWIVRQTVVGHFSLSMLVQWAYDNDITDESVLAYEYALLGNEDPNAAAFLASNCQAKYIKDAITMCKHYRRAEQAKMTMAQWITHRGDWKAIVKYLRYQQVEFVPFISALKLFLKGPKKSCMVFYGPSDTGKSLFCMSLLNFLGGAVISYVNSSSHFWLSPLADTKVGLLDDATYQCWQYIDTYLRTVLDGNAISDRKHRNLTQLKCPPLMITTNINPLEDYLHSRIVVFQFLHKCPLNSNGDPVYTLNNENWKSFFRRSWARIEGEEEFRCLADRLDACQEKLLDLYEDSNKLEDQILHWRLENAMLFKARQAGLTRVGHQMVPTLSVTKGKAHKAIEVHLSLQGLQTSAYAHEPWTLTTSLEMWNTQPCWKKKGRRLTVKFDGEDHKAVEYVSWGYIYVQSTETDLWYKVPGVSYKGLYYEHYYVTFAQEAQKYSTETG-DNCDSYSSPVIHLKGDPNKLKCFRYRLQHSVPELFDKASSTWHWYVNVEQRKQFLNRVTIPWRPGDGKVYLPPT-PVKVISTDRYVQRTNLFYYGGSRLLTVGHPYCKNTIPKVSGYQYRVFRVQLPDPNKFALPDGTLYNPDERMVWACRGIEVGRGQPLGVGTSGHPLYNRLDDTENTTLLDSRDNVSDYKQTQLLIVGCKPPIGEHWTKGTACTDCPPLEFTNTTIQDGDMVETGYGAIDFAALQENKSEVPLDICTTICKYPDYLQMAAEPYGDCMFFCLRREQMFARHFFNRQGYSPTPSGSMVSSDSQLFNKPYWLQRAQGHNNGICWFNELFVTVVDTTRSTNLTIYKATSFREYLRHTEEFDLQFIFQLCKIHLTPEIMAYLHNMNKALLDDWNFGVVPPPLEDTYSRAITCAPPPKEDRYAKLSFWTVDLRDKFSTDLDQFPLGRKFLLQAGKRK Seq81 MANCEGTRAGGWFLVDLVDFI-Q-EVPLDLFVQQNARDDAATVQALKRKYTCSPSPRLDAIRARRRLFDSGYGIFKVSNLRVTLLHKFKELFGLAYGDLVRQFKSDKSICGDWVFGVYHAVAEAVKLIQPICLYAHIQGMVILMLVRYKCGKSRETVAHSMLNIPEKQMLIEPPKIRSGPCALYWYRTAMGNGSGETPEWIVRQTVVGHFSLSTLVQWAYDNDITDESELAYDYAMLGNEDPNAAAFLASNCQAKYIKDAITMCKHYKRAEQARMSMTQWIAHRGD*E?IVKYLRYQRVEFVTFMGALKLFLKGPKKSCMVFYGPSDTGKSLFCMSLLKYLGGAVISYVNSGSHFWLSPLVDAKVGLLDDATYQCWQYIDTYLRTVLDGNAISDRKHRNLTQLKCPPLMITTNINPLEDYLHSRIVLFKFMHKCPLKSNGDPVYTLNNENWKSFFQRSWARIEGQEEFRCLADRLDACQEKLLDLYEDSDKLEDQILHWRLEHAMLFKARQAGLTHVGHQVVPTLSVTKGKAHQAIEVHLSLQGLQNSAYAQEPWTLNTSLEMWNAHPCWKKKGRTITVKFDCEDLKAVEYVSWGCIYVQSTEDEQWYKVQGVSYHGLYYKQYYVTFGHEARKYCTQQARDICNSHGAPIIHLKGEPNKLKCFRYRLQQSVPNLFLKASSTWHWYVDTDQRTQFLSRVNIPWRPGDGKVYLPP-NPVKVLSTDRYVQRTNLYYYGGSRLLTVGHPYCKNTIPKVSGYQYRVFRVKLPDPNKFALPDGTLYNPDERLVWACRGIEVGRGQPLGVGTSGHPLYNRLDDTENTSLLDSRDNVSDYKQTQLLIIGCKPPIGEHWTKGTPCTDCPPLEFTNSTIQDGDMVETGYGAIDFATLQENKSEVPLDICTTTCKYPDYLQMAAEPYGDCMFFCLRREQMFARHFFNRQGYSPTPSGSMVSSDAQLFNKPYWLQRAQGHNNGICWFNELFVTVVDTTRSTNVTIYTASNFREYLRHTEEFDLQFIFQLCKIHLTPEIMAYLHNMNKALLDDWNFGVVPPPLDDTYSRAITCTPPPKEDPYANLSFWTVDLKDKFSTDLDQFPLGRKFLLQVGKRK Seq82 MAESPEGGAGGWFVVDMVDFVDQ-EVPLGLYVQQTMQDDAATVQALKRKFMGSPSPRLDAIKARRRLFDSGYGLLQVSNLRVQLFTKFKELFGLSFKDLVRQFKSDRSTCAEWVFGVYYAVAEAAKLLQPVCEYAHIQGMVMLLLLRFKCNKSRETVAKCLLNIPEKRMLIEPPKQRSAPCALYWYKTAMGNASGDTPDWIVRQTVIGHFSLSVLVQWAYDNEITDDSELAYEYAKLGNEDPNAAAFLASNCQARYIKDAITMVRHYRRAEQARMSMSQWIAHRGDWRHIVKLLRFQGIEFISFMEALKQFLKGPKKSCLVFYGPSDTGKSLFCMSLLRYLGGAVISFVNSTSHFWLSPLVDAKIGLLDDATQQCWVYIDTYLRTVLDGNTMSDRKHKNLQQLKCPPLMITTNVNIAADYLRSRMVVFPFLQKCPLDSNGEPVYKLNNENWKSFFQRSWARLDLEEEFRCLADRLDACQDKLLDLYEDSNTLEDQLLHWRLEKAILFKAREAGLTHIGHQVVPASSVTKEKARQAITVHLSLQSLNNSEFKHEPWTLDTSLDMWNVPPCWKKGGRPIRVKYDGEDDKEMEYVSWGFIYIYCGSDETWHKVPGISHAGCYYKHYYVDFGKEAKQYIPQWSRDNSNSHGAPVIHLKGDPNRLKCLRYRLQQSVPQLFERASSTWRWYRDTEQRQQFLARVNIPWRPGDGKVYLPPT-PVKVLSTDRYVSRTNLFYYGGSRLLTVGHPYYKANIPKVSGYQYRVFRVRLPDPNKFGLPDAQLYNPDERLVWACRGLEVGRGQPLGVGASGHPLYNRLDDTENTSFLDSRDNVSDYKQTQVLIVGCKPSIGEHWGKGTVCGDCPPLQFTNSTIQDGDMVEAGYGAMDFDKLQENKSEVPLDICATVCKYPDYLQMAAEPYGDCMFFCLRREQMFARHFFNRQGYAPTPSGSMVSSDSQLFNKPYWLQKAQGHNNSICWFNQLFVTVVDTTRSTNFTIYDPSKFNEYLRHAEEYDLQFIFQLCKVRLTPEIMSYLHSMNESLLDEWNFGVVPPPLEDTYSRAITCAPQPKEDPYAGMVFWEVDLKDKLSTDLDQFPLGRKFLLQSAKRR Seq83 MAESPEGGQG?WFVVDMVDFIDQ-EVPLDLYVQQTMQDDAATVHALKRKYIGSPSPRLDAIKARRRLFDSGYGLLQVSNLRVKLLAKFKELFGLSFMDLVRQFKSNKSTCGDWVFGVYYAVAEAAKLLQPVCDYAHIQGMVMLLLLRFKCNKSRETVAHCILNIPEKRMLIEPPKQRSGPCALYWYKTAMSNASGETPDWIVRQTVIGHFSLSVLVQWAYDNEITEESELAYEYAQLGNEDANAAAFLASNCQARYIKDAITMVRHYRRAEQARMTMSQWIAYRGDWRHIVKLLRYQGIEFISFMEALKHFLKGPKKSCLVFYGPSDTGKSMFCMSLLKYLGGAVISFVNSTSHFWLSPLVDTKIGLLDDATQQCWVYMDTYLRTVLDGNTMSDRKHKTLQQLKCPPLMITTNVNIEADYLRSRMVVFPFLHKCPLDSNGDPVYKLNNENWKSFFQRSWARLDLEEEFRCLAARLDACQDKLIDLYEDSNKLEDQLLHWRLEKAMLFKARETGLTHIGHQVVPPLSVTKEKARQAITVHLSLQSLNNSEFRHEPWTLDTSLDMWNVSPCWKKQGRPIRVKYDGEDDKEMEYVSWGYIYIQCASTDTWLKVPGISHQGLYYKRYYVDFAKEAKHYNTQWTRDNCISNGAPVLHLKGDPNRLKCFRYRLQQSVPQLFDKASSTWRWYKDTEQRKQFLARVNIPWRPGDGKVYLPPT-PVKVISTDRYVSRTNLFYYGGSRLLTVGHPYYKSNIPKVSGYQYRVFRVRLPDPNKFGLPDAQLYNPDERLVWACRGLEVGRGQPLGVGTSGHPLYNRLDDTENTPFLDSRDNVSDYKQTQLLIVGCKPSIGEHWSKGTVCGDCPPLQFTNSTIQDGDMVEAGYGAIDFEKLQENKSEVPLDICTTVCKYPDYLQMAAEPYGDCMFFCLRREQMFARHYFNRQGYAPTPSGSMVSSDSQLFNKPYWLQRAQGHNNGICWFNQLFVTVVDTTRSTNFTIYDPTKFKEYLRHVEEYDLQFIFQLCKVRLTPEVMAYLHTMNESLLDEWNFGVVPPPLDDTYSRAITCATKPKEDPYTGMLFWEVDLKDKLSTDLDQFPLGRKFLLQSAKRR Seq84 MAESPEGGAGGWFVVDLVDFIDQ-EVPLDLYVQQTIQDDAATVQALKRKFMGSPSPRLNAIKARRRLFDSGYGLLQVSNLRVKLLGKFKELFGLSFMDLVRQFKSNKSTCGDWVFGVYHAVAEAAKLLQPVCEYAHIQGMVMLLLLRFKCNKSRETVAHCILNVPEKRMLIEPPKQRSGPCALYWYRTAMGNACGETPDWIVRQTVIGHFSLSKLVQWAYDNDITDESELAYEYAQLGTEEPNAAAFLASNCQARYIKDAMIMCRHYRRAEQTRMSMSQWITYRGDWRHIVKLLRYQGIEFISFMTALKQFLKGPKKGCLVFYGPSDTGKSLFCMSLINYLGGTVISFVNSTSHFWLSPLADAKIGLLDDATYQCWIYMDTYLRSVLDGNVISDRKHKNLVQLKCPPLLITTNINPETDYLRSRMVIFPFLNKCPLDANGDPVYQLNNENWKSFFRRSWARLDLEEEFRCLADRLDACQEKLIDLYEDSNKLEDQLMHWRLEQAMLFKAREAGLRHIGHQVVPTLSVTKEKARQAIMVHLSLQSLNNSAFKHEPWTLDTSLNMWTVAPCWKKHGQPIRVKYDGEDDKEMEYVNWGFIYVHCASEDTWYKVPGISNRGLYYKHYYVEFAKEAKQYSPKRPREHSNCDSAPVLHLKGQSNSLKCFRYRLHQSVPDLFERASSTWKWYKSTDQRKQLLARVHIPWRPGDGKVYLPPT-PVKVISTDRYVSRTNLFYYGGSRLLTVGHPYYKATIPKVSGYQYRVFRVHLPDPNKFGLPDAQLYNPDERLVWACRGVEVGRGQPLGVGTSGHPLYNRLDDTENTPFLDSRDNVSDYKQTQLLIIGCKPSIGEHWGKGTVCGDCPPLQFTNSTIEDGDMVEAGYGAIDFATLQESKSEVPLDLCTTTCKYPDYLQMAAEPYGDCMFFCLRREQMFARHFFNRQGYAPTPSGSMVSSDSQLFNKPYWLQKAQGHNNGICWFNQLFVTVVDTTRSTNFTIYKPTNFKEYLRHVEEYDLQFIFQLCKVRLTPEVMSYLHTMNDSLLDEWNFGVVPPPLDDTYSRAITCAAKPKDDPYAGMSFWDVDLKDKFSTDLDQYPLGRKFLLQSAKRR Seq85 MADGEGTSACGWFWVDMVDFIDQ-EVALELYRQQEAQDDEAFVQALKRKYLASPSPRLDAIKAKRRLFDSGYGLLKTSNLRATLLGKFKDIYGLSFMELARQFKSNRTTCLDWVFGVYCTVAEGVKLIQQHCQYAHIQGMVVLMLVRYNCAKNRDTVAKCMLNIPEQHMLIEPPKIRHPAAALYWYKAGMGNASGETPEWIVRQTVVGHFQLSVMVQWAYDHDITDESILAYEYAKLADVDGNAAAFLASNCQAKYVKDACTMCRHYKRAEQAQMTMSEWIRFRGDWRPIVRFLRHHDIEFITFVISLKNFLKGPKKCCIVIYGPADTGKSYFCMSLLRFLGGVVISYANSTSHFWLQPLCDAKIGLIDDVTPQCWSYIDTYLRNALDGNQVCDRKHRPLLQLKCPPLLMTTNTNPLEEFLRSRLQLFTFPNAFPVNQKGDPLYTLNDANWKCFFQRLWARLDLDDQFKCLASRLNACREKLLELYEDSDQLQDQIMHWRLENVIMYKAREAGMLHLNHQVVPVQLIAKAKACKAIEMQLALKTLLKSPYGTEPWTLDTSQEMWDAAPCWKKKGYTVDVKFDGEDTKTMCYTCWRYIYVQSGDDDTWTKVSGVDHAGLYFRVTYVRFAQEAQTYSAKQHGNIRVGDSAPVTHLRGDPNKLKCLRYRLHKHKSVLFSKVTSTWRWHDSAEQRATFLSTITLPWKPSDNKVYLPPA-PVKVLSTDAYVSRTNIYYYAGSRLLTVGHPYFPIVVPKVSGYQYRVFRVRLPDPNKFGLPDASLYNPDQRLVWACTGVEVGRGQPLGVGVSGHPLYNRLYDTENTNLYDTRDNLTDYKQTQLFIIGCKPPLGEHWAKGTPCGDCPPIELKSSTIQDGDMIDTGFGALDFAALQTNKSDVPLDIVTTTCKYPDFLQMAAEPYGDLMFFCLRREQMFIRHFYNRAGYGSTPSGSMVTSESQLFNKPYWLQRAQGPNNGICWGNQLFVTVVDTTRSTNMTIYKASNFKEYMRHGEEFDLQFIFQLCVINLTTEVMAYLHGMNATLLEDWNFGSLPPPLGDTYSQAISCVPTE-NDPYAGLTFWEVDLSERFSLELDQFPLGRKFLLQRGKRK Seq86 MADCEGTGACGWFWVDMVDFIDQ-EGAPELYRQQEVQDDEAIVQALKRKYIASPSPRLDAIRAKRRLFDSGYGLLKTSNLRATLLGKFKDLFGLSYMELVRQFKSNKTTCIDWVFGVYCTVAEGVKLIQQHCQYAHIQGMVVLMLVRYNCAKNRDTVAKCMLNIPEHHMLIEPPKIRYPPAALYWYKAGMGNASGETPEWIVRQTVVGHFQLSVMVQWAYDHDITDESILAYEYARLADVDGNAAAFLASNCQAKYVKDACTMCRHYKRAEQAQMTMSQWITFRGDWRPIVRYLRHQDIEFISFVIALKNLLKGPKKCCIVIYGPADTGKSYFCMSLLRFLGGVVISYANSSSHFWLQPLCDAKIGLIDDVTPQCWSYIDTYLRNALDGNQVCDRKHRPLLQLKCPPLLMTTNTNPLEEFLRSRLQMFTFKNAFPVNQKGDPLYILNDANWKCFFQRLWARLDLQDDFRCLASRLDVCQEKLLELYEDSDQLQDQILHWRWENVILYKAREAGHLHLNHQVVPVQLIAKAKACKAIEVQLALKTLLKSPYGTEPWTLDTSQEMWDTEPCWKKRGYTVDVKFDGEESKTMCYTCWRDIYVQSIADDTWDKVTGVDHAGLYYRVTYVKFSQEAQTYGANQHRNISVGHGAPVIHLRGDPNKLKCLRYRLKKHTPVLFTKASSTWRWHDSVEQRAKFLATVTLPWKPSDNKVYLPPA-PVKVLSTDDYVSRTNIYYYAGSRLLTVGHPYYPIVVPKVSGYQYRVFRVRLPDPNKFGLPDASLYNPDQRLVWACTGVEVGRGQPLGVGVSGHPLYNRLYDTENTNLFDNRDNMSDYKQTQLCIIGCKPPLGEHWAKGTPCGDCPPLELTSSTIQDGDMIDTGFGALDFASLQTNKSDVPLDIVTTTCKYPDFLQMAAEPYGDLMFFSLRREQMFVRHFYNRAGYGSTPSGSMVTSESQLFNKPYWLQRAQGRNNGICWGNQVFVTVVDTTRSTNMTIYKASNFKEYLRHGEEFDLQFIFQLCVINLTAEVMAYLHSMNAALLEDWNFGSLPPPLGDTYSQAITCAPA-KKDPYDGLTFWDVDLSERFSLELDQFPLGRKFLLQHRKRK Seq87 MADCEGTGAGGWFFVDMVDFINQ-EVAAEVYRQQEALDDEAIVQPLKRKFLASPSPRLDAIKAKRRLFDSGYGLLNSSNRRATLLGKFKDLYGLSYMELVRQFKSNKTTCLDWVFGVYCTVAEGVKLIQQHCEYAHIQGVVILMLLRYKCAKNRDTVAKGLLNIPETNMLIEPPKIRSTPAALYWFRASMGNASGETPEWIVRQTVVGHFQLSVMVQWAYDHDITDESILAYEYARLADVDSNAAAFLASNCQAKYVKDACTMCRHYKRAEQAQMSMSQWISFRGDWRTIVKYLRHQDIEFITFIIALKNFLKGPKKSCLVFYGPADTGKSYFCMSLLRFLGGVVISYANSSSHFWLQPLADAKLGLIDDVTPNCWSYIDVYLRNALDGNQICDRKHRPLLQLKCPPLLITTNTNPLEEFLRSRLQLFTFKNAFPLNSKGDPMYPLNDANWKCFFQRLWARLDLDEQFRCLASRLDACQETLLELYEDSDQLQDQIKHWRWENVLLFKAREAGITHLAHQVVPVLGIAKAKACKAIEIQLALKTLLNSPYSNERWTLDTSQEMWDAVPCWKKKGYTVEVRYDCKEEKTMCYTCWREIYVQNSTNETWEKVCGVDHAGIYYRVDCVLFSKEAVIYGAHEHGRTRDCNSAPVIHLRGEANKLKCLRYRLQKHKSVLFAKASSTWHWHDSVEQRAQFLATVHIPWRPSDSKVYLPPA-PRQVLSTDDYVTRTKLFYYAGSRLLTVGHPYFRIVVPKVSGYQYRVFRVRLPDPNKFGLPDASLYNPDQRLVWACKGLEVGRGQPLGIGVSGHPLFNKLNDTENATLFDTRDNVSDYKQTQLCIIGCKPPLGEHWAKGTPCGSCPPLELASTVIQDGDMVDTGFGAMDFAALQTNRSDVPLDIVTTTCKY?DYF?MAAEP?GDRMFFLR??E?MF?R?FYNRQAYASTPSGSMVTSESQLFNKPYWLQRAQGTNNGICW?NLLFVTV?DTSRSTNMSIYKASSFMEYLRHGEEFDLQFIFQLCVINLTAEIMAYLHGMDATLLEDWNFGSLPPPLGDTYSQAITCPPAEK-DPYADLTFWEVDLKERFSLELDQFPLGRKFLLQSGKRK Seq88 MEDSEGTRAGGWFHVEDLDFIDQ-EVPLQLYAQQIAQDDEATVQALKRKFVASPSPRLDAIKAKRRLFDSGYGLLKSSNLKATLLSKFKELYGVGYYELVRQFKSSRTACADWVFRVYYAVAEGIKLIQPHTQYAHIQGMVVFMLLRYNCAKNRDTVSKNMLNIPEKHMLIEPPKLRSTPAALYWYKTSMGNGSGETPEWIVRQTLIGHFKLSVMVQYAYDHDITDESALAFEYAQLADVDANAAAFLNSNCQAKYLKDAVTMCRHYKRAEREQMSMSQWITFRGDWKPIVKFLRHQGVEFVSFLAAFKSFLKGPKKNCIVFYGPADTGKSYFCMSLLQFLGGAVISYANSSSHFWLQPLADSKIGLLDDATAQCWTYIDTYLRNLLDGNPFSDRKHKTLLQIKCPPLMITTNINPLEEYLRSRVTLFKFTNPFPFASPGEPLYPINNANWKCFFQRSWSRLDLEDQFRCLASRLDACQETLLELYEDSNKLEDQIKHWRLENVMLFKARECGMTRVGCTTVPALTVSKAKACQAIEVQLALQTLMQSAYSTEAWTLDTCLEMWEAPPCWKKKGQSVLVKFDGSCDRDMIYTGWGHIYVQDINDDTWHKVPGVDELGLFYRVNYVDFGIEALTYSTDPRRGHSDLDAVPVIHLQGEANCLKCFRYRVQKHKDVLFVKASSTWHWYKSQEQRAEFLTRVHLPWRPNESKVYLPPT-PVKVLSTDVYVTRTNVYYHGGSRLLTVGHPYYKVSVPKVSGYQYRVFHVKLPDPNKFGLPDANLYDPDQRLLWACVGVEVGRGQPLGVGISGHPYYNKQDDTENS-HNDGREYISDYKQTQLFILGCKPPIGEHWSKGTTCGDCPPLQFTNTTIEDGDMVETGFGALDFAALQSNKSDVPLDICTNICKYPDYLKMAADPYGDSMFFSLRREQMFTRHFFNRGGYTSTPSGSMVSSEQQLFNKPYWLRRAQGHNNGMCWGNRIFLTVVDTTRSTNVSLYKASNYKEYLRHMEEYDLQFIFQLCKITLTPEIMAYIHNMDARLLEDWNFGVPPPPLQDTYSQAITCPKT-P-DPYATMTFWDVDLSESFSMDLDQFPLGRKFLLQRGKRK Seq89 MEDSEGTRAGGWFHVEDVDFIDQ-EIPLQLYTQQIAQDDEATVQALKRKFVASPSPRLDAIKAKRRLFDSGYGLLRSSNLKATLLSKFKELFGVGYYELVRQFKSSKTACADWVFGVYYAVAEGIKLIQPHTQYAHIQGMVVFMLLRYNCAKNRDTVSKNMLNIPEKHMLIEPPKLRSTPAALYWYKTAMGNGSGETPEWIVRQTLVGHFRLSVMVQFAYDHDIVEESVLAFEYAQLADVDANAAAFLNSNCQAKYVKDAVTMCRHYKRAERAQMSMSQWITFRGDWKPIVKFLRHQGVEFVSFLAAFKLFLKGPKKNCIVFYGPADTGKSYFCMSLLQFLGGAVISYANSSSHFWLQPLSDSKIGLLDDATPQCWSYIDTYLRNLLDGNPVSDRKHKTLLQLKCPPLMITTNINPLEEYLRSRLTLFTFNNPFPFASPGEPLYPINNANWKCFFQRSWSRLDLEEQFRCLANRLDACQETLLELYEDSNKLEDQIKHWRLENVMLFKARECGMTRVGCTTVPALTVSKAKACQAIEVQLALQTLMQSAYSTEAWTLDTCLEMWDAPPCWKKKGLSVLVKFDGSSDRDMIYTGWHHIYVQDANDDTWHKVPGVDELGLYYRVNYVDFGTESLTYSTAPRWDHGDTDTVPVIHLRGDANCLKCFRYRVQKHKDKLYDRVSSTWHWYTSVEQRKEFLTRVNIPWRPNESKVYLPPT-PVKVISTDVYVTRTNVYYHGGSRLLTVGHPYYRLAVPKVSGYQYRVFHVKLPDPNKFGLPDADLYDPDQRLLWACVGVEVGRGQPLGVGVSGHPYYNRQDDTENA-HTDGRENISDYKQTQLFILGCKPSIGEHWSKGTTCGDCPPLQFTNSTIEDGDMVETGFGALDFATLQSNRSDVPLDICTNVCKYPDYLKMAAEPYGDSMFFSLRREQMFTRHFFNRAGYTSTPSGSMVSSEQQLFNKPYWLRRAQGHNNGMCWGNRIFLTVVDTTRSTNVSLYKATNFKEYLRHMEEYDLQFIFQLCKITLTPEIMAYIHNMDPQLLEDWNFGVPPPPLQDTYSQAITCPKT-P-DPYANMTFWDVDLRESFSMDLDQFPLGRKFLLQRGKRK Seq90 MEDSEGTRAGGWFHVEDLDFIDQ-EIPLQLYAQQTAQDDEATVQALKRKFVASPSPRLDAIKAKRRLFDSGYGLLRSSNLKATLLSKFKDLFGVGFYELVRQFKSSKTACADWVYGVYYAVAEGLKLIQPHTQYAHIQGMVVFMLLRYNCAKNRDSVSKNMLNIPEKHMLIEPPKLRSTPAALYWYKTAMGNGSGETPEWIVRQTLVGHFRLSVMVQYAYDHDIVEESVLAFEYAQLADVDANAAAFLNSNCQAKYVKDAVTMCRHYKRAEREQMSMSQWITFRGDWKPIVRFLRHQGVEFVSFLAAFKLFLKGPKKNCIVFYGPADTGKSYFCMSLLQFLGGAVISYANSSSHFWLQPLSDSKIGLLDDATPQCWSYIDIYLRNLLDGHPVSDRKHKTLLQLKCPPLMITTNTNPLEEYLRSRLTVFTFKNPFPFASPGEPLYPINNANWKCFFQRSWSRLDLEEQFRCLANRLDACQETLLELYEDSNKLEDQIKHWRLENVMLFKARECGMTRVGCTAVPALTVSKAKACQAIEVQLALQTLMQSAYSTEAWTLDTCLEMWDAPPCWKKKGQSVLVKFDGSSDRDMIYTSWGFIYVQDTITDSWHKVPGVDELGLYYRVNYVDFGTESLTYRTDPRWGHGDTDSVPVIHLRGDANCLKCFRYRVQKHKDVLYARVSSTWHWYTSVEQRTEFLTRVSIPWRPNESKVYLPPT-PVKVISTDVYVTRTNVYYHGGSRLLTVGHPYYKVAVPKVSGYQYRVFHVKLPDPNKFGLPDADLYDPDQRLLWACVGVEVGRGQPLGVGVSGHPYYNRLDDTENA-HTDGRENISDYKQTQLFILGCKPPIGEHWSKGTTCGDCPPLQFTNTTIEDGDMVETGFGALDFATLQSNKSDVPLDICTNTCKYPDYLKMAAEPYGDSMFFSLRREQMFTRHFFNLGGYTSTPSGSMVSSEQQLFNKPYWLRRAQGHNNGMCWGNRVFLTVVDTTRSTNVSLYKATNFKEYLRHMEEYDLQFIFQLCKITLTPEIMAYIHNMDPQLLEDWNFGVPPPPLQDTYSQAITCPKT-P-DPYASLTFWDVDLSESFSMDLDQFPLGRKFLLQRGKRK Seq91 MADNSGTRAGGWFMVDMVDFIDQ-EVAQELLLQQAAADDDEAVHTVKRKFAPSPSPRLDAIKAKRRLFDSGYGILKASNQKATLLGKFKEQFGLGYNELVRHFKSSRTACVDWVFGVYCTVAEGIKLIQPLCEYAHIQGMTVLMLVRYKRAKNRETVAKGLLNVPESHMLIEPPKLRSSPAALYWYKTSMSNISGETPEWIVRQTMVGHFSLSEMVQWAYDHDITDEGTLAYEYALIADVDSNAAAFLASNCQAKYVKDACTMCRHYKRGEQARMSMSEWIRFRGDWKPIVHFLRYQNVEFIPFLCAFKLFLQGPKKSCLVFYGPADTGKSYFCMSLLKFMGGVVISYANSHSHFWLQPLSEAKMGLLDDATSQCWSYVDTYLRNALDGNVMCDRKHRSLLQLKCPPLLITTNVNPLEDYLRSRLQVFTFSNPCPLTSKGEPVYTLNDQNWKSFFQRLWARLSLDDEFRCLANRLDACQDKILELYEDSDKLEDQITHWRVESALYYKARECGMTRIGHQVVPTLSVAKAKACSAIEMHVALQQLQQSAYGKEPWTLDTSREMWDAVPCWKKRGVTVEVRYDGDETKAMCHVLWKDIIVQNLSDDQWVKVKGVSYEGLYYKVFYVKFHKDARVYSQNPYRHPSDPDCAPVIHLRGDPNSLKCFRYRLQNGKKGLYCKASSTWRWYTSVTQRAEFLANVKIPWRSSDNLVYLPPT-PVKVISTDDYVTRTNIYYYAGSRLLTVGHPHYKVDVPKVSAFQYRVFRVRLPDPNKFGLPDARIYNPEERLVWACTGVEVGRGQPLGVGLSGHPLYNKLNDTENSNIADSRDNIADYKQTQLCILGCTPPMGEHWGKGTVCGDCPPLELMTTHIEDGDMVDTGYGAMDFAALQVNKSDVPLDICQSTCKYPDYLGMAADPYGDSMFFFLRREQLFARHFFNRAGYSPTPSGSMVTSEAQIFNKPYWLQQAQGHNNGICWANQVFLTVVDTTRSTNMSLYDATKIKEYLRHGEEYDLQFIFQLCKVTLTPEIMAYLHTMNSALLEDWNFGLTLPPLEDTYSSAITCPT-EKQDPYAKLNFWDVDLKDRFTLDLSQFPLGRKFLLQIGKRK Seq92 MADNSGTRAGGWFIVDMVDFIDQ-EVAQELLLQQAAADDDVAVQAVKRKFTHSPSPRLDAIKAKRRLFDSGYGILKASNQRATLLGKFKEQFGLGYNELVRHFKSNRTACADWVFGVYCTVAEGIKLIQPLCDYAHIQGMTVLMLLRYKRAKNRETVAKGLLNVPESHMLIEPPKLRSGPAALYWYKTGMSNISGDTPDWIVRQTIVGHFRLSDMVQWAYDHDITDEGTLAYEYALIAEFDANAAAFLASNCQAKYVRDACTMCRHYKRGEQARMTMSEWIKFRGNWKPIVQYLRYQDVEFVPFLCALKSFLQGPKKSCLVFYGPADTGKSYFCMSLLRFMGGAVISYANSTSHFWLQPLSEAKMGLLDDATSQCWNYIDTYLRNALDGNVICDRKHRSLLQLKCPPLLITTNVNPLEDYLRSRLQVFTFKNKFPVTSSGDPLYTLNDQNWKSFFQRLWARLRLDDEFRCLASRLDACQDKMLELYEDSDKLEDQIMHWRLESVLLYKARECGMTHIGHQVVPTLSVAKAKACSAIEMHVALQQLQRSAYAHEPWTLDTSREMWDAAPCWKKRGVTVEVRYDGDETKAMCYVLWKELIVQNVSDDQWVKVAGVSYEGLYYKVFYVKFKTDARVYSQNSIRTPSDLDCAPVIHLRGDPNSLKCFRYRLKNGKKDLYCRASSTWRWYTSYTQRDEFLATVKIPWRSSDNLVYLPPT-PVKVISTDDYVTRTNVYYYAGSRLLTVGHPYFKVDVPKVSAFQYRVFRVRLPDPNKFGLPDARIYNPEERLVWACTGVEVGRGQPLGVGLSGHPLYNKLNDTENSNIADSRDNISDCKQTQLCILGCTPPMGEYWGKGTPCGDCPPLELMTSYIQDGDMVDTGYGAMDFTALQFNKSDVPLDICQSICKYPDYLGMAADPYGDSMFFFLRREQLFARHFFNRAGYSPTPSGSMVTSEAQIFNKPYWLQQAQGHNNGICWGNQVFLTVVDTTRSTNMSLYDATKIKEYLRHGEEYDLQFIFQLCKVTLTPEIMAYIHTMNTALLEDWNFGLTLPPLEDTYSSAITCPT-EKQDPYAKLNFWDVDLKDRFTLDLSQFPLGRKFLLQIGKRK Seq93 MDDTSGTRAGGWFMVDLVDFIDQ-EVAQELLLQQAAADDDVEVQTVKRKFAPSPSPRLDAIKAKRRLFDSGYGILKASNHKATLLGKFKEQFGLGFNELIRHFKSNKTVCSDWVFGVYCTLAESFKLIQPQCEYAHIQGMTVLTLVRFKRAKNRETVAKGFLNVPENHMLIEPPKLRSAPAALYWFKTSLSNCSGETPEWIVRQTVVGHFSLSEMVQYAYDHDITDESTLAYEYALQADTDANAAAFLASNCQAKYVKDACTMCRHYKRGEQARMNMSEWIKFRGDWKPIVQYLRYQDVEFIPFLCALKSFLQGPKKSCIVFYGPADTGKSYFCMSLLKFLGGVVISYANSSSHFWLQPLAEAKIGLLDDATSQCWCYIDTYLRNALDGNQVCDRKHRALLQLKCPPLLITTNINPLGDYLRSRLQVFTFNNKFPLTTQGEPLYTLNDQNWKSFFQRLWARLNLEDEFRCLANRLDVCQDKILELYEDSDKLEDQIMHWRLEQALLYKARECGLTHIGHQVVPPLSVTKAKARSAIEVHVSLQQLQHSAHAQDPWTLDTSREMWDTVPCWKKRGLTVEVRYDGDENKAMCYVQWREIIVQNYTDDNWVKVAGVSHEGLYYKTFYVKFKDDARVYCPHPIGHRSDPDCVPVIHLRGDPNCLKCFRYRLNKGKNKLYSRTSSTWRWYTSYGQREAFLSTVKVPWRSSDNLVYLPPT-PVKVLSTDDYVTRTNIYYYAGSRLLTVGHPYFKMDIPKVSAFQYRVFRVRLPDPNKFGLPDARIYNPDERLVWACTGVEVGRGLPLGVGLSGHPLYNKLDDTENSNIADSRDNISDNKQTQLCIVGCTPPMGEHWGKGTPCGDCPPLELITAPIQDGDMVDTGYGAMDFGNLQSNKSDVPLDICQTTCKYPDYLGMAAEPYGDSMFFYLRKEQLFARHFLNRAGYCPTPSGSMVTSETQLFNKPYWLRRAQGHNNGICWANQLFVTVVDTTRSTNMTLYDATKFKEYLRHGEEYDLQFIFQLCKVTLTPEIMAYLHTMNSTLLEDWNFGLTLPPLEDTYSSAITCPT-EKQDPYAKLNFWDVDLKDRFSLDLSQFPLGRKFLMQLGKRK Seq94 MDDTSGTRAGGWFMVDFVDFIDQ-EVAQELLLQQAAADDDVAVQAVKRKFAPSPSPRLDAITAKRRLFDSGYGILRASNQKATLLGKFKEQFGLGFNELIRHFKSSKTVCLDWVFGVYCTLAEGIKLIQPQCDYAHIQGMTVLMLVRYKRAKNRETVAKGLLNVPESHMLIEPPKLRSGPAALYWYKTAMSNCSGETPEWIVRQTMVGHFSLSEMVQYAYDHDITDESMLAFEYALLADTDANAAAFLSSNCQAKYVKDACTMCRHYKRGEQARMNMSEWIWFRGDWKPIVQFLRYHDVEFIPFLCAFKTFLQGPKKSCLVFYGPADTGKSYFCMSLLRFLGGVVISYANSNSHFWLQPLADAKIGLLDDATSQCWCYIDTYLRNALDGNQVCDRKHRALLQLKCPPLLITTNINPLEDYLRSRVQLFTFKNKFPLTTQGEPLYTLNDQNWKCFFRRLWARLSLDDEFRCLANRLDVCQDKMLELYEDSNKLEDQIMHWRVENALLYKARECGLTHIGHQVVPPLSVTKAKARSAIEVHVALLQLQESAYAQDSWTLDTSREMWDTVPCWKKRGVTVEVRYDGDETKSMCYVHWRDIFTQNYSDDKWVKVAGVSYEGLYYQTFYVKFKDDAYVYCPYTVGHPSDPDCAPVVHLKGDPNCLKCFRYRLHKGKRKLYCKTSSTWRWYTSYSQRNEFLSTVKVPWRSSDNLVYLPPT-PVKVLSTDDYVTRTNIYYYAGTRLLTVGHPYFKADVPKVSAFQYRVFRVRLPDPNKFGLPDARIYNPDERLVWACTGVEVGRGQPLGVGLSGHPLYNKLDDTENSNIADSRDNISDNKQTQLCIVGCTPPMGEHWGKGTPCGDCPPLELITAPIQDGDMVDTGFGAMDFAVLQANKSDVPLDICQSTCKYPDYLGMAAEPYGDSMFFYLRKEQLFARHFFNRAGYSPTPSGSMISSEAQLFNKPYWLRRAQGHNNGICWANQLFVTVVDTTRSTNMTLYDASKFKEYLRHGEEYDLQFIFQLCKVTLTPDIMAYLHTMNNSLLEDWNFGLTLPPLEDTYSSAITCPTT-KEDPYAKLNFWEVDLKDRFSLDLSQFPLGRKFLMQLGKRK Seq95 MDDNTGTRAGGWFIVDFVDFIDQ-EVAQELFQQQTAADDDVAVQTVKRKFAPSPSPRLDAIKAKRRLFDSGYGILRASNKKATLLGKFKEQFGLGYNELIRHFKSDRTSCADWVFGVFCTVAEGIKLIQPLCDYAHIQGMTVLMLVRYKRAKNRETVAKGLLNVPESQMLIEPPKLRSGPAALYWYKTSMSSCSGETPEWIVRQTMVGHFSLSEMVQWAYDHDITDESTLAYEYALIADTDSNAAAFLSSNCQAKYLKDACTMCRHYKRGEQARMSMSEWIWFRGDWKPIVQFLRYQDVEFIPFLCAFKTFLQGPKKSCLVFYGPADTGKSYFCMSLLRFLGGAVISYANSSSHFWLQPLSEAKIGLLDDATSQCWNYIDTYLRNALDGNQICDRKHRALLQLKCPPLLITTNINPLTDFLRSRLQLFTFKNPFPVTTQGEPMYTLNDQNWKCFFRRLWARLSLEDEFRCLANRLDACQDKMLELYEDSDKLEDQITHWRVENALLYKARECGLTHIGHQVVPPLSVTKAKARNAIEVHVALQQLQESAYAHEPWTLDTSREMWDTAPCWKKRGITVEVRYDGDESKAMCYVQWRELYVQNYSDDRWVKVPGVSYEGLYYNIYYVNFKDDACVYSAHPVRHPSDPDCAPVIHLRGDPNSLKCFRYRLHHGKRKLYSRSSSTWRWYTSDTQRTEFLNVVKVPWRSSDNLVYLPPT-PVKVLSTDDYVTRTNIYYYAGTRLLTVGHPYFKVDVPKVSAFQYRVFRVRLPDPNKFGLPDARIYNPDERLVWACTGVEVGRGQPLGVGLSGHPLYNKLEDTENSNIADSRDNISDNKQTQLCIIGCTPPMGEHWGKGTPCGDCPPLELITSPIQDGDMVDTGYGAMDFTALQLNKSDVPIDICQSTCKYPDYLGMAAEPYGDSMFFYLRREQLFARHFFNRASYSPTPSGSMVTSEAQLFNKPYWLRRAQGHNNGICWANQLFVTVVDTTRSTNMCLYDATKFKEYLRHGEEYDLQFIFQLCKVTLTPDIMAYLHTMNSSLLEDWNFGLTLPPLEDTYSSAITCPT-EKQDPYAKLNFWDVDLKDRFSLDLSQFPLGRKFLLQLGKRK Seq96 MDDNTGTRAGGWFIVDCVDFIDQ-EVARELFLQQAAADDDIAVQTVKRKFAPSPSPRLDAIKAKRRLFDSGYGILKASNHKATLLGKFKEQFGLGYNELIRHFKSDRTACVDWVFGVYCTVAEGIKLIQPLCDYAHIQGMTVFMLVRYKRAKNRETVAKGLLNVPESQMLIEPPKLRSGPAALYWYKTSMSSCSGETPEWIVRQTMVGHFTLSEMIQWAYDHDITDESTLAYEYALIADTDANAAAFLASNCQAKYLKDACTMCRHYKRGEQARMSMSEWIRFRGDWKPIVQFLRYQDVEFIPFLCAFKTFLQGPKKSCIVFYGPADTGKSYFCMSLLRFLGGAVISYANSSSHFWLQPLSEAKIGLLDDATTQCWNYVDTYLRNALDGNQVCDRKHRALLQLKCPPLLITTNVNPLADYLRSRLQLFTFKNPFPVTAQGEPLYTLNDQNWKCFFRRLWARLSLEDEFRCLANRLDACQDKMLELYEDSNKLEDQITHWRVENALLYKARECGLTHIGHQVVPPLSVTKAKARNAIEVHVALQQLQDSAYAHESWTLDTSREMWDAAPCWKKRGITVEVRYDGDESKAMCYVQWRDIFVQNYSDDRWVKVSGVSHEGLYYNIFYANFKDDAFVYRAFPVWPPSDPDCAPVIHLRGDPNCLKCFRYRLHHGKRKLYSRSTSTWRWYTSEAQRAEFLNVVKVPWRPSDNLVYLPPT-PVKVLSTDDYVTRTNIYYYAGTRLLTVGHPYFKVDVPKVSAYQYRVFRVRLPDPNKFGLPDARIYNPDERLVWACTGVEIGRGLPLGVGLSGHPLYNKLDDTENSNIADSRDNISDNKQTQLCILGCTPPMGEHWGKGTPCGDCPPLELVTSVIQDGDMVDTGYGAMDFTALQLNKSDVPIDICQSTCKYPDYLGMAAEPYGDSMFFYLRREQLFARHFFNRASYSPTPSGSMVTSEAQLFNKPYWLKRAQGHNNGICWGNQMFVTVVDTTRSTNLSLYDATKFKEFLRHGEEYDLQFIFQLCKVTLTPEIMAYLHTMNSSLLEDWNFGLTLPPLEDTYSSAITCPT-EKQDPYAKLNFWDVDLKDRFTLDLSQFPLGRKFLLQLGKRK Seq97 MADPEGTGCNGWFYVDMVDFIDELETAQALFHAQEVHNDAQVLHVLKRKFAGGSSPRLQEIKAKRRLFDSGYGLLKVNNKQGAMLAVFKDTYGLSFTDLVRNFKSDKTTCTDWVFGVNPTIAEGFKLIQPFILYAHIQGVLILALLRYKCGKSRLTVAKGLLHVPETCMLIQPPKLRSSVAALYWYRTGISNISGDTPEWIQRLTIIQHFDLSEMVQWAFDNELTDESDMAFEYALLADSNSNAAAFLKSNCQAKYLKDCATMCKHYRRAQKRQMNMSQWIRFRGDWRPIVQFLRYQQIEFITFLGALKSFLKGPKKNCLVFCGPANTGKSYFGMSFIHFIQGAVISFVNSTSHFWLEPLTDTKVAMLDDATTTCWTYFDTYMRNALDGNPISDRKHKPLIQLKCPPILLTTNIHPAKDYLESRITVFEFPNAFPFDKNGNPVYEINDKNWKCFFERTWSRLDLEEDFKLLSERLSCVQDKIIDHYEDSKDIDSQIQYWRWENAIFFAAREHGIQTLNHQVVPAYNISKSKAHKAIELQMALQGLAQSRYKTEDWTLDTCEELWNTEPCFKKGGQTVQVYFDGNKDNCMTYVAWDSVYYM-TDAGTWDKTATVSHRGLYYNTFYIEFKSECEKY-NNKRRKLCSGNTTPIIHLKGDRNSLKCLRYRLRKHSDH-YRDISSTWHWYHSETQRTKFLNTVAIPWRPSDNTVYLPPP-SVRVVNTDDYVTPTSIFYHAGSRLLTVGNPYFKQDIPKVSAYQYRVFRVQLPDPNKFGLPDTSIYNPEQRLVWACAGVEIGRGQPLGVGLSGHPFYNKLDDTESSHAADVRDNVSDYKQTQLCILGCAPAIGEHWAKGTACGDCPPLELKNTVLEDGDMVDTGYGAMDFSTLQDTKCEVPLDICQSICKYPDYLQMSADPYGDSMFFCLRREQLFARHFWNRAGYSPSPSGSIVTSDSQLFNKPYWLHKAQGHNNGVCWHNQLFVTVVDTTPSTNLTIYDATKFKQYSRHVEEYDLQFIFQLCTITLTADVMSYIHSMNSSILEDWNFGVPPPPLVDTYSVAITCPA-E-NDPYDKLKFWNVDLKEKFSLDLDQYPLGRKFLVQAGKRV Seq98 MADPEGTGCNGWFFVDMVDFIDEQETAQALFHAQEVQNDAQVLHLLKRKFAGGSSPRLQEIKAKRRLFDSGYGLLQASNKKAAMLAVFKDIYGLSFTDLVRNFKSDKTTCTDWVFGVNPTVAEGFKLIKPATLYAHIQGVLILALLRYKCGKNRLTVAKGLLHVPETCMLIEPPKLRSSVAALYWYRTGISNISGDTPEWIQRLTIIQHFDLSDMVQWAFDNDLTDESDMAFQYAQLADCNSNAAAFLKSNCQAKYLKDCAVMCRHYKRAQKRQMNMSQWIKYRGDWRPIVQFLRYQGVEFISFLRALKEFLKGPKKNCILLYGPANTGKSYFGMSFIHFLQGAIISFVNSNSHFWLEPLADTKVAMLDDATHTCWTYFDNYMRNALDGNPISDRKHKPLLQLKCPPILLTSNIDPAKDYLESRVTVFTFPHAFPFDKNGNPVYEINDKNWKCFFERTWSRLDLDEDFKCLSERLSALQDKILDHYEDSKDINSQISYWRLENAILFTAREHGITKLNHQVVPPINISKSKAHKAIELQMALKGLAQSKYNNEEWTLDTCEELWNTEPCFKKGGKTVHVYFDGNKDNCMNYVVWDSIYYI-TETGIWDKTAAVSYWGVYYTTYYVQFKSECEKY-NNKRRKVCSGNTTPIIHLKGDKNSLKCLRYRLRKYADH-YSEISSTWHWYNSEVQRNTFLDVVTIPWRPSDSTVYLPPP-SVRVVSTDDYVSRTSIFYHAGSRLLTVGNPYFKQAVPKVSAYQYRVFRVALPDPNKFGLPDSTIYNPEQRLVWACVGMEIGRGQPLGIGLSGHPFYNKLDDTESAHAADVRDNVSDYKQTQLCILGCVPAIGEHWAKGTLCGDCPPLELKNTIIEDGDMVDTGYGAMDFSTLQDTKCEVPLDICQSICKYPDYLQMSADPYGDSMFFCLRREQLFARHFWNRAGYSPSPSGSIITSDSQLFNKPYWLHKAQGHNNGICWHNQLFVTVVDTTRSTNLTLYDPTKFKQYSRHVEEYDLQFIFQLCTITLTAEVMSYIHSMNSSILENWNFGVPPPPLVDTYSVAVTCPP-EKQDPYDKLKFWTVDLKEKFSSDLDQYPLGRKFLVQAGKRV Seq99 MEDSQGTGCNGWFYVDMVDFIDELETAQALFHAQEVDNDAQVLHVLKRKYGTESSPRLQEIKAKRRLFDSGYGLLKANNKKAAMLAVFKETYGLSFADLVRTFKSDKTTCTDWVFGVNPTIAEGFKLIQPCTLYAHIQGVLILALLRYKCGKNRLTVAKGLLHVPETCMLIEPPKLRSSVAALYWYRTGISNISGDTPEWIQRLTIIQHFDLSEMIQWAFDNDFTDESDIAYEYAQLADCNSNAAAFLKSNCQAKYLRDCAVMCRHYKRAQKRQMNMSQWIKYRGDWRPIVQFLRFQGIEFITFLGALKAFLKGPKKNCIVIHGPANTGKSYFGMSFIHFIQGAIISFVNSNSHFWLEPLADAKVAMLDDATNTCWTYFDNYMRNALDGNPISDRKHKPLLQLKCPPILLTSNINPAIDYLESRVTVFTFPNAFPFDKNGNPVYEINDKNWKCFFERTWSRLDLDDDFKCLSERLSVLQDKILDHYEDSKDIHSQINYWRLENAIFFAAREHGIQTLNHQVVPAFNISKNKAYKAIELQMALKGLAQSQYNTEEWTLDTCEELWNTEPCFKKSGQTVEVYYDCNKDNCMSYVAWKCVYYM-TEAGTWDKTEAVSHWGLYYKTFYVQFEHESKKYGSNKRRKLCSGNTTPIIHLKGDKNSLKCLRYRFKKYNQ-YYSSISSTWHWYDSEHQRTKFLDSVPIPWRPSDSTVYLPPP-SVRVVNTDDYVSRTSIFYHAGSRLLAVGNPYFRQDVPKVSAYQYRVFRVTLPDPNKFGLPDSTIYNPEQRLVWACVGVEIGRGQPLGIGLSGHPLYNKLDDTESSHAADVRDNVSDYKQTQLCILGCVPAIGEHWAKGTPCGDCPPLELKNTVLEDGDMVDTGYGAMDFSTLQDTKCEVPLDICQSICKYPDYLQMSNDPYGDSMFFCLRREQLFARHFWNRAGYSPSPSGSIINTESQLFNKPYWLHRAQGHNNGICWHNQLFVTVVDTTRSTNLTLYDPTKYKQYSRHVEEYDLQFIFQLCTITLSADVMSYIHSMNSSILENWNFGVPPPPLVDTYSVAITCPA-EK-DPYDNLKFWNVDLKERFSLDLDQYPLGRKFLVQSGKRL Seq100 MADSEGTGCNGWFFVDLVDFIDERETAQALFNVQEAQRDAREMHVLKRKFGCS-SP-LQEIKVKRRLIDSGYGLLHSKNKKAAMYAKFKELYGLSFQDLVRTFKSDRTTCSDWVFGVNPTVAEGFKLIQPYVLYAHIQGVVILALLRYKCGKNRITVAKGLLHVPDTCMLIEPPKLRSGVAALYWYRTGMSNISGETPEWIQRLTIIQHFDLSEMIQWAFDNDLTDESDIAYEYALIADSNSNAAAFLKSNCQAKYLKDCAVMCRHYKRAQKRQMSMSQWIKWRGDWKPIVQFLRYQGVEFITFLCALKDFLKGPKRNCIVLCGPANTGKSYFGMSLLHFLQGTVISHVNSNSHFWLEPLTDRKLAMLDDATDSCWTYFDTYMRNALDGNPISDRKHRHLVQIKCPPMLITSNTNPVTDYLNSRLMVFKFPNKLPFDKNRNPVYTINDRNWKCFFERTWCRLDLEEDFKCLSQRLSVLQDQILEHYEDSKDINEHINYWRMENVILFAARENNIHTLNHQVVPTFLVSKNKACEAIELQSNRTSTVMPCFLKHFLGACHSSWHVSCIVSFLNSVCAKLSNAICSKENTMHYTSWTFIYYVN-DVGQWCKTTGVDFWGLYYQVYYVKFIHDAKKY-NNPRRHIPCSNTTPIIHLKGDKNGLKCLRYRLRKVHW-LFENISSTWHWYTSETQRNEFLDTVKIPWRSSDNKVYLPPP-SVKVVSTDEYVTRTSIFYHAGSRLLTVGHPYFRQDVPKVSAYQYRVFRVKLPDPNKFGLPDNTVYDPNQRLVWACVGVEIGRGQPLGVGLSGHPLYNKLDDTENSHVADTRDNVSDYKQTQLCIIGCVPAIGEHWTKGTACGDCPPLELINTPIEDGDMVDTGYGAMDFKLLQDNKSEVPLDICQSICKYPDYLQMSADAYGDSMFFCLRREQVFARHFWNRSGYSPSPSGSVVTSDSQLFNKPYWLHKAQGLNNGICWHNQLFLTVVDTTRSTNLSVYTPTSFKEYARHVEEFDLQFIFQLCKITLTTEVMSYIHNMNTTILEDWNFGVTPPPLVDTYSAAVTCPP-VKQDPYDKLKFWPVDLKERFSADLDQFPLGRKFLLQLGRVK Seq101 MANCEGTGCNGWFFVDMVDFIDERETAQVLLNMQEAQRDAQRVRALKRKYTDS-SP-LQELQARQPAYDSGYGLLQCNNKKAAMLTEFKKVYGLSFNDLVRTFKSDKTTCTDWVFGVNPTIAEGFKLIKQYALYTHIQGILILMLIRYKCGKNRITVGKGLLHVPDSCMLLQPPKLRSPVAALYWYRTGISNISGDTPEWIKRLTIIQHFDLSDMVQWAFDNELTDDSDIAFQYAMLADCNSNAAAFLKSNCQAKYVKDCATMCRHYKRAQKRQMTMPQWIKFRGDWRPIVQFLRYQGLEFITFLCALKDFLKGPKRNCIVIHGPPNTGKSYFCMSLIHFLQGTIISYVNSASHFWLEPLADAKIAMLDDATGTCWSYFDNYMRNALDGNPISDRKHRHLIQIKCPPMLITSNTNPVEDYLHSRLTVFKFPNAFPFDQNRNPVYTINDKNWKCFFEKTWCRLDLEDEFKCLSQRLNVLQEKILEHYEDSKCIQDHINYWRLENAIYYAARERGMHNIDHQVVPPVNISKTKAYQAIELQMALESLAKTAYSAEEWTLDTSNELWHTKPCFKKHGVTVEVWYDGDKSNSMHYVVWGTIYFKN-STDTWCKTQGVDYWGVYYKTYYERFMQDAQLYGQNKRRSLCCGDTTPIVHLKGDKNGLKCLRYRLQKHNA-LYDNISCTWHWYVSEAQRDKFLETVKLPWRASDNMVYLPPP-SVKVVNTDDYVTRTGMYYYAGTRLLTVGHPYFKQGIPKVSAYQYRVFRVTLPDPNKFSVPESTLYNPDQRMVWACVGVEIGRGQPLGVGLSGHPLYNRLDDTENSPFSDSRDNVADCKQTQLCIIGCVPAIGEHWAKGKSCGDCPPLELVNTPIEDGDMIDTGYGAMDFGTLQETKSEVPLDICQSVCKYPDYLQMSADVYGDSMFFCLRREQLFARHFWNRGGYAPSPSGSMVSSDSQLFNKPYWLHKAQGHNNGICWHNQLFLTVVDTTRSTNFTLYDSNKFKEYVRHVEEYDLQFIFQLCTITLSTDVMSYIHTMNPAILDDWNFGVAPPPLVDTYSAAITCAP-VK-DPYDGLNFWNVDLKEKFSSELDQFPLGRKFLLQAGHK- Seq102 MANCEGTGCNGWFLVDLADFIDERETAQVLYNMQEAQRDAQSVRALKRKYGGSNRVTLQELQARTNVYDSGYGVLQANNQKAILLSQFKHTYGLAFNDLVRTFKSDKTICTDWVCGVNPTIAEGFKLIQPYALYTHIQGVYILLLIRYKCGKNRITVGKGLLHVPESCMLIEPPKLRSPVAALYWYRTGMSNISGTTPEWIQRLTVIQHFDLSDMVQWAFDNDVTEDSDIAYGYALLADSNSNAAAFLKSNCQAKYVRDCATMCRHYKRAQKKQMTMAQWIRFRGDWRPIVQFLRYQGVEFITFLCAFKEFLKGPKKNCIVIQGPPNTGKSYFCMSLMHFLQGTVISYVNSTSHFWLEPLADAKVAMLDDATGTCWSYFDTYMRNALDGNPISDRKHRHLIQIKCPPILITSNTNPVEEYLTSRLTVFTFPNAFPFDQNRNPVYTINNKNWKSFFQKTWCKLDLEDEFKCLSQRLNALQEKILEHYEDSKLIYDQINYWRLENAIFYAARERGMHTIDHQVVPPGTTSKAKAYQAIELQMALESLAQTDFNKEEWTLDTSNEMWQTKPCFKKKGVTVEVWYDGNKDNSMHYVVWGAIYYK-THTDTWCKTEGVDYWGIYYKTYYEVFKQDAQMYGCNKRRHQCCGDTTPIVHLKGDKNGLKCLRYRLRKFNS-LYENISCTWHWYTTEAQRQKFLETVRIPWRSSDNTVYLPPP-SVKVVNTDDYVTRTGIYYYAGSRLLTVGHPYFKQEIPKVSAYQYRVFRVSLPDPNKFGLPDPSLYNPDQRLVWACIGVEIGRGQPLGVGVSGHPLYNRLDDTENSHFSDSRDNVSDYKQTQLCIIGCVPAMGEHWAKGKACGDCPPLELVNTAIEDGDMIDTGYGAMDFRTLQETKSEVPLDICQSVCKYPDYLQMSADVYGDSMFFCLRKEQLFARHFWNRGGYSPSPSGSMVSSDSQLFNKPYWLHKAQGHNNGICWHNQLFITVVDTTRSTNFTLYSPTKFKEYTRHVEEYDLQFIFQLCTITLTADVMAYIHTMNPAILDNWNIGVTPPPLVDTYSAAIACTP-EK-DPYDDLKFWNVDLKEKFSTELDQFPLGRKFLLQVGKHK Seq103 MANREGTGCNGWFLVDLADFIDERETAQVLLHMQEAQRDAQAVRALKRKYTDSSRGTLQEIQATQTVYDSGYGLLQSNNKKAAMLTQFKETYGLSFTDLVRTFKSDKTTCTDWVFGVHPTIAEGFKLINKYALYTHIQGVLILMLIRYTCGKNRVTVGKGLLHVPESCMLLEPPKLRSPVAALYWYRTGISNISGDTPEWIQRLTVIQHFDLSDMVQWAFDNEYTDESDIAFNYAMLADCNSNAAAFLKSNCQAKYVKDCATMCKHYKRAQKRQMSMSQWIKFRGDWRPIVQFLRYQGIEFISFLCALKEFLKGPKKNCIVIYGPANTGKSHFCMSLMHFLQGTVISYVNSTSHFWLEPLADAKLAMLDDATGTCWSYFDNYMRNALDGYAISDRKYKSLLQMKCPPLLITSNTNPVEDYLRSRLTVFKFPNAFPFDQNRNPVYTINDKNWKCFFEKTWCRLDLEDEFKCLSQRLNVLQDKILEYYEDSKSIYDQINYWRMENAIFYAARERGMHTIDHQVVPTINISKCKAYQAIELQMALESVAQTEYNTEEWTLDTSNELWHTQPCFKKQGTTVEVWYDGDKCNAMNYVLWGAIYYKN-NIDIWCKTEGVDYWGIYYKVYYEVFIQDAERYGHNTRRYLSCGNTTPIIHLKGDKNGLKCLRYRLQKYDT-LFENISCTWHWYATESQRQKFLDTVKIPWRSSDSMVYLPPP-SVKVVNTDDYVTRTGIYYYAGSRLLTVGHPYFKQDIPKVSAYQYRVFRVTLPDPNKFSIPDASLYNPEQRLVWACVGVEVGRGQPLGVGISGHPLYNRQDDTENSPFSDSRDNVSDYKQTQLCIIGCVPAIGEHWGKGKACGDCPPLELVNTPIEDGDMIDTGYGAMDFGALQETKSEVPLDICQSICKYPDYLQMSADVYGDSMFFCLRREQLFARHFWNRGGYCPSPSGSMVTSDSQLFNKPYWLHKAQGHNNGICWHNQLFLTVVDTTRSTNFTLYDPSKFKEYTRHVEEYDLQFIFQLCTVTLTTDVMSYIHTMNSSILDNWNFAVAPPPLVDTYSAAITCAP-EK-DPYDGLKFWNVDLREKFSLELDQFPLGRKFLLQARKHK Seq104 MADPEGTGCNGWFFVDLVDFIDDREAAQALLHAQEVETDTKLLHALKRKYGAHSSSPLQEITAKRRLCDSGYGLLKVNNKKAAILAKFKETYGLSFTDLVRTFKSDKTTCTDWVCGVNPNIAEGFKLIQPYVLYAHIQGVFILALLRYKCGKNRLTVAKGLLHVPDTHMLIEPPKLRSSCAALYWYRTGISNISGDTPEWIQRQTIIQHFDLSEMIQWAFDNDYIDESDIAYEYAQLADCNSNAAAFLKSNCQAKYLRDCAVMCRHYKRAQRKQMNMSQWISYRGDWKPIVQFLRFQGIEFITFLRAFKDFLKGPKKNCIVIYGPANTGKSYFCMSLIQFLHGTVLSFVNSNSHFWLEPLTDTKIAMVDDATPTCWSYFDNYMRNALDGNPISDRKHKHLIQMKCPPMLITSNTNPATDYLRSRVTVFTFPHTFPFDSNGNPVYDINDKNWKCFFKRTWSRLDLEEDFKCLSQRLNVLQEKILEHYEDSTDICDQIDYWRLENAIYYAAREHGLKTINHHVVPTFQISKSKAHEAIELQMALESLAKSEFKNELWTLDTCQELYQTPPCFKKQGQTVEVRYDGDKDNTMHYTSWDYIYYV-TEGDKWCKTKGVNYCGLYYQTYYVQFKCDAQQYGNNGFRKHNSGDTTPIVHLKGDKNRLKCLRYRLQKFHN-LYTQISCTWHWYANETQRQKFLDVVKIPWRSSDSKVYLPPP-SVKVVNTDDYVTRTSTFYHAGSRLLTVGHPYYKQDIPKVSAYQYRVFRVTLPDPNKFGLPDTNIYNPEQRLVWACVGMEVGRGQPLGVSLSGHPFYNKLDDTENSHVADTRDNVSDYKQTQLCIIGCVPAIGEHWAKGTACGDCPPLELVNTPIEDGDMIDTGYGAMDFSTLQDNKSEVPLDICQSICKYPDYLQMSADAYGDSMFFCLRREQLFARHFWNRGGYSPSPSGSMVSSDAQMFNKPYWLHKAQGQNNGICWHNQLFITVVDTTRSTNLTLYEPSKFKEYTRHVEEYDLQFIFQLCKITLTTDVMSYIHNMDPTILDSWNFGVSPPPLVDTYSSAITCVP-QK-DPYEKLKFWNVDLKEHFSSDLDQFPLGRKFLLQAGKRK Seq105 M-DCEGTGCTGWFSVDLIGFIDQ-EVTQALFQAQQKQANTKAVRNLKRKLLGS-SDSQQNT-AKRRAVDSGYGLLKCSNVKAALLSKFKTVYGVSFAELVRVFKSDKTCCSDWVFGVAGSVAESIKLIQQYCLYYHIQGVIVLMLVRFTCAKNRTTIKNCLLNVPETQLLIEPPKLRSTAVALYFYKTGLSNISGDTPEWIVRQTQLEHFDLSKMVQWAFDHDITDDSEIAFKYAQLADIDSNAAAFLKSNCQAKYVKDCATMTRHYKRAQKRSMCMSQWLQYRGSWKEIAKFLRFQHVNFIYFLQVLKQFLKGPKHNCIVIYGPPNTGKSQFAMSFIKFMQGSVISYVNSNSHFWLQPLEDAKVAVLDDATYSCWLYIDKYLRNFLDGNPCCDRKHRSLLQVTCPPLIITSNINPQEDYLHSRVTVIPFPNTFPFDSNGNPVYALTDVNWKSFFSTTWSRLDLDADFKCLCQRLNACQEKILDYYEDSNKLTDQIDYWRYECAIFYKAREGNMQCINHQVVPSTVVCKQKAWQAIEIHIALQSLINTDYNTEAWTMDTSYEMYMTEPCFKKEGTTVTVVFDCNKENTMDYIRWKYVYYK-TD-IGWCKGTGVDAKGIYYKQYYVDFKQEAEKYGHHPGRDTSSDQTVFIVHLKGDTNSLKCLRYRFKKHKG-LYCNVSSTWHWFNSITQRNNFLTTVKIPWRTSDSKVYLPPT-PVRVVNTDEYVTRTGIYYYAGSRLLTLGHPYFKAEIPKVSAYQYRVFRVHLPDPNKFGLPDPQLYNPDERLVWACVGVEVGRGQPLGIGLSGHPLFNKLDDTENSHLADNRDNVSDNKQTQLCIIGCTPPLGEHWGIGTICGDCPPLELISSIIEDGDMIDTGFGAMDFTALQATKSDVPIDISQSTCKYPDYLKMSADTYGNSMFFFLRREQLFARHFYNKAGYSATPSGSMVTSDAQLFNKPYWLQRAQGHNNGICWGNQLFVTCVDTTRSTNLTIFKPSDYKQFIRHGEEYELQFIFQLCKITLTTDVMAYIHLMNASILEDWNFGLTLPPLEDAYNSATTCPV-PKEDPFQKFKFWDVDLKEKFSIDLDQFPLGRKFMLQAGKRK Seq106 M-DCEGTGCTGWFSVDLIGFIDQ-QVAQALFQAQETQANKKAVRALKRKLLGS-SNSQQST-AKRRAVDSGYGLLKCSNVKAALLSKFKTVYGVSYTELVRVFKSDKTCCSDWVFGVAGSVAESLKLIQPYCLYYHIQGVLPLMLIRFTCAKNRATIKKCLLNVPDTQLLIEPPKLRSTAVALYFYKTGLSNISGDTPEWIVRQTQLEHFDLSKMVQWAFDHDITDDSEIAFKYAQLADIESNAAAFLKSNCQAKYVKDCATMTRHYKRAQKRSMGMSQWLQHRGTWKDIARFLRYQNVNFIYFLQVLKQFLKGPKHNCIVIYGPPNTGKSQFAMSFIKFVQGSVISYVNSNSHFWLQPLEDAKVALLDDATYGCWLYIDKYLRNFLDGNPCCDRKHRSLIQVRCPPLIITSNINPQDDYLHSRVTVIPFPNTFPFDSNGNPVYELTDVNWKSFFSTTWSRLDLDADFKCLCQRLNACQEKILDYYEDSDKLSDQIDYWRYECAIFYKAREGNMQCINHQVVPSTTVCKEKAWQAIELHIALQSLMNSEYGKEKWTMDTCYELYVTEPCFKKEGTTVTVVFDCNKENTMDYIRWTSVYYK-TD-MGWCKTNGVDYKGIYYKQYYVDFKQEALKYSNNPGRGTCSDQTVFIVHLKGDTNCLKCLRYRFKKHKG-LYCKVSSTWHWFDSETQRASFLTTVKIPRRTSDSKVYLPPT-PVRVVRRMNMYTHR-IYYYAGSRLLTLGHPYFTAEIPKVSAYQYRVFRVHLPDPNKFGLPDPQLYNPEERLVWACVGVEVGRGQPLGVGLSGHPLFNKLDDTENSHLADNRDNVCDNKQTQLCIIGCTPPLGEHWGVGTVCGDCPPLELISSVIEDGDMIDTGFGAMDFTALQATKCDVPLDINQSICKYPDYLKMSADTYGNSMFFFLRREQLFARHFFNKAGYSRTPSGSMVTSDAQLFNKPYWLQRAQGHNNGICWGNQLFVTCVDTTRSTNLTIFKPSDYKQFIRHGEEYELQFIFQLCKITLTTDVMAYIHTMNSTILENWNFGLTLPPLEDAYNSATTCAQ-PKEDPFSKLKFWDVDLKEKFSIDLDQFPLGRKFMLQAGTRK Seq107 M-DCEGTGCNGWFFVDLINFIDEQETARALFQAQELQANKEAVHQLKRKFLVSPNNTH-SH-VKRRLLDSGYGVLKSSNAKATLMAKFKELYGISYNELVRVFKSDKTCCIDWVFGVSPMVAENLKLIKPFCMYYHIQGTIVLMLIRFSCAKNRTTIAKCLVNIPQSQMFIEPPKLRSTPVALYFYRTGISNISGETPEWITRQTQLQHFELSQMVQWAFDHEVLDDSEIAFHYAQLADIDSNAAAFLKSNCQAKYVKDCGTMARHYKRAQRKSLSMSAWIRYRGNWREIAKFLRYQGVNFMSFIQMFKQFLKGPKHNCIVIYGPPNTGKSLFAMSLMKFMQGSIISYVNSGSHFWLQPLEDAKIALLDDATYGCWTYIDQYLRNFLDGNPCSDRKHRSLIQLVCPPLLITSNINPQEDYLHTRVTVLKFLNTFPFDNNGNAVYTLNDENWKNFFSTTWSRLDLEEDFKCLCHRLNVCQEKILDCYEDSDKLVDQINYWRYEAAMFYAARERNLRTINHQVVPATTVSKQKACQAIEMHMALQSLNKSDYNMEPWTMETCYELWCVAPCFKKGGITVTVIFDGNKDNAMDYTSWKFIYIYD-N-DKWVKTNGVDYTGIYYKEYYVQFKDEAKIYTNTGGHQSAT-QTAFIVHLKGDTNCLKCFRYRFTKHKG-LYKNVSSTWHWFDSAHQRETFIKTIKVPWRTNDSKVYLPPA-PVRIVNTEEYITRTGIYYYAGSRLITLGHPYFRAAIPKVSAFQYRVFRVQLPDPNKFGLPDPNLYNPDDRLVWGCVGVEVGRGQPLGVGLSGHPLFNKYDDTENSRIADVRDNTSDNKQTQLCIIGCAPPIGEHWGIGTTCGDCPPLELVSSVIQDGDMIDTGFGAMDFAALQATKSDVPLDISQSVCKYPDYLKMSADTYGNSMFFHLRREQIFARHYYNKLVYSATPSGSMITSDSQIFNKPYWLHRAQGHNNGICWNNQLFITCVDTTRSTNLTIFTPSNFKQYIRHGEEYELQFIFQLCKITLTTEVMAYLHTMDPTILEQWNFGLTLPPLEDAYNAATSCPQ-AK-DPLAKYKFWDVDLKERFSLDLDQFALGRKFLLQVGKRK Seq108 M-DSEGTGCTGWFYVDIIDFIDERETAQALLQVQETQAHKEAVQHLKRKFLGSPSNSQQQP-GKRRLLDSGYGVLKCSNAKAMFMAKFKELYGVSYNELVRVFKSDKTCCTDWVFGVSPMVAENLKLIQPFCMYYHIQGTIVLLLARFTCAKNRLTIAKCLVNIPQSQMFIEPPKLRSTAVALYFYRTGISNISGETPEWITRQTQLQHFELSQMVQWAFDHDVVDDSEIAFYYAQLADTDSNAAAFLKSNCQAKYVKDCGTMTRHYKRAQRKSLTMSAWIRYRGNWREIAKFLRYQGINFMYFIQTFKLFLKGPKHNCIVIQGPPNTGKSQFAMSLIRFLQGCVISYVNSGSHFWLQPLEDAKVALLDDATYGCWTYIDQYLRNFLNGNPCSDRKHRSLLQIVCPPLLITSNINPKEDYLHSRVTVFQFLNAFPFDPHGNPVYALNDVNWKNFFSTTWSRLDLEEDFKCLCHRLNVCQEKILDCYEDSDKLVDQINYWRYECAMFYTARERNMQTLNHQVVPASAVSKQKACQAIEMHMALESLNKSEYNMEPWTMDTCYELWGEAPCFKKGGKTVTVMFDGNKDNTMDYTCWTYVYIYK-E-DRWVKTQGVDYTGIYYKEYYVTFKDEAKKYPNTGGHLSAT-KTAFIVHLKGATNCLKCLRYRFAKHRN-LFKEVSSTWHWFDSAHQRQKFIDTVKVPWRTNDSKVYLPPA-PVRIVNTEEYITRTGIYYYAGSRLITLGHPYFRAEIPKVSAFQYRVFRVQLPDPNKFGLPDPNLFNPDDRLVWGCVGVEVGRGQPLGVGLSGHPLFNKYDDTENSRFADVRDNISDNKQTQLCIIGCAPPIGEHWATGTTCGDCPPLELVSTVIEDGDMVDTGFGAMDFANLQATKSDVPLDIAQSVCKYPDYLKMSADTYGNSMFFHLRREQIFARHYYNKAGYSATPSGSMITSDSQIFNKPYWLHRAQGHNNGICWNNQLFITCVDTTKSTNLTIFTPANFKQYIRHGEEYELQFIFQLCKITLTTEIMAYLHTMDSTILEQWNFGLTLPPLEDAYNAATSCPQ-AKEDPLAKYKFWNVDLKERFSLDLDQFALGRKFLLQIGKRK Seq109 MASPEGTGCRGWFHVDLDGFIDERETAQQLLH?QNTHADTQTLQKLKRKYLGSP------SAVKRRLIDSGYGILKCSNVQAKLYCKFKDIFGIPFSELVRTFKSDSTCCHDWIFGVN?TLAEALKIIKTQCIYYHMQGVVILLLIRYTCGKNRKTIVKSLLNVPTEQMLVQPPKIRSPAVALYFYKTSISNISGSTPEWIERQTQLQHFELSKMVQWAFDNEVTDDSQIAFHYAQLADVDSNAQAFLKSNMQAKYVKDCGIMCRHYKRAQQQQMNMKQWIKHVGDWKPIVQFLRYQGVEFISFLSYFKLFLQGPKHNCLVIYGPPNTGKSCFAMSLINFFHGSVISYVNSHSHFWLQPLDNTKLGMLDDATEACWKYIDEYLRNLLDGNPVSDRKHKQLVQIKCPPVLITTNINPMQDYLHSRIHVLQFLNPFPIDVNGNPVYQLNNANWKCFFERTWSRLDLDEDFRCLCQRLDACQEKILDCFEDSKNITDHIDYWRQENVIYYKARENNMTKLGHQVVPCLQVCKAKACVAIELQIALESLCKTEYNMEEWTLDVCESMWYTEPCFKKQGQHIEVWFDGSKDNRAEYVVWKWVYYCG-E-DGWCKVSSVSYEGIYYKTYYTNFKDEATKYSCNNTEIDSGYKTAPVVHIKGEANRLKCLRYRFQKHKQ-LFVTVSSTYHWYKDETQRQKFLDIVKIPWRPSDSKVYLPPT-PVKVITTDAYVKRTTIFYHAGSRLLTVGHPYYKADIPKVSAFQYRVFRVRLPDPNKFGLPDTNIFNPDERLVWACVGLEIGRGQPLGVGVSGHPLFNRLDDTESSSIADSRDNVSDPKQTQLCIIGCAPAIGEHWTKGTACGDCPPLELINSPIEDGDMVDTGFGALNFKALQESKSDVPLDIVQSTCKYPDYLKMSADAYGDSMWFYLRREQLFTRHFFNRAGYVATPSGSMITSEAQLFNKPYWLQRAQGHNNGICWNNQLFVTVVDTTRNTNMTLYNSKQIKQYVRHAEEYELQFVFQLCKISLSAEVMAYLHTMNSTLLEDWNIGLSPPVLEDKYSAAITCPP-EKQDPLSKYKFWEVNLQNSFSADLDQFPLGRKFLMQVGKRK Seq110 MASPEGTGCTGWFHVDLDGFLDDRETAQQLLHAQNTYADTQTLHNLKRKYLGSP------SGVKRRIIDSGYGLLKSSNVQAKLCYKFKELFGIPFSELVRTFKSDSTCCHDWIFGVNETLAEALKIIKSQCMYYHIQGVVILMLIRYTCGKNRKTIIKSLVNVPSEQMLVQPPKIRSPAVALYFYKTAMSNISGETPEWIQRQTQIQHFELSKMVQWAFDNDVTDDSDIAFYYAQLADVDSNAQAFLKSNMQAKYVKDCGIMCRHYKRAQQQQMNMKQWITHIGDWRPIVQFLRYQGVDFISFLSYFKLFLRGPKHNCLVLYGPPNTGKSCFAMSLIQFFQGSVISYVNSHSHFWLQPLDNAKLGMLDDATDACWRYIDEYMRNLLDGNPVSDRKHKQLVQIKCPPVIITTNINPLHDYLHSRIHVVPFLNPFPIDTNGNPVYQLNNVNWKCFFERTWSRLDLDEDFRCLCQRLDACQEKILDCFEDSKKIEDHIVYWRHENVVLYKARQNNITKLRHQVVPCLQVCKAKACVAIEIQMALESLYKTEYKVEEWTLDVCENMWHTAPCFKKSGKRIEVWFDGKKDNRTEYVVWQWVYYCG-D-NGWTKVPSVDYKGIYYKVYYTDFNDEAVKYTCYNTEVDGGYKTTPVVHLKGEPNRLKCLRYRCQKHK-HLFVNISSTYHWYKDETQRANFLNVVKIPWRPSETKVYLPPT-PVKVVPTDAYVKRTNIFYHAGSRLLAVGHPYYKTDVPKVSAFQYRVFRVRLPDPNKFGLPDTNVFNPEERLVWACVGLEIGRGQPLGVGVSGNPLFNKLDDTESSTIADSRDNISDPKQTQLCIIGCTPAIGEHWAKGTACGDCPPLELVNSPIQDGDMVDIGFGAMDFKTLQESKSDVPLDISQSTCKYPDYLKMSADAYGDSMWFYLRREQLFARHYFNRAGYVATPSGSMVTSEAQLFNKPYWLQRAQGHNNGICWGNQVFVTVVDTTRNTNMTIYNSSQIKQYVRHVEEYELQFVFQLCKISLSAETMAYLHTMNSTLLEGWNIGLSPPALEDKYSLAITCPA-EKEDPLAKYKFWDVNLQDSFSADLDQFPLGRKFLMQLGKRK Seq111 MASPEGTGCCGWFQVDVDGFIDDRETAQQLLQVQTAHADAQTLQKLKRKYIGSP------SEVKRRLIDSGYGLFKSSNVQGRLHFKFKEVYGVPYTELVRTFKSDSTCCNDWIFGVNETLAEALKILKPQCVYYHMQGVIVMMLIRYICGKNRKTITKSLLNVPQEQMLIQPPKLRSPAVALYFYKTAMSNISGETPEWIQRQTQLQHFELSKMVQWAFDNEVTDDSQIAFLYAQLADIDSNAQAFLKSNMQAKYVKDCGIMCRHYKRAQQQQMNMCQWIKHIGDWKPIVQFLRYQGVDFISFLSYFKLFLQGPKHNCLVLCGPPNTGKSCFAMSLINFFQGSVISFVNSQSHFWLQPLDNAKLGLLDDATDTCWRYIDDYLRNLLDGNPISDRKHKQLVQIKCPPVIITTNVNPMQDYLHSRISVFKFENPFPLDNNGNPVYELSNVNWKCFFERTWSRLNLDEDFRCLSQRLDACQNKILDCYEDSKCIIDHIDYWRHEYVLYYKARENDINVLNHQMVPSLQVCKAKACSAIELQIALEAISNTIYKNEEWTLDTCDELWRTEPCFKKEGQHIEVWFDGNKNNCMEYVVWKFIYYNG-E-CGWCKVSSVDYRGIYYKTYYTDFEQEAKKYPRINTQSHCGDKTTPVIHLKGEANRLKCCRYRFQKYKT-LFTDVTTTYHWYKDETQRDTFLNVVKIPWRPSDNKVYLPPT-PVKVVATDTYVKRTSIFYHAGSRLLAVGHPYYKTNIPKVSAYQYRVFRVRLPDPNKFGLPDPSFYNPDERLVWACVGLEVGRGQPLGAGLSGHPLFNRLDDTEVSNLADSRDNISDCKQTQLCIVGCAPALGEHWTKGAVCGDCPPLALVNTPIEDGDMVDTGFGAMDFKLLQESKAEVPLDIVQSTCKYPDYLKMSADAYGDSMWFYLRREQLFARHYFNRAGYVATPSGSMITSEAQLFNKPYWLQRAQGHNNGICWGNQVFVTVVDTTRSTNMTIYDAREINQYLRHVEEYELQFVFQLCKITLTAEVMAYLHNMNNTLLDDWNIGLSPPVLEDKYSTAITCPA-EKQDPLAKYKFWEVNLQDSFSADLDQFPLGRKFLMQLGKRK Seq112 MASPEGTGCCGWFEVDLDGFIDDAET?QQLLQVQTAHADKQTLQKLKRKYIASP------SGVKRRLIDSGYGLFKSSNLQGKLYYKFKEVYGIPFSELVRTFKSDSTCCNDWIFGVNETLAEALKIIKPHCMYYHMQGVIVMMLIRYTCGKNRKTIAKALLNVPQEQMLIQPPKIRSPAVALYFYKTAMSNISGDTPEWIQRQTQLQHFELSKMVQWAFDNEVTDDSQIAFQYAQLADVDSNAQAFLKSNMQAKYVKDCGIMCRHYKRAQQQQMNMCQWIKHIGDWKPIVQFLRYQGVDFISFLSYFKLFLQGPKHNCLVLCGPPNTGKSCFAMSLIKFFQGSVISFVNSQSHFWLQPLDNAKLGLLDDATEICWKYIDDYLRNLVDGNPISDRKHKQLVQIKCPPLLITTNINPMLDYLHSRMLVFQFQNPFPLDNNGNPVYELSNVNWKCFFTRTWSRLNLDEDFKCLSQRLNACQNKILDCFEDSRCIADHIEYWRHENVLYYKARENDITVLNHQMVPCLQVCKAKACSAIEVQIALESLSTTIYNNEEWTLDTCEELWLTEPCFKKEGQHIEVWFDGSKNNCMQYVAWKYIYYNG-D-CGWQKVCSVDYRGIYYKTYYTDFEQEAKKFRSINNNNHPGDKTTPVVHLKGEPNRLKCCRYRFQKYKT-LFVDVTSTYHWYKDETQRNSFLSHVKIPWRPSENKVYLPPT-PVKVVATDSYVKRTSIFYHAGSRLLAVGHPYYKTNIPKVSAYQYRVFRVRLPDPNKFGLPDTNIYNPDERLVWACVGLEVGRGQPLGAGLSGHPLFNRLDDTESSNLADSRDNISDGKQTQLCIVGCTPAMGEHWTKGAVCGDCPPLALINTPIEDGDMIDTGFGAMDFKVLQESKAEVPLDIVQSTCKYPDYLKMSADAYGDSMWFYLRREQLFARHYFNRAGYVATPSGSMITSEAQLFNKPYWLQRAQGHNNGICWGNQLFVTVVDTTRSTNMTIYDARKINQYLRHVEEYELQFVFQLCKITLSAEVMAYLHNMNANLLEDWNIGLSPPVLEDKYSTAITCPT-EKQDPLAKYKFWDVNLQDSFSTDLDQFPLGRKFLMQLGKRK Seq113 MDPEGTPGCTGWFNVDLVDFIDD-EAPGALLHAQETQAHAEAVQVLKRKFVGSPSPRLNEIQAKRRLFDSGYGLLRCSNLKATLLSKFKSVYGVSFSELVRSFKSDRTTCADWVAGVHHSVAEGLKLIQPFCSYAHIQGVYLLLLARFKCGKNRLTVSKCMLNVQETHMLIEPPKLRSAAAALYWYRTGISNVSGETPEWITRQTMFQHFDLSEMVQWAYDHDFTDDSVIAYEYAQLAGIDSNAAAFLKSNAQAKYVKDCATMCRHYKRAERQQMTMSQWIKQRGDWRPIVQFLRYQGVEFIAFLAALKLFLKGPKKNCIVLFGPPNTGKSYFGMSLIHFLQGSIISYVNSNSHFWLQPLADAKVAMLDDATPQCWSYIDNYLRNALDGNPISDRKHKNLVQMKCPPLLITSNTNAGQDYLHSRMVVFTFEQPFPFDQNGNPVYELNDKNWKSFFSRTWSRLDLEEEFKCLAERLSALQDRILELYEDSKDLKDQIEHWRQECAVLYKAREVGFSHLNHQVVPSLTVSRAKAHKAIEVQLALESLQNSEYNNEEWTLDASLEMWHTEPCFKKTGVPVTVLFDCDKDNTMEYVLWGHIYVWG-D-NGWVKTFGADNWGLHYKVYYVQFYEDAKKYHNNATGSSGDSDYTPIVHLKGESNCLKCLRFRL-GKHKHLYINISSTWRWFANELQRQQFLNTVKIPWRPSDSKVYLPP-VPVKVVSTDEYVSRTSIYYHAGSRLLAVGHPYYKVSVPKVSGLQYRVFRVRLPDPNKFGLPDANFYDPNQRLVWACLGVEVGRGQPLGVGTSGHPLLNKLDDTENGPKVDNRECVSDYKQTQLCMLGCKPPVGEHWGKGNPCGDCPALELVNSVIQDGDMVDTGYGAMDFNALQANKSDVPIDICTSVCKYPDYLKMASDPYGDSLFFYLRREQMFVRHLFNRAGFYPTPSGSMVTSDAQLFNKPYWLQKAQGHNNGICWGNQVFLTVVDTTRSTNMTLYNNESFKEYLRHVEEFDLQFIFQLCKVTLNTEVMAYIHSMDASILEDWNFGLQPPPLQDTYSAAITCPPKEKEDPLAKYTFWEVDLKEKFSADLDQFPLGRKFLLQAGRKR Seq114 MADPEGTGCTGWFEVDLLEFIDDTEAARALFNIQEGEDDLNAVCALKRKFAACSANPCRTSYRKRKIDDSGYGVLHSSNTKANILYKFKEAYGISFMELVRPFKSDKTSCTDWCYGISPSVAESLKLIKQHSLYTHLQGIIILLLIRFRCSKNRLTVAKLMLSIPETCMVIEPPKLRSQTCALYWFRTAMSNISGTTPEWIDRLTVLQHFDLSEMVQWAYDNELTDDSDIAYYYAQLADSNSNAAAFLKSNSQAKIVKDCGIMCRHYKKAEKRKMSIGQWIQSRGNWRPIVQLLRYQNIEFTAFLGAFKKFLKGPKKSCMLICGPANTGKSYFGMSLIQFLKGCVISCVNSKSHFWLQPLSDAKIGMIDDVTPISWTYIDDYMRNALDGNEISDVKHRALVQLKCPPLLLTSNTNAGTDYLHSRLTVFEFKNPFPFDENGNPVYAINDENWKSFFSRTWCKLDLEEDFKCISARLNAVQEKILDLYEDKTDLPSQIEHWRMECALLYTAKQMGFSHLCHQVVPSLLASKTKAFQVIELQMALETLSKSQYSTSQWTLQTSLEVWLCEPCFKKQGETVTVQYDNDKKNTMDYTNWGEIYIIE-E-DTCTMVTGVDYIGMYYKVYFKYFKEDAAKYCTNKQRTVCSSNVAPIVHLKGESNSLKCLRYRLKPYKE-LYSSMSSTWHWFVTEQQQQMFLGTVKIPWRPSEATVYLPP-VPVKVVSTDEYVSRTSIYYYAGSRLLAVGHPYFKLLVPKVSGLQYRVFRVRLPDPNKFGFPDTSFYNPDQRLVWACVGLEIGRGQPLGVGISGHPLLNKFDDTETGNKYDNRECLSDYKQTQLCLLGCKPPTGEHWGKGVACNDCPPLELINTIIEDGDMVDTGFGCMDFKTLQANKSDVPIDICGSTCKYPDYLKMTSEPYGDSLFFFLRREQMFVRHFFNRAGFFPTPSGSMVTSESQLFNKPYWLQRAQGHNNGICWGNQVFVTVVDTTRSTNMTLYKNENFKEYIRHVEEYDLQFVFQLCKVTLTAEVMTYIHAMNPDILEDWQFGLTPPPLQDTYSQAITCPPKEKEDPLGKYTFWEVDLKEKFSADLDQFPLGRKFLLQAGKRK Seq115 MDDPEGTGCTGWFEVDLIEFIDEAEAARALFNVQEGVDDINAVCALKRKFAACSANVCVSWHRKRKIIDSGYGILHNSNTKATLLYKFKEAYGVSFMELVRPFKSDKTSCTDWCYGISPSVAESLKLIKQHSIYTHLQGIILLLLIRFKCSKNRLTVAKLMLSIPETCMIIEPPKLRSQACALYWFRTAMSNISGTTPEWIDRLTVLQHFDLSEMIQWAYDNDITDDSDIAYKYAQLADVNSNAAAFLRSNAQAKIVKDCGVMCRHYKRAEKRGMTMGQWIQSRGNWRPIVQFLRYQNIEFTAFLVAFKQFLQGPKKSCMLLCGPANTGKSYFGMSLIHFLKGCIISYVNSKSHFWLQPLSDAKLGMIDDVTAISWTYIDDYMRNALDGNDISDVKHRALVQLKCPPLIITSNTNAGKDYLHSRLTVFEFNNPFPFDANGNPVYKINDENWKSFFSRTWCKLGLEEDFKCISARLSAVQDKILDIYEDKNDLTSQIEHWRMECAIMYTARQMGISHLCHQVVPSLVASKTKAFQVIELQMALETLNASPYKTDEWTLQTSLEVWLSEPCFKKKGITVTVQYDNDKANTMDYTNWSEIYIIE-E-TTCTLVAGVDYVGLYYKTYFKYFKEDAKKYCTYKGRNVCSSKVSPIVHLKGDPNSLKCLRYRLKPFKD-LYCNMSSTWHWYTTETQRQLFLNTVKIPWRPSEATVYLPP-VPVKVVSTDEYVSRTSIYYYAGSRLLAVGNPYFKVLVPKVSGLQYRVFRVRLPDPNKFGFPDTSFYNPDQRLVWACVGLEIGRGQPLGVGVSGHPYLNKFDDTETSNRYDNRECLSDYKQTQLCLIGCKPPTGEHWGKGVACTDCPPLELFNSIIEDGDMVDTGFGCMDFGTLQANKSDVPIDICNSTCKYPDYLKMASEPYGDSLFFFLRREQMFVRHFFNRAGFFPTPSGSIVTSESQLFNKPYWLQRAQGHNNGICWGNQLFVTVVDTTRSTNMTLYKNDNFKEYVRHVEEYDLQFVFQLCKITLTAEIMTYIHTMDSNILEDWQFGLTPPPLQDTYSQAITCPPKEKEDPLNKYTFWEVNLKEKFSADLDQFPLGRKFLLQSGKRK Seq116 MEDPEGTGCTGWFEVDLIDFIDEHEAARALFNAQEGEDDLHAVSAVKRKFTSSPSPRA-KHLPKRKPCDSGYGIMCENSIKTTVLFKFKETYGVSFMELVRPFKSNRSSCTDWCMGVTPSVAEGLKLIQPYSIYAHLQGVLILLLIRFKCGKNRLTVSKLMLNIPETHMVIEPPKLRSATCALYWYRTGLSNISGTTPEWIEQQTVLQHFDFGEMVQWAYDHDITDDSDIAYKYAQLADVNSNAAAFLKSNSQAKIVKDCATMCRHYKRAERKHMNIGQWIQYRGDWRPIVRFLRYQDIEFTAFLDAFKKFLKGPKKNCLVLYGPANTGKSYFGMSLIRFLSGCVISYVNSKSHFWLQPLTDAKVGMIDDVTPICWTYIDDYMRNALDGNDISDVKHRALVQIKCPPLILTTNTNAGTDYLHSRLVVFHFKNPFPFDENGNPIYEINNENWKSFFSRTWCKLDLEEDFKCIPARLNAVQEKILDLYEDSNDLNAQIEHWRMECVLFYKAKELGITHIGHQVVPPMAVSKAKACQAIELQLALEALNKTQYSTDGWTLQTSLEMWRAEPYFKKHGYTITVQYDNDKNNTMDYTNWKEIYLLG-E-CECTIVEGVDYYGLYYKIYFVKFSNDAKQYCTNKGRVAHTTCTAPIIHLKGDPNSLKCLRYRVKTHKS-LYVQISSTWHWYSDETQRQQFLKTVKIPWRPSEATVYLPP-VPVKVVSTDEYVSRTSIYYYAGSRLLTVGHPYFKVLVPKVSGLQYRVFRIKLPDPNKFGFPDTSFYNPEQRLVWACTGLEIGRGQPLGVGISGHPLLNKFDDTETSNKYDNRECLSDYKQTQLCILGCKPPIGEHWGKGTPCGDCPPLQLINSVIQDGDMVDTGFGCMDFNTLQASKSDVPIDICSSVCKYPDYLQMASEPYGDSLFFFLRREQMFVRHFFNRAGFFPTPSGSMVTSESQLFNKPYWLQRAQGHNNGICWGNQLFVTVVDTTRSTNMTLYKNENFKEYLRHGEEFDLQFIFQLCKITLTADVMTYIHKMDATILEDWQFGLTPPPLEDTYSTAITCPPKGKEDPLKDYMFWEVDLKEKFSADLDQFPLGRKFLLQAGKKK Seq117 MEDPEGTGCTGWFSVDLIGFIDDTQAARALFNLQEEEDDLNAVSALKRKF--TGGGNSN--AAKRRAYDSGYGIMHVNNIKATLMHKFKEAYGVTFTQLIRPFKSDRTSCTDWCFGITPSVAESLKLIKPQTLYTHLQGIIILLLVRFKCAKNRLTVSKLMLSIPETHMIIEPPKIRSTTCALYWFRTGMSNISGQTPEWIERLTVLQHFDLGEMVQWAYDNDITDDSEIAYQYAMLADVNSNAAAFLKSNSQAKIVKDCGTMCRHYKRAEKRKMTIGQWIQARGDWRTIVKLLRYQNVEFTQFLATFKKFLKGPKKSCMVICGPPNTGKTYFAMSLIHFLQGCVISYVNAKSHFWLQPLSDAKIGMIDDVTAICWTYIDDYLRNALDGNDISDVKHKALVQLKCPPLLLTSNIDVATDFLHSRVVVFRFNNPFPFDENGNPVYNLNDENWKSFFSRTWCQLDLEEDFKCIATRLNAVQEKILDVYENKKDLCTQIEHWRIECALYYKAKELGLARIGHQVVPPMSVTKAKACQIIELQMALQTLNETQYSNDEWTLSTSLELWLCEPCLKKKGETVTVQYDNDKENTMEYTSWNEIYIVK-D-SVWTVVVGVDYMGLYYKTYYVKFETDAKKYCTNKGRSVCAPNTAPIVHLKGDPNSLKCLRYRLKCNTD-LYCHMSSTWHWYASETQRQQFLNSVRIPWRPSEATVYLPP-VPVKVVSTDEYVSRTSIYYYAGSRLLAVGHPYFKVLVPKVSGLQYRVFRVRLPDPNKFGFPDTSFYNPDQRLVWACVGIEIGRGQPLGVGISGHPLLNKFDDTETNNKYDNRECLSDAKQTQLCIIGCKPPTGEHWGKGTPCGACPPLELMNTVIEDGDMIDTGFGCMDFKSLQANKSDVPLDICTSICKYPDYLGMASEAYGDSLFFFLRREQMFVRHLFNRAGFFPTPSGSMVSSESQLFNKPYWLQRAQGHNNGICWGNQIFVTVVDTTRSTNMTLYKNENFKEYLRHVEEYDLQFIFQLCKISLTANVMQYIHTMNPDILEDWQFGLTPPPLQDTYSQAITCPPTAKEDPLKKYSFWEINLKEKFSADLDQFPLGRKFLLQAGKRK Seq118 MADPAGTGCNGWFYVDMVDFIDEAETAQALFHAQEAEEHAEAVQVLKRKYVGSPSPRLKAITAKRRLFDSGYGVLKTSNGKAAMLGKFKELYGVSFMELIRPFQSNKSTCTDWCFGVTGTVAEGFKLLQPYCLYCHLQGMVMLMLVRFKCAKNRITIEKLLLCISTNCMLIQPPKLRSTAAALYWYRTGMSNISGETPEWIERQTVLQHFDLSQMVQWAYDNDVMDDSEIAYKYAQLADSDSNACAFLKSNSQAKIVKDCGTMCRHYKRAEKRQMSMGQWIKSRGDWRDIVKFLRYQQIEFVSFLSALKLFLKGPKKNCILIHGAPNTGKSYFGMSLISFLQGCIISYANSKSHFWLQPLADAKIGMLDDATTPCWHYIDNYLRNALDGNPVSDVKHKALMQLKCPPLLITSNINAGKDYLHSRLVVFTFPNPFPFDKNGNPVYELSDKNWKSFFSRTWCRLNLEEDFKCLSQRLNVCQDKILEHYEDSKRLCDHIDYWRLECVLMYKAREMGIHSINHQVVPALSVSKAKALQAIELQMMLETLNNTEYKNEDWTMQTSLELYLTAPCLKKHGYTVEVQFDGDVHNTMHYTNWKFIYLCI-D-GQCTVVEGVNCKGIYYITYFVNFTEEAKKYCTNQTRAVSCPATTPIIHLKGDANILKCLRYRL-SKYKQLYEQVSSTWHWYISTSQRDDFLNTVKIPWRPSEATVYLPP-VPVKVVSTDEYVTRTNIYYHAGSRLLTVGHPYYKIVVPKVSGLQYRVFRVRLPDPNKFGFPDTSFYNPEQRLVWACVGLEVGRGQPLGVGISGHPLLNKFDDTENSNRYDNRECISDYKQTQLCLLGCKPPIGEHWGKGSPCGDCPPLELKNSVIQDGDMVDTGFGAMDFTALQDTKSNVPLDICNSICKYPDYLKMVAEPYGDTLFFYLRREQMFVRHFFNRSGYFPTPSGSMVTSDAQIFNKPYWMQRAQGHNNGICWGNQLFVTVVDTTRSTNMSVFKSSNFKEYLRHGEEFDLQFIFQLCKITLSADIMTYIHSMNPAILEDWNFGLTTPPLEDTYSQAITCPQKPKEDPFKDYVFWEVNLKEKFSADLDQFPLGRKFLLQAGKRK Seq119 MADPAGTGCNGWFYVDLVDFIVETETAHALFTAQEAKQHRDAVQVLKRKYLGSPSPRLKAIAAKRRLFDSGYGVLKTSNAKAAMLAKFKELYGVSFSELVRPFKSNKSTCCDWCFGLTPSIADSIKLLQQYCLYLHIQGMVVLLLVRYKCGKNRETIEKLLLCVSPMCMMIEPPKLRSTAAALYWYKTGMSNISGDTPEWIQRQTVLQHFELSRMVQWAYDNDIVDDSEIAYKYAQLADTNSNASAFLKSNSQAKIVKDCATMCRHYKRAEKKQMSMSQWIKYRGDWKQIVMFLRYQGVEFMPFLTALKRFLQGPKKNCILLYGAANTGKSLFGMSLIKFLQGSVICFVNSKSHFWLQPLADAKIGMLDDATVPCWNYIDDNLRNALDGNLVSDVKHRPLVQLKCPPLLITSNINAGTDYLHNRLVVFTFPNEFPFDENGNPVYELNDKNWKSFFSRTWSRLSLDEDFKCLCQRLNVCQDKILTHYEDSTNLRDHIDYWRLECAIYYKAREMGFKHINHQVVPTLAVSKNKALQAIELQLTLETIYNPQYSNEKWTLDVSLEVYLTAPCIKKHGYTVEVQFDGDICNTMHYTNWKHIYICE-E-ASVTVVEGVDYYGLYYQTYFVQFKDDAEKYSSHKGRINCNSNTTPIVHLKGDANTLKCLRYRF-KKHCKLYTAVSSTWHWYDSEWQREQFLSQVKIPWLPSEATVYLPP-VPVKVVSTDEYVARTNIYYHAGTRLLAVGHPYFKILVPKVSGLQYRVFRIHLPDPNKFGFPDTSFYNPDQRLVWACVGVEVGRGQPLGVGISGHPLLNKLDDTENASAYDNRECISDYKQTQLCLIGCKPPIGEHWGKGSPCGDCPPLELINTVIQDGDMVDTGFGAMDFTTLQANKSEVPLDICTSICKYPDYIKMVSEPYGDSLFFYLRREQMFVRHLFNRAGYFPTPSGSMVTSDAQIFNKPYWLQRAQGHNNGICWGNQLFVTVVDTTRSTNMSLYKNTNFKEYLRHGEEYDLQFIFQLCKITLTADVMTYIHSMNSTILEDWNFGLQPPPLEDTYSQAIACPA-PKEDPLKKYTFWEVNLKEKFSADLDQFPLGRKFLLQAGKRK Seq120 MADPAGTGCNGWFYVDLVDFIVETETAHALFTAQEAKQHRDAVQVLKRKY?GSPSPRLKAIAAKRRLFDSGYGVLKTSNAKAAMLAKFKELYGVSFSELVRPFKSNKSTCCDWCFGLTPSIADSIKLLQQYCLYLHIQGMVVLLLVRYKCGKNRETIEKLLLCVSPMCMMIEPPKLRSTAAALYWYKTGISNISGDTPEWIQRQTVLQHFELSQMVQWAYDNDIVDDSEIAYKYAQLADTNSNASAFLKSNSQAKIVKDCATMCRHYKRAEKKQMSMSQWIKYRGDWKQIVMFLRYQGVEFMSFLTALKRFLQGPKKNCILLYGAANTGKSLFGMSLMKFLQGSVICFVNSKSHFWLQPLADAKIGMLDDATVPCWNYIDDNLRNALDGNLVSDVKHRPLVQLKCPPLLITSNINAGTDYLHNRLVVFTFPNEFPFDENGNPVYELNDKNWKSFFSRTWSRLSLDEDFKCLCQRLNVCQDKILTHYEDSTDLRDHIDYWRLECAIYYKAREMGFKHINHQVVPTLAVSKNKALQAIELQLTLETIYNSQYSNEKWTLDVSLEVYLTAPCIKKHGYTVEVQFDGDICNTMHYTNWTHIYICE-E-ASVTVVEGVDYYGLYYRTYFVQFKDDAEKYSSHKGRINCNSNTTPIVHLKGDANTLKCLRYRF-KKHCTLYTAVSSTWHWYDSEWQRDQFLSQVKIPWLPSEATVYLPP-VPVKVVSTDEYVARTNIYYHAGTRLLAVGHPYFKILVPKVSGLQYRVFRIHLPDPNKFGFPDTSFYNPDQRLVWACVGVEVGRGQPLGVGISGHPLLNKLDDTENASAYDNRECISDYKQTQLCLIGCKPPIGEHWGKGSPCGDCPPLELINTVIQDGDMVHTGFGAMDFTTLQANKSEVPLDICTSICKYPDYIKMVSEPYGDSLFFYLRREQMFVRHLFNRAGYFPTPSGSMVTSDAQIFNKPYWLQRAQGHNNGICWGNQLFVTVVDTTRSTNMSLYKNTNFKEYLRHGEEYDLQFIFQLCKITLTADVMTYIHSMNSTILEDWNFGLQPPPLEDTYTQAIACPA-PKEDPLKKYTFWEVNLKEKFSADLDQFPLGRKFLLQAGKRK Seq121 MADPAGTGCNGWFYVDLVDFIVETETAHALFTAQEAKEHRDAVQVLKRKYLGSPSPRLKAIAAKRRLFDSGYGVLKTSNAKAAMLAKFKELYGVSFSELVRPFKSNKSTCCDWCFGLTPSIADSIKLLQQYCLYLHIQGMVVLLLVRYKCGKNRETIEKLMLCVSPMCMMIEPPKLRSTAAALYWYKTGMSNISGDTPEWIQRQTVLQHFELSQMVQWAYDNDIVDDSEIAYKYAQLADTNSNASAFLKSNSQAKIVKDCATMCRHYKRAEKKQMSMSQWIKYRGDWKQIVMFLRYQGVDFMSFLSALKKFLQGPKKNCILLYGAANTGKSLFGMSLMKFLQGSVICFVNSKSHFWLQPLADAKIGMLDDATVPCWNYIDDNLRNALDGNLVSDVKHRPLVQLKCPPLLITSNINAGTDYLHNRLVVFTFPNEFPFDENGNPVYELNDKNWKSFFSRTWSRLSLDEDFKCLCQRLNVCQDKILTHYEDSTDLRDHIDYWRLECAIYYKAREMGFKHINHQVVPTLAVSKNKALQAIELQLTLETIYNSQYSNEKWTLDVSLEVYLTAPCIKKHGYTVEVQFDGDICNTMHYTNWKYIYICE-E-TSVTVVEGVDYYGLYYQTYFVQFKDDAEKYSSHKGRINCNSNTTPIVHLKGDANTLKCLRYRF-KKHCKLYTAVSSTWHWYDSECQREQFLSQVKIPWLPSEATVYLPP-VPVKVVSTDEYVARTNIYYHAGTRLLAVGHPYFKILVPKVSGLQYRVFRIYLPDPNKFGFPDTSFYNPDQRLVWACVGVEVGRGQPLGVGISGHPLLNKLDDTENASAYDNRECISDYKQTQLCLIGCKPPIGEHWGKGSPCGDCPPLELINTVIQDGDMVDTGFGAMDFTTLQANKSEVPLDICTSICKYPDYIKMVSEPYGDSLFFYLRREQMFVRHLFNRAGYFPTPSGSMVTSDAQIFNKPYWLQRAQGHNNGICWGNQLFVTVVDTTRSTNMSLYKNTNFKEYLRHGEEYDLQFIFQLCKITLTADVMTYIHSMNSTILEDWNFGLQPPPLEDTYSQAIACPA-PKEDPLKKYTFWEVNLKEKFSADLDQFPLGRKFLLQAGKRK Seq122 MADPAGTGCNGWFYVDLVDFIVETETAHALFTAQEAKEHRDAVQVLKRKYLGSPSPRLKAIAAKRRLFDSGYGVLKTSNAKAAMLAKFKELYGVSFTELVRPFKSNKSTCCDWCFGLTPSIADSIKLLQQYCLYLHIQGMVVLLLVRYKCGKNRETIEKLMLCVSPMCMMIEPPKLRSTAAALYWYKTGMSNISGDTPEWIQRQTVLQHFELSQMVQWAYDNDIVDDSEIAYKYAQLADTNSNASAFLKSNSQAKIVKDCATMCRHYKRAEKKQMSMSQWIKYRGDWKQIVMFLRYQGVDFMSFLSALKKFLQGPKKNCILLYGAANTGKSLFGMSLMKFLQGSVICFVNSKSHFWLQPLADAKIGMLDDATVPCWNYIDDNLRNALDGNLVSDVKHRPLVQLKCPPLLITSNINAGTDYLHNRLVVFTFPNEFPFDKNGNPVYELNDKNWKSFFSRTWSRLSLDEDFKCLCQRLNVCQDKILTHYEDSTDLRDHIDYWRLECAIYYKAREMGFKHINHQVVPTLAVSKNKALQAIELQLTLETIYNSQYSNEKWTLDVSLEVYLTAPCIKKHGYTVEVQFDGDICNTMHYTNWKYIYICE-E-TSVTVVEGVDYYGMYYQTYFVQFKDDAEKYSSHKGRINCNSNTTPIVHLKGDANTLKCLRYRF-KKHCKLYTAVSSTWHWYDSECQREQFLSQVKIPWLPSEATVYLPP-VPVKVVSTDEYVARTNIYYHAGTRLLAVGHPYFKILVPKVSGLQYRVFRIYLPDPNKFGFPDTSFYNPDQRLVWACVGVEVGRGQPLGVGISGHPLLNKLDDTENASAYDNRECISDYKQTQLCLIGCKPPIGEHWGKGSPCGDCPPLELINTVIQDGDMVDTGFGAMDFTTLQANKSEVPLDICTSICKYPDYIKMVSEPYGDSLFFYLRREQMFVRHLFNRAGYFPTPSGSMVTSDAQIFNKPYWLQRAQGHNNGICWGNQLFVTVVDTTRSTNMSLYKNTNFKEYLRHGEEYDLQFIFQLCKITLTADVMTYIHSMNSTILEDWNFGLQPPPLEDTYSQAIACPA-PKEDPLKKYTFWEVNLKEKFSADLDQFPLGRKFLLQAGKRK Seq123 MADPAGTGCNGWFYVDLVDFIVETETAHALFTAQEAKEHRDAVQVLKRKYLGSPSPRLKAIAAKRRLFDSGYGVLKTSNAKAAMLAKFKELYGVSFSELVRPFKSNKSTCCDWCFGLTPSIADSIKLLQQYCLYLHIQGMVVLLLVRYKCGKNRETIEKLLLCVSPMCMMIEPPKLRSTAAALYWYKTGMSNISGDTPEWIQRQTVLQHFELSQMVQWAYDNDIVDDSEIAYKYAQLADTNSNASAFLKSNSQAKIVKDCATMCRHYKRAEKKQMSMSQWIKYRGDWKQIVMFLRYQGVDFMSFLTALKRFLQGPKKNCILLYGAANTGKSLFGMSLMKFLQGSVICFVNSKSHFWLQPLADAKIGMLDDATVPCWNYIDDNLRNALDGNLVSDVKHRPLVQLKCPPLLITSNINAGTDYLHNRLVVFTFPNEFPFDENGNPVYELNDKNWKSFFSRTWSRLSLDEDFKCLCQRLNVCQDKILTHYEDSTDLRDHIDYWRLECAIYYKAREMGFKHINHQVVPTLAVSKNKALQAIELQLTLETIYNSQYSNEKWTLDVSLEVYLTAPCIKKHGYTVEVQFDGDICNTMHYTNWKYIYICE-E-TSVTVVEGVDYYGLYYQTYFVQFKDDAEKYSSHKGRINCNSNTTPIVHLKGDANILKCLRYRF-KKHCKLYTAVSSTWHWYDSECQREQFLSQVKIPWLPSEATVYLPP-VPVKVVSTDEYVARTNIYYHAGTRLLAVGHPYFKILVPKVSGLQYRVFRIYLPDPNKFGFPDTSFYNPDQRLVWACVGVEVGRGQPLGVGISGHPLLNKLDDTENASAYDNRECISDYKQTQLCLIGCKPPIGEHWGKGSPCGDCPPLELINTVIQDGDMVDTGFGAMDFTTLQANKSEVPLDICTSICKYPDYIKMVSEPYGDSLFFYLRREQMFVRHLFNRAGYFPTPSGSMVTSDAQIFNKPYWLQRAQGHNNGICWGNQLFVTVVDTTRSTNMSLYKNTNFKEYLRHGEEYDLQFIFQLCKITLTADVMTYIHSMNSTILEDWNFGLQPPPLEDTYSQAIACPA-PKEDPLKKYTFWEVNLKEKFSADLDQFPLGRKFLLQAGKRK Seq124 MADPAGTGCNGWFFVDMVDFINETETAQALFHAQEEQTHKEAVQVLKRKYASSPSPRLKAIAAKRRLFDSGYGILKCSNANAAMLAKFKELFGISFTELIRPFKSDKSTCTDWCFGIAPSVANFKH-----?ICIHIQAMVILALLRFKV?KTRTTIENY*LCISAASMLIQPPKLRSTPAALYWFKTAMSNISGETPEWIQRQTVLQHFDLSEMVQWAYDNDFIDDSDIAYKYAQLAETNSNACAFLKSNSQAKIVKDCATMCRHYKRAEKREMTMSQWIKRRGDWRDIVRFLRYQQVDFVAFLSALKNFLHGPKKNCILIYGAPNTGKSLFGMSLMHFLQGAIISYVNSKSHFWLQPLYDAKIAMLDDATSPC??YIDQYLRNALDGNPIFDVKH*A?VH??CPPLLIT?NINAGKDYLHSRVVVFTFHNEFPFDKNGNPEYGLNDKNWKSFFSRTWCRLNLEEVFKCLSQRLSVCQDKILEHYEDSTCLSDHIQYWRLECAVFYKAREMGIKTLNHQVVPTQAISKAKAMQAIELQLMLETLNTTEYSTEDWTLETSIELYTTVPCLKKDVYTVEAQFDGDKQNTMHYTNWTHIYILE-D-SICTVVKGVNYKGIYYETYYVTFREEAKKYCTNKDRCGSCSTTTPIVHLKGDANTLKCSRYRL-GKYKALYQDASSTWRWYTTEYQRDKFLTTVKIPWRSNEATVYLPP-VSVKVVSTDEYVTRTNIYYHAGSRLLAVGHPYYKIAVPKVSGLQYRVFRVKLPDPNKFGFPDTSFYDPCQRLVWACTGVEVGRGQPLGVGISGHPLLNKLDDTENLNKYDNRECISDYKQTQLCLIGCRPPIGEHWGKGTPCGECPPLELLNTVLQDGDMVDTGFGAMDFTTLQANKSDVPLDICSSICKYPDYLKMVSEPYGDMLFFYLRREQMFVRHLFNRAGYFPTPSGSMVTSDAQIFNKPYWLQRAQGHNNGICWSNQLFVTVVDTTRSTNMSVYKNDNFKEYLRHGEEYDLQFIFQLCKITLTADVMTYIHSMNPSILEDWNFGLTPPPLEDTYSQAVTCAPKPKDDPLKNYTFWEVDLKEKFSADLDQFPLGRKFLLQAGKRR Seq125 MADSGNWRCSGWFNVEMGDFIDQQEIAQALYHSQQVNADNEAIRVLKRKFAGSASPH--ILTSTHLLCDSGYGILKSSNVKATLLAKFKEVYGLSYMELVRPYKSDKTQCQDWVFGVAPSLAESLKLLTQYCLYIHLQGIIVLLLARFKCNKNRLTVQKLLLNVTQEYMLIEPPRLRSTPCALYWYRTSLSNISGEVPEWIKRQTVVQHFDLSQMVQWAFDNDITNDCEIAYKYALLASEDSNAAAFLKSNAQAKYVKDCGTMCRHYKAAERKQMTMSQWITHRGNWKHIVQFLRYQQVEFVPFLIALKQFLKGPKQNCIVIYGPPDTGKSHFGMSLMQFMQGVVISYVNSNSHFWLSPLADAKMALLDDATPACWTYIDRYLRNALDGNPMCDRKHKHLLQIKCPPLLITSNTNPKADYLHSRMKVFTFSNPFPFDSNGNPLYQLTNENWKAFFTKTWSKLDLDDDFKCLCKRLSACQDAILELYEDSIHLSDHIDHWRLENVLLHKAREMGLQSVNQQAVPSLAVSRSKGHNAIELQLALESLNESSYNTEEWTLQTSWEQWVTDPCFKKGGKTVEVRYDCDKDNTMQYVVWTFVYYW-LEG-KWYKVSSVDYNGIYYKVYYTQFDRDAKRYTTDSSTQCTLHNVAPIVHLKGDKNSLKCLRYRMHKGYSHLFNNVTTTWHWFSSTSQQKQFLQCAKIPWRPTEAKVYLPP-VSVKVVSTEEYVTRTNIYYYAGSRLLAVGHPYYKIAVPKVSGLQYRVFRIRLPDPNKFGFPDASFYNPDERLVWACAGVEVGRGQPLGIGTSGNPFMNKLEDTENAAKYDSRECMSDYKQTQLCIVGCKPPLGEHWGTGTPCGECPPLELKNTTIQDGDMIDVGFGAMDFKALQANKSDVPIDISNTICKYPDYLGMAADPYGDSMWFYIRREQMFVRHLFNRAGFYPTPSGSMVSSDAQIFNKPYWLQKAQGQNNGICWHNQLFLTVVDTTRSTNFSVYANSNFKEYLRHAEEYDLQFVFQLCKINLTTDVMTYIHSMSSSILEQWNFGLTPPPLEETYSQAITCPPKETEDPYGKMTFWEVDLKEKFSAELDQFALGRKFLLQLGKKK Seq126 MADSGNWRCTGWFNVEMGDFIDQQEIAQALYQSQQANADNEAIRVLKRKFTGSPSPQINVLTSKRRLFDSGYGLLQRNNAKAALLAKFKEVYGLSYMELVRPYKSDKTHCQDWVFGVIPSLAESLKLLTQYCMYIHLQGIIVLVLVRFKCNKNRLTVQKLLLNVTQERMLIEPPRLRSTPCALYWYRTSLSNISGDTPEWIKRQTLVQHFDLSQMIQWAFDNDITDDCEIAYKYALLGNVDSNAAAFLKSNAQAKYVKDCGTMCRHYKAAERKQMSMAQWIQHRGNWKDIVLFLRYQNVEFMPFLITLKQFLKGPKQNCIVLYGPPDTGKSHFGMSLIKFIQGVVISYVNSTSHFWLSPLADAKMALLDDATPGCWTYIDKYLRNALDGNPICDRKHKNLLQVKCPPLLITSNTNPKADYLHSRIKVFTFLNPFPFDSNGNPLYQLTNENWKAFFTKTWSKLDLDDDFKCLCKRLSACQDAILELYEDSVHLSDHIDHWRHENVLLHKAREMGLQTVNNQAVPSLAVSRSKGYNAIEMQIALESLNESLYNTEEWTLHTSWELWVTEPCFKKDGKTVEVRYDCEKDNSMQYVFWTHIYCWY-EG-GWAKVGSIDYNGIYYKVYYTRFDTDAKRYTTESCTQCTTHNVAPIVHLKGDKNSLKCFRYRLHKGYSHLFKNVTTTWHWFTTVLQQQHFLQHVKIPWRPTDAKVYLPP-VSVKVVSTDEYVTRTNIYYYAGSRLLAVGHPYFKTIVPKVSGLQYRVFRLRLPDPNKFGFPDASFYNPDERLVWACSGVEVGRGQPLGIGTSGNPFMNKLDDTENAPKYDGRECMSDYKQTQLCILGCRPPLGEHWGPGTPCGDCPPLELKNTPIQDGDMIDVGFGAMDFKALQANKSDVPIDISNTTCKYPDYLGMAADPYGDSMWFYLRREQMFVRHLFNRAGFYPTPSGSMVSSDAQLFNKPYWLQKAQGQNNGICWHNQLFLTVVDTTRSTNFSVYANSNFKEYLRHAEEFDLQFVFQLCKISLTTEVMTYIHSMNSTILEEWNFGLTPPPLEETYSQAISCPPKETEDPYAKLSFWDVDLKEKFSAELDQFPLGRKFLLQLGKKK Seq127 MADDTGTGCSGWFLVDMVDFID-LE-AQALLNEQEADAHYAAVQDLKRKYLGSPSPRLDAIKVKRRLFDSGYGLLKCKDVRATLHGKFKECYGLSFKDLTREFKSDKTTCGDWVFGVHHSVSEAFQLIQPLSTYSHIQGMVLLVLLRFKVNKNRCTVARTLLNIPEDHMLIEPPKIQSSVAALYWFRTSISNASGDTPEWIARQTIVEHFKLTEMVQWAYDNDYCDESDIAFEYAQRADFDSNAKAFLNSNCQAKYVKDCATMCKHYKNAEMKKMSIKQWIKYRGNWKPIVQFLRHQGIEFISFLSKLKLWLHGPKKNCIAIVGPPDTGKSAFCMSLIKFLGGTVISYVNSSSHFWLQPLCNAKVALLDDATQSCWGYMDTYMRNLLDGNPMSDRKHKSLALIKCPPLLVTSNIDITTEYLYSRVTLFKFPNPFPFDSNGNAVYELCDANWKCFFARLSASLDIE-DFRCLAKHLDACQEQLLELYENSNELKKHIQHWRYENVLLHKARQMGISHIGPQVVPPLQVSQTKGHEAIEMQMRIETLLKSQFGMEPWTLDTSFEMWLTPPCFKKQGKTVEVKYDCNAENTMHYVLWKYIYVYNTEKEIWLKVKGVDYKGLYYKTYYVDFEKEAKQYSSNNGRNNSYCTGTPIVQLQGDSNNLKCFRYRLHSNYKHLFFACISTWHWYVNEQQRQEFLNTVKIPWRPSDNKLYVPPPAPVKVLTTDAYVTRTKIFYHASSRLLAVGNPYFKTIVPKVSGFQFRVFKIVLPDPNKFALPDTSIFDSTQRLVWACIGLEVGRGQPLGVGYCGHPCLNKFDDVENSASYDNRVNVADYKQTQLCLVGCAPPLGEHWGKGKQCGDCPPLELVTSVIQDGDMVDTGFGAMDFAELQSNKSDVPLDICTSTCKYPDYLQMAADPYGDRLFFYLRKEQMFARHFFNRAGYFNTPSGSLVSSEAQLFNKPYWLHKAQGHNNGICWGNTLFVTVVDTTRSTNMTVYTASEYKQYMRHVEEFDLQFIFQLCTIKLTAELMAYIHTMNPTVLEEWNFGLSPPPLEDTYSQAITCPDKEKQDPYAGLSFWEVNLKEKFSSELEQYPLGRKFLLQTGRKK Seq128 MADNTGTGCSGWFLVDMVDFID-LE-AQALLNEQEADAHYAAVQDLKRKYLGSPSPRLNAIKVKRRLFDSGYGLLKCKDIRATLHGKFKQCYGLSFTDLIRQFKSNKTTCEDWVFGVHHSVSEAFELIQPLTIYRHIQGMLLLVLLRFKVNKNRCTVARTLLNIPEDHMLIEPPKIQSSVAALYWFRTSLSNASGETPEWIARQTIVEHFKLTEMVQWAYDNDYCDECDIAFEYAKRADFDSNAKAFLNSNCQAKYVKDCATMCKHYKNAEMKKMTMNQWIKHRGNWKPIVQFLRHQNIEFISFLSKLKLWLQGPKKNCIAIVGPPDTGKSMFCMSLIKFLGGTVISYVNSSSHFWLQPLCNTKVALLDDATHSCWGYMDTYMRNLLDGNPMSDRKHKSLALIKCPPLLVTSNIDITTEYLYSRVTVFKFPNPFPFDRNGNAVYELCDANWKCFFARLSASLDIE-DFRCLAKHLDACQEQLLELYENSNELTKHIQHWRHENVLLYKARQMGLSHIGLQVVPPLKVSQTKGHEAIEMQMTLETVLKSEYGTEPWTLETSFEMWLTPPCFKKQGQTVEVRYDCNAENSMHYVLWKYIYVC--ENDRWQKVKGVDIKGLYYKTYYIDFEKEAKQYNNNQQRNNSNSSGTPIVQLQGDSNNLKCFRYRLHDKYKHLFMLASSTWHWYVNEQQRQDFLNTVKIPWRPSDNKLYVPPPAPVKVITTDAYVTRTKIFYHASSRLLAVGNPYFKTIVPKVSGFQFRVFKIVLPDPNKFALPDTSIFDSTQRLVWACIGLEVGRGQPLGVGISGHPLLNKFDDVENSASYDNRVNVADYKQTQLCLVGCAPPLGEHWGKGTQCGDCPPLELVTSVIQDGDMVDTGFGAMDFAQLQSNKSDVPLDICTATCKYPDYLQMAADPYGDRLFFSLRKEQMFARHFFNRAGYFNTPSGSLVSSEAQLFNKPYWLHKAQGHNNGICWGNTLFVTVVDTTRSTNMTVYTASEYKQYMRHVEEFDLQFIFQLCSIKLTAEVMAYIHTMNPTVLEEWNFGLSPPPLEDTYSQAITCPDKEKQDPYAGLSFWEVNLKEKFSSELDQYPLGRKFLLQTGRKR Seq129 MAEDTGTGCSGWFLVDMVDFID-VE-AQALLNEQEADAHYAAVQDLKRKYLGSPSPRLDAIKVKRRLFDSGYGLLKCKDVRATLYGKFKDCYGLSFTDLIRPFKSDKTTCGDWVFGIHHSVSEAFELMQPLTTYMHIQGMVLLVLIRFKVNKSRCTVARTLLNIPEDHMLIEPPKIQSSVAALYWFRTGISNASGETPEWIKRQTIVEHFKLTEMVQWAYDNDFCDESEIAFEYAQRGDFDSNARAFLNSNCQAKYVKDCATMCKHYKNAEMKKMSMKQWITYRGNWKPIVQFLRHQNIEFIPFLSKLKLWLHGPKKNCIAIVGPPDTGKSCFCMSLIKFLGGTVISYVNSSSHFWLQPLCNAKVALLDDATQSCWVYMDTYMRNLLDGNPMSDRKHKSLALIKCPPLLVTSNVDITKDYLYSRVTTLTFPNPFPFDRNGNAVYELSDANWKCFFTRLSASLDIE-DFRCIAKHLDACQEQLLELYENSNELKKHIQHWRYESVLLHKARQMGLSHIGLQVVPPLTVSQAKGHEAIEMQMTLETLLESEFGMEPWTLDTSREMWLTPPCFKKQGQTVEVKYDCNTDNRMDYVSWTYIY-F--DTDKWTKVKGVDYKGLYYKTYYLEFEKEAKKYNNNKGRDNSYCAATPIVQLQGDSNCLKCFRYRLHEKYKDLFLLASSTWHWYVNEQQRQDFLKTVKIPWRPSDNKLYVPPPAPVKVITTDAYVTRTNIFYHASSRLLAVGNPYFKTVVPKVSGYQFRVFKVVLPDPNKFALPDTSIFDSTQRLVWACTGLEVGRGQPLGVGISGHPLLNKYDDVENSASYDNRVNVADYKQTQLCLVGCAPPLGEHWGQGKQCGDCPPLELISSVIQDGDMVDTGFGAMNFAELQSNKSDVPLDICTSTCKYPDYLQMAADPYGDRLFFYLRKEQMFARHFFNRAGYYNTPSGSLVSSEAQLFNKPYWLQKAQGHNNGICWGNHLFVTVVDTTRSTNMTVYKATEYKQYMRHVEEFDLQFIFQLCTIKLTAEVMSYIHTMNPTILEDWNFGLSPPPLEDTYSQAITCPDKEKQDPYAGLSFWEVNLKEKFSSELDQYPLGRKFLLQTGRKK Seq130 MADNTGTGCSGWFLVDMVDFID-ME-AQALLNEQEADAHYAAVQDLKRKYLGSPSPRLDAIKVKRRLFDSGYGLLKCKNIRATLLGKFKDCYGLSYTDLIRQFKSDKTTCGDWVFGVHHSVSEAFQLIQPVTTYSHIQGMVLLALVRFKVNKNRCTVARMMLNIPEDHMLIEPPKIQSGVAALYWFRSGISNASGETPEWITRQTIVEHFKLADMVQWAYDNDFCEESEIAFEYAQRADIDANARAFLNSNCQAKYVKDCATMCKHYKTAEMKKMNMKQWIKFRGNWKPIVQFLRHQNIEFIPFLTKLKMWLHGPKKNCIAIVGPPDTGKSCFCMSLIKFLGGTVISYVNSSSHFWLQPLCNAKVALLDDVTQSCWVYMDTYMRNLLDGNPMTDRKHKSLALIKCPPLIVTSNIDITKEYLCSRVTLFTFPNPFPFDRNGNALYDLCETNWKCFFARLSSSLDIE-DFRCIAKHLDVCQEQLLELYENSNKLTKHIQHWRYECVLLHKAKQMGLNHIGMQVVPALAVSQTKGHQAIEMQMTLETLLNSDYGTEPWTLETSREMWLTPPCFKKQGQTVEVKFDCNADNAMEYVWWKVIYVF--DTDKWVKVTGIDYKGLYYKTYYTNFEKEAEKYNSNKGRDNNYCTATPVVQLQGDANCLKCLRYRLHAKYKTLFVAASSTWRWYVDEQQRQQFLNTVKLPWRPSENQVYVPPPAPVKVIPTDAYVKRTNIYYHASSRLLAVGNPYFKTLVPKVSGFQYRVFKMVLPDPNKFALPDTSIYDPTQRLVWACIGLEVGRGQPLGVGISGHPLLNKLDDVENSASYDNRVNVADYKQTQLCLVGCAPPLGEHWGKGKQCGDCPPLELITSVIEDGDMVDTGFGAMNFAELQPNKSDVPLDICTATCKYPDYLQMAADPYGDRLFFYLRKEQMFARHFFNRAGYFNTPSGSLVSSETQLFNKPFWLQKAQGHNNGICWGNQLFVTVVDTTRSTNMTIYTSEQYKQYMRHVEEFDLQFMFQLCSITLTAEVMAYLHTMNAGILEQWNFGLSPPPLEDKYSQAITCPEKAKQDPYAKLSFWEVDLREKFSSELDQYPLGRKFLLQTGQKR Seq131 MAENTGTGCSGWFLVDMVDFID-LE-AQALLNEQEADAHYAAVQDLKRKYLGSPSPRLDAIKVKRRLFDSGYGLLKCKDVRATLLGKFKDCYGLSYTDLIRQFKSNKSTCGHWVFGVHHSVADAFQLIQPVTTYSHIQGMVLLALLTFKVNKNRCTVARMLLNIPEDHMLIEPPKIQSTVAALYWFRSSLSNASGDTPDWITRQTIVEHFKLADMVQWAYDNDLCDESEIAFDYAQRADIDANARAFLNSNCQAKYVKDCATMCKHYKNAEMKKMNMKQWIHYRGNWKPIVQFLKHQNIEFIPFLSKLKLWLHGPKKNCIAIVGPPDTGKSCFCMSLIKFLGGTVISYVNSSSHFWLQPLCNAKVALLDDATQSCWVYIDTYMRNLLDGNPMSDRKHKSLALIKCPPLLITSNIDITKDYLFSRVSVFTFPNPFPFDRNGNAVYDLCESNWKCFFTRLSASLDIE-DFRCIAKHLDVCQEQLLELYENSNNLEKHIQHWRHESVLLHKARQMGLHHIGMQVVPPLAVSQTKGHEAIEMQMTLETLLKSAYGMEPWTLDTSREMWLAPPCFKKQGQTVEVKYDCKADNIMEYVMWKFIYIL--DGDEWVKVEGVDYRGLYYKTYYTNFETEAKKYNNNKGRDNCYCRATPIVQLQGDPNCLKCFRYRLHDKHKHLFLSASSTWHWYANEQQRQQFLDTVRLPWRPSDNQVYVPPPAPVKVITTDAYVTRTNIFYHASSRLLAVGNPYFKTVVPKVSGYQFRVFKVLLPDPNKFALPDTSLFDPSQRLVWACTGLEVGRGQPLGIGISGHPLLNKLDDVENSASYDNRVNVADYKQTQLCMVGCAPPLGEHWGKGKQCGDCPALELITSVIQDGDMVDTGFGAMNFAELQPLKSDVPLDICNTTCKYPDYLQMAADPYGDRLFFYLRKEQMFARHFFNRAGYFNTPSGSLVSSETQLFNKPFWLQKAQGHNNGICWGNQLFVTVVDTTRSTNMTVYTSTDYKQYMRHVEEFDLQFIFQLCSIKLTAEVMAYIHTMNPTVLEDWNFGLTPPPLEDTYSQAIACPDKAK-NPYANLSFWEVNLKEKFSSELDQYPLGRKFLLQTGQKR Seq132 MADDSGTGCTGWFMVDMVDFID-LE-AQALFNRQEADTHYATVQDLKRKYLGSPSPRLDAIKVKRRLFDSGYGLLKCKDLRAALLGKFKECFGLSFIDLIRPFKSDKTTCLDWVFGIHHSISEAFQLIEPLSLYAHIQGMVLLVLLRFKVNKSRSTVARTLLNIPENQMLIEPPKIQSGVAALYWFRTGISNASGEAPEWITRQTVIEHFKLTEMVQWAYDNDICEESEIAFEYAQRGDFDSNARAFLNSNMQAKYVKDCATMCRHYKHAEMRKMSIKQWIKHRGNWKPIVQFLRHQNIEFIPFLTKFKLWLHGPKKNCIAIVGPPDTGKSYFCMSLISFLGGTVISHVNSSSHFWLQPLVDAKVALLDDATQPCWIYMDTYMRNLLDGNPMSDRKHKALTLIKCPPLLVTSNIDITKEYLHTRVTTFTFPNPFPFDRNGNAVYELSNTNWKCFFERLSSSLDIE-DFRCIAKRLDACQEQLLELYENSTDLHKHVLHWRHESVLLYKAKQMGLSHIGMQVVPPLKVSEAKGHNAIEMQMHLESLLRTEYSMEPWTLETSYEMWQTPPCFKKRGKTVEVKFDGCANNTMDYVVWTDVYVQ--DNDTWVKVHSVDAKGIYYKTYYVNFVKEAEKYDQHQRRNNSNSSATPIVQFQGESNCLKCFRYRLNDRHRHLFDLISSTWHWYDSEEQRQQFLDVVKIPWRPSDSTVYVPPPNPVKVVATDAYVTRTNIFYHASSRLLAVGHPYFKTVVPKVSGYQYRVFKVVLPDPNKFALPDSSLFDPTQRLVWACTGLEVGRGQPLGVGVSGHPFLNKYDDVENSGS-DNRVNVGDYKQTQLCMVGCAPPLGEHWGKGKQCGDCPPLELITSVIQDGDMVDTGFGAMNFADLQTNKSDVPIDICGTTCKYPDYLQMAADPYGDRLFFFLRKEQMFARHFFNRAGYVNTPSGSLVSSEAQLFNKPYWLQKAQGHNNGICWGNQLFVTVVDTTRSTNMTLYTNSDYKEYMRHVEEYDLQFIFQLCSITLSAEVMAYIHTMNPSVLEDWNFGLSPPPLEDTYSQAITCPEKEK-DPYKNLSFWEVNLKEKFSSELDQYPLGRKFLLQSGRKR Seq133 MADDSGTGCTGWFMVDMVDFID-VE-AQALFNRQEADAHYATVQDLKRKYLGSPSPRLDAIKVKRRLFDSGYGLLKCKDIRSTLHGKFKDCFGLSFVDLIRPFKSDRTTCADWVFGIHHSIADAFQLIEPLSLYAHIQGMVLLVLIRFKVNKSRCTVARTLLNIPENHMLIEPPKIQSGVRALYWFRTGISNASGEAPEWITRQTVIEHFKLTEMVQWAYDNDICEESEIAFEYAQRGDFDSNARAFLNSNMQAKYVKDCAIMCRHYKHAEMKKMSIKQWIKYRGNWKPIVQFLRHQNIEFIPFLSKLKLWLHGPKKNCIAIVGPPDTGKSCFCMSLIKFLGGTVISYVNSCSHFWLQPLTDAKVALLDDATQPCWTYMDTYMRNLLDGNPMSDRKHRALTLIKCPPLLVTSNIDISKEYLHSRVTTFTFPNPFPFDRNGNAVYELSDANWKCFFERLSSSLDIE-DFRCIAKRLDACQDQLLELYENSIDIHKHIMHWRLESVLLHKAKQMGLSHIGLQVVPPLTVSETKGHNAIEMQMHLESLAKTQYGVEPWTLDTSYEMWLTPPCFKKQGNTVEVKFDGCEDNVMEYVVWTHIYLQ--DNDSWVKVTSVDAKGIYYKTYYVNFNKEAQKYNKHQRRNNCHSAATPIVQLQGDSNCLKCFRYRLNDKYKHLFELASSTWHWYSSEEQRQQFLNSVKIPWRPSDSTVYVPPPNPVKVVATDAYVKRTNIFYHASSRLLAVGHPYYKTVVPKVSGYQYRVFKVVLPDPNKFALPDSSLFDPTQRLVWACTGLEVGRGQPLGVGVSGHPLLNKYDDVENSGGYDNRVNVGDYKQTQLCMVGCAPPLGEHWGKGTQCGDCPPLELITSVIQDGDMVDTGFGAMNFADLQTNKSDVPLDICGTVCKYPDYLQMAADPYGDRLFFYLRKEQMFARHFFNRAGYVHTPSGSLVSSEAQLFNKPYWLQKAQGHNNGICWGNHLFVTVVDTTRSTNMTLYTNSDYKEYMRHVEEFDLQFIFQLCSITLSAEVMAYIHTMNPSVLEDWNFGLSPPPLEDTYSQAITCPEKEKQDPYKDMSFWEVNLKEKFSSELDQFPLGRKFLLQSGRKR Seq134 MADDSGTGCSGWFLVDMVDFINL-SNAQALLHAQQTCADAVELCELKRKYISP-SPRLHAIKAKRRLFDSGYGLFKCKDLNAKLCGKFKELFGVGFHDLVRQFKSDKSTCTDWVFGVNPTIAEGFHLLKGQALYLHTQGMVLLALCRYKVAKNRETVVRQLLNVPDNQLMVQPPKLQSSAAALFWFRSGMGNGSGTTPEWIAKQTMLEHFSLTQMVQWAYDNGHTDECEIAYYYAQIADIDANAAAFLKSNNQAKYVRDCAAMCKHYRLAEMRRMSMADWIKHRGDWKPIVKLLRYQHIDIIVFLAALKKWLHGPKKNCICIVGPPDTGKSCFGMSLMHFLQGTIISFVNSCSHFWLQSLVDAKVAMLDDVTSACWAYMDTHMRNLLDGNPTSDRKHKSLAVIKCPPLLLTSNINIKHDYLQSRVTVFEFPNPFPFDSNGNAVYELSDANWNSFFKRLASSLELE-DF--LARRLDLCQEQLLELYEDSKQLQHHILHWRYESVIYYTARQMGIKRLGHQVVPSLDVSKAKAHAAIEMQMCLESLQTTEYNLEPWTLDTSQELWLAEPCFKKGGKTVEVRFDCNEHNAMHYTLWTAVYVQ-VE-DTWTKVEGVDHRGLFYTTYYVDFGKEAHTYSNNKIRNSGGGHSTPIIQLEGDANCLKCFRYRLTKVS-HLYTNSSTTWRWYSSVHQRSQFLALVKIPWQLNENQVYLPPPTPVTIVSTDEYVQRTSLYYHAGSRLLTIGHPYFDVSVPKVSGHQYRVFRVRLPDPNKFGLSDTSLFNSEQRLVWACVGVEVGRGQPLGVGISGHPYFNKDEDVENSSVYDSRENVADYKQTQLCIVGCTPPIGEYWGMGTPCGDCPVLELKSEVIEDGDMVDAGFGAMDFASLQANKSDVPLDLCTSISKYPDYLGMAAEPYGNSLFFFLRREQMFVRHFFNRAGYYSTPSGSLVTSDSQIFNKPLWIQKAQGHNNGICFGNQLFVTVVDTTRSTNLTLYDNSKFKEYLRHGEEFDLQFIFQLCVITLNAEVMTYIHAMDSSLLDDWNFKIGPPALEDTYNKAIACPPKEKEDPYKKYKFWEVNLTEKFSSQLDQFPLGRKFLMQAGKRK Seq135 MADSPGTGCSGWFVVDMIDFIDELSNAQALLHVQQTCADAADLCELKRKYISP-SPRLHAIKAKRRLFDSGYGLFKCKDLNAKLYGKFKELYGVGFGDLVRQFKSDKSTCTDWVFGVNPTIAEGFHLLKRQALYLHTQGMVLLALCRYKVGKNRETVVRQLLNVPDNQILVQPPKLQSPPAALFWFRAGMGNGSGTTPEWIAKQTMLEHFSLTDMVQWAYDNGHTDECEIAYYYAQRADVDANAAAFLKSNNQAKYVRDCASMCKHYRLAEMRRMSMAEWIKHRGDWKPIVKLLRYQHIDIIVFLAALKKWLQGPKKNCICIVGPPDTGKSCFGMSLMHFMQGTIISYVNSCSHFWLQSLADAKVAMLDDVTAACWGYMDTHMRNLLDGNPTSDRKHKPLAVIKCPPLLLTSNINITQDYLQSRVQVFEFPNPFPFDSNGNAVYELNDANWNSFFKRLASSLELG-DF--LARRLDLCQEQLLELYENSKELQQHILHWRYESAIYYTARQMGIKHLGHQVVPSLDVSKAKAHAAIEMQMCLESLQNTEYNVEPWTLDTSQELWLAEPCFKKGGKTVEVRFDCNETNAMHYTLWTTVYVQ-VD-DAWTKVKGVDYKGLSYTTYYVDFAKEAQTYSNNGHRNCGGGSSTPIIQLEGEANCLKCFRYRLGKVS-HLFCNSSTTWRWYSSVQQRSDFLAIVKIPWQLNENQVYLPPPTPVTIVSTDEYVQRTSLYYHAGSRLLTIGHPYFDISVPKVSGHQYRVFRVRLPDPNKFGLSDTSLFNSEQRLVWACVGVEVGRGQPLGVGVSGHPYFNKDEDVENSSAYDSRENVADYKQTQLCMLGCTPPIGEYWGKGTPCGDCPVLELKTEVIQDGDMVDTGFGAMDFASLQANKSDVPLDLCTSISKYPDYLGMAAEPYGNSLFFFLRREQMFVRHFFNRAGYYSTPSGSLVTSDSQIFNKPLWIQKAQGHNNGICFGNQLFVTVVDTTRSTNLTLYNNSNFKEYLRHGEEFDLQFIFQLCVITLNAEVMTYIHAMDPTLLEDWNFKIAPPALEDTYNKAIACPPKVREDPYKKYKFWDVNLTERFSSQLDQFPLGRKFLMQAGKRK Seq136 MADKQGTGCSGWFIVDMVDFINDHSSAQALLNAQQADADAAIVQELKRKYMSP-SPRLHAIKAKRRLFDSTNGLFKDKDVTVKLLGKFKELFGVGFNDLVRQFRSDKSTCTDWVFGVNPSISEGFHLLKEHTLYLHTQGMVLLALCRYKVAKNRSTIVRQLLNVPVQQILIQPPKLQSAPAALFWFRSSMGNGSGTTPEWISRQTMLEHFSLTDMVQWAYDNGYTEEYDIAYYYAQRGDIDANAAAFLKSNMQARYVRDCACMCKHYKLAEMKKMSMAEWIKHRGDWKPIVKFLKYQHIDIIAFLGALKKWLHGPKKNCICIIGPPDTGKSCFGMSLMKFLGGTILSYVNASSHFWLQPLVDAKVAMLDDVTAGCWTYMDMHMRNLLDGNPTSDRKHRALTVIKCPPLLLTSNLDISTEYLRSRITTFTFPNTFPFDTNGNAIYELNDENWNSFFKRLASSLELE-DY--LARRLDMCQEQLLELYEDSKTLEDHVLHWRYECALYYKAREAGIKHLGHQVVPQLEVSRQKAYLAIELQMSLEALLQTEYSLEPWTLDTSQEVWLTEPCFKKRGQTVEVRYDCNPANAMHYTLWSDIYV-PLN-STWLKVSGVDYEGLSYKHYYVEFHKEARTYDHHPRGHNRGSHTTPIIQLQGEANALKCFRYRLNKHK-HLFADVSSTWRWYISEQQRADFLSRVKIPWRLNDNKVYLPPPGPISIVSTDEYVQRTNLFYYAGSRLLAVGHPYFKITVPKVSGYQYRVFRVKLPDPNKFGFSETTLVTSDQRLVWGCVGVEIGRGQPLGVGISGHPYLNKYDDTENPSGYDNRENVADYKQTQLCIVGCTPPMGEYWGQGVPCGDCPVIELKSEVIQDGDMVDTGFGAMDFASLQASKSDVPLDLVNTKSKYPDYLGMAAEPYGNSLFFFLRREQMFLRHFFNKAGYFSTPSGSLVTSDSQLFNKPLWIQKAQGHNNGICFGNQLFVTVVDTTRSTNLTLYDNAKFKEYLRHVEEYDLQFIFQLCIITLNPEVMTYIHTMDPTLLEDWNFGVSPPALEDTYNKAIACPPKEREDPYKKYTFWDINLTEKFSAQLTQFPLGRKFVMQAGKRK Seq137 MADKQGTGCSGWFIVDMVDFINEQSCAQALLNKQQADADAAIVQELKRKYISP-SPRLHAIKAKRRLFHSNYGLFKDKDVTVKLLGKFKDLFGVGFNDLVRQFKSDKSTCTDWVFGVNPSIAEGFHLLKEQTLYLHTQGMVLLALCRYKVAKNRSTVGRQLLNVPVQQILIQPPKLQSAPAALFWFRAGMGNGSGTTPEWISRQTVLEHFSLTNMVQWAYDNGYTEECDIAYYYAQLGDTDANAAAFLKSNMQARYVRDCACMCKHYKLAEMKKMSMAEWIKHRGDWKPIIRFLRYQHIDIITFLAALKKWLHGPKKNCICIIGPPDTGKSSFGMSLMKFLGGTMLSYVNSSSHFWLQSLVDAKAAMLDDVTAACWNYMDMHMRNLLDGNLTSDRKHKALAVIKCPPLLLTSNMDINTDYLKSRITTFTFPNAFPFDTNGNAIYEFNDENWNPFFKRLASSLELE-DY--LARRLDMCQEQLLELYEDSRDLQDHVLHWRYECALYYKAREMGIKHLGHQVVPKLEVSRAKAHVAIEMQLSLESLLQTEYSIEPWTLDTCQELWHTEPCFKKRGQTVEVRFDCNPENTMQYTLWSEIYV-PVN-DTWVKVHGVDYKGLSYKTYYVDFIKEAQTYNHNQGGHSGGSNATPIVQLQGDANSLKCFRYRLGKYK-YLYVDVSSTWRWYASVQQREAFLANVKIPWRLNDNKVYLPPPGPISIVSTDEYVQRTNLFYHAGSRLLAVGHPFFKVIVPKVSGHQYRVFRVKLPDPNKFGFSETTLVTSDQRLVWGCVGVEIGRGQPLGVGISGHPYLNKYDDIENPSGYDNRENVADYKQTQLCIVGCTPPMGEYWGKGVPCGDCPVIELKSEVIEDGDMVDTGFGALDFASLQASKSDVPLDLCNTKSKYPDYLGMAAEPYGNSLFFFLRREQMFVRHFFNRAGYYSTPSGSLVTSDSQLFNKPLWMQKAQGHNNGICFGNQVFVTVVDTTRSTNLTLYDNTKFKEYLRHAEEFDLQFIFQLCIITLNPEVMTYIHTMDASLLEDWNFGVSPPALEDTYNKAIACPPKAKEDPYKNYTFWDVDLTERFSAQLTQFPLGRKFVMQAGKRK Seq138 MADDTGTGCSGWFSVDLVDFVDNQLKAQALLNRQQAHADKEAVQALKRKLLGSPSPRLGGLGAKRRLFDSGYGLLKCKNLQATLLGKFKELFGLSFGDLVRQFKSDKSSCTDWVFGVHHSIAEGFNLIKAEALYTHIQGMVLLMLIRFKCGKNRTTVSKGMLNIPANQLLIEPPRLQSVAAAIYWFRAGISNASGETPEWIQRQTIVEHFNLTEMVQWAYDNDLTEDSDIAYEYAQRADTDSNAAAFLKSNCQAKYVKDCGIMCRHYKKAQMKRMSMPQWIKHRGDWRPIVKFIRYQGIDFLTFMSAFKKFLHNPKKSCLVLIGPPNTGKSQFGMSLVKFLAGTVISFVNSHSHFWLQPLDSAKIAMLDDATPPCWTYLDTYLRNLLDGNPCSDRKHKALTVVKCPPLIITSNTDIRTEYLYSRISLFEFPNPFPLDKNGNPVYVLNDENWKSFFQRLWSSLEFEDEFRCLAKRLDACQEQLLELYEDSKHLEKHVQHWRIEAALLFKAREMGYAQVGHQIVPALEISRAKAHVAIEIQLALETLLQSTFGTEPWTLETSYEMWHAEPCLKKQGRTVEVVFDGNPENAMHYTAWTFIYVQTLD-GTWCKVYGVCYAGLYYKQFYCNFKNEAKKYNNQRRNPCGN-QTTPVIHLQGDPNCLKCLRWRLKKNCSHLFTQVSSTWHLYYNEEQRDKFLSTVKLPWRPSDNKVYLPPP-PVKVVSTDEYVQRTNYFYHASSRLLAVGHPYYRTSIPKVSGLQYRVFRVRLPDPNKFTLPETNLYNPEQRMVWACVGLEVGRGQPLGVGLSGHPLLNRLDDTENGPRYDNRENVSDCKQTQLCLVGCKPAIGEHWGKGAACGDCPPLELQNSVIQDGDMADVGFGAMDFSALQTSKAEVPLDIMNSISKYPDYLKMSAEAYGDNMFFFLRREQMFVRHLFNRAGYYPTPSGSMVTSDAQIFNKPYWLQQAQGHNNGICWGNQVFLTVVDTTRSTNMTVYKSTNFKEYLRHAEEYDIQFIFQLCKITLSVEVMSYIHTMNPDILDDWNVGVAPPPLEDSYSQAIRCAP-EK-DPFSDYSFWEVNLSEKFSSDLDQFPLGRKFLLQAGKRR Seq139 MADDTGTGCSGWFCVDLVDFVDQ-VHAQALLNKQQAHADQEAVQALKRKLLGSPSPRLGGLGAKRRLFDSGYGLLKCKNLHATLLGKFKELFGVSFGDLVRQFKSDKSSCTDWVFGVNHSIAEGFNLIKADSLYTHIQGMVLLMLIRFKCGKNRTTVSKGLLNIPTNQLLIEPPRLQSVAAAIYWFRSGISNASGDTPEWIQRQTILEHFNLTEMVQWAYDNDITEDSDIAYEYAQRADRDSNAAAFLKSNCQAKYVKDCGVMCRHYKKAQMRRMSMGAWIKHRGDWKPIVKFIRYQQIDFLAFMSAFKKFLHNPKKSCLVLIGPPNTGKSQFGMSLINFLAGTVISFVNSHSHFWLQPLDSAKIAMLDDATPPCWTYLDIYLRNLLDGNPCSDRKHKALTVVKCPPLLITSNTDIRTNYLYSRVSLFEFPNPFPLDTNGNPVYELNDKNWKSFFQRLWSSLEFEDEFRCLAKRLDACQEQLLELYENSRDLQKHIEHWRMEAVVLYKAREMGFANIGHQIVPTLETCRAKAHMAIEIHLALETLLQSSYGKEPWTLETSNELWLTNPCFKKQGRTVEVIFDGKQDNAMHYTAWTYIYIQTVQ-GTWCKVQGVCHAGLYYKQFYCNFKEEAKKYCNKRRNHCGS-QATPVIHLQGDPNCLKCLRFRLKRNCSHLFTQVSSTWHLYYDEAQRNLFLNTVKIPWRPSDNKVYLPPP-PVKVVSTDEYVQRTNYFYHASSRLLVVGHPYYKTSIPKVSGLQYRVFRVRLPDPNKFTLPETNLYNPEQRMVWACVGLEVGRGQPLGVGISGHPLLNKLDDTENAPTYDNRENVSDYKQTQLCLVGCKPAIGEHWGKGTACGDCPPLELKNSFIQDGDMVDVGFGALDFGALQSSKAEVPLDIVNSITKYPDYLKMSAEAYGDSMFFFLRREQMFVRHLFNRAGYYPTPSGSMVTSDAQLFNKPYWLQQAQGHNNGICWGNQLFLTVVDTTRSTNMTLYTAANFKEYLRHAEEYDVQFIFQLCKITLTVEVMSYIHNMNPNILEEWNVGVAPPPLEDSYSEAIRCTP-EK-DPYSDFWFWEVNLSEKFSTDLDQFPLGRKFLLQAGKRK Seq140 MADNQGTGCNGWFFVDMVDFIDQ-ENPQALLHAQQLQADVEAVQQLKRKYIGSPSPRLGAIKAKRRLFPPPNGLIHNTNIRVALFGMFKDLYGLSFMDLARPFKSDKTVCTDWVFGIYHGITDGFKLLEPHCLYGHIQGMVLLLLTRFKCGKNRLTVSKCLLNIPETQMLIDPPKLRTPAAALYWYRQGLSNASGTPPEWLARQTVIEYFDLSKMVQWAYDHNYIDDSIIALEYAKLADIDENAAAFLGSNCQAKYVKDCGTMCRHYIRAQKMQMTMSQWIKHRGEWKEIVRFLRYQHVDFISFMIALKQFLQGPKHNCILLYGPPDTGKSNFAMSLISFLGGVVLSYVNSSSHFWLEPLADAKIAMLDDATTQCWNYMDIYMRNALDGNPMCDRKHRAMVQTKCPPLIVTSNINASTDYLHSRVKCFCFPNRFPFDSNGNPVYDLSNKNWKSFFKRSWSRLALDNEFRCLATRLDVCQERLLDLYEDSNKLEDQIEHWRLECALQYKAREMGYKVLQHQALPALAVSKGKGHKAIELQLALETLQKTVYSTEPWTLDTCLERWNAPPCLKRRGQTVDVIFDGHQDNTMQYVMWGDIYYQNCDGEGWTKVCSIDAMGIYYKVYYVDFKKEASKYNKNQGRHTSSGDTTPIVHFKGEPNTLKCFRQRIQKYK-HLFEQASSTWHWYSSVEQRQQFLVTVRIPWRPSENKVYLPPT-PVKVVSTDEYVTRTSIYYHASSRLLAVGHPYFKQSIPKVSGYQYRVFRVQLPDPNKFGLPDPSLYNPEQRLVWACTGVEVGRGQPLGLGLSGHPLLNKLDDTENAPKYDNRENVSDYKQTQLCILGCTPPIGEHWAKGNLCGDCPPLELVNSYIQDGDMVDIGFGAMDFKTLQTSKSEVPLDVATSICKYPDYLKMAAEAYGDSLFFYLRREQMFVRHMLNRAGYAATPSGSMVTSEYQIFNKPYWLQRAQGQNNGICWGNQVFLTVVDTTRSTNLTLFNNSDFREYIRHVEEYDLQFIFQLCTITLTADVMAYIHGMNPTILEDWNFGITPPALEDTYSQAIACPAKEKEDPYSKFNFWTVDLKERFSSDLDQFPLGRKFLLQAGRKR Seq141 Seq142 ExaML-3.0.21/testData/140.model000066400000000000000000000000671330315463200156450ustar00rootroot00000000000000WAG, p0 = 1-399 AUTO, p1 = 400-699 AUTO, p2 = 700-1104 ExaML-3.0.21/testData/140.tree000066400000000000000000000021751330315463200155060ustar00rootroot00000000000000((((((Seq67,(Seq66,Seq65)),(Seq69,Seq68)),(Seq70,Seq71)),Seq72),(Seq63,((((((Seq38,(Seq37,Seq36)),(((Seq45,(Seq47,Seq46)),(Seq44,(Seq43,Seq42))),(Seq35,(Seq41,(Seq39,Seq40))))),((Seq31,(Seq34,(Seq32,Seq33))),(((Seq14,Seq15),(Seq16,((((Seq8,Seq7),Seq6),(Seq5,(Seq4,Seq3))),((Seq11,(Seq9,Seq10)),(Seq13,Seq12))))),((Seq17,(((Seq24,Seq23),Seq25),(Seq18,((Seq22,Seq21),(Seq19,Seq20))))),((Seq26,(Seq28,Seq27)),(Seq30,Seq29)))))),(((Seq49,Seq48),(Seq51,Seq50)),((Seq52,(((Seq55,(Seq53,Seq54)),Seq56),Seq57)),(Seq59,Seq58)))),(Seq64,(Seq62,Seq60))),(((Seq74,Seq73),Seq61),(((((Seq80,Seq81),(Seq78,Seq79)),((Seq84,(Seq83,Seq82)),(Seq77,(Seq75,Seq76)))),(((Seq86,Seq85),Seq87),(((Seq92,Seq91),((Seq93,Seq94),(Seq95,Seq96))),(Seq88,(Seq90,Seq89))))),((Seq140,((Seq138,Seq139),(((Seq132,Seq133),((Seq130,Seq131),((Seq127,Seq128),Seq129))),((Seq135,Seq134),(Seq137,Seq136))))),(((((Seq107,Seq108),(Seq106,Seq105)),((Seq111,Seq112),(Seq109,Seq110))),((Seq102,(Seq103,Seq101)),(((Seq99,(Seq97,Seq98)),Seq100),Seq104))),(((((Seq120,Seq119),((Seq121,Seq122),Seq123)),(Seq124,Seq118)),((Seq117,(Seq115,Seq114)),Seq116)),((Seq126,Seq125),Seq113))))))))),Seq2,Seq1); ExaML-3.0.21/testData/354.tree000066400000000000000000000127271330315463200155210ustar00rootroot00000000000000((((bn_001BGTue,((ac002MorArb,bn_002BGTue),((bf_005BGTue,(bf_002BGTue,st_001BGTue)),st_002BGTue))),((er101AA26384W,(er002MorArb,(er003MorArb,(er108AA26384W,er005MorArb)))),(ol037MorArb,(((si_006MorArb,ol111PRChina),si_003MorArb),(am111TS17259W,(((ja157TS17319W,ja117TS17319W),ja144TS17319W),((((ps209TS16075W,(ps202TS16075W,(ps117TS16020W,(ps120TS16020W,(ps211TS16075W,ps115TS16020W))))),ps121TS16020W),(pa005BGTue,pa006BGTue)),(((fl017MorArb,fl010MorArb),((wa125For29653E,(wa224Kin20879E,(wa112For29653E,am110TS17259W))),(ol039MorArb,(fl114PRChina,fl103PRChina)))),(((laevigatumSH,(cc009MorArb,cc004MorArb)),am104TS17259W),(sh109TS17342W,(sh_001aureum,(sh108TS17342W,sh106TS17342W)))))))))))),(((sterculiaceumSH,(db_038BGTue,(franchetiiSH,(db_021BGTue,db_025BGTue)))),(((cd018BGTue,(cd001BGTue,(cd127AragwiVGeo,(cd125AragwiVGeo,cd126AragwiVGeo)))),((my_005MorArb,my_009MorArb),((mo202ShenHubei,((mo203ShenHubei,(mo106ShenHubei,((mo324LongHubei,mo303LongHubei),mo103ShenHubei))),((pl1501SSweden,(pl_403Germany,pl1426SkeenS)),(ok103Sun4194W,(ok105Sun4194W,(tr_024BGTue,(ok112Sun4194W,(mo519TS16041W,(mo413TS16017W,(mo518TS16041W,(tr_002BGTue,(mo420TS16017W,(mo505TS16041W,mo415TS16017W))))))))))))),(ca1507EAustria,(ca1913QuilanF,(ca2111StAnastF,(ca2103StAnastF,(ca3102VdLlobrE,((ca30b10VdHeraultF,(ca2407VdCisseF,ca2905CsseNoirF)),((ca2835GdlJonteF,ca2837GdlJonteF),((((ca2804GdlJonteF,ca306PdCissaI),(ca1616EBulgaria,((ca301PdCissaI,(ca2912CsseNoirF,(ca2858GdlJonteF,(ca2114StAnastF,(ca2207BurgEltzD,(ca2212BurgEltzD,ca2102StAnastF)))))),ca1633EBulgaria))),ca2422VdlCisseF),(ca1407VeynesF,((ca27a66_2707loc1F,(ca2302MuehltLUX,(ca1801SWGer,(ca2303MuehltLUX,(ca30b04VdHeraultF,((ca3010VdHeraultF,ca2856GdlJonteF),((ca2807GdlJonteF,ca2808GdlJonteF),(ca3101VdLlobrE,ca3110VdLlobrE)))))))),ca2803GdlJonteF))))))))))))),(mp307SCalif,((mp103SequoiaNP,mp101SequoiaNP),mp001BGTue)))),((((gl_104BryceCyn,(gl_111BryceCyn,(gl_105BryceCyn,(gl_113BryceCyn,(gl_110BryceCyn,gl_114BryceCyn))))),(((((ts102TS17304W,(ko105TS16025W,(cb014MorArb,cb017MorArb))),(tegmentosumSH,((pe110NEStates,pe107NEStates),((((cp023BGTue,(cp021BGTue,(da121PRChina,(gs101BGTue,gs102BGTue)))),da220ZhejiangBG),(cr043BGTue,(cr101TS17261W,(cr041BGTue,(cr103TS17261W,(cr105TS17261W,caudatifoliumSH)))))),(cp107TS17302W,((cp101TS17302W,gs011BGTue),cp102TS17302W)))))),ds115TS17313W),(Di307XishTrBotG,(np102MtSankaiJ,(np107MtSankajJ,np101MtSankaiJ)))),((mt_105PRChina,((sp_001BGTue,(sp_005BGTue,(sp_003BGTue,(sp_002BGTue,sp_008BGTue)))),(uk_020MorArb,uk_004MorArb))),((he112BGTue,(he111BGTue,((cs103MorArb,cs009BGTue),he005BGTue))),((ne203NEStates,ne201NEStates),(ne1038ZionNP,(ne708NUtah,(ne704NUtah,(ne801EscalNM,(ne907ZionNP,ne806EscalNM)))))))))),((((tv101Georgia,(ve303SirinRudIRN,(ve202VazIRN,(tv112Georgia,(ve308SirinRudIRN,(ve150AssalamIRN,(tv111Georgia,(tv102Georgia,((ve112AssalamIRN,ve306MazanIRN),(ve240VazIRN,((ve115AssalamIRN,(ve209VazIRN,(ve153AssalamIRN,((ve207VazIRN,ve312SirinRudIRN),ve144AssalamIRN)))),((hd218CGreece,hd223CGreece),(tv110Georgia,((hd252CGreece,hd247CGreece),ve140AssalamIRN)))))))))))))),(((((gd116EmigUtah,(gd035MorArb,((gd241ZionNP,(gd126EmigUtah,gd114EmigUtah)),gd025MorArb))),(fd102FloridaCavSP,(fd119FloridaCavSP,(sc140RenssCoNY,(ni101AlbanyNY,(ni209AlbanyNY,ni206AlbanyNY)))))),((ms408BdlHerreriaE,(ms1908VaucluseF,((ms714VdCeleF,((ms903VdCeleF,(ms703VdCeleF,ms814VdCeleF)),ms718VdCeleF)),(ms2131GordesF,((ms1704GdlNesqueF,ms1705GdNesqueF),(ms1226GdlJonteF,((ms1315GdlJonteF,(ms1305GdlJonteF,(ms921VdCeleF,ms512VdCeleF))),ms411BdlHerreriaE))))))),((((((ib113AlpadGEO,hy102Iran),ib303NorawARM),ib402AlpadGEO),ib111AlpadGEO),(hy153Iran,hy133Iran)),(ib108AlpadGEO,ib403AlpadGEO)))),(((pp4004VdHeraultF,pp3012LdAydatF),(pp2804QuilanF,(pp3008LdAydatF,(pp3502GdJonteF,(pp2704Luxembg,((pp2209Hungary,pp2829QuilanF),(pp2247BudapestH,(pp3013LdAydatF,(pp2517Luxembg,(pp3405GdTarnF,(pp4007VdHeraultF,(pp3911cultSWGer,(pp3801CseSauvetF,(pp1702natBGTue,pp3009LdAydatF)))))))))))))),((us1104LovecBUL,us1109LovecBUL),(sv4a2DiktiCrete,(of110Cyprus,(((sv4a5DiktiCrete,(sv207Crete,(sv201Crete,sv204Crete))),sv102Crete),(sv4a3DiktiCrete,sv124Crete))))))),((ot103BGTue,(ot207AetnaSicily,(op1227GdJonteF,(ot202AetnaSicily,(op502CaussolsF,ot105BGTue))))),(op1201GdJonteF,(op702ArezzoI,(op509CaussolsF,(op1228GdJonteF,(op1607CseNoirF,(op816VdAudeF,((op1203GdJonteF,(op1374GdTarnF,op1432VdLotF)),((op1516CseNoirF,(op1334GdTarnF,op407StVallierF)),op404StVallierF))))))))))),(((se_025BGTue,se_021BGTue),((tt109NovosRus,tt_008BGTue),(tt107NovosRus,(us1201cultSENebr,(gi_021BGTue,(tt_014BGTue,(az123AA37692bW,(az112AA37692bW,(gi104ZhejiangBG,(us_903AlterBG,gi_022BGTue)))))))))),(cf_127BGTue,((cf_004BGTue,cf_001BGTue),cf_002BGTue)))),((cm001MorArb,(cm002MorArb,cm004MorArb)),(ga154ShenHubei,(ga122ShenHubei,ga131ShenHubei))))),((((la124Indonesia,(la107Indonesia,la102Indonesia)),la105Indonesia),((py002SeattleArb,py009SeattleArb),(ru_103NEStates,(ru_007BGTue,(ru_025BGTue,((sa_421SENebr,sa_424SENebr),(sa_406SENebr,(sa_109wieri,(sa_105wieri,sa_403SENebr))))))))),((pi108MtMNurs,pi105MtMNurs),((((pt109MunechMat,pt103MuenchMat),(ma102TS16051W,(ma103TS16051W,(ma104TS16051W,ma105TS16051W)))),((mx047MorArb,(mx053MorArb,((mx007MorArb,mx019MorArb),(mx017MorArb,mx001MorArb)))),((gr015BGTue,gr118PRChina),(tf_004MorArb,(tf_003MorArb,(gr128PRChina,(gr007BGTue,(gr001BGTue,gr002BGTue)))))))),((bu326ZhejiangBG,((bu301ZhejiangBG,(bu004BGTue,(bu324ZhejiangBG,bu328ZhejiangBG))),(bu015BGTue,(bu040BGTue,bu045BGTue)))),(ob114Taiwan,(co011ZhejiangBG,(co017ZhejiangBG,(co031ZhejiangBG,ob106Taiwan))))))))))),Di145BGTue,Di106BGTue); ExaML-3.0.21/testData/49000066400000000000000000001634061330315463200145050ustar00rootroot0000000000000049 1200 Seq1 ATGACCAACATTCGAAAATCACACCCCCTTATCAAAATCGTTAATCACTCATTCATCGATTTACCCACCCCACCTAACATTTCAGCATGATGAAACTTCGGCTCCCTACTAGGAGTCTGCCTAGTCCTACAGATCCTAACCGGCCTTTTCCTAGCCATACACTACACATCAGACACAATAACCGCCTTTTCATCAGTTACTCACATCTGCCGCGACGTCAACTACGGCTGAATTATTCGATACATGCACGCCAACGGAGCCTCTATATTCTTTATCTGCCTATACATGCATGTAGGACGAGGAATATACTACGGCTCCTACACCTTCTCAGAAACATGAAATATTGGAATCATACTACTACTCACAGTCATAGCCACAGCCTTCATAGGATATGTCTTACCATGAGGTCAAATATCTTTCTGAGGAGCAACTGTAATTACCAACCTCCTATCAGCAATTCCTTACATCGGCACTAATCTAGTAGAGTGAATTTGAGGAGGTTTCTCGGTAGACAAAGCTACCCTGACACGATTCTTTGCCTTCCACTTTATCCTTCCATTCATCATCTCAGCCCTAGCAGCAGTACACCTCTTATTTCTCCACGAGACAGGATCCAATAACCCCTCAGGAATCACATCCGACTCAGACAAAATTCCATTCCACCCATACTACATAATCAAGGACATTCTAGGTCTCCTAATACTAATTTTAATACTCACACTACTCGTCCTCTTCTCACCAGACCTGTTAGGAGATCCAGACAACTACATCCCCGCCAACCCCCTAAACACTCCTCCCCATATTAAACCCGAATGATATTTTTTATTCGCATACGCAATCCTCCGATCCATCCCTAACAAATTAGGAGGAGTCCTAGCCCTAATATTCTCCATCCTAATCCTAGCAATCATTCCAATTTTCCACACCTCCAAACAACGAGGAATAATATTTCGACCACTAAGCCAATGCTTATTCTGACTCCTAGTAGCAGACCTCCTCACCCTAACATGAATTGGCGGCCAACCTGTAGAACACCCCTTTATTACCATCGGCCAACTAGCCTCCATTCTATACTTCTCAACCCTCCTAGTTCTAATACCTATTTCAGGCATCATCGAAAACCGCCTCCTA------AAATGA------------------------------------------------------AGA Seq2 ATGAAAATTATACGAAAAACACACCCACTCCTAAAAATCATTAACCATGCATTCGTCGACCTCCCTGCACCCTCCAACATCTCATCATGATGAAACTTCGGCTCTCTATTAGGAGTATGCCTAATAATCCAAATCCTCACAGGACTGTTTCTAGCAATACACTACACCTCAGACACTATAACAGCATTCTCATCCGTAACCCACATCTGCCGAGACGTAAATTACGGTTGACTGATTCGATACCTCCATGCAAACGGAGCCTCCATGTTCTTCATGTGCTTATTCATACACGTAGGACGAGGCATCTACTATGGGTCCTACACCTTTATAGAGACATGAAACCTTGGTATTATTCTACTGTTTGCCGTAATAGCAACTGCATTTATAGGATATGTCCTCCCATGGGGGCAAATATCCTTCTGAGGGGCCACAGTCATCACAAACCTACTTTCAGCCATCCCCTACATCGGTACTAACCTAGTAGAATGAATCTGAGGCGGATTTTCAGTAGACAAAGCCACCCTTACACGCTTCTTCGCATTCCACTTTATCCTCCCCTTTATTATTGCAGCTCTGGCCATGGTACACCTACTTTTTCTCCACGAAACAGGCTCTAATAACCCCACAGGAATGAACTCCGATGCAGACAAAATCCCCTTCCACCCCTACTACACAATCAAAGACCTCTTAGGTGTATTCCTCATACTGTCAGTCCTCCTCCTATTAGTACTTTTCTCCCCAGACCTATTAGGAGACCCCGACAACTATACACCAGCTAACCCCCTAAACACCCCTCCTCACATTAAGCCAGAATGATACTTTCTATTTGCATATGCTATCCTACGCTCTATCCCCAACAAACTAGGAGGCGTATTAGCCCTAGTACTATCCATCCTAATCCTAGCTTTTATACCTCTCACCTACACCTTAAAACAACGAATCTTAATATTCCGCCCAATCAGCCAGACCATATTCTGAATCCTAGCAGCCAACCTACTTATCCTAACCTGAATCGGAGGACAACCCGTAGAACACCCCTTCATCATTATTGGCCAACTAGCTTCAATCAGCTACTTCTCCATCATTTTAATTCTAATACCAATCTCAGGACTAATCGAAAACAAAATACTAAAACTA------AAC---------------------------------------------------T-- Seq3 ATGAAAATTATACGAAAAACACACCCACTCCTAAAAATCATTAATCACGCATTCGTCGACCTCCCTGCACCCTCTAACATCTCATCATGATGAAACTTCGGCTCCCTATTAGGAGTATGCCTAATAATCCAAATCCTCACAGGACTATTTCTAGCAATACACTACACCTCCGACACTACAACAGCATTCTCATCCGTAACCCACATCTGCCGAGACGTAAACTACGGCTGATTAATTCGATACCTCCATGCAAATGGGGCTTCCATATTCTTCATGTGCTTATTCATACACGTAGGACGAGGCATTTATTATGGGTCTTACACCTTCACAGAGACATGAAACCTTGGTATCATTCTACTGTTTGCCGTAATAGCAACTGCATTTATAGGATATGTCCTTCCATGGGGACAAATATCCTTCTGAGGGGCCACAGTCATTACAAACCTACTCTCAGCCATCCCCTACATCGGCACTGACCTGGTAGAGTGAATCTGAGGCGGGTTTTCAGTAGACAAAGCCACCCTTACACGCTTCTTCGCATTCCACTTTATTCTCCCCTTTATCATTGCAGCCCTAGCCATAGTACACCTACTCTTTCTACACGAAACAGGCTCTAATAACCCCACAGGAGTGAACTCCGATGCAGACAAAATCCCCTTCCACCCCTACTACACAATCAAAGACCTTTTAGGTGTATTCCTCATACTATTAGTCCTCCTCCTATTAGTACTATTCTCCCCAGACCTACTAGGAGACCCCGACAACTACACACCAGCTAACCCCCTGAACACCCCTCCTCACATTAAACCAGAATGATATTTCCTATTCGCATATGCTATTCTACGCTCCATCCCCAACAAACTCGGAGGCGTACTAGCTCTAGTAATATCTATCCTAATCCTAATTTTCATACCCCTCACCCACACCTCAAAACAACGAAGCTTAATATTCCGCCCAATCAGTCAGGCTATATTCTGAATCCTAACAGCTAACCTACTTATCCTAACCTGAATCGGAGGACAACCCGTAGAACACCCCTTTATCATTATCGGCCAACTAGCTTCAATCAGCTATTTCTCCATCATTTTAATCCTAATACCAATCTCAGGACTAATTGAAAACAAAATACTAAAATTA------AAC---------------------------------------------------T-- Seq4 ATGAAAATTATACGAAAAACACACCCACTCATAAAAATTATCAACCACGCATTCATCGATCTCCCTGCACCCTCCAACATCTCATCATGATGAAACTTTGGTTCTCTATTAGGAGTATGCCTAATAGTCCAAATCCTCACAGGCCTATTCTTAGCAATACACTACACCTCCGACACTATAACAGCATTCACATCCGTAACCCACATCTGCCGAGACGTAAACTACGGCTGATTAATTCGATATCTCCATGCAAACGGAGCCTCCATATTCTTCGTATGCTTGTTTATACACGTAGGACGAGGAATCTACTATGGATCTTACACCTTTACAGAAACATGAAATCTTGGTGTTATTCTACTATTTGCCGTAATAGCAACTGCATTTATAGGATATGTACTTCCATGAGGACAAATATCCTTCTGAGGAGCCACAGTCATTACAAACCTTCTCTCAGCTATTCCCTACATCGGTACTAACCTAGTAGAATGAATTTGAGGGGGGTTCTCAGTAGACAAAGCCACCCTCACACGCTTCTTCGCATTCCACTTTATCCTTCCATTTATCATTGCAGCCCTAGCCATAGTACACCTACTATTCCTCCACGAAACAGGCTCTAATAACCCCACAGGAATGAACTCTGACGCAGATAAAATTCCCTTTCACCCCTACTATACAATCAAAGACCTCTTAGGCGTATTTCTCATACTACTAGTTCTCCTACTATTAGTACTATTTTCCCCAGACTTATTAGGAGACCCCGACAACTACACACCAGCCAACCCCCTAAATACCCCTCCCCACATTAAACCAGAGTGATATTTTCTATT-GCATACGCTATCCTACGCTCTATCCCCAATAAACTTGGAGGCGTACTAGCCCTAGTACTATCTATCCTAATCCTAATTCTCATACCCTTAATCCATACCTCAAAACAACGAAGCTTAATATTCCGTCCAATTAGCCAAATCATATTCTGAATCCTAACAGCTAACCTACTCATCCTGACCTGAATCGGAGGACAACCCGTAGAACATCCCTTTATCATTATCGGCCAACTAGCTTCAATCAGCTATTTCTCCATTATTCTAATCCTAATACCGATCTCAGGACTAATTGAAAATAAAATACTAAAATTA------AAC---------------------------------------------------T-- Seq5 ATGAAAAACATACGAAAAACGCAACCACTCCTAAAAATTATTAACCACGAATTCATTGA-TTTCCTGAAACATCCAA-ATCTCATCATGATGAAACTTTGGCTCTCTACTAGGCATCTGCCTAGTAATCCAGATCCTAACAGGCTTATTCCTAGCAATACACTATACCTCCGACACCACCACAGCATTTTCATCTGTAACCCACATTTGCCGAGACGTAAACTACGGCTGACTGATTCGTTACCTCCATGCAAATGGAGCCTCCATATTCTTCATGTGCCTGTTCATACATGTAGGACGGGGAATCTACTACGGATCTTATACCTTCATAGAAACCTGAAATCTCGGCATTATTCTACTGTTCGCCGTAATAGCAACTGCATTTATAGGATATGTACTCCCATGAGGACAGATATCCTTCTGAGGGGCCACAGTCATTACAAATCTACTCTCAGCTATCCCCTACATCGGAACTAATCTAGTAGAGTGAATTTGAGGAGGCTTCTCAGTAGACAAAGCCACTCTAACACGCTTTTTCGCATTCCACTTTATCCTACCCTTTATCATTGCAGCCCTAGCTATAGTCCACCTACTATTCCTCCACGAAACAGGATCTAACAA-CCCACCGGGATAAACTCTGACGCAGATAAAATCCCCTTTCATCCCTACTACACAATTAAAGATCTCCTAGGAGTATTCCTAATATTAACAGCCCTACTCTTATTAGTCCTCTTCTCCCCAGACTTATTAGGAGACCCCGACAACTACACACCAGCCAACCCCCTAAACACCCCTCCCCACATCAAACCAGAATGATATTTCCTATTTGCATACGCCATCCTACGCTCTATTCCTAACAAACTCGGAGGAGTACTAGCCCTAGTGCTATCAATCCTAATCCTAATTTTTTTACCCTTCATCCACACTTCCAAACAACGAAGCCTAATATTCCGCCCAATCAGCCAAACCATATTTTGAATCCTAGCAGCAAATCTTCTTGTCCTAACCTGAATCGGAGGACAACCTGTAGAATACCCCTTCACCATTATTGGCCAACTAGCCTCAATCAGTTATTTCTCTATTATCCTAATCCTACTACCAATCTCAGGTCTAATC-AAAATAAAATAATAAAAATA------AAC---------------------------------------------------T-- Seq6 ATGAAAATTATACGAAAAACACACCCACTCCTAAAAATCATTAATCACGCATTCGTCGACCTCCCTGCACCCTCTAACATCTCATCATGATGAAACTTCGGCTCCCTATTAGGAGTATGCCTAATAATCCAAATCCTCACAGGACTATTTCTAGCAATACACTACACCTCCGACACTACAACAGCATTCTCATCCGTAACCCACATCTGCCGAGACGTAAACTACGGCTGATTAATTCGATACCTCCATGCAAATGGGGCTTCCATATTCTTCATGTGCTTATTCATACACGTAGGACGAGGCATTTATTATGGGTCTTACACCTTCACAGAGACATGAAACCTTGGTATCATTCTACTGTTTGCCGTAATAGCAACTGCATTTATAGGATATGTCCTTCCATGGGGACAAATATCCTTCTGAGGGGCCACAGTCATTACAAACCTACTCTCAGCCATCCCCTACATCGGCACTGACCTGGTAGAGTGAATCTGAGGCGGGTTTTCAGTAGACAAAGCCACCCTTACACGCTTCTTCGCATTCCACTTTATTCTCCCCTTTATCATTGCAGCCCTAGCCATAGTACACCTACTCTTTCTACACGAAACAGGCTCTAATAACCCCACAGGAGTGAACTCCGATGCAGACAAAATCCCCTTCCACCCCTACTACACAATCAAAGACCTTTTAGGTGTATTCCTCATACTATTAGCCCTCCTCCTATTAGTACTATTCTCCCCAGACCTACTAGGAGACCCCGACAACTACACACCAGCTAACCCCCTGAACACCCCTCCTCACATTAAACCAGAATGATATTTCCTATTCGCATATGCTATTCTACGCTCCATCCCCAACAAACTCGGAGGCGTACTAGCTCTAGTAATATCTATCCTAATCCTAATTTTCATACCCCTCACCCACACCTCAAAACAACGAAGCTTAATATTCCGCCCAATCAGTCAGGCTATATTCTGAATCCTAACAGCTAACCTACTTATCCTAACCTGAATCGGAGGACAACCCGTAGAACACCCCTTTATCATTATCGGCCAACTAGCTTCAATCAGCTATTTCTCCATCATTTTAATCCTAATACCAATCTCAGGACTAATTGAAAACAAAATACTAAAATTA------AAC---------------------------------------------------T-- Seq7 ATGAAAATTATACGAAAAACACACCCACTCCTAAAAATCATTAATCACGCATTCGTCGACCTCCCTGCACCCTCTAATATCTCATCATGATGAAACTTCGGCTCCCTATTAGGAGTATGCCTAGTAATCCAAATCCTCACAGGATTATTTCTAGCAATACACTACACCTCCGACACTATAACAGCATTCTCATCCGTAACCCACATCTGCCGAGACGTAAACTACGGCTGATTAATTCGATACCTCCATGCAAATGGGGCTTCCATATTCTTCGTGTGCTTATTCATACACGTAGGACGAGGCATTTATTATGGATCTTACACCTTCACAGAGACATGAAACCTTGGTATCATTCTACTGTTTGCCGTAATAGCAACTGCATTTATAGGGTATGTCCTTCCATGGGGACAAATATCCTTCTGAGGGGCCACAGTCATTACAAACCTACTCTCAGCCATCCCCTACATCGGCACTGACCTGGTAGAGTGAATCTGAGGCGGGTTTTCAGTAGACAAAGCCACCCTTACACGCTTCTTCGCATTCCACTTTATTCTCCCCTTTATCATTGCAGCCCTAGCCATAGTACACCTACTCTTTCTACACGAAACAGGCTCTAATAACCCCACAGGAGTAAACTCCGATGCAGACAAAATCCCCTTCCACCCCTACTACACAATCAAAGACCTTTTAGGTGTTTTCCTCATACTATTAGTCCTCCTCCTACTAGTACTATTCTCCCCAGATCTACTAGGAGACCCCGACAACTACACACCAGCTAACCCCCTGAACACCCCTCCTCACATTAAACCAGAATGGTATTTCCTATTCGCATATGCTATTCTACGCTCCATCCCCAACAAACTCGGAGGTGTACTAGCTCTAGTAATATCTATCCTAATCCTAATTTTCATACCCCTCACCCACACCTCAAAACAACGAAGCTTAATATTCCGCCCAATCAGTCAGGCTATATTCTGAATCCTAACAGCTAACCTACTTATCCTAACCTGAATCGGAGGACAACCCGTAGAACACCCCTTTATCATTATCGGCCAACTAGCTTCAATCAGCTACTTCTCCATTATTTTAATCCTAATACCAATCTCAGGACTAATTGAAAACAAAATACTAAAATTA------AAC---------------------------------------------------T-- Seq8 ATGAAAAACATACGAAAATCACACCCACTACTAAAAATCATTAATCTCGCATTTATTGACCTACCCGCACCATCCAATATCTCATCATGATGAAACTTTGGGTCCCTTCTAGGAGTCTGTCTAGTAGTACAAATTATCACAGGACTATTTCTAGCAATACACTACACCTCTGATACCACAACAGCATTTTCATCTGTAACTCATATCTGCCGAGATGTAAACTACGGTTGATTGATTCGATATCTTCATGCAAACGGAGCCTCAATATTCTTCATGTGCCTATTTATACACGTAGGACGAGGAATCTACTACGGATCCTACACCTTTACAGAAACCTGAAATATTGGCATTATTCTACTGTTCGCCGTAATAGCAACTGCATTTATAGGATATGTGCTTCCCTGAGGACAAATATCCTTCTGAGGAGCCACAGTTATTACTAACCTTCTCTCAGCAGTTCCCTACATCGGTACTAATTTAGTAGAATGAATCTGAGGGGGGTTCTCAGTAGACAAAGCCACTCTTACACGCTTCTTCGCATTCCATTTTATCCTCCCATTCATCATTGCAGCCCTAGCTATAGTCCACCTACTTTTTCTCCACGAAACTGGATCCAATAACCCCACCGGAATCAACTCTGATGCAGACAAAATTCCATTCCATCCGTACTACACTATAAAAGACTTCCTAGGGGCCCTACTCATGTTAGTAGTTCTACTCCTACTTGTTTTATTTTCCCCAGATATTTTAGGCGACCCAGATAATTATACACCAGCTAACCCCCTAAACACACCTCCTCACATCAAACCAGAGTGATATTTCCTATTCGCCTACGCTATCCTACGTTCTATCCCCAATAAACTAGGAGGAGTGTTAGCTTTAGTACTATCCATCCTTGTCCTAGCCTTGCTACCTCTCATGCACACCTCAAAACAACGAAGCCTTATGTTCCGCCCAATTAGCCAAATCCTATTTTGAATACTAACAGCTAATCTTCTAATTCTAACCTGAATTGGGGGACAACCAGTAGAACACCCCTTCATTATCATTGGACAAGTAGCTTCAATCAGCTACTTCTCTATTATTTTAATCCTAATACCAATCTCAGGACTAATCGAAAACAAAATACTAAAACTT------------------------------------------------------------T-- Seq9 ATGACAAACATCCGAAAAACACACCCCCTACTTAAAATTATTAATAACGCATTCATTGACCTACCAGCCCCATCCAACATTTCATCATGATGAAACTTCGGGTCTTTACTAGGAATCTGCTTAATCATCCAAATCATCACAGGACTTTTCCTAGCCATACATTACACCTCAGACACCTCAACAGCATTCTCATCTGTTACCCATATTTGCCGAGATGTAAACTACGGTTGACTTATTCGCTATCTTCATGCAAACGGAGCCTCCATATTCTTTGTCTGCTTATTTATACATGTTGGACGAGGAATCTATTACGGATCTTATACCTACATAGAAACATGAAATATCGGCATCATTCTACTGTTCGCCGTAATAGCAACTGCATTTATAGGATATGTACTTCCATGAGGACAAATATCTTTTTGAGGGGCCACAGTCATTACCAACCTACTATCAGCTATCCCTTACATTGGCACTAACTTAGTAGAATGAATTTGAGGTGGATTTTCCGTAGATAAAGCCACCCTAACACGATTCTTCGCCTTCCACTTTATTCTCCCATTTATCATCGCTGCCCTAGCCATAGTTCATCTTCTTTTCCTTCACGAAACAGGATCTAATAATCCTACCGGAATTAACTCCGACACTGACAAAATTCCCTTTCATCCTTACTACACAACAAAAGACCTATTAGGAGCTCTAATACTCATTATAGTCCTACTAGCACTAGTATTATTTTCACCTGACCTCCTAGGAGACCCAGATAACTACACACCAGCTAACCCATTAAATACACCTCCCCATATCAAACCAGAATGATATTTCTTATTCGCCTACGCAATCCTCCGATCCATCCCTAACAAACTAGGAGGAGTCTTAGCCCTGGTCTTATCAATCCTAGTCCTAGCAATCCTCCCACTAATCCACACCTCAAAACAACGAAGCCTCATATTCCGCCCAATTAGCCAAACCCTATTCTGAATCCTAGTGGCCAACCTATTAATCCTTACCTGAATCGGAGGACAACCCGTAGAACACCCCTTCATCATCATCGGCCAACTAGCTTCCATCAGCTACTTCACAATCATCCTAACTCTCATTCCTATCTCAGGCCTAATCGAAAATAAAATAATG------AAATGAAAC---------------------------------------------------T-- Seq10 ATGACTAACATTCGAAAAACTCACCCACTGATAAAAATTGTAAACAACGCATTTATCGACCTCCCAGCCCCATCAAACATTTCATCATGATGAAACTTTGGCTCCCTACTAGGCATCTGCCTAATCCTGCAAATCTTAACAGGCCTATTCCTAGCGATACACTACACATCCGACACAACAACAGCATTCTCCTCTGTCGCCCACATTTGCCGAGACGTCAATTATGGCTGAATCATCCGATACATACACGCAAACGGAGCATCAATATTTTTTATCTGCCTATTCATACACGTAGGACGAGGCCTCTACTATGGGTCATATACCTTCCTAGAAACATGAAACGTCGGAGTAATCCTCCTATTTACAACAATAGCCACAGCATTTATAGGCTATGTCCTGCCATGAGGACAAATATCATTCTGAGGAGCAACAGTCATCACCAACCTTCTCTCAGCAATCCCATATATCGGCACAGACCTGGTCGAATGAATCTGAGGAGGATTCTCCGTAGACAAAGCAACCCTTACCCGATTTTTCGCCTTCCACTTTATTCTCCCCTTTATTATCGCTGCCCTTGCCATAGTCCATCTACTCTTTCTCCACGAAACAGGCTCCAACAACCCTACAGGAATCTCCTCAGACACAGACAAAATCCCATTCCACCCTTACTATACCATTAAAGACATCTTAGGCGCCCTACTACTAATTCTAGTCCTCATACTACTAGTATTATTCACACCCGACCTACTTGGAGACCCAGACAATTATACCCCAGCAAATCCACTTAGCACGCCCCCTCACATCAAACCTGAATGATATTTCCTATTTGCATACGCAATTCTACGATCAATCCCCAACAAACTAGGAGGAGTTCTAGCCTTAGTCCTCTCAATCCTAATCCTGGTACTCGTACCCGCACTCCACACATCCAAGCAACGAAGCATAATATTTCGACCAATCAGCCAATGCATTTTCTGAATCTTAGTAGCAGACCTATTAACACTCACATGAATCGGAGGACAACCAGTTGAACACCCATACATTATTATTGGACAATTAGCATCTATCACATACTTCCTACTTATCCTAGTACTTATACCAGTAGCCAGTACTATTGAAAATAACCTTCTA------AAATGA------------------------------------------------------AGA Seq11 ATGACAAACATCCGAAAAATTCATCCCCTAATAAAAACCATTAACCACTCCTTCATTGATCTCCCCGCACCATCCAACATCTCATCATGATGAAACTTCGGCTCTCTACTAGGAATTTGCTTAATAGTACAAATCATCACAGGTCTATTCTTAGCCATACATTATACATCAGACACAACAACAGCATTTTCATCAGTAACCCATATCTGCCGAGACGTAAATTATGGATGACTAATCCGATATATACATGCAAACGGAGCCTCAATGTTCTTCATCTGCTTATTCCTTCATGTAGGACGAGGAATATACTATGGATCTTATACATTCCTAGAAACATGAAACATCGGAGTGATTTTATTATTTACAGTCATAGCCACTGCATTCATAGGATATGTCCTTCCATGAGGACAAATATCATTCTGAGGGGCCACAGTAATTACAAACTTACTTTCAGCCATCCCATATATTGGCACAATCCTAGTAGAATGAATCTGAGGCGGATTCTCAGTAGACAAGGCTACTTTAACACGCTTTTTCGCATTTCACTTCATCTTACCATTCATTATTGCCGCCTTAGCAATCGTTCACCTACTATTTCTACATGAAACAGGCTCAAATAATCCAACAGGACTTAACTCAGATGCAGACAAAATCCCCTTCCACCCTTACTATACCATCAAAGATATTCTAGGAATCATAATTATACTTCTACTATTAATAATTTTAGTATTATTCTTTCCCGACTTACTAGGAGACCCTGACAATTATATGCCAGCTAACCCACTCAACACCCCTCCACACATCAAACCAGAATGATACTTCCTATTTGCTTACGCCATCCTACGCTCCATCCCTAATAAACTAGGAGGTGTACTTGCCCTAATTCTATCTATCCTTATTCTAGCCTTCCTACCCTTCCTTCACACCTCAAAACAACGCAGCCTAATTTTCCGCCCAATCACCCAAACCCTATACTGACTTCTAGTAGCAAATCTACTCATCCTAACCTGAATCGGAGGGCAACCAGTAGAACACCCATTCATCATTATTGGACAACTAGCCTCCATTAGTTACTTCTCCATTATCCTTATTCTAATACCAATCTCAGGTATAATCGAAAATAAAATACTA------AAATGAAAC------------------------------------------------------ Seq12 ATGACAAACATCCGAAAAACTCATCCCTTAATAAAAATTATTAATCATTCATTCATTGATCTTCCCGCACCATCCAACATCTCATCATGATGAAATTTCGGCTCCCTATTAGGAATCTGCCTAACAGTACAAATTGCCACAGGCCTATTTCTAGCCATACATTATACATCAGATACAACAACAGCATTCTCATCAGTAGCCCACATTTGCCGAGACGTAAATTACGGATGATTTATCCGATATATACATGCAAACGGAGCTTCCATATTTTTCATATGCCTATTCCTCCACGTAGGACGAGGAATATATTACGGATCCTACACATTTCTAGAAACATGAAATATCGGAGTAATTCTTCTATTTGCAGTTATAGCCACTGCATTCATAGGATATGTCCTTCCATGAGGACAAATATCATTTTGAGGAGCTACAGTAATTACAAATCTACTCTCAGCCATCCCATACATTGGCAGTACTTTAGTAGAGTGAATCTGAGGTGGATTCTCAGTAGACAAAGCTACTTTAACACGCTTTTTCGCATTTCACTTTATCTTACCATTCATCATTGCAGCCCTTGCAATCGTTCATTTATTATTCTTACATGAAACAGGCTCAAATAACCCAATAGGACTAAACTCAGACGCAGACAAAATTCCATTTCACCCCTACTATACTACCAAAGATATTCTAGGAATTTTAATTATACTAACACTACTAATAATCCTAGTATTATTCTTTCCAGACCTACTAGGAGACCCCGACAACTATATACCAGCCAATCCACTCAACACCCCTCCTCATATTAAACCAGAATGATATTTTCTATTTGCCTATGCCATCCTTCGTTCCATCCCTAACAAACTAGGAGGTGTAGTGGCCTTAATCCTATCTATCCTTATCCTAGCCCTCCTACCACTCCTACATACCTCAAAACAACGCAGCCTAATATTCCGCCCAATTACCCAAACTCTTTACTGAATACTAGTAGCAAACTTAATTATCTTAACCTGAATCGGAGGTCAACCCGTAGAACACCCATTCATCATTATTGGCCAACTAGCCTCCATCAGCTACTTCTCTATTATTCTCATTCTAATACCAATCTCAGGCATCATTGAAAACAAAATATTA------AAATGAAAC------------------------------------------------------ Seq13 ATGACAAACATCCGAAAAACCCATCCCCTATTCAAAATTATTAATCACTCATTCATTGACCTTCCAGCCCCATCCAACATCTCATCATGATGAAACTTCGGTTCACTTCTTGGAATCTGCTTAATAGTCCAAATTTTAACTGGCTTATTCTTAGCTATACACTACACCTCCGACACACTAACAGCATTCTCATCAGTAACCCACATCTGTCGAGACGTTAATTACGGCTGATTGGTACGATATATACACGCAAATGGAGCCTCAATATTCTTCATCTGCCTATTTATACACGTAGGACGAGGTATATACTACGGATCATACACATTTTTAGAAACATGAAACATCGGGGTAATTCTTTTATTTACAGTAATAGCTACCGCATTTATAGGTTATGTACTCCCATGAGGACAAATATCATTTTGAGGGGCAACAGTAATTACAAACTTACTATCTGCCATTCCATACATTGGAACTACTTTAGTAGAATGAATCTGAGGAGGATTCTCAGTAGATAAAGCCACCCTAACCCGATTCTTCGCATTTCACTTCATTTTACCATTCATCATTACAGCCCTCGTAATTGTTCACCTCTTATTCCTGCACGAAACAGGCTCCAACAACCCAACAGGACTAAATTCAGACGCAGACAAAATTCCATTTCATCCATATTATACCATCAAAGACATTCTAGGGATATTAATTATACTAGTACTCCTAATAATTCTAGTCTTATTCTTTCCAGACTCATTAGGAGACCCAGACAACTATATACCAGCCAACCCACTTAACACCCCCCCACATATCAAACCAGAATGATACTTCCTATTTGCCTACGCTATTCTACGGTCCATCCCTAATAAACTAGGAGGGGTACTAGCTCTAATTATATCCATTCTAATCCTAGTTTTTTTACCTTACCTTCATACCTCAAAACAACGCAGTCTAATATTCCGGCCAATTACTCAAATATTATACTGACTATTAGTAGCAAACTTACTAATTCTAACCTGAATCGGAGGTCAACCTGTAGAACACCCATTTATTATCATTGGTCAACTAGCCTCTATCAGCTATTTCTCCATTATTCTAATCCTCATACCAATTGCAGGCATCATCGAAGACAAAATACTA------AAATGAAAC------------------------------------------------------ Seq14 ATGATCAACATCCGAAAAACTCATCCATTAGTTAAAATTATCAACAACTCATTCATTGACCTTCCAACACCATCAAACATTTCAACATGATGGAACTTTGGGTCCCTGTTAGGAGTGTGTCTGATCTTGCAAATCTTAACAGGCTTATTTCTAGCCATACACTATACATCAGATACAGCTACAGCCTTTTCATCAGTCGCACACATTTGTCGAGACGTCAACTATGGGTGATTTATCCGATATATACATGCCAATGGGGCCTCTATATTTTTTATCTGCCTATTTATACACGTAGGGCGAGGCTTATACTATGGATCATACCTATTTCCAGAGACATGGAATATCGGAATTATTCTCCTACTTACAATTATAGCCACCGCATTTATAGGATACGTCCTACCCTGAGGCCAAATGTCCTTCTGAGGAGCGACTGTCATCACCAACCTACTATCGGCCATTCCCTACATCGGAACGAACCTAGTAGAATGAATCTGAGGGGGCTTTTCCGTAGATAAGGCGACCCTAACACGATTCTTTGCTTTCCACTTTATCCTTCCATTTATCATCTCAGCACTAGCAATAGTCCATCTATTATTCCTTCACGAAACAGGATCTAATAACCCCTCCGGAATTCCATCTGACCCAGACAAAATCCCATTTTACCCCTATCATACAATTAAAGACATCCTAGGCGTCCTATTTCTTGTCCTCGCCTTAATAACCCTGGCTTTATTCTCACCAGACCTGTTAGGAGACCCTGATAACTATACCCCTGCAAATCCACTAAGTACCCCGCCACATATTAAGCCTGAATGGTACTTTCTATTTGCCTACGCTATCCTGCGATCCATTCCTAATAAACTAGGAGGGGTGCTAGCTCTAATCTTCTCTATTCTAATTCTAACTATTATTCCACTATTACATACATCCAAACAACGAAGCATGATATTCCGACCTCTAAGTCAATGCTTATTCTGACTCCTAGTAGCAGACCTACTCACACTAACATGAATTGGAGGACAGCCAGTAGAACACCCCTTCATTATTATTGGGCAATTGGCCTCTATTCTCTACTTTACAATTCTTCTAGTACTTATACCTATCACTAGCATTATTGAGAATAGCCTCTCA------AAATGA------------------------------------------------------AGA Seq15 ATGAAAATTTTACGGAAAAATCACCCGCTACTTAAAATTGTTAATCATTCATTTATTGACCTCCCAACCCCATCTAACATCTCATCTTGATGGAATTTCGGGTCACTACTCGGTGTGTGCCTAGTAATCCAAATTCTGACCGGCCTATTCCTAGCCATACACTACACATCAGACACAACCACAGCATTCTCCTCAGTTGCCCACATTTGCCGAGATGTAAACTACGGATGATTAATTCGCTACCTTCACGCTAACGGAGCCTCCATATTCTTTATCTGCCTTTTCATCCACGTAGGCCGAGGAATCTACTACGGCTCCTATGTCCTCTCAGAAACCTGAAACATCGGTATCATCCTGTTCCTTACAACTATAGCAACAGCATTCGTAGGGTATGTTCTACCGTGGGGACAAATATCCTTCTGAGGAGCTACCGTAATCACAAACCTCCTCTCAGCAATCCCATACATCGGAAGCACCCTTGTTGAATGAATTTGAGGGGGCTTCTCAGTTGATAAAGCCACCCTAACCCGCTTCTTCGCCTTCCATTTTATTCTGCCTTTTATCATCACGGCCTTCGCCTTAGTCCACCTATTATTCCTTCACGAGACAGGATCCAACAACCCATCAGGCTTAAACTCAGACTCCGACAAAATCCCATTCCACCCCTACTACACAATCAAAGATCTCCTGGGCATCTTCCTCCTATTATTAATTCTCATAACTTTAGCCCTATTTTTCCCAGATGTCCTTGGAGACCCAGACAATTTTACCCCAGCAAACCCCCTCAACACTCCAGCACACATCAAGCCAGAATGATATTTCCTATTTGCTTACGCCATCCTTCGGTCTATCCCCAACAAACTTGGAGGTGTGTTAGCCCTTATTCTCTCTATTCTCATTTTAGCAACGTTCCCACTACTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTATCACACAAACCATTTACTGAACTTTTATCGCCAACCTTCTCGTACTTACATGAATTGGGGGGCAACCCGTTGAATACCCATTCACAACAATTGGACAAATCGCATCAATCACCTACTTCACTATTATTATCATTTTAATGCCAGTCTCTAATACCATCGAGAACAACATCATCAAACTT------------------------------------------------------------TAG Seq16 ATGAAAATTTTACGGAAAAACCACCCGCTACTTAAAATTGTTAATCACTCATTTATTGACCTCCCAACCCCATCCAACATCTCATCTTGATGAAATTTTGGGTCACTACTCGGTGTATGCCTAATAATTCAAATTCTGACTGGCCTATTCCTAGCCATACACTACACATCAGACACAACCACAGCATTCTCTTCAGTTGCCCACATTTGCCGAGACGTGAACTACGGATGATTAATCCGCTACCTCCACGCCAACGGAGCCTCCATATTCTTTATCTGCCTTTTTATCCACGTAGGTCGAGGAATCTACTACGGCTCCTATGTCCTCTCAGAAACCTGAAACATCGGCATCATCCTATTCCTTACAACTATGGCAACAGCATTCGTAGGGTATGTACTACCATGAGGACAAATATCTTTCTGAGGGGCTACTGTAATCACAAATCTCCTCTCAGCAATCCCCTACATCGGAAGCACCCTTGTTGAATGAATTTGAGGGGGCTTCTCAGTTGATAAAGCCACCCTGACCCGCTTCTTCGCCTTCCATTTTATTCTGCCTTTTATCATCACGGCCTTCGCTTTAGTCCACCTACTATTCCTCCACGAGACAGGATCTAACAATCCATCGGGCTTAAACTCAGACTCCGACAAAATCCCATTCCACCCCTACTACACAATCAAAGATCTCCTGGGCATCTTCCTCCTATTATTAGCTCTCATAATTTTAGCCCTATTTTTCCCAGATGTCCTCGGGGACCCAGACAATTTTACCCCAGCAAACCCTCTCAACACTCCAGCACACATTAAGCCAGAGTGGTATTTCCTATTTGCTTACGCCATCCTTCGATCTATCCCCAACAAGCTTGGAGGCGTATTAGCCCTTATCCTCTCTATTCTCATTTTAGCAATTTTCCCACTACTGAATGTTTCCAAACAACACGGTTTAATTTTCCGACCTATCACACAAACCATTTACTGAACTTTTATTGCCAACCTTCTCGTACTTACATGAATTGGGGGGCAACCCGTTGAGTACCCATTCACAACAATTGGACAAATCGCATCAATCACATACTTCACTAT-ATTATCATTTTAATGCCAGTCTCTAATACCATCGA-AACAATATCATCAAACTC------------------------------------------------------------TAG Seq17 ATGAAAATTTTACGGAAAAATCACCCACTACTTAAAATTGTTAATCACTCATTCATTGACCTACCAACCCCATCTAGCATCTCGTCTTGATGGAATTTTGGGTCACTACTTGGTGTGTGTCTGATAATTCAAATTCTGACCGGCCTATTCCTAGCCATACACTACACATCAGACACAACCACAGCATTCTCTTCAGTAGCTCACATCTGTCGAGATGTAAACTACGGATGATTAATCCGCTACCTACATGCTAACGGGGCTTCCATATTCTTTATCTGTCTCTTCATCCACGTAGGCCGAGGGATCTATTACGGTTCCTATGTCCTCTCAGAAACTTGAAACATCGGTATCATTCTATTTCTTACAACTATAGCAACAGCATTCGTAGGCTATGTGTTACCATGAGGACAAATATCTTTCTGAGGGGCCACTGTAATCACAAATCTCCTCTCAGCAATCCCCTACATCGGAAGCACCCTTGTTGAATGAATCTGAGGCGGCTTCTCAGTTGACAAAGCCACCTTAACCCGTTTCTTCGCCTTTCACTTTATCCTACCTTTTATCATCACAGCCTTGGTCCTAGTTCACCTACTGTTTCTTCACGAAACAGGATCCAACAACCCATCAGGTTTAAACTCAGACTCCGACAAAATCCCGTTCCACCCATACTACACAATCAAAGATCTCCTGGGCATCCTCCTTCTATTATTAGCTCTTATAATTCTAGCCTTATTTTTCCCCGATATCCTCGGAGACCCAGACAACTTTACCCCGGCAAACCCCCTCAACACTCCAGCACACATTAAGCCAGAATGGTATTTCCTATTTGCATACGCCATCCTCCGATCTATCCCCAATAAGCTTGGAGGTGTTCTAGCCCTCATCCTCTCTATTCTCATCCTAGCAACATTCCCATTATTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTATTACACAAACCATCTACTGAACTTTTATTGCTAACCTTCTTGTACTTACATGAATTGGGGGCCAACCTGTCGAATACCCATTCACAACAATTGGACAAATCGCATCAATCACCTACTTCACTATCATTATCATTTTAATGCCAGTCTCTAATACTATCGAAAATAATATCATCAAACTC------------------------------------------------------------TAA Seq18 ATGAAAATTTTACGTAAAAATCACCCACTACTCAAAATTATAAATCACTCATTCATTGATCTGCCAGCTCCATCTAACATCTCATCCTGATGGAACTTTGGATCCCTACTTGGTACATGCCTAGTAATCCAAATCCTAACAGGCCTATTCTTAGCTATACACTACACATCAGACACAACCACAGCATTCTCCTCAGTAGCTCATATCTGCCGAGACGTAAACTACGGATGATTAATCCGCTACTTACACGCTAATGGAGCCTCCATATTCTTCATCTGCCTCTTCATCCACGTAGGCCGAGGAATCTACTACGGCTCCTACGTCCTTTCAAAAACTTGAAATATCGGCATTATCTTATTCCTCACAACTATAGCAACAGCATTTGTGGGGTACGTACTTCCATGAGGACAAATATCCTTCTGAGGGGCCACTGTAATTACAAACCTCCTCTCAGCCATCCCCTACATCGGAAGCACCCTAGTTGAATGAATCTGAGGAGGCTTTTCAGTTGACAAAGCTACCCTCACCCGCTTCTTCGCCTTCCACTTCATTCTACCTTTTATCATTGCAGCCTTCACCCTAGTTCACCTATTATTTCTTCACGAAACAGGATCCAACAACCCCTCAGGCTTAAACTCAAACTCTGATAAAATTCCATTCCACCCCTACTACACAACCAAAGATCTTCTAGGCATCTTTCTGCTACTACTAGCTCTCATAATTTTAACCTTATTTTTCCCAGACATCTTAGGAGACCCAGACAATTACACTCCAGCAAACCCTCTCAACACTCCAGCACACATTAAACCAGAGTGATATTTCCTATTTGCCTACGC-ATCCTTCGATCAATTCCTAACAAACTAGGAGGCGTCTTAGCCCTCATCCTTTCCATTCTCATCCTAGCAACATTCCCACTACTGAATAATTCCAAACAACACGGTTTAATTTTCCGACCTATTACACAAACCATCTACTGAATCTTCATTGCTAACCTTCTTGTTCTTACATGAATTGGAGGCCAACCTGTCGAGCTCCCATTCACAACAATTGGACAAATCGCATCAATTACCTACTTCGCTATCATTATCATCCTAATTCCAATCTCTAATGCTATCGAGAACAATATCATCAAGCTT------------------------------------------------------------TAG Seq19 ATGAAAATTTTACGGAAAAATCACCCGCTACTCAAAATTGTTAATCACTCATTCATTGACCTACCAACTCCATCTAACATCTCATCCTGATGAAATTTTGGATCCCTACTAGGCATATGCCTAATAATCCAAATTTTAACAGGCCTATTCCTAGCCATACACTACACATCAGACACAACCACAGCATTCTCCTCAGTAGCACATATCTGCCGAGATGTAAACTACGGATGATTAATCCGCTACTTGCACGCTAATGGAGCCTCCATATTCTTTATCTGCCTCTTCATCCACGTAGGCCGAGGTATTTACTATGGTTCCTATACCCTCTCAGAAACCTGAAACATTGGCATCATCTTATTCCTCACAACTATAGCAACAGCATTTGTAGGATATGTACTCCCATGAGGACAAATATCCTTCTGGGGTGCCACCGTAATCACAAACCTCCTCTCAGCTATTCCCTACATCGGAAACACCCTAGTTGAATGAATCTGAGGTGGTTTTTCAGTTGACAAAGCCACCCTCACCCGCTTCTTCGCTTTTCACTTTATCTTACCCTTTATCATCACAGCCTTCGCCCTAGTTCACCTATTATTTCTTCACGAAACAGGGTCCAACAATCCATCAGGCCTAAATTCAGACTCTGACAAAATCCCGTTTCACCCCTACTACACAACCAAAGACCTCCTAGGCATCTTCCTTTTATTATTAGTTCTCATAATTTTAGCCTTATTTTTCCCAGACATTCTCGGAGACCCAGACAATTTTACCCCAGCAAATCCCCTCAACACCCCAGCACACATTAAACCAGAATGGTATTTTCTATTTGCCTATGCCATTCTCCGATCCATTCCCAACAAATTAGGGGGTGT-TTAGCCCTCGTCCTCTCCATTCTTATCCTAGCAGCATTCCCACTATTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTATCACACAAGTCATTTACTGAATTTTCATTG-TAACCTTCTCGTACTTACATGAATCGGAGGGCAGCCTGTCGAATATCCA-TCACAATAATTGGACAAATCGCATCAATTACATACTTCGCTATCATTATTATTCTTATCCCAGTCTCCAACACTATCGAGAACAATATTATTAAGCTC------------------------------------------------------------TAA Seq20 ATGAAAATCTTACGGAAAAATCATCCACTGCTTAAAATTGTTAATCACTCATTCATTGATCTACCAACTCCATCCAACATCTCATCCTGATGGAATTTTGGATCTCTTCTAGGAATATGCTTAGTAATCCAAATTCTAACAGGCCTATTCCTAGCCATACACTACACATCAGACACAACCACAGCATTCTCCTCAGTAGCCCATATCTGCCGAGATGTAAACTACGGATGGCTGATCCGCTACTTACACGCCAACGGGGCCTCCATATTCTTTATCTGCCTTTTCATCCACGTAGGCCGAGGGATTTACTACGGCTCCTACGTCCTCTCAGAAACCTGAAACATCGGCATCATCTTACTTCTCACAACCATAGCAACAGCATTTGTGGGATACGTACTCCCATGAGGACAAATATCTTTTTGAGGGGCTACCGTAATCACAAACCTTCTTTCAGCCATCCCATACATCGGAAACACCCTAGTTGAATGAATCTGAGGTGGCTTTTCAGTCGACAAAGCTACCCTCACTCGCTTTTTCGCTCTCCATTTCATCTTACCCTTTATCATTGCAGCCTTTGCCCTAGTTCACCTCCTGTTTCTCCACGAAACAGGGTCCAATAACCCATCAGGCTTAAACTCAGATTCTGACAAAATTCCATTTCACCCCTACTACACTACCAAAGATCTCTTAGGCATCTTCCTTTTATTATTAGTTCTCATAATTTTAGCCTTATTTTTCCCAGACGTCCTAGGAGACCCAGACAATTTTACCCCAGCAAATCCTCTCAACACCCCAGCACACATTAAACCGGAGTGATATTTTCTATTTGCCTACGCTATCCTCCGATCCATTCCCAACAAATTAGGGGGCGTTCTAGCCCTCGTCCTTTCCATCCTCATCCTAGCAGCATTCCCATTACTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTGTCACACAAGTCATTTACTGAATCTTTATCGCTAACCTTCTTGTACTTACATGAATCGGAGGCCAACCTGTCGAATACCCATTCACAACAATCGGACAAATCGCGTCAGTTACCTACTTCGCAACTATCATTATCCTAATCCCAGTCTCTAATACTATCGAAAATAATATTATCAAGCTC------------------------------------------------------------TAA Seq21 ATGAAAATTTTACGAAAAAATCACCCATTATTCAAAATTATTAATCACTCATTCATTGACCTACCAACCCCATCCAATATCTCATCCTGATGGAACTTTGGGTCTCTACTCGGTATGTGCTTAATAATCCAAATTCTAACTGGCTTATTCCTAGCCATACACTACACATCAGACACAACCACAGCATTCTCTTCAGTAGCCCACATCTGCCGAGACGTGAACTACGGATGACTAATCCGCTACTTACACGCTAATGGAGCCTCTATATTCTTCATCTGCCTTTTCATCCACGTAGGCCGAGGAATCTACTATGGTTCCTATGTCCTCTCAGAAACTTGAAACATTGGCATTATCTTATTCCTCACAACTATAGCTACAGCGTTCGTGGGGTATGTACTTCCATGGGGACAAATATCCTTCTGAGGAGCCACCGTAATTACAAATCTCCTCTCAGCAATCCCCTACATCGGAAGCACATTAGTTGAATGAATCTGAGGGGGCTTCTCAGTCGATAAAGCTACTCTTACCCGCTTTTTCGCTTTCCATTTCATTTTACCTTTTATCATCACAGCCTTCGTTCTAGTTCACCTACTTTTTCTCCACGAAACAGGATCCAACAACCCATCAGGCTTAAACTCAAACTCTGACAAAATTCCATTCCACCCCTACTATACAATTAAAGATCTCCTAGGCATTCTCTTCCTACTAACAGCTCTTATAATTTTAGCCCTATTTTTCCCAGATATCCTCGGAGATCCAGACAATTATACTCCAGCGAACCCACTCAACACCCCAGCACACATCAAACCAGAATGATACTTCCTATTTGCCTATGCTATTCTACGATCCATCCCCAACAAACTAGGGGGTGTGTTAGCCCTCCTTCTTTCTATCCTCATCTTAATAGCATTCCCATTACTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTATCACACAGACCATCTACTGAATTCTTATCGCTAATCTTCTTGTACTTACATGAATTGGGGGCCAACCTGTTGAATACCCATTCACAATAATTGGACAGATCGCATCAATCACCTACTTTGCTATCATCCTTATCCTAATACCAGTCTCTAATACTATCGAGAACAATATTATCAAGCTC------------------------------------------------------------TAA Seq22 ATGAAAATCTTACGAAAAAATCATCCACTACTCAAAATTATTAATCATTCATTTATTGACCTACCAGCCCCATCTAACATCTCATCCTGATGGAACTTTGGGTCTCTACTCGGTGTATGCCTAATAATCCAAATTCTAACCGGCCTATTCCTAGCCATACACTACACATCAGACACAACCACAGCATTCTCTTCAGTAGCCCATATCTGTCGAGACGTAAATTACGGGTGATTAATCCGTTACCTACACGCTAATGGTGCCTCTATATTCTTCATCTGCCTTTTCATTCATGTAGGTCGAGGGATCTACTATGGCTCTTATGTACTCTCAGAAACTTGAAATATCGGCATTATCCTATTCCTCACAACTATAGCCACAGCATTCGTAGGGTATGTTCTTCCATGAGGACAAATATCTTTCTGAGGGGCCACTGTAATCACAAATCTCCTCTCAGCAATCCCCTACATCGGAAACACCCTAGTTGAATGAATTTGAGGTGGCTTTTCAGTTGATAAAGCCACCCTCACCCGCTTTTTCGCCTTCCATTTTATCCTACCTTTTATTATCACCGCCTTCGTTCTAGTTCACTTACTATTCCTCCACGAAACAGGATCCAACAACCCATCAGGCTTAAACTCAGACTCCGACAAAATTCCATTCCACCCTTACTACACAATTAAAGATCTCCTAGGCATCCTCTTCTTACTAATAGCTCTTATAATTTTAGCCCTATTCTTCCCAGATATCCTCGGAGACCCAGACAATTACACCCCAGCAAACCCTCTCAACACCCCAGCACACATCAAACCAGAATGATACTTCCTATTTGCCTACGCCATTCTACGATCAATCCCTAACAAACTAGGAGGCGTCTTAGCCCTCCTTCTTTCTATCATCATCTTAGCGGCATTCCCATTACTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTGTCACACAAACCATTTACTGAATTTTTATTGCTAATCTTCTTGTACTTACATGAATTGGGGGTCAACCTGTCGAATACCCATTCACAATAATTGGACAAATCGCATCAGTTATTTACTTCGCTACCATCATCGTCCTAATACCAGTCTCTAATACTATCGAAAATAATATTATCAAGCTC------------------------------------------------------------TAA Seq23 ATGAAAGTCTTACGAAAAAATCACCCACTACTCAAAATTGTTAATCACTCATTTATCGATCTACCAACCCCATCTAACATCTCATCCTGATGGAATTTCGGGTCCCTACTAGGCACATGCCTAGTAATCCAAATTCTAACAGGCCTATTCCTAGCCATACACTACACGTCAGATACAACCACAGCATTCTCCTCAGTAGCCCACATCTGCCGAGATGTAAACTACGGATGATTAATCCGCTACTTACACGCTAACGGAGCCTCTATATTCTTTATCTGCCTCTTCATCCATGTAGGCCGAGGGATTTACTACGGCTCCTACATCCTCTCAGAAACCTGAAACATTGGCATCATCTTGTTTCTCACAACTATAGCAACAGCATTTGTAGGGTATGTACTTCCATGAGGACAAATATCTTTCTGAGGGGCCACTGTAATCACAAATCTCCTTTCAGCTATCCCCTACATTGGAAACACCTTAGTTGAATGAATCTGAGGTGGCTTTTCAGTTGACAAAGCCACCCTCACCCGCTTCTTCGCCTTCCATTTTATCTTACCCTTTATTATTACAGCCCTCGCCCTAGTTCACCTTCTGTTCCTCCACGAAACAGGATCCAATAACCCATCAGGCCTAAACTCAGACTCTGACAAAATCCCATTCCACCCCTACTATACAACCAAAGATCTCCTAGGTATTTTCCTTTTATTATTAGTTCTCATAATTTTAGCCTTATTTTTCCCAGACGTCCTCGGAGACCCAGACAATTTTACACCAGCAAATCCTCTTAACACCCCAGCACACATTAAACCAGAATGATATTTCCTATTTGCCTACGCCATTCTTCGATC-ATTCCCAACAAACTAGGAGGTGTTCTAGCCCTCATCCTCTCCATTCTCATCTTAGCAGCATTCCCACTATTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTGTCACACAAGTCATTTACTGAATTTTCATCGCCAACCTTCTTGTACTTACATGAATTGGAGGCCAACCCGTCGAATACCCATTCACAATAATCGGACAAATCGCATCAATTACTTACTTCACTATTATCATTATCCTTATACCAGTCTCCAATACCATCGAGAACAATATCATCAAACTC------------------------------------------------------------TAA Seq24 ATGAAAATTTTACGTAAAACTCACCCACTACTTAAAATTGTTAACCACTCATTCATTGACCTACCCACCCCATCTAACATCTCATCCTGATGAAACTTTGGATCCCTACTAGGCATGTGCCTAGTAATTCAAATTCTAACAGGCCTATTCCTAGCTATACACTACACATCAGACACAGCCACAGCATTTTCTTCAGTTGCCCACATCTGTCGAGATGTAAATTACGGATGATTAATCCGTTATCTACACGCCAACGGAGCTTCCATATTCTTCATCTGCCTTTTCATTCATGTAGGACGAGGAATCTACTATGGCTCCTATGTCCTTTCAGAAACCTGAAACATTGGAATTATCCTACTGCTAACTACTATAGCAACAGCATTTGTAGGATATGTTCTACCATGGGGACAAATATCATTCTGAGGCGCTACCGTAATCACAAACCTTCTCTCAGCAATTCCTTACATCGGAAATACCCTAGTTGAATGAATCTGAGGGGGGTTTTCAGTCGATAAAGCTACCCTAACCCGCTTCTTCGCCTTCCACTTCATCCTACCATTTATCATCACAGCTCTAGTCCTAGTTCACCTATTATTCTTACACGAAACAGGATCTAACAACCCATCAGGTCTAAACTCAGACTCAGACAAAATTCCATTCCACCCCTATTATACAATCAAAGACCTCCTAGGCATCTTCCTCCTACTAATAACTCTCATAATCTTAGCCTTATTTTTCCCAGATATCCTAGGAGACCCTGACAACTTCACCCCAGCAAATCCACTAAATACTCCAGCACATATTAAACCAGAGTGATACTTCTTATTCGCTTATGCTATCCTACGGTCTATTCCTAATAAACTAGGAGGAGTACTAGCTCTTGTCCTTTCCATCCTTATCCTAGCAACATTCCCATTACTGAATACTTCCAAACAACACGGTTTGATTTTCCGACCTATTACACAAACCATTTACTGAATTTTTATTGCTAACCTTCTAGTACTTACATGAATCGGGGGTCAACCTGTTGAATATCCATTCACAACAATTGGGCAAATCGCATCAATTACCTACTTCACAATCATCGTCATTATTATACCAGTCTCCAATACCATCGAGAACAACATCATCAAACTC------------------------------------------------------------TAG Seq25 ATGAAAATCTTACGAAAAAATCACCCACTACTCAAAATTATTAATCACTCATTCATTGATCTTCCAACTCCATCTAACATCTCATCCTGATGGAATTTCGGATCCCTACTAGGCATATGCCTAATGATCCAAATTCTAACAGGCCTATTCCTAGCCATACACTATACATCAGACACAACCACAGCATTCTCCTCAGTAGCCCACATTTGCCGAGATGTAAACTACGGATGATTAATCCGCTATCTACACGCTAACGGAGCCTCCATATTCTTTATTTGTCTCTTCATCCATGTAGGCCGAGGTATTTACTACGGCTCCTATGCCCTCTCAGAAACCTGAAACATCGGCATCATCTTATTTCTCATAACTATAGCAACAGCATTTGTAGGATATGTACTCCCATGAGGACAAATATCCTTCTGAGGGGCTACTGTAATCACAAATCTCCTTTCAGCTATCCCCTACATCGGAAGCACCTTAGTTGAATGAATCTGAGGTGGGTTTTCAGTCGACAAAGCCACCCTCACCCGCTTCTTCGCCTTCCATTTCATTTTACCTTTTATTATTGCAGCCTTCGCCCTAGTTCACCTACTATTTCTCCACGAAACAGGATCCAACAACCCATCAGGCTTAAACTCAGACTCTGACAAAATCCCATTTCACCCCTACTACACAACCAAAGACCTCCTAGGCATTTTCCTTTTATTATTAGTTCTCATAATTTTAGCCTTATTTTTCCCAGACGTCCTCGGAGACCCAGACAATTTTACTCCAGCTAATCCCCTCAACACTCCAGCACACATTAAACCAGAATGATACTTTCTATTTGCCTATGCCATTCTTCGATCCATTCCCAACAAACTAGGAGGTGTTTTAGCCCTCATCCTTTCCATTCTCATCCTAGCAGCATTCCCACTACTAAATAATTCCAAACAACACGGTTTAATTTTCCGACCTGTCACACAAGTCATTTACTGAATTTTCACTGCTAACCTTCTTGTTCTTACATGAATCGGAGGCCAACCTGTCGAATATCCATTCACAATAATTGGACAAATTGCATCAATTACATACTTAGCTATCATTATTATCCTCATACCAATTTCCAACACTATCGAGAACAATATTATCAAACTC------------------------------------------------------------TAA Seq26 ATGAAAATCTTACGGAAAAATCACCCACTACTCAAAATTGTTAATCACTCATTTATTGATCTACCAACTCCATCTAACATCTCATCCTGATGAAATTTTGGGTCTTTGCTAGGTATATGCCTAGTAATCCAAATTCTAACAGGCCTATTCCTAGCCATGCACTACACATCAGACACAGCCACAGCATTCTCTTCAGTAGCCCATATCTGCCGAGACGTAAACTATGGTTGACTAATCCGCTACCTACACGCTAATGGAGCCTCTATATTCTTTATCTGCCTTTTCATCCACGTAGGCCGAGGAATCTACTACGGCTCCTATGTCCTCTCAGAAACTTGAAACATCGGCATCATCTTACTTCTCACAACCATAGCAACAGCATTCGTAGGATACGTACTTCCATGAGGACAAATATCCTTTTGAGGGGCTACTGTAATCACAAATCTCCTTTCAGCCATCCCCTACATTGGAAGCACCCTAGTCGAATGAATCTGAGGCGGCTTTTCAGTTGACAAAGCCACCCTCACCCGCTTCTTCGCCTTCCATTTTATCTTGCCTTTCATCATCGCAGCCTTCGCCTTAGTTCACCTTCTATTTCTCCACGAAACAGGATCCAACAACCCATCCGGCCTAAACTCAGACTCTGACAAAATCCCATTTCACCCCTACTACACAATCAAAGATCTGCTAGGCATCTTTCTCTTATTATTAGTTCTCATAACTTTAGCTTTATTTTTCCCAGATGTCCTCGGAGACCCAGATAATTTTACCCCAGCAAACCCTCTCAACACTCCAGCACACATTAAACCAGAATGGTATTTTCTATTTGCCTATGCCATTCTTCGATCTATCCCTAACAAATTAGGAGGCGTCTTAGCCCTCGTCCTCTCCATCCTCATCTTAGCAGCATTCCCATTACTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTGTCACACAAACCATTTATTGAATTTTTATCGCTAACCTTCTTGTACTTACATGAATTGGGGGCCAACCTGTTGAATATCCATTCACAACAATTGGACAAATCGCATCAATCACCTACTTCACCATCATTATTATTCTGATCCCAGTCTCCAACACCATCGAGAACAATATCATCAAGCTC------------------------------------------------------------TAA Seq27 ATGACAATTATACGAAAAACCCACCCGCTACTTAAAATTATTAACCACTCATTTATTGATCTCCCTACCCCCTCCAACATTTCATCTTGATGGAACTTTGGCTCACTTTTAGGTATTTGCCTAATCATTCAAATTTTAACTGGCCTCTTCCTGGCCATACACTACACATCCGACACAGCCACAGCATTCTCCTCCGTCACCCACATCTGCCGAGACGTAAACTATGGCTGGCTCATCCGTTATATACACGCCAACGGAGCATCCATATTTTTTATTTGCCTATTCATTCACGTAGGACGAGGAATCTACTACGGCTCCTACATGCTCTCAGAAACCTGAAACATTGGCATCATCCTACTCCTAACCACAATAGCCACAGCATTCGTAGGCTATGTTCTCCCATGAGGGCAAATATCCTTCTGAGGCGCCACAGTAATCACAAATTTACTATCAGCAATCCCCTATATCGGAACAACTCTAGTTGAATGAATCTGAGGGGGGTTTTCAGTAGACAAAGCCACATTAACCCGCTTCTTCGCATTTCACTTTATTTTACCTTTCATTATCACAGCTTTTGTCCTGGTTCACCTCCTATTTCTACACGAAACAGGATCTAATAACCCCTCAGGCCTCAACTCAAATTCTGACAAAATCCCATTCCATCCCTACTACACAATCAAAGACTTGCTCGGAGTAATTCTTCTTTTAATAGTTCTCATAATTTTAGTATTATTTTTCCCAGATGTTCTCGGAGACCCCGATAATTATACCCCAGCAAATCCACTCAACACCCCAGCACACATTAAACCAGAATGGTATTT-CTTTTTGCCTACGCTATCCTCCG-TCCATCCCCAACAAACTAGGAGGAGTCCTAGCTCTAATCTTATCAATCTTAATTTTAGCAGCGTTCCCACTTCTTAATTCTTCCAAACAACACGGACTTATTTATCGCCCTATCTCACAAACCCTCTACTGAATCTTTGTTTCTAACCTTCTAATCCTCACATGAATTGGAGGACAACCTGTAGAATACCCATTTACAGTAATCGGTCAAATCGCATCAATCCTGTACTTCGCTATTATTATCATCCTTATACCTAT-GCCAACATAATCGAGAATAACATCCTAAAACTC---TAC------------------------------------------------------T-- Seq28 ATGAAAAT-TTACGAAAAAATCACCCATTATTCAAAATTATTAACCACTCATTCATTGACCTGCCAACCCCATCCAATATCTCATCCTGATGGAACTTTGGATCTCTACTCGGTATGTGCTTAATAATCCAAATTCTAACTGGCTTATTCCTAGCCATACACTACACATCAGACACAACCACAGCATTCTCTTCAGTAGCCCACATCTGCCGAGATGTAAACTACGGATGACTAATCCGCTACTTACACGCTAATGGAGCCTCTATATTCTTCATCTGCCTTTTCATCCACGTAGGCCGAGGAATCTACTATGGTTCCTATGTCCTCTCAGAAACTTGAAACATCGGCATTATCTTATTCCTCACAACTATAGCTACAGCATTCGTAGGGTATGTACTTCCATGGGGACAAATATCCTTCTGAGGAGCCACCGTAATTACAAACCTCCTCTCAGCAATCCCCTACATCGGAAGCACATTAGTTGAATGAATCTGAGG-GGCTTCTCAGTCGATAAAGCTACTCTTACCCGCTTTTT-GCTTTCCATTTCATTCTACCTTTTATCATCACAGCCTTCGT-CTAGTTCACCTACTTTTTCTCCACGAAACAGGATCCAACAACCCATCAGGCTTAAACTCAAACTCTGACAAAATTCCATTCCACCCCTACTATACAATTAAAGATCTCCTAGGCATTCTCTTCCTACTAACAGCTCTTATAATTTTAGCCCTATTTTTCCCAGATATCCTCGGAGATCCAGACAATTATACTCCAGCGAACCCACTCAACACCCCAGCACACATCAAACCAGAATGATACTTCCTATTTGCCTATGCTATTCTACGATCCATCCCCAACAAACTAGGGGGTGTGTTAGCCCTCCTTCTTTCTATCCTCATCTTAATAGCATTCCCATTACTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTATCACACAGACCATCTACTGAATTCTTATCGCTAATCTTCTTGTACTTACATGAATTGGGGGCCAACCTGTTGAATACCCATTCACAATAATTGGACAAATTGCATCAATCACCTACTTTGCTATTATCCTTATCCTAATACCAGTCTCTAATACTATCGAGAACAATATTATCAAGCTC------------------------------------------------------------TAA Seq29 ATGAAAATCTTACGGAAAAATCACCCGCTACTTAAAATTGTTAATCACTCATTTATTGATCTACCAACTCCATCCAACATCTCATCTTGATGGAACTTTGGGTCACTACTTGGTTTATGCCTAATAATCCAAATTCTGACCGGCCTATTCCTAGCTATACACTACACATCAGACACAACCACAGCATTCTCTTCAGTAGCCCACATTTGCCGAGATGTAAACTACGGATGATTAATCCGCTATCTACACGCTAACGGAGCTTCTATATTCTTTATCTGCCTTTTCATCCACGTAGGCCGAGGAATCTACTACGGCTCCTATGTCCTCTCAGAAACCTGAAACATCGGTATCATTCTATTCCTTACAACCATAGCAACAGCATTCGTAGGATATGTACTACCATGAGGACAAATATCTTTCTGAGGGGCTACTGTAATTACAAACCTCCTTTCAGCAATCCCCTACATCGGAAACACCCTTGTGGAATGAATTTGAGGAGGCTTCTCAGTTGATAAAGCCACCCTAACCCGCTTCTTCGCCTTCCATTTTATCCTACCCTTTATCATCACAGCCCTCGCCTTAGTCCACCTATTATTCCTCCACGAGACAGGATCTAATAACCCATCAGGCTTAAACTCAGACTCCGACAAGATCCCATTCCACCCCTACTACACAATCAAAGACCTCCTGGGCATCTTTCTCCTATTATTAGCTCTCATAATTTTAGCCTTATTCTTCCCAGACATCCTCGGAGACCCAGACAATTTTACCCCAGCAAACCCTCTCAACACTCCAGCACACATTAAACCAGAATGATATTTCCTATTTGCCTACGCCATTCTCCGATCTATCCCCAACAAACTTGGAGGTGTATTAGCCCTTATTCTCTCTATCCTCATTTTAGCAGCATTCCCATTATTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTATCACACAAACCATTTACTGAACTTTTATTGCTAACCTTCTCGTACTTACATGAATTGGAGGCCAACCTGTTGAATATCCGTTCACAACAATTGGACAAATCGCATCAATCACCTACTTCACTATCATCATTATCTTAATACCAGTCTCTAATACCATCGAGAACAATATCATCAAGCTC------------------------------------------------------------TAG Seq30 ATGAAAATTATACGAAAGAATCACCCCCTACTTAAAATTATTAACCACTCATTCATCGACCTACCAACCCCGTCCAACATCTCATCATGATGAAACTTTGGGTCCCTACTAGGTGCCTGCCTAATTATCCAAATCTTAACGGGCCTCTTTCTAGCCATACACTACACTTCAGATACAACCACAGCATTCTCCTCAGTAGCCCACATTTGCCGAGACGTAAATTACGGGTGATTAATTCGCTATCTACACGCCAACGGAGCCTCCATATTCTTCATCTGCCTATCCATCCACGCCGGCCGAGGAATTTACTACGGCTCCTACGTCCTTTCAGAAACCTGAAACATCGGTATCATCTTATTCCTTACAACCATAGCAACAGCATTTGTAGGTTATGTGCTTCCATGAGGACAAATATCCTTCTGAGGCGCTACCGTAATCACTAACCTTCTCTCAGCAATCCCCTACATCGGAAGCACTCTATTTGAATGAATCTGAGGAGGCTTTTCAGTTGATAAAGCTACCCTCACCCGTTTCTTCGCCTTCCACTTTATCTTACCCTTTATTATCACAGCCTTTGTCCTTGTACACCTCCTGTTCCTTCATGAAACAGGCTCTAACAACCCATCAGGCCTAAACTCAAACTCCGACAAAATCCCATTCCATCCCTACTACACAATCAAAGATCTCCTAGGAGTCTTCCTATTATTATTAGCTCTCATAATTTTAGCCTTATTTTTCCCAGATGTTCTCGGGGACCCAGATAATTTTACCCCAGCAAATCCTCTCAATACTCCAGCACACATTAAACCGGAATGATATTTTCTATTCGCCTACGCTATCCTTCGATCAATTCCCAACAAACTAGGGGGAGTCTTAGCCCTCATTCTATCTATCCTTATCCTAGCAGCATTCCCTCTATTAAATGTTTCCAAACAACACGGTTTAATTTTCCGTCCAATTACACAAACCATTTATTGAATCTTTATTGCTAACCTTCTAGTACTTACATGAATTGGAGGCCAACCCGTA-AATACCCATTCACAATAATTGGACAGATCGCATCAATCACCTACTTTGCTATCATCCTCATCCTAATACCAATCTCTAATACTATCGAAAACAATATTATTAAACTC------------------------------------------------------------TAA Seq31 ATGACAATCATACGAAAAAACCACCCTTTACTTAAAATCATTAATCACTCGTTTATTGACCTGCCCACCCCTTCCAACATTTCATCCTGATGGAACTTCGGCTCACTCCTTGGCATTTGCTTAATAATTCAAATTTTAACTGGCCTCTTCCTAGCCATACATTATACGTCCGATACAGCTACAGCATTTTCCTCCGTCACCCATATCTGCCGAGACGTAAATTACGGATGACTTATCCGCTACTTACATGCCAATGGGGCATCTATATTTTTTATCTGCCTATTTATTCATGTAGGACGAGGTATCTACTACGGCTCCTACATACTTTCAGAAACATGAAACATCGGAATTATCCTATTCCTAACCACAATAGCCACAGCATTTGTAGGCTATGTTCTTCCATGGGGACAGATATCTTTCTGAGGGGCCACAGTAATTACAAACTTACTCTCAGCAATTCCCTATATTGGAACCTCTCTAGTTGAATGAATCTGAGGGGGATTTTCAGTTGATAAAGCCACATTAACCCGCTTCTTTGCATTTCATTTCATTTTACCCTTCATCATCACAGCCTTTGTTTTAGTCCATCTTTTATTTCTACACGAAACAGGATCAAATAATCCCTCAGGCCTCAACTCAAATTCAGATAAAATTCCATTCCACCCTTATTACACAATCAAAGACCTGCTAGGGGTCATCCTTCCTTTAATAGTTCTCATAATTTTGGTTTTATTTTTCCCAGATGTTCTCGGAGACCCCGATAATTACACCCCAGCAAATCCACTTAACACCCCAGCACACATTAAGCCAGAGTGGTATTTCCTTTTCGCCTACGCTATTTTACGCTCCATCCCTAACAAACTAGGAGGAGTTTTAGCCCTAGTTTTATCTATTCTCATCTTAGCAGCATTCCCACTTCTCAATTCTTCCAAACAGCATGGACTAATATATCGTCCTATTACACAAACCCTCTACTGAATCTTTATTTCCAACCTCCTTATTCTCACATGAATTGGAGGCCAGCCAGTAGAATACCCATTTACAACAATTGGTCAAATTGCATCAATTTTATACTTTACTATTATTATCATCCTTATACCCATTGCCAACACGATCGAAAATAATATCCTAAAACTCCATTAC------------------------------------------------------T-- Seq32 ATGAAAATTCTACGGAAAAATCACCCACTACTTAAAATTGTTAATCACTCATTCATTGACCTACCAACCCCATCCAATATCTCATCCTGATGGAATTTTGGATCGCTACTCGGCGTATGCCTGATAATCCAAATTCTAACCGGTCTATTTCTAGCCATACACTACACATCAGACACAACCACAGCATTCTCTTCAGTAGCCCACATTTGCCGAGATGTAAACTACGGATGATTAATCCGCTATCTACACGCTAATGGAGCCTCCATATTCTTCATCTGTCTTTTTATTCATGTAGGTCGAGGAATCTACTACGGCTCTTATGTCCTCTCAGAAACCTGAAACATCGGCATCATTTTATTCCTCACAACTATAGCAACAGCATTCGTAGGATATGTATTACCATGAGGACAAATATCTTTCTGAGGAGCTACTGTAATCACAAATCTCCTTTCAGCGATTCCCTACATCGGAAGCACCCTTGTCGAATGAATCTGAGGAGGCTTCTCAGTTGATAAAGCCACCCTAACCCGCTTTTTCGCCTTCCATTTTATTTTACCTTTTATCATCACGGCCTTCGCCTTAGTCCATCTACTATTCCTCCACGAGACAGGATCCAACAACCCATCAGGCTTAAACTCAGACTCCGACAAAATCCCATTTCACCCCTACTACACAATTAAAGATCTCCTGGGCATCTTCCTTCTACTACTAGCTCTCATAATTTTAGCCCTATTTTTCCCAGATGTCCTCGGGGACCCAGACAATTTTACCCCAGCAAACCCTCTAAACACTCCAGCACACATTAAACCAGAATGGTATTTCTTATTTGCCTACGCCATCCTCCGATCTATCCCCAACAAACTTGGAGGAGTATTAGCCCTTATTCTCTCTATTCTCATTTTAGCAGCATTCCCATTATTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTGTCACACAAACCATTTATTGAGCTTTTATTGCCAACCTTCTCGTACTTACATGAATCGGAGGTCAACCTGTTGAATACCCATTCACAACAATCGGACAAATCGCATCAATTACCTACTTCACTATCATCATCATTTTAATGCCAGTCTCTAATACCATCGAGAACAATATCTTCAAGCTC------------------------------------------------------------TAG Seq33 ATGAAAATTTTACGGAAAAACCACCCACTACTCAAAATTATTAATCACTCATTTATTGACCTACCAACTCCATCTAACATCTCATCCTGGTGAAATTTTGGATCCCTACTAGGCATATGCCTAGTAATCCAAATTCTAACAGGCCTATTCCTAGCCATACACTATACATCAGACACAACCACAGCATTCTCCTCAGTAGCCCACATCTGCCGAGATGTAAATTACGGATGATTAATCCGCTATCTACACGCCAATGGAGCTTCTATATTCTTTATCTGCCTCTTCATCCATGTAGGCCGAGGTATTTACTACGGCTCCTATGTCCTCTCAGAAACCTGAAACATCGGCATCATCTTATTCCTCACAACTATAGCAACAGCATTCGTAGGATATGTACTACCATGAGGACAAATGTCTTTCTGAGGAGCCACTGTAATTACAAATCTCCTTTCAGCCATTCCCTACATCGGAAGCACCCTAGTTGAATGAATCTGAGGTGGCTTTTCAGTTGACAAAGCCACCCTCACCCGCTTCTTCGCTTTCCACTTTATTTTACCCTTTATTATCGCAGCTTTCGCCCTAGTTCACCTCTTATTTCTCCACGAAACAGGATCCAATAACCCATCAGGCTTAAATTCAGACTCCGACAAAATCCCATTCCACCCATACTACACAACCAAGGATCTCCTAGGTATCTTCCTTTTATTATTAGTTCTCATAATTTTAGCCTTATTTTTCCCAGACATCCTCGGAGACCCAGACAATTTTACCCCAGCAAACCCCCTCAACACCCCAGCACACAT-AA-CC-GA-TG-TA-TT-CT-TTTGC-TATGCCATTCTTCGATCTATCCCTAACAAACTAGGAGGCGT-TTAGCCCTCATCCTCTCCATCCTCATCCTAGCGGCATTCCCACTATTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTGTCACACAAGTCATTTACTGAAT-T-CATTGCTAACCTTCTTGTACTTACATGAATTGGAGGCCAACC-GTCGAATACCCATTCACAATAATTGGACAAATCGCATCAATTACATACTTCGCTATCAT-ATTATTCTTATCCCAGTCTCCAACACTATCGAGAACAATATTATTAAACTC------------------------------------------------------------TAA Seq34 ATGAAAATTTTACGAAAAAATCACCCCCTACTCAAAATTATTAATCACTCGTTCATCGACTTACCAACCCCATCCAACATCTCATCCTGATGAAATTTTGGATCCCTACTTGCCCTATGCCTAGCCATCCAAATCCTCACAGGCCTATTTCTAGCCATACATTACACATCAGACACAACCACAGCATTCTCCTCAGTAGCCCACATCTGTCGAGATGTAAATTACGGATGATTAATCCGCTATCTACATGCTAACGGAGCCTCCATATTCTTCATCTGCCTTTTCATCCACGTGGGCCGAGGGATTTATTACGGCTCATATATCCTCTCAGAAACCTGAAACATCGGTATCATTCTATTCCTTACAACTATAGCAACTGCATTCGTAGGATATGTCCTCCCATGGGGACAAATATCTTTCTGAGGAGCCACTGTAATTACTAATCTCCTCTCAGCTATTCCTTACATCGGAAATACCCTAGTAGAATGAATCTGAGGTGGATTCTCAGTTGACAAAGCCACTCTCACCCGATTCTTCGCCTTCCACTTTATTCTACCCTTTATCATTGCAGCCTTTGTCCTTGTCCACCTATTATTTCTACATGAAACCGGCTCAAACAACCCATCAGGCCTAAACTCAGACTCAGACAAAATCCCCTTCCACCCCTACTACACAATCAAAGACCTCTTAGGAGTTTTCCTTTTATTACTAGCTCTCATAACTTTAGCCTTATTTTTCCCTGATGTTCTTGGAGACCCCGATAATTTTACCCCAGCAAATCCCCTCAACACTCCAGCACACATTAAACCAGAGTGGTACTTCCTATTTGCCTACGCCATTCTTCGATCTATCCCAAACAAACTAGGAGGCGTACTAGCCCTTGTTCTTTCCATCCTAATTCTAGCAGCATTCCCGCTATTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTATTACACAAATCATTTTCTGAATTTTTATTGCTAACCTTCTGTTACTTACATGAATCGGAGGTCAACCAGTAGAATACCCATTCACAGCAATTGGCCAAATTGCATCAATTACTTACTTTATTATTATTATCATTTTAATGCCAGTCTCTAACACTATCGAAAACAATATTATCAAACTC------------------------------------------------------------TAA Seq35 ATGAAAATTTTACGGAAAAATCACCCGCTACTTAAAATTGTAAACCACTCATTTATTGACCTACCAACCCCATCTAATATTTCATCCTGATGAAATTTTGGGTCCCTACTCGGCGTATGCTTAATTATTCAAATCCTAACCGGTTTATTCCTAGCCATACACTATACATCAGACACAACCACAGCATTCTCTTCAGTAGCCCACATTTGCCGAGATGTAAACTACGGATGATTAATCCGCTATCTACACGCTAACGGAGCCTCCATATTCTTCATCTGTCTTTTCATTCACGTGGGTCGAGGAATCTATTATGGTTCCTATATCCTCTCAGAAACCTGAAACATCGGCATCATTCTATTCCTTACAACTATAGCAACAGCATTTGTAGGATATGTACTACCATGAGGACAGATATCCTTTTGAGGAGCTACCGTAATCACGAATCTTCTATCAGCAATTCCCTACATCGGAAACACCCTTGTTGAATGAATCTGAGGCGGCTTCTCAGTCGACAAAGCCACCCTAACCCGATTTTTCGCCTTCCATTTCATCCTACCTTTTATCATCACGGCCTTCGCCTTAGTTCACCTGCTATTTCTTCATGAGACAGGATCCAACAACCCATCAGGCCTAAACTCAGACTCCGACAAAATTCCATTCCACCCCTACTACACAATTAAAGATCTCCTGGGCATCTTCCTTCTATTGATGGTTCTCATAATTTTAGCCTTATTTTTCCCAGATGTGCTCGGGGACCCCGACAATTTCACCCCAGCAAATCCTCTCAACACTCCAGCACACATTAAGCCAGAATGATACTTCCTATTCGCTTACGCCATCCTTCGATCTATTCCCAACAAACTAGGAGGCGTTTTAGCCCTTATTCTGTCTATCCTCATTTTAGCAGCATTCCCATTATTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTGTCACACAAACCATTTACTGAACTTTTATTGCCAACCTTCTTGTACTTACATGAATTGGAGGTCAGCCCGTTGAGTATCCATTCACAACAATTGGGCAAATTGCATCAATTACTTACTTCACCATTATCATCATCCTAATGCCAGTCTCCAATACTATTGAAAATAATATTATCAAACTC------------------------------------------------------------TAG Seq36 ATGAAAATTTTACGGAAGAATCACCCGCTACTCAAAATTGTTAATCATTCATTTATCGACCTTCCAACTCCATCGAACATCTCATCCTGATGAAATTTTGGATCCCTACTAGGCATATGCCTAATAATCCAAATTCTAACAGGCCTATTCCTAGCCATACACTACACATCAGACACAACCACAGCATTCTCCTCAGTAGCCCATATCTGCCGAGATGTAAATTACGGATGATTAATCCGCTACTTGCACGCTAATGGAGCCTCCATATTCTTTATCTGCCTCTTCATCCACGTAGGCCGAGGTATTTACTATGGTTCCTATGTCCTCTCAGAAACCTGAAACATCGGCATCATCTTATTCCTCACAACTATAGCAACAGCATTCGTGGGGTATGTACTCCCATGAGGACAAATATCCTTCTGAGGTGCCACCGTAATCACAAACCTCCTCTCAGCCATCCCCTACATCGGAAACACCCTAGTTGAATGAATCTGAGGTGGCTTTTCAGTTGATAAGGCCACCCTCACCCGCTTCTTCGCTTTCCATTTTATCTTACCCTTTATCATCACAGCCTTCGCTTTAGTTCACCTATTATTTCTTCACGAAACAGGATCTAATAACCCATCAGGCCTAAATTCAGACTCTGACAAAATCCCATTCCACCCCTACTACACAACCAAGGACCTCCTAGGCATTTTCCTTTTATTATTAGTTCTTATAATTTTAGCCTTATTTTTCCCAGACATCCTCGGAGACCCAGACAATTTTACTCCAGCAAATCCCCTTAATACCCCAGCACACATTAAACCAGAATGGTATTTCCTATTTGCCTATGCCATTCTTCGATCCATCCCCAACAAATTAGGAGGTGTTTTAGCCCTCGTCCTTTCCATTCTTATTCTAGCAGCATTCCCACTACTAAATAATTCCAAACAACACGGTTTAATTTTCCGACCTATCACACAAGTCATCTACTGAATTTTCATTGCTAACCTTCTTGTACTTACATGAATCGGAGGTCAACCTGTCGAATACCCATTCACAATAATTGGACAAATCGCATCAATTACATACTTCGCTATCATCATTATTCTTATTCCAATCTCCAACACTATCGAGAACAATATTATCAAGCTC------------------------------------------------------------TAA Seq37 ATGAAAATTTTACGGAAAAACCACCCACTACTCAAAATTATTAATCACTCATTCATTGACTTACCAACTCCATCTAACATCTCATCCTGATGAAATTTCGGATCCCTACTAGGCATATGCTTAGTGATCCAAATTCTAACAGGCCTGTTCCTAGCCATACACTATACATCCGACACAACTACAGCATTCTCCTCAGTAGCCCATATCTGCCGAGATGTAAACTACGGATGACTAATCCGCTACTTACACGCTAACGGAGCCTCTATATTCTTCATCTGCCTCTTCATCCATGTAGGCCGAGGTATTTACTACGGCTCCTATGTCCTCTCAGAAACTTGAAACATCGGCATCATCTTATTCCTCACAACTATAGCAACAGCATTCGTAGGATATGTATTACCATGAGGACAAATGTCCTTCTGAGGGGCCACTGTAATCACAAACCTCCTTTCAGCCATCCCATACATCGGAACCACCCTAGTTGAATGAATCTGAGGAGGCTTTTCAGTTGACAAAGCCACCCTCACCCGCTTCTTCGCTTTCCATTTTATTTTACCCTTTATCATCGCAGCTTTCGCCCTAGTCCACCTCTTATTTCTCCACGAAACAGGATCCAATAATCCATCAGGCTTAAATTCAGATTCCGACAAAATCCCATTCCACCCCTACTACACAATCAAGGATCTCCTAGGCATCTTCCTTTTGTTATTAGTTCTCATAATTTTAACCCTATTTTTCCCAGACATCCTCGGAGACCCAGACAACTTTACTCCAGCAAACCCCCTCAACACCCCAGCACACATTAAACCAGAATGATACTTCCTATTTGCCTACGCTATCCTTCGATCCATCCCTAACAAGCTAGGAGGTGTTTTAGCCCTCATCCTCTCCATCCTCATTCTGGCAGCATTCCCACTATTAAATACTTCCAAACAATACGGTTTAATTTTCCGACCTGTCACACAAGTCATTTACTGAATTTTCATCGCCAACCTTCTTGTACTTACATGAATTGGGGGTCAACCAGTCGAATACCCATTTACAATAATTGGACAAATTGCATCAATTACATACTTCGCTATCATTATTATCCTTATCCCAGTCTCCAACACTATCGAGAACAATATTATTAAACTC------------------------------------------------------------TAA Seq38 ATGAAAATTTTACGAAAAAATCACCCATTACTCAAAATTATTAATCACTCATTCATTGACCTACCAACCCCATCCAATATCTCATCCTGATGGAACTTTGGGTCTCTACTCGGTATATGCTTAATAATTCAAATTCTAACTGGCTTATTCCTAGCCATACACTACACATCAGACACAACCACAGCATTCTCTTCAGTAGCCCACATCTGCCGAGATGTAAACTACGGATGACTAATCCGCTACTTACACGCTAATGGAGCCTCTATATTCTTCATCTGCCTTTTCATCCACGTAGGCCGAGGAATCTACTATGGTTCCTATGTCCTCTCAGAAACTTGAAACATCGGCATTATCTTATTCCTCACAACTATAGCTACAGCGTTCGTGGGGTATGTACTTCCATGAGGACAAATATCCTTCTGAGGAGCCACCGTAATTACAAATCTCCTCTCAGCAATCCCCTACATCGGAAGCACACTAGTCGAATGAATCTGAGGGGGCTTCTCAGTTGATAAAGCTACTCTTACCCGCTTCTTCGCCTTCCACTTCATTCTACCTTTTATCATCACAGCCTTCGTTCTAGTTCACCTACTTTTTCTCCACGAAACAGGATCCAACAACCCATCAGGCTTAAACTCAAACTCTGACAAAATTCCATTCCACCCCTACTACACAATTAAAGATCTCCTAGGCATTCTCTTCCTACTAACAGCCCTTATAATTCTAGCCCTATTTTTCCCCGATATCCTCGGAGATCCAGACAACTATACTCCAGCAAACCCACTCAACACCCCAGCACACATCAAACCAGAATGGTACTTCCTATTTGCCTACGCTATTCTACGATCTATCCCCAACAAACTAGGAGGCGTGTTAGCCCTCCTTCTTTCTATCCTCATCTTAATAGCATTCCCATTATTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTATCACACAGACCATCTACTGAATTCTTATTGCTAACCTTCTTGTACTTACATGAATTGGGGGCCAACCTGTTGAATACCCATTCACAATAATTGGACAGATCGCATCAATTACCTACTTTGCTATCATCCTTATTCTAAT-CCAGTCTCTAATACTATCGAGAACAATATTATCAAGCTC------------------------------------------------------------TAA Seq39 ATGAAAATTTTACGGAAAAATCACCCGCTACTTAAAATTGTAAATCACTCATTCATTGACTTACCAACCCCATCCAACATCTCATCTTGATGAAACTTTGGGTCACTACTCGGTGTATGCCTAATAATCCAAATTCTGACCGGCCTATTCCTAGCCATACACTACACATCAGACACAACCACAGCATTCTCTTCAGTAGCCCACATTTGCCGAGATGTAAACTACGGATGATTAATCCGCTATCTACACGCTAACGGAGCTTCCATATTCTTTATCTGCCTTTTCATCCATGTAGGCCGAGGAATCTATTACGGCTCCTATGTCCTCTCAGAAACCTGAAACGTCGGTATCATCCTATTCCTCACAACTATAGCAACAGCATTCGTAGGGTACGTGTTACCATGAGGACAAATATCTTTCTGAGGAGCTACCGTAATTACAAACCTCCTCTCAGCAATCCCCTACATCGGAAGCACCCTCGTCGAATGAATTTGAGGAGGCTTCTCAGTTGACAAAGCCACCCTAACCCGCTTTTTCGCCTTCCATTTTATTCTACCTTTTATCATTACGGCCTTCGCCTTAGTCCACCTACTATTCCTCCACGAGACAGGATCTAACAACCCATCAGGCTTAAACTCAGACTCCGACAAAATCCCATTTCACCCCTACTACACAATCAAAGATCTCCTGGGCATCTTCCTCCTATTATTAGTTCTCATAATTTTAGCTCTATTTTTCCCAGATGTCCTTGGAGACCCAGACAATTTTACTCCAGCAAACCCCCTCAACACCCCAGCACACATTAAGCCAGAATGATATTTCCTATTTGCCTATGCCATCCTTCGATCTATTCCAAACAAACTCGGAGG-GTATTAGCCCTCATTCTCTCTATCCTCATTTTAGCAGCATTCCCATTACTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTGTCACACAAACCATTTACTGAACCTTTATTGCCAACCTTCTCGTACTTACATGAATTGGAGGTCAACCTGTTGAATATCCATTCACAATAATTGGACAAATCGCATCAATTACCTACTTCACTATCATCATCATTTTAATGCCAGTCTCCAATACTATCGAGAACAATATCATCAAGCTC------------------------------------------------------------TAG Seq40 ATGAAAATTTTACGAAAAAATCACCCATTACTCAAAATTATTAATCACTCATTCATTGACCTGCCAACCCCATCCAATATCTCATCCTGATGGAACTTTGGGTCTCTACTCGGTATGTGCTTAATAATTCAAATTCTAACTGGCTTATTCCTAGCCATACACTACACATCAGACACAACCACAGCATTCTCTTCAGTAGCCCACATCTGCCGAGATGTAAACTACGGATGACTAATCCGCTACTTACACGCTAATGGAGCCTCTATATTCTTCATCTGCCTTTTCATCCACGTAGGCCGAGGAATCTACTATGGTTCCTATGTCCTCTCAGAAACTTGAAACATCGGCATTATCTTATTCCTCACAACTATAGCTACAGCGTTCGTGGGGTATGTACTTCCATGAGGACAAATATCCTTCTGAGGAGCCACCGTAATTACAAATCTCCTCTCAGCAATCCCCTACATCGGAAGCACACTAGTCGAATGAATCTGAGGGGGCTTCTCAGTTGATAAAGCTACTCTTACCCGCTTCTTCGCCTTCCATTTCATTCTACCTTTTATCATCACAGCCTTCGTTCTAGTTCACCTACTTTTTCTCCACGAAACAGGATCCAACAACCCATCAGGCTTAAACTCAAACTCTGACAAAATTCCATTCCACCCCTACTACACAATTAAAGATCTCCTAGGCATTCTCTTCCTACTAACAGCCCTTATAATTTTAGCCCTATTTTTCCCCGATATCCTCGGAGATCCAGACAACTATACTCCAGCAAACCCACTCAACACCCCAGCACACATCAAACCAGAATGGTACTTCCTATTTGCCTACGCTATTCTACGATCTATCCCCAACAAACTAGGGGGTGTGTTAGCCCTCCTTCTTTCTATCCTCATCTTAATAGCATTCCCATTATTAAATACTTCCAAACAACACGGTTTAATTTTCCGACCTATCACACAGACCATCTACTGAATTCTTATTGCTAACCTTCTTGTACTTACATGAATTGGGGGCCAACCTGTTGAATACCCATTCACAATAATTGGACAGATTGCATCAATTACCTACTTTGCTATCATCCTTATTCTAATACCAGTCTCTAATACTATCGAGAACAATATTATCAAGCTC------------------------------------------------------------TAA Seq41 ATGACAATCATACGAAAAAACCACCCTTTACTTAAAATCATTAATCACTCGTTTATTGACCTGCCCACCCCTTCCAACATTTCATCCTGATGGAACTTCGGCTCACTCCTTGGCATTTGCTTAATAATTCAAATTTTAACTGGCCTCTTCCTAGCCATACATTATACGTCCGATACAGCTACAGCATTCTCCTCCGTCACCCATATCTGCCGAGACGTAAATTACGGATGACTTATCCGCTACTTACATGCCAATGGGGCATCTATATTTTTTATCTGCCTATTTATTCATGTAGGACGAGGTATCTACTACGGCTCCTACATACTCTCAGAAACCTGAAACATCGGAATTATCCTATTCCTAACCACAATAGCCACAGCATTCGTAGGCTATGTTCTTCCATGAGGACAGATATCTTTCTGAGGAGCCACAGTAATTACAAACTTGCTCTCAGCAATTCCTTATATTGGAACCTCTCTAGTTGAATGAATCTGAGGGGGATTTTCAGTTGATAAAGCCACATTAACCCGCTTCTTTGCATTTCATTTCATTTTACCCTTCATTATCACAGCCTTTGTTTTAGTCCATCTTTTATTTCTACACGAAACAGGATCAAATAACCCCTCAGGCCTCAACTCAAATTCAGATAAAATTCCATTCCACCCTTATTACACAATCAAAGACCTGCTAGGAGTCATCCTTCTTTTAATAGTTCTCATAATTTTGGTTTTATTTTTCCCAGATGTTCTCGGAGACCCCGATAATTACACCCCAGCAAATCCACTTAACACCCCAGCACACATTAAGCCAGAATGGTATTTCCTTTTCGCCTACGCTATTTTACGCTCCATCCCTAACAAACTAGGAGGAGTTTTAGCCCTAGTTTTATCTATTCTCATTTTAGCAGCATTCCCACTTCTCAATTCTTCCAAACAGCATGGACTAATATATCGTCCTATTACACAAACCCTCTACTGAATCTTTATTTCCAACCTCCTTATTCTCACATGAATTGGAGGCCAGCCAGTAGAATACCCATTTACAATAATTGGTCAAATTGCATCAATTTTATACTTTACTATTATCGTCATCCTTATACCCATTGCCAACACGATCGAAAATAATATCCTAAAACTCCATTAC------------------------------------------------------T-- Seq42 ATGACCAACATCCGAAAGACCCACCCACTAATAAAAATTATTAACAATGCATTCATTGACCTCCCTGCCCCATCAAACATCTCATCGTGATGAAATTTTGGCTCCCTTCTAGGCATCTGCCTAATCCTACAGATCCTAACAGGACTATTTCTAGCAATACACTACACATCTGATACAACAACAGCATTCTCCTCTGTCACCCACATTTGCCGAGACGTCAACTATGGCTGAATCATCCGATATATACACGCAAACGGAGCCTCAATATTTTTTATCTGCCTATTCCTACATGTAGGACGAGGCCTATATTACGGATCCTACGCCTTCCTAGAAACATGAAACGTCGGAGTAATCCTTTTATTCGCAACAATGGCCACAGCATTTATGGGCTACGTTCTGCCATGAGGACAAATATCATTCTGAGGGGCAACAGTCATCACTAATCTCCTCTCAGCAATCCCATATATTGGCACAGACCTAGTAGAATGAATCTGAGGGGGATTCTCAGTAGACAAAGCAACCCTTACCCGATTTTTTGCCTTCCACTTCATTCTCCCATTCATCATTGCAGCCCTTGCCATAGTTCACCTCTTATTCCTCCACGAAACAGGATCTAACAACCCCACAGGAATCTCATCAGACGCGGATAAAATCCCATTCCACCCCTACTATACGAATAAGGACATTCTAGGCGCCCTATTACTAATCCTAGCCCTCATACTACTAGTACTATTCGCACCCGACCTGCTCGGAGACCCAGACAACTACACTCCCGCAAACCCACTTAACACACCCCCTCACATCAAACCCGAATGATATTTCCTATTTGCATACGCAATCCTACGATCAATCCCTAACGGACTAGGAGGGGTCCTAGCTTTGGCTCTCTCAATCCTAATCTTAGTACTAGTGCCACTACTCCATACATCCAAACAACGAAGCATAATATTCCGACCAATCAGCCAGTGTATATTCTGAATTCTAGTAGCAGACCTATTAACGCTCACATGAATCGGAGGACAGCCGGTCGAGCACCCATACATCATCATCGGGCAACTAGCATCCATCATATATTTCCTGCTAATCCTAGTACTAATGCCAATGGCCAGCACTATCGAAAATAACCTCCTA------AAATGA------------------------------------------------------AGA Seq43 ATGACCAACATACGAAAAACTCATCCTTTAATAAAAATCATTAACGAGTCTTTCATTGACCTTCCTACCCCATCTAACATCTCTGCATGATGGAACTTCGGCTCTCTTTTAGGATTATGCCTTGTAATTCAGATTCTCACAGGACTTTTCCTAGCCATACATTACACCTCCGACACCACAACAGCCTTCTCATCAGTCACCCATATCTGCCGAGACGTAAACTACGGATGATTAATCCGATACATACATGCTAACGGAGCTTCAATATTCTTCATCTGCCTCTTCCTCCACGTAGGACGAGGCCTGTACTATGGGTCATACACTTTCATTGAAACCTGAAACATTGGAGTACTATTATTATTCACTGTAATAGCAACAGCCTTTATAGGCTACGTCTTACCATGAGGACAAATATCCTTCTGAGGAGCCACAGTAATTACAAACCTCCTATCCGCTATCCCCTATATCGGCACAACCCTGGTAGAATGGACTTGAGGCGGCTTCTCAGTAGACAAAGCCACCCTGACTCGATTCTTCGCCTTTCACTTTATCCTTCCATTCATCGTAGCAGCCCTAGCTGTAGTACATCTTCTATTCCTCCACGAAACAGGATCCAACAACCCTATCGGACTAAACTCAGACGTGGACAAAATTCCATTCCATCCGTACTACACAATCAAAGATGCCCTGGGATTCCTTCTCCTAATCCTAGTTCTCCTTATACTAGTACTATTCTCCCCAGACCTCCTAGGAGACCCCGACAACTACACACCAGCTAACCCACTCAACACTCCACCCCATATCAAGCCTGAATGATACTTCCTATTTGCCTACGCCATCTTACGATCAATTCCAAATAAACTAGGAGGAGTAATTGCTCTAGTCCTATCAATCCTGATCCTAGCCCTCGTCCCATTCCTACATAATTCTAAACAACGAAGCATAATCTTCCGACCAATTAGCCAATGCCTGTACTGACTACTCGTAGCTGACCTGCTTACCCTAACTTGAATCGGAGGACAACCAGTGGAGCACCCTTTCATTATCATCGGACAAATCGCATCTATCCTATACTTCTCCATCATCCTCATCCTCATACCCCTAGCTAGCATACTAGAAAACAAGATATTA------AAATGA------------------------------------------------------AGA Seq44 ATGACAACCCCCCGCAAAACACATCCACTAGCAAAAATCATTAACAACTCATTCATTGATCTCCCCACACCATCCAACATCTCCGCCTGATGAAATTTCGGCTCACTCCTAGGTATTTGCCTGATTATCCAAATTACTACAGGTCTATTCTTAGCCATACACTACACACCAGACACCTCAACTGCCTTCTCCTCAGTCGCCCACATCACCCGAGACGTCAACTACGGCTGAATAATCCGCTACCTACACGCCAATGGCGCCTCCATATTCTTCATCTGCCTCTTCCTCCACATTGGCCGAGGCCTATACTATGGATCATTCCTTTTTCTGAAGACCTGAAACGTCGGTATTATCCTCCTACTCACAACCATAGCCACAGCATTCATAGGCTATGTCCTCCCATGGGGCCAAATATCATTCTGAGGGGCCACAGTAATTACAAACCTTCTATCAGCCATCCCATACATCGGATCTGACCTCGTACAATGAATCTGAGGCGGCTTCTCAGTAGATAAAGCCACCCTCACACGATTTTTCACCTTTCACTTTATTCTACCCTTTATCATCGCTGCCCTGGCAACCATCCACCTCTTGTTTCTGCATGAAACAGGATCAAGTAACCCATCAGGAGTAGCATCAGACCTCGATAAAATCACATTTCACCCCTATTACACAACCAAAGACATCCTAGGTCTAATTATTCTCCTCCTATGCCTAATAAGCCTAACCCTATTTTCACCTGACCTTCTAACTGACCCAGATAATTACACACTAGCTAATCCCCTCAACACTCCACCCCACATTAAACCAGAATGATACTTTCTATTCGCATACGCAATCCTACGATCTATCCCTAACAAATTAGGAGGCGTCCTAGCCCTAATACTCTCCATCCTAATCCTCATAATCATCCCTACTCTCCACCTATCAAAGCAACAAAGCATAGGATTCCGACCCATTACCCAAATCCTATTCTGAACCCTAGTAGCCGACCTATTTACGCTCACATGAATCGG---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Seq45 ATGACTACCCCCCGCAAGACACATCCACTAACAAAAATCATTAACAACTCATTCATTGATCTCCCCACACCATCCAACATTTCCGCCTGATGAAATTTCGGCTCACTCCTAGGTATTTGCCTAATTATCCAAATCACTACAGGTCTATTCCTAGCCATACATTATACACCAGACACTTCAACTGCCTTCTCCTCGGTCGCCCACATCACCCGAGACGTCAACTACGGCTGAATAATCCGCTACCTACACGCCAACGGCGCTTCCATATTCTTCATCTGCCTATTCCTCCACATTGGCCGAGGCTTATATTACGGGTCATTCCTTTTTCTGAAGACCTGAAACGTCGGTATTATCCTCCTACTCACAACCATAGCCACAGCATTCATAGGCTACGTCCTCCCATGAGGCCAAATATCATTCTGAGGGGCCACAGTAATTACAAACCTTCTATCAGCCATCCCATACATCGGATCTGACCTCGTACAATGAATCTGAGGTGGGTTCTCAGTAGATAAAGCCACCCTCACACGATTTTTCACCTTTCACTTTATTTTACCCTTTATCATTGCTGCCCTAGCAACTATCCACCTCTTGTTTCTGCATGAGACAGGATCAAGTAACCCATCAGGAATGGCATCAGACCTCGACAAAATCACATTTCACCCCTACTATACAACCAAAGACATCCTAGGCCTAATTATTCTCCTCCTATGTCTAATAAGCCTAACCCTATTTTCACCTGATCTTCTAACCGACCCAGATAATTACACACTAGCTAACCCCCTCAACACCCCACCCCACATTAAACCAGAATGATACTTCCTATTTGCATACGCAATCCTACGATCTATCCCTAACAAATTAGGAGGCGTCCTAGCCCTAATACTCTCCATCCTAATTCTCATAATTATCCCCACCCTCCACCTATCAAAGCAACAAAGCATAGGATTCCGACCTATCACCCAAATCCTATTCTGAACCCTAGTAGCCGACCTATTCACACTCACATGAATCGG---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Seq46 ATGACTACCCCCCGCAAAACTCACCCACTAGCAAAAATCATCAACAATTCATTCATTGACCTCCCTACACCATCCAACATCTCCGCCTGGTGAAATTTCGGCTCACTCCTAGGTATTTGCCTAATTATTCAAATCACTACAGGTCTATTCTTAGCCATACACTATACACCAGACACTTCAACCGCCTTCTCCTCAGTCGCCCACATCACCCGAGACGTCAACTATGGCTGAATAATCCGCTACCTACATGCCAACGGCGCCTCCATATTCTTTATCTGCCTCTTTCTCCACATTGGCCGAGGCTTATATTACGGATCATTCCTTTTTCTGGAGACCTGAAACGTCGGTATTATCCTCCTACTCACAACCATAGCCACAGCATTCATAGGCTATGTCCTCCCATGAGGCCAAATATCATTCTGAGGGGCCACAGTAATTACAAACCTTCTGTCAGCCATTCCATATATCGGGTCTGACCTCGTACAATGAATCTGAGGTGGCTTCTCAGTAGATAAAGCCACCCTCACACGATTTTTCACCTTTCACTTTATCTTGCCATTTATTATCGCTGCCCTAGCAATCATCCACCTCTTGTTTCTGCATGAAACAGGATCAAGTAACCCATCAGGAGTAGCATCGGACCTCGACAAAATTACATTTCACCCCTACTATACAACCAAAGATATCCTAGGCTTAATTATTCTCCTCCTATGCCTAATAAGCCTAACCCTATTTCTACCCGACCTTCTAACCGACCCAGACAATTATACACTAGCCAACCCCCTCAACACCCCACCTCA---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Seq47 ATGACTACTCCCCGCAAAACACATCCACTAGCAAAAATCATCAACAACTCATTCATTGATCTCCCTACACCATCCAACATCTCCGCCTGATGAAATTTCGGCTCACTCCTAGGTATTTGCCTAATTATTCAAATCACTACAGGTCTATTCTTAGCCATACACTATACACCAGACACTTCAACTGCCTTCTCCTCAGTCGCCCACATCACCCGAGACGTCAACTACGGCTGAATAATCCGCTACCTACACGCCAATGGCGCCTCCATATTCTTCATCTGCCTCTTCCTTCACATTGGCCGAGGCCTATATTATGGATCATTCCTTTTTCTGAAGACCTGAAACGTCGGTATTATCCTTCTACTCACAACTATAGCCACAGCATTCATAGGCTATGTCCTCCCATGAGGCCAAATATCATTCTGAGGGGCCACAGTAATTACAAACCTCCTATCAGCCATCCCATACATCGGACCTGACCTCGTACAATGAATCTGAGGTGGTTTCTCAGTAGATAAAGCCACCCTCACACGATTTTTCACCTTTCACTTCATTCTACCCTTTATTATCGCTGCCCTAGCAACCATCCACCTCTTGTTTCTGCATGAAACAGGATCAAGTAACCCATCAGGAATGACATCGGACCTTGACAAAATCACATTTCACCCCTACTATACAACCAAAGATATCCTAGGCCTAACTATTCTCCTCCTATGTCTAATAAGCCTGACCCTATTTTCACCTGACCTTCTAACCGACCCAGATAATTATACACTAGCTAATCCCCTCAACACTCCACCCCACATTAAACCAGAGTGGTATTTCCTATTTGCATACGCAATCCTACGATCTATCCCTAACAAACTAGGAGGTGTCCTAGCCCTAGTACTCTCCATCCTGATCCTAATAATTATCCCTACCCTCCACCTATCAAAGCAACAAAGCATAGGATTCCGACCCATCACCCAAATCCTATTCTGAACTCTAGTAGCCGACCTATTCACACTCACATGAATCGG---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Seq48 ATGACTACCCCCCGCAAAACTCACCCACTAGCAAAAATCATCAACAATTCATTCATTGACCTCCCTACACCATCCAACATCTCCGCCTGGTGAAATTTCGGCTCACTCCTAGGTATTTGCCTAATTATTCAAATCACTACAGGTCTATTCTTAGCCATACACTATACACCAGACACTTCAACCGCCTTCTCCTCAGTCGCCCACATCACCCGAGACGTCAACTATGGCTGAATAATCCGCTATCTACATGCCAACGGCGCCTCCATATTCTTTATCTGCCTCTTTCTCCACATTGGCCGAGGCTTATATTACGGATCATTCCTTTTTCTGGAGACCTGGAACGTCGGTATTATCCTCCTACTCACAACCATAGCCACAGCATTCATAGGCTATGTCCTCCCATGAGGCCAAATATCATTCTGAGGGGCCACAGTAATTACAAACCTTCTGTCAGCCATTCCATATATCGGGTCTGACCTCGTACAATGAATCTGAGGTGGCTTCTCAGTAGATAAAGCCACCCTCACACGATTTTTCACCTTTCACTTTATCTTGCCATTTATTATCGCTGCCCTAGCAACCATCCACCTCTTGTTTCTGCATGAAACAGGATCAAGTAACCCATCAGGAGTAGCATCGGACCTCGACAAAATTACATTTCACCCCTACTATACAACCAAAGATATCCTAGGCTTAATTATTCTCCTCCTATGCCTAATAAGCCTAACCCTATTTCTACCCGACCTTCTAACCGACCCAGACAATTATACACTAGCCAACCCTCTCAACACCCCACCTCA---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Seq49 ATGACTACCCCCCGCAAAACTCACCCACTAGCAAAAATCATCAACAATTCATTCATTGACCTCCCTACACCATCCAACATCTCCGCCTGATGAAATTTCGGCTCACTCCTAGGCATTTGCCTCATTATTCAAATTACTACAGGCCTATTCTTAGCCATACACTATACACCAGATACTTCAACCGCCTTCTCTTCAGTCGCTCACATCACCCGAGACGTCAACTATGGCTGAATAATCCGCTACCTACACGCCAATGGCGCCTCCATATTCTTTATCTGTCTCTTTCTCCACATTGGCCGAGGCTTATATTACGGATCATTCCTTTTTCTGGAGACCTGAAACGTCGGTATTATCCTCCTACTCACAACCATAGCCACAGCATTCATAGGCTATGTCCTCCCATGAGGCCAAATATCATTCTGAGGCGCCACAGTAATTACAAACCTTCTGTCAGCCATCCCATATATCGGATCTGACCTTGTACAATGAATCTGAGGTGGCTTCTCAGTAGATAAAGCCACCCTCACACGATTTTTCACCTTTCACTTTATTTTACCATTTATTATCGCTGCCCTAGCAACCATCCATCTCTTGTTTCTGCATGAAACAGGATCAAGTAACCCGTCAGGAATGGCATCAGACCTCGACAAAATTACATTTCACCCCTACTATACAACCAAAGACATCCTAGGCTTAATTATTCTCCTTCTATGCCTAATGAGCCTAACTCTATTTTCACCCGACCTTTTAACCGACCCAGACAATTATACACTAGCTAATCCCCTCAACACCCCACCTCA---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ExaML-3.0.21/testData/49.model000066400000000000000000000001251330315463200155700ustar00rootroot00000000000000DNA, gene1 = 1-300 DNA, gene2 = 301-900 DNA, gene3 = 901-1100 DNA, gene4 = 1101-1200 ExaML-3.0.21/testData/49.tree000066400000000000000000000005741330315463200154370ustar00rootroot00000000000000(Seq14,(((Seq10,Seq42),((Seq47,(Seq44,Seq45)),(Seq49,(Seq48,Seq46)))),(((((((Seq2,((Seq6,Seq3),Seq7)),Seq4),Seq5),(Seq9,Seq8)),(Seq13,(Seq11,Seq12))),((Seq27,(Seq31,Seq41)),((((Seq22,((Seq38,Seq40),(Seq28,Seq21))),(((Seq34,Seq30),((Seq20,Seq26),(((Seq19,Seq36),(Seq37,Seq33)),(Seq25,Seq23)))),(Seq17,(Seq29,(((Seq16,Seq15),Seq39),(Seq35,Seq32)))))),Seq18),Seq24))),Seq43)),Seq1); ExaML-3.0.21/versionHeader/000077500000000000000000000000001330315463200153415ustar00rootroot00000000000000ExaML-3.0.21/versionHeader/version.h000066400000000000000000000002201330315463200171710ustar00rootroot00000000000000#define programName "ExaML" #define programVersion "3.0.21" #define programVersionInt 3021 #define programDate "May 29 2018"