Brobdingnag/0000755000176200001440000000000014323753132012471 5ustar liggesusersBrobdingnag/NAMESPACE0000644000176200001440000000052414317451261013712 0ustar liggesusersexportPattern("^[^\\.]") export("sum") import("methods") importFrom("graphics", "plot.default") export("sum") export("prod") export("range") export("min") export("max") S3method("print","brob") S3method("print","glub") S3method("print","brobmat") importClassesFrom(Matrix,index) export("sum") export("prod") export("max") export("min") Brobdingnag/README.md0000644000176200001440000001223114176316640013754 0ustar liggesusersVery large numbers in R: the Brobdingnag package ================ # Overview The Brobdingnag package provides R-centric functionality for working with very large numbers. It represents a number ![x](https://latex.codecogs.com/png.latex?x "x") as its logarithm ![\\log\\left\|x\\right\|](https://latex.codecogs.com/png.latex?%5Clog%5Cleft%7Cx%5Cright%7C "\log\left|x\right|") together with a logical that indicates whether ![x](https://latex.codecogs.com/png.latex?x "x") is positive. The vignette functions as a “hello world” for S4 methods. The package has functionality to represent Brobdingnagian matrices, and complex numbers. # Installation You can install the released version of Brobdingnag from [CRAN](https://CRAN.R-project.org) with: ``` r # install.packages("Brobdingnag") # uncomment this to use the package library("Brobdingnag") #> #> Attaching package: 'Brobdingnag' #> The following objects are masked from 'package:base': #> #> diag, max, min, prod, range, sum, t ``` The package is maintained on [github](https://github.com/RobinHankin/Brobdingnag). # The `Brobdingnag` package in use Consider a googol, conventionally defined as ![10^{100}](https://latex.codecogs.com/png.latex?10%5E%7B100%7D "10^{100}"). In standard arithmetic we may evaluate this as follows: ``` r 10^100 #> [1] 1e+100 ``` But a googolplex, ![10^{10^{100}}](https://latex.codecogs.com/png.latex?10%5E%7B10%5E%7B100%7D%7D "10^{10^{100}}"), is beyond floating-point representation: ``` r 10^(10^100) #> [1] Inf ``` We may represent a googol straightforwardly using Brobdingnagian arithmetic, specifically by working with `brob` objects. ``` r as.brob(10) #> [1] +exp(2.3026) googol <- as.brob(10)^100 googol #> [1] +exp(230.26) 10^googol #> [1] +exp(2.3026e+100) ``` In the above, we coerce `10` to Brobdingnagian form (that is, an object of class `brob`) using `as.brob()`. Most arithmetic methods work transparently with Brobdingnagian numbers: ``` r googol #> [1] +exp(230.26) googol + googol #> [1] +exp(230.95) googol/10 #> [1] +exp(227.96) 1/googol #> [1] +exp(-230.26) sqrt(googol) #> [1] +exp(115.13) exp(googol) #> [1] +exp(1e+100) ``` Note that precision may be adversely affected for very large numbers: ``` r gplex <- 10^googol gplex #> [1] +exp(2.3026e+100) gplex - gplex/10 #> [1] -exp(-Inf) ``` The last line looks odd \[the return value is package idiom for zero\] but symbolically we have ![10^{10^{100}}/10=10^{10^{100}-1}\\simeq 10^{10^{100}}](https://latex.codecogs.com/png.latex?10%5E%7B10%5E%7B100%7D%7D%2F10%3D10%5E%7B10%5E%7B100%7D-1%7D%5Csimeq%2010%5E%7B10%5E%7B100%7D%7D "10^{10^{100}}/10=10^{10^{100}-1}\simeq 10^{10^{100}}"). The package is vectorised and allows Brobdingnagian arithmetic: ``` r googol/(1:20) #> [1] +exp(230.26) +exp(229.57) +exp(229.16) +exp(228.87) +exp(228.65) #> [6] +exp(228.47) +exp(228.31) +exp(228.18) +exp(228.06) +exp(227.96) #> [11] +exp(227.86) +exp(227.77) +exp(227.69) +exp(227.62) +exp(227.55) #> [16] +exp(227.49) +exp(227.43) +exp(227.37) +exp(227.31) +exp(227.26) ``` Signed quantities operate as expected: ``` r as.brob(5) - 1:10 #> [1] +exp(1.3863) +exp(1.0986) +exp(0.69315) +exp(-2.2204e-16) #> [5] -exp(-Inf) -exp(4.4409e-16) -exp(0.69315) -exp(1.0986) #> [9] -exp(1.3863) -exp(1.6094) ``` It is a semi-nonobvious fact that, in addition to large numbers (that is, ![x\\colon\\left\|x\\right\|\\gg 1](https://latex.codecogs.com/png.latex?x%5Ccolon%5Cleft%7Cx%5Cright%7C%5Cgg%201 "x\colon\left|x\right|\gg 1") and small numbers (![x\\colon\\left\|x\\right\|\\ll 1](https://latex.codecogs.com/png.latex?x%5Ccolon%5Cleft%7Cx%5Cright%7C%5Cll%201 "x\colon\left|x\right|\ll 1")), the package can deal with numbers very close to 1 (that is, ![x\\colon\\left\|x-1\\right\|\\ll 1](https://latex.codecogs.com/png.latex?x%5Ccolon%5Cleft%7Cx-1%5Cright%7C%5Cll%201 "x\colon\left|x-1\right|\ll 1")). Suppose we wish to deal with ![e^{10^{-100}}\\simeq 1+10^{-100}](https://latex.codecogs.com/png.latex?e%5E%7B10%5E%7B-100%7D%7D%5Csimeq%201%2B10%5E%7B-100%7D "e^{10^{-100}}\simeq 1+10^{-100}"). In the package: ``` r a <- brob(1e-100) a #> [1] +exp(1e-100) a^googol #> [1] +exp(1) ``` The last line being numerical verification of the fact that ![\\left(1+10^{-100}\\right)^{10^{100}}\\simeq e=2.718+](https://latex.codecogs.com/png.latex?%5Cleft%281%2B10%5E%7B-100%7D%5Cright%29%5E%7B10%5E%7B100%7D%7D%5Csimeq%20e%3D2.718%2B "\left(1+10^{-100}\right)^{10^{100}}\simeq e=2.718+"). The package also includes some functionality for Brobdingnagian matrices: ``` r brobmat(1:9,3,3) #> [,1] [,2] [,3] #> [1,] +exp(1) +exp(4) +exp(7) #> [2,] +exp(2) +exp(5) +exp(8) #> [3,] +exp(3) +exp(6) +exp(9) brobmat(1:9,3,3) %*% 10^brobmat(9:1,3,3) #> [,1] [,2] [,3] #> [1,] +exp(18659) +exp(929.93) +exp(47.249) #> [2,] +exp(18660) +exp(930.93) +exp(48.249) #> [3,] +exp(18661) +exp(931.93) +exp(49.249) ``` Brobdingnag/man/0000755000176200001440000000000014316743725013255 5ustar liggesusersBrobdingnag/man/brob.Rd0000644000176200001440000000476613762776702014512 0ustar liggesusers\name{brob} \alias{brob} \alias{as.brob} \alias{is.brob} \title{Brobdingnagian numbers} \description{ Create, coerce to or test for a Brobdingnagian object } \usage{ brob(x = double(), positive) as.brob(x) is.brob(x) } \arguments{ \item{x}{Quantity to be tested, coerced in to Brobdingnagian form} \item{positive}{In function \code{brob()}, logical indicating whether the number is positive (actually, positive or zero)} } \details{ Function \code{as.brob()} is the user's workhorse: use this to coerce numeric vectors to \code{brob}s. Function \code{is.brob()} tests for its arguments being of class \code{brob}. Function \code{brob()} takes argument \code{x} and returns a \code{brob} formally equal to \eqn{e^x}{exp(x)}; set argument \code{positive} to \code{FALSE} to return \eqn{-e^x}{-exp(x)}. Thus calling function \code{exp(x)} simply returns \code{brob(x)}. This function is not really intended for the end user: it is confusing and includes no argument checking. In general numerical work, use function \code{as.brob()} instead, although be aware that if you really really want \eqn{e^{10^7}}{e^1e7}, you should use \code{brob(1e7)}; this would be an \strong{exact} representation. } \note{ Real numbers are represented by two objects: a real, holding the logarithm of their absolute values; and a logical, indicating the sign. Multiplication and exponentiation are easy: the challenge is addition. This is achieved using the (trivial) identity \eqn{\log(e^x+e^y)=x+\log(1+e^{y-x})}{log(e^x+e^y)=x+log(1+e^(y-x))} where, WLOG, \eqn{yk^{g?{]绞+@DDDO"J+H;J}/QX"Po,-/ ĎD"d^C"`t@Sl1 }]=T̫~b@D"0(}-ۼ-DH$zHQŀ(Ė}-J}i"H$UGDaQ2pco*EH"w!v%E@"JkPj "ŀ(4STaЙ "b@R* e *DI$C*v\#>9O(W*B] D!8T̯_d7^l/C>eb(<ʀ`da-ކU_`n@#V6_m*^TꐽH/ 42 (+o@Q^l|w|!" %~ŪқRy.ΚcT)$!PW~tZ}{bxy JRHDPTa`TNEۀ}MY,(`D"\Kc3kJI洹c9bWߛdqD<DRJpx̯_ҴL bmO\MnW.%00 ʀ`LT̫!T~\YNaamHɢ( |2 (N =ѳa[׳dE/D>Q0sWw )ISb+>YY,c*[ &K1xeize(ًWvލ/@KY,#*zY3.T_:LuX5 -"00 򀪠0oNNp- J/ayB4wV&/")r;iܺPQ4IQ:H፶tK2 P)_峔Ϋ[np_I,ʈ``@$Ae@P^X57K@tu#V6}oyXY,҈00 rIUP(‰c/Ŝ($ͰdF"TL<gߍ#Vֵ=gn@P4Y9&AU1_GT|DYQ75Ԑ4YUAAI̞x'!GM[xj7 ei#Ȅv784bchh{S<"s (n)KUfFw(IE1DYTcJ޷J#kp;V5;y>Q8mµ8e"'IkYE4Y (To[Iz佁d^j;9"KU@P^8k퐣fOXtYlR10Q58BIԶ+X|R10HQL< aTd%>;lCbEd/䊏*I7mk[DP_G^@Im}oJ%Hc`@n;_uފ҂j%iR8ao&%hb`@*(8l|̯_3G7?k (4Tœ[1mJңlƪBR:=& H{r28}uliyeΫ€iMEPINz{1UM,vIc HKZ &8 ꗡfiJңLŖw`('^ C&u 4beXXn6Tye9r>++и;{_Wb eϚcT$="+흟v5zvIE2FU@0$,_3GT^n/XԀtz,)H w҂j̚xf D4d{Omk\Iz,) W*D!>0c9-®Jc1M~b`@PJpx,U%(I+ ֶ5߄vXT_TcJb^ݏ0%w O,k 3*ј]sC*kXtWrjϬ] rEbyB/oRFv0~ Ɩ$=" %{λB˭N8P.>sjov]Xt-ַ=@(fqN*00 )j1S_&\" /q!_Pu\QmU`DY o=Mנ{E>5rDvȧ`~2Ԏ8]IzDQ1Ƌ-wr{g MEP0sjovD:be ޙ|, Jq+pQ?RAakX޸bqOv00n\7*PQ* ʧbL00 C*e/ GD7/S *҂*̚nL}m7XP6@vCq~\иޔNU10 %A 0~K+I51" Sr? GDw&UĐ8Np-N%E rED*Y卋YX=Q$UüPV0NA W}`tZ&⅁AL &K2QHyb $cu "NE@PQT3kcFՅ rDD~l3M)ޙUF10(nLDٶw ܽZ:-V 䃂>sBE$%y""]p{g2 BTL(; ꗡ|;né~XD P`vM8$ WD{7beӷbu BN6(OıbNbnLc[:x%Z{)pc`R*Z T0xQ%SCXm;QTKpDG䈈oh7~3^m !XńP7r;d"m<tZjƒAyB_%̩ՊrEDqQ44^I*G 4l;亥.=VA(l|#;b7R.> sjoŴ+5wݏRiC^D\g b[*X 酁&dvskĈrEDd&<]-r)*6!,[qe'*3JJ*)x $,Ü[1  ""L󷹽s10l@PWS_&\RE""R,߶;{^NUHvw0%y""B Io{+riy&/E] rDD䏁d^j;1BmOXt=wQ~g܂ E"" hضzKê; SR* GDDzIWXt=zvI*L= U%0~ &W|TQymHbUdv':rEDm}oJtX@8_uC&"Bz{EۿI*Vkr$6r>/刈(Sxx;J՛;  F9q;d""]X|3w1S_'^퐉ljyytXv? sED흯BVXYb``B`S~jF(GDDu`{;0JU_n Ho\X9q;d""t 4beXT:10Ƞb;.o@Q^\+и;{_J#L<gM1*W!""mWgh\Z00ƗKQW~S{vc SӉy Ɓl@PZPYc/C"(WDD$cw;xj7^RĴj@&(8P_0WDD wv/Vl+ nT(GDDdjk[oBptbTMI` )yu?”s刈;ԆUۿ's K1 dkp+(R+""ێWи]+҉x@2~ sEDDA(7.D{RD^` }!(GDDd/^y7^hUj{U"CvDD19؄g#RH` C>mµ(+Q+"" /q!_J'UjV]؂UWC&"0ܱ@[[ШI`b;uKQ]zs`{?: c2Amq9"""rwhVm%;pڄk2igGZ,o\m]ϺN#@vw`\Q,z6N#@&(4Ø_JOP#""" &{fHvN@& (Ǚ51B9""" < C.évDDۻ_ƅh^: AAFuwh<-$ַ=MBx ( dZ &P[>KayuNNGu,0  k0&P} zo@DDԞwzUҁL@(‰c/Ŝ() ""PـEh}u*@&(Ry./èɮ ""djʦ;u:2@& *9N(v7֟ rQ` 7Fb;d"""?ĦNi`;0p% q|՗0VTJ(6?Eۿuv@`rG1~ JNd^ٹ/lvvS1Hf0.Ԛ;yߔew-E`=p~6"N o>up9PŠs@Da1C7}'_?Hg 1w:˟ tZtL<ڟ ց DDD}`k%䃈H vo#Q>0/4ݟ| V)4s?Kq0DY%PT&}i]+;{g.Uu $ ~;-M@*t.Ecꀪz`xPX,ŷnvn7q:zke#gy*L׃Щ9&l\a<_y4GtLࣗ떋uʥMXc K;@zuWZ!*}* \th2z tf~B<^ɯzp]15n<|.Qm'skkEDE**λQ\?njdA𑯉`)J$S׋'?(ZλrJ]t />14؏5ʧ<_68WZa'_Zfo:-"U7#>;dZ$+PqE//^Ү26{NSat-)ʧY?C4dU*-0/+.K]]F|) +C yB,g%vhnRprhRHbࢻft_|NuAAZtKܜeW~aP+B&̿gJurH+,W9@˦{+l]./FYwyBbyh9bpL.;Gn&yfAZ'C7䲻Iu'#E ֟<bo.'J+rh1kx/ W.;]&|ߖ_QپKe؀kh8Fi3S6ui5rh;i?4ɲgG6%uoJ+q,6x\1hpC`ygx@q0~u7* ذ=dW{B$O&*+#5SE68cpsΛV`W;A l8?T"7g؆ EwIwljtu?Ӷk<1;#u@gh-'V;ߜwgZ x"F*Ɗ~3>'sLOJ ۺNa:QZG7Y YྴB7ﳟ $X%.U8 ϡ~ǛNX2n& IDATgv7k6&mYrvt /_x^~ꦋ*"wr|^ufٟ5[+|~f}F<c1 MfJi;S)reSgA |{"7z7W3U4Ouw=cK/SJ&qc a{d1vz_ .p׿hxKb݀@v#_3 wwv&eOi%⻽y;bxPL2L`R1=&qkQoK]kRyX/S^>fgX +h"F܋AYydDB,ٗ7ut>(~zv7[jc7 7<󂽴2mYܯ&r}\g;'{\zS \pOџ)9,Vob>`r7d~^vz -/O _G\/ւ%O".j$W|Ҫz>okIly] 褃s*6m:2A_j+7^fs!(w?1000xx7O=V(2|*͞j-Ҩ@*l?dsUo9Uͯnu~w3C*ݧmFviϻB?]lDu^)**Njk6W٘舙毿w[BLə=/Ks>(uc7Vzj:ض7tyv+0: Hni`I(,r*)TztZhw/w>00LڳuEģj>/|v5݌6bĪC9IZ5StKOTfͦb~W3KwX uo,5zq>#FHt]#O;>#{/ij@h_hﻣvw\c? | ,9_*qG.;,:(Ѐ͎voj4-;m nyYZxW=>hPr\L;C HvӋJşq?VvF9WiffMXcNT5rm 77ʳ)v9]Ԍ ,7O4I>5xYg}V[^s]G_RJWj܋ԬiLrR) gY^btdgySA^,v›(qb+OpUub{r^ZL{iZf;sm⵨w10goFOTy@ȤkWHTR,Mo%alq*#*ݖۉdxgsX_ 6:R5v\qMK$2RAwQ:AlɤXJw΅3d {1(@r6ɪph: Ge%*[Txbtg\w`YH1;刓FCVfaoSt;Xh΅ 00s恁n W$r^#ĸwzR**65ڴVm:1MkXϻ3 2XmС[sb\OQX-`dP̎ 4GbwؒX$.>)ଯIk:ںjUkxޝa`a‘65m@c5YmwjU3Y89 4ژVcѤ[ =TO>qա>'ZD^]/OSVl{lYV`/V{ͼhxޝc`a毷n'voф5C@+'6͋Ům~yyjoMs%hKD1:r {K$}]<[[\w8p1s?ykV~q@qs4[Yļc3l>o~|MI3獂qSw^8r,^**VUOğ]l=| ;/Ǽ_׭)S7 Yr^}^Z=+3"V}C'fnJN싳"1ojM@F+5l9|1+SgTқi@n͹кcQȴg,/r͞f׭Sn:pbP++~}~hbD{m;1|_G7B"!V. <[gi*9ѲS3*0u{ ,6ϩYϻ;:Uf~'em5MA=K.x4.|AApdV1R#oc?^+vn#ZOV= >8yw'JGеKDEbߒr`t PUyG^MjYN`ů{8pكb~4<#5SE i[?K6z]8N_AGnlx~Վ</%f?XOǽ>tJٲ>#/E <>0/N:Ǜn t QQN99{ D Ţ<{-W*EhAl| x%Y?H?&nض@.1JHcD]8?SjYaH䉵fc0v/VP#/_lHU6 5AN~ 9j\Aſ=f䰨xȍ!|}g_icz;1S}8`x- <8au"2dxj?no:MMo^OK~Q*ζDXr&9r{Κb[Ã@`FQɼ:f[$ps[V)1vsaxN+_{grXIUWoQMz䏗ǻyw,`E NWoO'}xa`x| p΍;/4/T\no_,,_ԧ=<rꗪz1 Kw3 oom3q߅@Jrxg?-wæR"eO\MQ-^hy*6~thr6gK?.4upeT ^ 5}OGExޝ 7W'QDӍ fH_(*`k"e@A>{/fC;6UbigJ~3M?QL9Z̜0[|D޶STkhx/ri*u+vS̏59bJ]JXk|kb0lY%_$a`X qM&pWDys\`q_9,7]X}*,nB:-)nB @<==ߵE<}YI3N/ +voOAu ZTz v[4M6k6J?eⷔeh@=m@DžW1b"`u_Yx`@yGE>qlgDO6ZO(Z fbKle]91ֵ[m%:`d5c;A1SiOuWb"O<;68b~.%b~?uz^(""; /.1^|TRT @6T|yѧ+w9|HDuƫ ri"f412.] ćp0Qȝ/~o6^{te"ñXˋ\Wv '/f$Y8_OǮk'Ub?+b ǟmo/υl0y))<|gq/KtSВbIۢR1^D;C2NjˋM`pR1]WA^[)Ÿ1PU'Tk$wy NwI(`:yϪ/XA~`ůdHÎ]N)G‘ov?ğ)cxRѧ~!xĢ R8I`B`b4'Mk`Vi{$Q8_~NM8: 84` 4u]4ݹlY]2'/+RYN;NOMf-\׽ʡfwF.#QDeQT"R)[l-Fyt;zK[}^׊RA-gX~)St0"(Jq(:󞃭3N7 ²[,賲(v9x uh^; jxQ(o10J0`;UAU3h{} XQ.:fz]@Cɖfy1M,(hN1+=FQzM]qJ٫]:PB:(zx'Q8 to-08|n%S0Bᶒu^a A G9VWA6}R Iy?ka6AwW߁ * ʮ7;߱&*2DQe ~Uv쬪(f&"7\{٬rZỹs8-rFzaXin!rV"*4}eN|8 #śzUNEev̔*O.K;dlw30X}dET7l#9^ШY.{3qJUpr nOrl\%Ld8n1"wgKAw-.Ga§pz_Cz%A %`cg&$ ǜunEzpL)ڔoK.pХ`xss 9CYY_ngS}DL":TX*Ӱ(l!(%,Fz;6^pV #"hӕtc&RN4k&WSzFOJ7ĨzjctǍ\-FEXxuVAd_v R^~nۭȘ(JSe7.LDw%5+{s<^k Yn?g 6SՄBDyz%Qi5+Գ3a9ݤPhe/zc`W䙝^V' )Fa`v \ N*1;cGDtVT$nFo 'm`;OQ9DDv&0 ͈!0tCS9e1Ǡ2iWEKԦ"2d)WvEE,J oD Qwy,\||M:45'9aC&""p ͬ/E**ac ""&Jag0@DDQDDD"""ϓ5 N!"" ! "gc 8j(|8c`@DDD10 ""~ h?DDD"""ڏtC""8\7 10 "Y%Z}^X9eWҕ53SQ0( ) """ڏc ,>i"" ^5%8``@DD63-lc qFAAVAA!$6 2tod`@DDR4ȆWv10 ""es7n+o;X\RALiF ":D ̕ SAi00 Cd4ʗ(ZP wxut\|zCDQF3 nȊרڝm-Dk%T@YP8d_3Z 20 0xt^0[(8fMD]y5^3j-ףN51DdTe4+ٹ& { u2ƀQEMVG2nL#fB 8+(f&ϙץR7j`eM~:`3aеfV0fORYgzth1``@*5 zP[X=bWQDXv )K/ :]CD"ͨT4}/rR10 ҈n48[a',SqX iIe%@ȨAC"š`+nIW>dR[,-`\1RaQyuDhwQEt-tF b [ B@e2*2'߫q:n=Mu]D O\=) >|뾞"͈\OVMVt*2 a Ԣp.,Lג[c@ VB*|Qfh5fɘ91^ D> {+y| ;e[ 4椒- Xi`U[= 5Lva\ܚaXVaQܸVV({-*E.fz\+z3^\|H"Q~rmg;a x-KKWX+׊v< c 80O;A(_ L f6̋'}yC'Ux];aVP,A?&7{dKapǯ| =t (tX0Ϟ Ca@tVuc<:bhs#?L IDATzܼF᡺{nwcWY|00X!]$Ɏ.)צ>8]bG^Y.ītE,f7 TVa AQb'Wa涐ӹ"}*@.J "KGqV~]x1LB(h~N޳dHPx=гP"AWu ra`@&*b2Db*t Zn00X07mwt| I' ^5j3]7"jU'ܼDa>tCz ] sō!qM%a_T, AZQ)Mp ]3@53S-D{؋U2-J"sc$e;́ʹYFŒ &EQ%Obn\PxHJ6͉[ٕey`g۲B[ c ??3( E)BÏ DI 2X00zKWD5`ALEep=~EE  "DD00U^w#o lB fpnv":x @bJ% =VD`gB3TYSP00DUs}v!- d:.>v!/Ee&B.*ǃ(nܖ0P1g{d -M "=-d UkP &^q=D䭨5Bٸ"QhkeBopڬ;}%00]*@w hݸȾe[Ag%@f#M][Z<%,rNF[ݜ#Pe;ϏpA\N] J 0 |95ڰZ(62LEidA[wSXMPAW b ʅF&iebZYzܱnZ*c;|deNjrAy5KpAr#xA57UiJfA#yrZ:iyqaF|JOetpCb %}^d˰af i%$}Xth=2x)(P=!YQݔSV pnVދs`u 2cX[p100^vyyS; T6$cԯiAu np~/{vpN UAM?LPT!=ƃTnKAliE3݋m7C\Px1Iv28PI&}aE\ٽ&|PqS5 y^3LPdR!.˱NҶ3i*fȜS;Gk&Jؕ@ k9֮0aϿp/ӷj~mw,' >yϒ<hjuwd?DU|qMv=vv@Q gY8u[qqS+vFvY :¥K3[W 8n){d>ҵ^7O2׼4IdϽzc$HJ3HML~Mϲz r2NEȶ|;v}f7|W6 ʏc%e@l1Յ5 MfjF݊IkŵrUfO^m K5bV.rEF^6IPTk+L7An5.@|ؕ@.|1#W K B«J<1{.f۸ V``nGa `'dF(T/p;T 3 "&Dz8⌦+Y}uk'rA: F^W%1"^Bf``f,c:q9&I5De&a;:T*V\2be^msVVuUlb7_^wl,,;A.^bsV~,;AЙO~1ȞDP{z6 ƋM~ \;dҟKJc`V(ɬtVtmMeJ^E$ĝ5;DDPOC* Z=42 Z n,\/6VdVN~GXvrf֑ u tȼ,rX2tgn4{d][ 꼺 TIOA4e{~n5pAU[[:\tAng Ҳ1t#~w!uz snը΃\,T̾0T^S|4Z:\3^c`sU NӬ u;saܲV\*ƅ.JQo>$K*[2Ji|ա!vU d''=Z2,LB\[ 4";ثSYT'˪BvoEwLUDUٔV"8{+ WKut\|zCFt _UQI;:oVyMa7е[O>5WeWڝmIE&N+Vu%,l1cp@i ؕ@!u*[u0Tՠ\K)[}`tul#oٹfdl1ȳ{sz "1s7:c^HTl1 Rȯh`Q>Hr $sa#R vFy1x|dLzV2H 銁-탤cp'|U-f'0FPE$i(S*WBMv[6>R@^R\/S}mE] T_*?m ;ѭ_? d!P``@Ea$3zj4b' ׭8w.8 `u (RZ Ѭ EkKՁW:6i-tXA%ݚދ}@rmDs)#zYQPܪ sN?+=ף\uukp"M;}aLk)ҳ(Ac@U9NSd*0n+~wk^XAߝkѠRt춴0ƀEwxDrY. ?SX縻%68{ ҅N |HU#{C]2i Lי#ψ5‹)^ YN狫Jɓ.cAސ^\JE_~GE܂!#2`^g`@z%9Vıd^1O (Xꉕ!ѱ5®"09KaH*AO[^ 53S?\XF#B(hl1Xp:Cu( *~v]f\ZLo10Xj|VS nZع֍['?>ȕǺ^:.e+0Ә[w'*:ODL7 ¸Y2֪Hs ݑNGgDtuI`Ũ1/;XoYl36[ Rx{xq:j6䕺&Q4.䤕nS:<|wMz2WA;=,,߶;{^s9G] ~3ֵsjnŌ/@l@vfNkTUN0U,{TE,psڋRos`i6ַ=!΁mx|mWzd|k떛'{[Nޟ{2g_[nk}Vvrң賲iK9Lvcuxi1uF*B^*B*@l\_5z)zZ]A䗸.o'/WTʐєհrޛ|Zd_yoLK@FA g%k?[oq!/Q*SD^ӹ >7%[)1{C1iA)}>ï`ϬAe44.DS n8+!J9x/ _+?:DAS5 ^IkE+mt[Y6 1:H5y܎gBUz m=}s0̫ƔLu׼,TLR7]U2uT*V2N;NKBmt2{O/aN(-vWtnE缩b5>T&Dd?Wvm؎V}z(\agLNLڮpxe2Rî!k2-A@Z g^ Mn}P*k{o</' lo$3{oh7o;* "U2\wXYv'KvMd']/G۫uIŏrݫQ;vcyBrI E8q쥘SE#]C IeEaUNQΫf_^]vΗ L@- hhtD@rwEփ<57K߳ALA@Z.s? jF{5cdeIl 0(߈8J* ـ M$Z&P[>KUvLyYi8ZEawx SʾN>T?f5x d7^l[npu: rD] L}݅IJD$èS1E87Nҵ Nj) V4]½ փ¼8uU8mµ(+Q+"c:N 7: bWw ܽuU< DPQT3kcFՅ sDdfkq T B`Ӿem xy"aȹXPcKW#"ܬƦKF*F5G3;3t]C^n}1]/0䂃0sWw )u.t'D? acX lv4+ zb Io{1[pj@qHGATda08{(ίT++N_ԓl?Y{>on }%<;q!v: Mbi2BiAfMf D\Q}S* ح2#! +ۀ}M*ͪ`;ԆEx7_sTg"ίWB8GfIe>ox^l/X"5^ ML20\5Ǩ,:\M(j;] f[hmNEvTA̎{Oo*]A&x1lY߀]'\5/*R][q`l|w4tҴ dd/V܁maNmQ)$[QP.Ja bX|=ַ=(NX $A&;ׂ,.uo;yM>^ U1g{hh\ y0H̩ F(GU^t#|~7|a .5،MJm ? H ]W=Mk#a~R-=Ne(2 <wbDx"2fjց\MvWc`\JL10A(&NxŊrEQf0`A?]44.¶URo|I9M~b@]N75،U7]#TZc`lpw(GD.\68@@Ipj5߈X9% /Q.œ[QZP(W'TBJ`P<&LGи{7Iê=d1=FnLX!d{tRx%T:10PD6@*yK0⣊rD4E'TWX*_)/Q7mYz;dA*  0xD@;[ MXdjʦ;K*-Vcj10l(‰c/9?w˯ I~ T:CByD̮.N );f祹tlk5°Vv+{NUwxLE„_ uF'Lq Ң:0@ /܅-c8/,10|an]($OOv`k8C^-tKUoLΧMy%rE$-8wY%ْ14`B 0nlәԗMnri3ifKLá&1Lih'&Cn:NKjm01@)±:ˋawf|zW}c] 1,5F4֎DZ\``w&;8az _P007CO0c '{0HU@kewFbapa IDATnA-_B5-*qjx/3jqY 흷5?zQY.xj|d#K?B:\A ܷll`{g*S O  3芵c`Z\a$N/Telk~-5;FD~hLj'ĹK|18D@XW݆N*M`DDr͸ Y%pf!{o\ u?ƧPZ!4*ױ:9`|y>p-.;`.^ ~O0Z\n܁E$B}9HmOuqz_Z23CO!dZ\f܅;oDM#"?ȵ8Q͢!58fqq3e~'6ރpJhT;q뢙9^i{õIT7' w7sv rz}d>| gH5܉UH[}Au~}_ tg;dA S ÉwqvG6|#gҿ[0 ƿ7F"5bCp$vᡜ B:rESBO-Լ@w8 &Nob00P`s^>m >Á;hTBgw;j=ě2-d;oE[/`P<^Vl cOgAvC0D8 /|]˹\wp{Xs}~#躴 5/.`3a)1E szǠcQ*Fg^i-?+g$^Њی\?`-^y WWgn2PWfC(x;.'?EΕowi/,RN4 $rJ ݃k흟FIF`Tv!Phêa䴆Ya1 |:*);=߂lcaqѵɌ wzƀ`.G4ց_-҉R#PK#O\WZ…K ,yAOq'5 H5+}PY]Ԍ厫v\Fz[q<5 0݇t6i8I ̊'jHmeZϝKf_iwFk;1\:S Nž'fy%b%tڪ.ծvk[z^.jOGhNCͮ=&Cى1 $}~g=z'^&rON/\cqy;dw 0EQ L?/|WmCkue ~3kk-pq8!ǮR;*N"!)(;z0aBr?ZˮM%qAVI˿Dīx 3`޷ڋx5|O㶳#ɏ^@@fBbJf&uoDžFeҲ8?|rǴZq9^dSt҇c@{!ū}DKE:EbxyY Nys3pbIg>3\a2ԧO&]vg~ʅ[nv{e0k΋S]6 `( Wa0 HLls ޿e;{}a%gX>w:|z iYJjI ׽b`愦Ozf&|J`Jiyc مD&[<=1[V6/~P%0iC)VtNh'W[)2ىA" qOn~Jj] Zd." -M>|H뱬͝3Tccrr UfL/ ~ŋR=nZndD+;PiG* 4V܋DnnuGS:,GEHgTχ/99D@ ~[A`TO z'~c1/SS/99A8X Mk53yiDc9)RS.9T@XY nY-z]3az. q%`0 W ۰ԕGޑQpv81iYrrp k-MϠhHMr#:z^ɍ ȵBiMx`OpWݏDjē8ۅ S#R*T@-ps_#K?ʼnpvJZ&Tr; y{XQ'"yJ_=K_ɩI^`@&Vߍ4U/R&=o e^&M2PHM8ՅNēG2BYQ-_l?djr#*H DrXMIf&= RS: DH9jb;lz\&8"m t E2]V}{飈va|ވc0 Ir [~ W &p|1v DI59Mb5jr>IΈc0 "bkӳ(^-TI7F"5"WS"A ;'E4֎)ˆd1@2 (i73nY-Vc;d"`0 2d@R6F^@]j-{cqj,dr"2;?:f&( Bկ* |.|\TQϞ{8DdcpIENDB`Brobdingnag/man/as.numeric.Rd0000644000176200001440000000215713762776702015622 0ustar liggesusers\name{as.numeric} \alias{as.numeric} \alias{as.complex} \alias{as.numeric,brob-method} \alias{as.complex,brob-method} \alias{as.numeric,glub-method} \alias{as.complex,glub-method} \alias{coerce,brob,numeric-method} \alias{coerce,brob,complex-method} \alias{coerce,glub,numeric-method} \alias{coerce,glub,complex-method} \title{Coerces to numeric or complex form} \description{ Coerces an object of class \code{brob} to numeric, or an object of class \code{glub} to complex } \arguments{ \item{x}{Object of class \code{brob} or \code{glub}} \item{\dots}{Further arguments (currently ignored)} } \details{ Function \code{as.numeric()} coerces a \code{brob} to numeric; if given a \code{glub}, the imaginary component is ignored (and a warning given). Function \code{as.complex()} coerces to complex. } \author{Robin K. S. Hankin} \note{ If \eqn{\left|x\right|}{|x|} is greater than \code{.Machine$double.xmax}, then \code{as.numeric(x)} returns \code{Inf} or \code{-Inf} but no warning is given. } \examples{ a <- as.brob(1:10) a <- cbrob(a, as.brob(10)^1e26) a as.numeric(a) as.complex(10i + a) } \keyword{math} Brobdingnag/man/index-class.Rd0000644000176200001440000000213413762776702015763 0ustar liggesusers\name{index-class} \Rdversion{1.1} \docType{class} \alias{index-class} \title{Class \code{"index"}} \description{ A virtual class for matrix extraction, copied from the \code{Matrix} package. } \section{Objects from the Class}{A virtual Class: No objects may be created from it.} \section{Methods}{ \describe{ \item{[}{\code{signature(x = "brobmat", i = "index", j = "index")}: ... } \item{[}{\code{signature(x = "brobmat", i = "index", j = "missing")}: ... } \item{[}{\code{signature(x = "brobmat", i = "missing", j = "index")}: ... } \item{[<-}{\code{signature(x = "brobmat", i = "index", j = "index")}: ... } \item{[<-}{\code{signature(x = "brobmat", i = "index", j = "missing")}: ... } \item{[<-}{\code{signature(x = "brobmat", i = "missing", j = "index")}: ... } } } \references{ Douglas Bates and Martin Maechler (2019). Matrix: Sparse and Dense Matrix Classes and Methods. {R} package version 1.2-18. \url{https://CRAN.R-project.org/package=Matrix} } \author{Bates and Maechler, I guess} \seealso{\code{\linkS4class{brobmat}}} \examples{ showClass("index") } \keyword{classes} Brobdingnag/man/length.Rd0000644000176200001440000000073713762776702015041 0ustar liggesusers\name{length-methods} \docType{methods} \alias{length} \alias{length,brob-method} \alias{length,glub-method} \alias{length,brob-method} \alias{length,glub-method} \title{Get lengths of brobs and glubs} \description{ Get lengths of brob and glub vectors } \usage{ \S4method{length}{brob}(x) \S4method{length}{glub}(x) } \arguments{ \item{x}{vector of class brob or glub} } \author{Robin K. S. Hankin} \examples{ x <- as.brob(-10:10) length(x) } \keyword{math} \keyword{methods} Brobdingnag/man/Logic.Rd0000644000176200001440000000125013762776702014604 0ustar liggesusers\name{Logic} \alias{logic.brob} \alias{Logic,swift,ANY-method} \alias{Logic,ANY,swift-method} \alias{Logic,swift,swift-method} \title{Logical operations on brobs} \description{ Logical operations on brobs are not supported } \author{Robin K. S. Hankin} \note{ The S4 group generic \dQuote{Logic} appeared in R-2.4.0-patched. Carrying out logical operations in this group will call \code{.Brob.logic()}, which reports an error. Negation, \dQuote{\code{!}}, is not part of this group: attempting to negate a brob will not activate \code{.Brob.logic()}; an \dQuote{invalid argument type} error is given instead. } \examples{ \dontrun{ !brob(10) } } \keyword{math} Brobdingnag/man/Summary.Rd0000644000176200001440000000256413762776702015215 0ustar liggesusers\name{sum} \alias{sum} \alias{min} \alias{max} \alias{prod} \alias{range} \alias{Summary,brob-method} \alias{Summary,glub-method} \title{Various summary statistics for brobs and glubs} \description{Various summary statistics for brobs and glubs } \arguments{ \item{x,\dots}{Objects of class \code{brob} or, in the case of \code{sum()} and \code{prob()}, class \code{glub}} \item{na.rm}{Boolean, with default \code{FALSE} meaning to interpret \code{NA}s literally and \code{TRUE} meaning to ignore any such elements} } \details{ For a \code{brob} object, being \code{NA} is not entirely straightforward. The S4 method for \code{is.na} is too \dQuote{strict} for some of the functions considered here. Consider \code{max(a)} where \code{a} includes only positive, fully specified, elements, and elements with known negative sign and exponents that include \code{NA} values. Here, \code{max(a)} is unambiguously determined. Similar logic applies to \code{min()} and, by extension, \code{range()}. } \author{Robin K. S. Hankin} \note{ Function \code{prod()} is \emph{very} slow for long \code{glub} vectors. It has to compute four Brobdingnagian products and two Brobdingnagian sums per element of its argument, and this takes a long time. } \seealso{\code{\link{is.na}}} \examples{ a <- as.brob(1:10) max(cbrob(1:10,brob(NA,FALSE))) } \keyword{math} Brobdingnag/man/Print.Rd0000644000176200001440000000077613762776702014657 0ustar liggesusers\name{Print} \alias{print.brob} \alias{print.glub} \alias{show,brob-method} \alias{show,glub-method} \title{Methods for printing brobs and glubs} \description{ Methods for printing brobs and glubs nicely using exponential notation } \usage{ \method{print}{brob}(x, ...) \method{print}{glub}(x, ...) } \arguments{ \item{x}{An object of class \code{brob} or \code{glub}} \item{...}{Further arguments (currently ignored)} } \author{Robin K. S. Hankin} \examples{ a <- as.brob(1:5) dput(a) a } \keyword{math} Brobdingnag/man/glub-class.Rd0000644000176200001440000000270613762776702015612 0ustar liggesusers\name{glub-class} \docType{class} \alias{glub-class} \alias{.cPair,brob,glub-method} \alias{.cPair,ANY,glub-method} \alias{.cPair,glub,glub-method} \alias{.cPair,glub,ANY-method} \alias{.cPair,glub,brob-method} \title{Class "glub" } \description{Complex Brobdingnagian numbers} \section{Objects from the Class}{ A \code{glub} object holds two slots, both \code{brobs}, representing the real and imaginary components of a complex vector. } \section{Slots}{ \describe{ \item{\code{real}:}{Object of class \code{"brob"} representing the real component} \item{\code{imag}:}{Object of class \code{"brob"} representing the imaginary component} } } \section{Extends}{ Class \code{"swift"}, directly. } \section{Methods}{ \describe{ \item{.cPair}{\code{signature(x = "brob", y = "glub")}: ... } \item{.cPair}{\code{signature(x = "ANY", y = "glub")}: ... } \item{.cPair}{\code{signature(x = "glub", y = "glub")}: ... } \item{.cPair}{\code{signature(x = "glub", y = "ANY")}: ... } \item{.cPair}{\code{signature(x = "glub", y = "brob")}: ... } \item{Im<-}{\code{signature(x = "glub")}: ... } \item{Re<-}{\code{signature(x = "glub")}: ... } } } \author{Robin K. S. Hankin} \seealso{ \code{\link{brob-class}},\code{\link{swift-class}} } \examples{ a <- as.brob(45) new("glub",real=a, imag=a) as.brob(5+5i) # standard R idiom; imaginary component discarded as.glub(5+5i) # returns a Glubbdubdribian object } \keyword{classes} Brobdingnag/man/Compare.Rd0000644000176200001440000000203513762776702015137 0ustar liggesusers\name{Compare-methods} \docType{methods} \alias{Compare-methods} \alias{Compare,brob,ANY-method} \alias{Compare,brob,brob-method} \alias{Compare,brob,glub-method} \alias{Compare,ANY,brob-method} \alias{Compare,ANY,glub-method} \alias{Compare,glub,glub-method} \alias{Compare,glub,ANY-method} \alias{Compare,glub,brob-method} \title{Methods for Function Compare in Package Brobdingnag} \description{ Methods for comparision (greater than, etc) in package Brobdingnag } \note{ As for \code{min()} and \code{max()}, comparison is not entirely straightforward in the presence of \code{NA}s. The low-level workhorses are \code{.Brob.equal()} for equality and \code{.Brob.greater()} for \sQuote{strictly greater than}. All other comparisons are calculated by combining these two. Comparison [function \code{.Brob.compare()}] explicitly tests for a zero length argument and if given one returns \code{logical(0)} to match base behaviour. } \examples{ a <- as.brob(10)^(0.5 + 97:103) a < 1e100 } \keyword{methods} \keyword{math} Brobdingnag/man/glub.Rd0000644000176200001440000000306213762776702014503 0ustar liggesusers\name{glub} \alias{glub} \alias{as.glub} \alias{is.glub} \title{Glubbdubdribian numbers: complex numbers with Brobdingnagian real and imaginary parts} \description{ Create, coerce to or test for a Glubbdubdribian object } \usage{ glub(real = double(), imag = double()) as.glub(x) is.glub(x) } \arguments{ \item{real, imag}{Real and imaginary components of complex number: must be Brobdingnagian numbers} \item{x}{object to be coerced to or tested for Glubbdubdribian form} } \details{ A \dfn{Glubbdubdribian} number is the Brobdingnagian equivalent of a complex number. Function \code{glub()} takes two arguments that are coerced to Brobdingnagian numbers and returns a Glubbdubdribian number. This function is not really intended for the end user: it is confusing and includes no argument checking. Use function \code{as.glub()} instead. Function \code{as.glub()} is the user's workhorse: use this to coerce numeric or complex vectors to Glubbdubdribian form. Function \code{is.glub()} tests for its arguments being Glubbdubdribian. } \author{Robin K. S. Hankin} \note{ Function \code{glub()} uses recycling inherited from \code{cbind()}. } \seealso{\code{\link{brob}}} \examples{ a <- as.glub(1:10 + 5i) a^2 - a*a f <- function(x){sin(x) +x^4 - 1/x} as.complex(f(a)) - f(as.complex(a)) # should be zero (in the first # term, f() works with glubs and coerces to # complex; in the second, f() # works with complex numbers directly) } \keyword{math} Brobdingnag/man/cbrob.Rd0000644000176200001440000000322713762776702014644 0ustar liggesusers\name{cbrob} \alias{cbrob} \alias{cBrob} \title{Combine Brobdingnagian vectors} \description{ Combine Brobdingnagian or Glubdubbdribian vectors through concatenation } \usage{ cbrob(x, ...) } \arguments{ \item{x}{Brobdingnagian vector} \item{\dots}{Other arguments coerced to brob form} } \details{ If any argument has class \code{glub}, all arguments are coerced to \code{glub}s. Otherwise, if any argument has class \code{brob}, all arguments are coerced to \code{brob}s. Function \code{cbrob()} operates recursively, calling \code{.cPair()} repeatedly. Function \code{.cPair()} uses S4 method dispatch to call either \code{.Brob.cpair()} or \code{.Glub.cpair()} according to the classes of the arguments. } \author{Robin K. S. Hankin; original idea due to John Chambers} \note{ As of R-2.4.0, it is apparently not possible to use S4 methods to redefine \code{c()} to coerce to class \code{brob} form and concatenate as expected. This would seem to be a reasonable interpretation of \code{c()} from the user's perspective. Conceptually, the operation is simple: concatenate the \code{value} slot and the \code{positive} slot separately, then call \code{brob()} on the two resulting vectors. When concatenating \code{glub} objects, the real and imaginary components (being \code{brob}s) are concatenated using \code{.Brob.cpair()} The choice of name---\code{cbrob()}---is not entirely logical. Because it operates consistently on \code{brob} and \code{glub} objects, it might be argued that \code{cSwift()} would be a more appropriate name. } \examples{ a <- as.brob(2)^1e-40 cbrob(1:4,4:1,a) cbrob(1:4,a,1i) } \keyword{math} Brobdingnag/man/Arith.Rd0000644000176200001440000000220713762776702014621 0ustar liggesusers\name{Arith-methods} \docType{methods} \alias{Arith-methods} \alias{Arith,brob,missing-method} \alias{Arith,brob,ANY-method} \alias{Arith,brob,brob-method} \alias{Arith,brob,complex-method} \alias{Arith,ANY,brob-method} \alias{Arith,ANY,glub-method} \alias{Arith,glub,missing-method} \alias{Arith,glub,glub-method} \alias{Arith,glub,ANY-method} \alias{Arith,glub,complex-method} \alias{Arith,complex,brob-method} \alias{Arith,complex,glub-method} \alias{Arith,brob,glub-method} \alias{Arith,glub,brob-method} \title{Methods for Function Arith in package Brobdingnag} \description{ Methods for Arithmetic functions in package Brobdingnag: \code{+}, \code{-}, \code{*}, \code{/}, \code{^} } \author{Robin K. S. Hankin} \note{ The unary arithmetic functions (viz \dQuote{\code{+}} and \dQuote{\code{-}}) do no coercion. The binary arithmetic functions coerce \code{numeric} \code{brob} to \code{brob}; and \code{numeric} \code{glub}, \code{complex} \code{brob}, and \code{brob} \code{glub}, to \code{glub}. } \examples{ x <- as.brob(1:10) y <- 1e10 x+y as.numeric((x+y)-1e10) x^(1/y) } \keyword{methods} \keyword{math} Brobdingnag/man/plot.Rd0000644000176200001440000000124213762776702014526 0ustar liggesusers\name{plot} \alias{plot} \alias{plot,brob-method} \alias{plot,brob,missing-method} \alias{plot,brob,ANY-method} \alias{plot,ANY,brob-method} \alias{plot,glub-method} \alias{plot,glub,missing-method} \alias{plot,glub,ANY-method} \alias{plot,ANY,glub-method} \title{Basic plotting of Brobs} \description{ Plotting methods. Essentially, any brob is coerced to a numeric and any glub is coerced to a complex, and the argument or arguments are passed to \code{plot()}. } \usage{ plot(x, y, ...) } \arguments{ \item{x,y}{Brob or glub} \item{\dots}{Further arguments passed to \code{plot()}} } \author{Robin K. S. Hankin} \examples{ plot(as.brob(1:10)) } \keyword{math} Brobdingnag/man/swift-class.Rd0000644000176200001440000000066314162031142015766 0ustar liggesusers\name{swift-class} \docType{class} \alias{swift-class} \title{Class "swift" } \description{A (virtual) class that extends \code{brob} and \code{glub} objects} \section{Objects from the Class}{A virtual Class: No objects may be created from it.} \section{Methods}{ No methods defined with class "swift" in the signature. } \author{Robin K. S. Hankin} \seealso{ \code{\link{brob-class}},\code{\link{glub-class}} } \keyword{classes} Brobdingnag/DESCRIPTION0000644000176200001440000000166614323753132014210 0ustar liggesusersPackage: Brobdingnag Type: Package Title: Very Large Numbers in R Version: 1.2-9 Authors@R: person(given=c("Robin", "K. S."), family="Hankin", role = c("aut","cre"), email="hankin.robin@gmail.com", comment = c(ORCID = "0000-0001-5982-0415")) Maintainer: Robin K. S. Hankin Depends: R (>= 2.13.0), methods, Matrix (>= 1.5-0) Description: Very large numbers in R. Real numbers are held using their natural logarithms, plus a logical flag indicating sign. Functionality for complex numbers is also provided. The package includes a vignette that gives a step-by-step introduction to using S4 methods. Suggests: cubature, testthat License: GPL Repository: CRAN URL: https://github.com/RobinHankin/Brobdingnag NeedsCompilation: no Packaged: 2022-10-19 08:16:38 UTC; rhankin Author: Robin K. S. Hankin [aut, cre] () Date/Publication: 2022-10-19 10:50:02 UTC Brobdingnag/build/0000755000176200001440000000000014323731145013570 5ustar liggesusersBrobdingnag/build/vignette.rds0000644000176200001440000000040214323731145016123 0ustar liggesusers}; 0Ӈ*ͭ 8:i4-Ƥ/DCޓm !d#׶RWqޝ&@#++^v輐lB?TLF>dK˄POk 3x=mDcDQ{TcݒYꢚ Mt׹k({r6WGK[iXD~S:RёT;ҰEIFSzOH1ͧBrobdingnag/build/partial.rdb0000644000176200001440000001226614323731137015725 0ustar liggesusers]{SȖ7$w:Nؘ!!PK03;F< x_1߭>#փ@8mgnuK.g2LwgG WٿL /83z()^ѥTM?Ha\*(RvV[2eYCi.Ӌ6o{~~UV5 8{t鲧w֧zQ]6O匧^VeK0Xǵ=OY, zN]GtJ=p6rv+՟m )ܜ43=T zU%=lA4عxFkaeOUU9BZ=EG,pOǝ&z]^'m;.Y{+F4lY @z;X%V/%Mv; :k@wGJhHzB] uYzz  _ e_`tWT yQ fݨ _b˳J7KG%JwR8=.#T^yMj/&m-$+twx? CY6f}xrq{zy67jMAlCEaX?QA6%BɛzDM:)DT_ |,HDUۑb), 94XOsI,ތ!rspaWB-Tkj:{?j(2cW]^mbw\G75YB TҎLJvDU%/0z?>In1{&%n2ȚQLޭZvJ٩2ƞ>+KLu]na٨4zTI R3=U .mn]n ea1Hm2I6{[˦Rc h{0i(ubhnOHڻbe np;!WBd~H"~"LNujڃ:3hM}Bq)g} ]Ka>7X#k+oL,G ,8$C$$cJ2d4gI(S"* X09[0ɹdZ/R̄1HN0v*晉MLLS]'}d+Tm^>ua"L]LA\+%Գhu{0…y2Ɯ`J_F FIG'?evvt|5F_I~44J,Qv}G-jYTﲲQe?cT/V6VYitM#?5x[jstג慿0:I"R^„}D dlqd,nD$y-٦zO泳Sa] xHyaČ)=tSt9=NEd?- ^%rNI-9j*Sݺ歑[m)4 fXm dߴ >GyaN]ۮY\ t%&5g*-w0Ϲera"I~w25pÔU%k\-ŋsVtj3 _ȆS>l_ fJE7:u.E_g+Cb9X[z]v%]Iuh A3 )= FAk6jlE^JίO(ħ#eI2{;IxetFhJBj9Ґ^ziŨ$$F2ߺ8Hh0R~GVKfXo+dKL~k)6aR5M)3Ӷ N/,8S%=y),?଒uyJVdՔ!"e_¬K=0>^RɳoŠ&K<ඎ{^d\mrbTIwooGQ8=PKU?%*`!j;GmOO4AR|@HmUnsrk+{li/.T@^Rw1U!eL Ѓ/)b%!L3j^7?/Af\|9&6 c* o@W/[pwZ6k4W0>08焜?Fn̨QSro6mvdB7zf oq4Vq;_mp,4ֶc桵Q0/:TJl&6Uμ3xt&%`aI,-3AR'"d\kCWUҜ+,JY/'iuj=vxRX/=U,&nf#qfL5*~E%1+iйR^F?u,'9!JVJu&clJ8Q`nDe@xi9'f8a@; qDlx? s}:lL|l҇X~t {.15|W1PǑay-@^!]rr @/GBWߥ:ͷ/'ZurW|%Ż>5Ƌr]8n6)uo%D٨FzSt“O@_hن 6$L "ޛ#,?Jbͭ !ASXy) f=EPD M lb]cY$>ʈjS;X8}V`LVJ?A,@s]H" y'p`,Ebޔ2qCj='ۏ0;J{99Eei ")d}2PloӆгQX`X]7*/TUrp>?w84fPUClS*iȆ _n^Ez;bD\c>@!c͛%6G<\; lP[Rw@ `k 5:@(1?):9x4wkѷH|Y;CA62 qF刪wwMn"d/K!˥ U<[DTx@BWY*#u`l'Rq]P=nXXZraL6zޢ(0̃%2N'd}P#.#,d[zfzz.yfWĔUT^y槶6 fb!&P~@|q E_TnA [`hN<$&ax ݷ&ɞիM](xԘ,UuB_ITKN YjR TƓ`q#,XzGGFae3+`y$5?ƾa-ˢ.~k#^FN '~[.5P,w*Q14bH_; pu4aOPTd43hFPm)f"{`gZ䝹`.MG]#ؑٳf9 ;lۥhx,?Ӭd( )tsˑ _"c~:!$3cz~|sIeS>Mc^.=j¯V5P%y1*.*eN_Ѣ~(@XC/Z ݨYʁ@QEE;cTpjuEg-F|.-֕Zeփ vCDz0\YXܓĘ2{ۦGJ2\wXOV`3WJ&ܫ{m-UB#Y^=/5ŰE dV가Muo:*D^(&Ȼ䍺)uG?Ij_`6G@- ]yԇhlp= XY~%XX)D5X0\94rQ={{\ #~|̚u?=}8+lP+n<ҽusLг>Ue@j2 ȿ ĪQYD;;arI+ØC%geP?Pm%@]K]I }3Ʀ'Mjj>q'$jUltkNA@]_ugDA\kF_"5r(k,e,8q?O=uN^8Byv,?_KzznomG)~orui,i9M- 9kW2iqcjX,Nge9Zؿ?6s.l~nNy*>nؑr/bVſ?*2O<>i18VaA>4n9\ӐO<oJ;~1PcC:-|)8|foSⱟ &A>d9ЁmS?Mq^ŌǦw}=\;[bR =9,{_cu*,b(h:{'H4It{ РwY4sRݖwoX[R9(?> %%_FⲟX~Zlk&?k+oґETG.w 'ЀThoA{"H (r b*񰛍t:A ҽt Ku ; ~SY}Czt lDK(mZ  =as.brob(a))) expect_true(all(as.brob(a)<=as.brob(a))) expect_false(any(as.brob(a)>as.brob(a))) expect_false(any(as.brob(a)y$}\\ y+\log\left(1+e^{x-y}\right)\qquad &\mbox{otherwise} \end{array} \right. \] In practice this gets more complicated as one has to keep track of the sign; and special dispensation is needed for zero ($=e^{-\infty}$). One can thus deal with numbers up to about~$e^{1.9\times 10^{308}}\simeq 10^{7.8\times 10^{307}}$, although at this outer limit accuracy is pretty poor. \section{Class definition} The first thing we need to do is to define the {\tt brob} class. This uses the {\tt setClass()} function: <>= <>= setClass("swift", representation = "VIRTUAL" ) setClass("brob", representation = representation(x="numeric",positive="logical"), prototype = list(x=numeric(),positive=logical()), contains = "swift" ) @ It is simpler to ignore the first call to {\tt setClass()} here; for reasons that will become apparent when discussing the {\tt c()} function, one needs a virtual class that contains class brob and glub. To understand virtual classes, see section~\ref{logicSection}. The second call to {\tt setClass()} is more germane. Let's take this apart, argument by argument. The first argument, {\tt representation}, specifies ``the slots that the new class should have and/or other classes that this class extends. Usually a call to the `representation' function''. The helppage for {\tt representation} gives a few further details. Thus this argument specifies two `slots': one for the value and one for the sign. These are specified to be numeric and logical (NB: not Boolean) respectively. The second argument, {\tt prototype}, specifies default data for the slots. This kicks in when defining a zero-length brob; an example would be extracting {\tt x[FALSE]} where {\tt x} is a brob. The third argument, {\tt contains}, tells \proglang{R} that class {\tt swift} (which was specified to be virtual), has {\tt brob} as a subclass. We will need this later when we start to deal with {\tt glub}s, which are also a subclass of {\tt swift}. Let's use it: <>= new("brob",x=1:10,positive=rep(TRUE,10)) @ Notes: \begin{itemize} \item Function {\tt new()} is the {\em only} way to create objects of class brob. So, any object of class brob {\em must} have been created with function {\tt new()}. This is part of what the ``formal'' tag for \proglang{S4} means\footnote{Compare \proglang{S3}, in which I can say {\tt a <- 1:10; class(a) <- "lilliput"}}. \item Function {\tt new()} requires its arguments to be named, and no partial argument matching is performed. \item Function {\tt new()} is not intended for the user. It's too picky and difficult. To create new brobs, we need some more friendly functions---{\tt as.brob()} and {\tt brob()}---discussed below. \item There is, as yet, no print method, so the form of the object printed to the screen is less than ideal. \end{itemize} \subsection{Validity methods} Now, an optional step is to define a function that tests whether the arguments passed to {\tt new()} are acceptable. As it stands, the following code: <>= new("brob",x=1:10,positive=c(TRUE,FALSE,FALSE)) @ \noindent will not return an error, but is not acceptable because the arguments are different lengths (and will not recycle neatly). So, we define a validity method: <>= .Brob.valid <- function(object){ len <- length(object@positive) if(len != length(object@x)){ return("length mismatch") } else { return(TRUE) } } @ Advice on the form of the validity-testing function---here {\tt .Brob.valid()}---is given in the help page for {\tt setValidity}: ``The method should be a function of one object that returns `TRUE' or a description of the non-validity''. Examples are given in section 7.1.6 of the Green Book. In this package, I define a whole bunch of functions whose name starts with {\tt .Brob.}; these are internal and not intended for the user. They are also not documented. So now we have a function, {\tt .Brob.valid()}, that checks whether its argument has slots of the same length. We need to tell \proglang{R} that this function should be invoked every time a {\tt brob} is created. Function {\tt setValidity()} does this: <>= setValidity("brob", .Brob.valid) @ Thus, from now on [ie after the above call to {\tt setValidity()}], when calling {\tt new("brob", ...)} the two arguments {\tt x} and {\tt positive} must be the same length: recycling is not carried out. Functions like {\tt .Brob.valid()} that are user-unfriendly all have names beginning with {\tt .Brob}. These functions are there to help the organization of the package and are not intended to be used by the end-user. Clever, user-friendly operations such as recycling are carried out in the more user-friendly functions such as {\tt as.brob()}. If one were to call {\tt new()} with arguments of differing lengths, as in\\ \\ {\tt new("brob",x=1:10,positive=TRUE) } \\ \\ then {\tt new()} would report the error message in function {\tt .Brob.valid()}, because the {\tt positive} argument had length~1 and the {\tt x} was length~10; and the validity method {\tt .Brob.valid()} requires both arguments to be the same length\footnote{Placing the above call in {\tt try()} and showing the error explicitly would cause the package to fail {\tt R CMD check}.}. So now {\tt new()} works, but isn't exactly user-friendly: often one would want the above call to recycle the second argument to length 10 to match the first. This deficiency is remedied in the next section. \section{Basic user-friendly functions to create brobs} The basic, semi user-friendly function for creating brobs is {\tt brob()}: <>= "brob" <- function(x=double(),positive){ if(missing(positive)){ positive <- rep(TRUE,length(x)) } if(length(positive)==1){ positive <- rep(positive,length(x)) } new("brob",x=as.numeric(x),positive=positive) } @ Thus {\tt brob(x)} will return a number formally equal to~$e^x$. Function {\tt brob()} does helpful things like assuming the user desires positive numbers; it also carries out recycling: <>= brob(1:10,FALSE) @ Note that {\tt brob()} isn't exactly terribly user-friendly: it's confusing. {\tt brob(5)} returns a number formally equal to~$e^5$, not~$5$. This is documented in the help page, where the user is encouraged to use function {\tt as.brob()} instead. \section[Testing for brobs: an ``is.brob()'' function]{Testing for brobs: an {\tt is.brob()} function} Function {\tt is()} will test for an object being a brob: <>= is(brob(1:5),"brob") @ (see {\tt help(is)} for more details) but a small package like this, with only brobs and glubs to consider, could benefit from an \proglang{S3}-style function {\tt is.brob()}. This is easy to define: <>= is.brob <- function(x){is(x,"brob")} is.glub <- function(x){is(x,"glub")} @ now the user can just type {\tt is.brob(x)} to find out whether an object is a brob\footnote{This approach is fine for a tiny package like Brobdingnag, with only two or three classes. However, in the context of a more complicated package such as {\tt Matrix}, which uses dozens of different classes in a complicated hierarchical structure, one might prefer to type {\tt is(x,"dpoMatrix-class")} rather than define a plethora of functions along the lines of {\tt is.dpoMatrix-class()}.}. We also define an {\tt is.glub()} function similarly. So now we can check for objects being brobs and glubs. \section[Coercion: an ``as.brob()'' function]{Coercion: an {\tt as.brob()} function} Next, some ways to coerce objects to class brob: <>= "as.brob" <- function(x){ if(is.brob(x)){ return(x) } else if(is.complex(x)) { warning("imaginary parts discarded") return(Recall(Re(x))) } else if(is.glub(x)){ warning("imaginary parts discarded") return(Re(x)) } else { return(brob(log(abs(x)), x>=0)) } } @ So now we can coerce objects of various classes to brobs\footnote{The recommended way, appropriate for a complicated package such as Matrix, would be to execute {\tt setAs("numeric", "brob", .Brob.numeric\_to\_brob)} and {\tt setAs("complex", "brob", .Brob.complex\_to\_brob)}. Then, if {\tt x} is numeric, {\tt as(x,"brob")} would return the appropriate brob via {\tt .Brob.numeric\_to\_brob()}; we could then make {\tt as.brob()} a generic with {\tt setGeneric()} and define methods for it. Doing it this way would save function {\tt as.brob()} having to test for its argument being a brob [carried out in the first few lines of {\tt as.brob()}] because {\tt as()} has such a test built in, implicitly.}. The {\em only} way to create a brob is to use {\tt new()}, and the {\em only} function that calls this is {\tt brob()}. And {\tt as.brob()} calls this. Note the user-friendliness of {\tt as.brob()}. It takes numerics, brobs, and glubs (which give a warning). Check {\tt as.brob()}: <>= as.brob(1:10) @ \section[Coercion: an ``as.numeric()'' function]{Coercion: an {\tt as.numeric()} function} Now we need some methods to coerce brobs to numeric. This is a two-stage process. <>= <>= setAs("brob", "numeric", function(from){ out <- exp(from@x) out[!from@positive] <- -out[!from@positive] return(out) } ) @ This call to {\tt setAs()} makes {\tt as(x,"numeric")} carry out the function passed as the third argument when given a brob. But in this package, the user isn't supposed to type {\tt as(x,"numeric")}: the user is supposed to type {\tt as.numeric(x)}\footnote{Users can be expected to be familiar with functions such as {\tt as.numeric()} and {\tt as.complex()}, which is why the Brobdingnag package recommends this form. However, this might not be appropriate for a more complicated package such as Matrix because, to quote Martin Maechler, ``it seems very ugly to define more than very few {\tt as.FOO()} methods, and very natural to work with {\tt as(*, "FOO")} [constructions]''. Of course, there's nothing to stop a user typing {\tt as(x,"numeric")} if they wish.}. To accomplish this, we have to tell \proglang{R} that function {\tt as.numeric()} should execute {\tt as(x,"numeric")} when given a {\tt brob}. This is done by calling function {\tt setMethod()}: <>= setMethod("as.numeric",signature(x="brob"),function(x){as(x,"numeric")}) @ We similarly need to make {\tt as.complex()} work for brobs: <>= setAs("brob", "complex", function(from){ return(as.numeric(from)+ 0i) } ) setMethod("as.complex",signature(x="brob"),function(x){as(x,"complex")}) @ We'll need similar methods for glubs too. Better check: <>= x <- as.brob(1:4) x as.numeric(x) @ So that works. \section{Print methods} Print methods are not strictly necessary, but make using the package much easier. First, a helper function: <>= .Brob.print <- function(x, digits=5){ noquote( paste(c("-","+")[1+x@positive],"exp(",signif(x@x,digits),")",sep="")) } @ Then an \proglang{S3} method: <>= print.brob <- function(x, ...){ jj <- .Brob.print(x, ...) print(jj) return(invisible(jj)) } @ And finally a call to {\tt setMethod()}: <>= setMethod("show", "brob", function(object){print.brob(object)}) @ This two-stage methodology is recommended in the Venables and Ripley. The {\tt .Brob.print()} function does the hard work. Example of it in use: <>= as.brob(1:4) @ See how the brob object is printed out nicely, and with no special effort required of the user. \section{Get and Set methods} To be anal retentive about things, one should define {\tt C++} style accessor functions as follows: <>= <>= setGeneric("getX",function(x){standardGeneric("getX")}) setGeneric("getP",function(x){standardGeneric("getP")}) setMethod("getX","brob",function(x){x@x}) setMethod("getP","brob",function(x){x@positive}) @ but in practice I just use {\tt @} to access the slots. These are just here for good form's sake. \section{Length} Now a length: <>= <>= setMethod("length","brob",function(x){length(x@x)}) @ \section{Extracting elements of a vector} Next thing is to define some methods for extraction. This is done with {\tt setMethod()} for extraction, and {\tt setReplaceMethod()} for replacement. <>= <>= setMethod("[", "brob", function(x, i, j, drop){ if(!missing(j)){ warning("second argument to extractor function ignored") } brob(x@x[i], x@positive[i]) } ) @ See how the third argument to {\tt setMethod()} is a function whose arguments are the same as those to {\tt "["() %] }. Argument {\tt j} {\em must} be there otherwise one gets a signature error. I've put in a warning if a second argument that might be interpreted as {\tt j} is given. Now a method for replacement. This is a call to {\tt setReplaceMethod()}: <>= <>= setReplaceMethod("[",signature(x="brob"), function(x,i,j,value){ if(!missing(j)){ warning("second argument to extractor function ignored") } jj.x <- x@x jj.pos <- x@positive if(is.brob(value)){ jj.x[i] <- value@x jj.pos[i] <- value@positive return(brob(x=jj.x,positive=jj.pos)) } else { x[i] <- as.brob(value) return(x) } } ) @ See how the replacement function tests for the replacement value being a brob and acts accordingly. \section[Concatenation function ``cbrob()'']{Concatenation function {\tt cbrob()}} \label{cbrob} It is not possible to make {\tt c()} behave as expected for brobs\footnote{The ideas in this section are entirely due to John Chambers, who kindly replied to a question of mine on the \proglang{R}-devel email list} (that is, if any of its arguments are brobs, to coerce all its arguments to brobs and then concatenate). However, it is possible to define a function {\tt cbrob()} that does the job. This has to be done in several stages. First we define another user-unfriendly helper function {\tt .Brob.cPair()} which takes two arguments, coerces them to brobs, and concatenates them: <<.Brob.cPair>>= .Brob.cPair <- function(x,y){ x <- as.brob(x) y <- as.brob(y) brob(c(x@x,y@x),c(x@positive,y@positive)) } @ This is just {\tt c()} for the two slots separately. The idea is that function {\tt .Brob.cPair()} takes two arguments; both are coerced to brobs and it returns the concatenated vector of brobs. Now, we need to set up a (user-unfriendly) generic function {\tt .cPair()}: <>= <>= setGeneric(".cPair", function(x,y){standardGeneric(".cPair")}) @ Function {\tt .cPair()} is not substantive (sic): it exists purely in order to be a generic function that dispatches to {\tt .Brob.cPair()}. Now we use {\tt setMethod()} to organize the dispatch: <>= <>= setMethod(".cPair", c("brob", "brob"), function(x,y){.Brob.cPair(x,y)}) setMethod(".cPair", c("brob", "ANY"), function(x,y){.Brob.cPair(x,as.brob(y))}) setMethod(".cPair", c("ANY", "brob"), function(x,y){.Brob.cPair(as.brob(x),y)}) setMethod(".cPair", c("ANY", "ANY"), function(x,y){c(x,y)}) @ The four calls are necessary for the four different signatures that might be encountered. Note the {\tt ANY} class in the second, third, and fourth call. Thus if someone wants to write a new class of object (a lugg, say), and wants to concatenate luggs with a brob, this will work provided that they use {\tt setAs()} to make {\tt as.brob()} coerce correctly for lugg objects. The method used here allows this to be done without any changes to the Brobdingnag package. The final stage is the definition of {\tt cbrob()}, a user-friendly wrapper for the above stuff: <>= "cbrob" <- function(x, ...) { if(nargs()<3) .cPair(x,...) else .cPair(x, Recall(...)) } @ Note the recursive definition. If {\tt cbrob()} is called with {\em any} set of arguments that include a brob anywhere, this will result in the whole lot being coerced to brobs [by {\tt .Brob.cPair()}]. Which is what we want (although glubs will require more work). Just test this: <>= a <- 1:3 b <- as.brob(1e100) cbrob(a,a,b,a) @ So it worked: everything was coerced to a brob because of the single object of class brob in the call. \section{Maths} The math group generic functions are set with function {\tt setMethod()}. But, before this can be called, function {\tt sqrt()} needs a specific brob method: <>= <>= setMethod("sqrt","brob", function(x){ brob(ifelse(x@positive,x@x/2, NaN),TRUE) } ) @ Just check that: <>= sqrt(brob(4)) @ With these out of the way we can use {\tt setMethod()} to define the appropriate functions in the math group generic: <>= <>= setMethod("Math", "brob", function(x){ switch(.Generic, abs = brob(x@x), log = { out <- x@x out[!x@positive] <- NaN out }, exp = brob(x), cosh = {(brob(x) + brob(-x))/2}, sinh = {(brob(x) - brob(-x))/2}, acos =, acosh =, asin =, asinh =, atan =, atanh =, cos =, sin =, tan =, tanh =, trunc = callGeneric(as.numeric(x)), lgamma =, cumsum =, gamma =, ceiling=, floor = as.brob(callGeneric(as.numeric(x))), stop(paste(.Generic, "not allowed on Brobdingnagian numbers")) ) } ) @ See how the third argument to {\tt setMethod()} is a function. This function has access to {\tt .Generic}, in addition to {\tt x} and uses it to decide which operation to perform. See how functions {\tt acos()} to {\tt trunc()} just drop through to {\tt callGeneric(as.numeric(x))}. See also the method for {\tt log()}, which uses facts about brobs not known to \proglang{S4}. Just a quick check: <>= sin(brob(4)) @ So that works. \section{Operations} Now we need to make sure that {\tt brob(1) + brob(3)} works: the operations {\tt +, -, *, /} must work as expected. This is hard. First step: define some user-unfriendly functions that carry out the operations. For example, function {\tt .Brob.negative()} simply returns the negative of a brob. These functions are not for the user. <<.brob.arithstuff>>= .Brob.negative <- function(e1){ brob(e1@x,!e1@positive) } .Brob.ds <- function(e1,e2){ xor(e1@positive,e2@positive) } .Brob.add <- function(e1,e2){ e1 <- as.brob(e1) e2 <- as.brob(e2) jj <- rbind(e1@x,e2@x) x1 <- jj[1,] x2 <- jj[2,] out.x <- double(length(x1)) jj <- rbind(e1@positive,e2@positive) p1 <- jj[1,] p2 <- jj[2,] out.pos <- p1 ds <- .Brob.ds(e1,e2) ss <- !ds out.x[ss] <- pmax(x1[ss],x2[ss]) + log1p(+exp(-abs(x1[ss]-x2[ss]))) out.x[ds] <- pmax(x1[ds],x2[ds]) + log1p(-exp(-abs(x1[ds]-x2[ds]))) out.x[ (x1 == -Inf) & (x2 == -Inf)] <- -Inf out.pos <- p1 out.pos[ds] <- xor((x1[ds] > x2[ds]) , (!p1[ds]) ) return(brob(out.x,out.pos)) } .Brob.mult <- function(e1,e2){ e1 <- as.brob(e1) e2 <- as.brob(e2) return(brob(e1@x + e2@x, !.Brob.ds(e1,e2))) } .Brob.power <- function(e1,e2){ stopifnot(is.brob(e1) | is.brob(e2)) if(is.brob(e2)){ return(brob(log(e1) * brob(e2@x), TRUE)) } else { s <- as.integer(2*e1@positive-1) return(brob(e1@x*as.brob(e2), (s^as.numeric(e2))>0)) } } .Brob.inverse <- function(b){brob(-b@x,b@positive)} @ Note the complexity of {\tt .Brob.add()}. This is hard because logs are good at multiplying but bad at adding [{\tt ss} and {\tt ds} mean ``same sign'' and ``different sign'' respectively]. The first step is to make sure that the unary operators {\tt +} and {\tt -} work. We do this by a call to {\tt setMethod()}: <>= <>= setMethod("Arith",signature(e1 = "brob", e2="missing"), function(e1,e2){ switch(.Generic, "+" = e1, "-" = .Brob.negative(e1), stop(paste("Unary operator", .Generic, "not allowed on Brobdingnagian numbers")) ) } ) @ Note the second argument is {\tt signature(e1 = "brob", e2="missing")}: this effectively restricts the scope to unary operators. The {\tt switch()} statement only allows the + and the -.\ Check: <>= -brob(5) @ So that works. Next step, another user-unfriendly helper function that does the dirty work: <>= .Brob.arith <- function(e1,e2){ switch(.Generic, "+" = .Brob.add (e1, e2), "-" = .Brob.add (e1, .Brob.negative(as.brob(e2))), "*" = .Brob.mult (e1, e2), "/" = .Brob.mult (e1, .Brob.inverse(as.brob(e2))), "^" = .Brob.power(e1, e2), stop(paste("binary operator \"", .Generic, "\" not defined for Brobdingnagian numbers")) ) } @ And now we can call {\tt setMethod()}: <>= setMethod("Arith", signature(e1 = "brob", e2="ANY"), .Brob.arith) setMethod("Arith", signature(e1 = "ANY", e2="brob"), .Brob.arith) setMethod("Arith", signature(e1 = "brob", e2="brob"), .Brob.arith) @ Better check it: <>= 1e100 + as.brob(10)^100 @ \section{Comparison} This is pretty much the same as the others. First, some user-unfriendly helper functions: <>= .Brob.equal <- function(e1,e2){ (e1@x==e2@x) & (e1@positive==e2@positive) } .Brob.greater <- function(e1,e2){ jj.x <- rbind(e1@x,e2@x) jj.p <- rbind(e1@positive,e2@positive) ds <- .Brob.ds(e1,e2) ss <- !ds greater <- logical(length(ss)) greater[ds] <- jj.p[1,ds] greater[ss] <- jj.p[1,ss] & (jj.x[1,ss] > jj.x[2,ss]) return(greater) } @ These are the fundamental ones. We can now define another all-encompassing user-unfriendly function: <>= ".Brob.compare" <- function(e1,e2){ e1 <- as.brob(e1) e2 <- as.brob(e2) switch(.Generic, "==" = .Brob.equal(e1,e2), "!=" = !.Brob.equal(e1,e2), ">" = .Brob.greater(e1,e2), "<" = !.Brob.greater(e1,e2) & !.Brob.equal(e1,e2), ">=" = .Brob.greater(e1,e2) | .Brob.equal(e1,e2), "<=" = !.Brob.greater(e1,e2) | .Brob.equal(e1,e2), stop(paste(.Generic, "not supported for Brobdingnagian numbers")) ) } @ See how this function coerces both arguments to brobs. Now the call to {\tt setMethod()}: <>= <>= setMethod("Compare", signature(e1="brob", e2="ANY" ), .Brob.compare) setMethod("Compare", signature(e1="ANY" , e2="brob"), .Brob.compare) setMethod("Compare", signature(e1="brob", e2="brob"), .Brob.compare) @ Better check: <>= as.brob(10) < as.brob(11) as.brob(10) <= as.brob(10) @ So that works. \section{Logic} \label{logicSection} (The material in this section works in \proglang{R}-2.4.1, but not \proglang{R}-2.4.0). First a helper function: <>= .Brob.logic <- function(e1,e2){ stop("No logic currently implemented for Brobdingnagian numbers") } @ Now the calls to {\tt setMethod()}: <>= <>= setMethod("Logic",signature(e1="swift",e2="ANY"), .Brob.logic) setMethod("Logic",signature(e1="ANY",e2="swift"), .Brob.logic) setMethod("Logic",signature(e1="swift",e2="swift"), .Brob.logic) @ Note that the signatures specify {\tt swift} objects, so that glubs will be handled correctly too in one fell swoop. Note the third call to {\tt setMethod()}: without this, a call to {\tt Logic()} with signature {\tt c("swift","swift")} would be ambiguous as it might be interpreted as {\tt c("swift","ANY")} or {\tt c("ANY","swift")}. Here, class {\tt swift} extends {\tt brob} and {\tt glub}; so both brobs and glubs {\em are} {\tt swift} objects. But no object is a ``pure'' {\tt swift}; it's either a brob or a glub. This is useful here because I might dream up some new class of objects that are ``like'' brobs in some way (for example, a class of objects whose elements are quaternions with Brobdingnagian components) and it would be nice to specify behaviour that is generic to brobs and glubs and the new class of objects too. \section{Miscellaneous generics} We now have to tell \proglang{R} that certain functions are to be considered generic. The functions are {\tt max(), min(), range(), prod()}, and {\tt sum()}. The help page for (eg) {\tt max()} specifies that the arguments must be numeric, and brobs aren't numeric. In versions of \proglang{R} prior to 2.6-0 (I think), {\tt log()} needs to be made a generic with {\tt setGeneric()}. But, in versions 2.6-0 and above, all the group generics (including {\tt log}) are primitive, which means that the generic function is implicit and cannot be changed. This applies to the other group generics too ({\tt max}, {\tt min}, {\tt prod}, {\tt range} {\tt sum}). So to work with both types of \proglang{R}, one needs to check whether or not {\tt log} (or {\tt max} or whatever) is generic before calling {\tt setGeneric()}. <>= if(!isGeneric("log")){ setGeneric("log",group="Math") } @ <>= <>= if(!isGeneric("sum")){ setGeneric("max", function(x, ..., na.rm = FALSE) { standardGeneric("max") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::max(x, ..., na.rm = na.rm) }, group = "Summary") setGeneric("min", function(x, ..., na.rm = FALSE) { standardGeneric("min") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::min(x, ..., na.rm = na.rm) }, group = "Summary") setGeneric("range", function(x, ..., na.rm = FALSE) { standardGeneric("range") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::range(x, ..., na.rm = na.rm) }, group = "Summary") setGeneric("prod", function(x, ..., na.rm = FALSE) { standardGeneric("prod") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::prod(x, ..., na.rm = na.rm) }, group = "Summary") setGeneric("sum", function(x, ..., na.rm = FALSE) { standardGeneric("sum") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::sum(x, ..., na.rm = na.rm) }, group = "Summary") } @ Now we need some more user-unfriendly helper functions: <>= .Brob.max <- function(x, ..., na.rm=FALSE){ p <- x@positive val <- x@x if(any(p)){ return(brob(max(val[p]))) } else { return(brob(min(val),FALSE)) } } .Brob.prod <- function(x){ p <- x@positive val <- x@x return(brob(sum(val),(sum(p)%%2)==0)) } .Brob.sum <- function(x){ .Brob.sum.allpositive( x[x>0]) - .Brob.sum.allpositive(-x[x<0]) } .Brob.sum.allpositive <- function(x){ if(length(x)<1){return(as.brob(0))} val <- x@x p <- x@positive mv <- max(val) return(brob(mv + log1p(sum(exp(val[-which.max(val)]-mv))),TRUE)) } @ Note the final function that sums its arguments, which are all assumed to be positive, in an intelligent, accurate, and efficient manner. No checking is done (this is not a user-friendly function!). We can define {\tt .Brob.sum()} in terms of this: return the difference between the sum of the positive arguments and and the sum of minus the negative arguments. <>= <>= setMethod("Summary", "brob", function(x, ..., na.rm=FALSE){ switch(.Generic, max = .Brob.max( x, ..., na.rm=na.rm), min = -.Brob.max(-x, ..., na.rm=na.rm), range = cbrob(min(x,na.rm=na.rm),max(x,na.rm=na.rm)), prod = .Brob.prod(x), sum = .Brob.sum(x), stop(paste(.Generic, "not allowed on Brobdingnagian numbers")) ) } ) @ Better check: <>= sum(as.brob(1:100)) - 5050 @ showing acceptable accuracy. \section{Examples of the package in use} We can try to evaluate a factorial. Stirling's approximation is~$n!\sim\sqrt{2\pi n}\,e^{-n}n^n$: <>= stirling <- function(x){sqrt(2*pi*x)*exp(-x)*x^x} @ And this should work seamlessly with Brobs: <>= stirling(100) stirling(as.brob(100)) @ And are they the same? <>= as.numeric(stirling(100)/stirling(as.brob(100))) @ \ldots pretty near. But the great advantage of Brobdingnagian numbers is that they can handle numbers larger than the IEEE limit: <>= stirling(1000) stirling(as.brob(1000)) @ \noindent and this is accurate to about~12 sig figs, which is accurate enough for many purposes. The number of sig figs decreases with progressively larger numbers, essentially because an increasing amount of floating point accuracy is gobbled up by storing the exponent of a large number, and less is left for the mantissa. \section*{Acknowledgments} I gratefully acknowledge the help given to me by many members of the \proglang{R}-help and \proglang{R}-devel lists, especially Martin Maechler, Brian Ripley, and John Chambers. \nocite{*} \bibliography{brob} \end{document} Brobdingnag/vignettes/Brobdingnag.Rnw0000644000176200001440000001675014317730133017415 0ustar liggesusers\documentclass[nojss]{jss} \usepackage{dsfont} \usepackage{bbm} \usepackage{amsfonts} \usepackage{wasysym} \usepackage{wrapfig} \author{Robin K. S. Hankin\\Auckland University of Technology} \title{Very large numbers in \proglang{R}: introducing package \pkg{Brobdingnag}} %\VignetteIndexEntry{The Brobdingnag: package} \Plainauthor{Robin K. S. Hankin} \Plaintitle{Very large numbers in R: Introducing package Brobdingnag} \Plaintitle{Introducing package Brobdingnag} \Abstract{ This vignette shows how to use the \pkg{Brobdingnag} package to manipulate very large numbers; it is based on~\cite{Rnews:Hankin:2007}. The other vignette shows how to use \proglang{S4} methods in the context of a simple package. } \Keywords{\proglang{S4} methods, Brobdingnag, \proglang{R}} \Plainkeywords{S4 methods, Brobdingnag, R} \Address{ Robin K. S. Hankin\\ Auckland University of Technology\\ E-mail: \email{hankin.robin@gmail.com} } %% need no \usepackage{Sweave.sty} \SweaveOpts{echo=TRUE} \begin{document} \newsymbol\leqslant 1336 \section{Introduction} \setlength{\intextsep}{0pt} \begin{wrapfigure}{r}{0.2\textwidth} \begin{center} \includegraphics[width=1in]{\Sexpr{system.file("help/figures/Brobdingnag.png",package="Brobdingnag")}} \end{center} \end{wrapfigure} The largest floating point number representable in standard double precision arithmetic is a little under~$2^{1024}$, or about~$1.79\times 10^{308}$. This is too small for some applications. The \proglang{R} package \pkg{Brobdingnag}~\citep{swift1726} overcomes this limit by representing a real number~$x$ using a double precision variable with value~$\log\left|x\right|$, and a logical corresponding to~$x\geq 0$; the \proglang{S4} class of such objects is \code{brob}. Complex numbers with large absolute values (class \code{glub}) may be represented using a pair of \code{brob}s to represent the real and imaginary components. The package allows user-transparent access to the large numbers allowed by Brobdingnagian arithmetic. The package also includes a vignette---\code{S4_brob}---which documents the \proglang{S4} methods used and includes a step-by-step tutorial. The vignette also functions as a ``Hello, World!'' example of \proglang{S4} methods as used in a simple package. It also includes a full description of the \code{glub} class. \section[Package ``Brobdingnag'' in use]{Package \pkg{Brobdingnag} in use} Most readers will be aware of a googol which is equal to~$10^{100}$: <>= <>= require(Brobdingnag) <>= googol <- as.brob(10)^100 @ Note the coercion of \code{double} value \code{10} to an object of class \code{brob} using function \code{as.brob()}: raising this to the power~100 (also double) results in another \code{brob}. The result is printed using exponential notation, which is convenient for very large numbers. A googol is well within the capabilities of standard double precision arithmetic. Now, however, suppose we wish to compute its factorial. Taking the first term of Stirling's series gives <>= stirling <- function(n){n^n*exp(-n)*sqrt(2*pi*n)} @ \noindent which then yields <>= stirling(googol) @ Note the transparent coercion to \code{brob} form within function \code{stirling()}. It is also possible to represent numbers very close to~1. Thus <>= 2^(1/googol) @ It is worth noting that if~$x$ has an exact representation in double precision, then~$e^x$ is exactly representable using the system described here. Thus~$e$ and~$e^{1000}$ may be represented exactly. \subsection{Accuracy} For small numbers (that is, representable using standard double precision floating point arithmetic), \pkg{Brobdingnag} suffers a slight loss of precision compared to normal representation. Consider the following function, whose return value for nonzero arguments is algebraically zero: <>= f <- function(x){as.numeric( (pi*x -3*x -(pi-3)*x)/x)} @ \begin{verbatim} f <- function(x){ as.numeric( (pi*x -3*x -(pi-3)*x)/x) } \end{verbatim} This function combines multiplication and addition; one might expect a logarithmic system such as described here to have difficulty with it. <>= f(1/7) f(as.brob(1/7)) @ This typical example shows that Brobdingnagian numbers suffer a slight loss of precision for numbers of moderate magnitude. This degradation increases with the magnitude of the argument: <>= f(1e100) f(as.brob(1e100)) @ Here, the brobs' accuracy is about two orders of magnitude worse than double precision arithmetic: this would be expected, as the number of bits required to specify the exponent goes as $\log\log x$. Compare <>= f(as.brob(10)^1000) @ \noindent showing a further degradation of precision. However, observe that conventional double precision arithmetic cannot deal with numbers this big, and the package returns about 12 correct significant figures. \section{A practical example} In the field of population dynamics, and especially the modelling of biodiversity~\citep{hankin2007b,hubbell2001}, complicated combinatorial formulae often arise. \citet{etienne2005}, for example, considers a sample of~$N$ individual organisms taken from some natural population; the sample includes~$S$ distinct species, and each individual is assigned a label in the range~$1$ to~$S$. The sample comprises~$n_i$ members of species~$i$, with~$1\leq i\leq S$ and~$\sum n_i=N$. For a given sample~$D$ Etienne defines, amongst other terms, $K(D,A)$ for $1\leq A\leq N-S+1$ as \begin{equation} \sum_{ \left\{ a_1,\ldots,a_S\left| \sum_{i=1}^S a_i=A\right. \right\}} \prod_{i=1}^S \frac{ \overline{s}(n_i,a_i) \overline{s}(a_i,1)}{ \overline{s}(n_i,1)} \end{equation} \noindent where~$\overline{s}(n,a)$ is the Stirling number of the second kind~\citep{abramowitz1965}. The summation is over~$a_i=1,\ldots,n_i$ with the restriction that the~$a_i$ sum to~$A$, as carried out by \code{blockparts()} of the \pkg{partitions} package~\citep{hankin2006,hankin2007}. Taking an intermediate-sized dataset due to Saunders\footnote{The dataset comprises species counts on kelp holdfasts; here \code{saunders.exposed.tot} of package \pkg{untb}~\citep{hankin2007b}, is used.} of only~5903 individuals---a relatively small dataset in this context---the maximal element of~$K(D,A)$ is about~$1.435\times 10^{1165}$. The accuracy of package \pkg{Brobdingnag} in this context may be assessed by comparing it with that computed by \proglang{PARI/GP}~\citep{batut2000} with a working precision of~100 decimal places; the natural logs of the two values are~$2682.8725605988689$ and~$2682.87256059887$ respectively: identical to 14 significant figures. %Pari with 100 decimal places gives 2682.872560598868918515209515642292607616628612201118344882119616522539674163937533805390351760715777. % 2682.8725605988689 %and with R: 2682.87256059887 \section{Conclusions} The \pkg{Brobdingnag} package allows representation and manipulation of numbers larger than those covered by standard double precision arithmetic, although accuracy is eroded for very large numbers. This facility is useful in several contexts, including combinatorial computations such as encountered in theoretical modelling of biodiversity. \subsubsection*{Acknowledgments} I would like to acknowledge the many stimulating and helpful comments made by the \proglang{R}-help list over the years. \bibliography{brob} \end{document} Brobdingnag/vignettes/brobmat.Rmd0000644000176200001440000000663414176571204016610 0ustar liggesusers--- title: "Brobdingnagian matrices" author: "Robin K. S. Hankin" date: "`r Sys.Date()`" vignette: > %\VignetteIndexEntry{brobmat} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r set-options, echo = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>", dev = "png", fig.width = 7, fig.height = 3.5, message = FALSE, warning = FALSE) options(width = 80, tibble.width = Inf) ``` # Brobdgingnagian matrices R package `Brobdingnag` has basic functionality for matrices. It includes matrix multiplication and addition, but determinants and matrix inverses are not implemented. First load the package: ```{r} library("Brobdingnag") ``` The standard way to create a Brobdgingnagian matrix (a `brobmat`) is to use function `brobmat()` which takes arguments similar to `matrix()` and returns a matrix of entries created with `brob()`: ```{r} M1 <- brobmat(-10:13,4,6) colnames(M1) <- state.abb[1:6] M1 ``` Function `brobmat()` takes an argument `positive` which specifies the sign: ```{r} M2 <- brobmat( c(1,104,-66,45,1e40,-2e40,1e-200,232.2),2,4, positive=c(T,F,T,T,T,F,T,T)) M2 ``` Standard matrix arithmetic is implemented, thus: ```{r} rownames(M2) <- c("a","b") colnames(M2) <- month.abb[1:4] M2 M2[2,3] <- 0 M2 M2+1000 ``` We can also do matrix multiplication, although it is slow: ```{r} M2 %*% M1 ``` ## Numerical verification: matrix multiplication We will verify matrix multiplication by carrying out the same operation in two different ways. First, create two largish Brobdingnagian matrices: ```{r} nrows <- 11 ncols <- 18 M3 <- brobmat(rnorm(nrows*ncols),nrows,ncols,positive=sample(c(T,F),nrows*ncols,replace=T)) M4 <- brobmat(rnorm(nrows*ncols),ncols,nrows,positive=sample(c(T,F),nrows*ncols,replace=T)) M3[1:3,1:3] ``` Now calculate the matrix product by coercing to numeric matrices and multiplying:q ```{r} p1 <- as.matrix(M3) %*% as.matrix(M4) ``` and then by using Brobdingnagian matrix multiplying, and then coercing to numeric: ```{r} p2 <- as.matrix(M3 %*% M4) ``` The difference: ```{r} max(abs(p1-p2)) ``` is small. Now the other way: ```{r} q1 <- M3 %*% M4 q2 <- as.brobmat(as.matrix(M3) %*% as.matrix(M4)) max(abs(as.brob(q1-q2))) ``` ## Numerical verification: integration with the `cubature` package The matrix functionality of the `Brobdingnag` package was originally written to leverage the functionality of the `cubature` package. Here I give some numerical verification for this. Suppose we wish to evaluate \[ \int_{x=0}^{x=4}(x^2-4)\,dx \] using numerical methods. See how the integrand includes positive and negative values; the theoretical value is $\frac{16}{3}=5.33\ldots$. The `cubature` idiom for this would be ```{r,label = numericalintegration} library("cubature") f.numeric <- function(x){x^2 - 4} out.num <- cubature::hcubature(f = f.numeric, lowerLimit = 0, upperLimit = 4, vectorInterface = TRUE) out.num ``` and the Brobdingnagian equivalent would be ```{r,label = numericalintegrationbrob} f.brob <- function(x) { x <- as.brob(x[1, ]) as.matrix( brobmat(x^2 - 4, ncol = length(x))) } out.brob <- cubature::hcubature(f = f.brob, lowerLimit = 0, upperLimit = 4, vectorInterface = TRUE) out.brob ``` We may compare the two methods: ```{r,label=comparebrobandnumeric} out.brob$integral - out.num$integral ``` Brobdingnag/R/0000755000176200001440000000000014220452662012672 5ustar liggesusersBrobdingnag/R/aaa_allclasses.R0000644000176200001440000000053214220452662015745 0ustar liggesuserssetClass("brobmat", slots = c(x="matrix",positive="logical")) setClass("swift", representation = "VIRTUAL" ) setClass("brob", slots = c(x="numeric",positive="logical"), contains = "swift" ) setClass("glub", slots = c(real="brob",imag="brob"), contains = "swift" ) Brobdingnag/R/matrix.R0000644000176200001440000002134514207324737014334 0ustar liggesusers`.brobmat.valid` <- function(object){ if(length(object@x) != length(object@positive)){ return("length mismatch") } else { return(TRUE) } } setValidity("brobmat", .Brob.valid) `newbrobmat` <- function(x,positive){ new("brobmat", x=x, positive=c(positive)) # this is the only use of new() here } `brobmat` <- function(..., positive){ data <- list(...)[[1]] if(is.matrix(data)){ M <- data } else if(is.brob(data)){ jj <- list(...) jj[[1]] <- getX(data) M <- do.call(matrix,jj) # signs not accounted for return(newbrobmat(M,positive=getP(data))) } else { M <- matrix(...) } if(missing(positive)){positive <- rep(TRUE,length(M))} positive <- cbind(c(M),positive)[,2]>0 return(newbrobmat(M,positive=positive)) } `is.brobmat` <- function(x){is(x,"brobmat")} setMethod("getX","brobmat",function(x){x@x}) setMethod("getX","numeric",function(x){x}) setMethod("getP","brobmat",function(x){ out <- getX(x) storage.mode(out) <- "logical" out[] <- x@positive ## No occurrences of '@' after this line return(out) }) setMethod("getP","numeric",function(x){x>0}) setMethod("length","brobmat",function(x){length(getX(x))}) `as.brobmat` <- function(x){ if(is.brob(x)){ return(newbrobmat(matrix(getX(x)),matrix(getP(x)))) # n-by-1 } else if(is.numeric(x)){ x <- as.matrix(x) return(newbrobmat(log(abs(x)), c(x>=0))) } } `is.brobmat` <- function(x){is(x,"brobmat")} setAs("brobmat", "matrix", function(from){ out <- exp(getX(from)) negs <- !getP(from) out[negs] <- -out[negs] return(out) } ) `brobmat_to_brob` <- function(x){ brob(c(getX(x)),c(getP(x))) } setMethod("as.matrix",signature(x="brobmat"),function(x){as(x,"matrix")}) setGeneric("nrow") setGeneric("ncol") setMethod("nrow",signature(x="brobmat"),function(x){nrow(getX(x))}) setMethod("ncol",signature(x="brobmat"),function(x){ncol(getX(x))}) `.brobmat.print` <- function(x, digits=5){ out <- getX(x) out[] <- paste(c("-","+")[1+getP(x)],"exp(",signif(out,digits),")",sep="") noquote(out) } `print.brobmat` <- function(x, ...){ jj <- .brobmat.print(x, ...) print(jj) return(invisible(jj)) } setMethod("show", "brobmat", function(object){print.brobmat(object)}) setMethod("Math", "brobmat", function(x){ switch(.Generic, abs = brobmat(getX(x)), log = { out <- getX(x) out[!getP(x)] <- NaN out # numeric matrix }, log10 = { out <- getX(x) out[!getP(x)] <- NaN out/log(10) # numeric matrix }, log2 = { out <- getX(x) out[!getP(x)] <- NaN out/log(2) # numeric matrix }, exp =, cosh =, sinh =, acos =, acosh =, asin =, asinh =, atan =, atanh =, cos =, sin =, tan =, tanh =, trunc =, lgamma =, cumsum =, gamma =, ceiling=, floor =, stop(gettextf("Function %s not implemented on brobmat objects", dQuote(.Generic))) ) } ) setMethod("Arith",signature(e1 = "brobmat", e2="missing"), function(e1,e2){ switch(.Generic, "+" = e1, "-" = newbrobmat(getX(e1),positive=!getP(e1)), stop(gettextf("unary operator %s not implemented on brobmat objects", dQuote(.Generic))) ) } ) "brobmat.arith" <- function(e1,e2){ switch(.Generic, "+" = brobmat.add (e1, e2), "-" = brobmat.add (e1, -e2), "*" = brobmat.mult (e1, e2), "/" = brobmat.mult (e1, brobmat.inverse(e2)), "^" = brobmat.power(e1, e2), stop(gettextf("binary operator %s not implemented on Brobdingnagian numbers", dQuote(.Generic))) ) } setMethod("Arith", signature(e1 = "brobmat", e2="brob" ), brobmat.arith) setMethod("Arith", signature(e1 = "brob" , e2="brobmat"), brobmat.arith) setMethod("Arith", signature(e1 = "brobmat", e2="ANY" ), brobmat.arith) setMethod("Arith", signature(e1 = "ANY" , e2="brobmat"), brobmat.arith) setMethod("Arith", signature(e1 = "brobmat", e2="brobmat"), brobmat.arith) `getat` <- function(e1,e2=e1){ if(length(e1)>=length(e2)){ return(attributes(getX(e1))) } else { return(attributes(getX(e2))) } } `brobmat.add` <- function(e1,e2){ out <- as.brob(e1) + as.brob(e2) jj <- getX(out) attributes(jj) <- getat(e1,e2) return(newbrobmat(jj,getP(out))) } `brobmat.mult` <- function(e1,e2){ out <- as.brob(e1) * as.brob(e2) jj <- getX(out) attributes(jj) <- getat(e1,e2) return(newbrobmat(jj,getP(out))) } `brobmat.inverse` <- function(e1){ if(is.brobmat(e1)){ out <- 1/as.brob(e1) jj <- getX(out) attributes(jj) <- getat(e1) return(newbrobmat(jj,getP(out))) } else { return(1/e1) } } `brobmat.power` <- function(e1,e2){ out <- as.brob(e1) ^ as.brob(e2) jj <- getX(out) attributes(jj) <- getat(e1,e2) return(newbrobmat(jj,getP(out))) } "brobmat.equal" <- function(e1,e2){ out <- as.brob(e1) == as.brob(e2) attributes(out) <- getat(e1,e2) return(out) } "brobmat.greater" <- function(e1,e2){ out <- as.brob(e1) > as.brob(e2) attributes(out) <- getat(e1,e2) return(out) } "brobmat.compare" <- function(e1,e2){ if( (length(e1) == 0) | (length(e2)==0)) { return(logical(0)) } switch(.Generic, "==" = brobmat.equal(e1,e2), "!=" = !brobmat.equal(e1,e2), ">" = brobmat.greater(e1,e2), "<" = !brobmat.greater(e1,e2) & !brobmat.equal(e1,e2), ">=" = brobmat.greater(e1,e2) | brobmat.equal(e1,e2), "<=" = !brobmat.greater(e1,e2) | brobmat.equal(e1,e2), stop(gettextf("comparison operator %s not implemented on brobmat objects", dQuote(.Generic))) ) } setMethod("Compare", signature(e1="brobmat", e2="ANY" ), brobmat.compare) setMethod("Compare", signature(e1="ANY" , e2="brobmat"), brobmat.compare) setMethod("Compare", signature(e1="brobmat", e2="brobmat"), brobmat.compare) `brobmat_matrixprod` <- function(x,y){ stopifnot(ncol(x)==nrow(y)) out <- brobmat(NA,nrow(x),ncol(y)) for(i in seq_len(nrow(x))){ for(j in seq_len(ncol(y))){ out[i,j] <- sum(x[i,,drop=TRUE]*y[,j,drop=TRUE]) } # j loop closes } # i loop closes if(!is.null(rownames(x))){rownames(out) <- rownames(x)} if(!is.null(colnames(x))){colnames(out) <- colnames(y)} return(out) } setMethod("%*%", signature(x="brobmat", y="ANY" ), brobmat_matrixprod) setMethod("%*%", signature(x="ANY" , y="brobmat"), brobmat_matrixprod) setMethod("%*%", signature(x="brobmat", y="brobmat"), brobmat_matrixprod) setGeneric("as.vector") setMethod("as.vector", signature(x="brobmat"), function(x){as.brob(x)}) setMethod("as.vector", signature(x="brob"), function(x){x}) setGeneric("rownames") setMethod("rownames", signature(x="brobmat"), function(x){rownames(getX(x))}) setGeneric("colnames") setMethod("colnames", signature(x="brobmat"), function(x){colnames(getX(x))}) setGeneric("dimnames") setMethod("dimnames", signature(x="brobmat"), function(x){dimnames(getX(x))}) setGeneric("rownames<-") setMethod("rownames<-", signature(x="brobmat"), function(x,value){ jj <- getX(x) rownames(jj) <- value return(brobmat(jj,getP(x))) } ) setGeneric("colnames<-") setMethod("colnames<-", signature(x="brobmat"), function(x,value){ jj <- getX(x) colnames(jj) <- value return(brobmat(jj,getP(x))) } ) setGeneric("dimnames<-") setMethod("dimnames<-", signature(x="brobmat"), function(x,value){ jj <- getX(x) dimnames(jj) <- value return(brobmat(jj,getP(x))) } ) setGeneric("diag", function(x, ...){standardGeneric("diag")}) setMethod("diag", signature(x="brobmat"),function(x,...){brob(diag(getX(x)),diag(getP(x)))}) setMethod("diag", signature(x="ANY"), function(x,...){base::diag(x)}) setGeneric("t", function(x, ...) standardGeneric("t")) setMethod("t", signature(x="brobmat"),function(x,...){brob(t(getX(x)),t(getP(x)))}) setMethod("t", signature(x="ANY"),function(x,...){base::t(x)}) Brobdingnag/R/brob.R0000644000176200001440000002570414207324123013744 0ustar liggesusers ".Brob.valid" <- function(object){ len <- length(object@positive) if(len != length(object@x)){ return("length mismatch") } else { return(TRUE) } } setValidity("brob", .Brob.valid) "brob" <- function(x=double(),positive){ if(missing(positive)){ positive <- rep(TRUE,length(x)) } if(length(positive)==1){ positive <- rep(positive,length(x)) } new("brob",x=as.numeric(x),positive=positive) } "is.brob" <- function(x){is(x,"brob")} "is.glub" <- function(x){is(x,"glub")} "as.brob" <- function(x){ if(is.brob(x)){ return(x) } else if(is.complex(x)) { warning("imaginary parts discarded") return(Recall(Re(x))) } else if(is.glub(x)){ warning("imaginary parts discarded") return(Re(x)) } else if(is.brobmat(x)){ return(brobmat_to_brob(x)) } else { return(brob(log(abs(c(x))), c(x)>=0)) } } setAs("brob", "numeric", function(from){ out <- exp(from@x) out[!from@positive] <- -out[!from@positive] return(out) } ) setMethod("as.numeric",signature(x="brob"),function(x){as(x,"numeric")}) setAs("brob", "complex", function(from){ return(as.numeric(from)+ 0i) } ) setMethod("as.complex",signature(x="brob"),function(x){as(x,"complex")}) ".Brob.print" <- function(x, digits=5){ noquote( paste(c("-","+")[1+x@positive],"exp(",signif(x@x,digits),")",sep="")) } "print.brob" <- function(x, ...){ jj <- .Brob.print(x, ...) print(jj) return(invisible(jj)) } setMethod("show", "brob", function(object){print.brob(object)}) setGeneric("getX",function(x){standardGeneric("getX")}) setGeneric("getP",function(x){standardGeneric("getP")}) setMethod("getX","brob",function(x){x@x}) setMethod("getP","brob",function(x){x@positive}) setMethod("length","brob",function(x){length(x@x)}) setMethod("is.infinite","brob",function(x){x@x == +Inf}) setMethod("is.finite" ,"brob",function(x){x@x != +Inf}) setGeneric("sign<-",function(x,value){standardGeneric("sign<-")}) setMethod("sign<-","brob",function(x,value){ brob(x@x,value) } ) setMethod("[", "brob", function(x, i, j, drop){ if(!missing(j)){ warning("second argument to extractor function ignored") } brob(x@x[i], x@positive[i]) } ) setReplaceMethod("[",signature(x="brob"), function(x,i,j,value){ jj.x <- x@x jj.pos <- x@positive if(is.brob(value)){ jj.x[i] <- value@x jj.pos[i] <- value@positive return(brob(x=jj.x,positive=jj.pos)) } else { x[i] <- as.brob(value) return(x) } } ) setGeneric(".cPair", function(x,y){standardGeneric(".cPair")}) setMethod(".cPair", c("brob", "brob"), function(x,y){.Brob.cPair(x,y)}) setMethod(".cPair", c("brob", "ANY"), function(x,y){.Brob.cPair(x,as.brob(y))}) setMethod(".cPair", c("ANY", "brob"), function(x,y){.Brob.cPair(as.brob(x),y)}) setMethod(".cPair", c("ANY", "ANY"), function(x,y){c(x,y)}) "cbrob" <- function(x, ...) { if(nargs()<3) .cPair(x,...) else .cPair(x, Recall(...)) } ".Brob.cPair" <- function(x,y){ x <- as.brob(x) y <- as.brob(y) brob(c(x@x,y@x),c(x@positive,y@positive)) } setGeneric("log") setMethod("sqrt","brob", function(x){ brob(ifelse(x@positive,x@x/2, NaN),TRUE) } ) setMethod("Math", "brob", function(x){ switch(.Generic, abs = brob(x@x), log = { out <- x@x out[!x@positive] <- NaN out }, log10 = { out <- x@x/log(10) out[!x@positive] <- NaN out }, log2 = { out <- x@x/log(2) out[!x@positive] <- NaN out }, exp = brob(x), cosh = {(brob(x) + brob(-x))/2}, sinh = {(brob(x) - brob(-x))/2}, acos =, acosh =, asin =, asinh =, atan =, atanh =, cos =, sin =, tan =, tanh =, trunc = callGeneric(as.numeric(x)), lgamma =, cumsum =, gamma =, ceiling=, floor = as.brob(callGeneric(as.numeric(x))), stop(gettextf("Function %s not implemented on Brobdingnagian numbers", dQuote(.Generic))) ) } ) ".Brob.negative" <- function(e1){ brob(e1@x,!e1@positive) } ".Brob.ds" <- function(e1,e2){ # "ds" == "different signs" xor(e1@positive,e2@positive) } ".Brob.add" <- function(e1,e2){ e1 <- as.brob(e1) e2 <- as.brob(e2) jj <- rbind(e1@x,e2@x) x1 <- jj[1,] x2 <- jj[2,] out.x <- double(length(x1)) jj <- rbind(e1@positive,e2@positive) p1 <- jj[1,] p2 <- jj[2,] out.pos <- p1 ds <- .Brob.ds(e1,e2) ss <- !ds #ss == "Same Sign" out.x[ss] <- pmax(x1[ss],x2[ss]) + log1p(+exp(-abs(x1[ss]-x2[ss]))) out.x[ds] <- pmax(x1[ds],x2[ds]) + log1p(-exp(-abs(x1[ds]-x2[ds]))) # Now special dispensation for 0+0: out.x[ (x1 == -Inf) & (x2 == -Inf)] <- -Inf out.pos <- p1 out.pos[ds] <- xor((x1[ds] > x2[ds]) , (!p1[ds]) ) return(brob(out.x,out.pos)) } ".Brob.mult" <- function(e1,e2){ e1 <- as.brob(e1) e2 <- as.brob(e2) return(brob(e1@x + e2@x, !.Brob.ds(e1,e2))) } ".Brob.power"<- function(e1,e2){ stopifnot(is.brob(e1) | is.brob(e2)) if(is.brob(e2)){ # e2 a brob => answer a brob (ignore signs) return(brob(log(e1) * brob(e2@x), TRUE)) } else { #e2 a non-brob (try to account for signs) s <- as.integer(2*e1@positive-1) #s = +/-1 return(brob(e1@x*as.brob(e2), (s^as.numeric(e2))>0)) } } ".Brob.inverse" <- function(b){brob(-b@x,b@positive)} setMethod("Arith",signature(e1 = "brob", e2="missing"), function(e1,e2){ switch(.Generic, "+" = e1, "-" = .Brob.negative(e1), stop(gettextf("unary operator %s not implemented on Brobdingnagian numbers", dQuote(.Generic))) ) } ) ".Brob.arith" <- function(e1,e2){ switch(.Generic, "+" = .Brob.add (e1, e2), "-" = .Brob.add (e1, .Brob.negative(as.brob(e2))), "*" = .Brob.mult (e1, e2), "/" = .Brob.mult (e1, .Brob.inverse(as.brob(e2))), "^" = .Brob.power(e1, e2), stop(gettextf("binary operator %s not implemented on Brobdingnagian numbers", dQuote(.Generic))) ) } setMethod("Arith", signature(e1 = "brob", e2="ANY"), .Brob.arith) setMethod("Arith", signature(e1 = "ANY", e2="brob"), .Brob.arith) setMethod("Arith", signature(e1 = "brob", e2="brob"), .Brob.arith) ".Brob.equal" <- function(e1,e2){ (e1@x==e2@x) & (e1@positive==e2@positive) } ".Brob.greater" <- function(e1,e2){ jj.x <- rbind(e1@x,e2@x) jj.p <- rbind(e1@positive,e2@positive) ds <- .Brob.ds(e1,e2) ss <- !ds #ss == "Same Sign" greater <- logical(length(ss)) greater[ds] <- jj.p[1,ds] greater[ss] <- jj.p[1,ss] & (jj.x[1,ss] > jj.x[2,ss]) return(greater) } ".Brob.compare" <- function(e1,e2){ if( (length(e1) == 0) | (length(e2)==0)) { return(logical(0)) } e1 <- as.brob(e1) e2 <- as.brob(e2) switch(.Generic, "==" = .Brob.equal(e1,e2), "!=" = !.Brob.equal(e1,e2), ">" = .Brob.greater(e1,e2), "<" = !.Brob.greater(e1,e2) & !.Brob.equal(e1,e2), ">=" = .Brob.greater(e1,e2) | .Brob.equal(e1,e2), "<=" = !.Brob.greater(e1,e2) | .Brob.equal(e1,e2), stop(gettextf("comparison operator %s not implemented on Brobdingnagian numbers", dQuote(.Generic))) ) } setMethod("Compare", signature(e1="brob", e2="ANY" ), .Brob.compare) setMethod("Compare", signature(e1="ANY" , e2="brob"), .Brob.compare) setMethod("Compare", signature(e1="brob", e2="brob"), .Brob.compare) ".Brob.logic" <- function(e1,e2){ stop("No logic currently implemented for Brobdingnagian numbers") } setMethod("Logic",signature(e1="swift",e2="ANY"), .Brob.logic) setMethod("Logic",signature(e1="ANY",e2="swift"), .Brob.logic) setMethod("Logic",signature(e1="swift",e2="swift"), .Brob.logic) if(!isGeneric("max")){ setGeneric("max", function(x, ..., na.rm = FALSE) { standardGeneric("max") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::max(x, ..., na.rm = na.rm) }, group = "Summary") } if(!isGeneric("min")){ setGeneric("min", function(x, ..., na.rm = FALSE) { standardGeneric("min") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::min(x, ..., na.rm = na.rm) }, group = "Summary") } if(!isGeneric("range")){ setGeneric("range", function(x, ..., na.rm = FALSE) { standardGeneric("range") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::range(x, ..., na.rm = na.rm) }, group = "Summary") } if(!isGeneric("prod")){ setGeneric("prod", function(x, ..., na.rm = FALSE) { standardGeneric("prod") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::prod(x, ..., na.rm = na.rm) }, group = "Summary") } if(!isGeneric("sum")){ setGeneric("sum", function(x, ..., na.rm = FALSE) { standardGeneric("sum") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::sum(x, ..., na.rm = na.rm) }, group = "Summary") } ".Brob.max" <- function(x, ..., na.rm=FALSE){ p <- x@positive val <- x@x if(any(p)){ return(brob(max(val[p]))) } else { # all negative return(brob(min(val),FALSE)) } } ".Brob.prod" <- function(x){ p <- x@positive val <- x@x return(brob(sum(val),(sum(!p)%%2)==0)) } ".Brob.sum" <- function(x){ .Brob.sum.allpositive( x[x>0]) - .Brob.sum.allpositive(-x[x<0]) } ".Brob.sum.allpositive" <- function(x){ if(length(x)<1){return(as.brob(0))} val <- x@x p <- x@positive mv <- max(val) return(brob(mv + log1p(sum(exp(val[-which.max(val)]-mv))),TRUE)) } setMethod("Summary", "brob", function(x, ..., na.rm=FALSE){ switch(.Generic, max = .Brob.max( x, ..., na.rm=na.rm), min = -.Brob.max(-x, ..., na.rm=na.rm), range = cbrob(min(x,na.rm=na.rm),max(x,na.rm=na.rm)), prod = .Brob.prod(x), sum = .Brob.sum(x), stop(gettextf("Function %s not implemented on Brobdingnagian numbers", dQuote(.Generic))) ) } ) setMethod("plot",signature(x="brob",y="missing"),function(x, ...){plot.default(as.numeric(x), ...)}) setMethod("plot",signature(x="brob",y="ANY" ),function(x, y, ...){plot.default(as.numeric(x), as.numeric(y), ...)}) setMethod("plot",signature(x="ANY" ,y="brob"),function(x, y, ...){plot.default(as.numeric(x), as.numeric(y), ...)}) Brobdingnag/R/glub.R0000644000176200001440000002070214207324466013754 0ustar liggesusers ".Glub.valid" <- function(object){ if(length(object@real) == length(object@imag)){ return(TRUE) } else { return("length mismatch") } } setValidity("glub", .Glub.valid) setAs("glub", "complex", function(from){ complex(real=as.numeric(from@real), imaginary=as.numeric(from@imag)) } ) setMethod("as.complex",signature(x="glub"),function(x){as(x,"complex")}) setAs("glub", "numeric", function(from){ warning("imaginary parts discarded in coercion; use as.complex() to retain them") as.numeric(Re(from)) } ) setMethod("as.numeric",signature(x="glub"),function(x){as(x,"numeric")}) setMethod("is.infinite",signature(x="glub"),function(x){is.infinite(Re(x)) | is.infinite(Im(x))}) setMethod("is.finite",signature(x="glub"),function(x){is.finite(Re(x)) & is.finite(Im(x))}) "glub" <- function(real=double(), imag=double()){ if(missing(imag)){ imag <- 0 } real <- as.brob(real) imag <- as.brob(imag) jj.x <- cbind(real@x,imag@x) jj.p <- cbind(real@positive,imag@positive) new("glub", real = brob(jj.x[,1],jj.p[,1]), imag = brob(jj.x[,2],jj.p[,2]) ) } setMethod("Re","glub",function(z){z@real}) setMethod("Im","glub",function(z){z@imag}) setMethod("length","glub",function(x){length(Re(x))}) setMethod("Mod", "glub", function(z){sqrt(Re(z)*Re(z) + Im(z)*Im(z))}) ".Brob.arg" <- function(z){ atan2(as.numeric(Im(z)),as.numeric(Re(z))) } ".Glub.complex" <- function(z){ switch(.Generic, Arg = .Brob.arg(z), Conj = glub(Re(z),-Im(z)), stop(gettextf("Complex operator %s not implemented on glub numbers", dQuote(.Generic))) ) } setMethod("Complex","glub", .Glub.complex) setGeneric("Re<-",function(z,value){standardGeneric("Re<-")}) setGeneric("Im<-",function(z,value){standardGeneric("Im<-")}) setMethod("Re<-","glub",function(z,value){ return(glub(real=value, imag=Im(z))) } ) setMethod("Im<-","glub",function(z,value){ z <- as.glub(z) return(glub(real=z@real, imag=value)) } ) setMethod("Im<-","brob",function(z,value){ return(glub(real=z, imag=value)) } ) "as.glub" <- function(x){ if(is.glub(x)){ return(x) } else if (is.brob(x)) { return(glub(real=as.brob(x),imag=as.brob(0))) } else { return(glub(real=as.brob(Re(x)),imag=as.brob(Im(x)))) } } setMethod("[", "glub", function(x, i, j, drop){ if(!missing(j)){warning("second argument (j) ignored")} glub(x@real[i], x@imag[i]) } ) setReplaceMethod("[",signature(x="glub"), function(x,i,j,value){ if(!missing(j)){warning("second argument (j) ignored")} value <- as.glub(value) x@real[i] <- Re(value) x@imag[i] <- Im(value) return(x) } ) setMethod(".cPair", c("glub", "glub"), function(x,y).Glub.cPair(x,y)) setMethod(".cPair", c("glub", "ANY"), function(x,y).Glub.cPair(x,as.glub(y))) setMethod(".cPair", c("ANY", "glub"), function(x,y).Glub.cPair(as.glub(x),y)) setMethod(".cPair", c("complex", "brob"), function(x,y).Glub.cPair(as.glub(x),y)) setMethod(".cPair", c("brob", "complex"), function(x,y).Glub.cPair(as.glub(x),y)) setMethod(".cPair", c("glub", "brob"), function(x,y).Glub.cPair(as.glub(x),y)) setMethod(".cPair", c("brob", "glub"), function(x,y).Glub.cPair(as.glub(x),y)) ".Glub.cPair" <- function(x,y){ x <- as.glub(x) y <- as.glub(y) return(glub(.Brob.cPair(Re(x),Re(y)), .Brob.cPair(Im(x),Im(y)))) } "print.glub" <- function(x,...){ real <- .Brob.print(Re(x),...) imag <- .Brob.print(Im(x),...) jj <- noquote(paste(real,imag,"i ",sep="")) print(jj) } setMethod("show", "glub", function(object){print.glub(object)}) setMethod("Math", "glub", function(x){ switch(.Generic, abs = Mod(x), log = { glub(log(Mod(x)),Arg(x)) }, log10 = { glub(log10(Mod(x)),Arg(x)/log(10)) }, log2 = { glub(log2 (Mod(x)),Arg(x)/log( 2)) }, exp = { exp(Re(x))*exp(1i*as.numeric(Im(x)))}, sqrt = { exp(log(x)/2)}, cosh = { (exp(x)+exp(-x))/2}, sinh = { (exp(x)-exp(-x))/2}, tanh = { (exp(x)-exp(-x))/(exp(x)+exp(-x))}, cos = { (exp(1i*x)+exp(-1i*x))/(2 )}, sin = { (exp(1i*x)-exp(-1i*x))/(2i)}, tan = { (exp(1i*x)-exp(-1i*x))/(exp(1i*x)+exp(-1i*x))}, acos = { -1i*log( x + 1i*sqrt( 1-x*x)) }, acosh = { log( x + sqrt(-1+x*x)) }, asin = { -1i*log(1i*x + sqrt( 1-x*x)) }, asinh = { log( x + sqrt( 1+x*x)) }, atan = { 0.5i*log((1i+x)/(1i-x)) }, atanh = { 0.5 *log((1 +x)/(1 -x)) }, trunc = callGeneric(as.complex(x)), lgamma =, cumsum =, gamma =, ceiling=, floor = as.glub(callGeneric(as.complex(x))), stop(gettextf("function %s not implemented on glub numbers", dQuote(.Generic))) ) } ) ".Glub.negative" <- function(e1){ glub(-Re(e1),-Im(e1)) } ".Glub.add" <- function(e1,e2){ e1 <- as.glub(e1) e2 <- as.glub(e2) glub(Re(e1)+Re(e2),Im(e1)+Im(e2)) } ".Glub.mult" <- function(e1,e2){ e1 <- as.glub(e1) e2 <- as.glub(e2) glub(Re(e1)*Re(e2)-Im(e1)*Im(e2), Re(e1)*Im(e2)+Im(e1)*Re(e2)) } ".Glub.power" <- function(e1,e2){ exp(e2*log(e1)) } ".Glub.inverse" <- function(e1){ jj <- Re(e1)*Re(e1) + Im(e1)*Im(e1) glub(Re(e1)/jj, -Im(e1)/jj) } ".Glub.arith" <- function(e1,e2){ switch(.Generic, "+" = .Glub.add (e1, e2), "-" = .Glub.add (e1, .Glub.negative(e2)), "*" = .Glub.mult (e1, e2), "/" = .Glub.mult (e1, .Glub.inverse(e2)), "^" = .Glub.power(e1, e2), stop(gettextf("binary operator %s not implemented on glub numbers", dQuote(.Generic))) ) } setMethod("Arith",signature(e1 = "glub", e2="missing"), function(e1,e2){ switch(.Generic, "+" = e1, "-" = .Glub.negative(e1), stop(gettextf("unary operator %s not implemented on glub objects", dQuote(.Generic))) ) } ) setMethod("Arith",signature(e1 = "glub", e2="glub"), .Glub.arith) setMethod("Arith",signature(e1 = "glub", e2="ANY" ), .Glub.arith) setMethod("Arith",signature(e1 = "ANY" , e2="glub"), .Glub.arith) setMethod("Arith",signature(e1= "brob" , e2="complex"), .Glub.arith) setMethod("Arith",signature(e1= "complex", e2="brob" ), .Glub.arith) setMethod("Arith",signature(e1= "glub" , e2="complex"), .Glub.arith) setMethod("Arith",signature(e1= "complex", e2="glub" ), .Glub.arith) setMethod("Arith",signature(e1= "glub", e2="brob"), .Glub.arith) setMethod("Arith",signature(e1= "brob", e2="glub"), .Glub.arith) ".Glub.equal" <- function(e1,e2){ (Re(e1) == Re(e2)) & ( Im(e1) == Im(e2)) } ".Glub.compare" <- function(e1,e2){ e1 <- as.glub(e1) e2 <- as.glub(e2) switch(.Generic, "==" = .Glub.equal(e1,e2), "!=" = !.Glub.equal(e1,e2), stop(gettextf("comparison operator %s not implemented on glub numbers", dQuote(.Generic))) ) } setMethod("Compare", signature(e1="glub",e2="glub"), .Glub.compare) setMethod("Compare", signature(e1="glub",e2="ANY" ), .Glub.compare) setMethod("Compare", signature(e1="ANY", e2="glub"), .Glub.compare) setMethod("Compare", signature(e1="brob", e2="glub"), .Glub.compare) setMethod("Compare", signature(e1="glub", e2="brob"), .Glub.compare) ".Glub.prod" <- function(z){ out <- as.glub(1) for(i in 1:length(z)){ out <- out * z[i] } return(out) } ".Glub.sum" <- function(x){ glub(sum(Re(x)),sum(Im(x))) } setMethod("Summary", "glub", function(x, ..., na.rm=FALSE){ switch(.Generic, prod = .Glub.prod(x), sum = .Glub.sum(x), stop(gettextf("function %s not implemented on glub numbers", dQuote(.Generic))) ) } ) setMethod("plot",signature(x="glub",y="missing"),function(x, ...){plot.default(as.complex(x), ...)}) setMethod("plot",signature(x="glub",y="ANY" ),function(x, y, ...){plot.default(as.complex(x), as.complex(y), ...)}) setMethod("plot",signature(x="ANY" ,y="glub"),function(x, y, ...){plot.default(as.complex(x), as.complex(y), ...)}) Brobdingnag/R/extract.R0000644000176200001440000000431013762776702014503 0ustar liggesusers ## "x[]": setMethod("[", signature(x = "brobmat", i = "missing", j = "missing", drop = "ANY"), function(x, i, j, ..., drop){ return(x) } ) ## select rows, x[i,]: setMethod("[", signature(x = "brobmat", i = "index", j = "missing", drop = "ANY"), function(x,i,j, ..., drop) { if(missing(drop)){drop <- TRUE} xv <- getX(x)[i,,drop=drop] if(drop & (!is.matrix(xv))){ return(brob(xv,getP(x)[i,])) } else { return(newbrobmat(xv, getP(x)[i,,drop=FALSE])) } } ) ## select columns, x[,j]: setMethod("[", signature(x = "brobmat", i = "missing", j = "index", drop = "ANY"), function(x,i,j, ..., drop) { if(missing(drop)){drop <- TRUE} xv <- getX(x)[,j,drop=drop] if(drop & (!is.matrix(xv))){ return(brob(xv,getP(x)[,j])) } else { return(newbrobmat(xv, getP(x)[,j,drop=FALSE])) } } ) ## matrix indexing setMethod("[", signature(x = "brobmat", i = "matrix", j = "missing", drop = "ANY"), function(x,i,j, ..., drop) { xv <- getX(x)[i] return(brobmat(getX(x)[i], getP(x)[i])) } ) ## select both rows *and* columns setMethod("[", signature(x = "brobmat", i = "index", j = "index", drop = "ANY"), function(x,i,j, ..., drop) { if(missing(drop)){drop <- TRUE} xv <- getX(x)[i,j,drop=drop] if(drop & (!is.matrix(xv))){ return(brob(xv,getP(x)[i,j])) } else { return(newbrobmat(xv, getP(x)[i,j,drop=FALSE])) } } ) ## bail out if any of (i,j,drop) is "non-sense" setMethod("[", signature(x = "brobmat", i = "ANY", j = "ANY", drop = "ANY"), function(x,i,j, ..., drop){ stop("invalid or not-yet-implemented brobmat subsetting") } ) Brobdingnag/R/replace.R0000644000176200001440000000516613762776702014456 0ustar liggesusers## x[] <- value setReplaceMethod("[", signature(x = "brobmat", i = "missing", j = "missing", value = "ANY"), function (x, i, j, ..., value){ value <- as.brob(value) jj.x <- getX(x) jj.pos <- getP(x) jj.x[] <- getX(value) # matrix or vector jj.pos[] <- getP(value) return(newbrobmat(x=jj.x,positive=jj.pos)) } ) ## x[i,] <- value setReplaceMethod("[", signature(x = "brobmat", i = "index", j = "missing", value = "ANY"), function (x, i, j, ..., value){ value <- as.brob(value) jj.x <- getX(x) jj.pos <- getP(x) jj.x[i,] <- getX(value) # matrix or vector jj.pos[i,] <- getP(value) return(newbrobmat(x=jj.x,positive=jj.pos)) } ) ## x[,j] <- value setReplaceMethod("[", signature(x = "brobmat", i = "missing", j = "index", value = "ANY"), function (x, i, j, ..., value){ value <- as.brob(value) jj.x <- getX(x) jj.pos <- getP(x) jj.x[,j] <- getX(value) # matrix or vector jj.pos[,j] <- getP(value) return(newbrobmat(x=jj.x,positive=jj.pos)) } ) ## x[cbind(1:3,2:4)] <- value setReplaceMethod("[", signature(x = "brobmat", i = "matrix", j = "missing", value = "ANY"), function (x, i, j, ..., value){ value <- as.brob(value) jj.x <- getX(x) jj.pos <- getP(x) jj.x[i] <- getX(value) # matrix or vector jj.pos[i] <- getP(value) return(newbrobmat(x=jj.x,positive=jj.pos)) } ) ## x[i,j] <- value setReplaceMethod("[", signature(x = "brobmat", i = "index", j = "index", value = "ANY"), function (x, i, j, ..., value){ value <- as.brob(value) jj.x <- getX(x) jj.pos <- getP(x) jj.x[i,j] <- getX(value) # matrix or vector jj.pos[i,j] <- getP(value) return(newbrobmat(x=jj.x,positive=jj.pos)) } ) Brobdingnag/MD50000644000176200001440000000467514323753132013015 0ustar liggesusers299e3b7bf0ebec2a9764e109049d8be6 *DESCRIPTION 3266087168f5edb40d5e055bde20de61 *NAMESPACE 08d41e9ee1bde3c883df2efacbaf6e7e *R/aaa_allclasses.R 030838f02cd5b65357b740fe046e8bfc *R/brob.R 145939bb79e6c45436aa97a24212c79b *R/extract.R f4f808f9e9e147620c69e5ee8520d6fb *R/glub.R af8a9c578897fab5101a10835111bbbc *R/matrix.R 1bd953f4ebc0a611cab32113d3ddcb20 *R/replace.R fce5390eea91004c9afad9891e8c1353 *README.md c6a7c5451929d72f8c0d483de0abb624 *build/partial.rdb 647944a3ce961724698623792b04aa94 *build/vignette.rds 5f9c8a3521284acab0ed92e3cf7dfb20 *inst/CITATION 426c73ab618aedf0c74bae824bb614fe *inst/doc/Brobdingnag.R 81ba84ba4278c35d8b2b4256663aa3bd *inst/doc/Brobdingnag.Rnw ec5652b30a491c6901286d403d467b24 *inst/doc/Brobdingnag.pdf a04f6dc95e6970446ab875b10d25afc2 *inst/doc/S4_brob.R bf548afa5ac3694246cd3b92365cafaa *inst/doc/S4_brob.Rnw bb4fc0ff0f347372605ba0bfbba2ddef *inst/doc/S4_brob.pdf 0d2def0996a161ecbc9a96ca9cd090d5 *man/Arith.Rd 85243eea5c0b8e74b1595f231bc62849 *man/Brobdingnag-package.Rd 302f297f098a7bbbddecc887df17de75 *man/Compare.Rd 7ca6539ccaee5c5094b0e6d20b09786c *man/Complex.Rd 7d23bf124cd0aab34a25235244890b15 *man/Extract.Rd 89303f2a4b86ddccd5d2932fa1750816 *man/Logic.Rd 0d7d612faf4826b5b6c0945ba2ae305f *man/Math.Rd e787c21aeaeab370f76de321b1067fcf *man/Print.Rd 99e360c829510efe42b9715461235d35 *man/Summary.Rd 5009aaafb2e2906b3abb375582e48aa7 *man/as.numeric.Rd eff4e4d01ab9ddc1470197bf4a5bdb93 *man/brob-class.Rd 729c51856bf6ec30a84578109b732e3a *man/brob.Rd 39b6473e2d9fd1ce3af16b0600a5eda1 *man/brobmat-arith.Rd 5b08389f2638d8790b8ad50ba8e5894d *man/brobmat-class.Rd 7ab6fa254d90051ab2ba88fc0189a9f2 *man/brobmat.Rd aace3e63f8fbafd066356d5d14c2db3a *man/cbrob.Rd 8c5cabb210b66b4bfa021b558ee2bfc8 *man/figures/Brobdingnag.png 8a9c550cd6383e2fbe98c93122914f93 *man/getP.Rd 5a19831a55dc9eff9431fdd669ab500e *man/glub-class.Rd ad5494dd3a2c6a36b0c5a6d20f10aac4 *man/glub.Rd f13a73382f54d0518ee34f22d8606464 *man/index-class.Rd b5ea9051be1307aa715e50609dbc7e6f *man/infinite.Rd ea082304393290114fa77c7628715b1a *man/length.Rd 415843ee2c300b95e4b6462fd91684f8 *man/plot.Rd fc63023acdb227d91b55ad8fe4c31737 *man/swift-class.Rd 50094a0d3a95f0db524eadde492d6b26 *tests/testthat.R 17eefbc8e9e2ab565f8141d7700a68af *tests/testthat/test_aaa.R 81ba84ba4278c35d8b2b4256663aa3bd *vignettes/Brobdingnag.Rnw bf548afa5ac3694246cd3b92365cafaa *vignettes/S4_brob.Rnw 0e333c0d53899270ebf825c2d05b8f6a *vignettes/brob.bib 428a8158d30bad682c9cea7eedab404e *vignettes/brobmat.Rmd Brobdingnag/inst/0000755000176200001440000000000014323731146013447 5ustar liggesusersBrobdingnag/inst/doc/0000755000176200001440000000000014323731145014213 5ustar liggesusersBrobdingnag/inst/doc/Brobdingnag.R0000644000176200001440000000341014323731142016545 0ustar liggesusers### R code from vignette source 'Brobdingnag.Rnw' ################################################### ### code chunk number 1: googol_definition ################################################### ################################################### ### code chunk number 2: Brobdingnag.Rnw:76-77 ################################################### require(Brobdingnag) ################################################### ### code chunk number 3: Brobdingnag.Rnw:78-79 ################################################### googol <- as.brob(10)^100 ################################################### ### code chunk number 4: define_f ################################################### stirling <- function(n){n^n*exp(-n)*sqrt(2*pi*n)} ################################################### ### code chunk number 5: f_of_a_googol ################################################### stirling(googol) ################################################### ### code chunk number 6: TwoToTheGoogolth ################################################### 2^(1/googol) ################################################### ### code chunk number 7: define_function_f ################################################### f <- function(x){as.numeric( (pi*x -3*x -(pi-3)*x)/x)} ################################################### ### code chunk number 8: try.f.with.one.seventh ################################################### f(1/7) f(as.brob(1/7)) ################################################### ### code chunk number 9: try.f.with.a.googol ################################################### f(1e100) f(as.brob(1e100)) ################################################### ### code chunk number 10: try_f_with_bignumbers ################################################### f(as.brob(10)^1000) Brobdingnag/inst/doc/S4_brob.pdf0000644000176200001440000041153314323731146016210 0ustar liggesusers%PDF-1.5 % 1 0 obj << /Type /ObjStm /Length 4367 /Filter /FlateDecode /N 73 /First 605 >> stream xks6 |k:ět2GbW؝~%f#D5-Ѷz7 M pA!(ED(!,! ,"aHE`P3B ./ Zk"avE x3pa` b /pi$e )K`}&da).dBݘ $.\V Kc" ,*$-gJ$@VH $梑LIa`I A#u8,̑؁ (р&l";,6\ փ y _~!4FQ6"h@~Xfd/llt cB4#oX;>_n P<45#8bWŵ s 2GYGYL^ lY"Θ'&~~NFg5=9Ƿ85O+`l!z𷁶s ~?csż]wO&d9rp.x]BぷK>葡omF47]@RZdfp¶W "@ODxbL#z3qrw@Wt=CzD =szA?c:NNhL-zKooj[`CzG)x$& :3ж4)}$Lxr3Ʒ٪1`tAb|qL)]ҿW~Vaٽ`27P^3?N]2:Ez?z;d3+w, e;YpKАj0[NAPJ44S$8x"(=B䃛aK%DL gCX'wUHج3اH;.@rxh᰷t+-^ݷ6wEʟ|%Clȧʧj}wK^~WVZo8_;b:GF}-v v(C%=Oa OZ&ܩ*UΡB{i/~Dw' !T{nnVҏ[-^=}=஖Ҳ=ΧdۉN'4 er@ZVn&_d:w\*Ey)uO=ES"Q]H;E=G~5J&o7S/QōY0TSb<\1vYeM5e 1QT^{|`zo :. Z,d\˾vo ЏPKoSm~Ɲir| ˠh y+O7pw`4l"DGʣ_nc5ӟﻞ6W!N [=2C{Ʀ݁XqaPq!Og(rHL76F=bYL fڰuSs%!b -d?)^mBN5b6;LvGVe G>mS3@׫K[6uZ)ٵ= m HI<-=`'Sdͦ*10X.@*: $(X1? "ű犖'Φ|9W2~-d>/ӶﯽOGἦ  [sRKy[Q|7:/~d:@;|=hRUH7PyhԽjEviLՄ0@-nh']]Gd-WwM3aMJ[f2HT"jgv8Uql2GܑlcLcɖݢnד7jQNo?_1&{4a7STMRCmi;WeOFˁÝxy՟80Zj n^諧LآޟǸ(wcr"Cɺ{eL/gkObN%h^6[o-n\jVDMVU]`UzŨ4%)镠3T~.̓7&ǧϿ?ܤDJT k]#ڂYb1ʦ6|=:3J܌+f|XNqGd s<$@(̘+dzcF@j.0ke}l>94>/ms!Uhх홙3 yt-3g;]h6z PvPmo0gF+[J4Yqc^]Q!"UZ]IfƆy%GoU{:-PuS;Hѕs tT|@\<&$N@.SuYfZ}c/.RiPhYVu'P͚<2Wy}AmMԙ~s{q,ϧ?/P͢eD- ϯXY0۫WפtC<*_$Vթ<ϰ&t'8+mʸ+uyJK%SpJ˔N"DsuY[**cM&o \F-z,kk"sFjք&kiبUFrM&YVOZ *38t_kTF$W6C+n/G짉_/1kIWk0Z V ?'rx czue?S7y?~ I:YuA9JVVk&`C >[D8~ ~ ~%,~4&o@J.ta*r :[ YmJxOnocC,Ǖ+H~r 'goA=ЈJ(>l+G]?Moil[ucqy蹯I ۩#[m#Ղ u:}K1U `XAaZ64ST;Ͷc.A xendstream endobj 75 0 obj << /Subtype /XML /Type /Metadata /Length 1459 >> stream GPL Ghostscript 9.55.0 S4 methods, Brobdingnag, R 2022-10-19T21:16:37+13:00 2022-10-19T21:16:37+13:00 LaTeX with hyperref Brobdingnagian numbers in S4Robin K. S. Hankin endstream endobj 76 0 obj << /Type /ObjStm /Length 2656 /Filter /FlateDecode /N 72 /First 622 >> stream xZms6~۹1N&3yOڤi4y>N RiӖ<Ycg,YKpD2E#J 848I8ך8E_ #8!+ψP\ω,F/qaH)"["Hz 1"YapZ&bXPDi̓RʂLǙ%)P9=:LjvZ@`xzJq. эRΆ:[(Hc8 F @L=b$֢^ .3037 tƷ$ZMrp p( xv3ǀ2\Z0QBb` +0Xֱk`do`X`2tG(+E@.xdMEM݄d/4yArIHt*bnjG|`LwfE,lǏD+N5S,=t{;m=_W0Cħu_L " [YAZm-IbjDzX/#6A%3ZGE)]v%#Zp$J OF%-c]4a9= j&6(KThm .OV 2V oUw>-hiXϜBl ޓ|S^g /a+"4GSd= 8"g _8y1D]im k49hƮcEl`6F@zAdLNc PTmj#a".w1ØehHx7Dߖ$hjpT tQ$k;lF#X)Z@-#`5xmd~/Z`y Hi$;E1@~8apmh{ZvGsRcay}$ǭsC"O%Y?L=zbs3DC:>p-՚pAL2* 'c9dwT/zF:+s\pZ;Y u%e;aWƁ}A t~]Pۡ0?La-\Pt4G_>tdӇc-q~P@9S}7 j%n(x1.sQ5Ѥ/料9@AvABXԁNfϏ:N  [S/ӄlqϬ:rnmNfX0Bub51=Ew=9vKoCOP˶iOYB)*WOIT+j?%1x..ӫO<@/>SxrNY9/V$T6ESΜ]LDl]\V:VnϢB'~ӫU%IzOżDkFgDg3 gKLyq~A*lcDFe|\5pe%)ê__!XTe1{:b0 *w-ZYo}| L/웯u:iHAn驩i>,GA0Qooԏ[xM, Yʳu6|mʪoeu@:a;4]0H~*-T:Fb1fVԒZTH\4' { `wǫƩhèqI԰3Y(P 5 $TW& 쯤Lkzf!2(;HHvxJ%427 ne .2}aIՖz^\WNi ^S,S~A+ǤCxކ4 :ζRLKeAҙ(N^&]-8_m@+xXGlpij;t%\!Pr G!_L}\\L%pHZb$-ٱunC|Ҽ|ͬtJҕjU$ȾdBU]ZE9Dvզ.L넇2]]^J^ wZ{KFSROSgQFQm1IF Ks)]d (\VuE*wfJOQ-ul,Q)5ݙ9ќTIyxʽRcil ޕli;\[g!-M*(Crd18NM 7g.x768#G;N u$D0BdRCP6Dl7U$ixY{$ pJ?&orV媮ᢪ.ʲo߾Q,˓KNycrxKۛ x@pZ $z1GɺaeAyg\~„rT0(c[z}`So8&TBj,%Є]=:C9nK{#nwf~Te?<33;3=3Q1 "5 ?&OEʖew;ǒbh-\9jЂcO!Qm~P+dE BQendstream endobj 149 0 obj << /Filter /FlateDecode /Length 4137 >> stream x[sܶS[qC|Sܴ&j;3ѝ(/Hd7~oUYUr;{*wyX!qW_e8LRKvo\Q Tq^Pu=  V>ex@Y*UE)4 7j}LJI%E6JbQUm*ﯮ}{E4Qzö?g"jG dH–jDa<[]vm˾+ގ?+M}X0x%f8\Ն?)v_*R{68j%;M~mJ 7\W@5lʅf[ϋ81 >~ck])'of)/=4 RŅ5`!mX_'ZoҰ@r-4 ~I+Mt[:LU!᳝ɖN{L7L M&2eTQ=VQk9C.J*#XP.ȩ `J Y`J JifRf: c=io hBEjR޴l6H>e%ػ.n̷M*uJk/&:jGz3٤}[xf^*[gqSDwc~8B'YJ`ܨB97uj`,dO R,)݉e-~*>@@kY0.z]$:+ [`K 40,ʱ҅2EخL37$΂E\t+ J,0뫤/b%F_:j*KԻ뱀gt((FRKyd)B3ORKRFFXIXC:CMrh#x=aVY*XV)8풩#yj;'I-!gj ,1Ң ؝3JX&}xx "ssnl7y1HGvw)ې'Qg8;z;L`f))Sгe~iM!*6ROؓfA*)V(:Y@T$oB3``_%,F+!r+P+Ĭ# }BҁT BolME}X}&j4y=?HĠ٥jآmTz̨C@?@ՁD/c@WawȕJ\*e@eCkX<} Qp'Hr1 Lwv~RL9g&!eYJ2Aeֆs}҇f/]Hn im!Y P^31r9>.Rc Gjм}34ӄL+y!ok% uj&{r>Y e~(@ثKʁꤣy9Y\>WWb)l1 <9ѣK |P@"A:hMZ]?] g&[}z H:ms- *rEo.{E#_N#1ʹ7cmNR8agHa>ϳiԔJ(^-ݔRc r%^{(P4Zd⟮Jyp. m۰T֫8^Yr`~K$u nON.ˮGLYu^KD`[;4+:pZtZj K0~x^A:/ 4 aNpzs2k ŁLṴ39xnLg#ztS}Z_xh7Nߜ ɟgz,>q .En6LzBǮF.c)dPI SB0=~jmtM'[,m`H_ 6jݍv$e+w1ID:i"R.1lY < -]:i47?sSMBw4:J{XQ:n }'ZNe>o[O*PeV–*>K-E׈yiY\b:Y3g4O⊐|t|ggCCbV,1~UVPL)D d;壎h_Qn~&C l'' XjS޾}r*zBhqe<*xfL;[=FOӼ$mQ\w>?BI6HS6|#a _q:4u>j*M傱{saS*`J $+|t:x(@7ؓN=xp<iCNfnOx5GO zq:&#^~$=4N!`"74l,\0R,F-Q<|5OLHp#Z=+PD)eZ< TA +1])q3No!?HM:N~3cuX dv8/xѕ. Mq&E>^I"E@f2(0ޭQ8BLE94~ۦHI=^2QIz"r^8^+ [kZ] M 0?^>a땮T$ӊ}8'̪do@FB!$lثxD(]^MzP6ܨc'{9uV* 6ho\Mtm ꣝dQ9gwS!L%taFu,UUs^M!|0| \nE觢,˓~ [N@ pDҟ?g> ,Y^43Pwg1lYH2_(LhladF@Afw)`k:^ jv0@\rm8]lxÈl¶Ϻ#!̾- w|.P"Nq% QyPԈHeE%Dd穴xfCC\QZyÏ(pMpڶBn(](ǖem<e{zfB: (h=1)ai/wȚ /%-^)nYzc;_DTzK #hsv,^|:en1}qç2endstream endobj 150 0 obj << /Filter /FlateDecode /Length 4431 >> stream x[Ko7 |q:4ߤ/ց 9Xґdy2ݶHvb h"=6 ߌ4 S#^?5 8i$ph? gxϩO`(626l=hhkPaT#Spr` ~)N2as8ʌ.4Ԏ4`M8vqO%8}Zy5'MЖIDU6k>M7yVฯn!xA~.tcGV=W,9E0!]ͷfr?r,p xyIbB""o\lhp9lV%r3% _',q=3 5%sV7;ϑBJI?sq%d[j;<"=кH3ٯ>ہ{T H@=x%-PIM|1߶E \'\f%NE+Lk8DuuMPZS+-kB,D@@S;px:X:Oįe|!&!Gx xxx"X qYf0`FϥjCPH65h իH:G2_{p$p)leU5_W)2\Ѻ O5_A\|B>!vNcެyW^‹c.*$ϐAPв͹*>玆l^^LvC|MyτLGv0#o\Wa&`QMJƕ&$  &,My""{LDmP9!URLYJpV\y&npxhxsDW;&A N`5.|iEuO&lxO ?P!:DZW(]m /AI;]p)@~Ɗ$T!0 A&} #&RU:7JC\)e=]<xjͭ`D\yt4}:L- !\|KOICs1")DK6`.Y\ٹ1͒͑#e 0(c 4V1{CYWyg'/xyd䠼ixyQez'ewz <$xPz5hmG0'!7YŹڳ98?ҭq1H# -I4iBBj5f!d FBWe=H# D/]?f 1`pm Z`&Qu/=dDpn/]x-0#]]E—0u8 pcMNng`x.=prHJ<fΆ&1GK<1!NCPF.zԱtMmDVZHy;!RY YUj [ ib'ۼݬ^?CՀq^.XQ\}<*ً~~H[j坠|F!n.v_o;wC`:kOEw~&U{W]Iryôei-lkukof^g=bcCO! ~L"28YXxL`*u>vdyXFY=x`r"/X6F%F"0@qnUvθ m^" {G$3n8F Py8TjET.IP0Fj ||FIi]_e9T`g7Ę%CMBZ%fd9jYh>mc>Ep_JEw]X'sHxM)LBYj[x6 5TTK!BJ]uH}1 _Ť f70iZ&rkv1/_}IE7=05Xq[ E# ?( !~é)0A#t6/@4GO˔r+yT%s݁W D鋖{b_nԀ!3'9\!2xlڽvy]})p,o2|^<C=hW]fR#lVǥݧ+umKL]jЙviqЉPhno@M +\6Rfِ6*&?ҁT}wޅBiCnqU3F +#;qcGp.6î e]}3U[q[x/(@p)Ub[  3/==j&$}?2ɪQW?u2>mP["},[D:lh‡ߛ׏nC.獯=GQr3bMu#ktHm.zI@7Kh\|=֩J[)LEWjm;~H3Dw`JpO7W/ cIǤtwKy d{/֘#"' ,SYY0<!6R'4 eyK7wNJͽDw!0_Řۢ!䯄-5lcT8RYgЄ:@5$hiSS8C~ zQNo(嬿K#yF Dm\W  䤜.7UeI'V`ƛQ(2ɣش罻0d: }w#i?H[$bRY7A\^]FKɥ3k>|.+l',]RRaevօo7ny^,8m3ӇWYkoi77B^ O KY69f4>o?~b3);T4'L6)9}UNN޷L]" 5'>̟UrI \;A8~ǧ\-f,9WZS-ŊFsHҞB-"$bU*4zcEJ?\,|;gغ a*?/v9 9Os Pm^`A]A~~ qi)Hr{`Tb#Ӽ{`{]pKO۱3$ }O>ZLF_sBvKKy_> stream xZKd_tI0wA@v,@ݕ49#٩vc p_}U=?./kldׇT|ytKUŵXZm+/dx\YYsZK)*ؿ+v"-=˲b\f?hoߟ P&C[9@^˵ԕ3o{Zka=./N'|?.^޿j4.++˵ +<α/ހ ּVKb|I/%=dƗ񒏗\V/ )/X;XQ|ڔ$+8E_d U-/V */ ~`]~Y(Q\v'ԀXvIڰyJ(ԕPr=|MWMƽ>={mV2Yji07JȡE[1AQt0$d]Vl4nDvӶGed'%$h/1G=xu)@p  0FR.GAj#/]) ȔX؉iWm7f7erqYr7|/O:_J3=8Re`* f" _#RBY\=t{u \Cyi򔌹dطg#߀d&S{v"~F 27K7 [Ϯ g7 -?6C+ Njtyk$|!jNP˔}?"*LM"4Py5"69h0f؁^Y6K R ƸU&R.J7P:R W[VH(ڃߍTH ;YI$/$)?Ԕy[ n N7gvCk?cibt"7 B`1++(yUB>^vvf~C޶#Hm hmōt$| >@9&ӅweΛ<!Tka=G)4 u_AS 8ܙl􄲕)S6mM\TZz3,DPenZiMwkpyA_΁~m'!pΫPNzwK/'s}^)lÓ;86Cg`Hw{3 K>J6x&!${X ړ$PU-զ6-:)3]MBvwْBjr B<uiVFa2l*=Q -O1taD Bܤms>D 3bH-PXI3#bBLcSĤ컕Wvyӭ$V4*s9dZb MzR&nMIt2/= Y$,mWeCǛ НJbd t(M]BzCy])tb^d2ԇ%J9`쥁|S[zT> aF[ 9M{L%ڪ&O6ufLͣ0ZS!D٦ g9ײ`[W!7Q4),qdsӥ1W^¶Dm*1|̞' ~qVχpAъs8%⳯q ɣWӴ6Bkv9<`ԚEf? ]P\N @Y6g"iDB7t%)ZqA%0PR`U(0% ҮK" 93b]!8NPgΏ%- e \LŷmJ>^(HfW"C'ݪ XMHJk*C:Goh%B̀fpA9 A |N(=}uyHgE$Bס rys AްU\ષƵ 趸>XCBȏiW>U!o E<'x@6{?r8_űZ ~4vCS$2IP\DJ)@yr MZV6Ezx} H%;[r#$y$O_}Bµng;]Bn^b)mzy,|4<>TzPQ@- bpqr5k)GfFt&8&@3 KY^Et9,8M]赩ڏY|X35`HUD7Tz/ i˫Er8DvLn!Xӕ LAY"%XpV߇Iumr-+W;}Uk(/8V=+}d6Y++TXK^rW!s|+'-Cy؊ڈ~f@4t}: Eި8ϰ?NC#)kvW~wlWݣ Yɵoendstream endobj 152 0 obj << /Filter /FlateDecode /Length 2875 >> stream xZKJ/'!ww ,΅M6,#dfߩnݒ<$ܓXR?W2/ >/_fe͡^j)766nVjxAbl>sM b1²i9P`"HC/<u@KQBz̋CtaK"-)}7\8L >}{:P[op c[QsS~`|%[9#[’Thz0*Ֆ=tޣ񃵥"KǓ)⃓,0(<'CE᷶TLЦ;87-t_ S# Uj3Pe0:%AFae Hz Ygv7:SM7uAi~=t;#0C 8Bȁn1 qW5Vq=V ~.$RK+(60"hpnQ+5aadurס"wHА" AjK_eeYӘ)x~Q@Y˛m ~Bu)g?ܞVr5 qR R8yT.8Oñr[|x̞F-XEͭ&1b|ʞ>02VX"4 EJ]Rp !ޏ'5Hp"27$OǬ`&J ̄F)y,{4m_MS6TW.VM\"%9?_Ǎ$ 9Ft|SuC-1eO ̝R$4֥yZnJ{@9, SXHyl&A}ZK]R׿dw'Wr b T9HaD "!s::s 1G\JNdQs*@8[ހ3'?Ka0,~ϳ}\M#@E|j,R >]S/iMM X~):R~"cTJb隀TQA9R)wl=bbI``sĠ\DC!mZH:r , &sB{H>Q۾5S6$il'7o/f?B+ZϏ[̱*г2taDhCK4D\{;شxaѻJ:(ò'&B)E֯+[fgsu"?SU iݱCXx(r 䡩yӸlPŦS["*t~v]j&vVA3jx'P5] ne:#gʈq']Bj}*hʠ lhDފϦ Sx4QGgȠC˩ee6}Wג?ـ/ikVHgPϑxOZy,zbqû 9g,Z (0!56@s<ۈ%?΢s A5$PTXz\XgiI `)J^'I]A^|GᎅQ,v_M\ Ap&MVXUX2F}Բ?P$t/8ݪ3Z6%V\%Q>WOPyDis"&cͽ#ׄ(I l&'j@2Y<8Q@~5K#t2 ^b+^❣&$z%{xuu],}yϢkzח`Kv;-œJ4dX۾خ .3M6b8[$۫W' qR˼"9:$;[-Xf 27̈́?8XkRXQ N4ƫ91xUz%ނ•GLZczͺ{0hH4<"Dp!5]N\Гvl"eDWô8U u i&R(O#IE_ ^D=;CwA.TH?@τ`Y!ZkC[Q_2d eUT0뻓b}p -f<4\rD-GSendstream endobj 153 0 obj << /Filter /FlateDecode /Length 2070 >> stream xYKsd/&"yTeSN٪lCJ( ^d=f PD f5׍q^t^wwُ3V8–w3Ιl.,qvM7˲(%YR+YaG?EQmᚖe^ToŇ*y~wCta[ַ3BrefJ:_qYp5r%,I 9on!_}S(dqd%iqMlۦN}^BNǛ}.6rNP^Ha|lvX0ro[0%X rF Vi򐄵^2SP =$R6\:?&RNk4O^<U/WLAT&2( (rOKj dܧv%3F-I6uB^ 9yb3c`KM2oCo}J'PV2eIK6w1zx.@\)"u"es* fX;I(Cn .cRb-WMڴ3^(UZzC9{QeM=DsŠ^F6XBGtGŔyE7;}RLЂijwlOUlgq5W''&xG |eV~W#rˊKb繁uCR`eɪ JNZDx) ب?O6F.SJuWΡrP] r]u[!Z4\>quDTzZI})H#}>xS x4M3b80w 'LĈ/,4@.0HB 3D@w00>~hד8sr `  @z6u1Z[*>13X ̧N-d+͍c 'GE71tB;2sNR7!:+ ̧TF&%!݃dKn]WzlѪмz2֤-KOؗvb) Gw:ayApUց2I) $V pۤ*9OD1m suCG-PU(TcsTD =3J'^pur^@#i>4jγNN*5kHv:R] 12?s4n_pҎ /A40]δ|*:zkmFll_楏FZ'Ba~c\,%EH4Wn˼~ σqL8c_6mNJ@ 0S;DЃv- J'l*J7m9b䋔/0r:%/ \JkԎ Lo`yT9yx =̋*lrv7uΥQqefXD9wiBC-l4;2HoJy,5$]>*x"&ge|e?m} ~ Y-w0ka,6\C:*>hɂc>=eP,d &.i{LiDr+mcUF1>&݀`߬g}7endstream endobj 154 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 5720 >> stream xXX֞uagDlK8 VĆ "5^ ,H=,,HAVŒ ?5\Fg#z|9=0f]Dc~XwwG|F<5XtIxiR4;;]eoLsz1RdЩa782fO#f{ SG8xq=c'ajz2),gwCÂKzM0c܅^CG|cfGM]7=8  >q#pw 7@.p堯Pb([i)S̬62 ",@ %-"YdAF3Y=U@Ky/6F(y{.Q揲G7l .`+76 {y+54up0ϑ}->Il  hBD[Ј΍FEXEc 63Yو5޲)qxO,DGqvQpP3o\㟒qAϐ;VѼxײܼRJedzW 77gr'c&VM&|*+E <]H hľ5دI|A* E7}d,̞37p_߇RfL1YbJ!\=[[ON$$fBX^w')p @8xs@Ga|]&"!el$dp1(;hڥLVwmmBܤ0Z⩷U "!lu:&8S5#gE)5(A'dDp]DKx VĻST<,{1;+$4x./q4꜖99pHn2[\k:qVGV*b )s@[&G J9 RLn`ϋdV_B=^B5#J4Qj~z$~`ʍ_[N^fo94e=q``@k1oz ?e4k{DTl)4)ԉLe^ S)8$9aBK >-8[UT:┤+& c~$۠ z3,Nk2D8,H:ֱ@kuGik~mr?#,֛4"ttشmc# )9v2G,ڠA eBtm3."/k ,}A ůveYLmfQZKu]hUM#P_({*B9샏OG/b4λ6$xSo4T@ pNPfɻd*"uAN}v(K|AYVeJ*Fxo~]Lg ) " Yֱ !y{\>)6[Ǖy9`gb! z;[qm W_j \Kj)Il6*Vj| CeEl^yEq4%Br Y}҆ }R$kʱCyBz̢ OUrHք@y@ܥOܞ R>Es{soBn k:H7!OFH򛞰<'# FpGTwpT˖ =iG,Q*U!i+׮H nig@$#^Z_ 2vNۑE(|mDfmG &%%Q"vk6 mfgYh54).retHXdSkr3FGD,oֱkM;x 3ӳ΂]!2MZh!) s5YMEuRRm2Oi@))1[ ޳>-f,$nөa;?!8z7rfNҐsΫNZ%l$C|$IhkK"LFn}rVnJVO|'6@ iT(,VܮɈ+"ޞ5]lSŤ˪a=C,(lDS!6l7,r[!+ٍ%hJCȀ'%Ŭ|K3y'KbI/@9ꕻO(h6G2zUF+3~li @f]JL"~etA:?c2*PYp}awW-t%=]\<4t~gJ&&u*.ޕ|Ӎڲȼ0X©"? fcouŐ~=xv l>'ǐWYŊ[1xr q+RxqQBMG߆$μQf@I]Ͷ0 C57a7XC874c/ (6 ͠Mִ4M>hKnv(k 60"e[rb2ud6l.XOїӲKb'@ye؝ʧdn+ĩkxQDlvbNhUtC7\(˝`er#[=jC=X;QC]Ļ͟ qM 0XKuqGfPtC) fg_k75P2eUǟ«A`Qb6x3 0Xk^\@ͣgmth65 O&x[ŷ$xE3`"ѐ8 ÀĢ5 O,s@4["hF"ԥᕛ c:Jf- K`"|ҹWZB1 j:nZ?C (Ul/dʈR"yhgѮ$9v}KL-P% /4vhps9+=\8Ԓ^ ܃)S]MQ)IQSmIv~jXgEUt.q?v(93YOdTU_S%19q;*۳k:.Y mʀe+0,S k SCCG=]=qw{|^Dq(2ε䌲G&g#R-E\,mR&J~,>7.-`* =}O(LKށ2[_|w/w#^{$.8[+EpIq.תuk*WdeZ@t:ܸ_׉Bb<DȉiZP6W$> tpF*ӻ56Zɛ`Wv_'+ɟ iҾ@ߢSN0icYV#=[zt)EZ /qhlU?Ycm6- $@RQ!69%Âc`OOŏO͐Uɼ pD>8֐ z0&: )](y]<垍j"b7mª|i,S/cNn 5|Uwꜰr/wŗY*&M ՃT`2E{@FJ?,-yqА !6;qqnq*e(j>Iu*Z2_e&#y= |"@NkธX{VE돯b0rft+VfTYHrE_42},^c(+ϮbohBXj`h4ÙP4K̉m76V{EHHȬ 7> stream xzXTrԜ{&QҤHE20̚zCw@@{%&jL1b-7$&f}4oa8s^z׻޵ejBD"+m||'Nk(: ]- 驁#e}Pe/7%{l5i„cǒ3#捳Zwղq+Y #/kffuB[;Ŷ6F˹޾@Q<, \8xIeaNÝWDܹ}jwvkw0ߤS6}Ќ}<9#78惭c(j0eC VSQC5ԇ-5Sk=5ZGS b(=tCw~8m9o 93D6mfH21 (^xӿ23+*u,V~Y!c5IZ%$Y؁?M7^`p_)!dn: A7G&א5 gC w3Ȏ`n*,Y`J7)̼ 且ަ%)LL-QA9ZA58sr-޹JxY{ltU Hފ=‚=&G˥̯8i+%n].Uid'\7?P#G!ǽ=Mӱ"N~C%쭧qtC9G%9N*j5}2n'RTVU{!O);"K??C,7#C `w#8Cp N:tt!\cDw_f%5.jNM7)IJ9KRt$! jYZr3yp?rm9d( Q׿BҠA7AOTYMrdO#{Y)`IP1 15μwƢ(iG+@X*a:N{." xX\<` @W*Gt!+ &hְh6x* 'Uh3$Gix󖆨 WPAۛ/BRĎzMg;9qWi)*pFA5:d'fљtjdn>CR~.%\T)hAA4xњn^̈́Tg*G_h"~H,ġh|x?pMak3O^HKp-3l<ׅ7iE|9^' ?BNv1A< }C5z9^f"B3oCDn[2e_PM'A|6U qʖJyx.QR(yD?&@E QDYAR  Uk  o)}ϗ#J2UWW_ݷ`x#q1C&rߧ>8 TP:9A-NׂZ˩a1Ur$P!t.yXTXfzX ߆X+4k;rH}) c=GsSQEw v#i(^[*6;`gvW '}vxnpʰ^ $ue U 1ќ*)6.IZ Hjz.( T+b؛op=w*W L4$Dȱ ٩Mq1ՂAu)g_^{& P qO Lww-Hp/)fMFXwoDBUx'#ۛw*s&2hݔ)ɡ(@xZf5$wlZm <. 1!BW(QĄЬ;\#~iQ} J/О q:3џm- PY+ :ƻ6G(S$/I[ _A=Q3P>:M* onywrhv?g,l^J)BjTgC8%'%)>2lj`YEa\4>ZKo2(sPdiQ\ Wfd! t[YVFxdjLC|.G?aȻ[(`26 C޾nVbp?ǰCOl+ BvD9Ya׿4ats\:$ Td7ڬmvPCH!0NA_PBrb)jrBjvYѩl8Q6$'2:} rT9^.K hR~F _pcBx2tJ]зcz1.T޼rvO4Pz&Ў^Tx&LZɽq{Ƃ\eOꢒʜĺyUZ`>IFoP-T#p=80⣧wc繤T9Pz1[9Ռc&c[Z4˅wLhm)>p$A 댌ǿX3e ; }`|8F 2AKqiZ\f4Xl0o;p`l`05%GfWC6Gֲ{-4440>uh 96kUٟ<:Qrlq{K LSPآhq46ϱTn^:9ȝ*M% %}M/.PFW3LJWMɖoTb :Gn-.mEZbwϱd㖈H];QZ.l,)ܒm|zzúmFtP gA]ttF9rJg-8kF 'ud@)x(>"Vzav{ G aG'03uaEN;/z`^| #`'abɉ1ðZHB*E<Шv,puZEDҊ )z(`* B}|l9s*/Zt4@hduOo1?ufłh2, uhݖrgʒݟi)}>p-%UMQYUj=} ϖ"_U$K<Re`PTUrAC#1IN%]FJ6RioHZs4 A*dx⻈ tcJmxMO5R܈LCHpm{8$CeT:Ij)ijYhZ|^J{Ӿ £R>$W/%EɊ ۴g[Bʠͪ 5K {NA=2lIN6YM,EG]~ [sh/Qk ޟxHD.Siδ D:Eɏi*ˌѨӁɃb9/)EcjNk㒕ɜЉ ewp uP);fPoȼ ˗"K)*2 .ʶMtx)nsEO&C2S3qw-Cd'EGPA>o Y3O4)2"dzbKVnu8L+$1.9r@ \LRD42aU5%go%l0 u/K 6S^)}6ï:fӨ;}!o ʜ̱CeC 6 +\l,+(CPSf&EnK+~0v{ىcI2`ܢE8]+Bѻ"<s] a6;|-ꉺzv} ܺ5#$hRB PKUYaI_]X&oӐZDtB:")Q1ܘ2/^c\/ʪ4r"'z߀axw/8rآ'myЌn˳\Y;ڭ4 <OztꊺA7s㜚fsW.3d" AF`\})GQ+hޢ-*_^g:KC SlJC&o%}A-va3)3Q3b/w34mw]Uv_xl]+-^!"HRJ 1&]]N9:z"&4"=轱ũCۦm5D0'ԥūJ=Tx28֜ u93f?+ZʅBЦ ;Y^cU„*Q[uw/G/K4_ԡ3C`^:ȂZiD'[$$%dW Rڝex NIN#sPiDjTOrvY(wB[㩼B#FދO~)9nhK{Lͅ<Ц䢙| }Ԟeǫ ;j2lB{D_h-o'YTrd5y)_\$&m1w)߶#:D&ӋZQFwD7p'Ǘ[Y60/yע1MQD%ӞOy {G7d^BHHH!B Zc= [y{4xD] K0xK4qN K$xf']a}NseDG|2U\٧xG3YkWS {dZZ|B=!@!h+#+n)[u:3ͱ1km]`OLI^ ټCW%'@:A " G⁋|'i/ rR$B=?3B‡:3flZdJY ;̼QZs ͽNżx~O/0HJT|3cVQ,Z>̏=}89>`&on3_`jc;,S,Kz]JM]( 1Q)l l& lMRK)GKRS ؚQN<9mw JT ;wZSg+(/Y呰UΖʦ^LO%y߽z4ԓ3_z!蠣G@@CI^VZF+mTW+11$*&!5)5kԕC7o3".k}¼~Ȃm'q"vOXm0&w=ylpd1/ fr4$OHa3lcsAq@sţC$%Qj WFɤ8I{BrnR1( 2/椧݆\bX\$Oxb9|h YqNNgJ)˻le2 mο( ?“kj߬٥,Хj &W.Z]?sKj|wCfWUs4BI^$+EzL>im`'>F"Ӌ-8/Gٺfv?w }) =|ȴe}9‡Kͭ'nG6e[%46+7⹡߬#PMofc6{uB,b:oOn-T_fBi~zom?w{8AJ,vg!̽@cۋ^On}t؉1ۀMbxٸilv, ]`oCPtǟ<)}V v,O?sGbje;p2a} 8s-*ExuTȈC*fOeN.dq4 7+6nnUIiCKl՞z{7\ImA:)Vk 5X`IIJ$Gȟ8'&Vg{c *SҲ}qdpS n1D>1:Q<݇?cݱYCWD>aXq-AqXpaaijM%%Pǡ:TKC@#ZU q46T LV'CGCf}v7pJ?d<+ v_b=wۀE GC?-4>,eߩ=ZJx^ jvySyiYٜv*-JZ IƢDsd1NzNP$Pk^yd~cc:?̓+ŞЗ=:..)2 "cW_ۍ$v2I]"|<ҞB6D٨Hj.Z#x7㓄m0 6N-ļM4;.S? $̸켔,z^* ;'!\1m {V;&%rvzLG6>1#cj0aUj1 dF?pޙN/2|<4oY> stream x]}L[UXEX݇Iq+Q8b^Fdh ߌfu2@&2F!f Yغn" 8{o9jǓ7y9 EQddhJ< =+1qrX&*6AhWbynmuYI{LFѪ\Xa(cU0:C-6,cT*\YXcQ.ͤee?ZΐH^@1(ţ,C?P;CT@`s0jrp`EqbҵΊ߁I$`[V~z=8uA"n>KsVoR%CsCr&z =h>fa`,cx=gp}vߏ)w}T,8fTh5S=‡x)5HQ+K4uV¯td1Xp*NP?.{4ǪUPuv F1]{tD [`A0QS炔i/yz8y ~ 3m Ҹ.4Ċ@E6Mn ! \] R!9Do>jC~kr[rl:MALKûw7p$D,e(lRp 9~r=)|CO[[bV雞<ő_HveqrT?#Vj^JGlr0oǒ\Y$W%j$"=|B$z$G< Է\Hma5=Ms*ygCT_߬ +j0t7tvp*`eMmjus-٨elpw ZɮZΠ endstream endobj 157 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 4633 >> stream xX tS>!4Qhs * "xqP\b)C4mI$͜tN:7-- bZpzS=}-,}ﭮvigښsr\0o,aJ9;g%F.Lf::5 InD7\'.C,W\/pE៏F%G==?jUR(@$JIZ5uEAaԜܜ̤iۢl޸)*fcο&91WJV%N^S6u]ZL͢{ YD,@M&69b.##Oˈyb91& !bJbgb XGD611h P]44Z.F>By~NpAnCt'ߥ zJ#XUjv4'x ?賱R=*lO (-˖(.zM&}hfQ^F/aOtr`*Gi^g~x$%ټ-~׏5#n){H{/G[ӣn G/%nЎz{4vGb0R{:isi70FAZnol;`iA l.ދfKOqd4ͥ|e~b6 7/9,&AF{ν<]EIbvrjzjH' ;SK< u(a4B&/O'T,m@ҏa}'=],mF#*xe7uoߋgo7egιS2|e\.z՛]@2Xɡa.- y$GvDFGHhMS@ˍeJ7TT*jT4@ ^vMF_J w^{^=LPnl%#%AW2#nPb{3 edjݮ6z U,1 L#rR6*{~E4h Ѓ|dg-FŖnu5bP*[IcMޕUGTa )?~Wqu qu dwnIн=h!܈J0nȉ|Z%d@D%B%HTn^/`{gʉ<>*`cp.y3hh8* qt8/Z֬MKf NdK*:ŵ^"YcV`@/,vlWjsE% j@-l. +b`inp=:JIFdTl3Y"pk94_^ 2@d|ϛhZ u](̕#n7WS輥G>4sFv]t*P9&x0qϸAup Kٝ{®i<[RNEus㓖)k:KZ\ ;sΠ'n ƅ:fWB*vZ.2+0 0JäYr8=RdcfH&Mh'{{f=%Tx~M f[~TaHͻҧ/ eqCk"U\'J~NS =aamd\S@hx{z׵@ B#J'>ga_kCh>$ q!tEZaUKqIŇ{wt-%b)_#Zf wjδ CpiK֠%>&F\^BRFeve#A^x&p\&!zVn*,QF+]ic=-.))CxostXk.tфl صDiFb`kn6 X+\B9h HTXJJDBU9a3jhF *j5g62dH~'ɐdIKx~'l5o#Q$M%Ӏ .b)|ĮV^*}tiv XdդO.fXMq}/7v?.qV[7j鼅 lc]X Uuy"sZ=GW_sά?B|;W /En (q@ka|S2 Шe6޾ǻF8ƻGkR͆f * i g.m`!~954{0h ֤֤*[# ]'16Ҁ% jZ.+y%)_]'% QQr' " eAÎ^ktF촟zb?Qlp|s?~D_YKMJo֡`dӖ6ij@+1jyPyϯvW+#uuK`'9~Gq죰GSA, wya 躋Ai{ a[h@rC|"V7>{zxr:Y'h PԢjV6B=/v2H/vl uŎnɽ pe ,UW75wQ?f=E<)7sP?"SzۿEE-|(*]77Z{퀇y[PXW‚y1i q*!Wr&GOĭx`dz9Ňc:~%+$BAbw-+Βt/]GPuObo1>Ҏ&M#u>yĵ|4Ȋ, f b4U*gi[Pұňs\QqWw1p,ktt:/+߇+M-No7}=j3 OkJ'dl$/G|w*G+I#Oc RO|ՉfD3RH%*ut: Sa B ]mھrԚ,7 J:.}4ϨRFy rWn4/~S+MEXZnd9{B뀘1~]$A[~ /t4+ߟ#jPjj.M[r $cMh28&#J΋m#~^K6ze;[ %~YTa)? R[$gɥL1U> stream x]{LSwo)wؽ׉ d16ybDmNJOGQyS 20d4(.ĕls|9 r"CTi2n[Ž.HH Ym,xaB`J^_ר&",lUH'ˤ1BqoIdbBcC-:a,uVLbv&)aC|)㤭 +Bj.0LꭷYaR^dX&13aʅ+ ҋƀΰtG%jq|*=C7lq\;J)Rg}_aBz:+}:n$cS᧥QP Gg?P۱+;|ߜ)r+/Y|p}S&w:}Ƕ@<\z(އGR>@DVP_ :o"!y@Bhޚ^chE8Zc,@q[YP])čPUpj=XB7^d浔!GAvdZKM7}_JUr"3OVL"Q &N),a >;vk($+-9l?ep:@) BS[[qE4^\**U4 _AGJu UE dҚK-* >3\#Z |;XS;0$IA>F~vhG/]{ۥ_NE5)al;=S7yYzێZ- *Q^qjމ:+ ufUTI$.~^pðendstream endobj 159 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 5907 >> stream xXTT־C3^)h4J4* "@QTdeAz/R%Q,d4jb41jL4_sxkg 0&yYY3眽#t(@`hqcHp ;zDzHg-_ڙ8?Nh#Sߌx3C((m'duȾo ϟO.71^`n' $*,#x݂ BC?Y!^!^̷8ut2_if |1EQCVb.|}mdG}̞{7:9;l EYeS[5rΎv_EM6QӨ͔&H͠35BͦRs(jeMmVS)Wj ZKEP먷-ޡ6PK({j)zr )#&R,52L(SJ2&S5ңޠ5zG&PkH(*тSZsʹtttFF?n6ƈsYo^tX%5M׏??!`5HFFUL*jbğUI>2^d|D$䦩iU3#3W{'wNmʼ)~S|8{7"o2(6i,؟Xכ`Rء) GI(AԊjtm3B>ta)4M' 5Z uJbSLW3 ȜeF?Yn̜K;N !u9Fޅpt,׊*'ӕdu7fڟ:t|e&G*P̛'V)7яrPn HEЀ}HZ[Ptƾ94߆gMpCƍ|uݻ3 |a?]_"} ϰY0 byZ?=#Φ]j?^v㋫v 9T&h<+3xm/!mD8Iz%767 _7;h/ 3ЧZJb la&\mP>S8IƗGpl +0aHp0fOvYTc:5ԋA,F-A1i\v&N߆D%fa;'Lb ޒ*9 pE-&ЏcgWz O.$?#4wڕp7ѥܺh7-MYfWc5X/n_g#Bg< Oz8U÷XG˭?|t]~mU+SX~Rslp=DDuc8O;t4893}74WU;Aþb..k"̗}g,x}>زmb읹B+XkI**C ܰ"|r)rjZz3ůs>>#X0 Q)b yሑ|B2m Yf ו+GE]?}Svq+W6,S͹7h—2Tܗz7my{/TvGef""\98$(-|g-*` NJO48+;>2]Q\cdFCriʪiE|Qpbt0QfElے,Gqߋ,Pz L/ `n Leq]y'i2$o IvA?f/{;֙%W<0CN4֓042aig,STݦ.2RD6pޒ}l 9T"{=u 1mro@6[ s.|rV]l~1Z(Ћ.3(7a;$=,ηnk,3*).%" VJJINrC̖t0wcezc>v أm$ZKQbTӈPA^eC}Hbf%Himk(o.-הjx=f]x>1 /8qc;r@a̺[9ҮzDAEK0;}# d>V)²{I{vȷ.5;6:4q 2:QWz^i,;DuGc$0Cv(.&- ]iiq߬  >:yH[SWͩ O@.c5PxFx*ȶE4DD4F56*P]Xu͘ EW}%VxW֢ģܫ;sqejD%3bR9Ϟ-n-W,]012UmDc{ׂ{8rjsjrj(cQeW)w$HwWu>7 ;ۨBr$a|"P}^Dļ|Em5tW9fb.o?m>CL#}y0htV&X*'f;BR@φ0=xHR1wy̨42Uh@=񥄭ѫv+OOfMJԄӠ>3y:Tka0zn6^;8.0֙5rxA tq6e,eV=3nݼ>TC E 堎BV$|tzbb%):;.'2$UuG, G9`$vH1s ꛈ̄Kg>~D<]30qz+/nKihi+ϨH)NkZl8;g c ͈s 򮂫AГ!GE7v^Xt3,kwHV:;o(ڣ?q !dd;f#,R$wf?;'{/;*.,,.BzIxD|? Imݣjdo} ;TN^ /?.C9 Q8aQȿ4BLmԨ;G|#Pwg֝, *t`L@9$/X=-“GHӸhRĸN»j p^$>?imޚMl($XRLLlJٻ۵ʀ ntƚ!k|la^<\\b=ݸJx N* ?(FVR__3<dб~1A˷`@t[v{dQ\rs^3 \{[)_ N/(ZoD~("Z6jhl>DRSSSB/k٥ڼ<O2E$wVx*ntU'w>6xw_r -<^ `28:ntn'΅.J|uZ1l岋W~|tAf+I@(8)߽GTX[#`?P|zIx|g c% 5ұ|֞~Ν9zKVΚROnduAaa5ԇJbjiB0nʯX-,~v_o "i)[L2  xI;Btvr_)w~oB#Fݨ\ ݤy:=(Љ]<+{;V[XTVS'| L@ f?V*QIF}h0ލMp)?vvm'Ҭ֗(P /@Cߏ޴C"IzTj|YZaaA^BLo,Ɠ'fxQjQTK;&*UݸA#8c?%t~m AɱY(9 J#ҊLٿwd&qVވ޳[uu[}O5qx '`c8l .vqNw=ɱ'>P4Sm~'&4;WR;K&ŨNTpxOQi)G)yHKQ2J.KH`36'%(L| _dآ`ݍKs>nd~=$Rxv4"$$LQ[y;4Ѵ٪H?E9)5|]Q׵X_4"_2 }{щȷs0 {T8A*Іg-la=A^ܼb.~θ䬘 BU5]/>-nRO;rQo:"w:dj&[_Nh?6iq9T7WUq+\JL%`eYA-ӓsz:!c\Oa}AAOC^Aqn]/ 9;endstream endobj 160 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 283 >> stream xcd`ab`dd M34 JM/I,f!Cܬ<<,7 }_1<9(3=DXWHZ*$U*8)x%&ggg*$(x)34R3sBR#B]܃C50\``````(a`bdd?3qG߷0~բxy؜u̙[r| 87mBU\XBBy8yL;ódKމ}}}&201g>endstream endobj 161 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1125 >> stream x]SmLSg~KE; ȼ3Ժ,q8% cCHP "D>JO EXi Q1[dF26q qklrrUlٲ-4ԝYlT<+iXe ו6XWfeQjsX]ʦ$NLbS ?!$ުλ")Zdh Cvv1>Dt%ᡩ_ִc\56u_xLJF+'Fo4͠ ࣩ`1;s^;}K8 ??d C'x)Rg:+v wژ+מ@3c.}\ YZ:[e.-4p.kMꇉ #&-0f}+02{$a)~6YfpD!?#e! /E*zoeS†&W SNCq$'#}ïDˇ{?/~tOu.D{P8z4j1_F''7UN~W;ֵ4uR܊ d $+bmX&% K6bkH^C/3endstream endobj 162 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 4877 >> stream xXXTg־+"(סDs 'Ũh, E4zU̙t: 0b%ѬcYY%l<?&}}{Fb$%K# MTY^tK!VR ']`+>'88ୁa0RdUhGt̖а'N7uxAQ\_:uYt2}1=:508,@=ur_OQ}g3 3)jnG̼ظ'n ZuSаp_e#Z;dq3rf gV0#/ƛa|QJf41sՌnjg2יfY,f^b0/3KeL23p/cd",Ǝ0i:>Ld$W/+(MS羵ll?^6w6~UNeHvW0f_)?OAgݖ;?8:~{ċ`3~ent>1r4ā̡ _BS06=ޓMdZ^,Z z,}(2 gf|}{ek $km}Fl5;ిAxk2.C|B//psYx)dWZ6D%$(2>߹u[A5$̕ (?rER>kk,[)lQ`=`y+Z7`Th:.S0\Nþ#ws%^xH!"nC c۵'0c[+h A%0qfəGbI5ɋh{dejd,3ɢ_>lrB)k,:3[a:.d%J^"$ӿV4X#v6֘6:<םxwq/*0b:10X8򏉻З 7*n -?]tRHd Ln/U8ayw[NU$(%1Kp qiWޒQ$2d8;z*!_#i p)c=8g }kE[.D34F8ѡ:_CUl%+彡)z4DGطxũד^d#4c urm X ܜ%7K_^T7feKo:b_q|Od򀀥 ; }Nty9.iUhGLвmj:s15[j*KCeFlǴRQp(ٔX7pNyl28k ©qzA\PXۍ MffvVYNy_Dyl]Ey x]ڭ;)Mq#bLڂtÎ- 2 :]n!,?=HAcJ;I^v$;|9ehtƯqL/;GnG\j_ >Zű'7H"[]%lіBaډ;]1v&Pe[%W:_ <yd;9O2? ᐚ{vyR5vѺ]ңn ^YxLȒ1?`>;ySs:N \db8֔ܖ&r2;%k;q M~K F,P6gpPK8BRfm^'q8&RAsJIkBVF (tiUݨIn0Pz {":TA!s}tSșDd(Jp j!:|!@ݮڐN˱j媠U℃u&0s͉Yk޹[.v[cض 8'qOp]5a;Yڡ-dd&`7֫!4=P-^* uvi$q,eWP!s17%KDSrs~!* $uSUK~\{-;=VeLއFlt8g\_̾%?ê`uh(Ѓ=ſ-dڊ2? eSUuC>(L G;~&xb3뫙0#,qqjڽ _8X.sB;W| sߑѳ#7g Pڝ37S) Nw*I_۹RNGH:"jgw+4e;hS3U9ot~AVFOq%uX?6Yzaoy4z& hR &h=GҪ ]PLkV^ll\UFZnԮu}߃=4cC%/ZF9!].,&^ lO&ۍl9󆷣OˏP'u+c#+[׀7ʖ*PаQ zVYT7VBO;PUnF7L`E6qMV!Ҕ䧬sgʨ%pqg ) q[RcCsǻ\$(iޅjV%n-_~RUٚ-$ޡzGΖĵ*rC[PSȠ1d 7 mP vO% 6)K,B~Lij;ڸgrX;Sr1j\*'-hGM qӡ&?-/\J ( ]: ?YJ -RhE;D^hY3at3" o2j(+xi##r4QZݖu-]i5B;f[(,6̻ۧĻ拭ڃ˯H8SUz{QDN~>9Q[˻3ԇK- So{$G N4Y|$Spi*h!c-Y݆X}օ9\>bf@SBcڳYm>|5u˶㆑#=S,$WV;+ БA(b#5bI?丑LrL dNv}&d F78{8l&Q[ltEsqtޱn9E.;>i#J>u93,?c:~h1k)bM, xt#=x#GTbD!W\f8D=`D:`э@t ڞ {h%?7aɡt8Ji'~##UAQ0!vSypc=kܦhè 5m*Ԡu/{'R/x[cHG}TAb2̘jv?xXtKZGr;r` *L+,b`$/f&ZeWT\'NP)'?NF9rv< BXxWw\+`9Vh8BZ#,?, AQ6lͳktoA%e15;{ț####㛛{= =PYJm'ODXY2IRӪp4'Msu[mI)o@nCGB:Xo@7*'ӸgmB؞Ɣ)И6C.(ǯ#C/\lM!gƵYe "X7?7(5Tmݛ'ĝ%C,a nޤvtzv궷W;qnS٦] k Mm鋏`m|Ò!^XÅ8 KܰP) G jL;p4Xlt?MH#K{8cG0o'>~и듂J5+ ̀5s2L2}M ?-å4)7qr"#F0J1L& = ,%&&*f_YY^Qu3E.[O. _Vuz*Cfw_#,Ko'HQqH&WW(#-gTcG&mzʏRiZo &;\FC;'#zO/)FkJSPa󹣇z\~vad<ؾоdRЄ;yxIJғdRC2启6d9l…/-[eO _a@G"6sK++Nw?yr[:ZB'ڏ$ u^]xwZ!@K֒dFKS(.%'wU[bx!A)Vۃ2_`QwԻ_%iK3Sth:qdw@vQؔt.~kϡ#@a~Ag_b*Ho*VAzGXQIiy9CjRWFeiSiO}#K,ep4I.OLK^'D㤼)H.Jsԓ:O-}ZC[V$ AFXS^Xɧ3Y}ĖΣ |@CE=Q73t0$&^%hE ?hSiP.*)m: 6}||6~:=} twmm Ɲ<U 7Ӿendstream endobj 163 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 573 >> stream xcd`ab`dd N+ JM/I,f!CǗ <<,L*ݏ3#cxZs~AeQfzF.THTpSJL//THKQS/ f*h)$f$))F(+k꡹ e``` 6f`0f0a!85|f>fXP yQ#qabdqw>[Y^/n=y֊^~~];`gyKxzȃ0=X;Uj%"Gl>qg(rIbnJE?S~ڽݾAFVU{ּ[ˏߙ^`|Pz3+N2z#뻧h.zCs*. >r?>sC侽>ie+:*8Yeoooi`|srwg{鞀I9 ={EtᏀ9C]v5KHH<g7}=}===N9?gb/endstream endobj 164 0 obj << /Filter /FlateDecode /Length 1876 >> stream xX;sFY9E:O]CUǦ褐S@M& ѿ8EFvooo).ۿb=ozz2͸o ?L j2UB|=AgXd1ZrrN<˩]f) 62~(UrƨB 13:ZΨ.0EhQ [ϰ4r³73Qh)A>DNsHũ}Y\؟6.\jS#>E|4Q!dM+VNǮמ;7atN؂l,)Q[CД6.-S\TBEuUkgL*A+RhJ*%U^PsTVqy*ad?)2] sXg^yijc .~I0]o `glLC^G8~6,ۅkߕDI߸.Z}Gfz'a$臀{b{dn6 N[1Bk[[V\$A szS.iR67Blzp< Q@BJ(m а$gi%a9t$:k1]k:KѮ\5K@=i?e4MRs–aZ'6 =V ,,%MleD;gucJYv1)}2*oX&4=FPrI2As~v.56P֣] B3=UAo@Hh3od ӠHw *s4{ 6!ax84q ;5-@BaN2<%P˟@h Ú kKX=e#u\@PHvSߣ8Du⃩2&DLvNcNU= JwGjBFc4G.mrkmT "-DXze7x ͤrxnhsɂ*@۾QHP9sy7{d>y;`o_  O f% ],A5A6E[貾8m 'GQ|9aZ#G{w\$^G<"Xڵ+INt䘣t%Dt֯0e\DN;쾄W4}Èr]+3*9ݢy秹 Va`䱣C"6ٍ-**tWo 7^i 8cn*-zyuVCz]> stream xV PWEldZƫϣU; n"H&$ͩ@H J9ij>Uڪ8c:2j鼙N~#zb|xB$I)1;<̚5ugDȝ;c=JX*DR /{㉓0O"^+c>)cT%@:B* 1H/z>{[xiLz1`+B==w)nвW.k& Ac65wZZ/C܏tevPmE.|Mnpc8.noh܏VD heLn`Bh|HPVHGΚ#G?vZ,a9b)Oe 0<^}'5c v MmKTvW`4jTJȲAԕh MgaXxhk$*]؟ҘS$.(,^UZt|& 'șZEFC},ǜ|ȒTG.r>$T})r 4 uԙE1ApVK{x h 䟤h.&9;j$1A1N)F0%|=IfMm+T 2#ǜQQ\vPLR_b># ` \,ѯ?P0;g3amrq;:ltQ~r9(̅=iT;7 oּ+c}$E~- u&{7{q,4A85[-ӎQIl]8(HlHVbЭ56`ԑ\ ’`ʼZkVW۵ͭMQYsHefrxfQlfE(I0w#cVl$73džxւO O @LxgFy⚌Q2'醴# "1ZVXp=Isԩѥ*\]K65Ty '4r2&/> צ ճ] EwP @$ԢÖ肈{ӟ+Ikz x/\hrVFń$I!vVgXAhA"e= M"% ܍dn NEl{$/Iĵp㰘g]u}:46W Ѵ:CIR6q4Xy0L[wpBgVUHA&3Ӄݧ[7Za>uEty jzߦ!Ž=XبIh=LǛ]9{}]l_o!CCs9B;qPD9̝BʪTɪu]/oe$}N&!ʠK4GG^7{ I)WR;$fq}0e$Fr-jj '4Q # Vbc76i ʖCj ܅kKsۥU]- z )S)2uf jW&UIʝ)9H )1HJ6֙,5E%p 2Oӹn~,ѥGBΰ{LHmmmo£SGeiIW?V"cqF W{6F1ּҫe-7 o/)Ik!vE.B˒B&#,.hkQJ~Uqk̀c=b2Et.0*1TJlzXp_ʽ}ڕt!cÕêS5Vh`β|9&PĄpo Ce҆xDUJ^%ZP\R;ZnGѢzޝ!>[6}a%7.Zw ~TɅW}y܂RQ?۱-h\X BE) :fLٻ"UZE]lS?^3#ch4`2i傟o[tGOjbOŌN6~@N'>Jvzs S˂nViN-Dٱ x1m留 'y y Zml ]6֧%lBos޸1e,j:N-Ϻ՛ zdp@Xendstream endobj 166 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1464 >> stream xm{PTeƿeU8[g7ԠIKfSyK ^b!eYpWa1YR y"7KY8Y%Ө9 ͨ#ai|?y*@T*U؋ )YUR€B1yJ ?q'N|hՠ `cTxU+[J \qԸ"ewۍYlc|tB1YHhf9Ƶ ƴԘTc\JRZr;ۿ)BWq9f'$&$udYIbjOWHlʢ0 ,`Gbb^$l|S .FF]τI^)Wn0'9]+Ğz>bH-T)w,Wҙ{ hҜZH K@V)CQ^b ZsN8&me:epYs=:W3߽e#1bm}xn)Y_*I؊FC>l_鵂[2-44y ^2uX`-ɕ2')%aZG'.EgPɅt.39vz/glN;za@ǻIuA:dhtTa "㽆\wriY4Fhh5e2{^QBF~V;ޓ^᭢FkcE ^K?^ Cre43)LOxFy?A_ӱ f[F~ |n+Ǚ93Gv߆!82{dz@,;jO3D7".rTjP\*?wlvY69g6Y]Kef/_uW+ֺRf|yb4 ^bl㚮Figw7C3QWW`hP\WUwk [K=ֶ]7p}=`>;oS@0\=#Ӡq?+a\@uH<&%,]tji/\q)j곝ʆz8H1|09pS; SzkkkpPެlzy u`BS@Sendstream endobj 167 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1671 >> stream xe PSg"/IzEM:S.,hي+EVȫH-B@$1!hb 9Z@$ BID,m;Ȕڮ;tv,ZߥLg|3眙;1q\JRB,,(JW284XzY'zZ4)AA(78*J7GFn yA!ߣ8G m|ODR|NtZyRutyF˩iݩ6F__ `+DFm~f0l?%aAb0Q)1Vg<^&c~/ W XLN&r^@,5*"Sls,wv I$BFyNmBNqga߾tBPP.n`(uׁatHЖπ`0fts5y <4"!9JgC@sR'Ws0?5M>S;y`zu8A)׏YR77;o[joCvݳo! 6djl0:i;(vPܤ)3yxx})Κ;ãwa16>0ޥsq& ZN`Z]1 KcKh2_bdDJ#F|Z*X^?,n& w>^U@2ĕEËu~Džm7W` ?{6MB,6ECE |`::s{XgWV.S>:Zeʘi XQI{suX9%.(Ft ݅3+-[d#,@qd9x7P(z)xDQwV&>?dR՝& 1ޅm12 x1$6-Zo2 (#h0-mZ@Y(x%pLܯWe\$ybsUK>?wjI}0 4XoO$Cvut# ;u2u=VN 3[`͇,Nel&n ؜U΢Z9[&_= "8J_'=o5u tka#eZmYV;XviGˁN|lY&L6zʱν^ sW?ܰmgzhu-uVh xa#$f.*v4 6ݜ͌WHrglfLtG ?_PGa_H| Qp= *ZYV^oS2k);W\ZZT$#cE=9/kFߟY3 4XllQ p@qP DA' 4HJSX ΰ_niuT͕C4 M? Q`@76[ [ ܗaTh![:1^&s 478#]@?Gv*9zĵq*C!r(`mH6 rs|wl6[u??yFtk[?9> stream x]P AM1 ,߻l[fa5T0{{Q]ơEWH(f6ITdzIOBIg}1onzOd{C2/ @+fnxn5P[ bf$a)$iLɖWK%zSG͡J/OKHdendstream endobj 169 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1180 >> stream xm]LSwmj 2.Dt{=HTdc*~0  ZZ<," Z!~u21~s0dO3N^Hk^ᜇs9_$UX4iu͹EcuJz_#JAP*৖\ k҆CU.Uzk{^CŠ=1[rs?gtޑC(u FVk肜V74*FYt]Z]t_G9Ojðwfj;atc%]͒lIB2+MBgWڎ9>_sRG1l][\D3tr$ rԉKH6}ij#7&ʡ5U۾ G p~rķ@$-=~csi1P OzU{sљ쳗@\k ˄J1;q)>@ۺES|s)vn뙔8:Iq-_-ДP%:am M~/QOp )Fo.=$Z|JauUmiݖqTUSW丹P .oR >rŅ"d`tGLUh)#ĖO ;˪4iUrh޶X$ E10ZO-,*JvmZ^VbEE)*UzѨ'丈$]zGWtߡXFG/ag;sŜ b;.`2A&UGI^||VjWkR>Ql3)<5 *hjM8"/'r@ܒ en zIcS2vMԔj L% PE/cx(ɢV6s|^8E[6\VRR!_ 圇z@#z)Y J9endstream endobj 170 0 obj << /Filter /FlateDecode /Length 186 >> stream x]= {N Չ)X$Irš"?1EoaZ*6VyKT*rTU!ԧ|ŊI 7'$zag$}]^kNЪ&}L/ԪgghdM]M0ÏOj|rmkکܭ.h|\endstream endobj 171 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 700 >> stream xuPkHSMzݍ ؃a>|S|lwnp:sڔMv7+@@܂ z _?헄{ݰnA|p>8w·"4EQEMm-9Х[ֳEc砙䏢|^L{&oOLPsc9!$E{G]0Uf7uv 犊Ϋ"^"Di!QEw[lnABbIQ`%.AX:Fc Ѥ֠!*njN'?t?i0f$ iFi,>P?.G^DpOs~J2!B֢^&N a%KGNN[z'()v8ⴢMj)3cJGeqN{(@9*^IW|wwĆ~$欜uFv>!|; @/΂ [ C1VRQǂ0n\10!ۯ)\NM,; }ύ4G2mԀ~dzd'jN:'l@5֗_xc ~gKoJۢrCWEyF>}F[CKr5V j[_c^{ZW k Ja!S#C`1=*rbx6%i>Re=EL/`pf; AE+endstream endobj 172 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1217 >> stream x]yPSw_H^c$QPqģJjr+j8DCHRA# Ա(*ul=9Ʃ076bCõ yxRrZ8Ţ}li˫ wp@%BIB=z`+&YZIW%dRrW\JP!~EB֐Dj_IkpU|OJQVIE&m"քGP7GmXw9a<1ol&&p>V]cfG99בcl"_GG7p(ꎇ˚"A<_R:b`飞>=|y@@@A~TP:A^j.6NV0o`X;t㪁 rOG OVbҽ<[QG'DgO٠~ᯫyʒ2=.J6ӷ8hāVѭbyVyMw헮= ZJْt3pxtpB:wF'ݥ,t l_󫠞tr:J~~ nK!O4;467A6ho?Y0zH<AYݑ+A ˮ!+4؛wjj 9iE;FOJPxːe2";Z cZbjUtfPD'mN/qsʌqbsT~9CZUW-G.$B°g#bO u #Mg?!2|5dkx岯oc. wHѬiy;cv8$C9ޘ2_?Ƌ?#ߝp4WcL:LQ-iˬ&@'A;eq,3;炄Kmj9pX`Vl:#H[Vٍol6W vf:xTn6aQ5endstream endobj 173 0 obj << /Filter /FlateDecode /Length 177 >> stream x]OA  ~ڤb/l@X  ª=0duw6Q^ Qc5*#L֑ڪ+d5@X7̦r+j3)a RAnr.ZcV0 yf^y,ȲWKţUk=K=jhGZendstream endobj 174 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 854 >> stream xmolu+pBN3EwwD`Kʴ[[޺Iom:fײ2nt#mεT/!D77B"̽ТH|~|CJ0c39miitmm{6#jimrYj>ꡍϺh33dr кw]{N݇]\RFuOA꫐&:oEB%*aqI_oJt$t6Y NS0WH-SpY_h[+xN1 &gsLqLo,ܽ D1Fv>(=un1Yȥӳ$$£f>AL(7֯M5n0NhWD:C?nǹTw\*hdm@q}6*OyJލ@|Zae[tV hPkY߰cz7n~Y0\n!bUoP#T~r|rRCL0K,SY89=5iwʑgۏaݩ<Pe,[}+މ'SETv@؅D2WLX<ೱ%endstream endobj 175 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 454 >> stream xcd`ab`ddM,p(I+34 JM/I,jf!C[KOͬ=<<<,X }^R19(3=DXWHZ*$U*8)x%&ggg*$(x)34R3sBR#B]܃C5p:C"(195'5)3=Qe5|Udpo/g OM/sz{Uݩ}iwo ٻ3;9(ӓnzzr,).][_whnnpXФڦʞm-mW]w {6CUvXӳPq ?m-ýpv爛=}fn?y̜97^κIendstream endobj 176 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 567 >> stream xcd`ab`ddM,M) JM/I,If!CW~nn?6}/=]1<9(3=DXWHZ*$U*8)x%&ggg*$(x)34R3sBR#B]܃C5 U43/-3/a2.X3~_*afO٢ݓ:'4L=];6wB$Sۛ~im-ݒuuMS俧I54tvJMm1iBir@N0sb䌩SgC^g>Eݵr.Ֆv,)2̅݋X7xl/̿~g_E]KvWw>B9~fowFuO*us|;|~str(xT\Oyhoo?ܸi߬OnShl;vrq1pvp/0gbτi<> stream x]Q[HSq<`jZmv1 +%ҲM і:gl.P0gĕ--3®*",)${J~ԢC/|wDD(Rddj2} 6XQ7}(_7_ d) OW`0c6S#ƙElbBBZUMհJ*KI/c7i25/q\9k/ԗ\mt֜,]P9!D2CBI[ )` 'i &^`ht0KZTbei5Š6ˇC0 O9ӛNg:BwM}LLYP`⻁UJ7*]~z==B`bΪmKW*ZMv]%9R ]xIZXmzbcp> ACm ژjc?KU˅bSA}tĸ_|rWQXE1T%4 `vO2IeuΦG+e"!0]aI ȽuZ;CYM`[ua'd[2JsRTB{quWg6ГQfY|Ѭņ ؆4h L~QAJ;"D UzΎܯߎ]ǴZ԰Qhx15@\9kjpzf|bfH9y ȃܼmy[Ð\mfy{I>@^Zendstream endobj 178 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 7201 >> stream xY|֟v`2.5(.MAi$Z -T{ٖ=-lzP .XXg!(ԧ,! {dv̝{=.NAӨޑvEľ2s]“?zs4Nz8* wO/pA #юg(g'MaIoEO1kӧy]{=V&2192cw@@@ =6_nNJulYҌӶ~7)ZyI䖷/ZHӅA@j  *\ӫRg>}ĂRF@ORNur#z]YQ $$<V-l b+ۢ0G0$Mm]U8 &I nssB% #TDļ47f7̄Ԡ)5Î蒵) Cy 5LB]pv~/]EwqlE]BMMj"Hc>c],~.I}7~NftF\^]` >Wڑ&M#7Qexm>MM`ۊ% VlHdw|68[{\7Tsu2 !vCgnM! k;˂GΏ֭7`Jݢo۾ ?&4!rl H<NME]2bH!+^$DȍVVA+*e8} Mb7Hbf;dĬVB_Nalʲ{ݏ _~ fl(k7v2UaejS+ښd~wLhvPm7qϷ aC a-jФ4nk/j1M6d>AX o ,x8`WX9h&38.K2=>fإhauOqePm1TLJ WP !W'K}2c =ea؝L^NNL 9&^"^E]wX2bu܀;uDsyWͨB3|aaigm➠ O~J blU=ʼ'FĹ)S?!k-RͪRtdI]MSvCԀL:?s!%PRЖh3?)!QO 覨~ >CHH|KZ'kS0>C'NG~@ۜkR$eWTe'"- Kڼ`$9R/(-A'E{Uj,yw hb!!cCw9TdsK!TlD =cՕW.wQwuWx< D^RMߐӞmʳ u$-?xs[R2tԪ_RΩ& +9=^o( X+ Lrwon5=};`%dZQh=D4AEH냏!}R̜Rk_ZŎH/x*#C !00]##Uc&oX&'I#Z2ۤNȊoI+ˍ5=꣯HJ*";`pEH&jr{-7TuPlYGy=8Ѻ[mV;h @>skng44'(V*1P&LUEӅE Q >K@zLcXW*\EsgHPUH!P. pj !!)+Jnqx"ΔRm$Yǩ(~N$Il%"S#M߾;W3@O!wYA+SU*160ǁ`OGN6'~֗8?ϊ*;-`=BkݤEM~\RPZ4BXךp4"JjXo ou(|Gq:ZoN7y" ȜWh0!*N6Y3dDDrY@5?mwRy_xVdC@N`'"H5J?cQKCkfkbm7ܗ¶E]?}mx\[~DVѻۨc^I(x"VdE3a@s>RVkkAzm>D) de ^'40$]A* ~ƣ#ΙG2l;D$vG\Kv4V^Sp>Z>J _[moo|Flp|ݑ̗4@=f8Viv)tQF P*K`())Qm~oCMaj+R[A,Ic]B#qS&ZIxn=Br ˧ !?Ԣ?蟠iN^I~0Cעm)6_͎Z[y{yĆݪݴa?ݛZ}:6W3?$/1=%=N DdH= ¯MiWYF!٩$B}%o9Q:daX&55Y>ƬjCNRa'̂ag҇ma_GisGNd0+`9GEmŹp,J "R8bO`'amz+6~gGPdo<#NW IQqYҸzʞ~a ˪|壈dr+y1! 5_`7z09ҩ0+x\dGaTd|Q7Oy/7 UjƼZi em>;_S ϩyRt`Kħ-tH0i<4_O6f.5‚vy!'~?XU  SF5hl"_B\Dc/"E4+w ",N\p+slmk3<5? K3JH3ܟ8eZU R*K)<\,z#"[a l>3q!Y, /#U 6?2 .HU]>C~>;Ljš++?Ȭ/SHTՉt4WN@%Tordu+Eo`N-<>y)K ͬ$=n`X-%K$ߩYɔx[HH'~ uy_63DҪ\z BQE~][šoL7uҾ"b|+NOgs7VB+dʘOwt uc )!zYAܾwbS[pidIe28A<A! 7!d*.iVm e,D\FTȊU'- d^2B $Y%ń \B{8n8{ng) )xW1HR<1J̆"Y[Ed/N5RWS :}o\qhX'v__CkRsF52I1xLJg'(qܞVH\lɘ|$#I jG0 U֠_#l~fu9Xİa p?׀[>>RROnxe8^K܅$'fO۸nvÎ?ֵ{6|"č(D/jtq%-1h 0G_3uLt!!Z*"K%D ( RԩD2_q߇C}iJuD8h5*2TZ2EN.`$s߾KS P\/ WROѠDhr> stream xW TSg1)4 ҾTm*[MZ: K$%laQ¾eV[Z˴b%bRu| 8v<~{D <=QWl UG1?{wMfa _o"37 ޴۲ȵ eBLX\m΁ k\=+4a{=\=]0y"90D'B欐9o uxlQ.):jbr]̆؍* oH/\/pMQ/P,ʇMRsK6j.GmPPk:ʕZOmܨbʃz򤼨g({JH9QQS)55Q(3ʊJ I;mRP$~k*"E7@zH+ffor)˧t[[lɝhj[g۝QӶMk[kffwg#?G#hB>COk3KÐc:32#ZZD{jtU3T#9W\" oFUrxlgC ׂS3s3z0i8DZv7hv5Ľ!d%&uķo ^+[H$$VӒvV86\EXq#Faciy.E^u YGkGر ׬Y}_ \8㹈%Ҍ<2$xX)=Dّ(:S_ICW0jvu\AATnX'Be&v5 OBބ7$<8߇A#7B(dzׁO1o ؓ%g%K)z a+nguǗoy+ϟmK:3JXl5nܷbZGA`MK/k`}.KkJ74=lBABH](-I5qcŋf XemW,[3&ҳ./8m4R8L/*mac'%H { ~rG\ծ¶cdUd: )|=&P|uCq8P_cw_Dۋ>f[kQ)b9!c$i+>'u:4mH431t0NJKFJBlQH O9l=w:mr𽨉z"@gckPD'E?j3#vT( ̈c7 Y#L2 ,%|B`Ff SDjDaLj,3YLӉjJQr>0ډ]K²5L.٪9}Au:*l:* |:4 ]~r"x?t ZRE9tŔ% F j }_j`[ZPacI^e1j`ED|/e kK)Hc3{# ?mE!G5W#`h2^i1\ƄO?8- (63f!dHRR"HZ:=!UWmBmܰZ;7*sƖFF%m *8~5^.lbá~3)2xE?.q;/g8I&vj{TFJ-@I%~^[;sO߈,L5 >|hSɏ&JChaiC:ǏXm!{86q0[g~.-^< NIჸ=^ VC3|.hCtXRNDߠ Tq_=_hUS5~ mjkL*_7$=@t" lVN6}{ؔΨ}_';>[o|'x㸨4 c'L W&ԔHo 5p&B{kuI]N_59etw+{=>Ƅ=q'Q~^x$x΄BY>'q/UBR)@"+_+QuwIx~g3=菇+p;W/uԊ*9֑r'-Fȇ?* ʄNVַ'>= 7Cka`!]܀jQ?z')?Gzތ(}whpx Kzop ٓʼnb]h/>)[" Vi.-90[aыd^dr=.9xʕ0sxy<{t`@&;E|me3t)Yl e~m:E2ԦFvϋp,:%>"~EiWԁP>{Ŕ6"G71dO{o$$BiwDsL.kWvt7w '8O;ӅK=J<2VffxF[PpDfsލh])2.aSYqe w<>E)dnc NHDGԕdP4!PhΗgܿkII7o"]1v,z {{3eYj剋nky$P6j3:LBK<Ѥ-g32K8pX>f,30 "#+;]Q\sS?g?hqZBۅ;| $dcAo_4VȱN[eߟbͼz#jv,A]r9g(y1/SstQMO-LM~-T2g;W%J Yz cwu\cA޶&m Uu8f CSc1{eb>V'HOBj ~VfH($SGd($ FˏnnHxIp"X+irXYSLm Hu 3@_Wbcݘ_XW/T$e%endstream endobj 180 0 obj << /Filter /FlateDecode /Length 2965 >> stream xZM/^IV I`JUJWyWf}j83%qxgOw\Fuk߯˂Kr}z4v߶?8Rv_kUXW*au^wʢ\U±xRNQei"+^:Fò(b_wm?aʤ*͊R|5_ [JkHα[6XX 'ݻZ.PUg^~-뛫 .d-;=&~ӂQjvUQJҹ97cYl5N\R佮?sX\>]f.fVRKrr Y4.]2VAl31JWM@GK- \0 |$eUy{ {pqs'ӳ9.@YNC@-  @ݷߍ(iMR7Ӊ?+9" }\dn}S{A BkO\)C7{XYe%mK|gcD<*8^f&,~r5F M>x~3@,Jכlm6TCrH_ˡ< P[}..rA~7N;ASi֙*Rd!d#.ذ =yV ,T"rL4uhe}ĵn&3 m1Hnϧ_Y;M<&k9yڅ ϼipܜ_)&n'َ^L('dU-Ǧ,(o6A Osgaf5q9!bzzփEqB/rd. 4^`Tw]ҽ g(X8_,@>UYMMX BFf&ۄH}ۃ,.} 7â-:91@-}r» a=(B$=LnV& Ϗ2 R1g cvrC:_WJ*2BJoTuYbWŬdG\FJpX j)<5<Ɛ<{5(h}~8)\+Dǫ#RF@u% RAsY:louaI _rrӹXjօ/a.]]JKqq?oLna~[JP%'ދ bA5Ndg"۾go'#~ N,=8<ٻBr&3:2].CNuE`j'uTCI+6 e lYQݢaAɓ&)uQL %{,.8%1#ApTnzO{U\Ȳ"țq|_ƂsAfM+dPLS`"纳9ț9x#ɁdIʱz|QoPz>=IaJ̻aƍ 8<'"PK#s$RzFI 7:zϛ\QLOcq =%qhԚC$6bdÞH&_C$/8&`زЖ.,J):<˵\3.$flt^UTAz{P߿evc`Dlz;z/w޵IjxWR[jHw{X1.VMXg.9 #su%;xᦨ >r%g&p7t&3:؅UeODLL;CU8v_@ıM29 @^*즗^4Rfےq y!G E$gQ,H gRM 9r ],Q(bU _0..%>*Y|YJɍQgtC5+ao:녺UҚ x=l ;@@,>V}퐮ZC/RKM%b R͞N2lQ|$T@ rAXdSX'LÜc{{^=s|ӲǐDC7&sx:¿a#ܟ{!&e\ ^(>ƲG7WO㯵&%=' 9K]P(#|1CRbԖ-ꇇ +gAx4$5؄Webq a1ԙXcBeM\b#Y T7c}A/Txue^uB34AE;mbqohivxQQs/~l<*@N" `@TS ($I N*1 nF9V |b e av%57}OM. Jb:>b}xx8}vk=U!Bw}ۧaLFr ۞xwtkC}w&Ų難+^>˳C7ߞF!0A;gUA t2vG endstream endobj 181 0 obj << /Filter /FlateDecode /Length 3684 >> stream xZKs}`b^"b;T.IraIH"iZIOw 0)DӏnEUEZ\xhto[atc3-,[eJ'`盳nfbJ *Wunr%Un +ኻd۲ba{͊f Ym;8G0d|}o+VBVkUq_wvw}YhoA]=.Wlqcb4K:RI9;hܳkw,.arp/E)Yl m{}/pʦsɭMGa~Z}F|vi9lk(U:k{sa\IJ 0vAcXw٤Q*~Hu%9L ]hjZ_14/-*ݧ;Uqۺ3&? JwF3jѝmpISe-+ fQx+ " ͕dh/c7')y+EDn,~\B.Jmk7,7 @*v&ꖹ\kn8"|]`jh X BѩNwL1dH&H(Z(7Y#<_8m$w&Jw7Z5(vq](v G| *:_SoC^p6y 6U8?{pW9-\_JI!.fY b|Dp.epM5!~H3uY^s]VajM6c94AfpUn~t4Bh6@6#Lt%&mf"RV}V>4Ӭ:םPzf}eqy!na ;mKC0bzccسM\_.Ǒ tбFjL(Tx;Ն.2%V~H`xۧ#`*PP dNMD :6e6u*LXY9qU@zZ̍ɔxB?1; h=lh'>7.*0I9*­p ` H* L:$n Ix!Lvpsn?2)f@'$nMf.%b ~ 1 8w^nbI$~ۄ=oiJ{ `Bv*x1d{dȳez"A=%?9 6Ҩ, Đ-(-p2Ru8-Uzr0Ƒ>'2|gP@x01/_1_],UXw1EA{a }w(Jvbjn̆'J˱t>ty6ZZ*t&>[|"!2,R`!A@a.wI„'i7`/{Lª\vC ǝ9k|i~+Ǧm ` aGI$MXh7!€`-(#| `ybO|+)'8uV^,GCx..B;([G|1C u y:Dan\9 xnlsdr W.Tlu*1xXWnn1֤pq N!w:EHm {z4x2+42Lw Zv}vߙ5R| ˟-.A }Ձ}F@SѶ YΑ!5Kp-~CA{IL\ԥ F8ۮ)~XGcLLUI~RX|(7*a}&[(0sM{L\oE-뭸V%&^5ǛjDG_Y!ά-n!xfw' A!@|c˅H*cJֺ7]ߢ>PLL)(nwfS} JEJլo8DW/]Kj<[\x4G&C[Q(!mƩp8#߭Q& !U}ڇ lc݄yƿX].T^JnLL:a<4c3_&Q>81vb5- Nj0^2"EIfardM#8$öy1dae"SftX<ogׇլ?FaWje"<pRFm`#Q/I$8#XsAo /3XS7*N DH'RS9;ޮ>^Bjn5V!vt*5$td4G3UJ=FTw]C4UܷUft"KO SٱlvM8{f A߸A/r(!89- mYaAMOrx#d7iljzaB`*2JdhA y3e6G9(61J8Հ~yfTz\/㉡9Gz^S\k!Nlic60!RKP^P AGGDk><:`? u:GӃ_Glu}χ$$Fh) pgӬLѰ!kHD ?SEb8RځQlOZ ȴ84E!+M@) G𚇃wP7kb.Lz!˵۶RAl"M4Cu?kN.]i\->ܰ)g̖%;Bp DC5@n b/L(H!|pW^qqoD7L‘ {Qݦ{؀tN7s`@p΃/P 271±xݞ|Oq"? Rw}0[\BaYr ,`AG%'j.4yK8m¯$ū;:_u!:^ٕ%y~Gj4x!fErP^or@8RTIE6x7x?%Yo_}*C8)HٳPNme> sB'fm`0<38O1-/Cd//+dr㐰b x> stream xXK67`RkKH$(h^۫]r$mE"r-|Dq曑?3Lƙb;1cwYlǯf) jdEȘ c)$.϶KJ2 %-PKR(.8 [Lf $+Yf8#RwUa+K_f#$-l!Yk9L`z%9I`vn9-oMLj+f9G瓫̓~z䟲teɗy z)r<}4(*ZssVBM°J ]$)R f =63X*x'Σe>A\H3frTȧ@UhnB(DPC A=5gܛ7\E@j&[Ff7|^EGUo] bߛs-9lQ ݝo\AO'ty]> 8 :cc^a?G(NY. /r^u wr?9ebJzy߲]y'4assMa-zpxN K,4($,$um͊#RGpF?= su*3!4 2f4"Z@m * Gжe`(H3nX};{ݬ6;*}X@`RȤY.Д,(9&:hV9yN%j4f`n7Uv:P)C(dDڛ=U{JzbvZ¡ۻ`}:L塚_}=` 2fMպ"=ASz2u?tF}`I:N.^Ë}V]ia:1ek/Sk*l7 +4+ /aM}LJQ9ÒVSVA"@CN8^tpnʌΩ9%emV?g};0b`필 yFxN6Njjn=7} /J3U軨!UAPIt瀧7^K;13u3\ t?:' *S!B~?N!:PM Fz`A {v{hjP# 8 B -M ƭ%:jwz^z}o^;31ԣe_nJh Macĭ؟ s·t(urʨVrDv 3 I9a&@sFY"/*a^"=ggI4:/SPeKg?/z4`endstream endobj 183 0 obj << /Filter /FlateDecode /Length 2158 >> stream xYK_HN_ڱ)r  6sj:#{OII,;YW_?-.2o oqϿoRX߸-t"yj\7D'GXhdiqzwsGkɊ&.LfT>Q┬8g؞qC5DŽ4/^QR&+\V4`aѯ|X,Ydªaer5YI&LF6vm}+6"u(T)ǟnޑ;hCޔOW9_p*;4͌Vf27Z1{r8N&8y:: ݇mB)j#AM'[Pr-s( )Xڹq5S&NSW.H6` i Xv:Ha#$ٵ a.W`v:m 3l굌AsX XX6!ホ}rFIW})I.ѝ5qblNPDIP<5aw<(g|p'Hȋf Q:7㈰,=݀ѿ6m\_)PL l><㞷awUvLJe*[5F8ؾ%Xb5`MeCy*j!E6uf7YIxH<°\dd 'n{Tׯv/u'{?%t^N1]WQ]~5VO3hdUdFjr_8Ƥ\1mjRj909iu@C!@PQY# Z䣃fA@!I.O`Qk#<5=o#!a܂pRCWms1-c:U|?"UTP4w0c?zɿ ^Knt`$f]m>,FcN&e*cGwd1eK!JE赋gytF8Uд+^ѡ|$ǽ^V׎0.̛Q4uc=O-QI~h!nSV4<9Q ``a 0:E?w$X=Bl,)W׀,s1̀ݠ 7H 8L2Qeb[GB{vcbFg=^.)\t~3._Gnrk9ƖN-b8AOy ]0sC6x1Êat|dYw3;tnɔqqˮ3iH:/_$YdS@Hsqx./& Bva}Pendstream endobj 184 0 obj << /Filter /FlateDecode /Length 2635 >> stream xYKs7䠚Kb'Ivkjͣ@KYYP4 g&[>"F}w"E^[P|˯֋Mn C뫅[BLJ,e.̊T̐搭8g}yQhN%- ~auӿps}z4͂=FzPM֏^!-#~ 2MnaCPB3*ХPQDnj3a;AoR!NH87\I;+(gHf 5Wy v.3ke`Q[S" e7گ YIe%p8&܁N,YXP7MJS^AԃCG4)fՏ\t#RZI 84-y_/Y/~\D.YTKP,4͹K! 9)MJHi神ZwW\i W%9".>XO\؄1A lfmcK'Zp򺳷7Y A MQɏ]ΊUi RvC9@Usxzno͢`3qm,٭ғӼut!3x'p b̭9<L2j``m--0x%g⾲+I%94{O SK) |_ATMw. EPzHx9@FwCSy$ Lhv+GnJr(X {峑9Y;U'z%b$ =X-,|r+dlWNP6.n☶B`9[+*ѳRՠeﮥ3!jbN~D+Y KEXB*`Q5H#Ӷ#uY⦽_v(DɤHɧPŌ҆aY(_Mţ[9Ĵ1y'y\Ti>NH92.2MTynUHEbGK.S gB M.._um{Cy}vMd?DiO)m3D4܄ ,|kМE.l/SVTAlZ>֐ç4BɳfHNJY!U7 R .VJDmwPg9/4˱al9b(-4c˙ZBU5Û⧳=` C sK lJ1aXږ- SY<ׅ6> [`*kPdYG4À^AGO적 0j p(u?l[F~$Xuc>$uM;Aqp j5~7Dc@pލ;]%"Y5 {w_#7JP+4^1n;z 3Ŧju[@~c=«] :IR^`xYӊK ]np߾zޏsFendstream endobj 185 0 obj << /Filter /FlateDecode /Length 2578 >> stream xYKF_HœZka?m@l`|h4ƚM3͇,0b_/.rwwpՅ[\|J(XLnbssЅBr 4_n:O6\_&/rVzg CP~)r97CntSe'(/׸AS4O(d~æ""bf3܀k.3ߗk$dٷ\fU} o\ۭ ?oaE r~V-:o2Ԕ#.|gRb(Ǐ/Ġ0 Ǘ( Il %z6{'(GY)1v[ C<lnw ̀#3&Z>n\=L7"sA:ā8|B`?4MY9&(갮H{@Hr5!H4{izV&MDֲ Zd:Z6 FFY钑t=EKŔbEzg\voJ%U-ׂS0$'/Oɡ.Ȓ,NR͙K|ぇF|xɱlPF Yi8H\ϕ;b:HW#+T8*``vт)%' 0wDwT($?s E%>ՍׁCC U. 38OsJDݘF:okDM<%6xh|'f̸u K˰i;eYͩ$gpXTl}YlGM3ąQ0$  yA:㶼GzMV; SP}1eq*&N4%㺩:Z)泍uBYGqu2Aߐؤ}Tgpi˽8,м0Iybz` &>$^-҂P"cZ  0 aU'Xe8[ Jy8 ip-Xh xTX_:<ҷ%q\1/ڍu +1u )\\}kh&M^_uӄr*3d&6[v{'o2ܳP{ ,߉j. um*l'gyWSXsvEnzJڃW[z|ӤC'|{cUrwmL?'`Mh.aY6.=1-qYT-^M(ǩ>ru*h2+2r ^7&m 2j_ʔT:0{A@(\ ӯnZxcaN >~:R,_nͫJ~~GYxǀ:=j82s"O_￞hendstream endobj 186 0 obj << /Filter /FlateDecode /Length 1360 >> stream xV]D}o!6v3V@m޵w&NR!;w♬CZi9w=;8bV<}|tVӷɫ_'ƚL!SE( t B#,V8Y +דkkop+ hnaY1jPh3vњUFUȇ5Yn(B]#hirװ(n?KIY.R㒧\jǥ~QB_:@gW "tP2׽+%6mfpPiXfXpfqW2{)vlw d73OslP\~vO@Bg ! Ez6.%w4endstream endobj 187 0 obj << /Filter /FlateDecode /Length 1301 >> stream xWKoDoaic~^D XiHHArfüb;$+S~L2PiwWUW]U̓ Ng=y`˭s|3@`gq;*؉/h,89(,V+tYo\HAH#﬏tzv.TGKf0Șe'b JAspGC?\8="k핧A')@a`)= Qh ZHCF (@fc NGDYCVW J\ ]8wA-9$qL5s I& Ӌ"3sޗzVE Z @O/~mjȗ<1CH'SwՍW(;rqX|N"Q{x)*s:;+; e)RGPT;F/r9@T}nZnpKoS[&ybfχ a`SƉ*Nr8waG(f=@xK q`h;B!wA :X!.:/RU0C oU}BJ KbTgB(PnakuRK7o#pJ0#y YP1oˋ-ʽ}i٥d> (*tk%(jg='栛P;п:R!U#e}]ciW'1E4-bA꼇$9IyF>> stream xXK67ۗI[d,fY$8MVƶzly߷dL>%ŪW_}iYinRN77NÿbsMaKKBNԅrMU0ؔ`! %yvh^ gEV(%״'~6,[rJf%Ul 5ʐ1X aЋĈ y aeatahI~v6avj8 ҢeȻd>PxKŢ%?y=]DHR-Mޤ<1i&}wuY!.*&:V|DK yWݣOTdxS/Ur#vv3VmXϒwn*&IS]E 0(/l~%'^ߥێgm1D'z{{J3Iī q|H\ 4:%i2DӐcD60htɓ5x,ݼ!1{-0 &.M"[$qL75. {꘬܇B|&3[mb 2`ؔ EuZ2' Ul.uw . nVus5 6)6kq]ȇ/ց]*-3(4i4 v1o}1qd<\8Xf&mȌ̚5bAkFebihV!VRV`4nI4P0>h :eҡhKcCj)9֫čulK+C:>?"V#AI@[ S&Hnu \D 009RK[0hVKIldW{o~ ?ЬhJhO{]@QO;va+q5hL.01NlA9 P}֦MEb&?H+i *_.qc6dS:b&|40f \a2)2RĚ FSH.\8uĐ4-Nɔ=A17Y78|T7T($.hJ-*(^r?'p }i~,W߂7tP#w&j^xsIlL̾F -D;6UA Qʮ/rR9!:W}^DIm›p:ߺW#ҢLY^@!{t, EX]u>@~n02JM(D5^hN3:OV hT jA;D*, J6L?wP&ޅgEͲ=er7 xZȋ>~T4]p4İBjwW6akd~<00C(x #;wf a嘘aݞf J0PIXP HSTn2 @n#.vV)z>WRu y'PFˤb=H|V o:*hZYю:j Bpvfds"{T2 s!]Ƀ pXvRvNé: "M7XcR eC[Nz]BXyM8,=`Pqqރ'OHAQPԊy”AO7A^K~"렼?L[ -XҸ.(m t'%.1H0D^v̒]#`p`<ugۏTBj;ߗi\adPba-AK-u;|-gt|-#[1;|sI]_z zI6lA(Cx>%5eR\ mzp>j-pv1s+endstream endobj 189 0 obj << /Filter /FlateDecode /Length 1909 >> stream xX[۸A6/*R$Eݢ ]؍>)>r$;ËE2=3~sIӤ?lgE}Qe#Bd0*4Q4DR$vFJaUD j黏iPKIJeE M}e~7MOdE)&@M *5q%%4CET-q+ B#<0;2Ҟ9$4L)gXU%9 <]Zk̿_Fhӂ<ֻEj \h#@lp =,pld}:sﳧmYHŇpGo'Og7%yQq2n \1p׬C$]>wN(C~#%ĘMQ"\;ףۺD4P4KI~EdO@+Q Ja2/QH3]=.p [ Wd&DWnѦqC<.㶆($;gR> E5D֛,nl.!A a+飵 ueu+h,`bk + VƇ}d.2:m M縃i&%! hElK%%\p%g0 7݅;F^h)n-YTih*ڋ5X%Ul_"9ϝ㺆9 ~mL}Hs9eߩb$.q)ս\k! ]r&*e'q妿B40nʙR55Uش#I1=gA}]g^CC)>20>RE6k%@Mm{Ejp3͖]Q@z qAC]N9}vooW+MPq Kqչ[@eXr= MEhv^yW qu90p@ݜBWG%㊫[~6HtM0?-Aendstream endobj 190 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 543 >> stream xcd`ab`dd N+64uIf!CΟ <<,~ }M1<%9(3=DXWHZ*$U*8)x%&ggg*$(x)34R3sBR#B]܃C5P\000000020]°QLɲ ,x?v~bq_}B p> stream xU{LTgsQa93ntKPUT.ڱpQ:}fD._` raEttJUu*5mcXۤu^1a?6|ɗ|^BXm{ްnmF*iB ^IJ_+t 0})n9MKQaڵ"#-!"lOHIRSi;SVG_E3֭#MzJR4j#L) OFP%=Yq+>JJ_Ϫ^xP b(}hR^&ʐye*8!F8R[g!l=lLG"(\Ol!"S|l褯0k:za ƒNC4xFzxسQ7~UA\$h. Nz[ J%U֒ #p<븉;Ṫ .9?怜|¥Uw8 ܹ["{?bHm7;LY49/m _H;;bc_ ;ٸh(]Y8;^wC`-c^Gwdd%臐3M^z SLꟐ։X Jj\֥3]psa):h_-}p,Z=Eq#=!\Hq:izP3P |R#twoDudCUi߭?}Z- \:H-6d·Ⱦq! ◰EUZ:@. XAR.tUG |-`UeqlZ.RPVtۺ$10%!?QidZtD*4) xK5D"H h/nW X/]Dc&S< אoEގq=RitT󛊺jkˮiqų,o,G&+_u;NL_wnG:> /Filter /FlateDecode /Height 173 /Subtype /Image /Width 149 /Length 219 >> stream x!PA>nX܂­h1 $[FT2k{c|ZaչFfT羾_|p(UGգQzT=UGգQzT=UGգQzT=UGգQzT=UGգQzT=UGգQzT=UGգQzT=UGգQzT=UGգQzT=UGգQzT=UNF¯endstream endobj 193 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /Colors 3 /Columns 149 /Predictor 15 >> /Filter /FlateDecode /Height 173 /SMask 192 0 R /Subtype /Image /Width 149 /Length 12958 >> stream x]w|۟˵B HT@(*RDESDKo* ("(@AHBB H/wɕ}ٹK|33BОA4ihAP?|kEp'T*eɻvjC:tPXXhGdzZD`w6kݦ8WvveR1g+8F[7òe˖/_nԵʸ.CxހS /:9rd-C毨Ņ2|"Ж<^8NNN-F;'0{8{F*ޒ j̘1?#/̶ve=V_^uݻwgI' 3f㏹H{5:L|%p?/Fha'xnpש2Bb4pEɴxuj*)Dζ+^H⋉'NMi۠87\%-鵒xhA:z8WubNqOʀ;xI@ EO&) u=Z8Z!Vu={ƍ-:g_$Bn4{WW*>OɾB_ܫW5E[sρuٻT"o$%:\6Rnm,ooo˄:>Z1 &xT*uaÆ si$ȢT5mpכֿL Mq\'N :ԔFk7a„BY-h0[yioj$ץZ,rhꫯr] ɶy63b .-[, geeVqЌ0ZiiirADSLٹs'0ۅ4uG\BgggS?~wus<i]yVBclhccSQQ ubmzh>zFane Zd :?Aksy.,f]/WN m=@}2ps]h<,5<e4[GWHp%w-ǯJ DV\?DmDp(Q5:Fj㾗dvFܳѶI͓f/j*+s_|ܫP 8OE1 AVͱlA$6 ]IAѬ.A7CjMwKQoZ Ѩ1džLX; U RT"Bd%Ab,Af(lq,Uh=3ɦ|'/%кQUIq2$DklmQ8X ا`_>f6tzЦMq+%є\oN(Umтȩ#~^GȱL ퟯ{!^/s1\@96R Y:2іG):eP ۗ7!W(yahY$E~lBoBart/^C z饇jj{QfP#$h$P4 YIhD7Rj]B~dF] tE XS^ 'p=3xOUXk޷{QomAѐK8,z=rcWp];A݌}NAo@]#C3BFک?ra"1"C~;GhU*ЇId|q\&zgq]悭^C%25w(Wqf('Q x5a5?#-?#N:oj%n EuBx>K/(b5RP碢XBkǛf,~x+9GhL. ? B 5u[Řbl# B%8-{w~ ~׃6Jutf3 "pmysWSq3a4q3[H:N^O~{:nfФU/$aϸFr%%.WS'Yu5IZ:/xȴ=V<5=^P,LA]$=71|4z~z49k~Okb%tҹhY@qSR3z aS:uq?:o$ݻ ㏛j[1Z=ȝ@;uu4t@ߔ8m/ ~R>ՂX6h*ޏz YtB쩻?Rcu4֌ө`~|{H:Yq1'uͣ6IѪ[vq9$L$ OFYsDE߼U V Qe1)ԇ?\cqY(TըLՉ&Zc;?w?w~^-dQCc%"6 v_.Ss!ß#Z oNEB4phm`M?Vvew%f5X 3w^Gׅ6~ <(rwPtRi4WՇ?Qi> ah3SzΜ*KH~̣*dia$/X?璓>~Y pm 0H:F*Bh@f.HZ2_~7@I황}^uV:,A̞ @܁iLKIm,%DhjS sꈛZ=#m@]КY]=hK ? ?AQt{DVJ."B HP \ x%C:ę3~X CL `5e\Fx4C-A:?0lۚfnL ArݡkX&m  v)TErp9ǍRxv:2yQ,2z}FT⃽_:G CI{ D4 Znj4svtrdVhS\o3p9k-X{XC]5uY` ~qVc;t6]aZڦof5*ݏHY<{vW$@/Q"4ջ!PeLf6`(R3'[ό@ǚ9"rݬCEIQm5 ۈ eAz`J@ h#!blJjYxdܡV"@]ԛnv@u d⮷ 7oT^< xcEvP_~wן wv0}H7htsG3_-fd7ĊmDS#uF)%Y.~7]st'E3{H7ʎSfx%)է|L>w`RxVwC>,;]E}5%9"7'@BT IzJK$d n}K#5+)iF"kz}!x+'^ך)[|z:=ts+w{}`r`]VZaCI2nF@, ơ"zř*[?g/I+x]ԗ͵e'^@We; re Z1oC,HMg֌~ǹnDҋU kTƕͲ6k.{XGl]v͜H̝I(fьhExhpq"RHPW\e٬@ଁYC@p)7-~Tʹ*q"O!nV2cIsPu %xEBcP(熛 @ [zitݨ;%Ҷk_;b䤺.LTk+۞4O`S5VJUH# #& PnM5*ru13l6;hXH ]Kok?LW5x4aYƾZVVN5!BJ6=:C牅{bkgֻc6?j[_!o3wzVlvMm7Q>굗u |Dɺ!%b_~L`<@_ha-P~au@='nB @2\I-׹iK+5UwZg;/GxtM{Mk\e]FB _&H*S9󡝉v3BTgUvHVi{q7%$PQ(=-嵤¯00md5]p$n jf<4S3?Ki0 h M@:^NTo\+ Lo+wyKK}aLo?+cK 7P fnc7A k4欗|y\ϱC>un=P BRߊ<[ױXqIڕ}j#1Br[1eP'kx_ kh;Ulau1H`3+”-X Я7&%:2{w{ԺgGL;3 Qq} /l.[z~ (#BC: [ mVz ioBtҎCNnKU.&eàZ殼'O:.Kk9{S#Gtcdx@dm퉘!T.]}ȟ-3[i!fɜC/w% ;Jډ;9-TU_ !CcH(ը˜dhvUVdG^Nw{V }'IHM`KC|[_KB=CJ7EIdOvَ}'zk7v96]v9avX%JW+Uq1/hG1EwopTgm, ׭ ZUrwa|b?e^6~%˭c6cS+^d油)ޟNiPISy]{07\۔SRim4wط Wùhيs^K,;QH3CPɬ\kbvY}ΒGբo'kJсKPVS)^Vl4 #E;k_KLynP&r*58?@]~ĎRSjqt=MX-xE]iw}1\oV3(vƟLQ̹7OG~WBwp6HԚj2y 7*p?l0to HB>yf]CInm-r&QWm?bl;q'ޠzPvd w]WOQ5j/̝-55 6+>(\>iO~}KFͻe}?{:}gb'i?|Yc?̂ J@(IN]k`i$BTs؁`Ic^Zh~S @:vb/7.e78| $'{R"Tqw?;~즗8\ ]9s"SxHMܚЭ>ͱۋ=m W):kVԱBn]%\;0+"p_Y0׷#H[:zirL_Y U(=\s勐=jba_ ߕ{_*7Y褀xY?+mDu{ՂV5̠>Nqz_~U@,4uu<2YRDЇo\hฺ?>s( !E?#pK H@i/{;y.33J?x}L$"i^Dn[y9 9;4Ӏ@N'ȝVׂR&/kíVT"j0Er T[h|`^Bڬn޹:,h.|pH/<'OX,䘟m 1~)rTJ+9cwVr^W;rNHȓvu}~FN*D_ZG3m? Q|7r=yHԷoۋ;C$!#-CLp@A79g79:J̓ :=jꓖvxsDTDZNz?Q_yBL  wF}.ru 1kp5/~fjFnv}?Ne3zRHԴ<{Z~^x CbI'"ͮH}5۴%8nI \MZsw,c{VT{$ .:|"k:(5j*2I[G|2qWr"EݐՀ ֘)buNҕ5K/jtT%bMԱAn=eMd톫.d?\ժsdK*Wgiբ|| )Uz1]pzM!wlhF x{NuRG&7#˥,=poH`w&IZO*ɑ/Cs%މ],(kJׂ, SONז룄By$@J^ỹxwXhO0\'=$h@u\* ro`^[$ÿ,W*UJ5u,H\~xf2Sꮍ+|S,i +2H MB#O+ilkCث\+w/": /9N`rIsK Rl+@"_ohv~1s@kk6}.v#++g@Ŗ+F G.3EUeW{ ](;4K3ǂ4WC$mANM RS m'T-<-v[QGK2!x.?C<9͠Uagq"h'\uWQ3T/&w>@v>p:N _uϏH+Rv.o?98Yd/ h!FTR| M䔠/ EAU ^nng vejY?Z%,^\gw'=$tҤ$ϓ'}:OSkQmG߱sWB]"I+.C %P`ö́׷׆N 2zJu}E*,+yG3eAoA > B7,|(clzBr`D2"tF>o<+؂z -8r!o*NAM cZCD1i y\ڮ, \16Qҍ{ņ)44Cwp?'!V4+$Q0JP#)tJp‡dT(Y}Ipk=$hd3m"_W{V0KB:1g˘YaK((s_Yc6̞& -',KYeЋSH/tC:mwYݣGG+(|uغu ,`lkkI5 $u"F8k{a"[)O@鯹 ?r@i]i??DWYiAz.F0RL[Bjح7 g1A\ C}Mݵ{"Źzj3,ڋQLguW <ж1P O"rZw}evb;#Y'+Z_yn_@Y=$s;ϋаȌ<<МX͜HK*w4Hw |%Vhp W+ۮx/7|CqˬJ k [++BBޞ-6|VY0:%񴍨BU4',R}>&g5^gU <O?m]uQ<>)2-_n%8AܥE\Pjb%Bݜi@!oCJwJQƩڛ kI HmE ]tm+!o\)'v LRM]W kK~}@;wu3<#NBE{gr₪+n!x?pĐ494{K Ukhؚx>z/7^H-Yם!텡7n1ɟo=Ǐ-{4ۯt*W%TjR =mtŏzFo"a'+Q3w8WlY7>g_6 xQFF ry|*[ Gܛٻ 4&wsxA[YQ¯`|y5m7xuV$ ,oy?4vK lٻar8]&DK/ʠ#i 8ԕ)7%>B*|lDG! 6"Ù;`=ԇzG60N5 V Xju)ÔV뿘kiL>-7'F*[fN珌7 N>s&UT۟޽{_y^BŅh] A!4V%o; ݹ8W9$B+7ICc炍1`HӧO߾};K=ΐ,H8o:'؀OF}H']0 -'Ani\(|o)X_>ùd\4?R)t]WZjwKR: NfϪ"ޠ_B@ 5$X.l>-))qpp0q]h<G}ILuf1Dͧ~ UFNς)Qq\e!&>;9|J@T:[72U| +/_ξ ڠQ3ng5.ջm 1&.G4Q*%bd܃ͪd2ODG;͠tމĖ YQB )s| bvJܝB zR&Jb/JZ.jX2R 0e %=={f(F0?U@Sy:I(lhP]:uF#u_UpPx]`xmut ^L;"S~ʺDsO7-sη~F>wJo<;yS_D~؇s? .ud ",ͦ{Inlt v8hռ%!cjHċ,"Mdh-nڈ qi$}5#Ȯ]@S;D0v7}Tg~kX^?Y0\b2Ds[B J47m4Q=)Q"|mwxA,[Y#1fYFvz5 eJWY3gsWv l5'<|r:}dW&{e:hf͚GV>Uˣq+i596pcdC;opκ1Guܫ-rKWykM%b7zҧVCLacc59<X\\lm?Q))#%By%5-?\H\s 0VD@ pe3Z(. ֓7n=m?E.}972p18؏;O;vh \\\W 4(O#$TTT2[?LPɬ\}fW:Mre˖-]hܺuLJaݏ4(E]}b :}tbh!ӧOlހȫ=/sc0w$ʯl$Z?> stream x}SkPgHV IV+XjoJF ZByD @ pó`xB,hՖJE+?tDDg;."v3;;{s9Cq\V-^ьkuXX歴?ف ۳sx#B∃|pFԱeDdd *"Y)BBԺ($DD&K%:P)qU$Ȑp:\dKo-~  W5Eh2u | ?"$>%< /bitp`$l}DgZ>ՖM{Nkm)#=VZЂ-N&)RwP|xqR5Cӣ L؇G{NHv#fzx <ƿڂ-\kaG ##62r!"YM%pʕ >R4>vvOC9A^_oЗ05jP/wn[ʆ&}~-j?B;{hdU I$eN g/ڎqG> stream xXK67nbF|,"P4HM A~d-m,EK"mٻ-9C~g3/wl};;{ef4nFN:E5nt׋I3AxN5*ɔ15Gc38`EXN24uQE 2AeWe!B&O #T,3圌L`%Fd*(Zilp7Gt>  ~Fv2u82c*f;Pf\`/~>Q}ƚKe/t@0EEB͢E& ` ۬#)w;kmuWslYSĔPįQ[S5CP]P%tzI8aNʢ n7Crx?vI*%:^k¥umk8FN@v)ɔ0 U]a<`hOf { rdI7Ÿ-z2zf \@*9TKC='_;IIeB}.s[WkkI&  C4`7? HpK8mh֛A("hlCPi/l˿!E *2w\&v> stream xXˏۃ5;R7hmEA 5umɑ4$"eyȏ~\^|_fu˯֋*y뇅= s\fqq޶$r$$dCdeywJ,, lun7ЃP"d]ֻ4Yhp)2)Bݡ/ ʾmvj?T[ cYV(n mE6ωӌ,_oЫ$\‰C{vؠ϶^$e~i@Ds6SC:"G]5B1Ch% FP(0VKؽIm2L2X p5Y.A<˝MH |15{Z ȡ.l/rz9k۰c{(Х'X¡9Bi{L1Q)s ѡ>Eo. -7>!8>۟l1)W!DL*:˻eI$d:U DtmP臨3a[}h t,۱g\f0/{SE<8Q)4Qxj+gS]%sR )b>a>( 8[h AJNF[;;цnl s VGb}3>/8p yκ$cLndn jxl?)^C2O͔Wqu+_)1bD5+=`WBEX뾯Jy|¥ #pDzܠ/Uqm%zhj ʞJO!T`a9iA |}c*TNmB*wrmuH?7. >Z].lfK;quI \dXTn:F Pfhz[=y0\7Orau.(L=wnD1 t9ۋɌK턢LfTDM "3P]ϬsٺO y&3١93Fl`1."ГjPz2Τ\o*Lr49Na`q^ V!d>~rZ'+]iqQ/3ě04foWDX(*KИ~01R{%NwE(Onϗ[8s- g&>n3|oF>x2޿u"zwQ@^֎u!'9l00X"{g.%i9"Hp4C'3xNQpG^BVotxIJ'9E[Y3E& !ߎrddX~ Y_NPB#I7t|:g'_fYF2&g umY̓E/o#`]P7#`=rV1^ɠӦPzO.Ucendstream endobj 197 0 obj << /Filter /FlateDecode /Length 820 >> stream xU]o0}WHVA@ˢb{b!Lo2?rC9WY- ݴ +M+"1!q3pg0 &`\8N Fe(0x񢎬}Fy< hgѾ\e:]Y,j$*0OŇ6xw|vq*K }CRe2NX,g2e'Ԩ3[q6bR@>Af*,Eʳ=jۖ(0`? nޫolq> stream xYKs7[ۂh|-qu$e0(zb232ۍSIF_ʂJ .Oގ–'~ 1) *HK]X.GrE)̒z5p +EQ\!\%EJT'~?J`JFezwBO1Ҥc&Bф(>D2QXc?g_6ׄ+^hq=\Y>99N ì%waw̐IN x,/!arQ2L1(Cܢev ̿p'bH嬩oI͢^ͯ ̹>èf}`<DQ`C?JxM&E׍!%ǰ0")8T X\<$f0dAʒyۊS&]T՘iK8y4%Y3bڐ x`\$l1IFgNl|V Im-pTt^{8"{gؤ;P&cفȇ6E4To[,lzP"ڶ춋o=RR Xq2;`˞G9$hྺZNz-a%HkWIri;G"XT)AZSm(1(h/nRvixE}Qݤkqp^9H_%*j ?6G?=?0?p7 7EeIF `FBOmƩ:,x;27T |miG~l܍'/~xHҥG֝wZæKCWT<5:c \kRә娆TXkU"EL`.߸>xR 7ǯۈ5T#anl ,qwd]:, H#9L YvPVY{vfQ~ ^'7Z. }\OZAo:Lg63t~W{t&u鶕R}@-ː`Aej.nH9FO`ŒOD`D%DW9 jȧx4?NRz"M9F#ȓ^n[ 5!@t=T̈́+n:!c_g<;فzB'u)/"UEr˺rqy.FZ¹iyv""o9,jPqW -}`i cKN20TU08A vXJ/-T5'4ŗ?R82FC5ct ^d7/5%RΝ(iK1 3> ! qjGqA(ɇm?ʔ,T=)Gd]IwYjЬ01uyz#dUG7ȝqH}>f6DI`ۗHBR= 1: pIH*jZ3Mnh?s5Bendstream endobj 199 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 881 >> stream x]qLSw{밢61XcflLfRhK&PQN) œ*Y+UhV4ukJPԬl`αd1ی?1gwKQD""EڭљZ7 ,[[CqkE:1iKdDz! Wa Ԭ$b268K[TZ; Ycj&+.{A&Rhv`X}^֠Yc+j Zo&rUsRMDC2T!LQۨhXd"(sc,>LJbn[YQ `` % f)gƮ MW7A {Jsyv~<ECPԻ7ϩ鼅sƹ_\\-K|I}7ĂA-r[s?']Zo`\i9S ^._J_v&<Oyibfm+leI|(fEoiq?=fRG|N^ (@J~7~=Hn_Rӏq $ȝ{F3AB\-{sDZ;xŽ jkG;[缧["ݽTߍ7G0yp14nug̣&;SngC-G<^׾| ,P(ڷ?~ d H0A. iJU9V%/_j  3Y`Pnvh|ɎwTәAN;Af6eeHWA,qJPLvRsJH-'_kendstream endobj 200 0 obj << /Type /XRef /Length 224 /Filter /FlateDecode /DecodeParms << /Columns 5 /Predictor 12 >> /W [ 1 3 1 ] /Info 3 0 R /Root 2 0 R /Size 201 /ID [<03f8ff739d0fbe41dcd35d839579131b><40b6dea1398fbaf397f19aa7c076449e>] >> stream xѯ P{Ͽ8u0 C0L>]PdQE "lV,CbZos("0[(d φ @ ?y$}\\ y+\log\left(1+e^{x-y}\right)\qquad &\mbox{otherwise} \end{array} \right. \] In practice this gets more complicated as one has to keep track of the sign; and special dispensation is needed for zero ($=e^{-\infty}$). One can thus deal with numbers up to about~$e^{1.9\times 10^{308}}\simeq 10^{7.8\times 10^{307}}$, although at this outer limit accuracy is pretty poor. \section{Class definition} The first thing we need to do is to define the {\tt brob} class. This uses the {\tt setClass()} function: <>= <>= setClass("swift", representation = "VIRTUAL" ) setClass("brob", representation = representation(x="numeric",positive="logical"), prototype = list(x=numeric(),positive=logical()), contains = "swift" ) @ It is simpler to ignore the first call to {\tt setClass()} here; for reasons that will become apparent when discussing the {\tt c()} function, one needs a virtual class that contains class brob and glub. To understand virtual classes, see section~\ref{logicSection}. The second call to {\tt setClass()} is more germane. Let's take this apart, argument by argument. The first argument, {\tt representation}, specifies ``the slots that the new class should have and/or other classes that this class extends. Usually a call to the `representation' function''. The helppage for {\tt representation} gives a few further details. Thus this argument specifies two `slots': one for the value and one for the sign. These are specified to be numeric and logical (NB: not Boolean) respectively. The second argument, {\tt prototype}, specifies default data for the slots. This kicks in when defining a zero-length brob; an example would be extracting {\tt x[FALSE]} where {\tt x} is a brob. The third argument, {\tt contains}, tells \proglang{R} that class {\tt swift} (which was specified to be virtual), has {\tt brob} as a subclass. We will need this later when we start to deal with {\tt glub}s, which are also a subclass of {\tt swift}. Let's use it: <>= new("brob",x=1:10,positive=rep(TRUE,10)) @ Notes: \begin{itemize} \item Function {\tt new()} is the {\em only} way to create objects of class brob. So, any object of class brob {\em must} have been created with function {\tt new()}. This is part of what the ``formal'' tag for \proglang{S4} means\footnote{Compare \proglang{S3}, in which I can say {\tt a <- 1:10; class(a) <- "lilliput"}}. \item Function {\tt new()} requires its arguments to be named, and no partial argument matching is performed. \item Function {\tt new()} is not intended for the user. It's too picky and difficult. To create new brobs, we need some more friendly functions---{\tt as.brob()} and {\tt brob()}---discussed below. \item There is, as yet, no print method, so the form of the object printed to the screen is less than ideal. \end{itemize} \subsection{Validity methods} Now, an optional step is to define a function that tests whether the arguments passed to {\tt new()} are acceptable. As it stands, the following code: <>= new("brob",x=1:10,positive=c(TRUE,FALSE,FALSE)) @ \noindent will not return an error, but is not acceptable because the arguments are different lengths (and will not recycle neatly). So, we define a validity method: <>= .Brob.valid <- function(object){ len <- length(object@positive) if(len != length(object@x)){ return("length mismatch") } else { return(TRUE) } } @ Advice on the form of the validity-testing function---here {\tt .Brob.valid()}---is given in the help page for {\tt setValidity}: ``The method should be a function of one object that returns `TRUE' or a description of the non-validity''. Examples are given in section 7.1.6 of the Green Book. In this package, I define a whole bunch of functions whose name starts with {\tt .Brob.}; these are internal and not intended for the user. They are also not documented. So now we have a function, {\tt .Brob.valid()}, that checks whether its argument has slots of the same length. We need to tell \proglang{R} that this function should be invoked every time a {\tt brob} is created. Function {\tt setValidity()} does this: <>= setValidity("brob", .Brob.valid) @ Thus, from now on [ie after the above call to {\tt setValidity()}], when calling {\tt new("brob", ...)} the two arguments {\tt x} and {\tt positive} must be the same length: recycling is not carried out. Functions like {\tt .Brob.valid()} that are user-unfriendly all have names beginning with {\tt .Brob}. These functions are there to help the organization of the package and are not intended to be used by the end-user. Clever, user-friendly operations such as recycling are carried out in the more user-friendly functions such as {\tt as.brob()}. If one were to call {\tt new()} with arguments of differing lengths, as in\\ \\ {\tt new("brob",x=1:10,positive=TRUE) } \\ \\ then {\tt new()} would report the error message in function {\tt .Brob.valid()}, because the {\tt positive} argument had length~1 and the {\tt x} was length~10; and the validity method {\tt .Brob.valid()} requires both arguments to be the same length\footnote{Placing the above call in {\tt try()} and showing the error explicitly would cause the package to fail {\tt R CMD check}.}. So now {\tt new()} works, but isn't exactly user-friendly: often one would want the above call to recycle the second argument to length 10 to match the first. This deficiency is remedied in the next section. \section{Basic user-friendly functions to create brobs} The basic, semi user-friendly function for creating brobs is {\tt brob()}: <>= "brob" <- function(x=double(),positive){ if(missing(positive)){ positive <- rep(TRUE,length(x)) } if(length(positive)==1){ positive <- rep(positive,length(x)) } new("brob",x=as.numeric(x),positive=positive) } @ Thus {\tt brob(x)} will return a number formally equal to~$e^x$. Function {\tt brob()} does helpful things like assuming the user desires positive numbers; it also carries out recycling: <>= brob(1:10,FALSE) @ Note that {\tt brob()} isn't exactly terribly user-friendly: it's confusing. {\tt brob(5)} returns a number formally equal to~$e^5$, not~$5$. This is documented in the help page, where the user is encouraged to use function {\tt as.brob()} instead. \section[Testing for brobs: an ``is.brob()'' function]{Testing for brobs: an {\tt is.brob()} function} Function {\tt is()} will test for an object being a brob: <>= is(brob(1:5),"brob") @ (see {\tt help(is)} for more details) but a small package like this, with only brobs and glubs to consider, could benefit from an \proglang{S3}-style function {\tt is.brob()}. This is easy to define: <>= is.brob <- function(x){is(x,"brob")} is.glub <- function(x){is(x,"glub")} @ now the user can just type {\tt is.brob(x)} to find out whether an object is a brob\footnote{This approach is fine for a tiny package like Brobdingnag, with only two or three classes. However, in the context of a more complicated package such as {\tt Matrix}, which uses dozens of different classes in a complicated hierarchical structure, one might prefer to type {\tt is(x,"dpoMatrix-class")} rather than define a plethora of functions along the lines of {\tt is.dpoMatrix-class()}.}. We also define an {\tt is.glub()} function similarly. So now we can check for objects being brobs and glubs. \section[Coercion: an ``as.brob()'' function]{Coercion: an {\tt as.brob()} function} Next, some ways to coerce objects to class brob: <>= "as.brob" <- function(x){ if(is.brob(x)){ return(x) } else if(is.complex(x)) { warning("imaginary parts discarded") return(Recall(Re(x))) } else if(is.glub(x)){ warning("imaginary parts discarded") return(Re(x)) } else { return(brob(log(abs(x)), x>=0)) } } @ So now we can coerce objects of various classes to brobs\footnote{The recommended way, appropriate for a complicated package such as Matrix, would be to execute {\tt setAs("numeric", "brob", .Brob.numeric\_to\_brob)} and {\tt setAs("complex", "brob", .Brob.complex\_to\_brob)}. Then, if {\tt x} is numeric, {\tt as(x,"brob")} would return the appropriate brob via {\tt .Brob.numeric\_to\_brob()}; we could then make {\tt as.brob()} a generic with {\tt setGeneric()} and define methods for it. Doing it this way would save function {\tt as.brob()} having to test for its argument being a brob [carried out in the first few lines of {\tt as.brob()}] because {\tt as()} has such a test built in, implicitly.}. The {\em only} way to create a brob is to use {\tt new()}, and the {\em only} function that calls this is {\tt brob()}. And {\tt as.brob()} calls this. Note the user-friendliness of {\tt as.brob()}. It takes numerics, brobs, and glubs (which give a warning). Check {\tt as.brob()}: <>= as.brob(1:10) @ \section[Coercion: an ``as.numeric()'' function]{Coercion: an {\tt as.numeric()} function} Now we need some methods to coerce brobs to numeric. This is a two-stage process. <>= <>= setAs("brob", "numeric", function(from){ out <- exp(from@x) out[!from@positive] <- -out[!from@positive] return(out) } ) @ This call to {\tt setAs()} makes {\tt as(x,"numeric")} carry out the function passed as the third argument when given a brob. But in this package, the user isn't supposed to type {\tt as(x,"numeric")}: the user is supposed to type {\tt as.numeric(x)}\footnote{Users can be expected to be familiar with functions such as {\tt as.numeric()} and {\tt as.complex()}, which is why the Brobdingnag package recommends this form. However, this might not be appropriate for a more complicated package such as Matrix because, to quote Martin Maechler, ``it seems very ugly to define more than very few {\tt as.FOO()} methods, and very natural to work with {\tt as(*, "FOO")} [constructions]''. Of course, there's nothing to stop a user typing {\tt as(x,"numeric")} if they wish.}. To accomplish this, we have to tell \proglang{R} that function {\tt as.numeric()} should execute {\tt as(x,"numeric")} when given a {\tt brob}. This is done by calling function {\tt setMethod()}: <>= setMethod("as.numeric",signature(x="brob"),function(x){as(x,"numeric")}) @ We similarly need to make {\tt as.complex()} work for brobs: <>= setAs("brob", "complex", function(from){ return(as.numeric(from)+ 0i) } ) setMethod("as.complex",signature(x="brob"),function(x){as(x,"complex")}) @ We'll need similar methods for glubs too. Better check: <>= x <- as.brob(1:4) x as.numeric(x) @ So that works. \section{Print methods} Print methods are not strictly necessary, but make using the package much easier. First, a helper function: <>= .Brob.print <- function(x, digits=5){ noquote( paste(c("-","+")[1+x@positive],"exp(",signif(x@x,digits),")",sep="")) } @ Then an \proglang{S3} method: <>= print.brob <- function(x, ...){ jj <- .Brob.print(x, ...) print(jj) return(invisible(jj)) } @ And finally a call to {\tt setMethod()}: <>= setMethod("show", "brob", function(object){print.brob(object)}) @ This two-stage methodology is recommended in the Venables and Ripley. The {\tt .Brob.print()} function does the hard work. Example of it in use: <>= as.brob(1:4) @ See how the brob object is printed out nicely, and with no special effort required of the user. \section{Get and Set methods} To be anal retentive about things, one should define {\tt C++} style accessor functions as follows: <>= <>= setGeneric("getX",function(x){standardGeneric("getX")}) setGeneric("getP",function(x){standardGeneric("getP")}) setMethod("getX","brob",function(x){x@x}) setMethod("getP","brob",function(x){x@positive}) @ but in practice I just use {\tt @} to access the slots. These are just here for good form's sake. \section{Length} Now a length: <>= <>= setMethod("length","brob",function(x){length(x@x)}) @ \section{Extracting elements of a vector} Next thing is to define some methods for extraction. This is done with {\tt setMethod()} for extraction, and {\tt setReplaceMethod()} for replacement. <>= <>= setMethod("[", "brob", function(x, i, j, drop){ if(!missing(j)){ warning("second argument to extractor function ignored") } brob(x@x[i], x@positive[i]) } ) @ See how the third argument to {\tt setMethod()} is a function whose arguments are the same as those to {\tt "["() %] }. Argument {\tt j} {\em must} be there otherwise one gets a signature error. I've put in a warning if a second argument that might be interpreted as {\tt j} is given. Now a method for replacement. This is a call to {\tt setReplaceMethod()}: <>= <>= setReplaceMethod("[",signature(x="brob"), function(x,i,j,value){ if(!missing(j)){ warning("second argument to extractor function ignored") } jj.x <- x@x jj.pos <- x@positive if(is.brob(value)){ jj.x[i] <- value@x jj.pos[i] <- value@positive return(brob(x=jj.x,positive=jj.pos)) } else { x[i] <- as.brob(value) return(x) } } ) @ See how the replacement function tests for the replacement value being a brob and acts accordingly. \section[Concatenation function ``cbrob()'']{Concatenation function {\tt cbrob()}} \label{cbrob} It is not possible to make {\tt c()} behave as expected for brobs\footnote{The ideas in this section are entirely due to John Chambers, who kindly replied to a question of mine on the \proglang{R}-devel email list} (that is, if any of its arguments are brobs, to coerce all its arguments to brobs and then concatenate). However, it is possible to define a function {\tt cbrob()} that does the job. This has to be done in several stages. First we define another user-unfriendly helper function {\tt .Brob.cPair()} which takes two arguments, coerces them to brobs, and concatenates them: <<.Brob.cPair>>= .Brob.cPair <- function(x,y){ x <- as.brob(x) y <- as.brob(y) brob(c(x@x,y@x),c(x@positive,y@positive)) } @ This is just {\tt c()} for the two slots separately. The idea is that function {\tt .Brob.cPair()} takes two arguments; both are coerced to brobs and it returns the concatenated vector of brobs. Now, we need to set up a (user-unfriendly) generic function {\tt .cPair()}: <>= <>= setGeneric(".cPair", function(x,y){standardGeneric(".cPair")}) @ Function {\tt .cPair()} is not substantive (sic): it exists purely in order to be a generic function that dispatches to {\tt .Brob.cPair()}. Now we use {\tt setMethod()} to organize the dispatch: <>= <>= setMethod(".cPair", c("brob", "brob"), function(x,y){.Brob.cPair(x,y)}) setMethod(".cPair", c("brob", "ANY"), function(x,y){.Brob.cPair(x,as.brob(y))}) setMethod(".cPair", c("ANY", "brob"), function(x,y){.Brob.cPair(as.brob(x),y)}) setMethod(".cPair", c("ANY", "ANY"), function(x,y){c(x,y)}) @ The four calls are necessary for the four different signatures that might be encountered. Note the {\tt ANY} class in the second, third, and fourth call. Thus if someone wants to write a new class of object (a lugg, say), and wants to concatenate luggs with a brob, this will work provided that they use {\tt setAs()} to make {\tt as.brob()} coerce correctly for lugg objects. The method used here allows this to be done without any changes to the Brobdingnag package. The final stage is the definition of {\tt cbrob()}, a user-friendly wrapper for the above stuff: <>= "cbrob" <- function(x, ...) { if(nargs()<3) .cPair(x,...) else .cPair(x, Recall(...)) } @ Note the recursive definition. If {\tt cbrob()} is called with {\em any} set of arguments that include a brob anywhere, this will result in the whole lot being coerced to brobs [by {\tt .Brob.cPair()}]. Which is what we want (although glubs will require more work). Just test this: <>= a <- 1:3 b <- as.brob(1e100) cbrob(a,a,b,a) @ So it worked: everything was coerced to a brob because of the single object of class brob in the call. \section{Maths} The math group generic functions are set with function {\tt setMethod()}. But, before this can be called, function {\tt sqrt()} needs a specific brob method: <>= <>= setMethod("sqrt","brob", function(x){ brob(ifelse(x@positive,x@x/2, NaN),TRUE) } ) @ Just check that: <>= sqrt(brob(4)) @ With these out of the way we can use {\tt setMethod()} to define the appropriate functions in the math group generic: <>= <>= setMethod("Math", "brob", function(x){ switch(.Generic, abs = brob(x@x), log = { out <- x@x out[!x@positive] <- NaN out }, exp = brob(x), cosh = {(brob(x) + brob(-x))/2}, sinh = {(brob(x) - brob(-x))/2}, acos =, acosh =, asin =, asinh =, atan =, atanh =, cos =, sin =, tan =, tanh =, trunc = callGeneric(as.numeric(x)), lgamma =, cumsum =, gamma =, ceiling=, floor = as.brob(callGeneric(as.numeric(x))), stop(paste(.Generic, "not allowed on Brobdingnagian numbers")) ) } ) @ See how the third argument to {\tt setMethod()} is a function. This function has access to {\tt .Generic}, in addition to {\tt x} and uses it to decide which operation to perform. See how functions {\tt acos()} to {\tt trunc()} just drop through to {\tt callGeneric(as.numeric(x))}. See also the method for {\tt log()}, which uses facts about brobs not known to \proglang{S4}. Just a quick check: <>= sin(brob(4)) @ So that works. \section{Operations} Now we need to make sure that {\tt brob(1) + brob(3)} works: the operations {\tt +, -, *, /} must work as expected. This is hard. First step: define some user-unfriendly functions that carry out the operations. For example, function {\tt .Brob.negative()} simply returns the negative of a brob. These functions are not for the user. <<.brob.arithstuff>>= .Brob.negative <- function(e1){ brob(e1@x,!e1@positive) } .Brob.ds <- function(e1,e2){ xor(e1@positive,e2@positive) } .Brob.add <- function(e1,e2){ e1 <- as.brob(e1) e2 <- as.brob(e2) jj <- rbind(e1@x,e2@x) x1 <- jj[1,] x2 <- jj[2,] out.x <- double(length(x1)) jj <- rbind(e1@positive,e2@positive) p1 <- jj[1,] p2 <- jj[2,] out.pos <- p1 ds <- .Brob.ds(e1,e2) ss <- !ds out.x[ss] <- pmax(x1[ss],x2[ss]) + log1p(+exp(-abs(x1[ss]-x2[ss]))) out.x[ds] <- pmax(x1[ds],x2[ds]) + log1p(-exp(-abs(x1[ds]-x2[ds]))) out.x[ (x1 == -Inf) & (x2 == -Inf)] <- -Inf out.pos <- p1 out.pos[ds] <- xor((x1[ds] > x2[ds]) , (!p1[ds]) ) return(brob(out.x,out.pos)) } .Brob.mult <- function(e1,e2){ e1 <- as.brob(e1) e2 <- as.brob(e2) return(brob(e1@x + e2@x, !.Brob.ds(e1,e2))) } .Brob.power <- function(e1,e2){ stopifnot(is.brob(e1) | is.brob(e2)) if(is.brob(e2)){ return(brob(log(e1) * brob(e2@x), TRUE)) } else { s <- as.integer(2*e1@positive-1) return(brob(e1@x*as.brob(e2), (s^as.numeric(e2))>0)) } } .Brob.inverse <- function(b){brob(-b@x,b@positive)} @ Note the complexity of {\tt .Brob.add()}. This is hard because logs are good at multiplying but bad at adding [{\tt ss} and {\tt ds} mean ``same sign'' and ``different sign'' respectively]. The first step is to make sure that the unary operators {\tt +} and {\tt -} work. We do this by a call to {\tt setMethod()}: <>= <>= setMethod("Arith",signature(e1 = "brob", e2="missing"), function(e1,e2){ switch(.Generic, "+" = e1, "-" = .Brob.negative(e1), stop(paste("Unary operator", .Generic, "not allowed on Brobdingnagian numbers")) ) } ) @ Note the second argument is {\tt signature(e1 = "brob", e2="missing")}: this effectively restricts the scope to unary operators. The {\tt switch()} statement only allows the + and the -.\ Check: <>= -brob(5) @ So that works. Next step, another user-unfriendly helper function that does the dirty work: <>= .Brob.arith <- function(e1,e2){ switch(.Generic, "+" = .Brob.add (e1, e2), "-" = .Brob.add (e1, .Brob.negative(as.brob(e2))), "*" = .Brob.mult (e1, e2), "/" = .Brob.mult (e1, .Brob.inverse(as.brob(e2))), "^" = .Brob.power(e1, e2), stop(paste("binary operator \"", .Generic, "\" not defined for Brobdingnagian numbers")) ) } @ And now we can call {\tt setMethod()}: <>= setMethod("Arith", signature(e1 = "brob", e2="ANY"), .Brob.arith) setMethod("Arith", signature(e1 = "ANY", e2="brob"), .Brob.arith) setMethod("Arith", signature(e1 = "brob", e2="brob"), .Brob.arith) @ Better check it: <>= 1e100 + as.brob(10)^100 @ \section{Comparison} This is pretty much the same as the others. First, some user-unfriendly helper functions: <>= .Brob.equal <- function(e1,e2){ (e1@x==e2@x) & (e1@positive==e2@positive) } .Brob.greater <- function(e1,e2){ jj.x <- rbind(e1@x,e2@x) jj.p <- rbind(e1@positive,e2@positive) ds <- .Brob.ds(e1,e2) ss <- !ds greater <- logical(length(ss)) greater[ds] <- jj.p[1,ds] greater[ss] <- jj.p[1,ss] & (jj.x[1,ss] > jj.x[2,ss]) return(greater) } @ These are the fundamental ones. We can now define another all-encompassing user-unfriendly function: <>= ".Brob.compare" <- function(e1,e2){ e1 <- as.brob(e1) e2 <- as.brob(e2) switch(.Generic, "==" = .Brob.equal(e1,e2), "!=" = !.Brob.equal(e1,e2), ">" = .Brob.greater(e1,e2), "<" = !.Brob.greater(e1,e2) & !.Brob.equal(e1,e2), ">=" = .Brob.greater(e1,e2) | .Brob.equal(e1,e2), "<=" = !.Brob.greater(e1,e2) | .Brob.equal(e1,e2), stop(paste(.Generic, "not supported for Brobdingnagian numbers")) ) } @ See how this function coerces both arguments to brobs. Now the call to {\tt setMethod()}: <>= <>= setMethod("Compare", signature(e1="brob", e2="ANY" ), .Brob.compare) setMethod("Compare", signature(e1="ANY" , e2="brob"), .Brob.compare) setMethod("Compare", signature(e1="brob", e2="brob"), .Brob.compare) @ Better check: <>= as.brob(10) < as.brob(11) as.brob(10) <= as.brob(10) @ So that works. \section{Logic} \label{logicSection} (The material in this section works in \proglang{R}-2.4.1, but not \proglang{R}-2.4.0). First a helper function: <>= .Brob.logic <- function(e1,e2){ stop("No logic currently implemented for Brobdingnagian numbers") } @ Now the calls to {\tt setMethod()}: <>= <>= setMethod("Logic",signature(e1="swift",e2="ANY"), .Brob.logic) setMethod("Logic",signature(e1="ANY",e2="swift"), .Brob.logic) setMethod("Logic",signature(e1="swift",e2="swift"), .Brob.logic) @ Note that the signatures specify {\tt swift} objects, so that glubs will be handled correctly too in one fell swoop. Note the third call to {\tt setMethod()}: without this, a call to {\tt Logic()} with signature {\tt c("swift","swift")} would be ambiguous as it might be interpreted as {\tt c("swift","ANY")} or {\tt c("ANY","swift")}. Here, class {\tt swift} extends {\tt brob} and {\tt glub}; so both brobs and glubs {\em are} {\tt swift} objects. But no object is a ``pure'' {\tt swift}; it's either a brob or a glub. This is useful here because I might dream up some new class of objects that are ``like'' brobs in some way (for example, a class of objects whose elements are quaternions with Brobdingnagian components) and it would be nice to specify behaviour that is generic to brobs and glubs and the new class of objects too. \section{Miscellaneous generics} We now have to tell \proglang{R} that certain functions are to be considered generic. The functions are {\tt max(), min(), range(), prod()}, and {\tt sum()}. The help page for (eg) {\tt max()} specifies that the arguments must be numeric, and brobs aren't numeric. In versions of \proglang{R} prior to 2.6-0 (I think), {\tt log()} needs to be made a generic with {\tt setGeneric()}. But, in versions 2.6-0 and above, all the group generics (including {\tt log}) are primitive, which means that the generic function is implicit and cannot be changed. This applies to the other group generics too ({\tt max}, {\tt min}, {\tt prod}, {\tt range} {\tt sum}). So to work with both types of \proglang{R}, one needs to check whether or not {\tt log} (or {\tt max} or whatever) is generic before calling {\tt setGeneric()}. <>= if(!isGeneric("log")){ setGeneric("log",group="Math") } @ <>= <>= if(!isGeneric("sum")){ setGeneric("max", function(x, ..., na.rm = FALSE) { standardGeneric("max") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::max(x, ..., na.rm = na.rm) }, group = "Summary") setGeneric("min", function(x, ..., na.rm = FALSE) { standardGeneric("min") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::min(x, ..., na.rm = na.rm) }, group = "Summary") setGeneric("range", function(x, ..., na.rm = FALSE) { standardGeneric("range") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::range(x, ..., na.rm = na.rm) }, group = "Summary") setGeneric("prod", function(x, ..., na.rm = FALSE) { standardGeneric("prod") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::prod(x, ..., na.rm = na.rm) }, group = "Summary") setGeneric("sum", function(x, ..., na.rm = FALSE) { standardGeneric("sum") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::sum(x, ..., na.rm = na.rm) }, group = "Summary") } @ Now we need some more user-unfriendly helper functions: <>= .Brob.max <- function(x, ..., na.rm=FALSE){ p <- x@positive val <- x@x if(any(p)){ return(brob(max(val[p]))) } else { return(brob(min(val),FALSE)) } } .Brob.prod <- function(x){ p <- x@positive val <- x@x return(brob(sum(val),(sum(p)%%2)==0)) } .Brob.sum <- function(x){ .Brob.sum.allpositive( x[x>0]) - .Brob.sum.allpositive(-x[x<0]) } .Brob.sum.allpositive <- function(x){ if(length(x)<1){return(as.brob(0))} val <- x@x p <- x@positive mv <- max(val) return(brob(mv + log1p(sum(exp(val[-which.max(val)]-mv))),TRUE)) } @ Note the final function that sums its arguments, which are all assumed to be positive, in an intelligent, accurate, and efficient manner. No checking is done (this is not a user-friendly function!). We can define {\tt .Brob.sum()} in terms of this: return the difference between the sum of the positive arguments and and the sum of minus the negative arguments. <>= <>= setMethod("Summary", "brob", function(x, ..., na.rm=FALSE){ switch(.Generic, max = .Brob.max( x, ..., na.rm=na.rm), min = -.Brob.max(-x, ..., na.rm=na.rm), range = cbrob(min(x,na.rm=na.rm),max(x,na.rm=na.rm)), prod = .Brob.prod(x), sum = .Brob.sum(x), stop(paste(.Generic, "not allowed on Brobdingnagian numbers")) ) } ) @ Better check: <>= sum(as.brob(1:100)) - 5050 @ showing acceptable accuracy. \section{Examples of the package in use} We can try to evaluate a factorial. Stirling's approximation is~$n!\sim\sqrt{2\pi n}\,e^{-n}n^n$: <>= stirling <- function(x){sqrt(2*pi*x)*exp(-x)*x^x} @ And this should work seamlessly with Brobs: <>= stirling(100) stirling(as.brob(100)) @ And are they the same? <>= as.numeric(stirling(100)/stirling(as.brob(100))) @ \ldots pretty near. But the great advantage of Brobdingnagian numbers is that they can handle numbers larger than the IEEE limit: <>= stirling(1000) stirling(as.brob(1000)) @ \noindent and this is accurate to about~12 sig figs, which is accurate enough for many purposes. The number of sig figs decreases with progressively larger numbers, essentially because an increasing amount of floating point accuracy is gobbled up by storing the exponent of a large number, and less is left for the mantissa. \section*{Acknowledgments} I gratefully acknowledge the help given to me by many members of the \proglang{R}-help and \proglang{R}-devel lists, especially Martin Maechler, Brian Ripley, and John Chambers. \nocite{*} \bibliography{brob} \end{document} Brobdingnag/inst/doc/Brobdingnag.Rnw0000644000176200001440000001675014317730133017127 0ustar liggesusers\documentclass[nojss]{jss} \usepackage{dsfont} \usepackage{bbm} \usepackage{amsfonts} \usepackage{wasysym} \usepackage{wrapfig} \author{Robin K. S. Hankin\\Auckland University of Technology} \title{Very large numbers in \proglang{R}: introducing package \pkg{Brobdingnag}} %\VignetteIndexEntry{The Brobdingnag: package} \Plainauthor{Robin K. S. Hankin} \Plaintitle{Very large numbers in R: Introducing package Brobdingnag} \Plaintitle{Introducing package Brobdingnag} \Abstract{ This vignette shows how to use the \pkg{Brobdingnag} package to manipulate very large numbers; it is based on~\cite{Rnews:Hankin:2007}. The other vignette shows how to use \proglang{S4} methods in the context of a simple package. } \Keywords{\proglang{S4} methods, Brobdingnag, \proglang{R}} \Plainkeywords{S4 methods, Brobdingnag, R} \Address{ Robin K. S. Hankin\\ Auckland University of Technology\\ E-mail: \email{hankin.robin@gmail.com} } %% need no \usepackage{Sweave.sty} \SweaveOpts{echo=TRUE} \begin{document} \newsymbol\leqslant 1336 \section{Introduction} \setlength{\intextsep}{0pt} \begin{wrapfigure}{r}{0.2\textwidth} \begin{center} \includegraphics[width=1in]{\Sexpr{system.file("help/figures/Brobdingnag.png",package="Brobdingnag")}} \end{center} \end{wrapfigure} The largest floating point number representable in standard double precision arithmetic is a little under~$2^{1024}$, or about~$1.79\times 10^{308}$. This is too small for some applications. The \proglang{R} package \pkg{Brobdingnag}~\citep{swift1726} overcomes this limit by representing a real number~$x$ using a double precision variable with value~$\log\left|x\right|$, and a logical corresponding to~$x\geq 0$; the \proglang{S4} class of such objects is \code{brob}. Complex numbers with large absolute values (class \code{glub}) may be represented using a pair of \code{brob}s to represent the real and imaginary components. The package allows user-transparent access to the large numbers allowed by Brobdingnagian arithmetic. The package also includes a vignette---\code{S4_brob}---which documents the \proglang{S4} methods used and includes a step-by-step tutorial. The vignette also functions as a ``Hello, World!'' example of \proglang{S4} methods as used in a simple package. It also includes a full description of the \code{glub} class. \section[Package ``Brobdingnag'' in use]{Package \pkg{Brobdingnag} in use} Most readers will be aware of a googol which is equal to~$10^{100}$: <>= <>= require(Brobdingnag) <>= googol <- as.brob(10)^100 @ Note the coercion of \code{double} value \code{10} to an object of class \code{brob} using function \code{as.brob()}: raising this to the power~100 (also double) results in another \code{brob}. The result is printed using exponential notation, which is convenient for very large numbers. A googol is well within the capabilities of standard double precision arithmetic. Now, however, suppose we wish to compute its factorial. Taking the first term of Stirling's series gives <>= stirling <- function(n){n^n*exp(-n)*sqrt(2*pi*n)} @ \noindent which then yields <>= stirling(googol) @ Note the transparent coercion to \code{brob} form within function \code{stirling()}. It is also possible to represent numbers very close to~1. Thus <>= 2^(1/googol) @ It is worth noting that if~$x$ has an exact representation in double precision, then~$e^x$ is exactly representable using the system described here. Thus~$e$ and~$e^{1000}$ may be represented exactly. \subsection{Accuracy} For small numbers (that is, representable using standard double precision floating point arithmetic), \pkg{Brobdingnag} suffers a slight loss of precision compared to normal representation. Consider the following function, whose return value for nonzero arguments is algebraically zero: <>= f <- function(x){as.numeric( (pi*x -3*x -(pi-3)*x)/x)} @ \begin{verbatim} f <- function(x){ as.numeric( (pi*x -3*x -(pi-3)*x)/x) } \end{verbatim} This function combines multiplication and addition; one might expect a logarithmic system such as described here to have difficulty with it. <>= f(1/7) f(as.brob(1/7)) @ This typical example shows that Brobdingnagian numbers suffer a slight loss of precision for numbers of moderate magnitude. This degradation increases with the magnitude of the argument: <>= f(1e100) f(as.brob(1e100)) @ Here, the brobs' accuracy is about two orders of magnitude worse than double precision arithmetic: this would be expected, as the number of bits required to specify the exponent goes as $\log\log x$. Compare <>= f(as.brob(10)^1000) @ \noindent showing a further degradation of precision. However, observe that conventional double precision arithmetic cannot deal with numbers this big, and the package returns about 12 correct significant figures. \section{A practical example} In the field of population dynamics, and especially the modelling of biodiversity~\citep{hankin2007b,hubbell2001}, complicated combinatorial formulae often arise. \citet{etienne2005}, for example, considers a sample of~$N$ individual organisms taken from some natural population; the sample includes~$S$ distinct species, and each individual is assigned a label in the range~$1$ to~$S$. The sample comprises~$n_i$ members of species~$i$, with~$1\leq i\leq S$ and~$\sum n_i=N$. For a given sample~$D$ Etienne defines, amongst other terms, $K(D,A)$ for $1\leq A\leq N-S+1$ as \begin{equation} \sum_{ \left\{ a_1,\ldots,a_S\left| \sum_{i=1}^S a_i=A\right. \right\}} \prod_{i=1}^S \frac{ \overline{s}(n_i,a_i) \overline{s}(a_i,1)}{ \overline{s}(n_i,1)} \end{equation} \noindent where~$\overline{s}(n,a)$ is the Stirling number of the second kind~\citep{abramowitz1965}. The summation is over~$a_i=1,\ldots,n_i$ with the restriction that the~$a_i$ sum to~$A$, as carried out by \code{blockparts()} of the \pkg{partitions} package~\citep{hankin2006,hankin2007}. Taking an intermediate-sized dataset due to Saunders\footnote{The dataset comprises species counts on kelp holdfasts; here \code{saunders.exposed.tot} of package \pkg{untb}~\citep{hankin2007b}, is used.} of only~5903 individuals---a relatively small dataset in this context---the maximal element of~$K(D,A)$ is about~$1.435\times 10^{1165}$. The accuracy of package \pkg{Brobdingnag} in this context may be assessed by comparing it with that computed by \proglang{PARI/GP}~\citep{batut2000} with a working precision of~100 decimal places; the natural logs of the two values are~$2682.8725605988689$ and~$2682.87256059887$ respectively: identical to 14 significant figures. %Pari with 100 decimal places gives 2682.872560598868918515209515642292607616628612201118344882119616522539674163937533805390351760715777. % 2682.8725605988689 %and with R: 2682.87256059887 \section{Conclusions} The \pkg{Brobdingnag} package allows representation and manipulation of numbers larger than those covered by standard double precision arithmetic, although accuracy is eroded for very large numbers. This facility is useful in several contexts, including combinatorial computations such as encountered in theoretical modelling of biodiversity. \subsubsection*{Acknowledgments} I would like to acknowledge the many stimulating and helpful comments made by the \proglang{R}-help list over the years. \bibliography{brob} \end{document} Brobdingnag/inst/doc/Brobdingnag.pdf0000644000176200001440000025603414323731145017134 0ustar liggesusers%PDF-1.5 % 1 0 obj << /Type /ObjStm /Length 3191 /Filter /FlateDecode /N 52 /First 411 >> stream xZ[s۶~?oMc .$:̉:wGv>eIj|H")GJܜ36E.].FDE!QD \$FKDL(IL8S11s#Q&\µ@cHB&Q$ Z* D PDDr HxȈ!N!H&dDXж(pDnjqDD?(XcI,b( FL_IL.2 ā5&9ɉ1DU( lXH$6g(XEBi b !'Qp ̸2"맟}V$$6jDe5t=r ⯛#Wc7œe5+J4NS!cwmWL^^Xe1܏ӗ3J&UVIG?, !r#z*Hߓ۬,t_E9YBb,B]5(GqM~6Or͗;sd9NAӳWXTqTJ CΗO+LώO}~ MzW٩߿y?n3IV.0O*AY^T~8]T+~ =c8ɗ%V꘭k{!&jv|5pEJ ܉Wab . Dx /Pny|I_3ui@y Q@F,=,,5 >L{~8:==yëף:yxpX'P|\L\^͒ni3<\+q[[Y!/.T3+1rߟF?q5K q%jkHy͓?cέk!k: ص%ˑ>?i-V+ -va~,ͮfM"[>G}N_3:K:b^tBS:iF H洠Es8+& ZjV)n wsTT^ͯG+LD5{V/jcqM,⊅7c}5#^:FQ\׎ݜ!4v2;*xHA#ț1]pOغ34 QS\Oб5pelXГirp=!.ns,ڴcaacYkzJ6}G?lqq}8 ^OŌݍɵ32?a獑QG49ϵѶN(QoX[{+F6ޮBke2eexý]]s { hXgSewS z=Ŕ;G\`I5YgzF lh6LR!&馟KocRuǏ4uIH~uHm@{l כ6V.Z꜂,]C܈a.>;bW}]ȋE~v56`h]ײ_֚Ul5W͵-_C NPP]|I#LƩ;]ɟ1V(v0eRyXwf̗@n: 2b\;{`?Wx+5o"spw/˞ϓz%l_gSE}}n͕vS)"N,Y6zd[4l\#}%kũ&mJ&ub^)[ (EUѹf>QP:#WR̡?+Da/ S pwgJ ̤ C Z .WGwڏV~ᦧɢΨ&|mi@Ժ^{<TY ofʯ[vS|7u٥;bdu绅}#M2'+g鎘>&M-?wsfZ{ 1`Vof[屫Ͷq'ҮwmҮnh-JF z7fg /ʰ>=}x#J&5t_.D|?@o#(w[QJN=fP.7u85}@ftsCsFCE#@Pc Epe$"=#I"e1M9"aܔݗBU-}] `Blr\0,0@a@n~1z€b=Ł44IAܣsl^C+JRIQO߆$ [7NA/Z?0I< "^$@o MJ =4_Dfl4dn Q 2a`?6DIfL/, ){ rO wByH %x^e!z6DY )lk"MOܧ:pFWCJhVU7?Rz{{$evus0+`;ۙMUPI c12C" B.sG,anЁVBm%,0(d?FONMYد+bLGyzKd=9p(e`b@T_'ټ*~%,2}ex{A$l\2B~ {l:M4N_2K#@ڷ_d5u5~oV` Wkzmy/Fendstream endobj 54 0 obj << /Subtype /XML /Type /Metadata /Length 1462 >> stream GPL Ghostscript 9.55.0 S4 methods, Brobdingnag, R 2022-10-19T21:16:37+13:00 2022-10-19T21:16:37+13:00 LaTeX with hyperref Introducing package BrobdingnagRobin K. S. Hankin endstream endobj 55 0 obj << /Type /ObjStm /Length 2688 /Filter /FlateDecode /N 51 /First 410 >> stream xZYoH~_яX $>HEdED9jOꪯ aD[""i 牖@C 'V@N1p-1p! 7NBK½HB#!)" "=%Q3]XMrXC?4@' I#9M'ZN ZKEm hb8,H0恡ָ rH \3Sh 8a*C+)wJp !`Pΰ/p3 (ŐLaT(ט7^/3AZ#B|="Fd7B$ h N&iC"M[hvdӌ1K1ދ"m uū c5࿂M_Qlƴ8~M^/kVE\.X6+P%AlVd}s&ߚF_Δ򰗄@֘d,ʦSLW]Z)#&\35]]\3o\7F2iy?.. =Od~Md3_&{7:;fN1]6U霛\נe)somhصpDmD:"\;tB/蔆JcK9]&4߀7\r< z'l݄NLb X tzxx~oQ|bɶdX m$۹PUXD{o!^+@lJ]'EGi4+;epeS` Q#s-a` qPG2Y>1AvU˂1G X(^ UňoF|N'qFĚ\')0D5e\ `0d0<GSY.iLUB MtFo霦Jxtꭌ=NkYrֵ68@m"OU{Ve)珕yY5eMD󡈖EmT!o؆9OU˞S!Fa~&3}kk<1 d0gUrVfx|ƋGJѥJ]5d#='"u6l&0hp evؽRtbY\d]Ͳn؃Ɩ5ut7&CϮ+Q..EB/SȂ63*l)5FZ oXd1dMM[aL['ϒ<~&MҀ 8,RU0$dEDyYNKyQg0%/~CvjF#pl8(HV-ἨyZ`2 eZcTHcxL{bl9 eZ.y&iIRX9ο?cQ`1ils)]n-Jn\)Y[!>TuuLcU}GM >z2Ӿ6!4W-[ipz$"4 ^: 8ЌۖC3.nL~M](-i#G2F("%_:Cc䄿 #; 7Bh j1޸O%s;tcy9tG<ʴ;4~ʴ k~U ~U~K:8?}XSZ m|5m?rY>^[0dqq~';us{Q=q A4S%`F>7[CPlAF ~"V@*?J'JrNj-"e36 ] zh_ &qbTIY A r}Cjw>l$| endstream endobj 107 0 obj << /Filter /FlateDecode /Length 3755 >> stream xZM98'87"kKK ,`p]5;'3%UI35჻{TR*T[_/?W۳wg~].ϾxJpV#OVru?{aVWrlkZ3n?~GikڛF3|aוr L9:co-UC^99e eá]]7d`ev]oּR<_rcx xsVjHӗm"H-TZ U\گ6JTFKxFYsiVwUx>~V&ې,$lki=åZm_r_q/N*v`_pJ w:3v1aI)κWQ=X=M0mvmg8Ogp[WέgZz+osCX_i'V8Cs9H7Om64*eMty؄zBJ(nX 3qڪa]8ڰ4Wmш4@Q:H64GS Qȑ?ϦB;h+eL6c 60)+8t5͟ϷkFBcGKSFFotTΙRso(ح,}_kkX/CfiY ^+x8E0 y)0eYxL@zu8M !kYi*Mx5ق<_da+-fpV8K H#/ u<\Y7>q 5!;*@kJ. cl *{  ߗ(-ۤqO􈟍8B/2 eCv 0*8 Q [~L99v.9[AjZJpK^r5 ]Y5!Xw OG~)#kA%|4.99٧38'̏KVrJ<.WO''\>M4Aڜڷfz0 SK頓jd&4(ׇ7oDV @)>uZ(Pa@#uhI[YYhbѨVJoR gR*S4@`y~vB๲:x2#McEĚ<8p-AQԆ3r5LTs)P{ʕLI 3H8;fSoaQm"{f`yK a&<\E2|?Njp\7$AW/F, Zc@΁{82 IGB8G\?rkmswc؊"$+4P jP=0^ ؔTn`0[".ɸ5˚}p0a v*H0pL]]9qd=>)$c~4 *b^/,.|&k2 ^ JA`U " Kb2[դf*'C]ؔ^b6î#!x`3Zm1H1H6r"+8EȂ>$§"-'EG+~!-.̒U'VSªo&-?(WPBbAc F_ A} C1GЎ% ;"̰Zc\gjv_~$gF+A(j8z ^Η엷6}|2'ҳ<ʉ EUK(- M 9rdpDKv Aߐ0llovwBv@82!uE ћDoȦdKJHЭ,4OJC%x֋j EO!Hު+fQE;%$#lme!|Y|Urk3P50Sc.i<ήWk:(XU42UI XY As@qCoSxI*in}*HC-yn;CiX,FH?ǽaqBj|!Uj7Z hf,wzPYIp6풋kSlwwOp10iXT׾; ӺO\b֬ ސ= l̫IWKB%_HѰx,ۥ O OX7Ax]ov ДkN SLg@F*ͨ —~5;SޝcpsJN6ύӑI8)թ:ORܷQI (\Il$!eR&w.> |.%>y$Br\hIe!)Cʺx xkP\ 5;(,KƷ~*4ww%U{iPGVv*n𳢃k K?hRV/1~}%.AA[GeՑI[[eb8n֐j .elNg<ѫ}*x{6@1BMr5y;.rX&@]>+1߼9-u>B;>:)qrb&PDKwzv =ܡOIKZQEc7!GJqIˍB(סiBbJEoձ y~ 5gw %I1Si2iN~90y{Z Y?*`7 x]Jn^gb@ 4zJzwrM(B[]2Ft(k_At̊Ģ.|H76Mgv7LyFKd @HeW+ׄK\ZK"rzfrC-<{P5]B,նOXendstream endobj 108 0 obj << /Filter /FlateDecode /Length 2575 >> stream xY[o~_~Yq9WӢ@@"@S/VpmYF33Jz~(\e!/KoÅo/㿛巋?( uYE"/lU^.Bk /n/g^WJf(mKEZ+v3H'fAWv*Xmx7I8nZJC8^þD+LYD tG%`J(˺7Ac/Ru}us>ܬ\iQ E71ֹzޞk8Y˹w. ,:߀J+ڙDh%(H-!yHr`VEJ7p|鸑fw6]kt]Fb7rC6m !^o$9f$kqC.n9ujtsx>PWddkr|K ^ ގS+Ƽt=@ )$,M2`Ԩ<&F:2{+#3R WV#ʀ%PmPW֗ ^p;驄g乮]a4rwFUnee%ap2@0RS>mVEٟ1ݡ9=tyZ~ SҫI5C{خf)IP⾽zg1ᓡ3Ws]ob'4gg)~;E(P UuJˁg0ZM^u ƒgr 66ǀMICɛ=H ' gU4%X|Cˎ6~JcU7y6l<R D}c$PlLׄ9{>ܳ7q6~Xd'&>n6gre59 b38ҙ40it bw8^;E^իt9+E 87KnA !] (0s>5ɧ1b/=ν4Dĩ_8=qtĚw ]ΧHW ET# K}MYT΢6*T'bgx~U#3FV%I@( &nti"wA<PBl< Q :6iӷ=F_QӎrrՅTK"+R7S@J'C2j<(k>Qn{ Mu~ XȮ2;,0-. hTaendstream endobj 109 0 obj << /Filter /FlateDecode /Length 4673 >> stream x\o)'c<[zN󛴱^6Cn; вdog4_UEÑ%ˇQ7HVZWnqs㙠ϫ}g 4+ oLW@/}grVe97r;mUKO/wٿ!>k/Ch`vm. a_qm|п*ɦ?7oK={!FrHf[~+¡;[ff*>.}l_'BMs[>NhQ)-ݍv}qiGAo# }.˹l+WDTyL\JԸboׂiN%hDYL֨m$:0 Q %Z}Ѭ7c߈xq}yvɂMÂvsW(hDPC3 V"Z<%^]i$`&`矦y]| y+@,zJmTxV7pcm(E!4QЎAaFȒn~z#4,".~]<3uG}zim,.\c';nh>R@>hղb ((ّ)|iPR?HZvLa4. 'ΧHȆ1O8^ߠVHGa>UZ%+yg#&p# > !5zML&{v4_B?v2<쇫%S mU1 '4;:|srl q*m% *Npב WqǢyJ#+W#'`a: 7C 4W4RVAp@2X z=Li&AЦ4q{wa q`30: J}r,z&Wjds'Vomƞ>4?v>&-eCog15kH^w6o'!81xHjBTpHd׹ǮDtN-ЕUBJOܠuI6xl\^y4)<%" +z",70qKG~4c4Hi";{n !s_JlLzd_'X 00wgPc/IPJut 0[J^~t0II}m.QS Dθڑ&aܢ/cފ=WPLLY!Ӭh'Q+a-EE9)-̝9Jvwt7c 8͏V 5eLA}YMA= 䇗sUgDHt0P`Je+'-5fA^$FWda3ӫgh";s&3zt,W}lM [S4YM5` I(}x>N~q% rD_FE`F''s=9 6JZc@kv,<V,jrO)4јާ, HX-A |s>O8>=As͂ٙ<3piV,K !` li% hC}gRGK>7DoP}n3 1xz7~5+Z!'IZ"|C~QU"CEr*@+ ^2?bHS4@H,K|#|{b5.Vꛚ雷 (~ybj}; QJȇTAESrSAF8:-s-,'-'< ~]8Ug5NjXM1S& (/164p6YlY`d9ГJ[ v(\rSW4հUU@/ ބT9_zL@ 49Ԓ=8JP}ݓ ͈^ YqVhv9S/'Xk#2dR.=%j gWQ`;wٝU;@?X'%EgRߨϽkZ{5[I$w3- A9Tr ejĎɏZm㙞B~p[2'YfUȄX'q2Ͱԑu % OfTL9x"kήt31Dv|/mUږ tA3_b|5Ue+bO 1 >uېMQTQ ݡ8N3 mk (c$JDvO( :˙@OmT'KkOМwSv7!cMvDcV|uxWĜ?0'!OכVx~Mcͱςn5e㕏YE՘>M8Ir.~[kA lkVj Rg#'5Erv=N#p1T[E8KD"3DŽ?]:FRnT}&?3YgZjG4Fp7(ά&xVEMABvXaܽe8aD/Pi>O0.Ћ:;G&_5^ƈ{| O56TW-p.x@WN&:۬cۼٮ^r(7׻|pؔș{{uwoN!&ŹCs>Go 6M\2N k<ΰ3:Y% ԠCLRIܞSB"]yN/Dh .|3}b*$- 0Eendstream endobj 110 0 obj << /Filter /FlateDecode /Length 3364 >> stream xZs6Sot7sL~]j;iAd1%.EiLLIbomgtj{6GQ,ξ8:>clnO3CgZr91c3~:27,1/,Ґqg9\֛u(%͙rAinv4\h*iRk )v^| d3͘=RBn'N8 F%Ԥ+F[KVW~džjE6A[] oo0 &L؇M2| J~UWib^Mr3)Hd\(LH5[p|2ɔvWI Lڹ\*/4uU&3Rg*^ō" ;1Z(DXLlpa >`]DT92AewOeYVs${r_'R3,0%edq[+PB2bq7e,N0R]{qf0tg>7oMlAH.(e#ٽBqaQxJ<*#W{ʙKib `n @!d$\R0ĿbATpxrqfMjr.nML} $GDL%nnx%ЫabJʶV=F %V&8Uu8*hAʡG6~8篭2pı#pbuL&$4aI'ryZ !6l!LEY4A\̉TT2D:b e+$DLك1!`L5P *kTuѫ?~;R##w$i}h|y5Y1F*|O-{StFg漴9L@< h)'BlPMeYq<.m8 %z EݡDdD\@ZD疎=ӹO#W" 6ُ&}gvHq/jx]ŖzI•}R)3[m$;Gy&]ǩnP :֠b0*T;9>~xx-`UNM]gqnKDBNYp&Bɐ^{K1Q-|M+rvw-C3C^ Y"1B  W>d}IQ}c pZ9n1RD.qcPW$'K.%aX 3ЀPX*!ϱw\58H=u8)7Q>gBM*GGl#Pa9xJf#w<̃MFMm )iJFܒzZ%n/RM<'cMu~nm /\1-d3#7h7Ԝ! nokcQԐ\'Ъ6kbImD(¬x"Vic#GžpZ<\%xSD'HZ{UwɦҟJʎ$)cP`*:}+}ʣ+-@ˁfHL)06 {g-gAY*BC BQkNŻ $9*ɬ#7jPa4ӷgezaQ9Vc$,4,ZN|p5)2^DƱ4:t:24ڛOjZ=Gw'AQ[ !'Ⳝ^w:$ٌ&{9G.O 崷&{%{ExPu-w}}h%tti7wH d[6)+=7qYӽ$hlG?zwbz5Ż"fOU`C^$Da?fw&2Õt.J*L-~uNp5M߆j v ڸq +L`Mua}dU9^UWg;0g5p8fx623B_F|-a>['>ɾuw"ZQ+\>0[BN4Er Du=\ H>q=Hrjkn E~I߬ۦy]]<>S`Kj4wۄhO^N'7M5:]HJnn%ycwsbr? uRob#߷ m0iѴP8ak;^xhGc;x IL6v=p]9RHݏ,?)].H[L@]N/C [5&?VMRK63 bTbHwEN^d>La~Ϫ8wA4If}e{w`Ei-S_|_7o˃XF> stream xW XS׶>1$爈0zN`:𮵽Z+ΊuJ"(T SȬ $2"qQ[:~WKmپo'}_k_ aP(-Z4y[ (S!8HO pE<n 3J"08rq[BT薐ɾSƏӵ[ ŒqaZ}dvKqt2T;57k+WkWY|J1~0HmQ;/7$l eyh@XIL}m0#?,cJf ˼Ōc0w93c0 "f13Y¸0<38)r }%yCUǒ^rhsFZ{䞶 ƬL.A>dBcqN!XꎕꏈjNdh̑!j*^5]'JQ6T7/{\%?,c3G^23T 5-GcCH>ӱ+p3a(_EFo %ο lbқlFttRuhԠ$2mKĕp?@4ሆuYj;^.мLLaqq i ;(WOp~Q'\o o[S jֈVCN0sv@缚YA ćl&CƠEgt)d>6.(yh OqaS,Cfg_โ9!p88J$Ng:]pYΣe'/ &{4v>xrnV~Sf5]9OH=Tɫz:[7Z X~-`!є8mgm@@tv36|G4|ܠh.)1(js-p$4oe}|*Q7'*d'!j+w!ueJ2m\ u$i2lЖz _](d.ve!4 eCCNC9xJÎHǓc% sȎ8\ӭdGD/O<=kv,n+ 盤QukǕk^WW+\R7 tWr䞇i:itI9忟ұGL#{qA?;O*ݶR]S9ž4hes5%3ff֞xw;?4}G5$dv$˼D/"JAAb~t [ѡ8f}>4?_PV';.Ti*S!QX ePa8{+8fL7%5WT,l5Pܥ&L&S6/rq?A_tԕP%@?-!_i~)3'=rUƮ̽)Ic*nW\Xp<$VkeбUPc9Y>GrEM_meI5+72=L@cRm ݲn{<UWiKf9(WX͑ij6SnjơI<A+8g,_NNLK{ocX B%Tu'4$jÕ]K~^1.!7a]!NijG{@EUgLmчQ6kץ\ܙXiɻS8?_GK*T(勲FbC͙`X脤tKHylP#D?l\`qqOFrbdFG09 `ʳf7@ g ]wL׎0T-rfE ;sQ)P*1A.%9CH6o"p psn`1-bVVnGvV;yy+ZXweԈ\0#؞v[yX [,/=.TlGBgNVZ@ȁ[_œ / X"6=W p,i0߰+{pύ\, ,YIcRC><+i5su6]_Rw[FɇO rq"zhHڞZ\nDӠz q)PrJ5-oe0YkTǨȐlV9O؝bMM KٓyRJ[I~x 2$ӅqI~6IK _˟D:E5Ns~9B7{כpgKyx;doMMB^gMxTړ+ޘ^dw'PUoߛXpvoGkkOnW]ZsY('ԙ?lN.jrX2Kb:R c5o0SpoHiy&$dqM}ٖ AjOsL-V£6l\ 8ˍ{{r-iI!cMxB'{w]# =mW4wmXSF|>C6hJJ%<: ]rꖥǒE$OЬL% d065N˙o/ӯ]WBpZlr˯ {ʜ{J\0\FYld8dk#UoJ؆~mwn]|ioE->* lzz^G*XT ("UҲ,)5c|ID1yDT;ǔb%a53qBGCNܯrſ_dg Ņjk?X+ɮ|/>|(Z5 ]8\E|r.SvbNfi?yǒza;ʗlIM֞LZS2J%X4@agZ)|e\/e%q(ug,x7ъdGES{-vg=Y41Xm>믑$W+)z/Ѣn {(*8 MDBշ: mw`4.RWh)2(J,vۗ[t 6WmSOs/qnn.aחsK+8v-9o>PqGGbfAd(9҅8&J)Q96B֛!L(_B.tcqU5ztIRbFΊMߝ'm?QMi`*@Ggĝ.J]\y#2> stream xm{PT.{#Ხ &P$5H E^>XPw]"A"5ZcD$6Suv:=wc'&w~;|{dDAd2w#-{ofYm0e%#/2q#9ǁ#~n{9?/;)xW) Np@+b#KvJ*h+EZTl}"Ux-}x9\r6jyߠl?q05f40t?(q  g{88LHD)^/2(L~%_='vUA!_QER4~07cePPcN[  ;|UCS]Npgz\L}5>OdI7.p6Bd;y|=%7@l7*{A K?ϴ((2Q^Fp$|<,`LP j_gQ]1q拏z7,TQpJJf]I\K]{ ό6yF4"aF8&4}w˻~pcߏg><n J{KdwbKփ p-* :V+tU ],f1}I*ttsځ类< d_BeTL3ScC}?lJO#z0z]KUa*KH-qyo;x(t[Gz3AL+T%v32i}L9#,v1'വД 1>+ )gQ noEwp'(&iH_e( (i>uFg o nnYܻ~&$•Qg ^4х`.ׅ]1>ȣ\yP\)2 > stream xyw\, ;cWƕE,{Q{/]"R-{]"{Fci5&M,9ソ3{ͽ,9s}}޳ڊH$˖ p 0~jOPpA" ^z`3M[ BOӃ^O&CE}ЪT"Y27(X'qƎ%;s\-pq9"w8 ttqr r\yjgDž\V:}@QԒفs6 2?tAXőKܖt_Xk O'>w8s_n'Mﭩ}G4浱qE JmjzZM 75 5ZKQj K6Rq&j>&O-&P$j 5ZJMQoQ˩ jՏK*5rQ Fu^T ՛ HKzPKIr(kJE=$JYY}' ޶^n}->fԭ9gnqRzЧo>{!֍=_|nuE}o^s(0^-yq*rҢcg= NHХw[h/l UĤ"9W Ѡ$`] ?:ZQi6fMkԚ4p`Οn0_}(S#dݴwf xW[lUyՎj:9pxBߒU06o ZFW`?}-#i[հ٘Ej8Dhg/_vYᘗ}΅]&)oHƢyǪAoPX ~/:Nu{/"Ix'm'hCDix-X{>UTpێ+!9bG=3\#+4u=]lyk3[ҙtjt>Dr=8 ۈ;Q]{bK֡V9Z<!$}G+;Q(GˢlJHzA}Bг<P|r0=qY\#}~k^}2ٵ>Nlm S f'3_Nw$(eHC=IY;P>:_}O-j(-/Zܒ7?1!= ɛΙ=rc{ohۛģ09{nMP1蹚 j]]W/J1wI\ݎ*/]r!⮿${n/vM"+Rx 1R!UF"\hbh4dNHkq[ZM.W6AiX cޟ)\4 #EZ)9ȝ)YTdb_)vA!mFKϤ7 un0 < CQo༖ch`!xga'sT6)y;b\,̾˧>ets\:{ T󒢶6P#H0N `QA h@;g*FZmAlUMPB" @@H9'+ƠƔTC.1DSZjϨA nLQs, }(:GQꧤxbVPgzUF=ʡ4@w `‒]E%9u[ʪcٵ;}ҋ^[0kG:peXB/]9H1Hr;Pz1k%~焜5cFgZniBi /ѯ-"Sh-B32Nh!:?&e5 ,!|RKq.dҴXQD;g'MF;V'-+]@e lŞ}W G ٶ>k$fKc5g(f 4{,12l.4`h8@yU+@V4JQ aN|"CMX;:Ҟ(s4ퟫyN62/sˌ|e3mVEsie: sb)pk 0V.k$ E rMgd!h)t7w(mQQĮ?ckG'cw=^expw32~φH\,Ew"w=]dZ7cKEO!WGGI@y>hTD2bMЂ`H"iE|J ʝQ[[_j>wC󄙕N D +9"6nj}0 gŃhF[I4V˩KzNLHQTueIតg6)4pw`-%U&Q~5ZLgB I*~As x:tt0l&:nfMHRh0HV`HF^ cuBk4a?F3CП)B7:r"N#]1C,Cw⅞**S)6_12m=$Ǥ۲?:Y!%)?¯4[?ذE|Xه#򡽵ŤTWbئM[#9rW i֝fh4]9T; вߚJҨ4Z^M,EgD~3iT(H1wC!P3`'^/p/S0"3hH&ҋ1 <^,t1,є$9a 6ǞƀpT+Rw̛"ּ!$-V.Fr/KC#TIvخʶi8D6 AY\-9Ys;V *a0v{ݍc0n\-*_\O>i6`>ZzYsb}5z ~)<UVXԬ+懫Wo4F7)6ݶS٠&!ٕWU^yCowhb\x0qY6B^VdUwW"ryF_p}(_ws#_LWhoƀ~=;P %߂$OmmlxMJAJ簣чl[^`*?˫+vD[R]u&Gy4ȣ%g/t-,h/5&ow,x4ΨMv,t IC\:ƽy"6Is3X=wmWUҞjҐ,_em;5pf걵ܪӺˆCV"螏;Ft);0ԝw\n%]WS*H/Nh~D^䂚cDHndq&LY!\~JIT1 UTȺA>ۿm "N"% (eTHf ;!vҦД:4ZPC8Cbpf/p|@3=$;(%TEy<7Oya8E% ϯ4n $^0* 4R_ʸtT*@],#bCb!*&BWוČ^esv'a&kPCd[B/|霟>_:EÏiO310W|sHIBs|.)=%MR΋Wvr;D\),(T؆>W_|nsB-H 3i18 _jM#'\^{ꀭVV~R_>\+Q3+Gd9LX&$ύ( L*LtٍJ<]pnI'Np%dL{>;n'oa?|ql7"EKE o7Ђ~m7ގ}&9J'$NJ\LdOp#لpol3͉\X\IԃAǕ}x<0x{x UEL:2?P!A ͔íe7ު:vkg:K,57n?v%3B\vB 0}$ Ϩӡ;(ոp$ u۬}ɼ1 %a~1X$u@Bugr aA6-:A' ;lQdѻ"E >Izr .-=c n6"o dw{àH9ַ!yۿ/|SExsh2Zi$%ۍҒuQ eEyͥfxJ|VAb^ɜe4NBŖ Ui;>+d էvϰffCC]aEy -JT1(d_~B,_-Y)r/  ) n(J#]d2)F4wre\ɻIJզfucH Cn¶}/N8M؉?aBr '[4;,n_R'i?v Y.A̼$B9(MawחAM|E r+QK"hwo#U)X+ýA-fBe؝tpsAܜK| [/Va8ŝL锲?@h"S<+eA|MXy]pQHHʗkjdmL,0 &<^^VXVSS^^ W;e*>POK@{|vK,x⚍8n0/6/h;t˪].B>,?": a 9!?v"É:%U#Q6Vߗ[O%yt^$9qt]C4g~]h͚ 1[ⰔXٸls$ sVGddM58>S>Fjt/V)8'&xbN4)ڴ{#}ARü#sk -.++pXa?R3acnXw%.$h1IQ~999Ҳ9ӻA+\7k4h;嗈^KGtMzRP5Z0&{! "'(ļӏmz>9a4~zמݠg$XdسgE9͔f6SRza endstream endobj 114 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1394 >> stream x]yPSW_IH/Q0"ZSQdl!l B$80@XZ,R6J hep"ŢٱaZ3woΡaFc'lLJ%Wt t!ednL`bػAqlyatmx81-)&Z(;ۯտi|w;GXDXE=<{R}0F,G |g;8rWN_c` 1 #1c}W!ݥyxЙtVHcрpRsjZ zAea.%{;s/PGKYoB7$Elw |Lye ޼a+eL-QʜAȠ Jcf}DGmo8f\+ygAatʅ]#kc=vXw*h8_]wp?8 8mɳ& %K B6u H-vJчQ_^!y^n-U\8=f17BKқ>#'fΟU )مY$5!.:͖X&V k9C#aZy,7 *a hV#D|yܤ3.7dDȏUߞ 8bxO;f>m1"*DH|}(Dߍhh{r BDRbTTtPcwIƓZxhS呞8ki,.EO+A:*2ɿ T7f*Aţ*ffJZݼfT5Ӕ%.ajGƆb#0Y.?EKLL edxqI7Nendstream endobj 115 0 obj << /Filter /FlateDecode /Length 229 >> stream x]10E{7$H4lCh\qeBwf[^?|rZt[pEǔQ)+d/rytˏn:d_Ka^|` 1> stream xkpWmbV"BHZi9 U?c֗h|4ͺۡK JpL)I fImhm\tEo.:c▞?|[(K9½UMFG/>B+=D+gV#nn@ܻ8^uBm6[2uW(%h JwH7iyІa8#Yxma6":byvIgIkJS]MC|EϸWw54=Izrd`ᓽ7ECZj$Y k dϵѡ n4&G$Ljj:0tW3me0=h;z[aG7}4T]IAQLFPFVP[4gp{w &ޢ8gl# 3_X`@nB],Buh5α.e :ݜF>g`` ?l5?F9YAaZ*b2ΪR{yGRe'S qBjPUP՝loODLirօoFo0UI,0j#NPMYeE1S.OEf[~˸"Ȉ(fdx1t>6 Te(.v&UUDۛl$ܒx}r>t%1lj`Ao@T{ !pNƏшaS3:?S"cpgnu)8*gfVpϨOB2MfDlY  {tOur< NMu;A?_pv'~.}ŵ-ߡ#Zέ\"7~}i/vKf3j!csB44' iO*+pwǰDa t)AhGK'p+ s~It>BiƢ'*sx}A5K\ghL cQ_kʰAxW[{{z6[jhA\A86m6m#YZŃ=ni4 Ő6JmL^hQv͍lGX,(4 8zK'hE8E<> stream xX XS׶>89"p< ؞PPTš 8+DyaFfsD8Pqmz[v׾uz}}%';{?Q(Hdnzi]9n>^2ũD(M %b7, Rǂ)'mYϳ?gy]b/a<4+s]rrz4zWAkAkm֛ܭWmؼ}NkhLQ`CаpW\ļ;/n[vv3w=gw(jHMm)j3F9P۩*ʑzrVSk(gj>B-R+eF)Q5@YP5zMRoQF2ʘZAPc);ʔZHpxJ-1Do^XtV~._ff4ѰhM1&!&/ƆM#L]17?gMco01&wkMAPR oEͰ9lZ9T~8!?-7"]NVRi.\*nx`^vޜy9M EW4Ш| ?a}?w:6a9Nv?[޻bÓBZt\Ea(8Oa16 0_m[.ɍΉiEL'UJ@"DAQI|Vʊv+!s$ +y|T15| bB6^3*Џgj*TT'Tnя?+q?qs}1k~:,G h@O1b#NpbQ<#b~<EPP`|lGPNWhX 3}ka 7"NY<\{jV {C\m@Rե퇯ʃBryEtNt TC3R={P$siw^F?|0r/y(ӫ3JB"䒙$k-Tt=>Ty_LcHy؛F|z0Ĭ@% d]]KX؈*$Op&=c<` N`c65ٞwmvQL҄>]ZT=>]وڴ.E{ة' SPc1JJUj$=v| h?u#%@3Sc>Cd[APd絤Ů8-V7>Q1 :kR]JQʭ̫6?H!C^I)<n~;94T<*R(92TO/`L,|]_bؽ2mXw~}S laXB ~ZJ=u\_nr5R㦁5MW'P XpmwdYC$Ʒf9򯈔"*1&9< ˊ6NZ}Y{ku~[s|WݻqSP%6a_Qw[}#lcǑ&$~=,jERw] B.(&*Hs17nyOn&~%ߣg6|~6HjaHN:3}x2d|nO8UxT.օTuuf-Y H4޷&B rω}.*Dg =aŜ>7$M9d,t =:(׹ԓ(ݲEk8*!B|ֽIw5罚3NdWgWeW :l1` ۋAꘛDL{O\Z!-gGt!b#a94F!qrbs(2`M~)G&ώS$!G`!i<Xt`sEExԥ2v=vpsiK`-Zo!Rk[ub 1UFC9:/9bȇt=/h_){DZPP\h8~ٚ%GQtEG%O1eOtE$Zw/vq8r?ä"y}7@Ldp)0̼xw*tl| t;34m9VEH(jc`5fv{hP42Ө->$1ʂu#ϏdHʼ+F>(''v{6qiРÒlelf!ϋ'.C tm%4Q\$*U"yE[#b#H YuzEMwS+[䍨IZd`B`7$H)iڅ矜<ΰ=s +0 6˖,:JR%gζ]F̣vwܱCCkrJZ: lD<h(,nZRPErzX*F*tzkΦuy&u ~ &8 e0ILZOE:TS1Yʣ 97aT~0'H a9U]A2>blɿ1Nwy\~|3(P$ DP0mS šMl(9"/,@J!R) &"A›z=JZ/tGj/CQzvG[$ǣ,$gSxʚa}XC]Ce4WmjX=@6)E qx } RGH\#Bayꫤ\tme)bQ!bKXeDlPŏA~z zCF~,!zrwVY!6s@ǣnɗ[?ztHCQLhQYLVx I>ы`LBg.zr>!3}5#j)!*P bPxKtU4!G1qȿχ.kaOjM@FWl>qf_Ety!6-u;kv?{#sn8lӽ{}έr쾘g;jWo|:A2/.;}IAzS'`ŋUݧ$l|,|yiRAի 48nm|N䤣ő%LL \WPS,0`kHƶ6_5K[%l䥤XG$gf'ޟ"-y8ɹ٤*kJ뵛{RKH͋*Ŧw%}1շ%y)JWc3vn/9|N)_Y4QkO}ooY<%$5?S/$lA,mbRQ,R olb-5ѩo{4rJ3QRG<5(3~I,uY =O-1x~ܨN z5`K~J9[O?||ӧ6j3z.PUBqBV#keC-yl2IqXp 1u#8 "Ky|TldIZYD11!5> -3PqLed;`dс:[og5j;^191ʲ >ȽIef>fq֊ ;"Im:}Q0.Eȗ&IѷJ`L' NYd$.%GG|ً}tafg2=bLZ,ܥ#ޥ"FshR*oW>ƧqSjL6B)QʺŠݩRPIbjCo!5U(|e^qgmN^FqÎc(%vendstream endobj 118 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3577 >> stream xuV XW&EH)EQEVjk-uE% l$B¾R\VkhNk먵Nt{}\:?}jpn([] lަ띇K₯7N 4ʛْY($/-% daXآywx!QI=!QY/*"i!ɩ{CD{CbŬfӆcmO,R|v('7/0xwҞ)ia eP0zjDfTT "dw8߶ ^=J^Z%|V0O/髏{qn-)Vq,aP).Sd2 SA[N.۹iK>/sH.`GK=M(_*}=I?F\*x\& 7CShK#R@wdZ"kڪoKesu>s-06; 2jw.( R)W~.';Yجޛ;!&kB*TE92l`h<2~Y}|ˤ5hw@ܒ kK+ `9؆4p)hxaeRC25Z KreY8 ulwk%sϧ@u{qoXNh=߆19l}қ 2y[>)8|@nu\ <Ddz7Kݫ,w#;An=ŷ[F '{UY0)=XxDv I;G91ky.{J{"yXO=  KzΡe t9언7 g6gFӫonŁ뷤'{jdM k+dKT 5eBM:՞WU/_<3o['vv= ^SBRzEH`6[4E ܾFDYm)nm7 9*;8p۲k A10\CSb3}cjWx,kT}`jt4w7`$&#h]1e?1n6aBBLhO 8Y>>̈́Ʊ|swID[X)҈ :[ǰ+#è ØoO?6 xS.eaor[M,O4muLp`- 7`t7Z&0wWgW:s*Q#г:u&=/ gTWfM:ԍw$v q㸡}DO=v1{4:eiJ@ iPY-V% ŕi35#''wW쥓HKDQ(ٶFT 盚U؎" "~Qmj 6J@ZD' *RXWfT$N)z력65*|% mZBZ + 5J q_*Ogyq+fR(I`֓ܞ`~EP%|܄&9t1~cM0Ts! *Stm;q1N5Gc!fє̯sN:O@(+uRʢE31/GڀsJ+T4'M#d fĬ`(orm:CsݾzsVPWU_ej2-=Ig#v^l}Ϊݞ]˝}tG*(IV-kU?D OtJ{D}ЌkF-d}XLcd<|!]bjr44_BaHr–rbթ%dʫ%Tb9So$: :Q}C`X{_5ۙɐT7/w/w;V!U==ڒfb:v/xװԠ7k5<{|&Ŋ|' Vci6[}}Ok U)kw*E?%`Zendstream endobj 119 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3264 >> stream xW pS~,c/ⴣ@B!,jc˲K6^d[.[6ȋ& y NP'@ !Pi!?}U0!N37{; ݰ1"3=>#R!{u+b\a `~-cnE ACN A]QT7r8;ҋVgfJRd-x|],J(+Z73?wo(>#I~ƹMfhVf(A/Me&EE%r܏Agdfo'$&%{ӗ%b+Il#vb1XMDokD8XOFl 6MD1xCF eyx{&0>$o' Myqʗ˂QG/ 2<^¿Pʹ?m(m7VdoU%yFz쪲h:u(!h͈zA > mQ^?{10EE$5R!3:e3a,(MFO-Nv:XN;] &h_܈";jIYTFlzLtND+ۺ=C]'θqŕnUɇe{C{7ܾ74fIү@X;cer爐Q35+`SҔnك[ 4#V}4قTa* h2Ng+ _:hJHn0}(Wx> < G02z;1+k{vkFw<pϣ*bqZa8 #pztSsV8mho&0tBͬ-@-30dJy~LGO *sJŎGs}u{@Z)Y6Z?\c+1:bV,Z`/TTe6[/h[X]N|2 Aְ`)0trV(TNPgy|}7 0aկ9&4{ц%g@SQS(Gü>_M2Y t8~o9B<c>/ŻD:ۚN+p")xJ{Cz~ Q>v`e*cȳ֣k`ϧsؗJCs> [z.*wЋ\_PYfTPq]Y5[$ ,}Fk-z2|i=]`1,߭|K^S -ஷ6c?x>Nޡ[[N/IMݡ%)ws>#NԊD]}07|p ]/sƄECJLŻgo%6 w9vcGfcV?aD ";N]$F++oq[eB4?MG &L_(-S߲At'XmE( gY^WК$+h2~{V=(oM7mW, ; Bk;]^ą*YO~$\F:YY%KXe6vծg:ڳk U?6S9xXosQL+ӧd@/Px ՅZ_jЫ G}:(,H2·)NĵoMk@E*em.t02%t[rϙaBF.lltr&Zy3ìCRA:upE2lǚhw*fN/dofhTGε=yyCoZ l ZR:.@YBR)Ude&IqWKItCʪ#;(|Q+#O=,(Zs6+73c sYBf4AX^}6Ph39KDIU oK^ױ;端@b=$GBJ*QcI +|z+CEE6!wA/kpzubK2nkB%, UYLU34B=|e/;㏴q-jB-Y=yˣ~+pˣx䚻SiˡtHLm&. :4ނr/ZEox{ђ!IP-gzUWuk}]C jY1՘Î 2El05|`0kAs_?ꓬJiŇͪV'ٕmMS)ܸzddXYԓzfr8O RߓK- B~@3FPH(uq`AKh4Xnr\?fr1 l27b38m~B6XxAc̈x?+u 9Vh1Gbs9 C߾OZ* yceخlJm>&>"' \Zm(תuj O(bLF mm&$bfCBꖿ~.ngU]f[?2QvD?' =6犍[_L]oѵPtzH}y?Ow.!,7f:dh2s[hm%kI? Oh?,0kP{'Nmb&Bdh2L |PPfa66KRendstream endobj 120 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 346 >> stream xcd`ab`dd N+64O,,M f!CgO/nnC }_1<=9(3=DXWHZ*$U*8)x%&ggg*$(x)34R3sBR#B]܃C53000103012_*ÂO|qwaW[ߙV޽4w~+wsne׋!۹Y}} 5.v*T];G҅?|_8{! 'r\,!!<<܇zl^}?20lendstream endobj 121 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1457 >> stream xmTiPSW~!ק"*/O6:FN "ТZMbeS6 $aAE@0%VV`iG:iyuƾh39+|}(D2D.qv!j^zuaO{򦠐>R O'?ςYMÝS0u*%H6gĘvd;s[!)ʕ8UzioNA2jquAf2*ڝ,ҤSnnQnJMLRI\)!Wb&EQ+M*Fol*JVR1T,&SRT$\rȇiFJ=4}}޶Sfπx L wC8Cfbsí_)c`Z=ȴ<$lNjh[Șx՜^sjQzsQq(YJNyoMb`o a<C9Yh\7MI^kXğ\`3žb]Zc0~Ċq%YlQɴ·O޲$0:4C:*H 1ᢩ6攦嬿` ["B߁b@xP!ssȜ#;Jpu9żPQA;FOͅޖpLG9ٜ?x) ^- Ճ _dHԜ i,y %lrQL[ W0Z]{AoՍOb8c2no1+A@(}'$ګ{[U=0y# dx--3mc,mƗ:j(rAYž-ܸrQtd/ʆQȩ+wb[Dɠ.쾀AdYǾ#٣ yiq'wa(Kd|- Bƶ},{ 5 9N3<ɒ/]Q"2O(;M*-%,!Es_`G,q9 'KIX6 0C]uwU4LqkTUzVLJDOin$n ݸޭ 8K |(0wtP :uR]mLUZv4զlK-[OeZra,`|?Z#I ̞ӎZji+@]K.s}cMqf;PQr7t*:Wr]8oRn5,yںkkP_{6jT[fC(:_sn,+Zq i^/BX x6 亱a347Jb\\_.iN˄'|ѽR@[T3j1 BB-32iDߍ& 7rTV;+yC7Wendstream endobj 122 0 obj << /Filter /FlateDecode /Length 193 >> stream x]PK s nPP[mҰ.4FEPkL2̛hkgM#8HC-Aa4BVhoҿ?h*껜xcO| )7쥂 aL4Z v5Ĥ)XbTɩЭ[d"%γyl>`ߗ%+#9E+_endstream endobj 123 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1198 >> stream xm[LSw;JE]Isl.ss{F7r5V @[nPwZNoRhZxt@\=sa!&n/9nfے230__\,V5SeҝKkՍgSԆFenxd.nȼ nQ7!f!ԳZjAo02D(NS[C!'룾^ dDh$ yg6rfŒgIYz L;*kTFaߴ4}7yKXWm56Zpl |->pazxM{ v9 IAxtoFdjfߣWf*Rhn5*Oiyi%T4{LiPd6ҊC@jΌcOi1pv#q0=6^?TWU{FE+#47^¯Uzހ ط//ADQn2~^|DVhMhnfXgHlVV_i_-&mGEm"uu aN{NoJV yME{ץ/xͪ+e=Gl cL&C[=kCGF/M8lH:넄)a ;o*sF(֟azUe$VI 6Qlpx0s9tMKK(Cg_yDAWӊR,'Ό'NЁ8.፶K'JEDq~lptŔf=Tf4?0wr ;3pS 1r Va_NM>qendstream endobj 124 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 371 >> stream xcd`ab`dd N+64uIf!CO/nnC/ }S1<%9(3=DXWHZ*$U*8)x%&ggg*$(x)34R3sBR#B]܃C5P0000103012_i eO_^Pw*ˋ T\)S^m. =wnw6/ i^O mӺvKc?{oi~}/.cA<_qsg.a][9\Ğ{z{&>&20endstream endobj 125 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1632 >> stream xU{LTgsQa93ntKPUT.ڱpQ:}fD._` raEttJUu*5mcXۤu^1a?6|ɗ|^BXm{ްnmF*iB ^IJ_+t 0})n9MKQaڵ"#-!"lOHIRSi;SVG_E3֭#MzJR4j#L) OFP%=Yq+>JJ_Ϫ^xP b(}hR^&ʐye*8!F8R[g!l=lLG"(\Ol!"S|l褯0k:za ƒNC4xFzxسQ7~UA\$h. Nz[ J%U֒ #p<븉;Ṫ .9?怜|¥Uw8 ܹ["{?bHm7;LY49/m _H;;bc_ ;ٸh(]Y8;^wC`-c^Gwdd%臐3M^z SLꟐ։X Jj\֥3]psa):h_-}p,Z=Eq#=!\Hq:izP3P |R#twoDudCUi߭?}Z- \:H-6d·Ⱦq! ◰EUZ:@. XAR.tUG |-`UeqlZ.RPVtۺ$10%!?QidZtD*4) xK5D"H h/nW X/]Dc&S< אoEގq=RitT󛊺jkˮiqų,o,G&+_u;NL_wnG:> stream x]}lSeޖQ sz{J:Jpb#R.3Fgjk]P`Kޭ XvH!d@pi q KU)")4Ƙȹ<99$wC! Qb{U/4܎N|ҘĥLi_+I-@4Eշz_ju×ҬxM^v Zo%kp _gl[-;O#T/m5- FZ*C-"!9ZO22A:>%nSGtfe!fECYA1|vęo]Q3e4%;rN t7) KרԂHݢť,*#а |qoܧO&gxwlx'}#wܣmא3ĕ,nnc֍ؒ6714^d?@öŒPK{N|)yqb}]"GL #5 # }mz^#Q(3ICIKl!yҿ}u|B'k8r + 3`&3 8nf&yY Xˀ*eޔ!705iZ셝,v_x wFwz8J\msm۸mԀDk:.84 }pߩߋah3_l|`C_A(5IO5lR+V |@jP4$YR\=x;3 vwqdO p8c`Jf/&G>~IZm7˰z~BR+P(%~pendstream endobj 127 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 4228 >> stream xX TSw1Kj3%s/ڎVݦSQ}a !,HBn%!;!l ;ܗXb7jMûyN8$'mߟCLDp8ٛ6oLzty ¤ s&~eF\1|6rgȻ .&^-.煭X|ҥaa. ې$./%d%mXyYؖ0lQvVXbJzBFjXvj؎]a÷mue?/1?+[?"|Ɇ ed>4 "DN bb'C]ȶ~KD:TZPTqd g=;5?*kR}~D"SGYNS'-Ї %yE[DwܐJ"ߏdr:Kix r(PCyn6 ^npW蕙;)@.y5$l@+?@\z/)C2˩!3P.SPR_ 6hotҎ4d5zH jl4&??)hE QPMfbhA~ƫva֔B1 -*X"*W%̮ Y+yCdI丄Lr)@'~Hx ߭(; 趷ƤIId NDs2Z9jPĀ^'wiunǾ ݽfA/V5j+Sy%:j Aͼl?. [r!9n`V |-%.$2+5Y0 \jOA&Ke A_*H2「-q{-PK_.ҎTYN_ r19UbY2bUYgNhkkjhk MwŅ .<~ 3 V^n^ܦjB^<1i[R2VD^r迚_կ2?ƷܑI#+Y/! {:> ^5`}ARIhjtͶ^Ov46%VSęK7g2l-6{?<9sn!kChܑͿ$ZP#J| ŽW}s$ /K#J5 2L;)[N۵9 ]ش=vt pͶ N;܀m5FcFXfGDU"R\v]z >CkOa#|h;ܫ>vN$^%>]BRJ6}6/f؍N#T6E#e JpJBW*ʰ؁[-5t'zhMZzZeҦ1CL+,a-.4e$Ɖ&n"Ѥ%"! P R LȀZ4JU";6q=^st"mkPn Q?vkܑDZQgIvy0XNм@qW.v//щ`N֎ʼn5<H1`|hMCsz6;/ e~G5YI[A𿕾MO 䋲n M6#T4C-vRs-d^ٛDgބk@MER Zt5zKTޓ[ 'Ů_?C|X=6' 8(_[[C&Y)0^Kqjc3>b< &"@3A 5z5;itc(V8ych5èh6tY#U^V K8w%yL QAo3fW!~"FoXJJ$lԢPhեsV#i0VOLVCO.= 7{fվHٸ}`!_3'`%A3y^, Ʈ kHhx}܏EwIO\F$줐^Az苼gG*6Z(IHJOH_87 =f/J=h†|ȫvb SC4wNzwqfl?5ƺNlA>nQ7mq=AQVq dv hĕGz+*hcZIP7 ۲2@쪳WxKks 3dI]wT1ƱihUױ64{n<׏15B~΋kcr/gfPo; hSޠ_U:Jjj:NɎFSM{]W{s=玞wV%~W.zjMiL]*djcV_ҙ.0H nt˩átė)e$vj!?^Fqxޜ\¼Ejpv%?|k7Z"4| q9n[E nO~9c,_Sb|;Ŵi=S%v%sCVYsfb*BlI lZj3vUtwE_*9$>4'hfXv,^֍LT2m(X\[pMF`@[sy9͔d4:-^t(M/U6Ti3O$ s.ClsY9Tb;/jkFY/یj+W!d1S"4{G/#wI#pm-F m0޼Q_6O8VMY:vf_KMwS؝ IBj, +fkq(x12_;uQ!0cg ~0csncʴPPܢpiB6)Ocgb)+΃ǺTug奱r0GNFt㨺2)X=/Sđ@&K_Jo`ݿ梿/;U=Q70ud:[v8>)7=KTV8NJh9FHƬբt4uB(<osN]elx~. QWs_ݯ hLcn\)$?+4eɵ|1U4dÏyϳ#؇49i k~x{_w-z{ۑC]F\hM;76yǎSatK.Θ]*qdxgE 2caendstream endobj 128 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2199 >> stream xe PSgo^AWPܛ춫+!Ul]TEM(%+pE@%Bh@ "VPl_ڮ+V[Z? Nwfg3眙ss3m HN OruY. O59LsLfǢY{XZۡb[e|o[ܞɻ)qib7ES!r$R%(zg_gdg;%'#¥1q`v-kmݼe_AɱRW7.YiBL-aGM$ b1`Kb aEqD ol6[HvrOkI5[ EkF'& Jьy?iva[L[,Ѵ7/YZIC,lMM M 0J鄫gxyMtca) 8Bjuty:;=pb/$&ɉV5EB #!V4F3D_ 5_$ "կ5gtnFF)\>%eh2Щ$+z:8xϘmLщZN8 ^PlHyTVM^ `ݥHkMG" Eu1K!5Az\j5v#d"_yt?1AaB#i }pNd7)+,ʂq5FJ">kJ׎9hygQ%׎0tE ~Y~jOĻh9|^e+.+WMC7ji5 ^N!O!~+p*{uN 8&02ߴdAB*"S4w;H\Ǩ#d2ϕHc8t7/ÈVN%)ҁ>\ g!}l-V~ⶥXccq%Pdt7{}@])ބς>Ł8AHL`]Duhʛkzrj囂 lHxmo]"AyP=ѽ rÅ/ %W旦@~iA)f:9Ia^+qE-R-R%.O@-n1[XdHE+)CE\cR&9iDf/ -^21C_e+Dd/1cL13,;.AH!)o.hrD6Gjʕ DBK@ EJپ2n=̈Hإg8i/gR+TlySUk;\}p6FAܒF Up) %*e*f!KW,j< sD}ZL :O ǹHl)cHT4tkH6hkO<R<;bZT$ϟ!~vBPVl_pQl#pRCMv9afk⺵JjA ڃk+ʇ();&`q^s.+{tu^C(`5@CMV/pg .7B7L\֚JHՒ[hVrn}3?^ˌfLVGDg#uP/_sf Bpx ,%G{Gq ,I?EVUL*½p3a>,Uxelяm?Ty[Q64 )д@dl> stream x}Oaߗ~Q{1 B>7˰ O܏9\.0 bS# 33d<}z1]b܋%6fj}ւ==\ȉ.*p"+pǤ ּpeD5ԖD} ;PɂaHCb !iZ&#I5N‚+f4GBvBMC+^eàIXVXge+Yh$IXg>jm4v-YHX d2 < ;oBۘtڨeQsP?P|U1wo -Ѝ֎$ekceP'DY~uֺNX Y+[*JAUFI7S?endstream endobj 130 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceGray /DecodeParms << /Columns 149 /Predictor 15 >> /Filter /FlateDecode /Height 173 /Subtype /Image /Width 149 /Length 219 >> stream x!PA>nX܂­h1 $[FT2k{c|ZaչFfT羾_|p(UGգQzT=UGգQzT=UGգQzT=UGգQzT=UGգQzT=UGգQzT=UGգQzT=UGգQzT=UGգQzT=UGգQzT=UNF¯endstream endobj 131 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /Colors 3 /Columns 149 /Predictor 15 >> /Filter /FlateDecode /Height 173 /SMask 130 0 R /Subtype /Image /Width 149 /Length 12958 >> stream x]w|۟˵B HT@(*RDESDKo* ("(@AHBB H/wɕ}ٹK|33BОA4ihAP?|kEp'T*eɻvjC:tPXXhGdzZD`w6kݦ8WvveR1g+8F[7òe˖/_nԵʸ.CxހS /:9rd-C毨Ņ2|"Ж<^8NNN-F;'0{8{F*ޒ j̘1?#/̶ve=V_^uݻwgI' 3f㏹H{5:L|%p?/Fha'xnpש2Bb4pEɴxuj*)Dζ+^H⋉'NMi۠87\%-鵒xhA:z8WubNqOʀ;xI@ EO&) u=Z8Z!Vu={ƍ-:g_$Bn4{WW*>OɾB_ܫW5E[sρuٻT"o$%:\6Rnm,ooo˄:>Z1 &xT*uaÆ si$ȢT5mpכֿL Mq\'N :ԔFk7a„BY-h0[yioj$ץZ,rhꫯr] ɶy63b .-[, geeVqЌ0ZiiirADSLٹs'0ۅ4uG\BgggS?~wus<i]yVBclhccSQQ ubmzh>zFane Zd :?Aksy.,f]/WN m=@}2ps]h<,5<e4[GWHp%w-ǯJ DV\?DmDp(Q5:Fj㾗dvFܳѶI͓f/j*+s_|ܫP 8OE1 AVͱlA$6 ]IAѬ.A7CjMwKQoZ Ѩ1džLX; U RT"Bd%Ab,Af(lq,Uh=3ɦ|'/%кQUIq2$DklmQ8X ا`_>f6tzЦMq+%є\oN(Umтȩ#~^GȱL ퟯ{!^/s1\@96R Y:2іG):eP ۗ7!W(yahY$E~lBoBart/^C z饇jj{QfP#$h$P4 YIhD7Rj]B~dF] tE XS^ 'p=3xOUXk޷{QomAѐK8,z=rcWp];A݌}NAo@]#C3BFک?ra"1"C~;GhU*ЇId|q\&zgq]悭^C%25w(Wqf('Q x5a5?#-?#N:oj%n EuBx>K/(b5RP碢XBkǛf,~x+9GhL. ? B 5u[Řbl# B%8-{w~ ~׃6Jutf3 "pmysWSq3a4q3[H:N^O~{:nfФU/$aϸFr%%.WS'Yu5IZ:/xȴ=V<5=^P,LA]$=71|4z~z49k~Okb%tҹhY@qSR3z aS:uq?:o$ݻ ㏛j[1Z=ȝ@;uu4t@ߔ8m/ ~R>ՂX6h*ޏz YtB쩻?Rcu4֌ө`~|{H:Yq1'uͣ6IѪ[vq9$L$ OFYsDE߼U V Qe1)ԇ?\cqY(TըLՉ&Zc;?w?w~^-dQCc%"6 v_.Ss!ß#Z oNEB4phm`M?Vvew%f5X 3w^Gׅ6~ <(rwPtRi4WՇ?Qi> ah3SzΜ*KH~̣*dia$/X?璓>~Y pm 0H:F*Bh@f.HZ2_~7@I황}^uV:,A̞ @܁iLKIm,%DhjS sꈛZ=#m@]КY]=hK ? ?AQt{DVJ."B HP \ x%C:ę3~X CL `5e\Fx4C-A:?0lۚfnL ArݡkX&m  v)TErp9ǍRxv:2yQ,2z}FT⃽_:G CI{ D4 Znj4svtrdVhS\o3p9k-X{XC]5uY` ~qVc;t6]aZڦof5*ݏHY<{vW$@/Q"4ջ!PeLf6`(R3'[ό@ǚ9"rݬCEIQm5 ۈ eAz`J@ h#!blJjYxdܡV"@]ԛnv@u d⮷ 7oT^< xcEvP_~wן wv0}H7htsG3_-fd7ĊmDS#uF)%Y.~7]st'E3{H7ʎSfx%)է|L>w`RxVwC>,;]E}5%9"7'@BT IzJK$d n}K#5+)iF"kz}!x+'^ך)[|z:=ts+w{}`r`]VZaCI2nF@, ơ"zř*[?g/I+x]ԗ͵e'^@We; re Z1oC,HMg֌~ǹnDҋU kTƕͲ6k.{XGl]v͜H̝I(fьhExhpq"RHPW\e٬@ଁYC@p)7-~Tʹ*q"O!nV2cIsPu %xEBcP(熛 @ [zitݨ;%Ҷk_;b䤺.LTk+۞4O`S5VJUH# #& PnM5*ru13l6;hXH ]Kok?LW5x4aYƾZVVN5!BJ6=:C牅{bkgֻc6?j[_!o3wzVlvMm7Q>굗u |Dɺ!%b_~L`<@_ha-P~au@='nB @2\I-׹iK+5UwZg;/GxtM{Mk\e]FB _&H*S9󡝉v3BTgUvHVi{q7%$PQ(=-嵤¯00md5]p$n jf<4S3?Ki0 h M@:^NTo\+ Lo+wyKK}aLo?+cK 7P fnc7A k4欗|y\ϱC>un=P BRߊ<[ױXqIڕ}j#1Br[1eP'kx_ kh;Ulau1H`3+”-X Я7&%:2{w{ԺgGL;3 Qq} /l.[z~ (#BC: [ mVz ioBtҎCNnKU.&eàZ殼'O:.Kk9{S#Gtcdx@dm퉘!T.]}ȟ-3[i!fɜC/w% ;Jډ;9-TU_ !CcH(ը˜dhvUVdG^Nw{V }'IHM`KC|[_KB=CJ7EIdOvَ}'zk7v96]v9avX%JW+Uq1/hG1EwopTgm, ׭ ZUrwa|b?e^6~%˭c6cS+^d油)ޟNiPISy]{07\۔SRim4wط Wùhيs^K,;QH3CPɬ\kbvY}ΒGբo'kJсKPVS)^Vl4 #E;k_KLynP&r*58?@]~ĎRSjqt=MX-xE]iw}1\oV3(vƟLQ̹7OG~WBwp6HԚj2y 7*p?l0to HB>yf]CInm-r&QWm?bl;q'ޠzPvd w]WOQ5j/̝-55 6+>(\>iO~}KFͻe}?{:}gb'i?|Yc?̂ J@(IN]k`i$BTs؁`Ic^Zh~S @:vb/7.e78| $'{R"Tqw?;~즗8\ ]9s"SxHMܚЭ>ͱۋ=m W):kVԱBn]%\;0+"p_Y0׷#H[:zirL_Y U(=\s勐=jba_ ߕ{_*7Y褀xY?+mDu{ՂV5̠>Nqz_~U@,4uu<2YRDЇo\hฺ?>s( !E?#pK H@i/{;y.33J?x}L$"i^Dn[y9 9;4Ӏ@N'ȝVׂR&/kíVT"j0Er T[h|`^Bڬn޹:,h.|pH/<'OX,䘟m 1~)rTJ+9cwVr^W;rNHȓvu}~FN*D_ZG3m? Q|7r=yHԷoۋ;C$!#-CLp@A79g79:J̓ :=jꓖvxsDTDZNz?Q_yBL  wF}.ru 1kp5/~fjFnv}?Ne3zRHԴ<{Z~^x CbI'"ͮH}5۴%8nI \MZsw,c{VT{$ .:|"k:(5j*2I[G|2qWr"EݐՀ ֘)buNҕ5K/jtT%bMԱAn=eMd톫.d?\ժsdK*Wgiբ|| )Uz1]pzM!wlhF x{NuRG&7#˥,=poH`w&IZO*ɑ/Cs%މ],(kJׂ, SONז룄By$@J^ỹxwXhO0\'=$h@u\* ro`^[$ÿ,W*UJ5u,H\~xf2Sꮍ+|S,i +2H MB#O+ilkCث\+w/": /9N`rIsK Rl+@"_ohv~1s@kk6}.v#++g@Ŗ+F G.3EUeW{ ](;4K3ǂ4WC$mANM RS m'T-<-v[QGK2!x.?C<9͠Uagq"h'\uWQ3T/&w>@v>p:N _uϏH+Rv.o?98Yd/ h!FTR| M䔠/ EAU ^nng vejY?Z%,^\gw'=$tҤ$ϓ'}:OSkQmG߱sWB]"I+.C %P`ö́׷׆N 2zJu}E*,+yG3eAoA > B7,|(clzBr`D2"tF>o<+؂z -8r!o*NAM cZCD1i y\ڮ, \16Qҍ{ņ)44Cwp?'!V4+$Q0JP#)tJp‡dT(Y}Ipk=$hd3m"_W{V0KB:1g˘YaK((s_Yc6̞& -',KYeЋSH/tC:mwYݣGG+(|uغu ,`lkkI5 $u"F8k{a"[)O@鯹 ?r@i]i??DWYiAz.F0RL[Bjح7 g1A\ C}Mݵ{"Źzj3,ڋQLguW <ж1P O"rZw}evb;#Y'+Z_yn_@Y=$s;ϋаȌ<<МX͜HK*w4Hw |%Vhp W+ۮx/7|CqˬJ k [++BBޞ-6|VY0:%񴍨BU4',R}>&g5^gU <O?m]uQ<>)2-_n%8AܥE\Pjb%Bݜi@!oCJwJQƩڛ kI HmE ]tm+!o\)'v LRM]W kK~}@;wu3<#NBE{gr₪+n!x?pĐ494{K Ukhؚx>z/7^H-Yם!텡7n1ɟo=Ǐ-{4ۯt*W%TjR =mtŏzFo"a'+Q3w8WlY7>g_6 xQFF ry|*[ Gܛٻ 4&wsxA[YQ¯`|y5m7xuV$ ,oy?4vK lٻar8]&DK/ʠ#i 8ԕ)7%>B*|lDG! 6"Ù;`=ԇzG60N5 V Xju)ÔV뿘kiL>-7'F*[fN珌7 N>s&UT۟޽{_y^BŅh] A!4V%o; ݹ8W9$B+7ICc炍1`HӧO߾};K=ΐ,H8o:'؀OF}H']0 -'Ani\(|o)X_>ùd\4?R)t]WZjwKR: NfϪ"ޠ_B@ 5$X.l>-))qpp0q]h<G}ILuf1Dͧ~ UFNς)Qq\e!&>;9|J@T:[72U| +/_ξ ڠQ3ng5.ջm 1&.G4Q*%bd܃ͪd2ODG;͠tމĖ YQB )s| bvJܝB zR&Jb/JZ.jX2R 0e %=={f(F0?U@Sy:I(lhP]:uF#u_UpPx]`xmut ^L;"S~ʺDsO7-sη~F>wJo<;yS_D~؇s? .ud ",ͦ{Inlt v8hռ%!cjHċ,"Mdh-nڈ qi$}5#Ȯ]@S;D0v7}Tg~kX^?Y0\b2Ds[B J47m4Q=)Q"|mwxA,[Y#1fYFvz5 eJWY3gsWv l5'<|r:}dW&{e:hf͚GV>Uˣq+i596pcdC;opκ1Guܫ-rKWykM%b7zҧVCLacc59<X\\lm?Q))#%By%5-?\H\s 0VD@ pe3Z(. ֓7n=m?E.}972p18؏;O;vh \\\W 4(O#$TTT2[?LPɬ\}fW:Mre˖-]hܺuLJaݏ4(E]}b :}tbh!ӧOlހȫ=/sc0w$ʯl$Z?> stream xu_L[UCgF]{JP#DAq][ʠQ Vn0u`0 FܺaaA=t}?9eo4cA'z14[]fzv 2y帠rΩ@<q+^_)GIO:^_eW-6;ޞ!=bcZk;3 )Yo\W!>SҭJy; nӕ0&&̻5>ˬ}-W~̋j= 0,#?j!L I'Y#,f .~[I^F$}H2~ ]b+TSG:߷o_ :嫋ԯs¹C=GI+5'_#0,lwj ,_ޒۧ7{Z-J 6d|(c/bהKGN BNQT">lA!(be#ZoGFWHa\0LrBS2\E ?Ltsnի.|d*ɏW2ّ<]ccCa2endstream endobj 133 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 398 >> stream xcd`ab`dd M3 JM/I, f!C럺<<,*=3#cxzs~AeQfzF.THTpSJL//THKQS/ f*h)$f$))F(+k; g```2e`b8LR ݛ~t҇?z6%tX#c\9Oong/˞]"vfa }?r]gs?Et`).,\=SgEKW,-鮕V[[=K۬e@9?g}ϟ:y&{r\,!<<ܫ{z{zz'N>ówsO)Syxtkendstream endobj 134 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 626 >> stream xmOLRq/+SUwM[Y\h`CA"" X©rJMfMVWNښۺ|!)Akh즻vwܬR\B,='ɞBGn,Ri)LvwO@JZjs]&;{zUU~oz[b빎g9K'[jPVgl &ldFŠc[5wNڬT <~Y|Dlǁ7=ƕN_Ia,[t=,,} 饕%f N])$XoA568NV`4(H0 ԇնD/8 ,dRː{;'JX:b~F+v@䎇߾;H᫸2ec>[ƶ´l-VV(D2iz=BEA$D"endstream endobj 135 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 318 >> stream xcd`ab`dd M̳ JM/I, f!CGO]nnW}G1<=9(3=DXWHZ*$U*8)x%&ggg*$(x)34R3sBR#B]܃C53000201012~_I؁{͏kN3~#XlMN ?/)KJ+b_}2?S:u2ض=tp-<{ p]b ^&N>óoֲz'Lav%endstream endobj 136 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 323 >> stream xcd`ab`dd M3 JM/I, f!CGO]nnW }_1<=9(3=DXWHZ*$U*8)x%&ggg*$(x)34R3sBR#B]܃C53000201012~_)Y{ӏN3~_Gئvkb_ޝ+ڝ͑¾lzٳTR> 7s-<{ 6qb ^;wq {'O]wendstream endobj 137 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3030 >> stream xV TSg~!j_RXPVPܰaE$l!%@e (VAQJqVjXtJvߞsWDP"h䊕kTQhkC88?ކZ 07ibp=9I匯"ѺP*f{\xhX|Ysf=[=ފHUr|d\M]*Yx.o S(C_pw_5}|XSt*&.>aY"h[pHhX_2j N1ӝVQ>jʗiZʓzZL-R˨W)oyjzIj<5SN3 PA%Ʀ;n7ٶRH6^efcpX^-6[W_ X%䂶}ʪ-4q0GG`VHh._4Jš$TAFjjxS y'{t~U 2{|*>1?6O(u3f`Op)>8v"#LEgdCgb)-͛7b= mptʃpDք+@a͵.ߕG]}K'n zi!j1u٣?σnmxt@*{~4,3?0@< P` ڿz}#̉,Ƣlwyx᧮?!JXHدȄ'c(dc,ɴMnRNOl#* &NڍżGIXrSb}Т+b = RE \^:SEղ(N }efhuJc80dLg@dEl}Uy(;;cnGI)9!mR'9mޘLdmQ,3U 充[;&B+e ڬl`-">U>hve/qʟ~Y >a NIBEMt2q4{bz8 b % ~ނocm@hKP'm\E|FYO_7Cd$bHo'c{eiv*;6@攠qCPCl{l,ƞuXz'5Ra-;dvKui\=>in'lM ]s!I]!~3%#S ˖SR+)FUp )(Vv̵ .ownre'6NC8=|L2v4;NױP%܌\mՍ &\{ \̧:㯷veGQ|.?EZf Tq1u*ZB@KhNN ^ڴaRB6=7kp:sHѐj YhcJyUaeq)ղ/\ѥjU!;|8F팺(#ބ&s[B͆ {d5M15 grzOU/Le'74tlS2z+a;~AGUBV޵!R.+܄F8޹ox1͞!{^((^81CmQڥe1ҖkԺ`~|4~%$ѮYR5ftj0 ؛!Bp9ۦGqP0ml/4`/ j+u$TCl( BM|PS煞`MdqZ0N M%]/ˆTHIݕE!cX<uXk7=ɯkUtHMWZC|@2vcD?]p6=gG}w}۩ ,44Z_l@D~AO9a6 Aذ.i3Z6_SYRymU?iM.&~&(*k[X԰V-#h"6upovߡkpyL +anOQUvg_hLF٩[!Mv/ap?ou?V\,UIt|vd.̂!K$|p;=p,3n %Y;4u-U[-sK&-q,'Bc<;TIG7%[h^c !.-V3*I tQPtyYTNd:q%t2֌UC`q8ZuрS鹂rS\*C&/%?R=Mb O qBMf.0 nV>19/Xᕕ)4\Fc.*v$;5YtW_L)js2@/>O)d?ED8W1"ge~ӅX :Uaei5mQuhC9XL"t\0ZCVI+(:ɝ!2Hߋmc-TYȋՀ৲K?ֲזQxWJϓ"%{Rj7 Elu.5I,8{[?-ѡ! a-zѱ9ߴ( _q8E3endstream endobj 138 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1359 >> stream xukPWwIJu[ݝ: 5*`EK VEBb1ezC D%Z#MVwth)uݙǗ9{qL8g2V%ffY iyB0. ޑ'4PP@! w1O3aJWb߮ݻd.eesK""ߕ\zŦi&EҌ\lx\8o:nȥgfImKNڐmLT''$- GcS!a ɜgɷ 05mX2 v`,.·Ibo 04TzN&͇B ࡗW_|0'v33F<ٷ2ewaN&C 73&ieM}:p_06_gI`E/?`\A|A 4T=C2$ [H9P:6LTXo-a(x80վClP/s$MI+4f3Jk{{ .JǠzsI2_cԬo6.c^CDH 馃}+7[w1rjsZ )aj`@/#x;/ Da$=|1\*= ֳILx6kxPE~C^s.2>ćls<)YL$u&SA>O̦h=´r0۹u`i0fkؘ棵&@jAہ]_W:\4V9LqA6 ߈Hc\H4ݕ JlǙc4V pq>Z ugBg yىwogp躏Q]U X.1A5{j ڃ|[Ψ svV~z"V43#SS^u`fPd30K~O}qHcKU~Trx>f$Un(n::x]NaQ$hil$)'{zwBepH41seD}HQ\d쯈F3gU΂o=v\Mn| g"I?aHp$pmhknp33JjpM]iҭ&@x(+p4T([++^+c_m2endstream endobj 139 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1881 >> stream xUkL[>k7YH#tKVmkn\B $q`c_16;11$@@:ڰ)mZRwNd6mڦ㹽Ò0ެsl'²1!K"ݼH/&W%R!.ZօFI%qTg>Tw|^bvlE ւC>zpUmجLv8I B탐DwJB}!*&V{C% Q;$H؆w@?@6+<(E\`1sk|WhkYa~L iO}x ˍ:(=tN׎B#7ʚڳptEHz]ɢ%c-Z"yt(W z ▬ljK iTX|<68!c}%ͣy>ӉEsVȮd_g׳؝HV5(3.2%R$HQ xltaJF>;G Tha"ym̾x,p2qR,ޭ G{eU!@[CY ml8pAO|d,O’}H2W!zqGW)Lj+6׺GzQG/yͥF~.@-h m}boGoyVnIyCY}CA;iVt7z'!\$~=85WeH$ToIG7 xfgp3+}- 7|4Kn[k8{g..d 9n߻,LEnJQFQ| e'n^L\ J\1{\sDzrD/}m`)q0)Cm>n0NBj9M恐yO<;K Zg\hpΆ%06e!rYvX/1cٴ.LNƦI_! g!ǃgzAξu4lxAϥaoݞ=-Wj!.4" ~̉.SSgQ htx\fe|7Y" &*.`۾|"*qRȖPVYTDP'AɯilWJ`*Z6mӥ}^qU}moX2/!}jEKMabY.*eeUGC(o> /W [ 1 3 1 ] /Info 3 0 R /Root 2 0 R /Size 141 /ID [<3302cd4a413d74cbe658ea81df6f0fb7>] >> stream xcb&F~0 $8J@gysf;0$-d;D uH<?D+H ,d) R8>DJH-`<`\ ,˾D\`39)ddZ b7Ոu˞gl*ɱ endstream endobj startxref 88676 %%EOF Brobdingnag/inst/doc/S4_brob.R0000644000176200001440000005031314323731145015632 0ustar liggesusers### R code from vignette source 'S4_brob.Rnw' ################################################### ### code chunk number 1: setClass ################################################### ################################################### ### code chunk number 2: S4_brob.Rnw:125-134 ################################################### setClass("swift", representation = "VIRTUAL" ) setClass("brob", representation = representation(x="numeric",positive="logical"), prototype = list(x=numeric(),positive=logical()), contains = "swift" ) ################################################### ### code chunk number 3: new ################################################### new("brob",x=1:10,positive=rep(TRUE,10)) ################################################### ### code chunk number 4: new_flaky_arguments (eval = FALSE) ################################################### ## new("brob",x=1:10,positive=c(TRUE,FALSE,FALSE)) ################################################### ### code chunk number 5: validity_method ################################################### .Brob.valid <- function(object){ len <- length(object@positive) if(len != length(object@x)){ return("length mismatch") } else { return(TRUE) } } ################################################### ### code chunk number 6: call_setValidity ################################################### setValidity("brob", .Brob.valid) ################################################### ### code chunk number 7: brob_definition ################################################### "brob" <- function(x=double(),positive){ if(missing(positive)){ positive <- rep(TRUE,length(x)) } if(length(positive)==1){ positive <- rep(positive,length(x)) } new("brob",x=as.numeric(x),positive=positive) } ################################################### ### code chunk number 8: call_brob_recycling ################################################### brob(1:10,FALSE) ################################################### ### code chunk number 9: use.function.is ################################################### is(brob(1:5),"brob") ################################################### ### code chunk number 10: is.brob_definition ################################################### is.brob <- function(x){is(x,"brob")} is.glub <- function(x){is(x,"glub")} ################################################### ### code chunk number 11: as.brob_definition ################################################### "as.brob" <- function(x){ if(is.brob(x)){ return(x) } else if(is.complex(x)) { warning("imaginary parts discarded") return(Recall(Re(x))) } else if(is.glub(x)){ warning("imaginary parts discarded") return(Re(x)) } else { return(brob(log(abs(x)), x>=0)) } } ################################################### ### code chunk number 12: as.brob_call ################################################### as.brob(1:10) ################################################### ### code chunk number 13: setAs ################################################### ################################################### ### code chunk number 14: S4_brob.Rnw:363-368 ################################################### setAs("brob", "numeric", function(from){ out <- exp(from@x) out[!from@positive] <- -out[!from@positive] return(out) } ) ################################################### ### code chunk number 15: setMethodbrob ################################################### setMethod("as.numeric",signature(x="brob"),function(x){as(x,"numeric")}) ################################################### ### code chunk number 16: setAsbrobcomplex ################################################### setAs("brob", "complex", function(from){ return(as.numeric(from)+ 0i) } ) setMethod("as.complex",signature(x="brob"),function(x){as(x,"complex")}) ################################################### ### code chunk number 17: asCheck ################################################### x <- as.brob(1:4) x as.numeric(x) ################################################### ### code chunk number 18: print_methods ################################################### .Brob.print <- function(x, digits=5){ noquote( paste(c("-","+")[1+x@positive],"exp(",signif(x@x,digits),")",sep="")) } ################################################### ### code chunk number 19: print.brob ################################################### print.brob <- function(x, ...){ jj <- .Brob.print(x, ...) print(jj) return(invisible(jj)) } ################################################### ### code chunk number 20: setmethodbrobshow ################################################### setMethod("show", "brob", function(object){print.brob(object)}) ################################################### ### code chunk number 21: as.brob14 ################################################### as.brob(1:4) ################################################### ### code chunk number 22: get.n.set ################################################### ################################################### ### code chunk number 23: S4_brob.Rnw:462-466 ################################################### setGeneric("getX",function(x){standardGeneric("getX")}) setGeneric("getP",function(x){standardGeneric("getP")}) setMethod("getX","brob",function(x){x@x}) setMethod("getP","brob",function(x){x@positive}) ################################################### ### code chunk number 24: setlength ################################################### ################################################### ### code chunk number 25: S4_brob.Rnw:478-479 ################################################### setMethod("length","brob",function(x){length(x@x)}) ################################################### ### code chunk number 26: setmethodSquareBrace ################################################### ################################################### ### code chunk number 27: S4_brob.Rnw:489-496 ################################################### setMethod("[", "brob", function(x, i, j, drop){ if(!missing(j)){ warning("second argument to extractor function ignored") } brob(x@x[i], x@positive[i]) } ) ################################################### ### code chunk number 28: setReplaceMethod ################################################### ################################################### ### code chunk number 29: S4_brob.Rnw:509-526 ################################################### setReplaceMethod("[",signature(x="brob"), function(x,i,j,value){ if(!missing(j)){ warning("second argument to extractor function ignored") } jj.x <- x@x jj.pos <- x@positive if(is.brob(value)){ jj.x[i] <- value@x jj.pos[i] <- value@positive return(brob(x=jj.x,positive=jj.pos)) } else { x[i] <- as.brob(value) return(x) } } ) ################################################### ### code chunk number 30: .Brob.cPair ################################################### .Brob.cPair <- function(x,y){ x <- as.brob(x) y <- as.brob(y) brob(c(x@x,y@x),c(x@positive,y@positive)) } ################################################### ### code chunk number 31: setGeneric_cbrob ################################################### ################################################### ### code chunk number 32: S4_brob.Rnw:565-566 ################################################### setGeneric(".cPair", function(x,y){standardGeneric(".cPair")}) ################################################### ### code chunk number 33: setMethod.Cpair ################################################### ################################################### ### code chunk number 34: S4_brob.Rnw:576-580 ################################################### setMethod(".cPair", c("brob", "brob"), function(x,y){.Brob.cPair(x,y)}) setMethod(".cPair", c("brob", "ANY"), function(x,y){.Brob.cPair(x,as.brob(y))}) setMethod(".cPair", c("ANY", "brob"), function(x,y){.Brob.cPair(as.brob(x),y)}) setMethod(".cPair", c("ANY", "ANY"), function(x,y){c(x,y)}) ################################################### ### code chunk number 35: cbrob ################################################### "cbrob" <- function(x, ...) { if(nargs()<3) .cPair(x,...) else .cPair(x, Recall(...)) } ################################################### ### code chunk number 36: test.cbrob ################################################### a <- 1:3 b <- as.brob(1e100) cbrob(a,a,b,a) ################################################### ### code chunk number 37: sqrtmethod ################################################### ################################################### ### code chunk number 38: S4_brob.Rnw:630-633 ################################################### setMethod("sqrt","brob", function(x){ brob(ifelse(x@positive,x@x/2, NaN),TRUE) } ) ################################################### ### code chunk number 39: checklogsqrt ################################################### sqrt(brob(4)) ################################################### ### code chunk number 40: mathgeneric ################################################### ################################################### ### code chunk number 41: S4_brob.Rnw:645-676 ################################################### setMethod("Math", "brob", function(x){ switch(.Generic, abs = brob(x@x), log = { out <- x@x out[!x@positive] <- NaN out }, exp = brob(x), cosh = {(brob(x) + brob(-x))/2}, sinh = {(brob(x) - brob(-x))/2}, acos =, acosh =, asin =, asinh =, atan =, atanh =, cos =, sin =, tan =, tanh =, trunc = callGeneric(as.numeric(x)), lgamma =, cumsum =, gamma =, ceiling=, floor = as.brob(callGeneric(as.numeric(x))), stop(paste(.Generic, "not allowed on Brobdingnagian numbers")) ) } ) ################################################### ### code chunk number 42: checktrig ################################################### sin(brob(4)) ################################################### ### code chunk number 43: .brob.arithstuff ################################################### .Brob.negative <- function(e1){ brob(e1@x,!e1@positive) } .Brob.ds <- function(e1,e2){ xor(e1@positive,e2@positive) } .Brob.add <- function(e1,e2){ e1 <- as.brob(e1) e2 <- as.brob(e2) jj <- rbind(e1@x,e2@x) x1 <- jj[1,] x2 <- jj[2,] out.x <- double(length(x1)) jj <- rbind(e1@positive,e2@positive) p1 <- jj[1,] p2 <- jj[2,] out.pos <- p1 ds <- .Brob.ds(e1,e2) ss <- !ds out.x[ss] <- pmax(x1[ss],x2[ss]) + log1p(+exp(-abs(x1[ss]-x2[ss]))) out.x[ds] <- pmax(x1[ds],x2[ds]) + log1p(-exp(-abs(x1[ds]-x2[ds]))) out.x[ (x1 == -Inf) & (x2 == -Inf)] <- -Inf out.pos <- p1 out.pos[ds] <- xor((x1[ds] > x2[ds]) , (!p1[ds]) ) return(brob(out.x,out.pos)) } .Brob.mult <- function(e1,e2){ e1 <- as.brob(e1) e2 <- as.brob(e2) return(brob(e1@x + e2@x, !.Brob.ds(e1,e2))) } .Brob.power <- function(e1,e2){ stopifnot(is.brob(e1) | is.brob(e2)) if(is.brob(e2)){ return(brob(log(e1) * brob(e2@x), TRUE)) } else { s <- as.integer(2*e1@positive-1) return(brob(e1@x*as.brob(e2), (s^as.numeric(e2))>0)) } } .Brob.inverse <- function(b){brob(-b@x,b@positive)} ################################################### ### code chunk number 44: setMethodArithUnary ################################################### ################################################### ### code chunk number 45: S4_brob.Rnw:767-776 ################################################### setMethod("Arith",signature(e1 = "brob", e2="missing"), function(e1,e2){ switch(.Generic, "+" = e1, "-" = .Brob.negative(e1), stop(paste("Unary operator", .Generic, "not allowed on Brobdingnagian numbers")) ) } ) ################################################### ### code chunk number 46: check_minus_5 ################################################### -brob(5) ################################################### ### code chunk number 47: brob.arith ################################################### .Brob.arith <- function(e1,e2){ switch(.Generic, "+" = .Brob.add (e1, e2), "-" = .Brob.add (e1, .Brob.negative(as.brob(e2))), "*" = .Brob.mult (e1, e2), "/" = .Brob.mult (e1, .Brob.inverse(as.brob(e2))), "^" = .Brob.power(e1, e2), stop(paste("binary operator \"", .Generic, "\" not defined for Brobdingnagian numbers")) ) } ################################################### ### code chunk number 48: setMethodArith ################################################### setMethod("Arith", signature(e1 = "brob", e2="ANY"), .Brob.arith) setMethod("Arith", signature(e1 = "ANY", e2="brob"), .Brob.arith) setMethod("Arith", signature(e1 = "brob", e2="brob"), .Brob.arith) ################################################### ### code chunk number 49: check_addition ################################################### 1e100 + as.brob(10)^100 ################################################### ### code chunk number 50: brob.equalandgreater ################################################### .Brob.equal <- function(e1,e2){ (e1@x==e2@x) & (e1@positive==e2@positive) } .Brob.greater <- function(e1,e2){ jj.x <- rbind(e1@x,e2@x) jj.p <- rbind(e1@positive,e2@positive) ds <- .Brob.ds(e1,e2) ss <- !ds greater <- logical(length(ss)) greater[ds] <- jj.p[1,ds] greater[ss] <- jj.p[1,ss] & (jj.x[1,ss] > jj.x[2,ss]) return(greater) } ################################################### ### code chunk number 51: brob.compare ################################################### ".Brob.compare" <- function(e1,e2){ e1 <- as.brob(e1) e2 <- as.brob(e2) switch(.Generic, "==" = .Brob.equal(e1,e2), "!=" = !.Brob.equal(e1,e2), ">" = .Brob.greater(e1,e2), "<" = !.Brob.greater(e1,e2) & !.Brob.equal(e1,e2), ">=" = .Brob.greater(e1,e2) | .Brob.equal(e1,e2), "<=" = !.Brob.greater(e1,e2) | .Brob.equal(e1,e2), stop(paste(.Generic, "not supported for Brobdingnagian numbers")) ) } ################################################### ### code chunk number 52: setMethodCompare ################################################### ################################################### ### code chunk number 53: S4_brob.Rnw:872-875 ################################################### setMethod("Compare", signature(e1="brob", e2="ANY" ), .Brob.compare) setMethod("Compare", signature(e1="ANY" , e2="brob"), .Brob.compare) setMethod("Compare", signature(e1="brob", e2="brob"), .Brob.compare) ################################################### ### code chunk number 54: check.compare ################################################### as.brob(10) < as.brob(11) as.brob(10) <= as.brob(10) ################################################### ### code chunk number 55: brob.logic ################################################### .Brob.logic <- function(e1,e2){ stop("No logic currently implemented for Brobdingnagian numbers") } ################################################### ### code chunk number 56: setmethodlogic ################################################### ################################################### ### code chunk number 57: S4_brob.Rnw:906-909 ################################################### setMethod("Logic",signature(e1="swift",e2="ANY"), .Brob.logic) setMethod("Logic",signature(e1="ANY",e2="swift"), .Brob.logic) setMethod("Logic",signature(e1="swift",e2="swift"), .Brob.logic) ################################################### ### code chunk number 58: logchunk ################################################### if(!isGeneric("log")){ setGeneric("log",group="Math") } ################################################### ### code chunk number 59: miscgenerics ################################################### ################################################### ### code chunk number 60: S4_brob.Rnw:954-1005 ################################################### if(!isGeneric("sum")){ setGeneric("max", function(x, ..., na.rm = FALSE) { standardGeneric("max") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::max(x, ..., na.rm = na.rm) }, group = "Summary") setGeneric("min", function(x, ..., na.rm = FALSE) { standardGeneric("min") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::min(x, ..., na.rm = na.rm) }, group = "Summary") setGeneric("range", function(x, ..., na.rm = FALSE) { standardGeneric("range") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::range(x, ..., na.rm = na.rm) }, group = "Summary") setGeneric("prod", function(x, ..., na.rm = FALSE) { standardGeneric("prod") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::prod(x, ..., na.rm = na.rm) }, group = "Summary") setGeneric("sum", function(x, ..., na.rm = FALSE) { standardGeneric("sum") }, useAsDefault = function(x, ..., na.rm = FALSE) { base::sum(x, ..., na.rm = na.rm) }, group = "Summary") } ################################################### ### code chunk number 61: brob.maxmin ################################################### .Brob.max <- function(x, ..., na.rm=FALSE){ p <- x@positive val <- x@x if(any(p)){ return(brob(max(val[p]))) } else { return(brob(min(val),FALSE)) } } .Brob.prod <- function(x){ p <- x@positive val <- x@x return(brob(sum(val),(sum(p)%%2)==0)) } .Brob.sum <- function(x){ .Brob.sum.allpositive( x[x>0]) - .Brob.sum.allpositive(-x[x<0]) } .Brob.sum.allpositive <- function(x){ if(length(x)<1){return(as.brob(0))} val <- x@x p <- x@positive mv <- max(val) return(brob(mv + log1p(sum(exp(val[-which.max(val)]-mv))),TRUE)) } ################################################### ### code chunk number 62: setmethodsummary ################################################### ################################################### ### code chunk number 63: S4_brob.Rnw:1050-1062 ################################################### setMethod("Summary", "brob", function(x, ..., na.rm=FALSE){ switch(.Generic, max = .Brob.max( x, ..., na.rm=na.rm), min = -.Brob.max(-x, ..., na.rm=na.rm), range = cbrob(min(x,na.rm=na.rm),max(x,na.rm=na.rm)), prod = .Brob.prod(x), sum = .Brob.sum(x), stop(paste(.Generic, "not allowed on Brobdingnagian numbers")) ) } ) ################################################### ### code chunk number 64: checksum ################################################### sum(as.brob(1:100)) - 5050 ################################################### ### code chunk number 65: factorial ################################################### stirling <- function(x){sqrt(2*pi*x)*exp(-x)*x^x} ################################################### ### code chunk number 66: use.stirling ################################################### stirling(100) stirling(as.brob(100)) ################################################### ### code chunk number 67: compare.two.stirlings ################################################### as.numeric(stirling(100)/stirling(as.brob(100))) ################################################### ### code chunk number 68: stirling.of.1000 ################################################### stirling(1000) stirling(as.brob(1000)) Brobdingnag/inst/CITATION0000644000176200001440000000070713762776702014625 0ustar liggesuserscitEntry(entry = "Article", title = { paste("Very large numbers in R: Introducing package Brobdingnag") }, author = "R. K. S. Hankin", journal = "R News", year = "2007", volume = "7", issue = "3", textVersion = { paste("R. K. S. Hankin 2007.", "Very large numbers in R: Introducing package Brobdingnag", "R News", "7(3)" )})