From 25aecb96e098664e3ca472afdc8a93657ec52317 Mon Sep 17 00:00:00 2001 From: Karthik Gururaj Date: Sat, 18 Jan 2014 11:07:23 -0800 Subject: [PATCH] Added support for dynamic selection between AVX and un-vectorized C++, still to include SSE code from Mohammad. Debug flags turned on in this commit. --- .gitignore | 13 ++ PairHMM_JNI/Makefile | 45 +++-- PairHMM_JNI/avx_function_instantiations.cc | 12 ++ PairHMM_JNI/avx_function_prototypes.h | 19 ++ PairHMM_JNI/baseline.cc | 85 +++++++++ PairHMM_JNI/headers.h | 24 +++ PairHMM_JNI/libJNILoglessPairHMM.so | Bin 77757 -> 96945 bytes ...e_sting_utils_pairhmm_JNILoglessPairHMM.cc | 125 +++++++++---- PairHMM_JNI/pairhmm-1-base.cc | 177 +++++------------- PairHMM_JNI/pairhmm-template-kernel.cc | 10 +- PairHMM_JNI/pairhmm-template-main.cc | 5 +- PairHMM_JNI/run.sh | 9 +- PairHMM_JNI/template.h | 28 +-- PairHMM_JNI/{convert_char.cc => utils.cc} | 39 ++++ PairHMM_JNI/utils.h | 13 ++ .../utils/pairhmm/JNILoglessPairHMM.java | 7 +- 16 files changed, 399 insertions(+), 212 deletions(-) create mode 100644 PairHMM_JNI/avx_function_instantiations.cc create mode 100644 PairHMM_JNI/avx_function_prototypes.h create mode 100644 PairHMM_JNI/baseline.cc create mode 100644 PairHMM_JNI/headers.h rename PairHMM_JNI/{convert_char.cc => utils.cc} (84%) create mode 100644 PairHMM_JNI/utils.h diff --git a/.gitignore b/.gitignore index 65f111587..ede62ef81 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,16 @@ dump/ lib/ out/ /atlassian-ide-plugin.xml +kg_tmp/ +maven-ant-tasks-2.1.3.jar +null-sequenceGraph.25.0.0.raw_readthreading_graph.dot +null-sequenceGraph.25.0.1.cleaned_readthreading_graph.dot +null-sequenceGraph.25.0.1.initial_seqgraph.dot +null-sequenceGraph.3.0.0.raw_readthreading_graph.dot +null-sequenceGraph.3.0.1.cleaned_readthreading_graph.dot +null-sequenceGraph.3.0.1.initial_seqgraph.dot +org/ +package-list +resources/ +velocity.log + diff --git a/PairHMM_JNI/Makefile b/PairHMM_JNI/Makefile index 70bf96dd3..62dc3b0f6 100644 --- a/PairHMM_JNI/Makefile +++ b/PairHMM_JNI/Makefile @@ -7,40 +7,59 @@ OMPCFLAGS=-fopenmp JAVA_ROOT=/opt/jdk1.7.0_25/ JNI_COMPILATION_FLAGS=-D_REENTRANT -fPIC -I${JAVA_ROOT}/include -I${JAVA_ROOT}/include/linux -CFLAGS=-O3 -W -Wall -pedantic $(OMPCFLAGS) -Wno-unknown-pragmas -xAVX - -CXXFLAGS=$(CFLAGS) +COMMON_COMPILATION_FLAGS=$(JNI_COMPILATION_FLAGS) -O3 -W -Wall -pedantic $(OMPCFLAGS) -Wno-unknown-pragmas CC=icc CXX=icc LDFLAGS=-lm $(OMPLDFLAGS) -#BIN:=pairhmm-1-base #pairhmm-2-omp pairhmm-3-hybrid-float-double pairhmm-4-hybrid-diagonal pairhmm-5-hybrid-diagonal-homogeneus pairhmm-6-onlythreediags pairhmm-7-presse pairhmm-8-sse #pairhmm-dev -BIN:=libJNILoglessPairHMM.so pairhmm-template-main checker +BIN=libJNILoglessPairHMM.so pairhmm-template-main checker +#BIN=checker -#SOURCES=pairhmm-1-base.cc input.cc -LIBSOURCES=org_broadinstitute_sting_utils_pairhmm_JNILoglessPairHMM.cc convert_char.cc -SOURCES=$(LIBSOURCES) pairhmm-template-main.cc pairhmm-1-base.cc -LIBOBJECTS=$(LIBSOURCES:.cc=.o) DEPDIR=.deps DF=$(DEPDIR)/$(*).d +#Common across libJNI and sandbox +COMMON_SOURCES=utils.cc avx_function_instantiations.cc baseline.cc +#Part of libJNI +LIBSOURCES=org_broadinstitute_sting_utils_pairhmm_JNILoglessPairHMM.cc $(COMMON_SOURCES) +SOURCES=$(LIBSOURCES) pairhmm-template-main.cc pairhmm-1-base.cc +LIBOBJECTS=$(LIBSOURCES:.cc=.o) +COMMON_OBJECTS=$(COMMON_SOURCES:.cc=.o) + + +#No vectorization for these files +NO_VECTOR_SOURCES=org_broadinstitute_sting_utils_pairhmm_JNILoglessPairHMM.cc pairhmm-template-main.cc pairhmm-1-base.cc utils.cc baseline.cc +#Use -xAVX for these files +AVX_SOURCES=avx_function_instantiations.cc +#Use -xSSE4.2 for these files +SSE_SOURCES= + +NO_VECTOR_OBJECTS=$(NO_VECTOR_SOURCES:.cc=.o) +AVX_OBJECTS=$(AVX_SOURCES:.cc=.o) +SSE_OBJECTS=$(SSE_SOURCES:.cc=.o) +$(NO_VECTOR_OBJECTS): CXXFLAGS=$(COMMON_COMPILATION_FLAGS) +$(AVX_OBJECTS): CXXFLAGS=$(COMMON_COMPILATION_FLAGS) -xAVX +$(SSE_OBJECTS): CXXFLAGS=$(COMMON_COMPILATION_FLAGS) -xSSE4.2 +OBJECTS=$(NO_VECTOR_OBJECTS) $(AVX_OBJECTS) $(SSE_OBJECTS) + all: $(BIN) -include $(addprefix $(DEPDIR)/,$(SOURCES:.cc=.d)) -checker: pairhmm-1-base.o convert_char.o +checker: pairhmm-1-base.o $(COMMON_OBJECTS) $(CXX) $(OMPCFLAGS) -o $@ $^ $(LDFLAGS) -pairhmm-template-main: pairhmm-template-main.o convert_char.o +pairhmm-template-main: pairhmm-template-main.o $(COMMON_OBJECTS) $(CXX) $(OMPCFLAGS) -o $@ $^ $(LDFLAGS) libJNILoglessPairHMM.so: $(LIBOBJECTS) $(CXX) $(OMPCFLAGS) -shared -o $@ $(LIBOBJECTS) -%.o: %.cc + +$(OBJECTS): %.o: %.cc @mkdir -p $(DEPDIR) - $(COMPILE.cpp) -MMD -MF $(DF) $(JNI_COMPILATION_FLAGS) $(CXXFLAGS) $(OUTPUT_OPTION) $< + $(CXX) -c -MMD -MF $(DF) $(CXXFLAGS) $(OUTPUT_OPTION) $< clean: diff --git a/PairHMM_JNI/avx_function_instantiations.cc b/PairHMM_JNI/avx_function_instantiations.cc new file mode 100644 index 000000000..c29370561 --- /dev/null +++ b/PairHMM_JNI/avx_function_instantiations.cc @@ -0,0 +1,12 @@ +#include "template.h" + +#include "define-float.h" +#include "shift_template.c" +#include "pairhmm-template-kernel.cc" + +#include "define-double.h" +#include "shift_template.c" +#include "pairhmm-template-kernel.cc" + +template double compute_full_prob_avxd(testcase* tc, double* nextlog); +template float compute_full_prob_avxs(testcase* tc, float* nextlog); diff --git a/PairHMM_JNI/avx_function_prototypes.h b/PairHMM_JNI/avx_function_prototypes.h new file mode 100644 index 000000000..1836a1c37 --- /dev/null +++ b/PairHMM_JNI/avx_function_prototypes.h @@ -0,0 +1,19 @@ +void GEN_INTRINSIC(_vector_shift, PRECISION) (UNION_TYPE &x, MAIN_TYPE shiftIn, MAIN_TYPE &shiftOut); +void GEN_INTRINSIC(_vector_shift_last, PRECISION) (UNION_TYPE &x, MAIN_TYPE shiftIn); +void GEN_INTRINSIC(precompute_masks_, PRECISION)(const testcase& tc, int COLS, int numMaskVecs, MASK_TYPE (*maskArr)[NUM_DISTINCT_CHARS]); +void GEN_INTRINSIC(init_masks_for_row_, PRECISION)(const testcase& tc, char* rsArr, MASK_TYPE* lastMaskShiftOut, int beginRowIndex, int numRowsToProcess); +void GEN_INTRINSIC(update_masks_for_cols_, PRECISION)(int maskIndex, MASK_VEC& currMaskVecLow, MASK_VEC& currMaskVecHigh, MASK_TYPE (*maskArr) [NUM_DISTINCT_CHARS], char* rsArr, MASK_TYPE* lastMaskShiftOut, MASK_TYPE maskBitCnt); +void GEN_INTRINSIC(computeDistVec, PRECISION) (MASK_VEC& currMaskVecLow, MASK_VEC& currMaskVecHigh, _256_TYPE& distm, _256_TYPE& _1_distm, _256_TYPE& distmChosen); +template void GEN_INTRINSIC(initializeVectors, PRECISION)(int ROWS, int COLS, NUMBER* shiftOutM, NUMBER *shiftOutX, NUMBER *shiftOutY, Context ctx, testcase *tc, _256_TYPE *p_MM, _256_TYPE *p_GAPM, _256_TYPE *p_MX, _256_TYPE *p_XX, _256_TYPE *p_MY, _256_TYPE *p_YY, _256_TYPE *distm1D); +template void GEN_INTRINSIC(stripINITIALIZATION, PRECISION)( + int stripIdx, Context ctx, testcase *tc, _256_TYPE &pGAPM, _256_TYPE &pMM, _256_TYPE &pMX, _256_TYPE &pXX, _256_TYPE &pMY, _256_TYPE &pYY, + _256_TYPE &rs, UNION_TYPE &rsN, _256_TYPE &distm, _256_TYPE &_1_distm, _256_TYPE *distm1D, _256_TYPE N_packed256, _256_TYPE *p_MM , _256_TYPE *p_GAPM , + _256_TYPE *p_MX, _256_TYPE *p_XX , _256_TYPE *p_MY, _256_TYPE *p_YY, UNION_TYPE &M_t_2, UNION_TYPE &X_t_2, UNION_TYPE &M_t_1, UNION_TYPE &X_t_1, + UNION_TYPE &Y_t_2, UNION_TYPE &Y_t_1, UNION_TYPE &M_t_1_y, NUMBER* shiftOutX, NUMBER* shiftOutM); +_256_TYPE GEN_INTRINSIC(computeDISTM, PRECISION)(int d, int COLS, testcase * tc, HAP_TYPE &hap, _256_TYPE rs, UNION_TYPE rsN, _256_TYPE N_packed256, + _256_TYPE distm, _256_TYPE _1_distm); +void GEN_INTRINSIC(computeMXY, PRECISION)(UNION_TYPE &M_t, UNION_TYPE &X_t, UNION_TYPE &Y_t, UNION_TYPE &M_t_y, + UNION_TYPE M_t_2, UNION_TYPE X_t_2, UNION_TYPE Y_t_2, UNION_TYPE M_t_1, UNION_TYPE X_t_1, UNION_TYPE M_t_1_y, UNION_TYPE Y_t_1, + _256_TYPE pMM, _256_TYPE pGAPM, _256_TYPE pMX, _256_TYPE pXX, _256_TYPE pMY, _256_TYPE pYY, _256_TYPE distmSel); +template NUMBER GEN_INTRINSIC(compute_full_prob_avx, PRECISION) (testcase *tc, NUMBER *before_last_log = NULL); + diff --git a/PairHMM_JNI/baseline.cc b/PairHMM_JNI/baseline.cc new file mode 100644 index 000000000..b953c4436 --- /dev/null +++ b/PairHMM_JNI/baseline.cc @@ -0,0 +1,85 @@ +#include "headers.h" +#include "template.h" + +template +NUMBER compute_full_prob(testcase *tc, NUMBER *before_last_log = NULL) +{ + int r, c; + int ROWS = tc->rslen + 1; + int COLS = tc->haplen + 1; + + Context ctx; + + NUMBER M[MROWS][MCOLS]; + NUMBER X[MROWS][MCOLS]; + NUMBER Y[MROWS][MCOLS]; + NUMBER p[MROWS][6]; + + p[0][MM] = ctx._(0.0); + p[0][GapM] = ctx._(0.0); + p[0][MX] = ctx._(0.0); + p[0][XX] = ctx._(0.0); + p[0][MY] = ctx._(0.0); + p[0][YY] = ctx._(0.0); + for (r = 1; r < ROWS; r++) + { + int _i = tc->i[r-1] & 127; + int _d = tc->d[r-1] & 127; + int _c = tc->c[r-1] & 127; + p[r][MM] = ctx._(1.0) - ctx.ph2pr[(_i + _d) & 127]; + p[r][GapM] = ctx._(1.0) - ctx.ph2pr[_c]; + p[r][MX] = ctx.ph2pr[_i]; + p[r][XX] = ctx.ph2pr[_c]; + p[r][MY] = ctx.ph2pr[_d]; + p[r][YY] = ctx.ph2pr[_c]; + //p[r][MY] = (r == ROWS - 1) ? ctx._(1.0) : ctx.ph2pr[_d]; + //p[r][YY] = (r == ROWS - 1) ? ctx._(1.0) : ctx.ph2pr[_c]; + } + + for (c = 0; c < COLS; c++) + { + M[0][c] = ctx._(0.0); + X[0][c] = ctx._(0.0); + Y[0][c] = ctx.INITIAL_CONSTANT / (tc->haplen); + } + + for (r = 1; r < ROWS; r++) + { + M[r][0] = ctx._(0.0); + X[r][0] = X[r-1][0] * p[r][XX]; + Y[r][0] = ctx._(0.0); + } + + NUMBER result = ctx._(0.0); + + for (r = 1; r < ROWS; r++) + for (c = 1; c < COLS; c++) + { + char _rs = tc->rs[r-1]; + char _hap = tc->hap[c-1]; + int _q = tc->q[r-1] & 127; + NUMBER distm = ctx.ph2pr[_q]; + if (_rs == _hap || _rs == 'N' || _hap == 'N') + distm = ctx._(1.0) - distm; + else + distm = distm/3; + M[r][c] = distm * (M[r-1][c-1] * p[r][MM] + X[r-1][c-1] * p[r][GapM] + Y[r-1][c-1] * p[r][GapM]); + X[r][c] = M[r-1][c] * p[r][MX] + X[r-1][c] * p[r][XX]; + Y[r][c] = M[r][c-1] * p[r][MY] + Y[r][c-1] * p[r][YY]; + } + + for (c = 0; c < COLS; c++) + { + result += M[ROWS-1][c] + X[ROWS-1][c]; + } + + if (before_last_log != NULL) + *before_last_log = result; + + return result; + //return ctx.LOG10(result) - ctx.LOG10_INITIAL_CONSTANT; +} + +template double compute_full_prob(testcase* tc, double* nextbuf); +template float compute_full_prob(testcase* tc, float* nextbuf); + diff --git a/PairHMM_JNI/headers.h b/PairHMM_JNI/headers.h new file mode 100644 index 000000000..42485fc51 --- /dev/null +++ b/PairHMM_JNI/headers.h @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + diff --git a/PairHMM_JNI/libJNILoglessPairHMM.so b/PairHMM_JNI/libJNILoglessPairHMM.so index 435034f78de8b6b51001484dd15d775e3fdae892..9b6b8e6930e9764b187f019979a525dd50840252 100755 GIT binary patch literal 96945 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

cZ-x*bL@^bRF-^(%PSLf5Xx1N{0S zk9PgXO8q&fQq>Zrj6PW5b`3#qSE}lw6utMCpSc}r?E@N+^eA3IFaLB~@7;Kfx+^Vb z=hoS-A=RdQ<7R@TV>$!~T#4kb971wPdKt=}2+Gd(X2v5sw@Qh(S{YqKmXbkQcG~o` z+tcotHeFfv1=rM7{eq^i^0a|xn*Oe)S9=`5YWg<4uSW^3@m#?)!9Lrn#hasjb!#6; zjbyQspy{WT;0BT3O5Twsrc;`kfI6p9^+xbES#YrIN^a;Nmwkt<*mE!JhP+j&+AQRB zxT*~&xC5j}05<{j)qLryepI}C;;Np@1jLLNFNa;#SK=jYS^GbukRkL{FZ{?xv?rsc zT?wucOqJj&!7W|i>{*C3(8*#v6n%|n2ei2fve6QqrFaFwPq>O zrFpjlGh%?gVNKS>DB<8{tKe~_+MuW3a*qi-p1Og^QAWFf{hIG+=) z{?(pVusz|5?fr`v9FBi{3sH@Ok`#@0+w6(E2AJzGQYoR7hmnN1W@Mp;1?>>5{&nyN zX0a#6@S;;Qje#`A(*bQhSHr24I>QpN-*VqS~Rl68FRp0)we?kDUGoJ2)k_2 z9wT3%Vpj=qH67%f9j^F#qc2Nf!AfX@Ec5=;-IQ6$GKG8z=vJGcwn#z}a(t>pZm&{E1}LQ9)HZNP0u!YHAsH8RbU!YT${@)uci2WpHou`&%jKKZ-~K0x-B z$ju%mGMc}J7&UdS>bp^D)nZRyM_?cmfw|D3Nc3Ce1T9w5IByg*!Sx|Y8z5<%6AGG; zJP$NcW!UE$p-00Fl%j7{YT&cq7)ZTBBVQSRf*p;c+joT?2Ua2WL!$zYCtW|1*507h zABk3iYef@ect3;DU!myPSH!rMufYT_d<>4kv<|BweR@NBFe;;_&a#z%+4$0YXe@DV zXg@g8wc;rBl#%>pTKkT4y~vY=F7)QRZZu4~Cp%p~Mcj-{KS6DwtsJ4!s)p8JT=LGe z*9axo>4QCn@NZQOvER622R{7=Y9`w=13RcMd>R%c z@NvL{YP^KvT=6>u1YCd36K^~T91wWrAf^T{gAJv7^F0daecy8}k3$q3UJujJg3<+O zh>M;>J++`T1uZE30gaBXLIHjUpUWEPgG`@3?zMN^4r4Hk7iJM7yH7uMTnEw^`K?yB z5jfFZvLp`OMc_m?84H}{uZ(sA93N)WwTkg!-2MY7<*%qWOKEu0a9q}~x*4OhOz=5}WztZ~m|KzLFHE9;NNEn< z0=OPt4Oy53K8@o}Dveb9QTUc+OlFVH+hB@>1aN6E^LPcqia&{b8)aNa)?g5C3`P}` zzeIe;S~y%QzQ#%z{D6Lp!Kne9@jQx!^&@01+atUtT&WU_HTId_BiMU}4WAWjye0_M zo{eCLTx0CiID`I+VQ{Ua4z^R>(!YZGoTOgZ-BDszjNwOKh(bSo7>N!d5gzZ$M>8I- z>Sy5*b-1|Ao|S-&x4vXWQ;t2uCfe*-4cvCL7#`?*Kw;p()A&rZ`oKHPc<%||kc^CF zvJE1q(GG6Fvs{Va>|s*lr(d8HI&QdS2Xx5Vk0$wen`yv%Bc9O2B3CC(Y^98$l=T?QEny%Z^K{b0 z`|wptXrNC-2@!>{1WOa58YjUG*(rdf2_gK|Ev6>UT_!Za1hN+54S>}Q#y+rsv}7$) zh&MBZD5O@Vpo}twcr#Ooc6$UVgeK~Mg(e#0V+YfKcP*aKL>6SR*~Dvw~T_o8CY1&7?4R{J5vzwZ@IBaU-Pkn_Zm_XJ-yaBMd z8n1%|q+J(DA>PasLKACc3d$&Xh&MBZ(8T>nkzD7ip@UwCdoi@J6bW3_m!N!G?f*i# zLMfMZu04}>s{Jn57;5kRV~3mwGdN>~+-B8311lgoo9(Dff5WWzqnD!Ii#-cvShf&p zIugB!oS-e1w8a)p+COOsorx6QM7#l@zC>LgK?)JIeQ11xYNNJg5{$%nW08VBeHXHRgLP-cMaD)5PHY4ZJT~>?xCr2Tuc%f{Xs-Mg3egb0sn&?HNcbDM=j^A?imF zN?VLz#5_XI#t7vfpd{B}w!k{gaIF}LHdKOmW%cTt5$Vdw2FY`j;D}g5M_ymy`(o4v zzoi%?6$Ex5ZWd!bLcOw@eOfR(DQ3JrV2FkgfoUh`>CR{kYacQrnq-n*eQB1+EmQdP zHBJR^npgsHtylw%X26sS-((iXhZGFUY}pJ9HBX#^5YZikwq~zp%*0e_?R7rq*SEP| zA3SKHp7S`ONQpO*{U_>cA3t~zl+hV~Iq}b7#OQ*LP4{jmY2gnc3RYB}5b-b7gCMTG zF3r15s%`mB#&7y@a~>|WOhIFexu18Yuw_IQjI1sc+8!x!#?6ufgEbjuBeuMTNEDs= zI=fl&K1?-3i;EqTg3)c0^z=4VRr91y3XMHu-0=xb^dqWgrm=}8Nm6^G_eBxrWCjPH zQFN!GPs5zWg&AQNOFjra8qUv5GZzE<4;r^Y9&=F&>9`^VLpD+=JyRNg zWdo9h@uKa_3RyuAM7XhzBcQ&YG229oJ*I!YbkM4`?YqmL+bD+*mDk}rBY z9djf$&I#2u^wSe*uA%Q_xc>Yl?o%Kz)<5AI+DQC|K;!)_Cj1hUzTj5ah`w9ZcdGgu zs=iy%_gLjB`Wy6ybTg_B39H4bi>mM9(k-VYs{W>mM7&kzYGf2*rN@Lcp5b}OL&ucY^*+ptSF(W11$=EQ=&y=@2ci1K%|7f zumv9NDB(SpFt($Fx(-%C*kzJcLkC)vFjt~?5RFX=dkIrm0#7lRbvVru4xv@eI#hSC z5+w|gtk!j)MF}wyy`E@Sbu)JPBX#%^O%UEqjI@%093vK5C5V_%tUU(lA}q!Ns@0M`OlL4Pe=mhpFR%qFiGx5@@h$5^r#?jBl$*2{tERm?vv#CGWQ=z zzCn`rkUZ5a8-;@TN|F;Kxt8Q)N&WfN%HlQTu$=I_eH%+ zBsqcPcuAf{@;j0|5fK)0_a*s9l01Us|CQvGlKkakAYU!X14({Dl6Ok-ZjuK}@~K~f zyhxHS0Upf%O!8Hd{4U9NO7bL0UQP0qlDv^*FUita<}|t;#w7GJ>6o}&Q~V*?e2Lg8 z9ru!~++=b%3)4fR&L@X6heh2pWwYEw@)=3KgXBY!+#<=bB%hSzQ6&EjWY-YvcfxFv zX{|DS%1`l*c*OHJJc8qD{tn7aiW(gFbG$1U!}WI*{asaWQuTdUD$PhfjK!ZDLCfHt zKxU$*tE19a&PdyqIw5LX>O|+Z)XCA?QnPz$`s7qipQ8A5CCjI0&dAVn5VfVFPgU0i z#%RH7Rq)VsERUtU0b4OLWvPcZQ;?LwEIiozRRQ(8PKeS=(JyNmg`BQP&byg2R_1(0 z<~%AMy`6$VzZVJV%!#6m`A{=zc`uQnfr*<$QTG8#%L&hgf@ZIl`@yPy07Imze=D{` z`(owWhi!-IPtcxfFxmrF8Yi3sXTxmJJa^%NOy#tl2mjlx)Yxww_?k>zB2&9Nr@kBp6OYu2K0e;sk_(Na-$MIV!6r8ymc}?Q zgcck2o-pMWY3cbSzbnZa$u3D=Bgq*gb0C4JHVMl8>(f`DIBCO0ofmx9JT@ZX)^Dl3etN$i0(f4lyYEFC+)dvL*R>lDA9pqa;rU z*~N1V)-eO_R^rS-DiBMN&e8S!L035K4xG5at_1cd5zia1f}dEIB`||_j+i~oFPFwK zLyR%J2aX!;4ki2bWFK<;o4kRd8wi| zDbBryDmZZ#p>H)_e1`?M8|&W%dnd}njv9;02aJ6_ML#5Ak4T4wV-gq8c|$<4Eo+nU zA5J@^7Tymxj^?R^l z(-3FdDEHxzNWw?1>Rm8KHF#UBnozIQw?!-7t*+&bz+ny)Sd8YyB&`0}t^a^B9Ex*4 zmge`K<-9vasoAFli#)OOQ#4EooNa-NGxZTMnR-zSN@{NnT#~5=Vqyu$Ded(*&f`|R zyUO=tBgH3pg(kKu-h=Z8D)pa7YtB7t)tT5pjH=()s_KPptPe$3o$vX)2J!d6^Wnxb za202RSS7)1Q`M)#$7Nv3)fkI}mB+hOQrXxpFPECI9mTmG4x$A#?>SX}-{+e6xzG8z z&-;1#;Er^fw|PN7U(F|#mt*P}o&04>yt+BU0~q0#aeiaKAc5~=pMDG@bHck~ zBCdwYT}u50r&9mb*vwF1kPGqwj#l+=)V(c`Y5vbt{kYG0HgGu{`WRJ@9;ybj$3WxR zL!n+Y=m0gCJ_Z_3ABrI*8^VFYrd1)K>V2cUP6-W=O|iG;V3cZvleU+8Bp zwf?MAtv@z)N~q`()N2D9dxQ-Rni!LbNFZkZBX+$%=Ymq5E0 zS_AzFBKc@O<9zy}7-5~;+-g-l?nqTeM5>~N#$KX@Cb#>%Z&h5cI1j4a9>>dzb-o~(f+|U}PI=}Ei097xE?P{Q*agRKV@#17t zm+=Dr14DusK$b!c=#HlX=T>8#3HoAfB_+JY zg)Zk_rT#1!pW#}U<~{0q_;w_PqmGEgRQi6Ls_d(J-*>I}BMeA2SF}6QU=i(f3w%05 zSn^BwhAdePte_R{qnO4AY%L`0$aVTXrU!qlnRQ5^6rOzo5xtpBb)HwE?v62jPxE(v zpm|#`^@j}Pjg`PGu_JE$We=#!8d(lfR2~g4W0HiAHN81-6I&Jb-q<BTX|AXWns`MehbKSDTTlOjQ|+|F#Ef@S9>Q8tcS z@mTnOuZwXgr$53lr#LTY-p^eR=R@N@Zv#$(sIG}ksqZqoFz=!{Y? zJhjuI%GtY7KdDNrOImu-!yP3k!Ah9sZfO|Qfb%_?hcu%1l*0WiNZB6kK^tJdTy%F| zOhQy2oQYO+JNNMTX#ms7M3*IXl|L z#^rB;CMHo2I($yVGa2YY4|d}qi83uN{G+0BtzfZdlyK7{JeV|Vdcc$Fsy>8c zXG(Aid|G7XJ^_B1tM_byGt#4-a6SC>MGQ+9zy*Ax25(Xlur7a&>+-Ie)u1p^Kq!jA zSV!&A0E+i3RyW>NT}$IgILQNuIItwnhbf_Z5c}YSd40=Roast-VbTC@JioQq@YU4K z&r;Dto$mxNdF?w)(fjtnR?{$8qt*wZ&sl^%2-t>UtkL?Qk+osiHr4td^npSUH=y4m z^yw>uv-+dGwNPK|rrd`h?VF107!IKOE0XyDFdxtdnjVIF<@7?_g?{K-aR*$GrW=z&gXcpZPE9|eBy2@L6qc)b4OewN zw4H$yUa(cH*mI_ksMPGl!UXU>{d97jmT+!Tu;`}NNeM+a!NSf%)+n5jRP;0mm=^1* zxrptB9T6xSiziM4(|UA@x+%e&n~X`p#W%HT-j5W0Zmg^NCFosEIEO=g=El#0NW6&% z?G{%u<|StkKJQlceuZF$IV4rIGh@{D?U;1I1zvD1|A=byQz=yqifxKX z*OdEm3IdbjOcH~E)(DHxJTb27PuU)babdh_)%MQ)pR@Voy2+uyIEOD-(&|en zF*uWgD%t-dou4b}s@3^5tMk`u=dybhl?j*N3~MlV#VZyUnJ%-7ej2o9OxvLN;{$&*^SQ zVR8%m{f1qi?shwZw7?J4;Nlc$U~Hl4|37?+ezM2)*lJy`Q;iKD0C|4V0D| zoDu_#VtBm^Jp}{I9nj|vG)2UkZr%<6)`V1*$HFg>6j^ByY~X$u+(F$T2sI4aUWax3 znFZ3mEbG`P=&+6{;w54otpJUy8f0qYC=GEAiZTqmiN*_$g!zi{!W!QqG6?&ih2CLV zXg+wE0SYa2&bcl!jId;Q1I#HIOqnMOiYUWxw#wATJ(S^-Z-L6knKE1`54%FXDAqbsNmd7n}$?!IxJfl>~%@=Q--JOJLVvJUrldc=cB?98jg8us>`^ ze}Usv^g@h)Tyw!Rj~gTCLVu@$`a%lUEY4ufB8)W)EedNEbsPqL`Yv@Z29tdp2DkZ~ ztz31vAyL(DK+v-ohN>@ipf6y(0;?`XiSW2Z4y?K?PQ=24lrYRA$X7G1{n$<)U>FdX*5Iz_+%2mC2~`Pg^` zDMvY!2}hG8M^x z&@#Dhiu5hB;ag_Iw|ooV@<}H}wjr<(D{QcrD9zbSl_8kZ^j!Fs*`{x4wtP!N@+r%= zEQD`q$LM$*qhroRQlaP2%|2509*0Y(LhF6b9f8ZI1P8c%`T)n2V742DGIj}&K?Zy&Nwu6Hs6{>ho3+ECU9N}CNE$3p!a>BWwwZ@JxeanchzD0#^*#d|A zj_Uo&RdcwrLWO(5(G@K?2R`OYELN$wu{e*;=Bhr(ts}g`Jk6+0P!P3Y*Xb`H(rd%5 zslkU@u`8tprx;qok%)f#DEe(M)Z1XFt6&pSzfdm1TPoj+FK=di-!M+_0JMC{Y zA1yQymf8kOHOBfv`J+U;OzPCMr!7%EnNx5H3(ltb{rVoeR}XT2wf2E?eL2jH~7Wzg|CVsRM^YQgBynjX!A zHKS1z4b0&>kR1G`La&^3Ay8`;J{u?9sjPVFQVY7-qoF#V_tQX@FX4+0pMgN-hw5p> zXYZ)>7chxBf2%Lyq>7_HoLgW@Etcx4UWdcsysiOW{j2iN7*c@!hnn63-kg6A}_^E%$+c{5%?Mnbg}S^ zSoDHd677q|4c{uP$2L~166r8j{6xH%V@15kZyf(SohBlQztVd$-Z(E_5URqF1#S^u z*C-UO^&@@?^oVfm9}2vvi19w^X8h6OQ)2PSFiRU{BnT9~H=%-X1g!5=1mEzqH@pGw zvlUCrjSgcZQn&okNJUa%uHgxy8mL`3n{S*qoP8bso^37Hzy&J~HENg63>}4Wcn21qn zWcVuUn?Y-s?r#i)R{b|wnE=keM0q^|>a9P=xVXnyh|xQ;zWl)7to0Mb$``ok zl+SgLZ#5lZrhc-c!%Rg&_7?QF$}opp^g#?2z+mATQxbFiG(qx{>jU_@8Y`#XlQ^ft zaRfU$SV`A{H>(NQR(ueM>9I<}yJ8=z{w(&QwzwX?774YW4<396CP|zMsopx*!y)=N zy@6)Kz4k|1IG%Vf%*Q6?Srw}|-lI$6H1BEGiY7WY{RG&m-nU(=>e=T)^U+nY?BLza z^t-s~gY*Lx@7Jys>ySW6_*(V;)3pi*K+rJT)PxVQZE`EzrE^=F*w9h-wsHG}D-w0{ zC!!8Yy@7AGwgR6S95I|*3i^mKn86O`;4mg;a!?!2fOZT6+Tjdn#~@zWf&pho`EK+d z=@>()VoNNJBlo0WdLmqW`l!}P!R*8~Y_^PQql&`4I3w?nX&_|4h zOi7e!G-XPnOrt4N5@i|!39*hk>#|FmV)( zvTw-{(J1tMAfa8v))3ofpKDbkuxbc4A=>5*vu*Zk-hFJF_gpL1i?(@B^&WDq!l@&) z>sBpc50-UqRjZD)YR;|6JJr2yW~6{HD|sJRcP45$*T^(j^4xoFaxj|hgFy!Elg;+Q zF4yE>4%;V(?UT>;$+z0)4eCPfYpG&8YnN-qipLdy(C8)c6{8)?JQM%tLRFiu5u zBNul6>~ihwRxY*?Lnov8 zuqSD>_;+~>Ky#kZyjbKA`vVCdChwEmyrD^mvCbgI3S+q}aD@wokDWqpIPY!265M(u|jgCeGhz0 z#gD`uFr;!KyikJ!Zc+6Cqt&2x3;Yhk0CaPT&aU2ak=f@}=eLUfAiRfx^#=3HZx~*U z*v-}(5Z#Lbg_V1Xt%b^+l07#x4V62K${j=Hv@2cg$7fKvH##a8)||VR;tIR-H>_N=j305x7jZZ$hkaVCuR5E^b3kIIJ^-sx zS|axgc4*AAT!QxWN zaZpdV?!jlH{rh^1LL?(;A|_wkjjJ|TEW_lXSwzHM+l>paSj0C;yop3>OY&%hR!iCs zMB#VLL^c+_OO!AQrPd?I0M7~6&-dZ;)Gfvfk!)%Ovb_)Wd`D)4Gbs}~$^0sk367~0 z>)r^D6c+u2MN~-4j1c2Ue1Jqt=3x=qw}qhjMd4j!#%Hr#Wj_6~rH04Kku6?i>!Rl@ z$oyL{?a*_SB~}*2dL_bR8H@e|Y8MrnLE_^PVm^u6Nwj3XKSEPTdjYhxU>BKj*t@ID z6C&A;+=pxdWTR14HN^0@8p8iXbJ^{6n&_RbXY0d*tByqJJMKadu@pVm+7Gtq%Z~8h zF|Q8~kVzuvsjU5n>DV~tbO~n$_pWgxMEF*0Hgn2~H9QQR!5GDrv3t`ce8&b_JP7e5 z82kPLC0Dg!QE&xmc}0ltuz1rV>Tz7fX?O)&WX9nRnBVpoZve&|o=NM(E7k;#8?TDj zM!r5TGN7w6Ru83Al;KBee0r--KZBn>nXcl%J^8Bma7gg;LQ&9CY*kyIzz;;w3MldJ z$PZjt8UB-#To1wAn4XLgGo)d91W)(xPk>ECzBJ4u#>ua=ehzP;5#)i3Bhc04h~A*5hzJ@;7LaD?}KzurPzqdbtJUR&=c2AnNuiHUk(bIe5j z#m)Q(YJ$FYGe3HopjU6^7f$2x+0^Lq`ry~OdW}kG-geij61Y#UjA2C{a&mRb%|#~G zW3eaNvBYC(oW-!ZuGjna()+GZ+UwLjq)@!u7r)Pq-LIhq9+eA==W*i*o-}~>_+;xF zd+>&pqfYIKW4KF8Xp1Sucx<|rwioI*v=nNMtz{pn1_n6S>)Wg9K8hR@jQm!SB9;uk z0o%|9PmBPn#WQu~0R?RmXQE>9G@hnts0IN|Z{>#-%)-M_nEQ)Et88r6;*~$s4(qV? zwcQxWcfE>s%0nc~V*DC7eL{2ub^>NUu;>+l#R0)BO7L%@=hTynNye%`jFClzS;X7_ zBZ?4~YEN?m(%@4rJL*X!wUs1T^|qHL`q4CCf|v4p7FJeCSR<8#p+6Lj)1g4+p(Rj1 zZqv&T(7_(X@*&kT)dGu)KlBpAu8fC-G( z(_e`(_JW+&zAdeNd+^e9Y`gre-!+KNwS59t8;kQ(d8-Hb4RgIW|w&2X7 znTSg?h-i-+Z7=YrSXyy>N#gJwT#gSfx{n* zRUj;8!N8~$-2pY4n?BvD|iM^fJ(72E1u-ud;JT|=| zWk{q96_g<~u0e|U7m{C=afj#kED#r`uV7+0PIG=o%JXwcH(E7*2~_ZuNT7Z|Rkc{aAEAc#N9+Fc74^8YRAS3H`ziuIQ@Lf#By+1ixVK00_jg&N!aQ z-@X$HO*oStbc_!TK%YNbkpXSc+|Y#4w<2DsxC}3gsB~s)xsC_3LIV~>v-@8* za_?A_0dD+?y>9;Xmbd=JfL_)6_)~|n#P+(C11@dHqT;|Ky4&IHRsL?bmCJz|=nm82 zE>d3=;~C}M7VUJjZ>6WLxr}xXlM~fIdxt?bPC~opZ`IVXrlB`T!H-j+-3+30~WxB)x7vgAv|3*2PrN_Okv)q52?<#IsGTip;VoX!b&Ml z=U|bl+OwJ|y<5tYBWuM&6nq0tbomg4pTIIf6@K-CnJceD_d%{F0JPj{%VKe|GQea7 z=g?TLZ{d3@YQW4$!30+%A|ot}G%42UT|@&{)8HjRDu5Z6BB8M!iecQqYWck1vcW_; z{UG)-VYmu@se=i5u}>Z(cN|T>3Vneel7P<+^2wosk(mGk646EUgJ4;?gZYSOIkn8s z?gQLPyyMust9lX(0)hqc+01985d3o3T2B*D#_2!ELI|i;4WbY*sKiEzOktH^bzl%J zzOL#fwky^=mO)hJX3pc`mj!mcXB~KQcLvi8@e51Bfv-S;mMJic)!*UB{dYn}%XD7< zFACPl8ohs%9b^$V^`U)H@dVR7${-m#2g2jlB5C-wb4X_&i*`|?D4>-!|GNo1M_?Vh zvsLsfLMIsejtMNi|4i`n1+RnmQiCPf7BM}S&XkttviutPl!2*|@S?Nhu|oG`YLvl` zOt0iM;k3ZwH%X$-6j&Rh1FVeEO52D+m!R9nO4<9U9_!8&#!Uo}Tx1gqX@57##2B%H zEcHVhuO%xh1WRTu>>(Jd6A8g8O+Lb!VwiMU14mK&=_a$$Mbi#^2ByH@N4HF&i~{U| zd4)fQA^Ffc;lF_#F>qKctnzcCuaI$#?7YyxYDxjuA*4a?5Hg4Q!a=PP4lO*Ib}5Rc z$*}#x%PbUBA-W*;$?{=KA{scyrUPLm8KWVZDA+a#X4FGwaxzwmBrwH2;>GOG=*N?k zkf}YG$`+9vAuWCtf;^V9@5muhcpkVi3U6ehMn-|f`v$NSKeXSSt26#bs9BcL^0MU( z!Y8dhg|dX>LWO>92{}}}NFi9E9W3-D3vFG;s+zil4oL~$YU8yK2yP-yq)?YwQ6CDS z6Cq(33D4S^QH)tT(Ej1UVmndBoOLYn1gh9_xZ6SYU8shG>~GtU@sIf9s=-%=4sK8% z7r~5z%{1c~A?{jf?D&rEG>**R#QKMkQ`j@X2Il}mV{hO`1u$Ut0UpV~f(jfl8tfLf zfinjXDiP^4gFQH2{mSpD3@oe zN(f@F+^^^-jXuyQC%U_zZf}1L%5-evgs%FqNaD)CaguGu<-)$qIN(#XZ$|Ye2<1X4 zzq%V*ATMJGH7MSC3qvCAE?ORbIMC{>)=$Ecb}MO|Z_G#eo$D9buY3R^;rkD3J#pG} ztcqhH1s~hJ#kDJZfPyA>RX+!LeL;NFBR-wmu6i3?%hv&iWBsc0BiCPxvH$hK{M$7B z9O|hie83$5{K{rXNPwdQ*izIF`Jzg23PA~;paA2qb1;Eq@)}3 zK+~|LhO&7EfuC9=yrbglA|uJH9Xn-{`5ioNTU+Uj>5LlF&BRX z857hqIOyQ>p4WmN558#lh{sCs-5|ap9H4C93cG-Td}RCxZGx4&7HnG_uKWtefA9?e zgoX{d{#prt_dDvB=Y@`898(i;h#s2e~FQ_=sn{FZHKtq*tIKacEZzW`?Zp2zxr z>bEA$uXwN;bA6ZnZFYw^=u8G0pK@^~-?p>e@q6Q4zR$u+E+$ymrjk`iK`EFoq}?43 zN-@J#;@PoY-8p^lNcy{Edhz{}`Tc_UdLb1vm$pDM#l>Q316NkDGj^Wm3+F)XIOBrA z=nJkUq}#to==3eZ@4*}0G+xXaJHA;^g8X83>QiRt_&Mxob>!F3tG>YY0Xi*D@v;lR zcJTot&Q+wks^6sB3{J!uJ$#~NMH=|X@{sUTqU**RXIUtO8pThrc&Z~+3ogXicMh9! z8cqZ7U_Li@|A%HMJX>h+TX<(zfW}p*cef9NKWRW@?vEb`HZ!q)db&dqVmXD z`L3)v8B3)@-`1+p06Q8eReICFd*Kx*Z&mQk>cEX(a6R6`q!>^M)YIzPlt zabQp+XMQB-H#koX9~^HSfhaAT6*D%8H}(P!PZY-$Fl?gkZVs_;pmQlfIJsHk1@%*c z0aPRzt!NB;5=4e1Ct=bp8>!5=uy#QrBP>>0EQWMu(TW0%mM2UWFM~z6TsSUr;l`(s z%@Sn1#pOLDByUrY=gH*{7MCJ&xdB|HEV<-@&l2&495<0Sg1~DCt)HJ4pQ7b^_p6v> zxh9^~oM$!f+4Ac<(rMnd1(>o!ANa0^vk4q=g~7E~4#C1{%Lr1`e+ZU>X-66yt~$?7 zVf+>XiPdkk4x5>-7^Z>^C@45El$$JZe8(o3=p^v4Y@7fqgi6MX4uWsQ(6r8I$jxN`RjOcQdLNetz0Qn%~T-X;* zIu6FpSdPc-s?HPUoI^QtDCgn8Krt(Ys5uaI=Wi$~-ssa<0CKZ4LsF4|43*#*ae|jj zyypYyN&>nlJfjlIxCna1M+3$95z*F7=xy5N$;VjF)FePQi;20|G z661l#S-Q~5aGa^fO!-dqyYaE%kG=(g#tkhd(vqX#vy~t$`3chjq2laRg($?xCmULF zf*>MQxp<+#sPI^F8D*3pm7HxE$;gFX4c8z^PH4gSk;Uax7^Ns{vsujfc+Xk}J*G4m}zKCXpk!aft$h+!Gy@vXYW_)0N;nC={a? z{-q8qg0Aip<=BXI1V`i9(th)&(}Vs!ri^mD>c9i>R^yqHy2dkQO`yEgR!YhrTJgXF zV&mC|LQBtFXvg!hGCnVS_B#QekL^7#8!W%PV_)N!IUhHEaL*27DtrsdkQu(dATuB% zGc-K&VE^h*o959QHbkq-zFi7|%4@}sU^kwN?L7=~HMT7<9zi2Dp6g%Jgz}ANpoxs& zunhf+wBYU0L>~lN*C(S$Y0KdnhwXe=Hu=(L+z*Z`!g?;1-uYcxhVI z7g1?dZ+@HB-jJamt%P2VTBHSnACu8b3Dd)w3MkN-%2H4d33g!&5DlyYs!#E35NK9K?Gl=jI8cIU}Br%xX2UwJN2uCUZswVk!a(F z`ih~GQR~>6GE}hf+&w$fs@lJGJ#v8+ui751=5230e@9*8`TjLoWM9=5>ss|tf9Ubt z<@IS*pSP-c?eVz;9?Dja&v|y02k`|<=#D5V49kG&zC74i9ri{uLmSSs z;LOmf^R?ia8Cr9mqT#I8S=?vP^nEYz`xI|mc}q)Qd$qYnShE@m!Xv96iqdOhuNIFc z3@W6J6^|?pKLhr6no5-Gku6x8_2r$%uP(&6R^^}zsUh*(oj9^JL~lBM5GU2^jb1ox zpV1V`gm*mST6Hs0W#IQ7>e3VTrBxlhDDCv24CetJ$X~(pPiUrra}hLW1glqYqbMV| zb_KV8(yE#tN~`+#p|s$t6=HMe$U_tG4MElC4>h*rRKF$qR7=jP^P=&C8w6r;>#*Gh6 z+zne(;!Z&0*T#Jt)i^z88}2<&NA&?3HeOa8sO1aPEGqzx_0;tmsl;bcGf}vfhlml< zUq9$YQ~I<)rd=RSwGg%O$e<0P9*t)Pnfd^`-Hl%t@1&4Tjp5>b6nPJ!y;>elB}34> z9a`RT8n_TQZ(!VR*yOmlkJxIf4zShSA9rmCMQ9AsAc;~V4JP^1r?L0CPzI9{p`)UvNvZNbE~$+djMx7gGU z%AOq*J)7QkJiKikf@0V5FW{zpdDzdxLd4(M@m2oQ86rJGfra$xaAJS(IUJKhBOZqf zKEQG^L)D^+lksGWOb)FThB`U4O7xA%NXPEDIz71gb$U3AJP)M@H@r?Sm{#@KLz9Cq z3YGix8_wW9hu>9wU3$h(A8L4JUXEGY`Um<)pPd*QJB;~>mp)^1P4%UEelM zAAx)9SurG>DX-RoqC#fvwVpB->{I_= zcW(n9RdMwJ-z9e;K*(-1*jPaq4H^W}4G9ngF$-BpG+;DXiKZ-JvytHD!|aBF4TvUC z)?^`1pU~PGY|zl!K4{YxTG|Gi$Zq%$Au4SVQ6r)xf*KVqAdvTe=3{rW*#%Kw-{0@O zzhuwcbI+VPGjrz5nU6ack10kf#qc$)KnqCT5XyVOlQ?4)_ z-ceU=@wI{faCwj_Q{C4ytp7y|U~Q`xih72%FAq%2e_>)q#+@f+MX!NkK%m8IqyVzO zn+mx6o5>|oM7tMlinRceiV5nSA{#g|!6o*PcuXo1kFyI-HCv`y#%iGzz5qI>|AF6( z56r-Y;~H8%d5-nNIb+Y?;f{SCTK6HzTH|~?5;~Mo)517sxTfu<1Cgd4D1YxnB=u|q z;Spn;f{C(>D(0D?cmF>5Q#Gsg(C8ZG6Q;X1Q-5b_!LSI*fR~WY$2@1m;|!O(5x_k| z3qJvYP_EdP$I+}utP{-j$BkRv&HX~t{ zhcd#ih}oD;_bXy-b@bEheQCh~kLlLDy|{Dh@d)!R7300<^~_K7zH{#z-cMp*^PY<_ zci?ArGnh~x`>qCeo3n9u!VKaals)o3ng937y&odHv4e1DVqf;Y6Z;;hcM!Gb-HNz> z!94va?sMX>f%pMdbjTFp@p{kc=iokOwUHhoXB~hhHY%Cnj-s7IsF!Wef_sL0L-Tpi zz&W0=j&|uB-A+%dc96?_9+ivnKZYr*aK|R;xZ!%Z)ZIa`9xh$o0|-M<2Lc#^G6Jq0 zYXR_)!F1P|N8h=P1_qH;-I}UBt-WnkXEeI%UD)u58ZEBFRx(JvO;6csOLBaIR-uHo@Rp9^vT?&)wETIhvEZqS^a$?uKl-Ij67a@U#t^54HJ;zU4huW-sTi zuA^t?V=C&r-uWMZXh$<4yt$i=yf(q%{QM(GezOq|Jl64Xn<+0O!iEkaefSZUInTSJ z?_ky1>K&iE5gF_C{wufJ`=i{=WfZS%^!$UAaMOFjao@n$?Obv7hZ?WTaX!*}#_?vP z$23&`A5Ysubnnm~@>tJY)vdYRRr_8u7(&YDC`F7Ju0DjCJ#$q%o^5@PTyqb6vX?a8 zO^!Drz3(`_jP(A_aT?sL`jZ~hSp8?7O+V2$yvIfg=VIn`c#!OI4QP%;dS7>(i==dr zqx{EkMB9 zv-)JsIje^0g0%Vce&H@d*3{>yUF&Mco}=98Sz}MHVOF5VO=CSV-l|zm!#pwSVy&O@ zZUipfZI8rweGQ&+Q-X1wR1%uLXK7Vyjj#rwtktqd=k@j4X4nE? z8ni~{P3oJpWv~RmY}NLRpg_#(9t`^c-8B3I+>mW&aHF2X&1D>JGZI9TZzec#!SK;$ z7!K3an`fyo9}9MS+V08g#`6swoc_5wKr`CE5vc{Y|JBB`us$eW=4|^+fF9Tr8KD14 zCV;4eO#tx&-))S)NS8Hs48WoJZjMK$iH^8Jh-jX*pLbBk$#xLed*(k!8E19_io|G6+b&vk$Sx%K-X8`%->FQv`kR)LJh2QVb3iPsTu zxIur48;Q1jG7VtX@;O3;p&6yYe;im6YqrO>k?<*Ljq#RM`P=k=m?F^K{K zVFF-h+gOD|!a3GsXyCqyo0<)z6;w>s?=8k--%L(KC%Pmk4NZ)}=CEn98a9Cja}9Y^JNBoxwG2UV#H|5ptC8t1$PwSa*I49(^_YV zJ@rcz^Go znYtHJvAGIwXHNT1=Flk_uIZV(sN+`fU>P=1^CuauGkEE3Kt|Q^h|Hmx*wZ+~bX z481Fky~_StXQsy^~s;+h$ZmN!+!y%s5S1}Xi{p904-ZM*E zalip)tW?j=GgoCA6b3RdLd9JfyK~X2kqj}IKTY6IBl(??-|6{XD!+^4cWLa-#JQRT z*KGc58K<1j?p&*68kq|@VyzFcm?P>W!oy5WKP|ydu$Rpf36oXIhtYJ zGY4-tPkp_75@z4B#$xkt?9cGuffG>YxYU?AuJjlz1gFQ~;D+>=xXfMYF$P4&Y;9Wt zosN14XBkvofOGvQcxTlN|M^0L(z`$1wMY0~ zYJN?xCzv8|kIB+Kvvq$N5i$Gm5m3q~muc0PYDHYe;Mm<6gXiszq#r%~05xy70hRoQ z2@ZcR9d2+ab8zfS=~MTYuicqU)zv);0uo#ZSQlC!x6i1V_6yU{DX!@zzdF*n9PEMX zOk1~FbzEnHE;3ad@!D}yfF=r}SGu8wpiy0ORjA%|j7TMQMHBOL(pDY64pgzO+llHL zMind7-WJ=OxsBh@GdL04%o0P>t63GAAbnv?{&Bw%S+H&Xz`#`@pd~75oRTpm0r{{nmr$X z;r+z%hU#tm7#+;=m5Z}IrYRq{(lZQSKgP&)`O1t0k7>-uufpnTR4qn3b@8vLD_gj2I!*=M7}VM zejBOXvOuQ{7$reE!_!;wEO1N)QY1kJ!&5_Nfi4+HC1F_+B8B;}^l*Lw{XVf(kUXIh z57Y9MX)HtY<0zalk5MkBa9xw6+)e>to;W2jks|KGNJc+`o-Urx!gdNbKPxF)MBMGC zB_>M9KHos}WqB-C8U1eGB57Jh;MsE$qZhH#^hB8*Prn(d^t&*Ne$y5*ypw*{l4+zs zV}l5+Y8HVyj|i+iBxz1c8bu^g7b^m56GWhK8UmS*wx$8h!G~ra8;x!d77*&sZ7Hly ze_L7yTWWSi>CLVzy-Gik^b=*;m9E!Q8^QrNvBH+N!j`W53GC?H`+as4CUVt^AUk@U zFr#W)_ceiLR2$NaUO6~+?cjN9Rs2WdKMMc)J{I%|)8N<|vY_jj1>Ms<7Gfb^-Ae$a zArRZPXg}Jsi?JW=n&t2++!GrR#(p&0e1Mu;+wa4ZO?Z+EE3yhD3ZwA~cF*h9J&my0 z)y78crnc_uP-+poO|P6WeEPQ>9E=r*o-d_>&Zyt(LVOjGxitFX^clW<4IINne{~q&GACr%qw@Ic}$v{|^_D ze+lGo05e(%@1YGsT><-}tb4L*eoN`5BP(;PZ_J4}ik{AXL+`A|;}g=?#v>~%qjMrY zpdN7SEaWBKpP7HscA*~1481Ga6*e;?`e(*_1~&EVBLnb1Loe$i?0RtaYDL)|iCkjZ zbL5)I3=Urhh&w$*_+n0nJy1J3;rzhR%oa;OrwCdpO+OLGWA-PI=g-M;vx) z^mCC2VeMD}ptWNfw=*)m_SeLZraV~m(hZD_C%4C&K7W@tEBAo+$i2rrrfGSv(?rxp zN(@s;_n+|Q z4I}cNj#=GG%xhTTU?sH!ciTH*5^FY43Ai>K0s@h%wN%!iuhw?pT|i)JwW~O$R@=%k z_1ZFy!DI->G-wxcOoO(OW16(t9Mhz&116)YE4!kRgcIyn6L(KrIjxGH#k?e?ewJ3n z&z#n+YlA|Ys@ftmt*>~`VO5-FHNXvTpums$`<1Bep7u6Syn|)&HY|&u({G^Xd|4dS z_3jSji3Q3q=0u>{t$$x&dgP-z`N)Vzd{ujQc^lqjc4v}{?LB=j7G7T|pFPLACv)s8 zx4T;y4=iuHi7A%1c`9dP)JLI6>Kgn+{gkiP;>AY2_td?N2U2&Fbfj!lVFc?Qy?>pn$G5=!h0fgL z{vj5)aoo#qK$Y%lP2MxM9iyoK9x_F=VoRrP%@fR0=!e%QqkwB#*0ELW<58f{AUg_wcsrz-0VT??sYGT0zWXm134Puf-8-I}QtsPmejnp=Us=HR7 z#tr6;JE1gawp{?8QFpyjn?%{6_fS2X?s}s>iPpZ^!U~pf_R^9LCemqLr|rzj*XZX! zh7~Vz_hR9+jh6K0SYN}zn*dlI>@~n(wlE#_E-&F3_l#Oz(!kXgp(Zy|V1!y&&ODp& zbR)wd)byMTiMS?{y$cSp{ghW@|I+)q{j|rVZ*O1gRoV}%^~}6A?iG#4l$CcF)1(c< zs6>%!lT3aKD|bqMD^H%1;>lA|EO~TYBtf-Lf)*|TA_)oFuD1Wn>$1P(&9(3LK%5Tm z;`Z0qdQ8UlqmV$%(QX;WG*hMoDOz~ql%y|lG%sqrl%6l|Ej(pP&zCaSBv0F5`vLDe z_M_hAb}V#FvA^yuYd?mR6WUK8<&m_~P#Lpz7-<<*TvHOM7q3E6N^kCkvtG>`UaG-e zgl*xUEYT-dP#%@VlNU?#JzIu-ZOJW+y#xNEh}#qS+8NtaGVi3L5z0SQTg-Q@u_H*6-R5G zHc<8MCP}M#MIpqSAFDD^AXDsz>9&^D8*yNGu9^=)JB;ne*LvCv?JqL9|ARL4DvA6$ z+X;XGRz=RNJdDM3k{o83H=)zCwC;I#WLzgLA2khQh7GB(lFhW@Y^$>dCOB6T2-@xS zWeei8aETGB=aqqwkSy1}3#1J`G*^6Yw|zI1>zr5LzGtm>d;6}no_8n4?WWXghcOdV z)n>p^Zo0=_{}M){h8q&zIo5DPQo{{N4KpOkd)(Qu{;!f5eT+tpw4TXL4cwzN*zvx` zDAS#?Cd0LjEK-KMo*D2A*9HYWa+d2YVVp9?_Mnd&eqAECxm%dA$E+ixao4gw0V^KN zrhx-B1L8ytF~eQGnyf*cS=ee?PseT~W`JoY(ySWZy3<|i<7WD=sb+?pb}Eta+ykQ2Em!x<)sC= zsYuW@p<^BsMfqDzmRhdP6Z#6E(_JsJ)%h1;)Q9zsLl-3pcOfmB9C8&FDcMuRpDW4+X=f9*E+oV0_N-uVhU?rXOlNmfp zuo8>=qtHs3-GbJ0GmbzDiw{P^TtcEV-Xi-;WVDZg-840LD{2yLuF z`t79Ag43CjElh>8tp6s-VQoJoHyAsgkb2&lRLbhxBm(ajk#apt8QW>Nph@;msc+c7 zmV{!gAQW#5-bd|cz4^soQkrLk3?Y(6ny`Us?H#bL6XOn3Q>bROLcPmsJya9^C118* zhIw^zc%;ggPn=_I#Rn7aa7V4drV$pa#`!2M+t=_Ca!q@Tj&hm0v-~&~?a^ib@n*cL z^(sQcc2TI++jZ}&nN{cEx11aTGyZPTs2BB_?g}_(%SRnHnA~>`_Pm=v>O~{Dq(*X! zu(Xs7h}E4QbmUkEhF=R84UMW5K(sx)RU{e{Un-JruHUhBlh=_x+Uq6~!g0~VYbrhjeznPe0Jfp83O^upDwWGcD4cbF>m4Wp^)6Rv4A888ZM z8O=RK{Wj((k6SSEzA-dQGK2OQz&p-n{u4F`@FmuJ>VVux^Av!a>o}6F0z(D(#)Hb3 z&CP@dG!ooP+YF{*n?WVtsX*Hd(!A%e)I!1^y7!p(uzru{-G@dU)Ki@vfsxN2bn*-u|6FSA-gookTApg%bLpoY|#Ihk( z9hM%;u|1(u&*}zCkLB2&fa2jviR}roxoj%~M%X)yl(~Jm8>mRYgLWuHVTZ!?%i~%$ zQ#s?AnN(mKrQ`Lm9SYcy;K8~i*9p$y9Cj$2)3aS70Xq~bF_b|~cKZtg(X(-w~%3P`wVvlvdXZ4*+v%vsz zEPzv_(=i+QU_H>Lx##J7vDX~5Y}oFScCA4U*c-IMt~JR4dy^cnZ;=D`Epou#A_wd( ze89d81OIGFdl?4)+^&fM`^GvU5^={F{aTOd`kNQ1q{U@;;u!@yHNFFuj_g#!_#V6t z$86X5I$_zij5o5OV5Pogd>L6b#Hb#xC(DLV?f7gsJl=<)>?j;>!vc)vV>WhBn&+^A ziNoiZ4A`P%r29&Yqd9c<@aJwL4(|j0xokjB+szBG?vRyt3LLiSfx#E1rh7lozv0Dh zg)+n-({&VPEO*ogFk^R(dX>zWyBX6$1nU5)%Wfq@wmKVkCl>BEe ztquc1?a83AVj(od)Fb(HSJ!A^)o4RSr`S+2n>JJkeK27c6s%eY6^`Gkv1;*IHI@*p z8bMgKY^p?9HL5(aYT3L%SOGD^2IOWV5urXA5w~bNnu*YZ%~<@|jxq+hQ7gkUZq$$p znbr+Pq9&sT1U6XQ?k3e>My;9R38U77Fj<>gUeEL9Kc^>7Wadc0=muhJAokvZ`Oi`J zO?ZN0Lk0FyL}C5HaRKJ$VeF%Tajf6Llm}ZaRPO-&>tOI4NfW%GLKr-@&5F$42Oioy zp)$L^gNz>z;-ftlD($g=O}(D)u|PWa(T0jed_zSu;~cd0ii^Fv4$zEq_G{UO3N!~M zKeR=U2f{#k&tXFa=_RtnH&pnhC2Ka2R$yPWzIyW(Joe2~$_*6?N)HAuk^wfEj13hu z4;`?fVo&!kPeKYT^*;7F6{db-iGdu)?ngf*jB3lXxU%! zg2{AqO`(d(%TI3 z_nK>J*|?C#hkQ@=JK}AXt!$nT<2ktTIH*+nZ?xgrZuM#!CE|WqJMMAXYxOCT<uvN__ zSk-F8D?_@+=A)a(3w^qEZ)<4+a;}Y!<~asTek% z#`2E!)k0lttABk)H)ezfW#Lf<--^3Jxu$MKP?Fm9bnhd7%$DU$>SQU2i)c)T_&QDJ>-Kv1tjEOfDr{9h=4~ zhXP3tQ{vUJtEN*Sfo|1oCJr#!5a-bs=>bkL0!2d+vps=U$Q7zrNUfB8!>&qE#2i)S% zGJ5ww{NXD`l0^Dp1k+tj@g2|}9Hg^lKUJ8n%YB)CJoNJ>{T!s959#Mvp>F<# zLbGoEZu&V)KPPAE#|~+ zXSqkj^DI%pWZ`%*DvCJ~hvr0d&@si8Cn5QB7?!RmWq)1@k*^? zy5-}Ff$6%0lPC0PtIp4Lo-(cKo$LGvT)RJ=t<$G`K)>-Pz&!VT1m~xmq~P11nsvDy z6#5*Y`G@J}6yZJxP0ZF4lyk87H{CUyq&vLaoP~0z!K){iYS<*RXmiXxiP{iM}CW%kB;ax9;v_uw{1-Aatf_FA*THWiL@6uyrqyAkeZ`&>X?dzwo~w z|M=b)7R;vZD}M$zhw;A~|F0wcLf!D4sQyC;;xH>mYK9eWmvfEDD0-RXg=F#cncRpr z)WiJhPD+@Cj#3EYB*ZH}h8Y3pK++*IY>kIHF?slbDG&Q3kDb_rJ(4*nHf)XDj((4f zX!qL)z`AsA|B`ovVt)ah7xTmIFeOUH-|?f6Q;Wl=QRQ0A)rwN6D``z`MeD(9%!OIH zlD#;*{WFv9{a3(qk4cx%TByt0TWG==>0LMHLe`luVkgnEF6=Fwsrz2~Nt`|J9gz9x z`Bh+BP6k$cB2H1*`^jBr?q^4N$5h8Fu#8xLVDEn6eh7zY2Hm#hNVZ=O%Yvyr%2RJl>B}C!YKT z8hL!3`+nr_<5mziB8V1`!kr_YmqUtJN8Oie#8CnXxx8BU3fJKMxpw83eBqF7_8@|Y(;7WTL3YG+(6H< z?#JjpL&uV`1rHFYPkEM6R;M(J7~28qvqJbdlJ2p4VVLl(Qr)^qs6JE8BWl%oJw&LF zUyB0L)mCDz<1^jO$8`yNT_1d=Td)t?&TuBCb+4{{56+>fW`(Td`%TbyZ>7F_YhCrV z=*Vlg@;*FoEA`!58wJt;BS)0fcW-SLNZyC%ZA~L&t3akv7f{uXNzPBopTRDlsolEA zXr~rU?9)dR_hwX`!Isf~;8hVR;(jLL`{(F`WY#ZWQ|p-wkTuI)TTgOjxzp?QFx?}b zpr2pjC+b(3RXf$Jsc)5cAtgr=cpU(nSF+sIEH?Z*789oj)$3jApIqu+p~f+>&GZEX zh<1{7e+M8K-e6DeZTkotY)lcS_*YY2xqy!?Siiu!?NU36wKkrW4KJ_H;6KDtHNtXH zk;m?174xEzsxQh|e=V|=yVq46)rf0aGuO|1RB~ zewzlf!SEc8>ejpnXAIN9nMJ!B!G%PK>TzC+7Ybw3DE)&CNR!kzJqp#1WJx|GLd9lc zts0wD@f{l7Iyx_!Y$-L4O!p5l7{K{5&~qF*wjHWsMoSrn)eIdJ-}K)%%n?U2tuN8Y z1BbXZQ;|%$oJo6I6Y9rLOj`kn=P2Q?)ATJ3g3(j8V6xQb}VvoaGQr zN^g&fHMPJwq4ouTq#hYZz23IAWJe>kJ23`#M&6n}-fj9tf;{PB? z1^6NUk5P|`|C2M|yFA?lg_wnQ`t(*FXn5Mg16!Uxh(IPrVEE9H?y+*1h^Y;%UUZLr zz#3pHJ97>>$Qav!&RtWXrM{yWdpp$1&rPm_x4XCa%9)qJT(=z+;VTGqwCA85Xs49l z47YtX%k&%yP|i21l+TSS&lPe*5^p4lsj<$PdZheye80$H;T%~bf`>!OOPD5E_ruWM z@hQ;=3CyA zPL^raIp$=+)nZN-)KQ;Og>>`f9#*YNrAQ|(&r|goRyb%dJkwR+ryrx?`UO zgX+gf9tu240aj-1ujU-YxHm>f~0Oy-dAH)vr*T-H*Tx zbG_I-08fGJE@smZ=_oSM?Q;JM<_=Sd3B#YK>TsQdzg0TyX9$~hIWPKMutRv}h0}Ei z|D7;shfTWqfcL+G@FC%ly$F9ym-ntNcVE|-JFx=}{@51yU@G}!FG)x2AF$rqa`0yx z_qrC&Lw=d(rNAP0ZSvi!xMe%`h<*m>yC(Xc(LsgWG1JjGIWj-AzjfcO2BmB2T$G)A zVk^Sf-@1A{K+Uc1{{R5H2fKIRDT{XxPSeT3p>a4FNt;SU_>u|Ens<*JiyKTcWK^Aq z?Cr>?!AmHodn-Pn$oKErSyx9jhTCvD(Gu)oPG~ZHM{(xmsd1-z@ zQHjG@k1ak1t0xtUp|57=!EM>a4SbLLo>o2k4!e>o@m)^3pomLmhMrKLp$-#qss>;7yzzDg!})&sKH55a54 zN6}Au1>Y<9HsqgeFI|*x&nzi&hLhW}#A?rXICyo4puZ%0ZsSGTbK75jdR~uxsNx=j z8k@7Cyu`9J-(F#JkfJ0ympMUPPFi9sdBC~YFwHR0Xr%aro00FZISfS(!`yqavJCl7 zXhnf-nc)@#o|i7QmFL^-vu9?9CZPCtRpi^l#a{|VD=oj}7Rww{5r!}`)@<2U?A6` zi*ofBmA{U->;d=RN(uq`z!L~WdytnFoqju+f2p=!+A}-E%{-D6NsNw-jK}B&H^TyY zuUJORals{J6=o?eEwD&0D8b<@xaF2b`Hmv1rKk|St}VZKnssr0`8Wf6LP3kOJio~4 zVCd=74L6Q6$k^m#E-EdxkMT2?j}l~n`JtJ2T4rTtnGH7w_32zP{_8A#&{pC|bU?8a zSOb_~7;8wmIl)&h7m4fV!_Gv&Z8+%ne|enX`^Yqo4+RY-MY-5N`O+8rPXq6Z{qr@8 z0T6)Z0Urta$1Pjakk4tPjoDNM^UVsT#Y5673gyr5;|G@urax$)%+l+hH#|^eIRusy zn@C9rH^Z+&k9--%ervN(uqfj87fboDGIKX5c z3a1m$4%h=&O@&q5+uH!x0k{t^tpxOVB`Okd7=?031Iz+! zt?BJeK{<2+<^d|Tkb~~mAs?8%=mD$-Y_10#MsfNLNFQ+FuK{C`4&WBRv__-@d^X@X zocyXh4Ssl!i}ngT0S$n)fJVS3z%syNfU5w{0X71T!@F_Kfa!o8fKI^dXOKU@I_%MN zA|3j!4$YnGUqF2VwgReG0pALKfSqmN2iW87?Ty7NREBoQ4cG~o2iUv|<%8#CZzEs0 zU-drtVb#fa9Qg%QFntw;MZ6Bcd4MB;qD%8|_T7qRnSS7t*WYYVu8A5HNgqJz^E`_Y z40=*S1d;+GE12q0DrffgqIi5)147gA?<73*Nqq)F(cF;|t*;%x199#M9x$v^c_3lE zmfoFLqK#Dpc_4MoAeGcCx^sp~I}V~#+Xcl=4igRt9{UB;mpRn$<1mtwbMYY~T0t{sSs>hcIMPiDum}P@z64-V}i7#a_&)q6UTdhV`T+1^BNN@tYA=9sc<1r2edr;FW8rQaMMXT1gxYLO0?BXT8u3k%F;G zT{mDo^$c9jV@M|pa(3Wey@AqUI;dYWKqy3nx(<(`^+NSz)kLfrpfLRht0RaXsQ-k| z1O8wLyc76+A@H@pdqUuwfNu%H(?J&vz;6Y<2T)y)6h--7Zu?@Dk*%gu9=~Su$_{K@ z>fvvV)6Y>g--=9BA19Gfr>%cIQNL&pfgb^UK@ff%_{5U^0G{c~STuH@n$%Oqed>W5 zWgh<1L4OYPWeBU+5j`t$BeN6h2C`NU!$(E|icDZl1Zx^Q8DnlJ4v>`iwjn)^j%0e* z08A|UchWocHFPq#D4z#`j}mx>#1HAqN#IrB>!2^+P*<|R;ajN}bu9$@b~sghTb!uO zs2oS2J1Btv6Wp#-fX@rUQ$3FZejf0R2&;F(Ns#q?3lO!uX5Cs=r>ONCf!xO`^<_r4 zpWGYL9;)YPBaa(Nax{T&Lr{8TAIa~k2fh_y^#r7p>7@g4F}>o(U1}Gl*G@i0zr=x} z<8VmlP9mK&^mXcbN{1};<@e)E>sM*iFQI>5x5`&(`dFG~669;ztRPmikjrm}6=Y)i zlZP(#)Y88C6OU(3;7~@x4erLobx*gevK; ztr@7^1t~-inIJk~!^NF4W0iKzK<<-Ke(jJywo=%$6XdLOd7FTb0^Yzd{D;c11$gy` zz>_R~S!pR+I)BVJJqEgy*h0UGvLopF`w(g&^)>xm2A&+VvRHtp0&-3W47Wd_xeP%3~k!)hk3f3B9Tsz&un@ACU^todR8D ze>&f07m`nVR;kar*1G#R+_vzMq0=ZwRVqvNusM zK=mQ;@xa#x;i(^*27EQ}X$XhugQ&^(>w}1#(yJ8l0esguglL|n5_}B^tKTD~V``>% z4^SzZ7~oTHCi(}^+l74UXXwOm5uX;|3nZW8z+Z$<0q9SHejeyoA*}8sdS=Fq%y9Yr zw`=iOI&NrW{k$gLs*JTNd_59I(9%817l?Uq4N2ZK%&V!TedOZpX`P%GSugEMU_Z-* zf*VEeOZ)Ap>~V!XjT8NkUX~V@3O*0IT=#%=5n$bp)M}&E1d@@}KYD;z%zvR6eAfts z;(_0X_dtz=6*fg3jW9e4r+9t@&ztG-Sbu(eePiG_oi#L{oorTllM8DnWk=4FZDw|| z7IxBuv>G6n6Z3Xu5MDh1eUP%z_$DfX>>l-L`hf$MD(dwVidL7d>Rh4MsY};(u28>E zs3>)5&)X~X!_=jx-(I0!jnUaYW-VW4zx&zm0j3D;>=!d*yr@|MjCWriL5aj85zGLY z2`EgHa5tOX;fJ+@Y9u=1SzdmGql@aJ0r;)JQ%@o<%6C2RwRqpRmFBIE!X_bhgYAKw0v$*q|0 zObf^#<+~m~M{p2^-0M&Dq=z&Qd+_-nJ-i7Ipodh=Co$-s&nC!s^53$)m^6LnkVQWK2I<4*ll12#_&EO)q(8!r;jz;D zq)9V1Z8fZiOV#ckq&%T&j}B5ctJ=+x%HP%HYa^BITEZOEYCj*Oyu-pDX^HaZ1NR9X z?tQXZqxqetK{N5w!O9n!XEe2gmF5UDZay3g^Z)4(t!K2dVW{?l(aMgY+BXxGT|@t* z!Od@mZPz?|lk#OWJ!#f$*F2t}td60ZzsGFXoJ>&GUr9HfE4OR*k5PU(oNitm{u@p6 z&C2TUT^NYF-x;)z->B>`Xn%jB@|r=r_eSMS7Cz4K|2wLelKC*6(mxxog+M^P-RPPD?~bocP$9VYFjl*+U*S*Wj#gtN1u53hN8H7pZqG}r!<=X)qE0} zd|gZ{A-=|&$@{J=!U$b zQ$A+l&H5i;W9#>|Z+t(Z_xnR!*F^mOnwws^MtSQR2-tPa7zF=!1U=k^-w_e#M-a(R zM^gA7Benk?8F6+bVXCjC@c&UJkqw@0lto}ZbQWe4Q`$vOp#wEE%cS|RT}+p+~1_lP*MT!3w-t~jb^>(I$+jnw110L>IT#f z_;85wzN-D_70P*4`>!jM$F&sxz4nymO`Y=gAg%j~h~GwP+hQVW2WxwD5w8x`0*^ZR z%@xY#A#n)5J46c>zZ(jse;#@}g1?CxcRE@*95n&q#%S%)Xyql+!;ShOztu;)qR*|0 zQ9g>H@VP6tX+RUM%mT|dFdVIk9IIWRJRF#>pK3HKGJ*KLM!Qdq_}KvM-&Ezm0PVlD z5x^!A-qZSG;Qehu_qPY#&kMR=7<6A6biX3#z9#7Y$)Nkq;+~vuy2`LJPZx&2 z>`MKNL)ad6v7>_!LIJZY1FerPbja)~69J4g*!890kC86BX!VXRax3XdxPg}!^+a?v z3PQLQ>>_u8F2P3WNaptvpTHbx>r1zzYIKr*Tf#3YaM1bOGlI zxIn-X0apsRPQa%Gd|tp81l%v+TLOM0-~|DrO$xiN6);i2=>pCbaDjj&0r1zzYIK&k*Sgm?+?M0p|+1K)@0KR|>dJz^4R!UceUw+%Mo;0)8am z1p%YUQ^$3!fQbT57jUkC3j{0?aHW9j1bj-s=LLL0!2JTgCE!N_UJx)kU8FByqJYx{ zoGai00ZRm2Dd0K*pAztS0bdYszkqKE_>q7Y1dKL|^aV^5aJqnV1zaFtiGV8wTqodD z0zNO`3j*#J@GSv967Yh6(X&MQ0wxMLUBI~lE)cLpz?A~76YwbkpBL~20rv~|mVh4# zctODE*&=-b69t?u;9LQTY5*r?zo|EkVsL6j$%7@OKQ5X2jo<9)|8C3F8DJbIsyM7(oY@pUF3gK^3)0V50U=% z?L33h(%=5wq>uKO z8nXSRj{8pXkM@@uvi)uUZqlEG^e2TX|J3o{LH?5`Cr_pSQ1$=+ar&u=-+lh67u2w> zP@~MAIrA1n!tA;Cj4`AnrX)@_OfV)*FeWD@8xrouOA;A)qmkjqr;Jg?7uX8(E9_2t z(V|=MzpP|&sl#aq#4anb5N=XRK_B#G5j&O^+bsn}jsxalT`*l31|31hF`DmMe?~Z#_BiW@Mim z3!atR?D-Tygv#trC6QipR1%#wyo;Jxh#NdBEx;?AN}_GCrLa7|*k)N=fVlDwOs!Un zZJE_p=CnXayG==?mq{HEfrBMhkP{0^58Rk+`Nc(6L@h-s_(^0*^JEs`ozO&UX)(QG z!@a0)_InMY55m9n#rTe8?4{<4$>#b4Q&0nM5T;?X7XLE7oG0)>5g|gvljC*CCk1#K z`pfuo9znuGIv$beiAKhkX-Hp%|Y? zci`4eD+A~b zmwL4yfnXuyN%(P4e1jNA8*UQmhiQL;o$@&X#7idAD*T}4L>|A314*tJd?6k<3lK!Y z9?19;f*uClDzuI+)8-uc@6jJ{%7~x{LANaJpeDu`EKcQ=8Pvhy8j1f({L6Bac8%tX zL#5xG!{cji0ztqPoPNNge!&PxC;QRBhY_$gvVZK0k5FX4*B7rUvOnvK*DA7~>WjxB z%MSuEJRE_ZUiK@2Pa{w&vcKqyAMEQ7`r?Nu(!Te_4^^by?u(C7q&@D7AErn<+ZPX` zEA42&g9t^ZNV^z-M*Zm(Y47^tV-#u6`r@xpq@C)EzfzI*r!PKMk#?moez+p-MPK|? zX#b-EQ7jyR)ePCb10P0UwL-SrzWA#Z*&h4iY1d8Pi}Z2;JgMOFr}m{PpY-;n=6gXj zXnn!uLu+FirGNRPGJOB?p=nP_ca`Y3WjgmWdcXX#-H^YcQLa{Y3p*p*<1)cV$&eg4 z3@3jz;}fG~2d!WH55wyer|1VIw_h`SfBDJ1Ao&&1?@RhN1VWYDdB(@Dx2Hq|vQrw3 zUk}p-ektLR-^D)|#W1oTImGbbBN+Ti(7z@4vBF7xR;n{&UG+;3a(wjHw3t+!#ckEbwxkQ_|ll z@CGseC;2}l@N!;K(z_-9Ao@Q@{sJ%QUy}UA{F>zdq2w>{l727>mdPJPKUUzk2hqf7>KZyR0JQANP z@UcPojRJ27!gmY&IDvm!$g>y*kob25(eD!YBLYvGFzKSbbwuA2M1L#rWXI$_1_KvY znN9St8+KuT1X{U=;fE;(asY9y0-S^P(rAeu6H^r%~X4#L-Ft@rRt}gq%eJ z|7VtNobs%wcPYSWxhtCYauzi1Rvp!D${@uRnGSl zJ$7NN!Y^G0_KR2k1s~PG@nTv;`HjHG2H~Zgavw{uoQ*+p9u6bV`$C>Z4Nq5&dnA9k zKPH%eQxN}ij1T$+QSTyKN?a7>_mkdWzbKL6`}@%u z;5UcCw=#VH@m+fu`pz);FT>ysC^VMepnADS;9F?|6IUzyRg@3ur7UJXNk5_l@Ny49Rc z=J&=}j&CjE_zn(~TLj(^RL*wbLzT}T1pO*OZxDPAgrR>U4F2;l`0vB<#(9=Y|HVM2EB+o(ML&-A^ z{YfbN%rN+S7#{M7bfr9-fG0V#MgPU#&x1^#2>MPp7tkQ&91I6LRJtR9zh2M;f+>uC zD9$Y6Sefq6!tnW{px6I`)6@Hmbe$3S#uxd08h00zM3_!A?S7XDc*<8tQ28%s^l{1- z;U}mfrc2NpMfs-*{NI2NmEV^cpR1L%LH$UV;A0T|ph57_VoD_xpV49PX5d5RD-U?4 zw}QVc&-IKC^tqKM*eufZ2>ND`FN46p$>_yR0Js_sWGFe4!{F^<@NK}8oQl)jF;%L3Vdr&J-UFW{-|yfr<3`8O3>?_9N)-+a)i-~n*cBZ6Su^t zwUr|~gQjQBGIp^;B<7J16{uZK2*JU zfY-ynZ4UB#I|QFPk*?H}t}uL}t_#ioCg4e)x}fsU3q!w6(6fa*$lbxDSClZg%Qz)F7Y4z@0^cn3T-NW6Fv3LNTFvPtel_r+hnzwE%egRou8j{Z&$KZ3M}enwJ4$)F zqWF}Z0?%HG#Um-t1xeq;=~r=}Ts=B;`!WC@syuH2p3+r5^8i9$1PBmf>z< zlEU}w;5gIb(5){AaO!s%A|>w2`nR4i*+&f zuj7jo)(0(#lZ~m0?=iAzwb)D9S?(29CnHImXiV}`P)TqSijHSS|1;ksY%uf1o}3gu z_T;2X#hz%K;^*Hl?Mq2M`67}}zNF+6lO~5xJ86>tS;%}(oG{T(5iI$H6#ui3u_sLq zpZ285mr8rmr0}ISY0{-iZBj~j$tR^;Qt}Dm>wD6KOV;<4@cEuNqvY79_BWIE&`;MGsi?m;t5t+qf9DI?d_`dd#xx}2~nCE9ZH^(`N zA77oB<4mE0$1}5&k^;UjlbuiU<)m25=1Ju?Iwsm&jJr^*3&OLuT$($jG6|_nwAyX? z<>sZn6aqv{mB(8Xu@S`SNuddIE+fHjgNMIpCi#mdK=8|vCn=@x_gBnwr&ui5<7=@l zTb4B0Vkx2X$?rDrFm$sq;

wBpMTwCQOD1 zQ>>*WOXrnlmN;`9zO1FP6V=g9zG{M?^EE*SDYnCG_HpBt_(S$#9t)(mL1tzy(kJxQ zd{lJ^DnFLKJ`h-v_XTLDWErk8NvXoc&yfU|uey#Lm^-Gq{t`?w`p@16YsVs45&27( zSqdvktn_^!`Z$p@zXadnVc#X9)BF>&EE9_C#zK2(zLQ)Vn=>&vbt39%!US@S>2qC$ z6>z@G%1aknz^fp$z&y|5ukUP_6koxIiQ~vD3>SxL$6i!o3nL0Tko0@8_q{L?t$Eop zOBr_KmzLm5LeAxurSKnTXWco&lx4Yd)~p<)FwZn2%S>Z{0!OK3aehewHq?s&fpE^# zbLX1oWX?qP`s;|VLP$%(7eJ`Ygywgt2A(tpHVfaVu*@s7pq~OPNP~sqIPSi~*Iu)&*-MIwSem7Fhq)k#0q>LPMUQ-^b+M%c?>1OcD$>$^ zXudlq^Uk?nGvmp~c!5pi*=Ej0-&oAE4Wkz#7jttQGtth1WV>%}(v+;y{DOH!#kNe} z7pBUo!J*nwu=tKfkt{sR1o#=G*K?UEpgQi)E@>ug6TaRx6Q7bunn;FR{HLoSJ@h$@=lHWZaQK7(aYx1Zo5WDZf-!PCDe9aiB5(?Mp3p+a4%#z=vR;U&FU< zkc~TX9242VvA;r<SVJFd&{x6mie!T8mNp(|RvxfqQEi6>3&S2ZEbGZ7}U zu3dV90p>f^B0hKms=%%pw*~g>{%s`30WSexxLXRBHmJ}o_#_<~kEJlb$SxkqR>$6k zvcMV3x8U1-WVq7OV9!i5GA&7o$w-TeF@-tGA(Hf0bqeWfNK??SzJ2EWVrKSh)rDV? zCox6tmvleny{HI&cZ0bq{UWpO2+k`yh@eu%XL4+I6gM2LVq3Ap=2W1+fhcPk&0Ddz z>dH!gT!`_M|AsmeZdc&}JA$i{^Kqa;lTl-3#Gf(ymYhTgLb?DOv#iJ&l&er(^QCNy z=(76_*;pRQqYtzMe$D9D4>_nC%5mBq7~ z@i+5+Iw9Rf=3Dq`VFDA7eAAhsI-~$2$26b1wxF5{QCcFYq~P3Hzh34-_Q(Co)ZdaW zR#y|@w~|Gt!BIc?fGz&!y_x^3qg1w&#b;qBOvI<=(7hGIyf5V+ft^{7Fa{{*?8%lT z?2~rci&^bo{)7Xo#o!{5)ezRp%W;-FLXD>QSS3K)(B&{~V^bYw6w}?9_khm?&7+Br z{u<%vuPBA(He26@_Kl}>{eA<_zw`uT#xHkBZk59t*0rVLvtcklDHAM?in6lOa!k>a zTPF>Z4R~ic`a)q!(8I6~jQ+ot$7~FM@)s3h=uyNw{+y!8@G)udV$Qb84$o%+zLgOz z%5_3=1@pxMTzD%Sb&I3u?kRKN)x)q^X2Anuz92dCOB8$!t*E4LIRv(ZDR<-RdKh+H zvNbF%Qs$WEV`XKo*^*_RJ9}P+PtPwtL4vV3&3hzU6o+}U>OarIr1Xn(8BRSPsj?ni zOtM|H`Z38{>ag{%uMp$Jf`Ab|A14Y0Op+S$)oQkXKLSUv7~h%f+oZ+%8s;l37y*bc zJ!2J(KCEqnY4pz)gqa}-GB~cU;sF32?{xG6!!eU&+>`&?iI5$Y08`1kF&OItNL~RwIEraWhiV5K5|QQZkQs+Xvwe9Vm>LPXHIh!cNYa4uTZ1*{u89E ztOBP2gV{jEzfws~7T;g(uPxvp%|VzBLaZwxr3uWs!@}d+y|VR7TY}p`2%>iM<@Oy%0+(L3Lg7i(;`MOHe09&-!#?{|}kU BX;J_H delta 32353 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 KbhT`e9QS{C2kt%q diff --git a/PairHMM_JNI/org_broadinstitute_sting_utils_pairhmm_JNILoglessPairHMM.cc b/PairHMM_JNI/org_broadinstitute_sting_utils_pairhmm_JNILoglessPairHMM.cc index 59d00928e..432a528bb 100644 --- a/PairHMM_JNI/org_broadinstitute_sting_utils_pairhmm_JNILoglessPairHMM.cc +++ b/PairHMM_JNI/org_broadinstitute_sting_utils_pairhmm_JNILoglessPairHMM.cc @@ -1,44 +1,25 @@ +#include "headers.h" #include -#include -#include #include "org_broadinstitute_sting_utils_pairhmm_JNILoglessPairHMM.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include -#include -#include -using namespace std; #define ENABLE_ASSERTIONS 1 -//#define DEBUG 1 +#define DO_PROFILING 1 +#define DEBUG 1 //#define DEBUG0_1 1 //#define DEBUG3 1 - #include "template.h" +#include "utils.h" + + +#include "define-float.h" +#include "avx_function_prototypes.h" #include "define-double.h" -#include "shift_template.c" -#include "pairhmm-template-kernel.cc" +#include "avx_function_prototypes.h" - - -#define MM 0 -#define GapM 1 -#define MX 2 -#define XX 3 -#define MY 4 -#define YY 5 +using namespace std; class LoadTimeInitializer { @@ -46,6 +27,54 @@ class LoadTimeInitializer LoadTimeInitializer() //will be called when library is loaded { ConvertChar::init(); + m_sumNumReads = 0; + m_sumSquareNumReads = 0; + m_sumNumHaplotypes = 0; + m_sumSquareNumHaplotypes = 0; + m_sumNumTestcases = 0; + m_sumSquareNumTestcases = 0; + m_num_invocations = 0; + + if(is_avx_supported()) + { + cout << "Using AVX accelerated implementation of PairHMM\n"; + g_compute_full_prob_float = compute_full_prob_avxs; + g_compute_full_prob_double = compute_full_prob_avxd; + } + else + { + cout << "Using un-vectorized C++ implementation of PairHMM\n"; + g_compute_full_prob_float = compute_full_prob; + g_compute_full_prob_double = compute_full_prob; + } + cout.flush(); + //if(is_sse42_supported()) + //{ + //g_compute_full_prob_float = compute_full_prob_avxs; + //g_compute_full_prob_double = compute_full_prob_avxd; + //} + } + void print_profiling() + { + double mean_val; + cout <<"Invocations : "<(&(tc_array[tc_idx])); - double result = log10(result_avxd) - log10(ldexp(1.0, 1020)); + float result_avxf = g_compute_full_prob_float(&(tc_array[tc_idx]), 0); + double result = 0; + if (result_avxf < MIN_ACCEPTED) { + double result_avxd = g_compute_full_prob_double(&(tc_array[tc_idx]), 0); + result = log10(result_avxd) - log10(ldexp(1.0, 1020.0)); + } + else + result = (double)(log10f(result_avxf) - log10f(ldexpf(1.f, 120.f))); + likelihoodDoubleArray[tc_idx] = result; } #ifdef DEBUG @@ -353,5 +389,14 @@ JNIEXPORT void JNICALL Java_org_broadinstitute_sting_utils_pairhmm_JNILoglessPai RELEASE_BYTE_ARRAY_ELEMENTS(haplotypeBasesArrayVector[j].first, haplotypeBasesArrayVector[j].second, JNI_RELEASE_MODE); haplotypeBasesArrayVector.clear(); tc_array.clear(); +#ifdef DO_PROFILING + g_load_time_initializer.m_sumNumReads += numReads; + g_load_time_initializer.m_sumSquareNumReads += numReads*numReads; + g_load_time_initializer.m_sumNumHaplotypes += numHaplotypes; + g_load_time_initializer.m_sumSquareNumHaplotypes += numHaplotypes*numHaplotypes; + g_load_time_initializer.m_sumNumTestcases += numTestCases; + g_load_time_initializer.m_sumSquareNumTestcases += numTestCases*numTestCases; + ++(g_load_time_initializer.m_num_invocations); +#endif } diff --git a/PairHMM_JNI/pairhmm-1-base.cc b/PairHMM_JNI/pairhmm-1-base.cc index 90f95aeec..a3b5e0ad5 100644 --- a/PairHMM_JNI/pairhmm-1-base.cc +++ b/PairHMM_JNI/pairhmm-1-base.cc @@ -1,29 +1,15 @@ //#define DEBUG 1 //#define DEBUG0_1 1 //#define DEBUG3 1 -#define MM 0 -#define GapM 1 -#define MX 2 -#define XX 3 -#define MY 4 -#define YY 5 - -#include -#include -#include -#include -#include -#include +#include "headers.h" #include "template.h" +#include "utils.h" -//#include "define-float.h" -//#include "shift_template.c" -//#include "pairhmm-template-kernel.cc" +#include "define-float.h" +#include "avx_function_prototypes.h" #include "define-double.h" -#include "shift_template.c" -#include "pairhmm-template-kernel.cc" - +#include "avx_function_prototypes.h" using namespace std; class LoadTimeInitializer @@ -36,85 +22,6 @@ class LoadTimeInitializer }; LoadTimeInitializer g_load_time_initializer; - -template -NUMBER compute_full_prob(testcase *tc, NUMBER *before_last_log = NULL) -{ - int r, c; - int ROWS = tc->rslen + 1; - int COLS = tc->haplen + 1; - - Context ctx; - - NUMBER M[MROWS][MCOLS]; - NUMBER X[MROWS][MCOLS]; - NUMBER Y[MROWS][MCOLS]; - NUMBER p[MROWS][6]; - - p[0][MM] = ctx._(0.0); - p[0][GapM] = ctx._(0.0); - p[0][MX] = ctx._(0.0); - p[0][XX] = ctx._(0.0); - p[0][MY] = ctx._(0.0); - p[0][YY] = ctx._(0.0); - for (r = 1; r < ROWS; r++) - { - int _i = tc->i[r-1] & 127; - int _d = tc->d[r-1] & 127; - int _c = tc->c[r-1] & 127; - p[r][MM] = ctx._(1.0) - ctx.ph2pr[(_i + _d) & 127]; - p[r][GapM] = ctx._(1.0) - ctx.ph2pr[_c]; - p[r][MX] = ctx.ph2pr[_i]; - p[r][XX] = ctx.ph2pr[_c]; - p[r][MY] = ctx.ph2pr[_d]; - p[r][YY] = ctx.ph2pr[_c]; - //p[r][MY] = (r == ROWS - 1) ? ctx._(1.0) : ctx.ph2pr[_d]; - //p[r][YY] = (r == ROWS - 1) ? ctx._(1.0) : ctx.ph2pr[_c]; - } - - for (c = 0; c < COLS; c++) - { - M[0][c] = ctx._(0.0); - X[0][c] = ctx._(0.0); - Y[0][c] = ctx.INITIAL_CONSTANT / (tc->haplen); - } - - for (r = 1; r < ROWS; r++) - { - M[r][0] = ctx._(0.0); - X[r][0] = X[r-1][0] * p[r][XX]; - Y[r][0] = ctx._(0.0); - } - - NUMBER result = ctx._(0.0); - - for (r = 1; r < ROWS; r++) - for (c = 1; c < COLS; c++) - { - char _rs = tc->rs[r-1]; - char _hap = tc->hap[c-1]; - int _q = tc->q[r-1] & 127; - NUMBER distm = ctx.ph2pr[_q]; - if (_rs == _hap || _rs == 'N' || _hap == 'N') - distm = ctx._(1.0) - distm; - else - distm = distm/3; - M[r][c] = distm * (M[r-1][c-1] * p[r][MM] + X[r-1][c-1] * p[r][GapM] + Y[r-1][c-1] * p[r][GapM]); - X[r][c] = M[r-1][c] * p[r][MX] + X[r-1][c] * p[r][XX]; - Y[r][c] = M[r][c-1] * p[r][MY] + Y[r][c-1] * p[r][YY]; - } - - for (c = 0; c < COLS; c++) - { - result += M[ROWS-1][c] + X[ROWS-1][c]; - } - - if (before_last_log != NULL) - *before_last_log = result; - - return ctx.LOG10(result) - ctx.LOG10_INITIAL_CONSTANT; -} - #define BATCH_SIZE 10000 #define RUN_HYBRID @@ -129,45 +36,55 @@ int main(int argc, char** argv) if(argc >= 3 && string(argv[2]) == "1") use_old_read_testcase = true; - testcase tc; - if(use_old_read_testcase) + if(true) { - FILE* fptr = fopen(argv[1],"r"); - while(!feof(fptr)) - { - if(read_testcase(&tc, fptr) >= 0) - { - double result_avxd = GEN_INTRINSIC(compute_full_prob_avx, d)(&tc); - double result = log10(result_avxd) - log10(ldexp(1.0, 1020)); - - cout << std::scientific << compute_full_prob(&tc) << " "<; + g_compute_full_prob_float = GEN_INTRINSIC(compute_full_prob_avx, s); + } + else + { + g_compute_full_prob_double = compute_full_prob; + g_compute_full_prob_float = compute_full_prob; + } + + std::ifstream ifptr; + FILE* fptr = 0; + if(use_old_read_testcase) + { + fptr = fopen(argv[1],"r"); + assert(fptr); } else { - std::ifstream ifptr; - std::vector tokens; ifptr.open(argv[1]); assert(ifptr.is_open()); - while(1) - { - tokens.clear(); - if(read_mod_testcase(ifptr, &tc, false) < 0) - break; - //double result = 0; - double result_avxd = GEN_INTRINSIC(compute_full_prob_avx, d)(&tc); - double result = log10(result_avxd) - log10(ldexp(1.0, 1020)); - - cout << std::scientific << compute_full_prob(&tc) << " "<(&tc); + baseline_result = log10(baseline_result) - log10(ldexp(1.0, 1020.0)); + cout << std::scientific << baseline_result << " "< +#include "headers.h" #include #include #include @@ -7,11 +8,11 @@ #include "define-float.h" #include "shift_template.c" -#include "pairhmm-template-kernel.cc" +#include "avx_function_prototypes.h" #include "define-double.h" #include "shift_template.c" -#include "pairhmm-template-kernel.cc" +#include "avx_function_prototypes.h" #define BATCH_SIZE 10000 //#define RUN_HYBRID diff --git a/PairHMM_JNI/run.sh b/PairHMM_JNI/run.sh index 8b8d44b54..495a3761b 100755 --- a/PairHMM_JNI/run.sh +++ b/PairHMM_JNI/run.sh @@ -3,8 +3,8 @@ rm -f *.txt export GSA_ROOT_DIR=/home/karthikg/broad/gsa-unstable #-Djava.library.path is needed if you are using JNI_LOGLESS_CACHING, else not needed java -Djava.library.path=${GSA_ROOT_DIR}/PairHMM_JNI -jar ${GSA_ROOT_DIR}/dist/GenomeAnalysisTK.jar -T HaplotypeCaller \ --R /data/broad/samples/joint_variant_calling/broad_reference/Homo_sapiens_assembly19.fasta \ --I /data/simulated/sim1M_pairs_final.bam \ +-R /opt/Genomics/ohsu/dnapipeline/humanrefgenome/human_g1k_v37.fasta \ +-I /data/broad/samples/joint_variant_calling/NA12878_low_coverage_alignment/NA12878.chrom11.ILLUMINA.bwa.CEU.low_coverage.20121211.bam \ --dbsnp /data/broad/samples/joint_variant_calling/dbSNP/00-All.vcf \ -stand_call_conf 50.0 \ -stand_emit_conf 10.0 \ @@ -14,3 +14,8 @@ java -Djava.library.path=${GSA_ROOT_DIR}/PairHMM_JNI -jar ${GSA_ROOT_DIR}/dist/ #--pair_hmm_implementation JNI_LOGLESS_CACHING \ #-I /data/simulated/sim1M_pairs_final.bam \ #-I /data/broad/samples/joint_variant_calling/NA12878_low_coverage_alignment/NA12878.chrom11.ILLUMINA.bwa.CEU.low_coverage.20121211.bam \ +#-R /data/broad/samples/joint_variant_calling/broad_reference/Homo_sapiens_assembly19.fasta \ +#-R /data/broad/samples/joint_variant_calling/broad_reference/ucsc.hg19.fasta \ +#-R /opt/Genomics/ohsu/dnapipeline/humanrefgenome/human_g1k_v37.fasta \ +#--dbsnp /data/broad/samples/joint_variant_calling/dbSNP/00-All.vcf \ +#--dbsnp /data/broad/samples/joint_variant_calling/dbSNP/dbsnp_138.hg19.vcf \ diff --git a/PairHMM_JNI/template.h b/PairHMM_JNI/template.h index e70784073..52a4e4650 100644 --- a/PairHMM_JNI/template.h +++ b/PairHMM_JNI/template.h @@ -1,24 +1,14 @@ #ifndef TEMPLATES_H_ #define TEMPLATES_H_ -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include +#include "headers.h" +#define MM 0 +#define GapM 1 +#define MX 2 +#define XX 3 +#define MY 4 +#define YY 5 #define MROWS 500 #define MCOLS 1000 @@ -130,6 +120,7 @@ struct Context }; + typedef struct { int rslen, haplen; @@ -182,7 +173,8 @@ public: return conversionTable[input] ; } -} ; +}; + #endif diff --git a/PairHMM_JNI/convert_char.cc b/PairHMM_JNI/utils.cc similarity index 84% rename from PairHMM_JNI/convert_char.cc rename to PairHMM_JNI/utils.cc index 01c5a5137..5b91fc7e9 100644 --- a/PairHMM_JNI/convert_char.cc +++ b/PairHMM_JNI/utils.cc @@ -1,7 +1,36 @@ +#include "headers.h" #include "template.h" + uint8_t ConvertChar::conversionTable[255]; +float (*g_compute_full_prob_float)(testcase *tc, float* before_last_log) = 0; +double (*g_compute_full_prob_double)(testcase *tc, double* before_last_log) = 0; + using namespace std; +bool is_avx_supported() +{ + int ecx = 0, edx = 0, ebx = 0; + __asm__("cpuid" + : "=b" (ebx), + "=c" (ecx), + "=d" (edx) + : "a" (1) + ); + return ((ecx >> 28)&1) == 1; +} + +bool is_sse42_supported() +{ + int ecx = 0, edx = 0, ebx = 0; + __asm__("cpuid" + : "=b" (ebx), + "=c" (ecx), + "=d" (edx) + : "a" (1) + ); + return ((ecx >> 20)&1) == 1; +} + int normalize(char c) { return ((int) (c - 33)); @@ -184,3 +213,13 @@ int read_mod_testcase(ifstream& fptr, testcase* tc, bool reformat) return tokens.size(); } + +void debug_dump(string filename, string s, bool to_append, bool add_newline) +{ + ofstream fptr; + fptr.open(filename.c_str(), to_append ? ofstream::app : ofstream::out); + fptr << s; + if(add_newline) + fptr << "\n"; + fptr.close(); +} diff --git a/PairHMM_JNI/utils.h b/PairHMM_JNI/utils.h new file mode 100644 index 000000000..8c244333e --- /dev/null +++ b/PairHMM_JNI/utils.h @@ -0,0 +1,13 @@ +#ifndef PAIRHMM_UTIL_H +#define PAIRHMM_UTIL_H + +#define MIN_ACCEPTED 1e-28f +bool is_avx_supported(); +bool is_sse42_supported(); +extern float (*g_compute_full_prob_float)(testcase *tc, float *before_last_log); +extern double (*g_compute_full_prob_double)(testcase *tc, double* before_last_log); +void debug_dump(std::string filename, std::string s, bool to_append, bool add_newline); +template +NUMBER compute_full_prob(testcase *tc, NUMBER *before_last_log=0); + +#endif diff --git a/protected/java/src/org/broadinstitute/sting/utils/pairhmm/JNILoglessPairHMM.java b/protected/java/src/org/broadinstitute/sting/utils/pairhmm/JNILoglessPairHMM.java index 58b8fc591..a80800f82 100644 --- a/protected/java/src/org/broadinstitute/sting/utils/pairhmm/JNILoglessPairHMM.java +++ b/protected/java/src/org/broadinstitute/sting/utils/pairhmm/JNILoglessPairHMM.java @@ -66,13 +66,13 @@ import java.util.Map; */ public class JNILoglessPairHMM extends LoglessPairHMM { - private static final boolean debug = false; //simulates ifdef + private static final boolean debug = true; //simulates ifdef private static final boolean debug0_1 = false; //simulates ifdef private static final boolean debug1 = false; //simulates ifdef private static final boolean debug2 = false; private static final boolean debug3 = false; private int numComputeLikelihoodCalls = 0; - + //Used to copy references to byteArrays to JNI from reads protected class JNIReadDataHolderClass { @@ -138,6 +138,7 @@ public class JNILoglessPairHMM extends LoglessPairHMM { jniInitialize(readMaxLength, haplotypeMaxLength); } + //Real compute kernel private native void jniComputeLikelihoods(int numReads, int numHaplotypes, JNIReadDataHolderClass[] readDataArray, JNIHaplotypeDataHolderClass[] haplotypeDataArray, @@ -160,6 +161,7 @@ public class JNILoglessPairHMM extends LoglessPairHMM { } int readListSize = reads.size(); int alleleHaplotypeMapSize = alleleHaplotypeMap.size(); + int numTestcases = readListSize*alleleHaplotypeMapSize; if(debug0_1) System.out.println("Java numReads "+readListSize+" numHaplotypes "+alleleHaplotypeMapSize); JNIReadDataHolderClass[] readDataArray = new JNIReadDataHolderClass[readListSize]; @@ -275,6 +277,7 @@ public class JNILoglessPairHMM extends LoglessPairHMM { return likelihoodMap; } + /** * {@inheritDoc} */