speedcrunch-0.10.1/0000755000175000001440000000000011015364704013257 5ustar helderusersspeedcrunch-0.10.1/HACKING.txt0000644000175000001440000001154011015364561015066 0ustar helderusersHACKING file for SpeedCrunch BUGS AND FEATURE REQUEST ---------------------------- The issue tracker location is http://code.google.com/p/speedcrunch/issues/list. Report any known bugs and other annoyances as a new issue in our issue tracker. This makes sure that the report will not get lost. Contributed patch can be filed as an issue, with the patch attached to the issue. For a feature request, file it also as a new issue but tag is with "Label:Enhancement" (instead of "Label:Defect"). If possible, tag every issue with appropriate milestone, e.g. "Milestone:0.8" is this feature is supposed to be fixed/implemented in the upcoming version 0.8. If the targeted milestone is not available yet, add it using tab Administer, Issue Tracking. TEST SUITE ---------- In order to catch regressions as early as possible, automatic test suite is already implemented (and should always be updated). At the moment, it comprises of two programs: testhmath and testevaluator. These programs are available only if you build using CMake. Generally it is recommended to run these both test programs as often as possible, preferably after changing something and before committing the changes. New feature which breaks the test suite or without a corresponding test case is subjected to be reverted. Program 'testhmath' checks all the functionalities of the core math library. Some corner-cases are necessary to ensure the library is well behaved. If you change hmath.h/hmath.cpp, make sure to run 'testhmath' to verify that your change does not break anything. If you add new feature(s), add the proper feature(s) tests into testhmath.cpp. Program 'testevaluator' mainly checks expression parser and evaluator. This includes all the supported built-in functions. If you add a new function, make sure also to add test cases for that function (the more, the better) in testevaluator.cpp. REPOSITORY ------------ /trunk is the main development tree. This is considered unstable. Features development should happen here. /branches is for the development of stable versions. A branch, like /branches/0.8, is created before making the very first release (it may be alpha, beta, or even .0 release) of version 0.8. This can be prepared by the following steps: mkdir branches/0.8 svn copy trunk branches/0.8 /tags is for tagging a release version. Think of it as a snapshot of a branch. Nothing should be committed to this directory, thus bug fixes should be applied the appropriate branch. Furthermore, each release must have exactly one tag. For example, there are release like version 0.8-alpha, 0.8-beta, 0.8, 0.8.1 then the /tag directory may look like this: /tags/0.8-alpha /tags/0.8-beta /tags/0.8 /tags/0.8.1 Tagging the repository can be done like the following steps: svn copy branches/0.8 tags/0.8-beta /www stores files for the web site. Ariya Hidayat will synchronize his server content (http://www.speedcrunch.org) with this directory every now and then. WEB SITE --------- Files for the web site is stored in the Subversion repository under directory /www. When making changes to HTML files, please make sure that the HTML code is still valid. Use http://validator.w3.org/ to verify it. For convenience, the ChangeLog is linked directly to the file in the repository, e.g. http://speedcrunch.googlecode.com/svn/branches/0.7/ChangeLog The web site pages must be updated just prior to make a release. See in details under the topic 'Preparing a release' below. The web site can also updated without a release. This is the case e.g. when putting a new interesting screenshot or adding a question (and answer) in FAQ section. PREPARING A RELEASE --------------------- This is a checklist of things that must be done to prepare a release: * Make sure that ChangeLog is up to date * For the first release of a version (e.g. version 0.8-beta, not version 0.8, 0.8.1, 0.8.2), create a branch (e.g /branch/0.8). * Tag the repository with a good name, e.g /tags/0.8-beta and change version numbers in CMakeLists.txt and crunch.pro. * Create the source code package, e.g. speedcrunch-0.8-beta.tar.gz. Place it in the download location. * Calculate the MD5 sum of the source code package * Notify packagers to make them aware of the new release. * Update the website. Most important is the link to new source code package and its MD5 sum. For a stable release (e.g. 0.8 or 0.8.1): update "download version xx" link in all pages update main content in download.htm add or change features description in features.htm create new screenshots for screenshots.htm update link to ChangeLog in the sidebar of download.htm For a non-stable release (e.g. 0.8-alpha, 0.8-beta, 0-8-RC) update sidebar in download.htm PORTABLE VERSION ---------------- Build the "portable version" using the following command: cmake -DCMAKE_CXX_FLAGS:STRING="-DSPEEDCRUNCH_PORTABLE" \src speedcrunch-0.10.1/TRANSLATORS0000644000175000001440000000226111015364561015020 0ustar helderusersca | Francesc Farfán | franfar@gmail.com cs | Blondák | blondak@neser.cz de | Wolf Lammen | ookami1@gmx.de es_AR | Lucas Sallovitz | krusty.ar@gmail.com es | Francesc Farfán | franfar@gmail.com eu | Iñigo Salvador Azurmendi | xalba@euskalnet.net fi | J-P Nurmi | jpnurmi@gmail.com fr | Grégory Treiber | kenshinjonin@gmail.com he | Jonathan Avraham | shambler.com@gmail.com id | Yolla Indria | yolla.indria@gmail.com it | Alessio Sclocco | alessio.sclocco@gmail.com nl | Maarten Fonville | maarten.fonville@gmail.com no | Thomas Finneid | tfinneid@student.matnat.uio.no pl | Witold Wysota | wysota@wysota.eu.org pt_BR | Fábio Margarido | fabiomargarido@gmail.com pt | Helder Correia | helder.pereira.correia@gmail.com ro | Iulia Taulescu | iulia.taulescu@gmail.com ru | Irek Khasyanov | quard8@gmail.com sv | Johan Thelin | e8johan@gmail.com tr | Serdar Soytetir | tulliana@gmail.com zh_CN | Liang Qi | cavendish.qi@gmail.com speedcrunch-0.10.1/LISEZMOI0000644000175000001440000001274711015364561014451 0ustar helderusers SpeedCrunch est un calculateur puissant et de haute prcision. Sont dcrites ci-dessous ces possibilits les plus intressantes: * Haute prcision, jusqu' 50 dcimales * S'utilise facilement avec le clavier informatique * Rsultats montrs dans une liste dfilante * Historique des expressions utilises (en utilisant les flches haut et bas) * Fonctions intgres: abs, sqrt, pi, log, exp, ln, sin, cos, etc * Auto-compltion des noms de fonctions * Support des variables, pour comprendre essayer x=pi/3 puis sin(x) * Variable spciale ans, ayant pour valeur le rsultat du calcul prcdent * "Oprateur" de pourcent, pour comprendre essayer 45%*75, ou prix/80% * Support des angles: Alt+D pour passer en degrs, Alt+R pour passer en radians Aide et patches sont les bienvenus. Critiquez ou envoyez vos messages lectroniques ariya@kde.org. Utilisation de SpeedCrunch -------------------------- L'utilisation de SpeedCrunch est aise: Tout ce que vous avez faire est de taper l'expression que vous dsirez calculer et de presser la touche entre. Le rsultat est affich dans une liste supportant plusieurs lignes. Vous pouvez tout aussi aisment copier le dernier rsultat d'un calcul dans le presse-papiers en utilisant la combinaison de touche Ctrl+R. Si vous souhaitez rutiliser l'expression que vous venez alors de taper, pressez les flches haut et bas de votre clavier pour ainsi accder l'historique. En sus des oprateurs algbriques de bases tels que + (addition), - (soustraction), * (multiplication), / (division), ^ ou ** (mettre en puissance), sont aussi supportes certaines fonctions, comme sin, log, abs et beaucoup d'autres. Vous n'avez aucunement besoin de vous rappelez les noms des fonctions, vous avez pour cela une fentre vous donnant toutes les dfinitions en tapant la combinaison de touches Ctrl+F. Notez aussi le support de l'auto-compltion: tapez par exemple le lettre s et dans un temps trs rduit il vous sera donn le choix entre les fonctions sin, sinh et sqrt. Les calculs plus avancs ncessitent parfois l'utilisation de variables. SpeedCrunch est tout fait capable de dfinir des variables. En les dfinissant au dpart, en prenant par exemple x=0,3, cela voudra dire que la variable nomm x aura une valeur de 0,3. Si vous tapez alors sin(x), cela reviendra faire dans la cas expos ci-avant sin 0,3. Vous pouvez dfinir autant de variables qu'il vous plaira. Si force d'utilisation de nombreuses variables, vous ne souvenez plus qui correspond quoi, la fentre accessible via la combinaison de touches Ctrl+I vous aidera surement en vous donnant accs toutes les variables prcdemment dfinies. Il existe une variable spciale, appele ans, qui a systmatiquement pour valeur le rsultat du calcul prcdent. La non-moins clbre et indispensable variable pi est aussi prsente. Votre historique des expressions (100 expressions au maximum) et vos variables sont enregistrs pour une utilisation future. Ce qui revient dire que vous pouvez utilisez les rsultats de vos travaux mathmatiques n'importe quel moment. SpeedCrunch peut aussi comprendre certaines expressions incompltes. Pour prendre un exemple, si vous tapez sin suivi d'entre - communment calculer le sinus de la dernire valeur- , le logiciel traduira automatiquement l'expression en sin(ans). Vous pouvez galement pour des fonctions comme celle-ci omettre les parenthses si comme variable vous prenez un simple nombre sin 0,1 gale sin(0,1). En parlant de parenthses, ne pas les fermer n'est pas grave: SpeedCrunch le fera automatiquement pour vous ( cos(pi/4 gale cos(pi/4).< Il est aussi possible de personnaliser l'apparence de SpeedCrunch en changeant les polices et couleurs utilises pour l'affichage selon votre bon-vouloir. Raccourci-claviers: ------------------- Haut/Bas raffiche l'expression prcdente Ctrl+I insrer une variable Ctrl+F insrer une fonction Ctrl+R copier le dernier rsultat dans le presse-papiers Ctrl+S sauvegarder la session actuelle dans un fichier texte Alt+D mode degrs pour les fonctions trigonomtriques Alt+R mode radians pour les fonctions trigonomtriques Installation ------------ Rendez-vous sur le site officiel http://www.speedcrunch.org pour le tlchargement Vous aurez besoin de Qt (par Trolltech), avec au minimum une version 4.2 si vous dsirez compiler SpeedCrunch. La plupart des distributions Linux ont normalement la dernire version de Qt, il n'y donc pas de quoi s'inquiter si vous tes dans ce cas de figure. En sus de cela, vous aurez aussi besoin du paquet de dveloppement (appel qt-devel ou qt3-devel, cela dpend des distributions). Licence ------- Copyright 2004-2005 Ariya Hidayat (site internet) 2005-2006 Johan Thelin 2007 Helder Correia 2007 Wolf Lammen Portions Copyright 1991-1994, 1997, 2000 Free Software Foundation, Inc. French translation: Vibet Alexis SpeedCrunch est un logiciel libre; vous pouvez le redistribuer et le modifier conformment la licence "GNU General Public License" tel que publie la "Free Software Foundation"; soit la version deuxime, soit selon votre choix n'importe quelle version ultrieure cette dernire. Ce programme est distribu dans l'espoir qu'il sera utile et plaisant, mais SANS GARANTIE AUCUNE; mme avec le concept implicite de VALEUR MARCHANDE. Rfrez-vous pour plus de dtail la "GNU General Public License". speedcrunch-0.10.1/ChangeLog.floatnum0000644000175000001440000007105311015364561016664 0ustar helderusers2008-04-10 fixed a buffer overflow floatnum.c: - a temporary buffer in float_setinteger holding the ASCII representation of an int, was 1 byte too short. 2008-03-29 fixed a semantic error in floatconfig remove expbase from structures in floatio floatio, floatconvert - refactor: remove unnecessary expbase field from structures floatconfig - bug fix: corrected semantic errors in BITS_IN_*EXP that could lead to failures when converting huge numbers to non-decimal bases 2008-03-25 let most of the IO conversion code see the exponent as an integer value (instead of an ASCII string) floatio - refactor: keep exponents as integers, not strings 2008-02-04 separate the formatting of the scale from that of the significand clarify semantics of BITS_IN_EXP floatconfig: - clarify semantics of BITS_IN_EXP floatio: - return the scale as integer and provide a separate scale formatter 2008-01-30 simplify _trigreduce bugfix in float_shl error reporting in float_out floattrig: - use float_divmod to simplify calculations floathmath: - corrected a recently introduced bug in float_shl floatio, floatconvert: - float_out now reports an Error 2008-01-17 made floatnum 'const' aware. use of enum Error instead of #define'd error codes bug fix in _gamma0_5, when a fall back to the general gamma routine did not handle a negative argument correctly. cleaner error reporting, several fixes in this area all routines in floathmath and floatnum now take const parameters (const floatstruct*), when a parameter is invariant in a function call. Actually, these parameters are not guaranteed to be constant; they may, for efficiency, assume intermediate values throughout an operation. But they are always restored on return (note: this 'constness' is *not* safe with respect to concurrency!). This rework revealed a few minor bugs related to error handling, not visible to SpeedCrunch, and one, where SpeedCrunch could freeze (Gamma(x), when x is a very large multiple of -0.5). Fixed these. All error values now use the enum Error from errors.h floathmath, floatnum, floatcommon, floatgamma, floatlogic: - const awareness - bug fix in _gamma0_5 - error constants from an enum floatio - error constants from an enum 2008-01-09 bugfixes in float_frac, float_gamma floatnum.c - float_frac could cause memory corruption, when the fractional part had leading zeros floatgamma.c - pochhammer_i reported a series of poles for x == 0 and n >= 0, where it should be regular, actually. testfloatnum - added a testcase checking correct handling of tiny fractional parts 2008-01-01 introduced a few const attributes 2007-12-28 refined error reporting floatconvert - float_in reports all IO errors now 2007-12-09 fine tuning fixes of minor bugs floaterf, floatseries - fine tuning of erf and the Taylor series - fixed a few glitches testfloatnum - added a test suite for float_erf - extended the suite of float_erfc to check more corner cases 2007-12-08 bug fix floaterf - _erfc could hang on tiny x. Fixed - tuned _erfc floatseries - adjusted working precisions to be best for _erfc testfloatnum - added test suite for float_erfc 2007-12-06 bug fixes fine tuning floaterf - recent changes introduced a bug in _erf for large x. Fixed floatseries - testing revealed: erfcsum could die if the working precision fell below 1 before the final loop was executed. Fixed. - fine tuned the precision parameters in erfcsum testfloatnum - added a test suite for erfcsum 2007-12-05 fine tuning floatseries: - adjusted the working precision such, that the relative error of the asymptotic series of erfc is below 1e-99 for a 100-digit evaluation floaterf - sharper evaluation of the lower bound for the asymptotic series based on a theoretical analysis - correct error reporting in _erfc testfloatnum - added a test suite for erfcasymptotic 2007-12-02 fine tuning floatseries: - the asymptotic series for erfc accumulated round-off errors. increased the working precision in the loop by one. 2007-11-30 bug fix floaterf - fixed wrong evaluation of erf for 0.5 < x < 1 2007-11-29 erf and erfc implemented, but rigorous testing and fine tuning are not done floaterf - completed functions _erf and _erfc floatconst - several new constants and a working space for the erfc function 2007-11-28 started implementing the erf function: Taylor series for erf floaterf - new file containing erf related functions floatconst - new constant 2/sqrt(pi) used for the erf function floatseries - added Taylor series for sqrt(pi)*erf(x)/2 - added asymptotic series for erfc floathmath - added float_erf - added float_erfc 2007-11-20 comments floatnum.h - minor style change in comments 2007-10-30 relax behaviour of float_setexponent floatnum: - it's convenient if you can assign any exponent to a zero (without effect), regardless of the valid exponent range. Reworked float_setexponent accordingly. testfloatnum: - adjusted testfloatnum to reflect the change 2007-08-30 fix error reporting rename a couple of functions more and better tests floatnum - float_round takes a dest parameter - fix error reporting of float_round - fix error reporting of float_int - rename float_changesign -> float_neg - rename float_clone -> float_copy testfloatnum - added tests for float_move - new (extended) test routine for float_round 2007-08-29 bugfix: new tests uncovered a memory leak more tests floatnum - fix memory leak in float_clone testfloatnum - better and more tests 2007-08-28 start testing error behaviour more tests floatcommon - const modifier for parameter in setasciiz floatnum - make float_clone sensitive to maxdigits 2007-08-26 allow modification of the precision limit get rid of float_setbcnum: do not expose too much of the internals in the interface more tests floatnum - update comments - simplify float_setrange - new functions float_setprecision and float_getprecision - remove float_setbcnum - rewrite float_setinteger to not use float_setbcnum testfloatnum - remove test cases for float_setbcnum - rewrite test_divmod so it does not use float_setbcnum - more tests 2007-08-23 bugfix, extend testcases a new set of test cases uncovered a bug in float_setsignificand floatcommon - refer to the variable maxdigits instead of the constant MAXDIGITS floatnum - make maxdigits mutable - bugfix in float_setsignificand (digit count could be off by one in rarely encountered special cases) testfloatnum - more test cases 2007-08-11 extend test cases testfloatnum - extend tests of test_getexponent to extreme values 2007-08-10 refactor, extend test cases floatconvert - pack2floatnum: simplify a bit, uses variable range limits now testfloatnum - started refactoring testcase handling - {long,check}{add,mul}: check reverse order of arguments automatically - bugfix: tc_checkadd, tc_checkmul: check expression was wrong, rendering the tests useless - added some corner case tests to test_longarray{add,mul}, test_setnan, test_setzero, test_isnan, test_iszero 2007-08-09 sometimes it would be nice if temporary results could exceed the overflow underflow limit. Make these limits variable. Rename this file to ChangeLog.floatnum. floatnum - introduce a variable overflow/underflow limit. New functions float_setrange and float_isvalidexp 2007-08-01 comments, refactor floatconst, floatgamma - simplify a bit by merging two constants floatconfig - changed some comments 2007-07-31 refactor, comments floatgamma - added some comments - minor refactoring 2007-07-30 bugfix, extension of nCr floathmath - extend the range of nCr towards big integers by using lnGamma floatseries - bugfix: lnGamma returned NaN on extreme large arguments (> 1e43). 2007-07-29 compatibility issues, refactor floatcommon - new function float_roundtoint hmath - make trunc and round work more like current SpeedCrunch 0.8 implementation - enable engineering format - check unstable evaluation near poles and zeros: underflow to zero or set NaN floatconvert - refactor: use float_roundtoint 2007-07-28 bugfixes hmath - break conditions in loop of cbrt were often missed. rewrote cbrt and used adapting precision and exponent extraction. - implement fall back behaviour in formatFixed. formatFixed falls back to scientific format, if it cannot display large or tiny values 2007-07-27 bugfix, refactor, comments, checking memory leaks floatconfig - make DECPRECISION user-definable. MATHPRECISION is the maximum precision of the math library, the user cannot change that - made comments reflect the new meaning hmath - The algorithm in HMath::cbrt could overflow. Applied some low level improvements, that not only fixed this, but also improved performance. - removed a define HMATH_MAX_PREC - let + and - underflow to zero in case of almost full cancellation floathmath - trigonometric functions now report FLOAT_UNSTABLE, if fed with a large value > 10^DECPRECISION floatnum - refactor: was no leak, but always call float_free when float_create is called. floatconvert - refactor: was no leak, but always call float_free when float_create is called. - checked all memory allocations, seems to be free of mem leaks floatconst - add a floatmath_exit routine, that releases all constants not needed so far, but want to have a complete interface floatseries - fixed a memory leak in an error path (that should never be reached, but anyway) floattrig, floathmath, floatcommon, floatexp, floatgamma, floatipower, floatlog, floatpower, floatlong, floatio, hmath - checked all floatnum memory allocations, seem to be free of mem leaks 2007-07-25 bugfixes, comments refactor: finally got the ioparam stuff out of the core. It is free of grammar information now, except that digit sequences are ASCII sequences in big-endian format. This is not going to be eliminated, because almost all clients (scanners) will have digit sequences in this format (or can easily convert it to it). floattrig - fixed a comparison in _arctan: An optimization was completely skipped. Now arctan runs a bit faster when x > 1 and does not choke on an endless loop any more when arguments are really huge (> 1e100000000) - create an early out path in _arcsinlt1 so that this function does not underflow on extremely tiny arguments floathmath - fixed comparisons in float_arcsin, float_arccos and float_arccosxplus1. They did not recognize the error case |x| > 1 before floatio - added or modified comments - refactor: _str2seq: rename match into leadingdigit - refactor: _int2str: remove unnecessary code, leave n unmodified, get rid of getioparams - refactor: _clearprefix has only one caller and is trivial, so get rid of it - refactor: _exp2desc: _int2str does not query ioparams any more so there is no need to set the default ioparams some minor changes 2007-07-22 refactor, removed all fall back behaviour in IO. floatio - refactor: let the caller of str2int set the prefix floatconvert - refactor: simplify _outeng no _out* has fall back behaviour any more, it returns an error instead testfloatnum - removed a few test cases, that tested fall back behavior 2007-07-21 refactor buffer overrun checking completed floatio: - added comments - refactor: new type t_buffer, to allow overflow checking - refactor: make all digit sequence handlers use t_buffer - refactor: encode* was called only once, include the code in caller - refactor: all *2str functions report error in case of buffer overflow - refactor: get all the t_ioparams stuff out of the core of floatnum floatconvert: - refactor: adjust _emptytokens to handle t_buffer - refactor: all output handlers report buffer overflow - refactor: get all the t_ioparams stuff out of the core of floatnum - refactor: get all fallback logic out of the core of floatnum - bug fix: fixed memory leak in error path hmath: - refactor: doFormat uses t_buffer now testfloatnum: - adapt test cases to new interface 2007-07-20 refactor, comment hmath - use IO_FLAG_SHOW_BASE and IO_FLAG_SHOW_EXPBASE - cattokens needs no buffer for sign encoding floatio - started commenting - refactor: rename leading0 to leadingSignDigits in t_seq_desc - refactor: Flags IO_FLAG_SHOW_NONDEC_BASE and IO_FLAG_SHOW_NONDEC_EXPBASE replaced by saner IO_FLAG_SHOW_BASE and IO_FLAG_SHOW_EXPBASE - refactor: make _significantdigits public, as it can be used in floatconvert - refactor: input: restrict knowledge about sign characters to the parser only - refactor: input: do not separate complement information from sign information - refactor: input: restrict knowledge about basetags to the parser only - refactor: input: sanitize maxdigits handling - refactor: input: reduce dependancies, only the parser knows about t_ioparams - refactor: output: restrict knowledge about sign characters to outermost cattokens only - refactor: output: do not separate complement information from sign information - refactor: output: restrict knowledge about basetags to the cattokens only - refactor: output: pass base of exponent directly to float_out - refactor: started implementing buffer overrun checking floatconvert - refactor: rename leading0 to leadingSignDigits in t_seq_desc - refactor: use _significantdigits 2007-07-18 bug fix provide an INSTALL file for those curious enough to try floatnum floatconvert - to convert really huge numbers, a constant in _lg2 needs to be specified more precisely. 2007-07-17 got floatnum running under SpeedCrunch! first bug fixes hmath - bug fix: operator>> should use float_shr, not float_shl - get rid of HMATH_COMPARE_PREC - for 80 digits precision, a working precision of 83 is sufficient - general mode for non-decimal bases has now fractions equivalent to HMATH_MAX_SHOWN floatgamma - _lngamma, _gamma return NaN in all error cases - refactor: rename _lngamma_ext to _ln_gamma_prim - refactor: lngamma_prim: separate pos x handling from neg x - refactor: remove special cases x==1, x==2 from _lngamma_prim - refactor: _pochhammer: leave the pole detection to the subroutines. floattrig - bug fix: _trigreduce returned a non-zero value in case of error floatio - new flags IO_FLAG_SHOW_NONDEC_BASE and IO_FLAG_SHOW_NONDEC_EXPBASE 2007-07-16 finally the two-valued factorial of SpeedCrunch, which is a rephrasing of the Pochhammer Symbol, which in turn can be written as a quotient of two Gamma function values, is fully supported. That means, that the quotient does not necessarily overflow, even if one of the Gamma values does, that cancellation of poles is handled properly, and that neither the difference of the arguments to the factorial nor any argument itself need to be an integer. Started merging the latest changes from 0.8 hmath - added extra tests to nCr and nPr, because the redefined factorial would otherwise interpolate and extend both functions (e.g. nPr(-21, 2) == residue(Gamma(-22))/residue(Gamma(-20)) == 462 and not NaN) - added Gamma and lnGamma - added logic operators - added formatEngineering - added constant phi and limited it to 130 digits - added gcd - added cot and friends - added min/max - added statistic functions floatgamma - evaluation of rising Pochhammer symbol, Gamma and ln Gamma are based on a primitive, that allows handling of poles, and negative values. - ln Gamma is extended to negative arguments by redefining it as ln abs Gamma x 2007-07-15 CMakeList.txt - added all floatnum files - added compiler switch -g to allow easy debugging testfloatnum - typo: missing _ in _FLOATNUMTEST - rewrote the test suite for the Pochhammer symbol floatgamma - refactoring: use _sinpix in several places - in _pochhammer: corrected handling of poles in the denominator - some bug fixes in _pochhammer - replaced a few EXACT parameters, that lead to trouble with huge numbers - in _ofs: no need to do evaluations using floatnum floattrig - moved evaluation of sin(pi*x) here floatcommon - this was needed in several places: float_isodd 2007-07-14 Added all higher functions to hmath The Pochhammer symbol needs some testing hmath - refactoring: removed duplicated code - pi value used from floatconst - replaced higher mathematical functions by floatnum's functions - introduced inverse functions of the hyperbolic functions floathmath - added float_raisei - added float_lg - added float_pochhammer - bug fix in float_tan floattrig - bug fix in trigreduce floatgamma - removed a memory leak - generalized the pochhammer symbol 2007-07-13 started reworking hmath, got a first version running. The testhmath suite is almost completely passed. The few failures are all explicable and do not really indicate a problem. testfloatnum - compile an empty program if _FLOATNUMTEST is not set CMakeList.txt - added some floatnum sources to testmath - added floatipower to the sources list of testfloatnum hmath - rewritten to use floatnum floatnum - float_setsignificand, float_setscientific use const char* now floatconvert - some const modifiers added - other minor changes floatio.h - added missing extern "C" tag - removed include of floatnum.h, floatio is based on text only - forked t_tokens into two almost identical structs, one for input, using const char*, the other for output, using char* many const modifiers needed for this floatipower.c floatipower.h - new files that contain all the power functions not using logarithms This way, conversion does not include all the high math stuff floatpower.c floatpower.h - moved all integer based power functions to floatipower 2007-07-12 first v0.01 release of floatnum two io routines linking floatnums io to external parsers added last issues connected to two's complement io are resolved. only error and corner cases are not tested yet. 2007-07-10 again a rework of the io floatlong.h floatlong.c - removed unused _longintneg function 2007-07-05 major rework of io routines. Mostly floatio and floatconvert are effected, but there are smaller improvements on other files as well. Base 10 output seems to run, base 16 output has still to be tested thoroughly. floatconfig.h - fixed a bug due to typo --- testfloatnum.c - added new testcases --- floatlong - refactor: move t_longint and basic procedures here --- 2007-06-21 complete new input parser capable of parsing inputs of base 2, 8, 10 and 16 floatio.c floatio.h - added new input parser --- floatconvert.c floatconvert.h - new conversion routines float_parse and float_str2num converting input strings to floatnum, bases 2, 8, 10 and 16 supported --- testfloatnum.c - added test cases of float_str2num - added convergence tests of gamma series 2007-06-17 started input parsing floatio.c floatio.h - added several input parsing routines 2007-06-16 floatlogic.c - removed unused _canconvert - bug fix in floatnum2logic: removed memory leak - bug fix in floatnum2logic: crashed when 0 < |x| < 1 --- floatio.c floatio.h - new files containing all IO related stuff like character handling - refactor: output routine significand2ascii --- floatnum.c - refactor: moving most of float_getsignificand to floatio - deleted some unnecessary stuff in float_setsignificand 2007-06-15 Logic functions seem to be ok. I'm sure, some corner cases are still lurking, that will make an operation fail, but on the whole... Gamma function and family seem to be ok as well Next, special output routines will be addressed. A standard output routine is already available (for bases 10, 16, 8 and 2) --- CMakeList.txt - updated dependencies --- number.c - fixed a bug, bc_int2num could not convert the most negative integer --- testfloatnum.c - added test_pochhammer - added test_lngamma - added test_gamma - added test_gammaint - added test_gamma0_5 - added test_longint2floatnum; - added test_floatnum2logic - added test_logic2floatnum - added test_not - added test_and - added test_or - added test_xor - added test_shl - added test_shr --- floatgamma.c - bug fixed in _pochhammer - added special case treatment in _lngamma for x == 1, x == 2 - adjusted working precision in _lngamma, _gamma --- floatconst.c - fixed a bug - added constant cUnsignedBound --- floatconvert.c floatconvert.h - added reverse conversion _longint2floatnum - added support for zero in floatnum2longint --- floatlong.h floatlong.c - added _longshl --- floatcommon.h floatcommon.c - boolean result type is char --- floatlogic.c floatlogic.h - new files containing a draft of logical operations --- floathmath.c floathmath.h - added float_not, float_and, float_or, float_xor, float_shr, float_shl 2007-06-14 conversion seems to run, at least in ordinary cases. added a draft version of factorial computation. testfloatnum.c - added test cases to test_stdconvert - added test_lngammaseries --- floatconst.c - added Bernoulli numbers to constant list - added constant 12 and -20 to constant list - extended precision of constants to 120 - added constant ln(sqrt(2*pi)) - added constant sqrt(pi) --- floatseries.h floatseries.c - added lngammaseries --- floatgamma.c floatgamma.h - draft version of _gamma, _lngamma, _pochhammer, _gammaint, _gamma0_5 --- floattrig.c floattrig.h - boolean result type char --- floatexp.h floatexp.c - boolean result type char - added new function _power10 --- floatnum.h floatnum.c - boolean result type char - removed test_floatnum declaration --- floatpower.h floatpower.c - boolean result type char --- floathmath.h floathmath.c - boolean result type char - added functions float_power10, float_gamma --- floatcommon.c floatcommon.h - added float_asinteger 2007-06-13 the conversion algorithm is in many parts ok, a lot of test cases are handled correctly. Some tests are still outstanding ChangeLog (this file) - reverted the order of entries. It is better to have the latest at the beginning --- floatconvert.c floatconvert.h - renamed u_array to t_uarray - renamed t_bigint to t_longint - reworked interfaces to use t_longint - introduced a new struct t_convert to hold an intermediate conversion state - reworked interfaces to use t_convert - rewrote many parts - bug fix: half size of UARRAYLG is big enough, because a char contains 2 hexdigits - fixed several bugs in the conversion algotithm --- floatconfig.h - adding a comment explaining the limit on BITS_IN_EXP --- testfloatnum - adapted test cases to interface changes - added test cases for _stdconvert 2007-06-12 tying together the parts to implement a draft conversion algorithm For the moment, to hex only, and to intermediate data structures CMakeList.txt - updated dependencies --- floatconst.h floatconst.c - added constant 16 for conversion --- floatconvert.h floatconvert.c - declared t_bigint, to be used later - implemented a draft version of a hex conversion algorithm, has to be tested --- floatgamma.c floatgamma.h - introduced empty templates to the code base. After all, that's where all started from. 2007-06-11 testfloatnum.c - added test cases to _raiseposi - added test_raisei; --- floatpower.c - fixed a bug in _raiseposi - adapting scale in _raiseposi, so that the error is always < 1e-99 for 100-digit computations --- all - renamed arcsinh to arsinh, arccosh to arcosh and arctanh to artanh 2007-06-10 radix conversion is on its way. floatconfig.h - introduced a define MATHPRECISION, that controls to what maximum precision a higher mathematical function can be called --- floatconvert.c - changed return type of _bitsubstr to unsigned, so we can deal with more than one digit at a time. - introduced type u_array - fixed typo in name '_floatnum2uarray' fixed bug in _floatnum2array - replaced all uarray2* by a generic uarray2str --- floattrig.c - using MATHPRECISION --- floatcommon.c - using MATHPRECISION --- floatconst.h - removed FLOATMAXPRECISION. MATHPRECISION has taken over its role --- floatpower.h floatpower.c - modified the interface of _raiseposi slightly --- testfloatnum - added test_floatnum2uarray - added test_uarray2str - added first testcases for _raiseposi, more pending 2007-06-09 floatlong.c floatlong.h - added an overflow-checking addition routine _checkadd - added an overflow-checking multiplication routine _checkmul - moving _findfirstbit here and make it public --- floatconvert.c - using floatlong's version of _findfirstbit --- floatpower.c - removed _lgi - use floatlong for exponent calculations --- floatnum.c - clean up: using _checkadd in float_setscientific --- testfloatnum.c - activated somehow dropped test_setzero, test_getsign, test_getlength, test_setscientific tests - added test_checkadd - added test_checkmul - added test_longarrayadd - added test_longarraymul --- floatconfig.h - removed define FLOATMATHTEST. FLOATNUMTEST is enough --- all - spelling: mathma.. replaced by mathema.. 2007-06-08 heading towards the missing radix conversion routines. Necessary, before a hmath version can be installed. As a side effect, the power operation is developed CMakeList.txt - updated dependencies --- floatlong.h floatlong.c - introduced these two files to the code base. They contain a portable long integer arithmetic --- testfloatnum.c - added a final message - added test cases for _longadd, _longmul, _longshr --- floatnum.c - using floatlong's _long* functions in float_setscientific instead of special bit pattern based integer overflow detection --- floatexp.c - in _exp: cleaned up the setting of the exponent and added a safety check --- floatcommon.c floatcommon.h - introduced a new function float_isinteger - using floatlong's _long* functions in leadingdigits. Should now return correct results without exception --- floatpower.h floatpower.c - introduced these two files to the code base. They contain the basic routines for the power operation --- floatconvert.h floatconvert.c - introduced these two files to the code base. They contain the basic procedures for converting a number to a char array based on radix 16, 8, 2 --- floathmath.h - added comments --- all - whitespace removing - replaced 'unsigned int' by 'unsigned' 2007-06-07 The first target testfloatnum is compiling and running, and all tests are passed. CMakeList.txt - updated dependencies --- floatconfig.h: - moved configuration settings into a separate file, floatconfig.h. - introduced a define BITS_IN_EXP, the number of bits available for the exponent (including the sign of the exponent) in a floatnum. This definition is more basic than EXPMAX, and useful when implementing exponentiation. --- floatnum.h - introduced a new error code, FLOAT_UNSTABLE. It indicates a situation where the mathematically correct result cannot be evaluated due to limitations of the algorithm. Used with higher mathematical functions only, not with the basic operations in floatnum. - updated many comments to reflect the latest state and to improve the style. --- floatnum.c - removed defines that are handled in floatconfig.h now - fixed float_sqrt and float_round, where a spurious result value could be returned. - declared _movepoint explicitly static void - introduced a new function float_getdigit to access a single digit in a significand. - removed superfluous variables - updated and introduced new comments --- testfloatnum.c - removed defines that are handled in floatconfig.h now - removed function declarations that were leftovers from changes - removed conflicting definition of float_error - correct initialization of floatnum module - made tests verbous - extended tests to higher mathematical functions --- floatcommon.h, floatcommon.c - introduced these two files to the code base. They contain declarations and definitions for helpers and convenience functions, used throughout the evaluation of higher mathematical functions --- floatconst.h, floatconst.c - introduced these two files to the code base. They contain declarations and definitions of constants used throughout the evaluation of higher mathematical functions --- floatseries.h, floatseries.c - introduced these two files to the code base. They contain declarations and definitions of routines for evaluating Taylor series of cos x - 1, cosh x - 1, arctan x, arctanh x, used throughout the evaluation of higher mathematical functions --- floathmath.h floathmath.c - introduced these two files to the code base. They contain declarations and definitions of the top level calls to higher mathematical functions --- floatlog.h floatlog.c - introduced these two files to the code base. They contain the basic routines for all functions related to the logarithm --- floatexp.h floatexp.c - introduced these two files to the code base. They contain the basic routines for all functions related to the exponential function --- floattrig.h floattrig.c - introduced these two files to the code base. They contain the basic routines for all functions related to the trigonometric functions and their inverses --- hmath.h - corrected comments related to hyperbolic functions. Hyperbolic functions are not based on angles, so they do not depend on any degree setting 2007-06-03 number.c: - fixed a bug in bc's number.c, function bc-divide, that causes trouble when overwriting the dividend while dividing by 1. floatnum must have this fixed. speedcrunch-0.10.1/COPYING0000644000175000001440000004316011015364561014317 0ustar helderusers GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. speedcrunch-0.10.1/doc/0000755000175000001440000000000011015364704014024 5ustar helderusersspeedcrunch-0.10.1/doc/new_engine.pdf0000644000175000001440000064777311015364561016666 0ustar helderusers%PDF-1.4 %äüöß 2 0 obj <> stream x]ˎ$mWڋv; TW €;^$OD03$VWe<lLE)-cbh: .mMt1gqmL7?eHz~ԗ7y'/pjeS)o'}硅^7+F^jr0y lryhݮ|mʌmq$(,m.ӭ嫻+.'/Kv ;WᮿL?h6V6}Ίoc8XiyEumR[5N;8pD Ѥx jyNi9$/S`ojaOL>k5P߷B,k_?+wpIK~̍kY7%Y,~v 7B ̫Øhwe4a["8Oȿ4G&xQy"ܡWxR#qD0HG-#p\l?]' 36/~5D*WoL>xs_#Zv_!'H%#7:+T$̌}GVH4+d(L#&ux໵։<84qޓ2DNN>F+;лf7quq3!xwCغ=g/GgqG7m+ڍh>3JnNjK㮀fI!#CwW@(| ء`S54?p/{Kܛ\l4"b:|L.G:b%g!r$qTsTϦ&qfL^0'aAovGwfגF\oO0lr K.dC%ڽfOЬ܅dO;%MA4qYm@$](EVHZ"BTЃp~I[N_%b cv7esu;@Ƙ$ͬhGoJY"m,K.\$P$${XL*_/SwUHh׉94lQ1dsK{,Qz2O˴(z G.{ [G,D# yIZ*?r(?Ϯ}L%0@TTm/9vVU~hc1B)^Xçz2 k7<^ļL ts&9\2EiqRBS/:37ă<8ytQ$S5;H>s? :i/q*-;6.X|x ҦVNAhpS tjW}܃"鐌`9*%s$4b$%՛oD(eO"spea~^њze&jIX^+Zn.6fPISqi?WL+F#b ̙8HfNJdv;{&Z EbG ;H{-D/+d7 Wzq*j eQ:P~J'@T0hZGwy z=lj[Ʈq@D*$[JX1hҺg&" @y^TZV랴n2@gb6s`+zȴF 2 D6Woz/  ҳ6n{G/#QD۞~rʎP[_ב~܊ܰVdIXëHKzҢ-l¬aeЛbrj;f-Q &.!J@K:h!IIJ{IZs;8Yu*}Yb׫lWJTr.dݦkyQM9t-S+W_OKIuqqCiLk%[Ц=;z9 bx UGbg! n{;b0䬢GwDTe z3Ka]tGf D*rҖ!zc@vRgIoV-.9^ R]F}#?=1GO}P]utjczQX9ĝoԟ`M6h3۽-xNl꼣mZN#ܞ–UȒhTAM@!Wf>UkZ.0n`j"b <f})rXz`qojY Mko0%@)#Qc]C#(+hSxa*~-M- >Gy֙o~Cq> nFCrÆ p5yP6h+yKل"[B=fokw}!/OO@PyPk}sA艶V;! ɷqBz$p"IJ-ۡWY{s`H[~Fvl1[u~ݓ1cI>"%L۱oNQMN_ ah]|o/w*4 U~gg:{*xmR0ayK9r8Gj<6}wI\ŤoaLokFlگlq#5rj=ͪ[{l0. hUGP$zɔz-c^" $K"ؙ5)<Vܬx+5nTGvoes KgB;J/u<ָin4Zd^2l,툢8~ f:=sF a $$|X z[]m  ɝlˡ ]o 4cЕ!q`vr,bBJh4_M,d%+n`W NFv(67:'ǫd8E-EG w"tT*BZU_4K'I I0([uwfj"0Σ Y^{GkD Z9rF1)Ikn'C4Ԧ S%dK7VíP< wخi'۱l n5@x᧨ߐ 뀑DKͺ"Z @\\ TNӛqU>mu#&CmՃ~WI)[ T{}mK2$Fh{f/!_Zë9ǐЙmϏ >" 8EdXqrt#0jIfaN_RAŌv# |g?/`_0YBr~Sa2G ó=!;JZAĐÃػt\ԓ7:>gO oys(F.bZj ۗ}е9kVɽhZS%)xQ(@ho&/ Ol @!vv$'Why5|e8 &.8iq|~s "TWki{5a>~8k$D4ޜHjזg$tQ@_]mCB?T~B^GbG}`B/}x(}%͡KJ"Pmb|LN=7dA/HƵ/BΝ{>qՅDtt B {S=gb4bG i=Xsi}f'hݾZm7i+ǡ(In"TkX&mkpچ`} /|j)ޞּk+rf̔6wMPS]r@6;ok*Pws#nw-/\pt7|YM='ɟΖAI-tKtɟW!Rp?Fߤ^t&SQ|dY( rT ϟ9Lf.^{rr j4-D[":ٚe#sN|i#{b>$_M V;SL1=g69h[2T,IPNT='h`_zG^Ӗ]W<(_eP|F͙-. WĠ#',\DXB+Wн+G Hq._ױy"ҩb;fcU]j,~08A .#p_t|1oT?\N*9A6Ugik!_-ADT[I)`3vc{;!(x#ˣy. PBW ҽr)se\x[|8SvbvPA5y;-Fb-,6.T 4C 7Q]kk +6 K7]WU|xvJsڮJts6xJp ͡э%Kz[ T6<N)dzEʪ#%tNhjJkc=yIz/O\*=QzSc: PPe0tY"R؍R.q65^ϥz, ̓@V]4׸Tg"@ U vFlrHAĭOEΓoQNٶK.]+2pI~4E\$] oF7SYk nb׷V endstream endobj 3 0 obj 5506 endobj 5 0 obj <> stream x]ˎ8WzѶ$K6 ƽ07m=H#"׶DqxH߷mzߖmyok߷ۿԿ~cs[Jݽۼ5nJ_~77k\)W+Υ5m?wS:Ս>bpSsLq<7,녴 ?oH?t/x)+$pҶ߷ŸOkxkZ{WN*auNޯo m[Nkw1yMYvTޥuu.gbYܴfY{fyo2\FrP1 ;~Teثsh~K}Nl$ad TGcN45IKalwTxMϓifH)E }-XEbMEx:JH>놼)lͲqʋ(d z S3"ה<(3gĵ!-EW s\0f˯d}vmC/AMaa?Y=fal@e03_pIGSi{x~l< +SK 'RGy6BĹӚwWΈ JN$]ZqZ~H[9+Nq!0hEwe}V/\ 0~hmvљq? Q I`T6jFACIrv HO>"Mu4d,S~mG2Nyq ]87޵:2C Ͳ PFߎ۶EBv zRb8<}2֖y5-fT1 p ދPC<ص&:Ф2D9Ӓ2&/r$n93M7{0U9J\,3f8ڌ#hI$CLm:fN=5b֨ y1B l`Nmdeہȋ6,.qNX Q/Nz9D8E۴U&\ ,lBddC"EYx?{>>>(,,er{.4V+G0Ova;G9.5DtOhX$d%"okFX0t9AG+[omkp@Ubw/uF0_+{iե QL)3G_CU vTW[H6报8.vi d.DKR.R[UZ4K-Ƥzt[@mQ)/ncܟ1;,Ywf±o~6*Bkۚ?6x^ _=Vfp%Ym&ey0|}܃1:-&5$C6½ );gREQhwP<) :Y!Kߺ W%>. 9cB9DO+2*T^hf*[8l(:OQrzr!;=vz$5|9*Ou5W t W#GQ90IlWth_@~ܐ] YK 1YwMf 4;s^)_T&րVIM5aSp73wu}Q]n ]佇}H% KOYGvFAuDhqIR?_"O`6\EsH)|m8+b eh=m vu7R"D;=a]#c R+1M˜[`!Ҩe3R7fB2Xh>1 SYTݫhYK38x,Aj3]Y[da~4@i A:>;|[&pOcw]NM\E2:n_e,-`+#cn rzY\jV2>U*v"MR^[iN\|smʤ췣#c#y,8 l;+')"9eAFN=x P\]H, đ7NN#*lՕ*Ys]I;WMh*޶>lGjۺgk*4|VTgm`C~ӆ:d#fb/a+=-qPyp4z%!~ԗ 5uJ]8*c{e<7.xx]e}~\ZSGKxFxɗ~Ɓt[Zz_cLؕLlp(tgUQ0yU0[g:* BގYi0|!g\셧橷Id!-K %iJ c/^O5}LBdK$\GI8nuOeĩfΛWU O>Y45^8'.kmFzcjnU) 5XWHNă9{gz,~6ੴH3SpMf%5=?JMGHd竽윑C.diU̸wr;r#qphdzlj*A{6G='>{9Q>NGi2\bc|vY4ѱ`K 0L8yM,?P2A_k65"`?~Bآϱ C0xUpS&R햺Μ._':˧*6.} Km=GUonǣ]WSE9^Wv6ř$dK-Rt,VR- \^n= nmeU`:6=xݻp ~z9;Oa\k3PQָQuU73wqܖ._T9l%L|^⪌6\SsK ccW_wspP@Wݐչ{{re2FCŮL縏uvb.0ȩA=pY= 1YCN]7.ƺ!.L| 'vSqtnT|PC³̪ؽ.^\9S-"܎{i={x(#wd3KCJc:8[hH`N㪅=P=1TO 8VX͠(eW3?5gAҋu#tJa~}>#s憣Uܹ`7b>sJ I3)݂@@\;iUK0VsqHsRѻ pMUw4G1&qaENvOh`m%eԷ\kx|A )ѾnHWz9-qAKb-v> stream x\ɮ ݿ: G5F_[7@ M~?5qP| HkK%yxxrܖr7Vooo?![Jno?vL~9y_?RԿs%Cם{Pn?.s]װo}BC3/%p7h)]av5\.\MSYVܪ}7z2g?w#8X cU_ב:+>ptںjPw> O߽'_WKuS:4 ű2\jӣX}--ߞ;Ly vr$s3£(Y"yk|>K<<ȍ#aõ,$k]-ebb0v=uZ-}Zܙ94!0P5fUpGC*LSq`.umw5K Ybw{į "xzfŸƒ:ZM( _vf)az @0xk}BV-t+{Ʈf1)kܦ)8J@OUtPav%He-lFy?'.n1B-B3qRNDG<dz` a8-3c %U"yjn]/=`[(>Ll 3}fm|V鴧fC1W-4&Kӆ% Y(\+bА3<.R-WNWQiyn3D'DX B,5rk8Y cy]mEV{(G*8a ]I>}vpbí$e/M4Je ϊ{xq(Q.{.J^>vJ́y~f۪|"Ic;LbpiҀ%f܎W [Tp0Mt[#"FlMQ5yi\<,v^+M?$} u)7 PU6"*CAKfmFXya&:KǎsM̳?I.Kuw-

6qr~%ȁ] a ;M@(BU.vUSz*fT/NH7%)xHmL>UAaDM[Y0nUwr7dRS l[ +`Q{&> S &ҰEfZ q.W~q%JO݇o$'Fd*g?5TR6ͭ/"EPTYJ2Xu:oS8>+VC?oHy`ھN6Cu"c3cո': ~yhגJ忙Lrr z_Pa+AQk .AaV07eM؈2~sάq'W@ xq -{hrvlvIޟ'YzL!kO ԩxZQ(c!Eu8tPN͵Ըc$  <t/o+ۂс!~&0 xd aD <Ɯ).C4RBU0u>l1{ v7҆7v0GXI:W~vP$ٚz(d(Ind{>pKh~ʙ(LxVI]{ G-PrJ \#kzenAw|=SK7G!<&' HtfRK TTB?Xl\U`> .f7 æP yb)Ev\)0}2,ZWcUm@zh߁ȴEu8WdfhALspT5RZY>:;wONMܻͿgl5tV>f`l/7Nce>a:%i??ȇxL| x0S0\~Agvq5%Ϯ?Aoӱc#Y+^',o̓PkX H^Ya@`C8/պCb1 ~`ր7:=#00sxk+ܧ?'x[mP@@aߝɝg*zcfqgr~1e",r'ajy7%Ss+oW( x&:)\@܌6LcTR2֣TLdrx&`%P#tP f>Sc_8zOgS3=r*f@ /M\{*FyuAi( Su2hen:' 6?QQk?ho}F@BJ`+ie sQ¶a*\n~dx=ᢀ ]9>kj>tpKOnTu$O!r iݰ6-h/.IJ|'n,]y]4:>(cͰѼ1ST?N DD-ȔwTa{MՕLLJ(뎎P^q$Pb唎]q,^m̈8^7Wy%a MFKIxv_=Gۘ鍧R}6aة166['}>:L- T 7Œ#`̚IN^U7H _|_^*J8f_xl ' KFƷm/Wu4J wZCTzhvN}͜V́ b B+;,c,X>2p4m6ny>F8i CjC<+5~ ~R endstream endobj 9 0 obj 4552 endobj 11 0 obj <> stream x< x[yGum8vl6ImR;8:˶( I΃-ҕuIW^14Q }(02&]Q )i>AHlkiheensÖM^m{_?|XٜFhJ4y<_iNZkEkxf"55#HNdzO}/MU܍ϯO=SNQ A%)uOAˋ>Ҿ|LJ&uqB9j2i$CT/%y _%ɝ)=HWysK:\=B6zMNP*eF(al/yupg y#P&A"+R;mݞ'Q=7vVl"w{^ɍrCE: (G=JyN9*ϓs[yB-vc"'xsB什>Cw3q4qSޝgޝUH\#@E5/Te=VMp Jw#G6{;?#_ E| 㔱v }+N9)X\)wҨpI=Xê χnӹ=OCj#Oy'% ) {_ _p%& `Xµwy\^ur`X;ߗp0%a/ilB.p%kpjBՈ'%iMiBrNSFȷf #ߦ$~Z K,kz\Ui W%\ؼmn0VHC+)jR|s)`%  +dy$\Ij-aCQ Wk {+HUK۲JhVp=(J\$o0C;$qaDyK,[>.ai9;=9 B^ҲB* WKHtpm[ WI\t eo`ӬGL+) ̟L2YH3k^ʏF.#=z]%5=LjLOLnfwiQpF+51avQAr1 ( mXY^"cfBM&&b`%zi,KY̚hq;Bi<:45ia!DXLh'ErI5K9fi!ƄxGE"&?cIRd &g\9 PtrEaN:Y0!_0洬84edc&ka+nVdA/fCpLz^0mLKOj|)sP-PMKl£1KǤQp1Fgpwʒz`5[@0zrAU %\M?2a6(a6 V[}l[0id,#`#?m X`h(ӑ  <7<a`FFQI*sbCP&|> #M.l{!6: FK`(J ޑEpG#!_`cHlU1ҎR" 7YO0!˭30<2#c}HpdP` U|?L8N BA z@;CވDۣ%#cx. ݶ) X~WH&Fu9H(e[01(ܟ#"ОyR^#6?: H0Z2mNieԩ>NHc:kk 3K:Nu+\:9Wn԰Yjb2" LΝL5"RM13/fIBQ2du<2-,&LjVV^YyM XAΥP[JԒ툛wDOc E.U؄ 3,];Tt\:h+{f AT Z)At~$|TP2;LZhXJkW^^: {Z=-J{%ZBD؉JW*Nߒv s,g]]b.q32ѴNegeeb2ѹ-;mɴL4:ytJ-h~:u#v:-)uGlwN;Z(Ƈ.h|;ƇƧwxrE@}Uǔ[бi$2 ~75uqIӼ2K2錁}J&GY it"XJᥕq#eѧe)tw I4wTy`BHxeaPbI cC >PĈ\_yܽnFHd ܵɂa otB'6\4!HsI0kAϥEt%Wdn~v\Z/qQIL0Prr0N0e10{Znw9ebix!IZLFKv|]˳7Y57/9^b &Y ad I{BHXĿ,шJRćAFv$oFByZx[3CLz\/s Ib*99}s[I1 j8 RIgqƑx ]{s%2{[&5Nsc nqhjI?p-t;&' ΢.8Z# Qszb& 2gœL#NBq/#䶄7?:9*s(DP$҆⻜T6?)YwozBq泲 :Cde)aݸf^N٨ bOzM.iu-cN<\~Zr8HՒ1(P TҴs)*x:] ۑ݉eM{EQ*<ķ)UGED1BS%v\JLZW.D?X _Ɉ!8JX"q(JTLHcIˤZFْt kZTAL<[@_^QAC[V-Zs#rєG8U;-5Ԋ8'#*98x'ees=cBb]J%3"S!*Cŵ` ͕Ŋk@9&tVTXs%"4-ǤSP?NͩJK,Yniy8ܹBƘl~ő4VsoPU܈IDń_"kLܫ'"zuy̵:RRA!T\{'9{'+*Jb#͗&&p9M b|k5۶(ʜs|7d.;[W_b﷊l܆08B-F?9i3̟ 0gd@jalaN{W; ^\gޅ:TD?eq$zkTAѕlBH#RNr!AۈS4{QAW{ž~#С]BD=9V"'9-ˑlDz*Җ[BA|3W"7~ucg@PrSa1_aDpx܊ܞ yW؋K'8Ee5q{\t<_@XjP`юWx ]{N;11Xd^#5 c/lW6!A ~[dw]y"sU\ ,u8#"c+Ԁ1#yJ摋w"á.`A)a8o .Bש]עwۥ7wqXFN_Q-*< pSs ί%*)v;v;ޘϝw%|g2%v wzFNy*~_{h9}*,cͅo(:aF)[3$._vίaw3\]u go)]Xn 6pj9^/DEN &$ [S8O*;zNgz*Zђy땛Ѳ vAA|H¬< j }Jl\\hT0nΕh ͕h_k-;W*htvJtyٙ+Qrs¿u:sBΕ}.9ϝN6]tT~qvKt" LTnOkxDL u攉씉)=){ŦLT`+R,u7;e}j͎{fGtQaώI̎Ύʺ2COaS<9zZNmC&>ĄƚG& TO\uƿ![LtMZi7&uyommߴ;g: /_m:x ~q_ ?co6 ~Oʳ3DI~dzxƆN&'nỈݽp^xj|b O6 gÑxmx|NxԆoԠ|\F :哝:x A{fl6ܵJ|zc+zS љZ6GGfS>>T2 Anwra)}mx{ەvռF S71x7ZmpS 7Aцw5;mm>{wذw/=EZmSSKaBkY5!mCr5aWC+ 0q4b6DmA킝Kj~߆lر*;fa;m-+mՆ1<f{ 5+W0Z#6 +6 à [pg > endobj 14 0 obj <> stream x]j0z= ;9$|qvJ߾km F34+}n. 9fTymTh¶˔plUM)g:|RvVt;)ArϋfD}i X"! h,UU5Tk?o# Kdq<sv;]u6`gfig=W*/5m endstream endobj 15 0 obj <> endobj 16 0 obj <> stream xstd_5bv1*Iul6ӱmum۶}FQ֚gqFQ*1ٙ%lYX '5c[yFQ;k3_ Rhboo \MN|w u5 h@v|s;č櫹lV^>V>V fficGGЉRda[-==#G@'-E]v [[LNc33?@+$doo ,feņ@ ĖswBKgg{>f4'dd tfI)ak&fgO7N`w [m=-(#!,N6^t7dYm|N@9pvtxB`eL&@ -V0vvtYj`_w]`fgk6@¢v/FVnv#;__rxy>DBA SؚA*]M ۢ3*eH=N^{aˮ?Lmա9tQ'ۀ=+S M `q6;c 'I;Lljπd Ts+`d S+[_1Y dkPsncG 8:_ks@w)P0歩uɷW6j:0'z,{i]0h<ծ|&kUΦ܌ې2Zq~ܨ>r3b&nhiNjv`Z~EiȕXA'p m$p^wZ&DŻ Dw_=qs@GuvbDOjQj_O/1epVlsՠ3_Dlv|5iG9YY&ylsϗ1QhvXŦxS?]th emWST :?&q:c?  {l,b h&Q扉ĥSxEDY=5Iw >IܽB儏0gh~ E」r籧Cc>-#!_rzZUES0z=~q#˨vL/c8e:J}os|~RnbQi;硕TTװpcTX,T.웝}bf~C.GCk;;wjCEpM95mEn=~]L2lSZAG7D"5`>I ˎ۴"@ܑ:@x4ni6><m [%p<L=Uꪑ_!clPً Ԓ@t6E`k’}I&3cJD4e2uMأ㼅XhHw6ԷLHrrOtr MdǗ|4!Ofh̋^2t3ڌqKQ+aO8!z13ed @Uߢ׾/hr3BgSN6GLwUH%G-;L5aAapJycoFZqo 8ie0h>b{ ic⍾P{,^0:!lLXBζCM;Cs1cWLo<8WfP&Љ`/v%#z#D /}IXE-mLb.`RrS`e<0-N֘|GqM߳v\;NQBkt/⠐x'ty5]]n/5AkB^sb k&lHr=OمH@O!SgE\vJ).V1NJWv$~xK K?)qgU@ʜS;MSA1eǛb e @_lQ,qD$)p.rFm*ѕ6Y3Y*tj aFK̢\u`fuWW]l3 =G*P7*u_ ZHF8' {S cK2[-*J; K>ae":V%ǨB-kxv .RƥY7E45iޛ`9>qX 7 k<ҙw&5ٲcIXnXWγU08 <'$X2ށ z0ɋeWk[9.Z\&BlI* d) .RvҮ젍hQ߇KI`%&!HxwpŵrɞgMtG>}+TS -D/VlGk7:A_c!t=Epȷv"& yH4d-ml%'Cw@>kOBJHCKl^ p Zxp^#)Rvb=A-Rߨ/XI2{rVn[y<'{b2lÝCMt)Z+(2Q-V@L}xm`~7|ZYѨ >Y䝷- rx!8SY l ; $=c%'4{PjΨ1]&lB-n8)m76G7$r=I?}'`fj ,sRX6n: {n[|"+=uD\ugZ=9{x*(/5_}b&~nyr\t-L(tޏ'oMꉞǬhe0x,yI Wl?r8E#}˨qO̫Ͷoql ":vᦺ}'\ep{u%;U0^ 71߬2>]m:Q\.L5~GwO#ԳiRdF49Thd؝o51{XBFBPl骉)!5 arMPuA$ȢӟRsГm%>Y#ێaSNxYLyKmI*s0s`ߓsmqd&]پ)m͡oN 0jPqB%POSyNυf/[( !qKudn_O1֗~F^@KM󊐦5f"`/38`C$s„T Y.K'ءg!Twi ^`J)D% 4<[1Z1@`9G#NH vXWj?tMd PK peqZ`,mbȡ96иyvcCnI)ar\Aظ\Gqk=G,[3(hhݤ rXܢVX ά_ B-(=ؒuf_1WI,p~A3F@T-Di3Q۴RIt[rZF53W550r8!TGt| ?ld:)Y\Xya6bOJ'Q))7c܌/-Խ#λjZ^Pi)\mO5&[?4,NWt۰ppCǯ&C}o\|v(,HVUxeXj,鏘n ;D,j>x ZGeK_%|Iʫ~O-X]x@%Ugz&SÕ3BΝwÛSZ[`ÕgE?v rےp=7 3ba@h4ǎ{עÍZT{Wpy A]aK>q |^Q.fωHnbas֜ bGT{IZᐶ1F F Tg.HiNHgWO]Gsg]fŴ=qc&0͐Կlj5dKZQ' 39BE4x􏓲xI"SAKt߇hՇ`ٝ86[Ab5[\j^6 d1KS:-&{dYLuLǭ/6ɩV%*JȤ{܅9ȰQ_?rJw:*} U/ι>UX97\yNB%عlv!o/Ί9=),tF|HWVwrk$dŅӉ 2&AsID {\&u#q T˱{{ߧe !L#^[CkYr,GU YP?}ru12+nG e00['=ou [7|2:N (eS9CZr6atg†@ƲkN'l$@ؐ(DZƱCCp؀ssΓMr~Wi7 w_NJ@sqG~=ΤFہ 'Ff:? L30Q{X.:EuWb+/'B9Po!˯c6*LGCP(JJ&)0ʚ=9P-BJK2Rrhqݗp RY ]4k@d +ne ktK|,Mm@DtPR#_0~aʸ Px1Οcؕ%1=+,G#^̹MFzsw*\oQL11;&} rx"(@ʳeD =7䘠tv_Rz4f,Xa->xix>56AΗ%tm$U֏acَm"kJT3շ k?\.k"Rd̩v"˖(v4՛9;+Lv6 LOe(ܱDz>B'Vj-O(o wܚ Fȿ:&%̎RCxi{',QB Ͱ7zjyA_oH~C庞OHڬ~eURxCj|~;Ӂr05JXiICY@}C{epZ+K}z`]0#FMyE~z,x3O69}`>#_ޣmB51"]?jd*j Rj' oia{]@aCQoWP1Im1KtԾ [Rzu(R,:8i.HdHĵE=s{Ob> nPw澂ֽv؂1/k7g%2XZN1r% "B,b)9GyOG 'ʝQBcQ_8mG' o8 vF1:K4zUMqB;y )ǽf-4BQb¹;˭)hnsx+4<~7UC*:UwxŒc+H?]z񜞾|տb_9]hТp\Ɛ@!gFxfI}W# $KNu̡3/2JIҹ̚gz V|>hm[u[ IE%?7N1. Zae;AbTJBXm^??gC `-:)^xóDtgzdV뵠(P H$.l "%N"=uy#ܮ iPٚJ?ܪ$UP;\|$G|_3F4+zr'jYu$rG=?2UhF_~.x 0A5I1P͘Ec:Ǟ}TL0i_n5Uڤ܆k.>O/2U=N gZ%}?^Ʊ <7~DZlC'SJKѯz p^]/%C`b`akQ-6X|Qu4)M QH]1:@/l6,vI%r{%X)-*pB75 :Bl yOc]-hkv_BK|m89Ӿjuzj8fa BR :8>ی:H7jw] !p$)lk抅Lƒ2uUv^^*gTMKz b*z!&f G|+J?`W.V(%a#^C6ѳ 1q!5\mL_fVBW `/P6\ S@g-pnd;#"z!hqlCRG)?۶M%εakӐTw /V}D7dk}0TNcюbe^pC/,i)FCQhW:.?M܂/B1ll9[YK`]|ȲMH(e 7Rt%;acy9&|#d6pKb0+: @APG$b,Q7u=2l?$a>^\Vz*L+KD̶x,Hq.;ޒѲ+Egg\b|,pԠ/SܐdN0<+V |ˡ ? L?MNllQIK4Uhj%0wj<8jc sVoHMg,%LU E-]#ٯqdxMCZL=9c.xuNHpdzgBə@cR1Jj6cX/O|z>j,n%@skkxghRC-RatʗLaE{k!=/|8^2Y oQ\2&TNRB] A0Ʋ*^dgzf# zO N@ 0IP0_[YLt+(g$ | EfȨt(*GF"'RJ\;K#wBY8ㅔѼxW8Bq5XSQ9@SDөAG5(wRK%`V˓~/*4ҵOkո\=`PYw\:-PE7nr[K&#t"u`e~6="F HXE9+Q7q&iqa@kv"8Vq)VDrONbq7{e郪OV/Uf/vߣ獱۰@9m΢',<)4S΄TBzaLy ה+Y! : |p\9ߍ|G66TԅY21;=\M'Ue8; <[{\TE[$ 5|OG 4cŋ_ Ϟ e+^~bx6$PE oG*g~Lq=McШG~Q}A#[-ٷ)o^8мMHBby]TLV1(}Y]Z鞫PR)G/7LXT01 !OY|\a Mʼn2}/+E/k}hDc@/uѽF7uJܢHrAqƋj-k #7BE٨-Q B3??GazlKsEU]r@P3l9YcMThӶnÑ(zЁJRo,>F8pr|\ vGťT+? r9X Љl/ : K ";n?&hqzUd@b|anR kD4f * 7~cW #ޏŐO_5bQX :3Bř5@lmm\?.*N ?T[//QsJh`|;_XDe;ߪfka3rU؟ƵfS5W9cX8DhXH6|v?c'XGz2֫ -3m93]NJxĔ5߻Feis8sPֿJe<0P2 @ֲ{_vYK>k$".66Q@OQC$TuC. ـ\C/%E q3[APܧj! H7nu'4 M8|vRk6XsU1+'F˨T'_ u4 < ZG'IJJEA/R>Ap"]{龳B˿c` F#א 0ĥy%c xc eDcko)]z ĵ":Ci0,ّ9DuݮDc2B,cQ/Oݨl7Y8^_xڰn&8/鴸FLzQ 9-߿hx!/~Jl$㏟uwl E(P'{Dis9*}q)ҮOM=.YNqeC\#{_';Z.fizoɄN T% Vu5|z(&0JZJ}mpD}&O:gv,j?ۥ<6stx! w.n?)3NvR+kL*/j c֡miȂ}(qz*u ]FύVsN;g)Nd뼯w~JkImMoowY.x%}U&owC]i>{20l"H/M,WJ2ɭ/oQKtzcNw]ָNj0l|2׀SjzǠC [v+,dRr;U.>tjZ%<޵^,zv9ϜU Ys5/ת|\oo%'>4G3~,jZ5t|mFx1--$Opp=5s/SbO Fv._YLk՗:g-$klz_=yr, 8۸vٔ+B1"o/#sD^A7򋕥v#PTBK%{%7'0,zJ}!'G1_s!d֯ӨThZ֦vM`=8IV:elJ9q^ JZALUvf-'mJh| Z2\Iv}实x 5S麚 zocyh;eֳ`<¬(F`v?tNSMsWl_Zl~2Q֨ V2+?>nڳ43h_  ʀwnնm0nf{H%!L'h^֚҅7ZE}T1Y r& juƒU,O:^0w6D>` 3P.PԐկ^lG]%v : a]=޷N} 畕G]봱f_1KR$L2NhxM _Y~b ⍥l܎Si I=;!r`(ƖW-\8mUlʻxÜTY""ȥ^F##_XE:tw$3oP+wzI{Q,^~P94 wMyhq~2 يq $zTwso@ >H囟e2N I# [ w33)K1l_3gOI鵀.1Fdz J|^`*3B51eNE]fVr:-GjK=l黜6|$[2tXB늵H!~bhGP?oPVb/5DI 2˸q^DGS5vFu%dBM-:PR;iMj(xiwK|M V5fJ-D?Di}@͝T'},<[} W:g#_.úSUڵ = oz*jì,hū^-/Xdp)@`u#_upKˀ^fjlǣF̟5#wCI-3:fZctm>7qzbZkykޡgcA>_6 ܠȱN#/DG /IvyaDhtϧlcS8 |w׿/T.u3r>nʧ#Zڿ]1nhwτMΨZTMhs>oHZdRIm.eT۬F0Ws/ݒ(&C.|2$_k_ ^15{{iRºC) {svɝr-0 YF 7g9Ҋp5a#%rs`⋭H6a~r1C]}H0@8[]U>e3YUujܬvneTʀ9#fp;Zh;*К75|t˵}"5/|Ŝ`TAΚ\TܤDy4WJ;_.Q7Z׍bwuiՎ ЋDIU5 ٙoQp+| t)C&W?VX4%MdeѕH, rP?[)" ;4)Z ĸ>F΢igpX' +=K N͐(;y-We }O鹪KL(Єk:#j/UsNz߸H^ҨiEvcK!M'.*vrk0?Z1I!(%ݡZu*57$& {"b6eIzDtM(kI]CLMoٟ^=]V,!Q]E =C⮈{sG$&ήʤ7U,vRpoɗ2y<2 zM]i)$Nդ6Zm4mˢ|Jal2 ec= įcP5j(̵Zzm_/u,yE8翈eM< ձt\tGř" Bą@sJ. e G+ @]۹|+9 /+5TWq·S2ǁ9x>`(A_ͩV}*{Rb ;o]ռH~kn>Ǐa层WߡRr`\V!Gؕ1lÁ8R  && lm{E\aCBȋV:TvOܟU6@q~vߦOvvc>'y&ЦJ袴u]LH#c%%+ˉ4۾cWR-+P/MUQ]3<yN=]n]ȗ5 @-} |~-_SИeSR !}u"+2אsHהGf\Eq ӟ C&ޤ$A8Îe6J&'-#Q(99<'x!E+1K%,q N0?DsJƕ1bv%ʓ\͝s2DҴF15>ǑtLG 3bOϠJM+T|{z1e5,'F#cQQ@%'~3{ QןHPQ`#{jb**Ed{\d;U+/|s匵>]t)yց$|EρMŊ H9=DO*^(LW9h%LQxZީ(lalgs0uoec60ˇA1.)QVr'+qYG7` ywL}zPNMoӚ /-rS֫uۦSAg~_]8na%Iv4jT..isE%mՖnr>*`r4/L <:eE}$RA^an?jVGK 4֌ MLY-g#:P{Ǻ RU+z7?=#,獡~?YQ)hƦ3A9HDV6#Ig6̍ۊ|C:8rvAQry+jVwmm:PXC S.^sWpD/ӏѰڽF-:u%lw jC٤K;;{oie$[D6-R^ar[(qX (A%Ԅ=y|=]#F&],W\XdswR0VfX]f4(y7:BTg_j tp9} Ҫ58恥!)bZdJ^e mܡ%Bsi$i1ƩrvtL)%l u׊Od|XYPW!C 6ZJA"G^ůRURmn-HcdّE$4"(u~À/I-Sa )z#O`XӷJư ՂeGYף~rԴD]P)Vv5t._և\nѺT2M9T[GM4YZ qqUEA5ezBZ ZYXcgwh1oWw]A8BC2裟opŘ,ԍ YGS}1/ݍA7ոH)HƯdq]đ7~ a482$g \yEcyal[b9t>Oq>1Y3zv)]56 ,q(b#*`^=]mѩ|z CM5 B$ ݲ4[2Efcwt+,4at1r4okuOӳIxFc}[4Ef\8O˽ ÈidînuLP4S4^uCAC=^ Q?0uΎK\%X }p_UC~S/ыB%A`疽wz+bF""6M;ޞ8wGhej&{6`n]ڴ?KIpPw<$ L MBVU/"O2{pT1n[Î5) PN2+5#()P;3X8LeHoBKgtA P%d,ɟh+^i3i9âE<𨜿#z cBf%Ts =)P+%LM9`^:3gLԽty"{6o["RW'DG7fT닎}'c7nAr΋qhcVuo=w.=Ӈ*5m</z$#H1p)"$d𲷿wȱb'_"}G,⧧-ZDDm:6:D]n -/~iнq5 JH-+R:?7dF8jn؉ޭtAX-8N-Rwy{rF+rܜ,yK6Q+yB/8ւC扂@ 0=b |e߯fwy~ sd|ZG,ovZD6ez(gHf%r!?}M&*KsLQ3KntXBJa'?)Nts1|Fo]dv0F;>9af51vERk3u//<0^*E Zs& : 3 n( W#=3PDJC% 4޺u{N$773phezd1W?&bfT:Xײ&!VLy2kCg5Jz{ǗF՝Q c||{`Ncᖋrh ϻ02ЦŻ w[ޟ譟d8XZ[>Uӎh= yʂ@ӧ{ufq_Ľq?j2yS%0Hb %΄f?,| mB]$LZ5\ѩ{ްZVBP$j$͈׃ʢEUy⊸PJezv7گhH~C׽ך=Vn.pBlʯ@ #" ȡL3UwWtr ĊTg &Fi FP7!(GQJهzC_UY7rhě}ԕc\+nF2G!,c g|("Y1q^PIA=d KN͊qNITy8< X縆vbsCL)w1fMV$,*GLwgJ'!#:ϑPqWU .XqGx]Im 2"(5ȡ^ZzD,I؁ǝ*b7^No ӱI[.]gQr}T (IalulOpT, i#P6*3)S:{ Y]lCB*#UVP25^,˫go!^k>qR ۦ!)xYȲ=÷-rs( -4W*V'}Xa,?Y teo cm";!́aþͼM8T?p 5f<N"7/4M= _؆+oR>è3X ,JDA-)[1"+X<\ZlFKVsr";珆8)}({"ȇlM1M޵!Q  ,~h3v%=<ޑ-iQwM$oL5Kx$w}c6f.hAO=Y:3{&Rq9Q[ A"cn^u-8hø6| cq! (WY%RB;=OW>؀4MMV_ZEvE`b`N2;̘$? 쬡~0{^NJd"uʵLP fRïB)#b&k c ƅS$bYf~$1q#97̩.N!}"%q#e`iħLdQl PM}]k n,Lcl3 K rAb|/9Z}7P[\"OHtGZ,,t~ӬLAjRL,Ǿ&1w^Aѝ?*\hݶz\um5P2ſ~t7a{CD hEbǎ"ؿI 9uE>Os'f焥59,k!S[GC18ۥS2eK9E>} H  OF+&e*JHy3~`?3X#T;qntX]dA! B./Egّ/F]t2(N"%&Qc$нY79vEaahN걥Y vtИtXm;(l*wPQTdozu,ψlPHLxm3Lyd<.6~SEEwnqI֚ l3Wx]sѓae5[ٌP-?ωà\|< ^N:-n;?8]#\c]41KǝHw<2㺯_gv%E}Vg~dqh[CL&*napJrz뱦>Vsi}λM3iAb';4s%S 9^=-s l]lt;x':lY,'nE}_HW60`೹GPF'|C|.Oeƚ;Uч1ewjH_;<Wl4#hcLwD4لĸ(YNǕ3Y jE"Ifg׳Aui|HUaJ4]!>@BFw &&Yg KOs)0 W67#QL7xF]2Oq5"nvЛ'f!A,IV`xǡ)^ Gw`00qE;̀EehdpU$YH w RDu+W#brv𖯩퍦CiOzkҎ_P Ïɥ7b!C:+vm|=n.]QV y nkNY/Qy<&o%x]D"r7|rәo8^g긼gе̓dBiQ 08}uĞ?1d#N@-\핾:L[=6{ۥ㱶KHv ˴O +?;i[vڛTb4dcGKZrl #< 'CetĚ*rT&+=lrSNK6E!LYݘbz-Ma˾  >at(O.4/ΙT[LEx@X5\jܼ.n"A84T41ZELL/X?jb S׉a.XT\`}Ct-%`'xEvN3pGx4ػʑh֬і?CJO> +2.1c7kJiLϴ=ƎJݶp} aJqahNkT''^-Z26 N&CCL>夁U:HOl'Ԏ34ó|@;Kݛ AĜɑx%$q]ufd?d5aV[y* nK"B6j^9n QC#vǑI| o .x; 0OhW۳ 9[:ޤ]񒌻-Ufÿd</Q8M3F+tրHa9G(y;xEێ@O,` ΋plY0)3IܿKg=70zs KlHm7ښPB2 1:B-'R%`I=Q6fM^,XU^OUQ0 rz @^vNxU?x0&fHs~IQN)'˙X?ğBRq EeIŵwL ~u2= UZQ=t7 BKbgmNӥ@D3>VlEt^y -s2a>K#'ayjhJhb\] ?aY tDm>TM8o`.ahٮ2?;t>uhF|}=s"rOަ'MMfnKYK,,3]| gF/)| nu2x("K?V e(S_ § vEӮ;8{Biqz}=۹\0l0Lv[}vrAt)*=|]>Ԫo@6P|-KB1;gOT,Wsά"z;a2ȕFAOо\qViTSm(Ω -D/?IZV$c|TsS bJB=N(BXl=ݤ0 ZNuSD6M> qL0w/V>ns@634@?lp W[jJ,15l<']֚#prwL.a4R3.aQ)j5O\PT,{i%nOLVjtZ>g%1lvB#-+cwV;xq!wWpޚo9 j?yAMQ8h }VU^CaV3cKk}Rǡ-?jpc6[Z?PtOD"?U&i*.;8[,Q|ȝ\Ef 8 %YdTG} k'0!}-22KGОleǏq2響Bcpw/Ƴ yi}gv5u :_ۭcRIڕw;y;Kcge/x'v9K'IŶ,7kb/H%оP.2zݠM.`P%OρC`rP`+j8} \ДJW`2@e iQ=JY -MeTT XɰŃ"p ;/פ?u,xOKL"sE/Yx$+Fp z<8H9˺U(.; Dd&0:k{[1GRZ\Fk?@ :J u8nlS#lјu-'~ڇSv(OyAST/*sj?PzH'rfє[3+OO!pഺP|ޭ3{B$Nb!RQM;mO1! 4sn^WT'kR\vjW5P[BW+ƊP(vYhlM^\օ9yͻo<X1vDivIް8.d13P,&+j;'Ur3eFu +.Fn-BB|&sEL^?Hj V46> |:9Wq0Q bx߂;㳉Q@EP-~ 'Σz|-iwLuYZ6?#!8N][ "z x_PH.4ZDwN鋡YXˏ/c j-\񔀘R/M> |&#$'|iD@c/VT%-j1{<.\XIP"D0(MxBVgHrja( pZh`#wsajPaCĔڿXqcQK& >I5% qdL[V\s͚—)Gf$=Bkޘ]4AsT&>ϳbzP1P!9n\p [No)\Dq pTn76LiIAQzvĔi8D[oنj ~P $G'kWleEc5LWDZVѽ YwU N3+YK[6_`E,֑I?+Õ7R-Q$AMxqI~[d#= d4f-#j.5e<_ՀZEJn@aqWǸ!MBeG'W:2Qm,+W}BjZ2C2u)d|'"VPsmABkLy1f.'*c ,;N+/ \Ng`A U~pɭ/m'ԅR@@AU"?V-a̅{MFdRLk7_#y<-*,M1{sA,$ek}Ǖ}ۦ|v`t~:~v^Q]mmc\"Ũ>,^KUY("2|0Ҵ:*FEКF4Fm[sO;n7[^O$T|Z0w34ߘxnQtsG b!{ɿv{1rkI͠5i,mYJubMHq2,)F5 o~|":: = (ܱiL5;%ru jť^~"5IN^2'X3f^ ,Ѱ)53 E~U,-Mп^jFpJ$"w{"d'$" =K9ѫ9*vG)}#7Q 6vTv-DxN9+BWqc_h/A#G2ԡe ?G5JZ~񽞪s^H 4e^ͬ!H42LGBxaA=]H=e87zXU.֫?y >mdG A& Y.O0y`qŗK1b.68p|EZ6yZv&^e.70vk ƪloKLweoҠMӘ݊&3ZރV5c.sv*G1φRᚣ Eτ2&>1 Z+r{&boV5pk_+j*oghpꓭŊ rH`1] 9oP~dYp(B61[C [ɧiZZDǐQhÚEA10C8Dk{Ka% S|ĿB wa;W!ZT:9ժnI_/:-?m;S 1]e/f/#Z]ȍ&qbTV- *y9tN0@,w"%A/ӕ)r't&dWd-u8!EҿPcлg ݋J931c I5+,zޙq+d|yMp{ƹ=^sUF ߛRȺVX ֢Jtw,EVk]E4pOdã@ZB66%G[ a?֕ë6M+4 aQk;*Acj'o҄ϟg؜K:HSlSyZH7{ TEu 8"+BԠʯŅ&#ݕpnFkTjK5a.FJZ);,un(< .1x5 P20a~k~;e+^oHYoy eQts]YHz.FTCk8Q77R<ٱM@lha5eٿqr(ǿg_v~ճKb:DjˀS%Y!ǻǚ ~4Nz!j@^F;;lg7TH'PA.Ye7ϛbD͐ ۜ0(eߧD!lغ UcٳR8> h)q۪3"$CkmDv<^4K=ݠZzpK"/\>0㔊#;L }+>B3ag;S.ɿg;^DWOTutRLgvPHU]oޤ݌H[7qS (GA2\S 0$cɩTRFoGE4lr 3Q b+1yecQ%=ZT\prpm% qE V-TR niIs&bdÛxw2<*c۬.AG⹒=;ꇐub2b|j6`>.2|TovKo(G۩73vWsۂT5U ƥZ']X KJ|Z[J> d<1y`d':.*َ JX?Y̻f(xJΗ|t0D-֔$~׌ƞĴixzbRS 8-=P"c&p+2V "L֊{?H%׹~L(yl%[*TLC#fs" :2w4p"w!vL ї'*,F- -)Xn%X \,(l&kdܟz w@J z#t"E2P0wHi&ps_ªѬz4eOX?F#So& TJ 9_mr/inaVvӐYX;7"ce5k&1/2DK=4(S&}_@?8yb'$)׃ _na 韈q*Z*p$M&÷>hT_3'1:mf?E61>w\G x{O?+AB%13-㯶%TQkC͎p4{> W澼x=D a]X:\T6w`X>=ޅ\lQ{J5T*K9Xkǣd}WF9'Jv啕KimSrQQe R ߈Ytdq!([a+d>P;KMbfAp#R2ĹcRѸ65&7^ p|y ب0+TQeU_΍b ŅehP9HޡXWlp#p-7 \~w!@"3* s_p\LY^Ru @Ki` .lzʲMg#KOtVM ]*,sኝ?V$:TGOϒ҂?oHk4>Uj🧴9QngDd_ljA55sO=m5Gԭ>] 2On iUvK%Fyjo绲-u#<ݑNTʛ6E0)X)Y"1aWۤl裂<_d7,¼Y rrCH29dnzgV.fdXJqn{WgOeCeˑC?Ɯ! Z4b:[҃4a9 $BXÚJcyVV_j#Jܽ eD,k2BK9uWm`IF#G rj:z qBx0? .Yk#6'sAG_ijÝ㡮i1|IU+rT\5 3̒+W笑xΡJr-P8Y^;6̢ G[2E{hJf'QkLвW\RϽ;cQQ4קġ @|cp18ԟ .vAdZoAi) J-^=zuS9! XS,򷿎tق855 di0)Eao$uNaXGjxWexp=f jkl +`_(`>En'5l8_oXv_o%}-\,QbwB /l3 Mp$;@rcd+|KIX~H ug}WS"ܬ/XXp`6)VW5ė 5s$y_p'pc~\{ڃCG"=eLK+5V@yF >x2sdԅshGY6Hˁ>m͢zҶRƑt pjЬ ك[Pa5!0\0eaҁ?5P7zsF?R%})85E.Q*'3ʊk}.`?_p 73-%PcB2\XvGPj̟cyz&<ECP< wQ+T+j^G[JL3#36,MPGztLj1򯐜wcze(6YH`Ed&-#vUJiǁŢx!.֌r1RܔXhsQмӥ_іٯaZ& *z3"9|+!|/Q||$Mr_^j.":Y~o<ߕk'&y0&2)@b-i)Ѭ L%M.vR`A0} l43).g+򲢈r[[4gy#pyP$9Jӓ# }d` )kǻxee-Ry f.¢pA&\U+{KVs2jBa_ o[ kAT"Y+r5,s.q./lZ ) h^`_)*=fB52^mqwBiɜe}8 |8ڳX>Hr|i;Wf E,Ό@1UpjZA%""R6;{fe,OD?­Db0}+{dyVa4gۯp43V-ٰF*A}+@%LDVcN?ƿ9+u 5{|;%$mnQg0?0mw^3Rt_iί~ݘu֯h;O^@(H%әhJP8#{LZ>uk99CXr#T.FAs^0'H&n8'S<3/ǖ;XS3z(9܋]nZ>,#~Kz'< '¿h,[ԑ$ ;ZS/Hkӄ"C mGD{6Heh/nb& 鎤d_QqxVm]4VpAYd+RRZ.82<Ց&-(̒/`;"l9g$}v].+fU/NCdnG!{`*2Rju`ۨjݶH3Ն|l& xLh˂;29p3fOwuO73i0h5Ј~5AվhD퉮rH|D!C7gxu4JavԶf82iKQ(DG/ K&J|'Vm&锰V5$2>Hڶ_Ω{!e")h <_-CH# E["gUʭ\BfAs"Ew9f^P^$=;p PG蟀?5L&H{- ڥ1q^Nh84˱korYq30&%@~6^>5?ڋLBĂROd0+rcȥFU*c;TluMfHU334Cgi}Dh+ JhEbN;O8@ -*o˩-rCIgcx:3)9@IUA;~vY'ݡ ^l&XB;2iy<HsZ#Mx_b0ϫ4A=܅kg$<gv/&YrYw - w?0*앚]4 ;Eq#?Nύ͘ ICs ؏j ƨ 'Vh>ǰqPҡxt"`$Jά?ƹʱT[?+íauuiy+e Y/rxjڏ?GN|-Gc9p49ѴנNzٔ&䒄/9m 5i~Kykd<jV!PI?EyRpI;}o|ԕRn$¿=Zcڪڹ=e֒iczZj6pu?,v1ҸS2%Ɠeh׌剬qRrmZbzms'A'炾̑3H5U8__8pcFʼj3Z̅uS̖DogBzx{^z*p宂GNJ堝1i^Y#(Ugr2*,Jw3@P#“~q;͚JniAg+@8w(2+Vԫ xGrWJ*Q! L/!+KF #iM/25'[_i9d['忑gS}Px&- }f00-s3;,A=r i'R T7%M Bmc˥uOWyC6/fAtP=[=(Q=_r9I֬.kh$c%,fΈb e{RqU{(x举Sh~ڂ4v"i}<['$ZbSJR֢-\Wϭ EGdK$]fƜAoW6"j ɋV2}8җ<6{z[h6y^8h*I&N$x#mo2[ !SrN ۯ"yQ{4|<>[:"x"jxe: {Jග#l?r6CHNSk>_k<<~3iJRE vuɆ\|ꏜ9YD^CM>oc ?j6gb<@7]J{8;UnJN:}gmߥbpL%ɟićW8k1pvq>s SE:kێzm^TFU>43 FRRdDݾ*@RW_t=>fpWiBGa6oOK|:Im*_EԩApސȎ,ƫ)!PǗqmBt[@3E]j]#[2T3'$4Zπ oMK}2rTϕ<\1~x]Pw?įigEdUf d | ; 1veE?9Y^,G,d,1"`K۔,n,-Z" Eߒ " /I<#:WU<9kbKJ~X/ G`TC26Ct$'9k3;*d6ĻU)ǍVJTdK|(w}A5T`VU ]P;Kxpf&i~&D"=k*P&S܊LLX,eBFlgf8g7b)ТEd`/{X 9'#^SZ^'52nM@Ґaz4*ڲܷՓSqL gax}<gmf x k!oP DnM|v%BE:ZI3j>>&`7F͟Y椴. Xc~Zds#J:z&B11ՈQ/C0!F!|_'s H(E9=8G@Q0Ͱ=χ`:+7k|T>RL58-׷M>G)s!eW݊\ ;7M^ m[ ބ6:/ o.SЗ`{RwKP= Mu*>ARI3e:KaK,Z؆mʺp&_=I=@d¡k{gy*o>eQHc\[>/u)]ל.SZ*<ʿ"R"C9 CJŦ)'D8f:EsKx`T%O-V|9eF2Q"@y@F6!,IДNn86 auH=_3?v'P`L]"cE=Xw:vJe~kyk:u Ox/%g̏"gQFљ Fv';*VRG C})9"q^=翿`4O(;O_{ R3FAdI]\֝Ծ7t-S|g%" g&N%@P| SWe>ДTNQBcQ"me WD` #$!0Eb*gu̢pT8n.ݑ. PQ%LzuqpMӫ41 n$'o-h)9g,_`A(oV,>"V5pζ|pwqdϣME˱bbc#8aoЬ'OԏxN.SI,>xx͖oXJU[1GBW.O2f_ս25(Z?5N7Z!CQJW[R֘2ƾ]_ݥ=p+`1EKm9#[#п?Xh779P,V(xbLz3e}[H۰\~}L(|ETDrfBOnbTOEnS'ƨp+ iAeJb66Bi^W2Ob7aRׁ1hp?e FX^tZJNPzc@΅R^#ƀɎ@Y}{˼-Mb]l6ZCZ˿ ݵtFy x]L44㴓fYɉѢ<(ϻCĨ;R׆* V|q֘2۷Hn0+lzS:ćvFl\cح.z_c}BNQɎ6h@JxJbۄ%d`G QlI* V oS\g6 \:/,w0k:ܨc2B[r]Ryk)Wc99|4gvKEvzzuv,rq?|{}qjs'vH Q3r wkx1! hթ r1ŊV<٤`]ޛٓ@7Ɯؓrx1qBnR WB!y%^}VM[}06@; :4)F˪?`%*R;AE==jŢ\_튤 j ER J^#O7ŕM묡xέ&# G=#>&Az:5_tv2a!:g`Bwr)!Udm۔V"6wm),}p?z3R"Iz|B2F^:y{LI2)c9щ9E ϕڃ>m,N{2a2iKqρHa x*~Eɶ䜹 ArVt`L*|.\̱Mc}_SrBWoj*\!5نYLYzse~vp'z2MQη4hі}gb:JLԐmMd1l}%(tU_ddm?jڂ5hZDf%w\]Y-2Eǂs#1jq0j-AV-d~ϨRg=)' 5ߒ6IhHsP=J`NUH۟.]*re (EssH =#~Z@M iѼW"BjD B <(9$*3{>86B&')_}C07QI^NۼpZ}\NFZb K42Xro;A7+s >(ċ*cQVu%Oq C^f GV_[{YıNjxƫh߾8':Ud<ݑs =/ 1Sa!(τE%S%Og9C%Q&XB4$mg9q*y]KpЃ _v Zp{*{ʺ̵{u8AUdrp۩v_fƍ섵+Z"Tw3_IӦoEx}AYd;\{06H-Qr0ϯ\^O|z7A3g=:ȣB|X?rR?m-v3T?fD;}\G`wԷy{LuL'2,edNdwBG-Q5m hܱ&'baBiƛ&A%ؖlXacb,lӜ୅sڰ/DeO*UqƷVb(+^Kyr5]pB\ ۆY1r̄iaUiG3)vh# /7xhMpe"1G4a6 P|(ϓX3\ؑ~p<5fL(?Ye="mzp[RBQe Dgŭ֡dSgv=&3Q.N)usO/|:WS+# miUk'o#yl ܈oT1ί%\ / R~q|&rIQs]%7mn@7&}o`#_N71T8 j W$Ȁ_ x>dZ]B4;hAWVOq4$ʚ3,7y3NKe\߯W. l O!ǧrz& 0Zcy@}KqBy0rJr?4cgmQt>\{B7V 9v eK~LH-Z~g1iS%ٝ$](<-gbVpZQx C!0~Cm9־i<(c ۟]Dm` 2 OG xK@>⡥';qD|w$Jf% h?THaGE3ʴ/)Ub{f%PgwޞFQ8ykƸ/?,^$zP@=Ҽ}2j[\(h"+= ఞ7T'J wD=Ǟ uH2't4|-*׍r ۳=,QO:ZaAH'KZ3pUcdaӳ$2 `h=a!?iM;;i5U1YbbQ3SqJVU_tFh"WeGK?19Rw6x(9&e$N{5XgS8y8k뛌:NEfVڞX0@SFG(er@s#TQOm>ڛb2SDvnD, KM9A $-FNMWgqM? 0ȳ֞۔ ӝZazJlW|w]t|^6oxig1 U|OZ7@؛4 P:3c EIV668@, J_H4#ևY`Гذdm-JUM isE9UaXL}×@q?#gv؜YYIfU>nt5ui}&/˜r:fNIf2 "̣'T)/J4gOZ8,|݌o S@*$BWrU<*К(XJzҨ -U粟[6,̓!0lљCmkߓ℮0>0JDP7Àfjw KSw99HJ]p$hkg`.v׬ yO/ V-Ԅ0 I?d<>N#;ޢ& V^W`q$pK?c iD0zHp00ǵ\';͋zQW#|!t&E}4I/0:ې}M.w*PۘQqz/`3&$WG-Mָ=m*HVlZH{PW0 ~f3aYR)ij~ZdtM{LJ/ȹcfK{9Hm@3i~:G /v>fHbXUФjQ>ot|9kF8.]e m|[&< EV^!19 Nvt`Ks9C:3ulcNl@u)³[(fb Cc_bEG*鱿Uva@jNwnB<_z'F#.M_<*RaN[0W?2ꦢ]oc𴢼K4&򸊫m$j75a\%{Xَ8)ք^=5 WcC2EVmg[02k-F=!Ơxy 4ќkҖ+'޾i$XњY/~WȎ.ٌKAOfzڰ3,N[&`5*Ef?1L`8=biwO«4 /v)T&\m~S(x;'>`qTȝZcҨE1M׹c1גdkķFlX\bT@*·6=Bȫ"U\Zx%Qװ0~a Aɒ ~|g%V0l89-$q&@Ncatfm^۶*m,h<4-{$]XM~jYJ~ 2[.j1@MsŬ*Fh¾)lvc0>q}.QA[`#ȴ0u&<- }xwPc8UUUǍ<&dJq|k3HA`x-W/blT(4כ/1!,E#$WB+^At~G.%[z{;nGHB$$WzO^̴&\( q@俗&'1a͒у.T]=cT@x_sg'6 5R-wYJ<1CT/ ^s͜X!%v7f쎫 K*}EZ4 vP^Д'"$hG(bwv_vH1:!mRxH^)7ju$!Gc)р-H'D xJ Mwү`/ ŕ<2289"GZ7vMrqptw1/_?/_wAM9!MkrZIn]?BP5f{>f|;y ܁:"jNҞr>޿K^d_Lݎsl|B2Rs(c)y >H ^Ug^,cjtm]VeIbR#vQn:=r<ֈ6tM3›^(0# ޕe&TiAI겏a|Q>P~Lj+6d{$R ^r,?-=b[U-g[5-,vA<4u*7/CbccH U6{ Ɛ&.TTXN,bנ&Q B1֖Ne STĥf;&5[Uz{`c>57΍)fb ,ua?C؍ƎȫdXhCF~TR8: Ao`W%.axU¸J-O6yi1\VN+M5R/`]_LS+ֹ^E:ssIf4$*cܱ/PB5E_Ľa<{У {'Y~Mp|>(x-Nk 5-Ԏ<5i S R W;Y8݅v9©MoV%SJTS E8e\j!!}ND~2`1^J;I.Vǒ)Y'6YӨ hHqȎa_ BjzZ-Ais,/4u{.ExD!$3L[D=)5)0v=dgNhևbO@Z,Ay8פf% [\\x;PŒwae:p7X HVjS7Z}!fDuT ,f7%Ol-n}!8,ܰ\ʴ< Xs^`֥'׮P2 /kj w/B7n6K5ɃgR:~RJ_Z迁N-{*C~-_ Dp"x@|iTUS=Ht`V^}'P+x^ZMM*V0 vw=:\)/%əmǠ߽Ӯqa#i]p y3Z1 vpb`Ma(H;'2[}ܿx7ˣ.+"L:r=k]K +Qo:)QmSѵ `+fe 1okPODQ,U I#. Haq+OT-0 VǕh:a>QFN_NVdW;7fGq 4JxH>}~$N_EɠD>.ы]␊Ɛy`.`6^ tf! @$rXRCy(g{֤ҹV[g[܁>YqDq<)Sڑ&4 <.S/EGΦ jeAWAUZe)nKE M捝<XT72Ji.:B?B_jñ\drb"3:(Li7 /'Py(a(8}~ý*l_FO9\)3"y&okg(@(TCސ~=y[?sgz64SfqLKO+CI}Le4ΦX9.F"v0hl?`?/݀J\NF tP$EIo{ÏG) }}F\*6˩Uvt<7F ï8`D7KP(UR20LAogB컛۰EW/zr0?xH#-?pI0 ^➮MiUsh'rR!M]Z OoPÕ0--[ޜ~ų_g+[T{0V˷}􆻘G Ee7 JFhFtܖ!Q/#jܰ >>\PLace}s15pa-KL呛э]Ôf Emǡ%ny*t0{Iݥ~nlIMJ+p).zġ#+Len`pςk&(-v^*ZdKf.Q@1ZjLůKyK46+vIqQVåL?$&-Pz㨂Ě'{(Z)"4Oc tWr/GL AGBXj?^ Q(=l{+ lėmq#Vf}txG8G_r0XoKl4т\lfpgPFעGeCV{ Е(%g$՘$8Hz{m!Y/rO$jE{tlS"%&]TFIxe zl~]00F2遵44u H< QsOI&Ql""nFN @e8HrT#F$+D-"l!{GkPz8[iɨ)-|BӼ.[)o˶9,?bTΟ GŁgiE;u@fP6CbbsQduWJ]6hWTȱGs\!츫q|/t(AĨ@pU!A" -zƠEja yU +P~Gt`嚔v_ѩPjW"X=Qbvu"h]yS俙fTGMoKxc.q-2huBf)}>mW>] xyiّ~( ya7g E&D]HMmo #|dVO*rlfKvEg<1Ň =əˇI%k6@2Wuܢ~GUG\po6gh΄8 ,$V+/0nM${EaxfPPwqJp}JpzЎDOɖ*@I )> ጞ"h}6v~4kl\Z69َ8V*H@סm4\y?ɅBF#V_2A%#Ђ^@ %`e_{Ѩsx#$.%TW@?YЄwԉ<-·"J@ŚSF9#K~صg =$ul4m7BMOPFx'cHN Gu*O80 {AΐOKܾz|5P t6MaDGnjDxZ0̐Azk@P.]F޼Dapf0]##$!R׫@/jbiHmT r. z<8\9X)AU~jpTÑApvD ;g!.yDk VcCߞ[y"R$>!2N)Wo$x145Ш}`:} E?-JUS9q/IJUn^Eᛪ PТq)n, t۸=L%,NO{VM?zaf"宜L%Bt&1ȻM// Ǎ6)_jEV V/VQa);7fƷٝ^_ux=.7Qנ6;uH_{.뽎)uZv %>(;M*,DбSŀ+dDY#'ZG:UA5[:wTOg\'A=@iÕV_vÛaL9F=Rnh:k6R3/ G FQ+Oغ' SUV:Dս_}N6 qƳe*HrIYiub5#,<9[4>9ũdC8MtTFi/B}[f wB9&+ڔJ7f{'@v2̙d'^S"|Ow9ڊ "RabpԱT{2@DEc_ ('5FN|^NnՃ;PfkzfXq(Eha95?Ty*?I|[Ւ,pk/Zn`?ωUi׌?jۏ_<̀𭬽jKRkRLTeGэ(EDj%c Xpp֩n%P/n M Az.X!.*krv_n?QIZtNwߠI04~2@kzH3˫PT)CjJQFSxw۠',wLΖʡ8vup H<[WΥ%cŔPBw." ijy)- 𰃲=kyՑ(ƏfkሃQACwghBaРvlՃlUozXe!b ƃۑY;>Z۱(ê`J.WNeRg8Ip/cⰜ^IϏWnq`}&1M2r)3vL+PMz"?y;jR nq'P $ۖ>KD lP ^5cFj"Baq .A M ꋨWx Rf,셂oY8 ";㵷hIy"mF@ ؅4=!BҊ+3a٨N wuƧӰ&.`J*ѵH܄Z Sj W2PwU)Z^D{ *3#1LXw_-|i3ֳ1;FEX8ab7 R )h <~*bSL pz=D1\&M(jKzC:A\1  8/l{U B05$6Q7r>47"ad~m1ƗN$߁n^0nod@:l"FW'>a3ԋhQsNU FfkDO&AEUƋX?kfwiig+'7Wrsp"vKod 8-!Y9jH@)K?>~ƓG8>9q߇Q0|o!ANXafB|peʛg:V{dwuSyfP4 BYb=۟/O*`_[RtJ8 P8{bPDL_NQH@ǫ\|tS =1jYVoޱf/<^XgEN4%:+c@?(pC2zdjI~>/3H`r+; ֹ+}j&=d}0lK-Uh/!̡$LXbgi'A8)`MtEjtn=כLT01t6q2Oi}` <@4k:\b0jZ|&rn+cp婜eNL )@Aflƈ,*QZ)q<f!a~P8ͬ9*@)% 0(>™ Hkk_]C:ZT -ޖr/OnLyQy5w0\@6vLIpeűъ5֮Ȋ[+ ?Ap/"zXTE-y ~^jcekA=;_Qv)>S] DC~Tꌺ+%hV,?6u_eo,?Y|x|a8C(d Aze/>Bsocν~!^7*Ϟr;#T}Y3mtx=!rݢLy.@l'X9n7bn<"go-&x*aR75G"d$ݩ*:z3T=cR; nTו)2 %-6KOI"-^PUBhhD.NL,-Y͙8!v}D X|+`H` -,Y43!530]gOĿ|3NA1QLMJ2ɣ0sO( 2Bv&%"~-VG? ( KՐY 4h89"`7ŎB5; 0,-Rt(#iEFz|',wfC)#nPG0== uvx)> 'Z-,G̵:%qaqR9sHQدNНV}^v.<*eoxҦ1f *uu4-&+}Lb'0FBgBP-q3\FU%/zkuXj8*@j x0J޲V?yI%1#$8ܳWDk)3U/~ҟK0$wMU_77 G/1SB"9ũ@P/AE[-%PiD4#_s6ՑOz·:dRz%v xO ya-%ٻ'SA0ݔ oL Rv%"Z08>f&xkշc[ LP0* RF qb9olš,%)T\!T~rLSn<YȳFz-mƄIet3.B涍('L2Qb;f 9Mtqow#P:~(> 1'ڐ hJӰ @ڪȣ|-5 vZOkٳEMwøKB`\E<> H$._<ݦZɨ:Lqwa^QˍzD%%Ar2wDLcG)ӞْhXsD8h%ݯI 88E8-YD!<]3cMHYi1yWDϖ<$g)0vwY"K.a=HӲTRp+BÄ=et# JIg Bd4dWb*T_@#NvֆjeHU 8hH_]R]SҒd*C(q; oe0,aV9~.۫5O,j[zǿsh-230R7!ؿcbs(0{LexR#ٌy"vۚN ~B1&7EgsdfnO]âoClvd6=ۦZ?[wR/\jW|%~NiT Ǖ"dsl] .yԨZ+G7<:E`A>!Ԟ]H.!oSr_S+"8%kWu 'PWFP~tYj'/fMy˿TeL+a6~ a#21r߫rn+$܉PjÙ婷~ нt=rtG0EźOݮq3oT r 5r/&5T?o~p78B198??G'p[`k49 ` U96bІV=t!ʬQJY(,SGuO6xT0Y9f+q!H%\̛,7(/FcБnM5W;=9Ǡ. :QT ҜLf@֬eMFMbWKڊuP.ŵAzB3ȍ.E}GL<BVNg^_#D1CYPcbz&hdEX; gj'9swW܌ggtHL2a7/5HR`Hǁ.[:֫Z_+zKM/N;?헜7eFV|>AA@u{ԍ'KDEtd/*e|YLw=,rt$[$oS. cPlSHz_ɸڿ Ӳ`Έ߽:)). m6sfc~= gR4/( km@wd]Vx#pSem|oN@Ǡ|. `c?FKj'3cBVI(W83Sr9NY5HE {_lK7 1!~7k0fX3w q`suZ;_ V:'z~}Z[.壘jk9LO >{`EoP6Qy먰ayѩ+Nd|+ȋ6C?3[sthxQ|ٝ&j^iEsƒ >b$ǓN*^ryqmZ bKL!li"lMp>93e|#M~9u7|A^c8=Y=!V=*  2G^A[H],vV%5aWz kFS0o7|@ٴ¥N>0N?O TO).菐kSaؠ"vB%sMh%TaRQA/`q6^m0*W(fvtHg Z.:̹+$+q3))Zd,7[8ךcJSa 2QRL/ $i nidcg8);O\HJ?I FH4 Whn"Zwг_r&MJ/>ȝW?H, I Vw:^S݋5S W,[h3Jr$&_uxRVvXc-%`6z2*a)G.w"޲wAHšAsE+{6x^yxww"|hH?> mBG]=rІfbDa6ыbz|V^7ɫ\!0ήфn $d>~\2bq?0gq\7\9P.93f;*<ً~a׫'L>XVA&7^ ɚr>t'G 8\s zb2@c-&d܋L-Y5jj6!P3sV_׵r{Ch͹ؐQk^8ū9Ϋ,e1tݘ Dn;sWj̗+4ɀ<+GHporԆ:z`ѱ7δ]q V0̿)sA,GTxj:rxvXJ[ k%iͮi@91VRCV;Pf}2!@lbk2ŒƄ?M7Gw \w9.\˜Ք{TQYέD&/G H'ؾg@{Yh`b;" :3 omAPv*Hm=ր-O}Li#d?~J) ,V"Bt5P#?8ABv8':-8@DdC~o!ɑ_fATx<Nj^p\smƶ;@=w*cq*8S{\750t[zk SiנtGe}T Ƭz+6èQ雯ay& Q/j8 ޮH]y`xٵ-sϸ|Zn:2Ȗ:K쬝PCݏ9`ًN#^R밈NGGnM>$?ܶyF,Tnª60XJeO ^|U+dFoYY #F5?7< Ek5PySl)~aI__*10.2⒗.򍈳8uTkhȯ4W)3] 0+"l9(#ipԝ\5e >pOCmKOU|*.ف_,;/JT֝iY/쁁\}*;? z:ℰv7`Q&h`[:nIΚPŽdſnX-g. U:J'Ux~>zwdZÒ>"9;S:^r͟ЯUUJR(be6%2pf; ,#wF *gQ\q ,hwP<)I94Ws}KfYU_4s/gE/egƵ$ :`O |q,&.Uvlrl$M{3+&Ft@u3 UY3AZ/ed^l C"uuEթJ; T7d۬WOD:8:+i%\-94l o⎆Ie }y-1& IȸqIJ)9bi< Z%?|ϛ3+AUTMa%-@1MgFI{ᗎ 3bJڛFX2^*u: )O's΄JҲ ((ow׉凍(܋пazںF9йa݉oUw/`U~c,TX|dJ@4[XC5 5ƒ ~qK#7p.7q[ ?NnXPRfB!h_z cü\6[]%ɚv ֎ʊ#zdH9,8O?b2+7JYqA5ݍH,k0K<lj-JZm|oxz"6SpGA8 &8< oH"$$_;zVku vQ[giوnX DV"~O2tɝ8 dpG~A#j܄tC+})B)l2LB$qȇ{?^m&Kw[BJO [E``LQ^We6a 9`0 - 3:\EN(C+Y887ʯ06I}n|!exv.q%ģJ @>LK2[,nV%/"N{^ 7 u+чvX!59cݔ(K4@92wKk6y+zp8/(!{laUmū%r1{sLzqdtd1s=N`KyHZ3% ;})Vr5 pQo!w\jۋ(n_|b_h6>17@S-/blhWł:yGʳ5ȽzIۀwӁj.#4"/Ys!W{O^{Zrw!.$~}o"lC8N 0>mELmSmv`a9.Rs) K7'S I~c}5!'_lw)qx*7oa,\ R ZǍþM(4Lٵg2~h Adl$.9s;2uD`/7BH 㓭%0 &t7nyK`-勮xA(/-arF.cV>ߌ4XK6 $+sTS/n$$]ߗ&`eCĜ3[4)@kF]DR֣t=ιuT1DቱB 1_+K”X;<'<!3 ܟ1#eE#k(#ʉg0ډS3"#3P5 yj?K7!C3冓:XPHr<NNn{Dct=7Zp҃ f_V #z`WMby$#G_Xj\SBV.~Z iwUٟEy40 !auNJ!u-,JSNFoj 9)n `]n²-įK}C/x6˸!LЇ? (O.i|-/F<Ņ2q^ %rާqSt*s8\$xEdVd h8.Gp|4 \4)9!#?@]h~?&q;([-SJbp&TEXRscgV0ZtJ`2ҹWéqSPT@l蚠8@S)(yUGj ڏ]}V~.5pU?_ r>NpU+,,Is( %{h?sut"Ѕ(SbgHSȽ|F-USEVQ1i/L52ymY^ -hk w Bօ\G[^hzjt& n پ %([s86Hê+Sp˝cgr%Nsgֺqu&TU&7C/sr,0Cl&h&s)W_y hמleNX 'yHo|+oO~oqbT'^_4}G9E&1tnwHv:?e;1B}uJsU'2z ͝]X­RòG`ml1eCvLR93iR?d9Q6ݕG3Q߼k2`ZP;L!CLʸnw߲KI6 ߛw킁"׸! 29Gj /<8Su;udX@??4iw)eCo[+4 rjkF<ނͦϩ!v ^Zޥ/*a\)LV' bƷo6&BėxZåL-3 AۭJI3ĭϛuwJ)"λTPh)Ae}*CrOu ~C[6.MڤtN:˷*]# PrewyZN![w(/xu@f[)cXOvͷ889ێH~wtR3`FM+>Ӳ!,f~C?4HwR?V6Nb%JdmvEՔ%LwX8Bj$L_z8`s_ CF (N.l0^[yԥ$m{Õ +k' `oyjT^p?]l3.)c/#۸ @{v+s O00H-!o^O9QUD3=wd+#%ٶOZAp%}Hͬ%7MmsuDcFUNC+|`d2S$Xɞ`LPL<\7DbXo[ۧA"8QTdD)0ɓQ9sߒ+NH=ai!3@Rm(qp@pOw]DK&C"1,g'ͤLZ:]IûK{4Soc{ޙD~(-ۺGj2p5D+Xɏåy9!?W V]Yկ-<׫"~?P|)?%*n|!cBj)%I ^4I@5u?$qpVj,ee&PV!˙.sd؀OD7jbBJQq=;|-C!׊-ݕ@Y*3vbsPF*Aƻ~B4]7|'̦F3x"wR0w.s\PQŠL?v9y|Ƞ%U%X]~^Bg;fxeFi s_1lTm斨}9 "H/Lldx|h T|a6B Tc_8a'ͱ)tRQ/rqgxz\1!OT4=9:Q&+J${qz"f X:9=ٱ|82qA0S+]sV`D)_,ڰI6HuUPW&{jFI_<~5?6()A0hbEX 4JO= 7k"ϛsa:f HKִ!9 Vi|xEdj%~Xw0)%M˭O01?╫~8ŲaєČJyd> ;gO$ȰO}E@Je wNnok 0|^KJqF^[[Wym3 l)*Ϊ`,'mID,j8;6+ː_n@aI#Rampa9Wnj…,KCw-R<1(]z#B9I?g#,B3&/ azۉ 7JF!!/XN) hE,RUw76[1q) H;3?#o/NW{贙0&m@P1*b `3!)R*͜Hk~):Ǔ-W 5x*LQ୊ftVs愙)1rW3[$+i )i~\ !T ϴw|clk {}Uz ==zU`/Xu0Ł#eūΰuLأ;XC=p5߉$mԼys#vt_mxFAbZDʐ{1\n`JS)^6^pfEI'!,[vI!pdI [ߒ_YQu)mule{G)zQաyWse PnKYa 'O4H=%G쏬@NNPV?ًhYpyme5c܇"U٤pj2c\k*"?=`IwG>X / Q>f:Q\Lᔙ<,}+LֲTҺMa>H9o6N6G.*u&rȜ- K=8i`b endstream endobj 17 0 obj 72958 endobj 18 0 obj <> endobj 19 0 obj <> stream x]n8ཟBvQXO HYi@#WGt>R4uwϷ?oytnW/^}cZNy:Շo|v/yUjNi%]O| _sՖ㆔_cs^mzWmasM]ǧôڶcsS1疹EYY٘ w#rbNsmܳGn@?@?@?@?~_~_~_~_~_~_~_~_W~_W~_W~_W~_W~_W~_W~_W~_ᷚs~7~7~7~R~7~7~7~9w~w~w~w~w~w~w~tF8#Hg3ٶ l+ڲr Y,h6;сDt8. Pi|Fv +KdDTguNm-^F ̸>-AāNą,ua`ʼnALt&8eM<#art˄F{ǁN tޮLvqpvvΙK2=n=azf1OOg$@;<) bwW<}ynS~y.XG) 3,ud@ژ4͛rPvc1Kzp endstream endobj 20 0 obj <> endobj 21 0 obj <> stream xwste_ul۹mvR1nl۶JRI*IŶm[VWݯ7=^s5CA b`twe`ad(Zٙ:):3-pN8 qS7;Ll tIԭ\mOLb`ĜƮqc?)jncg+μqcs/33ЅBҕ[ ?"q=@[ǿmmL^.c33_ƶ@;ZY욅+@+{s+{+W/@ha 36&ng`gw?HTNW@mW_ 13]BL\JrӋ?4?ET`ƛ92i[9ek_:L-[o)|ƶ.@?+s ;̬L]&@? 4XGD_q׿+u0prXY,ae;?uCk7wZ_~V-gV?9Xυ?t(fkP!?1i @WWlwk?[L2f"i 4Sr5+aot*;X003Ϡ=S߽$ao`feoPs#?¦nZ7@O)P(mW*fZM[ѷRCDf2~` `IMBqa.Ԙu/6hv$=ij]5\Vδ7ݯh,, 8:5K^.]ۿ@/ X ,6^"4J}o(DV#H `jS(  __)fڏȿjIw8,R!3w:誶UaR`A"Ԗ 3xiM̊Csx8pAxV'gs;7 .VHr3 42NJY,HH9@֥!Z MgZ&Ͻ,|ľ+e((y%CܓuOe׃BEȗzsYhT{/hB'f=+_|!ǭn5:3A#..=VxʴSU7u:t%oi(b|u;IooMē3Ӣx?NKN%Z}`h8} {FFUg }Fh*`td>B:jǝU{,<@-;NIS\ouQCxF^\¨ߟc`:vN4+0SIo!Ss6oT ub.ox{COV>ŷ ?ED|_Pf(<2BT+mGD7AÄ*`]7&Ⱥ\mt뻧wi#9Y,%L=L4]d?O5V5,7l@H D`)- tkޤ].HRz';X87~}[V 6]Z\J[ ]!?5c|$NS17y%"ѧ~ 3 R -EZ"79, !ȅhi"1CA{]?P[, 7?hb\++f _tD5mmb;ca)"mB]mlۻ.ߡ>1Qe"D-QX8fzveWk )k# nP esN>#a>jj2Y{oğg5en=IΕp/Y(}%>Zx>5J"kȉS%U\d7 3v Y!f4a3#R大2}*R3#B4ji2L]n/͑naKOG.ԑGG 2`e֢ذ%I:g/oX湠01qTPAsMAke'{[1Θ)əRt k7M".H}4du@=G08ZH|GX6L5{9I0^="ģ1_+!5q\ u5ccIFcAA Kv)j3z)V!cb= FZp`i ĶCa0|`#N v} pm7E5!]5TᢓN.<] XG0ު3ON@iDނg˕~gwӈL{qYZaU7f$ Ueǰ۾!ƹsW8[qM~)gu@uK+-z(;3'2c=\Dӓ#\V, ]ϧ Y!kw&` un$*OVoJ@c̼k.1"Sd


x-jv" !WSh20OWb~2OJs>Z@䤙U}ӳ_>&2%J EP[gXF?iTbؽH oA84W$ 켢zP3blcG.XD⬅!Q5Cbjt*G1bo+6Mk7^O9M1&QYFm:h+G ljG%DʝoD[d\OO:byT-mA!m =u6wDl5*O>a J?: 0o;HTz vf܎/Sj3}[iY wn\ |0չƜc-dybwaR_ų3ԗG"mnSߌ<1#")$"ѣ&gkM!v]QTv`8k hؠ7kٰp[E/~KS ğҷʯ6F([iE'@\ͭŒ~FӎpCc:jC>l^ۧᾤWp+~h"7ߒրpAӢdr_Z ?.=)AMKJ -9e)!őƆJ%9hywp_^hq&Du } 8愻-K ޲k9誳c_HҶ՗O:lS{y8˾jۤ#l`!'hŠ=8,?1Xnf-gNhg{ՇӿI$w^uЮ G}֡ 8 )~bʰ BXwٺRF$Jt~:,ul5܊_ oZzydKntKt.UR7ucÖ3$mw@>阂&SBU]U>!Z<9ȏ^&C[yO;NDQ"4U9mJ S %7,m0M44Bmg)(pיWOkV6i."u2y1-L`GN2f2!iQdt&rcmIQw:=}7{':|?2ձ\.K9[$otG΋$cby1m'X\2t0l:za1܁p;y^BD)Ƒ>4u)/#s+Szn)jkMۑ9#dm)RPmɘcDCMO<= !>f EmøWKU?O/7]& .w& 'Nph=R;W2+ᶷ|V62 QdWX}UCJ mNqiMʻ[zFuOfaƝ]ufi;פ6JDgYT,qx w)HrC{;i6ѬHD"gla]0PHK'\" W(cWh`#r+ŹWA[zmp_/Xc"(zm^h\=i[㧳ʭn+|u-7NpوcGH`ڴYTxcX*_{b~53^G@{%fnPn '/ &ĬK<5ۉ%t;*W CBt8t)vuƍ+ V j( K34}?/ /xnYb-URt~xez40ϜFŹFt mǬ1hT6CV/HD.}x J} 0 ((umVSJp8ڴTj #Uh8f=E dW]Z JICXE[.ʽU mqn uagUdlt<5QM Hӈqck\!zKwyH9lz.8T~opq2 n:QsmēJn{R೵4*nYHW~]'ʇƻ?g9 $i,Xibr5  i;X'ƁT2r' hqp E hI› ; 3t^-Ӗ2vȌA:AoU%g*eoqڰK c?so2 Dr6$ES'_>aH0:T_juR΅ls9Xb6>QKEOnuԐjZ֟.ZX8 EȽLJߤRxP3!RrXesXEu d,{  N! !)G1ׯsZLn,3&/ŠP46,&I6aR|Z4My?ѵCͦϪ6`^T^ʫ`1ɯQSDMF~?''`E3PRG6@PC5-C$Pv[|?8 M3f ~% !%4hNt[,,.=@YCY[W iH Y!F{>.q;#:-G<|BJ/jԙ7o ui+A|}p96jp4wkNddɈ99G<9gw$(I1syAmGe+b4p[jmI/\? "Sx^+S4S)G:;--X**#,{6ng7~,Mnkrٴj ^\Q<1H՗64}yU/) EQǡy 62lvǙ`x5>^XwJ$ pF-8RtlQ= ˊi~yg0!_RXbtH{%ɒx-2Mh#2T~53i=UhܢɔI19n7QuÊBdzRw٪,(ynNAVyݿyiϟ9{ h!zdG^R7:SjI~vTf|f}9KWB&6BZEk4Bɸ=8ln.j~O_?~FP5T=Xlh:3{9Y`po':E'PVDeԧ7~6J=Bo}EAe!GG!"nEʗ˟Y Zk*=cKW'nH>o :e4eVRν~}MyEa9[[M UCWkob{e>CTf\ߨ>Rڹ$Ksuf{vj &: OޕdڜfWL,lDq8W'Žm#I0 .ةfľׄb`;Lɽ2Iq(ۼ`%gBů?BE;35V-^3gQʳcLifx4GXB#&{/ f`V&͉,73]~!2a,x;JK"CZL,8 C$ f+/Œ9f3^*&F<. m2 (?5d6es>t1*N^K40;%zh0.#P鋈ޝ`~ 3/ iwF_)޹3QIv0Xf"ٯF`FR]!TTu_oV%>Zy*Yέrڦ٩W$G||I]1kIsL #"$tu3#,ڮv)GN8ϧ&?G×n\J( ĈV ǁ7b9U0KădݧG A@T-/ӝNӕَwǰӄLiKd/Eឿ( 9@_ڏqYN7 s8!x&Gt0@ ʪ9J5}86Y%BmX@=E"mS?BY6Aqуair=//U(c~=T ֝Ku^K \w@Pf q.Wa2Ic;hJomۗ TtFnŀIJXA1ę%kț̾%9戟,›I7S"U-XjVܤ;hʧ-V||LsfhTH"|VvP6 ?ڵ,l mmJ?'S`J5M"4+ge=~3 ܘn);$>"qې歼*ƞҷ&`eϖ -b܇s 'j'dx4 I6dluv^[E>e@7! թД˳/dqn~1ND8gBOU\ #̲xtxbrm]lGݵM]%\5qu!/.hB֙ Al+[𴿱;9j;~NN+趫IP^$MtAFy-CPGqdZ!1\6`bmJX@)X0X+3*ToΏߧXkBNK4}DVfdU:JHނL5)HxlνI,qen=̮yf8 i(6)U׌:fJz(pJ/ k.5JGRKWߓ`لy2l"̬ ]:F+ 䰩,k -ʩL 6˸ ql2G\0- *mR %;WV m08FYI=CU 8 WYծMGS;Xw?# . N}{N)}x/el"ExP9d "Y:̌8!œ@(^,}Ggn>PȟڎyFm/syūnل;{G~F:v<7u/($7|_ſR W*瞰#Fr|WO9|Uw a㑿ڬbW}E UMh`LR~]#p7GOh+s\\He5Fκy?W~&1fƒ"fȊLnl NApGxf+NPPZ2Sh$}zw@+u>Vn_6>6D)@rƚk 0z.M(1^?Szp=\Ki5`ێIx3sOҶ!sB'9nTS]Oz B5b9dHa=٤$@L_LbǬ+g);5VBXocw@zUi5ԣR([]FgkϊbpZd[X=<Ȃ+˯V3tÇKx¬\IPaG]|^7}f;"` O)w_ }R>ҩ@,qh~7|5DY$ٴ_ :*{'?xv͍oL"HMYF wkÿj'Sf)O$jD}ɦ1h1*4G}y§E8IMZ ||kLW5>ndࣚn;sXS nzxBS<=QDuɮZL*x7&|YڼVy]ai'* j̜A.aRڢLfыn2qp6nw'!o|p3Ӗ[$_THk͒H :(od¤Bz,P SOLe7.s^Rq[m ,s3>ciY!ݮMtAKo,G_:+Twt9X%r;{mU՟煽GU$)H"@VQ, 6|4Tifp+,u)$o객+)/:[< LMU+62-[^*+!bURe B 15a|Aa \J(w,'X 4@(.'r?Q/eJPİg=?Mc . ZќHCaOk'ȣyS33J ш;r ~9~mJ[FFj;edWi3y˱#.V|j),b)[PqeL$`TTKHwpSe{E^o߅*wz7'닒RM1&6YD&>Y8=٫_g 3nReZHv:QpVs,LOƀ*7N$y9N,چI *mɆGT9biɓ^}[."Ⱦt^zB?O&4c4Sf^ wG3%ŋ [5tWs~&8(}g,8k.yA``0q 6ibsZ,(#:KySһO.AQ+1 zmEAt8mV:v"sIOLg~G+/dΌ6JݛxRX$ni3os`e(Dik%:'>*'&Zb 7g;CKLnV1a{핧4 {_<pos;ࢶxxA';6h1st8Љ1 b_n;>B7\<)\.M1rgTܬmvZ=^hZ@nc\ݿuBrϼS+ i>e>~Oσ] UȂ+!U!<:\`k]'9 * TUkB|Ч[A*)7̨7# 2)N&%3/C­ĹJI΂4i9@'R!$"@ uf(o?]{֭%pܓZ ΰl/i`LO/ NRF.z}DS+{'+KkoI8l5BZndLo(9I9\"ae/2l$#uZXX qY/KbҶaKoLDiK3=2aC-.%yN0lZw2쥑}6(l"jRƕ@mk{_/FEz5룟T1ˌFؽ[)1Aʬ?vzi\d.y?_aٹm/KAKb@J-d2ebA@.*>'8x!ꋃ7@WS݊ylD?pDYv'2C"7/劻 T#deAxjz%Vn=ܮ9ˑZwa*z 4ɓ䝿ؚP#q7˟L"`e:$K Dj 7{j0R kA p\C2ow@ eڳ"t; 'M2u$6S<&$ExmQ.~ ?DﺹRIju{SgXCx]F̍A <i]ynVBݒI*&n}]?ܱl. zW&0wBHuILCF!^y25~pts[̫f cQa^й$cɤ1 eDU V51*ȟ.4O3 JڴO0ڒeP*a2{VMYNfp`1qNo,=O=9uAmW]}l>-"=cdI#s8CHl\Ù3Ւ\Aڸ W.aCW&Og0[po.f-y*WH-ֺx!¯6_+ @TND%-BiU#~HdK)%x- ߌS[a.4sUh :\B_'H|0t\= #6uAtYw >Gہ{8Qdђ =f rĠ*ZCx!$~$޼(XJ,hE (M:OzGBSyU_]2SC+c]qk{ '*yY2,0B *W֎-ȩaD{`Ejۋl YijΛf'd֌" 7|B ۾ 4F$y %4бqH?N Űt0!9$..[Å`թSۏߊ4!*W԰/דJ;E1eK{?rgF _0f8Hœ\D"Zuk JZnu 10n6_<#WSJDC? 3~9k(B'--'1Jgәȵg[M!?C!TOm?͞xih}*uKdDƳ.nC Я3EPwA5q\M.61Gˑc}G?j4F@U+Bł )V(j :@I%_).`Ф’MÖs\߁;7l3ȑD1Eb4l*hfTZUQ-cu.~,Qt0ZOt=ZVwv2J-a/⢳%o$/#(XṴdSm%ȅbVq"ŠƬ4%ePz`q`Rmo8?[}bum]7xMn9+VG7KA5VYWZ OӔǧfh!Oes_4z&ZA$ V _['}h4f*)J99dʌ'##c͗ WEN,ű0kc4:q;VjbcL=2aLXbwn|cѲ5GY1է  A^SV6R 4|k'T1#J*`TKdU漺94`}Dx*&! UaT!Oh pT6[2ƥ }WqAgV ty|.{c3iq8< dӆSX+ԓݵL솰>T}hM›*eh0VV:͋%.U F<6?pt΍v `p\ezTMz [|uעJwsڤAH$>xM#ѳw0F~.M5F]!TOfUG5˦\^N)ɿBق Ꞁ' Bzw(,֟h:z1ӂC&zNE6]D5)B,7 ıuN'39^3D1kF|'ѥ7;8tوan'ҰQX,`ORoK} Q_\û)0L;?*TTXvX5׏TY[u ӆdVRe=r ,'r`$MZ,y:#GTp-YM&G)r%oM|P% m Ϛ 8OIJQm_^X* ɘ/F}>Z"c-Yv[(SI.o̻8 ctoo?-4fsFnW<|<x,Y$!(5a8oÙ@5\r q^@.< ϲNujj)e$ුi9Pm^p]n;B3E q{}.JК>Rym"O2(9A* ML3ꞈz>cJԺjYr_YR}]r{ӗGȆVeR~F tۜNB$"y}-x(C[n!d4AK|k&"{(+&cV4;X jG - >JVv 1n͖_4 =N{x7߁p4us_)6;fq,4Rd'F]&u*ΏKU/ڇ2ӫDOg(Sd~q(S<W h)ue#mWBBkۿ;hi-\Q6z Y tۥc'Y*Qݎb<ҍH Z kv%ObzS0p R֗Ôa9%{Y-1K,A\7m;vd. =fGT{hFIFh0@rW.0KhƱxOqY42#o$}oe.2I2^sT b\+w~;LPE3]A)AW1KU0.^bTjwSmyߧu_27EfEqj&W";kĀ U`3@'GA-v!<bS@KZ0*9~l#/qtFXdn1/U׿G/)'^:HlBl,dyurCMP 3ȣv5#P:zOGGB Xc#rn8Alj3A"ke!~|Ak@y1h_XYo0yճs#t}v i.8j .սq2B'.-Etde YUI]fE*}KBK"``u486&SH1,!U#'.4LQ"p7BeJe}0YJ(\#Pk'T^ȒjOA ECI&RΦ86S/YK0h8/,%1̏ayi3R ( GCPقK|^$K+ysI)y}1wܱ HE()Kx&'ĄO]w,}Ff(#Աw_կY/yQXAmIL{B,@r.7lƈqQ~KYta fZM#ux3d#CLM\~ذbC0ٌmݵ;BCM!N4V ^dI(a~jIAP99"!&0#^"FIzSS=D9i(KU{A%=8R*C2(A-uBye!c1M>j3DdQ'{:,}|.}LfO+uЍh!Ε qvJ{˪Ʒg gVEu?P-i,O4aҁV.o묿X"qş=^LE !-4 Fx[[d7&.5D|dS㭽XĶdMֱ$;zպ7uJ}D\!88ZA"iG".9iM3H8ݭ3!xbfO XczƷTa)`D!-wCujRW@J9F6J֚*O,{7$FyEpSəG8]pD}ra<#XWt1atܝڔxV :csRVe;͙݇5&^B6o]qcAXn:'-u ]J((F`eYڼ`_یk!%WxP㈉l .%L^?$/$/8 Rn (Du:,WPxs5_y0%)PbME2mN#\ O⃲1W)F߸|Q>.)[  ɢ!*'C*$άc נK&M;~a!Z@|/T;sxQ3E 5!4;FѽA`ǥ@oW/uBb CJ: "ݐJ7#r!l`n>׼{~6ԑk$ُ*&s TYTZ~EaZu ^$wC{QgzR-Ͽu} ywu սtu]al?~II~TZ"ƥּķYU6]kq"1{K$ RX%ˮyT0j뒪…l8 )DLoMHw1\qqfNiSonVGVLО8e[&|Ϩ,i)}F隅4RX"m6A $nݍ&cZr9օn)^bxHOi@qhnzBZ탱 Sx@$Avh opT?jH]'~*7hmyK)&קRٻ8RxtV+aꮒYafbH͕OƈVX3uy؇a'L92X! JzEH5L5RfX( +5,Ӱl!p}^VA԰mo!.fnD&3Hu/'Zr r= (B9?ϵxQH?XAt.I&ٌ0gt^7uБ,qSOzKT'ux#aZ8*wwŰ=@x³(KNw]ٙ\8%e)ݭ% f溥7IYahlHp7xZ@' 9x1QA; n/fmj֏l$Sғxx7-B'+YiL8{/q:G2kĭ-}Xq'][L0y"<@yXKA)ɟj-?\P-F>=5J>KFׂ4鴩>E/Yqo(}0ݎ9;#gg+GOCB4!6-Z+b`Ɏ'Eq!Pk㵧(XWW8ҳ,uFgTAx^ٯ$v=8,1~M-VXS[I` &.frF<Vi 0Cve(5Bdpg+foypO[J0hyJ}lj]ucs8qE-<!bznط\  8 ZZc2jR4mTA5Y'ˤ.>oFEg c7h55ɷr#  XDB֖I<`dž4:lSQmU^=q("A?)0G!с޺ a'dÉq}@x(M#kq,Տc.ܲdVyJ k5ٮ~4=(#1H8 obD_m²x~(C{bl1,0,Ҳ6BG[Ujln?5.#aN΢[x"n{tʣU%jr+FCnni=$mTC€( >hNuBx5Et$Ӕ2Gp*@VHkS33e폋7sºEn\4 ŒM=oҌs/J708U6ӄym 9P8Yqm84rݥxTbRJ,gK'Gʶ]%37S4 ŵtnwpbSY\XT0.{J<뮄e,k@mAWR&vޝ|iL"is47XR}>?z#^@du% i:?@0*U_8;.7}p]0M.c~0+sVA{ʘ+l=ؠ6GHo_r]g0'uA&},F/aJyhA*lR䷽:jz]`_ \X8E,Ⱦ's5M$_޻ڤ-Ɵܒp|@*LF$~XޝY@Ie:vXظ:KS2az}tN.((R]auκ:={4w^ 'kf>]hzoW/g\ 嘃 9YB!8s9:_8+V-ktDA/B)DcΆ}{R `vIJk<.b29J"қ\U%"#^J (#+Լ64^-t1С6o1_@Rmq2:eE/{9)zNY{҆e) %ۛFA^sC޾-\{]"r=J^/9k2?V>lNĝEѼ9ŦV# -}f>)$P |ה-#nrBix G:F>}ɿgO:fF V%OKl jo*ȟhhY˃JpG7iu Hirs5ԉ5llOXpY/K&jm}Nj ~lk?$pt7#?&P8a7ed Kà{:"{i Pwo- rQ?صK=wh6H(}cKѯŲ811Ϥ/'&4ݹq5 QW,IqF܏xJ&1,v)arT̢f$ngTz$:8l>j#qm[KD!HRdz3YbPR P+"OQ994#CĒy`0 Guɦ\G^hAdZav. ޘg 3T[kE:?{3ѢqOVc)uW\G0 s4CE?0Zrhf۞XOr`Wg ,T ze;4_@GmOD۷Ž?y GNbVW`7ڠ/?v& zٟp#9ݥԱkD Y7Q( Fѹ=O!#p@VBEo҆YӳKTbEG7 2N!khw+Q`TšcOy\zu{>H$Ah1߱Zִ¨ƷHoӅz>2 -[a: 3Vriʪq_NdћځL"& (aVa4@Yz `CBnO$c+G{ /1+)OS 1{:mokl0ng {PB2rw$vv+5nrsk;Rlq+Fv]$6=U0HHʊ.8<'f}m3.S8dd: P%HcG%dUb>cw pP[ G?)|8f/D&ç5.? ̉48fHnPбGUPbcH$G 4~CǜG?0Z_qEGֻBb'\Ǘu^E6Wl[1@# F/?uHWY'tN^W1֟A0s ]ΘxQ1T'I^*ivHI&Wi)"Ą8mn.>b 3eh2wi|R>8>Z~,]A& +UB9ϝ~DS%AFbg drU< BFmu犰̟HZp$ d`2)#$VY`; RrHk<^Iz;P>K9r'`.$f_w':LG$ QlnWrQSpח#!T26.E@si,^$O~' /-a] csD~=/en J?{u+.gbgKSO>ã V]Pa7@uwBz1ӠsިquRٲUVqknWaʪ+)ma<)"5h_잨JX0 Xep7p@@uaYY`4B#wȈo$uZ{{|8qSoƠL]ڋ1 _(z:.Ęח%j⨝ɭ?"\X~}C֚=n+R9$L&X9=H`l\7c]jrzo8?zBX͂vQ/Y鄉${z)E#zⅾ!?PrKf;[?iL,PF-f,rDT"I@2 OLgso.͊W W\kr=~’`h3CDߢ$e~ 0Qsftasl;oR]U!'ݛ"r.z=?Umʹ H*y1_2@j ͍ޢNs$FpC sRks;]YjlsXfca <;~GMj X %Vסpa?#Y̡z]0YnM:}n  VgP^Dh̼5IyJV8YOޑ-}9|qSzDC*Ζ.R4z8E!@W800(i4 FSKrg@&t[em}c EQc,B9`!U`>ǯZ5Si0][^mG{D5hsмY7(U?U.{ӡd<\"ϖos)1ktJ<_BIwb5Za/}0 ^DJƜ#`L~ Ƴ*Y;] YΌھ8 r5h ' ~ Q]٥*SB0-`g9 oڵ\K;z1kV; 1.74jz#2>z@a[W[hŁG1 ÖֿKx Lt~ibkKaJ7#Z9&aDfM^0!ˉ#1c>NN#,<_BJ}Ťh)U#Z<, H1 4B^JG29$BҴ Լ)Wdh Y,)F_)I TzxiY%w@U3t 5fLvظ50⟠ 8AJ)|+5D+Qfe_Frb22KV81E*Lt=AeA1)#J+ReR8`:{ fːF Ɯe}i^FHx6"ﲜL境hdO]x9 9 NX/نXhט/}".(n%W߸;_H;Dȶ..Ce.(_~)֛ APjg(" R%}*qaNJDĖ}Z;@:HlŞ+\i=JIvbR݄RF=Tpo[A4QhYOO"i7$b)ю$ՠކd ;R'@E¡@sD 5 qI:;`t~PpŽ#cVnaM%6/{ײ}Cq ;Ezև7awţٟp] R^E "%Cl6)aHGIꗹv1s J]6(oRINZA|zPof`:pV'i봐ϋT^s!9t `wQ 'xV$?aWGيn)n{2駹tR{&m##p:[#E/Ú[yYF%58k73c+-SP?qGY7rY| c85/jUܼDc)˨0zwdQ 2E<؝IqKkGA]6\ϷiNc/*W|gHO((klWnĔ6Ify y'j**+ W;A[ГLl@9b-Ìi;Io^t9SCmï*p:+=!9Ap;bLC 08i6mU쟭QUW }nقųEy%WzzZ6D=`. ˰Z ׍QЕ&`;lc$_+ԕrtQGyHS? E@dCgի7u(ؿR Cvc-}iG}#L\]HrCᗖ7G pXihԓG (UԒaˢ衝jhϩ^/hĮQyzl6nEտJ@o.#yTx5y{'ׇ ~{!-m=`E70Hn:8wz=j7CEM5m c,¾W_,a"*S;wq}Bd3l,R|t@%Gbxɧ98i;?⪏Y$ϙ?wpxMRH7&-P(ywN t4x"U <9{OuĈ:oS"}ILXPCG=+tsDH~@ )FkG'~ )jYyt''Fiz'=3_^Ā"sid^S4Me .]O`J^Y\2sA*Z&QA\PAL֞qt+M+hRC1n=GUΏ"uY_L`H̕j3r#@Y;znA,qv-zCvpbm!){w3w<`j_<ZvaYSH+T+T Ð $Ko+[p-ǟC2NljVO(eU 9dC:#NF" T I Eq2d (KQFXE苀@;o_壷0RSf'%a c?ۧ خJVL<ޤhNN Rr z1pZ DFS+ٷ@0$n&Xm^zoy3D+ GGh!*E泉b/fskwH E#/H5UeaF9L؛7ZWD-O+uf~/ Ԯ6#貌Y}Qx :z^: !b@fu6Z[և Ȣ&gzrixQHg~Cl51&$ĸ. knЎOMv'#noft+wA̕E>fF]_)f`tTew}3I [U:&P?2ɐ_jɢ80XnIR2pqLZY\-f+ /|&"mסi+A8{?8Q{i1zk5gэh$!-h:Px._RHC$& wa&xKzPOc"19f\ gaJ #4 Fz,}s=>2`=4{ *(*X߂xC!7 JF3.Iȃ4TM))Ød 6<`4>N A`Ds$EkOpNO #xB/6Wպ;@aH*vԏ&Mu \Di)@i3 qNX:'d {7ȥ;\J5nLͯWz {v9ruj/Mw= TXSE˱ ñ"m0Yr/ď *;O9PZ84tw|=E͸Ca :Ůی8! m)?P*nF,pMi|4jv8p/ j;;O RUتV$GqBprSMc]Hޚ27r3 kᾌ;l_L>{tO7v?m 21Ak~BAU:MX ʮG'lw<_gj~P]0% ,J2(d0k7@A~$E.&u24K]ɣMxݍ9%0@o/{ EFQ_7Vo5(S?_Kf9BJY(xS)/aG+bx-J忁 4Ԃ Wm% gXᩌDY_qs1I/M(Pϸ GAUO EC]ii6䝿JNs_{tDgn><ӆګ?ѦB龽n)3dҧK]5P+Vgsq3qu%ˠh|6fq0w$ʭ/SnsS J;S>0OCUH]0Ҵ%J3FG+c]`WR)φX:cZL ѿrNui1thB^<1,WYaJp22h4MZ+ YwZ{7oކ%"]}ַ&#P<ԭX^-}!%u7ʘξ([nށVDenVS +&I<&j4+ d/4NDF6d)ߧ*1u ^ȓeOSLc|sŬ;!#]Z F!@SsԠ.VQO/VpTEeL5e7>P8O_իG1iBKr=5TfΚEqy-C뜊'1%} qXeƳ'MmzSJ|G"7߂VP?=/0X1 Q]LSuKZ[-UozXd^/z.nEXecȣ 5:P.`"lm˛6KGIR0%Gi+ OK6v#w}V.sz8.4jK``w m dѷ>>W?-#:9>џ4)=e"̸L&@ pVioVmpD O]=knVc 4 fWh0N^Y+öP)w_QWFZGiAqE^KV%u|#x'hqp^~'dY{,Pİ8Ⱦ6U>q_)("4J%ʶGIКyr|=ldܡ`65*~i5a%s"{`rH겳0 2nW =KYb"iHX! I&sqQN\98Qt[TRzvTPn@\>%6*UK<lHmh/gqcgU)wRs75Zo<.9qZv^~ G3#Kp20.={wYG]TYt$n`<׵,@emj@(h_ZVKSD"KM!C;X'$ lN B*(k煄.+c(E x8]'1Sz~n$}dk\80YEyK㰖0P}~l#E[lBH bk-}~n(i+qv by[чdQ$#R}&Rsⱃ_.!XZX]r[70^Z& msr},'$ v_s5+"OHbr_xaHLBO+PAqYQ4-/>q^Z/,鉸bv#=L{f^y>/?פ5b$(uU BeF;WŸ )|DǨ&1䲐71( 'DdNmtM9Ĥ(=ʦ#;Ny41ŻpZfll,"6oh`^URD*e+a0ٶU1+'GV|+f@;) 1pL7t[257:Jۉї?E)3g}#Lj>8J[1 mk[)e݀Z#~!夐7g)ڐ%8ڳ˳iu8Q!aW  OqNᏐ bZGIt5uYU[3O yD7 :2nEdTGy/b<#Lij8X>ߘ)Ux5x~TE=|S%l 0H}o<7pǁSX o{*F3ЫX>X"n}&V6 hhOO\A7V`=Cv(mS$ 2+) o.2.d:PpL*7^^i>>+ftU]WTƀ\k*<45s~O F.J^utIUxj)AKXJ$Z9 t+Ig|sXe܎n3D vKI - 8,11T ^k+eMP)R!t.z|m~oU$2L @ȻAWTJyOa %X?K "V)t<陥D">ud0oTF )R4ю\Bn5Arϝ{& \$A׋M ˥nK}ǁ{ݰATlej)Bz$M#慳>1>d@ q ɢ: FǓ6!)Ȓ&Swe!ѹ\@}nhr䘑HʾPʾл!V`J8++ $Z/NX.g,.i*ōv\]s HVo3yua.nndERuMK!fҙ:f8*|XJzfuI.A],"6bH,II.| %`T6 E(#9BۯV,"|Y_KT~Z0:c:i߷F\7̑y>j}^"&?QL`2;!("%,;u? PxqYi9x\":-:g*{P۫.XT!гY6gl,4~B- j%n9bD(1CA JwE^0^diTNS gSXux:hBWE+#Y^v->i>NZt:x$̭2 k ]\  U'dP&^s5*_=9qFؑn _Lg7/=˱gN ~D"^%k3 *Qu=02jZ,oJHd492cF[1:،b!X'`UpJ_ǂM >ӯڳz=~kj h\dxIgJ*UmNAYuoZ(o:^8[p*% Ԅ* wAP#&2ٖH!>9DOTVW3Z?zp?j2(Ezr)1˲67~Lȫ3 &?&+aqQgUen& { :="YFJÎs\r,JKy:8E#IXNh|pN-)[򨽳PmeD>y|LFƒʔ{*x]LUM5ގY%E&4hU4U`eayG%l/OV"37mrec" '_hG SCKX6m\ޑUQeEqe*비;?cL kpA82tA~f'I|(pG߾HUIVr"9o6QH*y` *s=Vyj(z6|A\M暟({s|5bejG$ޗ6fr5!FFW`zWW/triQ^Gk-3κFH۫Dw8Yʍ'd,F΋\rZ\<~RKFC˛$jYoS7|+>|ȞivK,i?[!Qu>Y"[^*d&S_n_Tʛ>|hf1(B&m0G}*HmO ~[;-+}:'tgblv߇8CL]˨Mt46~(m_tvduSr!96ʾzƥ#3RR*kC.AXSCb't\(-yc3{80LDP] tl"` AqOBv %oEACP7)@Xm8nDS~@q&_fXcd:pHpmXݽLh*h2e]@)K`~%Qwަ@NSS [[.ڊ6[@Rݬt zqFb8}*: KSΓ.0}ccSVJHW~fꛘEu)S3oK !,ٱϊ%htW >hV8Fõo0uҞ!3RwE+M 8oͫ-+D~5|ƉgFZ~uɎy]}1Nzz6eT)@Xw=_y^yu;_5 {MTZ/\!(rXhL؋p*_vWzpE2#dCöuAʻe'q ዩw۪ hR :jKk*g$FMnozlN6C'4d8i VqaWnξ"6",ȕyo& nꟹ㩕ѷ1t)C޼ |c{i1KrA`f! 'm*;G)&3ajlYCclңیX[x n{5k|q3LEOXA[wa@b5wG= dd5wC̑SY8ܗ'lxɪ|.my,&no5 Wx9*6FׇS:Xjjf]&}")a"Ii-([ƚbZT,1@rYpV@gȊdtkWĚ3?S q4:Ăv,aCWiK#/oխVVa|'6nF¡N5ӱIg)⸚rQaHԨE?&|K8peUOOqkBJqjޕ ֜D^O'g3٦M7G<Շr'eX?8:U{tc FöUlnU șkY=:;cl ߙ~b^ (~V1?-zgby#'S}XYڪ %ݡ-9=Sfx'oX/W\K 4){A v[w1Fv}#Y%Щ\h5 { i%|oq:fa8@L;`c$f^29 fRؑkMRKRLemgOG, ~9${&o,^ 1Gǥ9U3Z `rŴ.yRFU[ y@Rw$sS&mCIY%boݘ%`2t,g탮iVAk}lA#:{F}|KZ\MN`J,z X8}jz8ilۛ gďԔt*6ECAzPPr/P_ɼ!M1gwYa?i Y!p2Eܾ^go#4l yȋ cmu"BqíѰ v`@taK0`Q5$%E2УjH>]Oh؇H7빙8¦#{IJ=񪿢pjUd#2\S-!*/հe,50K @MMG7gdyoQ9h?-Kaܯ@3l ӷK=#A| 4% S,֬&Gt&֢=yPo,5ӫ=ם1?9Č[jg h z(":f>بa3 ]ݫdwa{ ?g* Jg m?X -&]T\0 _t?U|Dk3Dֱ ~#>X)יe i!$}uB/)TZyCn,JN&ˎ*h4=ALxdknwcQQ Y. /`s"gs-|gF%XJe#Gr&. p4DFF%?Z1\5HF琋*ƺpߪ^S` xHƄ)Ke`WiSU)z#9Pʼod#0 kԍnG,5&a/bzɧ37]囫!~Tω}sZ;ĵϗZ w3ŗЀn훭a0 />x{؁# krC\:j~ib=IXJ."_ |'"|&H%F6D+a} &p ;?к];+PkǼh<\ c6;$G׆^K$ 1H4ԑ?Hl4N `56I#B[O(?(1JתC~@[fy녽Tfm+ۙ/ o bj3FC? Uri{2Z/fwB0W;Uj7+jփ,˼}"gȯ!~IrɥH}.%^rWY|N7ɐlu Ź;hzNs;ꪄ)-A~M $Վu5z7 )|yg%˕^Bh[?N fpg<,Xկ]ZG|H*,ȁў\|.4V~=Wpk b ~Ƶ8Qp^K;5|a,̲ΊbbO?3q&K a t2P0ֈ&_k!Btutshgm"}g-v̍;+2+-&mv_xdhFzj> v^hw視Lz 񅇡U5b"b\?P}kʥM$ld8Z]J؜J^o,0k;ωj5L۹L]oҩiA:l.;jlĶRЎƤݿ,!RΞ5Z>M,Qh|Qqgg{=2 .;+@ݴUA%+FgEM$`1Kzl`;2`^\kX$*˜u#D("iU71ρS\.9xb傖!Y4gGn(rA#/|[ S(|JVY{4YqRC5W=ˋ$69>5<q$SsLN+#^G?S:n 7\NsJh ?]9J=FasdPW&EReN'eS9,- n|b,oA*M=P'o $aӕO? Z[ʐ/twMM(&!9R)q<_vCwuCw 01#G Z9bƱkaZ}@C|o Ze JG\WgXbGv$!uʸ)}.ʳ ³<Ӧ} yrh)ǹLBșw8mGxa&ڐӄܚA!έ6aĸ0FSߑR %K6hN rW-q ,2Yڴ-ǚv~&[q@H޾?~$͖Y1 5m_zPswPC2#@;G41{L]XX)[{)y? &ߤkUӴjI6kQTH]=> WxdI zra,M]W*s$K`\5S<I4[U9FB~<@׌])"#}iܸ,ȑb"dwȿ;XQ[fG̹mX4F$k]qw|ǘH㽗Lz3Ws[^&`ARl"J`gOtƳChf^)蚖G M| >@mk[<.rohϳ0N4|Y[MѡP._ VM=63آPs~s4k0'] *Gl0]|CE5yVV9QГ)xAU&9'8>5K%8E 7 ƴ!gwMȣl|xn.ʒW WX~C\wDzݏ}~|LfX7ϯݖ:W&kDC*=BHm\Jj¯0% r@-xRO^ltX\GdɄf_.};~i~F&8> VC56}z8珸6슭pp!.d'&T|7 4HO[6nVC/dm%-mSHV,G!iumC5xv<38YKΏV/@Z&i H [VOKf`X>^wWԙI@Bd L!XZvi߯X"KjxSy}Kp#S'M8A[ESw,/e- 2ޫo ~c%9zo7a"h wGlrΐ1me'#T'K^wG0Cř?o_兂Sh7`%)\TT9oSoF*TvJ<^Oqf1m^ "gݻN ')oBՕ&?3rCz)4ee7GT)OҦIȥ^!$|֥nRI8[g;e^(I['P%,_Z8gk<KKDi <蟨s( #?6xZ"BK:Id1+^MTz7Q|t(!GNnjuI͚Gl>*ccW,.({yy(|AE)CE rԣDΠz4۷}`Jp%u«g +Kpw6IwYlgO`֎M.gcjgAdߖ\@){)=}63&t}3$N;btչ1ZN6GHzz:_>щx#ơ;%ϖJw᥹z];YZOCC/Km\gn/΢}9i, '^nl5;x,rQ[)MZP؝RXJ!޵]LX=v E:j0My0+0dѤ(m "kjHζ˗H*bh<riӮ53^vpzIJ.3fA,k!V?Yp0lPOqRA*oV6Uuukr >S!"/f.2hPSH\0p\?"$ DzG5t~@[[JփrƔwlG^$GH:4~7i|c̈ʒsJ) /2op'Ů8mx *CoeUâN(a^A_y+31]o4nΓZ D+L~_iCuSD&k6O^7i <rPeA4^ 0:͹`oWgq,jJv[jS#bH$2 DEʖ(EE  H<ߚ?%{'< ܛ{?ׂat PTJZm>?=U/\"ZEU!. U B"ITocp#FU(J L/bmKisJ=׼ Du02cMR4h QO(mzZHf0raE\Wo"D7$7DUY| G;Y9c"72/ufcj% XڡpoQJ]OVx@4He28) %`ڳUG{3G-ns͓.;<:Ӧ*z*Na:N@6LW8ބP\)V"Ds+bG\)rFdSF<)'>+GLLEPYykma%Pr'jZBm.Z/6y׀Z|JބQqFZ׭ c-bZ 0Ic[s1v&$WW@( Hp ľQG}KTW-|JfEN͕$,P!@Z5uS%e[I!&vhbfgؽ`V:Hqah\-"kd/iŕ]7u(VZ ;q*ˀ97_؏s`̵CuDah۟g<,GǡqoI5Y6~9kSKwVAVT(m);q!NfEv]U=h>A*[C{t聆R<vz۸FF .<[֋up-e]PkئLǏJ uɝbH'NOZQ)L˃Ω JRBbF4VkZR`Иr6DZx gv`hޯ;ߡq{kҋ;զf3q/EsH %X>\ ӱmLZ&>pʆa~.P/d_E'M lI:/ xV;=rOo11Қ4Kd+J&^G9<`u|܎{6KӛF) nm ukpu݇#z#-C/yWfRid8yM#$s&x`lظ7+Emв1+[xcČ2.1F"lqAUeBr힟]Nj@G, 0} ZJB!G:B#FSS\s{Ue=nEDk1GO,b!!hYmxj>JGL?@PwIɀe{ў}`3=i!aޓ;+r-|oY֫wVID`B PvӠ5eRmrl%dOBxU9vhe6lg'n}fu!nP0Nό]P.(?࿛ q-ʎJh>{ 7z|7 $;A=Wl3 8?q3wvJ{k>z>f1w۞>q;*׮+ņ c";>+ʩ*B dMo%gb6Y_jwŭe! 01[uG{6yBzJ B{[ùɏF` ҷj[ QcN)!¦rE\"uɏ=)dBMj4<ݠ-2P6'r+;F *A#u;f@X >$KWOr8)H W%_Y[ԄW&$Z :b^s&LʭCG/{e{&Oء/+2B_'K3VQ״~ ߶#xuZaDv:mwyدm3R~}W-vФb{k.|XE7h,u utX?N(Yu@&!Gl_#_Ę`y. t<W!%F"I+}P1 HQndvPk= n(?oRj(mNj n=Iݼ8GB0q9< ʂn5LG4a9AV{/ z#ӠQՅu'-D6Iđˠ9f aD#O L!}iF E5X< _(ݖ~"]O%AQA^OwzpRNr `w1ȉd-N⪆Ir P}D;Cr8 ʜ;3fCo!j(dN`:XO%q> N_QZµrUN uK$J~ĞwGOqCYQ61Xb%HJJ}쮉fUGq:iVru;p7(< +08 Q6f,S}ML -{V",JY%Ë'qr+ګiẙEx H\nYPc27s1pZs}{U4CIlXiÞc" o@D$DzIrO^#:3#8ݘOEA .~V޼)htpVvLȂ$p* ff0U4DJ#{}t*K>/"r:"31V|</^wq_N$j{g!M0ڭ*r{BFavaP}i16&ɛ-@w񔙳]'o:'OtJ[1[%y;-N]3hWbvUϙt"#kvV/+C +]ΩJ>1", cA5֟;BH}M_ٔ 厡FM}`_GF= ?Wb$ o; M`-Kd;t2/,&U{C9@%qxdo q;UBWsED nEv ˨DQkxϵúrĦWDn}{XP Yf̅_̫V] g~#p5&GNAct_mh~U"7~5 sl m֎jEO,cFuJy!h[j)~&CXEAh2EV`|~ds%nY,{xq= yKMwU;H# R\$HkǸXQ2.FN>u2 | yY"G_jCB3ҫCJ=bl*/1LG*4@V|:VKn}8+q2VŸb<Rl.p֜.Z4x[S{~WKVkz]MNrJ)6W3J.JyNt${:glJun3j)J1I6x0AZ\ڵ{hnNˊ?BS6.!H!U2O'^ ɾrK8 ~clz4] ,{e+exOgTA33N`黵ug) [BOQ|kJ0.)e7ciXQa L%ʡ,7|m[@}oELb9@?O_7O봐<ߺ0*rxiZX SG_7,~hpGubc?uAhB<.+=;Z룩n$ 4n{wF6P=s9/(Fm ͛[_ E}e q NHmkdgw-:PE- >yvbRd7I)^|Uxk9Eɳ ~~$]M/iwXYN(O9Ԛ 55*.ȷ[,}㋒%{'RpIEF6a4ȃ渞PL1 @s$@;%HϚʨu?ӳ W1ve44% $TL 2f.=;3'P0ky\3 x,ѴA7 6s6׍ 83F_+YEjzB냲N=/٦3*cş u%<5FɤDցݛȴ5aCuFwe/T'Ym]J_.9Iס8UR{A6wqb 4Q{EtBBTJ80ʴ\֓WeR-aBX_d:Ҳְ3\ /4^Wǻ¿|_ߒ'g&w%0S׫v"/+H޽&geiFZb`Xj#A|6" KLfrfvx%5!Gtg<[|LlZf0\R+@NKs0+ ރ^?L),fP=>WRYuy?cc0eJyJ߿'|z +%*k@=E ;t*7^ZqUO|GOv:<vC#Z2kV ͩA_N,#| :e +j'v%E4D㽤/2HM(XW,@ 2D\40C"kW[$-*Y A=Cuirݬy=9QVқ9-gqK+ tXXڋ<.eVl=n;';MZNx,!k5FD F҇$cLB Nݡˀ8x CuMc/lM[)u7dHh֘_r+V=3`4OhƖ(ˡ[2gEf ^nę7L ̉rޭJ'lވ+7"+6{Ӿȼ}Z{SxA̓K` A`3|uug؉':#.p&x^<PM4SM !V 1C}~GM!щYT&ʱ5z|u`GZ{Cxė^k㚞-ՙ r˸BX'N6SPT550~z`S5~#A H 0;m##qz~0]ӿQ75ng]A+s0YAKz/V~ |D]23t>6*=Xi,! IqmU yL2=t 7ζ_18MgUC&eesNrekhQH1 vKhKJ.ǐ=,p'dᥢp&6 "U]փ7ou}\)[;FeT6R^uH1utv˺Whqɦe(-%uf¹YW]LkeM\l`22"\TK?fݚFk8`ؓp^\B3CբQBS68BS%?;͙v@dzWn`3jl>F6(䂥wmHEe&f*H: "DUAO2%TxJ]Z{9GW)$K\<[ɸB߯ٻ2"nJӋwߪ!b-'?;zGzfǦ{ 뀇$rɬRFw-p,:[D(NJm'!XS_rES+ =5nlB`O٫`l}|۱5gs uC7G,nrg$ p?9 C=`cJeQs W y[󾁫͟jiZ<}'?%o ƐZ5q㔻2Ämu{x!G_eOp{IDn t՞Gsn?\!aRАE8)c#nSqcyvbs#d/&9j : 7z|P~ruL#$5z]mb)/(&@fȮaC߁25՞5rNViYR*rgBLv$u(B;У #_)E60$5`҇ӣCFԁ׭ƾ|.F*y?SU0g'yX[ka_yhL~bE䔭 ESHUi`l j`LlBAeƵx<[b(M?~yeTSSnzϼ~9`[-OV&1.w*`Ʊaw T:|ri 6U 4QD㮅Muz Τ.KӒ' +S8!UX&r:;0LڬM;'{y@|Pτ風͚y,xFn‹/tcLKa'Aa0uŗoZGu1AF;ˉ,CQSS܊|CiUSލfNA*[g</%)Tķ6 2TASPeȇD_ fVGFewb]  /_9]<(E #AGlt"ՌoT #~Ke4hm 'G6t)g@}}5=I.zT'q˗W-XBR},BZH"2 jfIqK?W,$ S p.imMbmrSO8N! 9 LP5?w`fnE[2eBCe6T{-<‘1[KT稲zKZCAY%?ПуFQw﹘+}H_m2ԭ=A^Tʑ4T.0oi&͗\R֋/շZ@d_ż7yvQ JiB[xt rsmi.,zmfkR;q5~ߝ?UبHEL)~ ω;ZpHŒݳ-HѻIW]IsͳV]\>W RϦ[*;9 x?TV'tl++9qI#.2'f[Vfw̅ůq-Ps+?2Nxh0Vh(֞[çӤI6$YѫBQSq>cr{ډLWO $qbLߒPJ_CߎeA\&eBG^:mh?ڡ @kvr+شN t2: K5+f}:x׵K_.z4E iK G#a۸c'33v+OkX)YY4z}*˙gNzu_MVvb<7A \TaY}`\5Gҍc6zCuȩ wS5â:לi+q5X(.@6glu8 ;գ8&x {K1Weڳ"h `,E9bII'nC{9E/ h գD$RhL:h8MQgYm%5a,[V"t'-.N{.Tl/b}66;L]ܥܤ>ѻ2ks=ozъM~ȀQ(| 4ƞ]&v~X2T2afIG.|BbBiOޠ2dU߈oQA&b/Lv CxX>vV"6P?5ʥyqm7is"h-KmBGtdY):V,VvG7RGz%i:=+lh}yBShӯ^0s]@*v\݌ZAi$3Ln G^mvs5i& zK/ Vrt"DEjpj?Hr(/0Y=iY펪U;hT4͢{kl!DOKNByTv};X̎ WD~J<:N׭$Ugg6rky^Ի޴Fm~~ $pqq=`R#!AmE}c8n/縰m ̷FPTQcJs%r?uV%[N,Pa5R Qڤ]U} r wJ=Kڂ'W0ɜģ#?$Az,$+sr˞ʒ3 |ܺ;[+Lxz+ZumWQ{eЄ*\xޏ1?_W) ";gሾIGG,"3/\A"K8/lMO˨^pf [^.@9n*yNlrnhtC"Ԩn.F\P:=I9]/g~~4Qͻ%*U]O~\?ڤ6( :7p&UZ)gF4d9=2!Yy EMg'2{M Z]Sb.ծ eT)Y%gdq0o {^ WWcRNUX8dÒ!%H/! @ͮ; (mH %XovZ%( .bU#/NݞdVTy*@-,&W7NtArA٥ƞ(Z귀>cF~^P|Z 3[Ug 3e4ˤ:*5=Nբ]j5º EٻU.OrlXsR5)|)Jzl]DO]_BS _yÿwr\82+{F$517SejtNwW=z+ɔN9řTJMy\-kXf룑mc-2|t.{<f@mhPo;]4~X1r΍$5 0DXؚ=, S\F}t3QeJ/)sO~Jǭ% A\GA_.UUb%Ɣyl"As0[k@A6-aUrw4ӡJE1aW;,'v!#՟}-뀡93ovD;5\ H(+Ұ]A٭]v$j`2 CܞԈ8!EGp ~hZ UC>${YS-S^E^"16zqHXt.dL> L/RY c3>\Gk:N%24kGy}@B huЇQZlSs]\[<1[qE5,*("ꃱn(Ƭ:W#[-s%]8DFmjb(#pLz$-}B#wc 2GۃQJA'i96@H_@BfK)u}gG좸mk}%.'uM8yp`G՘4f5.ĶgTyΒM֭CL9 ٵYY3_P ;B&3IRD.'l g$;XK'r00Hvp AH'*X_ 0Ɍvg1)1hJߛ?ߋYj=h".*.c?HQ*D=]T۽}j %08{& 4]n ' -ֲtZiDU;(u;TΟ쉩-h PT L#PCP=;S^(T0ٛ|\xl+ *X"J8^~ ilvvr{@[?cOA$1QXTӻ ȗPwUSwf.ȱ֒|%b*X̏ތlT @=M<(2 SEl)cW~LHyM9nWӵJcMnqE.$y]9Nh6 8,B?lM(?y@V4XV ]yLBrf䏽b*Y‹,Ve =+AlE=*Fc앎7"Vk krzx\m͙k8 KJS 4>1W1P 2oCMp<00e|'ԱEGDmH&v<![8+cvPxxev^fh),\$wgf8Jc@UۋDjIzs@gwVP2%mX[|>Nơ2kkS$7x<9 Htz-2֥QvCه01EJmnTE7 .4vJzMjN7ofsA7hV>504_m!X y\6UT(]`̻;ZotuNÂwC 8Q aЇx-LF~;+6moN'腣:)|.w [n؍R3ڻ:qd:B1)D柦Y c 2'N2~ s7H #JK@חCnXx\HU="lW?PPhۛ)MIxDIO NbG3ŻE2v9$C a lߏPT]Nϣ:m=蓋Uُ=lxV: fN}g,bcf1 6irf_%UX7I)YHRxÐx33- ]?wqht;0 uDey{PYCemN xd^D[#v (݌K[Rq'6k;M)G|+pwkdӷKO u8s=i uGkthקaj}}}@4i5-WM=@- .C#&H)#XɮVs: UDBǔfi'sօcy>r6ŋ_oP01ȈOJI"zٺ^^bp|naѻKoebا-ڟ3FnAMD]FS* ޣEF_,n5o W =*oۖ.u{GD,::ɗ Q(V}։z(Brڳ,$qU5ɞzFx2|񵕮k'њa7tR/E<jBsWաk'"$dDF2 aO=蕔m6XAk4p.p=?rzA:#=V[hوf&i1]?N6$.OQ NNFjٌ_x;u1 //63)#CC/ Q- :ӇSnw6QyR/4: 6⢇j[I@+YAdA݄hWc&/lBWkB}]4:ɻͬ)^ŮsczPw\x[6~Ц(atus|B %4f;tO%܀T=;V@@s6q`d/~)2eESK mAg>2hO]~5>DwZܱk tzwp]t-E8JUdDÀy`>N4U^_|>+q"̗,|BrG݇ q*aMkn}R9ɂ@(0Qc<.i' 씿11H@5EYA.-,I@^ǏQ !d ]=bWin2ޱeMف}JMqqMdau+ GµDhœ9dY $H>t LdtIUZRɪd5q+z=Q Pi%Ka(K#q} KTxu#i98揉=a%L} '"zz< 6Ѩgoe:%=RGC4BY ,+$Nן%v)j8W„qkߟ,> _z]o }Oz88}EZ0beAӂ_'> *~7{v(ž yypHnG63RjL1OOEbO?X8#q[[u &PXR*Z_&ʝ4Z˨Q/]~8k1e lrT$a pm>=eF .iW 7 fƟ;}"?>꣚kzdeUh|;8AҟjcnHOv87[LD){\b*Rm$ w` pVRkqMei崯&}4IQxAM@+=Zq֖ed\:fqn8J`3 'aIq#k~iA0'LX `W=[(kk7pI3mUZAE8X^6I+Jp)mJɥﱪw,ڊ २Vģ~50g{(Н(l*08k`ܨ|>5f] о` f-B@c \#$To7#3S>)ќ~KctټJF63%tU4 =ITSŸQCAv;VG~9h-QwٞNIt)ѝ˩U[Ay i(n\Ăv </<2f0*JhLc}^QCpP/{"WVF=N||davI%fcZ &3`N_bIkxN5E2 ryx.:_49 #i6(lMDQ[$V⚴6ъ֕;Rf?g!ӳb[~E ~ (w6 v†yE1FFw6w!8FӏyVKHoޏz2l|Q8-U&~izKej1+żV ؒCpi\ ,iĊOx&a[[w_8TF!X0V%Z¾_wneDg>@_:^Ҩє2C6#5#^pka@z7:ZTT`.ӊa0s!J 8~M )RY;" IW ]8M'L4=0-C@A_|l.aVFD@,Iz|Y"+N︺_~o-xɿ;խFFybQ#LQ0a*$-l* Hv(wAgpW l qU)|NY薒OXtE٩]CT6{海 A| /e_^D@Z#h^jǵF͖":Jܙ}.A"N">r\g?b\u *Do-.L5(|Oƃr1Z5[YD՜+Sr}.(Z҄S OxB-3nV$Q"/5Z]j$TC3;I&Ed Iנ*F` _{y@ԝN#ϒk#7R*f]頩loO:!mr[ x+Av5ˏ@ 5(n- LQo[*f)cK}7Cz0*AVl|"K3rշkaf31#isi&*LEύURO+6ǡV(6 ڐ \ 2z v) J.2ޘQ.b.G!t=HG:XgI\e!]MS-N qjIsEcX)-w;_UO"/|3\4 !;Yo0Yܼb7κKyח;s5p "q'% Ai3PGs"sxaԇ{UtCjLr5P20j;X=g MFi\ JQP! X (M/^ո7Β6.l-H*$]6+n- >!o_eAv̆mۢ/jcH rKEfdhLUQA*F8D J&X<؝tUWb(V+nXG)Zٍ79!f$9If]/w}YOԕzTkÜYyY,ߋύT`'_]T~`˳Bͺ_>1>V7)D)g%nNUѧ-_ma8z&A!&lh + C_:趏S3J%9YQcR,{tMY7S/A A_%ώlsx=6VCZ6v1^Gin9AeG'ҿRy=tP7 h)Z͚X=JHȔ.P Kɘ1(gCg6u,ckSLC&:#(}N,(r>cQAt~|%VB]d0a>X?IGu3ym |f&H >W);U:A0PUV!P4qkhfIt2'-viUG}*`Id[KlFO](U'EE`S 'G3Эya{KI]p 3]y8Y]sWk&ܵ۠Er̘ Kl,;(JY:%%=@ꫤFyn"0&Æz$.P-.0Iz/t=VuWUf*S^~Α$ýe@m1zyE[`EDA=r.mà(Q>e2vO{26[&Y(Tpؽ毰C[Dtt Es KDkqʀW/%W=YTLx]K4fw;1/5S |&G&福E䫢3co@P%F!F Q4NTèwl{⽏ծ̱nE w_hC;Kd1WڏCI+ϰ0 LM{#)Phc^? ׀̮ٷ#.eLYu,t`Pu4ycVpOUS+{+{ WD-g ~E# sܜ>tF2Ch>Sp=wl8IpQVH"0 T92MK=ˌ4Ib]gvJt e}Ϩp?W5sOAe8ҘH(3~XVnUD4Y*byvܲݞA2v]L2\|wy~~j6IiPn!`j|2 q Tʨ,*.XhW]5Q?{)P?Zu@'Ԟl{)`Id`NjZaE03>xcm K/k@x=9j"UuxD);-ɨo3L'%Xn~ztH8]nPU/LO"(^J/nM& ()M8on% `k^bJH{c[LZeTC*y=8j%o7jg#b73ogdǨ0 8fYBB8,mܻM2Q&zR b@q>sj!e VsI3>yw< 3X -Xs 6\fPwgբ<`U l{Jj,9lfQ\Y6p0Prx软"_(c!0IZ8>aH˲؏~jzaWe6}S}Y(J~ϓ8A;+p\"Nvᬂy6C,[e6!ʔy¾xIW\$~?e+ϊC,a %9D+R? L͸eP^f.粼>T糕ہB!"RӀAb~ݖEk[|݁Sf]K>A 9XEEhPB8go{YG #I`êDqMP1fXObgZ. 9\"+i.Nilߗh;toSXEg¬1vC-nIVeӛ/t0^,ы]as4b$DVFV,(Bj5'm750B]EaI1j% M6ebA:2HjݫȤqx cTM*p_Nn}޾ zossuxSČpjXJVɋsD/pO#kx89W/ԙb:h(ˏ $u',Ó˘J7)k @L$n8; p !pCQIAFWma󬎚یJڀ+0$'h0z|}TϠ6~'IZ^xj6u>`q{ Z@DE/p:q;wLp 3 C0s(z{cdX|h %[[h>W,|?B!=~??e?2b#*-q9Mی\}V"ZN'HfwuBW[ct}W>-ƿư MɆn1B &c=)ԩ5+Akzo>CB%X9l5:&HI,R1L88D`Hi\N%Pr3fB62D(wGiO/H^a]]zuaK]+>%B_eUi\6DW|G&An~jYU=ikzjzzsCq@ "$굖6S>R}Mtspq TF8,0C!*jv⯄ha]a^1{B*d¯gh#}2`בD2:bibCk8 moKiGgnjn>@ߦm%fEm̈́2aGC`9\$y\yy^[ܶpZW.YISCs x ړ0`#yڧЪvL9t]'k86~QPazsIͺGEqg[ժUD2x-ȼ^㻜q, Z. ;Ker>m&"%cx#jx>^*4~ZԀk+Mf+FUxC 4X3 tHBGx1.]4*b֫h-90N[͡EQq 1'iFR[i: m/ݔ[mQHtC.qϠW3!!`a yE6]?ɶ ZtgT`3V|%Qބe@DbdaGŻTޔF5'% &Yk/)7*M\eb8qgF+MKP i D*{srsoHFSUJr*Sa㔙BPyYP&PT.wV\`HT}gGE6RTS1ޡk4.ѻ‘-80U Nw 6 Gjw Fm޷je"|Cxa{"Kg rB<+sjb+0YJ;X}UrT#-';В'7B|ε9!᣻*`J#+U zNH\RdhGn_#E2R zBV2Et)<:ןEQ&$Qh[}('+^ZEG ŧ޲diPKL7EmL%`UXbkM_ LJH>y[ bbͺB#6ɷ5F}t|XW(IY../`ڕ9kFjKW׌^Z0HU0R`g<3Mʳ.x(,|P;wmd] n:v}3/ 󺻻g /*IQ0g6cBTQ |ŒGT$0 ՇVnVgQ5hu$y&pt 7Sjh|0#v}7]Fqg'tݘI[6#k;|mƗ$\a2ԅ qp5 bbvξ3 $"':* 3 Vy >J5c U~^pSre{WHKx"{p'˧ƍ @D.,YE廩?ʘ1̺l yj2B'/"=q /%ēD\i;s^Jo*v#fVL8Fա 9芛5PFwHbtFZ3쿉9nێfQx,C:I~^HW3 Yp Jt$pdжGφU:Iwѵ: l=1etAdm ǷGwBTъbU9Tcƃ:PC\FC%Wb{x0{r GLX|(*^ Q'9tAI {`Z{'<(`{ ,F*H^GB4>x@drnhStP4{LH\S9D÷Ȋܴi9Oͩn,5땱4҇=u#FC-Ū bTD %69b'|rU!PΜrƩ5@u@uo {\ c(”d@K{GAYvޱtNՊn"SFPO탪GsH0i4?D2s"4㦲5sްN^JUf(kS+<ݑ W;ϡI;م|;yo^AmL3aKg\0d89&l@Ag\)cMˬdCC(̎Ѫ KM&I5X1Bd|Cs)BE-ټ%]ߧt/#1`J(O ʏ1zbx|ps~ d _>=r d kłT~B9xXH|WCNqOw`Do.^“z06Bu:]ob#+PI~FXZւ5KhСׯ{,s1O {@[#32x@+` sgvw@}3GY)n:SvdLe`,}Ċ))O|X"ԉISia %.k S1?Jq拘Ӷ×fi`A9ur0ټFz* ɉ Ȯs<Ð.)ZXg|ͯo X-x\0S?Y|2tmj!a 4 4v"V,;s)gmC~W ȦqkBU,`y''qU3gH/to- R(JuiQCNdߵ%H4#?܆,W;9Ѥ+' iFUO"S(ItLΖI\c^K9E<6+^3Z%d3\ ]gN}OUei{g"o{bprI '\6¯(+񈃬t uvT1,9;M*yEtpO'5̆)gycnA o0\O%أ~~lߕ#<,edCtɪֽ&y=9tK2ɽHF4(\y)^u#u撣\\>qwLߓy+]m>٠ikDv9>a;0}dfX!d>&2U3./}pm1L ͳoe Ҝv+fSmf:B_^FcR-$#[O_;UG'*do^#w+@!Ka(r!lT$涨;#/o~y@7|q3Sr;H--9:-efz0˘MuʨmcZj'M5;gO\z1dMZd=p,6t-٦Y͠$Gm01>>)>kDXqWk뛥]]'u!?)ĀFhkz7'WC4>3p:QzL%P  Wc#s]w诋:$xH5aWI'Ħ+C.m ]YMc+U}g&᪢}7V0o昼sǚn(}s7J,Dr6@_J"E˞]fMB/ -e >Hs4d*76S"6=.&䈜j;̂aēo@$R5dƔfS6:su _[ިFz癴e^)SĠ{-z {hV$gU+댧/~楏xbzeOLB48V`]wzs/+6Dld`8#Ț !ۭ9wx}"b#QEذ }iz&W g&&I3Rз2[{r2E˼v_EÚ(,4{(/|$//ճ<ؖF5`ͲGu;~GV.WqUkm(e{-ܤ9X8ɤ:uemC*n\I^ PP!U5.9\G+OT-ՙPk‚\H%Y WCg8W38A% pj;,Bdul+1i]䰦u7Kb{}9h픛6<ӏ́J+3XmaZ^l3R$>s2:`1er+cO6}@5ڌgRy(M@[i\K4}$wS=͖l$z%yŬ9X&ҟ5 W{@NYrIBǪ]r3h4o`ڂacxۯ|y]hS}EUZ\s_̅ Hs-) ZDr(R "!i:lE{8zS[q/> ԏ [9qd*5xG5@~an3`DݿEL?9\+ |V0i\$' !HCdխlHOBЕw|j؎IKWNv:Cf?g3BdXKUlpnVb`" 4B=*[4_BH_`׺mk.Ob)0=Ft f$l2Û@'Ev/g9ɬr=2n'<;4) ;{%F3n/?uD1PvÐg4qKeBBγ|>HzlꚈ^RHy^ϊ$ 2iWH$[Unj9яJD/ium<b'1}Lk9 VH_Xi.$t[c _=kPB7#,2.2}X?uVv^9Lɖya{*%"ub:/ +F,Zdj0Vfy ].t/;jeh%K_IL^/%}?5wd bsi%evCqGs @o_y:?m77Hzʘ4!+@S=g 𡄓_]~#UZ4s֔C$0h͝/GI.ܭ Sfd䐤O //^\6X! =fΕOX>~$)Jׯy= }6.j{%9&_X#kCR43TI/ 5\TP`Y+WED%7K( &P]V}Hެ,BA:ևlU\_/ҝWlJ޸87O̐)L {kǙW+r-'`)-Up=MB h]5{lLm]q4^N[ȼY0vY \eioEw{]Ɣq CtamICS#2SU^HR ),yoq|9fdƽH!-9˱:_m-濭8fISL2u 3&'媞/P`dydr8!"#6~XB<Αq}.񐚇as~CFc7ݛф~׃9Pry\Rmهf|\D_g|`CloyɩK y7zC8&WdbbDѕ yJF_bzm>?Ee !3$n;Es/)fӸ\L1ѿl"%jukN?+KOiQݾ.Fdr x6:,iunJ:j2,X8j_|fehB;l 'R^jOsMFYeYLrYyd49p1i@"~dнaaq񖭃|Vv=[C^M)x{]L [7TAS?I+aÏ"[clGן05Uxtj?vjS ŀMC"vA:Zds뎞!0 s!`c`hJv_7qwugǷh! K} gh}⛰yӨB֩ųʦ`_A9=ٔ$ :%3([C0Lf4;B- I\ qK.ӻO#QQلF70"pJP>Lζ> |6jBY/:XAb-OĿ$ ":Y`\ dl , N~C<4^u`( ـS<=ݔk逛!aPB F-yN#`4c}_g/LCd{1.qþ3QTx &Oy-]/@"O 4>p6l" (lPY5]FJ-7d^u X :ܳ8JEɹX='^2s` h/F>uz_NsvQ^U8b^ə[S7Z /-A*:{* 1by);dU{ P20j=']r77WxbOr&RQǸG,RFx.)`Fc\[gϗ/-{hHY8"G3~ T&o{s XBa -ǠoTUFhϘ \ n 2 ",eZ GA,ï:7ܬ (L0U㵦wy ?_dƧ. kSoiDj0Y}8:g8]G]G'' Xx[7H!;Dxs 6w2*֗/:޶td&fq{IYO[2Ψ;]ơbV6r%!֞90 -0HI0 =)3F k<An 0=%z_~^S<3hׅgvBFF,j6;9[4 A- #Rc⯓<* Y܁ɬXtoMstE%SHg G*ļЏ#*Ø߹_f0?&Q Uwឣd vܹNH3sJu+N_T̘B[81-_$kP q7ŰFs|nKl6.㬺 Tsi0_Z C52I2lH`T6ƓN`pa~eRI# H.5a'X^igH,4eKvpXʡ.뽵iſܬNngk&37~uҘմ䏵VS{Bbh7 NmZQL#xKN^Ly=|<i/iOvB.z !ݪdKG'aV9bvYKb$ 2315~)fJw8#BWUKN:ƍߢ,jaeDR4HsUw.5+@i'<|nG!EGTh3!'o`nBmZIH:#<:篂9FlNZUk٭qFzh=@("S.zݒh5+?_U&\=aVWk:8tfݍNd5Gak@&rvPnjYu:*BvHϓLG@Z׼~fg |mb@/4z 8\śxld 27aP8o3U<6iĻxT eM 'M@F0iMRz#)Dg2;9^kPc2 џ"_̂9%C~T8oTf-mq6з^o{]hᷭ4ҳyba{jXy Z.{h-jgrB!\2qiZbդt M7{2nJE6m*۰((P\2<[T[?b> KUg~ /2"!Oc GߺBB^0ycO,@Fi)s7]Pyd%yXۯS 4O=J,G0} ?9SO)SnhFʿPbMC ezB3o/nɾx6iOA E}CےnN0G./$nqVӓeWJ3RHNWܝSITOs^Vx2RL+R^F͘Ԃ\FsC :u{/8cR~sww__$Ozjl#DvBNDn:\:Wz h_` &4-5 ?`ߋVДsawS{Z*`=ZTԐ)D֝6Mcf?BHHѯJ8BWT>&إ  6GHlCz|Vژb36y1ZdmD 1c?7M:-eAHp,8N_jaRiwWs݂95FtyX=@|z8չ Kɘ%==˵d%_ܢk׶ٺv6v~^pzw"euHh6٩^n"HOyuc<FkwI}pa;V3VuoaS4T \;{}(/-lH&#+[-`7+p|>t c T>4A#*{,?\|''\$:%%$I^uVh,0\a^}~0V}]ݤ>[ ^}Y蜿^X-4/eW:TO?գEL`E%7_A~i NĕE-iyE`TZ 9 .u-gq#,qa2hfzw^?$>~/^Xpe ?'G-xgðOߦi 4}V.rn{燗䇦Bż! V=n ^0+OkQ: 5@HBzMPt< VH\d6Rjt~5MSZV"涾J}EZ !H.*0s{G=gn{%wP%'NepaR_DT@@P_z5:T?ն{B<ʛ .l$KLȦnó!NAA-}D=7*>\8^zMf 3L7nu莵vV5sȘ%̈ˁQߖ\}r=({n#~3iť_[0,Hys7q&jw7?单JETn,;I̻G7n!Egc}p$S+.K C\q*)@iӓj,thc$9ÃR5\0w}ޕ p. u>c]mK]/[I(Q) Dys.WctjIm<.  hXKbXGa$)m3H1l@`ht͏r"]QL=8,Y*̫9EEȈe(S xl+g1dTfۡ@$arϙYܘ<}4f/j'~/ }`&jI eY>uxE8=M$d۴L=Upgg<;>N kOo#8&3&_cF6:%b#0rJ"tzSdfhR 2Z:p+ڢ.pug"SO(0i <-7 ; Ȩ bEZu6nŧ.!$O5wGSow# $^*G@WSšԻuem$fL9ňF9$;gGpa CYbj/=~ќC+sF pLX݅k݋ZT}3 zԎ7LcSC/<6r)jO EƉ%궺6M@x_0OJ ".t)_s`~kI~`u?[ KCbnR-s&?m""vNWPWНB(pkGhl m!}*e xݏ1>E[9Uׇʏybh?f)v[8! Uc_c_[3/Cv]G Vrm*|cj܌:_z8,|#&Iy!p;PBɨ4UmBX:r"u}Q"Qi%v%8&U+A8^9 |g?K%s5clk|Ms}փpҀ{K6d`Y KƬ]=B`#]@ j K93 <:wx-\05{FL&z'\4fT,^^ǻnR~;(->d lOD  H`B`i%#,1k4 Nn2Os3j3I2Ug{5)zn>eiAmjokDh`YgÙlT78Sa'`?50 555W&ʉSe]2n s46I:϶\ GOr"6#ѯO!coRʥ9Ġz;v𘵌]ć~K vEɞ7A)r㔝KZkVT:Qc!~We٭ac:aQ [ޠHkc]?o5dp/tV9"Uy̔nWDV+Lz2auKءL?h5m,^"B/&h$Kg]lRXɪa|@6MhFuo\w(.c]w-!5f́R͞П^ iT]B >RL ,X?bNL0\w20$@Ӟ #ֶ"#x<"zen8LK7'GPTƭ0cZ-ƧK58dwS*(5'ʞ,a9a) pjtO6 $FGΕZ$&r2!d)QI|ʫLt} ('MJƐfnUS35?Jϣ*NhOߣ+0ܬfNqs44+hRw7a|as>§''d)#٩f_T9$rש!B" Q("ĀCRףqXW ٠!EK|&b(EvmعK_5[v]MNs(`mc XdW;Q/EoQy=Ƕ5~fċԮ)RðrHt(ТFc˞Jmya\PӏhId,<$ҥnOHZhSͳt&l*+[5 IX]:>+~'y ? Μ;Z{LNBPPEN@P4m+=8 ·kʰIۿ`tQ Z<˚vgM م&I |@Wwj鴷ɾvNm56k c;} Hal>m}oB+Ofh 2t}YqWaj5L`>ػ+WNZ6hGfyMky;J?&I_ 5x.F~8}t(FA~Ӌ%m@|#-v)]mY2<3wLi|Z:Mg3_ӝ4=f;TYq&!_Uݽp>S?@t S1+TlqZGg7Ÿՠ:J1Y ۳D,IG39@vASRջJlfJ cv˄gdpMZ_f#X- B5W,u-P0J`Kk1t+ukXCFY,&5 ^G:}ܱM19 ==([UpQ?k/[-p:Uh~TyΖ^k a#jz]C̱efEf`gyBwi\@t #7NJ73Ǩ?:{`h$ ƄSၪ$0HRaEpa(p t桛|3f+xys!ˑYdɲ'&Xg矰paKo5^<ŝ0&DW+O&l UO<[yJnDMY7,JǓAeaͷhZq +[4F>Yó-2Y4@.h9LuU4K:mHM Yךd1lx1i1]} SfoBm'Mi7_i._Q=]ԬMTΕ&hny_SbC3P>;YP`DM铜׬BNjOvē_iAGDWUjR*ɀYYpa&VhIL /B,DR.w(9 D_d6wsqIͪD#Ay~ om>=Ic|P]Y)s8y%AmTUY`ړfbLS>wP G$2mQi|5'\ō 1;wg$YO8qp,漑߱>SO:R4=#$idKQ쎗!삻}tD||r~S)bn5J KiNŻ\M I]ϻ6/IDliPdKpwlV;|u(js-1V,քB)!8a%7_NFm%QDdPCvIy"TZ:k<%jNJmf49D2 s&x$"[D- Lyr҃ܺ \KLs7U0_99R=QhcזvI6VFXF$ğڂJo8szA ()?B~P.yM*Hnxy{jwyޚW42U9-4 3<,TAm:ues/+!p y|T03A%X6?|ҽvt 1²ʼnVrƨ!zͼdM([#شBvmtк˪$ cޤmcHpdV*ǎCsR xvW(4f Om 6qV!Tq3e{Db q弍y]$4 ́$Ae$_1z܋/v4f|W Z͓;-+ UCzv|gڵe{u &&")7ul#A|Oύ#J)&avҏQl*aQvEdFKT񻢃_JĊ @Cج8g%UV&eunp#L-6s?6zP4%YlDO};w[LYD, ? mpeUߺ^l~{C Rj7eNbmмp&.Pp3.jZ' 3Fv9RŴ=_=O~̩WD#*h9'  I9`)M^ǚY{Qif4 3$AHH7f&eI Q%gS3oM`/Yb4y)}</SWj *ZږN ޘRjp){tO9.g/jĨ#sٟeIYft.':a* =^}7&Zsm򭙁4ȧfF&#0ҙ1ѳRniO[BAakrlfr4>ڑyD"u!yH`"]y7h1XO"d(ȠS+S4 ^,$a||wO #Ï3gKЙS5~sS5$W{ w`--G]!kqdTF$.v ކHf(ēA'C"׈ 9ΛKwN8#8 2Xpו@N AJhfxV.omؤ'J/e_WoW{Ry6 dSH.'Uc0 aꞡ}d);}JqF\WT=pyocl:RƢG[Z,ۓŀGvFƅ}Ft653ٮyl'`A*gjLy{i` +Z>CysĖ+u!2fW7psцsCuN=kȹ4L#9 jewwM2oܚ*I9&^;Fat+2i6cV, Z6A14SX݋'v Ķ%VwڴikLi%Gsk\  u.BH͎+hЪIna)\ɏEfakH_.3]C>s*;]__m*_ۿ?vMa'MK.=z© '"}Z/FK*&*ZJըUqR`8nUք]# 7B?UBT|u-Vٞsl_P8i8ɺrYu[[M>3Qd揙 ;L 04r]PEId٦/yR$/O=eIc u<*OPP"; kG{R$iss<,dYɂ4{q6wrK;]%F_ 4ܲ=2BD/$@KXq,XR@\nx`"p&܂=Ŋ4Uփ!5Q>mw;{QQ*Man-Z!%Z Yݭ>f_iz.TFe絛K2]FxЖ |AYH!׎87YY+{pњ!0}"&Yi k;ݘ$gz`$` h`NKZk*DNT`l 5fW r "̛4T8?e*:-3z8 ǩȨihw4qӂl&.$".y}&!̍뢜H3g8cR 뻚9E*:#ᧇjWF?֧!6P~ d }>ڛ5>P+O͋9H61ޑ8) Xk]5a|lGt55Ɩ_"/RL8=1xPmL?iW&Sr3miMXfc4a^*T!"6Ѐ ZCփ,}$ke3ɟ5uɲ' !!A~$7W(6֚Ʈ߫E~gI܉9iIS+zWc&܁:80\ާ04N9  sLQzTMG7%UQEHK5IN>K\=*۽xI#IOtHtҪy~3c { ᷿k(S g[%@{ R`Nܨzce_8BeO&5/w(0Fapkl.zR(8е?ZpaY\J\džݺܟ6 ;Jg7ixɕ$`;Eä[ _-.|gy{ɖj&dŸW_s=Rq˳dK(J,0l!(oH֥Ԇt03\z;ޒ{{Yi%ы"Cx5|*rF@ʹ9{eߗ\x0fң%Cr::tqKL@H!##*>0tZG~ 9&;_+A֪TpR@ٶz+ϏK@uzV. '+X {I, 36BvCUM+טt\DGKu%ǘ^THy戁" 3KM  ZyxeJ| nyI;ɥۦ4;=A{lq<;.(J7%vc˱NXLtTTE4xvF@g&*Il(r~}Inž2|U7Jb-zYGd،b! ',air%k"$N*Z8VTc[|LP)i>3K,|#u(h83} zNx~Lșr[ϱѧnk fsZ }٤M—Z@N(#3}8 @BMDݒg+K]IzCu|~mw亸*-I2 ȉ,-kLs 7 Mn)ʋVI6gOKo@ *fpmd{ -C/&K||E#'eJp-OفO$WRPށ+B ]lGXǩ0cȈ^ |xS7*|$6#NdꓣabLJpuZG[k%Dѓj-0Pg!du{79EʭtF=]mV%5)p1}um5sq(P--#lc=Zr c"[XYR[CI;n'E1Irj:3za>\_> De/x? T}L.g!j(Q4f`Km %1wpīe-G"1;@YyC"h^D?ϺH<PNzݦ"' _-Z}WuV?QSܼ վ ~LAs8$NXH`U ' r>صГoMdpL/>5_ 8w awj<\@M J{Aśq{-K\]V?,zY;T^xnM(,ko %hǢQP)iX Uw)f!Kcvaer]܌P, י=B3OjJNP+ycԁ#\N  \*LQ!5O)'}$D 0At%m4:]%ezkxԂ<"JKQ͇o& 9MPvrz=_|bT}|Y0Z v-BM|<˭0ð3KW]ah}ᗻk\[!tA SgME뼚Pc' !sx?UqvɕܔN|'\)`ALT46@ t{J8Ҕm.sFP)C|ֲ5 t-Mn$yQ:GGNA_:9rKA!mcBH0/ +S򳤂! 1 t7Q)e䁄7*pU=BF*fg Y+6GQ=[IB<{NKRɶrt 紝c)ϊ/HH8޿#u%36 h(݊Zt&*w\RJwҍTQZ6F:7)zATpmAsyi@JByXKYNGgB}"w;xԾ@qFAPj[O!3?FO( rTY[~E?.lӜ Ja 7d1Gts"x<)٥E6~ʼna{-}tP5>< v +qJOAbI.l׾.o\:Q-f0Et9J3xߎ)-c.X#&L%FX?Dզq"W/Ƹ- <D |&:db"9HR`em傣-9&^JP":zeΈæ@YYBk0#bS?+`nDjq'ˤoy'-^6pվЕ WJE[fA:"` ϡ[b |.?w¸7>KJSnN u\:XE]Hgź| z/&q^lhiiKG4mUHUH qɄzD6,:3:a."4[h =+;c?n zϽ<*DlpQ]7ca҉obȫ1PKƃy<fzgvK,8!~RG/1tE1M`Oh"юuB0zUZ';<1^|/?'̤A5XzT\$ŠDɩĝsP]?Ğoey* N jS՚|,b=4qb1X  A+mpSǠ̺tB0 ۾Lvgv< 5X6܆n{3{ JیmgXORW oGՋ W/`ǂ.Wvq"4 mt-HzKe)8ou$lN6CbfѪ`mZ3I8YWS$ K=6CfC>5/ߨ=|9&K04|o<j12ul['7\ED"J{2ҨhM N|'0ՌSXd˷@%_`!cD-|U6*9ܶ{t%-iq;O*կtZ ?Hx g !IALѐr $v9{(<qr~knlwd y;HfwB=>ys: xJ'hOGkn;P;g f04F}<+L- G["oCGNSQV+4,1=)=yL:L؀{ÿ+1B/߈Cή> lOcBtO+g5ඏ^Ns، Nyi}Yʰ9ƁJV1'1D1V)hLgc:M]&uq6`(<U䘢{sW?xFs#} ?W>}!C ,ʔtQX7._|d+xb\hߗ`嚟"͐C0JwctxVݿVDX[1Y8o6ʎC37H_k I4)5?: $y/EiݢD+{I\*w`D @r γz ܔ /S=?F1'@UT:&#LYwh78 rڢXa͎=M@jԾsoFd/ŀnKX?jMypA}VĂ딑:%Q$Ovtkym%Nfˡb qo|i)T;~4w`E7t,c=!ׇ8bҭָ$l37=E k\\xSln j7ڊvʛNٹf/J:Eveu^2k5+:_S #)6fPKYgr* OEv >z3x {A89ڙL|dN2ՕR3!x32V2wܾnzI&|4{"9s@|{mtwܠ`MyŊLW{r6).AԗjقݩW-x 1Mdwc䎶m`DygdF<6]g~\ۡxNg]سd݄z4Ñc"Q|Jcz8;6ؘ>vd1|Kr M/0 SdUR9#U9 U}_ H{McJ*:3M 8ָ6Х esܲc!PB~<zCe)Bq;ZO/lqCm7|/>~0~B N.Cͷ!|~Re;.͙穆ĚPCd^]U꯭_NJ7u];S)l"oε;=-0Xszzv8a!^nCs iNi֔'>#fdo՚lA+.{؈dmֵNQyVfdF!Öɺ#*vPeazoZқm~ich8)GP Ή8*n:rQԜw l 2jf ϸgQ1{S2ܱK)2E'#SJd9 0_SZ[u77UspFuU·e)6_02 .dVV,.zgqgI:.M?f_Ĺؿ$ o%@9gvx`:? 0DbIwpJE>;_R@B#PhRChwRkz&H_0kau)McI\\l;TS^{F=) 80 #۪Xs"/J0[s]N"#dй |KHW#tz%20gf6KHA}FvFO:h";=Lùkڻ%VzrPу?>"ڭ.c̤0ljo(|=xnfԕ"W|Qc~a.TI%)lmԂ9(=RljQ tY5{({qSn*xqQ~WY4Z9̓Q8%PPF<4 M>vr0>lOsɽV̶xD =(pQ!w$@[%\ވwv*<GI boI F]cC?Q5oˀJjߪ鎠qۚ=O WL]|l{$,'^h{d~0'I749~QWMOwM%rxd6HִVaef-~C}ʊS,.jh zn:mvV18Ǝ TgM\,@ke<}Wf,9<$aWN~ʠ*dx;BX*4nxXl/+U]oZDM] ~׺Lt684H!ރo93kq#0Ϯ } %]Շ ݍo=i_Ib631 k&M%Z1 t>ԡt0µۿVqEe:\<2m,/Y.! 1g%JrX?NJԌkL閾0uTą7 gaT K!>T Dk02I~<1Rn`=kH{!{CFGdzܺ8W:6gm3 rWf']0FoJ*vmỳZ3WYkǐ 67lS:9ЎæhVTU$V.N^d\ \e"-:j&FOP<7;0ҟWpUxk4#e?GG#E2s !컠/S\_AER'r0i`in36wF>1Zn7h.X(9M |HU踽&iKiL{9uIBiG,}^wA&|J~7qR$?" >o/HAtIG- U-[I)`XLY)Fero,O*OZʑkf=`ËxEw$-!WgqMk !5Hsu*Ys8yLn4/iSČ+k(d (TA۵H~5Tv("x<*0]*qzevv[hs @i\2W[UF݇4$](#AE _u|`A uv5mN(Lej}ׂ"#)D=Q ݁t:<,Zf*cA* ^yYX ÏNvP^ߗuUřL7,cTyK?h|I tت> -j=Ykp8u<V>aGLP^?|kϰ_̾D(ʤ[ٻBu{,EN_ ,ԃT}@h.;Nqh2Mߏ$-xmxeiNC5ٳZWIC #l럊-|_939hWua*mECLb@)-FnlqM^yPBY4i0-r2w| J]x{9_ L Ņt%ĝIGi8ABQKП?zCA0FBl&k[w}'Bbg 3 zu}!O:+n endstream endobj 22 0 obj 113085 endobj 23 0 obj <> endobj 24 0 obj <> stream x]n8ཟBvQXO HYi@#WGt>R4uwϷ?oytnW/^}cZNy:Շo|v/yUjNi%]O| _sՖ㆔_cs^mzWmasM]ǧôڶcsS1疹EYY٘ w#rbNsmܳGn@?@?@?@?~_~_~_~_~_~_~_~_W~_W~_W~_W~_W~_W~_W~_W~_ᷚs~7~7~7~R~7~7~7~9w~w~w~w~w~w~w~tF8#Hg3ٶ l+ڲr Y,h6;сDt8. Pi|Fv +KdDTguNm-^F ̸>-AāNą,ua`ʼnALt&8eM<#art˄F{ǁN tޮLvqpvvΙK2=n=azf1OOg$@;<) bwW<}ynS~y.XG) 3,ud@ژ4͛rPvc1Kzp endstream endobj 25 0 obj <> endobj 26 0 obj << /F1 20 0 R /F2 25 0 R /F3 15 0 R >> endobj 27 0 obj <> endobj 1 0 obj <>/Contents 2 0 R>> endobj 4 0 obj <>/Contents 5 0 R>> endobj 7 0 obj <>/Contents 8 0 R>> endobj 28 0 obj <> endobj 29 0 obj < /Dest[1 0 R/XYZ 56.7 773.3 0]/Parent 28 0 R>> endobj 30 0 obj < /Dest[1 0 R/XYZ 56.7 699.7 0]/Parent 29 0 R/Next 31 0 R>> endobj 31 0 obj < /Dest[1 0 R/XYZ 56.7 217.3 0]/Parent 29 0 R/Prev 30 0 R/Next 32 0 R>> endobj 32 0 obj < /Dest[4 0 R/XYZ 56.7 460.3 0]/Parent 29 0 R/Prev 31 0 R/Next 33 0 R>> endobj 33 0 obj < /Dest[7 0 R/XYZ 56.7 738.4 0]/Parent 29 0 R/Prev 32 0 R/Next 34 0 R>> endobj 34 0 obj < /Dest[7 0 R/XYZ 56.7 612.4 0]/Parent 29 0 R/Prev 33 0 R/Next 35 0 R>> endobj 35 0 obj < /Dest[7 0 R/XYZ 56.7 451.4 0]/Parent 29 0 R/Prev 34 0 R/Next 36 0 R>> endobj 36 0 obj < /Dest[7 0 R/XYZ 56.7 339.8 0]/Parent 29 0 R/Prev 35 0 R/Next 37 0 R>> endobj 37 0 obj < /Dest[7 0 R/XYZ 56.7 178.9 0]/Parent 29 0 R/Prev 36 0 R>> endobj 10 0 obj <> endobj 38 0 obj <> endobj 39 0 obj < /Producer /CreationDate(D:20070808215617+02'00')>> endobj xref 0 40 0000000000 65535 f 0000213832 00000 n 0000000019 00000 n 0000005596 00000 n 0000213976 00000 n 0000005617 00000 n 0000011445 00000 n 0000214120 00000 n 0000011466 00000 n 0000016089 00000 n 0000215760 00000 n 0000016110 00000 n 0000022539 00000 n 0000022561 00000 n 0000022755 00000 n 0000023048 00000 n 0000023209 00000 n 0000096279 00000 n 0000096302 00000 n 0000096490 00000 n 0000097435 00000 n 0000098399 00000 n 0000211597 00000 n 0000211621 00000 n 0000211812 00000 n 0000212757 00000 n 0000213722 00000 n 0000213778 00000 n 0000214264 00000 n 0000214320 00000 n 0000214584 00000 n 0000214706 00000 n 0000214856 00000 n 0000215070 00000 n 0000215188 00000 n 0000215326 00000 n 0000215480 00000 n 0000215630 00000 n 0000215872 00000 n 0000215938 00000 n trailer < ] >> startxref 216125 %%EOF speedcrunch-0.10.1/doc/man.docbook0000644000175000001440000000355611015364561016153 0ustar helderusers Jean-Remy Falleri jr.falleri@laposte.net 2005 Jean-Remy Falleri 2005-05-12 speedcrunch 1 SpeedCrunch A speed calculator in QT. speedcrunch DESCRIPTION SpeedCrunch is a scientific calculator written in QT. SpeedCrunch is a high precision calculator, is optimized to be used with keyboard support variables, functions, history, dynamic result displaying and syntax highlighting. COPYRIGHT This manual page was written by Jean-Remy Falleri jr.falleri@laposte.net for the Debian system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation. On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL. speedcrunch-0.10.1/doc/logic-unit.pdf0000644000175000001440000142530311015364561016602 0ustar helderusers%PDF-1.4 %äüöß 2 0 obj <> stream x\ɮ$;WԚ%=%]I-  $x!̺'N;ۿݶs 9|G/?_?[ #ܾX^߿偭1!J|Y~~x/wGG;}#Y,a<q: nOW+^:+i&8;K|#YK".:YrE|6m8=_?=NJl%-ϺK-ə#o(cm <'_T7Cئ>xyvo!Ym[P8R(Wt1.lwX 3535'DaGI`驲gr1O9Uu˰aRlrx-y 0X\Y#~H$R[O&ޅD6c1`7OҿrЧܢ(h,^ ﶕ_| U4d, ]DÖ^1CH+Jʧ"e;HDrcA4}RDR>U1*>N&Ohx!}<gII-(T}h0F?R5:4Sɡ;}Jvf2@*hb*b[X\QluY"+ZK7t2WAIf*bP4Zbo8՟dC2@Iqx-:B8q\6㙹ui8vʓ#C?iMS'HU=hpK06i,,5$Dћ9 C֡0ip'^E7k&Ǯ&W:^o'HyawV^HýIa]+Dqm@@c@jR~aNJ{B zF$L<@)8m㺱O"|?/i}=`들nK#bIfg]C֝JYX/sO2kafVmu72\#'Rx¼^@A?;\)Nne/Dz^dېC`x` q4 !Or)u"8 $S7|'g Z >WZXѦ-Q36c`a* },EJ$ "xM\K !0ѝˉ 4ډ@)Kpijqeދ;ͻ} !R^5[7aqs "e͔j!Pۈ8ֻ˩wg*f :( &]!`0-]%|0˽jtRoe1YdOxeuޘ>ƬS|^V?SD-A[Mc p'Pflņl,_ͧA(ω PGm<>xUkʓ|Z8g̓g$/MٶK%,&kNŲM}ʿJ#D~e !:TpT4RƬ1,k>"6γp.+z=hDfZ" l%K3y!drY{Q%6ZjٹBCBcF4 O+Ge2aXr5:kT{>r™}afs 0& n^ ʚlTz#i$yn`!ޚ*r`ޅyX+ɌV?4G`a,u4EOd(ua+CċNٽQF1ry+6W˃tf8Xy* XyxU҂b(N D Ryנ>䘳n偩s#,)4Ъ#l |燼r7&ϸ mM>De9W )=L"IZ̺nUHc^Q>??S!Z_钘Nbd&ҍ tb~&-!J}r뫑-fDyyo!8 ,OzяE=qmfHm<lkdFӣ-5ʿ{}C{NϱX-b^ ePNVXWDUF,HnN$9!fz<fls+;(5l?F>Ms?|vi(-ήކ;m_Խ)biwOM/z{To|s,/xOɆ..ŀc#|RPOrLEeש N唣V4Ѥx97gD. MձFsJ#PO٠oXg1,0q<эFUW* p|>[:i"rsm~SFlXui|okUk/[= endstream endobj 3 0 obj 5184 endobj 5 0 obj <> stream x\Ɏ+C9'^ x.}s-dfzd`"2X_,vݶv7vo_o緿{-~K_n|7S/Es nͦ/~9 O>֖+zh+\ Gp/}lc{8G|~橭N}$J^},SPj䃏 n9r|Y͕+oQxGo$؂|LI6U?gV/K\,~wuEDKG)}oi5"GU>/~d3g4 x|%: {Y >& 9EX xi&alcL"\8xWy fWB>P_:Em)69ᚭjPM9\Fb6b=QǦEUӦ:6v>k aNW Жƺ1qz@]Y9FEP(^UFTIw3kV[1^` ۩"fHc0}~OOLH9@O((ϹwGbȺ: oa 46a6#N׈ϡ%CRf0?Z-ļ_0Ơ-ct\2nn8+}Da5Y+|@|3 4)]A`&pl=Ⱦt`\ľ 4zr]&gnq.fST hVo3'e4Ղ]!WmvsdT4ܬ[s%א'rnRKf1tg,:>@ܙdŵԡXPBvC g B/4 U a- RI,*3 ^ʕ0B?-eoyf(QY:کn(Ui[x+{G@܊h+GIRIZLSTE2 B&Rn{R. Cۘgv+Mg^ayڤCtcbnPOt^jm^G&٫l^~! ,|Cj'F1ß7CEa2J[}T3YZ; !&y%Qh1fXղ,;|G4o Qά(j (`hŝ9u=Q<6\}-km`~({{ͺ KوһeL’+֛9dɊ6Mt؃4cDCEA¹QXl I8gExde%W$Z(F7n,SsIc;< 'e xbx*"FRnM 19mL$2ܠ߳&;|#J?mXxsW8kgYۑ <F)ΦX-Ls%h-:Pmva#j_˜& 8"ihnµ-eLOhʙ]9-ʈڵ oy"B {Zڸdabr zb"ǚWbQ%} L}F:QvkHK}zv톉~:(G7GxbC k-oYO&@?kA^߽Wgڡ+--)d\i5 `ɋ>lLQʐU W1 ;3I ( h]YY :–kڷkW7G '~qkWNY>(-_+e6S ev!"<Ղ<1#=t5T&Yuag`1b dtx1Rي9wWdP2O-.l'aNڔpT/-|n坈:s!R] oY>&m; endstream endobj 6 0 obj 3558 endobj 8 0 obj <> stream x\Ɋ$WYR*@~@ \^ydduH3 c͞m,r˿.ey37wYy.?\?/![|w1|ǗGX͟|~]kԋ&kZЇDg}he28UvX?a_<=`z1dsYdh%>=ZGK&,?olHDxko<:ɳEޒۺC;V%S\0.,t-Ki,yqyLP7Ҳ1.k)^z>U`+B88HoitUf' SF9oф(oS_  ֵu@8]̷.6֎8~ x4. ƨc_7#GN9#0Ft+ڙY{?+f-FBDGNϬxLF [nߠs`L<`QWFʺIG/]5m\MQм{e-m oWk?(HG-нIi4GZ >{lN$w(mJPU/ X>w] ` ̶X8x +/$붜>$=0[Lj9b1t%2/kILϲSE+>M03K(;9Ȑ 6Kq l O }Npn8n<.஛TÃ%pWV%XLtm!%ZۧwWA|2zO_BbKD]84" 1Q6(cv !']Ho/ zMCАu-lͻ-2ށ/vRBr! ybU/%f #B$PEaM S$/FS]2cn^)8FK{KUYCWǛI=[s<ZtkӜU"bU, [׸qE23HUʔÌsb( -BJ$z¸5~:?(40Β*NJQxUnɐd]-]/ fx Hwh([A3ܻbf?>m {EUu0@F\5O17 D'-mxց+1*^>\1"t{P!;jXBگ`T-jľ"G7sI624n{D|E3EVbՇMy\e )Q\UG)~oyJ4rhD!UEjL  cu*xyJn0mohbtmH'y!r16#@ :(-y2 #≯7v/K!Tha ' 7Ml I &8#+o^ϲQF[=j{1Lf6_CuFA&W19P3ͫ/G1b[O8j c.O:;'Mv@ؐCr Cι9, :R;k<(vZtdN| 5+huV/&)2Asłrdmð3u;6@CQQʂmK.ǰӻv.<3XF*9S1GxbŁqLgJy\qEgJrWvHjB!2u&"׋^8kQpHea-[$._ zwu$IR9nL?qt7t吠Cy٠+B^ccP[{׍#7͒< }L03? w|UC>R)YAČb}ޚir$#=O&H%KcQ_'?qiUc +8рt[8wc!(IR>T%$. .P om[_klVƜUᏕ>CkR6 kFfV~Rnao/'Ꮽxx'؏NQ^VAB !0LB Ew %fG1J֣S'ŊUwHI~d@|Lz :]'v̓nJ.NN:%[[U> stream x\ɎWهU2Sx|0$c)gcИ(/"^,o-mms[_tw >mnmro/_Yz5/6xDxo.Q)ϚcHEwlfqf>Y` IpkɎxOMyڦ-fq >x$R r=&$a-,D^͒o_$g;;yx–}ӂ_i|#"&X<3vٺuלn u,“lPIyM+{҂ Ske92ɦSt1[F8M`0$fZZXo(yYg+9`\[w-lQQtzʇ=[V p(A7 ç ܪ ;ga=8rQЧ,+~.i|Ecޜg7 N|ϾEa,-;n-il24|=ۉI <ɏ^Y$:_gI#4ܧV\#4354zբk5S <,Dd : Uk;(vjuQFQm M,Ip(Q=!}nB).+9R CVs ov UԶQƾ3)nS,k "DK*EOQ*.#N9hwW}bGIR>:ٿ).'TwYjWZईYS!p 7l }z$Ht+εJXE/5 * Wַ/ {u%9`>'۰c#:aIσ0^ݍj8.m ,B3WtVpBFlK̭5+d(uxмO{rš:xل-i3qB} U`pu[-{VyizNĮYA ,0_*#Ir+K_ vpԞR , 6neWx-:רy^<`Jf;ӡ vbt!)P ^jcJՊ6{IpĐ@*E|Q Ty3עdqJ3m$#TXKT)'&锇m%QQjp+)\K}&_Ui+*qV !Wp)jIcNQAJ >'T1%2,cxxd[jN?7kZ!D#2C<#mUx4 ؟KqLZoc[pYZ2ҶZB*SWk0ihdGVSq/K3>,Sx-nȥke=xgI-8Ȑ'Mֵ{,4=ꌥYW,+$!_C&+;SA:WGa=Q+=aNvbYn(bBu1@QIq0xŹk[_/ kDU)kê]4B(ped&T3t`3knJmPv]A%jiOMʽ'8˫k%*NZ+|Io,PE]<5BTꞑ_[jDdd:=xUQw\kOʢ%qY|@Ww®b*ԅ^X?+o:%RbMy-mvoͶmދ=]O95hke+8z[]UN3F"pHizi,nI\TӁUl 6]4cUTﭢNeMD{.{+&L6< %6}m(z*TwS +y`:#>P<ꩆvױ&=}..=< _Qi83\`&4:5 剁/JqfI]饔faG%usZ!-9$? #`oQT30Tl@r娵n ;nDݹ0LS;Ŧf]NERmj1]&,To}tŀy6=^VF&2'l7~^^05>vi7֚=Wt=A| zrX+8a|mk|Y26i(FI18RaĎi5I)#&~p̞ Kz$wlu?2Cەk6ꫬn:@ʹRMAņZuSZj:p>);NH8L\ҩpKm\& / F/)xIumOf}v BxtSTB:CqWm=~x}6#9i͙9g}m٩.1U͉lȼ,P-ac5%;1@6Aʻ9缅WhrzguL T46~(WGz<\\m5=;wFy;Nw:gD≯3h }1'a ζ?A3cĩʹkgCl\@kCs@ۆ/y܈' iKwBI*Y8{YA_ eU +Sgh8|wixS-֒` ۥ9p\b[8ۭJܰ ~ KJr8~7ԭ|OR;G3jN,&e18qnᩚ9e9%pvl/me'F%o_d+ltrQxGwD'5컌*Fm\G.l晿z,Ir͛Y8 ]JS j򉆔 *&?Pr^ N&VA"(4}JΠ nZi6_*a}qhjЄЪ8_\r_8,AA!ߊ ?bo'hK\s4 x!:?5SyS `TrK_OLbñ7MG> stream x}Tn0 ;%t蝽8 ?@ɒߏh;^ {z|bpӛ .谠On˽|sYL?osn .ֿ)A n53H]hș -8кdr^JAOV JcOa$L !%X[Ql6=?$[\RHGxzWΌU5Qc i^T<@dLQRqvG\;LiDDnu5/r#@ZЉt+70RBOg+`gy+Bo8ߛ,ÐSnݐFY;QEDDNDhHYԸ 9W =˚DLeƱrXef*>2)J(#3(|AK ~`\>+TN9muT~~GA !i_C'}͂;~r5a& endstream endobj 15 0 obj 504 endobj 17 0 obj <> stream xSKkQI >6aUۅ1"t!BZh0"d:yf:BP|AzjkqۿsTw> endobj 20 0 obj <> stream x]Ak0s=,Q7eC? & I1k[!Mt=u~`{L0zrKX" 8yRetD%Z7] Nm/_c)Arϳ/fFKix"Buyb%lhBUE($;a%YJzht~ڀ]I=WCܩm endstream endobj 21 0 obj <> endobj 22 0 obj <> stream xstd_5bv1*Iul6ӱmum۶}FQ֚gqFQ*1ٙ%lYX '5c[yFQ;k3_ Rhboo \MN|w u5 h@v|s;č櫹lV^>V>V fficGGЉRda[-==#G@'-E]v [[LNc33?@+$doo ,feņ@ ĖswBKgg{>f4'dd tfI)ak&fgO7N`w [m=-(#!,N6^t7dYm|N@9pvtxB`eL&@ -V0vvtYj`_w]`fgk6@¢v/FVnv#;__rxy>DBA SؚA*]M ۢ3*eH=N^{aˮ?Lmա9tQ'ۀ=+S M `q6;c 'I;Lljπd Ts+`d S+[_1Y dkPsncG 8:_ks@w)P0歩uɷW6j:0'z,{i]0h<ծ|&kUΦ܌ې2Zq~ܨ>r3b&nhiNjv`Z~EiȕXA'p m$p^wZ&DŻ Dw_=qs@GuvbDOjQj_O/1epVlsՠ3_Dlv|5iG9YY&ylsϗ1QhvXŦxS?]th emWST :?&q:c?  {l,b h&Q扉ĥSxEDY=5Iw >IܽB儏0gh~ E」r籧Cc>-#!_rzZUES0z=~q#˨vL/c8e:J}os|~RnbQi;硕TTװpcTX,T.웝}bf~C.GCk;;wjCEpM95mEn=~]L2lSZAG7D"5`>I ˎ۴"@ܑ:@x4ni6><m [%p<L=Uꪑ_!clPً Ԓ@t6E`k’}I&3cJD4e2uMأ㼅XhHw6ԷLHrrOtr MdǗ|4!Ofh̋^2t3ڌqKQ+aO8!z13ed @Uߢ׾/hr3BgSN6GLwUH%G-;L5aAapJycoFZqo 8ie0h>b{ ic⍾P{,^0:!lLXBζCM;Cs1cWLo<8WfP&Љ`/v%#z#D /}IXE-mLb.`RrS`e<0-N֘|GqM߳v\;NQBkt/⠐x'ty5]]n/5AkB^sb k&lHr=OمH@O!SgE\vJ).V1NJWv$~xK K?)qgU@ʜS;MSA1eǛb e @_lQ,qD$)p.rFm*ѕ6Y3Y*tj aFK̢\u`fuWW]l3 =G*P7*u_ ZHF8' {S cK2[-*J; K>ae":V%ǨB-kxv .RƥY7E45iޛ`9>qX 7 k<ҙw&5ٲcIXnXWγU08 <'$X2ށ z0ɋeWk[9.Z\&BlI* d) .RvҮ젍hQ߇KI`%&!HxwpŵrɞgMtG>}+TS -D/VlGk7:A_c!t=Epȷv"& yH4d-ml%'Cw@>kOBJHCKl^ p Zxp^#)Rvb=A-Rߨ/XI2{rVn[y<'{b2lÝCMt)Z+(2Q-V@L}xm`~7|ZYѨ >Y䝷- rx!8SY l ; $=c%'4{PjΨ1]&lB-n8)m76G7$r=I?}'`fj ,sRX6n: {n[|"+=uD\ugZ=9{x*(/5_}b&~nyr\t-L(tޏ'oMꉞǬhe0x,yI Wl?r8E#}˨qO̫Ͷoql ":vᦺ}'\ep{u%;U0^ 71߬2>]m:Q\.L5~GwO#ԳiRdF49Thd؝o51{XBFBPl骉)!5 arMPuA$ȢӟRsГm%>Y#ێaSNxYLyKmI*s0s`ߓsmqd&]پ)m͡oN 0jPqB%POSyNυf/[( !qKudn_O1֗~F^@KM󊐦5f"`/38`C$s„T Y.K'ءg!Twi ^`J)D% 4<[1Z1@`9G#NH vXWj?tMd PK peqZ`,mbȡ96иyvcCnI)ar\Aظ\Gqk=G,[3(hhݤ rXܢVX ά_ B-(=ؒuf_1WI,p~A3F@T-Di3Q۴RIt[rZF53W550r8!TGt| ?ld:)Y\Xya6bOJ'Q))7c܌/-Խ#λjZ^Pi)\mO5&[?4,NWt۰ppCǯ&C}o\|v(,HVUxeXj,鏘n ;D,j>x ZGeK_%|Iʫ~O-X]x@%Ugz&SÕ3BΝwÛSZ[`ÕgE?v rےp=7 3ba@h4ǎ{עÍZT{Wpy A]aK>q |^Q.fωHnbas֜ bGT{IZᐶ1F F Tg.HiNHgWO]Gsg]fŴ=qc&0͐Կlj5dKZQ' 39BE4x􏓲xI"SAKt߇hՇ`ٝ86[Ab5[\j^6 d1KS:-&{dYLuLǭ/6ɩV%*JȤ{܅9ȰQ_?rJw:*} U/ι>UX97\yNB%عlv!o/Ί9=),tF|HWVwrk$dŅӉ 2&AsID {\&u#q T˱{{ߧe !L#^[CkYr,GU YP?}ru12+nG e00['=ou [7|2:N (eS9CZr6atg†@ƲkN'l$@ؐ(DZƱCCp؀ssΓMr~Wi7 w_NJ@sqG~=ΤFہ 'Ff:? L30Q{X.:EuWb+/'B9Po!˯c6*LGCP(JJ&)0ʚ=9P-BJK2Rrhqݗp RY ]4k@d +ne ktK|,Mm@DtPR#_0~aʸ Px1Οcؕ%1=+,G#^̹MFzsw*\oQL11;&} rx"(@ʳeD =7䘠tv_Rz4f,Xa->xix>56AΗ%tm$U֏acَm"kJT3շ k?\.k"Rd̩v"˖(v4՛9;+Lv6 LOe(ܱDz>B'Vj-O(o wܚ Fȿ:&%̎RCxi{',QB Ͱ7zjyA_oH~C庞OHڬ~eURxCj|~;Ӂr05JXiICY@}C{epZ+K}z`]0#FMyE~z,x3O69}`>#_ޣmB51"]?jd*j Rj' oia{]@aCQoWP1Im1KtԾ [Rzu(R,:8i.HdHĵE=s{Ob> nPw澂ֽv؂1/k7g%2XZN1r% "B,b)9GyOG 'ʝQBcQ_8mG' o8 vF1:K4zUMqB;y )ǽf-4BQb¹;˭)hnsx+4<~7UC*:UwxŒc+H?]z񜞾|տb_9]hТp\Ɛ@!gFxfI}W# $KNu̡3/2JIҹ̚gz V|>hm[u[ IE%?7N1. Zae;AbTJBXm^??gC `-:)^xóDtgzdV뵠(P H$.l "%N"=uy#ܮ iPٚJ?ܪ$UP;\|$G|_3F4+zr'jYu$rG=?2UhF_~.x 0A5I1P͘Ec:Ǟ}TL0i_n5Uڤ܆k.>O/2U=N gZ%}?^Ʊ <7~DZlC'SJKѯz p^]/%C`b`akQ-6X|Qu4)M QH]1:@/l6,vI%r{%X)-*pB75 :Bl yOc]-hkv_BK|m89Ӿjuzj8fa BR :8>ی:H7jw] !p$)lk抅Lƒ2uUv^^*gTMKz b*z!&f G|+J?`W.V(%a#^C6ѳ 1q!5\mL_fVBW `/P6\ S@g-pnd;#"z!hqlCRG)?۶M%εakӐTw /V}D7dk}0TNcюbe^pC/,i)FCQhW:.?M܂/B1ll9[YK`]|ȲMH(e 7Rt%;acy9&|#d6pKb0+: @APG$b,Q7u=2l?$a>^\Vz*L+KD̶x,Hq.;ޒѲ+Egg\b|,pԠ/SܐdN0<+V |ˡ ? L?MNllQIK4Uhj%0wj<8jc sVoHMg,%LU E-]#ٯqdxMCZL=9c.xuNHpdzgBə@cR1Jj6cX/O|z>j,n%@skkxghRC-RatʗLaE{k!=/|8^2Y oQ\2&TNRB] A0Ʋ*^dgzf# zO N@ 0IP0_[YLt+(g$ | EfȨt(*GF"'RJ\;K#wBY8ㅔѼxW8Bq5XSQ9@SDөAG5(wRK%`V˓~/*4ҵOkո\=`PYw\:-PE7nr[K&#t"u`e~6="F HXE9+Q7q&iqa@kv"8Vq)VDrONbq7{e郪OV/Uf/vߣ獱۰@9m΢',<)4S΄TBzaLy ה+Y! : |p\9ߍ|G66TԅY21;=\M'Ue8; <[{\TE[$ 5|OG 4cŋ_ Ϟ e+^~bx6$PE oG*g~Lq=McШG~Q}A#[-ٷ)o^8мMHBby]TLV1(}Y]Z鞫PR)G/7LXT01 !OY|\a Mʼn2}/+E/k}hDc@/uѽF7uJܢHrAqƋj-k #7BE٨-Q B3??GazlKsEU]r@P3l9YcMThӶnÑ(zЁJRo,>F8pr|\ vGťT+? r9X Љl/ : K ";n?&hqzUd@b|anR kD4f * 7~cW #ޏŐO_5bQX :3Bř5@lmm\?.*N ?T[//QsJh`|;_XDe;ߪfka3rU؟ƵfS5W9cX8DhXH6|v?c'XGz2֫ -3m93]NJxĔ5߻Feis8sPֿJe<0P2 @ֲ{_vYK>k$".66Q@OQC$TuC. ـ\C/%E q3[APܧj! H7nu'4 M8|vRk6XsU1+'F˨T'_ u4 < ZG'IJJEA/R>Ap"]{龳B˿c` F#א 0ĥy%c xc eDcko)]z ĵ":Ci0,ّ9DuݮDc2B,cQ/Oݨl7Y8^_xڰn&8/鴸FLzQ 9-߿hx!/~Jl$㏟uwl E(P'{Dis9*}q)ҮOM=.YNqeC\#{_';Z.fizoɄN T% Vu5|z(&0JZJ}mpD}&O:gv,j?ۥ<6stx! w.n?)3NvR+kL*/j c֡miȂ}(qz*u ]FύVsN;g)Nd뼯w~JkImMoowY.x%}U&owC]i>{20l"H/M,WJ2ɭ/oQKtzcNw]ָNj0l|2׀SjzǠC [v+,dRr;U.>tjZ%<޵^,zv9ϜU Ys5/ת|\oo%'>4G3~,jZ5t|mFx1--$Opp=5s/SbO Fv._YLk՗:g-$klz_=yr, 8۸vٔ+B1"o/#sD^A7򋕥v#PTBK%{%7'0,zJ}!'G1_s!d֯ӨThZ֦vM`=8IV:elJ9q^ JZALUvf-'mJh| Z2\Iv}实x 5S麚 zocyh;eֳ`<¬(F`v?tNSMsWl_Zl~2Q֨ V2+?>nڳ43h_  ʀwnնm0nf{H%!L'h^֚҅7ZE}T1Y r& juƒU,O:^0w6D>` 3P.PԐկ^lG]%v : a]=޷N} 畕G]봱f_1KR$L2NhxM _Y~b ⍥l܎Si I=;!r`(ƖW-\8mUlʻxÜTY""ȥ^F##_XE:tw$3oP+wzI{Q,^~P94 wMyhq~2 يq $zTwso@ >H囟e2N I# [ w33)K1l_3gOI鵀.1Fdz J|^`*3B51eNE]fVr:-GjK=l黜6|$[2tXB늵H!~bhGP?oPVb/5DI 2˸q^DGS5vFu%dBM-:PR;iMj(xiwK|M V5fJ-D?Di}@͝T'},<[} W:g#_.úSUڵ = oz*jì,hū^-/Xdp)@`u#_upKˀ^fjlǣF̟5#wCI-3:fZctm>7qzbZkykޡgcA>_6 ܠȱN#/DG /IvyaDhtϧlcS8 |w׿/T.u3r>nʧ#Zڿ]1nhwτMΨZTMhs>oHZdRIm.eT۬F0Ws/ݒ(&C.|2$_k_ ^15{{iRºC) {svɝr-0 YF 7g9Ҋp5a#%rs`⋭H6a~r1C]}H0@8[]U>e3YUujܬvneTʀ9#fp;Zh;*К75|t˵}"5/|Ŝ`TAΚ\TܤDy4WJ;_.Q7Z׍bwuiՎ ЋDIU5 ٙoQp+| t)C&W?VX4%MdeѕH, rP?[)" ;4)Z ĸ>F΢igpX' +=K N͐(;y-We }O鹪KL(Єk:#j/UsNz߸H^ҨiEvcK!M'.*vrk0?Z1I!(%ݡZu*57$& {"b6eIzDtM(kI]CLMoٟ^=]V,!Q]E =C⮈{sG$&ήʤ7U,vRpoɗ2y<2 zM]i)$Nդ6Zm4mˢ|Jal2 ec= įcP5j(̵Zzm_/u,yE8翈eM< ձt\tGř" Bą@sJ. e G+ @]۹|+9 /+5TWq·S2ǁ9x>`(A_ͩV}*{Rb ;o]ռH~kn>Ǐa层WߡRr`\V!Gؕ1lÁ8R  && lm{E\aCBȋV:TvOܟU6@q~vߦOvvc>'y&ЦJ袴u]LH#c%%+ˉ4۾cWR-+P/MUQ]3<yN=]n]ȗ5 @-} |~-_SИeSR !}u"+2אsHהGf\Eq ӟ C&ޤ$A8Îe6J&'-#Q(99<'x!E+1K%,q N0?DsJƕ1bv%ʓ\͝s2DҴF15>ǑtLG 3bOϠJM+T|{z1e5,'F#cQQ@%'~3{ QןHPQ`#{jb**Ed{\d;U+/|s匵>]t)yց$|EρMŊ H9=DO*^(LW9h%LQxZީ(lalgs0uoec60ˇA1.)QVr'+qYG7` ywL}zPNMoӚ /-rS֫uۦSAg~_]8na%Iv4jT..isE%mՖnr>*`r4/L <:eE}$RA^an?jVGK 4֌ MLY-g#:P{Ǻ RU+z7?=#,獡~?YQ)hƦ3A9HDV6#Ig6̍ۊ|C:8rvAQry+jVwmm:PXC S.^sWpD/ӏѰڽF-:u%lw jC٤K;;{oie$[D6-R^ar[(qX (A%Ԅ=y|=]#F&],W\XdswR0VfX]f4(y7:BTg_j tp9} Ҫ58恥!)bZdJ^e mܡ%Bsi$i1ƩrvtL)%l u׊Od|XYPW!C 6ZJA"G^ůRURmn-HcdّE$4"(u~À/I-Sa )z#O`XӷJư ՂeGYף~rԴD]P)Vv5t._և\nѺT2M9T[GM4YZ qqUEA5ezBZ ZYXcgwh1oWw]A8BC2裟opŘ,ԍ YGS}1/ݍA7ոH)HƯdq]đ7~ a482$g \yEcyal[b9t>Oq>1Y3zv)]56 ,q(b#*`^=]mѩ|z CM5 B$ ݲ4[2Efcwt+,4at1r4okuOӳIxFc}[4Ef\8O˽ ÈidînuLP4S4^uCAC=^ Q?0uΎK\%X }p_UC~S/ыB%A`疽wz+bF""6M;ޞ8wGhej&{6`n]ڴ?KIpPw<$ L MBVU/"O2{pT1n[Î5) PN2+5#()P;3X8LeHoBKgtA P%d,ɟh+^i3i9âE<𨜿#z cBf%Ts =)P+%LM9`^:3gLԽty"{6o["RW'DG7fT닎}'c7nAr΋qhcVuo=w.=Ӈ*5m</z$#H1p)"$d𲷿wȱb'_"}G,⧧-ZDDm:6:D]n -/~iнq5 JH-+R:?7dF8jn؉ޭtAX-8N-Rwy{rF+rܜ,yK6Q+yB/8ւC扂@ 0=b |e߯fwy~ sd|ZG,ovZD6ez(gHf%r!?}M&*KsLQ3KntXBJa'?)Nts1|Fo]dv0F;>9af51vERk3u//<0^*E Zs& : 3 n( W#=3PDJC% 4޺u{N$773phezd1W?&bfT:Xײ&!VLy2kCg5Jz{ǗF՝Q c||{`Ncᖋrh ϻ02ЦŻ w[ޟ譟d8XZ[>Uӎh= yʂ@ӧ{ufq_Ľq?j2yS%0Hb %΄f?,| mB]$LZ5\ѩ{ްZVBP$j$͈׃ʢEUy⊸PJezv7گhH~C׽ך=Vn.pBlʯ@ #" ȡL3UwWtr ĊTg &Fi FP7!(GQJهzC_UY7rhě}ԕc\+nF2G!,c g|("Y1q^PIA=d KN͊qNITy8< X縆vbsCL)w1fMV$,*GLwgJ'!#:ϑPqWU .XqGx]Im 2"(5ȡ^ZzD,I؁ǝ*b7^No ӱI[.]gQr}T (IalulOpT, i#P6*3)S:{ Y]lCB*#UVP25^,˫go!^k>qR ۦ!)xYȲ=÷-rs( -4W*V'}Xa,?Y teo cm";!́aþͼM8T?p 5f<N"7/4M= _؆+oR>è3X ,JDA-)[1"+X<\ZlFKVsr";珆8)}({"ȇlM1M޵!Q  ,~h3v%=<ޑ-iQwM$oL5Kx$w}c6f.hAO=Y:3{&Rq9Q[ A"cn^u-8hø6| cq! (WY%RB;=OW>؀4MMV_ZEvE`b`N2;̘$? 쬡~0{^NJd"uʵLP fRïB)#b&k c ƅS$bYf~$1q#97̩.N!}"%q#e`iħLdQl PM}]k n,Lcl3 K rAb|/9Z}7P[\"OHtGZ,,t~ӬLAjRL,Ǿ&1w^Aѝ?*\hݶz\um5P2ſ~t7a{CD hEbǎ"ؿI 9uE>Os'f焥59,k!S[GC18ۥS2eK9E>} H  OF+&e*JHy3~`?3X#T;qntX]dA! B./Egّ/F]t2(N"%&Qc$нY79vEaahN걥Y vtИtXm;(l*wPQTdozu,ψlPHLxm3Lyd<.6~SEEwnqI֚ l3Wx]sѓae5[ٌP-?ωà\|< ^N:-n;?8]#\c]41KǝHw<2㺯_gv%E}Vg~dqh[CL&*napJrz뱦>Vsi}λM3iAb';4s%S 9^=-s l]lt;x':lY,'nE}_HW60`೹GPF'|C|.Oeƚ;Uч1ewjH_;<Wl4#hcLwD4لĸ(YNǕ3Y jE"Ifg׳Aui|HUaJ4]!>@BFw &&Yg KOs)0 W67#QL7xF]2Oq5"nvЛ'f!A,IV`xǡ)^ Gw`00qE;̀EehdpU$YH w RDu+W#brv𖯩퍦CiOzkҎ_P Ïɥ7b!C:+vm|=n.]QV y nkNY/Qy<&o%x]D"r7|rәo8^g긼gе̓dBiQ 08}uĞ?1d#N@-\핾:L[=6{ۥ㱶KHv ˴O +?;i[vڛTb4dcGKZrl #< 'CetĚ*rT&+=lrSNK6E!LYݘbz-Ma˾  >at(O.4/ΙT[LEx@X5\jܼ.n"A84T41ZELL/X?jb S׉a.XT\`}Ct-%`'xEvN3pGx4ػʑh֬і?CJO> +2.1c7kJiLϴ=ƎJݶp} aJqahNkT''^-Z26 N&CCL>夁U:HOl'Ԏ34ó|@;Kݛ AĜɑx%$q]ufd?d5aV[y* nK"B6j^9n QC#vǑI| o .x; 0OhW۳ 9[:ޤ]񒌻-Ufÿd</Q8M3F+tրHa9G(y;xEێ@O,` ΋plY0)3IܿKg=70zs KlHm7ښPB2 1:B-'R%`I=Q6fM^,XU^OUQ0 rz @^vNxU?x0&fHs~IQN)'˙X?ğBRq EeIŵwL ~u2= UZQ=t7 BKbgmNӥ@D3>VlEt^y -s2a>K#'ayjhJhb\] ?aY tDm>TM8o`.ahٮ2?;t>uhF|}=s"rOަ'MMfnKYK,,3]| gF/)| nu2x("K?V e(S_ § vEӮ;8{Biqz}=۹\0l0Lv[}vrAt)*=|]>Ԫo@6P|-KB1;gOT,Wsά"z;a2ȕFAOо\qViTSm(Ω -D/?IZV$c|TsS bJB=N(BXl=ݤ0 ZNuSD6M> qL0w/V>ns@634@?lp W[jJ,15l<']֚#prwL.a4R3.aQ)j5O\PT,{i%nOLVjtZ>g%1lvB#-+cwV;xq!wWpޚo9 j?yAMQ8h }VU^CaV3cKk}Rǡ-?jpc6[Z?PtOD"?U&i*.;8[,Q|ȝ\Ef 8 %YdTG} k'0!}-22KGОleǏq2響Bcpw/Ƴ yi}gv5u :_ۭcRIڕw;y;Kcge/x'v9K'IŶ,7kb/H%оP.2zݠM.`P%OρC`rP`+j8} \ДJW`2@e iQ=JY -MeTT XɰŃ"p ;/פ?u,xOKL"sE/Yx$+Fp z<8H9˺U(.; Dd&0:k{[1GRZ\Fk?@ :J u8nlS#lјu-'~ڇSv(OyAST/*sj?PzH'rfє[3+OO!pഺP|ޭ3{B$Nb!RQM;mO1! 4sn^WT'kR\vjW5P[BW+ƊP(vYhlM^\օ9yͻo<X1vDivIް8.d13P,&+j;'Ur3eFu +.Fn-BB|&sEL^?Hj V46> |:9Wq0Q bx߂;㳉Q@EP-~ 'Σz|-iwLuYZ6?#!8N][ "z x_PH.4ZDwN鋡YXˏ/c j-\񔀘R/M> |&#$'|iD@c/VT%-j1{<.\XIP"D0(MxBVgHrja( pZh`#wsajPaCĔڿXqcQK& >I5% qdL[V\s͚—)Gf$=Bkޘ]4AsT&>ϳbzP1P!9n\p [No)\Dq pTn76LiIAQzvĔi8D[oنj ~P $G'kWleEc5LWDZVѽ YwU N3+YK[6_`E,֑I?+Õ7R-Q$AMxqI~[d#= d4f-#j.5e<_ՀZEJn@aqWǸ!MBeG'W:2Qm,+W}BjZ2C2u)d|'"VPsmABkLy1f.'*c ,;N+/ \Ng`A U~pɭ/m'ԅR@@AU"?V-a̅{MFdRLk7_#y<-*,M1{sA,$ek}Ǖ}ۦ|v`t~:~v^Q]mmc\"Ũ>,^KUY("2|0Ҵ:*FEКF4Fm[sO;n7[^O$T|Z0w34ߘxnQtsG b!{ɿv{1rkI͠5i,mYJubMHq2,)F5 o~|":: = (ܱiL5;%ru jť^~"5IN^2'X3f^ ,Ѱ)53 E~U,-Mп^jFpJ$"w{"d'$" =K9ѫ9*vG)}#7Q 6vTv-DxN9+BWqc_h/A#G2ԡe ?G5JZ~񽞪s^H 4e^ͬ!H42LGBxaA=]H=e87zXU.֫?y >mdG A& Y.O0y`qŗK1b.68p|EZ6yZv&^e.70vk ƪloKLweoҠMӘ݊&3ZރV5c.sv*G1φRᚣ Eτ2&>1 Z+r{&boV5pk_+j*oghpꓭŊ rH`1] 9oP~dYp(B61[C [ɧiZZDǐQhÚEA10C8Dk{Ka% S|ĿB wa;W!ZT:9ժnI_/:-?m;S 1]e/f/#Z]ȍ&qbTV- *y9tN0@,w"%A/ӕ)r't&dWd-u8!EҿPcлg ݋J931c I5+,zޙq+d|yMp{ƹ=^sUF ߛRȺVX ֢Jtw,EVk]E4pOdã@ZB66%G[ a?֕ë6M+4 aQk;*Acj'o҄ϟg؜K:HSlSyZH7{ TEu 8"+BԠʯŅ&#ݕpnFkTjK5a.FJZ);,un(< .1x5 P20a~k~;e+^oHYoy eQts]YHz.FTCk8Q77R<ٱM@lha5eٿqr(ǿg_v~ճKb:DjˀS%Y!ǻǚ ~4Nz!j@^F;;lg7TH'PA.Ye7ϛbD͐ ۜ0(eߧD!lغ UcٳR8> h)q۪3"$CkmDv<^4K=ݠZzpK"/\>0㔊#;L }+>B3ag;S.ɿg;^DWOTutRLgvPHU]oޤ݌H[7qS (GA2\S 0$cɩTRFoGE4lr 3Q b+1yecQ%=ZT\prpm% qE V-TR niIs&bdÛxw2<*c۬.AG⹒=;ꇐub2b|j6`>.2|TovKo(G۩73vWsۂT5U ƥZ']X KJ|Z[J> d<1y`d':.*َ JX?Y̻f(xJΗ|t0D-֔$~׌ƞĴixzbRS 8-=P"c&p+2V "L֊{?H%׹~L(yl%[*TLC#fs" :2w4p"w!vL ї'*,F- -)Xn%X \,(l&kdܟz w@J z#t"E2P0wHi&ps_ªѬz4eOX?F#So& TJ 9_mr/inaVvӐYX;7"ce5k&1/2DK=4(S&}_@?8yb'$)׃ _na 韈q*Z*p$M&÷>hT_3'1:mf?E61>w\G x{O?+AB%13-㯶%TQkC͎p4{> W澼x=D a]X:\T6w`X>=ޅ\lQ{J5T*K9Xkǣd}WF9'Jv啕KimSrQQe R ߈Ytdq!([a+d>P;KMbfAp#R2ĹcRѸ65&7^ p|y ب0+TQeU_΍b ŅehP9HޡXWlp#p-7 \~w!@"3* s_p\LY^Ru @Ki` .lzʲMg#KOtVM ]*,sኝ?V$:TGOϒ҂?oHk4>Uj🧴9QngDd_ljA55sO=m5Gԭ>] 2On iUvK%Fyjo绲-u#<ݑNTʛ6E0)X)Y"1aWۤl裂<_d7,¼Y rrCH29dnzgV.fdXJqn{WgOeCeˑC?Ɯ! Z4b:[҃4a9 $BXÚJcyVV_j#Jܽ eD,k2BK9uWm`IF#G rj:z qBx0? .Yk#6'sAG_ijÝ㡮i1|IU+rT\5 3̒+W笑xΡJr-P8Y^;6̢ G[2E{hJf'QkLвW\RϽ;cQQ4קġ @|cp18ԟ .vAdZoAi) J-^=zuS9! XS,򷿎tق855 di0)Eao$uNaXGjxWexp=f jkl +`_(`>En'5l8_oXv_o%}-\,QbwB /l3 Mp$;@rcd+|KIX~H ug}WS"ܬ/XXp`6)VW5ė 5s$y_p'pc~\{ڃCG"=eLK+5V@yF >x2sdԅshGY6Hˁ>m͢zҶRƑt pjЬ ك[Pa5!0\0eaҁ?5P7zsF?R%})85E.Q*'3ʊk}.`?_p 73-%PcB2\XvGPj̟cyz&<ECP< wQ+T+j^G[JL3#36,MPGztLj1򯐜wcze(6YH`Ed&-#vUJiǁŢx!.֌r1RܔXhsQмӥ_іٯaZ& *z3"9|+!|/Q||$Mr_^j.":Y~o<ߕk'&y0&2)@b-i)Ѭ L%M.vR`A0} l43).g+򲢈r[[4gy#pyP$9Jӓ# }d` )kǻxee-Ry f.¢pA&\U+{KVs2jBa_ o[ kAT"Y+r5,s.q./lZ ) h^`_)*=fB52^mqwBiɜe}8 |8ڳX>Hr|i;Wf E,Ό@1UpjZA%""R6;{fe,OD?­Db0}+{dyVa4gۯp43V-ٰF*A}+@%LDVcN?ƿ9+u 5{|;%$mnQg0?0mw^3Rt_iί~ݘu֯h;O^@(H%әhJP8#{LZ>uk99CXr#T.FAs^0'H&n8'S<3/ǖ;XS3z(9܋]nZ>,#~Kz'< '¿h,[ԑ$ ;ZS/Hkӄ"C mGD{6Heh/nb& 鎤d_QqxVm]4VpAYd+RRZ.82<Ց&-(̒/`;"l9g$}v].+fU/NCdnG!{`*2Rju`ۨjݶH3Ն|l& xLh˂;29p3fOwuO73i0h5Ј~5AվhD퉮rH|D!C7gxu4JavԶf82iKQ(DG/ K&J|'Vm&锰V5$2>Hڶ_Ω{!e")h <_-CH# E["gUʭ\BfAs"Ew9f^P^$=;p PG蟀?5L&H{- ڥ1q^Nh84˱korYq30&%@~6^>5?ڋLBĂROd0+rcȥFU*c;TluMfHU334Cgi}Dh+ JhEbN;O8@ -*o˩-rCIgcx:3)9@IUA;~vY'ݡ ^l&XB;2iy<HsZ#Mx_b0ϫ4A=܅kg$<gv/&YrYw - w?0*앚]4 ;Eq#?Nύ͘ ICs ؏j ƨ 'Vh>ǰqPҡxt"`$Jά?ƹʱT[?+íauuiy+e Y/rxjڏ?GN|-Gc9p49ѴנNzٔ&䒄/9m 5i~Kykd<jV!PI?EyRpI;}o|ԕRn$¿=Zcڪڹ=e֒iczZj6pu?,v1ҸS2%Ɠeh׌剬qRrmZbzms'A'炾̑3H5U8__8pcFʼj3Z̅uS̖DogBzx{^z*p宂GNJ堝1i^Y#(Ugr2*,Jw3@P#“~q;͚JniAg+@8w(2+Vԫ xGrWJ*Q! L/!+KF #iM/25'[_i9d['忑gS}Px&- }f00-s3;,A=r i'R T7%M Bmc˥uOWyC6/fAtP=[=(Q=_r9I֬.kh$c%,fΈb e{RqU{(x举Sh~ڂ4v"i}<['$ZbSJR֢-\Wϭ EGdK$]fƜAoW6"j ɋV2}8җ<6{z[h6y^8h*I&N$x#mo2[ !SrN ۯ"yQ{4|<>[:"x"jxe: {Jග#l?r6CHNSk>_k<<~3iJRE vuɆ\|ꏜ9YD^CM>oc ?j6gb<@7]J{8;UnJN:}gmߥbpL%ɟićW8k1pvq>s SE:kێzm^TFU>43 FRRdDݾ*@RW_t=>fpWiBGa6oOK|:Im*_EԩApސȎ,ƫ)!PǗqmBt[@3E]j]#[2T3'$4Zπ oMK}2rTϕ<\1~x]Pw?įigEdUf d | ; 1veE?9Y^,G,d,1"`K۔,n,-Z" Eߒ " /I<#:WU<9kbKJ~X/ G`TC26Ct$'9k3;*d6ĻU)ǍVJTdK|(w}A5T`VU ]P;Kxpf&i~&D"=k*P&S܊LLX,eBFlgf8g7b)ТEd`/{X 9'#^SZ^'52nM@Ґaz4*ڲܷՓSqL gax}<gmf x k!oP DnM|v%BE:ZI3j>>&`7F͟Y椴. Xc~Zds#J:z&B11ՈQ/C0!F!|_'s H(E9=8G@Q0Ͱ=χ`:+7k|T>RL58-׷M>G)s!eW݊\ ;7M^ m[ ބ6:/ o.SЗ`{RwKP= Mu*>ARI3e:KaK,Z؆mʺp&_=I=@d¡k{gy*o>eQHc\[>/u)]ל.SZ*<ʿ"R"C9 CJŦ)'D8f:EsKx`T%O-V|9eF2Q"@y@F6!,IДNn86 auH=_3?v'P`L]"cE=Xw:vJe~kyk:u Ox/%g̏"gQFљ Fv';*VRG C})9"q^=翿`4O(;O_{ R3FAdI]\֝Ծ7t-S|g%" g&N%@P| SWe>ДTNQBcQ"me WD` #$!0Eb*gu̢pT8n.ݑ. PQ%LzuqpMӫ41 n$'o-h)9g,_`A(oV,>"V5pζ|pwqdϣME˱bbc#8aoЬ'OԏxN.SI,>xx͖oXJU[1GBW.O2f_ս25(Z?5N7Z!CQJW[R֘2ƾ]_ݥ=p+`1EKm9#[#п?Xh779P,V(xbLz3e}[H۰\~}L(|ETDrfBOnbTOEnS'ƨp+ iAeJb66Bi^W2Ob7aRׁ1hp?e FX^tZJNPzc@΅R^#ƀɎ@Y}{˼-Mb]l6ZCZ˿ ݵtFy x]L44㴓fYɉѢ<(ϻCĨ;R׆* V|q֘2۷Hn0+lzS:ćvFl\cح.z_c}BNQɎ6h@JxJbۄ%d`G QlI* V oS\g6 \:/,w0k:ܨc2B[r]Ryk)Wc99|4gvKEvzzuv,rq?|{}qjs'vH Q3r wkx1! hթ r1ŊV<٤`]ޛٓ@7Ɯؓrx1qBnR WB!y%^}VM[}06@; :4)F˪?`%*R;AE==jŢ\_튤 j ER J^#O7ŕM묡xέ&# G=#>&Az:5_tv2a!:g`Bwr)!Udm۔V"6wm),}p?z3R"Iz|B2F^:y{LI2)c9щ9E ϕڃ>m,N{2a2iKqρHa x*~Eɶ䜹 ArVt`L*|.\̱Mc}_SrBWoj*\!5نYLYzse~vp'z2MQη4hі}gb:JLԐmMd1l}%(tU_ddm?jڂ5hZDf%w\]Y-2Eǂs#1jq0j-AV-d~ϨRg=)' 5ߒ6IhHsP=J`NUH۟.]*re (EssH =#~Z@M iѼW"BjD B <(9$*3{>86B&')_}C07QI^NۼpZ}\NFZb K42Xro;A7+s >(ċ*cQVu%Oq C^f GV_[{YıNjxƫh߾8':Ud<ݑs =/ 1Sa!(τE%S%Og9C%Q&XB4$mg9q*y]KpЃ _v Zp{*{ʺ̵{u8AUdrp۩v_fƍ섵+Z"Tw3_IӦoEx}AYd;\{06H-Qr0ϯ\^O|z7A3g=:ȣB|X?rR?m-v3T?fD;}\G`wԷy{LuL'2,edNdwBG-Q5m hܱ&'baBiƛ&A%ؖlXacb,lӜ୅sڰ/DeO*UqƷVb(+^Kyr5]pB\ ۆY1r̄iaUiG3)vh# /7xhMpe"1G4a6 P|(ϓX3\ؑ~p<5fL(?Ye="mzp[RBQe Dgŭ֡dSgv=&3Q.N)usO/|:WS+# miUk'o#yl ܈oT1ί%\ / R~q|&rIQs]%7mn@7&}o`#_N71T8 j W$Ȁ_ x>dZ]B4;hAWVOq4$ʚ3,7y3NKe\߯W. l O!ǧrz& 0Zcy@}KqBy0rJr?4cgmQt>\{B7V 9v eK~LH-Z~g1iS%ٝ$](<-gbVpZQx C!0~Cm9־i<(c ۟]Dm` 2 OG xK@>⡥';qD|w$Jf% h?THaGE3ʴ/)Ub{f%PgwޞFQ8ykƸ/?,^$zP@=Ҽ}2j[\(h"+= ఞ7T'J wD=Ǟ uH2't4|-*׍r ۳=,QO:ZaAH'KZ3pUcdaӳ$2 `h=a!?iM;;i5U1YbbQ3SqJVU_tFh"WeGK?19Rw6x(9&e$N{5XgS8y8k뛌:NEfVڞX0@SFG(er@s#TQOm>ڛb2SDvnD, KM9A $-FNMWgqM? 0ȳ֞۔ ӝZazJlW|w]t|^6oxig1 U|OZ7@؛4 P:3c EIV668@, J_H4#ևY`Гذdm-JUM isE9UaXL}×@q?#gv؜YYIfU>nt5ui}&/˜r:fNIf2 "̣'T)/J4gOZ8,|݌o S@*$BWrU<*К(XJzҨ -U粟[6,̓!0lљCmkߓ℮0>0JDP7Àfjw KSw99HJ]p$hkg`.v׬ yO/ V-Ԅ0 I?d<>N#;ޢ& V^W`q$pK?c iD0zHp00ǵ\';͋zQW#|!t&E}4I/0:ې}M.w*PۘQqz/`3&$WG-Mָ=m*HVlZH{PW0 ~f3aYR)ij~ZdtM{LJ/ȹcfK{9Hm@3i~:G /v>fHbXUФjQ>ot|9kF8.]e m|[&< EV^!19 Nvt`Ks9C:3ulcNl@u)³[(fb Cc_bEG*鱿Uva@jNwnB<_z'F#.M_<*RaN[0W?2ꦢ]oc𴢼K4&򸊫m$j75a\%{Xَ8)ք^=5 WcC2EVmg[02k-F=!Ơxy 4ќkҖ+'޾i$XњY/~WȎ.ٌKAOfzڰ3,N[&`5*Ef?1L`8=biwO«4 /v)T&\m~S(x;'>`qTȝZcҨE1M׹c1גdkķFlX\bT@*·6=Bȫ"U\Zx%Qװ0~a Aɒ ~|g%V0l89-$q&@Ncatfm^۶*m,h<4-{$]XM~jYJ~ 2[.j1@MsŬ*Fh¾)lvc0>q}.QA[`#ȴ0u&<- }xwPc8UUUǍ<&dJq|k3HA`x-W/blT(4כ/1!,E#$WB+^At~G.%[z{;nGHB$$WzO^̴&\( q@俗&'1a͒у.T]=cT@x_sg'6 5R-wYJ<1CT/ ^s͜X!%v7f쎫 K*}EZ4 vP^Д'"$hG(bwv_vH1:!mRxH^)7ju$!Gc)р-H'D xJ Mwү`/ ŕ<2289"GZ7vMrqptw1/_?/_wAM9!MkrZIn]?BP5f{>f|;y ܁:"jNҞr>޿K^d_Lݎsl|B2Rs(c)y >H ^Ug^,cjtm]VeIbR#vQn:=r<ֈ6tM3›^(0# ޕe&TiAI겏a|Q>P~Lj+6d{$R ^r,?-=b[U-g[5-,vA<4u*7/CbccH U6{ Ɛ&.TTXN,bנ&Q B1֖Ne STĥf;&5[Uz{`c>57΍)fb ,ua?C؍ƎȫdXhCF~TR8: Ao`W%.axU¸J-O6yi1\VN+M5R/`]_LS+ֹ^E:ssIf4$*cܱ/PB5E_Ľa<{У {'Y~Mp|>(x-Nk 5-Ԏ<5i S R W;Y8݅v9©MoV%SJTS E8e\j!!}ND~2`1^J;I.Vǒ)Y'6YӨ hHqȎa_ BjzZ-Ais,/4u{.ExD!$3L[D=)5)0v=dgNhևbO@Z,Ay8פf% [\\x;PŒwae:p7X HVjS7Z}!fDuT ,f7%Ol-n}!8,ܰ\ʴ< Xs^`֥'׮P2 /kj w/B7n6K5ɃgR:~RJ_Z迁N-{*C~-_ Dp"x@|iTUS=Ht`V^}'P+x^ZMM*V0 vw=:\)/%əmǠ߽Ӯqa#i]p y3Z1 vpb`Ma(H;'2[}ܿx7ˣ.+"L:r=k]K +Qo:)QmSѵ `+fe 1okPODQ,U I#. Haq+OT-0 VǕh:a>QFN_NVdW;7fGq 4JxH>}~$N_EɠD>.ы]␊Ɛy`.`6^ tf! @$rXRCy(g{֤ҹV[g[܁>YqDq<)Sڑ&4 <.S/EGΦ jeAWAUZe)nKE M捝<XT72Ji.:B?B_jñ\drb"3:(Li7 /'Py(a(8}~ý*l_FO9\)3"y&okg(@(TCސ~=y[?sgz64SfqLKO+CI}Le4ΦX9.F"v0hl?`?/݀J\NF tP$EIo{ÏG) }}F\*6˩Uvt<7F ï8`D7KP(UR20LAogB컛۰EW/zr0?xH#-?pI0 ^➮MiUsh'rR!M]Z OoPÕ0--[ޜ~ų_g+[T{0V˷}􆻘G Ee7 JFhFtܖ!Q/#jܰ >>\PLace}s15pa-KL呛э]Ôf Emǡ%ny*t0{Iݥ~nlIMJ+p).zġ#+Len`pςk&(-v^*ZdKf.Q@1ZjLůKyK46+vIqQVåL?$&-Pz㨂Ě'{(Z)"4Oc tWr/GL AGBXj?^ Q(=l{+ lėmq#Vf}txG8G_r0XoKl4т\lfpgPFעGeCV{ Е(%g$՘$8Hz{m!Y/rO$jE{tlS"%&]TFIxe zl~]00F2遵44u H< QsOI&Ql""nFN @e8HrT#F$+D-"l!{GkPz8[iɨ)-|BӼ.[)o˶9,?bTΟ GŁgiE;u@fP6CbbsQduWJ]6hWTȱGs\!츫q|/t(AĨ@pU!A" -zƠEja yU +P~Gt`嚔v_ѩPjW"X=Qbvu"h]yS俙fTGMoKxc.q-2huBf)}>mW>] xyiّ~( ya7g E&D]HMmo #|dVO*rlfKvEg<1Ň =əˇI%k6@2Wuܢ~GUG\po6gh΄8 ,$V+/0nM${EaxfPPwqJp}JpzЎDOɖ*@I )> ጞ"h}6v~4kl\Z69َ8V*H@סm4\y?ɅBF#V_2A%#Ђ^@ %`e_{Ѩsx#$.%TW@?YЄwԉ<-·"J@ŚSF9#K~صg =$ul4m7BMOPFx'cHN Gu*O80 {AΐOKܾz|5P t6MaDGnjDxZ0̐Azk@P.]F޼Dapf0]##$!R׫@/jbiHmT r. z<8\9X)AU~jpTÑApvD ;g!.yDk VcCߞ[y"R$>!2N)Wo$x145Ш}`:} E?-JUS9q/IJUn^Eᛪ PТq)n, t۸=L%,NO{VM?zaf"宜L%Bt&1ȻM// Ǎ6)_jEV V/VQa);7fƷٝ^_ux=.7Qנ6;uH_{.뽎)uZv %>(;M*,DбSŀ+dDY#'ZG:UA5[:wTOg\'A=@iÕV_vÛaL9F=Rnh:k6R3/ G FQ+Oغ' SUV:Dս_}N6 qƳe*HrIYiub5#,<9[4>9ũdC8MtTFi/B}[f wB9&+ڔJ7f{'@v2̙d'^S"|Ow9ڊ "RabpԱT{2@DEc_ ('5FN|^NnՃ;PfkzfXq(Eha95?Ty*?I|[Ւ,pk/Zn`?ωUi׌?jۏ_<̀𭬽jKRkRLTeGэ(EDj%c Xpp֩n%P/n M Az.X!.*krv_n?QIZtNwߠI04~2@kzH3˫PT)CjJQFSxw۠',wLΖʡ8vup H<[WΥ%cŔPBw." ijy)- 𰃲=kyՑ(ƏfkሃQACwghBaРvlՃlUozXe!b ƃۑY;>Z۱(ê`J.WNeRg8Ip/cⰜ^IϏWnq`}&1M2r)3vL+PMz"?y;jR nq'P $ۖ>KD lP ^5cFj"Baq .A M ꋨWx Rf,셂oY8 ";㵷hIy"mF@ ؅4=!BҊ+3a٨N wuƧӰ&.`J*ѵH܄Z Sj W2PwU)Z^D{ *3#1LXw_-|i3ֳ1;FEX8ab7 R )h <~*bSL pz=D1\&M(jKzC:A\1  8/l{U B05$6Q7r>47"ad~m1ƗN$߁n^0nod@:l"FW'>a3ԋhQsNU FfkDO&AEUƋX?kfwiig+'7Wrsp"vKod 8-!Y9jH@)K?>~ƓG8>9q߇Q0|o!ANXafB|peʛg:V{dwuSyfP4 BYb=۟/O*`_[RtJ8 P8{bPDL_NQH@ǫ\|tS =1jYVoޱf/<^XgEN4%:+c@?(pC2zdjI~>/3H`r+; ֹ+}j&=d}0lK-Uh/!̡$LXbgi'A8)`MtEjtn=כLT01t6q2Oi}` <@4k:\b0jZ|&rn+cp婜eNL )@Aflƈ,*QZ)q<f!a~P8ͬ9*@)% 0(>™ Hkk_]C:ZT -ޖr/OnLyQy5w0\@6vLIpeűъ5֮Ȋ[+ ?Ap/"zXTE-y ~^jcekA=;_Qv)>S] DC~Tꌺ+%hV,?6u_eo,?Y|x|a8C(d Aze/>Bsocν~!^7*Ϟr;#T}Y3mtx=!rݢLy.@l'X9n7bn<"go-&x*aR75G"d$ݩ*:z3T=cR; nTו)2 %-6KOI"-^PUBhhD.NL,-Y͙8!v}D X|+`H` -,Y43!530]gOĿ|3NA1QLMJ2ɣ0sO( 2Bv&%"~-VG? ( KՐY 4h89"`7ŎB5; 0,-Rt(#iEFz|',wfC)#nPG0== uvx)> 'Z-,G̵:%qaqR9sHQدNНV}^v.<*eoxҦ1f *uu4-&+}Lb'0FBgBP-q3\FU%/zkuXj8*@j x0J޲V?yI%1#$8ܳWDk)3U/~ҟK0$wMU_77 G/1SB"9ũ@P/AE[-%PiD4#_s6ՑOz·:dRz%v xO ya-%ٻ'SA0ݔ oL Rv%"Z08>f&xkշc[ LP0* RF qb9olš,%)T\!T~rLSn<YȳFz-mƄIet3.B涍('L2Qb;f 9Mtqow#P:~(> 1'ڐ hJӰ @ڪȣ|-5 vZOkٳEMwøKB`\E<> H$._<ݦZɨ:Lqwa^QˍzD%%Ar2wDLcG)ӞْhXsD8h%ݯI 88E8-YD!<]3cMHYi1yWDϖ<$g)0vwY"K.a=HӲTRp+BÄ=et# JIg Bd4dWb*T_@#NvֆjeHU 8hH_]R]SҒd*C(q; oe0,aV9~.۫5O,j[zǿsh-230R7!ؿcbs(0{LexR#ٌy"vۚN ~B1&7EgsdfnO]âoClvd6=ۦZ?[wR/\jW|%~NiT Ǖ"dsl] .yԨZ+G7<:E`A>!Ԟ]H.!oSr_S+"8%kWu 'PWFP~tYj'/fMy˿TeL+a6~ a#21r߫rn+$܉PjÙ婷~ нt=rtG0EźOݮq3oT r 5r/&5T?o~p78B198??G'p[`k49 ` U96bІV=t!ʬQJY(,SGuO6xT0Y9f+q!H%\̛,7(/FcБnM5W;=9Ǡ. :QT ҜLf@֬eMFMbWKڊuP.ŵAzB3ȍ.E}GL<BVNg^_#D1CYPcbz&hdEX; gj'9swW܌ggtHL2a7/5HR`Hǁ.[:֫Z_+zKM/N;?헜7eFV|>AA@u{ԍ'KDEtd/*e|YLw=,rt$[$oS. cPlSHz_ɸڿ Ӳ`Έ߽:)). m6sfc~= gR4/( km@wd]Vx#pSem|oN@Ǡ|. `c?FKj'3cBVI(W83Sr9NY5HE {_lK7 1!~7k0fX3w q`suZ;_ V:'z~}Z[.壘jk9LO >{`EoP6Qy먰ayѩ+Nd|+ȋ6C?3[sthxQ|ٝ&j^iEsƒ >b$ǓN*^ryqmZ bKL!li"lMp>93e|#M~9u7|A^c8=Y=!V=*  2G^A[H],vV%5aWz kFS0o7|@ٴ¥N>0N?O TO).菐kSaؠ"vB%sMh%TaRQA/`q6^m0*W(fvtHg Z.:̹+$+q3))Zd,7[8ךcJSa 2QRL/ $i nidcg8);O\HJ?I FH4 Whn"Zwг_r&MJ/>ȝW?H, I Vw:^S݋5S W,[h3Jr$&_uxRVvXc-%`6z2*a)G.w"޲wAHšAsE+{6x^yxww"|hH?> mBG]=rІfbDa6ыbz|V^7ɫ\!0ήфn $d>~\2bq?0gq\7\9P.93f;*<ً~a׫'L>XVA&7^ ɚr>t'G 8\s zb2@c-&d܋L-Y5jj6!P3sV_׵r{Ch͹ؐQk^8ū9Ϋ,e1tݘ Dn;sWj̗+4ɀ<+GHporԆ:z`ѱ7δ]q V0̿)sA,GTxj:rxvXJ[ k%iͮi@91VRCV;Pf}2!@lbk2ŒƄ?M7Gw \w9.\˜Ք{TQYέD&/G H'ؾg@{Yh`b;" :3 omAPv*Hm=ր-O}Li#d?~J) ,V"Bt5P#?8ABv8':-8@DdC~o!ɑ_fATx<Nj^p\smƶ;@=w*cq*8S{\750t[zk SiנtGe}T Ƭz+6èQ雯ay& Q/j8 ޮH]y`xٵ-sϸ|Zn:2Ȗ:K쬝PCݏ9`ًN#^R밈NGGnM>$?ܶyF,Tnª60XJeO ^|U+dFoYY #F5?7< Ek5PySl)~aI__*10.2⒗.򍈳8uTkhȯ4W)3] 0+"l9(#ipԝ\5e >pOCmKOU|*.ف_,;/JT֝iY/쁁\}*;? z:ℰv7`Q&h`[:nIΚPŽdſnX-g. U:J'Ux~>zwdZÒ>"9;S:^r͟ЯUUJR(be6%2pf; ,#wF *gQ\q ,hwP<)I94Ws}KfYU_4s/gE/egƵ$ :`O |q,&.Uvlrl$M{3+&Ft@u3 UY3AZ/ed^l C"uuEթJ; T7d۬WOD:8:+i%\-94l o⎆Ie }y-1& IȸqIJ)9bi< Z%?|ϛ3+AUTMa%-@1MgFI{ᗎ 3bJڛFX2^*u: )O's΄JҲ ((ow׉凍(܋пazںF9йa݉oUw/`U~c,TX|dJ@4[XC5 5ƒ ~qK#7p.7q[ ?NnXPRfB!h_z cü\6[]%ɚv ֎ʊ#zdH9,8O?b2+7JYqA5ݍH,k0K<lj-JZm|oxz"6SpGA8 &8< oH"$$_;zVku vQ[giوnX DV"~O2tɝ8 dpG~A#j܄tC+})B)l2LB$qȇ{?^m&Kw[BJO [E``LQ^We6a 9`0 - 3:\EN(C+Y887ʯ06I}n|!exv.q%ģJ @>LK2[,nV%/"N{^ 7 u+чvX!59cݔ(K4@92wKk6y+zp8/(!{laUmū%r1{sLzqdtd1s=N`KyHZ3% ;})Vr5 pQo!w\jۋ(n_|b_h6>17@S-/blhWł:yGʳ5ȽzIۀwӁj.#4"/Ys!W{O^{Zrw!.$~}o"lC8N 0>mELmSmv`a9.Rs) K7'S I~c}5!'_lw)qx*7oa,\ R ZǍþM(4Lٵg2~h Adl$.9s;2uD`/7BH 㓭%0 &t7nyK`-勮xA(/-arF.cV>ߌ4XK6 $+sTS/n$$]ߗ&`eCĜ3[4)@kF]DR֣t=ιuT1DቱB 1_+K”X;<'<!3 ܟ1#eE#k(#ʉg0ډS3"#3P5 yj?K7!C3冓:XPHr<NNn{Dct=7Zp҃ f_V #z`WMby$#G_Xj\SBV.~Z iwUٟEy40 !auNJ!u-,JSNFoj 9)n `]n²-įK}C/x6˸!LЇ? (O.i|-/F<Ņ2q^ %rާqSt*s8\$xEdVd h8.Gp|4 \4)9!#?@]h~?&q;([-SJbp&TEXRscgV0ZtJ`2ҹWéqSPT@l蚠8@S)(yUGj ڏ]}V~.5pU?_ r>NpU+,,Is( %{h?sut"Ѕ(SbgHSȽ|F-USEVQ1i/L52ymY^ -hk w Bօ\G[^hzjt& n پ %([s86Hê+Sp˝cgr%Nsgֺqu&TU&7C/sr,0Cl&h&s)W_y hמleNX 'yHo|+oO~oqbT'^_4}G9E&1tnwHv:?e;1B}uJsU'2z ͝]X­RòG`ml1eCvLR93iR?d9Q6ݕG3Q߼k2`ZP;L!CLʸnw߲KI6 ߛw킁"׸! 29Gj /<8Su;udX@??4iw)eCo[+4 rjkF<ނͦϩ!v ^Zޥ/*a\)LV' bƷo6&BėxZåL-3 AۭJI3ĭϛuwJ)"λTPh)Ae}*CrOu ~C[6.MڤtN:˷*]# PrewyZN![w(/xu@f[)cXOvͷ889ێH~wtR3`FM+>Ӳ!,f~C?4HwR?V6Nb%JdmvEՔ%LwX8Bj$L_z8`s_ CF (N.l0^[yԥ$m{Õ +k' `oyjT^p?]l3.)c/#۸ @{v+s O00H-!o^O9QUD3=wd+#%ٶOZAp%}Hͬ%7MmsuDcFUNC+|`d2S$Xɞ`LPL<\7DbXo[ۧA"8QTdD)0ɓQ9sߒ+NH=ai!3@Rm(qp@pOw]DK&C"1,g'ͤLZ:]IûK{4Soc{ޙD~(-ۺGj2p5D+Xɏåy9!?W V]Yկ-<׫"~?P|)?%*n|!cBj)%I ^4I@5u?$qpVj,ee&PV!˙.sd؀OD7jbBJQq=;|-C!׊-ݕ@Y*3vbsPF*Aƻ~B4]7|'̦F3x"wR0w.s\PQŠL?v9y|Ƞ%U%X]~^Bg;fxeFi s_1lTm斨}9 "H/Lldx|h T|a6B Tc_8a'ͱ)tRQ/rqgxz\1!OT4=9:Q&+J${qz"f X:9=ٱ|82qA0S+]sV`D)_,ڰI6HuUPW&{jFI_<~5?6()A0hbEX 4JO= 7k"ϛsa:f HKִ!9 Vi|xEdj%~Xw0)%M˭O01?╫~8ŲaєČJyd> ;gO$ȰO}E@Je wNnok 0|^KJqF^[[Wym3 l)*Ϊ`,'mID,j8;6+ː_n@aI#Rampa9Wnj…,KCw-R<1(]z#B9I?g#,B3&/ azۉ 7JF!!/XN) hE,RUw76[1q) H;3?#o/NW{贙0&m@P1*b `3!)R*͜Hk~):Ǔ-W 5x*LQ୊ftVs愙)1rW3[$+i )i~\ !T ϴw|clk {}Uz ==zU`/Xu0Ł#eūΰuLأ;XC=p5߉$mԼys#vt_mxFAbZDʐ{1\n`JS)^6^pfEI'!,[vI!pdI [ߒ_YQu)mule{G)zQաyWse PnKYa 'O4H=%G쏬@NNPV?ًhYpyme5c܇"U٤pj2c\k*"?=`IwG>X / Q>f:Q\Lᔙ<,}+LֲTҺMa>H9o6N6G.*u&rȜ- K=8i`b endstream endobj 23 0 obj 72958 endobj 24 0 obj <> endobj 25 0 obj <> stream x]n8ཟBvQXO HYi@#WGt>R4uwϷ?oytnW/^}cZNy:Շo|v/yUjNi%]O| _sՖ㆔_cs^mzWmasM]ǧôڶcsS1疹EYY٘ w#rbNsmܳGn@?@?@?@?~_~_~_~_~_~_~_~_W~_W~_W~_W~_W~_W~_W~_W~_ᷚs~7~7~7~R~7~7~7~9w~w~w~w~w~w~w~tF8#Hg3ٶ l+ڲr Y,h6;сDt8. Pi|Fv +KdDTguNm-^F ̸>-AāNą,ua`ʼnALt&8eM<#art˄F{ǁN tޮLvqpvvΙK2=n=azf1OOg$@;<) bwW<}ynS~y.XG) 3,ud@ژ4͛rPvc1Kzp endstream endobj 26 0 obj <> endobj 27 0 obj <> stream xctd];tl۶ѱUmfǶmNǶuGQ5ל{yQ$J4F6Ƣ6֎4 Y4%/ GB"lcdeldkk 46R4vq74v;_2U6֜߂_5@F`d`d0ӳw='@X oo4v#u9r@+ F@Sk:n.߲%`jfk7226GCU 8ȅ(U 4Hb75@nhIG&@&Ǝt5IDl0ntYX۸X{[hmɖNhd,!_%;X9vcWC3Vv5៲-D hbl pw2c` Ʀ@kU[66ϵ=IOK?#kKmշ2ۃO+ @D`_Lj6?%%Mlts.ׁtt?AǴqSo.^mhK?ZB(oLτNa)Z @l_߰O/|GQ2J/t1@Q.#R?[0OKcZz|ד;œЇ>ICub<p:>B'߅("~/.2 n-B E=RRx.vRUFB9v)Wu_7G 824TBS%ͳ^~HwyoƤrr9 l|UW%C!fgmye6:b۟}}Qe":FuvrY,hJyO;֡xR`M;~bMcp2 ,mSg: A"?r~-:k^8ͺWd=/YC)Z-ϕ9 ,)@"=[%nL ~59~ʱ/=paxb ,zL-}]z=:F-wX"kOrK|AzrUza]@gZ +nn*>ab~H/Xʮ` ̧C<ˆ 8 Ǫ?cWȠ%˄e*M|)4m5ykT>\e uۛtP-NS[mN햌P +n|g~&6b'c=$  "KףU)!WcV{0jҳb gi<`F-K´,heְ RrGؒRpFlV \%S| )'~\`A*.1`{)/Mhڲ:|u{oULJ!u/Y/ʔ ڙ`WgiMerL`S)1<J$rx9&Y݄^|a͝;JBEhQUX! yQ+1Rûd~jq =3? kž["e@ZMΟfνܟf[!iZ)~Y*nB}IJ/O|~&8^01hi++. ÕW *wRM '$ _g7/A?."{ttZϣW֙a%zU WU"` j;{5\4;Aj']oB{g,6DAe5Pjc'5H+⢼Fsowiu]W^*ɥ(0rdavo[娠.^W{B6cmtC'<=sM{Y.PZ1]xCB懶k+Cr*LJ7L oNO)hadkHtƸ6r1fQ1\nDƾǏ@!M6}%oNM /D ݙ(WDUcD+vX>lzB0QB-t~s%lu=,3.M|d Lٌqa+q)[҇m6XC5$mSv?(&<o2JB KJU *:OV[PC-ŦY.A">o\38t:)L=B m2$Jdt#= Q>7RzH0陇:XWm6/Ţe"{<+Fn/̾r d{ݍ+& ٌ<rk8_I(][Z1ͥo(InXUսv(%2qNڸv‘Ӫ̄% `f&ߛzcI)ט>T&AFV vl @EfF"u},/b.R%b,D)6b̕Ъҵe/ٛ~طa^ދX*HҨ}3/)lٛ suSZywշ9W|TY?ԭ#4Nh6N,^D>Jnms՜L. eDߗGaHPPTQ|Epti5raΒ kg^4z5( ޭ&x_D RlӌÕrqmdi3y;9(A#&%WKM*ũ>F]qFdlm^2B!PQSPgՈAid҅f9څ=I:ޡY@ k󃇢2rNbpd(HC!)m949`/X岬&cX,o!~M<,([`'᧋hf5mJ0"l˭>avԅtP62dZ'PynR nSZMoamIφe2Bc{|}DXa'KH+z9_h܌Lf>Js N#2#X,%H.?(p1hz0.EvdM9tr?[^@9G;_z#͵I밬$q gtcmmBL2:$L*hDqӣ!>k$9`Bs(K<ф+ 5)5bl fK9Fk@Y7~x  :TT.i],'u%W= ~f;ނ@1|k%X/8'u ڷW5ctJtAv%y)BОDﴅ]a /rF]Uphq_ۂ \׽y:ݰFe^ے:Lz^Xpfs6.7A |)%?,f2ŭ6q?^Թs%%Y֡<+S \ߟ ɕj#k\A7GfUF|DŨgS7vPCǂsN BaP\9Dڇqρgr-r!D>蛴] Z{. +;ó͐K}TyC%1NGv) WvyC~[W՗i|Sez?Quf֛>s,a.]+oNdLǓv HT/U J/\͒Fᮾr:3AޤƄ 'oQ4Љ Fu|&_+ AGEdb n>PM_/ڪ*ǯ@@#TI`MLُ+ _&QOQPsRpÉbphy : N&O+}6hOPGNC(ݮ #<=d]Ƈ6~P*LMLm$ bChob+UͭpTveMĿ@9h΍aiFh2}%xW[u|JL\hN׏4Vxz`\ E0^$4;g ,Z ։lU vGxF+1؄mG<,9dRC/-̲R:9'd Pe.|B~@4栺pJ'rkW'g9|9O Hƛ;֠ kbl̝pxreЛ >ڏV0κ'&TV)"E"!Luh8Aǯ²:$¥is ?˫gLT3-u1/-8G4MHbJ]KGo<̈́bts(5xe#=5 z?8בL)z|D,{:d\'Oo& 2!W ~^ )LJҨX sZׇ<]u;8^Dc $)J։1/xL_oS;;;\t/H֮||_cinlu3QI~;,>3/5RcV?OIDR4iv@(|[X:sA&2fa -U>sQĐ} c/D]ZpTC/ _.ab@;p0[uB-ÖG(usQ^Z9T8k/}o=3]zFp4O 4S?%D%4*nn \K@nҗZgNmZ_|ߛ/7l1]I.3UP"&+e#A)AxA3ze1<gp^Kg"V×bdG;oPrAuBFxiS?K*I%sEkR럯XULgԉ RYB-Pv1Yc XNJuѹЮ9Lu 3K>=6prWb=G 4Ϟ6zĆq2'Vi$(. ,c3 \!&ͮ5 J$Vp f^q!kI/6,3H]?%Uj2> p3SfiH ҂VPktۆuqS ~V ‰QZ"L. lϟpz}MIL!q(dUM7Rz?'щDS$|T_xj[_M;T f)_Ǧt*V dՍ"ą~52fs|.#c&DYԱ!y%LKiğ?c39kBet$k9L;㴔;0ڮB^RPޒ%n=)Ԥ #aAqʈb N4 p~i_Y|o~J3 I}w`knJG.B$Uk0*t(͟-|}AB+_ [w_V7N|("H7}K#;Ϩ< 0i 'jEn0ss2mu63CNϦw:րtH 2E8Bqe& kn,Ȣ}GhϺ47J) =:Vx3( ލ_?}AH}% &W$~ߙU +,W.!&˫lHPeS^1sg[KD<&5 T8 usXy><5Gj8g={Rz^-j,"kH=^!NO'\gjZWh$5ޔtKt\5$w+,Ŷ5YṕC7co}.HOJoKӐ1&)K:+b[Bye~kh["3>֭/Y -ςmCF-l!]zSqâk%5=b?o3o 7bk3{D=z7V^r̍aڊcRy˥2Jȑ_|&hMepʷy彚Ƹ䯬N7b7u?3 ~L皖5\-^(*DL^L|7/8鬜mqV~|bD?%gxp }1  6 2 %̼N&Fn ȓ6V}פ6јr6+UE خo5q]ܵoB-F?īHc[MgQ\YمYZv.锼Kݟ5WYxc;=QQ=5ٿtIɦ)j=C eXoͭdpӃ{1{9;fKV8w&+-=g%7n*Ͼ>43|\56\Kx(qPPyžL! 5ጪ;M$ӨL{R̛Di}!P"zSc|A4<X#DW oFIIH4v7Fu*b(缫6M~uly j*^v*L]|/F$pjSA..6|3Ȃj?]7i88 HSp *jN]!QV"8G1tVTZ|]k,?. /2v$fPKYݠ%nk,b^B(j9O|Nۃ;  !;v -IwjO;(eqBܕ?=swm3 Uan%C8SAa;B2lg ~s=)C<+`EGܬkTH;ݙ!7/,AkgiIݚ"gE!߹#0ŽBV\zƏb6î;G-E)0oO=6*E!j|V!K6Tc+7=pxe5ő{.nmEoE>=$UWViXFaA`j\O*QA:%&\z&>?X#QayNh&@Q;$ՊwOl`x |0?8Wv)_x`F,E2YŤ=!i2Péx YioQhܵ Eb\}{ [e)jr:0!6D=L;$4U?F}%#Z# %L2 ,:MFzb.*3HE&@4)u79~YF™Ƌ!7h7q:gA'AtR@Kl߆OlB+s= ,C& ^c]&GwY ¯jVI\.[BT2pEdnqF] iDh) 6w.n5Xjmj_RX|T3RB-E|{cK= Yju#Z{_7(r⣍Iu&c1XJAֈo!l:,!s"B(ҹf(KQ3{w賯f"E Zӟ|zxyl`~X] \ ]ߵF. m~kMO7&!H>/`Y7%тKTm!2k)m/k}5MoDlӻ"Yb)bABmo$ŗY6gż#%ƵYE(~T4ަ(#@ %ccvEܷh?dZjAe8tVțdXyjhH!DZGl^EOD1y.%Yap}-}qƑuEcBB}8@&urYdJnr. <0bGdA]jf}.Ug"<e-hXpVj 9:n)IFm<^8[\\.zlB(0(-_k++--UOS;5i!FBHDrYnZq}H1ƾim:ߟ4r{Fq&h ȯdKI8,V f[)y.VhS&`-YFXvgk^"ȽSλpp~.m5C` 1pQo+U<6|צǒ͞cv<`GG &0ww-sBGs\ܐ43\y>'f\> , ,VND=KtN?0ěpw5jlD3`;mT8)u4zxm8|̱; [c3ģԃ9P3#UVAê8@B[:^[b|w Cc*7XbzɿF.axke@o`!6^~}7k޵|7c/0I >V~旋=$2䒏7>u>m g0WJE,Zs{ۨ]Ym\6ۜPa } ,}^BkT1+um wͺ4ItA%CKsl&3 b%^$Sr?w\Q]`ԎFV`g^:mS淰T;B'yV!Rz/xm-r5!әg_ݨ)[vI#M(K C 1Du|E(|wtZ7!l[n~з:aю@^۝;߿j4KKYKDz .j{6N B}p X)&G1ֵQHA6C-%MQ s5 c_SVPD"GqލёLޏ=“Aa$t)f_c;ln{f:H{*k;B*y jWI]ʎ Ky"0™F,yW9쉅$F+qāPxc=xHڙKJM4ܞOij>:t z=4<\ַ8HM8OjU축{(!P1K!ױjF}e:pY@gERػĺ/s"JN F^T\ߠ$I;JHQWz#LHi #՛)ιE$ŗC8^J[u##j9H7ZFW" Azi$R&!Ku_IԘm.kYao$ӻzwgun~jK3ry3K tk>3&hA[(0B۰]G9fa5M(Dv-2$=Fua4aa-$l$M?)%GGPQzҷ:P.-t9}0o]{B7Oƅg@X,Q7Il澔޸qvb<;J0Gx7Ě [x},!㏭bmE2/ptqu.ͽĞ $6C]x1;U[)y3T~_XMJg!c!Kdt\-4/e& pE:E$WqpV/pJ^CXtTDĬɈEjUV{ZC'X{M 8[`eZ/RѮ萝“/hވ,Ԉ7jyp~5AhO }χ'95QrAzd#"+]b'sOzxf"[[3e@=GC@ TvO^6Cb㾹8YhB3g4! `.ܒ:ބ,,z1f0K d*{C$M0љUzJ5RtW,+}.t%]! 5JxNK j$FrwrC?&0AD-u}EOOu:8G, E (M&V]J9"Ў ڠfug1P AܫbkPOKD9Tuano;Gb㲂]pMÈ1ڔ-8WԤ* "#~O4g#U~RDBe*'Cqʚ3Q˯GQ5!El}Bp"ɜ*u`;}oZk3ϮZ + y92FȳKg>_I@#꿒pqumB, )2fy|_|\Qp*xZ~w U.UZWw nZx ]Xs#+#+Z߮wdvaBަsC}Záq^ba򇆽 tgO9R߅Ԗzkv]Kp\A0s[ɒ+0ƃ}oWLoFrH0T M5dK)F1m©]*`*EOȂ'\wMŕء2g-/dXp+Z P[^' c%ݽՒNrMqO/yb`/KG\E$`ɭz;'V_E3-870] I4ϼu@JO9<2ۆa[ FUK H oih5,.W,E|Q ;U?{xnfr瘠MmdvsyW*%HQi* Ek nIq2kn?^^;Ң>2 6QfUY5$3xa+_h,DvOc m,ߴ4 7eOؘ >ˠKEֆ) tr%g.,}aj$A{j@$x4ɚ8u5Q b'jZӨo g,3m_)>'tCvT]Фye 4N=9dulM2ȧڰ0p#n> wZe#~7\̓m)jU9+s)^U(u$/r~W2S&qeL9 ѼV&K$25j[]v[HVެ''7Z>$wœc4NY: iA{$u^q"oñ YI ڥ=wLlކka'GdN\ %u#"+Cˣ[ 7;pY0m2Õ~%di) (JڋSۡSwXth17tA_k:!QBrr݆̝cotFuc3ҥ.N:0:\.U/qb]*׵WaȜQH N:kO|)"7) _+mLt$@q^sƒO1f eXQ h} {]r=:Ye52 ?_qw[[L 4 :ڻZA2ac5#[dV dNsO=-WXR}D aME Q" vSZhmӜ ;f\aݗC Gt˹tK> 9=۳,:-lKt@c/f(E5{LKo%JE1*`bzׂ15Ò&rE7&U& #W"%dIݔul{~oV|g|i2Qv)hv]nbTTs0n~ ҿ皢G])s+T/Jbvc./QljI,%^NV"ŠqtߪIDNm A%OG-7.@ q W<I>!:ƒMh0 ?BɫGgfl*dZ{"[5%_5K\2G\ơ,K놤+Zg(G1: ++gMK_lqeVb@\n6F%Ft*,'J=>0'48ڝƁ<ɜJ/}4sj. 'M)?Iρ=VD[-!Gm؟\k$CW3;w `ڠZt}ebY=$`$DUSe\ՂNild/Lο-IV{PS1D7NI2y&5kMK韘4L5}IjQaʼl̷,;y:C]?WWT3u juJa[ܛXHJ HC|r)#pfC-\Zdfh|Us/[!p;NVG+e}Wxhp\َ\.4~n TY/$>ZsbӶ2s36Exp̐Ig;yWQt7+R7f QD?%d*-w(l{$[C4>ϸT0R$gC9Y &\-C9j4zW_0.[`UdcurtЅ˵}&Ǭ}Ֆ׸[ e-!@?׆%-8Ql7 gKDkjlmUq75TܼlG[kVo5P[g3jQ٨J*C 7&6FQpbYdmk)vE9;K*ijyD@ R& IRi1,1,wM" h{ڲ L4-u0;v"QO0qtbĦC)*UIckG,Wqø1p/QDx&M ^*%6iϲSP_iKu3"ܒ/j@#0qjؓ\7 LmvFsM.8]JeGϖ0ʕޝ@7G>8*B.3N2rS~f^]@C|UoD(̹$QaLoT0q<߼}լe`ҋ|M7-_kmQKŪ"!yD((oezYLm7Tc$< ?;4N\2S敕 \5*&oG_߇1;oABe'wo0eu!G,@;(ҳ nO`lQ81[QDL16ǚHs8;D@JFaqj6[䷢_Z>-^w]/H-JAjI?F;hAvtRٷ.r++Nj!>1MdlUWϥdDމSBhVȰP4nRmx(R`U 2:#S i){Q֠ Za74+ JbD29b xiIMW6pT4MJWlVߥ1ٟ~Wd,-LwKM܈!gmq$)[9f$_`]' ٟ0v `{a =`,`z 9F';uǵƌ}wU()Ȧ14 d<2yȅJc(jch9lB@*gԬ1|&hn,E?K4O9c1WqlPlt {qrE?X;vr}wB ͕[#oa) UW7 ;Kg 9`4`E('j)'*4m'Z+M M\IMu,$qh W|kܤyhv"θ~4YfH^P؏I}tڲP0eFgp)[>O[::e?p\26R&ih{>*`W$ }P>go03t8Tͳ{?gT5-l ;k?٨/,MvdUQVi$!OnFdq]Tҧn{^i ]~sG1u@zX_ߵ~'"h2UҀN K/'"YG~{9TM Vl{ailQ0βIyQTpl{9*9U\_d`}tC2/+LB׌m`\ཨ3mA V+N9[*|> v|գ:ҩ@Dv gv?aԨ|_Z= P 2js7#m}N^gV+ P"=^p`(%q~ gD>6w? _VSE]kB3&\&=3s݁Тߎ z0Nޑrq>ك- 1Eː>[(p@s댺#){r:R2X-!ԑvdҜ5wѼdr@Zܞvq056%;f2V:,62+OW2;baK;CU˾뢽jX!&60yi=EH29< +NOzU@)7R-/ 5vL+to"+Λ'i=;H($@ ԬM}%(o$95vki@wd`3_IȻ| G$n:R#Ug#R+W1,-=O^S/+F) {OyL9soQh0>$}#rVYwBbN$m9Q&9i8¡YpQ_ p&k~сѠ쿄*`P+V1hV9>+HJb A|yE]7 }Ξ>tؑ$bApz4uӏ;1Py2jTʙ+ N+H;&ε)0ʫ]}D]{;ihKTAA L & .ď tEZn%)Op@rd$k"&AOWC+ d>͈*:~roob䴽'ܜ;vy7x"(0g@a$.~ņnøy1N9~]Kyw V|$ےHs)A]B*`zﶫN5!?bՅ;`_M@cI;#Y" x90c{w< -@]<8q)n{]Xd"i.G2LKDn0i7L0O>Z>*> 3RLߕsXY:[pr*Ru\% fY-_.R2bY.EX%N\Wϸ PW)kUDꊚq}/l6hy{% W\4|ՓM~~EP&F)YD pa6dpf/  Mט%B! dA[DW dWgVS߆u/mee0M#U˨p&f! SBֵQ tZ½lX,Ք={>c$,e :]>U˱sQew-uΌFCѷŝwI ,W{lnrt-w߉d"EPl\>YT|D!^U{B5#Q[3LLW#]>/Qڪ6A+gWb8};!BGo+TyL=+m ޴'ȉOpB{:Nit(!y~f"A|nq3J]v?|KQ4RL7-Ȇ+nԹctHEIS4ʪ.CCUR av wO.r%)T[K {lVj_CiأuMSXQlXaܛu/׈^7'x><$t_#ٯYM̉!o:*֡|L%#CjZmpCڬC| .l$x2<}@ 6QzNy-2$W!ĤTNBؚFfX+w2N':3 %M} JVK;o^"G߸y7VKPW莡)B~М%7J aUh]ѡ ܵ$l`R?ĬH!nvU] GajΚ-08dI@g *k[1 j1u#A ̈́pMZ'^63|V:+T:EIfAmlK"ܮqߙQpa5+[0^)MҲkpcD*=)5f-0+ɑ>@,6ZbP hBlk LB`䒒[TR-%6ُ?\N|1U!2%پ G$LK3*AP`nE%؍vn7 =X]f,FB2 Zm ;jo2Q=Uim?B?]a2dw-pp>DEazBG X?E4y4Yd8|L'C0!c]{<>" b.u>t*{ÖL%ΑT%8>E'ђ8ڿO!D<4'6ȺQ۝8lq3ZG]j Z#NEVSC|- 8P@iF9ĴJ㋲pPa)3@ f"ԦCVߪ*~m` JhHV"9 ~*UӨ. 0}0I~#b5J3qa=,P=T'=Xc^j^(VM:DZ|kMQ0fN0=_Eofl8Z4y?ZҘKOTC)v/il͔~ScϤ"{t<# k ztJʂ]yz Zv5X7/nrWYξx+ m~h'cdY2qzaż6WKfC6 xe#cz  Pu =ղ ^+9OK֘R Ծ:d-Dd,7l2ɟ[J:*~vhqi)V䣉2_ Va]Mf46:g{*̺c,w\lD)ɀ CÆE*nW"Ƌrq_]O29. JQ[~|sQbw3#DforPE^[<zL(*ϒ c^cby d71dĿmvMqiUQJߏg;j4yz%?rB*o!5ƨvw Ա[p9V8+$ԤP69qt`~!l4V2{ *5-q ;.d\k: ~Z17I*w}$E!lTq*'Wm)R+0G^&Cwl=S6ALt}gH R~$f?="*'iOR_JUNvPO#)twWn@ &oz\? j۶jb].gZ*"$מD et)#y4tMr"hDu`)<݉@YlNf*Uڜ\ilT0=e<Ҫ,PvH} wOKcșX[^2띉wr`戫B9/ f= (Ek,v}{w6uutn-1'v6RȾK@?O$+HOťY)Vo`v|l!,z(kT2:SřX^;bGOp\͌G8uεGN/%|c-Z t,Ó|pη D1rAM]T&ѱFO [& y>l 򇜷)i/ߖJ6Pûcֈ<TǦɅaT[[;`"~e7Yi+ D +v1L 04V:/(jj1z0[Q7V(&i ؚPZTNPLզۃ&+/T̯:7R}W%iĔ"IjBGӝ0Wp)3fo<3}jf"/f[$d,#$п2ؙݨ43 sìI*?9X3g_K =)2ԏܤ:ۊ|*v[i UE|x7гv)\HiylCm10j#hH;tF^'_ HEA&L~bB1K뢘\m;}mQf͡6\ LJy4F~Hdl,a=\m>fRʙg&  T . fgnFB n\;R.XHc4fTRZSglۖ<OYj'Ӗ磱ZR.ă:72,Yu/jP3A +*a^2DurYԆS",Y^&el ~JݹDk!d(Xr53 95DpW_Ӑo2$.y^m6Gad>iE5BMr?7 ^'!C$}i\=Yf&z1 IFtg6gA"H]#{1v^Kq?HFA,Sezr~QBZ\3$> WK݋=<+oP[`VYHLlR*HMR#kF!,OL"ZaOޏ{/̼D%=X:JS ցg.cHUwnÿ ~^bgИQBc ׿+?=/N[0.Yf۪NE ?[ge֩ 6X׭[jų:Ym F7<E, m=4e*}=V(sֺ76XU$B :&2~=Gc1㻻@_D 3c3!0 8riWAtG>kwBĝXj >x%-~m`a^'7VmPȹ E;o_3e .s1n"v"AvpzNsW,\N%Go䷸9bz"t/K$\u%ĎqN V`gva~c[nB<Ά}S4>uJo{t(2@$[pb7sd\p`'LvIDQ `qs4y"Dv>,Bjz(I8++[g6 8gf2w@ìi S-_9Q m &>%dDte!:@(;-p"|3%|.^P.E/9 $"=4m0щ[KĦKȘñީ,a/X&wcbٍaiFːТ1!. :f3(UNZ\)Zg64H l=\7B=J1S,U( t} 9bY%yN0FJCPA$wTrq㍕7=_N!Qk!BG=m+Bjr5T`ĭR0 ^T/3ԮltB8E\?NÜ\'UF-~+jkTANLIOKBr4xiCIHXKc@U s|zVVG"+Y mK%=|;=D$ ޸3HXo pQ)5qܖ[8*c4{bx1OknTɟ Eӟ ѓ4}"ly>9#o & mr!7OGCf_+0Hper8)y -0/(Osw)"%x6:\fxpu8^OXɁ'}V?hx!fkiYe!8)n+ S 3:צRFzed4n$9b DcܛVyM+?f._)qA)-BG٪HXے;w?/f`_'jp~=<׸:hCZL75}dT@jOֽ&ff8DO'd[;Ѩe,Q&>$a3CӲ3Jo(\E\Ӄ*ԴH[ɀ#Q MA/v~sC1q}gѩ5X@wL)h2+Y'3f uJ̓:M1?\)g ide HbRV.PXN90|~ b!r7B%@M_Q>39KPVr$ H OJԿ05[sŒWP1g1a%Pϛ(]l>TqXKxT7 ;΅RWY[n;wPYq»WJ L|MLD$#Y"vx!9F5ۡY!&EmZȿX-,}V;jV d|X :R9uK9^)ێa#YjDt2N8w>h^q':,-a<ʥS1G%ءA MD6ltR9ᜡV$9k }G-.mɏg$W1?iilJ{gC:/3hA3*Gb@If:f7i9} +@&8T4.5˔N;.6B7)Eh;Sd WЌߗլ.~j`S#w5C" @zRZNe.WHΞRF2'ֺ|ZoGԕIXqqES"x~dVM,V1{q@Uܖ9UY#6?o)I{Vn hW sxkUQC 8ٺ!RUNH?t% ?_7ފrn]څOW̿n#t%jDXBXrvdxc!4"efR$/Bzoה',\}x?2'gZrz#qyjfBfޑQ1 gSJ5b_zT\ӀsKZi#(!qlRRIcqqS.9NtO%G@3 P[<'< &GXHY~lǽheQ[Y,>c+KclGsP$eiRi+Z^1w}y2[%Cϔ]/̮ʡf^I1OxA:kD!PV3[e}YSZ84}h2DKicGtlGrʡ8vG 6~Y "XXԝ.uHZyz|V3dRܶ( X;1%oIQDVGxu=ߕHIxcog*T!\c-.2"W) _%O1杷1fU誱N^Bz Wo,L8Ά0ӳVLc{2&Di 5ʡFh RRj) i5IfPʣ^$ 0gDH~ݧ VnݑEwb 3Lr4t8:ֱjX8N<1ևХaY۽7YHC9Oj3!)*ͪQꍳDZ}}ĵQi>kJݣFO y״ݘ)#Pu?7ZJ"EQ&$#\R0k ̏W+z6&bSR46^ήsB$ }2@]La7nlF9Z9%~n p0 [p_)C{27p9U\F 5R cReW1PuN+?,wm|J 4] GZq[/bV_D$_(q hϴВ@bQ\[U&#0VbpPuz]TwFIIU8}96tˠjCv3_ (/ e2dgHy_H " .*9Ҏ='b9Lㅴ[sDZcɆ/#ݕq?.~ ϛ[q$E.p1]P%^SMh յ#N%?4u}J6ֵr>Ku$%R)7T0k ПUX?LohP Xnh]p;(c;jQFofI»Y3e'P"yyأjóOTm$̫.zffE«)H8,+$19b@ 7Nx&ʏ՘vfK6jQ{jEHL?UCpʸmjzA.vq[AGn%ģ%qmE2P=Ŝjo Z5 {{Ť[ڴdP0NCUmKk  -5anB%.ߓ$g ,z o+nS@~vP 7-E#vfI#H[\{U^P1 \g $^s~y+ކ!ϛ\<ʺG0 &vUc{ [R$n@5m4\ٯ7%Wy4s)AxtȺ0$* EUw2)7Zol}WHNTX?Z0K|DxᓊIde^vi;@V~߮yP Ql #,; AܙK>`Ӥ6'~eD{>繳{ mӓ!3\>sJk<O?%\rΕ*$Rةr̽v;Pj4Ƌ0coE4-̥D"!8(3 kKwjdaCzpbjp-0er!1QKM)ް]JkXw,!8i;;7w fhZm@)sSU*W. g[Z"lE u5Ý'Me$,$|ᣢ'yvt V! <]~ _+t\5V҄ oK@e >z*t$fRئCCշaM'.;zmWOykMԭ}c}TB|(ZoG2+lDW!S6^ˣDeIXzB&fpb.lBapɇ%~(%V Jp|w'@Q,VI>mKtPnxs8[]Qz/~"?[8f^t5tBջ#[ЯrNeX{oPr"_ZWRbj?'6I=`y[=}g;ch1t󌸎 I"dyE1<O &c22}RSC`P𿶟RY-" ,)A X sF u*I'S}|;өڷ+ 40_::XAxRh]PVGزۈ! JthLe6 soabȽ-0bPYQY?St1o/U^A$(lqj+kls [wW+a[ 5Z¢QiXP4>ogyaR^/B#n= on|}GzP|JwKbqХv8e񔛖lpΑI 6z?1Pҋf}cLfEh ͚R u-g;~ 6Pb -sa6; {or L[ vD)(yIAdy22(& S w]3iQPGq ՃuR@Wt+RZr NK7dS\}Tlm(RceˑnTQjowۻ[f4Gsos]5*oYkf. HqاCEpPA2uū׻%OmHWTYTU kd9xGLspeH8Hn;ϗy3 h痠ƕ_߻R"+h5MlfPqI/0ûEz*yGUXRSʄ1r܎N4hI 9?ޮ3 H:xii a .{mFgAW ހ3B"q NokM`n#R&.bO2ݰWYlt%\ú lejd$"@6arVH+bT"ɿ8Y7^&%/-j9Dm0)zQ_GZJbs~D]ȯdסfKY 4Ǚ{gvTSo͑[Cwm|tݳ_{fWH dnGna-ӃGr/߁qO;Y? ;[F.k4`d\_gM}&UU7ai10'uD=>ZWz"SqI8M{,P 10:jN ˲z͊Lp2Qݗ׬2ُ(^w%KvCOEh@Cw&Fa fEoVVClm a;&l _Ksg *&Zi9+|bvfuaGa,ZyYi9Ċ(YTYb_Ms)QΑ*B%F5Yn*-4-0~䅍\`SgrZIܼ  e׀Svy) %{_8rѤ<8Aamr0<R|༠Yy\a;>δ̴Ǣ\Wh6͌ " s;@['üҭRFhg*-kP }eI z/=cl;3 ,!@{y 4x$#$=yn$ƔE7 v@$0@f9czP?sjTDbs򭭮}@ha VۻqiTi&6Rl"FjTXg;ӫ3Wcƿ"ۀ6h[Z~aKbS{4LZaRne X˪ß:IS$}bM^ad,M ؍8z>rwVQȱU'jZ?ogeZ7CnA@Ԕߞ**9pؗJ,engmЯkDmy_hmNoVB91<"&xf0:0ZcM\(#΄cWf>}ojYA;!2gܽB̰ҢרU]HorϨӰBD]rG QM?1u^*9UA$*K\aN yαٵ1迁_|{ H#<"OG(zGƓ=;M57R~Aj^[K[Rfb?yY ѓ?-ϸFDԬv߂ }FO +M7J>.rŠM1t`Z P9Enԋ}x)۔(cXcڂ\n`\j`;|w/SSť:Flþ݃6 #|YV9qm-h+oyG UNI'}?KKXIO+k/<$1hPlx}j_(T| }8s\Hd̠]M',uڬ{LU kI)j{T/ qNypDi޽|LlBj=b9$ix˶Jn4|YkXC,7Luun%7[H%TX;<3B?(N3WIAYtEl_Y ,V7*$vc>`# q?XMUNSÉnF m!7`Ub}a\q mf;@t,=)uCnIPۺ2WEfq7`J=ㅺ1?$hl+%1;gqN1\jZs@{)qGIP]sᣠCe"(ԌKfq[}X-aNpH56(fӶܼy^9*ں}zɃgme7M0ו_O <33_:39zS/U}8D?lͶdT]u/%2iS LZ\Jb䏮@m h>ҟYu'qc+۷eAm>]?K 3laS&H"~f1sk'WK~"IaHPj;eUtDL#* 9ȢSF -x&pԊM4ZgïŇ4UL%e6\H97v~Oٔx AԽ<:-?>.Z/R%!E Cٓ__ߙefS,+{ T=R6[ß~'"fI?Sn3Z/ZR֓fXHvsI[jgj0/5ZVRPpq7k(&揿8zA4d()LPXR [Q1Bd180%aʧOx}x`NMUg&>5Z/zZK~[>TkyK?uwS6k ynzI:zkS ffm)Y.s0*Ĺ";.U'iTZzZϊnΖPڼx\c,Zke|I'Zyީ'e@3oNQfP=DLH.Ah&`9~2|f1=y`bICBd?2jTnUnqG5p нCѣS9%eW?(PfFޔE@4'ǾqLwF֒xt d)BLL,0Q> ; Mg7ϲMXU$;+}*7#!8/ܴ=Nr1ca͂Pe ==,z& >zxԊ%<*_]zHTb8jP zd RzTt!nF{x괺bb`P wxӤaH w].L@YP3~y] ذ4 ;p 0>;f ݒ C_)NolfSbc$ v@2\Y^/w ]6(Nx/8޻$py&a,4>PmTb5E3 }8ZXOhiJ Z4g:@"Xw; 󑌕eIcS0S)y롖kwU' KB{D14=Ẃt&>La F'c& t)oA; p9bl;{%u>x%qe3)P뤽bӉaujL+YR d禮mf=Bc(4Lu |ԍO*G[dճҲRj% TFP§OOB-;-oGH8uƙڥv+dfxQ#>L>$yfdW{SgY:\e4pȉj$t6eP"u &sV"vmһniFg/yv֬ jtsJ[G=3_ O \oNUW-]Pg"yA췃,a!UNAv5t 3fq<M E7+ $0J58b&DoP"#\)6cQ`ijs;.ơ0zLijm ԙk6uI/ظ;"DN| Н­(Vi~*6n)kץKXV2SQfH[ђB#7}]dq\CJ뻰|8LEL"y^A#67 WA/vݷc /cPTPqU}O,oz؈"V)H9a KоE9G8CpUV RYEHyz*˿3dtL0Pq +ͳ*! 3ķOQVţ[6KxBcqq/w#۳` 6|Qm*0^%bZ"+ٵ[`r#,?(@Zj঴&B<=?6N;ịͼ^@d-jeR:= /4x/a\MdzG[g'R¤:f&7n/Q;W;c \L# rX⁓)mq. eF<AANUcdADE )vڗ?ۂfI0EeCxϤl1H24—{_4HAG֎+b~\Lg XÕA'%/X2?'g#H;:yCUg[ ^BVl$x[ߢހwrټ=*l\N6x@iV*gl~f fn#Nɣ25>hF]NQ^{˗ʚ=Y$5`#= "\7'W!@eY$_w#CrNM4z]1V,qV#9}ƾBYCG:t%?YX>i 9C^_]='zdГ{g>8^O18eY]!(qւ)ɧ_L,q ҷ)Yƥ*oK#L)pO'>Ð֊SHHee Aa]bFL tɁ18qL7#Ybz!v[>IEsSr@-H}>;SUUHJŝZ` 1&][)u"Ć(XHVj4|T\=8Rq=D޲Ap)oHW\j2srwOb0 IJ㤶Ǵng& 2> `qpVIst$iٻHe,6RR1lL ^72VQF+ %EC.>Y#29N8،"̪bpF<*ff*X[kqVՒ,hȠjғvPj_Z,vG%R.z蘴Wr#8ESQL c7][Kw"O@ct}Ibd(ž}x2Qr1RhrX$*Ϯoue?UZegFŞ W,}jX?6#?W)7@$=WMcIe20"5b3L?t':FEOę_n-.P52cV X^?qxw5)]YQftO$:˶jӈ_~<̦u^zY 3?6zXﳨ11b?W68dƃX]t(TgFp_3 g\9)}3LYNi-{!ǰuP[/yA!aYrG3#i#{z7sͰҿxjmO.MD|uY%S93rh3Ίܮ`N",2ΉcRl"p]mN0NJY)B$a.J-cDҰE|2BjNMbαcsIz=|r+m6kBzj 4t.";>b}A몊Ÿ0Jo@yw;̇o4p'Һ@6?I0W6Pgn;eQDFpZ@'uHf291HC ;<=]`UvEbP 1. ? Ǜ"yd03887JGqo8YL֛N `sTCS_ ΞC8q>Bԋ{ȵ`3fPjՑ:q:UE)LBC7bgȶ>F~W3 ,^CBLݕe_Ħ8WEOZ[p 3*=tiq"4>of3RGH <G ~ˊC>`9x!#_f.:54~VB('fP~X+Nа[/Do0'_90y*;MnPK"<" T͕K]TfۡmY,_@44%^0셄$x_,<_qYŖC{){Zddz.e>+Cy0F d3rTXuqL ?2ݨ3n 윫Qʇ0^kuUMr]6i{m|8Bý!8'~뤹jbSS(!MJHˬRiGRUӸG ^$+) В=zVDAarxYy,jPIv򊍂ǵukמoFkJIU}J7RohiHCۅ WV#Om7]x6viPih>$4+żDz-4C&//4pw1f$SuTj9F.9YTX?#O8>~tBQvlAL_ qRc+D iG& ú 9Jc[2SEhzgKBO pdQfZ!GyĒ/y*L"=0gcnZ_3I?W:3x}k0.q6•&1]ߨљ'0wHG?Uu즳&L$]=Nc! <ۃ3Ţ!#TI6LM~Xwؘϫ)^CH_&lDB2r' :.[^tNV΃9gW(Hcm X'e4 TH61'f%Qg{ Y#1] /CW}hPmY̨:6طH ZHn'Zj.w)zPyR^)zvAN><+5I՗j&徆J4dU܈[psӗf K4SR{,<7glE<ݲ[C tCXœdžZ$ =`~jLT7d\L Hm*3ϸ} Gɖ`s2t5[[ )c.HIB(e?lNFl!طQ'ڟn(qY҅ dceHLm~@u;O ^W4옉ORpbkڀ@9a C9~]J Fq8VwzStڜr$5Mnq|yR$8Cz ع a*׼%YqʉENr7"lQqVɥYN6<립11Jy%ܠV|&+3l3'K \n7!jD(QY=s9zcpiԌ?ݹr1+g=O}mDc><$1F@vjFtӏ9e[7 En 4R-7* Á|̫{&T j @t6gd &re~Kw>x+W//}o|#zBUARV2(kE- pqIne!H)noķFH Ldyr!W>Y=t / ŗuu#ll-~YӁßS^Y®X`;ݿ1_̠H3g]+R.t #gn>5+7\1Q[0=N U'y _-9O )ZfC5 퀵g`&@ߜ"W(ڦUT-$4~#8,wmiPAㆆ\p?bD)>wJRջ۾i4è+40zD#*VNJ>=?ԣ^bPntjnp$[vϘ}7 isJ_D!;f-[g?Wga5u_ bҠ`/^Cܟ\mT[1 >&]›Y̱S o\#ŶloF9_~XSd3Hy_<蔘eC" 8ք N`[G_q|Nk^!yh4os I+WH%# >2[ CJ #ݕE{b15oԂX>l מRڋv"{i(KHR$M.)5`hy #Y8o,2rʛ4$jǣ=29\1X`Fq(һ- O/75^ Ђݾ}0)h1"yz>kNdA'h;,Q;l1޻k]uyDjR }8sQ;)^ ³Tlb_&-x,i2ˌ>c&P T(oQX4Gj j),FS1< VD7=D02 #>OcNo{_~|H~!:Kl_ ~*Rn;MKo21r.`*DLvd5HKHH;%H]7ׯO84fqHucE^t|^V@p{G/4&aHYU(ݍtWOWÕW5bd/Wv+_v:ANe#;dNJD"ѳL oK.c}~|vX%kP{xivGX?R.q&]4,#zS@87ڨV: T-U Ev/֑UCuԔ1 VGd%FLTvHzlS0I`l"aSxFKvM!m]C|٭7L,rO7.u h8l,U9,d.n79J-G2M>JAC{ß݀ǃx\O|K2gw~6j6ʊ]$\Ş\xaR~_eG~P%k&͠>:T*gT}2 ^aϽgڇf;>ͮ5jk&ɑpe"3A} 5 (Q1Z% %=a") R{|xG?cGHewj!{&9b'K6/L2ӽrݠ_DX&W!t^@UWO8tKYz?R2";)E]!J~1clst@u7f HlL Slx`[勖r0nOFOX;3^TؽBor4'}7z%J) lz-. f`*_CBx[-ϋI~=]Wr{ SsР'W  ^<Ň?˖"{`6þ3BEbEHYXr^ry6- cζ:/Vb\C̅VX7~їt@#dT(:",*7 R\_Z zkG 5Gr/qKZ],7IB |aHGdA<-?|ƊP(ZTSGc=/z8jy5]O#7+]&Ÿ N$J3I.v_EQb7G}#/37^ @K> 8S ub+%REaIJߢj(ؠmY>H[iraXd ?)mN-+F{T.#@z8ϐYJ~Y=&cP|euiш?Roٝ]86zBb`x+9M(xS뙈'gAŮ=pʒĹT؍3U{F ^G^#XKlg,qx: =sJ&֓&28Df%d`A?/E<&.|7w2-0S0K.?@Ȅ=m߃<3 #>ԔQUl B9aĦ܏FhtK~AκO`rÆ$;tڴYF)&qƎbwKtZD[Ovԟ9Su]^dYGfwVnny`:>,I ^C<~s}ls8z&ZL[+ V{QE4D]q(|ʜZUD뻩N\3 0Phb}ӽ$8Etv2iF႔\ }'SdB7/#[dFqi,Ԩ_ۯA=ԌEi Q߱IA[ΛY K#ƒNqY۠56 30tt!`%44Z`$JcBAh}y&( ݞxa+@tR(g^jr 0aƈb!5{}j\n2oJS}Qhmw?op^)!>$U6u5ذ2M8%;A{*Gwnv@CX&ReRwj4lTׂtLQt C37ć{'1w1^{#O6)Tm2)Mj#=hpTuT^)-}.HH]WcQ{'iW4\>?5 ^Ipa)GH.A}=D{o$Bѡ4 m9̎ꉙ+OFy-Ə%La54"mLDf,3r}M YUpPՏEĤ/֬27P;xhXr D6xXjUTn[e M(4/0?T!^~ꃜߵh ѯf\-. !k;0Ҥv\ZAM֖R ;9Vx*&F5B@m[lm:dsW櫧ukM D}}L5eCY8CDGjr :˭`A.Q$?3u^ zR b WC;S;pl\ ؅(sY4f>WڍJO'YB&Y@i*Y}L2Ĥșœ& z;~]T]y>)Imct&/t!N 4ac^AS*=AvOKݸs$Pax;)־KR|v'U#-lA,^yxNnu;j>Q}8[s +M>nƹg@QOX'{[yEH&]܏$a7 (һM~k=ҹDmkƹE}""S78!ؖq|#t`Xz$UΥ_ޣPtYVP;q zRaQpx+'/ v|.,0|:MW7CҐ.PT]JQ`D+'}3:͗%pRlצK["jkU5OZX#AOɃ1ҐDyc8P'z>h0-/݆J6"n25QS.2BN TMVDW[.-5a&uƜp@!Q#5}f r1quɉsɨtկ0@'z60%j?9eővj7V'3R5:b2f.L8O>8nW3Y׎|4& gE#-gZl=UuywD6UxrkӾNKjW<ǘ*4ǡsZFHmF쯔РE1p/pLFQNvJ _H ~62;8v\jr*-ZFk}a=;,rS25G_;]6hnpꃥ&Mϙ B*T&j^s_Q#^Qsҙ'JbӸgE`W'}m ;]WBeW~h0AWQǕV/va'`oUī*:X,﬚R SD PEFC(6 qq*)wdOܭə9Owx[Uց6A\0 ]\@Ej |x̴Av9iugT }* @MY*8"Ѕ{B%v+)_RaNs/} "俥oܫP&!qnTl"› |Ì;Onmډu QJ= =îRlW^O8"d6Gov dRiPHo;L"R~7qgRY;P˯@NqH*Bt##5#*4%' d͡K)^H\2&+\7W+sןJLTI,p -b2|"G>bi=^ >\LHn`G՜qk|#!@شxxQlDT&nXa0=~]wV (T/\O˕Q|it7zѿ (3%Qd sڂVVb7:H\Tx}1nps8=ލL(}^-Lȧ"mr,%/i .|׵N]'tODE*C B W~M+fJ2+BƀfLXa&v1r.H Wt0XOۖ*d[th_mOG=5!(^WMz-"U. 43 ;,eݕUIXx.b!r1%Wqzފ 42[.ͭS_ ;h?2׷-be(|Pi2&2xnypJ=yJ*Z(Z̻.Ȏ흂|FtTtle E§'u Dt~V3l V;c)WC7ZcۮvYDSvcſxq<ԡ#CmB MjzM n"3C!f2kK<ZW& o~ĀVԈEh=P7˻,FGQd &ј 3n_+@:)RQ]á  ÒJ؊SU_k9$32-PdMbΟ%/}4`'74>TvLG[F'k6/:e. OL0NK "+g<396lXAp)"E9gFg6Z3W.ٰot"04(ZC[fN:QD)-=(u]c+$&}4*ÝT1U|$+xԎoX/#C[8C9'PI';X^"?xV42#ڭ^3+(̖i{Qz>x\ЃE|5 86WYVQ'W^d'R^+8`R 8< l-5`R@K'F)&ٳa<Ԁ 2 nCI8[Y$_+-J5Ͼȅ^UL4?_bʃڗ]y/=f0~!+cP60+B&ؖBW7y4^:ξ]^ n=̪3F@`zaCP2c6r AVJrnuEA,+ᤘN[ޓ[S&hf,« rMD%EJ?F2I aW![&IݏbN= ]8H0iݖ^!i߼"&ݪwtZQF,a<`zb9 D5-!Yż&bYhy$A'ٜ2w*kPy;!?ƤnP VXcuq"j9칵!nն˨7Cdťx4Fq.D1.bnqGE+X;D*? AX"K'(.m|?ثF9uQ 8uX1f+ A'^L}tJ _{%-W(_@zd^F>-W_/0; 0[ YF(=؉gM0hfWD&۲Tgg/d%Nz ¨V懵~f-'ͼkLrY%.4ESBӵbFׯE(QdNSLPrl=(͚~Xwv+f@7.͐¿;cdQ$IhQl Hq7pcz3.SSW1kS]_]`9$Q_a&]Whߟ<zY|+:nnb1MN60|]==; sX^S* IJ)-8Jzl4M`姢G';)qpY\30er}ӋG{}8 +Z h*ʏDEGY;R/EJ5Iy?~%&J&{me5FNJ }EfxNd(j 4;4t.hkx5ݠ4o[kCO}MFϷ)"$`h7ߴE쁌KNb]&`_1RO\՝߹L/҄ՠP%г> J(?SSG~@I{PPP`ɱ#/z :GLSbvW`:65Q_a2F8Qo/8'9OLѹY _Ԃ)^|'!VKׅ#੾rËf-)Ȗbא 4 yX1sô;ޕ%@80Rfz_Itb}$B`ZW$2?gH4j1SS(Se|h6!QQ08fE23^–uQ>Q]Vtr" @_ONX3ltF ᱿k2WMDuK|^ =O"Hh17]n0\B6X6Th#gfГB'_sɪQ*< >%Tqə`E/h9 Q-=7,WE)j@nxx&V՜_oQ]Ð(D-.&GwY=ޛstM=>grϤaXF{%_UnLn &KKާuA!9awؿdT,3K,B0,DM7WHqwW~Bd9pOEH{@ ˴FnivG" +LzӁ1|ɆrϺf+tA.=0G]vQA&rXjj>SP3QKU+@g >sN.![($VkuZ[ZwgYUšJA 04bWՐLo3&i?L6#ͱn?A9 h?iWHt<6S ӒEfIxPr@us6s4{1@Hu6Z~v|%J44n)@݇sT5=(,͑r9rL,@#FT4|~<ݶZ{g^ab ±ȱVh=mSa i_66]Lb^yOEBiZ Im]bʚ oaJ5w4b%PBzk lj68\Eu6LC^C!qǧ! ˁ`IZPda 0#0ZSWLL H7,Pynoƈ> 儜 sOdSAd|W |[D`~] YcesD6fp{k YnЩy$M*iUG*hj(ncOu(YC>C6zBj֣tMK QS΢=)K߬txA q# &ܲPY@S:z(w3&cU. OYr- x *vmhe}bѮ8ŜTZKQ6o QMyr(r]1k%ƣcZ,#n6XUQyXz~\a<eiئoZH=2̞Ģ>:]Y: ?7x!ySxi$V ~jwp& ERWsx L JQ%FZd4]ڻV}3>E@~@S u1/E(ڃ!& h &\l>HTfۅ< GbM! :qK}}UZb(K_"mwm2%3xBUP6yc"鵾1ov x4+:oDX\-'T0ۂq>r04l+?2>ـ@&&E(C۔)`c$"\bΜE/x᧴NpAt>4oI E 25VR+v99pɉ^3j-ѬLpajU6u˟ut=9K6`}]i>;#Fm-kq2ts#ɰO#8$!!#* #&L)e}vm6r!eBH8/c\Xjut>ip?ad6i_^'l% "I)ژ/o;dWxrE'Zx0)z3\&Hīf,/ 'sph=әM-s=5jEJ5>f4Wc`-|^X{눚&wͷo~%pB|%0INjʽ:)d |tt;PF7ĻwNIv;=Ek^yFsDd) U}G\B4r@ ag1+; 58ByTF[>Vf68A`[X}tY1 l0P<'1 ]'IԠ )fBDcBFPĽ^ʸ٦OS^.qQ*2z_&MNp?B+oXbԗA6 }) )`ZCPBw`;'mҤi.oaf.*Ҋ(Ot+_b9>﫬uyK &ջ&J;l@ΓJTʛgw O*sI̟rP1 ,/iG_C"Y7yeKE9O M1Tb06#LvՑOȹcڬBƙQrz.TIIEZi^QsBN~#:gji@R) 쭜vĀ,9(<2Tӧ[.ʼn!ٲ0,Jj7-Rnd8HEPWfhq)Bg>8bwHXkD;xU0Ļ3dl Ssd.af=,38ޒ(n _ Ver~Ou?[8bYVE3SzȗgGPABB$6$䦬cV#UTohnIz5oq;U'`xĐ,=ݑfݰ̣^7YR>,CjyKv>459%+[5nS Ԁ#81 LxZZ徕oneYdҪވ^%KUYZS|zeCJ)[pT(@ uEzjn\?G։amo Lz$K 9J(v&Ccfux+(W EQu5Lmr\~c0w viZ> .zi^kX\R80ԿP@q] 7pj=ҷ™;*43nZ }ݶrze +OA_I (.O9t9F(M=<5L?-ɱ}n}7ylW3Cu}>A},4FE"ؤRd{'ϻ@,DVdcAM Z9NÈ؅o9\3Z.d,VQa$py=y26³wYA5rgS# f 32t2N$L*Q+oqD1(068|CӜ'_)$qbbpKDDmv>2XOwvK7O_Ȇfke@6aMВo֌c@sI4M\5NLT<OilmE^q]5zsLOx7;)iاiRe)J$νN|G &sCGhQKY]'cwĩξ,"d3T&кuPO D_N W ۙ\CU`T&ya/F/^YTS@`wtjO"iN# 0F/y%p6hLΫ?`#v"tz b`DPy0o4Yڀm y' LM=VO1.]c0 X0^+˚Bu}M(uÙC X| !| *gwRS׋Pk+wA'ůS)ԫl9@+y;)`pL>Уׅ5r+El"Y FfˀY۟ᨠ)|"3d(5sD`#AM7NqԹ:. 5S4oI8ͩA&{sb&,J2w(U{]a f~|jptk-ρ'3{/\J;Hcu}08yrC&($!zLiwNYNG=N5H?HK ʞc<֎BT[h{^%6kjתZQՑ(v_ Ɓ?6.NԵҮ..=`.l*ycc&@ gM?3{uQH+ԈUy. 2q}˂p<&w/25i@+gtNn4;8]TY 1xMlRuzLvCQ򯤹O4I0U>  ;Us4t#Æd$Ou5v:OJ"S3o+. FQ^l</"4k,>ɒ&N~ zkW5H NR1O#[)G:$Uo7+IFȋ;l@.Ud! (`daHV) EnnI@ i/Yqt$ zN&}P2t"71"9!VĹt\pRk  M/8|$g{P 3B15+wSoI"sMgL^oML)th YH;ˆrz\~!`/ g̈́ڭ#q950F,Om(ڃI<.`{=bՏC_&ǵeX)H}ўZ䣈 `֝鎖鏯_PHt*n qPRAM+eN :&!.j^b~vx+?Sv>V 3mNqm1 O1K`I96)Evb YPA<@\r+$_Nϝ%/ry`0 /R*Y`rRy eyon y>?`lCu ` dnG&SԽ;wؼl/ZpcᮠCkk]}i‚&. @OJ ~ ~_מ$PatD(Zjۚwq6K5qU랣$3r;vTSxek&-P,]/zEFTQgLRd0a?8wv(,庇Q2P$(QPfC q e5Pn;V(ʹ~'x7 \hvzC|3Yqe#$\0D[\AJ;*IZwNt٧ċjC[;L]/av.4a vh Q@"θs "o"kD;Aʐj`fNHaYw.Y77lYDs@~:H t[Jʹ4&1F8rC?I㽲4i{U _=HqrVR7s TVX- E:+4m](L,>i -IvuZM&7Bw,w'zJϧGW_N!ԼIU2tF g\$bKKr:K^}0`;0cEs/Ǜ0hD ; 8*=Lw ."N#Fi@Y PgJiU_ ZqnCK(ٞ5l#F(=moS7g g=,Y 'i SE{D~wN&#Q'фyum0Ϳ9qԯϯ5wfQ,}uK; 5KvV;NH3Ήmw}b `'v}7Ymg qBjGT(:Pը2=^od#WΉ"<~#GQYvfT:} hXV"*}V}t ol#pP"E&yZ},0U& #m.1h )~-%N;i# ޭ~gv6iP'BzDA; ]frQ3# XK}x*V_@9_]3aAXlNP쏅4'9R)R1L@JM3üylKR#21(Ej*ѴJ=;Þl&Dg=䉮&@=U0n]&enp-2Ǯ/{BPe4n4ïOS҂9 uF]6I{Qk9ܳOL'O n!sQL`XSUf%nba[>ܕ!p0|ݧN,oW)5Ѿ᪤A p+?|e oIbrs8秷s>1R >"^kaJ ZoH*I%ZW0*30Ƶ)ZD' b~(JL{gH e 2`#e%َ 5?6z[>ȋ.Ѻ< .[CwTCuGASzIzlg+>T x|Odצ`/=BCpE]ih|t"3I`.b.Aw1AmUN^u.3qq|v*]eg~g1չS;n[gJr[n iVlsZ s[0rs4v I#%3GxBxPm+^eNImf9yI Rsf{*|sKa$_{2dMGWE$5 ]Ma$bF;gV\W#XUUSn8J~,^guP>ˋX`'󧼲B'RDP7-aCWM|0T"Ej@|uH'kUʿM0Ac}"o1KE= ^tڴG)JP<^fHY("QԢf$Ⓟho&?*K%ysv/ß?;AskF?eVBr\捥֗!"&=^mVҲѩI ES9CKnCqCQjsZ)7DGl+v:kman Lfb`yvHO ҫ3%;)R`ր\EE݃S%U6iC/8T7dHZow7f"2Z5N7)H~;*DFRLi9XEhʃy6;coPx‹qڕUbC 3k; P ĦOzV.=n` AgyL'#k`[&>ԚœڼmXVnRXʏw57Kb/T׀I&Ut*mzzRk҇M'[nV1sPBܰ<,~@Z aR N=.p ^":T:%!yYAa76ꀝGoN?4u!+ХyXqwt:lY(U=/=IZ׬uS R{gKoҷ1].K(bTڋ.h{RGY&lʆD}G SOQ70*(tV2m0A)4\D$d:ۋoPBX=ty&$ԟEpt 2#Q}(Sqt9iXQ8k!YجTjxR\b#5i%-#i|䟺,3Oz'n[[WҬp,K9C핺C*=;K1*"Uf!)3}W}˭0 `|[]C.d>Pt6}&h8;zZ 8ȫHU3D},v/Y$18|L,ȇ ;U げNJ,DV=Ej wc5*jW >]"ʙ,vEW$R$T5,鸼9GR4 `ƪe š _# >Dtz+'eϏs/Lkwd`AU|ѺK+\]Q>߻A11 #[;IՖA5w;c9:YM6;M9zox.,vwn}% OMX 7msdR.2M5~mv]ƟX)ؚeQv $s8zu3`-y֝$sԬC"WA|Ré{4ф)ZDOy-.4]FZz{-/%)ϡ<ž&T?]8l+c֮xJS DZz_6P6;~o儐ck $׃M󉐋axU9zΪD9wUr>SfdXZ -S0J4jej 4>r8lߎ ܐ*v?f x R(ct\RiҼ]q5cӔ#aaŅ0[aԚ8vMM礚[uaَd7SKT)g:+~u0RNE^KQ'DPah;􏂫BȝO=@47c4a(A{eW*Ʒݿǎb1N6cd% B*y#ܴi'FHk>Ԛ݆ߺb\Yob5f}Ë2PQMztPiL'x:FVڊc E*nvD|9]:pJgo`Y[Y |%' X-QpP[>[$(b58gW-s4Ҡ:\Pr$El}*~ H@ U-֖xi})]TUkÖx! 2ebnsm~;\`rxRZRy7ÎXFbhXh]Nt<+{wiJ&A:Ƅb=$6ȞGbPx $ůxOsL SwwYlgzn*d jaZdCC"gЍ;fDdj $Dy#(s2D }fca,"OӆT^ė]Z)+rGdmOO^+$aPOt4Wߴ@%0 -#wB>(stѼ:jR1OfVe.]ϫB˃,]&m6B!g؟jMhie)R#yy zi1vGMڌsbt~-s,@Nņ!Gg0{)հ_[%rDz7Dy ܕi\V&33Apl G4ƒiT, |^L1DkpNJ$|_ {+/2{ky &3O sUP{HN%Rn+j6az/:cn9fj1, dc FzV;'! l@t@Mw¡x[[Fwڿe FݖrH/.M6Gy4#s@@KAw[g[$Z.!F.=X79Fǖ5:]O4RP}V .߰RkCoSG%wWo7Ε,݂+(] YSAOv 5Iv>xEaZw!0jۑef'ÈSANtƜmc\ÐA']|(5cXձsZfUQk*9Ǒ8M7R7̳AqP-yV12}%",NɠmV޴f;yVÝ-upxc?ڧʹ'pD;L(_`Wl3zPΖm-&9RJQ[BZXQ^P׮:$U|CmpC/`OIM|y/ׯ^ܗk&V{# 34-B+ T uYO/<k\tZ׶FjlU"^v]&D٤C(5r̝aՍ9Sٺ{*P)@g0!Fk6tBT68JFeَ@Zɩ gvG{~H?7=KEPU\` EqS6.!X5@EbMxkq\8H*;S޿4̴x 2m\k-[.kZnCg҈ũʜՏJΣ]x&vy4ȭ7?pTgMk6"Tp꿼?:a3UvVa.:=ӆH_63j*'H#Mɾ*-mIU:YNo}*W6%p?X%)D5IHL )!Aj M|o4pVqUwePs _oS2Cg IIIu8-rczUV6Wɉ0E_~zϱD[יPIsl֍rw^GAb$$<7 p͕fo޳C n\YR*f`-I֘{.0Է P>FY ˖爼S:b0~{ [#T3~I@ILOH_cA 0 9*$ݸb/zx5>b3%Q\f|ȈkI,s])eЂi_tbkq x%D` |2AzN/z߀hZ@(o\ԋKs7(&Ӵ }ڼ ׋ڌح(4H{mǓztnIu1#C]pg]Tp2JX,ለçr/l>mH^>bĭ>o(wD^>''1{=X.]6IS]%*E 0{\ފrag J"qvyt+g6߹Ru W4 tґOѣMŋ${8Y`;W'KG?GkDؚG?h(7ͥ-;F%P1i9;JφKMZl8AX8,OUP.z0@3G)`" h`XU w͓7Ů2l?%_p&^eЬnWr}x(DQ_ 3oCgJX,iHMA` Nڃ}Z=Be%q'rQJ&=qڹ2杆@{v1c$A;t {25ƭ@MfsM>T).2=Rnm?1ve!kd/N*Ě%KaςEZЏk<t1uy.3t, Nj P`AЧ틙yJ()x7H=8ؓ0C5/b>>^A>4l)UJ'Wcp[kfEVCMCDu#8q5x@񘝼cc``n;Hf=( ޓkWf5>q 86y ȵ @S>ⵚWվubIRPd7.ln{ʰ\v4$ gb t&!mPM!8K;|P 1ƨO<Po oiO{.ߡ/E2792E}Y wDEy_=!Q qe߽+8AVE/(#nǤ>/PWK3x'cWHR*at<]՗9, Q@R T!W`)Uh&S=ԯm;֨( sF'9mCͩn dDo5( $ȑ7$= a@DzPK !qnVu3D#}EOQ cMj@y˚7ۃ=Ñ8=["er=Kw"!i#ȩ#Y] VA)n3"ouN89:^^ j9 T<(#T6J=2ڒ0O 9|P㮍e\#2&΁`;Dk2oKRol?ݱ;յgxk) 𖕣 NW~XvЕt RgOzg"l9W+4虝\mxzf]V {ϻrI9L]o\ivp|d^<\>C$uP@6^mY0Hi'ؐl qǕK¹["bw xrPBh&ZO=D] sInҠ Cz mr[EƲfVd E&D*x}o0W)KHl=ҤrCԱ zkj'*E v8Fa‚P+8:O-l e*TH ZʚHD[^EK$zڐߙPM5g_wMBƟdK9B?i~Õ%x;m$M2&RJ-D/I1G~`´E^btѾzkl@U>xCc k5^,d 9kJ@. RG4;L.ޯNeI$ C# =aany6kd f0O_p3 Lx׃PIzm"FR)g/Kpj_.]Ka&3 eڷ7> c&-沧jbӔ e&+[lzJ[WB27 q&;f [h=nؤᐯt00hWwt-j.‚UeI }n7؁%7XGVidm,rىTj6jmC!bWG\&׾F6QVWjSemH n3vJ' ;a˲9]ǮiXa9G G* <ǎZ1&]pe!YNy-Bb덁>XY(-N|s%Wۀ%r%zxWoj>-JmY||FQY#KU N{4Ae&#G lgoK|=H0/ּpt* yj"?N%e&Tx63i(% 99־S_!W4 <0#BqB.+")օᑐv^bqJ 8({X")> k.i_AM1G~3^^j鈴ppa=ގՙvf5}Y|K&h`:,cdh~4aWgG,kLkĉN4#yv8h?ŌNTFeM{բp CU](/o"gldThT2ULҵ9SpCUmLF<}Jxfj3Q \"D[oo5"Ñmwn]Q xۀv\lЎڸ+,")=JGmSaxXJj=>eq +d#IemDe.v9ݛ2Zdw}v$.!l@+=%† x( kOK;"7 -Qg{G8E=ru"bzV*+Ud5 pXoS9egzɑ[_E'ʂz?| vn jaǐ#4 s8>;Żڹ:l\P'q#y$`tFpS{B|7M vhyQW1q4U=^~hrTAhu%̝R[;>))ipy?}O6b)gnOMNȭYcYe*5M !eS7 rabciFir"|o*ԙGN5\DZK'N*Y$U9pCdC ҏ'mۥ m%u #@!]ΐ~xtsn릐~:JCN yª*w,yA}Jo%unj̵lC5:B?>> ]?L3cXH5eJPj_=P#hpu,/:NDҷ2੧%%*ghTڈ]-K|AOtDtsTv޼×D jw^ul#lt ujUcy/\c2죢hOy_3A'Uuo: ,[]VЫbjW^5"4kJ>|jE0?ʥb,э[OHXqscN&*,]=sE})@bj3}MGѩ f"-S H ûztHCuX`4,,"M k0/ڤ&HcpR[ hp(2C wej8ԜIMK-=-S}.Gނ5\-ZDÂ^ц. 3:feaEt«4+VTiQ^OVp}V {ҹfȴs'$c)Z$Q|4d^3Z?&q7SnZfݳv_` 7ʧQ!#;ȞB7|7-Av|#l!kyp|R",*vUU iNri!|<,QS z'|EEp6%zaZ U:)̓tXϴr leJJ#.8O@;擩dSr*a_3o%JlWk.R<6f p @ L;6s}gBr WEKvg85awnɵp 1Dp~+Oh= @oZr 7w-cBsKy*"a9ⅮRF $vuZɿH{|s/+S6]iRZB?~vFCr̤ʷ&~3i,'20zB"6919> v7$.^tQg w+:Mkr\ǔڇ 2'L+lPd1NTR endstream endobj 28 0 obj 74223 endobj 29 0 obj <> endobj 30 0 obj <> stream x]n8ཟBvQXO HYi@#WGt>R4uwϷ?oytnW/^}cZNy:Շo|v/yUjNi%]O| _sՖ㆔_cs^mzWmasM]ǧôڶcsS1疹EYY٘ w#rbNsmܳGn@?@?@?@?~_~_~_~_~_~_~_~_W~_W~_W~_W~_W~_W~_W~_W~_ᷚs~7~7~7~R~7~7~7~9w~w~w~w~w~w~w~tF8#Hg3ٶ l+ڲr Y,h6;сDt8. Pi|Fv +KdDTguNm-^F ̸>-AāNą,ua`ʼnALt&8eM<#art˄F{ǁN tޮLvqpvvΙK2=n=azf1OOg$@;<) bwW<}ynS~y.XG) 3,ud@ژ4͛rPvc1Kzp endstream endobj 31 0 obj <> endobj 32 0 obj <> stream xwste_ul۹mvR1nl۶JRI*IŶm[VWݯ7=^s5CA b`twe`ad(Zٙ:):3-pN8 qS7;Ll tIԭ\mOLb`ĜƮqc?)jncg+μqcs/33ЅBҕ[ ?"q=@[ǿmmL^.c33_ƶ@;ZY욅+@+{s+{+W/@ha 36&ng`gw?HTNW@mW_ 13]BL\JrӋ?4?ET`ƛ92i[9ek_:L-[o)|ƶ.@?+s ;̬L]&@? 4XGD_q׿+u0prXY,ae;?uCk7wZ_~V-gV?9Xυ?t(fkP!?1i @WWlwk?[L2f"i 4Sr5+aot*;X003Ϡ=S߽$ao`feoPs#?¦nZ7@O)P(mW*fZM[ѷRCDf2~` `IMBqa.Ԙu/6hv$=ij]5\Vδ7ݯh,, 8:5K^.]ۿ@/ X ,6^"4J}o(DV#H `jS(  __)fڏȿjIw8,R!3w:誶UaR`A"Ԗ 3xiM̊Csx8pAxV'gs;7 .VHr3 42NJY,HH9@֥!Z MgZ&Ͻ,|ľ+e((y%CܓuOe׃BEȗzsYhT{/hB'f=+_|!ǭn5:3A#..=VxʴSU7u:t%oi(b|u;IooMē3Ӣx?NKN%Z}`h8} {FFUg }Fh*`td>B:jǝU{,<@-;NIS\ouQCxF^\¨ߟc`:vN4+0SIo!Ss6oT ub.ox{COV>ŷ ?ED|_Pf(<2BT+mGD7AÄ*`]7&Ⱥ\mt뻧wi#9Y,%L=L4]d?O5V5,7l@H D`)- tkޤ].HRz';X87~}[V 6]Z\J[ ]!?5c|$NS17y%"ѧ~ 3 R -EZ"79, !ȅhi"1CA{]?P[, 7?hb\++f _tD5mmb;ca)"mB]mlۻ.ߡ>1Qe"D-QX8fzveWk )k# nP esN>#a>jj2Y{oğg5en=IΕp/Y(}%>Zx>5J"kȉS%U\d7 3v Y!f4a3#R大2}*R3#B4ji2L]n/͑naKOG.ԑGG 2`e֢ذ%I:g/oX湠01qTPAsMAke'{[1Θ)əRt k7M".H}4du@=G08ZH|GX6L5{9I0^="ģ1_+!5q\ u5ccIFcAA Kv)j3z)V!cb= FZp`i ĶCa0|`#N v} pm7E5!]5TᢓN.<] XG0ު3ON@iDނg˕~gwӈL{qYZaU7f$ Ueǰ۾!ƹsW8[qM~)gu@uK+-z(;3'2c=\Dӓ#\V, ]ϧ Y!kw&` un$*OVoJ@c̼k.1"Sd
x-jv" !WSh20OWb~2OJs>Z@䤙U}ӳ_>&2%J EP[gXF?iTbؽH oA84W$ 켢zP3blcG.XD⬅!Q5Cbjt*G1bo+6Mk7^O9M1&QYFm:h+G ljG%DʝoD[d\OO:byT-mA!m =u6wDl5*O>a J?: 0o;HTz vf܎/Sj3}[iY wn\ |0չƜc-dybwaR_ų3ԗG"mnSߌ<1#")$"ѣ&gkM!v]QTv`8k hؠ7kٰp[E/~KS ğҷʯ6F([iE'@\ͭŒ~FӎpCc:jC>l^ۧᾤWp+~h"7ߒրpAӢdr_Z ?.=)AMKJ -9e)!őƆJ%9hywp_^hq&Du } 8愻-K ޲k9誳c_HҶ՗O:lS{y8˾jۤ#l`!'hŠ=8,?1Xnf-gNhg{ՇӿI$w^uЮ G}֡ 8 )~bʰ BXwٺRF$Jt~:,ul5܊_ oZzydKntKt.UR7ucÖ3$mw@>阂&SBU]U>!Z<9ȏ^&C[yO;NDQ"4U9mJ S %7,m0M44Bmg)(pיWOkV6i."u2y1-L`GN2f2!iQdt&rcmIQw:=}7{':|?2ձ\.K9[$otG΋$cby1m'X\2t0l:za1܁p;y^BD)Ƒ>4u)/#s+Szn)jkMۑ9#dm)RPmɘcDCMO<= !>f EmøWKU?O/7]& .w& 'Nph=R;W2+ᶷ|V62 QdWX}UCJ mNqiMʻ[zFuOfaƝ]ufi;פ6JDgYT,qx w)HrC{;i6ѬHD"gla]0PHK'\" W(cWh`#r+ŹWA[zmp_/Xc"(zm^h\=i[㧳ʭn+|u-7NpوcGH`ڴYTxcX*_{b~53^G@{%fnPn '/ &ĬK<5ۉ%t;*W CBt8t)vuƍ+ V j( K34}?/ /xnYb-URt~xez40ϜFŹFt mǬ1hT6CV/HD.}x J} 0 ((umVSJp8ڴTj #Uh8f=E dW]Z JICXE[.ʽU mqn uagUdlt<5QM Hӈqck\!zKwyH9lz.8T~opq2 n:QsmēJn{R೵4*nYHW~]'ʇƻ?g9 $i,Xibr5  i;X'ƁT2r' hqp E hI› ; 3t^-Ӗ2vȌA:AoU%g*eoqڰK c?so2 Dr6$ES'_>aH0:T_juR΅ls9Xb6>QKEOnuԐjZ֟.ZX8 EȽLJߤRxP3!RrXesXEu d,{  N! !)G1ׯsZLn,3&/ŠP46,&I6aR|Z4My?ѵCͦϪ6`^T^ʫ`1ɯQSDMF~?''`E3PRG6@PC5-C$Pv[|?8 M3f ~% !%4hNt[,,.=@YCY[W iH Y!F{>.q;#:-G<|BJ/jԙ7o ui+A|}p96jp4wkNddɈ99G<9gw$(I1syAmGe+b4p[jmI/\? "Sx^+S4S)G:;--X**#,{6ng7~,Mnkrٴj ^\Q<1H՗64}yU/) EQǡy 62lvǙ`x5>^XwJ$ pF-8RtlQ= ˊi~yg0!_RXbtH{%ɒx-2Mh#2T~53i=UhܢɔI19n7QuÊBdzRw٪,(ynNAVyݿyiϟ9{ h!zdG^R7:SjI~vTf|f}9KWB&6BZEk4Bɸ=8ln.j~O_?~FP5T=Xlh:3{9Y`po':E'PVDeԧ7~6J=Bo}EAe!GG!"nEʗ˟Y Zk*=cKW'nH>o :e4eVRν~}MyEa9[[M UCWkob{e>CTf\ߨ>Rڹ$Ksuf{vj &: OޕdڜfWL,lDq8W'Žm#I0 .ةfľׄb`;Lɽ2Iq(ۼ`%gBů?BE;35V-^3gQʳcLifx4GXB#&{/ f`V&͉,73]~!2a,x;JK"CZL,8 C$ f+/Œ9f3^*&F<. m2 (?5d6es>t1*N^K40;%zh0.#P鋈ޝ`~ 3/ iwF_)޹3QIv0Xf"ٯF`FR]!TTu_oV%>Zy*Yέrڦ٩W$G||I]1kIsL #"$tu3#,ڮv)GN8ϧ&?G×n\J( ĈV ǁ7b9U0KădݧG A@T-/ӝNӕَwǰӄLiKd/Eឿ( 9@_ڏqYN7 s8!x&Gt0@ ʪ9J5}86Y%BmX@=E"mS?BY6Aqуair=//U(c~=T ֝Ku^K \w@Pf q.Wa2Ic;hJomۗ TtFnŀIJXA1ę%kț̾%9戟,›I7S"U-XjVܤ;hʧ-V||LsfhTH"|VvP6 ?ڵ,l mmJ?'S`J5M"4+ge=~3 ܘn);$>"qې歼*ƞҷ&`eϖ -b܇s 'j'dx4 I6dluv^[E>e@7! թД˳/dqn~1ND8gBOU\ #̲xtxbrm]lGݵM]%\5qu!/.hB֙ Al+[𴿱;9j;~NN+趫IP^$MtAFy-CPGqdZ!1\6`bmJX@)X0X+3*ToΏߧXkBNK4}DVfdU:JHނL5)HxlνI,qen=̮yf8 i(6)U׌:fJz(pJ/ k.5JGRKWߓ`لy2l"̬ ]:F+ 䰩,k -ʩL 6˸ ql2G\0- *mR %;WV m08FYI=CU 8 WYծMGS;Xw?# . N}{N)}x/el"ExP9d "Y:̌8!œ@(^,}Ggn>PȟڎyFm/syūnل;{G~F:v<7u/($7|_ſR W*瞰#Fr|WO9|Uw a㑿ڬbW}E UMh`LR~]#p7GOh+s\\He5Fκy?W~&1fƒ"fȊLnl NApGxf+NPPZ2Sh$}zw@+u>Vn_6>6D)@rƚk 0z.M(1^?Szp=\Ki5`ێIx3sOҶ!sB'9nTS]Oz B5b9dHa=٤$@L_LbǬ+g);5VBXocw@zUi5ԣR([]FgkϊbpZd[X=<Ȃ+˯V3tÇKx¬\IPaG]|^7}f;"` O)w_ }R>ҩ@,qh~7|5DY$ٴ_ :*{'?xv͍oL"HMYF wkÿj'Sf)O$jD}ɦ1h1*4G}y§E8IMZ ||kLW5>ndࣚn;sXS nzxBS<=QDuɮZL*x7&|YڼVy]ai'* j̜A.aRڢLfыn2qp6nw'!o|p3Ӗ[$_THk͒H :(od¤Bz,P SOLe7.s^Rq[m ,s3>ciY!ݮMtAKo,G_:+Twt9X%r;{mU՟煽GU$)H"@VQ, 6|4Tifp+,u)$o객+)/:[< LMU+62-[^*+!bURe B 15a|Aa \J(w,'X 4@(.'r?Q/eJPİg=?Mc . ZќHCaOk'ȣyS33J ш;r ~9~mJ[FFj;edWi3y˱#.V|j),b)[PqeL$`TTKHwpSe{E^o߅*wz7'닒RM1&6YD&>Y8=٫_g 3nReZHv:QpVs,LOƀ*7N$y9N,چI *mɆGT9biɓ^}[."Ⱦt^zB?O&4c4Sf^ wG3%ŋ [5tWs~&8(}g,8k.yA``0q 6ibsZ,(#:KySһO.AQ+1 zmEAt8mV:v"sIOLg~G+/dΌ6JݛxRX$ni3os`e(Dik%:'>*'&Zb 7g;CKLnV1a{핧4 {_<pos;ࢶxxA';6h1st8Љ1 b_n;>B7\<)\.M1rgTܬmvZ=^hZ@nc\ݿuBrϼS+ i>e>~Oσ] UȂ+!U!<:\`k]'9 * TUkB|Ч[A*)7̨7# 2)N&%3/C­ĹJI΂4i9@'R!$"@ uf(o?]{֭%pܓZ ΰl/i`LO/ NRF.z}DS+{'+KkoI8l5BZndLo(9I9\"ae/2l$#uZXX qY/KbҶaKoLDiK3=2aC-.%yN0lZw2쥑}6(l"jRƕ@mk{_/FEz5룟T1ˌFؽ[)1Aʬ?vzi\d.y?_aٹm/KAKb@J-d2ebA@.*>'8x!ꋃ7@WS݊ylD?pDYv'2C"7/劻 T#deAxjz%Vn=ܮ9ˑZwa*z 4ɓ䝿ؚP#q7˟L"`e:$K Dj 7{j0R kA p\C2ow@ eڳ"t; 'M2u$6S<&$ExmQ.~ ?DﺹRIju{SgXCx]F̍A <i]ynVBݒI*&n}]?ܱl. zW&0wBHuILCF!^y25~pts[̫f cQa^й$cɤ1 eDU V51*ȟ.4O3 JڴO0ڒeP*a2{VMYNfp`1qNo,=O=9uAmW]}l>-"=cdI#s8CHl\Ù3Ւ\Aڸ W.aCW&Og0[po.f-y*WH-ֺx!¯6_+ @TND%-BiU#~HdK)%x- ߌS[a.4sUh :\B_'H|0t\= #6uAtYw >Gہ{8Qdђ =f rĠ*ZCx!$~$޼(XJ,hE (M:OzGBSyU_]2SC+c]qk{ '*yY2,0B *W֎-ȩaD{`Ejۋl YijΛf'd֌" 7|B ۾ 4F$y %4бqH?N Űt0!9$..[Å`թSۏߊ4!*W԰/דJ;E1eK{?rgF _0f8Hœ\D"Zuk JZnu 10n6_<#WSJDC? 3~9k(B'--'1Jgәȵg[M!?C!TOm?͞xih}*uKdDƳ.nC Я3EPwA5q\M.61Gˑc}G?j4F@U+Bł )V(j :@I%_).`Ф’MÖs\߁;7l3ȑD1Eb4l*hfTZUQ-cu.~,Qt0ZOt=ZVwv2J-a/⢳%o$/#(XṴdSm%ȅbVq"ŠƬ4%ePz`q`Rmo8?[}bum]7xMn9+VG7KA5VYWZ OӔǧfh!Oes_4z&ZA$ V _['}h4f*)J99dʌ'##c͗ WEN,ű0kc4:q;VjbcL=2aLXbwn|cѲ5GY1է  A^SV6R 4|k'T1#J*`TKdU漺94`}Dx*&! UaT!Oh pT6[2ƥ }WqAgV ty|.{c3iq8< dӆSX+ԓݵL솰>T}hM›*eh0VV:͋%.U F<6?pt΍v `p\ezTMz [|uעJwsڤAH$>xM#ѳw0F~.M5F]!TOfUG5˦\^N)ɿBق Ꞁ' Bzw(,֟h:z1ӂC&zNE6]D5)B,7 ıuN'39^3D1kF|'ѥ7;8tوan'ҰQX,`ORoK} Q_\û)0L;?*TTXvX5׏TY[u ӆdVRe=r ,'r`$MZ,y:#GTp-YM&G)r%oM|P% m Ϛ 8OIJQm_^X* ɘ/F}>Z"c-Yv[(SI.o̻8 ctoo?-4fsFnW<|<x,Y$!(5a8oÙ@5\r q^@.< ϲNujj)e$ුi9Pm^p]n;B3E q{}.JК>Rym"O2(9A* ML3ꞈz>cJԺjYr_YR}]r{ӗGȆVeR~F tۜNB$"y}-x(C[n!d4AK|k&"{(+&cV4;X jG - >JVv 1n͖_4 =N{x7߁p4us_)6;fq,4Rd'F]&u*ΏKU/ڇ2ӫDOg(Sd~q(S<W h)ue#mWBBkۿ;hi-\Q6z Y tۥc'Y*Qݎb<ҍH Z kv%ObzS0p R֗Ôa9%{Y-1K,A\7m;vd. =fGT{hFIFh0@rW.0KhƱxOqY42#o$}oe.2I2^sT b\+w~;LPE3]A)AW1KU0.^bTjwSmyߧu_27EfEqj&W";kĀ U`3@'GA-v!<bS@KZ0*9~l#/qtFXdn1/U׿G/)'^:HlBl,dyurCMP 3ȣv5#P:zOGGB Xc#rn8Alj3A"ke!~|Ak@y1h_XYo0yճs#t}v i.8j .սq2B'.-Etde YUI]fE*}KBK"``u486&SH1,!U#'.4LQ"p7BeJe}0YJ(\#Pk'T^ȒjOA ECI&RΦ86S/YK0h8/,%1̏ayi3R ( GCPقK|^$K+ysI)y}1wܱ HE()Kx&'ĄO]w,}Ff(#Աw_կY/yQXAmIL{B,@r.7lƈqQ~KYta fZM#ux3d#CLM\~ذbC0ٌmݵ;BCM!N4V ^dI(a~jIAP99"!&0#^"FIzSS=D9i(KU{A%=8R*C2(A-uBye!c1M>j3DdQ'{:,}|.}LfO+uЍh!Ε qvJ{˪Ʒg gVEu?P-i,O4aҁV.o묿X"qş=^LE !-4 Fx[[d7&.5D|dS㭽XĶdMֱ$;zպ7uJ}D\!88ZA"iG".9iM3H8ݭ3!xbfO XczƷTa)`D!-wCujRW@J9F6J֚*O,{7$FyEpSəG8]pD}ra<#XWt1atܝڔxV :csRVe;͙݇5&^B6o]qcAXn:'-u ]J((F`eYڼ`_یk!%WxP㈉l .%L^?$/$/8 Rn (Du:,WPxs5_y0%)PbME2mN#\ O⃲1W)F߸|Q>.)[  ɢ!*'C*$άc נK&M;~a!Z@|/T;sxQ3E 5!4;FѽA`ǥ@oW/uBb CJ: "ݐJ7#r!l`n>׼{~6ԑk$ُ*&s TYTZ~EaZu ^$wC{QgzR-Ͽu} ywu սtu]al?~II~TZ"ƥּķYU6]kq"1{K$ RX%ˮyT0j뒪…l8 )DLoMHw1\qqfNiSonVGVLО8e[&|Ϩ,i)}F隅4RX"m6A $nݍ&cZr9օn)^bxHOi@qhnzBZ탱 Sx@$Avh opT?jH]'~*7hmyK)&קRٻ8RxtV+aꮒYafbH͕OƈVX3uy؇a'L92X! JzEH5L5RfX( +5,Ӱl!p}^VA԰mo!.fnD&3Hu/'Zr r= (B9?ϵxQH?XAt.I&ٌ0gt^7uБ,qSOzKT'ux#aZ8*wwŰ=@x³(KNw]ٙ\8%e)ݭ% f溥7IYahlHp7xZ@' 9x1QA; n/fmj֏l$Sғxx7-B'+YiL8{/q:G2kĭ-}Xq'][L0y"<@yXKA)ɟj-?\P-F>=5J>KFׂ4鴩>E/Yqo(}0ݎ9;#gg+GOCB4!6-Z+b`Ɏ'Eq!Pk㵧(XWW8ҳ,uFgTAx^ٯ$v=8,1~M-VXS[I` &.frF<Vi 0Cve(5Bdpg+foypO[J0hyJ}lj]ucs8qE-<!bznط\  8 ZZc2jR4mTA5Y'ˤ.>oFEg c7h55ɷr#  XDB֖I<`dž4:lSQmU^=q("A?)0G!с޺ a'dÉq}@x(M#kq,Տc.ܲdVyJ k5ٮ~4=(#1H8 obD_m²x~(C{bl1,0,Ҳ6BG[Ujln?5.#aN΢[x"n{tʣU%jr+FCnni=$mTC€( >hNuBx5Et$Ӕ2Gp*@VHkS33e폋7sºEn\4 ŒM=oҌs/J708U6ӄym 9P8Yqm84rݥxTbRJ,gK'Gʶ]%37S4 ŵtnwpbSY\XT0.{J<뮄e,k@mAWR&vޝ|iL"is47XR}>?z#^@du% i:?@0*U_8;.7}p]0M.c~0+sVA{ʘ+l=ؠ6GHo_r]g0'uA&},F/aJyhA*lR䷽:jz]`_ \X8E,Ⱦ's5M$_޻ڤ-Ɵܒp|@*LF$~XޝY@Ie:vXظ:KS2az}tN.((R]auκ:={4w^ 'kf>]hzoW/g\ 嘃 9YB!8s9:_8+V-ktDA/B)DcΆ}{R `vIJk<.b29J"қ\U%"#^J (#+Լ64^-t1С6o1_@Rmq2:eE/{9)zNY{҆e) %ۛFA^sC޾-\{]"r=J^/9k2?V>lNĝEѼ9ŦV# -}f>)$P |ה-#nrBix G:F>}ɿgO:fF V%OKl jo*ȟhhY˃JpG7iu Hirs5ԉ5llOXpY/K&jm}Nj ~lk?$pt7#?&P8a7ed Kà{:"{i Pwo- rQ?صK=wh6H(}cKѯŲ811Ϥ/'&4ݹq5 QW,IqF܏xJ&1,v)arT̢f$ngTz$:8l>j#qm[KD!HRdz3YbPR P+"OQ994#CĒy`0 Guɦ\G^hAdZav. ޘg 3T[kE:?{3ѢqOVc)uW\G0 s4CE?0Zrhf۞XOr`Wg ,T ze;4_@GmOD۷Ž?y GNbVW`7ڠ/?v& zٟp#9ݥԱkD Y7Q( Fѹ=O!#p@VBEo҆YӳKTbEG7 2N!khw+Q`TšcOy\zu{>H$Ah1߱Zִ¨ƷHoӅz>2 -[a: 3Vriʪq_NdћځL"& (aVa4@Yz `CBnO$c+G{ /1+)OS 1{:mokl0ng {PB2rw$vv+5nrsk;Rlq+Fv]$6=U0HHʊ.8<'f}m3.S8dd: P%HcG%dUb>cw pP[ G?)|8f/D&ç5.? ̉48fHnPбGUPbcH$G 4~CǜG?0Z_qEGֻBb'\Ǘu^E6Wl[1@# F/?uHWY'tN^W1֟A0s ]ΘxQ1T'I^*ivHI&Wi)"Ą8mn.>b 3eh2wi|R>8>Z~,]A& +UB9ϝ~DS%AFbg drU< BFmu犰̟HZp$ d`2)#$VY`; RrHk<^Iz;P>K9r'`.$f_w':LG$ QlnWrQSpח#!T26.E@si,^$O~' /-a] csD~=/en J?{u+.gbgKSO>ã V]Pa7@uwBz1ӠsިquRٲUVqknWaʪ+)ma<)"5h_잨JX0 Xep7p@@uaYY`4B#wȈo$uZ{{|8qSoƠL]ڋ1 _(z:.Ęח%j⨝ɭ?"\X~}C֚=n+R9$L&X9=H`l\7c]jrzo8?zBX͂vQ/Y鄉${z)E#zⅾ!?PrKf;[?iL,PF-f,rDT"I@2 OLgso.͊W W\kr=~’`h3CDߢ$e~ 0Qsftasl;oR]U!'ݛ"r.z=?Umʹ H*y1_2@j ͍ޢNs$FpC sRks;]YjlsXfca <;~GMj X %Vסpa?#Y̡z]0YnM:}n  VgP^Dh̼5IyJV8YOޑ-}9|qSzDC*Ζ.R4z8E!@W800(i4 FSKrg@&t[em}c EQc,B9`!U`>ǯZ5Si0][^mG{D5hsмY7(U?U.{ӡd<\"ϖos)1ktJ<_BIwb5Za/}0 ^DJƜ#`L~ Ƴ*Y;] YΌھ8 r5h ' ~ Q]٥*SB0-`g9 oڵ\K;z1kV; 1.74jz#2>z@a[W[hŁG1 ÖֿKx Lt~ibkKaJ7#Z9&aDfM^0!ˉ#1c>NN#,<_BJ}Ťh)U#Z<, H1 4B^JG29$BҴ Լ)Wdh Y,)F_)I TzxiY%w@U3t 5fLvظ50⟠ 8AJ)|+5D+Qfe_Frb22KV81E*Lt=AeA1)#J+ReR8`:{ fːF Ɯe}i^FHx6"ﲜL境hdO]x9 9 NX/نXhט/}".(n%W߸;_H;Dȶ..Ce.(_~)֛ APjg(" R%}*qaNJDĖ}Z;@:HlŞ+\i=JIvbR݄RF=Tpo[A4QhYOO"i7$b)ю$ՠކd ;R'@E¡@sD 5 qI:;`t~PpŽ#cVnaM%6/{ײ}Cq ;Ezև7awţٟp] R^E "%Cl6)aHGIꗹv1s J]6(oRINZA|zPof`:pV'i봐ϋT^s!9t `wQ 'xV$?aWGيn)n{2駹tR{&m##p:[#E/Ú[yYF%58k73c+-SP?qGY7rY| c85/jUܼDc)˨0zwdQ 2E<؝IqKkGA]6\ϷiNc/*W|gHO((klWnĔ6Ify y'j**+ W;A[ГLl@9b-Ìi;Io^t9SCmï*p:+=!9Ap;bLC 08i6mU쟭QUW }nقųEy%WzzZ6D=`. ˰Z ׍QЕ&`;lc$_+ԕrtQGyHS? E@dCgի7u(ؿR Cvc-}iG}#L\]HrCᗖ7G pXihԓG (UԒaˢ衝jhϩ^/hĮQyzl6nEտJ@o.#yTx5y{'ׇ ~{!-m=`E70Hn:8wz=j7CEM5m c,¾W_,a"*S;wq}Bd3l,R|t@%Gbxɧ98i;?⪏Y$ϙ?wpxMRH7&-P(ywN t4x"U <9{OuĈ:oS"}ILXPCG=+tsDH~@ )FkG'~ )jYyt''Fiz'=3_^Ā"sid^S4Me .]O`J^Y\2sA*Z&QA\PAL֞qt+M+hRC1n=GUΏ"uY_L`H̕j3r#@Y;znA,qv-zCvpbm!){w3w<`j_<ZvaYSH+T+T Ð $Ko+[p-ǟC2NljVO(eU 9dC:#NF" T I Eq2d (KQFXE苀@;o_壷0RSf'%a c?ۧ خJVL<ޤhNN Rr z1pZ DFS+ٷ@0$n&Xm^zoy3D+ GGh!*E泉b/fskwH E#/H5UeaF9L؛7ZWD-O+uf~/ Ԯ6#貌Y}Qx :z^: !b@fu6Z[և Ȣ&gzrixQHg~Cl51&$ĸ. knЎOMv'#noft+wA̕E>fF]_)f`tTew}3I [U:&P?2ɐ_jɢ80XnIR2pqLZY\-f+ /|&"mסi+A8{?8Q{i1zk5gэh$!-h:Px._RHC$& wa&xKzPOc"19f\ gaJ #4 Fz,}s=>2`=4{ *(*X߂xC!7 JF3.Iȃ4TM))Ød 6<`4>N A`Ds$EkOpNO #xB/6Wպ;@aH*vԏ&Mu \Di)@i3 qNX:'d {7ȥ;\J5nLͯWz {v9ruj/Mw= TXSE˱ ñ"m0Yr/ď *;O9PZ84tw|=E͸Ca :Ůی8! m)?P*nF,pMi|4jv8p/ j;;O RUتV$GqBprSMc]Hޚ27r3 kᾌ;l_L>{tO7v?m 21Ak~BAU:MX ʮG'lw<_gj~P]0% ,J2(d0k7@A~$E.&u24K]ɣMxݍ9%0@o/{ EFQ_7Vo5(S?_Kf9BJY(xS)/aG+bx-J忁 4Ԃ Wm% gXᩌDY_qs1I/M(Pϸ GAUO EC]ii6䝿JNs_{tDgn><ӆګ?ѦB龽n)3dҧK]5P+Vgsq3qu%ˠh|6fq0w$ʭ/SnsS J;S>0OCUH]0Ҵ%J3FG+c]`WR)φX:cZL ѿrNui1thB^<1,WYaJp22h4MZ+ YwZ{7oކ%"]}ַ&#P<ԭX^-}!%u7ʘξ([nށVDenVS +&I<&j4+ d/4NDF6d)ߧ*1u ^ȓeOSLc|sŬ;!#]Z F!@SsԠ.VQO/VpTEeL5e7>P8O_իG1iBKr=5TfΚEqy-C뜊'1%} qXeƳ'MmzSJ|G"7߂VP?=/0X1 Q]LSuKZ[-UozXd^/z.nEXecȣ 5:P.`"lm˛6KGIR0%Gi+ OK6v#w}V.sz8.4jK``w m dѷ>>W?-#:9>џ4)=e"̸L&@ pVioVmpD O]=knVc 4 fWh0N^Y+öP)w_QWFZGiAqE^KV%u|#x'hqp^~'dY{,Pİ8Ⱦ6U>q_)("4J%ʶGIКyr|=ldܡ`65*~i5a%s"{`rH겳0 2nW =KYb"iHX! I&sqQN\98Qt[TRzvTPn@\>%6*UK<lHmh/gqcgU)wRs75Zo<.9qZv^~ G3#Kp20.={wYG]TYt$n`<׵,@emj@(h_ZVKSD"KM!C;X'$ lN B*(k煄.+c(E x8]'1Sz~n$}dk\80YEyK㰖0P}~l#E[lBH bk-}~n(i+qv by[чdQ$#R}&Rsⱃ_.!XZX]r[70^Z& msr},'$ v_s5+"OHbr_xaHLBO+PAqYQ4-/>q^Z/,鉸bv#=L{f^y>/?פ5b$(uU BeF;WŸ )|DǨ&1䲐71( 'DdNmtM9Ĥ(=ʦ#;Ny41ŻpZfll,"6oh`^URD*e+a0ٶU1+'GV|+f@;) 1pL7t[257:Jۉї?E)3g}#Lj>8J[1 mk[)e݀Z#~!夐7g)ڐ%8ڳ˳iu8Q!aW  OqNᏐ bZGIt5uYU[3O yD7 :2nEdTGy/b<#Lij8X>ߘ)Ux5x~TE=|S%l 0H}o<7pǁSX o{*F3ЫX>X"n}&V6 hhOO\A7V`=Cv(mS$ 2+) o.2.d:PpL*7^^i>>+ftU]WTƀ\k*<45s~O F.J^utIUxj)AKXJ$Z9 t+Ig|sXe܎n3D vKI - 8,11T ^k+eMP)R!t.z|m~oU$2L @ȻAWTJyOa %X?K "V)t<陥D">ud0oTF )R4ю\Bn5Arϝ{& \$A׋M ˥nK}ǁ{ݰATlej)Bz$M#慳>1>d@ q ɢ: FǓ6!)Ȓ&Swe!ѹ\@}nhr䘑HʾPʾл!V`J8++ $Z/NX.g,.i*ōv\]s HVo3yua.nndERuMK!fҙ:f8*|XJzfuI.A],"6bH,II.| %`T6 E(#9BۯV,"|Y_KT~Z0:c:i߷F\7̑y>j}^"&?QL`2;!("%,;u? PxqYi9x\":-:g*{P۫.XT!гY6gl,4~B- j%n9bD(1CA JwE^0^diTNS gSXux:hBWE+#Y^v->i>NZt:x$̭2 k ]\  U'dP&^s5*_=9qFؑn _Lg7/=˱gN ~D"^%k3 *Qu=02jZ,oJHd492cF[1:،b!X'`UpJ_ǂM >ӯڳz=~kj h\dxIgJ*UmNAYuoZ(o:^8[p*% Ԅ* wAP#&2ٖH!>9DOTVW3Z?zp?j2(Ezr)1˲67~Lȫ3 &?&+aqQgUen& { :="YFJÎs\r,JKy:8E#IXNh|pN-)[򨽳PmeD>y|LFƒʔ{*x]LUM5ގY%E&4hU4U`eayG%l/OV"37mrec" '_hG SCKX6m\ޑUQeEqe*비;?cL kpA82tA~f'I|(pG߾HUIVr"9o6QH*y` *s=Vyj(z6|A\M暟({s|5bejG$ޗ6fr5!FFW`zWW/triQ^Gk-3κFH۫Dw8Yʍ'd,F΋\rZ\<~RKFC˛$jYoS7|+>|ȞivK,i?[!Qu>Y"[^*d&S_n_Tʛ>|hf1(B&m0G}*HmO ~[;-+}:'tgblv߇8CL]˨Mt46~(m_tvduSr!96ʾzƥ#3RR*kC.AXSCb't\(-yc3{80LDP] tl"` AqOBv %oEACP7)@Xm8nDS~@q&_fXcd:pHpmXݽLh*h2e]@)K`~%Qwަ@NSS [[.ڊ6[@Rݬt zqFb8}*: KSΓ.0}ccSVJHW~fꛘEu)S3oK !,ٱϊ%htW >hV8Fõo0uҞ!3RwE+M 8oͫ-+D~5|ƉgFZ~uɎy]}1Nzz6eT)@Xw=_y^yu;_5 {MTZ/\!(rXhL؋p*_vWzpE2#dCöuAʻe'q ዩw۪ hR :jKk*g$FMnozlN6C'4d8i VqaWnξ"6",ȕyo& nꟹ㩕ѷ1t)C޼ |c{i1KrA`f! 'm*;G)&3ajlYCclңیX[x n{5k|q3LEOXA[wa@b5wG= dd5wC̑SY8ܗ'lxɪ|.my,&no5 Wx9*6FׇS:Xjjf]&}")a"Ii-([ƚbZT,1@rYpV@gȊdtkWĚ3?S q4:Ăv,aCWiK#/oխVVa|'6nF¡N5ӱIg)⸚rQaHԨE?&|K8peUOOqkBJqjޕ ֜D^O'g3٦M7G<Շr'eX?8:U{tc FöUlnU șkY=:;cl ߙ~b^ (~V1?-zgby#'S}XYڪ %ݡ-9=Sfx'oX/W\K 4){A v[w1Fv}#Y%Щ\h5 { i%|oq:fa8@L;`c$f^29 fRؑkMRKRLemgOG, ~9${&o,^ 1Gǥ9U3Z `rŴ.yRFU[ y@Rw$sS&mCIY%boݘ%`2t,g탮iVAk}lA#:{F}|KZ\MN`J,z X8}jz8ilۛ gďԔt*6ECAzPPr/P_ɼ!M1gwYa?i Y!p2Eܾ^go#4l yȋ cmu"BqíѰ v`@taK0`Q5$%E2УjH>]Oh؇H7빙8¦#{IJ=񪿢pjUd#2\S-!*/հe,50K @MMG7gdyoQ9h?-Kaܯ@3l ӷK=#A| 4% S,֬&Gt&֢=yPo,5ӫ=ם1?9Č[jg h z(":f>بa3 ]ݫdwa{ ?g* Jg m?X -&]T\0 _t?U|Dk3Dֱ ~#>X)יe i!$}uB/)TZyCn,JN&ˎ*h4=ALxdknwcQQ Y. /`s"gs-|gF%XJe#Gr&. p4DFF%?Z1\5HF琋*ƺpߪ^S` xHƄ)Ke`WiSU)z#9Pʼod#0 kԍnG,5&a/bzɧ37]囫!~Tω}sZ;ĵϗZ w3ŗЀn훭a0 />x{؁# krC\:j~ib=IXJ."_ |'"|&H%F6D+a} &p ;?к];+PkǼh<\ c6;$G׆^K$ 1H4ԑ?Hl4N `56I#B[O(?(1JתC~@[fy녽Tfm+ۙ/ o bj3FC? Uri{2Z/fwB0W;Uj7+jփ,˼}"gȯ!~IrɥH}.%^rWY|N7ɐlu Ź;hzNs;ꪄ)-A~M $Վu5z7 )|yg%˕^Bh[?N fpg<,Xկ]ZG|H*,ȁў\|.4V~=Wpk b ~Ƶ8Qp^K;5|a,̲ΊbbO?3q&K a t2P0ֈ&_k!Btutshgm"}g-v̍;+2+-&mv_xdhFzj> v^hw視Lz 񅇡U5b"b\?P}kʥM$ld8Z]J؜J^o,0k;ωj5L۹L]oҩiA:l.;jlĶRЎƤݿ,!RΞ5Z>M,Qh|Qqgg{=2 .;+@ݴUA%+FgEM$`1Kzl`;2`^\kX$*˜u#D("iU71ρS\.9xb傖!Y4gGn(rA#/|[ S(|JVY{4YqRC5W=ˋ$69>5<q$SsLN+#^G?S:n 7\NsJh ?]9J=FasdPW&EReN'eS9,- n|b,oA*M=P'o $aӕO? Z[ʐ/twMM(&!9R)q<_vCwuCw 01#G Z9bƱkaZ}@C|o Ze JG\WgXbGv$!uʸ)}.ʳ ³<Ӧ} yrh)ǹLBșw8mGxa&ڐӄܚA!έ6aĸ0FSߑR %K6hN rW-q ,2Yڴ-ǚv~&[q@H޾?~$͖Y1 5m_zPswPC2#@;G41{L]XX)[{)y? &ߤkUӴjI6kQTH]=> WxdI zra,M]W*s$K`\5S<I4[U9FB~<@׌])"#}iܸ,ȑb"dwȿ;XQ[fG̹mX4F$k]qw|ǘH㽗Lz3Ws[^&`ARl"J`gOtƳChf^)蚖G M| >@mk[<.rohϳ0N4|Y[MѡP._ VM=63آPs~s4k0'] *Gl0]|CE5yVV9QГ)xAU&9'8>5K%8E 7 ƴ!gwMȣl|xn.ʒW WX~C\wDzݏ}~|LfX7ϯݖ:W&kDC*=BHm\Jj¯0% r@-xRO^ltX\GdɄf_.};~i~F&8> VC56}z8珸6슭pp!.d'&T|7 4HO[6nVC/dm%-mSHV,G!iumC5xv<38YKΏV/@Z&i H [VOKf`X>^wWԙI@Bd L!XZvi߯X"KjxSy}Kp#S'M8A[ESw,/e- 2ޫo ~c%9zo7a"h wGlrΐ1me'#T'K^wG0Cř?o_兂Sh7`%)\TT9oSoF*TvJ<^Oqf1m^ "gݻN ')oBՕ&?3rCz)4ee7GT)OҦIȥ^!$|֥nRI8[g;e^(I['P%,_Z8gk<KKDi <蟨s( #?6xZ"BK:Id1+^MTz7Q|t(!GNnjuI͚Gl>*ccW,.({yy(|AE)CE rԣDΠz4۷}`Jp%u«g +Kpw6IwYlgO`֎M.gcjgAdߖ\@){)=}63&t}3$N;btչ1ZN6GHzz:_>щx#ơ;%ϖJw᥹z];YZOCC/Km\gn/΢}9i, '^nl5;x,rQ[)MZP؝RXJ!޵]LX=v E:j0My0+0dѤ(m "kjHζ˗H*bh<riӮ53^vpzIJ.3fA,k!V?Yp0lPOqRA*oV6Uuukr >S!"/f.2hPSH\0p\?"$ DzG5t~@[[JփrƔwlG^$GH:4~7i|c̈ʒsJ) /2op'Ů8mx *CoeUâN(a^A_y+31]o4nΓZ D+L~_iCuSD&k6O^7i <rPeA4^ 0:͹`oWgq,jJv[jS#bH$2 DEʖ(EE  H<ߚ?%{'< ܛ{?ׂat PTJZm>?=U/\"ZEU!. U B"ITocp#FU(J L/bmKisJ=׼ Du02cMR4h QO(mzZHf0raE\Wo"D7$7DUY| G;Y9c"72/ufcj% XڡpoQJ]OVx@4He28) %`ڳUG{3G-ns͓.;<:Ӧ*z*Na:N@6LW8ބP\)V"Ds+bG\)rFdSF<)'>+GLLEPYykma%Pr'jZBm.Z/6y׀Z|JބQqFZ׭ c-bZ 0Ic[s1v&$WW@( Hp ľQG}KTW-|JfEN͕$,P!@Z5uS%e[I!&vhbfgؽ`V:Hqah\-"kd/iŕ]7u(VZ ;q*ˀ97_؏s`̵CuDah۟g<,GǡqoI5Y6~9kSKwVAVT(m);q!NfEv]U=h>A*[C{t聆R<vz۸FF .<[֋up-e]PkئLǏJ uɝbH'NOZQ)L˃Ω JRBbF4VkZR`Иr6DZx gv`hޯ;ߡq{kҋ;զf3q/EsH %X>\ ӱmLZ&>pʆa~.P/d_E'M lI:/ xV;=rOo11Қ4Kd+J&^G9<`u|܎{6KӛF) nm ukpu݇#z#-C/yWfRid8yM#$s&x`lظ7+Emв1+[xcČ2.1F"lqAUeBr힟]Nj@G, 0} ZJB!G:B#FSS\s{Ue=nEDk1GO,b!!hYmxj>JGL?@PwIɀe{ў}`3=i!aޓ;+r-|oY֫wVID`B PvӠ5eRmrl%dOBxU9vhe6lg'n}fu!nP0Nό]P.(?࿛ q-ʎJh>{ 7z|7 $;A=Wl3 8?q3wvJ{k>z>f1w۞>q;*׮+ņ c";>+ʩ*B dMo%gb6Y_jwŭe! 01[uG{6yBzJ B{[ùɏF` ҷj[ QcN)!¦rE\"uɏ=)dBMj4<ݠ-2P6'r+;F *A#u;f@X >$KWOr8)H W%_Y[ԄW&$Z :b^s&LʭCG/{e{&Oء/+2B_'K3VQ״~ ߶#xuZaDv:mwyدm3R~}W-vФb{k.|XE7h,u utX?N(Yu@&!Gl_#_Ę`y. t<W!%F"I+}P1 HQndvPk= n(?oRj(mNj n=Iݼ8GB0q9< ʂn5LG4a9AV{/ z#ӠQՅu'-D6Iđˠ9f aD#O L!}iF E5X< _(ݖ~"]O%AQA^OwzpRNr `w1ȉd-N⪆Ir P}D;Cr8 ʜ;3fCo!j(dN`:XO%q> N_QZµrUN uK$J~ĞwGOqCYQ61Xb%HJJ}쮉fUGq:iVru;p7(< +08 Q6f,S}ML -{V",JY%Ë'qr+ګiẙEx H\nYPc27s1pZs}{U4CIlXiÞc" o@D$DzIrO^#:3#8ݘOEA .~V޼)htpVvLȂ$p* ff0U4DJ#{}t*K>/"r:"31V|</^wq_N$j{g!M0ڭ*r{BFavaP}i16&ɛ-@w񔙳]'o:'OtJ[1[%y;-N]3hWbvUϙt"#kvV/+C +]ΩJ>1", cA5֟;BH}M_ٔ 厡FM}`_GF= ?Wb$ o; M`-Kd;t2/,&U{C9@%qxdo q;UBWsED nEv ˨DQkxϵúrĦWDn}{XP Yf̅_̫V] g~#p5&GNAct_mh~U"7~5 sl m֎jEO,cFuJy!h[j)~&CXEAh2EV`|~ds%nY,{xq= yKMwU;H# R\$HkǸXQ2.FN>u2 | yY"G_jCB3ҫCJ=bl*/1LG*4@V|:VKn}8+q2VŸb<Rl.p֜.Z4x[S{~WKVkz]MNrJ)6W3J.JyNt${:glJun3j)J1I6x0AZ\ڵ{hnNˊ?BS6.!H!U2O'^ ɾrK8 ~clz4] ,{e+exOgTA33N`黵ug) [BOQ|kJ0.)e7ciXQa L%ʡ,7|m[@}oELb9@?O_7O봐<ߺ0*rxiZX SG_7,~hpGubc?uAhB<.+=;Z룩n$ 4n{wF6P=s9/(Fm ͛[_ E}e q NHmkdgw-:PE- >yvbRd7I)^|Uxk9Eɳ ~~$]M/iwXYN(O9Ԛ 55*.ȷ[,}㋒%{'RpIEF6a4ȃ渞PL1 @s$@;%HϚʨu?ӳ W1ve44% $TL 2f.=;3'P0ky\3 x,ѴA7 6s6׍ 83F_+YEjzB냲N=/٦3*cş u%<5FɤDցݛȴ5aCuFwe/T'Ym]J_.9Iס8UR{A6wqb 4Q{EtBBTJ80ʴ\֓WeR-aBX_d:Ҳְ3\ /4^Wǻ¿|_ߒ'g&w%0S׫v"/+H޽&geiFZb`Xj#A|6" KLfrfvx%5!Gtg<[|LlZf0\R+@NKs0+ ރ^?L),fP=>WRYuy?cc0eJyJ߿'|z +%*k@=E ;t*7^ZqUO|GOv:<vC#Z2kV ͩA_N,#| :e +j'v%E4D㽤/2HM(XW,@ 2D\40C"kW[$-*Y A=Cuirݬy=9QVқ9-gqK+ tXXڋ<.eVl=n;';MZNx,!k5FD F҇$cLB Nݡˀ8x CuMc/lM[)u7dHh֘_r+V=3`4OhƖ(ˡ[2gEf ^nę7L ̉rޭJ'lވ+7"+6{Ӿȼ}Z{SxA̓K` A`3|uug؉':#.p&x^<PM4SM !V 1C}~GM!щYT&ʱ5z|u`GZ{Cxė^k㚞-ՙ r˸BX'N6SPT550~z`S5~#A H 0;m##qz~0]ӿQ75ng]A+s0YAKz/V~ |D]23t>6*=Xi,! IqmU yL2=t 7ζ_18MgUC&eesNrekhQH1 vKhKJ.ǐ=,p'dᥢp&6 "U]փ7ou}\)[;FeT6R^uH1utv˺Whqɦe(-%uf¹YW]LkeM\l`22"\TK?fݚFk8`ؓp^\B3CբQBS68BS%?;͙v@dzWn`3jl>F6(䂥wmHEe&f*H: "DUAO2%TxJ]Z{9GW)$K\<[ɸB߯ٻ2"nJӋwߪ!b-'?;zGzfǦ{ 뀇$rɬRFw-p,:[D(NJm'!XS_rES+ =5nlB`O٫`l}|۱5gs uC7G,nrg$ p?9 C=`cJeQs W y[󾁫͟jiZ<}'?%o ƐZ5q㔻2Ämu{x!G_eOp{IDn t՞Gsn?\!aRАE8)c#nSqcyvbs#d/&9j : 7z|P~ruL#$5z]mb)/(&@fȮaC߁25՞5rNViYR*rgBLv$u(B;У #_)E60$5`҇ӣCFԁ׭ƾ|.F*y?SU0g'yX[ka_yhL~bE䔭 ESHUi`l j`LlBAeƵx<[b(M?~yeTSSnzϼ~9`[-OV&1.w*`Ʊaw T:|ri 6U 4QD㮅Muz Τ.KӒ' +S8!UX&r:;0LڬM;'{y@|Pτ風͚y,xFn‹/tcLKa'Aa0uŗoZGu1AF;ˉ,CQSS܊|CiUSލfNA*[g</%)Tķ6 2TASPeȇD_ fVGFewb]  /_9]<(E #AGlt"ՌoT #~Ke4hm 'G6t)g@}}5=I.zT'q˗W-XBR},BZH"2 jfIqK?W,$ S p.imMbmrSO8N! 9 LP5?w`fnE[2eBCe6T{-<‘1[KT稲zKZCAY%?ПуFQw﹘+}H_m2ԭ=A^Tʑ4T.0oi&͗\R֋/շZ@d_ż7yvQ JiB[xt rsmi.,zmfkR;q5~ߝ?UبHEL)~ ω;ZpHŒݳ-HѻIW]IsͳV]\>W RϦ[*;9 x?TV'tl++9qI#.2'f[Vfw̅ůq-Ps+?2Nxh0Vh(֞[çӤI6$YѫBQSq>cr{ډLWO $qbLߒPJ_CߎeA\&eBG^:mh?ڡ @kvr+شN t2: K5+f}:x׵K_.z4E iK G#a۸c'33v+OkX)YY4z}*˙gNzu_MVvb<7A \TaY}`\5Gҍc6zCuȩ wS5â:לi+q5X(.@6glu8 ;գ8&x {K1Weڳ"h `,E9bII'nC{9E/ h գD$RhL:h8MQgYm%5a,[V"t'-.N{.Tl/b}66;L]ܥܤ>ѻ2ks=ozъM~ȀQ(| 4ƞ]&v~X2T2afIG.|BbBiOޠ2dU߈oQA&b/Lv CxX>vV"6P?5ʥyqm7is"h-KmBGtdY):V,VvG7RGz%i:=+lh}yBShӯ^0s]@*v\݌ZAi$3Ln G^mvs5i& zK/ Vrt"DEjpj?Hr(/0Y=iY펪U;hT4͢{kl!DOKNByTv};X̎ WD~J<:N׭$Ugg6rky^Ի޴Fm~~ $pqq=`R#!AmE}c8n/縰m ̷FPTQcJs%r?uV%[N,Pa5R Qڤ]U} r wJ=Kڂ'W0ɜģ#?$Az,$+sr˞ʒ3 |ܺ;[+Lxz+ZumWQ{eЄ*\xޏ1?_W) ";gሾIGG,"3/\A"K8/lMO˨^pf [^.@9n*yNlrnhtC"Ԩn.F\P:=I9]/g~~4Qͻ%*U]O~\?ڤ6( :7p&UZ)gF4d9=2!Yy EMg'2{M Z]Sb.ծ eT)Y%gdq0o {^ WWcRNUX8dÒ!%H/! @ͮ; (mH %XovZ%( .bU#/NݞdVTy*@-,&W7NtArA٥ƞ(Z귀>cF~^P|Z 3[Ug 3e4ˤ:*5=Nբ]j5º EٻU.OrlXsR5)|)Jzl]DO]_BS _yÿwr\82+{F$517SejtNwW=z+ɔN9řTJMy\-kXf룑mc-2|t.{<f@mhPo;]4~X1r΍$5 0DXؚ=, S\F}t3QeJ/)sO~Jǭ% A\GA_.UUb%Ɣyl"As0[k@A6-aUrw4ӡJE1aW;,'v!#՟}-뀡93ovD;5\ H(+Ұ]A٭]v$j`2 CܞԈ8!EGp ~hZ UC>${YS-S^E^"16zqHXt.dL> L/RY c3>\Gk:N%24kGy}@B huЇQZlSs]\[<1[qE5,*("ꃱn(Ƭ:W#[-s%]8DFmjb(#pLz$-}B#wc 2GۃQJA'i96@H_@BfK)u}gG좸mk}%.'uM8yp`G՘4f5.ĶgTyΒM֭CL9 ٵYY3_P ;B&3IRD.'l g$;XK'r00Hvp AH'*X_ 0Ɍvg1)1hJߛ?ߋYj=h".*.c?HQ*D=]T۽}j %08{& 4]n ' -ֲtZiDU;(u;TΟ쉩-h PT L#PCP=;S^(T0ٛ|\xl+ *X"J8^~ ilvvr{@[?cOA$1QXTӻ ȗPwUSwf.ȱ֒|%b*X̏ތlT @=M<(2 SEl)cW~LHyM9nWӵJcMnqE.$y]9Nh6 8,B?lM(?y@V4XV ]yLBrf䏽b*Y‹,Ve =+AlE=*Fc앎7"Vk krzx\m͙k8 KJS 4>1W1P 2oCMp<00e|'ԱEGDmH&v<![8+cvPxxev^fh),\$wgf8Jc@UۋDjIzs@gwVP2%mX[|>Nơ2kkS$7x<9 Htz-2֥QvCه01EJmnTE7 .4vJzMjN7ofsA7hV>504_m!X y\6UT(]`̻;ZotuNÂwC 8Q aЇx-LF~;+6moN'腣:)|.w [n؍R3ڻ:qd:B1)D柦Y c 2'N2~ s7H #JK@חCnXx\HU="lW?PPhۛ)MIxDIO NbG3ŻE2v9$C a lߏPT]Nϣ:m=蓋Uُ=lxV: fN}g,bcf1 6irf_%UX7I)YHRxÐx33- ]?wqht;0 uDey{PYCemN xd^D[#v (݌K[Rq'6k;M)G|+pwkdӷKO u8s=i uGkthקaj}}}@4i5-WM=@- .C#&H)#XɮVs: UDBǔfi'sօcy>r6ŋ_oP01ȈOJI"zٺ^^bp|naѻKoebا-ڟ3FnAMD]FS* ޣEF_,n5o W =*oۖ.u{GD,::ɗ Q(V}։z(Brڳ,$qU5ɞzFx2|񵕮k'њa7tR/E<jBsWաk'"$dDF2 aO=蕔m6XAk4p.p=?rzA:#=V[hوf&i1]?N6$.OQ NNFjٌ_x;u1 //63)#CC/ Q- :ӇSnw6QyR/4: 6⢇j[I@+YAdA݄hWc&/lBWkB}]4:ɻͬ)^ŮsczPw\x[6~Ц(atus|B %4f;tO%܀T=;V@@s6q`d/~)2eESK mAg>2hO]~5>DwZܱk tzwp]t-E8JUdDÀy`>N4U^_|>+q"̗,|BrG݇ q*aMkn}R9ɂ@(0Qc<.i' 씿11H@5EYA.-,I@^ǏQ !d ]=bWin2ޱeMف}JMqqMdau+ GµDhœ9dY $H>t LdtIUZRɪd5q+z=Q Pi%Ka(K#q} KTxu#i98揉=a%L} '"zz< 6Ѩgoe:%=RGC4BY ,+$Nן%v)j8W„qkߟ,> _z]o }Oz88}EZ0beAӂ_'> *~7{v(ž yypHnG63RjL1OOEbO?X8#q[[u &PXR*Z_&ʝ4Z˨Q/]~8k1e lrT$a pm>=eF .iW 7 fƟ;}"?>꣚kzdeUh|;8AҟjcnHOv87[LD){\b*Rm$ w` pVRkqMei崯&}4IQxAM@+=Zq֖ed\:fqn8J`3 'aIq#k~iA0'LX `W=[(kk7pI3mUZAE8X^6I+Jp)mJɥﱪw,ڊ २Vģ~50g{(Н(l*08k`ܨ|>5f] о` f-B@c \#$To7#3S>)ќ~KctټJF63%tU4 =ITSŸQCAv;VG~9h-QwٞNIt)ѝ˩U[Ay i(n\Ăv </<2f0*JhLc}^QCpP/{"WVF=N||davI%fcZ &3`N_bIkxN5E2 ryx.:_49 #i6(lMDQ[$V⚴6ъ֕;Rf?g!ӳb[~E ~ (w6 v†yE1FFw6w!8FӏyVKHoޏz2l|Q8-U&~izKej1+żV ؒCpi\ ,iĊOx&a[[w_8TF!X0V%Z¾_wneDg>@_:^Ҩє2C6#5#^pka@z7:ZTT`.ӊa0s!J 8~M )RY;" IW ]8M'L4=0-C@A_|l.aVFD@,Iz|Y"+N︺_~o-xɿ;խFFybQ#LQ0a*$-l* Hv(wAgpW l qU)|NY薒OXtE٩]CT6{海 A| /e_^D@Z#h^jǵF͖":Jܙ}.A"N">r\g?b\u *Do-.L5(|Oƃr1Z5[YD՜+Sr}.(Z҄S OxB-3nV$Q"/5Z]j$TC3;I&Ed Iנ*F` _{y@ԝN#ϒk#7R*f]頩loO:!mr[ x+Av5ˏ@ 5(n- LQo[*f)cK}7Cz0*AVl|"K3rշkaf31#isi&*LEύURO+6ǡV(6 ڐ \ 2z v) J.2ޘQ.b.G!t=HG:XgI\e!]MS-N qjIsEcX)-w;_UO"/|3\4 !;Yo0Yܼb7κKyח;s5p "q'% Ai3PGs"sxaԇ{UtCjLr5P20j;X=g MFi\ JQP! X (M/^ո7Β6.l-H*$]6+n- >!o_eAv̆mۢ/jcH rKEfdhLUQA*F8D J&X<؝tUWb(V+nXG)Zٍ79!f$9If]/w}YOԕzTkÜYyY,ߋύT`'_]T~`˳Bͺ_>1>V7)D)g%nNUѧ-_ma8z&A!&lh + C_:趏S3J%9YQcR,{tMY7S/A A_%ώlsx=6VCZ6v1^Gin9AeG'ҿRy=tP7 h)Z͚X=JHȔ.P Kɘ1(gCg6u,ckSLC&:#(}N,(r>cQAt~|%VB]d0a>X?IGu3ym |f&H >W);U:A0PUV!P4qkhfIt2'-viUG}*`Id[KlFO](U'EE`S 'G3Эya{KI]p 3]y8Y]sWk&ܵ۠Er̘ Kl,;(JY:%%=@ꫤFyn"0&Æz$.P-.0Iz/t=VuWUf*S^~Α$ýe@m1zyE[`EDA=r.mà(Q>e2vO{26[&Y(Tpؽ毰C[Dtt Es KDkqʀW/%W=YTLx]K4fw;1/5S |&G&福E䫢3co@P%F!F Q4NTèwl{⽏ծ̱nE w_hC;Kd1WڏCI+ϰ0 LM{#)Phc^? ׀̮ٷ#.eLYu,t`Pu4ycVpOUS+{+{ WD-g ~E# sܜ>tF2Ch>Sp=wl8IpQVH"0 T92MK=ˌ4Ib]gvJt e}Ϩp?W5sOAe8ҘH(3~XVnUD4Y*byvܲݞA2v]L2\|wy~~j6IiPn!`j|2 q Tʨ,*.XhW]5Q?{)P?Zu@'Ԟl{)`Id`NjZaE03>xcm K/k@x=9j"UuxD);-ɨo3L'%Xn~ztH8]nPU/LO"(^J/nM& ()M8on% `k^bJH{c[LZeTC*y=8j%o7jg#b73ogdǨ0 8fYBB8,mܻM2Q&zR b@q>sj!e VsI3>yw< 3X -Xs 6\fPwgբ<`U l{Jj,9lfQ\Y6p0Prx软"_(c!0IZ8>aH˲؏~jzaWe6}S}Y(J~ϓ8A;+p\"Nvᬂy6C,[e6!ʔy¾xIW\$~?e+ϊC,a %9D+R? L͸eP^f.粼>T糕ہB!"RӀAb~ݖEk[|݁Sf]K>A 9XEEhPB8go{YG #I`êDqMP1fXObgZ. 9\"+i.Nilߗh;toSXEg¬1vC-nIVeӛ/t0^,ы]as4b$DVFV,(Bj5'm750B]EaI1j% M6ebA:2HjݫȤqx cTM*p_Nn}޾ zossuxSČpjXJVɋsD/pO#kx89W/ԙb:h(ˏ $u',Ó˘J7)k @L$n8; p !pCQIAFWma󬎚یJڀ+0$'h0z|}TϠ6~'IZ^xj6u>`q{ Z@DE/p:q;wLp 3 C0s(z{cdX|h %[[h>W,|?B!=~??e?2b#*-q9Mی\}V"ZN'HfwuBW[ct}W>-ƿư MɆn1B &c=)ԩ5+Akzo>CB%X9l5:&HI,R1L88D`Hi\N%Pr3fB62D(wGiO/H^a]]zuaK]+>%B_eUi\6DW|G&An~jYU=ikzjzzsCq@ "$굖6S>R}Mtspq TF8,0C!*jv⯄ha]a^1{B*d¯gh#}2`בD2:bibCk8 moKiGgnjn>@ߦm%fEm̈́2aGC`9\$y\yy^[ܶpZW.YISCs x ړ0`#yڧЪvL9t]'k86~QPazsIͺGEqg[ժUD2x-ȼ^㻜q, Z. ;Ker>m&"%cx#jx>^*4~ZԀk+Mf+FUxC 4X3 tHBGx1.]4*b֫h-90N[͡EQq 1'iFR[i: m/ݔ[mQHtC.qϠW3!!`a yE6]?ɶ ZtgT`3V|%Qބe@DbdaGŻTޔF5'% &Yk/)7*M\eb8qgF+MKP i D*{srsoHFSUJr*Sa㔙BPyYP&PT.wV\`HT}gGE6RTS1ޡk4.ѻ‘-80U Nw 6 Gjw Fm޷je"|Cxa{"Kg rB<+sjb+0YJ;X}UrT#-';В'7B|ε9!᣻*`J#+U zNH\RdhGn_#E2R zBV2Et)<:ןEQ&$Qh[}('+^ZEG ŧ޲diPKL7EmL%`UXbkM_ LJH>y[ bbͺB#6ɷ5F}t|XW(IY../`ڕ9kFjKW׌^Z0HU0R`g<3Mʳ.x(,|P;wmd] n:v}3/ 󺻻g /*IQ0g6cBTQ |ŒGT$0 ՇVnVgQ5hu$y&pt 7Sjh|0#v}7]Fqg'tݘI[6#k;|mƗ$\a2ԅ qp5 bbvξ3 $"':* 3 Vy >J5c U~^pSre{WHKx"{p'˧ƍ @D.,YE廩?ʘ1̺l yj2B'/"=q /%ēD\i;s^Jo*v#fVL8Fա 9芛5PFwHbtFZ3쿉9nێfQx,C:I~^HW3 Yp Jt$pdжGφU:Iwѵ: l=1etAdm ǷGwBTъbU9Tcƃ:PC\FC%Wb{x0{r GLX|(*^ Q'9tAI {`Z{'<(`{ ,F*H^GB4>x@drnhStP4{LH\S9D÷Ȋܴi9Oͩn,5땱4҇=u#FC-Ū bTD %69b'|rU!PΜrƩ5@u@uo {\ c(”d@K{GAYvޱtNՊn"SFPO탪GsH0i4?D2s"4㦲5sްN^JUf(kS+<ݑ W;ϡI;م|;yo^AmL3aKg\0d89&l@Ag\)cMˬdCC(̎Ѫ KM&I5X1Bd|Cs)BE-ټ%]ߧt/#1`J(O ʏ1zbx|ps~ d _>=r d kłT~B9xXH|WCNqOw`Do.^“z06Bu:]ob#+PI~FXZւ5KhСׯ{,s1O {@[#32x@+` sgvw@}3GY)n:SvdLe`,}Ċ))O|X"ԉISia %.k S1?Jq拘Ӷ×fi`A9ur0ټFz* ɉ Ȯs<Ð.)ZXg|ͯo X-x\0S?Y|2tmj!a 4 4v"V,;s)gmC~W ȦqkBU,`y''qU3gH/to- R(JuiQCNdߵ%H4#?܆,W;9Ѥ+' iFUO"S(ItLΖI\c^K9E<6+^3Z%d3\ ]gN}OUei{g"o{bprI '\6¯(+񈃬t uvT1,9;M*yEtpO'5̆)gycnA o0\O%أ~~lߕ#<,edCtɪֽ&y=9tK2ɽHF4(\y)^u#u撣\\>qwLߓy+]m>٠ikDv9>a;0}dfX!d>&2U3./}pm1L ͳoe Ҝv+fSmf:B_^FcR-$#[O_;UG'*do^#w+@!Ka(r!lT$涨;#/o~y@7|q3Sr;H--9:-efz0˘MuʨmcZj'M5;gO\z1dMZd=p,6t-٦Y͠$Gm01>>)>kDXqWk뛥]]'u!?)ĀFhkz7'WC4>3p:QzL%P  Wc#s]w诋:$xH5aWI'Ħ+C.m ]YMc+U}g&᪢}7V0o昼sǚn(}s7J,Dr6@_J"E˞]fMB/ -e >Hs4d*76S"6=.&䈜j;̂aēo@$R5dƔfS6:su _[ިFz癴e^)SĠ{-z {hV$gU+댧/~楏xbzeOLB48V`]wzs/+6Dld`8#Ț !ۭ9wx}"b#QEذ }iz&W g&&I3Rз2[{r2E˼v_EÚ(,4{(/|$//ճ<ؖF5`ͲGu;~GV.WqUkm(e{-ܤ9X8ɤ:uemC*n\I^ PP!U5.9\G+OT-ՙPk‚\H%Y WCg8W38A% pj;,Bdul+1i]䰦u7Kb{}9h픛6<ӏ́J+3XmaZ^l3R$>s2:`1er+cO6}@5ڌgRy(M@[i\K4}$wS=͖l$z%yŬ9X&ҟ5 W{@NYrIBǪ]r3h4o`ڂacxۯ|y]hS}EUZ\s_̅ Hs-) ZDr(R "!i:lE{8zS[q/> ԏ [9qd*5xG5@~an3`DݿEL?9\+ |V0i\$' !HCdխlHOBЕw|j؎IKWNv:Cf?g3BdXKUlpnVb`" 4B=*[4_BH_`׺mk.Ob)0=Ft f$l2Û@'Ev/g9ɬr=2n'<;4) ;{%F3n/?uD1PvÐg4qKeBBγ|>HzlꚈ^RHy^ϊ$ 2iWH$[Unj9яJD/ium<b'1}Lk9 VH_Xi.$t[c _=kPB7#,2.2}X?uVv^9Lɖya{*%"ub:/ +F,Zdj0Vfy ].t/;jeh%K_IL^/%}?5wd bsi%evCqGs @o_y:?m77Hzʘ4!+@S=g 𡄓_]~#UZ4s֔C$0h͝/GI.ܭ Sfd䐤O //^\6X! =fΕOX>~$)Jׯy= }6.j{%9&_X#kCR43TI/ 5\TP`Y+WED%7K( &P]V}Hެ,BA:ևlU\_/ҝWlJ޸87O̐)L {kǙW+r-'`)-Up=MB h]5{lLm]q4^N[ȼY0vY \eioEw{]Ɣq CtamICS#2SU^HR ),yoq|9fdƽH!-9˱:_m-濭8fISL2u 3&'媞/P`dydr8!"#6~XB<Αq}.񐚇as~CFc7ݛф~׃9Pry\Rmهf|\D_g|`CloyɩK y7zC8&WdbbDѕ yJF_bzm>?Ee !3$n;Es/)fӸ\L1ѿl"%jukN?+KOiQݾ.Fdr x6:,iunJ:j2,X8j_|fehB;l 'R^jOsMFYeYLrYyd49p1i@"~dнaaq񖭃|Vv=[C^M)x{]L [7TAS?I+aÏ"[clGן05Uxtj?vjS ŀMC"vA:Zds뎞!0 s!`c`hJv_7qwugǷh! K} gh}⛰yӨB֩ųʦ`_A9=ٔ$ :%3([C0Lf4;B- I\ qK.ӻO#QQلF70"pJP>Lζ> |6jBY/:XAb-OĿ$ ":Y`\ dl , N~C<4^u`( ـS<=ݔk逛!aPB F-yN#`4c}_g/LCd{1.qþ3QTx &Oy-]/@"O 4>p6l" (lPY5]FJ-7d^u X :ܳ8JEɹX='^2s` h/F>uz_NsvQ^U8b^ə[S7Z /-A*:{* 1by);dU{ P20j=']r77WxbOr&RQǸG,RFx.)`Fc\[gϗ/-{hHY8"G3~ T&o{s XBa -ǠoTUFhϘ \ n 2 ",eZ GA,ï:7ܬ (L0U㵦wy ?_dƧ. kSoiDj0Y}8:g8]G]G'' Xx[7H!;Dxs 6w2*֗/:޶td&fq{IYO[2Ψ;]ơbV6r%!֞90 -0HI0 =)3F k<An 0=%z_~^S<3hׅgvBFF,j6;9[4 A- #Rc⯓<* Y܁ɬXtoMstE%SHg G*ļЏ#*Ø߹_f0?&Q Uwឣd vܹNH3sJu+N_T̘B[81-_$kP q7ŰFs|nKl6.㬺 Tsi0_Z C52I2lH`T6ƓN`pa~eRI# H.5a'X^igH,4eKvpXʡ.뽵iſܬNngk&37~uҘմ䏵VS{Bbh7 NmZQL#xKN^Ly=|<i/iOvB.z !ݪdKG'aV9bvYKb$ 2315~)fJw8#BWUKN:ƍߢ,jaeDR4HsUw.5+@i'<|nG!EGTh3!'o`nBmZIH:#<:篂9FlNZUk٭qFzh=@("S.zݒh5+?_U&\=aVWk:8tfݍNd5Gak@&rvPnjYu:*BvHϓLG@Z׼~fg |mb@/4z 8\śxld 27aP8o3U<6iĻxT eM 'M@F0iMRz#)Dg2;9^kPc2 џ"_̂9%C~T8oTf-mq6з^o{]hᷭ4ҳyba{jXy Z.{h-jgrB!\2qiZbդt M7{2nJE6m*۰((P\2<[T[?b> KUg~ /2"!Oc GߺBB^0ycO,@Fi)s7]Pyd%yXۯS 4O=J,G0} ?9SO)SnhFʿPbMC ezB3o/nɾx6iOA E}CےnN0G./$nqVӓeWJ3RHNWܝSITOs^Vx2RL+R^F͘Ԃ\FsC :u{/8cR~sww__$Ozjl#DvBNDn:\:Wz h_` &4-5 ?`ߋVДsawS{Z*`=ZTԐ)D֝6Mcf?BHHѯJ8BWT>&إ  6GHlCz|Vژb36y1ZdmD 1c?7M:-eAHp,8N_jaRiwWs݂95FtyX=@|z8չ Kɘ%==˵d%_ܢk׶ٺv6v~^pzw"euHh6٩^n"HOyuc<FkwI}pa;V3VuoaS4T \;{}(/-lH&#+[-`7+p|>t c T>4A#*{,?\|''\$:%%$I^uVh,0\a^}~0V}]ݤ>[ ^}Y蜿^X-4/eW:TO?գEL`E%7_A~i NĕE-iyE`TZ 9 .u-gq#,qa2hfzw^?$>~/^Xpe ?'G-xgðOߦi 4}V.rn{燗䇦Bż! V=n ^0+OkQ: 5@HBzMPt< VH\d6Rjt~5MSZV"涾J}EZ !H.*0s{G=gn{%wP%'NepaR_DT@@P_z5:T?ն{B<ʛ .l$KLȦnó!NAA-}D=7*>\8^zMf 3L7nu莵vV5sȘ%̈ˁQߖ\}r=({n#~3iť_[0,Hys7q&jw7?单JETn,;I̻G7n!Egc}p$S+.K C\q*)@iӓj,thc$9ÃR5\0w}ޕ p. u>c]mK]/[I(Q) Dys.WctjIm<.  hXKbXGa$)m3H1l@`ht͏r"]QL=8,Y*̫9EEȈe(S xl+g1dTfۡ@$arϙYܘ<}4f/j'~/ }`&jI eY>uxE8=M$d۴L=Upgg<;>N kOo#8&3&_cF6:%b#0rJ"tzSdfhR 2Z:p+ڢ.pug"SO(0i <-7 ; Ȩ bEZu6nŧ.!$O5wGSow# $^*G@WSšԻuem$fL9ňF9$;gGpa CYbj/=~ќC+sF pLX݅k݋ZT}3 zԎ7LcSC/<6r)jO EƉ%궺6M@x_0OJ ".t)_s`~kI~`u?[ KCbnR-s&?m""vNWPWНB(pkGhl m!}*e xݏ1>E[9Uׇʏybh?f)v[8! Uc_c_[3/Cv]G Vrm*|cj܌:_z8,|#&Iy!p;PBɨ4UmBX:r"u}Q"Qi%v%8&U+A8^9 |g?K%s5clk|Ms}փpҀ{K6d`Y KƬ]=B`#]@ j K93 <:wx-\05{FL&z'\4fT,^^ǻnR~;(->d lOD  H`B`i%#,1k4 Nn2Os3j3I2Ug{5)zn>eiAmjokDh`YgÙlT78Sa'`?50 555W&ʉSe]2n s46I:϶\ GOr"6#ѯO!coRʥ9Ġz;v𘵌]ć~K vEɞ7A)r㔝KZkVT:Qc!~We٭ac:aQ [ޠHkc]?o5dp/tV9"Uy̔nWDV+Lz2auKءL?h5m,^"B/&h$Kg]lRXɪa|@6MhFuo\w(.c]w-!5f́R͞П^ iT]B >RL ,X?bNL0\w20$@Ӟ #ֶ"#x<"zen8LK7'GPTƭ0cZ-ƧK58dwS*(5'ʞ,a9a) pjtO6 $FGΕZ$&r2!d)QI|ʫLt} ('MJƐfnUS35?Jϣ*NhOߣ+0ܬfNqs44+hRw7a|as>§''d)#٩f_T9$rש!B" Q("ĀCRףqXW ٠!EK|&b(EvmعK_5[v]MNs(`mc XdW;Q/EoQy=Ƕ5~fċԮ)RðrHt(ТFc˞Jmya\PӏhId,<$ҥnOHZhSͳt&l*+[5 IX]:>+~'y ? Μ;Z{LNBPPEN@P4m+=8 ·kʰIۿ`tQ Z<˚vgM م&I |@Wwj鴷ɾvNm56k c;} Hal>m}oB+Ofh 2t}YqWaj5L`>ػ+WNZ6hGfyMky;J?&I_ 5x.F~8}t(FA~Ӌ%m@|#-v)]mY2<3wLi|Z:Mg3_ӝ4=f;TYq&!_Uݽp>S?@t S1+TlqZGg7Ÿՠ:J1Y ۳D,IG39@vASRջJlfJ cv˄gdpMZ_f#X- B5W,u-P0J`Kk1t+ukXCFY,&5 ^G:}ܱM19 ==([UpQ?k/[-p:Uh~TyΖ^k a#jz]C̱efEf`gyBwi\@t #7NJ73Ǩ?:{`h$ ƄSၪ$0HRaEpa(p t桛|3f+xys!ˑYdɲ'&Xg矰paKo5^<ŝ0&DW+O&l UO<[yJnDMY7,JǓAeaͷhZq +[4F>Yó-2Y4@.h9LuU4K:mHM Yךd1lx1i1]} SfoBm'Mi7_i._Q=]ԬMTΕ&hny_SbC3P>;YP`DM铜׬BNjOvē_iAGDWUjR*ɀYYpa&VhIL /B,DR.w(9 D_d6wsqIͪD#Ay~ om>=Ic|P]Y)s8y%AmTUY`ړfbLS>wP G$2mQi|5'\ō 1;wg$YO8qp,漑߱>SO:R4=#$idKQ쎗!삻}tD||r~S)bn5J KiNŻ\M I]ϻ6/IDliPdKpwlV;|u(js-1V,քB)!8a%7_NFm%QDdPCvIy"TZ:k<%jNJmf49D2 s&x$"[D- Lyr҃ܺ \KLs7U0_99R=QhcזvI6VFXF$ğڂJo8szA ()?B~P.yM*Hnxy{jwyޚW42U9-4 3<,TAm:ues/+!p y|T03A%X6?|ҽvt 1²ʼnVrƨ!zͼdM([#شBvmtк˪$ cޤmcHpdV*ǎCsR xvW(4f Om 6qV!Tq3e{Db q弍y]$4 ́$Ae$_1z܋/v4f|W Z͓;-+ UCzv|gڵe{u &&")7ul#A|Oύ#J)&avҏQl*aQvEdFKT񻢃_JĊ @Cج8g%UV&eunp#L-6s?6zP4%YlDO};w[LYD, ? mpeUߺ^l~{C Rj7eNbmмp&.Pp3.jZ' 3Fv9RŴ=_=O~̩WD#*h9'  I9`)M^ǚY{Qif4 3$AHH7f&eI Q%gS3oM`/Yb4y)}</SWj *ZږN ޘRjp){tO9.g/jĨ#sٟeIYft.':a* =^}7&Zsm򭙁4ȧfF&#0ҙ1ѳRniO[BAakrlfr4>ڑyD"u!yH`"]y7h1XO"d(ȠS+S4 ^,$a||wO #Ï3gKЙS5~sS5$W{ w`--G]!kqdTF$.v ކHf(ēA'C"׈ 9ΛKwN8#8 2Xpו@N AJhfxV.omؤ'J/e_WoW{Ry6 dSH.'Uc0 aꞡ}d);}JqF\WT=pyocl:RƢG[Z,ۓŀGvFƅ}Ft653ٮyl'`A*gjLy{i` +Z>CysĖ+u!2fW7psцsCuN=kȹ4L#9 jewwM2oܚ*I9&^;Fat+2i6cV, Z6A14SX݋'v Ķ%VwڴikLi%Gsk\  u.BH͎+hЪIna)\ɏEfakH_.3]C>s*;]__m*_ۿ?vMa'MK.=z© '"}Z/FK*&*ZJըUqR`8nUք]# 7B?UBT|u-Vٞsl_P8i8ɺrYu[[M>3Qd揙 ;L 04r]PEId٦/yR$/O=eIc u<*OPP"; kG{R$iss<,dYɂ4{q6wrK;]%F_ 4ܲ=2BD/$@KXq,XR@\nx`"p&܂=Ŋ4Uփ!5Q>mw;{QQ*Man-Z!%Z Yݭ>f_iz.TFe絛K2]FxЖ |AYH!׎87YY+{pњ!0}"&Yi k;ݘ$gz`$` h`NKZk*DNT`l 5fW r "̛4T8?e*:-3z8 ǩȨihw4qӂl&.$".y}&!̍뢜H3g8cR 뻚9E*:#ᧇjWF?֧!6P~ d }>ڛ5>P+O͋9H61ޑ8) Xk]5a|lGt55Ɩ_"/RL8=1xPmL?iW&Sr3miMXfc4a^*T!"6Ѐ ZCփ,}$ke3ɟ5uɲ' !!A~$7W(6֚Ʈ߫E~gI܉9iIS+zWc&܁:80\ާ04N9  sLQzTMG7%UQEHK5IN>K\=*۽xI#IOtHtҪy~3c { ᷿k(S g[%@{ R`Nܨzce_8BeO&5/w(0Fapkl.zR(8е?ZpaY\J\džݺܟ6 ;Jg7ixɕ$`;Eä[ _-.|gy{ɖj&dŸW_s=Rq˳dK(J,0l!(oH֥Ԇt03\z;ޒ{{Yi%ы"Cx5|*rF@ʹ9{eߗ\x0fң%Cr::tqKL@H!##*>0tZG~ 9&;_+A֪TpR@ٶz+ϏK@uzV. '+X {I, 36BvCUM+טt\DGKu%ǘ^THy戁" 3KM  ZyxeJ| nyI;ɥۦ4;=A{lq<;.(J7%vc˱NXLtTTE4xvF@g&*Il(r~}Inž2|U7Jb-zYGd،b! ',air%k"$N*Z8VTc[|LP)i>3K,|#u(h83} zNx~Lșr[ϱѧnk fsZ }٤M—Z@N(#3}8 @BMDݒg+K]IzCu|~mw亸*-I2 ȉ,-kLs 7 Mn)ʋVI6gOKo@ *fpmd{ -C/&K||E#'eJp-OفO$WRPށ+B ]lGXǩ0cȈ^ |xS7*|$6#NdꓣabLJpuZG[k%Dѓj-0Pg!du{79EʭtF=]mV%5)p1}um5sq(P--#lc=Zr c"[XYR[CI;n'E1Irj:3za>\_> De/x? T}L.g!j(Q4f`Km %1wpīe-G"1;@YyC"h^D?ϺH<PNzݦ"' _-Z}WuV?QSܼ վ ~LAs8$NXH`U ' r>صГoMdpL/>5_ 8w awj<\@M J{Aśq{-K\]V?,zY;T^xnM(,ko %hǢQP)iX Uw)f!Kcvaer]܌P, י=B3OjJNP+ycԁ#\N  \*LQ!5O)'}$D 0At%m4:]%ezkxԂ<"JKQ͇o& 9MPvrz=_|bT}|Y0Z v-BM|<˭0ð3KW]ah}ᗻk\[!tA SgME뼚Pc' !sx?UqvɕܔN|'\)`ALT46@ t{J8Ҕm.sFP)C|ֲ5 t-Mn$yQ:GGNA_:9rKA!mcBH0/ +S򳤂! 1 t7Q)e䁄7*pU=BF*fg Y+6GQ=[IB<{NKRɶrt 紝c)ϊ/HH8޿#u%36 h(݊Zt&*w\RJwҍTQZ6F:7)zATpmAsyi@JByXKYNGgB}"w;xԾ@qFAPj[O!3?FO( rTY[~E?.lӜ Ja 7d1Gts"x<)٥E6~ʼna{-}tP5>< v +qJOAbI.l׾.o\:Q-f0Et9J3xߎ)-c.X#&L%FX?Dզq"W/Ƹ- <D |&:db"9HR`em傣-9&^JP":zeΈæ@YYBk0#bS?+`nDjq'ˤoy'-^6pվЕ WJE[fA:"` ϡ[b |.?w¸7>KJSnN u\:XE]Hgź| z/&q^lhiiKG4mUHUH qɄzD6,:3:a."4[h =+;c?n zϽ<*DlpQ]7ca҉obȫ1PKƃy<fzgvK,8!~RG/1tE1M`Oh"юuB0zUZ';<1^|/?'̤A5XzT\$ŠDɩĝsP]?Ğoey* N jS՚|,b=4qb1X  A+mpSǠ̺tB0 ۾Lvgv< 5X6܆n{3{ JیmgXORW oGՋ W/`ǂ.Wvq"4 mt-HzKe)8ou$lN6CbfѪ`mZ3I8YWS$ K=6CfC>5/ߨ=|9&K04|o<j12ul['7\ED"J{2ҨhM N|'0ՌSXd˷@%_`!cD-|U6*9ܶ{t%-iq;O*կtZ ?Hx g !IALѐr $v9{(<qr~knlwd y;HfwB=>ys: xJ'hOGkn;P;g f04F}<+L- G["oCGNSQV+4,1=)=yL:L؀{ÿ+1B/߈Cή> lOcBtO+g5ඏ^Ns، Nyi}Yʰ9ƁJV1'1D1V)hLgc:M]&uq6`(<U䘢{sW?xFs#} ?W>}!C ,ʔtQX7._|d+xb\hߗ`嚟"͐C0JwctxVݿVDX[1Y8o6ʎC37H_k I4)5?: $y/EiݢD+{I\*w`D @r γz ܔ /S=?F1'@UT:&#LYwh78 rڢXa͎=M@jԾsoFd/ŀnKX?jMypA}VĂ딑:%Q$Ovtkym%Nfˡb qo|i)T;~4w`E7t,c=!ׇ8bҭָ$l37=E k\\xSln j7ڊvʛNٹf/J:Eveu^2k5+:_S #)6fPKYgr* OEv >z3x {A89ڙL|dN2ՕR3!x32V2wܾnzI&|4{"9s@|{mtwܠ`MyŊLW{r6).AԗjقݩW-x 1Mdwc䎶m`DygdF<6]g~\ۡxNg]سd݄z4Ñc"Q|Jcz8;6ؘ>vd1|Kr M/0 SdUR9#U9 U}_ H{McJ*:3M 8ָ6Х esܲc!PB~<zCe)Bq;ZO/lqCm7|/>~0~B N.Cͷ!|~Re;.͙穆ĚPCd^]U꯭_NJ7u];S)l"oε;=-0Xszzv8a!^nCs iNi֔'>#fdo՚lA+.{؈dmֵNQyVfdF!Öɺ#*vPeazoZқm~ich8)GP Ή8*n:rQԜw l 2jf ϸgQ1{S2ܱK)2E'#SJd9 0_SZ[u77UspFuU·e)6_02 .dVV,.zgqgI:.M?f_Ĺؿ$ o%@9gvx`:? 0DbIwpJE>;_R@B#PhRChwRkz&H_0kau)McI\\l;TS^{F=) 80 #۪Xs"/J0[s]N"#dй |KHW#tz%20gf6KHA}FvFO:h";=Lùkڻ%VzrPу?>"ڭ.c̤0ljo(|=xnfԕ"W|Qc~a.TI%)lmԂ9(=RljQ tY5{({qSn*xqQ~WY4Z9̓Q8%PPF<4 M>vr0>lOsɽV̶xD =(pQ!w$@[%\ވwv*<GI boI F]cC?Q5oˀJjߪ鎠qۚ=O WL]|l{$,'^h{d~0'I749~QWMOwM%rxd6HִVaef-~C}ʊS,.jh zn:mvV18Ǝ TgM\,@ke<}Wf,9<$aWN~ʠ*dx;BX*4nxXl/+U]oZDM] ~׺Lt684H!ރo93kq#0Ϯ } %]Շ ݍo=i_Ib631 k&M%Z1 t>ԡt0µۿVqEe:\<2m,/Y.! 1g%JrX?NJԌkL閾0uTą7 gaT K!>T Dk02I~<1Rn`=kH{!{CFGdzܺ8W:6gm3 rWf']0FoJ*vmỳZ3WYkǐ 67lS:9ЎæhVTU$V.N^d\ \e"-:j&FOP<7;0ҟWpUxk4#e?GG#E2s !컠/S\_AER'r0i`in36wF>1Zn7h.X(9M |HU踽&iKiL{9uIBiG,}^wA&|J~7qR$?" >o/HAtIG- U-[I)`XLY)Fero,O*OZʑkf=`ËxEw$-!WgqMk !5Hsu*Ys8yLn4/iSČ+k(d (TA۵H~5Tv("x<*0]*qzevv[hs @i\2W[UF݇4$](#AE _u|`A uv5mN(Lej}ׂ"#)D=Q ݁t:<,Zf*cA* ^yYX ÏNvP^ߗuUřL7,cTyK?h|I tت> -j=Ykp8u<V>aGLP^?|kϰ_̾D(ʤ[ٻBu{,EN_ ,ԃT}@h.;Nqh2Mߏ$-xmxeiNC5ٳZWIC #l럊-|_939hWua*mECLb@)-FnlqM^yPBY4i0-r2w| J]x{9_ L Ņt%ĝIGi8ABQKП?zCA0FBl&k[w}'Bbg 3 zu}!O:+n endstream endobj 33 0 obj 113085 endobj 34 0 obj <> endobj 35 0 obj <> stream x]n8ཟBvQXO HYi@#WGt>R4uwϷ?oytnW/^}cZNy:Շo|v/yUjNi%]O| _sՖ㆔_cs^mzWmasM]ǧôڶcsS1疹EYY٘ w#rbNsmܳGn@?@?@?@?~_~_~_~_~_~_~_~_W~_W~_W~_W~_W~_W~_W~_W~_ᷚs~7~7~7~R~7~7~7~9w~w~w~w~w~w~w~tF8#Hg3ٶ l+ڲr Y,h6;сDt8. Pi|Fv +KdDTguNm-^F ̸>-AāNą,ua`ʼnALt&8eM<#art˄F{ǁN tޮLvqpvvΙK2=n=azf1OOg$@;<) bwW<}ynS~y.XG) 3,ud@ژ4͛rPvc1Kzp endstream endobj 36 0 obj <> endobj 37 0 obj <> stream xsxO5v:mkbulLl[kbLl۶3m'g~9{9W_WUk^7*1P΅`ikbo`# 49((M\mv.6@S Й`7fbX4NΖv/ f7E Xyxٸ9{/@ kc wp4p@ICGG/`@o@{ Xm<,F@84l KKjQg[5 /V8 $HGu {'s?KYXY..LL(jOٌBTjItUƒ96k;{7;-bfigGfng !a@3+3X0?,Fv>^3#g ?>caZvpb s,:̌0_/xk-?+DD^ ,6v<g[@,FQJۙ^_~o3L]f濦`_o?%ӿ<U(jcR #cdki-TR?0ImL_;T?=_u;SPYXXĀv^9@ٍL'lW8=7[#4s F3)|SjhbA} 2^{`O_߄}[e,, q A(́L8N._Țԡ2卆Gf6g4[d}s%:¥ck`(@C,@dCQ&7}#h[o||*vuv BAᄇrk~/R*N> r]X&AyU&Fb/-ވD=XX `з{mu۪Yp3q +ȟ@" ~[.8h jNxy7;c3~K9j7|"]v35w#SeqɘuůX b9f6=mE+HeРHl"b߅@\fey\:eRAy[</]d;Cwnj$J/]YbmgNy!aF4`rb9\"Ũrz*wpK`>/7ϜiJ:~|D4۫ΰf٤ȅAlW?HveHʖ#Yp 1ݩ'HWx'M4Îxe;"B/29,՜f/Q\Ss >m WNhy>QP'So35~&^U(xkzEO^F9 ?C,W՘@Bf=+.izcs'};6p${eRA fvz $3yWWPL&CȒOzGs7@3ƚeBcrJ;>+$Ez A {˔Y{GN0W7Iaʱn9"| T:{xnfTQ}/IwKGK;[@"OŅ#*d7-C aF;DΑ}02ux?-k}̡y^Wm@zs_ U?2Jxu=57TU())3:ђ3I$RWaA7Že $^G qe7 ̘n-*w?D$ 4xJTZw-|.4W2Uр=F%XƤ"q]K9,W7lS=r5׫8u{~ |F92un<[#%b#,H& '%ߚiǘd!͔=uYj)"~VE|uga[pz<-|2ęEڔᏴ(8L%Q zl1 ,6ho2RTŖ{6:,uÅQCꑨ*\2]WJ̃N>?0 Fp}G4 pZy=CLP˜lB՟-/tagfUY,3%fm*^1jeM"/Zʤ #ڽt5S9A5ʗ*Kb] ZqέuېJTK]ڲ z߸[of<%ܮu7pŎA_wmRR= S|WǣvKYn[; =byQ$1f"2`avCv GO&7 AQ99KպXx8oZ~3{f25|BRD#]23[)e[f\[?ms˧;?Rr~Ep@P\-G(?~nה50-B8jZYXl~WhuȾo yX~BbȚeN?О9Y]` pq{@ѧ&玔0h&]A .LPl8hfPvsipJHy /̙uRK7[ٛvVxc=ݙ[#G@`UV0 ٱ* \2n 3 (>Vuث>>єrd ;6}A~ ͵tVк~ɐ thGK_Eɏ7wq 0 @Փk{4>nLӚ%ca $߭HH1$Jb8E L&"'$?}ͽ姌ə@\x|ͼJv{g. 3xFN%Ht= Ԕ_'|ϖVI?o hVh9ӊ⭔Ŀr 4;YRIל*þOiib]J+l\wلJx:eQ˞9$m4TИ "StNڋ1U!{i[t (AM<7PL2$mfeʮKAnݕBtՉLQ Sܢ^|.(٧Q K֥^Hv|2Is|׾e~}_6(rmɕ7n'1Tr}^{děDaA8OO f3/JBrܘŤGFV1нpV4QrPʀYI#!]*1!LF5an߇Ӌ@=$@unCmظ-_];GTlb0H&[>wWv2x9EivjI5`#.Wv`?7&b)%_p J&ys8HG}8ᅨ)/'err{M2,lGd %M?2ؐ-uĢ~SAafQ5fTس́#SYиF*:&\XZ$OWL/d]<=SHyy4S5p{ 9pcX~z9y5OE"equ8P}M*L @p'1Ob7%BwѐƝpsc[A%$xJhA~{\/l_+, T-]3Coč׎rH$::~?*?R|{y|$)(ʺpwcs L(ڷA!ʻjS&t'+Fwq%z#x==qap4qW%{ =:5/J!{'\vZ/~P'>Wlr ?PZ^cg90'f:'рA{ٽsR@#3J`1e ()cr vHXV#',3ŴSx|ԵH9%Ҝ᝶W: ;u3NdUgG@,QFOR=>r:g| -FC!dKBRWDÖv).gWXfU\I>.bBf,|oW>B| X}+F )6#0޹+Agͼ&Ƶs+)g]٬ؑ02Zf Q¤1 1 3sѼ6,X!l'-%$j<^Ps(dt *#Eh p`w5iQ[{/ ,YXT=_g"7bzO?|#Q撍#j)8|*2;/_CtJ!pkL4aY1=Wv]RMjZfg(K{'vvHF4ąwPF voIa^e~͙m;{L:֞ TdaD` s>ϙܨR"=08d8Ӭ* }Y$~6J٭rrԶ=RrNRJѶgE J&VϵJsHq-ǍY4vc 8ʀ,T|PJ1;m8F @n'd tN2NPҵZZzʱ e6JJsRSRäGTna>V%N X"*{ $9Fn%sQ y]uiqϭ˨TLHH-1W8H};฻jk^ڥ6ҥs׀O[_=,џ8n೶Hߵ48֐9FNIX1 HKn`v^^{W鶺nRTfGT"ꗸEl'BTRnNEXؑ&{.eꨒ ryDɍLŰm[`C*,X3CkVA遁c R/p H]iDdR)|"_>Ħm+uU&EkXݠ<"Nb:0N+:}P(| , rmpD5dv+]/p7 H-b;-_g. qr\ˈtMMG}4ӵyja֝Rimm;˜}ɱ[Q7^*x$hdu^>|+g|R?q9~*3jϤ~TǾFI0;@XlN6L1[AdqSW!X{jmzx|~j*^Gx~ɰ`XR'QKV v5{~|G# cxokK5Q+axk 09(|8r’%{$2֙xT6{'>w㲣:N-$jTuz:hw.8^ad _ .G3A-%n,m$kCa?y0Z7F9~Ÿ55%"<_ HGif(4i;kR D2;}sŞ}ŭvlFxu)/<:P.ԊD 'i[g'aO=jOIؑe_"oI!#;1LQɚ<OE $rv 興 lLw?n iM^&` d x(.mpv$r "Ǎ7w~'n%C'uGQK9mǏ#I mIB1(j EKa' 9vl)#]F*E2!Ä(|f|=a;0V]D%>b E'?P"\WÚ$B`[/z5} eW#4:ocڛdAD?;]|wX~)2k.">ZM8Ws ޙCxFo>n/q1E2%?֠&BZi X"9%xdEP!Bt*R ZHW ̩ܿ/;7zXr_@[ưc2 EԎRLj9{v@7wf_X `f}4HuB5 *!@T|]!0_Ó"1#c*?xV6 Vs =l'("vTsH>Q(~++WAzoŌΗW`@#(1L\»X>}@'j2$Bt{FAd{8|!LNRxȌI)[lE)y,L :nʏSJ9v/V>AlďT^+] xt'D?F#ṉC֯1oAa\1||x^:ϻjdU$'?M >p!So=* +m`JTt(An FfD_LG)-@K"zUkv4,0 ⃍ @`RNVbS1ķ |3UoG}uvƞ4ޜXA9utO PHjoEr#v.HTzlR /]vΕi/HuOjaSWlŶFigc$*x]͘f=rFoTEt3 1V4 %Im&"fӢn?O/ZH=Xf[Gd7n*M*s׶E6;|[p$[d}FIQ3kZh99Ly­CzV WcrqH-I2mk4Zhë GY4aj*?u'}2֭M_o7ѬGQA<9cI8MF JP_1Vs-EC",\rT%"A"6ṼɲS:}՚3)Rڙb~LVu8ynJǹva|QOĈRyCGxҟ lf_ve!bI_ pvٮF7횂m[lR+Y"~p'Ș,([U̇+s%#9 F& 4\hAykeUohVZ'/\|E1 P()z,V* UAk.W%H0:'1P3Gɰ@ fh? \A-Ļë5YEKA֟צ,ϦD{J=`/KdÒSɧpٿtԹajIHy- _zUŶ2:3%μL7lIo/i6Kġ8hݡ U{c1%makb]Y'k,Wt>::dK@(H;)/6Mz٥Yz?Y:Q+xc7BēWƘdoI# ki?n X#h(0rqЪ̞MU(c,?v{`q*0L$جN 2BNR `|Wkf, iutttyXHp0vK8E4LJr2+ j@'p R U%㲸adeO֝c]iϮP|N+~C'NՊHLպ!ɞ+DIgx6r ,Wm/8>,]Ro]]o^b֞tI}Y:RW.Ú>cn=b´{7Zs{1_!ˤ[ zߡb%I\:?{v0yWgi|g/y Ҋ}kauo?]8DȽʑb.Zn+%\hwI+/,YHUnp)vBP?֚֕ILJ;K9_7y>x߼ '}⽳/L[`WGO y(LHxqzb6dis#E_j9M%dɩ_J_n|"?oKr. R(0֎pxD&7[٠4˲佞s \7+8ӀjsT{378Cr?SU#YA@C>tRKEaěU L.*?1G-7<JeJyDskz}>*B[Zy+]տ:P AKLXhwظNw)DV/z>U \/=[~uc{RyC*7c:UwQo^3)"*Y"[H:$Yz+gl^uX)J}2LCi[\G!)otyQh&jWo܈%Bҥ]rفg(}uisv*RVN-+ot ;`"jaw|lwJeH_;z=%f>#t.tK]va`d)V]qLFcG%ݕB>'*hFt\~*7eqaSF(:]OV3s{U-Q@:"ߙ{ODr (08Tء[ϭToƣgip]kk:XolҰQHD c\*諮jv=4J*8o5\{18(TihF'`& a,qKGJ0u'07[4- `_V(=è{agnPxZzȧG!4o]|42^:)+Kbyx:蠗x *fN%gh^{QY>[- DQKuj'دwh탎<,>a> }N-0}gzԚT6hwryY)G~q6PmgX}3"?i}ƅvVU_|,ѳ)jgo+)kvB=/Wpz&Kl})Fu2J,D4ƷhG1#ބܲ ٖ P4S\g(n. J5ك\fEaU >r1sšWn%1'^F+ bH7ڶg:妊K˲ Wv :cEv4ful+ʒ\9M ?1Κᖍu\l >aQow-0]3-'\g&6zS( }]qPwRoasʙ?&x?\$q&vU)4+ΰC D9uQ > d .W,'wXd`TE`qP xf Ûl;MM 0X <^ VLun$؂rftwT { ExEN1,Cqw"^],듺4`5_\%W(TO+','%Vy;< ܈ojk+k2L!uR1rNfjHNɾEu>mR#H\WD~j-E/_bJQ.8V1*GQH#nJgVfgj-2O$l2\SuCw_eStm(p᠖Qٰ4!I ^M!5kŀZ\E@WAC*fFN'>XPoeΚޖ6cR!n2*\U [R%E糬܏QLll~1@*KzwSׂǕrHS5~LʅZ= C?s }ii@3D@4`:7KU2Mf5#xz!YΗIdvBwWR$K}No4xe2!3 :{"IxԀtY[~ JRRq鯈A6;Z^̂&-cA;C[-MHf3մ>uw\PcUOS ֚f0܋5&.'N<΃0G\W390\c1KK0K>k|E>.HMV[-K¼T^Z3IZyeX4.k`GMHW*҂@vjj 3Qܴ%$~5mfvTW;aIN/.<ކCWd-ahS4|&䰹CY]v5&Z\NUʕxF+Njbz ݇t}r@ 3#vŶsPv;kN}nX'mo.ۜ[Sh[kl z3 B8mYTѣҶd -C@,xğs:tO E kl@+Yn.@YBɒam I)5ޒ:}RT\pܳEP7oX @-5rpIc/lS2ENMqQmn)$=$M>KzLihI>\!ޒ[ ^>ݐ'EMZ^[L:o"SǢkC#rx戊]bS& tDzzݩH;:e͹{Ÿ0`_ؾrʲsv3NO#<[rb0FA`3%~NDXe҅n<֥T M8NF8ޜl>)kb3#^\M-nS Kث*n~ztU`!Vdd5k"6MCʦ6?ꊿ+fKtKܘ="qjSFX=A\$W*Qo䴯)GSN+g6}2Rj_ft5d*u>;h񖞩exBھY)9xs<5/Oa4DžlҪ!3GRAshuoR/~ h6A, VcV"\&á Lj=#2mw>MY6`> p:zrOg;$\x"bf Xl݇!J7c+hwؖq;tB)a "ܫˣq}bm՞,k"&>'s #6.%c0`?ܫ63=?4tr$%sjx~E- Vtăѱ7!`%jq]*MF_a*`6f `Tf=% 34Yaa1*$qˆ#2V%A٪s/F*HHЀ˭?? ; [-)3<ňX*vXYwT5Eg,}e}4;>z~*-oh?kWo"\ۋ>okO xJ_!& Hς4Ⱑc?Pׇe);~a1(~_>u x%.X e)}6b~掄o4Gr?Q\V|0:%[6Y ːw OXC--\ϒihY4'yUfBok^(_j _jBUM^82$j$?Kwַvv|~n,*rm@&KWnڥN=%  n\](f&-kV"F&53n)SfKt8lOm.[.`gN/2GT`[7PX{Ұ}#ZER:2XDP;ӫR?Ҁ``"в g8ؠ\ޕV(eсTܳr]xwJ|Lهk%>xt;;5-6"2Nsfz& )Tt7 Isvܳ- [`qPjAޝYc˥>*v 0<ر SAr+fZC`>c!ۇ&> wܭ)VGh@x 'Z!:Es᎓ 00Vm2u3MQ:z*[T9מ f2r(zkxϖK^QkvfNO4j PN;;O#ş06e%…JV$wxsJGnUK(w,r7yCKW@N-` h2Bd,S-ƲK9DfwlRX+̫r ܶwN )~C5 ­u74u&I~8Bk,M-15[6ڧ8~ԺŔyеհI*nUb>Lg'-+eT6E@; }02 _ Hd㋩Sv@$)c:][j*ʰt 9d.nv:&@ET$qCgwT7icE==TS)6hmNTo/^EJR!*tɆ{{i$/sxeq$p $]@3< zM``kWc& tK^_;|Xj-./@ܫñ;ڇ歐-3@Zn@_DzX}"]Zq#=1KAEt?lNvpՙP9ve߼^CqQ7^ջzy17b>sRn#CjYoΕ#+CxnzU=06f '[O" SOߌG?=^ʐ*QہT+tp_q"Xݵ'MDtkmjqeM7"7*}.q`זeݏY-^3l; jp5[DȀOm Sd.khofz{o,]r\#>z}-oeOga9'bβ:cO^k_EK3mXƩp„a;Uhe.=TIng$]\9F_(O >pH]q05Vۺ;` hOJ0`0D9ݻ1IV?i1yuPά݀څ j_(;Wf" _}Sn0thTi|:B\S̛fh}}'&$`j{6=tu4]Ah]DMMS =%.sfmӲQpcbZSF۞x Y70GMiFo|gڅ,+>{<4O|xr7 [I넢2LsDlQbYc!yYǞe˷84TRw NuAҶ\؍w%r3xi[7ԾOc:7 y St LcDY[ը 89Ր9YkW8rS]b7ǛfCf#ƐwP\( t| 'FHZo0:m-&Rilcrwh%]c3-u婪NO; ,->5ϝ9]14+zG'hL6H{YV'>n`K](@jh<^{CU{ƃIak$6A8*讧yX2zzI 0F4`Xo5$S 'kijbYgf8>T-IDW3 -S+ܤ4_nV./X2afS JX%%q."/ #T_C? jY52Wwϕwx [ҫsvƛw _F3꒖Seu8cmkZH?C=H'4ɘ`շun-K,H.찿@f @i]jR5jc }7`/ܱ܋t#{ b(́MhNAAyё>M' G~Z"?d H8zpNJOm Eܡ:r?IRE]3ڟz##مV -Ʃޞt;ֶ{hS Ot|ݐ5:K)Gۭ_ۊ+Rau}<{(阜AN|^jF/s&YR]4wN˶F˂U2h$c )G8]NpmҞcEU_WH[GAtsjD<1l倄d{* ;PL.l_o=^hͱgŃHJ gҔq%Me ڬY# :M,Tm3̉pA5nm6SA"f,027Ң">7/ۓwO0fK3+S8L $4Z-hmxt41 3O;oQtj% HMOI@ uE$Uн"Z!Թp('mɁXqI&Xc=6Hi;[_nUL0J/xDZ wh6.K3x S>笀"_^ %C$7H,J b9+# Ja/`o mk3/m*pP ?|׸vմ9t:SX 5^uR5|"bh~gn&xF1^=\EI #Ow00I4WvCI;_dRm@ An?=Qz7e.$8:\@( _,eӮ:2 'GB[0g})sBz[}C, Z~?$'r UsE7 &5ra$mx4Z$uH rܿ]Z skʦj.I)0d98t)fG0NTӘ1 i7v'x.3٣Ɣ'609Vq`/7r gKPGb`D 0)}+@bYIeX~%B((p۠Q~UgIdGߣEщ=YP-Q2]~lx 8*g{=k%+rsG5ENIowa)ُl-AaL[u2q5m2 IUxLK{\$TQCh ;Lʛ%cB%ő] LV9D.fOd"{98,ڷszR÷tc !ٶkJ_ l69mLu>JxNh[|,ob;O7%;Z[eQv )@hSydް';W>K`Dr&WtڙflbX "oŃE T:(u_C5Ѽ#< E< ABoOJs\ߜVQ I}v H _}uQ mEeDVhe 0J' nu$cdds0ьpDiُKρo.ycaU)2]+y/҇Dh?HĬ,gK맇kJ?"Β$̐Eg$1h!vwŠPD7`#gю =?E#QO0{xC5' ٧>'BG6`@MkB@܃>j6ޛxO~9[ʙo8>`_ڨ']N^ x/i%!>HZ=qd6}2E y-a:^nLs7vFd* l7oS:Y ԰J53*iȞ3ꈦ"${$μG=<Ԩ|nųTL-X*C "Ԧ[!2R߈xUTݪ9l (Wch8)`(Y Pyڦ#蝹=z8 sGٚìp,U m} ZZVQ]뒫~#rgJ-R,#K#ܗ\$BkIi/-k%bmPJY}u|3Fsqx[if H2HZl~(r&y5#>zIVp 8DD$Ӎq\ >8/a |#dK/_TFT_fd(DAn=_lY!*`/Xȩ]`[SpwɤF1t:*pT@5|ёxW%|B)?t%;cm(.SY*@tSy<>G^%Ď*qʌT{c9j3>`1i#$S>iR* ;0S;/=Cv ݤѥ!]O_Rx2+L*^"lF)| m$>nPBtT;եAGodԁ? y<;i2xuNߖ2lp=BM35nq>U/K >xƼH❸6mdi#SqټO5 GjO> 3 lO8` Esi`ĥγohC%.{E% d~];]):=K#=81!jYk#vk;jE=JYSzj;]̝]Y7mfU}96 n 8&c(>UmcӘlt2NNXz,br[Sk..hD7%=QXM SDxCVi~X,m0\V疰U׼+.X5CDԜ][wB4xv;])p<_][(qDxE%caҹ EbRDfHoIaϟ_&c>Cl@uɞw.;?z~Ks>[y}@`c֠;BGjJkQh߁i65G$1iZUjKBa.iUqM۬F ȵPLJZE'Fo7d^>^ CfpϓR؂{[@ T'>S'JgqJeS J]uf?bS)^B+<莘_F WOێKJ`rn93kiaok˧pQx@Ŵ{ެgcߴĵ;Q%9ղPr/I:A̓""sl(c_b~>R rՒ3W ʄêf%?%(KP|l\24)a"F+·t)9ôAF!:z-N[_[ .&{ i.* ?nb,jVi1'Q DU^R 4C)FCOO䧽4bVLI¾i?T~g B6/ӔU<m\ʸp/oF<fjexQB5/rwl䏺35#]/P>=!Xmu)>1<>$b5rڐ_]]v)DJ;A'gA8 f' o+'R͞G8FZ4r>̔3YivęS 0#;uʟksn?tB|-߷ EQ ľ p w%g0V5aQ#Hx/B}z9ygRY1Ⴝ}ɾ4`L{>Vg\xf'Т/6giLնR. m \pr}q+?kE$v)`f{ QhsѪ㊶7M{ qދG-!o2sȈ @ ryˈIbG3RIҖBD4[zr6n K~SZ̊b}vur3$zq'+S oſw!Hes\pܧJ`pq?QqJ,=V]UKRm)xd2ZڿT8CN[jDf?V5Dy;d*cE째0hH%cAi);j[ؔ}l: Mwłf딺'q(0g'la)O28fEG̘0J˫Ԩ; ֒e[2L4OdF3~[ă lzAgxհ-A}E1#!OoDKhS֋)rw4?7f27xJ[+ٜ ۅ m~ŕ` ύ܃Xj'T0bZ6ɶT xTG^/?Ze_J_3I,<SeSu{Y84gF ly`~b< b_MY:9Gk!6U}G& Ecy ,I;_|6jMsģ ދ9ڋ-c:o&s`ջeY._ZȂk5U W-ßuK*O& 3xmNepu k/,V EQ%pV2B{\,$`v"Q٪3wf(Wҡ9d5a]j/3,z#Eďj"Y ;nKؿ"Fw+{ͥ9HS #a./.=JÄFI H ~ "ys4N݋؝$f $ ӇOjpڏ,⻈_iXiܶ-{NgcyOyп|6^js.ظ:Q彍\@a'͛&D;YͿU(TmLM]($^57d*G~y)g3*_ ӜDz$Md6^iz;ѓ [Q Q,QOK`(6:U3>MdpIH%:ɟiðBQhB*ꥆxnl4 %:M|a>f:7eC:AY|x&u Qq^IonS1+Q h I+oP_爨IICvx#0 kۊL-z}]Ff0+ۯ1Z[֙"[dr Q$j\3B)"4xc~8p񋢽 q?ZG BNt\kAwYh,^ =Th v&ô)0b53ޠAGl8&j"rb`i) q$6CKrv'ZCPC&0DL^:_onƝ38GT߾P; kX?dd|$\$/93p9B:찊;H`&% xE)o_ǖ(9 ʱQe!%J˖pFOŘtmMw@~3H!үODڎ]vmOԫ2|%@&&uYe Y 5ڴh2jP8l[ {2 yz㔢8.U0ik)ց*tGO_(m뾛C6rw&[zBOϽYx`vv6{8Hv$ NM֤BL{ '0D>wړ&?snJ|e+fcR/1C4avzηl\|TJZ[)wYIXVa|H+|œ$;cƾ#wAj:='+!I9ƫ!gNZ݉bIe.xm o'r ާu 5x~I&DW{2kkÍf`Mr߮T5 ^5-z#CXWWG⇓/H<3(I Iɺ1laA^3 jand>@i?_;hc'h˜s< |}}]wRkۛq-zV"E-ѭX^A1eA赱Si/Ձ^z4,E4ْWcPF%C"* `rm_K R ʏK6rɡ{ oΆu2IXd,<_iՒt/2ր?j@8>K'g6& ?hN{rN&iIrn_AB=ɦK}HzpٿzxBGb9Br/(Do[ķeP␣,N#r1}̺b]%LOwL޶VįAB&gОFȼMRs =2rgᳺV̋Nެ{w+4X$f|wq[;|M KBz"ti%c 3@F\I0.CC5נ"{qdA)Q~Eg|f$%?㔷sqVF=2 <_0x1ה a [SQ_NV-ؾp̝_I5'ߤ cO+{7-}_qʅWԫ>&j< k%](dljN* rKtI3.y6{Cj~*)Twsz %E~iF =f\Ï]n$/[c5ts3*w}4 Wxs5/yQ@U1 Rl@N8A5`$ފѐuS=/ѐѱhЙ]_ /WJ)yu:vz 9G3Lc aZ@xMlNݾ+'twk0Y&CP*֙A-͈)@#3ԡqZ)}P(i==KdCtIC%_҅Og wGoasJIK\':k ^lz.uMzyճVlT1{[;^LgKگ3lUWc+kqs?F*8%am"t3 ŽՃma*j%jQf?k\^m$o:mT+rl"tbS8C\$bZ` )p($bb׾&;e)IVXv9`=稭P(W(zx2&U"39K_z@ܶ <8pƱRK=28}:R䃱νkwy˰+[pE7";6p3M@YrT`S%䶱zxӠj#Z]>- $o㰯O/NKȠr\=O}Sĥ "Uep/ʸfmXzpK<điAVh#U;|3@>VY…N5b)T(YDJh1hwbO_/fVjw6f`7(O^]iF}=y ضboĄSli_Pmyj^ݲI sƤB NSbĚKm4 2[}jH='qSόkoŨ>~/%57JcTU}$/֒w >iJI!1>e(5Т餝ډܲfa9fv1#Mp[$j%'K;1;Ib+9#詢}m`&Ս4T1%DN5h˅2*$Kr1~@:cul趶=/2tke#;9ԣg"ݺgbTX' kOx t܆(*׸Ըf5W)\4?mʑs!D:{-m; A#N0)j丂] QAYLN8 LKB=ɗqp=+8(R#.[N{v{U3x|`U&t/";gS׶UgA0ևi drCt<())qJٔ#gu.! DT֐!xkhnh+Ytt@dJ'3jJ )ǔ㖜mi.ύ~X&kQ^Dډ A,LĩﮏTD ;,n$_ aoA5`%_FC5HVސ28:{(Ѹ~?Ugܬf5A ou Y<;nv5_5bHCzN0hK?s Far hࢺ`Kp{ro,],ƥ QAXNxT/R7{8JS+UQ(h\E|Zt5v*(*,Z lG}eiނpՖ_'[vc#UBcKa:漣|*]{'hO/J?RD,rBpD9O}x:8A)0,XeDI"VIڲ8 ,@}jh˭UHr?}-?f/#7-ѱy|*n&}*//x*Zcz_rL.0jy!?ȁO-@)j(!& yJ5~h,f*to&i,ʝff^ /Yw(v۰n\*>m^ܚX,!/ERGj'9ECpRū i * $GeSGV[%hx֪ 'LE"Xh|wr>9 Aݥw3y7wˮ-,5]XV){UD C&۠p! |WEA-LJ @l4KhvDn(|>C.Ѡבk^NRա?ߐVJ2P1+CT{zOGKO1 7OK멖A4tVArm{/F7p`̃O5IG:0^gKXG3;mki5b;d# - >TD >NGeҚ٨R%Oxb.<QMFa6Gz@&:DZ=vE0ɤy 8 }{l6MdXO`|Ah" GMP킔xGeI,'ud0S8B qCo)o@:P]a4'~LTf>P% aja?)7h֓3|ksk@:GelrAB+6s-AR\aQf#l,*3ʳPԴUn7!ձPsfP玕Wo{-z%AXwjlQ3M*~oHHh޹{rFjTy2 T%(l'_m7;\M{Þhx̳Vf[5\+8((nQ@ 8tVGMfwq&BHcU>ݿD e /`_tl1Ф*($1"JGq8OhKa ,?Ɇg=| -+yG}\u'QnDόDl ȼ.(ʛ((NV7`cUY͗>tYnĞZ]R>%Gv}i_탄G]KsA4}_IZZQ[RMB lУdl]$F&9ּ0l"Y[\YhoǞükJW4{\-VD45:(.z zȤ/K(w%Ԣmk]y$J\Cof8MI{7ծ-~GPz{]T؅H87#rBxPi K38~pqB/DύLy4ewh.yaA?|AmW#gBY @dUj)(vP 2  )+WPi0&;X~4=Yؗc8o.='FQc^iUWZweᤈ; ~F[ImO4 IF}7I,?^ 3(f$qr3$`⿖3ջj{ [4;J=W1S)8 +%ؘ@x-DjDjۧ#)mu3wHùLKd2|pBkxiCD3 $ Q}9ǺLټT6n xe>tpσeWFyw[u.=dr Uu7_eikjj\C-/"kBl#yѱ'$ClTf lZRԖҏ(~n{zjQGnQNʼyp,JuΦ1뜅;bi<.G~k2zG꨽dp(aΩ" [Afq -LNy:Veupl2OoAgW^9ED,t|׿Oω; VwV @Cw#k0xp勤B7c<Љ̷ Ry7Y'C$WW"vW_%S&^:JosPkXBeMb T5W$f}]'$I?l 5*1>x8ϯqԹ2q՛'-1-!φ H5(<;o_=C)_FHޤoitA}=S;Ds @f4TNg%|Vh5VSW Aeb8f69E}Wj[<7~`[?,\ 9;=)J5bˮ3D;D7%45eݶK=|q09s!.S\r}\mwS :`F^TT'lJ.Ǒ(䰒B|g8߼~WSx(B7➲.Y& uu_s\A1WH0V%ռdz<~N.v|^/e .8e1JNʣ j[@ށ !i,C8LSIvU6:I]l:fbQ.t2\;}X20?;8q)il0_( |Sä`e[R +u{Y(Dv(J3]Lw)L4j %-#HTf2b0Ye (IAq_ J8TŃPķ$%a!sH <@1˫AknI.ՖĊbGc> |3k}rQ6.$ϺHm͋nAhۚ?H7sۏîHl^Cr7}G/㿸28}w"'lU"w6لHHp(WJ~f 'ey<*VQn{H 8/Dy7JnD'U9mwL*8u1ӏX pٶJ(8wGʛ3\`D ؋}8@]V3"ƖҾ.tUc{P,^ 1:6l+OŔk>U]/Q76id? {nHh{Ht0X81=%:-'w[s͡]\̆xyhЃ-g``BpaAߍn}ݲSFʂ~)6! ;ȎA8;r}g^=ʮ Ƣ׷Ũ[<%15CE ϫ]b"%"h?nPO vTꘙݿ}|_¹$&|X Uئ_[egNvR,^C؀X:_d9,KA|?.ρ %Ʃ^FPe< ,ٽf16$#]HK:LԊ={ǎw 6~{8Zo,fW/-%ΏB*/o1CI |ML=.(ǭ8,ԺjOemM!A5rmx C*}"h,/*kpZa5u?V((W 1S%<EH$UBYK)̥plf,ӭ$Oai` &>zFQRbJv86# J ] ˛cmڶsH(t6TᫌtQ-Iƶv`ЪE Il0#N}q\C\c Qy Ԏ u_\𕍎&<ϝ] 3ĦM" uFe)D,C踈Q@1dnJ: .ݱm6τ޺+31=YqnC?eqdj%P*ͿǒwR|[zuЍmjMʁ9VIUmF /ƌv- qhgNѨ;em_sgNO32V;(@",d3PJ C?ӐRYX%w%ot)f am50 8jqcdCӛ`,_6s}v w59Nq=oc''P{y 4!X5&7o5o'Ϋˮ>bǪӧUh]ڃn瑐7Zoq9sjEN7WA?MPTx S̓d>Tl#+a2Zw {e+ٝX&bt8 @ɰ]i}p~FLbk yI'Ln }>}ftd [kuC <~f/>6'ƶƧg )7k PoU3 '%zzű:)u:Vk8x Uyq\,5]+3x,Z9Jľ9l`sqGW(Eohl|.ܠm5ե{+e֒I|5pzs2 jӥ5BY$V/M 4gf@4=J4/c=5bĎ,.WΝncI8L/P}BAj?pϦ_ %CgpjeІ7ײ^ e;h%J9h\g<sǼlbpbLX03I|tL!UZ ?#T[4Bwf#N3AVP(kJI4aǍ@g LE%.ۣᛆ%J+ Ͼ[MíS}Y<*e~e z]PVodT39Tɶ%NLC:ݒb#L)Y} v+&ֳ ZR(;橎}$ '$\AAiĊ&ĸw/YTW6 "7c7]]1*1ճøY"\`M;_":y)=)mU,p0T6 x#gliT0A͵z*i|fEqPo4ԔG=75\B8Q<(Fޯ 9 M315yU9ق侚HG@B\Wddx5rA~+4 X'i{e_qGTu1SN '$̱C#rj5n$wө^YY?OԹionc\MBFLW8@o-˃}eJ0F/Ȗ#)RL@dwϜrS4I\K?}pJ {IbC{O)]L/|bQmv,Vn]szD"^T={+ YGtQ{La8aʾN";^AaxgQCh ;j̰Ro2 5r!ZΉԘ(4H$k fyL@D ٱrkN-Gϔ|As1*5kRj<ЧF nvUHcYu_2QzQI^SHTOyK?s+w;Pqe끥`ew t鮝4T314,;eewkǏf/] !d_bd;M @ɯ[\7k~:=%u[T %8 `Bh՟>6۲zⳌ]x 束+m ʑ^6zaRۅ%%bt7̧9 Py7inۛ^zrV@Q`'ICH Q;<4ޙ{O5h!<3$;և|\:sc%*;1R򮏰H) 15l)l~s 7PL:$3(,ʮ:Ѓ_˪{ͥGž>>v»s?IC5j?֏`{C$$Ĩ)Ѽ8GToqYtreh|ب/me]DUBn6'xg@δs}P?IavN5α͍e֫;Im@EC)?O-'\ ,hf3vv쩑"mكCUSO\lG\2I'8 [@BNַm')7dtnKQnuwMk5.b>6TY' dƤt%>cܺz>f;?Illjc}^X8X&X ]/*wٴ)|]ƍN"( 5P5 㴐c:cۢъEZ:ƟR`J♜s" ӹm|Dqvz ľN>N 5M p$C%.W1hJ1ox|'67,84=`Rx[ {څ]E+s1 nkޭbOJZ濖 Pf"DuQ9AۙŶ$­S[j!SjBÄĻr/I}rќ@5_^l9. G$I(k==y@Sy 3T4壚$5{=JH4p#e:reơ"4VߛA+>ơx&])$xLx LJV/~\+2qo NA(*yr/Si^w^1@4=Zv_/SWsbWDV&r=ͬL\X7Qt&BMa9Ek7>O^@a, h4a] ݱ1.vPKcſXt"bX j&2=Q?s-_5k²[q-Q{`KV훕?2j6FM*Kxh'iVt/~!\TBɸ3PJ6*g:_ `W}8X.0<ɱ[_2]h5ѓg:朳{0D 2I3N>.&z3m[{䎴2JQ=s'=N:R( os}h}ʔ$-|?AٹT6@P5zYT7 FT(Kze@ͺDWbnP>mC/~Ke6=òe(uG[~s^^?LҐI"US> d);v2bkumRLRdl:`/t Ӛ(虜Au𕯚pUe9N2 :?!ca}<4*lD?F#N"6e1ErCDȾ4kM.;RNI"mw%V0"9{*nqhCZXl/W(7ĕY-lb+yx./Rg3.1o=}hE=i-ʛ!*{Jӛhh*U#X߲,vcM ٝsF sSҀ,YsF*idTke>]ewhh l(PZgIqn(+]-uEXwH.:XOӹ^np:,EM*T '8%m8ȓ"~ CBH S[nZ:q-]F+PR8jH-{S}sʼn.G֒kh(>%΋6B,aQ|ŀJCI Oq}8w^`Ͳ 1#3h`#:B9ZIk.\8˧ eZ^) }` ܹ~JeY.C\Ƽ_b%G>sr֎Oԯx G< u>ϻ־n ݕu>s =r9|!q:TAVd`5ExZ ys^WSF/ ;KktsJ0\MN{= J4:jՎ\yg:,v}f6OVqwl-~F9 &v8w,FNGP cD$p6YtXrA:~`cQ"vH H88 #>¸$rZΛ~\!m5f`Hob#r0NjE5방CTͥ{D!)+1B h~/KȒ6ҟGSBUܗH*J> m^U@U3R%+ػّ߄y<$S1w>ŕp\QNt2W(" :X{Cxډt|>hǔY~YU0RfaC7l$,uK*'R3<(_};y#fiە&ReLjg[S+ 洳|Yf y➝_!i U`}fS9A`9C_9@+@;("da,muS]j°x"FM,rɦ2<^=JODz 6z@/ר[ȴ qvv ;xp]"ѓeN]P{)U\S%]mj5Ƙ֑55·T~?=14# r _:${Dl=c/K&R?t F?G&}CӝnLbjk3ܸ'w)mlgbU:K*&v4@@sX_l_J!-=xHsS#Rohr&{,!A#K<*Xl t Ag?1hԿٱ·zu'Ke3([[R|"}oŬ wIcRC$r^BK327t!G/?)(`hG˪GZ#+:][("Cwc5W6߷=0sv[W̢;hW1#5UuNk|mW:!I:ۊW˝BC~S#KeO.ǕwY~{sc>ijRwQ 0sF{$ƦKZ``^B,ě˶w K a>00jW3n/mx}U]\}= !${ ]vIdݽxeKuDtGPV$4D͟& ]@ gt`eL$Rw ZFL9eG0})4~ ͷhȝ`x_D Yr h7e)DW9u %"KRVOarFHob9Nv2r) ྨ -Vr):8 \z:8!Mda rH}P# r19x_4erN6 6 |dMꔔ',l;5d6Aug(ev' M L|) & Ô Ss Ni?q;x8yWipKղͯOu3GxJȺ8N|k2Պeؖ+״t)uOҢVybݳq_5B#FQy0-ex鮋 Ü?RplMШ@o]NmhƒؕR˿LNӱV&Rѩ_M9dK^YZw]H^Llڰ RQ9Z>'pO6%Z#@B&>k 3\t% .|Y'.e6xX["CxQeF#=o{T`/3DI|˄6 _r:vhX7T$JP$0Ž /ÕG,+n+V#I`'pl( ps\k L+YOD^)s_f};5FIZ}H]j_ꠒK OH}^zf.%d&F̵c>C *tB' >b$;8FY}-߉\/c|¦^\"ulwNʌekyk6K3,,)-ss`]&ۜ0auvw$(@7d w t3֦WfT~׃i"v[g\K^Pf1,;-=M\ExA(ZH29 u Í"8:޺ ZD:JQIBψL}X [xR]+Xo\z,8&6.ZwSgcQ(LER a@#ޟ1rqZ+;S6rjn|Ӗ7~*v{]/7* 9Nj>8_č? 8Mt'0'rr.zjpO2!2.xuj8r#v2,w%TB(ΧnEgAW0;-`~l0#/jVLEWɏ5TXǏ;wzr4)h#hT,VwI' POh)Ը,:JȋWN|A_6/, al,.{qw$E UjlJvz^b3qKympLUT}vT\uQI˟Xg]!6@u4$r->BNDc8K%>#(p7^_;c5"Z5l@حIJb@B$.i?i䤿8>["˷K\K>,oX&(SK& U1R[\:RYDL7a}H@Kx]5qAl_.]6-39gFYЎ]npӆWT{]z&q^! w=}_JECG'(dGrB`>dql>~J8V̨b$ђU4ѕAhl`h|B~@ _*i s枬#yK9bR&@GjJGt$ u}Q5ȪąåI)uE۰w./xTxHq3,@Rk|5w~$*[Ht,5SaqE΃-c̚|=6@_tmZ`o;$u'J0&+L:;s&>G iP,x*^0X@Y䖮jkt,!C$1} 0[WxgJM'{GJ`% % f- %n3 );Ia>rH~'}byo&j|y80z8ꭲj<`r輱kA#uF2Zc'д*?^ J0QR-w&tG@h|緉QCcQ_hT;jϓ6/,E P~%|Mù"-oEҾ+&\`DC ?u74EXxIک)}nUt ^}Z=ouA"x\vM86 ) #TP'XE C9n;s^J9- ɲgWU?q.Z—B4u%z9M̦.í .DzA\ވ_ޢ*XGu/:0"_.S5 1ub>s",AU '#W,u>RySjoy.AArw5n@*^TcK …î@@Qu K];qkϺ #!0Y/ w: 8.X01vˣ>,.%6rxSөH(>>Ѯ/0V(EبcD%16\.!t ohp*¾&#ܒ' F6vN>B8[Vf' 6gmܾSͨAt@1cI:icbMiĔ*ks`}s9d`e1gwO:;Bi}Z4LY'Wd= Ɓfdևn:P߫ BG-tՁu%S0J`;$7-x)ys)/C u MZu ORv\z6\|q*XJ޾-6-D.+JefoeVa=hg2L=PR6 ^KeMŰdIl)#]z#X@~|Yh@)WUuz^є&4s=V}BI^05;BٿS6+6Y1A'VP }< ^73?#94[WT j\Nnkv=HrɎK2f֮xFH\ԉvz:+Z0W磓+~ ~e ϥ:hjbaGMmhswG_;X`4_eyNѩm-W-]_Ȥ^CHHͣ´z*Q(U:q^qb;Q RUkeJ-¢-laN@uĺ+|uDʩUPA^O@*ۄv0xW\63|yY7 O I'6FeUص'_zT%]^'J5 / Mca3z:qšskspMu48+- ˀ-)L sĩD$ǷD3#:EcUaHYVuBs?u/ϼGW(дD=P> źl5f;رlPD7 \՘rAO|WG,:HD v05rvG\,-)mΒnJAJ{-램 Unӈ>9WQ³R.OFqHF4b56;Pd<5HDed7E7hvdYk.:A/v^о)0p}лLnZ|VT_ug=$>Murk }Zson7 ~zxp`>h?i۴2UhCR1~MA> .;|v-{6ޓJຆN$+Whg"48gd';H*Oh֓ Բ2:7{<| pi0AJa,uK6M爽VV'I53;,sr.gg/M uPnW0]`;61ťI:ךEyiy!8MF=9!CӼaZn&P2[]w'" 潢_~2< n0/Q$"!L'EVE)p&"*bASS ƾ|k^E[=w\CM\,Ǥ8<8hfa5e$qcQ_Rqk>vǻqH 3쌲9a5"hV}AUw)y{}T vw})0~L- lnW1d/[D(z+Nպ dbpF5nQ٭_a@^</=5f#>ٲS5rg'ZpaC* QFDҺq¨KGW6Opw:qfOPY@#9wE%&+[t4zt{,I8I)Њrz*t|#LK !?%5ҿ.:OI b;kIMDn5rK05 c|*]}3LWS+طƁwX־JQN"]]o /ŭ%hqj0eTQ% $osAh Yv {G@~3U A !.;ԵҠG@ `e*ּV`bcAay/֭ጬRmk(y~a^sjdW_iTy2 и ]lfN'49mP..O=0K0D}-(9>>dm17G'p+<-]V3@lhA_e>%N{S^EtٗeQN𓕠xV790Y+b*΋jg<[@LE2 rF}hF iE}d1 ]cl,pb{pqia !P)QXG5W|t]?= IŁK+²%3˜r3S {`3l2?Ho:}}Fj}J$চrc-5C ٍk ?r]Iݱw7Omy5CHL(tb`HmԢ5NN5JiwMHV]snaͯ)^Œ̵@zވ»sM9?Ҭ?DTMls+-mmq7DH S5AwLOHF>ֲ92nd1}U#KI\ѕg-A153 ]^vLu>(P=[ܰ39l‰{7`O8rU^:`QCa7EƮ)ň~6kvd ǷSuDS̡Bd$5.cCILn7PmDIWah(t˿zH/-e X3c#rto߂fܸǗ [#j^FNfkj 01 't20xhhrϞp9c[."0Qg.YuDWqH7~y({S,"`Ɔ_E:P/7ܠ8 Al']Y;HtqsH8(e~"7&Y~3uU=Ξri|)BH[L፞_1I"Z4#`%yMI&)R!I:cpӒOj{>\}RhN07n/OwSxfs g&\A{ҋE7b1m q&w_R#)PoOO G$d㰨o:y[+VDI9bַVeC:nCFN*`S!w F9}1h,TZO%ϜT.}LW{ zkDtoq]m?[MHhQ¥@؟IPWh&}$}mן*n2Vʶ[]~ &[C\HXq4hm33|4d囧`|yNw1blb<6ĸ2t>,;/@ɳG0?h-`-74 C~֥8;OOqay3uiAbe 3ņ{L8_.,$o, _q^;%P)=}<5[lbz9*~BF- L6wx;]$- f2Kҕ{*RgObo!rGUPwݔ"i!%&P_#X͛2'iXAeY[2=(7 3dHp$I? ? (ܐjd0'˝ԛa  J5׷Z2.ݑvI-Ap4^j-'c|ug2M&b >uug|ĵ2[1k(to)h%YNdlїpKvg^z7I.d?[ rxb x| ?HU7XL_ %/y9FT$zu#iz:M9XC[p)K˒UܝaFXrgQCHe,o>u-_'Z5CЂ䋊ݬ*!/Uh0g{䘝N<.˘׹.UZ\#X^byh1[O a-xmnMjgOb"6s) GS*^>0w wns#> Wd}//=ȳH5|>QV@_*xa;YlBaqM Y;X8~/m3 HUl[6³KI^uGB;C ;=75Eog_Zȓt3ku׺yy!H|CKxC 28~(}wԷ7Ȩ'j1E=$nC#8=);I`b-OvNy["DEC :w>ܫ\i 6mw/0k\- i9s3VQA-n#!2dmَϧqZu1+Y.O};35ŀ[X}e]|e)HJvs5cEOAqm|T{-.iZsiȰ;,eMrbgUZu ˔AMpwjRnQMVaG_x9^M.ӴKvZ8?ރSIU/*/bC}]]A7`C\Z)]'Ye:vuV{QC] ݗj79 WtK1r<4;pmNthkD;@yyj|I^,_}uz.mƊV*Vw~!"!;~:eo%!sg2ΩƗn'_} y-O^ApZas7m筼gdؔ krN@yw ar\)t`^"modb7*ڸX9[Xj36>wH9F) @wUj ő\*-Sr>4Tt\BAJVSNOhY㼄ֿk J?)Tp PxC6m+x_p>dj\^cUjWByyhZpJ+Op,1OwDsx$c."{2uh&zߢ0*yY8<^&b/@CŊ }H4hPrXŲ 2 ȆP*d(N۸fw'so,DV8mx}{*2w68˷&m$Vr[32i]1%zZ(qŗ7T$pdz\9dp"ߟ{h-ґe%-)4Sk\fi")smu-G>vހ G#*~s0. ' +3[ۤBaf[="F0ҐÿUl~[-+- G}9$-w y/N-)by0I!CLzK+rb 8l޿l͍ ̺&L37ڰ%R1 ۿw%ߝ8{x5.L^שU$)eEgNG(=X1]Rk*lm>BwIN"dv܉By_Dtc&m\NG?5! MݽxwWjDoK==jgq,ē#yE*_u_jU@d8 .EZgLSPƧڥc.Fnw8TxN|YgqGp%D*8` O),LTr`!Wڽ=I۸Tl@1J|FjejLVf]W<:"@MM\jZ92nnbЃk)J>/=]Y]6.AӒa$+Q"]m@zPBf2sJ&I6՛ ҡI\D!)$4qj䮈ΣT]'%u1-B`Sa;Im{ts$#GzbVw<(kj57wPT \t ,~4d,B%0s VsCB z*6Н=6Rz[~;":.㜮;H {p |>rĈKc-/{h2;.ե0r77 $@c!XcksoKɂa<21oBvx^b ݶgcoBd"*|B ɄSރ̳:u¢uT I ]bg4.,4%`" _񠧖Hod @Ibjǔ7V"q >]@GVa v_ڃt#TvB ,|1.89 fV%i@i\Ut l)dP+0жXDxXY؋)ݍ vSʗh/n`r(dk$\FiE-HUU|8E`Cz!YqB11.{ &s;0}y0wC%p 0LK/E!RL#_~j'*JM]0R2$/ υe -nG?-!KдN@p+NK&U199tPGP  i[j(Xg~ uT {!TI馅wIw(=Gvxj\ar-zcdRQ:>}T Շ]܁8 ,U3"leuĠb sA*_=\$)8[Ia׀z2&#^KTZ 獿oxmF\%tw\^Ӷ<]v&_T1SJD}2k KjTvM{m\P`:K[ ω Pi_ǿW XWMkT)EJSr Gga:O]( QVC-|#vqmeSBtPHq~MY3 .W[J|fKI;, O;dƒЌ))[>#T1&$~iCKaFXZU ]f-% n p/XDq8#{G~22hV XEDvbLQل|8ytlX Ů}b. hںǥ6 590E@j#ݴZVcbC 5 ;,qy+%̠hAY3VtD@h}A* axߢk @oɇZ5Ř D> cnB ]μͭwIp}r9z"{h{`IB'7RB!0`{,%tՋPA\W2@B>I(g%KrOstI-Pw $!H9vU؜{CW7Pehq脽~åYiXMu5ۙ0YcXd ̍ n} D/ 1|ʾXGU~2+QaR/ !QL.n5D#`kd6WGVߦ@\1'K$`R96QwsEηP582nt ,j9fU4?yYaF{Iu{PV!큻ī+ yvJUSle7rS"4 ‰-4Gt A;\7ƢБ E$:Rq#̋沮lzk]i+(c9K}~->9Y Fwg I׺«fX< 1|!CU);/joJWxxZ *|ͥ/I!q O%ȨIWoZ ӝ|2m@4gShRF.IܭǺ%0C|eV1ZOo #0Zc~uQCՍ5&Ϧpw esǷ ۼ_aCuH('jFOX]Y/UNHvaMt>Fre H2'ڤ*;]ݓHgaRE)Iss$S vĒN1,qy TʚKFSj"~J NUy$Zp) 7k?5Q; >ϟ$+xI9KfL37yf(QvG6vHY`i6ݿ6VF U7O͘=b:!h< W~3Od-S$z+[Swc6'΁F+vZ;~:Va<؞;9X!k,7Tn[S5u}gtR;U @@*e9(kϕx7Wݶ pWCmPB6~evi"A/kwrSP,fŁb2Z^6*uN41D{/O6cPtre K>wxZ}T`6=|Q=N.LgD7{*%۟[r{˖ksHKz{RUͭ@Q~;5z=RdBny3zAf;KA7h:գuw☳p'X^:ٹp 2uofcf,-).07r+a>Ta~3)oltox:!GS!ؚg.O7 /):ͪuZtxzWi3j2hg IDtu$A{xj=+[ {q \gV¢)o 3@Z~((P!W<9Y"4ZΡjYX+YϚ;+~[}$Co%sTg$#hѯ'8?6Dsf1|JY+p9J#ɦ62JbqvsoF##D(0#ŋ[GUx )wa 0ѓzM|ٖ[]tb| 2<|'tS`p"T<Ըʓ f=odxEKa#;# ˙5ߠtΔMkKJˣ{I3tUش6 ͗Iq,LeFF" t\왢ɠlSѪ]7|_PV*2PN Fݘ^X'{>UImi=vK1K \ sC $t/\INK2&[aHj:[bqPd?e;y BRt-FL? )ݮ=A=rhs^Y IP˧f]v1 (' pc0cA!dDyY?SGdY3}H cnSHu65̥4]yVWA3khg]p'mI?OKYܘt;8R ̟[~nѻ`w{Z*mXϠ34FcitAi[lfuYG# ltJ-=Cm`ظNSN%dw?t0i$W4axx([v0j 8}$A9V)!!Ex0v1c(W)YZKY^*Hs^;i|c0FtEPha3#:"Fx('] L=S@\mFXz\:{ bBpM2dޛQ1M2rjgW:މ>^h7;";hp-{QSj((<~m!t^0j+O_tcf[G+/n5Ð.K|‰5D$z4k,@0Ya-Jɜ@34&ZqvoLC.d΁SNJ.vl[żE<ʉ<9`.#%<`F{&w/IlZ_/ʲ_Q͛/](!b E>簍UmHO9gNPsI^/ qf=ew*n_0[g2g-~rU7?cc7~޽rN 3&˙ x0p>ni=a]]" MRVY}M"E-F^E 'K*3pei[fNgZBaΞ= VP,O)q ߯7߄2%qOH!},f^"&}~rjYWܕ kсYVK6+Y].a1Egrw} qH#SdȽs:2qFF]xp̌|Yh V?,{V;(}; (pd|j7;SrkyNg>-gH; y^1 ?oɠoyO]o <`/WrgKKy*N%N\.Pv!1+Ǐ5M2?K631uO+?Œ 6~Ic1Qa!cFE4s @h\5!d@d5h$=% (<%LFU\b.0_%ݸ$)(G1DP8wa=5#S;! z}xA_= 0.. (6zTt ,jTx0+7LxϿ¤#ȕa\ڴtm?=&RÞdzOqB= )^@ՓccF;=tp IGUqيHB;!q^tK]t1ؿ˝mCJ[c0ݡZ~~#%Q(hbyvc'f蟛(HaHZ/~7olJ>CBjXtk0\i %ujXIg$o,MreSt| lAV]eG+XnԈ*yYHZnJ4A@z^ya5Ywb ͿN|ahoR,k7u3AwN֓T05¬& H=+6a:A Q֌}8D#E2qõU L8')wMBc7v{U6*zyW$J(-Ũ102j+Oh,_͠P@Cҧ^Q<@E !F.+K2PwFG=Bto j2(ӢTtd?q{xH8GTqFh7TbthZ7b}q{[ 8Ѓ Ӈu03 rtfAjV4bSV-n>l\r`ٽ}ث#(d_-\5e脸 3wZ$l~y lq=eE-Yp<@P9] '1{d9h-w./d/(mIm,U!5yB a(^rvTLQ |x r c^NDu_od#-"xF:L2Dxїg&O+1 7iV4psa |uWU}C8ǭVP>v;-0+r:}D$b9}hk.ASA3h6Mr\BR]M^cc%-Wlv .g6ȋ?5,b$;Œb{D|wLv^z(d@kjEH&QQH B}RJޅĦZ]Esԉ: aJ)H^ ',m}`~ʮ_& (PĝDrd7G{CjlJ[Nlm:I/Ǎ%Z,bHXxr3§s:V;7-iD/]m6mOFbҪ޲7/@Љe]rҴ1iXN97nVIk,]A6wͭ8 <"J_ "_ԛS½ؙd4 Qjuo03cQ'Ġ5m]igTPj)}am -tV_vKnpeTLJH68DIw?$cMbm˗8Gj4Rq]65]Fٌ~,(9=Lf3KE/>&rlLN`Dtv ްn,mPOD2et"eVm:2[-)T9. `RuؗD3?_ Ku"M*vv5cJt=H[v8Uԯ$ȝeQeAS/ԊEu]JYʮu{"%'6 Zu5L: QgyĽ`ؗsmUzLbƲj>C~lVG+@ F dv ejy&k4 v`ԁ%c9ӯּ /K󴞍̦ -d5G;9q֔qήuJH Lr{o[(ӰŶ)"xZ#?%G/Ka=7zvqx(³b\yk CSUڟ4wV x;#3̣_` `!L į&03yNi\AWO)Te/0cjwByOई,KšS|WvbC;|H.+ p'Sҟ\H^4,:Cs,#vn=R yq*u_)2ѳW(-D:>.%8)(5.u5͙\(/WoF A8m/)Cu(n Y8`"&]_b _Y_E-7m&D!eW)}FOH^ -y@P{Ca(cX!JhPt5u2ےLl:/oMEIK sZ9HŕKPNBeϹ}>tzB_jpzٮ6dQ RSI{9MžD}Gv_aqq O{DCCWP\J7eMO4!x90M9F҈f1}_kc,z#_N< 2e{`0"<ˎp Z wxOtQ:Tt\S9vؘy+nb2_Aչ3xIG9 zǻ) Z9 8ºNJYC:L@=U}E۹u9Ο۝BNLI8ĉ?YcfA %&z6xl?I[%_<ܡ$@5qaηơ֮AYz ZCf{|w|;20JNM1qgMNp#!B̻ԝ2.`Mϥsu RD?kC2@+&Xw"dЄPHJ|#+v# l%Fj;OmLЎzImMM!i^3Èj4t6 c:5 yRhOY|j \_|VSʦ0˚Vka'؀}Z:^`XSg0(%::>cy쏰Pu$kIMr.`c{[N*+,-Hj3~e`7E.*|'dc\Vy].JhYQ#B!>=8O9تΕJ\$2q2μaL ~Qн;d3*$yVj$25%BKy=q"-xXjP-qZ@EUB B]: 3~}r\ۡI)&Ve 5A>4<+Fz3Pk v,766YdCxcq n p_"Th aže 3ƉBs Nd2r(:?*Lp%k]DԣwE ~Ra|18x ?7I^V h<ɔG%\T];14ja^ʘ;97a b$\M)o[s:'Y^j56BUT (X|<#ٶ1=(]c͗s/Gn 4kn+'OvWZibk6a)Hw"LtnA@/YGsmqG(pd螫]>-C;́p7V)^O[wnEҍI Y8FH1eq?}{H6ġs݄8ٷ-f?A/B•i& -Y+W-#:9ω}76̯ՇE/L)~d.]]"ϵ~̂w`F4N$;D%#{7+;T*+nA @;rJI?zKHK | 3&h,ᘀș*]OݍZS[okXe`C^hb Z-%`G*:8;*0 _ ~Z0Q J&\t2peDs8>JC 4+I$io D Lx |9Nw=IuHQlLb.əzQ1T.+Mp.~̿5/YFfbPP{P7&'dx ˆ֮#i .Z3thC5AΗhcс h.&^`2x3p/[` :1xEs*S*STԛ/Ў)VR _IVԌ.$#1-LsF zLԪl<|q<0('½j^8:V[E$sEB|-K,szuϦ1XLH^M &sRZ#=Qvi!N?.S-N_w/Ef v˷l7]&RJ(P' G͜4["A xPBNu5rF6BN>ja 3ާz޽FNr9TQ(1{>CiG!j2yƮ!U",TmfDy!}[.'W 3H~ޭf&؂v7J?kٯ^/kL5 vv(eAa?2$e~P+ tlRvU".x~UR1ohJ0Zdk)hv{[Hs\@lOEv BØKˬxeFrmYr0Pvӳ% FO.sx2\)Q|UO%-P b\Z[s%ۧBK3k`lBfUQ&lݡ@Z u;9AGpē(gqa*[\mZ!i]6=Z9ij}_fnpSw~V.mlx.#_uk@^E}l C{D# -}햇vu&gPkGmcJ2*7޿%/4 {1u eɻt++?dxomg$Z (0'}5EyG^6)L\=eX+S9$U9`6g!\B vM}~6&L&@_X!E" ^~(`" _9:&?_s2ޜqJjGPHvEiU Ӄm,2 TH]Z݆*0^ƼhV%Z|9#WOXv_8_Q2p?+ ~dY=O|7/6Gҭea,_^BQF So P[  /Z(y kMi鸦!Du&7mG8Vt5%j#e; @?jV ]JٞVZIXJ7/ݔ2UJXW(LT}/i2p_/M5A&dNdkCTn8}14iI Zv-<_ O[4u&[?L⟡܏\16jX-j "2cUheyJua "3ۢC+8g`QQ0}bt mR$sH /f 97(١g?;|[W҆K21{H؁"Dbw5\a<v$PA < AkX_S6u$CN"_Dxõ7vpX9$r-P az׶d%ş`DvЗauGο햸lG}0d_{-z[q6 ej6Dϋ5yO-g |}p^G$m5Oc -cǦA# %Zo$ՏFa vBJo`Okj-⇢2YZƄkh9&ͮL.y'TCWJHĠ~:Zy:!9 U*pJ1H'} {ŧH<Ԁ0,XUCk\3,͇`~$ a*հ<}[D֡ƽs`^pZQ΄Eݒ<\i\1)(] :0W{z-yÌeg) S[\ֹ("̞ )]pso2fh[`]mW5gqI W疩zx?חEjOOe}iXHDY_= ،gqǔQ]a'XD!q1Bn]'P¨>;mۦ=5_!I5 `>cV` e(NaQ^y'~"aq!+i9H ;9,ڲ1\lO瀮QӰ忑g_RV~{kbtZQIR ;Q)^`6aBmpyA7w}"D^+ "W^; 4NZTHNןb~lH9`qcK-px|G&d [LxKsYamaf[O1.P-vSjv$SM?w) "HQҘ`nV,mKY g-Wj!| tYݼPWf=X~T:SK4.bm%|O$w~vO?l#B3cWunIR2*+g)Xm "۠.o ѕc6ͧ9cAs.*Q8JXF0h]<@Op$n`耯%|P_ٟN?HUM)d t*GA,2]d]K)_i9$ RlCc/7ưb4QOu! UIDFfK) XHY D!d= FPZgߔg6#K2H~Yit\MF׿`z G^VYRMWQ+u!Mvt"oB Veɑ"@W9S"f-i) J*~(BMuhPp~5$aT~Adckڲl:WcZ3 " ? 4[d,k $-H_6tsO_lPOd0*ģgq_cقu>q:?r`]{uݞ.uG;t߮_rP.$1C'װ|GVLKK2(e Zr!QUޙe8), 8ɜNTBMpQ/TCo< Kݼ,d@VS"gMZIelKj;,J\1Y9R;ɰc>03*X{} @gAΨIcdO%7Ri~y ~&`:R&oU z?fc>P aJI :eL^TU?$ra^KiIr i*Cm}`6X/=3,: C<Җ#n~,w=MURFOw4y~V .3t&q[9]tx#87>۔e0vY՘o':;*0U)4G,hN;oG;R$M(Vcm>T^ދr&K9 ʾErdFHY]XN'ܣ ͦN/4+ j: Ct՞9ރ̏T fUut& ;H' ڢtV]ͪYn; |Ѹ5娳˳YgfK:))^&a٧[[T XTJd|]C)OmfQtd4Bhnf]+v YmM?OE@x^:!)Ȥ]+ͮJꞏh@{,2-ุ,[VOaFE*yeF[w,b&L`\%eRW\;U vR]KX.0kĊ?bq~#"`VԯfH՝#piE i˖yh eE30UK7ϚuD[p}*\ÎntgUک{yx9:SI˝: )Cb@khWd)rE QQP"LQ]"M@HBh;6=292Ym5˧jSMtx? qCʩd3EcPeٸfd0P/yvs?S*Ȉ{f{l&{D 2SQ #|m0U˪.W$>;3 > 2 'g5Xr?2&s8'^s6[֥Q23h_Wӧ%6e…w>(ȝ.J tz\Ϊ+<nLan/+ yC]b+~7x®n|^-|6©febv#6:' - ^cOܕK,lg斕9sG߰GYJMY*+vt `nG AVͯK4[ |qZ YPNr sqfVg30ipjZm8iyQxGN@ǃ%ؼ"#*ήl*c3o{S#VV Jڦ;ٷ5[l@p/&E͡-TtuZaPPvVr,<kBzz;3Bڅ,|N6MS^ϷJyTz} }\2 7TR4b+A\6!?U';(q]1Yhfs 1d[hLV欯m+uVË40(0+dNK6.jDPV!*xk㱫ʶh.11]N<[{]ƒ%Lx* [~z|4BP ns5(_G 8UɨECnih+z׽Y8`M?Kȣ͌zd)PVv4Y{_ֶ(jHg1R >gؙ 6ėfdVJ]9Kc=R"n6gp=8!qc) JdC2`= *[|FQ݆mZȏ@M8RͲ&p9npBOё7* )c2 ];ؚl3䨺CSl:iуĺR#M;|W0`p3Z \,\Y]M9nto@l_ BJT4-DX9tƿW ?jrQhgo(Rz\fW8}f7Xj=Bq랜Ѿ\@d:}1mgr:|[ `.}]z#:Us`x'8ֲ?nrge.;5=U?cwQ=΅0ZԮE0^8j0vư3T{ĒBO2ym,_+ZS W<:L#{B8 Cɵ8HZ7`hMxm.(6ah}(T//Hh#WCRD8ϖ2x7`))TenmrM=İm`0٫%K pz.E:n [RKq'g)%vYP ,*EC5VH!9i|7H4=]ݾbV ?g2Tc=!݅m2BQ@ݰpaqq$Yk8a_ype0GCi 7FY 9h׳`zkZ>t+c([ ?q"K7Jji9KbQqvPgapvA`YXa 김ϰjE H!4\/a1#ݔ%-ZƤhJeAli&y}5`MzE'?A@SIqW~hf=]4Ld-SZB?ܚU"v"Q CÆk$1xQǠp|ֆY#hb8/&Eryfc$4&fiq*`ՐГ3لgmqER:3tteUo)0FɂUjQ@ܑHU`U Mԭl)'4?Z,yBo$B_x6+(Ʃ1HMZFGu 7#*"[5[А*ηbϣ _p5 ǹ=ǂ4w΀Vg\E3I̸R2ߝzMXs6k( q~Jۢ|"43@S}o'G#T΅Uw {l2%m-yNc>$o=}f7zPJAФ_Qn󦱑VT3}>]c\?p(ВĤ Y.Tokҝl)Bq4?CZRMД]sQXQťObй8ZEv-BF%X>Szȍ|ZTUUn*wlWn{-[%P+`q7Zo1lrm zzjj&xI]&0i t݌AH̟ *M;8[H 1\"Ս.nƵl,KA.R6#T_k"|e;1;;7T!lݯNnp+qcV.x z~Ymo:hkxIX晤[H#e@B,;T;CM*pΗd_Ա8/=Tq.mw7j#ؿ <_+oWtk*<4^50Zѧ=UD miX=ĤjGw1۴oJ#@7"wͿtޮ_Dl-w8@fqr@9Yff-N3sAJ5$w7 lU>"5Nk/lq D8p5M Scy.'ԓr5S#Dd% KYĉ zsDYyās8w-\Ի1n (vjŅ<46"%_$ղH!ݚ9)g*=.d#:?+RΨj5{{!—\t[#xR9^A{fr>̧f'`J9W|&o{xFz99z}Onb-IĩDkX2!o}ׂUF<!wOf`.wFrhtx֧(= O%$?AWT.Ju*TEsxF5wbZ,[dkl7W{֜-q=X ΌOPn|bH+װ_B[f\2 1RA`N:iYҫb!RZsH^nbcrae|67hYdI9vن3{_YBSZ0nK6ww'm^Ӽ)}ii.BTtͣ$Qv#+F:g`_(gD؛^<m޷o߾D_r9{4ɐ+[˭޲bx~h|o&X=ٵ(.GHH}Z1璙\g$4fu2xh]1,s~ÜdCA)q0F`1\|sc5Nrhyc.kJ`{eAE:h߭3j>-.bݹDU՗/nz3]8hؽR 4yT  S_Flùf gSGV̱~yba6tR wеt^wLYZY|J]6&,(U5>;$$dK'E.vl޹p}v[yL9TBmj}>>˗2A HJЎldas"  ;bjt] l=Itjo>}iKNW1$&T?{Ԛ)K޽h;/Y L VDtQ1Gz5I#;+}Z+M;>{R/ӏRtzoS;;J5<< QR&ҧmU% N,u#*`RĦ ϵwez]ˣT1o'}XFU-K{ B5t},9Gfqȶ~,Rշ;-ٰڻ{Rut؜igO @_oCKns;`,2S+/٧ќt&!#Ȁ15jVyQt>z bƃNH":nLɛZ|Ɗ X'4~Nw7 tPyeDD.;},J8 P63d)GɈ+4.E!Jha ]QK!_7BK8,{gYª E<J1@:n3ώ<:FIq9m9And cV\b{D6M/gjV?멓N7D^;JHy)8\X{WDƊA|Z6-JsuȾf{HSE8GL!s^P_)>M]ʋ1ِ8cZXBMɾ$SШ.Xq}BQYy3u U'=WJ#6]7.ѻŻ4[hnϻ90- Z埳Q;Lt`41 F1KSMJr[aԤ5E8>bRiIT@ZO9=9]Ǖ\_ cj*Risܪ'aDz9җR <[`"w`9 G8 u2?FxC#fu^'+Fc 811@I`m^M.Bm[3ڂĂ\t(eX%J"?_\II$ze ¬On;1!h~䴉jIV~dޑ͹LuԺU" ,ؿ̝xȵĸɦ.44 \$?R!6A %{F>ͪ!㶨H RXzC@+F`t)9,[Yɪ[pɩ .+*g?snJQظwo[\oƃ3q䀘wHq9rRmӭ3Ux,~gyUeƷ߬>Z7$tˁh-t+G?kQrh2Q!f3NxLZEʰP.ŏAr%0=JJao0ᤁrE+`A/U{?Ю1OjFIhcsjЂx 2\d=|v$$T],b\nspY9l (w\7Ni> 6@PPFk&Z30VB:28oK+S cĿWŴ8^HhӐVf&I$\&*RI=\aE*X=e9eQ$~م3 z GDZ[kIH2@FlԯSX0JTS#n7$|QY#liJ@u{r-,Ĺpt_6%)<%7dARPeHR K.bɹE=W3%]_ҼWCԲ9Qs+Hj8 {0H~>4nJ˪}Nح/ۯ"`#9n%_K?r&2؄?Ǒ9ϴԈ1]M,%t9([b& ON #{p"z=Jx83|1ҊO*efw͈#grG9nk8uDv^8KY# O \"4&2ě@̳}}Ӭ`hs^r7d7P-\͌H-yA#!#ZЧєr~-q)i9bKS֠jMF1#LKH3?³:K.0|][NEy6j˜ඖYGPqyOwBg?AÕ41`jgQ q·ƦC 4ְWU UTx_5QLeJ[ϩ973ν| ҉ɿ<;(E±ܰ죢s,D.|ڻiV +?Ȩc~ Xaf}5,(tPyO͛F 7H̻]K}\|VV_nCֈf%0mV)S9O,qr2S19Z[6Po\&FI ^G?;Qf ӅaX+vN&zI'Gvo[n"e Q흤<#lEMb:IwN^"6sD?m9) kHx=\9Mkă܅dF=- EDlUϿE=JL~F@Pq8z rry_&pC`A>ATϔ Qr05q h& U90O9쩦 %Mg,Sg+cږ;?; I-1lpԨK.61o;BX>牜~X%舖.J`w5ԴQ8N(,}Ф^N6~ծ Y=Q&[DT]G=Y^B&i%!yM,u7UI&϶d}&}#^Wc\R{)Nvd7ϱ?1rfj*Tfn׵=5;\hLeš Dᆮ3!{Wxu_`5(+sQqщ_;›5a_%>;Z.&pR;If J, NI/ix X)ǤxZVsxZ= L T`a\]E0.$3}jCY/腝+]˱u'P*uXM:Ѭӻ\hO6Qswūxw5DG Cyϐ 4ɝxnKq}04ĢC(94PRIsVi#-Gb`DBjvD &t6wZWW18|%!cθ'H!o!EjuЕLv,cspm[R)Q66s |kdOSR/R۟O?w?t `հ< yڧ}4F*-"溢;.4N|y Ig$Vhvc/ޒ*_<\%WǦgfc:R1YĩA'VCVƣYKl|':E7$gWITP@TxL;!M*^?s|mEdNF&?ejFq8恓cDCx-O'br$4J_gcˎ ӹzI-ic޵vCj5;3h+s xSggC_t}|>]R<{=jGfgւpܥfSqtY AS[i5VݫnqnE BVs%쀿JFĹVz!2_/+-g9E8j t)c+.I8m'nIvCHQ)B]dGl U A(t2̙]Y-̖$ wrF1`1J◊)Ľl(hfS2`+()y,X+xE@[fqAd~,/ЫFo"0zZ.w$SԼ;C~]bXM,󅆺-G?C[ 7 %OrdOq3s£}zɫ=I"AЦ~,{e)+;*hm%>2e3wxfl4fTF -}k̉ᲲwDOkg%]rRxti9Yz]S9pVmz~-g G˄z)()\oh2fd=C QrFvnXHs~*~!pg $m:MQN"_4HA"<j^rGs{K^~!Xe Օ=R;69H><2,ߟ12}-7S%X'QdFĴC2M!uiGdtȘݪ\bz}H@Qq5}6F:H1VawƓgևb\L%fM$u6&f\#r֘/S:y:=i!rbݐ̗9.Տ4Yre$u \[ *B1Z5̥~)40-:֨}ekdmDz,~͙=h#xpOrX.0~HƦw:<}9*M߻|ÕBo {1 `Titė%+,Ggmz!.$N-M<7RmPM&xƠDZ@ HRiwe@ukdцm"kiV'ӹO2D_kjØ^yt˃D|H#&KIX Z =Jߒ@S5V0k sAO_P,&M qٿKn݈pD&<l`ĵ:жX,Fp6_1 x; ?$54EnE Mpi 9ifjtm9o׋@Bf Cջ\x2-x>ulEc\/5c /:d2w&=roR>Hml=[YHӊ ydhenwe q4Sqd/'ՙW+Q6SD#\i ;<'k"|4 s u~hcRޤ ѠD{jyY/{F,AC ٲ >OMue|J62xX73?0ߠyxʇBNT! S" Ǭ(-VӘ" kK³s$Sm>OS|@9pLdY (h9,} ǵE %T7{vKQ<~DsƼ-D(jk 8P^#3^\z:_4 Ƥz@WJ? i F 0m&mx;`_ԎFV] kP!*qEhD1cizvZi`=&g Jw@ZI̧Mx t%ܠ 7# 6]bToH˕KA^FT=†ǚ|޾1_U,`yiUNuk?{gp }D=z9Kgsg_9'Y:55weAb8#GNꡇٜ0ASC;bSE^vlNE(V7=P;3t' E,On>*2Kc2ts=ԑzlpSdMG]o:CkPɟTPT XL@qT7q).Ud>TxɄkbd;[KXUͬr ^ yoo5f,=Ԭ+sƠˢ,H3zXr˺ыkpiwd)*V  z-$0+u Ce~KZU5la2KpIyI!eJקo2ueXn*ou-k6FYәH%^M!Gte՟W RcV<ś~wn2 6K5|7/ eWQIʀs5qM*1 WM\'h\|#WHdt6&BJ[xUO}ʝw% $fR5u7Nuuʃq-9ૈ{t(Vd[RiI5Aذ'GK! P&8a,u1;T`d鍟ݐ7"_ViyL0>OD@Fdw]f|` Hg9Qe{XB07,J)EleYHpw `5zQu+6Bu:o/Pp/~+KP)xAr9aaeAm5X!V8!‹ Q5Q^5PXdl;:gu(@7od٘Ӥ \zΟ3?,L(as"-TlD%0Bʂ?Ow{SY6* y:IЏ?[N(]G26;"@%I*' m*.s?{Hq2iL ՈKp*O-mTzBX' UuLp̉.@Fl` b3X %]z L\C=5/?~K8Hhb9d}p+s(&1.qmG!w‘0'&J;2-ijk:\h* > n0ڻ+3p "!BU GqP笺 '0re : 0ý{.iնAfRcL^fG6ɝwT[p[30˕+ǓFUCM'__<_`ØL/H@>6r]lavo|Y9L5Z{S51*M甸Y- :?\AEz!GC.v{XE?^ ׎T/1p"0KQ8鵾F{VZ؇ oIJd)55H먗4]7ap6ҿ[C|jLdRѷ/$#q#Ё4wN#)cѝdVCh|-UcI,% ȅpZw?V]?xf*2ki"aRR YG*dHiFa=ҍʨطr,swI:/m{ڢMX飽Eg'~CYp}F `bTS^ӹC0:andEpo+2BPj ; `9FvJkߥr(0Ce1~zԣ[L El\ZOrDph3/чBR6 H KË С0ˏhC`R.uV0jv͹>+=:? $4{pMjT6I8uz(+27{[D!E뤗j8L٘`q˃<:9oq |Px n|ZMd ų_煩AFVcVSzK%`.Qv5<:Y.}-yB/5qnyD)a :/gklu뷮¹Ll.ϪMh X( {}AD<w˾3Q^&>Hf=omoǮO_d˲{BxcSNϡY ݧމKXFISו_Y֎NG"~D 5'+7w"nMr'q'!_ta4cdxh;V8 ̢jo5\I=S!Ih 2lxqLƼdӮXe˽A W<*k:e6525lky y; ȔFƈ% t1qG[[lH8߶ףI4lEhLģ /uVV19̡uN6t&e J~42fU!L'ĒqEqv}7puDJҽ&{{\+T57bCjuY#>нm#π2111F^?hh* [75RS |O_,nMn~Yl$uſ6FFB ?in+f*FJi^1*Ql/  5[I]14wl'n0TtX$څye ۼW00rEh93#T 9ǀR观뢘 5Re8^磻Wr=FMw\"D^r"h5!twP} lOp:^l[E-i:<*ZCWWN:h@h]1?ZjY+z.С+B2SLlefm,nUC߀2)c-]n Bw/ςpϥ:/AsZj_BvGb 5nHj!im~*sŧ[|E'C@7bT3doԌ˦ܴ[8q h&DN9+Bhh$q}o BPeq>2oJ]m+7,[ح9׼ WՒ6b#j(E^ouS鶇-CXO(@x*֐E[37kzB`SCv=rx,࠽c%%2 lU1z$P-rͽLnwAep@xVz *DYHۚDKByzzk }%' GrM&rrroW +! l 7g˹UJa>2_]Qfo^ Z.Ag16OG dx oXGQ?X}oME#BUk*c'OisK)׌&Ʀ2fɸm&ޏ 򭉽Ud/3vV:UE a0{WZp}Q總bS@lIhepKicGUnqkkrL?AL< q;->8F0t[)%XG_gi;\S/MM 43>/n'ߜ@}>L~fi9č'I= v<ů+ Nor湔O6>W(L2SZq͜Sv S"Y9A0%If&>H>5 %db@GO^ xSt)睈WF͑1>Opvarc*g޽F6J9qo'kA2+~7~W˕y盅dgi>@)aϵnB 9k2QY| Q` ^u'֥kNNu;"6n9|*>sg{ kd]i Ù @ ?"F{=i8{T҇$\9zntAf/p5 g[9 N&<ylWdyO=+8`VI/ w]IvAkDt"7I2T@j"艭WMKj,Ly6!͒/WMbA%;fFDxtDoOtH] L4q6pVIf&oa-߶{buOcaUk#5>jwgo=WMV )/ũ>}єR47׆G,rWzrk!"7]Pm,Mlҝ џD؍,B(*yd~F+}cDD{zTIQP*rzc蒚K$,#sc1bpi5Er\ >\YּZI 8R7#"@0&"35+$A-RQ* 7|=m;8<>V Ƣ"@:d.ρj% p 6%rEf)뱑lXeA<<_#|p?56"$k#yDշ1n{1 8p6][N@Hl[Jv;JaE7^BSBk zvu:Y'E W _ѫ ۘ'm9#=(! I$%m+Yʒ""j]9vGERɕB _všFsps 5HS_b.m/ .}y aLҕA.Id%lO/%Usx*5%Tm*Qg#rfw7-Pj@.ZH'5G7^2RӺ"bN!PQ/f\h._FO.:EȘ^% ӟL76-_p &_QnWGd\ -_(["ҙ?~*G'V;}AG" :ƙ2qxSt#wb Kb~59M!ۂȉ[e…2OͲ9B ճ;|W[U0# ΧVg:JnF,uq_o^ _T. v\<|{mHkc/B:2 坽5@H~ofAjohuV዆f^wʚ90`ԡdD泗RT U3zF'Id$l4zG ˔>3e06yJ![fvq4P #\\2Hc $) /mUI2} O}Tgu"]c5#Vi!  Aob 5ok+(.Ċr n ռ=5V9u {E JC/e !o.KQqm4{(K?]☥uEFPPZ2\0;But@fԮfbf'Xzn<+wC5^:N=ĕno #tG 9; k1(yUFVm6A<`͜([shѳFk=L\߀^x?GCv'_x0X:~lU%Eotz:Mv1)IQpv3.]l2! "T߶{Xk^#1ݏ(dԅ]6 1'%2>⨤ڃh`?UE> V[WfQ IaN<6=7c v_]FkiGw` xe]2{`EVd5YFTb^݌ \$+ǥC.׍[w*HB%ɠ_: `g"єڶI?t4S_ɰ=)29_+'4%do`>za0^ vLd9* QU;H^Z Na*&Q5*@Kbc9{mV-6=> Ng6ϖFZG6&9[|Wfsj/"]bP݋#(t*bB?nO{޴rxZMq] V!TrXb&-P.嫕#ie1=Rr/[;,,܇mi1݀Q$(P$IZ#fR=;gÅ;S)1%y;O{Oi\a1 XJRzbJ:HaM]b8#F%P Hƛ$,OU"4B1g G&%\xtӫz: =|)#31Ya7?﹬5B,! BtZFx.hud\#bgN`k\h T[Ս[nٳ7߹.]aAZ'kNt "זB_o[B-*5GMM.k{EF1|9iW{ԧW(EW74njUdhץ<2!]:Q[W+tIZUu'UUVe>TDA#/!ۻq!zEN?h8"uʷp֊.CY Ⱦ o͍noTsc '\j@6lS>&<ᛛaص(gKygxli^qI&O5T$ʬattꏢ5$z;?ndASiKǑUF"Tp{c%=({S.]gMMd'ʥ=*e.he=P1"LW H )4!3s4d&HK޽J/@$}N]~-IQ=1q$cxFdf !FO|P:kR}3.VvE/O)3Z6>@ 8C| cj.*6X{sJC k S3L˵ ^;N4HUv ++dߗNMyf|>rev2tBѶfTrhƒΧEN~._8o_lތ嵘)AOX )O E*es<)'k<[.To= CpkGc^fJpp|7YI~K燂5~*DL4NƘrUuaHY |Rw9 NȡdS(%/b^T<@_O[i&N̬hr{i](U[DBHQ*l\O&{v궗 xJıChATfƒ~)1fSݢ/eC39xvyWa,ȕS<.SsxR[D,drW|hbVh ~8\0KXwjRuءQCR~X|FrgfhxpLA_GPͣ9OW৳m-/EKmF!]%+n;/|$Trm: CVK2x赞dHI-(M^ˤvjT磆Ӂ5ʨAҞu9a{O3}M$)&AyqjȽ;G̯}/Ns1̳!cQRNgif8iS}2).LjhQB|aLYrTS6"卭 µ\r$z:.DbPd578D|0n y _H:5f8hL <6LP̈́ԏNlᨑ(yKFQcxTQ'=jE7>{~n ]I{/4G)Zwh)"{FdIUoxk5-$i\RܲXwfk uؤ/s0YzJ]Src>|'=!Զcnkd'eޅ$^yrO+Uk(zg8lZ;A3Vĥ iϤm*Vv珌0S\ٖED7Ȣr7}bhڅ$Yo>^/m؟,ۉVnpSmp-*\Y$!-Kn[b5PZ­Ҥd*ӱW/ЎZ,*>55y{L3j?HmamZѡiԋ뭾4huwY0~[O;{IY;7%8i׫m},Lv8X+xzE4i˃ܻ4;jlyBdiiqvz$ңgVTFށN2#H\Cfob:G#]ɹw];ܜG}H:'sBN)quvf2Ewl/yJ"S'aT_PTA)M2F9SXWqcfAKƈnP .s/%&{&{ ңN|r/)C ' 2\anpʏU'ZԽk8L#{ R p" n|yXudF7"8wgG̕^|_F_/uD3..2s~E.*MYXԗ35MgΝ`]CY"R"Nk1k.W}ž xIHQ^ NyExYcgVīVʨ!Oׇr󡾇`CzS<_OőkP.NRKAK)TNm/k`fHǦ98^8 SC'psO*8xN>E3 [9ÝqZKQz+}B' z-),6\J}`^Lr+#fq[V&.t%[%j_%(1n!abgM+2Bi:<+ /uRl З$H%M~V6ӼLMPwB;P.ldz21euAۉ^ACntaQqk_B<ll`!l%BnnDxGLSG3;8 W[8 znzxDh&;[ڦ±#'/bkmj.c &k8ZDzMqХYY,*Vh~sK]RXƟ[؉*EqPuH/p$gHR~'K!n(&ofQiс#8~nUVMβ|Jڬ>,vpJ<zl=m ڎf-ەSf|S)x5*6)Ƹ޳sĶK/XQ'{偙dЖa$fBV䑷-b~ؖ ͎A7S:5ᒑo8Ρ-+wk P5K F?Ӏ&F9_c<ūY0RL~1b)Q*p0pi. r(G:Ȟ}zǴIL3F}}1Jׂkq*B]f6WSXWNnmϣ #o<ö=<1d/oO~_9k˲vWk )6gS3UK?ƛz&`;wVM#wkһʞej㑿Zx6M(\9%,g9K;UșB`qkQkգeXvfx*OZq@2}n#b6Y˪4^b11ŨY7OYm9ڑ(ݫ>￞{!߰*4 N5wS1cEz]!9ZgO0u]f""fZ0bu>U}KsHʎbޑ$EaN鮟Wߧ)D㪬YXx-"a`h od 6Wg3! Ц(sNeGêj>>tU%-){cT%h2?„:X0JCt{at=骏k~~*Oe}p8 k3*U]$+H-Et S |sSVIn 5YwCAb%U.(nyKdJX*3bĸߤw5o$XVkca#t ''xxGgUB-G6eE7`X.@q<Ҽ~ZRRmy,&KbbefVjŒ'Ҥ(\F1|SqhTΤ!vHq#wb@Y./"j*m,[׼4ɩ/Z\$RŁ#{dLIjPس#Zh(<(^'\\CCbpltFB԰nܿ#,q`y?Fe5 㪔è^$B,7`ZaX8Xu]-H #i8җD:ww2Bϋ(:$A,R ű ^tڒseevcIcWs2:l>T,Bζ51}D bDvȄleMy>&O*ʔj% T0\!J4i4 : 2ĒIS𳛂qX Ӊ? חݘ XtH Rz]Dr'%+.3kt=+%[B@%.ۊZpuro{+6hebxrIU0\aW6{t^hו֣r \%x)˪!>M9_w&RW5#5m0xjVvSt*㨵pc鐑S-c!.%NpIP"4O6ĂUS7g}vJt8!=/(5 ڤg: y4ͦoWRMY dbk9}6A){n*TUMa@SnRH4'w&LZRД^21I\6 xr҈v`'"dLFs՞|,XpHȿRi}@ :RNHwڋiJWuڍ c -w&㲩)@/iP|Uj́0-}i_Ag L]ok cM7\;\sJ 7;G\_he3GO٦;9ؘ0jxDZc184 @ "g,#lSf=$0GEm ffߛޝ7Gs+5Y w8;3F@QСjz1\գ>'ќbR]6fࠐ`^lʪ( ]FۍF~kh;঩Q3 Gql%{/tC".谮(Gc5-~ Hd.fuj"_^/N.ᒺ(ښ'/mG;lW8 1VHXd#x/f"<6LU(`24$8|g3>l|E \9d(񎜟Ԯ{WA? tINߧOȶ WԌIr:C̵kixrHմXx^OXa}0"&r.L5C0~9fHpH?St8ly9\Jh뀸CI^sX22'hBz+lj*swQ'}`#IjH'k6.S1 ]̭t.AlDbpNɔNŽnL4(t' n0RCN˛c&0Y(puΉ( n4|/ T)&`7 v5 yYL;פXمdD8&5Q!fWPw4r]&sMɽ8-Yv9u&…t|)Cy2iIy Xj52%tڍtp:M4խ.$sЅnv;1JV̺ e lŪIitM"郬d>a$OFڠH׹b7ŚEDB2ҝ0FOa\ 2>QAJ;8xPґY)=By.yF?xۓd2v:)B͹fd"cv6s3NoS[b' N~w~Eܞ67>F ٧LIs\31 F#)CK/RQY`.n_gd;pn nN܎3^ZqYf.D^O%ވZ&9nlQhrЙy4#EROJ Ϣ?ژXcek<5$(F[ rYUZ ~D<{Vp1 *O W7?F ~ TR]T)' Qie wRiZǴJM[g9mn8.!kVι} F&x V܃:y*Nةzdض 0chiP)PcSU IM-ɠ߷N3,, ڑE4y`-5;x-}=F2=5԰KѪ`sVz_{1a0@iͪ娇W3,^GG4Lhe?IoƇqsZiDZ6((8R_ni^hS"7J{ЭdY7I![v *:H\iz-y "}ǒ'jnU̯Tڂ蒗@XyZCƑB6pߎ]>ؠUC*`uɣNk8ܷ Z&fqsꫩy|Y2t/acK._^-?0 X%+FG_p`WE?;zn"D·~ dUZQmb,Ay쪴aL'ag `'Z8 9 \Dvk26E籠XZv촴E%אbCL 3an~dؔӱN_[ܲj?hÁr(ahsӿ+1˷S,~.'Jk4yݤ7][‚{x^K}ҹ e3|7m@ \/$(j,"2fvmhn͟{k" L~>R> ta$GVS`Bn'`0G_ endstream endobj 38 0 obj 110085 endobj 39 0 obj <> endobj 40 0 obj <> stream x]n8ཟBvQXO HYi@#WGt>R4uwϷ?oytnW/^}cZNy:Շo|v/yUjNi%]O| _sՖ㆔_cs^mzWmasM]ǧôڶcsS1疹EYY٘ w#rbNsmܳGn@?@?@?@?~_~_~_~_~_~_~_~_W~_W~_W~_W~_W~_W~_W~_W~_ᷚs~7~7~7~R~7~7~7~9w~w~w~w~w~w~w~tF8#Hg3ٶ l+ڲr Y,h6;сDt8. Pi|Fv +KdDTguNm-^F ̸>-AāNą,ua`ʼnALt&8eM<#art˄F{ǁN tޮLvqpvvΙK2=n=azf1OOg$@;<) bwW<}ynS~y.XG) 3,ud@ژ4͛rPvc1Kzp endstream endobj 41 0 obj <> endobj 42 0 obj << /F1 26 0 R /F2 36 0 R /F3 31 0 R /F4 41 0 R /F5 21 0 R >> endobj 43 0 obj <> endobj 1 0 obj <>/Contents 2 0 R>> endobj 4 0 obj <>/Contents 5 0 R>> endobj 7 0 obj <>/Contents 8 0 R>> endobj 10 0 obj <>/Contents 11 0 R>> endobj 13 0 obj <>/Contents 14 0 R>> endobj 44 0 obj <> endobj 45 0 obj < /Dest[1 0 R/XYZ 56.7 773.3 0]/Parent 44 0 R>> endobj 46 0 obj < /Dest[1 0 R/XYZ 56.7 574.6 0]/Parent 45 0 R/Next 58 0 R>> endobj 47 0 obj < /Dest[1 0 R/XYZ 56.7 439.8 0]/Parent 46 0 R/Next 50 0 R>> endobj 48 0 obj < /Dest[4 0 R/XYZ 56.7 738.4 0]/Parent 47 0 R/Next 49 0 R>> endobj 49 0 obj < /Dest[4 0 R/XYZ 56.7 523.4 0]/Parent 47 0 R/Prev 48 0 R>> endobj 50 0 obj < /Dest[4 0 R/XYZ 56.7 329.9 0]/Parent 46 0 R/Prev 47 0 R>> endobj 51 0 obj < /Dest[4 0 R/XYZ 56.7 273.5 0]/Parent 50 0 R/Next 52 0 R>> endobj 52 0 obj < /Dest[4 0 R/XYZ 56.7 123.5 0]/Parent 50 0 R/Prev 51 0 R/Next 53 0 R>> endobj 53 0 obj < /Dest[7 0 R/XYZ 56.7 785.3 0]/Parent 50 0 R/Prev 52 0 R/Next 54 0 R>> endobj 54 0 obj < /Dest[7 0 R/XYZ 56.7 731.5 0]/Parent 50 0 R/Prev 53 0 R/Next 55 0 R>> endobj 55 0 obj < /Dest[7 0 R/XYZ 56.7 677.7 0]/Parent 50 0 R/Prev 54 0 R/Next 56 0 R>> endobj 56 0 obj < /Dest[7 0 R/XYZ 56.7 589 0]/Parent 50 0 R/Prev 55 0 R/Next 57 0 R>> endobj 57 0 obj < /Dest[7 0 R/XYZ 56.7 500.3 0]/Parent 50 0 R/Prev 56 0 R>> endobj 58 0 obj < /Dest[7 0 R/XYZ 56.7 246.7 0]/Parent 45 0 R/Prev 46 0 R>> endobj 59 0 obj < /Dest[7 0 R/XYZ 56.7 161.2 0]/Parent 58 0 R/Next 62 0 R>> endobj 60 0 obj < /Dest[7 0 R/XYZ 56.7 125.3 0]/Parent 59 0 R/Next 61 0 R>> endobj 61 0 obj < /Dest[10 0 R/XYZ 56.7 574.8 0]/Parent 59 0 R/Prev 60 0 R>> endobj 62 0 obj < /Dest[10 0 R/XYZ 56.7 258.7 0]/Parent 58 0 R/Prev 59 0 R>> endobj 16 0 obj <> endobj 63 0 obj <> endobj 64 0 obj < /Producer /CreationDate(D:20071121223502+01'00')>> endobj xref 0 65 0000000000 65535 f 0000398274 00000 n 0000000019 00000 n 0000005274 00000 n 0000398418 00000 n 0000005295 00000 n 0000008924 00000 n 0000398562 00000 n 0000008945 00000 n 0000012824 00000 n 0000398706 00000 n 0000012845 00000 n 0000016890 00000 n 0000398852 00000 n 0000016912 00000 n 0000017489 00000 n 0000402326 00000 n 0000017510 00000 n 0000018171 00000 n 0000018192 00000 n 0000018383 00000 n 0000018675 00000 n 0000018836 00000 n 0000091906 00000 n 0000091929 00000 n 0000092117 00000 n 0000093062 00000 n 0000094026 00000 n 0000168361 00000 n 0000168384 00000 n 0000168579 00000 n 0000169524 00000 n 0000170492 00000 n 0000283690 00000 n 0000283714 00000 n 0000283905 00000 n 0000284850 00000 n 0000285815 00000 n 0000396013 00000 n 0000396037 00000 n 0000396228 00000 n 0000397173 00000 n 0000398142 00000 n 0000398220 00000 n 0000398998 00000 n 0000399054 00000 n 0000399402 00000 n 0000399566 00000 n 0000399738 00000 n 0000399908 00000 n 0000400086 00000 n 0000400274 00000 n 0000400404 00000 n 0000400598 00000 n 0000400788 00000 n 0000400982 00000 n 0000401152 00000 n 0000401320 00000 n 0000401518 00000 n 0000401702 00000 n 0000401866 00000 n 0000402044 00000 n 0000402211 00000 n 0000402452 00000 n 0000402518 00000 n trailer < <688B732FB3220685B9413720A9630D31> ] >> startxref 402705 %%EOF speedcrunch-0.10.1/doc/speedcrunch.docbook0000644000175000001440000003346511015364561017705 0ustar helderusers ]> The SpeedCrunch Handbook Ariya Hidayat JonathanJesse WolfLammen 2007 Ariya Hidayat &FDLNotice; 2007-04-30 0.9 SpeedCrunch is a multiplatform desktop calculator for power users SpeedCrunch calculator Introduction This document describes SpeedCrunch version 0.10, a multiplatform desktop calculator for power users. Have fun with SpeedCrunch! Installation Installation for &Microsoft; &Windows; To install &app; on &Microsoft; &Windows;, download the installer from the Speedcrunch website. Once the installer is downloaded, launch the application to install &app;. By default &app; is found in the Start Menu, under All Programs, Speedcrunch and is stored in C:\Program Files\Speedcrunch. Installation for &Mac; OS X To install &app; on &Mac; OS X (10.3 (Panther), 10.4 (Tiger), and 10.5 (Leopard)), download the installer from the Speedcrunch Website. Once the file is downloaded, click on the binary file, and then follow the step-by-step instructions. Installation for &Linux; To install &app; on &Linux; please follow the directions specific to the distribution you use. If your distribution is not listed, then either find the appliacation in the package manager which your distribution uses or use the instructions to compile your own version. Installation for OpenSUSE Installation for &kubuntu; SpeedCrunch is part of default &kubuntu; installation since &kubuntu; 5.10. It is located in the K Menu, Utilities, Calculator (SpeedCrunch). If it is not available yet, SpeedCrunch can be installed using the following terminal command: apt-get install speedcrunch Installation for &ubuntu; Speedcrunch is installed by default as a part of &kubuntu;, however in &ubuntu;, it is as simple as sudo apt-get install speedcrunch. apt-get install speedcrunch Installation for Fedora Core Speedcrunch is part of Fedora Extras and is provided by the package speedcrunch. This package can be installed either with the graphical software management program Pirut, or with the terminal command: yum install speedcrunch To update SpeedCrunch to the latest version, use the terminal command: yum update speedcrunch Installation for Debian Installation on Debian is as simple as: apt-get install speedcrunch Compilation from source code To compile SpeedCrunch from source code, the following tools are required: CMake version 2.4 or newer Trolltech's &Qt; library version 4.2 or newer C++ compiler It is necessary to create a build folder which specifies the target location for the buid process. In this build folder, CMake should be invoked. The input for CMake will be the src folder in the source tree. The exact steps to do all these will depend on the operating system. As an example, to compile and build SpeedCrunch on &Linux; using GCC, use the following commands: tar zxvf speedcrunch-0.9.tar.gz cd speedcrunch-0.9 mkdir build cd build cmake ../src make Getting Started Algebraic Notation Using Functions Here is an alphabetical listing of functions abs (x) Returns |x|, turning negative numbers into positive ones, and leaving positive ones unchanged. acos (x) Returns the arc cos (x), the inverse function to cos y The return value is dependent on the degree setting; if “degrees” is enabled, the return value is from the range 0 <= result <= 180, else from 0 <= result <= π. and (x1; x2; ...) Performs a bitwise logical AND on the submitted parameter(s) (one or more). All parameters have to be integers from the range -2255 to +2256 – 1 (signed or unsigned 256 bit integers). The result is from -2255 to +2255 – 1 (signed integer). Note that and(x) is not the identity, because the unsigned +2255 is mapped to the signed -2255, for example. An error is returned, if the parameters are not from the valid range. arcosh (x) Computes the area hyperbolic cosine of x, the inverse fuction to cosh y. arcosh (X) is the positive solution to cosh(y)=x. Except for 1, there exists a second solution to this equation: -arcosh (X). The parameter x has to be >=1. arsinh(x) Computes the area hyperbolic sine of x, the inverse function to sinh y. arsinh (x) is the only solution to sinh(y)=x. artanh (x) Computes the area hyperbolic tangens of x, the inverse function to tanh y. artanh (x) is the only solution to tanh (y) = x. The parameter x has to fulfil -1 < x < 1. asin (x) Returns the arc sin (x). The inverse function to sin. The return value is dependent on the degree setting; if "degrees" is enaled, the return value is from the range -90 <= result <= 90, else from -pie/2 <= result <= pie2. atan (x) Returns the arc tan (x), the inverse function to tan y. The return value is dependent on the degree setting; if "degrees" is enaled, the return value is from the range -90 < result < 90, else from -pie/2 < result < pie/2. The arc tan(x) is the principal solution to the equation tan (y) = x. Other solutions are (radians): arc tran (x) + n*pie for all integers n; or (degrees): arc tan (x) + n*180 for all integers n. average (x1; x2; ...) Computes the average, or mean value of the sumitted parameter(s) (one or more). bin (n) Displays n in inary format, without gloally changing the output format. A fractional part of n is cut off efore conversion, and the remaining integral part has to e from the rang -2 power of 2555 to +2 power of 256 -1. binomcdf (max; trails;p) Trials is a non-negative integer, max a positive integer, and 0 <=p <= 1. This fnction determines the proability, that in a series of 'trials' independent probabilistic tests, each resulting in an event with probaility p, at most 'max' events occur. binommean (trials; p) Trials is a non-negative integer, 0 <= p <= 1. If you have 'trials' independent tests each of them resulting in a given event with a probability p, this number tells you how many events you will have on average. binompmf (hits; trials; p) Trials is a non-negative integer, max a positive integer, and 0 <= p <= 1. This function determines the probability, that in a series of 'trials' independent probabilistic tests, each resulting in an event with probability p, exactly 'hits' events occur. binomvar (trials; p) Trials is a non-negative integer, 0 <= p <= 1. The variance of the binominal distribution function, based on 'trials' independent tests, each resulting in an event with probability p. In other words, it tells how 'good' the results of binommean is. cbrt(x) Computes the third (cubic) root x. This function operates on negative numbers as well. The inverse function of y power of 3. ceil (x) Finds the smalles integer greater then or equal to x, the ceiling of x. cos (x) Evaluates the cosine of x. The result is depndent on the degree setting. If "degrees" is active, the paramter x is assumed to be an arc from a 360 degree circle, otherwise a full circle is represented by 2*pie. The inverse function is acos(y). Although the cosine is mathematically defined for all x, for x beyond approximately 1e7, the periodicity of the cosine is not recognized any more, so &app; issues an error then. cosh (x) Finds the hyperbolic cosine of x. This function overflows for |x| > 1236190959.52. The inverse function is arcosh. cot (x) Evaluates the cotangent of x. The result is dependent on the degree setting. If "degrees" is active, the parameter x is assumed to be an arc from a 360 degree circle, otherwise a full circle is repsented by 2*pie. Although the cotangent is mathematically defined for all x, for x beyond approximately 1e77, the periodicity of the cotangent is not recognized any more so &app; issues an error. csc (x) Evaulates the cosecant of x. The result is dependent on the degree setting. If "degrees" is active, the paramter x is assumed to be an arc from a 360 degree circle, otherwise a full circle is represented by 2*pie. Although the cosecant is mathematically defined for all x, for x beyond approximately 1e77, the periodicity of the cosecant is not reconginized any more, so &app; issues an error. dec (x) Displays x in decimal format, without globally changing the output format. This function is useful when you changed the output format to a binary format. degrees (x) Converts an angle measured in radian to degrees. This function is especially useful, if you want to override the current angle mode for just one expression. erf (x) Determines the normalized error function of x, the cumulatvie distribution function to the normal distribution (bell cure, Gaussian distribution). erfc (x) Determines the normalized complementary error function of x, related to the cumulative probability function of the normal distribution (bell curve, Gaussian distribution). Erfx(x) + erf(x) is always 1. exp (x) Evalutes the natural exponential function to the base e == 2.7182 floor (x) Finds the greatest integer less or equal to x, the floor of x. frac (x) Cuts off the integral part of a real number gamma (x) gcd (n1; n2;..) Returns the greatest common divisor of the integers n1, n2 ... (2 or more). You can use this function to reduce a rational number. If a rational number is given as p/ q, its reduced form is (p /gcd(p;q))/(q/gcd(p;q)). Related to the gcd function is the lcm function (least common multplier). You can find the lcm by: lcm(n1;n2;...; nk) = n1*n2*..*nk/(gcd(n1;n2;..;nk)^(k01)). geomean (x1;x2;..) Finds the geometric mean of the positive numbers x1, x2... (one or more parameters). Non-positive parameters are not allowed. hex (n) Questions and Answers What is ans? Ans is a special variable which holds the last calculation result. Credits and License Program Copyright © 2004-2007 Ariya Hidayat Program Copyright © 2005-2006 Johan Thelin Program Copyright © 2007 Helder Correia Program Copyright © 2007 Wolf Lammen Documentation Copyright © 2007 Ariya Hidayat. &underFDL; &underGPL; speedcrunch-0.10.1/doc/speedcrunch-manual.pdf0000644000175000001440000224466311015364561020317 0ustar helderusers%PDF-1.4 %äüöß 2 0 obj <> stream x\ɎWـ[̝UEele[,$5 4d23/r嶼[»޼o_qnm?~׷[ =ܾ|a77_y1?ݾ,Ǵ+^^X ^<=š^yB/y .ضMԗ}iM܃ NkK¶~K Em{ѝwGǽGs<[SA'_~ڂ ` fleK[]ffPi6 3~:t{wA98w)kG.κ% Ⱑ! x߰yG?DC5S3 I!zgAC#IfllYnq8,Z[1!,}'ѩ7,_=,f}5ynvdevO.Vzx\GU ߌoVH!:2]RM\I/EpA @̤"[l6IFiQ$-"^%FGFN1N"xRPoS@@T zL]H$r&ʫ8xW' f`QR$au΋́EjeCkzؘW~H0GsoziwDKi&nt&&$U~I*^yh{I ś*7/gCET-盃W^WXK+k4+ pTfRq&-|6~j3KvY\΀'PSǚ@h0v# }}n{fR F|#q*X=Du` ֮4?*ؗ̆])|\67pjP%&HQ԰Gy Xq!ktB,gh]Xb)۞| K/#KG2ķbky+{@O:ʔ3)V?I"p16d+?2W\F ʸȄ(;.fn#"7a7OKn'xeir1ȵ, h˙2W=UJܪx Cy*dV:,#NP> X̑V z0Sso bEUMե~Q`1x(?Dɏ"ԈYE(d{`dBte*SJMԬ:tD3;+/AyȝU{ 5|SX,D0r:10I ^a!aikȨ_ɕt~+L1' (C@B#!V(QGxʂdC}Wya/^;$aICFiũ * wzT|!dZIisen"Q!u'籽~c#ڀXb"tC3)E `+qDS*ԺEMAFojfQ,l#gmƱyقjj5O:Z3i肧 `AU,yf1Ȕ MbGF4B:¶Gt{w# CEY<:c3CߐdAT<EMgʍ.B5 4xj*Q KKldsCr{>g(aȃB6y=xi(ŕ)шA rVHɥqX4:# yY%ɇ 0, 4PQ%٬ @_ 1XXά8@w^1OxLu+]?}L^' fd5{͊NXly; @冈FGi^:ݐE8ّ66| )Ҫ(RoY:#ϻ1.nTkNf f |T:r2C*=lɧU%Q}]5^\;ꅅv5@!9jXz]:Muo ր<1^{N:XQ12tϋdQ-5hfn8|(b uFwKI)Π])S 6 M L5T6eP) $rΛST3=sZ}pTN>[ }CdzMYe#+2l?hJNS^ M_Ê' l^~%H%Р948TA p Y REBQ;,񍍭[I;VDl2Q FUֱd AFϠu-dsB&EJ:F6faum9ȑ+e,We7][縄\^>p2e5O|-bӟ.˓ntB* $R# 2si%VSK0:֖xg&' T^uWIW3 YIQц}5 d&}k$d+4I?ðj,s$.̻Fd#˪Gnqv+{9>xCN;'s{O:` e*гKg)Q*0lNNɽ0G|fO,pb+E%g3,ypƱD;0trYV)m&Rе:q`T}! d \FP>NEV=I5]Vmmj 7ci ZA^_q b `b%XB gНV^hKM4Qr=Ýn^Bj@NZ#Lི*[ 6n}X;']y-aaWaתN~ fP!t,# V=WфcbJ_GRh~xcѕh"_&0c u?Q4=jFi#? I1KIQMNRv w1jL_v́(φFk@;˕w-au)3 D_uSzeY Rv<927F 8Ħ9L7U~^ΰk6a@OfZ.ו|QJs *GBE*'z=9#l5s:grR}8J7@KK)j6[kmX~3 =|m7xIW@os$>ɊW᠐V@XrȁXu§%C~: %hΓ_Xh"YkYeHjyė7yyX tPa&pP vG)rf,_9(:W* #Z!<0)WMQѰ|􆎡Щ އ%O!3 fb >"ui ucاqOfKDMFbXsU,|l 7%9[ûpb Ĥl~W[bxdC,^>a7_F'4~+0/2:K;%6O ЦrR> stream x\Ɋ$WYT+@~@ \͖0sn00={Dm~elWs 9\e/?]+総o!^KJ.i/^>q-dc_.fRfO]|Ge>\ p0b۸ݮ渵2̎UL!b&oO[6iamf6!'py<i_nu\ir_[Ix̌ 6>MV4vbz\u<>:Jω˒&ދWGO;̎4j %>4o ƕs#Hi`VkVtkUmR~{1vX*%˳Ofc"*`\e\-#>IeK[] 1oi mkÎ^ܠX707e?cJI6,* 5e2THj'-(,bQe0_J!( .rVUekjmlyQ|wx5N# ` x쑒ڏ?6֯o};qȹ1h<"i8 E5CQ `΃<єoe;Ԃ5}טqlVnc+._&B|mhް=!l6*ojl~L3Wm[Œb.]U̩poe[F- ܁Cy[a<:µ,3CP(KL5Ю1ZuU& ;Kx(8ːL2E"*jb$Sr\iMKmv!L50&(f$F.,Xj0u.= G1.]*GS=GXsX IYgp%%+7Q{7֢(}ǨE)XÔp>g+Ȫ+?({g*%̺ FMڐS&q=şаk42T]!6Q`?9zͦ؃{Ӂ«3 uCt,hV<lLFzYyޅ/W l!ǜތswTYJ6]b-s?~í67+XJ&20xfحc(s+o}1Ιu%$t{5N3 3*fLI1:AN5/4Fxt'{:T"G%@8, 4.yjxɗM[/ a"Z&Ʋ+Nu <t,{o2i3h8 c(?B ig %6w p.1o8'nB.(>8Tk% 8㲲&MwZ(X*=YD%&lwq뜴/e1퉺\W^PIԨ 1F C7oPMJKK* t)!]Z&C22щ3?H[ުP„:”~X/NvwL12oMJTSoh| }P%_>nA=h~&QEuC 2g_wx=D^)8s7ʇ&r%nmǝ Lg957w@vh b9a8?{ !A&p0e"5_d`M9]h@(20vAx f1>w@!O+X[{H$>Yj@ՊtI51Id왼<޴XT< ϰ{w4,slO՛Kg>J AUtZf`FG= ڥ[Gbyx oV)dt2җm*flA-[9(j3O@٤3W-S#gB\dM1RYKNl hƅg\b~]S^M[їZ@shJYGnԔvnni|@ !D9( ccA5ɜȦT\O"xHx>49=$lO?^OͭcƃxڏjZ N52(PB9)v>eb*;&hlB]kvS _&r[y" TUyAW -U.=w+.~fY@BAM̵E's{˺zXolLKwC\;9 msQs‡u|h4 o8f15qL일MV 0C©jN)Zhz*EiŒ*@з-=X0=+_Mfu,&oVgYO nXls9JG7*k-sⓑFiVG?fB)!LaUfd!-ox'T ~]o5W76CxU#gm QnGOϑִ!Ҫ NcTbr4s3]?֍Ziק 7^ef)wl_/ ydY>^;y͏V]i)CSe̻ 57U,@OJhMWjTU݇֟ªt)}ѥERV&Fi}}(,Bњ1n0_Ke endstream endobj 6 0 obj 3588 endobj 8 0 obj <> stream x\Ɏ+C;'V->\KFhIU1X_vݶan!w۽ȷznV~~?R/?͔7-۟n?_Sm{jbY?M6l/KG1hMU;.\^c/ll|'эլ6i;6f `ŝ~H|]*:xʫb(/+,'61N7<^%C>XpTWvnb_ ~1a( ٞ>|Uq18ⱣwGq;1, fb0e1Ȭ#a4bm+kQ{){pwAj8Ar0}'XcNgAðI}̐ +-Vr\M?%7M8D.?32c%7 D0xWU"wVx3x=xǡмW_sFɸqͨ˹4j[ݖ6хT7VNFu>:"aMK7`QK̉k9N,VUGmjGP~-d 1Fl yj,)yM#Md NGҩ:݇D-x\?]{:3\cxs\Y^!yױKyh de4`Wify_?M ! !#&:\1jdn!̀Q Q*A'7Cbuڐ[Fj"Q5jb`y,4'݇'l聾,bK!lV"]V별%b !5kh;0ؽav}RSqܜ>I3zna UEC:aHUW t3<:ƴ^] q9Fc;* _b%޲t6OHӪh+_YEt$Ư\Pd_aB,ɖ!I5f ,yZ*yռ@DS͚M4ࣙE*t+y۴&km'܄OFtGɐ ((GV1L!aBn8jf,ҞS>DPʅ2pAy:C^ջ~9`-tj@^ 2pb~Qaɰgc+K I]k^ot_OAN= \ˀ>?2/u{~."CT1zS8TuB,f,Sc^nI89:6qGc[ZB>Jwg`}5$\SëQGJ= NdUER|1t;od'`j(֙wrqC5zFҫȕs{E._lϺ^7l|!TpǢSGuKpp wF$74 dgv!Zt2dtLI/j8POT-D'R„#lnp`fW9nuBN *wfӎ شΤ<081tמսÚ]C#8ɰu#]2D5IAû(o1҈>3<)7IU47Y An0ԳC3!ϓٓOwyߪ 6rtu NEZWWJ >}ג4,=j-9dOƍiYyQLpYZN)1T;'QrWS嗘QzBRTf| S%Ǘ_*7L;)hN ZS+#۳a'4E.'(]4k(Fا) (x$05 ٟRh4QP'2=(K`5V\1$;V|:;ҕ:Y{KZ凤AK,nĚ/G֣3[07$v\PQI&>EǛ$VJ.bc5_ACe?42X-kj[-OKWD <] Q|v',jJ>ڼ$=vKrRE)gw:c 5MֳM|ø=)TQb7yo%#"Q|Tty Ps\X11?ʼnz@7gQ`Ru3]oՙu\۾rNbpfm} F૪rK*{69}> stream x\˪߯ NM`7tȠ!=GzH%>CAh޶,cUժnv>EanUn[|_n~7}M~I a/|z]ʅww5ppGK6t),]T:N鸛E66y5IW.v! xpvvCS ;՛WA{$7Rx?h_xJ_eAyzZ-vzPMLm֊ >6!*X@)c A`3^81-{V/f,t:٠B[V8I^MݦM8wҶZ:N YSrx2 SV5#2y9Fbw2g{,mJd\ൎY wGak'E=^0Å3Ř]83B 4G_꽞gA$ITv:*^kiŐ҂M;,A֒ۅ-۠Ͳ͈^=:ggOn;O@Pm3,Y:W@Intw3t.`|"D_vװ/8="IZts\SPLѶ-,\g;BNҖ)(4#Mf(^"U %+35f≱P)if^ 1 0vÀ\ըz WbޖN$wdXm$Y 6ra-bqeA`̠9F5!~1ZC HQ4&2~p(!=<{^) ZVDvoTd%7][N4YMDU O"7,s"Jfݰ"ԵyPUc$r;֨sssrsA7R&.1R5c!BoVEr,0鮸\ QT% CZOp4OJfk :R_73̴f;33c䯽0hb==]@R{pE$@16#(Qe*+&, ssZFK}e  X2lL]n\ ElY Tʐ+rz;k'=J8Ѐa~Jg-mS;Pg i'L灉 _zL65oc̹0;yl9$W8{_}1AՄ LG&1iK PXIcvK,),K ` q}lm b@YqF _NU}ɲR)PL\FU" ι2FbV wamiv72n,gfdsv-|qyP\O)ؿ+ʑ_v7ɸA^L'5YHyr[6E\NE*6Ѧ#KPFΣS$^ Hk' e=fOYa[SumRE4[ٲ;lYxȟ \!9x 0cns28z(a=q" ]E=Q 9Ԩ'PxcSR7n`Tv Q7C"IY*&"3D0f~uuƷvd3f|Gƴb QZMWcL> `L/}&a;S?Gc)vú:VSòX2J$y@:&ȒA"Ijx~D}NHubnHSc3 &څazYs0gӻ56=YfP+{YYRzReeܢ6~? 7X'rxc}K󋺱m,ܩf`9tS1ZEѾ\Q zB@Fú>z{jV? GL&qp2̚3\@}3;=cgrԍ l]s ?hYI8,%k\|Dxʇ Pl-=6Vs=4kDN}GćBc8 Caο84^V$&*(oϪ56(kj)MSmnp-k6EM2HZb0عᕜ*m>A@ 5M1P7_{!/}a_) R#!&Ew--$3:q:7=$ V kRv8E*Um.ůJlG +"Ns?Ժ+|G!r7`_ D}.#fTԅ2&ޚk=])i$1f³\ǩ"PP (DW>[ .vtӼ"ȿ:u 6+2~4Iˢ<{\tȃx{|AL=<ށ%W,OkG-BQq13R#]aOh,is]ClF4sd p? 6t~#@!M0C HHvC48s~pyhhӈ\obg&n71FECv֚XiS?l*I?Txպ&̾hߜ-#8cVzH%SD{@(ܙ2X벤'QBfT54HN'L?^M<:r3Џ:i&ffzfeI!b^*4jWcݰgZCeԅ0`phDꠠ*t㽶^qJ(w^NrQ.V]vտV0D20!(6Ovcfe +͝F>zA.9y4lz@]>Њ-u |H'dDg~ S̶&}9l6T%Zky` 2b7@'8G&w"ݷdjPfO<Aч'KwvF灦xpXܙE$!e`L'=^(MiW&f9llLDBj YL?bN gqPnm^rh-14f*'ܫe=rLJ6_rAve8b2m; AɏMSooK{]|_xn endstream endobj 12 0 obj 4084 endobj 14 0 obj <> stream x\Ɏ$ Wهvƞ jx|`][@ЖY1%gom{stpۣ{;n~_ߜ oVJ|o׿nۏ|Ku^<=~|u>oͼx7uVINպvgCR~oeqxVJ%]~:$< k|qQ4 'B]c ~ˮY8s&䏶|{N9\uu+Mrͼrs[?Yq !#sWLye\eVdTieسx6YDS}1EW OvٗT" ޅ]E:h>7ZUe>Yt(:{NL)]Snp힇TUIOMj$z4ѵwsdtU##<%&%@cE<[} 0)zmt zȋ'TOxз-'DVsvX  B w4n;4̨zOIiAC#_YN~Hڐr+CҰԲNETwNWĀ 2 P<^gwx@cƩxri:\]p)wy) ڲs?fWx zzB 8*4 l3-*9rg5$kSG'~TiEѣI̪&M~4=DfYiTwFQ(:].J" Ѻma2UEg'Ni\^"|%incf'k E.Z9[u]&t xtq1 ~ N\ß38|-K958qag#΂KA?qVh7} Ma"^uo`/z9uAWʑIS*S[bh ,K ? 5B1JJwDyDãVpN^T+_grh̢`wv@-#(.NM[A"Ș$dr}!,IN 9)I mjMDXY߾ZzSor+=G8O7E4&pI*V{ɮw[,"@iN< DRN6\hvHQB *tH[ʥw)A^*Dẃ#;e*ˆ篱e;/~ $-eED0]~:'teByM::Ej끍+9 QӲm1|}'4sğ0zkQ=X ??h1_T6zj,@Ɨthԭya=';s^>!0m5x\,8LGռ#cU?EH~к ~z&j9WWfxG2OcXpcre.{__~~Oq-ҵQL2~yg endstream endobj 15 0 obj 3589 endobj 17 0 obj <> stream x\ɎWه@U.w >\ F_fT)ŋݶrn7ۿʿǷ﷔w{_f[ۏ~9[oɵ { ]p=\&>[-n!kf+_ڕPV v+x z=I<~ue[g ؘ[ۥaᦈ+z}EdA &ON;$<| ""M閛7##_1t1F>> =HI}x4y3&~~Xw.fq>9هsඕ4>8#>`@tRi][,~I|ǛjȒn:p˪_O%.ZB;$J=|V\xgO>W rg"m]Zyq!_DE/eo|CIt(U^rG:XawY8ʋYcA=$^=JzaѓA*ޝtcYq;bV\1QQhoH.IJ0ȑF9V%H:Lix/e81pD=q#W&r&^k7NL D_=h\%դ-ށ/X/1 <]`#0;Cq5S`"Suu_AQi+ýC9\~j| 5!* "g\|WfۥqMT5?D4UZW,V'AKP# ŔLZ_#,>:rK90_V`$0Wpر5(K:~;@^Uc3K@akCĵRQtc_\'O2o>2[ٚ${&M,D ^X͔S($ZٿDf3!UJAquL6;I5P~' 4`vo /Vg,:`rɘJ$c9̰dSީ0GGݮtaǬ`deK3B\Of%kI[rR47?n7TNM;t^J-ZQ)Jl@F !_c M"$,(8O#E)k3?%ᨇ4R$A%9%D835v#d޴f Tc BNWci6EZ+'Z|qZ;Oy{Fsh&\㞸8QW(6MuǪ@I=I12ڕ⨖ 0=G:0%bzhqjx;VKY}?[$ow弻0ZRZ-m#:EE9Ovknz>AN^\;U%̒#!bSWvmom@_#F8xY9}y ٠C?я3yCc!s=:9Ȱmf{eh,…Qq_"m[±SQARM44C)o#S74Y|Z%Vg:",n-ڜX3׫{1=bmX+R_fVrab#-̈|YaG<)`,웙Rs()[ź\O9ژܙYdzdʅeڣe yI=Hv;tRk3[tnYQhc&l56q͡g@_b20-cVjݫfϩcH!E)q(&rU&bdQMʮ]=D*`WN["9K #(p693NTAbeF A#=l ΪՁ;\GHquѦ85(eMwZEl.5>.{cVe!z]gPZ3w6.b#D%^I*N㎱dă Nڹa5uc:3| BP{[h؎[N,f@\q8~Mbq UEvUKp~e Ĕ' NqI6rG9*~_,ﷳ1HeZ3F0-Ƶ/ x.o4ѩ#\[*ٍE/Ύy^98j.iteL1"u4:rggA3=ٿVP4م-́GYQC!$b0d9C8$җ͒dZk9JDi}7ݒ؂!C1#Qp9ޱԪF_!7ǝ%shA>[^?iNlB?d6&ɂ. $$jme9lz^+VlwONݝ;ӔΈpx?/i5GSr69BBť5CCĆp?Aph+$*%[D/媘ȳ"Q1$ݡCxz90q `l?`/. jzB9Lg,Cqq4hGAB*agzLx-9te} 8+O10I}6TϷkQ!E6Q!s֜uw'ۡI*6`ό"EqYIiY+Ëc>'fk@Cs}Z<^!z݁QRje"on0ǑԲq'=։\Zt??OB[kNmWNn.ϐfb5:{8$2vIbDv_2,ͩo+zw;qyܪⰍ'cX+ڸr6޻D\Bњހ 8(G+ Hh.`gՌf6{e~Wt*4D8#[t:tC竦6y[2\)?~+҉uƞ"DjhѢ`1u@孂=룽cUfKHn*qYg5ı}.V~*@ղh^NB~JD"3\IGE zfwcĎA! *`cDNͿ{S葤צg7wZʎHW~IofG$DP,'#  ?wїV+7#v}fiVҡȓ, O}mtMfR/l; q үJw>!EዜnȼW |'

> stream x\˪Wڋ-`uj?0x6}gdK)Uݞ6ÀuKRf'o,.iKpYnz.n߿x]/_gl?]_;6_oge_Jn5ㅜo*9+= /O.:/ȯs}B O|Pڿ~g _MnWm]馠>.Q&V^QTe>*F bTBI~cguK{Y ~)?T/ֺ%Tegp̹>*ӂ[.jµ| r;E4A 闘Z.*j~WQ9`~;~<[`͆pU ux! 7;_"'Y6:i9nPއr_։qɁ%9ƀ5$(^ QeeE~i}W E! v6e}R\!p@ܕ S*gݔeS lc#xH)rߔr_㙮q]3.+/nqrA(Tsfv^ΡcD[E[62"J#x1yRz쿼H:%ثc}P_;}";-<ϞD=ppE1Q>:>g|FehGkw:XH,l%a9O(~z+yCqy6ZF>c&Z@9d  /CCa8/ "\A̧f 3nbL:Ezǟ^3~cyn1Vn2oDi'",~2Kԡ-VQCZ=z֠;IS5b/q ?z4j[ܺG>:3 yAyZ5H&Φmb\ +\|ב('r"R~ F&[|ׅ rBJC}'wr=%g插[\ ƴ~.] ʍ腠D79.^0Z*T|wqWR6g+;-;| qJowrj}ZnZT ;;Pͬ<ЃF+8V4maAZ>^e8ˬHҽ`T9UFhӔRrOz(o(P9q.7=+fX=>+mc8+HVmbزc0!6ۡ#"{z: oV zLɔu_gG%J}30XõdKZܭ~2`Ne)eq7+Xb 4e݂CaSYcOQ׿i?#iWv2bC F߭V<||22.zoiH/Zߎ.*Fn@'-ܪYaV( 9LMVܮRj7d%F5ͤ[ֻ[0@'7C&d&k|}$ (ݶhJ++['ǥh}w"4Ǿk Rߖ~ $1ۣU;#uW9W3]M{p#ܿ!ғE=ǀ[ii\>HMxWߌzetsѝe45}Dc6S8GӾ=zqp"T`WkTm҄ь"`Y]jJch6|x^x+Nd gw jGp|)Y4v0~g,`mV}G4lP 6v)pRc*,[,obB[Kͩ*mȎG`8oc~QL 8N`jOd);}!d' [FDd3؇dzO[ <'RW= Oa:VqgC _υu_a?\}TИ$1GAE#ϱԇGboUUdFez9-riNm5N}uyT)Eߖ㇎C0X'QLJϋr^@Lk:  =~Rhܦ]\&/0'T9M]{[oEt ]IC o/KɌ7d8]1;5΃u<5qik|M~J~ xO5oZ5~J)rtwU(pKq~ӯww endstream endobj 21 0 obj 4015 endobj 23 0 obj <> stream x[ˎWx#E"m/@~  ~dDR=zddO9Ud/\zs͗z.lub෿]~99$?>L|)%1sM0n{GĚO\O5 >wN]fmA4vϴĐ,,"OY|X=Rkd奘"x@[`M!:(կEþaG6 062*֣,8 aߠT<$d45к6#C2ΩD3hplh3t50茬5>Fn~?u%/.P`\:zC4{Ҹe]f0[w yE?gѾ{`#}`;[q`vU8# nrU:T)p@M+f53f]!)ؾlǘhw-, \~A% QT Q+NfyqZ(''cd+ Gq%/Jb.XIJ 9HQt8gmX c$%sHf]yelқ8 A2b KCl0+is ~d[ZbĚ-l ~%=T !! xÃfEy6W<ЁՙCU|n v[6fz (Dҝx{{<88hىHUlgLt?6Ԙ<0b;Ҏ:8M*9t >EK0Oɔ$Hٷ3ߟeI}1'F-Bp͡4rTyH& < +Fĉ@{ 5&p&ơ޲ï&JXSy <m! 0^ef;ahjILb_A]I"E>?ﲃ5[?#32^[`*+M]A6~F3Kљc!DF'ib>T,dYk@pJbS2X!frTj:+46'L,)!~g7FJ/s?zrXv*R3)V[ J}렔~]@rCd(`PDl-it~ȌXqk|e_}Z3a&/lW |0ih?*&_ 2nD,ۛ['},OO"g~,pwwo yD-1A_LNRD"jáa3;4qcb6?E /҉VI7QRJn@g]uuSr܌|EU)&cܭ;EtUO#=6F+"cuMfE*YDSu{=%Xċt&'{ {{⢄JvPu:1YWOh' 4t s̱gFjYʹW>Xz!]䱨FiT%1W4``Tw'vap?U4uAҴ(CKρ2frQQ(|N"8RZ^Nxl3H#"m_ ˝aR !;% XfpnO'1XYJb&&F\>S2xo(樣ׯb %I('(0TVןb@&]d\ǚݠhwlN:3ÒM^d=:]{8!*p"zWPנ5Mv)1s ADg HUGOv<`# 8 HHfT g#Vܛj^/4xڠ _Yik~'RZ,FSp!Iop.99 s)I6-jONf:m:!N*_oÁpbzآ1n=)a\43"!88rZ.%M 7?74ǛM[tTQ3ON+e!{hp]ƙ<=:S'.JYӺ= 0.]AͫMgf=66Qn< < wDe{3nq_Jzm8ф"- VEJ,c2<1.8_iU>@r(¤˜zPjYGUׁ6wnCG1*- ZT_UZBrs*6ԝic&oaCʛJH8gp'ݯ6I> stream x[ɮ69o4s7@ %.10Hdy/jr]̴Xu_?y}{qL!؋~~I6߼O/:~cI9/^& r! K2 ^.̓, [tW] 4a{mTY4aƘ Ayyĺ EHrm2`R͐$C0y*Cj*)>0 3=o(+_o`en !-{$vzp2[niQɍ>ׂ0;T\n/-$Nrڨ3$l"Uum (ā=8$KH*Q1I"2a^!tXw< +yG9hGelq"ֲMe^gYx!✛j&sT3@-Y}4*oe/QR|l_g{%5ӃRqJDȲ6m9oYֱX]uȪo+73xuWJK ̆g@WO_n[ŶY8qPelAx\ZB$ z׳w{{ =le mڥvH%G)M^mJ⓾c]5Ď){l=Fe$Ԗ 'O{A~E_#DCq& WHT"5ƒ:eRqN oL͏P(&C#F(X'ȸn?FP\KnSr>]: \:=bLq7\?ٺ}+(0G!yDY=7G~?tYss|p da#Ц{@Q?[*$hhpэT|ل%VGЛՑ( .<޻x_oJ,hey8.rѡ ?ŌOGkxnR$(XPP xkm#W8jlW7YvGU|bB:Go̠Us 8ywfc%@|go f> stream x\ɮWuq#{wh ?"@SU(v@֕(XéSE-~m--lỻ|n?~~BRn~ٛ/aǿR~%ꅐoRK=.KFStM.׫0q4Pj>kZöQqZ߱`}YIy^dO6di 'S@7o{L\[knlo%+rL_==n_Y['-y`"o}yo}_Ƹ,U")Xg8;eA9Xύz_Vp]؎V,Ȧނ@,L ' 8]h1ڧ,Ekx){6[j~)JO[y.٥d=1b|ZhiV36J-{Awꆾwl_[y!m-׊SMʜ1gQ=tXdOhץɺj/^GԼM f9DqSåH#3[ [qW:ƅhbVG`*D ,#kù%/aU˿_]F]G ΝȢ2߉#e}րR).#K144Qz$ p2Wr⽪ffUdE~ ;"x S=IW͞yMHv^tT{ e\\i Oƻ`$P꒛RaHs4fq~[Ge*Yf &Jeg(Hj1GOlv/T]7nlN^[>Ѯݢ%<#e#5 =!a$xv>+/v%2B]~k2|V 8?(Σ-f\\$9`VY-yB[u_|Hݮ\Zi_$}U1C+1 so{F$I.`r:f!\e:Y[gK/ΟaĹ.݄:sgEICMI5,{@&AVv! gj{Ey7z^d3eiiHa#ۆiPK=5=7g;j vS|S@YEuuB֎g`;`|i^g6K3 4xC3g}<:d,BS'T.p4;8v/%Kw%$vGvhD HmefŒ\] n_U#ՐL&k 0ɔ90 Lt$וH0`«s ?λ0Ծթ=i\K}c, %cЀS8/ I0PثzB\!Qco@$X U>c ?즻2m7 Mi%+K(csUQS-:k e^լ|\FlFX $:rϩHfҾ) ] #h|1x? 0ɥ1'd:.\lLޠP<@N8 `(-[<6:I|_ N㉧ޮ̛٠ q!EtB*5kI_y4SӇ}*/2miBT`&Զsw^RԅVk^ t DNZ,)QDL '-xR&ibD1 5+=`MC@z W@N?z} )m8 j$Q9B|R5n.b]G !8#90Wk&$䁚[yK)TR@o#JT9,-?MJF$OKH G~jpN+iGb7T^}$AOx,0[Ng)mf WS뀃hh߲@}ud]?1m[3H`w%DlH p/H#wX_O$xu;):6YS }#]TG"V6 ?͍MiVR탺XA.¿v(GKfV.0Owɀ6QHY4aBHY¸gmn(y2D<[FH<zĮ9}5Kz.2E~QZ~ :DiJ6GiYNP2]n R8zSGXcV@WbXH7uGh[[& )^3_vETHfm'^āG+*$-p݁lM {%Eu>&\@LGuNKcft d#x^G)4Di~V,5 I>^&6rԖc؍}߁̣6]iCUц4 'D7_FzX<P/u5h:,M|*5 }&CWC➚t eZ*@WKKǯ^N#0^Gx|pN?ɳpA+p$rcpԂbS&ͫsP|s%XC;Ip9a.,28&Xcv@QgZ [A4rN:BNihLU/G )&AMPgGqa?;%YNbR耹گYU]!~?k\;POנMMz-txk! , pR~숤8NE 5W6Z$QfX4~ZEK,kGs:AyW0z.Ia'҃j:9$=@HֽJͦ۴=MpPccYcT5`^;#<+LJ$wn$@_{ƙCNHlzY܋MmqQ@bdZw첯ߑbO'## @43bvo(vT4tblzܣfCї@r c@ ~p }+*7>_4d}׷_r\`~/Jduˍ{V.,qR5G!$ EZřfgJV"STR@cp5#} ݁\plf *./cUY;ߑQW9D1%XI#Bc~HZyc̻5:F;B5.<(e+B^G. ifmvPuO>3%ko>9p4W'^|"z/y՚> stream x]ɮ8rWڋgq) 79EB]ySEpĐr[~ۺ?m~nK?5n1n7co/_GL.K壐nZ? [X.6ߧ%zgv)1t,Mm_\.}=ѥkLo.'>=ޞ{{ƴ>>7EW{_n?M2A^v)/j_[MWxio7V?<~N3( +IB\ڡӛG/?`%_|.wo|;xoq(}I`Ņh#2W5~tMѬuK/ >vpm*fr{GIˌW??J%֩].jQ\!xo0_%Kr ^f'Z+[*^l_,[[G[5k ]z V@M̧n[HN6xr3n?H9ZUNI==6jޢ%w 8i;,a1WJ}ڂͿ1EIЁI$ӓ6.z> uKw[xn.I*xYRNQ9Yiu%Y<3oܼ(}n7S,gn`pEٴtӤ.P}G/ +).YQ[ma#OZ`} Iji,L٫^a̪6w+|mŰi#W0&pHxy.z;q#QԎ#OAp3Q$uBgAȌUYwr)ԣWeDK66Uu8d*6Hdk5~٣S&g$h]0o>K' A=h|V}fp~}nn}fwG0֚ p"&Wp*hVGoB6p cBάf򍗋 4*R| ]!be`~bGd ,+$ 17s{6!9Wܰ رetaز% $6j;/L' ?ϮpW~zL pON4sKBYmQ"AC 1ހ'SL75-I3nQ`siӃU+:pQ8b`埇DaD^|%H=d.c=h3df:شQCk?c?}k$WZa8u-s`iO/[*lq{GgRg*goD_:r[j  ѧD|X>-=ARYW1sIhяz#E /|,KH+T_)JFl$WZ ifis TaifАX?C_L r+\JY@cIO<Ǘ>vRwC!ve)g VhXj>?A]Vu_@|?lbgod|;/ru=V Bw7E<\cބ |WM++)?oF|brjR q[-ÀĹ3D!Z SD:";oK2n/b)0r7Zɍh-8)akI̦n\)f7 a&-S Ap}LνnN n}Lu *I'xվeh,E^._d#͆_YzA2}XUxUߤ#=P?7mbf6I<]pTdk7 @aj*4Vq{{#/oؠi^4SW;1707yqO %dEJ 9}sJHG.oVF^rl YI(+n[<˫qZ%.zfɈxù@?ܰ|`ʘ!=9B Zm~2&;uf,R0?ЎǏeJC&:q׵-^~2R&]|k'Ԋz!BY` P@MYY7qx?=°wĜVLY[3 d 9+s?_F |.)B,JUJ 'ZMXwceޠ,&.ZX ''ZzPCx|^:^Zu彴Itߵ^Iu% |ब@,Ts)f` jQnQ YCT''b'qx>q4s609`˴fլje;ZIp r+ďg#JoFl`nh4 <[?D:W}z>wzty۳i2`Nĭ;jRߗP?/6x9 >Цds!6P`@ h4-Jmy{m]{ٰ栵kIJfC6`{ybj{}{cɼÃJˮGtV1ԏ` C֜eQ=)^G.P+R~wʶd??)EluJv6y%@"` *łRv:o4$4ϗCk.tsg6)FqQnWjna͇Z Qcb8􂺃a˯pjsQH(j IL T̏]l[m<}U$ȎoW@o1b8(W'nJLokQ 7 T.UHv$ R{cGH-̇=j̇&Q#2ޭ6hdA<]r(R ͤ|f3/0g%Ѵ'YTx^'b. {P] h&g dԘα|Y ͜=)l]DX$aEa۳h36p]2nMbiYJ^1Wd n,L-C;WBsAV CZ DZXab}npx1d'';-_841|1No;IP `0 U!KEA'IcW 5UKP:sA*qYUPN&f4+} vB+jiC!c+Zbxՙڥ+w9 s؟e[FT% ٬G9JJe|IӪ㉇\ `B<Jwe {ج JܠZ x4i~W'dXͽ;C3Дb?JMO{QixVNia'҆Фnz('8$mpr@0莊=74  z^HnD *CR(r^P*)?5~ ᾧ_/+"i M1"i}9 ;^-޽{c4d$ .w>o$W W '6t2# 2\F: m81Yh6z} Jg1?zsx;H^:|B/_gSiZpm6{{&>CF6ѻ2Q.28đ`P6* 7aP'S( !FY=Y`̮gڛ[#TnRsW>>ɤpQAjꁧt{:t0߀ibz ._Dž8d4Ҍ>WFzLb"4 pwmaw66ebGba,l'2_r"%5 9P.T:Ȇ}뀈ۑCp:M֥m%:|R>f̀tgTCܿ2s6NCe.uޠ/l0~p=I}ύc kC<|}@aˣP jGQPy5Dz\5~](7c/sqhIU# QRex;7Pܱ.~iQ2Ҟyݪ;"أ<90fq =4bnugkMϔ9)lȈ1i܁x_Q`ds: V-Bb`'t*,9/G (zHtoJFz ̥Klk^[5PS[w@:O1?3 T ;4 wtl06Fd4U&"Iǽ.zQU5DuMP|23H.sSbM|k 9Ռ]` %vq"%U&!^} q_xa" L5!$!vqX8ҎeBZ/LaƑC58gpuXÞ9:)lј45HLDžx]קߒ$f3fvBN zgٯq"BW,~g=S’ D F endstream endobj 33 0 obj 5934 endobj 35 0 obj <> stream x[Ɋ,ݿȵ,Ac7<x/5)](CΝU?}.ۛ%{V.?]~~総B|˗|ϟbK |7_wn_R -B |_4^9K! o. +c;S|}KʸDx/ ~aBL byX@9[_(eձZ[ |A8uݢ{D8Pq<6eֺUBJA/Sfj'\Zr52A3A"(!qA~Y*m(H 3:bN+htt6Uկ?c6㗍DgVm:,616e;0YyЈv`; 5+o1[M߸jWB:ZJ"NJÕ9Y#nGqHd!IfQkM@azv_A- |e{X^RuR`gW “HBU{RPth! 8=2<t9qj"$;!QȖL뷙Q=+ްGXb`ʡ{hkVgUYNtEAW+ݒEnʡ6A;Pe^K^ːדRFt)]Q8jzŖ̙<ہF]b>Y?=&+%tJdǶ<>ڶ,2m(J gi|f!$v j<6j6-j?wi}H:x,nLan_u&$C{d>zhP"ĜDD%"aJT5Z/LQ EF6O\JNЗ&Ճe GU0P"nBH0֊HJLFa\ vZ+QHXy?Y#f#EhƱf}jщn597Np"?* ~uѨFJ0Ri! 7E|_Mbb2H:u oc'-kߒ=q`/-bH&=bE2Za.ϋ8\f ԇ<' 4-Y ^j-2e!ZSSw Β;٧CNJ6LL{#=Z_FҁCL'+mEԯRf?5T w"QD]D{zL`du' -qYYb?xeɩf]#umܰD᧨C?%zC+Ҟx/spB;Cfd{#c9ZҶ_wímR'y}aSnbަW[hg. GTB)wh[tTPjD$QSSG>۬4~U7of1H؊\Cm`]\8ildL&h2{?`(6x~ ҔTE;UŎg yfR,kvIm(tQ ysz&醠x<4 -ZMs%G u?ȴ34y5ao&=):)pE+Lt+U!6DsN5YȒ񙓌^o */L"il :6p [kwG>U S_iMrԂӷ<0LAytΡ-Q P/GCvVCTk{ȡV%E`t\3O> i185 C=m' zۘz>tFmkX'k cI;u 9hH,}`Xѭ\iyg|bRGspyҼިϛ2ǯFk4Gc!8mX3:.X  ϟuKֹûMn&B$Ȯs1! ;Tr%ǡwy,ɨlx[ `KY9ix'k8/4*%]s:f9ň෰d7z%=K˔Q(@gU/zO}q4YDŪ_L K"*4 $$(wxX$,i.u|gmrF# ]cabZ;Sӥw.wuFS+hX%T4)aRue"ـ2KQ2y@;蝨nO( ¹ؕMq)̯0c%j!sՀ|j \{=?!xKfmn h\nr&J# >_86 ΈM2kdx㾌`S={ endstream endobj 36 0 obj 2858 endobj 38 0 obj <> stream xZɎ7 W9Ni#Yė~("UT-3cC>>j}g&LѪS>w }SB'=6|ӓ1}ʟYa*h'@~.XGƁ{eŝ<=lYTq+h /pO, xN`ŊRuuHCoe)K{Nӱphc--W<^btY<}>7s>CѦ&|VCR_dI N[wlO`|[}DGK0 `)1&15r5BqƷ,Vn bM ܱuZ.3Tc\k kP溪k ފv"rc9Խpr38kX$?, UsΩx@g/͵k]-J#',L `h?U^Q;| C|tSN-ĖaU,rA\u%JJR֟s 7y B1Pqwp:ΰ#asYZ f]yβFjYSmEMxsyicXwyYd3Ev ҖjQ(7t7Rg@n\O4O ňSaY Ȓ˪$j[!ߩߌ[2œS jqQa`y *Y;ICe~i{sNzmz#4 1EFjmn]["S]x]^-t%2!`wŗЦ~9ENj8MP}iG-)NKd 7QM@Twf‚ozʽ*?|*}XiJ3~3 qE6x#-kL)Q0ΪJZ;@bۛ$n'r6@`tz(p7 (/8PI#U@#-f{ \u/שn>ݒg=##xR⋅Eͯz{QnVQ}M=ݯ =0 c6 D٢Ƿ@N L/ ȎܲDc=Ќo?^\AZ$'FJMP'q &DKtZ¤Du 쒒v`-lw5ST1l V3G\!@Ф9w*nvyoH*_1n>NM|]%YaFJH,ř{H;됡kGk]Όъ3u㌵Quzǜ3:ׂTNK*SN ked:2:? endstream endobj 39 0 obj 2039 endobj 41 0 obj <> stream xZɎ$5WCaהRwW}\}iRvn4RkrڱxfLb0y黯_oo?==xSJ璘vh~~'?~\e]<-ܖt9eɚKzӪtP"& l ڹn/KJh 090mxj :ZY8ThД3iz2/<7E)(fSoxuM*uݽ;o}wGg{G'dϱr>b 4Ԍ!}1h2/k(X \ҾTB$497 (Rڄ1Ս^eQTc\﬷"Cr/դRVu.VkW,#QI\Zgcސ~䲺1 x43)fxZ| 7CH2 "mI]V)XCbAk;nә!ݫҵQy(tru .}jXإ2&^YB1n& w!o2֖nh#oQp T;şU :HgJ%\ZF[ٶ9QD#k04FY/$@X AHPȤ!ZZN$[)h=G/K Tz RC)Vh-՟Y@#Z.;7[Ą L)54 z?"[P[,&(dsuMXyl3(U_c{q:m$N-]b-$ߺxv/> Е<'nWN۳d-qq~0Y)a.i>TT1Hvآc5 TaXzOݦm?ι}R3]q._${A95ڻ*={v\M&/`f:«<(樺6_*e2嗙Mfet4@V6^iT lٰ?)-K0ܘzAbѲ>41Hrk:m7ͪ ug*oY6~j{Z-$y0Ȏ'Ioy 箥w Kso1Ghzŕ@[sDzCWRIq0~#47}P#gKH; ? l}pMQep[EcGIfCa<yz&@KFEA'`%`slj5j6&zInM)\>] nhH94)fzxN|lݞԨ24ӊ{YNl;k2fʐg^ټfst %31 pi!%8 U,вyq̭]nT0$^a_4M'ǡV=[=Ez&579&'& 9囌n-foNscZB8fhq0'|:~WUwuE }mPJHFˬ:UGqb\h 3Td;VlsMb-FcW /3w>Cf:;a*UVmf@bw#vtL1|FY_|(( ]#S~=@c;2+,ktG4~x |+]v&JX2S|=!JhZFFd}"ڇqf':BSV+ .yĞg3 #"wY:˾Fᶲ}>LCq%.ڛ;@) @g2iKɡQ{\'1)׵S![2L=rUh?2t;vx_ i&#2UanNG8c["^?K3 b:pCj^{uQj`DՓTUS4sT2&vLVf!ddn+FUFz۸IKH8671aqd##*j3wD&>M)R endstream endobj 42 0 obj 2170 endobj 44 0 obj <> stream x[ɊFWCY@ `\LŦLa1 9_8'790Ew/?0}!4ē~6|ʷx۱)g?GY#pJs%ˏQ~tzaY3ӹ|$\G/Sٴl/\ +ỳ, E#_ЭQ|EB8HԀg &z@cc\.6NuNq;Db-~*]Oeya𹉠0BP#>Hi֢q­R"[Ow$[M¼w{rl{'VN׽L^9.:#I 2sNqo3犮qº[$?;al=~oƲ(gH'}뎀߮  Dc![n໖$#'MN1H`/ӀC9 1@Il_V@9 F[|[ *J8 3f Y 5'L|%7z xao܁ !b͒ q6M`jR$Gz]yZeyy¢’y2b58ȕ6xՔ@`,y=`JS\ [Lb,<&^l-kՃ@2`x(r3Hm ʄ@Bj(pՂfeƛ!^Zr:RDyOm*P01f|l_ltLy{j=tFVQV3Qn̛7-v k|!-ܿ6Ř$>eej=&QqHsk g=Ʃeעe՜mi;- ahzh|bb{QDi7C![AL=˖Ε?f5YPbV8JEƘ^v 4ٗ6W^ V. Gkjwt~4`lۋ]rnȲ>^4%ϣ'#?i9bV_3K耦 JI(^ X2|m8Ovi̴iY΢ucuc,+EU s mw˼#Q6ں\$AT w,KZjb,ZTu $ enVUչY"mpfpPr@L>40 w'KEa틳zOo.Bs>㽨iv!l64rE=^Q@N12_~BWp2ry9z|]O5̷D:tH`Ϫ. {Xno-q #3.i2&MZե٘-?O`hwgβL`"_Q)DJz 1|# >`H1F0V'`jJ̥~SAIR=Ԍ%=5MWiY*l 0ܸܷ,dF7v׵|?2ي.C|jm1k}DxI\)R :1EZHou7#vt.l1 CsX1[r-xZ?hn튛;.t[tcn|G1&ZpP:(Th[[D ˆx"wqfR#J57ݼuZ343K 0T?%#gxZ5aAVfRClZ:vx:Zy/SV*vfVM37e^y`'Vvnf/c$A«D4jR1Ɖx<6Ҝ)ci L"uI{5 EOP]c@@w@; Gs|>P3?F8*`YƏ \Ps6AqZaLݠXw3a5ӝG1{B ^id&R!* (i֔8P)8MJt>r]QօO'"NWd U|thYJ$S8'M| %I d?/$ y_('';}uhz; +~o endstream endobj 45 0 obj 2281 endobj 47 0 obj <> stream x[nF+xan@@~ CO/M79ےA [-*RjE-.S^>WW~>Ak{Kd_w`^|冪rt6ʤvQ+z<+,/XS'Z>ᔖضCіŞ1F`zrqpKiIǰx488.NdTO 4< $I[)xغv<ʆ P{qaɑqB(s'=;p>GgTwWT%pWX۝KXi)}qvYfpU:St0w0nj|zǾE&@`#ۭ-ޜlh܍]40^TRytxB3C[(4g&>gq4ڰlU9Q0(:.`\7e{0&@9Ec~,:+.ak`C.m4\ 3G6W V&pnv!g`Z'uF$ӹBsHNC0C h}3B ~JT_m)9q#!xD0B.YPdMIJ4k vY(a0q60UߤJ[U] H&t48Y`5$B{Gg)@I(cncгsRN: +b+b?BLm0* f S$U9Eۜ1(zƤm]U|Nc&0r?u r[9 8E`v3D89Xfkה8'qf;:D9^^3W"i2uIVbD|Q+>aq1)B aIyIIJ#ן,1L9&1P;Uf뽷 Le;(Ml5ޚwEݭ9h,_c a}Kߌzͱdx؈"^RIh?\ 'tW4F xwT5VN)TB<[*.MZjު "(bZigu컣c91Xt&V57wFq=w0b7~忦Bfesϰrs_XU`@: 2r x]\{XzAin\uNh5Obcɦd84=>\%h/TW1  nTͪ% ~; Naf}[ct3\ߊƷZ4lʉQU||8l2kGZ| t+K\MT$|cWsh'*+DaX&дnC%Jq>1h\}/ߵb0Lq}':l}A: Mz` rgȆn2>\- 1Zy\unEhm}@K>?%^]l%]\ي£Uf _ț_ى̧sE=s<,Eۑ> stream xZɎ7W9 Rn`@ %ZTlJ{ؘˀZ#ߧuYOfٟ`IΜןoO_|8%FwoW˻hY^zZz|t{S:}eb[{Z<7͞&Mk{S c}V/sS!v[۶y'J`BqR9)\b?M_B̕ūyݩOF0Ȩ-YzΦ=cj= fC|86h&^} pM? pԐhz[04$zkT(X2[L*Uw=A*fdsI0ti (Y$t%N(HKTl"5r LɞLF0 *{&/达n8M݁9N Vyj{3Z=:9٦ɉKϕdg9'jL|k2fDC >:SғJ*C+a  !o6jZթEq]],`TY\I4"̠j륇PZ.z&0F6^yV6PBG7BqwɻAH}#u58NYyK=‹qE =sy*Q*řTk<~uֿ^0^ka`o|?>V$a[qN |g} ߯Yk*k) >Ч48`EȢfnj*=$J!FPkV::zd t25Z<~ʦBnTʕ|o;Tb Um}rfx7V<*Zά`k)M> D^)R%5D8+M<ὼQJ{7Jc2DH Xz7Mhf=ϥkGX$rl=x:iٯMF-xOnI&ZX-W0۪&Tlm&G_gZlda3:..ט)9}#'#,##nj̀Qѓ6 f*Wj!2\Usw03%HY<جIfHn < &*W=-#aM5^^xLn}?"d'>Q0oD)ӿ6 T,Iv9SytddZJk#n/h~OUGhwӛig.32ۗ&<[(;Ҵ1Pߩ:7K# endstream endobj 51 0 obj 2046 endobj 53 0 obj <> stream xZɎ8WĹ1n2c7P4Ї/CILYB6 (T),#HyrYt 5v?r[RJ_[J|p:nvWԶ)³ӷk i! º?rrϢHeȠ45'\vJ GS.m ]XײdFr+Rb = 3gӹ-ɛ2)؟aĖB&w3艊RB'b]*x-2[|!@nbM X:,[+l-!DZVyDv-`ﮃחKFO }?jHPPѣP}Oܻ@{p ;qmZQzkW3n %u}mhk~ÊtM)gWF >lW8ӥÚvKwFȩ\<(q*c!>UVr-Y.wbKVԊQq|@p_}ߪR'V/Ʉ|:BBUt6Cݒs[T&$7 4+dd:NYB>MhOXޭUpHݡ\ 7Tdޜn(Jn-K RsWM={vi-'*8^3ǰe1C Tqn*<{AxI A ȣ^V︶ XNJ᭾E`q^T Ipo)plD&lm}Hn*Ma'ۇ*橡M,C;:+MU|]b~ G!Y1LJ"Pg&'W)| _xJ#-1U:*~p:K)yqW{1ۧﭱiˇw}At-CDA#X:qW4U&'N)=f$4ޟ:ȦS4>Z(]OEr+Ĥ%j:yx)C2$^Zn#,_IrT8 3U+N؋9̀k D+R6i$#>NBfȡU=v4vSfLu?jh n1WeyK6>761a|V+* FҜuL,p*1> :f$|;shj^Ct~,=5 Eb⊎Q+wlp_QU`)sa?2R7VY n3'#Ȝ/|/SVR ;xdxU5]Q߆Q:Ubō: ^oY> stream x[Ɋ$GWYT@wV]P0?0e~_Y,Y=-1-ByFb3to2]%t 9k?~˗p͗]~||RqyŅki/?i@n~ Dz%.LפߡG$a~Y7\b~,3%nw[`fγZ;W*F[D0&kll]Ϣ6|wlw8?\]囟ʔ]ف8|jvNŗg'kԛ'PKs"OUHb/.s ?3^\m[k6}gn,l1,ɹ f[$gq$؀l`&)<_W  KYs܍9:X4Jh J|Hx%Bhx;\7 *sV\*\ApLf)`!h# jXX1 ")o!7I7~.0Yr҉YriO䀌&-ݩݲm)5Ea_DDm"9`fmLzw܅]36_ȡqE67|XYl3&XA S&68MOqx&j & ƩIÎS=rX;4dӟ,+$58y{9aIzͻ ! %!zl^2o.dނ^{Uv1sʮ_UeM8'" :H飭òBL ɰq/cgKeBSzr?T1oʆ5rmo ؾYW~vre[1gF6)" жv!H aU 2ܢ!>M e(QVq&S͈ߵJ,>ZOߟJ!>;TIp:EȔn^40;0zfݢ^hUpMćFHvH9Zgi![T:>c`sCf}3soۋYf ` :[lxqTӆ"wSYlEdJx~a>:) 7h,nKNqDAt6+A`N"CV-^2LK.F}TiIێvڨ:!`Cư@Zcp E|NEPd^ }k1w?)vb >Y ^#gq?klNu:̲=kX(M[l>Y4] vDg(!80/PD(Kxdt yDj%!uIK4* zJ(]hx&$Yx'-YXjڒ"ʴF PwICtIH> `]eF GFl KB"Dd@+;> bTQ7ƟlܰFv kkG&> ίFQ6`>sUQ$QD+Jqm Kӂe [5Bf*+Q1'ܭѬT5Pʼnk7%AX]GtiX$c)3&&L+FK+Ofjp4O+uoxp`). ϭKC8ɢidS Oʮ~άضO$B2Jt.7'/ Kh*{mr``vLiZOW3ݦ x04CPåL-7;m Ɖ4M]` O be-ֶާE4@&o{<683F%*3su4"ꋚ^!}zjz혆mzeeDt0hXoYe^ɜ0ōŬ;ɫK8=be#Wש8(MwEt(EWj"EEmtV~=Tb3 ߥ$ Wc [uam ii,"FVzG&wPKAOBz?G7W_/*Vsp [B_X!P{uݐupɶi =h{%O;w# ֹ &YD=VE쉲6L*nFG+_;}t ?b!;(Qr!qeʐ\cSKW-F zn5槐&B4 zz^^,q0Lo7Kc͕ͿFџg6xmn=vB_PG=DZ}LvyK;~&w~j^CLN|^_4mI/?Cn[K&d ;͐usv`.OO0؝;,FGGK:@O@B5 3D8`.> stream xYɊGWهvf0} wdU,YU]=0BH\bybi3d&sS(L_~~i{)O)S~~oL'w?~i^H'0B@Zr^M9Է0YH@od"$?/e,eҴj1nvYbW ::. `I"$^Y4#kHm9@{tt]PAQڔM$kdeϫШkr;2O.#N+| EAJʖ꾐{{Zw Ś=JKdYRXs9r;&b 9H WGhzW-[NCI-!k1I YF ⥗6BM|c !T]hvZxʕ'dJm 1Ad8 A^$U,<~q*F gy`fw<~`f^^ =gwL@ + (+zApB[͛[HB%0!_ ~GG6ĻHXOXl8Dc0>-~b"xZpl1<Ì3*;űx 6QV> Y#u:,rlҢX n6?Wnsܶ)x_v XcdqߴUҦEiUj&G>yh~q@z`=dwZwt,f;6Pj>|xo]YL)8Ӵ}: cPfIQp4Zw.4̧p>BAddߞ|rυ_TΥndf4m3%8~z_[Iɂq[-&cO[?CRzX=k޵}Eq#%iSsq64b=Ư/{fH[-7LY[@i&~h}}&ex*<9֝jt}!_vw,?ٔ*Db9 Èn*n9pBL9WyJxp;r&߰.- N$-y:œ )K buᛮ#YA endstream endobj 60 0 obj 1732 endobj 62 0 obj <> stream xZɎ$5WCvxIK#Z#H O؎iR̢!fby/f_`Zӯ?LOpYNL?>d~>O/ + օ( I`sH \_/B0BHe-ʖFCMi<\b'{سV8Ǻj"o2tq}Lx`g2En`ļo7=`N3BǚM=tsDb׈#z0UYU(i,=F=TD`oxh\.`mٕгA 7F9Y%rV 9F?B JTUFH8ˡ=&'Ld%NnlΧb-pvqȅI?=#K qp[|sClJ{ԟ#ZӬm/, vҙy WMò}3p6N!ߐl`iFOj \]$@Llޜpn ̉! te.F_zIzܷs吓s((YF+_D1MEa;y/F֨XAOeH_T tAwD0ppJ-"R7yIΥAKU!R9{%iS2xoz]Cv`9Ts b@vak{GR~ -P[Gs؍3>X:s􎁽, Dfϴk.Rn܎2gaԤ;ƍSQfhJVMate9 ##L PCjueڌ{Zx3,J<˼8Lj6i:@VX aUU֩ken LCpX؄q4u vn;M@JP+=gc#mÌD =ʉ(W[{@اOr5ÙYXOdžFs2hm J4 be} FNݾ9`H}C9sjg pcìg,[~2;u#.ڋٍ?{g;&s X*-ݎIXKXB[- 6vD'm5wbCkU xBO2N+wrv_8/=NXV5FS=trƨz H[j_47 vi4  h* %Ɯ bbSumHvajs70rKf[Uݼ qM$l,WPM䫽C+j*XHMrm`o)qnexr/ȶ HOJ3vL[<𡮕¼Y{YsU^#My!/|m+ܘՉZ e|d7"+'}_TT endstream endobj 63 0 obj 2232 endobj 65 0 obj <> stream xZKk-W: Tz6 }~?d1Gz} YXG-ջY,.a n>[[ (1F kN>j:ǣZ)J9nb5rB*<*[YeWstf| ]BTWB|‡R l4o;J/*`T3f(*v`WTMgɬ0xH, ΰ*e(2vH3d 9D ӁLW\zi$xPmHObk4@_O],*x͞*k]À%wѩTg~k͇-|{װ#}ؼ~9!U߈5c٢q: lZ_<_?| S342oPdjLM >{uʅ >jwhT>m~VIKݭ+餖}]$t9"~dk=C18v*r."L9 bG!^+dyɌ-S=p@`eҲS"$fu\wL_peg1»m@ddLFRF:T8];/ZFiȁۄYpiITܵ;jah%<-QHѾj0ӥV%V+" LRG|j10V"m70yGB3?h V!YzQ@1 9=ષ6u^ u#4yf cԙc_t#qۃtaʣ#sSp/m#_U%کfP*u":OhThwNMQgZ/}Fs뮅 7gTWj,>g*XL$ۜqMGb?&R  cQz,1^<)x+0⭻N-:qCؽsarm|o6lc=(o~pkX̾X#̃.{wZêp]b[yT窵kT*(jm]%mO0X9}b6Q gT F37ɐouNSBHo\Q9SLu2><6kȵG߮Y*(W~wtUCcw=:kp|~apRYhLq=h,kj*N/nyg%D6;Go._~Q;ӵ*H벛+|X5;URH_ώ3HBL(:@ݪTE~+ZZx;Œ' )+{ɘkdKݺ"']Wߑ4Mjm$y`1 qD2 #9{ۍSfmZvf , A x!Ѭ(|MiԠj2Sλ#]cubSLtz sW6*<-ڷB*?1.У)N>c9?- endstream endobj 66 0 obj 2708 endobj 68 0 obj <> stream x[ۊ\tK`}0$@&IK ²R\=]tr5_~k[x/)v^L_~/TKiKWGxWu1.vZ⣽K-uNm3vn ]<.LjMӯ ڵ{d(| HqINn}@A1woovC 9Ь U4X!.ѕ'|qiF|&n3c:,Rˡb9s1Չ$2ɓ 'SHFz%6/t;W±䕗 "Tv EW %RU*Pͽe?u,a^_:Jv.*kH|Gg6/{;c@$k碋u&;.J6EEw tM|R\XUjNMf8nzLKa2݊0Yɳh$U3+J={g֯jYx6wցTo 15;D厰Kaqj^o\yRE'd3Mu95V_c`\_%6Hb6p$\~߻ϕu7*]FCP64m@|%ov{+Co08R@nqe8`6&QNT0ڴP8TNܣHx_.4s,_us4@G4t0=C|LHtI/ N=a'>dQ=y7[LhMGd@~j, I (E !j](g%֦fgy81e~6dJ-\rJ_z7tsMN ]-4%F,8 YS5>P~mljx\g.#v ԯ%rAf7OO=^7Y~=un{Nöb VbG z ^az!HBԗO,/_~{凥<Ӗ߿K߾K-=4}|.=(RNJO;brvlkxP Reau\I(JAřz_5  Y+xj6)0ԊlFOŌK7Y Għ5hqA:GCO,/bJ+VfjFJ~6AEXI,Rn4:۰[Q{0H!X(8StTF{i_'׳'QMCO gjHW:a~C'dBXB_?:H`Q[ͲԙТ ,*GٝNQى_: 53™£1K W5M=ѣ3p+"1Czzѫ*@YNG0Jvx_ΙsE|GOȯk]m(81aN +N rzA΅mYro:CN %u ɭ61?vy(Hz34,l Be0jq*=^#<":}c^{EH83Aۮ=h~W\O> stream x[ɮݿ: 5@Oda SÝxHJ46l{z?2]%,.7?.[ǿ>>>BΗ5^~i.˯MY)oWT8~0>253f5.ڽfl}~}64YLdb, ,Rk)6zDX yX\r_;CtG4Ǚ=\( GWMz~>D ΂i&oc39'ۚi_rv9OA UѢƐ3q,ӃLh I @b+'F(ߘ T 5c9+ikSl@%ZF[Mɣ"dq1=z"ew&q `zD|vwۛg1`ENKX "c"z`';b(HG8%zt;чl;K i^-h|we0Y~~❧6SoBX朎[/Qaj4~ ʴ#Mvui~:p'Ҝqj=~ߠDZLjkTҷ֕E-H..i~!.\ eȼ 0 {28SV{GNZjMsm/Fс›qC:JnY0cGJ]nÿdA˷Q(E`B~5ً4{ m[j& Ӿ:: Wr2}աod;yN*6IV3mQQ-uϊ `M80%βȥ1 Up2.̘\# aIbhG @IFduWG ؊s,[Qdd8d {>U~M-.MBaU7ݱ2j©-F|};%UΔ4aLS{t)(oߒ endstream endobj 72 0 obj 2774 endobj 74 0 obj <> stream x[n$7+ vK!ܖl{X"Bºq!҂G Bw,~S?A~SuFR ?O-|E_d <*exm5VPF6QۆxtK]Hv )BCP09`ZM t-u -ĔE0([͊J(Q9F*;Z|OL7Қ_.d.s1ϔF,NЙ-D4lZ۽vgpt "VB2VA + "l8Im1lʌlÌ͌ˌL"By'U,HjWG_qrCd(Y T1Ch#ъh$–7Zr$wEH=jaF7F 3 LY vQLbCGbkEb71 &?91nX{욟> ;օL3s}䫻3ozhpRSlhs, Yu %+y̢ʁ^uF, Ń Mq 屋rvCal Ai*m6,h7-Y/6ɇ;A[A&R QDL0Igql*FrMfoGăfKU=&ohi# ;ʇYu/p@eRm@;!zcɈ IU'Qn1ءjQ =/S8HWPȬ|Wh2j̯}Z]â:STD3AA2Vz i8*r;CE~։uڵZ)FDH|*ZJqϱh&;.lمbcnac?б:J)=6mGn c{.9YI_|/piu(`| kTZWEX #v8ݓ8|ܛj%n">BSqT)"jT隦{.'Ό يRm[#j4`i/z64 5 ^ջLzm7U> ȵ*TQJ>h[ r"4b P24)Oj4U]vP8AUV9$)8ݺ=fWpNޔ+ x3B>]BiM DC~)#D]gan Bl:fK']j2B8fuGsnB-Mw$*!l<x =Yn_ a-jua}f4ZkN! bgfya-=bW%K";B~*OSZ;_XSFXhQ[r:ܣH!m`umk8IJ!]?.OvGHHoBO7s#aASO$ endstream endobj 75 0 obj 2536 endobj 77 0 obj <> stream xZɎ6WG܊" 9H.pE,OMId^{紜;Fw.?Ƿs8Ӈ;s s}>9Ϟ|_\cK7Tpa}xW_Ӧ`7a`| G6pKN}/JH9NWoxN,*QT.{H]2OqEw7Zsv_U `XR(p9>=*:umF!;t[k谀ksi4c4ȶooF>hxp6¾Y}gQM9}p="E6L'gk]/B.c= : )k΁(R,.+I鍀VVU nOE27Տ?0Wx4AL+8 &Ve0B= Q% l@A/HL+!1S.Gft>P-s("<Q(RlOMȂQ j~L^GRW!I*(=CC %r=:W _A@m5"(#Pm *ETYh U;<W,45/qٜL Q깆#0CbQ÷V|N!a ;š=^9KǓ) I|c9鱧=R Ed(/bg`%t7Al0Cr^[IrX}ܹRgL1)_ZwR^$ubںq u7\v)tJZ% ςĂ'SG9Nu8d5ꥧ~ul/A:@Ʋ@N6\ I %$C !]xa{W5bmj춑f#Ic2KCAre!Pc󂿵Dm`4aK![ɣcI{ ~}~Xm=d7phe U)$ `x`߅[ 8QS >R$ GF+V<\zQ3'mCd`)lW`KyQkcbl9cjBeN ۺm&Q KP C*P$1jb[*˚Qk͐+4y6u/~SUpo>EjQL#h8LRܘ-lN !R&UD"O4 ce)m[D3Zv6x f Sۚ'wk?6ga̹!оvFtN)U#?30ep%Z5B%ؓ. $Cʽ y}ٿT<<#[] ܶp*c>N\"rP)$hETB+!aAǝG+;.k@~WKs%dgEb8,\΢#G9\eo/oer+<5xMѫ:.~koi`7Dh]·7/ S1u%=vwl9laH{!U0M*;! (ЏL `P୘_̍֙(:}~8J!DJy|oCWx^mBQ@f5Cp^M8T͘.\n=ڦ}\k& c/쑨@־]xUsԯ'znnP7/.[mDit͙ endstream endobj 78 0 obj 2170 endobj 80 0 obj <> stream xZɊeWW 2߰o(^47}kr(H =])É!-\Wsٿ%9/_.ʿ?Ňtѽˏ]~y؋)._/_}5<LkǥڥPl)ی]{o/mJTVZX=ӌR0mȘ1RVk!{9"D6^/v..SDZEā6˲EhCfEF궞LU{j,Nn{S[<Pjl:֢ՖVžHssES%a\cȝ;M:EZteg5 ׭"P 3q,Ptg#X[9Z?qH0j[tkFgiDOvjZ^Hr3,ېA%OcIq$=!K„ 8JaR/  P_ВzT+Px*۩"Cd'{xٿ("P?IT:' s{8nv-b#kŷCDG5[}m{?Z$cx&__TAD{Yk5A\,j`euJwÔ{zW=Hk.a!Jyo% ^`őfRU.UTF,G\R ًxԄ<+p1Mk-$.ׯi [ ѣW/ @87ܚZۼMea^Zny keZ*I&Ȅ,rEKYk9Ü9OxM g9 itg.j褺e6u /k O/Jp0]X\ D=H endstream endobj 81 0 obj 2554 endobj 84 0 obj <> stream xSKkQI >6aUۅ1"t!BZh0"d:yf:BP|AzjkqۿsTw> endobj 87 0 obj <> stream x]Ak0s=,Q7eC? & I1k[!Mt=u~`{L0zrKX" 8yRetD%Z7] Nm/_c)Arϳ/fFKix"Buyb%lhBUE($;a%YJzht~ڀ]I=WCܩm endstream endobj 88 0 obj <> endobj 89 0 obj <> stream x< x[uW:zs;#;Iq6)8e[vI+['%ГBKS (02J2J!06~on-m떵ew~l9$mλ=:5\ItESjr !jN؆o"cdggrxr*^ݫ\/'45v7 D >V&RS _4daI3QjJ>B]Lt~~eZ&i|$pͅoB*&_s(A"78._+!{IWzu{5A^ O"QC\:\%iM^tEȽHr;e rrwW$7[]Ot"ȍqo$^Uq_qG!!%l\Cט<V+rr۫TyW n;\r8< K^ ϝdmA!k u9ug.sώ1mB!j@wkPR{9XӁBԚ!;|CV4هU땗͞gQ}/KVhk)3MU.c mm_75Tdd;p6ifmųm>ڷyd@ыkm'\@L+mOp~Mk]mj4[Ӟr;Vj򖮅ߑ߹j+Sג?uxm=N{9k_eVao:Ftt.X\CZ6a<ÏZX}uuͰxfΆޖuowh}9gEMׯ]WbSXчyvw+u mp'>`-ܩ" Y~RT5c֬k\޼W)9DDryݙG~}O]rVݯ?b&enDX'ɍq(MYqd'e#Xn+,%vqtũz]PUucKIp |&*B$\CŸnq9;b`v?KY {HN i%*Rp5^("`,f$|WKzo0{pY}Lդ1*/Hx9ٶmn0VHc󰄫!|%=57JHsmVH5OhCF;4?/`e ݤ+a &aCz +pkFLJ}^80\h5-,y\nRy RrE §Ixp i]p-ٰt\um:IgzTVO*ֹf:66źjjǂh;',ıLL-;霣u"Hn51^m%eQMk&S,KQ3Rvpj6]%%-kFuWKFPD.|iQ-ndǵh\DAo46%UngɩLdz*cdsZųFڄ! Tʆ"wTLeh+G}ѹ8fWYu,UcZJbF|6JGlJ7u%ƳjUC},g05=2/<`b:@eQ"f.9vFT9B.ZD Bb1UGcF495ItJNQ`a#D`?5b&tTL4.-;C7GdR%|I琵Md&su|,q3+<;,35b(Tk.pCm:h25wC<EAh!aT9J;J4X` ?`H8 9.N` #!@U[6Tg^0h:EsP~?0|,< r z"m 9,|tƀ` !Pt"áHAp`{/4rE{r Iy@,~Z* 0h.FW`wTxlK(v􉨵p^ ^KYֱ[ױ.|`tMd؄RIW`ʰT4>ë749K4 ڏ:w:VDC}\屟gM]\R4ot/Ld*c`IQ֧GBڥyV$bRxiCY긨h%i$p=GAK%,]5!᠘HRXc0b7Gp->cWaF4g/i.wmhtX[7]PMp6MyDy =Zz@P"Et:,߂]n* K\uT>0#y Tzy4L1& UIYد'cHҡӏ+>ђ]%:_%cMsyjN$CHd$H0D*$k1`qrĿ,шJRćAFv$oFBZx[3CLz \-p f*ym{ډ綐!!32lRemi*i)*x ۖݎeM{%Q*<ķ)UGED1BSJN8# c*\Ưc&|%#&#MLh69kGEmI Qur2)VC,*mi†p8%iTOWгCT&(`֥U˽tf rѤG88U;-5J8';#*8x'ees<cBb]JAdgDJ"ECTJkQs+As22\'W+YSQcͶ}G!n9&}q,ȉߜԨRG;m2%;y\q-ؒrJ|^u Q5#)hA+]b{PUD1_U'GJ*5(F*|tmJ>O5dEUE])uVBD:2dӄIULop}s۶D31FyNL^b-윖}{j~evVhLI ķ)eD$'NTc&H ګUiJ}xjls2wB')fDDq1>QE UTk5&s$'xRI@&C Sl>2$ư |^"")QA˦ON{;pL<͈?&xZ%FH<~WFw6!<qYlI#^Z.UPpt$ħ(wH;(q}?Ӷ\HP69h@Nm=U6/<&lM=G; Mn.R4P?s! :l155kݘ#בŤʮ#` m;z/Z6U=4֯҂_LM ~:ṟg0'Og'?G^i4?[}D8Trh<O>qO[O`ix3,xLNxĂmTs:|[|ӂoXu ΂koen>[|>[mr4޲PՂ[͟^OԠ|zNF >5]|ʂ:$4|'Vfc7<|̂] pgG۔}.Gz HrikQkp͇kkZRjA @rh[pWXu}{(`xo .4+eLY&0g ;@Â˂0$8>-,Y`u영?YX\lmT>(lmYl-"n4CՠB mZ\dH- [04ؠ Y0lƝl 6(C:%߂iLC=J t?e- ?…,R.l ίS.:ί g{ws^8Z8y&εJkkaMG:j}V/_'6cU6X+ަmmA[-Ղ.&`18kDΌup:Zt Nt2|Xf,AK-,f , ,hD]a,Au [: "6 jƂj/TfUjb+z/F p FT endstream endobj 90 0 obj 6477 endobj 91 0 obj <> endobj 92 0 obj <> stream x]j0 ~ C02 9d6sOq vяOl.,_)3>8%d|U |W巳IB2oKƹ cl!߸dG!_!0YkJ_8cȠp9&]͌Pqȟ}Ku-d, F) W߈aYS[Kp.ݱOWIv%T%=Ui&o endstream endobj 93 0 obj <> endobj 94 0 obj <> stream xstd_5bv1*Iul6ӱmum۶}FQ֚gqFQ*1ٙ%lYX '5c[yFQ;k3_ Rhboo \MN|w u5 h@v|s;č櫹lV^>V>V fficGGЉRda[-==#G@'-E]v [[LNc33?@+$doo ,feņ@ ĖswBKgg{>f4'dd tfI)ak&fgO7N`w [m=-(#!,N6^t7dYm|N@9pvtxB`eL&@ -V0vvtYj`_w]`fgk6@¢v/FVnv#;__rxy>DBA SؚA*]M ۢ3*eH=N^{aˮ?Lmա9tQ'ۀ=+S M `q6;c 'I;Lljπd Ts+`d S+[_1Y dkPsncG 8:_ks@w)P0歩uɷW6j:0'z,{i]0h<ծ|&kUΦ܌ې2Zq~ܨ>r3b&nhiNjv`Z~EiȕXA'p m$p^wZ&DŻ Dw_=qs@GuvbDOjQj_O/1epVlsՠ3_Dlv|5iG9YY&ylsϗ1QhvXŦxS?]th emWST :?&q:c?  {l,b h&Q扉ĥSxEDY=5Iw >IܽB儏0gh~ E」r籧Cc>-#!_rzZUES0z=~q#˨vL/c8e:J}os|~RnbQi;硕TTװpcTX,T.웝}bf~C.GCk;;wjCEpM95mEn=~]L2lSZAG7D"5`>I ˎ۴"@ܑ:@x4ni6><m [%p<L=Uꪑ_!clPً Ԓ@t6E`k’}I&3cJD4e2uMأ㼅XhHw6ԷLHrrOtr MdǗ|4!Ofh̋^2t3ڌqKQ+aO8!z13ed @Uߢ׾/hr3BgSN6GLwUH%G-;L5aAapJycoFZqo 8ie0h>b{ ic⍾P{,^0:!lLXBζCM;Cs1cWLo<8WfP&Љ`/v%#z#D /}IXE-mLb.`RrS`e<0-N֘|GqM߳v\;NQBkt/⠐x'ty5]]n/5AkB^sb k&lHr=OمH@O!SgE\vJ).V1NJWv$~xK K?)qgU@ʜS;MSA1eǛb e @_lQ,qD$)p.rFm*ѕ6Y3Y*tj aFK̢\u`fuWW]l3 =G*P7*u_ ZHF8' {S cK2[-*J; K>ae":V%ǨB-kxv .RƥY7E45iޛ`9>qX 7 k<ҙw&5ٲcIXnXWγU08 <'$X2ށ z0ɋeWk[9.Z\&BlI* d) .RvҮ젍hQ߇KI`%&!HxwpŵrɞgMtG>}+TS -D/VlGk7:A_c!t=Epȷv"& yH4d-ml%'Cw@>kOBJHCKl^ p Zxp^#)Rvb=A-Rߨ/XI2{rVn[y<'{b2lÝCMt)Z+(2Q-V@L}xm`~7|ZYѨ >Y䝷- rx!8SY l ; $=c%'4{PjΨ1]&lB-n8)m76G7$r=I?}'`fj ,sRX6n: {n[|"+=uD\ugZ=9{x*(/5_}b&~nyr\t-L(tޏ'oMꉞǬhe0x,yI Wl?r8E#}˨qO̫Ͷoql ":vᦺ}'\ep{u%;U0^ 71߬2>]m:Q\.L5~GwO#ԳiRdF49Thd؝o51{XBFBPl骉)!5 arMPuA$ȢӟRsГm%>Y#ێaSNxYLyKmI*s0s`ߓsmqd&]پ)m͡oN 0jPqB%POSyNυf/[( !qKudn_O1֗~F^@KM󊐦5f"`/38`C$s„T Y.K'ءg!Twi ^`J)D% 4<[1Z1@`9G#NH vXWj?tMd PK peqZ`,mbȡ96иyvcCnI)ar\Aظ\Gqk=G,[3(hhݤ rXܢVX ά_ B-(=ؒuf_1WI,p~A3F@T-Di3Q۴RIt[rZF53W550r8!TGt| ?ld:)Y\Xya6bOJ'Q))7c܌/-Խ#λjZ^Pi)\mO5&[?4,NWt۰ppCǯ&C}o\|v(,HVUxeXj,鏘n ;D,j>x ZGeK_%|Iʫ~O-X]x@%Ugz&SÕ3BΝwÛSZ[`ÕgE?v rےp=7 3ba@h4ǎ{עÍZT{Wpy A]aK>q |^Q.fωHnbas֜ bGT{IZᐶ1F F Tg.HiNHgWO]Gsg]fŴ=qc&0͐Կlj5dKZQ' 39BE4x􏓲xI"SAKt߇hՇ`ٝ86[Ab5[\j^6 d1KS:-&{dYLuLǭ/6ɩV%*JȤ{܅9ȰQ_?rJw:*} U/ι>UX97\yNB%عlv!o/Ί9=),tF|HWVwrk$dŅӉ 2&AsID {\&u#q T˱{{ߧe !L#^[CkYr,GU YP?}ru12+nG e00['=ou [7|2:N (eS9CZr6atg†@ƲkN'l$@ؐ(DZƱCCp؀ssΓMr~Wi7 w_NJ@sqG~=ΤFہ 'Ff:? L30Q{X.:EuWb+/'B9Po!˯c6*LGCP(JJ&)0ʚ=9P-BJK2Rrhqݗp RY ]4k@d +ne ktK|,Mm@DtPR#_0~aʸ Px1Οcؕ%1=+,G#^̹MFzsw*\oQL11;&} rx"(@ʳeD =7䘠tv_Rz4f,Xa->xix>56AΗ%tm$U֏acَm"kJT3շ k?\.k"Rd̩v"˖(v4՛9;+Lv6 LOe(ܱDz>B'Vj-O(o wܚ Fȿ:&%̎RCxi{',QB Ͱ7zjyA_oH~C庞OHڬ~eURxCj|~;Ӂr05JXiICY@}C{epZ+K}z`]0#FMyE~z,x3O69}`>#_ޣmB51"]?jd*j Rj' oia{]@aCQoWP1Im1KtԾ [Rzu(R,:8i.HdHĵE=s{Ob> nPw澂ֽv؂1/k7g%2XZN1r% "B,b)9GyOG 'ʝQBcQ_8mG' o8 vF1:K4zUMqB;y )ǽf-4BQb¹;˭)hnsx+4<~7UC*:UwxŒc+H?]z񜞾|տb_9]hТp\Ɛ@!gFxfI}W# $KNu̡3/2JIҹ̚gz V|>hm[u[ IE%?7N1. Zae;AbTJBXm^??gC `-:)^xóDtgzdV뵠(P H$.l "%N"=uy#ܮ iPٚJ?ܪ$UP;\|$G|_3F4+zr'jYu$rG=?2UhF_~.x 0A5I1P͘Ec:Ǟ}TL0i_n5Uڤ܆k.>O/2U=N gZ%}?^Ʊ <7~DZlC'SJKѯz p^]/%C`b`akQ-6X|Qu4)M QH]1:@/l6,vI%r{%X)-*pB75 :Bl yOc]-hkv_BK|m89Ӿjuzj8fa BR :8>ی:H7jw] !p$)lk抅Lƒ2uUv^^*gTMKz b*z!&f G|+J?`W.V(%a#^C6ѳ 1q!5\mL_fVBW `/P6\ S@g-pnd;#"z!hqlCRG)?۶M%εakӐTw /V}D7dk}0TNcюbe^pC/,i)FCQhW:.?M܂/B1ll9[YK`]|ȲMH(e 7Rt%;acy9&|#d6pKb0+: @APG$b,Q7u=2l?$a>^\Vz*L+KD̶x,Hq.;ޒѲ+Egg\b|,pԠ/SܐdN0<+V |ˡ ? L?MNllQIK4Uhj%0wj<8jc sVoHMg,%LU E-]#ٯqdxMCZL=9c.xuNHpdzgBə@cR1Jj6cX/O|z>j,n%@skkxghRC-RatʗLaE{k!=/|8^2Y oQ\2&TNRB] A0Ʋ*^dgzf# zO N@ 0IP0_[YLt+(g$ | EfȨt(*GF"'RJ\;K#wBY8ㅔѼxW8Bq5XSQ9@SDөAG5(wRK%`V˓~/*4ҵOkո\=`PYw\:-PE7nr[K&#t"u`e~6="F HXE9+Q7q&iqa@kv"8Vq)VDrONbq7{e郪OV/Uf/vߣ獱۰@9m΢',<)4S΄TBzaLy ה+Y! : |p\9ߍ|G66TԅY21;=\M'Ue8; <[{\TE[$ 5|OG 4cŋ_ Ϟ e+^~bx6$PE oG*g~Lq=McШG~Q}A#[-ٷ)o^8мMHBby]TLV1(}Y]Z鞫PR)G/7LXT01 !OY|\a Mʼn2}/+E/k}hDc@/uѽF7uJܢHrAqƋj-k #7BE٨-Q B3??GazlKsEU]r@P3l9YcMThӶnÑ(zЁJRo,>F8pr|\ vGťT+? r9X Љl/ : K ";n?&hqzUd@b|anR kD4f * 7~cW #ޏŐO_5bQX :3Bř5@lmm\?.*N ?T[//QsJh`|;_XDe;ߪfka3rU؟ƵfS5W9cX8DhXH6|v?c'XGz2֫ -3m93]NJxĔ5߻Feis8sPֿJe<0P2 @ֲ{_vYK>k$".66Q@OQC$TuC. ـ\C/%E q3[APܧj! H7nu'4 M8|vRk6XsU1+'F˨T'_ u4 < ZG'IJJEA/R>Ap"]{龳B˿c` F#א 0ĥy%c xc eDcko)]z ĵ":Ci0,ّ9DuݮDc2B,cQ/Oݨl7Y8^_xڰn&8/鴸FLzQ 9-߿hx!/~Jl$㏟uwl E(P'{Dis9*}q)ҮOM=.YNqeC\#{_';Z.fizoɄN T% Vu5|z(&0JZJ}mpD}&O:gv,j?ۥ<6stx! w.n?)3NvR+kL*/j c֡miȂ}(qz*u ]FύVsN;g)Nd뼯w~JkImMoowY.x%}U&owC]i>{20l"H/M,WJ2ɭ/oQKtzcNw]ָNj0l|2׀SjzǠC [v+,dRr;U.>tjZ%<޵^,zv9ϜU Ys5/ת|\oo%'>4G3~,jZ5t|mFx1--$Opp=5s/SbO Fv._YLk՗:g-$klz_=yr, 8۸vٔ+B1"o/#sD^A7򋕥v#PTBK%{%7'0,zJ}!'G1_s!d֯ӨThZ֦vM`=8IV:elJ9q^ JZALUvf-'mJh| Z2\Iv}实x 5S麚 zocyh;eֳ`<¬(F`v?tNSMsWl_Zl~2Q֨ V2+?>nڳ43h_  ʀwnնm0nf{H%!L'h^֚҅7ZE}T1Y r& juƒU,O:^0w6D>` 3P.PԐկ^lG]%v : a]=޷N} 畕G]봱f_1KR$L2NhxM _Y~b ⍥l܎Si I=;!r`(ƖW-\8mUlʻxÜTY""ȥ^F##_XE:tw$3oP+wzI{Q,^~P94 wMyhq~2 يq $zTwso@ >H囟e2N I# [ w33)K1l_3gOI鵀.1Fdz J|^`*3B51eNE]fVr:-GjK=l黜6|$[2tXB늵H!~bhGP?oPVb/5DI 2˸q^DGS5vFu%dBM-:PR;iMj(xiwK|M V5fJ-D?Di}@͝T'},<[} W:g#_.úSUڵ = oz*jì,hū^-/Xdp)@`u#_upKˀ^fjlǣF̟5#wCI-3:fZctm>7qzbZkykޡgcA>_6 ܠȱN#/DG /IvyaDhtϧlcS8 |w׿/T.u3r>nʧ#Zڿ]1nhwτMΨZTMhs>oHZdRIm.eT۬F0Ws/ݒ(&C.|2$_k_ ^15{{iRºC) {svɝr-0 YF 7g9Ҋp5a#%rs`⋭H6a~r1C]}H0@8[]U>e3YUujܬvneTʀ9#fp;Zh;*К75|t˵}"5/|Ŝ`TAΚ\TܤDy4WJ;_.Q7Z׍bwuiՎ ЋDIU5 ٙoQp+| t)C&W?VX4%MdeѕH, rP?[)" ;4)Z ĸ>F΢igpX' +=K N͐(;y-We }O鹪KL(Єk:#j/UsNz߸H^ҨiEvcK!M'.*vrk0?Z1I!(%ݡZu*57$& {"b6eIzDtM(kI]CLMoٟ^=]V,!Q]E =C⮈{sG$&ήʤ7U,vRpoɗ2y<2 zM]i)$Nդ6Zm4mˢ|Jal2 ec= įcP5j(̵Zzm_/u,yE8翈eM< ձt\tGř" Bą@sJ. e G+ @]۹|+9 /+5TWq·S2ǁ9x>`(A_ͩV}*{Rb ;o]ռH~kn>Ǐa层WߡRr`\V!Gؕ1lÁ8R  && lm{E\aCBȋV:TvOܟU6@q~vߦOvvc>'y&ЦJ袴u]LH#c%%+ˉ4۾cWR-+P/MUQ]3<yN=]n]ȗ5 @-} |~-_SИeSR !}u"+2אsHהGf\Eq ӟ C&ޤ$A8Îe6J&'-#Q(99<'x!E+1K%,q N0?DsJƕ1bv%ʓ\͝s2DҴF15>ǑtLG 3bOϠJM+T|{z1e5,'F#cQQ@%'~3{ QןHPQ`#{jb**Ed{\d;U+/|s匵>]t)yց$|EρMŊ H9=DO*^(LW9h%LQxZީ(lalgs0uoec60ˇA1.)QVr'+qYG7` ywL}zPNMoӚ /-rS֫uۦSAg~_]8na%Iv4jT..isE%mՖnr>*`r4/L <:eE}$RA^an?jVGK 4֌ MLY-g#:P{Ǻ RU+z7?=#,獡~?YQ)hƦ3A9HDV6#Ig6̍ۊ|C:8rvAQry+jVwmm:PXC S.^sWpD/ӏѰڽF-:u%lw jC٤K;;{oie$[D6-R^ar[(qX (A%Ԅ=y|=]#F&],W\XdswR0VfX]f4(y7:BTg_j tp9} Ҫ58恥!)bZdJ^e mܡ%Bsi$i1ƩrvtL)%l u׊Od|XYPW!C 6ZJA"G^ůRURmn-HcdّE$4"(u~À/I-Sa )z#O`XӷJư ՂeGYף~rԴD]P)Vv5t._և\nѺT2M9T[GM4YZ qqUEA5ezBZ ZYXcgwh1oWw]A8BC2裟opŘ,ԍ YGS}1/ݍA7ոH)HƯdq]đ7~ a482$g \yEcyal[b9t>Oq>1Y3zv)]56 ,q(b#*`^=]mѩ|z CM5 B$ ݲ4[2Efcwt+,4at1r4okuOӳIxFc}[4Ef\8O˽ ÈidînuLP4S4^uCAC=^ Q?0uΎK\%X }p_UC~S/ыB%A`疽wz+bF""6M;ޞ8wGhej&{6`n]ڴ?KIpPw<$ L MBVU/"O2{pT1n[Î5) PN2+5#()P;3X8LeHoBKgtA P%d,ɟh+^i3i9âE<𨜿#z cBf%Ts =)P+%LM9`^:3gLԽty"{6o["RW'DG7fT닎}'c7nAr΋qhcVuo=w.=Ӈ*5m</z$#H1p)"$d𲷿wȱb'_"}G,⧧-ZDDm:6:D]n -/~iнq5 JH-+R:?7dF8jn؉ޭtAX-8N-Rwy{rF+rܜ,yK6Q+yB/8ւC扂@ 0=b |e߯fwy~ sd|ZG,ovZD6ez(gHf%r!?}M&*KsLQ3KntXBJa'?)Nts1|Fo]dv0F;>9af51vERk3u//<0^*E Zs& : 3 n( W#=3PDJC% 4޺u{N$773phezd1W?&bfT:Xײ&!VLy2kCg5Jz{ǗF՝Q c||{`Ncᖋrh ϻ02ЦŻ w[ޟ譟d8XZ[>Uӎh= yʂ@ӧ{ufq_Ľq?j2yS%0Hb %΄f?,| mB]$LZ5\ѩ{ްZVBP$j$͈׃ʢEUy⊸PJezv7گhH~C׽ך=Vn.pBlʯ@ #" ȡL3UwWtr ĊTg &Fi FP7!(GQJهzC_UY7rhě}ԕc\+nF2G!,c g|("Y1q^PIA=d KN͊qNITy8< X縆vbsCL)w1fMV$,*GLwgJ'!#:ϑPqWU .XqGx]Im 2"(5ȡ^ZzD,I؁ǝ*b7^No ӱI[.]gQr}T (IalulOpT, i#P6*3)S:{ Y]lCB*#UVP25^,˫go!^k>qR ۦ!)xYȲ=÷-rs( -4W*V'}Xa,?Y teo cm";!́aþͼM8T?p 5f<N"7/4M= _؆+oR>è3X ,JDA-)[1"+X<\ZlFKVsr";珆8)}({"ȇlM1M޵!Q  ,~h3v%=<ޑ-iQwM$oL5Kx$w}c6f.hAO=Y:3{&Rq9Q[ A"cn^u-8hø6| cq! (WY%RB;=OW>؀4MMV_ZEvE`b`N2;̘$? 쬡~0{^NJd"uʵLP fRïB)#b&k c ƅS$bYf~$1q#97̩.N!}"%q#e`iħLdQl PM}]k n,Lcl3 K rAb|/9Z}7P[\"OHtGZ,,t~ӬLAjRL,Ǿ&1w^Aѝ?*\hݶz\um5P2ſ~t7a{CD hEbǎ"ؿI 9uE>Os'f焥59,k!S[GC18ۥS2eK9E>} H  OF+&e*JHy3~`?3X#T;qntX]dA! B./Egّ/F]t2(N"%&Qc$нY79vEaahN걥Y vtИtXm;(l*wPQTdozu,ψlPHLxm3Lyd<.6~SEEwnqI֚ l3Wx]sѓae5[ٌP-?ωà\|< ^N:-n;?8]#\c]41KǝHw<2㺯_gv%E}Vg~dqh[CL&*napJrz뱦>Vsi}λM3iAb';4s%S 9^=-s l]lt;x':lY,'nE}_HW60`೹GPF'|C|.Oeƚ;Uч1ewjH_;<Wl4#hcLwD4لĸ(YNǕ3Y jE"Ifg׳Aui|HUaJ4]!>@BFw &&Yg KOs)0 W67#QL7xF]2Oq5"nvЛ'f!A,IV`xǡ)^ Gw`00qE;̀EehdpU$YH w RDu+W#brv𖯩퍦CiOzkҎ_P Ïɥ7b!C:+vm|=n.]QV y nkNY/Qy<&o%x]D"r7|rәo8^g긼gе̓dBiQ 08}uĞ?1d#N@-\핾:L[=6{ۥ㱶KHv ˴O +?;i[vڛTb4dcGKZrl #< 'CetĚ*rT&+=lrSNK6E!LYݘbz-Ma˾  >at(O.4/ΙT[LEx@X5\jܼ.n"A84T41ZELL/X?jb S׉a.XT\`}Ct-%`'xEvN3pGx4ػʑh֬і?CJO> +2.1c7kJiLϴ=ƎJݶp} aJqahNkT''^-Z26 N&CCL>夁U:HOl'Ԏ34ó|@;Kݛ AĜɑx%$q]ufd?d5aV[y* nK"B6j^9n QC#vǑI| o .x; 0OhW۳ 9[:ޤ]񒌻-Ufÿd</Q8M3F+tրHa9G(y;xEێ@O,` ΋plY0)3IܿKg=70zs KlHm7ښPB2 1:B-'R%`I=Q6fM^,XU^OUQ0 rz @^vNxU?x0&fHs~IQN)'˙X?ğBRq EeIŵwL ~u2= UZQ=t7 BKbgmNӥ@D3>VlEt^y -s2a>K#'ayjhJhb\] ?aY tDm>TM8o`.ahٮ2?;t>uhF|}=s"rOަ'MMfnKYK,,3]| gF/)| nu2x("K?V e(S_ § vEӮ;8{Biqz}=۹\0l0Lv[}vrAt)*=|]>Ԫo@6P|-KB1;gOT,Wsά"z;a2ȕFAOо\qViTSm(Ω -D/?IZV$c|TsS bJB=N(BXl=ݤ0 ZNuSD6M> qL0w/V>ns@634@?lp W[jJ,15l<']֚#prwL.a4R3.aQ)j5O\PT,{i%nOLVjtZ>g%1lvB#-+cwV;xq!wWpޚo9 j?yAMQ8h }VU^CaV3cKk}Rǡ-?jpc6[Z?PtOD"?U&i*.;8[,Q|ȝ\Ef 8 %YdTG} k'0!}-22KGОleǏq2響Bcpw/Ƴ yi}gv5u :_ۭcRIڕw;y;Kcge/x'v9K'IŶ,7kb/H%оP.2zݠM.`P%OρC`rP`+j8} \ДJW`2@e iQ=JY -MeTT XɰŃ"p ;/פ?u,xOKL"sE/Yx$+Fp z<8H9˺U(.; Dd&0:k{[1GRZ\Fk?@ :J u8nlS#lјu-'~ڇSv(OyAST/*sj?PzH'rfє[3+OO!pഺP|ޭ3{B$Nb!RQM;mO1! 4sn^WT'kR\vjW5P[BW+ƊP(vYhlM^\օ9yͻo<X1vDivIް8.d13P,&+j;'Ur3eFu +.Fn-BB|&sEL^?Hj V46> |:9Wq0Q bx߂;㳉Q@EP-~ 'Σz|-iwLuYZ6?#!8N][ "z x_PH.4ZDwN鋡YXˏ/c j-\񔀘R/M> |&#$'|iD@c/VT%-j1{<.\XIP"D0(MxBVgHrja( pZh`#wsajPaCĔڿXqcQK& >I5% qdL[V\s͚—)Gf$=Bkޘ]4AsT&>ϳbzP1P!9n\p [No)\Dq pTn76LiIAQzvĔi8D[oنj ~P $G'kWleEc5LWDZVѽ YwU N3+YK[6_`E,֑I?+Õ7R-Q$AMxqI~[d#= d4f-#j.5e<_ՀZEJn@aqWǸ!MBeG'W:2Qm,+W}BjZ2C2u)d|'"VPsmABkLy1f.'*c ,;N+/ \Ng`A U~pɭ/m'ԅR@@AU"?V-a̅{MFdRLk7_#y<-*,M1{sA,$ek}Ǖ}ۦ|v`t~:~v^Q]mmc\"Ũ>,^KUY("2|0Ҵ:*FEКF4Fm[sO;n7[^O$T|Z0w34ߘxnQtsG b!{ɿv{1rkI͠5i,mYJubMHq2,)F5 o~|":: = (ܱiL5;%ru jť^~"5IN^2'X3f^ ,Ѱ)53 E~U,-Mп^jFpJ$"w{"d'$" =K9ѫ9*vG)}#7Q 6vTv-DxN9+BWqc_h/A#G2ԡe ?G5JZ~񽞪s^H 4e^ͬ!H42LGBxaA=]H=e87zXU.֫?y >mdG A& Y.O0y`qŗK1b.68p|EZ6yZv&^e.70vk ƪloKLweoҠMӘ݊&3ZރV5c.sv*G1φRᚣ Eτ2&>1 Z+r{&boV5pk_+j*oghpꓭŊ rH`1] 9oP~dYp(B61[C [ɧiZZDǐQhÚEA10C8Dk{Ka% S|ĿB wa;W!ZT:9ժnI_/:-?m;S 1]e/f/#Z]ȍ&qbTV- *y9tN0@,w"%A/ӕ)r't&dWd-u8!EҿPcлg ݋J931c I5+,zޙq+d|yMp{ƹ=^sUF ߛRȺVX ֢Jtw,EVk]E4pOdã@ZB66%G[ a?֕ë6M+4 aQk;*Acj'o҄ϟg؜K:HSlSyZH7{ TEu 8"+BԠʯŅ&#ݕpnFkTjK5a.FJZ);,un(< .1x5 P20a~k~;e+^oHYoy eQts]YHz.FTCk8Q77R<ٱM@lha5eٿqr(ǿg_v~ճKb:DjˀS%Y!ǻǚ ~4Nz!j@^F;;lg7TH'PA.Ye7ϛbD͐ ۜ0(eߧD!lغ UcٳR8> h)q۪3"$CkmDv<^4K=ݠZzpK"/\>0㔊#;L }+>B3ag;S.ɿg;^DWOTutRLgvPHU]oޤ݌H[7qS (GA2\S 0$cɩTRFoGE4lr 3Q b+1yecQ%=ZT\prpm% qE V-TR niIs&bdÛxw2<*c۬.AG⹒=;ꇐub2b|j6`>.2|TovKo(G۩73vWsۂT5U ƥZ']X KJ|Z[J> d<1y`d':.*َ JX?Y̻f(xJΗ|t0D-֔$~׌ƞĴixzbRS 8-=P"c&p+2V "L֊{?H%׹~L(yl%[*TLC#fs" :2w4p"w!vL ї'*,F- -)Xn%X \,(l&kdܟz w@J z#t"E2P0wHi&ps_ªѬz4eOX?F#So& TJ 9_mr/inaVvӐYX;7"ce5k&1/2DK=4(S&}_@?8yb'$)׃ _na 韈q*Z*p$M&÷>hT_3'1:mf?E61>w\G x{O?+AB%13-㯶%TQkC͎p4{> W澼x=D a]X:\T6w`X>=ޅ\lQ{J5T*K9Xkǣd}WF9'Jv啕KimSrQQe R ߈Ytdq!([a+d>P;KMbfAp#R2ĹcRѸ65&7^ p|y ب0+TQeU_΍b ŅehP9HޡXWlp#p-7 \~w!@"3* s_p\LY^Ru @Ki` .lzʲMg#KOtVM ]*,sኝ?V$:TGOϒ҂?oHk4>Uj🧴9QngDd_ljA55sO=m5Gԭ>] 2On iUvK%Fyjo绲-u#<ݑNTʛ6E0)X)Y"1aWۤl裂<_d7,¼Y rrCH29dnzgV.fdXJqn{WgOeCeˑC?Ɯ! Z4b:[҃4a9 $BXÚJcyVV_j#Jܽ eD,k2BK9uWm`IF#G rj:z qBx0? .Yk#6'sAG_ijÝ㡮i1|IU+rT\5 3̒+W笑xΡJr-P8Y^;6̢ G[2E{hJf'QkLвW\RϽ;cQQ4קġ @|cp18ԟ .vAdZoAi) J-^=zuS9! XS,򷿎tق855 di0)Eao$uNaXGjxWexp=f jkl +`_(`>En'5l8_oXv_o%}-\,QbwB /l3 Mp$;@rcd+|KIX~H ug}WS"ܬ/XXp`6)VW5ė 5s$y_p'pc~\{ڃCG"=eLK+5V@yF >x2sdԅshGY6Hˁ>m͢zҶRƑt pjЬ ك[Pa5!0\0eaҁ?5P7zsF?R%})85E.Q*'3ʊk}.`?_p 73-%PcB2\XvGPj̟cyz&<ECP< wQ+T+j^G[JL3#36,MPGztLj1򯐜wcze(6YH`Ed&-#vUJiǁŢx!.֌r1RܔXhsQмӥ_іٯaZ& *z3"9|+!|/Q||$Mr_^j.":Y~o<ߕk'&y0&2)@b-i)Ѭ L%M.vR`A0} l43).g+򲢈r[[4gy#pyP$9Jӓ# }d` )kǻxee-Ry f.¢pA&\U+{KVs2jBa_ o[ kAT"Y+r5,s.q./lZ ) h^`_)*=fB52^mqwBiɜe}8 |8ڳX>Hr|i;Wf E,Ό@1UpjZA%""R6;{fe,OD?­Db0}+{dyVa4gۯp43V-ٰF*A}+@%LDVcN?ƿ9+u 5{|;%$mnQg0?0mw^3Rt_iί~ݘu֯h;O^@(H%әhJP8#{LZ>uk99CXr#T.FAs^0'H&n8'S<3/ǖ;XS3z(9܋]nZ>,#~Kz'< '¿h,[ԑ$ ;ZS/Hkӄ"C mGD{6Heh/nb& 鎤d_QqxVm]4VpAYd+RRZ.82<Ց&-(̒/`;"l9g$}v].+fU/NCdnG!{`*2Rju`ۨjݶH3Ն|l& xLh˂;29p3fOwuO73i0h5Ј~5AվhD퉮rH|D!C7gxu4JavԶf82iKQ(DG/ K&J|'Vm&锰V5$2>Hڶ_Ω{!e")h <_-CH# E["gUʭ\BfAs"Ew9f^P^$=;p PG蟀?5L&H{- ڥ1q^Nh84˱korYq30&%@~6^>5?ڋLBĂROd0+rcȥFU*c;TluMfHU334Cgi}Dh+ JhEbN;O8@ -*o˩-rCIgcx:3)9@IUA;~vY'ݡ ^l&XB;2iy<HsZ#Mx_b0ϫ4A=܅kg$<gv/&YrYw - w?0*앚]4 ;Eq#?Nύ͘ ICs ؏j ƨ 'Vh>ǰqPҡxt"`$Jά?ƹʱT[?+íauuiy+e Y/rxjڏ?GN|-Gc9p49ѴנNzٔ&䒄/9m 5i~Kykd<jV!PI?EyRpI;}o|ԕRn$¿=Zcڪڹ=e֒iczZj6pu?,v1ҸS2%Ɠeh׌剬qRrmZbzms'A'炾̑3H5U8__8pcFʼj3Z̅uS̖DogBzx{^z*p宂GNJ堝1i^Y#(Ugr2*,Jw3@P#“~q;͚JniAg+@8w(2+Vԫ xGrWJ*Q! L/!+KF #iM/25'[_i9d['忑gS}Px&- }f00-s3;,A=r i'R T7%M Bmc˥uOWyC6/fAtP=[=(Q=_r9I֬.kh$c%,fΈb e{RqU{(x举Sh~ڂ4v"i}<['$ZbSJR֢-\Wϭ EGdK$]fƜAoW6"j ɋV2}8җ<6{z[h6y^8h*I&N$x#mo2[ !SrN ۯ"yQ{4|<>[:"x"jxe: {Jග#l?r6CHNSk>_k<<~3iJRE vuɆ\|ꏜ9YD^CM>oc ?j6gb<@7]J{8;UnJN:}gmߥbpL%ɟićW8k1pvq>s SE:kێzm^TFU>43 FRRdDݾ*@RW_t=>fpWiBGa6oOK|:Im*_EԩApސȎ,ƫ)!PǗqmBt[@3E]j]#[2T3'$4Zπ oMK}2rTϕ<\1~x]Pw?įigEdUf d | ; 1veE?9Y^,G,d,1"`K۔,n,-Z" Eߒ " /I<#:WU<9kbKJ~X/ G`TC26Ct$'9k3;*d6ĻU)ǍVJTdK|(w}A5T`VU ]P;Kxpf&i~&D"=k*P&S܊LLX,eBFlgf8g7b)ТEd`/{X 9'#^SZ^'52nM@Ґaz4*ڲܷՓSqL gax}<gmf x k!oP DnM|v%BE:ZI3j>>&`7F͟Y椴. Xc~Zds#J:z&B11ՈQ/C0!F!|_'s H(E9=8G@Q0Ͱ=χ`:+7k|T>RL58-׷M>G)s!eW݊\ ;7M^ m[ ބ6:/ o.SЗ`{RwKP= Mu*>ARI3e:KaK,Z؆mʺp&_=I=@d¡k{gy*o>eQHc\[>/u)]ל.SZ*<ʿ"R"C9 CJŦ)'D8f:EsKx`T%O-V|9eF2Q"@y@F6!,IДNn86 auH=_3?v'P`L]"cE=Xw:vJe~kyk:u Ox/%g̏"gQFљ Fv';*VRG C})9"q^=翿`4O(;O_{ R3FAdI]\֝Ծ7t-S|g%" g&N%@P| SWe>ДTNQBcQ"me WD` #$!0Eb*gu̢pT8n.ݑ. PQ%LzuqpMӫ41 n$'o-h)9g,_`A(oV,>"V5pζ|pwqdϣME˱bbc#8aoЬ'OԏxN.SI,>xx͖oXJU[1GBW.O2f_ս25(Z?5N7Z!CQJW[R֘2ƾ]_ݥ=p+`1EKm9#[#п?Xh779P,V(xbLz3e}[H۰\~}L(|ETDrfBOnbTOEnS'ƨp+ iAeJb66Bi^W2Ob7aRׁ1hp?e FX^tZJNPzc@΅R^#ƀɎ@Y}{˼-Mb]l6ZCZ˿ ݵtFy x]L44㴓fYɉѢ<(ϻCĨ;R׆* V|q֘2۷Hn0+lzS:ćvFl\cح.z_c}BNQɎ6h@JxJbۄ%d`G QlI* V oS\g6 \:/,w0k:ܨc2B[r]Ryk)Wc99|4gvKEvzzuv,rq?|{}qjs'vH Q3r wkx1! hթ r1ŊV<٤`]ޛٓ@7Ɯؓrx1qBnR WB!y%^}VM[}06@; :4)F˪?`%*R;AE==jŢ\_튤 j ER J^#O7ŕM묡xέ&# G=#>&Az:5_tv2a!:g`Bwr)!Udm۔V"6wm),}p?z3R"Iz|B2F^:y{LI2)c9щ9E ϕڃ>m,N{2a2iKqρHa x*~Eɶ䜹 ArVt`L*|.\̱Mc}_SrBWoj*\!5نYLYzse~vp'z2MQη4hі}gb:JLԐmMd1l}%(tU_ddm?jڂ5hZDf%w\]Y-2Eǂs#1jq0j-AV-d~ϨRg=)' 5ߒ6IhHsP=J`NUH۟.]*re (EssH =#~Z@M iѼW"BjD B <(9$*3{>86B&')_}C07QI^NۼpZ}\NFZb K42Xro;A7+s >(ċ*cQVu%Oq C^f GV_[{YıNjxƫh߾8':Ud<ݑs =/ 1Sa!(τE%S%Og9C%Q&XB4$mg9q*y]KpЃ _v Zp{*{ʺ̵{u8AUdrp۩v_fƍ섵+Z"Tw3_IӦoEx}AYd;\{06H-Qr0ϯ\^O|z7A3g=:ȣB|X?rR?m-v3T?fD;}\G`wԷy{LuL'2,edNdwBG-Q5m hܱ&'baBiƛ&A%ؖlXacb,lӜ୅sڰ/DeO*UqƷVb(+^Kyr5]pB\ ۆY1r̄iaUiG3)vh# /7xhMpe"1G4a6 P|(ϓX3\ؑ~p<5fL(?Ye="mzp[RBQe Dgŭ֡dSgv=&3Q.N)usO/|:WS+# miUk'o#yl ܈oT1ί%\ / R~q|&rIQs]%7mn@7&}o`#_N71T8 j W$Ȁ_ x>dZ]B4;hAWVOq4$ʚ3,7y3NKe\߯W. l O!ǧrz& 0Zcy@}KqBy0rJr?4cgmQt>\{B7V 9v eK~LH-Z~g1iS%ٝ$](<-gbVpZQx C!0~Cm9־i<(c ۟]Dm` 2 OG xK@>⡥';qD|w$Jf% h?THaGE3ʴ/)Ub{f%PgwޞFQ8ykƸ/?,^$zP@=Ҽ}2j[\(h"+= ఞ7T'J wD=Ǟ uH2't4|-*׍r ۳=,QO:ZaAH'KZ3pUcdaӳ$2 `h=a!?iM;;i5U1YbbQ3SqJVU_tFh"WeGK?19Rw6x(9&e$N{5XgS8y8k뛌:NEfVڞX0@SFG(er@s#TQOm>ڛb2SDvnD, KM9A $-FNMWgqM? 0ȳ֞۔ ӝZazJlW|w]t|^6oxig1 U|OZ7@؛4 P:3c EIV668@, J_H4#ևY`Гذdm-JUM isE9UaXL}×@q?#gv؜YYIfU>nt5ui}&/˜r:fNIf2 "̣'T)/J4gOZ8,|݌o S@*$BWrU<*К(XJzҨ -U粟[6,̓!0lљCmkߓ℮0>0JDP7Àfjw KSw99HJ]p$hkg`.v׬ yO/ V-Ԅ0 I?d<>N#;ޢ& V^W`q$pK?c iD0zHp00ǵ\';͋zQW#|!t&E}4I/0:ې}M.w*PۘQqz/`3&$WG-Mָ=m*HVlZH{PW0 ~f3aYR)ij~ZdtM{LJ/ȹcfK{9Hm@3i~:G /v>fHbXUФjQ>ot|9kF8.]e m|[&< EV^!19 Nvt`Ks9C:3ulcNl@u)³[(fb Cc_bEG*鱿Uva@jNwnB<_z'F#.M_<*RaN[0W?2ꦢ]oc𴢼K4&򸊫m$j75a\%{Xَ8)ք^=5 WcC2EVmg[02k-F=!Ơxy 4ќkҖ+'޾i$XњY/~WȎ.ٌKAOfzڰ3,N[&`5*Ef?1L`8=biwO«4 /v)T&\m~S(x;'>`qTȝZcҨE1M׹c1גdkķFlX\bT@*·6=Bȫ"U\Zx%Qװ0~a Aɒ ~|g%V0l89-$q&@Ncatfm^۶*m,h<4-{$]XM~jYJ~ 2[.j1@MsŬ*Fh¾)lvc0>q}.QA[`#ȴ0u&<- }xwPc8UUUǍ<&dJq|k3HA`x-W/blT(4כ/1!,E#$WB+^At~G.%[z{;nGHB$$WzO^̴&\( q@俗&'1a͒у.T]=cT@x_sg'6 5R-wYJ<1CT/ ^s͜X!%v7f쎫 K*}EZ4 vP^Д'"$hG(bwv_vH1:!mRxH^)7ju$!Gc)р-H'D xJ Mwү`/ ŕ<2289"GZ7vMrqptw1/_?/_wAM9!MkrZIn]?BP5f{>f|;y ܁:"jNҞr>޿K^d_Lݎsl|B2Rs(c)y >H ^Ug^,cjtm]VeIbR#vQn:=r<ֈ6tM3›^(0# ޕe&TiAI겏a|Q>P~Lj+6d{$R ^r,?-=b[U-g[5-,vA<4u*7/CbccH U6{ Ɛ&.TTXN,bנ&Q B1֖Ne STĥf;&5[Uz{`c>57΍)fb ,ua?C؍ƎȫdXhCF~TR8: Ao`W%.axU¸J-O6yi1\VN+M5R/`]_LS+ֹ^E:ssIf4$*cܱ/PB5E_Ľa<{У {'Y~Mp|>(x-Nk 5-Ԏ<5i S R W;Y8݅v9©MoV%SJTS E8e\j!!}ND~2`1^J;I.Vǒ)Y'6YӨ hHqȎa_ BjzZ-Ais,/4u{.ExD!$3L[D=)5)0v=dgNhևbO@Z,Ay8פf% [\\x;PŒwae:p7X HVjS7Z}!fDuT ,f7%Ol-n}!8,ܰ\ʴ< Xs^`֥'׮P2 /kj w/B7n6K5ɃgR:~RJ_Z迁N-{*C~-_ Dp"x@|iTUS=Ht`V^}'P+x^ZMM*V0 vw=:\)/%əmǠ߽Ӯqa#i]p y3Z1 vpb`Ma(H;'2[}ܿx7ˣ.+"L:r=k]K +Qo:)QmSѵ `+fe 1okPODQ,U I#. Haq+OT-0 VǕh:a>QFN_NVdW;7fGq 4JxH>}~$N_EɠD>.ы]␊Ɛy`.`6^ tf! @$rXRCy(g{֤ҹV[g[܁>YqDq<)Sڑ&4 <.S/EGΦ jeAWAUZe)nKE M捝<XT72Ji.:B?B_jñ\drb"3:(Li7 /'Py(a(8}~ý*l_FO9\)3"y&okg(@(TCސ~=y[?sgz64SfqLKO+CI}Le4ΦX9.F"v0hl?`?/݀J\NF tP$EIo{ÏG) }}F\*6˩Uvt<7F ï8`D7KP(UR20LAogB컛۰EW/zr0?xH#-?pI0 ^➮MiUsh'rR!M]Z OoPÕ0--[ޜ~ų_g+[T{0V˷}􆻘G Ee7 JFhFtܖ!Q/#jܰ >>\PLace}s15pa-KL呛э]Ôf Emǡ%ny*t0{Iݥ~nlIMJ+p).zġ#+Len`pςk&(-v^*ZdKf.Q@1ZjLůKyK46+vIqQVåL?$&-Pz㨂Ě'{(Z)"4Oc tWr/GL AGBXj?^ Q(=l{+ lėmq#Vf}txG8G_r0XoKl4т\lfpgPFעGeCV{ Е(%g$՘$8Hz{m!Y/rO$jE{tlS"%&]TFIxe zl~]00F2遵44u H< QsOI&Ql""nFN @e8HrT#F$+D-"l!{GkPz8[iɨ)-|BӼ.[)o˶9,?bTΟ GŁgiE;u@fP6CbbsQduWJ]6hWTȱGs\!츫q|/t(AĨ@pU!A" -zƠEja yU +P~Gt`嚔v_ѩPjW"X=Qbvu"h]yS俙fTGMoKxc.q-2huBf)}>mW>] xyiّ~( ya7g E&D]HMmo #|dVO*rlfKvEg<1Ň =əˇI%k6@2Wuܢ~GUG\po6gh΄8 ,$V+/0nM${EaxfPPwqJp}JpzЎDOɖ*@I )> ጞ"h}6v~4kl\Z69َ8V*H@סm4\y?ɅBF#V_2A%#Ђ^@ %`e_{Ѩsx#$.%TW@?YЄwԉ<-·"J@ŚSF9#K~صg =$ul4m7BMOPFx'cHN Gu*O80 {AΐOKܾz|5P t6MaDGnjDxZ0̐Azk@P.]F޼Dapf0]##$!R׫@/jbiHmT r. z<8\9X)AU~jpTÑApvD ;g!.yDk VcCߞ[y"R$>!2N)Wo$x145Ш}`:} E?-JUS9q/IJUn^Eᛪ PТq)n, t۸=L%,NO{VM?zaf"宜L%Bt&1ȻM// Ǎ6)_jEV V/VQa);7fƷٝ^_ux=.7Qנ6;uH_{.뽎)uZv %>(;M*,DбSŀ+dDY#'ZG:UA5[:wTOg\'A=@iÕV_vÛaL9F=Rnh:k6R3/ G FQ+Oغ' SUV:Dս_}N6 qƳe*HrIYiub5#,<9[4>9ũdC8MtTFi/B}[f wB9&+ڔJ7f{'@v2̙d'^S"|Ow9ڊ "RabpԱT{2@DEc_ ('5FN|^NnՃ;PfkzfXq(Eha95?Ty*?I|[Ւ,pk/Zn`?ωUi׌?jۏ_<̀𭬽jKRkRLTeGэ(EDj%c Xpp֩n%P/n M Az.X!.*krv_n?QIZtNwߠI04~2@kzH3˫PT)CjJQFSxw۠',wLΖʡ8vup H<[WΥ%cŔPBw." ijy)- 𰃲=kyՑ(ƏfkሃQACwghBaРvlՃlUozXe!b ƃۑY;>Z۱(ê`J.WNeRg8Ip/cⰜ^IϏWnq`}&1M2r)3vL+PMz"?y;jR nq'P $ۖ>KD lP ^5cFj"Baq .A M ꋨWx Rf,셂oY8 ";㵷hIy"mF@ ؅4=!BҊ+3a٨N wuƧӰ&.`J*ѵH܄Z Sj W2PwU)Z^D{ *3#1LXw_-|i3ֳ1;FEX8ab7 R )h <~*bSL pz=D1\&M(jKzC:A\1  8/l{U B05$6Q7r>47"ad~m1ƗN$߁n^0nod@:l"FW'>a3ԋhQsNU FfkDO&AEUƋX?kfwiig+'7Wrsp"vKod 8-!Y9jH@)K?>~ƓG8>9q߇Q0|o!ANXafB|peʛg:V{dwuSyfP4 BYb=۟/O*`_[RtJ8 P8{bPDL_NQH@ǫ\|tS =1jYVoޱf/<^XgEN4%:+c@?(pC2zdjI~>/3H`r+; ֹ+}j&=d}0lK-Uh/!̡$LXbgi'A8)`MtEjtn=כLT01t6q2Oi}` <@4k:\b0jZ|&rn+cp婜eNL )@Aflƈ,*QZ)q<f!a~P8ͬ9*@)% 0(>™ Hkk_]C:ZT -ޖr/OnLyQy5w0\@6vLIpeűъ5֮Ȋ[+ ?Ap/"zXTE-y ~^jcekA=;_Qv)>S] DC~Tꌺ+%hV,?6u_eo,?Y|x|a8C(d Aze/>Bsocν~!^7*Ϟr;#T}Y3mtx=!rݢLy.@l'X9n7bn<"go-&x*aR75G"d$ݩ*:z3T=cR; nTו)2 %-6KOI"-^PUBhhD.NL,-Y͙8!v}D X|+`H` -,Y43!530]gOĿ|3NA1QLMJ2ɣ0sO( 2Bv&%"~-VG? ( KՐY 4h89"`7ŎB5; 0,-Rt(#iEFz|',wfC)#nPG0== uvx)> 'Z-,G̵:%qaqR9sHQدNНV}^v.<*eoxҦ1f *uu4-&+}Lb'0FBgBP-q3\FU%/zkuXj8*@j x0J޲V?yI%1#$8ܳWDk)3U/~ҟK0$wMU_77 G/1SB"9ũ@P/AE[-%PiD4#_s6ՑOz·:dRz%v xO ya-%ٻ'SA0ݔ oL Rv%"Z08>f&xkշc[ LP0* RF qb9olš,%)T\!T~rLSn<YȳFz-mƄIet3.B涍('L2Qb;f 9Mtqow#P:~(> 1'ڐ hJӰ @ڪȣ|-5 vZOkٳEMwøKB`\E<> H$._<ݦZɨ:Lqwa^QˍzD%%Ar2wDLcG)ӞْhXsD8h%ݯI 88E8-YD!<]3cMHYi1yWDϖ<$g)0vwY"K.a=HӲTRp+BÄ=et# JIg Bd4dWb*T_@#NvֆjeHU 8hH_]R]SҒd*C(q; oe0,aV9~.۫5O,j[zǿsh-230R7!ؿcbs(0{LexR#ٌy"vۚN ~B1&7EgsdfnO]âoClvd6=ۦZ?[wR/\jW|%~NiT Ǖ"dsl] .yԨZ+G7<:E`A>!Ԟ]H.!oSr_S+"8%kWu 'PWFP~tYj'/fMy˿TeL+a6~ a#21r߫rn+$܉PjÙ婷~ нt=rtG0EźOݮq3oT r 5r/&5T?o~p78B198??G'p[`k49 ` U96bІV=t!ʬQJY(,SGuO6xT0Y9f+q!H%\̛,7(/FcБnM5W;=9Ǡ. :QT ҜLf@֬eMFMbWKڊuP.ŵAzB3ȍ.E}GL<BVNg^_#D1CYPcbz&hdEX; gj'9swW܌ggtHL2a7/5HR`Hǁ.[:֫Z_+zKM/N;?헜7eFV|>AA@u{ԍ'KDEtd/*e|YLw=,rt$[$oS. cPlSHz_ɸڿ Ӳ`Έ߽:)). m6sfc~= gR4/( km@wd]Vx#pSem|oN@Ǡ|. `c?FKj'3cBVI(W83Sr9NY5HE {_lK7 1!~7k0fX3w q`suZ;_ V:'z~}Z[.壘jk9LO >{`EoP6Qy먰ayѩ+Nd|+ȋ6C?3[sthxQ|ٝ&j^iEsƒ >b$ǓN*^ryqmZ bKL!li"lMp>93e|#M~9u7|A^c8=Y=!V=*  2G^A[H],vV%5aWz kFS0o7|@ٴ¥N>0N?O TO).菐kSaؠ"vB%sMh%TaRQA/`q6^m0*W(fvtHg Z.:̹+$+q3))Zd,7[8ךcJSa 2QRL/ $i nidcg8);O\HJ?I FH4 Whn"Zwг_r&MJ/>ȝW?H, I Vw:^S݋5S W,[h3Jr$&_uxRVvXc-%`6z2*a)G.w"޲wAHšAsE+{6x^yxww"|hH?> mBG]=rІfbDa6ыbz|V^7ɫ\!0ήфn $d>~\2bq?0gq\7\9P.93f;*<ً~a׫'L>XVA&7^ ɚr>t'G 8\s zb2@c-&d܋L-Y5jj6!P3sV_׵r{Ch͹ؐQk^8ū9Ϋ,e1tݘ Dn;sWj̗+4ɀ<+GHporԆ:z`ѱ7δ]q V0̿)sA,GTxj:rxvXJ[ k%iͮi@91VRCV;Pf}2!@lbk2ŒƄ?M7Gw \w9.\˜Ք{TQYέD&/G H'ؾg@{Yh`b;" :3 omAPv*Hm=ր-O}Li#d?~J) ,V"Bt5P#?8ABv8':-8@DdC~o!ɑ_fATx<Nj^p\smƶ;@=w*cq*8S{\750t[zk SiנtGe}T Ƭz+6èQ雯ay& Q/j8 ޮH]y`xٵ-sϸ|Zn:2Ȗ:K쬝PCݏ9`ًN#^R밈NGGnM>$?ܶyF,Tnª60XJeO ^|U+dFoYY #F5?7< Ek5PySl)~aI__*10.2⒗.򍈳8uTkhȯ4W)3] 0+"l9(#ipԝ\5e >pOCmKOU|*.ف_,;/JT֝iY/쁁\}*;? z:ℰv7`Q&h`[:nIΚPŽdſnX-g. U:J'Ux~>zwdZÒ>"9;S:^r͟ЯUUJR(be6%2pf; ,#wF *gQ\q ,hwP<)I94Ws}KfYU_4s/gE/egƵ$ :`O |q,&.Uvlrl$M{3+&Ft@u3 UY3AZ/ed^l C"uuEթJ; T7d۬WOD:8:+i%\-94l o⎆Ie }y-1& IȸqIJ)9bi< Z%?|ϛ3+AUTMa%-@1MgFI{ᗎ 3bJڛFX2^*u: )O's΄JҲ ((ow׉凍(܋пazںF9йa݉oUw/`U~c,TX|dJ@4[XC5 5ƒ ~qK#7p.7q[ ?NnXPRfB!h_z cü\6[]%ɚv ֎ʊ#zdH9,8O?b2+7JYqA5ݍH,k0K<lj-JZm|oxz"6SpGA8 &8< oH"$$_;zVku vQ[giوnX DV"~O2tɝ8 dpG~A#j܄tC+})B)l2LB$qȇ{?^m&Kw[BJO [E``LQ^We6a 9`0 - 3:\EN(C+Y887ʯ06I}n|!exv.q%ģJ @>LK2[,nV%/"N{^ 7 u+чvX!59cݔ(K4@92wKk6y+zp8/(!{laUmū%r1{sLzqdtd1s=N`KyHZ3% ;})Vr5 pQo!w\jۋ(n_|b_h6>17@S-/blhWł:yGʳ5ȽzIۀwӁj.#4"/Ys!W{O^{Zrw!.$~}o"lC8N 0>mELmSmv`a9.Rs) K7'S I~c}5!'_lw)qx*7oa,\ R ZǍþM(4Lٵg2~h Adl$.9s;2uD`/7BH 㓭%0 &t7nyK`-勮xA(/-arF.cV>ߌ4XK6 $+sTS/n$$]ߗ&`eCĜ3[4)@kF]DR֣t=ιuT1DቱB 1_+K”X;<'<!3 ܟ1#eE#k(#ʉg0ډS3"#3P5 yj?K7!C3冓:XPHr<NNn{Dct=7Zp҃ f_V #z`WMby$#G_Xj\SBV.~Z iwUٟEy40 !auNJ!u-,JSNFoj 9)n `]n²-įK}C/x6˸!LЇ? (O.i|-/F<Ņ2q^ %rާqSt*s8\$xEdVd h8.Gp|4 \4)9!#?@]h~?&q;([-SJbp&TEXRscgV0ZtJ`2ҹWéqSPT@l蚠8@S)(yUGj ڏ]}V~.5pU?_ r>NpU+,,Is( %{h?sut"Ѕ(SbgHSȽ|F-USEVQ1i/L52ymY^ -hk w Bօ\G[^hzjt& n پ %([s86Hê+Sp˝cgr%Nsgֺqu&TU&7C/sr,0Cl&h&s)W_y hמleNX 'yHo|+oO~oqbT'^_4}G9E&1tnwHv:?e;1B}uJsU'2z ͝]X­RòG`ml1eCvLR93iR?d9Q6ݕG3Q߼k2`ZP;L!CLʸnw߲KI6 ߛw킁"׸! 29Gj /<8Su;udX@??4iw)eCo[+4 rjkF<ނͦϩ!v ^Zޥ/*a\)LV' bƷo6&BėxZåL-3 AۭJI3ĭϛuwJ)"λTPh)Ae}*CrOu ~C[6.MڤtN:˷*]# PrewyZN![w(/xu@f[)cXOvͷ889ێH~wtR3`FM+>Ӳ!,f~C?4HwR?V6Nb%JdmvEՔ%LwX8Bj$L_z8`s_ CF (N.l0^[yԥ$m{Õ +k' `oyjT^p?]l3.)c/#۸ @{v+s O00H-!o^O9QUD3=wd+#%ٶOZAp%}Hͬ%7MmsuDcFUNC+|`d2S$Xɞ`LPL<\7DbXo[ۧA"8QTdD)0ɓQ9sߒ+NH=ai!3@Rm(qp@pOw]DK&C"1,g'ͤLZ:]IûK{4Soc{ޙD~(-ۺGj2p5D+Xɏåy9!?W V]Yկ-<׫"~?P|)?%*n|!cBj)%I ^4I@5u?$qpVj,ee&PV!˙.sd؀OD7jbBJQq=;|-C!׊-ݕ@Y*3vbsPF*Aƻ~B4]7|'̦F3x"wR0w.s\PQŠL?v9y|Ƞ%U%X]~^Bg;fxeFi s_1lTm斨}9 "H/Lldx|h T|a6B Tc_8a'ͱ)tRQ/rqgxz\1!OT4=9:Q&+J${qz"f X:9=ٱ|82qA0S+]sV`D)_,ڰI6HuUPW&{jFI_<~5?6()A0hbEX 4JO= 7k"ϛsa:f HKִ!9 Vi|xEdj%~Xw0)%M˭O01?╫~8ŲaєČJyd> ;gO$ȰO}E@Je wNnok 0|^KJqF^[[Wym3 l)*Ϊ`,'mID,j8;6+ː_n@aI#Rampa9Wnj…,KCw-R<1(]z#B9I?g#,B3&/ azۉ 7JF!!/XN) hE,RUw76[1q) H;3?#o/NW{贙0&m@P1*b `3!)R*͜Hk~):Ǔ-W 5x*LQ୊ftVs愙)1rW3[$+i )i~\ !T ϴw|clk {}Uz ==zU`/Xu0Ł#eūΰuLأ;XC=p5߉$mԼys#vt_mxFAbZDʐ{1\n`JS)^6^pfEI'!,[vI!pdI [ߒ_YQu)mule{G)zQաyWse PnKYa 'O4H=%G쏬@NNPV?ًhYpyme5c܇"U٤pj2c\k*"?=`IwG>X / Q>f:Q\Lᔙ<,}+LֲTҺMa>H9o6N6G.*u&rȜ- K=8i`b endstream endobj 95 0 obj 72958 endobj 96 0 obj <> endobj 97 0 obj <> stream x]n8ཟBvQXO HYi@#WGt>R4uwϷ?oytnW/^}cZNy:Շo|v/yUjNi%]O| _sՖ㆔_cs^mzWmasM]ǧôڶcsS1疹EYY٘ w#rbNsmܳGn@?@?@?@?~_~_~_~_~_~_~_~_W~_W~_W~_W~_W~_W~_W~_W~_ᷚs~7~7~7~R~7~7~7~9w~w~w~w~w~w~w~tF8#Hg3ٶ l+ڲr Y,h6;сDt8. Pi|Fv +KdDTguNm-^F ̸>-AāNą,ua`ʼnALt&8eM<#art˄F{ǁN tޮLvqpvvΙK2=n=azf1OOg$@;<) bwW<}ynS~y.XG) 3,ud@ژ4͛rPvc1Kzp endstream endobj 98 0 obj <> endobj 99 0 obj <> stream xctd];tl۶ѱUmfǶmNǶuGQ5ל{yQ$J4F6Ƣ6֎4 Y4%/ GB"lcdeldkk 46R4vq74v;_2U6֜߂_5@F`d`d0ӳw='@X oo4v#u9r@+ F@Sk:n.߲%`jfk7226GCU 8ȅ(U 4Hb75@nhIG&@&Ǝt5IDl0ntYX۸X{[hmɖNhd,!_%;X9vcWC3Vv5៲-D hbl pw2c` Ʀ@kU[66ϵ=IOK?#kKmշ2ۃO+ @D`_Lj6?%%Mlts.ׁtt?AǴqSo.^mhK?ZB(oLτNa)Z @l_߰O/|GQ2J/t1@Q.#R?[0OKcZz|ד;œЇ>ICub<p:>B'߅("~/.2 n-B E=RRx.vRUFB9v)Wu_7G 824TBS%ͳ^~HwyoƤrr9 l|UW%C!fgmye6:b۟}}Qe":FuvrY,hJyO;֡xR`M;~bMcp2 ,mSg: A"?r~-:k^8ͺWd=/YC)Z-ϕ9 ,)@"=[%nL ~59~ʱ/=paxb ,zL-}]z=:F-wX"kOrK|AzrUza]@gZ +nn*>ab~H/Xʮ` ̧C<ˆ 8 Ǫ?cWȠ%˄e*M|)4m5ykT>\e uۛtP-NS[mN햌P +n|g~&6b'c=$  "KףU)!WcV{0jҳb gi<`F-K´,heְ RrGؒRpFlV \%S| )'~\`A*.1`{)/Mhڲ:|u{oULJ!u/Y/ʔ ڙ`WgiMerL`S)1<J$rx9&Y݄^|a͝;JBEhQUX! yQ+1Rûd~jq =3? kž["e@ZMΟfνܟf[!iZ)~Y*nB}IJ/O|~&8^01hi++. ÕW *wRM '$ _g7/A?."{ttZϣW֙a%zU WU"` j;{5\4;Aj']oB{g,6DAe5Pjc'5H+⢼Fsowiu]W^*ɥ(0rdavo[娠.^W{B6cmtC'<=sM{Y.PZ1]xCB懶k+Cr*LJ7L oNO)hadkHtƸ6r1fQ1\nDƾǏ@!M6}%oNM /D ݙ(WDUcD+vX>lzB0QB-t~s%lu=,3.M|d Lٌqa+q)[҇m6XC5$mSv?(&<o2JB KJU *:OV[PC-ŦY.A">o\38t:)L=B m2$Jdt#= Q>7RzH0陇:XWm6/Ţe"{<+Fn/̾r d{ݍ+& ٌ<rk8_I(][Z1ͥo(InXUսv(%2qNڸv‘Ӫ̄% `f&ߛzcI)ט>T&AFV vl @EfF"u},/b.R%b,D)6b̕Ъҵe/ٛ~طa^ދX*HҨ}3/)lٛ suSZywշ9W|TY?ԭ#4Nh6N,^D>Jnms՜L. eDߗGaHPPTQ|Epti5raΒ kg^4z5( ޭ&x_D RlӌÕrqmdi3y;9(A#&%WKM*ũ>F]qFdlm^2B!PQSPgՈAid҅f9څ=I:ޡY@ k󃇢2rNbpd(HC!)m949`/X岬&cX,o!~M<,([`'᧋hf5mJ0"l˭>avԅtP62dZ'PynR nSZMoamIφe2Bc{|}DXa'KH+z9_h܌Lf>Js N#2#X,%H.?(p1hz0.EvdM9tr?[^@9G;_z#͵I밬$q gtcmmBL2:$L*hDqӣ!>k$9`Bs(K<ф+ 5)5bl fK9Fk@Y7~x  :TT.i],'u%W= ~f;ނ@1|k%X/8'u ڷW5ctJtAv%y)BОDﴅ]a /rF]Uphq_ۂ \׽y:ݰFe^ے:Lz^Xpfs6.7A |)%?,f2ŭ6q?^Թs%%Y֡<+S \ߟ ɕj#k\A7GfUF|DŨgS7vPCǂsN BaP\9Dڇqρgr-r!D>蛴] Z{. +;ó͐K}TyC%1NGv) WvyC~[W՗i|Sez?Quf֛>s,a.]+oNdLǓv HT/U J/\͒Fᮾr:3AޤƄ 'oQ4Љ Fu|&_+ AGEdb n>PM_/ڪ*ǯ@@#TI`MLُ+ _&QOQPsRpÉbphy : N&O+}6hOPGNC(ݮ #<=d]Ƈ6~P*LMLm$ bChob+UͭpTveMĿ@9h΍aiFh2}%xW[u|JL\hN׏4Vxz`\ E0^$4;g ,Z ։lU vGxF+1؄mG<,9dRC/-̲R:9'd Pe.|B~@4栺pJ'rkW'g9|9O Hƛ;֠ kbl̝pxreЛ >ڏV0κ'&TV)"E"!Luh8Aǯ²:$¥is ?˫gLT3-u1/-8G4MHbJ]KGo<̈́bts(5xe#=5 z?8בL)z|D,{:d\'Oo& 2!W ~^ )LJҨX sZׇ<]u;8^Dc $)J։1/xL_oS;;;\t/H֮||_cinlu3QI~;,>3/5RcV?OIDR4iv@(|[X:sA&2fa -U>sQĐ} c/D]ZpTC/ _.ab@;p0[uB-ÖG(usQ^Z9T8k/}o=3]zFp4O 4S?%D%4*nn \K@nҗZgNmZ_|ߛ/7l1]I.3UP"&+e#A)AxA3ze1<gp^Kg"V×bdG;oPrAuBFxiS?K*I%sEkR럯XULgԉ RYB-Pv1Yc XNJuѹЮ9Lu 3K>=6prWb=G 4Ϟ6zĆq2'Vi$(. ,c3 \!&ͮ5 J$Vp f^q!kI/6,3H]?%Uj2> p3SfiH ҂VPktۆuqS ~V ‰QZ"L. lϟpz}MIL!q(dUM7Rz?'щDS$|T_xj[_M;T f)_Ǧt*V dՍ"ą~52fs|.#c&DYԱ!y%LKiğ?c39kBet$k9L;㴔;0ڮB^RPޒ%n=)Ԥ #aAqʈb N4 p~i_Y|o~J3 I}w`knJG.B$Uk0*t(͟-|}AB+_ [w_V7N|("H7}K#;Ϩ< 0i 'jEn0ss2mu63CNϦw:րtH 2E8Bqe& kn,Ȣ}GhϺ47J) =:Vx3( ލ_?}AH}% &W$~ߙU +,W.!&˫lHPeS^1sg[KD<&5 T8 usXy><5Gj8g={Rz^-j,"kH=^!NO'\gjZWh$5ޔtKt\5$w+,Ŷ5YṕC7co}.HOJoKӐ1&)K:+b[Bye~kh["3>֭/Y -ςmCF-l!]zSqâk%5=b?o3o 7bk3{D=z7V^r̍aڊcRy˥2Jȑ_|&hMepʷy彚Ƹ䯬N7b7u?3 ~L皖5\-^(*DL^L|7/8鬜mqV~|bD?%gxp }1  6 2 %̼N&Fn ȓ6V}פ6јr6+UE خo5q]ܵoB-F?īHc[MgQ\YمYZv.锼Kݟ5WYxc;=QQ=5ٿtIɦ)j=C eXoͭdpӃ{1{9;fKV8w&+-=g%7n*Ͼ>43|\56\Kx(qPPyžL! 5ጪ;M$ӨL{R̛Di}!P"zSc|A4<X#DW oFIIH4v7Fu*b(缫6M~uly j*^v*L]|/F$pjSA..6|3Ȃj?]7i88 HSp *jN]!QV"8G1tVTZ|]k,?. /2v$fPKYݠ%nk,b^B(j9O|Nۃ;  !;v -IwjO;(eqBܕ?=swm3 Uan%C8SAa;B2lg ~s=)C<+`EGܬkTH;ݙ!7/,AkgiIݚ"gE!߹#0ŽBV\zƏb6î;G-E)0oO=6*E!j|V!K6Tc+7=pxe5ő{.nmEoE>=$UWViXFaA`j\O*QA:%&\z&>?X#QayNh&@Q;$ՊwOl`x |0?8Wv)_x`F,E2YŤ=!i2Péx YioQhܵ Eb\}{ [e)jr:0!6D=L;$4U?F}%#Z# %L2 ,:MFzb.*3HE&@4)u79~YF™Ƌ!7h7q:gA'AtR@Kl߆OlB+s= ,C& ^c]&GwY ¯jVI\.[BT2pEdnqF] iDh) 6w.n5Xjmj_RX|T3RB-E|{cK= Yju#Z{_7(r⣍Iu&c1XJAֈo!l:,!s"B(ҹf(KQ3{w賯f"E Zӟ|zxyl`~X] \ ]ߵF. m~kMO7&!H>/`Y7%тKTm!2k)m/k}5MoDlӻ"Yb)bABmo$ŗY6gż#%ƵYE(~T4ަ(#@ %ccvEܷh?dZjAe8tVțdXyjhH!DZGl^EOD1y.%Yap}-}qƑuEcBB}8@&urYdJnr. <0bGdA]jf}.Ug"<e-hXpVj 9:n)IFm<^8[\\.zlB(0(-_k++--UOS;5i!FBHDrYnZq}H1ƾim:ߟ4r{Fq&h ȯdKI8,V f[)y.VhS&`-YFXvgk^"ȽSλpp~.m5C` 1pQo+U<6|צǒ͞cv<`GG &0ww-sBGs\ܐ43\y>'f\> , ,VND=KtN?0ěpw5jlD3`;mT8)u4zxm8|̱; [c3ģԃ9P3#UVAê8@B[:^[b|w Cc*7XbzɿF.axke@o`!6^~}7k޵|7c/0I >V~旋=$2䒏7>u>m g0WJE,Zs{ۨ]Ym\6ۜPa } ,}^BkT1+um wͺ4ItA%CKsl&3 b%^$Sr?w\Q]`ԎFV`g^:mS淰T;B'yV!Rz/xm-r5!әg_ݨ)[vI#M(K C 1Du|E(|wtZ7!l[n~з:aю@^۝;߿j4KKYKDz .j{6N B}p X)&G1ֵQHA6C-%MQ s5 c_SVPD"GqލёLޏ=“Aa$t)f_c;ln{f:H{*k;B*y jWI]ʎ Ky"0™F,yW9쉅$F+qāPxc=xHڙKJM4ܞOij>:t z=4<\ַ8HM8OjU축{(!P1K!ױjF}e:pY@gERػĺ/s"JN F^T\ߠ$I;JHQWz#LHi #՛)ιE$ŗC8^J[u##j9H7ZFW" Azi$R&!Ku_IԘm.kYao$ӻzwgun~jK3ry3K tk>3&hA[(0B۰]G9fa5M(Dv-2$=Fua4aa-$l$M?)%GGPQzҷ:P.-t9}0o]{B7Oƅg@X,Q7Il澔޸qvb<;J0Gx7Ě [x},!㏭bmE2/ptqu.ͽĞ $6C]x1;U[)y3T~_XMJg!c!Kdt\-4/e& pE:E$WqpV/pJ^CXtTDĬɈEjUV{ZC'X{M 8[`eZ/RѮ萝“/hވ,Ԉ7jyp~5AhO }χ'95QrAzd#"+]b'sOzxf"[[3e@=GC@ TvO^6Cb㾹8YhB3g4! `.ܒ:ބ,,z1f0K d*{C$M0љUzJ5RtW,+}.t%]! 5JxNK j$FrwrC?&0AD-u}EOOu:8G, E (M&V]J9"Ў ڠfug1P AܫbkPOKD9Tuano;Gb㲂]pMÈ1ڔ-8WԤ* "#~O4g#U~RDBe*'Cqʚ3Q˯GQ5!El}Bp"ɜ*u`;}oZk3ϮZ + y92FȳKg>_I@#꿒pqumB, )2fy|_|\Qp*xZ~w U.UZWw nZx ]Xs#+#+Z߮wdvaBަsC}Záq^ba򇆽 tgO9R߅Ԗzkv]Kp\A0s[ɒ+0ƃ}oWLoFrH0T M5dK)F1m©]*`*EOȂ'\wMŕء2g-/dXp+Z P[^' c%ݽՒNrMqO/yb`/KG\E$`ɭz;'V_E3-870] I4ϼu@JO9<2ۆa[ FUK H oih5,.W,E|Q ;U?{xnfr瘠MmdvsyW*%HQi* Ek nIq2kn?^^;Ң>2 6QfUY5$3xa+_h,DvOc m,ߴ4 7eOؘ >ˠKEֆ) tr%g.,}aj$A{j@$x4ɚ8u5Q b'jZӨo g,3m_)>'tCvT]Фye 4N=9dulM2ȧڰ0p#n> wZe#~7\̓m)jU9+s)^U(u$/r~W2S&qeL9 ѼV&K$25j[]v[HVެ''7Z>$wœc4NY: iA{$u^q"oñ YI ڥ=wLlކka'GdN\ %u#"+Cˣ[ 7;pY0m2Õ~%di) (JڋSۡSwXth17tA_k:!QBrr݆̝cotFuc3ҥ.N:0:\.U/qb]*׵WaȜQH N:kO|)"7) _+mLt$@q^sƒO1f eXQ h} {]r=:Ye52 ?_qw[[L 4 :ڻZA2ac5#[dV dNsO=-WXR}D aME Q" vSZhmӜ ;f\aݗC Gt˹tK> 9=۳,:-lKt@c/f(E5{LKo%JE1*`bzׂ15Ò&rE7&U& #W"%dIݔul{~oV|g|i2Qv)hv]nbTTs0n~ ҿ皢G])s+T/Jbvc./QljI,%^NV"ŠqtߪIDNm A%OG-7.@ q W<I>!:ƒMh0 ?BɫGgfl*dZ{"[5%_5K\2G\ơ,K놤+Zg(G1: ++gMK_lqeVb@\n6F%Ft*,'J=>0'48ڝƁ<ɜJ/}4sj. 'M)?Iρ=VD[-!Gm؟\k$CW3;w `ڠZt}ebY=$`$DUSe\ՂNild/Lο-IV{PS1D7NI2y&5kMK韘4L5}IjQaʼl̷,;y:C]?WWT3u juJa[ܛXHJ HC|r)#pfC-\Zdfh|Us/[!p;NVG+e}Wxhp\َ\.4~n TY/$>ZsbӶ2s36Exp̐Ig;yWQt7+R7f QD?%d*-w(l{$[C4>ϸT0R$gC9Y &\-C9j4zW_0.[`UdcurtЅ˵}&Ǭ}Ֆ׸[ e-!@?׆%-8Ql7 gKDkjlmUq75TܼlG[kVo5P[g3jQ٨J*C 7&6FQpbYdmk)vE9;K*ijyD@ R& IRi1,1,wM" h{ڲ L4-u0;v"QO0qtbĦC)*UIckG,Wqø1p/QDx&M ^*%6iϲSP_iKu3"ܒ/j@#0qjؓ\7 LmvFsM.8]JeGϖ0ʕޝ@7G>8*B.3N2rS~f^]@C|UoD(̹$QaLoT0q<߼}լe`ҋ|M7-_kmQKŪ"!yD((oezYLm7Tc$< ?;4N\2S敕 \5*&oG_߇1;oABe'wo0eu!G,@;(ҳ nO`lQ81[QDL16ǚHs8;D@JFaqj6[䷢_Z>-^w]/H-JAjI?F;hAvtRٷ.r++Nj!>1MdlUWϥdDމSBhVȰP4nRmx(R`U 2:#S i){Q֠ Za74+ JbD29b xiIMW6pT4MJWlVߥ1ٟ~Wd,-LwKM܈!gmq$)[9f$_`]' ٟ0v `{a =`,`z 9F';uǵƌ}wU()Ȧ14 d<2yȅJc(jch9lB@*gԬ1|&hn,E?K4O9c1WqlPlt {qrE?X;vr}wB ͕[#oa) UW7 ;Kg 9`4`E('j)'*4m'Z+M M\IMu,$qh W|kܤyhv"θ~4YfH^P؏I}tڲP0eFgp)[>O[::e?p\26R&ih{>*`W$ }P>go03t8Tͳ{?gT5-l ;k?٨/,MvdUQVi$!OnFdq]Tҧn{^i ]~sG1u@zX_ߵ~'"h2UҀN K/'"YG~{9TM Vl{ailQ0βIyQTpl{9*9U\_d`}tC2/+LB׌m`\ཨ3mA V+N9[*|> v|գ:ҩ@Dv gv?aԨ|_Z= P 2js7#m}N^gV+ P"=^p`(%q~ gD>6w? _VSE]kB3&\&=3s݁Тߎ z0Nޑrq>ك- 1Eː>[(p@s댺#){r:R2X-!ԑvdҜ5wѼdr@Zܞvq056%;f2V:,62+OW2;baK;CU˾뢽jX!&60yi=EH29< +NOzU@)7R-/ 5vL+to"+Λ'i=;H($@ ԬM}%(o$95vki@wd`3_IȻ| G$n:R#Ug#R+W1,-=O^S/+F) {OyL9soQh0>$}#rVYwBbN$m9Q&9i8¡YpQ_ p&k~сѠ쿄*`P+V1hV9>+HJb A|yE]7 }Ξ>tؑ$bApz4uӏ;1Py2jTʙ+ N+H;&ε)0ʫ]}D]{;ihKTAA L & .ď tEZn%)Op@rd$k"&AOWC+ d>͈*:~roob䴽'ܜ;vy7x"(0g@a$.~ņnøy1N9~]Kyw V|$ےHs)A]B*`zﶫN5!?bՅ;`_M@cI;#Y" x90c{w< -@]<8q)n{]Xd"i.G2LKDn0i7L0O>Z>*> 3RLߕsXY:[pr*Ru\% fY-_.R2bY.EX%N\Wϸ PW)kUDꊚq}/l6hy{% W\4|ՓM~~EP&F)YD pa6dpf/  Mט%B! dA[DW dWgVS߆u/mee0M#U˨p&f! SBֵQ tZ½lX,Ք={>c$,e :]>U˱sQew-uΌFCѷŝwI ,W{lnrt-w߉d"EPl\>YT|D!^U{B5#Q[3LLW#]>/Qڪ6A+gWb8};!BGo+TyL=+m ޴'ȉOpB{:Nit(!y~f"A|nq3J]v?|KQ4RL7-Ȇ+nԹctHEIS4ʪ.CCUR av wO.r%)T[K {lVj_CiأuMSXQlXaܛu/׈^7'x><$t_#ٯYM̉!o:*֡|L%#CjZmpCڬC| .l$x2<}@ 6QzNy-2$W!ĤTNBؚFfX+w2N':3 %M} JVK;o^"G߸y7VKPW莡)B~М%7J aUh]ѡ ܵ$l`R?ĬH!nvU] GajΚ-08dI@g *k[1 j1u#A ̈́pMZ'^63|V:+T:EIfAmlK"ܮqߙQpa5+[0^)MҲkpcD*=)5f-0+ɑ>@,6ZbP hBlk LB`䒒[TR-%6ُ?\N|1U!2%پ G$LK3*AP`nE%؍vn7 =X]f,FB2 Zm ;jo2Q=Uim?B?]a2dw-pp>DEazBG X?E4y4Yd8|L'C0!c]{<>" b.u>t*{ÖL%ΑT%8>E'ђ8ڿO!D<4'6ȺQ۝8lq3ZG]j Z#NEVSC|- 8P@iF9ĴJ㋲pPa)3@ f"ԦCVߪ*~m` JhHV"9 ~*UӨ. 0}0I~#b5J3qa=,P=T'=Xc^j^(VM:DZ|kMQ0fN0=_Eofl8Z4y?ZҘKOTC)v/il͔~ScϤ"{t<# k ztJʂ]yz Zv5X7/nrWYξx+ m~h'cdY2qzaż6WKfC6 xe#cz  Pu =ղ ^+9OK֘R Ծ:d-Dd,7l2ɟ[J:*~vhqi)V䣉2_ Va]Mf46:g{*̺c,w\lD)ɀ CÆE*nW"Ƌrq_]O29. JQ[~|sQbw3#DforPE^[<zL(*ϒ c^cby d71dĿmvMqiUQJߏg;j4yz%?rB*o!5ƨvw Ա[p9V8+$ԤP69qt`~!l4V2{ *5-q ;.d\k: ~Z17I*w}$E!lTq*'Wm)R+0G^&Cwl=S6ALt}gH R~$f?="*'iOR_JUNvPO#)twWn@ &oz\? j۶jb].gZ*"$מD et)#y4tMr"hDu`)<݉@YlNf*Uڜ\ilT0=e<Ҫ,PvH} wOKcșX[^2띉wr`戫B9/ f= (Ek,v}{w6uutn-1'v6RȾK@?O$+HOťY)Vo`v|l!,z(kT2:SřX^;bGOp\͌G8uεGN/%|c-Z t,Ó|pη D1rAM]T&ѱFO [& y>l 򇜷)i/ߖJ6Pûcֈ<TǦɅaT[[;`"~e7Yi+ D +v1L 04V:/(jj1z0[Q7V(&i ؚPZTNPLզۃ&+/T̯:7R}W%iĔ"IjBGӝ0Wp)3fo<3}jf"/f[$d,#$п2ؙݨ43 sìI*?9X3g_K =)2ԏܤ:ۊ|*v[i UE|x7гv)\HiylCm10j#hH;tF^'_ HEA&L~bB1K뢘\m;}mQf͡6\ LJy4F~Hdl,a=\m>fRʙg&  T . fgnFB n\;R.XHc4fTRZSglۖ<OYj'Ӗ磱ZR.ă:72,Yu/jP3A +*a^2DurYԆS",Y^&el ~JݹDk!d(Xr53 95DpW_Ӑo2$.y^m6Gad>iE5BMr?7 ^'!C$}i\=Yf&z1 IFtg6gA"H]#{1v^Kq?HFA,Sezr~QBZ\3$> WK݋=<+oP[`VYHLlR*HMR#kF!,OL"ZaOޏ{/̼D%=X:JS ցg.cHUwnÿ ~^bgИQBc ׿+?=/N[0.Yf۪NE ?[ge֩ 6X׭[jų:Ym F7<E, m=4e*}=V(sֺ76XU$B :&2~=Gc1㻻@_D 3c3!0 8riWAtG>kwBĝXj >x%-~m`a^'7VmPȹ E;o_3e .s1n"v"AvpzNsW,\N%Go䷸9bz"t/K$\u%ĎqN V`gva~c[nB<Ά}S4>uJo{t(2@$[pb7sd\p`'LvIDQ `qs4y"Dv>,Bjz(I8++[g6 8gf2w@ìi S-_9Q m &>%dDte!:@(;-p"|3%|.^P.E/9 $"=4m0щ[KĦKȘñީ,a/X&wcbٍaiFːТ1!. :f3(UNZ\)Zg64H l=\7B=J1S,U( t} 9bY%yN0FJCPA$wTrq㍕7=_N!Qk!BG=m+Bjr5T`ĭR0 ^T/3ԮltB8E\?NÜ\'UF-~+jkTANLIOKBr4xiCIHXKc@U s|zVVG"+Y mK%=|;=D$ ޸3HXo pQ)5qܖ[8*c4{bx1OknTɟ Eӟ ѓ4}"ly>9#o & mr!7OGCf_+0Hper8)y -0/(Osw)"%x6:\fxpu8^OXɁ'}V?hx!fkiYe!8)n+ S 3:צRFzed4n$9b DcܛVyM+?f._)qA)-BG٪HXے;w?/f`_'jp~=<׸:hCZL75}dT@jOֽ&ff8DO'd[;Ѩe,Q&>$a3CӲ3Jo(\E\Ӄ*ԴH[ɀ#Q MA/v~sC1q}gѩ5X@wL)h2+Y'3f uJ̓:M1?\)g ide HbRV.PXN90|~ b!r7B%@M_Q>39KPVr$ H OJԿ05[sŒWP1g1a%Pϛ(]l>TqXKxT7 ;΅RWY[n;wPYq»WJ L|MLD$#Y"vx!9F5ۡY!&EmZȿX-,}V;jV d|X :R9uK9^)ێa#YjDt2N8w>h^q':,-a<ʥS1G%ءA MD6ltR9ᜡV$9k }G-.mɏg$W1?iilJ{gC:/3hA3*Gb@If:f7i9} +@&8T4.5˔N;.6B7)Eh;Sd WЌߗլ.~j`S#w5C" @zRZNe.WHΞRF2'ֺ|ZoGԕIXqqES"x~dVM,V1{q@Uܖ9UY#6?o)I{Vn hW sxkUQC 8ٺ!RUNH?t% ?_7ފrn]څOW̿n#t%jDXBXrvdxc!4"efR$/Bzoה',\}x?2'gZrz#qyjfBfޑQ1 gSJ5b_zT\ӀsKZi#(!qlRRIcqqS.9NtO%G@3 P[<'< &GXHY~lǽheQ[Y,>c+KclGsP$eiRi+Z^1w}y2[%Cϔ]/̮ʡf^I1OxA:kD!PV3[e}YSZ84}h2DKicGtlGrʡ8vG 6~Y "XXԝ.uHZyz|V3dRܶ( X;1%oIQDVGxu=ߕHIxcog*T!\c-.2"W) _%O1杷1fU誱N^Bz Wo,L8Ά0ӳVLc{2&Di 5ʡFh RRj) i5IfPʣ^$ 0gDH~ݧ VnݑEwb 3Lr4t8:ֱjX8N<1ևХaY۽7YHC9Oj3!)*ͪQꍳDZ}}ĵQi>kJݣFO y״ݘ)#Pu?7ZJ"EQ&$#\R0k ̏W+z6&bSR46^ήsB$ }2@]La7nlF9Z9%~n p0 [p_)C{27p9U\F 5R cReW1PuN+?,wm|J 4] GZq[/bV_D$_(q hϴВ@bQ\[U&#0VbpPuz]TwFIIU8}96tˠjCv3_ (/ e2dgHy_H " .*9Ҏ='b9Lㅴ[sDZcɆ/#ݕq?.~ ϛ[q$E.p1]P%^SMh յ#N%?4u}J6ֵr>Ku$%R)7T0k ПUX?LohP Xnh]p;(c;jQFofI»Y3e'P"yyأjóOTm$̫.zffE«)H8,+$19b@ 7Nx&ʏ՘vfK6jQ{jEHL?UCpʸmjzA.vq[AGn%ģ%qmE2P=Ŝjo Z5 {{Ť[ڴdP0NCUmKk  -5anB%.ߓ$g ,z o+nS@~vP 7-E#vfI#H[\{U^P1 \g $^s~y+ކ!ϛ\<ʺG0 &vUc{ [R$n@5m4\ٯ7%Wy4s)AxtȺ0$* EUw2)7Zol}WHNTX?Z0K|DxᓊIde^vi;@V~߮yP Ql #,; AܙK>`Ӥ6'~eD{>繳{ mӓ!3\>sJk<O?%\rΕ*$Rةr̽v;Pj4Ƌ0coE4-̥D"!8(3 kKwjdaCzpbjp-0er!1QKM)ް]JkXw,!8i;;7w fhZm@)sSU*W. g[Z"lE u5Ý'Me$,$|ᣢ'yvt V! <]~ _+t\5V҄ oK@e >z*t$fRئCCշaM'.;zmWOykMԭ}c}TB|(ZoG2+lDW!S6^ˣDeIXzB&fpb.lBapɇ%~(%V Jp|w'@Q,VI>mKtPnxs8[]Qz/~"?[8f^t5tBջ#[ЯrNeX{oPr"_ZWRbj?'6I=`y[=}g;ch1t󌸎 I"dyE1<O &c22}RSC`P𿶟RY-" ,)A X sF u*I'S}|;өڷ+ 40_::XAxRh]PVGزۈ! JthLe6 soabȽ-0bPYQY?St1o/U^A$(lqj+kls [wW+a[ 5Z¢QiXP4>ogyaR^/B#n= on|}GzP|JwKbqХv8e񔛖lpΑI 6z?1Pҋf}cLfEh ͚R u-g;~ 6Pb -sa6; {or L[ vD)(yIAdy22(& S w]3iQPGq ՃuR@Wt+RZr NK7dS\}Tlm(RceˑnTQjowۻ[f4Gsos]5*oYkf. HqاCEpPA2uū׻%OmHWTYTU kd9xGLspeH8Hn;ϗy3 h痠ƕ_߻R"+h5MlfPqI/0ûEz*yGUXRSʄ1r܎N4hI 9?ޮ3 H:xii a .{mFgAW ހ3B"q NokM`n#R&.bO2ݰWYlt%\ú lejd$"@6arVH+bT"ɿ8Y7^&%/-j9Dm0)zQ_GZJbs~D]ȯdסfKY 4Ǚ{gvTSo͑[Cwm|tݳ_{fWH dnGna-ӃGr/߁qO;Y? ;[F.k4`d\_gM}&UU7ai10'uD=>ZWz"SqI8M{,P 10:jN ˲z͊Lp2Qݗ׬2ُ(^w%KvCOEh@Cw&Fa fEoVVClm a;&l _Ksg *&Zi9+|bvfuaGa,ZyYi9Ċ(YTYb_Ms)QΑ*B%F5Yn*-4-0~䅍\`SgrZIܼ  e׀Svy) %{_8rѤ<8Aamr0<R|༠Yy\a;>δ̴Ǣ\Wh6͌ " s;@['üҭRFhg*-kP }eI z/=cl;3 ,!@{y 4x$#$=yn$ƔE7 v@$0@f9czP?sjTDbs򭭮}@ha VۻqiTi&6Rl"FjTXg;ӫ3Wcƿ"ۀ6h[Z~aKbS{4LZaRne X˪ß:IS$}bM^ad,M ؍8z>rwVQȱU'jZ?ogeZ7CnA@Ԕߞ**9pؗJ,engmЯkDmy_hmNoVB91<"&xf0:0ZcM\(#΄cWf>}ojYA;!2gܽB̰ҢרU]HorϨӰBD]rG QM?1u^*9UA$*K\aN yαٵ1迁_|{ H#<"OG(zGƓ=;M57R~Aj^[K[Rfb?yY ѓ?-ϸFDԬv߂ }FO +M7J>.rŠM1t`Z P9Enԋ}x)۔(cXcڂ\n`\j`;|w/SSť:Flþ݃6 #|YV9qm-h+oyG UNI'}?KKXIO+k/<$1hPlx}j_(T| }8s\Hd̠]M',uڬ{LU kI)j{T/ qNypDi޽|LlBj=b9$ix˶Jn4|YkXC,7Luun%7[H%TX;<3B?(N3WIAYtEl_Y ,V7*$vc>`# q?XMUNSÉnF m!7`Ub}a\q mf;@t,=)uCnIPۺ2WEfq7`J=ㅺ1?$hl+%1;gqN1\jZs@{)qGIP]sᣠCe"(ԌKfq[}X-aNpH56(fӶܼy^9*ں}zɃgme7M0ו_O <33_:39zS/U}8D?lͶdT]u/%2iS LZ\Jb䏮@m h>ҟYu'qc+۷eAm>]?K 3laS&H"~f1sk'WK~"IaHPj;eUtDL#* 9ȢSF -x&pԊM4ZgïŇ4UL%e6\H97v~Oٔx AԽ<:-?>.Z/R%!E Cٓ__ߙefS,+{ T=R6[ß~'"fI?Sn3Z/ZR֓fXHvsI[jgj0/5ZVRPpq7k(&揿8zA4d()LPXR [Q1Bd180%aʧOx}x`NMUg&>5Z/zZK~[>TkyK?uwS6k ynzI:zkS ffm)Y.s0*Ĺ";.U'iTZzZϊnΖPڼx\c,Zke|I'Zyީ'e@3oNQfP=DLH.Ah&`9~2|f1=y`bICBd?2jTnUnqG5p нCѣS9%eW?(PfFޔE@4'ǾqLwF֒xt d)BLL,0Q> ; Mg7ϲMXU$;+}*7#!8/ܴ=Nr1ca͂Pe ==,z& >zxԊ%<*_]zHTb8jP zd RzTt!nF{x괺bb`P wxӤaH w].L@YP3~y] ذ4 ;p 0>;f ݒ C_)NolfSbc$ v@2\Y^/w ]6(Nx/8޻$py&a,4>PmTb5E3 }8ZXOhiJ Z4g:@"Xw; 󑌕eIcS0S)y롖kwU' KB{D14=Ẃt&>La F'c& t)oA; p9bl;{%u>x%qe3)P뤽bӉaujL+YR d禮mf=Bc(4Lu |ԍO*G[dճҲRj% TFP§OOB-;-oGH8uƙڥv+dfxQ#>L>$yfdW{SgY:\e4pȉj$t6eP"u &sV"vmһniFg/yv֬ jtsJ[G=3_ O \oNUW-]Pg"yA췃,a!UNAv5t 3fq<M E7+ $0J58b&DoP"#\)6cQ`ijs;.ơ0zLijm ԙk6uI/ظ;"DN| Н­(Vi~*6n)kץKXV2SQfH[ђB#7}]dq\CJ뻰|8LEL"y^A#67 WA/vݷc /cPTPqU}O,oz؈"V)H9a KоE9G8CpUV RYEHyz*˿3dtL0Pq +ͳ*! 3ķOQVţ[6KxBcqq/w#۳` 6|Qm*0^%bZ"+ٵ[`r#,?(@Zj঴&B<=?6N;ịͼ^@d-jeR:= /4x/a\MdzG[g'R¤:f&7n/Q;W;c \L# rX⁓)mq. eF<AANUcdADE )vڗ?ۂfI0EeCxϤl1H24—{_4HAG֎+b~\Lg XÕA'%/X2?'g#H;:yCUg[ ^BVl$x[ߢހwrټ=*l\N6x@iV*gl~f fn#Nɣ25>hF]NQ^{˗ʚ=Y$5`#= "\7'W!@eY$_w#CrNM4z]1V,qV#9}ƾBYCG:t%?YX>i 9C^_]='zdГ{g>8^O18eY]!(qւ)ɧ_L,q ҷ)Yƥ*oK#L)pO'>Ð֊SHHee Aa]bFL tɁ18qL7#Ybz!v[>IEsSr@-H}>;SUUHJŝZ` 1&][)u"Ć(XHVj4|T\=8Rq=D޲Ap)oHW\j2srwOb0 IJ㤶Ǵng& 2> `qpVIst$iٻHe,6RR1lL ^72VQF+ %EC.>Y#29N8،"̪bpF<*ff*X[kqVՒ,hȠjғvPj_Z,vG%R.z蘴Wr#8ESQL c7][Kw"O@ct}Ibd(ž}x2Qr1RhrX$*Ϯoue?UZegFŞ W,}jX?6#?W)7@$=WMcIe20"5b3L?t':FEOę_n-.P52cV X^?qxw5)]YQftO$:˶jӈ_~<̦u^zY 3?6zXﳨ11b?W68dƃX]t(TgFp_3 g\9)}3LYNi-{!ǰuP[/yA!aYrG3#i#{z7sͰҿxjmO.MD|uY%S93rh3Ίܮ`N",2ΉcRl"p]mN0NJY)B$a.J-cDҰE|2BjNMbαcsIz=|r+m6kBzj 4t.";>b}A몊Ÿ0Jo@yw;̇o4p'Һ@6?I0W6Pgn;eQDFpZ@'uHf291HC ;<=]`UvEbP 1. ? Ǜ"yd03887JGqo8YL֛N `sTCS_ ΞC8q>Bԋ{ȵ`3fPjՑ:q:UE)LBC7bgȶ>F~W3 ,^CBLݕe_Ħ8WEOZ[p 3*=tiq"4>of3RGH <G ~ˊC>`9x!#_f.:54~VB('fP~X+Nа[/Do0'_90y*;MnPK"<" T͕K]TfۡmY,_@44%^0셄$x_,<_qYŖC{){Zddz.e>+Cy0F d3rTXuqL ?2ݨ3n 윫Qʇ0^kuUMr]6i{m|8Bý!8'~뤹jbSS(!MJHˬRiGRUӸG ^$+) В=zVDAarxYy,jPIv򊍂ǵukמoFkJIU}J7RohiHCۅ WV#Om7]x6viPih>$4+żDz-4C&//4pw1f$SuTj9F.9YTX?#O8>~tBQvlAL_ qRc+D iG& ú 9Jc[2SEhzgKBO pdQfZ!GyĒ/y*L"=0gcnZ_3I?W:3x}k0.q6•&1]ߨљ'0wHG?Uu즳&L$]=Nc! <ۃ3Ţ!#TI6LM~Xwؘϫ)^CH_&lDB2r' :.[^tNV΃9gW(Hcm X'e4 TH61'f%Qg{ Y#1] /CW}hPmY̨:6طH ZHn'Zj.w)zPyR^)zvAN><+5I՗j&徆J4dU܈[psӗf K4SR{,<7glE<ݲ[C tCXœdžZ$ =`~jLT7d\L Hm*3ϸ} Gɖ`s2t5[[ )c.HIB(e?lNFl!طQ'ڟn(qY҅ dceHLm~@u;O ^W4옉ORpbkڀ@9a C9~]J Fq8VwzStڜr$5Mnq|yR$8Cz ع a*׼%YqʉENr7"lQqVɥYN6<립11Jy%ܠV|&+3l3'K \n7!jD(QY=s9zcpiԌ?ݹr1+g=O}mDc><$1F@vjFtӏ9e[7 En 4R-7* Á|̫{&T j @t6gd &re~Kw>x+W//}o|#zBUARV2(kE- pqIne!H)noķFH Ldyr!W>Y=t / ŗuu#ll-~YӁßS^Y®X`;ݿ1_̠H3g]+R.t #gn>5+7\1Q[0=N U'y _-9O )ZfC5 퀵g`&@ߜ"W(ڦUT-$4~#8,wmiPAㆆ\p?bD)>wJRջ۾i4è+40zD#*VNJ>=?ԣ^bPntjnp$[vϘ}7 isJ_D!;f-[g?Wga5u_ bҠ`/^Cܟ\mT[1 >&]›Y̱S o\#ŶloF9_~XSd3Hy_<蔘eC" 8ք N`[G_q|Nk^!yh4os I+WH%# >2[ CJ #ݕE{b15oԂX>l מRڋv"{i(KHR$M.)5`hy #Y8o,2rʛ4$jǣ=29\1X`Fq(һ- O/75^ Ђݾ}0)h1"yz>kNdA'h;,Q;l1޻k]uyDjR }8sQ;)^ ³Tlb_&-x,i2ˌ>c&P T(oQX4Gj j),FS1< VD7=D02 #>OcNo{_~|H~!:Kl_ ~*Rn;MKo21r.`*DLvd5HKHH;%H]7ׯO84fqHucE^t|^V@p{G/4&aHYU(ݍtWOWÕW5bd/Wv+_v:ANe#;dNJD"ѳL oK.c}~|vX%kP{xivGX?R.q&]4,#zS@87ڨV: T-U Ev/֑UCuԔ1 VGd%FLTvHzlS0I`l"aSxFKvM!m]C|٭7L,rO7.u h8l,U9,d.n79J-G2M>JAC{ß݀ǃx\O|K2gw~6j6ʊ]$\Ş\xaR~_eG~P%k&͠>:T*gT}2 ^aϽgڇf;>ͮ5jk&ɑpe"3A} 5 (Q1Z% %=a") R{|xG?cGHewj!{&9b'K6/L2ӽrݠ_DX&W!t^@UWO8tKYz?R2";)E]!J~1clst@u7f HlL Slx`[勖r0nOFOX;3^TؽBor4'}7z%J) lz-. f`*_CBx[-ϋI~=]Wr{ SsР'W  ^<Ň?˖"{`6þ3BEbEHYXr^ry6- cζ:/Vb\C̅VX7~їt@#dT(:",*7 R\_Z zkG 5Gr/qKZ],7IB |aHGdA<-?|ƊP(ZTSGc=/z8jy5]O#7+]&Ÿ N$J3I.v_EQb7G}#/37^ @K> 8S ub+%REaIJߢj(ؠmY>H[iraXd ?)mN-+F{T.#@z8ϐYJ~Y=&cP|euiш?Roٝ]86zBb`x+9M(xS뙈'gAŮ=pʒĹT؍3U{F ^G^#XKlg,qx: =sJ&֓&28Df%d`A?/E<&.|7w2-0S0K.?@Ȅ=m߃<3 #>ԔQUl B9aĦ܏FhtK~AκO`rÆ$;tڴYF)&qƎbwKtZD[Ovԟ9Su]^dYGfwVnny`:>,I ^C<~s}ls8z&ZL[+ V{QE4D]q(|ʜZUD뻩N\3 0Phb}ӽ$8Etv2iF႔\ }'SdB7/#[dFqi,Ԩ_ۯA=ԌEi Q߱IA[ΛY K#ƒNqY۠56 30tt!`%44Z`$JcBAh}y&( ݞxa+@tR(g^jr 0aƈb!5{}j\n2oJS}Qhmw?op^)!>$U6u5ذ2M8%;A{*Gwnv@CX&ReRwj4lTׂtLQt C37ć{'1w1^{#O6)Tm2)Mj#=hpTuT^)-}.HH]WcQ{'iW4\>?5 ^Ipa)GH.A}=D{o$Bѡ4 m9̎ꉙ+OFy-Ə%La54"mLDf,3r}M YUpPՏEĤ/֬27P;xhXr D6xXjUTn[e M(4/0?T!^~ꃜߵh ѯf\-. !k;0Ҥv\ZAM֖R ;9Vx*&F5B@m[lm:dsW櫧ukM D}}L5eCY8CDGjr :˭`A.Q$?3u^ zR b WC;S;pl\ ؅(sY4f>WڍJO'YB&Y@i*Y}L2Ĥșœ& z;~]T]y>)Imct&/t!N 4ac^AS*=AvOKݸs$Pax;)־KR|v'U#-lA,^yxNnu;j>Q}8[s +M>nƹg@QOX'{[yEH&]܏$a7 (һM~k=ҹDmkƹE}""S78!ؖq|#t`Xz$UΥ_ޣPtYVP;q zRaQpx+'/ v|.,0|:MW7CҐ.PT]JQ`D+'}3:͗%pRlצK["jkU5OZX#AOɃ1ҐDyc8P'z>h0-/݆J6"n25QS.2BN TMVDW[.-5a&uƜp@!Q#5}f r1quɉsɨtկ0@'z60%j?9eővj7V'3R5:b2f.L8O>8nW3Y׎|4& gE#-gZl=UuywD6UxrkӾNKjW<ǘ*4ǡsZFHmF쯔РE1p/pLFQNvJ _H ~62;8v\jr*-ZFk}a=;,rS25G_;]6hnpꃥ&Mϙ B*T&j^s_Q#^Qsҙ'JbӸgE`W'}m ;]WBeW~h0AWQǕV/va'`oUī*:X,﬚R SD PEFC(6 qq*)wdOܭə9Owx[Uց6A\0 ]\@Ej |x̴Av9iugT }* @MY*8"Ѕ{B%v+)_RaNs/} "俥oܫP&!qnTl"› |Ì;Onmډu QJ= =îRlW^O8"d6Gov dRiPHo;L"R~7qgRY;P˯@NqH*Bt##5#*4%' d͡K)^H\2&+\7W+sןJLTI,p -b2|"G>bi=^ >\LHn`G՜qk|#!@شxxQlDT&nXa0=~]wV (T/\O˕Q|it7zѿ (3%Qd sڂVVb7:H\Tx}1nps8=ލL(}^-Lȧ"mr,%/i .|׵N]'tODE*C B W~M+fJ2+BƀfLXa&v1r.H Wt0XOۖ*d[th_mOG=5!(^WMz-"U. 43 ;,eݕUIXx.b!r1%Wqzފ 42[.ͭS_ ;h?2׷-be(|Pi2&2xnypJ=yJ*Z(Z̻.Ȏ흂|FtTtle E§'u Dt~V3l V;c)WC7ZcۮvYDSvcſxq<ԡ#CmB MjzM n"3C!f2kK<ZW& o~ĀVԈEh=P7˻,FGQd &ј 3n_+@:)RQ]á  ÒJ؊SU_k9$32-PdMbΟ%/}4`'74>TvLG[F'k6/:e. OL0NK "+g<396lXAp)"E9gFg6Z3W.ٰot"04(ZC[fN:QD)-=(u]c+$&}4*ÝT1U|$+xԎoX/#C[8C9'PI';X^"?xV42#ڭ^3+(̖i{Qz>x\ЃE|5 86WYVQ'W^d'R^+8`R 8< l-5`R@K'F)&ٳa<Ԁ 2 nCI8[Y$_+-J5Ͼȅ^UL4?_bʃڗ]y/=f0~!+cP60+B&ؖBW7y4^:ξ]^ n=̪3F@`zaCP2c6r AVJrnuEA,+ᤘN[ޓ[S&hf,« rMD%EJ?F2I aW![&IݏbN= ]8H0iݖ^!i߼"&ݪwtZQF,a<`zb9 D5-!Yż&bYhy$A'ٜ2w*kPy;!?ƤnP VXcuq"j9칵!nն˨7Cdťx4Fq.D1.bnqGE+X;D*? AX"K'(.m|?ثF9uQ 8uX1f+ A'^L}tJ _{%-W(_@zd^F>-W_/0; 0[ YF(=؉gM0hfWD&۲Tgg/d%Nz ¨V懵~f-'ͼkLrY%.4ESBӵbFׯE(QdNSLPrl=(͚~Xwv+f@7.͐¿;cdQ$IhQl Hq7pcz3.SSW1kS]_]`9$Q_a&]Whߟ<zY|+:nnb1MN60|]==; sX^S* IJ)-8Jzl4M`姢G';)qpY\30er}ӋG{}8 +Z h*ʏDEGY;R/EJ5Iy?~%&J&{me5FNJ }EfxNd(j 4;4t.hkx5ݠ4o[kCO}MFϷ)"$`h7ߴE쁌KNb]&`_1RO\՝߹L/҄ՠP%г> J(?SSG~@I{PPP`ɱ#/z :GLSbvW`:65Q_a2F8Qo/8'9OLѹY _Ԃ)^|'!VKׅ#੾rËf-)Ȗbא 4 yX1sô;ޕ%@80Rfz_Itb}$B`ZW$2?gH4j1SS(Se|h6!QQ08fE23^–uQ>Q]Vtr" @_ONX3ltF ᱿k2WMDuK|^ =O"Hh17]n0\B6X6Th#gfГB'_sɪQ*< >%Tqə`E/h9 Q-=7,WE)j@nxx&V՜_oQ]Ð(D-.&GwY=ޛstM=>grϤaXF{%_UnLn &KKާuA!9awؿdT,3K,B0,DM7WHqwW~Bd9pOEH{@ ˴FnivG" +LzӁ1|ɆrϺf+tA.=0G]vQA&rXjj>SP3QKU+@g >sN.![($VkuZ[ZwgYUšJA 04bWՐLo3&i?L6#ͱn?A9 h?iWHt<6S ӒEfIxPr@us6s4{1@Hu6Z~v|%J44n)@݇sT5=(,͑r9rL,@#FT4|~<ݶZ{g^ab ±ȱVh=mSa i_66]Lb^yOEBiZ Im]bʚ oaJ5w4b%PBzk lj68\Eu6LC^C!qǧ! ˁ`IZPda 0#0ZSWLL H7,Pynoƈ> 儜 sOdSAd|W |[D`~] YcesD6fp{k YnЩy$M*iUG*hj(ncOu(YC>C6zBj֣tMK QS΢=)K߬txA q# &ܲPY@S:z(w3&cU. OYr- x *vmhe}bѮ8ŜTZKQ6o QMyr(r]1k%ƣcZ,#n6XUQyXz~\a<eiئoZH=2̞Ģ>:]Y: ?7x!ySxi$V ~jwp& ERWsx L JQ%FZd4]ڻV}3>E@~@S u1/E(ڃ!& h &\l>HTfۅ< GbM! :qK}}UZb(K_"mwm2%3xBUP6yc"鵾1ov x4+:oDX\-'T0ۂq>r04l+?2>ـ@&&E(C۔)`c$"\bΜE/x᧴NpAt>4oI E 25VR+v99pɉ^3j-ѬLpajU6u˟ut=9K6`}]i>;#Fm-kq2ts#ɰO#8$!!#* #&L)e}vm6r!eBH8/c\Xjut>ip?ad6i_^'l% "I)ژ/o;dWxrE'Zx0)z3\&Hīf,/ 'sph=әM-s=5jEJ5>f4Wc`-|^X{눚&wͷo~%pB|%0INjʽ:)d |tt;PF7ĻwNIv;=Ek^yFsDd) U}G\B4r@ ag1+; 58ByTF[>Vf68A`[X}tY1 l0P<'1 ]'IԠ )fBDcBFPĽ^ʸ٦OS^.qQ*2z_&MNp?B+oXbԗA6 }) )`ZCPBw`;'mҤi.oaf.*Ҋ(Ot+_b9>﫬uyK &ջ&J;l@ΓJTʛgw O*sI̟rP1 ,/iG_C"Y7yeKE9O M1Tb06#LvՑOȹcڬBƙQrz.TIIEZi^QsBN~#:gji@R) 쭜vĀ,9(<2Tӧ[.ʼn!ٲ0,Jj7-Rnd8HEPWfhq)Bg>8bwHXkD;xU0Ļ3dl Ssd.af=,38ޒ(n _ Ver~Ou?[8bYVE3SzȗgGPABB$6$䦬cV#UTohnIz5oq;U'`xĐ,=ݑfݰ̣^7YR>,CjyKv>459%+[5nS Ԁ#81 LxZZ徕oneYdҪވ^%KUYZS|zeCJ)[pT(@ uEzjn\?G։amo Lz$K 9J(v&Ccfux+(W EQu5Lmr\~c0w viZ> .zi^kX\R80ԿP@q] 7pj=ҷ™;*43nZ }ݶrze +OA_I (.O9t9F(M=<5L?-ɱ}n}7ylW3Cu}>A},4FE"ؤRd{'ϻ@,DVdcAM Z9NÈ؅o9\3Z.d,VQa$py=y26³wYA5rgS# f 32t2N$L*Q+oqD1(068|CӜ'_)$qbbpKDDmv>2XOwvK7O_Ȇfke@6aMВo֌c@sI4M\5NLT<OilmE^q]5zsLOx7;)iاiRe)J$νN|G &sCGhQKY]'cwĩξ,"d3T&кuPO D_N W ۙ\CU`T&ya/F/^YTS@`wtjO"iN# 0F/y%p6hLΫ?`#v"tz b`DPy0o4Yڀm y' LM=VO1.]c0 X0^+˚Bu}M(uÙC X| !| *gwRS׋Pk+wA'ůS)ԫl9@+y;)`pL>Уׅ5r+El"Y FfˀY۟ᨠ)|"3d(5sD`#AM7NqԹ:. 5S4oI8ͩA&{sb&,J2w(U{]a f~|jptk-ρ'3{/\J;Hcu}08yrC&($!zLiwNYNG=N5H?HK ʞc<֎BT[h{^%6kjתZQՑ(v_ Ɓ?6.NԵҮ..=`.l*ycc&@ gM?3{uQH+ԈUy. 2q}˂p<&w/25i@+gtNn4;8]TY 1xMlRuzLvCQ򯤹O4I0U>  ;Us4t#Æd$Ou5v:OJ"S3o+. FQ^l</"4k,>ɒ&N~ zkW5H NR1O#[)G:$Uo7+IFȋ;l@.Ud! (`daHV) EnnI@ i/Yqt$ zN&}P2t"71"9!VĹt\pRk  M/8|$g{P 3B15+wSoI"sMgL^oML)th YH;ˆrz\~!`/ g̈́ڭ#q950F,Om(ڃI<.`{=bՏC_&ǵeX)H}ўZ䣈 `֝鎖鏯_PHt*n qPRAM+eN :&!.j^b~vx+?Sv>V 3mNqm1 O1K`I96)Evb YPA<@\r+$_Nϝ%/ry`0 /R*Y`rRy eyon y>?`lCu ` dnG&SԽ;wؼl/ZpcᮠCkk]}i‚&. @OJ ~ ~_מ$PatD(Zjۚwq6K5qU랣$3r;vTSxek&-P,]/zEFTQgLRd0a?8wv(,庇Q2P$(QPfC q e5Pn;V(ʹ~'x7 \hvzC|3Yqe#$\0D[\AJ;*IZwNt٧ċjC[;L]/av.4a vh Q@"θs "o"kD;Aʐj`fNHaYw.Y77lYDs@~:H t[Jʹ4&1F8rC?I㽲4i{U _=HqrVR7s TVX- E:+4m](L,>i -IvuZM&7Bw,w'zJϧGW_N!ԼIU2tF g\$bKKr:K^}0`;0cEs/Ǜ0hD ; 8*=Lw ."N#Fi@Y PgJiU_ ZqnCK(ٞ5l#F(=moS7g g=,Y 'i SE{D~wN&#Q'фyum0Ϳ9qԯϯ5wfQ,}uK; 5KvV;NH3Ήmw}b `'v}7Ymg qBjGT(:Pը2=^od#WΉ"<~#GQYvfT:} hXV"*}V}t ol#pP"E&yZ},0U& #m.1h )~-%N;i# ޭ~gv6iP'BzDA; ]frQ3# XK}x*V_@9_]3aAXlNP쏅4'9R)R1L@JM3üylKR#21(Ej*ѴJ=;Þl&Dg=䉮&@=U0n]&enp-2Ǯ/{BPe4n4ïOS҂9 uF]6I{Qk9ܳOL'O n!sQL`XSUf%nba[>ܕ!p0|ݧN,oW)5Ѿ᪤A p+?|e oIbrs8秷s>1R >"^kaJ ZoH*I%ZW0*30Ƶ)ZD' b~(JL{gH e 2`#e%َ 5?6z[>ȋ.Ѻ< .[CwTCuGASzIzlg+>T x|Odצ`/=BCpE]ih|t"3I`.b.Aw1AmUN^u.3qq|v*]eg~g1չS;n[gJr[n iVlsZ s[0rs4v I#%3GxBxPm+^eNImf9yI Rsf{*|sKa$_{2dMGWE$5 ]Ma$bF;gV\W#XUUSn8J~,^guP>ˋX`'󧼲B'RDP7-aCWM|0T"Ej@|uH'kUʿM0Ac}"o1KE= ^tڴG)JP<^fHY("QԢf$Ⓟho&?*K%ysv/ß?;AskF?eVBr\捥֗!"&=^mVҲѩI ES9CKnCqCQjsZ)7DGl+v:kman Lfb`yvHO ҫ3%;)R`ր\EE݃S%U6iC/8T7dHZow7f"2Z5N7)H~;*DFRLi9XEhʃy6;coPx‹qڕUbC 3k; P ĦOzV.=n` AgyL'#k`[&>ԚœڼmXVnRXʏw57Kb/T׀I&Ut*mzzRk҇M'[nV1sPBܰ<,~@Z aR N=.p ^":T:%!yYAa76ꀝGoN?4u!+ХyXqwt:lY(U=/=IZ׬uS R{gKoҷ1].K(bTڋ.h{RGY&lʆD}G SOQ70*(tV2m0A)4\D$d:ۋoPBX=ty&$ԟEpt 2#Q}(Sqt9iXQ8k!YجTjxR\b#5i%-#i|䟺,3Oz'n[[WҬp,K9C핺C*=;K1*"Uf!)3}W}˭0 `|[]C.d>Pt6}&h8;zZ 8ȫHU3D},v/Y$18|L,ȇ ;U げNJ,DV=Ej wc5*jW >]"ʙ,vEW$R$T5,鸼9GR4 `ƪe š _# >Dtz+'eϏs/Lkwd`AU|ѺK+\]Q>߻A11 #[;IՖA5w;c9:YM6;M9zox.,vwn}% OMX 7msdR.2M5~mv]ƟX)ؚeQv $s8zu3`-y֝$sԬC"WA|Ré{4ф)ZDOy-.4]FZz{-/%)ϡ<ž&T?]8l+c֮xJS DZz_6P6;~o儐ck $׃M󉐋axU9zΪD9wUr>SfdXZ -S0J4jej 4>r8lߎ ܐ*v?f x R(ct\RiҼ]q5cӔ#aaŅ0[aԚ8vMM礚[uaَd7SKT)g:+~u0RNE^KQ'DPah;􏂫BȝO=@47c4a(A{eW*Ʒݿǎb1N6cd% B*y#ܴi'FHk>Ԛ݆ߺb\Yob5f}Ë2PQMztPiL'x:FVڊc E*nvD|9]:pJgo`Y[Y |%' X-QpP[>[$(b58gW-s4Ҡ:\Pr$El}*~ H@ U-֖xi})]TUkÖx! 2ebnsm~;\`rxRZRy7ÎXFbhXh]Nt<+{wiJ&A:Ƅb=$6ȞGbPx $ůxOsL SwwYlgzn*d jaZdCC"gЍ;fDdj $Dy#(s2D }fca,"OӆT^ė]Z)+rGdmOO^+$aPOt4Wߴ@%0 -#wB>(stѼ:jR1OfVe.]ϫB˃,]&m6B!g؟jMhie)R#yy zi1vGMڌsbt~-s,@Nņ!Gg0{)հ_[%rDz7Dy ܕi\V&33Apl G4ƒiT, |^L1DkpNJ$|_ {+/2{ky &3O sUP{HN%Rn+j6az/:cn9fj1, dc FzV;'! l@t@Mw¡x[[Fwڿe FݖrH/.M6Gy4#s@@KAw[g[$Z.!F.=X79Fǖ5:]O4RP}V .߰RkCoSG%wWo7Ε,݂+(] YSAOv 5Iv>xEaZw!0jۑef'ÈSANtƜmc\ÐA']|(5cXձsZfUQk*9Ǒ8M7R7̳AqP-yV12}%",NɠmV޴f;yVÝ-upxc?ڧʹ'pD;L(_`Wl3zPΖm-&9RJQ[BZXQ^P׮:$U|CmpC/`OIM|y/ׯ^ܗk&V{# 34-B+ T uYO/<k\tZ׶FjlU"^v]&D٤C(5r̝aՍ9Sٺ{*P)@g0!Fk6tBT68JFeَ@Zɩ gvG{~H?7=KEPU\` EqS6.!X5@EbMxkq\8H*;S޿4̴x 2m\k-[.kZnCg҈ũʜՏJΣ]x&vy4ȭ7?pTgMk6"Tp꿼?:a3UvVa.:=ӆH_63j*'H#Mɾ*-mIU:YNo}*W6%p?X%)D5IHL )!Aj M|o4pVqUwePs _oS2Cg IIIu8-rczUV6Wɉ0E_~zϱD[יPIsl֍rw^GAb$$<7 p͕fo޳C n\YR*f`-I֘{.0Է P>FY ˖爼S:b0~{ [#T3~I@ILOH_cA 0 9*$ݸb/zx5>b3%Q\f|ȈkI,s])eЂi_tbkq x%D` |2AzN/z߀hZ@(o\ԋKs7(&Ӵ }ڼ ׋ڌح(4H{mǓztnIu1#C]pg]Tp2JX,ለçr/l>mH^>bĭ>o(wD^>''1{=X.]6IS]%*E 0{\ފrag J"qvyt+g6߹Ru W4 tґOѣMŋ${8Y`;W'KG?GkDؚG?h(7ͥ-;F%P1i9;JφKMZl8AX8,OUP.z0@3G)`" h`XU w͓7Ů2l?%_p&^eЬnWr}x(DQ_ 3oCgJX,iHMA` Nڃ}Z=Be%q'rQJ&=qڹ2杆@{v1c$A;t {25ƭ@MfsM>T).2=Rnm?1ve!kd/N*Ě%KaςEZЏk<t1uy.3t, Nj P`AЧ틙yJ()x7H=8ؓ0C5/b>>^A>4l)UJ'Wcp[kfEVCMCDu#8q5x@񘝼cc``n;Hf=( ޓkWf5>q 86y ȵ @S>ⵚWվubIRPd7.ln{ʰ\v4$ gb t&!mPM!8K;|P 1ƨO<Po oiO{.ߡ/E2792E}Y wDEy_=!Q qe߽+8AVE/(#nǤ>/PWK3x'cWHR*at<]՗9, Q@R T!W`)Uh&S=ԯm;֨( sF'9mCͩn dDo5( $ȑ7$= a@DzPK !qnVu3D#}EOQ cMj@y˚7ۃ=Ñ8=["er=Kw"!i#ȩ#Y] VA)n3"ouN89:^^ j9 T<(#T6J=2ڒ0O 9|P㮍e\#2&΁`;Dk2oKRol?ݱ;յgxk) 𖕣 NW~XvЕt RgOzg"l9W+4虝\mxzf]V {ϻrI9L]o\ivp|d^<\>C$uP@6^mY0Hi'ؐl qǕK¹["bw xrPBh&ZO=D] sInҠ Cz mr[EƲfVd E&D*x}o0W)KHl=ҤrCԱ zkj'*E v8Fa‚P+8:O-l e*TH ZʚHD[^EK$zڐߙPM5g_wMBƟdK9B?i~Õ%x;m$M2&RJ-D/I1G~`´E^btѾzkl@U>xCc k5^,d 9kJ@. RG4;L.ޯNeI$ C# =aany6kd f0O_p3 Lx׃PIzm"FR)g/Kpj_.]Ka&3 eڷ7> c&-沧jbӔ e&+[lzJ[WB27 q&;f [h=nؤᐯt00hWwt-j.‚UeI }n7؁%7XGVidm,rىTj6jmC!bWG\&׾F6QVWjSemH n3vJ' ;a˲9]ǮiXa9G G* <ǎZ1&]pe!YNy-Bb덁>XY(-N|s%Wۀ%r%zxWoj>-JmY||FQY#KU N{4Ae&#G lgoK|=H0/ּpt* yj"?N%e&Tx63i(% 99־S_!W4 <0#BqB.+")օᑐv^bqJ 8({X")> k.i_AM1G~3^^j鈴ppa=ގՙvf5}Y|K&h`:,cdh~4aWgG,kLkĉN4#yv8h?ŌNTFeM{բp CU](/o"gldThT2ULҵ9SpCUmLF<}Jxfj3Q \"D[oo5"Ñmwn]Q xۀv\lЎڸ+,")=JGmSaxXJj=>eq +d#IemDe.v9ݛ2Zdw}v$.!l@+=%† x( kOK;"7 -Qg{G8E=ru"bzV*+Ud5 pXoS9egzɑ[_E'ʂz?| vn jaǐ#4 s8>;Żڹ:l\P'q#y$`tFpS{B|7M vhyQW1q4U=^~hrTAhu%̝R[;>))ipy?}O6b)gnOMNȭYcYe*5M !eS7 rabciFir"|o*ԙGN5\DZK'N*Y$U9pCdC ҏ'mۥ m%u #@!]ΐ~xtsn릐~:JCN yª*w,yA}Jo%unj̵lC5:B?>> ]?L3cXH5eJPj_=P#hpu,/:NDҷ2੧%%*ghTڈ]-K|AOtDtsTv޼×D jw^ul#lt ujUcy/\c2죢hOy_3A'Uuo: ,[]VЫbjW^5"4kJ>|jE0?ʥb,э[OHXqscN&*,]=sE})@bj3}MGѩ f"-S H ûztHCuX`4,,"M k0/ڤ&HcpR[ hp(2C wej8ԜIMK-=-S}.Gނ5\-ZDÂ^ц. 3:feaEt«4+VTiQ^OVp}V {ҹfȴs'$c)Z$Q|4d^3Z?&q7SnZfݳv_` 7ʧQ!#;ȞB7|7-Av|#l!kyp|R",*vUU iNri!|<,QS z'|EEp6%zaZ U:)̓tXϴr leJJ#.8O@;擩dSr*a_3o%JlWk.R<6f p @ L;6s}gBr WEKvg85awnɵp 1Dp~+Oh= @oZr 7w-cBsKy*"a9ⅮRF $vuZɿH{|s/+S6]iRZB?~vFCr̤ʷ&~3i,'20zB"6919> v7$.^tQg w+:Mkr\ǔڇ 2'L+lPd1NTR endstream endobj 100 0 obj 74223 endobj 101 0 obj <> endobj 102 0 obj <> stream x]n8ཟBvQXO HYi@#WGt>R4uwϷ?oytnW/^}cZNy:Շo|v/yUjNi%]O| _sՖ㆔_cs^mzWmasM]ǧôڶcsS1疹EYY٘ w#rbNsmܳGn@?@?@?@?~_~_~_~_~_~_~_~_W~_W~_W~_W~_W~_W~_W~_W~_ᷚs~7~7~7~R~7~7~7~9w~w~w~w~w~w~w~tF8#Hg3ٶ l+ڲr Y,h6;сDt8. Pi|Fv +KdDTguNm-^F ̸>-AāNą,ua`ʼnALt&8eM<#art˄F{ǁN tޮLvqpvvΙK2=n=azf1OOg$@;<) bwW<}ynS~y.XG) 3,ud@ژ4͛rPvc1Kzp endstream endobj 103 0 obj <> endobj 104 0 obj <> stream xwste_ul۹mvR1nl۶JRI*IŶm[VWݯ7=^s5CA b`twe`ad(Zٙ:):3-pN8 qS7;Ll tIԭ\mOLb`ĜƮqc?)jncg+μqcs/33ЅBҕ[ ?"q=@[ǿmmL^.c33_ƶ@;ZY욅+@+{s+{+W/@ha 36&ng`gw?HTNW@mW_ 13]BL\JrӋ?4?ET`ƛ92i[9ek_:L-[o)|ƶ.@?+s ;̬L]&@? 4XGD_q׿+u0prXY,ae;?uCk7wZ_~V-gV?9Xυ?t(fkP!?1i @WWlwk?[L2f"i 4Sr5+aot*;X003Ϡ=S߽$ao`feoPs#?¦nZ7@O)P(mW*fZM[ѷRCDf2~` `IMBqa.Ԙu/6hv$=ij]5\Vδ7ݯh,, 8:5K^.]ۿ@/ X ,6^"4J}o(DV#H `jS(  __)fڏȿjIw8,R!3w:誶UaR`A"Ԗ 3xiM̊Csx8pAxV'gs;7 .VHr3 42NJY,HH9@֥!Z MgZ&Ͻ,|ľ+e((y%CܓuOe׃BEȗzsYhT{/hB'f=+_|!ǭn5:3A#..=VxʴSU7u:t%oi(b|u;IooMē3Ӣx?NKN%Z}`h8} {FFUg }Fh*`td>B:jǝU{,<@-;NIS\ouQCxF^\¨ߟc`:vN4+0SIo!Ss6oT ub.ox{COV>ŷ ?ED|_Pf(<2BT+mGD7AÄ*`]7&Ⱥ\mt뻧wi#9Y,%L=L4]d?O5V5,7l@H D`)- tkޤ].HRz';X87~}[V 6]Z\J[ ]!?5c|$NS17y%"ѧ~ 3 R -EZ"79, !ȅhi"1CA{]?P[, 7?hb\++f _tD5mmb;ca)"mB]mlۻ.ߡ>1Qe"D-QX8fzveWk )k# nP esN>#a>jj2Y{oğg5en=IΕp/Y(}%>Zx>5J"kȉS%U\d7 3v Y!f4a3#R大2}*R3#B4ji2L]n/͑naKOG.ԑGG 2`e֢ذ%I:g/oX湠01qTPAsMAke'{[1Θ)əRt k7M".H}4du@=G08ZH|GX6L5{9I0^="ģ1_+!5q\ u5ccIFcAA Kv)j3z)V!cb= FZp`i ĶCa0|`#N v} pm7E5!]5TᢓN.<] XG0ު3ON@iDނg˕~gwӈL{qYZaU7f$ Ueǰ۾!ƹsW8[qM~)gu@uK+-z(;3'2c=\Dӓ#\V, ]ϧ Y!kw&` un$*OVoJ@c̼k.1"Sd


x-jv" !WSh20OWb~2OJs>Z@䤙U}ӳ_>&2%J EP[gXF?iTbؽH oA84W$ 켢zP3blcG.XD⬅!Q5Cbjt*G1bo+6Mk7^O9M1&QYFm:h+G ljG%DʝoD[d\OO:byT-mA!m =u6wDl5*O>a J?: 0o;HTz vf܎/Sj3}[iY wn\ |0չƜc-dybwaR_ų3ԗG"mnSߌ<1#")$"ѣ&gkM!v]QTv`8k hؠ7kٰp[E/~KS ğҷʯ6F([iE'@\ͭŒ~FӎpCc:jC>l^ۧᾤWp+~h"7ߒրpAӢdr_Z ?.=)AMKJ -9e)!őƆJ%9hywp_^hq&Du } 8愻-K ޲k9誳c_HҶ՗O:lS{y8˾jۤ#l`!'hŠ=8,?1Xnf-gNhg{ՇӿI$w^uЮ G}֡ 8 )~bʰ BXwٺRF$Jt~:,ul5܊_ oZzydKntKt.UR7ucÖ3$mw@>阂&SBU]U>!Z<9ȏ^&C[yO;NDQ"4U9mJ S %7,m0M44Bmg)(pיWOkV6i."u2y1-L`GN2f2!iQdt&rcmIQw:=}7{':|?2ձ\.K9[$otG΋$cby1m'X\2t0l:za1܁p;y^BD)Ƒ>4u)/#s+Szn)jkMۑ9#dm)RPmɘcDCMO<= !>f EmøWKU?O/7]& .w& 'Nph=R;W2+ᶷ|V62 QdWX}UCJ mNqiMʻ[zFuOfaƝ]ufi;פ6JDgYT,qx w)HrC{;i6ѬHD"gla]0PHK'\" W(cWh`#r+ŹWA[zmp_/Xc"(zm^h\=i[㧳ʭn+|u-7NpوcGH`ڴYTxcX*_{b~53^G@{%fnPn '/ &ĬK<5ۉ%t;*W CBt8t)vuƍ+ V j( K34}?/ /xnYb-URt~xez40ϜFŹFt mǬ1hT6CV/HD.}x J} 0 ((umVSJp8ڴTj #Uh8f=E dW]Z JICXE[.ʽU mqn uagUdlt<5QM Hӈqck\!zKwyH9lz.8T~opq2 n:QsmēJn{R೵4*nYHW~]'ʇƻ?g9 $i,Xibr5  i;X'ƁT2r' hqp E hI› ; 3t^-Ӗ2vȌA:AoU%g*eoqڰK c?so2 Dr6$ES'_>aH0:T_juR΅ls9Xb6>QKEOnuԐjZ֟.ZX8 EȽLJߤRxP3!RrXesXEu d,{  N! !)G1ׯsZLn,3&/ŠP46,&I6aR|Z4My?ѵCͦϪ6`^T^ʫ`1ɯQSDMF~?''`E3PRG6@PC5-C$Pv[|?8 M3f ~% !%4hNt[,,.=@YCY[W iH Y!F{>.q;#:-G<|BJ/jԙ7o ui+A|}p96jp4wkNddɈ99G<9gw$(I1syAmGe+b4p[jmI/\? "Sx^+S4S)G:;--X**#,{6ng7~,Mnkrٴj ^\Q<1H՗64}yU/) EQǡy 62lvǙ`x5>^XwJ$ pF-8RtlQ= ˊi~yg0!_RXbtH{%ɒx-2Mh#2T~53i=UhܢɔI19n7QuÊBdzRw٪,(ynNAVyݿyiϟ9{ h!zdG^R7:SjI~vTf|f}9KWB&6BZEk4Bɸ=8ln.j~O_?~FP5T=Xlh:3{9Y`po':E'PVDeԧ7~6J=Bo}EAe!GG!"nEʗ˟Y Zk*=cKW'nH>o :e4eVRν~}MyEa9[[M UCWkob{e>CTf\ߨ>Rڹ$Ksuf{vj &: OޕdڜfWL,lDq8W'Žm#I0 .ةfľׄb`;Lɽ2Iq(ۼ`%gBů?BE;35V-^3gQʳcLifx4GXB#&{/ f`V&͉,73]~!2a,x;JK"CZL,8 C$ f+/Œ9f3^*&F<. m2 (?5d6es>t1*N^K40;%zh0.#P鋈ޝ`~ 3/ iwF_)޹3QIv0Xf"ٯF`FR]!TTu_oV%>Zy*Yέrڦ٩W$G||I]1kIsL #"$tu3#,ڮv)GN8ϧ&?G×n\J( ĈV ǁ7b9U0KădݧG A@T-/ӝNӕَwǰӄLiKd/Eឿ( 9@_ڏqYN7 s8!x&Gt0@ ʪ9J5}86Y%BmX@=E"mS?BY6Aqуair=//U(c~=T ֝Ku^K \w@Pf q.Wa2Ic;hJomۗ TtFnŀIJXA1ę%kț̾%9戟,›I7S"U-XjVܤ;hʧ-V||LsfhTH"|VvP6 ?ڵ,l mmJ?'S`J5M"4+ge=~3 ܘn);$>"qې歼*ƞҷ&`eϖ -b܇s 'j'dx4 I6dluv^[E>e@7! թД˳/dqn~1ND8gBOU\ #̲xtxbrm]lGݵM]%\5qu!/.hB֙ Al+[𴿱;9j;~NN+趫IP^$MtAFy-CPGqdZ!1\6`bmJX@)X0X+3*ToΏߧXkBNK4}DVfdU:JHނL5)HxlνI,qen=̮yf8 i(6)U׌:fJz(pJ/ k.5JGRKWߓ`لy2l"̬ ]:F+ 䰩,k -ʩL 6˸ ql2G\0- *mR %;WV m08FYI=CU 8 WYծMGS;Xw?# . N}{N)}x/el"ExP9d "Y:̌8!œ@(^,}Ggn>PȟڎyFm/syūnل;{G~F:v<7u/($7|_ſR W*瞰#Fr|WO9|Uw a㑿ڬbW}E UMh`LR~]#p7GOh+s\\He5Fκy?W~&1fƒ"fȊLnl NApGxf+NPPZ2Sh$}zw@+u>Vn_6>6D)@rƚk 0z.M(1^?Szp=\Ki5`ێIx3sOҶ!sB'9nTS]Oz B5b9dHa=٤$@L_LbǬ+g);5VBXocw@zUi5ԣR([]FgkϊbpZd[X=<Ȃ+˯V3tÇKx¬\IPaG]|^7}f;"` O)w_ }R>ҩ@,qh~7|5DY$ٴ_ :*{'?xv͍oL"HMYF wkÿj'Sf)O$jD}ɦ1h1*4G}y§E8IMZ ||kLW5>ndࣚn;sXS nzxBS<=QDuɮZL*x7&|YڼVy]ai'* j̜A.aRڢLfыn2qp6nw'!o|p3Ӗ[$_THk͒H :(od¤Bz,P SOLe7.s^Rq[m ,s3>ciY!ݮMtAKo,G_:+Twt9X%r;{mU՟煽GU$)H"@VQ, 6|4Tifp+,u)$o객+)/:[< LMU+62-[^*+!bURe B 15a|Aa \J(w,'X 4@(.'r?Q/eJPİg=?Mc . ZќHCaOk'ȣyS33J ш;r ~9~mJ[FFj;edWi3y˱#.V|j),b)[PqeL$`TTKHwpSe{E^o߅*wz7'닒RM1&6YD&>Y8=٫_g 3nReZHv:QpVs,LOƀ*7N$y9N,چI *mɆGT9biɓ^}[."Ⱦt^zB?O&4c4Sf^ wG3%ŋ [5tWs~&8(}g,8k.yA``0q 6ibsZ,(#:KySһO.AQ+1 zmEAt8mV:v"sIOLg~G+/dΌ6JݛxRX$ni3os`e(Dik%:'>*'&Zb 7g;CKLnV1a{핧4 {_<pos;ࢶxxA';6h1st8Љ1 b_n;>B7\<)\.M1rgTܬmvZ=^hZ@nc\ݿuBrϼS+ i>e>~Oσ] UȂ+!U!<:\`k]'9 * TUkB|Ч[A*)7̨7# 2)N&%3/C­ĹJI΂4i9@'R!$"@ uf(o?]{֭%pܓZ ΰl/i`LO/ NRF.z}DS+{'+KkoI8l5BZndLo(9I9\"ae/2l$#uZXX qY/KbҶaKoLDiK3=2aC-.%yN0lZw2쥑}6(l"jRƕ@mk{_/FEz5룟T1ˌFؽ[)1Aʬ?vzi\d.y?_aٹm/KAKb@J-d2ebA@.*>'8x!ꋃ7@WS݊ylD?pDYv'2C"7/劻 T#deAxjz%Vn=ܮ9ˑZwa*z 4ɓ䝿ؚP#q7˟L"`e:$K Dj 7{j0R kA p\C2ow@ eڳ"t; 'M2u$6S<&$ExmQ.~ ?DﺹRIju{SgXCx]F̍A <i]ynVBݒI*&n}]?ܱl. zW&0wBHuILCF!^y25~pts[̫f cQa^й$cɤ1 eDU V51*ȟ.4O3 JڴO0ڒeP*a2{VMYNfp`1qNo,=O=9uAmW]}l>-"=cdI#s8CHl\Ù3Ւ\Aڸ W.aCW&Og0[po.f-y*WH-ֺx!¯6_+ @TND%-BiU#~HdK)%x- ߌS[a.4sUh :\B_'H|0t\= #6uAtYw >Gہ{8Qdђ =f rĠ*ZCx!$~$޼(XJ,hE (M:OzGBSyU_]2SC+c]qk{ '*yY2,0B *W֎-ȩaD{`Ejۋl YijΛf'd֌" 7|B ۾ 4F$y %4бqH?N Űt0!9$..[Å`թSۏߊ4!*W԰/דJ;E1eK{?rgF _0f8Hœ\D"Zuk JZnu 10n6_<#WSJDC? 3~9k(B'--'1Jgәȵg[M!?C!TOm?͞xih}*uKdDƳ.nC Я3EPwA5q\M.61Gˑc}G?j4F@U+Bł )V(j :@I%_).`Ф’MÖs\߁;7l3ȑD1Eb4l*hfTZUQ-cu.~,Qt0ZOt=ZVwv2J-a/⢳%o$/#(XṴdSm%ȅbVq"ŠƬ4%ePz`q`Rmo8?[}bum]7xMn9+VG7KA5VYWZ OӔǧfh!Oes_4z&ZA$ V _['}h4f*)J99dʌ'##c͗ WEN,ű0kc4:q;VjbcL=2aLXbwn|cѲ5GY1է  A^SV6R 4|k'T1#J*`TKdU漺94`}Dx*&! UaT!Oh pT6[2ƥ }WqAgV ty|.{c3iq8< dӆSX+ԓݵL솰>T}hM›*eh0VV:͋%.U F<6?pt΍v `p\ezTMz [|uעJwsڤAH$>xM#ѳw0F~.M5F]!TOfUG5˦\^N)ɿBق Ꞁ' Bzw(,֟h:z1ӂC&zNE6]D5)B,7 ıuN'39^3D1kF|'ѥ7;8tوan'ҰQX,`ORoK} Q_\û)0L;?*TTXvX5׏TY[u ӆdVRe=r ,'r`$MZ,y:#GTp-YM&G)r%oM|P% m Ϛ 8OIJQm_^X* ɘ/F}>Z"c-Yv[(SI.o̻8 ctoo?-4fsFnW<|<x,Y$!(5a8oÙ@5\r q^@.< ϲNujj)e$ුi9Pm^p]n;B3E q{}.JК>Rym"O2(9A* ML3ꞈz>cJԺjYr_YR}]r{ӗGȆVeR~F tۜNB$"y}-x(C[n!d4AK|k&"{(+&cV4;X jG - >JVv 1n͖_4 =N{x7߁p4us_)6;fq,4Rd'F]&u*ΏKU/ڇ2ӫDOg(Sd~q(S<W h)ue#mWBBkۿ;hi-\Q6z Y tۥc'Y*Qݎb<ҍH Z kv%ObzS0p R֗Ôa9%{Y-1K,A\7m;vd. =fGT{hFIFh0@rW.0KhƱxOqY42#o$}oe.2I2^sT b\+w~;LPE3]A)AW1KU0.^bTjwSmyߧu_27EfEqj&W";kĀ U`3@'GA-v!<bS@KZ0*9~l#/qtFXdn1/U׿G/)'^:HlBl,dyurCMP 3ȣv5#P:zOGGB Xc#rn8Alj3A"ke!~|Ak@y1h_XYo0yճs#t}v i.8j .սq2B'.-Etde YUI]fE*}KBK"``u486&SH1,!U#'.4LQ"p7BeJe}0YJ(\#Pk'T^ȒjOA ECI&RΦ86S/YK0h8/,%1̏ayi3R ( GCPقK|^$K+ysI)y}1wܱ HE()Kx&'ĄO]w,}Ff(#Աw_կY/yQXAmIL{B,@r.7lƈqQ~KYta fZM#ux3d#CLM\~ذbC0ٌmݵ;BCM!N4V ^dI(a~jIAP99"!&0#^"FIzSS=D9i(KU{A%=8R*C2(A-uBye!c1M>j3DdQ'{:,}|.}LfO+uЍh!Ε qvJ{˪Ʒg gVEu?P-i,O4aҁV.o묿X"qş=^LE !-4 Fx[[d7&.5D|dS㭽XĶdMֱ$;zպ7uJ}D\!88ZA"iG".9iM3H8ݭ3!xbfO XczƷTa)`D!-wCujRW@J9F6J֚*O,{7$FyEpSəG8]pD}ra<#XWt1atܝڔxV :csRVe;͙݇5&^B6o]qcAXn:'-u ]J((F`eYڼ`_یk!%WxP㈉l .%L^?$/$/8 Rn (Du:,WPxs5_y0%)PbME2mN#\ O⃲1W)F߸|Q>.)[  ɢ!*'C*$άc נK&M;~a!Z@|/T;sxQ3E 5!4;FѽA`ǥ@oW/uBb CJ: "ݐJ7#r!l`n>׼{~6ԑk$ُ*&s TYTZ~EaZu ^$wC{QgzR-Ͽu} ywu սtu]al?~II~TZ"ƥּķYU6]kq"1{K$ RX%ˮyT0j뒪…l8 )DLoMHw1\qqfNiSonVGVLО8e[&|Ϩ,i)}F隅4RX"m6A $nݍ&cZr9օn)^bxHOi@qhnzBZ탱 Sx@$Avh opT?jH]'~*7hmyK)&קRٻ8RxtV+aꮒYafbH͕OƈVX3uy؇a'L92X! JzEH5L5RfX( +5,Ӱl!p}^VA԰mo!.fnD&3Hu/'Zr r= (B9?ϵxQH?XAt.I&ٌ0gt^7uБ,qSOzKT'ux#aZ8*wwŰ=@x³(KNw]ٙ\8%e)ݭ% f溥7IYahlHp7xZ@' 9x1QA; n/fmj֏l$Sғxx7-B'+YiL8{/q:G2kĭ-}Xq'][L0y"<@yXKA)ɟj-?\P-F>=5J>KFׂ4鴩>E/Yqo(}0ݎ9;#gg+GOCB4!6-Z+b`Ɏ'Eq!Pk㵧(XWW8ҳ,uFgTAx^ٯ$v=8,1~M-VXS[I` &.frF<Vi 0Cve(5Bdpg+foypO[J0hyJ}lj]ucs8qE-<!bznط\  8 ZZc2jR4mTA5Y'ˤ.>oFEg c7h55ɷr#  XDB֖I<`dž4:lSQmU^=q("A?)0G!с޺ a'dÉq}@x(M#kq,Տc.ܲdVyJ k5ٮ~4=(#1H8 obD_m²x~(C{bl1,0,Ҳ6BG[Ujln?5.#aN΢[x"n{tʣU%jr+FCnni=$mTC€( >hNuBx5Et$Ӕ2Gp*@VHkS33e폋7sºEn\4 ŒM=oҌs/J708U6ӄym 9P8Yqm84rݥxTbRJ,gK'Gʶ]%37S4 ŵtnwpbSY\XT0.{J<뮄e,k@mAWR&vޝ|iL"is47XR}>?z#^@du% i:?@0*U_8;.7}p]0M.c~0+sVA{ʘ+l=ؠ6GHo_r]g0'uA&},F/aJyhA*lR䷽:jz]`_ \X8E,Ⱦ's5M$_޻ڤ-Ɵܒp|@*LF$~XޝY@Ie:vXظ:KS2az}tN.((R]auκ:={4w^ 'kf>]hzoW/g\ 嘃 9YB!8s9:_8+V-ktDA/B)DcΆ}{R `vIJk<.b29J"қ\U%"#^J (#+Լ64^-t1С6o1_@Rmq2:eE/{9)zNY{҆e) %ۛFA^sC޾-\{]"r=J^/9k2?V>lNĝEѼ9ŦV# -}f>)$P |ה-#nrBix G:F>}ɿgO:fF V%OKl jo*ȟhhY˃JpG7iu Hirs5ԉ5llOXpY/K&jm}Nj ~lk?$pt7#?&P8a7ed Kà{:"{i Pwo- rQ?صK=wh6H(}cKѯŲ811Ϥ/'&4ݹq5 QW,IqF܏xJ&1,v)arT̢f$ngTz$:8l>j#qm[KD!HRdz3YbPR P+"OQ994#CĒy`0 Guɦ\G^hAdZav. ޘg 3T[kE:?{3ѢqOVc)uW\G0 s4CE?0Zrhf۞XOr`Wg ,T ze;4_@GmOD۷Ž?y GNbVW`7ڠ/?v& zٟp#9ݥԱkD Y7Q( Fѹ=O!#p@VBEo҆YӳKTbEG7 2N!khw+Q`TšcOy\zu{>H$Ah1߱Zִ¨ƷHoӅz>2 -[a: 3Vriʪq_NdћځL"& (aVa4@Yz `CBnO$c+G{ /1+)OS 1{:mokl0ng {PB2rw$vv+5nrsk;Rlq+Fv]$6=U0HHʊ.8<'f}m3.S8dd: P%HcG%dUb>cw pP[ G?)|8f/D&ç5.? ̉48fHnPбGUPbcH$G 4~CǜG?0Z_qEGֻBb'\Ǘu^E6Wl[1@# F/?uHWY'tN^W1֟A0s ]ΘxQ1T'I^*ivHI&Wi)"Ą8mn.>b 3eh2wi|R>8>Z~,]A& +UB9ϝ~DS%AFbg drU< BFmu犰̟HZp$ d`2)#$VY`; RrHk<^Iz;P>K9r'`.$f_w':LG$ QlnWrQSpח#!T26.E@si,^$O~' /-a] csD~=/en J?{u+.gbgKSO>ã V]Pa7@uwBz1ӠsިquRٲUVqknWaʪ+)ma<)"5h_잨JX0 Xep7p@@uaYY`4B#wȈo$uZ{{|8qSoƠL]ڋ1 _(z:.Ęח%j⨝ɭ?"\X~}C֚=n+R9$L&X9=H`l\7c]jrzo8?zBX͂vQ/Y鄉${z)E#zⅾ!?PrKf;[?iL,PF-f,rDT"I@2 OLgso.͊W W\kr=~’`h3CDߢ$e~ 0Qsftasl;oR]U!'ݛ"r.z=?Umʹ H*y1_2@j ͍ޢNs$FpC sRks;]YjlsXfca <;~GMj X %Vסpa?#Y̡z]0YnM:}n  VgP^Dh̼5IyJV8YOޑ-}9|qSzDC*Ζ.R4z8E!@W800(i4 FSKrg@&t[em}c EQc,B9`!U`>ǯZ5Si0][^mG{D5hsмY7(U?U.{ӡd<\"ϖos)1ktJ<_BIwb5Za/}0 ^DJƜ#`L~ Ƴ*Y;] YΌھ8 r5h ' ~ Q]٥*SB0-`g9 oڵ\K;z1kV; 1.74jz#2>z@a[W[hŁG1 ÖֿKx Lt~ibkKaJ7#Z9&aDfM^0!ˉ#1c>NN#,<_BJ}Ťh)U#Z<, H1 4B^JG29$BҴ Լ)Wdh Y,)F_)I TzxiY%w@U3t 5fLvظ50⟠ 8AJ)|+5D+Qfe_Frb22KV81E*Lt=AeA1)#J+ReR8`:{ fːF Ɯe}i^FHx6"ﲜL境hdO]x9 9 NX/نXhט/}".(n%W߸;_H;Dȶ..Ce.(_~)֛ APjg(" R%}*qaNJDĖ}Z;@:HlŞ+\i=JIvbR݄RF=Tpo[A4QhYOO"i7$b)ю$ՠކd ;R'@E¡@sD 5 qI:;`t~PpŽ#cVnaM%6/{ײ}Cq ;Ezև7awţٟp] R^E "%Cl6)aHGIꗹv1s J]6(oRINZA|zPof`:pV'i봐ϋT^s!9t `wQ 'xV$?aWGيn)n{2駹tR{&m##p:[#E/Ú[yYF%58k73c+-SP?qGY7rY| c85/jUܼDc)˨0zwdQ 2E<؝IqKkGA]6\ϷiNc/*W|gHO((klWnĔ6Ify y'j**+ W;A[ГLl@9b-Ìi;Io^t9SCmï*p:+=!9Ap;bLC 08i6mU쟭QUW }nقųEy%WzzZ6D=`. ˰Z ׍QЕ&`;lc$_+ԕrtQGyHS? E@dCgի7u(ؿR Cvc-}iG}#L\]HrCᗖ7G pXihԓG (UԒaˢ衝jhϩ^/hĮQyzl6nEտJ@o.#yTx5y{'ׇ ~{!-m=`E70Hn:8wz=j7CEM5m c,¾W_,a"*S;wq}Bd3l,R|t@%Gbxɧ98i;?⪏Y$ϙ?wpxMRH7&-P(ywN t4x"U <9{OuĈ:oS"}ILXPCG=+tsDH~@ )FkG'~ )jYyt''Fiz'=3_^Ā"sid^S4Me .]O`J^Y\2sA*Z&QA\PAL֞qt+M+hRC1n=GUΏ"uY_L`H̕j3r#@Y;znA,qv-zCvpbm!){w3w<`j_<ZvaYSH+T+T Ð $Ko+[p-ǟC2NljVO(eU 9dC:#NF" T I Eq2d (KQFXE苀@;o_壷0RSf'%a c?ۧ خJVL<ޤhNN Rr z1pZ DFS+ٷ@0$n&Xm^zoy3D+ GGh!*E泉b/fskwH E#/H5UeaF9L؛7ZWD-O+uf~/ Ԯ6#貌Y}Qx :z^: !b@fu6Z[և Ȣ&gzrixQHg~Cl51&$ĸ. knЎOMv'#noft+wA̕E>fF]_)f`tTew}3I [U:&P?2ɐ_jɢ80XnIR2pqLZY\-f+ /|&"mסi+A8{?8Q{i1zk5gэh$!-h:Px._RHC$& wa&xKzPOc"19f\ gaJ #4 Fz,}s=>2`=4{ *(*X߂xC!7 JF3.Iȃ4TM))Ød 6<`4>N A`Ds$EkOpNO #xB/6Wպ;@aH*vԏ&Mu \Di)@i3 qNX:'d {7ȥ;\J5nLͯWz {v9ruj/Mw= TXSE˱ ñ"m0Yr/ď *;O9PZ84tw|=E͸Ca :Ůی8! m)?P*nF,pMi|4jv8p/ j;;O RUتV$GqBprSMc]Hޚ27r3 kᾌ;l_L>{tO7v?m 21Ak~BAU:MX ʮG'lw<_gj~P]0% ,J2(d0k7@A~$E.&u24K]ɣMxݍ9%0@o/{ EFQ_7Vo5(S?_Kf9BJY(xS)/aG+bx-J忁 4Ԃ Wm% gXᩌDY_qs1I/M(Pϸ GAUO EC]ii6䝿JNs_{tDgn><ӆګ?ѦB龽n)3dҧK]5P+Vgsq3qu%ˠh|6fq0w$ʭ/SnsS J;S>0OCUH]0Ҵ%J3FG+c]`WR)φX:cZL ѿrNui1thB^<1,WYaJp22h4MZ+ YwZ{7oކ%"]}ַ&#P<ԭX^-}!%u7ʘξ([nށVDenVS +&I<&j4+ d/4NDF6d)ߧ*1u ^ȓeOSLc|sŬ;!#]Z F!@SsԠ.VQO/VpTEeL5e7>P8O_իG1iBKr=5TfΚEqy-C뜊'1%} qXeƳ'MmzSJ|G"7߂VP?=/0X1 Q]LSuKZ[-UozXd^/z.nEXecȣ 5:P.`"lm˛6KGIR0%Gi+ OK6v#w}V.sz8.4jK``w m dѷ>>W?-#:9>џ4)=e"̸L&@ pVioVmpD O]=knVc 4 fWh0N^Y+öP)w_QWFZGiAqE^KV%u|#x'hqp^~'dY{,Pİ8Ⱦ6U>q_)("4J%ʶGIКyr|=ldܡ`65*~i5a%s"{`rH겳0 2nW =KYb"iHX! I&sqQN\98Qt[TRzvTPn@\>%6*UK<lHmh/gqcgU)wRs75Zo<.9qZv^~ G3#Kp20.={wYG]TYt$n`<׵,@emj@(h_ZVKSD"KM!C;X'$ lN B*(k煄.+c(E x8]'1Sz~n$}dk\80YEyK㰖0P}~l#E[lBH bk-}~n(i+qv by[чdQ$#R}&Rsⱃ_.!XZX]r[70^Z& msr},'$ v_s5+"OHbr_xaHLBO+PAqYQ4-/>q^Z/,鉸bv#=L{f^y>/?פ5b$(uU BeF;WŸ )|DǨ&1䲐71( 'DdNmtM9Ĥ(=ʦ#;Ny41ŻpZfll,"6oh`^URD*e+a0ٶU1+'GV|+f@;) 1pL7t[257:Jۉї?E)3g}#Lj>8J[1 mk[)e݀Z#~!夐7g)ڐ%8ڳ˳iu8Q!aW  OqNᏐ bZGIt5uYU[3O yD7 :2nEdTGy/b<#Lij8X>ߘ)Ux5x~TE=|S%l 0H}o<7pǁSX o{*F3ЫX>X"n}&V6 hhOO\A7V`=Cv(mS$ 2+) o.2.d:PpL*7^^i>>+ftU]WTƀ\k*<45s~O F.J^utIUxj)AKXJ$Z9 t+Ig|sXe܎n3D vKI - 8,11T ^k+eMP)R!t.z|m~oU$2L @ȻAWTJyOa %X?K "V)t<陥D">ud0oTF )R4ю\Bn5Arϝ{& \$A׋M ˥nK}ǁ{ݰATlej)Bz$M#慳>1>d@ q ɢ: FǓ6!)Ȓ&Swe!ѹ\@}nhr䘑HʾPʾл!V`J8++ $Z/NX.g,.i*ōv\]s HVo3yua.nndERuMK!fҙ:f8*|XJzfuI.A],"6bH,II.| %`T6 E(#9BۯV,"|Y_KT~Z0:c:i߷F\7̑y>j}^"&?QL`2;!("%,;u? PxqYi9x\":-:g*{P۫.XT!гY6gl,4~B- j%n9bD(1CA JwE^0^diTNS gSXux:hBWE+#Y^v->i>NZt:x$̭2 k ]\  U'dP&^s5*_=9qFؑn _Lg7/=˱gN ~D"^%k3 *Qu=02jZ,oJHd492cF[1:،b!X'`UpJ_ǂM >ӯڳz=~kj h\dxIgJ*UmNAYuoZ(o:^8[p*% Ԅ* wAP#&2ٖH!>9DOTVW3Z?zp?j2(Ezr)1˲67~Lȫ3 &?&+aqQgUen& { :="YFJÎs\r,JKy:8E#IXNh|pN-)[򨽳PmeD>y|LFƒʔ{*x]LUM5ގY%E&4hU4U`eayG%l/OV"37mrec" '_hG SCKX6m\ޑUQeEqe*비;?cL kpA82tA~f'I|(pG߾HUIVr"9o6QH*y` *s=Vyj(z6|A\M暟({s|5bejG$ޗ6fr5!FFW`zWW/triQ^Gk-3κFH۫Dw8Yʍ'd,F΋\rZ\<~RKFC˛$jYoS7|+>|ȞivK,i?[!Qu>Y"[^*d&S_n_Tʛ>|hf1(B&m0G}*HmO ~[;-+}:'tgblv߇8CL]˨Mt46~(m_tvduSr!96ʾzƥ#3RR*kC.AXSCb't\(-yc3{80LDP] tl"` AqOBv %oEACP7)@Xm8nDS~@q&_fXcd:pHpmXݽLh*h2e]@)K`~%Qwަ@NSS [[.ڊ6[@Rݬt zqFb8}*: KSΓ.0}ccSVJHW~fꛘEu)S3oK !,ٱϊ%htW >hV8Fõo0uҞ!3RwE+M 8oͫ-+D~5|ƉgFZ~uɎy]}1Nzz6eT)@Xw=_y^yu;_5 {MTZ/\!(rXhL؋p*_vWzpE2#dCöuAʻe'q ዩw۪ hR :jKk*g$FMnozlN6C'4d8i VqaWnξ"6",ȕyo& nꟹ㩕ѷ1t)C޼ |c{i1KrA`f! 'm*;G)&3ajlYCclңیX[x n{5k|q3LEOXA[wa@b5wG= dd5wC̑SY8ܗ'lxɪ|.my,&no5 Wx9*6FׇS:Xjjf]&}")a"Ii-([ƚbZT,1@rYpV@gȊdtkWĚ3?S q4:Ăv,aCWiK#/oխVVa|'6nF¡N5ӱIg)⸚rQaHԨE?&|K8peUOOqkBJqjޕ ֜D^O'g3٦M7G<Շr'eX?8:U{tc FöUlnU șkY=:;cl ߙ~b^ (~V1?-zgby#'S}XYڪ %ݡ-9=Sfx'oX/W\K 4){A v[w1Fv}#Y%Щ\h5 { i%|oq:fa8@L;`c$f^29 fRؑkMRKRLemgOG, ~9${&o,^ 1Gǥ9U3Z `rŴ.yRFU[ y@Rw$sS&mCIY%boݘ%`2t,g탮iVAk}lA#:{F}|KZ\MN`J,z X8}jz8ilۛ gďԔt*6ECAzPPr/P_ɼ!M1gwYa?i Y!p2Eܾ^go#4l yȋ cmu"BqíѰ v`@taK0`Q5$%E2УjH>]Oh؇H7빙8¦#{IJ=񪿢pjUd#2\S-!*/հe,50K @MMG7gdyoQ9h?-Kaܯ@3l ӷK=#A| 4% S,֬&Gt&֢=yPo,5ӫ=ם1?9Č[jg h z(":f>بa3 ]ݫdwa{ ?g* Jg m?X -&]T\0 _t?U|Dk3Dֱ ~#>X)יe i!$}uB/)TZyCn,JN&ˎ*h4=ALxdknwcQQ Y. /`s"gs-|gF%XJe#Gr&. p4DFF%?Z1\5HF琋*ƺpߪ^S` xHƄ)Ke`WiSU)z#9Pʼod#0 kԍnG,5&a/bzɧ37]囫!~Tω}sZ;ĵϗZ w3ŗЀn훭a0 />x{؁# krC\:j~ib=IXJ."_ |'"|&H%F6D+a} &p ;?к];+PkǼh<\ c6;$G׆^K$ 1H4ԑ?Hl4N `56I#B[O(?(1JתC~@[fy녽Tfm+ۙ/ o bj3FC? Uri{2Z/fwB0W;Uj7+jփ,˼}"gȯ!~IrɥH}.%^rWY|N7ɐlu Ź;hzNs;ꪄ)-A~M $Վu5z7 )|yg%˕^Bh[?N fpg<,Xկ]ZG|H*,ȁў\|.4V~=Wpk b ~Ƶ8Qp^K;5|a,̲ΊbbO?3q&K a t2P0ֈ&_k!Btutshgm"}g-v̍;+2+-&mv_xdhFzj> v^hw視Lz 񅇡U5b"b\?P}kʥM$ld8Z]J؜J^o,0k;ωj5L۹L]oҩiA:l.;jlĶRЎƤݿ,!RΞ5Z>M,Qh|Qqgg{=2 .;+@ݴUA%+FgEM$`1Kzl`;2`^\kX$*˜u#D("iU71ρS\.9xb傖!Y4gGn(rA#/|[ S(|JVY{4YqRC5W=ˋ$69>5<q$SsLN+#^G?S:n 7\NsJh ?]9J=FasdPW&EReN'eS9,- n|b,oA*M=P'o $aӕO? Z[ʐ/twMM(&!9R)q<_vCwuCw 01#G Z9bƱkaZ}@C|o Ze JG\WgXbGv$!uʸ)}.ʳ ³<Ӧ} yrh)ǹLBșw8mGxa&ڐӄܚA!έ6aĸ0FSߑR %K6hN rW-q ,2Yڴ-ǚv~&[q@H޾?~$͖Y1 5m_zPswPC2#@;G41{L]XX)[{)y? &ߤkUӴjI6kQTH]=> WxdI zra,M]W*s$K`\5S<I4[U9FB~<@׌])"#}iܸ,ȑb"dwȿ;XQ[fG̹mX4F$k]qw|ǘH㽗Lz3Ws[^&`ARl"J`gOtƳChf^)蚖G M| >@mk[<.rohϳ0N4|Y[MѡP._ VM=63آPs~s4k0'] *Gl0]|CE5yVV9QГ)xAU&9'8>5K%8E 7 ƴ!gwMȣl|xn.ʒW WX~C\wDzݏ}~|LfX7ϯݖ:W&kDC*=BHm\Jj¯0% r@-xRO^ltX\GdɄf_.};~i~F&8> VC56}z8珸6슭pp!.d'&T|7 4HO[6nVC/dm%-mSHV,G!iumC5xv<38YKΏV/@Z&i H [VOKf`X>^wWԙI@Bd L!XZvi߯X"KjxSy}Kp#S'M8A[ESw,/e- 2ޫo ~c%9zo7a"h wGlrΐ1me'#T'K^wG0Cř?o_兂Sh7`%)\TT9oSoF*TvJ<^Oqf1m^ "gݻN ')oBՕ&?3rCz)4ee7GT)OҦIȥ^!$|֥nRI8[g;e^(I['P%,_Z8gk<KKDi <蟨s( #?6xZ"BK:Id1+^MTz7Q|t(!GNnjuI͚Gl>*ccW,.({yy(|AE)CE rԣDΠz4۷}`Jp%u«g +Kpw6IwYlgO`֎M.gcjgAdߖ\@){)=}63&t}3$N;btչ1ZN6GHzz:_>щx#ơ;%ϖJw᥹z];YZOCC/Km\gn/΢}9i, '^nl5;x,rQ[)MZP؝RXJ!޵]LX=v E:j0My0+0dѤ(m "kjHζ˗H*bh<riӮ53^vpzIJ.3fA,k!V?Yp0lPOqRA*oV6Uuukr >S!"/f.2hPSH\0p\?"$ DzG5t~@[[JփrƔwlG^$GH:4~7i|c̈ʒsJ) /2op'Ů8mx *CoeUâN(a^A_y+31]o4nΓZ D+L~_iCuSD&k6O^7i <rPeA4^ 0:͹`oWgq,jJv[jS#bH$2 DEʖ(EE  H<ߚ?%{'< ܛ{?ׂat PTJZm>?=U/\"ZEU!. U B"ITocp#FU(J L/bmKisJ=׼ Du02cMR4h QO(mzZHf0raE\Wo"D7$7DUY| G;Y9c"72/ufcj% XڡpoQJ]OVx@4He28) %`ڳUG{3G-ns͓.;<:Ӧ*z*Na:N@6LW8ބP\)V"Ds+bG\)rFdSF<)'>+GLLEPYykma%Pr'jZBm.Z/6y׀Z|JބQqFZ׭ c-bZ 0Ic[s1v&$WW@( Hp ľQG}KTW-|JfEN͕$,P!@Z5uS%e[I!&vhbfgؽ`V:Hqah\-"kd/iŕ]7u(VZ ;q*ˀ97_؏s`̵CuDah۟g<,GǡqoI5Y6~9kSKwVAVT(m);q!NfEv]U=h>A*[C{t聆R<vz۸FF .<[֋up-e]PkئLǏJ uɝbH'NOZQ)L˃Ω JRBbF4VkZR`Иr6DZx gv`hޯ;ߡq{kҋ;զf3q/EsH %X>\ ӱmLZ&>pʆa~.P/d_E'M lI:/ xV;=rOo11Қ4Kd+J&^G9<`u|܎{6KӛF) nm ukpu݇#z#-C/yWfRid8yM#$s&x`lظ7+Emв1+[xcČ2.1F"lqAUeBr힟]Nj@G, 0} ZJB!G:B#FSS\s{Ue=nEDk1GO,b!!hYmxj>JGL?@PwIɀe{ў}`3=i!aޓ;+r-|oY֫wVID`B PvӠ5eRmrl%dOBxU9vhe6lg'n}fu!nP0Nό]P.(?࿛ q-ʎJh>{ 7z|7 $;A=Wl3 8?q3wvJ{k>z>f1w۞>q;*׮+ņ c";>+ʩ*B dMo%gb6Y_jwŭe! 01[uG{6yBzJ B{[ùɏF` ҷj[ QcN)!¦rE\"uɏ=)dBMj4<ݠ-2P6'r+;F *A#u;f@X >$KWOr8)H W%_Y[ԄW&$Z :b^s&LʭCG/{e{&Oء/+2B_'K3VQ״~ ߶#xuZaDv:mwyدm3R~}W-vФb{k.|XE7h,u utX?N(Yu@&!Gl_#_Ę`y. t<W!%F"I+}P1 HQndvPk= n(?oRj(mNj n=Iݼ8GB0q9< ʂn5LG4a9AV{/ z#ӠQՅu'-D6Iđˠ9f aD#O L!}iF E5X< _(ݖ~"]O%AQA^OwzpRNr `w1ȉd-N⪆Ir P}D;Cr8 ʜ;3fCo!j(dN`:XO%q> N_QZµrUN uK$J~ĞwGOqCYQ61Xb%HJJ}쮉fUGq:iVru;p7(< +08 Q6f,S}ML -{V",JY%Ë'qr+ګiẙEx H\nYPc27s1pZs}{U4CIlXiÞc" o@D$DzIrO^#:3#8ݘOEA .~V޼)htpVvLȂ$p* ff0U4DJ#{}t*K>/"r:"31V|</^wq_N$j{g!M0ڭ*r{BFavaP}i16&ɛ-@w񔙳]'o:'OtJ[1[%y;-N]3hWbvUϙt"#kvV/+C +]ΩJ>1", cA5֟;BH}M_ٔ 厡FM}`_GF= ?Wb$ o; M`-Kd;t2/,&U{C9@%qxdo q;UBWsED nEv ˨DQkxϵúrĦWDn}{XP Yf̅_̫V] g~#p5&GNAct_mh~U"7~5 sl m֎jEO,cFuJy!h[j)~&CXEAh2EV`|~ds%nY,{xq= yKMwU;H# R\$HkǸXQ2.FN>u2 | yY"G_jCB3ҫCJ=bl*/1LG*4@V|:VKn}8+q2VŸb<Rl.p֜.Z4x[S{~WKVkz]MNrJ)6W3J.JyNt${:glJun3j)J1I6x0AZ\ڵ{hnNˊ?BS6.!H!U2O'^ ɾrK8 ~clz4] ,{e+exOgTA33N`黵ug) [BOQ|kJ0.)e7ciXQa L%ʡ,7|m[@}oELb9@?O_7O봐<ߺ0*rxiZX SG_7,~hpGubc?uAhB<.+=;Z룩n$ 4n{wF6P=s9/(Fm ͛[_ E}e q NHmkdgw-:PE- >yvbRd7I)^|Uxk9Eɳ ~~$]M/iwXYN(O9Ԛ 55*.ȷ[,}㋒%{'RpIEF6a4ȃ渞PL1 @s$@;%HϚʨu?ӳ W1ve44% $TL 2f.=;3'P0ky\3 x,ѴA7 6s6׍ 83F_+YEjzB냲N=/٦3*cş u%<5FɤDցݛȴ5aCuFwe/T'Ym]J_.9Iס8UR{A6wqb 4Q{EtBBTJ80ʴ\֓WeR-aBX_d:Ҳְ3\ /4^Wǻ¿|_ߒ'g&w%0S׫v"/+H޽&geiFZb`Xj#A|6" KLfrfvx%5!Gtg<[|LlZf0\R+@NKs0+ ރ^?L),fP=>WRYuy?cc0eJyJ߿'|z +%*k@=E ;t*7^ZqUO|GOv:<vC#Z2kV ͩA_N,#| :e +j'v%E4D㽤/2HM(XW,@ 2D\40C"kW[$-*Y A=Cuirݬy=9QVқ9-gqK+ tXXڋ<.eVl=n;';MZNx,!k5FD F҇$cLB Nݡˀ8x CuMc/lM[)u7dHh֘_r+V=3`4OhƖ(ˡ[2gEf ^nę7L ̉rޭJ'lވ+7"+6{Ӿȼ}Z{SxA̓K` A`3|uug؉':#.p&x^<PM4SM !V 1C}~GM!щYT&ʱ5z|u`GZ{Cxė^k㚞-ՙ r˸BX'N6SPT550~z`S5~#A H 0;m##qz~0]ӿQ75ng]A+s0YAKz/V~ |D]23t>6*=Xi,! IqmU yL2=t 7ζ_18MgUC&eesNrekhQH1 vKhKJ.ǐ=,p'dᥢp&6 "U]փ7ou}\)[;FeT6R^uH1utv˺Whqɦe(-%uf¹YW]LkeM\l`22"\TK?fݚFk8`ؓp^\B3CբQBS68BS%?;͙v@dzWn`3jl>F6(䂥wmHEe&f*H: "DUAO2%TxJ]Z{9GW)$K\<[ɸB߯ٻ2"nJӋwߪ!b-'?;zGzfǦ{ 뀇$rɬRFw-p,:[D(NJm'!XS_rES+ =5nlB`O٫`l}|۱5gs uC7G,nrg$ p?9 C=`cJeQs W y[󾁫͟jiZ<}'?%o ƐZ5q㔻2Ämu{x!G_eOp{IDn t՞Gsn?\!aRАE8)c#nSqcyvbs#d/&9j : 7z|P~ruL#$5z]mb)/(&@fȮaC߁25՞5rNViYR*rgBLv$u(B;У #_)E60$5`҇ӣCFԁ׭ƾ|.F*y?SU0g'yX[ka_yhL~bE䔭 ESHUi`l j`LlBAeƵx<[b(M?~yeTSSnzϼ~9`[-OV&1.w*`Ʊaw T:|ri 6U 4QD㮅Muz Τ.KӒ' +S8!UX&r:;0LڬM;'{y@|Pτ風͚y,xFn‹/tcLKa'Aa0uŗoZGu1AF;ˉ,CQSS܊|CiUSލfNA*[g</%)Tķ6 2TASPeȇD_ fVGFewb]  /_9]<(E #AGlt"ՌoT #~Ke4hm 'G6t)g@}}5=I.zT'q˗W-XBR},BZH"2 jfIqK?W,$ S p.imMbmrSO8N! 9 LP5?w`fnE[2eBCe6T{-<‘1[KT稲zKZCAY%?ПуFQw﹘+}H_m2ԭ=A^Tʑ4T.0oi&͗\R֋/շZ@d_ż7yvQ JiB[xt rsmi.,zmfkR;q5~ߝ?UبHEL)~ ω;ZpHŒݳ-HѻIW]IsͳV]\>W RϦ[*;9 x?TV'tl++9qI#.2'f[Vfw̅ůq-Ps+?2Nxh0Vh(֞[çӤI6$YѫBQSq>cr{ډLWO $qbLߒPJ_CߎeA\&eBG^:mh?ڡ @kvr+شN t2: K5+f}:x׵K_.z4E iK G#a۸c'33v+OkX)YY4z}*˙gNzu_MVvb<7A \TaY}`\5Gҍc6zCuȩ wS5â:לi+q5X(.@6glu8 ;գ8&x {K1Weڳ"h `,E9bII'nC{9E/ h գD$RhL:h8MQgYm%5a,[V"t'-.N{.Tl/b}66;L]ܥܤ>ѻ2ks=ozъM~ȀQ(| 4ƞ]&v~X2T2afIG.|BbBiOޠ2dU߈oQA&b/Lv CxX>vV"6P?5ʥyqm7is"h-KmBGtdY):V,VvG7RGz%i:=+lh}yBShӯ^0s]@*v\݌ZAi$3Ln G^mvs5i& zK/ Vrt"DEjpj?Hr(/0Y=iY펪U;hT4͢{kl!DOKNByTv};X̎ WD~J<:N׭$Ugg6rky^Ի޴Fm~~ $pqq=`R#!AmE}c8n/縰m ̷FPTQcJs%r?uV%[N,Pa5R Qڤ]U} r wJ=Kڂ'W0ɜģ#?$Az,$+sr˞ʒ3 |ܺ;[+Lxz+ZumWQ{eЄ*\xޏ1?_W) ";gሾIGG,"3/\A"K8/lMO˨^pf [^.@9n*yNlrnhtC"Ԩn.F\P:=I9]/g~~4Qͻ%*U]O~\?ڤ6( :7p&UZ)gF4d9=2!Yy EMg'2{M Z]Sb.ծ eT)Y%gdq0o {^ WWcRNUX8dÒ!%H/! @ͮ; (mH %XovZ%( .bU#/NݞdVTy*@-,&W7NtArA٥ƞ(Z귀>cF~^P|Z 3[Ug 3e4ˤ:*5=Nբ]j5º EٻU.OrlXsR5)|)Jzl]DO]_BS _yÿwr\82+{F$517SejtNwW=z+ɔN9řTJMy\-kXf룑mc-2|t.{<f@mhPo;]4~X1r΍$5 0DXؚ=, S\F}t3QeJ/)sO~Jǭ% A\GA_.UUb%Ɣyl"As0[k@A6-aUrw4ӡJE1aW;,'v!#՟}-뀡93ovD;5\ H(+Ұ]A٭]v$j`2 CܞԈ8!EGp ~hZ UC>${YS-S^E^"16zqHXt.dL> L/RY c3>\Gk:N%24kGy}@B huЇQZlSs]\[<1[qE5,*("ꃱn(Ƭ:W#[-s%]8DFmjb(#pLz$-}B#wc 2GۃQJA'i96@H_@BfK)u}gG좸mk}%.'uM8yp`G՘4f5.ĶgTyΒM֭CL9 ٵYY3_P ;B&3IRD.'l g$;XK'r00Hvp AH'*X_ 0Ɍvg1)1hJߛ?ߋYj=h".*.c?HQ*D=]T۽}j %08{& 4]n ' -ֲtZiDU;(u;TΟ쉩-h PT L#PCP=;S^(T0ٛ|\xl+ *X"J8^~ ilvvr{@[?cOA$1QXTӻ ȗPwUSwf.ȱ֒|%b*X̏ތlT @=M<(2 SEl)cW~LHyM9nWӵJcMnqE.$y]9Nh6 8,B?lM(?y@V4XV ]yLBrf䏽b*Y‹,Ve =+AlE=*Fc앎7"Vk krzx\m͙k8 KJS 4>1W1P 2oCMp<00e|'ԱEGDmH&v<![8+cvPxxev^fh),\$wgf8Jc@UۋDjIzs@gwVP2%mX[|>Nơ2kkS$7x<9 Htz-2֥QvCه01EJmnTE7 .4vJzMjN7ofsA7hV>504_m!X y\6UT(]`̻;ZotuNÂwC 8Q aЇx-LF~;+6moN'腣:)|.w [n؍R3ڻ:qd:B1)D柦Y c 2'N2~ s7H #JK@חCnXx\HU="lW?PPhۛ)MIxDIO NbG3ŻE2v9$C a lߏPT]Nϣ:m=蓋Uُ=lxV: fN}g,bcf1 6irf_%UX7I)YHRxÐx33- ]?wqht;0 uDey{PYCemN xd^D[#v (݌K[Rq'6k;M)G|+pwkdӷKO u8s=i uGkthקaj}}}@4i5-WM=@- .C#&H)#XɮVs: UDBǔfi'sօcy>r6ŋ_oP01ȈOJI"zٺ^^bp|naѻKoebا-ڟ3FnAMD]FS* ޣEF_,n5o W =*oۖ.u{GD,::ɗ Q(V}։z(Brڳ,$qU5ɞzFx2|񵕮k'њa7tR/E<jBsWաk'"$dDF2 aO=蕔m6XAk4p.p=?rzA:#=V[hوf&i1]?N6$.OQ NNFjٌ_x;u1 //63)#CC/ Q- :ӇSnw6QyR/4: 6⢇j[I@+YAdA݄hWc&/lBWkB}]4:ɻͬ)^ŮsczPw\x[6~Ц(atus|B %4f;tO%܀T=;V@@s6q`d/~)2eESK mAg>2hO]~5>DwZܱk tzwp]t-E8JUdDÀy`>N4U^_|>+q"̗,|BrG݇ q*aMkn}R9ɂ@(0Qc<.i' 씿11H@5EYA.-,I@^ǏQ !d ]=bWin2ޱeMف}JMqqMdau+ GµDhœ9dY $H>t LdtIUZRɪd5q+z=Q Pi%Ka(K#q} KTxu#i98揉=a%L} '"zz< 6Ѩgoe:%=RGC4BY ,+$Nן%v)j8W„qkߟ,> _z]o }Oz88}EZ0beAӂ_'> *~7{v(ž yypHnG63RjL1OOEbO?X8#q[[u &PXR*Z_&ʝ4Z˨Q/]~8k1e lrT$a pm>=eF .iW 7 fƟ;}"?>꣚kzdeUh|;8AҟjcnHOv87[LD){\b*Rm$ w` pVRkqMei崯&}4IQxAM@+=Zq֖ed\:fqn8J`3 'aIq#k~iA0'LX `W=[(kk7pI3mUZAE8X^6I+Jp)mJɥﱪw,ڊ २Vģ~50g{(Н(l*08k`ܨ|>5f] о` f-B@c \#$To7#3S>)ќ~KctټJF63%tU4 =ITSŸQCAv;VG~9h-QwٞNIt)ѝ˩U[Ay i(n\Ăv </<2f0*JhLc}^QCpP/{"WVF=N||davI%fcZ &3`N_bIkxN5E2 ryx.:_49 #i6(lMDQ[$V⚴6ъ֕;Rf?g!ӳb[~E ~ (w6 v†yE1FFw6w!8FӏyVKHoޏz2l|Q8-U&~izKej1+żV ؒCpi\ ,iĊOx&a[[w_8TF!X0V%Z¾_wneDg>@_:^Ҩє2C6#5#^pka@z7:ZTT`.ӊa0s!J 8~M )RY;" IW ]8M'L4=0-C@A_|l.aVFD@,Iz|Y"+N︺_~o-xɿ;խFFybQ#LQ0a*$-l* Hv(wAgpW l qU)|NY薒OXtE٩]CT6{海 A| /e_^D@Z#h^jǵF͖":Jܙ}.A"N">r\g?b\u *Do-.L5(|Oƃr1Z5[YD՜+Sr}.(Z҄S OxB-3nV$Q"/5Z]j$TC3;I&Ed Iנ*F` _{y@ԝN#ϒk#7R*f]頩loO:!mr[ x+Av5ˏ@ 5(n- LQo[*f)cK}7Cz0*AVl|"K3rշkaf31#isi&*LEύURO+6ǡV(6 ڐ \ 2z v) J.2ޘQ.b.G!t=HG:XgI\e!]MS-N qjIsEcX)-w;_UO"/|3\4 !;Yo0Yܼb7κKyח;s5p "q'% Ai3PGs"sxaԇ{UtCjLr5P20j;X=g MFi\ JQP! X (M/^ո7Β6.l-H*$]6+n- >!o_eAv̆mۢ/jcH rKEfdhLUQA*F8D J&X<؝tUWb(V+nXG)Zٍ79!f$9If]/w}YOԕzTkÜYyY,ߋύT`'_]T~`˳Bͺ_>1>V7)D)g%nNUѧ-_ma8z&A!&lh + C_:趏S3J%9YQcR,{tMY7S/A A_%ώlsx=6VCZ6v1^Gin9AeG'ҿRy=tP7 h)Z͚X=JHȔ.P Kɘ1(gCg6u,ckSLC&:#(}N,(r>cQAt~|%VB]d0a>X?IGu3ym |f&H >W);U:A0PUV!P4qkhfIt2'-viUG}*`Id[KlFO](U'EE`S 'G3Эya{KI]p 3]y8Y]sWk&ܵ۠Er̘ Kl,;(JY:%%=@ꫤFyn"0&Æz$.P-.0Iz/t=VuWUf*S^~Α$ýe@m1zyE[`EDA=r.mà(Q>e2vO{26[&Y(Tpؽ毰C[Dtt Es KDkqʀW/%W=YTLx]K4fw;1/5S |&G&福E䫢3co@P%F!F Q4NTèwl{⽏ծ̱nE w_hC;Kd1WڏCI+ϰ0 LM{#)Phc^? ׀̮ٷ#.eLYu,t`Pu4ycVpOUS+{+{ WD-g ~E# sܜ>tF2Ch>Sp=wl8IpQVH"0 T92MK=ˌ4Ib]gvJt e}Ϩp?W5sOAe8ҘH(3~XVnUD4Y*byvܲݞA2v]L2\|wy~~j6IiPn!`j|2 q Tʨ,*.XhW]5Q?{)P?Zu@'Ԟl{)`Id`NjZaE03>xcm K/k@x=9j"UuxD);-ɨo3L'%Xn~ztH8]nPU/LO"(^J/nM& ()M8on% `k^bJH{c[LZeTC*y=8j%o7jg#b73ogdǨ0 8fYBB8,mܻM2Q&zR b@q>sj!e VsI3>yw< 3X -Xs 6\fPwgբ<`U l{Jj,9lfQ\Y6p0Prx软"_(c!0IZ8>aH˲؏~jzaWe6}S}Y(J~ϓ8A;+p\"Nvᬂy6C,[e6!ʔy¾xIW\$~?e+ϊC,a %9D+R? L͸eP^f.粼>T糕ہB!"RӀAb~ݖEk[|݁Sf]K>A 9XEEhPB8go{YG #I`êDqMP1fXObgZ. 9\"+i.Nilߗh;toSXEg¬1vC-nIVeӛ/t0^,ы]as4b$DVFV,(Bj5'm750B]EaI1j% M6ebA:2HjݫȤqx cTM*p_Nn}޾ zossuxSČpjXJVɋsD/pO#kx89W/ԙb:h(ˏ $u',Ó˘J7)k @L$n8; p !pCQIAFWma󬎚یJڀ+0$'h0z|}TϠ6~'IZ^xj6u>`q{ Z@DE/p:q;wLp 3 C0s(z{cdX|h %[[h>W,|?B!=~??e?2b#*-q9Mی\}V"ZN'HfwuBW[ct}W>-ƿư MɆn1B &c=)ԩ5+Akzo>CB%X9l5:&HI,R1L88D`Hi\N%Pr3fB62D(wGiO/H^a]]zuaK]+>%B_eUi\6DW|G&An~jYU=ikzjzzsCq@ "$굖6S>R}Mtspq TF8,0C!*jv⯄ha]a^1{B*d¯gh#}2`בD2:bibCk8 moKiGgnjn>@ߦm%fEm̈́2aGC`9\$y\yy^[ܶpZW.YISCs x ړ0`#yڧЪvL9t]'k86~QPazsIͺGEqg[ժUD2x-ȼ^㻜q, Z. ;Ker>m&"%cx#jx>^*4~ZԀk+Mf+FUxC 4X3 tHBGx1.]4*b֫h-90N[͡EQq 1'iFR[i: m/ݔ[mQHtC.qϠW3!!`a yE6]?ɶ ZtgT`3V|%Qބe@DbdaGŻTޔF5'% &Yk/)7*M\eb8qgF+MKP i D*{srsoHFSUJr*Sa㔙BPyYP&PT.wV\`HT}gGE6RTS1ޡk4.ѻ‘-80U Nw 6 Gjw Fm޷je"|Cxa{"Kg rB<+sjb+0YJ;X}UrT#-';В'7B|ε9!᣻*`J#+U zNH\RdhGn_#E2R zBV2Et)<:ןEQ&$Qh[}('+^ZEG ŧ޲diPKL7EmL%`UXbkM_ LJH>y[ bbͺB#6ɷ5F}t|XW(IY../`ڕ9kFjKW׌^Z0HU0R`g<3Mʳ.x(,|P;wmd] n:v}3/ 󺻻g /*IQ0g6cBTQ |ŒGT$0 ՇVnVgQ5hu$y&pt 7Sjh|0#v}7]Fqg'tݘI[6#k;|mƗ$\a2ԅ qp5 bbvξ3 $"':* 3 Vy >J5c U~^pSre{WHKx"{p'˧ƍ @D.,YE廩?ʘ1̺l yj2B'/"=q /%ēD\i;s^Jo*v#fVL8Fա 9芛5PFwHbtFZ3쿉9nێfQx,C:I~^HW3 Yp Jt$pdжGφU:Iwѵ: l=1etAdm ǷGwBTъbU9Tcƃ:PC\FC%Wb{x0{r GLX|(*^ Q'9tAI {`Z{'<(`{ ,F*H^GB4>x@drnhStP4{LH\S9D÷Ȋܴi9Oͩn,5땱4҇=u#FC-Ū bTD %69b'|rU!PΜrƩ5@u@uo {\ c(”d@K{GAYvޱtNՊn"SFPO탪GsH0i4?D2s"4㦲5sްN^JUf(kS+<ݑ W;ϡI;م|;yo^AmL3aKg\0d89&l@Ag\)cMˬdCC(̎Ѫ KM&I5X1Bd|Cs)BE-ټ%]ߧt/#1`J(O ʏ1zbx|ps~ d _>=r d kłT~B9xXH|WCNqOw`Do.^“z06Bu:]ob#+PI~FXZւ5KhСׯ{,s1O {@[#32x@+` sgvw@}3GY)n:SvdLe`,}Ċ))O|X"ԉISia %.k S1?Jq拘Ӷ×fi`A9ur0ټFz* ɉ Ȯs<Ð.)ZXg|ͯo X-x\0S?Y|2tmj!a 4 4v"V,;s)gmC~W ȦqkBU,`y''qU3gH/to- R(JuiQCNdߵ%H4#?܆,W;9Ѥ+' iFUO"S(ItLΖI\c^K9E<6+^3Z%d3\ ]gN}OUei{g"o{bprI '\6¯(+񈃬t uvT1,9;M*yEtpO'5̆)gycnA o0\O%أ~~lߕ#<,edCtɪֽ&y=9tK2ɽHF4(\y)^u#u撣\\>qwLߓy+]m>٠ikDv9>a;0}dfX!d>&2U3./}pm1L ͳoe Ҝv+fSmf:B_^FcR-$#[O_;UG'*do^#w+@!Ka(r!lT$涨;#/o~y@7|q3Sr;H--9:-efz0˘MuʨmcZj'M5;gO\z1dMZd=p,6t-٦Y͠$Gm01>>)>kDXqWk뛥]]'u!?)ĀFhkz7'WC4>3p:QzL%P  Wc#s]w诋:$xH5aWI'Ħ+C.m ]YMc+U}g&᪢}7V0o昼sǚn(}s7J,Dr6@_J"E˞]fMB/ -e >Hs4d*76S"6=.&䈜j;̂aēo@$R5dƔfS6:su _[ިFz癴e^)SĠ{-z {hV$gU+댧/~楏xbzeOLB48V`]wzs/+6Dld`8#Ț !ۭ9wx}"b#QEذ }iz&W g&&I3Rз2[{r2E˼v_EÚ(,4{(/|$//ճ<ؖF5`ͲGu;~GV.WqUkm(e{-ܤ9X8ɤ:uemC*n\I^ PP!U5.9\G+OT-ՙPk‚\H%Y WCg8W38A% pj;,Bdul+1i]䰦u7Kb{}9h픛6<ӏ́J+3XmaZ^l3R$>s2:`1er+cO6}@5ڌgRy(M@[i\K4}$wS=͖l$z%yŬ9X&ҟ5 W{@NYrIBǪ]r3h4o`ڂacxۯ|y]hS}EUZ\s_̅ Hs-) ZDr(R "!i:lE{8zS[q/> ԏ [9qd*5xG5@~an3`DݿEL?9\+ |V0i\$' !HCdխlHOBЕw|j؎IKWNv:Cf?g3BdXKUlpnVb`" 4B=*[4_BH_`׺mk.Ob)0=Ft f$l2Û@'Ev/g9ɬr=2n'<;4) ;{%F3n/?uD1PvÐg4qKeBBγ|>HzlꚈ^RHy^ϊ$ 2iWH$[Unj9яJD/ium<b'1}Lk9 VH_Xi.$t[c _=kPB7#,2.2}X?uVv^9Lɖya{*%"ub:/ +F,Zdj0Vfy ].t/;jeh%K_IL^/%}?5wd bsi%evCqGs @o_y:?m77Hzʘ4!+@S=g 𡄓_]~#UZ4s֔C$0h͝/GI.ܭ Sfd䐤O //^\6X! =fΕOX>~$)Jׯy= }6.j{%9&_X#kCR43TI/ 5\TP`Y+WED%7K( &P]V}Hެ,BA:ևlU\_/ҝWlJ޸87O̐)L {kǙW+r-'`)-Up=MB h]5{lLm]q4^N[ȼY0vY \eioEw{]Ɣq CtamICS#2SU^HR ),yoq|9fdƽH!-9˱:_m-濭8fISL2u 3&'媞/P`dydr8!"#6~XB<Αq}.񐚇as~CFc7ݛф~׃9Pry\Rmهf|\D_g|`CloyɩK y7zC8&WdbbDѕ yJF_bzm>?Ee !3$n;Es/)fӸ\L1ѿl"%jukN?+KOiQݾ.Fdr x6:,iunJ:j2,X8j_|fehB;l 'R^jOsMFYeYLrYyd49p1i@"~dнaaq񖭃|Vv=[C^M)x{]L [7TAS?I+aÏ"[clGן05Uxtj?vjS ŀMC"vA:Zds뎞!0 s!`c`hJv_7qwugǷh! K} gh}⛰yӨB֩ųʦ`_A9=ٔ$ :%3([C0Lf4;B- I\ qK.ӻO#QQلF70"pJP>Lζ> |6jBY/:XAb-OĿ$ ":Y`\ dl , N~C<4^u`( ـS<=ݔk逛!aPB F-yN#`4c}_g/LCd{1.qþ3QTx &Oy-]/@"O 4>p6l" (lPY5]FJ-7d^u X :ܳ8JEɹX='^2s` h/F>uz_NsvQ^U8b^ə[S7Z /-A*:{* 1by);dU{ P20j=']r77WxbOr&RQǸG,RFx.)`Fc\[gϗ/-{hHY8"G3~ T&o{s XBa -ǠoTUFhϘ \ n 2 ",eZ GA,ï:7ܬ (L0U㵦wy ?_dƧ. kSoiDj0Y}8:g8]G]G'' Xx[7H!;Dxs 6w2*֗/:޶td&fq{IYO[2Ψ;]ơbV6r%!֞90 -0HI0 =)3F k<An 0=%z_~^S<3hׅgvBFF,j6;9[4 A- #Rc⯓<* Y܁ɬXtoMstE%SHg G*ļЏ#*Ø߹_f0?&Q Uwឣd vܹNH3sJu+N_T̘B[81-_$kP q7ŰFs|nKl6.㬺 Tsi0_Z C52I2lH`T6ƓN`pa~eRI# H.5a'X^igH,4eKvpXʡ.뽵iſܬNngk&37~uҘմ䏵VS{Bbh7 NmZQL#xKN^Ly=|<i/iOvB.z !ݪdKG'aV9bvYKb$ 2315~)fJw8#BWUKN:ƍߢ,jaeDR4HsUw.5+@i'<|nG!EGTh3!'o`nBmZIH:#<:篂9FlNZUk٭qFzh=@("S.zݒh5+?_U&\=aVWk:8tfݍNd5Gak@&rvPnjYu:*BvHϓLG@Z׼~fg |mb@/4z 8\śxld 27aP8o3U<6iĻxT eM 'M@F0iMRz#)Dg2;9^kPc2 џ"_̂9%C~T8oTf-mq6з^o{]hᷭ4ҳyba{jXy Z.{h-jgrB!\2qiZbդt M7{2nJE6m*۰((P\2<[T[?b> KUg~ /2"!Oc GߺBB^0ycO,@Fi)s7]Pyd%yXۯS 4O=J,G0} ?9SO)SnhFʿPbMC ezB3o/nɾx6iOA E}CےnN0G./$nqVӓeWJ3RHNWܝSITOs^Vx2RL+R^F͘Ԃ\FsC :u{/8cR~sww__$Ozjl#DvBNDn:\:Wz h_` &4-5 ?`ߋVДsawS{Z*`=ZTԐ)D֝6Mcf?BHHѯJ8BWT>&إ  6GHlCz|Vژb36y1ZdmD 1c?7M:-eAHp,8N_jaRiwWs݂95FtyX=@|z8չ Kɘ%==˵d%_ܢk׶ٺv6v~^pzw"euHh6٩^n"HOyuc<FkwI}pa;V3VuoaS4T \;{}(/-lH&#+[-`7+p|>t c T>4A#*{,?\|''\$:%%$I^uVh,0\a^}~0V}]ݤ>[ ^}Y蜿^X-4/eW:TO?գEL`E%7_A~i NĕE-iyE`TZ 9 .u-gq#,qa2hfzw^?$>~/^Xpe ?'G-xgðOߦi 4}V.rn{燗䇦Bż! V=n ^0+OkQ: 5@HBzMPt< VH\d6Rjt~5MSZV"涾J}EZ !H.*0s{G=gn{%wP%'NepaR_DT@@P_z5:T?ն{B<ʛ .l$KLȦnó!NAA-}D=7*>\8^zMf 3L7nu莵vV5sȘ%̈ˁQߖ\}r=({n#~3iť_[0,Hys7q&jw7?单JETn,;I̻G7n!Egc}p$S+.K C\q*)@iӓj,thc$9ÃR5\0w}ޕ p. u>c]mK]/[I(Q) Dys.WctjIm<.  hXKbXGa$)m3H1l@`ht͏r"]QL=8,Y*̫9EEȈe(S xl+g1dTfۡ@$arϙYܘ<}4f/j'~/ }`&jI eY>uxE8=M$d۴L=Upgg<;>N kOo#8&3&_cF6:%b#0rJ"tzSdfhR 2Z:p+ڢ.pug"SO(0i <-7 ; Ȩ bEZu6nŧ.!$O5wGSow# $^*G@WSšԻuem$fL9ňF9$;gGpa CYbj/=~ќC+sF pLX݅k݋ZT}3 zԎ7LcSC/<6r)jO EƉ%궺6M@x_0OJ ".t)_s`~kI~`u?[ KCbnR-s&?m""vNWPWНB(pkGhl m!}*e xݏ1>E[9Uׇʏybh?f)v[8! Uc_c_[3/Cv]G Vrm*|cj܌:_z8,|#&Iy!p;PBɨ4UmBX:r"u}Q"Qi%v%8&U+A8^9 |g?K%s5clk|Ms}փpҀ{K6d`Y KƬ]=B`#]@ j K93 <:wx-\05{FL&z'\4fT,^^ǻnR~;(->d lOD  H`B`i%#,1k4 Nn2Os3j3I2Ug{5)zn>eiAmjokDh`YgÙlT78Sa'`?50 555W&ʉSe]2n s46I:϶\ GOr"6#ѯO!coRʥ9Ġz;v𘵌]ć~K vEɞ7A)r㔝KZkVT:Qc!~We٭ac:aQ [ޠHkc]?o5dp/tV9"Uy̔nWDV+Lz2auKءL?h5m,^"B/&h$Kg]lRXɪa|@6MhFuo\w(.c]w-!5f́R͞П^ iT]B >RL ,X?bNL0\w20$@Ӟ #ֶ"#x<"zen8LK7'GPTƭ0cZ-ƧK58dwS*(5'ʞ,a9a) pjtO6 $FGΕZ$&r2!d)QI|ʫLt} ('MJƐfnUS35?Jϣ*NhOߣ+0ܬfNqs44+hRw7a|as>§''d)#٩f_T9$rש!B" Q("ĀCRףqXW ٠!EK|&b(EvmعK_5[v]MNs(`mc XdW;Q/EoQy=Ƕ5~fċԮ)RðrHt(ТFc˞Jmya\PӏhId,<$ҥnOHZhSͳt&l*+[5 IX]:>+~'y ? Μ;Z{LNBPPEN@P4m+=8 ·kʰIۿ`tQ Z<˚vgM م&I |@Wwj鴷ɾvNm56k c;} Hal>m}oB+Ofh 2t}YqWaj5L`>ػ+WNZ6hGfyMky;J?&I_ 5x.F~8}t(FA~Ӌ%m@|#-v)]mY2<3wLi|Z:Mg3_ӝ4=f;TYq&!_Uݽp>S?@t S1+TlqZGg7Ÿՠ:J1Y ۳D,IG39@vASRջJlfJ cv˄gdpMZ_f#X- B5W,u-P0J`Kk1t+ukXCFY,&5 ^G:}ܱM19 ==([UpQ?k/[-p:Uh~TyΖ^k a#jz]C̱efEf`gyBwi\@t #7NJ73Ǩ?:{`h$ ƄSၪ$0HRaEpa(p t桛|3f+xys!ˑYdɲ'&Xg矰paKo5^<ŝ0&DW+O&l UO<[yJnDMY7,JǓAeaͷhZq +[4F>Yó-2Y4@.h9LuU4K:mHM Yךd1lx1i1]} SfoBm'Mi7_i._Q=]ԬMTΕ&hny_SbC3P>;YP`DM铜׬BNjOvē_iAGDWUjR*ɀYYpa&VhIL /B,DR.w(9 D_d6wsqIͪD#Ay~ om>=Ic|P]Y)s8y%AmTUY`ړfbLS>wP G$2mQi|5'\ō 1;wg$YO8qp,漑߱>SO:R4=#$idKQ쎗!삻}tD||r~S)bn5J KiNŻ\M I]ϻ6/IDliPdKpwlV;|u(js-1V,քB)!8a%7_NFm%QDdPCvIy"TZ:k<%jNJmf49D2 s&x$"[D- Lyr҃ܺ \KLs7U0_99R=QhcזvI6VFXF$ğڂJo8szA ()?B~P.yM*Hnxy{jwyޚW42U9-4 3<,TAm:ues/+!p y|T03A%X6?|ҽvt 1²ʼnVrƨ!zͼdM([#شBvmtк˪$ cޤmcHpdV*ǎCsR xvW(4f Om 6qV!Tq3e{Db q弍y]$4 ́$Ae$_1z܋/v4f|W Z͓;-+ UCzv|gڵe{u &&")7ul#A|Oύ#J)&avҏQl*aQvEdFKT񻢃_JĊ @Cج8g%UV&eunp#L-6s?6zP4%YlDO};w[LYD, ? mpeUߺ^l~{C Rj7eNbmмp&.Pp3.jZ' 3Fv9RŴ=_=O~̩WD#*h9'  I9`)M^ǚY{Qif4 3$AHH7f&eI Q%gS3oM`/Yb4y)}</SWj *ZږN ޘRjp){tO9.g/jĨ#sٟeIYft.':a* =^}7&Zsm򭙁4ȧfF&#0ҙ1ѳRniO[BAakrlfr4>ڑyD"u!yH`"]y7h1XO"d(ȠS+S4 ^,$a||wO #Ï3gKЙS5~sS5$W{ w`--G]!kqdTF$.v ކHf(ēA'C"׈ 9ΛKwN8#8 2Xpו@N AJhfxV.omؤ'J/e_WoW{Ry6 dSH.'Uc0 aꞡ}d);}JqF\WT=pyocl:RƢG[Z,ۓŀGvFƅ}Ft653ٮyl'`A*gjLy{i` +Z>CysĖ+u!2fW7psцsCuN=kȹ4L#9 jewwM2oܚ*I9&^;Fat+2i6cV, Z6A14SX݋'v Ķ%VwڴikLi%Gsk\  u.BH͎+hЪIna)\ɏEfakH_.3]C>s*;]__m*_ۿ?vMa'MK.=z© '"}Z/FK*&*ZJըUqR`8nUք]# 7B?UBT|u-Vٞsl_P8i8ɺrYu[[M>3Qd揙 ;L 04r]PEId٦/yR$/O=eIc u<*OPP"; kG{R$iss<,dYɂ4{q6wrK;]%F_ 4ܲ=2BD/$@KXq,XR@\nx`"p&܂=Ŋ4Uփ!5Q>mw;{QQ*Man-Z!%Z Yݭ>f_iz.TFe絛K2]FxЖ |AYH!׎87YY+{pњ!0}"&Yi k;ݘ$gz`$` h`NKZk*DNT`l 5fW r "̛4T8?e*:-3z8 ǩȨihw4qӂl&.$".y}&!̍뢜H3g8cR 뻚9E*:#ᧇjWF?֧!6P~ d }>ڛ5>P+O͋9H61ޑ8) Xk]5a|lGt55Ɩ_"/RL8=1xPmL?iW&Sr3miMXfc4a^*T!"6Ѐ ZCփ,}$ke3ɟ5uɲ' !!A~$7W(6֚Ʈ߫E~gI܉9iIS+zWc&܁:80\ާ04N9  sLQzTMG7%UQEHK5IN>K\=*۽xI#IOtHtҪy~3c { ᷿k(S g[%@{ R`Nܨzce_8BeO&5/w(0Fapkl.zR(8е?ZpaY\J\džݺܟ6 ;Jg7ixɕ$`;Eä[ _-.|gy{ɖj&dŸW_s=Rq˳dK(J,0l!(oH֥Ԇt03\z;ޒ{{Yi%ы"Cx5|*rF@ʹ9{eߗ\x0fң%Cr::tqKL@H!##*>0tZG~ 9&;_+A֪TpR@ٶz+ϏK@uzV. '+X {I, 36BvCUM+טt\DGKu%ǘ^THy戁" 3KM  ZyxeJ| nyI;ɥۦ4;=A{lq<;.(J7%vc˱NXLtTTE4xvF@g&*Il(r~}Inž2|U7Jb-zYGd،b! ',air%k"$N*Z8VTc[|LP)i>3K,|#u(h83} zNx~Lșr[ϱѧnk fsZ }٤M—Z@N(#3}8 @BMDݒg+K]IzCu|~mw亸*-I2 ȉ,-kLs 7 Mn)ʋVI6gOKo@ *fpmd{ -C/&K||E#'eJp-OفO$WRPށ+B ]lGXǩ0cȈ^ |xS7*|$6#NdꓣabLJpuZG[k%Dѓj-0Pg!du{79EʭtF=]mV%5)p1}um5sq(P--#lc=Zr c"[XYR[CI;n'E1Irj:3za>\_> De/x? T}L.g!j(Q4f`Km %1wpīe-G"1;@YyC"h^D?ϺH<PNzݦ"' _-Z}WuV?QSܼ վ ~LAs8$NXH`U ' r>صГoMdpL/>5_ 8w awj<\@M J{Aśq{-K\]V?,zY;T^xnM(,ko %hǢQP)iX Uw)f!Kcvaer]܌P, י=B3OjJNP+ycԁ#\N  \*LQ!5O)'}$D 0At%m4:]%ezkxԂ<"JKQ͇o& 9MPvrz=_|bT}|Y0Z v-BM|<˭0ð3KW]ah}ᗻk\[!tA SgME뼚Pc' !sx?UqvɕܔN|'\)`ALT46@ t{J8Ҕm.sFP)C|ֲ5 t-Mn$yQ:GGNA_:9rKA!mcBH0/ +S򳤂! 1 t7Q)e䁄7*pU=BF*fg Y+6GQ=[IB<{NKRɶrt 紝c)ϊ/HH8޿#u%36 h(݊Zt&*w\RJwҍTQZ6F:7)zATpmAsyi@JByXKYNGgB}"w;xԾ@qFAPj[O!3?FO( rTY[~E?.lӜ Ja 7d1Gts"x<)٥E6~ʼna{-}tP5>< v +qJOAbI.l׾.o\:Q-f0Et9J3xߎ)-c.X#&L%FX?Dզq"W/Ƹ- <D |&:db"9HR`em傣-9&^JP":zeΈæ@YYBk0#bS?+`nDjq'ˤoy'-^6pվЕ WJE[fA:"` ϡ[b |.?w¸7>KJSnN u\:XE]Hgź| z/&q^lhiiKG4mUHUH qɄzD6,:3:a."4[h =+;c?n zϽ<*DlpQ]7ca҉obȫ1PKƃy<fzgvK,8!~RG/1tE1M`Oh"юuB0zUZ';<1^|/?'̤A5XzT\$ŠDɩĝsP]?Ğoey* N jS՚|,b=4qb1X  A+mpSǠ̺tB0 ۾Lvgv< 5X6܆n{3{ JیmgXORW oGՋ W/`ǂ.Wvq"4 mt-HzKe)8ou$lN6CbfѪ`mZ3I8YWS$ K=6CfC>5/ߨ=|9&K04|o<j12ul['7\ED"J{2ҨhM N|'0ՌSXd˷@%_`!cD-|U6*9ܶ{t%-iq;O*կtZ ?Hx g !IALѐr $v9{(<qr~knlwd y;HfwB=>ys: xJ'hOGkn;P;g f04F}<+L- G["oCGNSQV+4,1=)=yL:L؀{ÿ+1B/߈Cή> lOcBtO+g5ඏ^Ns، Nyi}Yʰ9ƁJV1'1D1V)hLgc:M]&uq6`(<U䘢{sW?xFs#} ?W>}!C ,ʔtQX7._|d+xb\hߗ`嚟"͐C0JwctxVݿVDX[1Y8o6ʎC37H_k I4)5?: $y/EiݢD+{I\*w`D @r γz ܔ /S=?F1'@UT:&#LYwh78 rڢXa͎=M@jԾsoFd/ŀnKX?jMypA}VĂ딑:%Q$Ovtkym%Nfˡb qo|i)T;~4w`E7t,c=!ׇ8bҭָ$l37=E k\\xSln j7ڊvʛNٹf/J:Eveu^2k5+:_S #)6fPKYgr* OEv >z3x {A89ڙL|dN2ՕR3!x32V2wܾnzI&|4{"9s@|{mtwܠ`MyŊLW{r6).AԗjقݩW-x 1Mdwc䎶m`DygdF<6]g~\ۡxNg]سd݄z4Ñc"Q|Jcz8;6ؘ>vd1|Kr M/0 SdUR9#U9 U}_ H{McJ*:3M 8ָ6Х esܲc!PB~<zCe)Bq;ZO/lqCm7|/>~0~B N.Cͷ!|~Re;.͙穆ĚPCd^]U꯭_NJ7u];S)l"oε;=-0Xszzv8a!^nCs iNi֔'>#fdo՚lA+.{؈dmֵNQyVfdF!Öɺ#*vPeazoZқm~ich8)GP Ή8*n:rQԜw l 2jf ϸgQ1{S2ܱK)2E'#SJd9 0_SZ[u77UspFuU·e)6_02 .dVV,.zgqgI:.M?f_Ĺؿ$ o%@9gvx`:? 0DbIwpJE>;_R@B#PhRChwRkz&H_0kau)McI\\l;TS^{F=) 80 #۪Xs"/J0[s]N"#dй |KHW#tz%20gf6KHA}FvFO:h";=Lùkڻ%VzrPу?>"ڭ.c̤0ljo(|=xnfԕ"W|Qc~a.TI%)lmԂ9(=RljQ tY5{({qSn*xqQ~WY4Z9̓Q8%PPF<4 M>vr0>lOsɽV̶xD =(pQ!w$@[%\ވwv*<GI boI F]cC?Q5oˀJjߪ鎠qۚ=O WL]|l{$,'^h{d~0'I749~QWMOwM%rxd6HִVaef-~C}ʊS,.jh zn:mvV18Ǝ TgM\,@ke<}Wf,9<$aWN~ʠ*dx;BX*4nxXl/+U]oZDM] ~׺Lt684H!ރo93kq#0Ϯ } %]Շ ݍo=i_Ib631 k&M%Z1 t>ԡt0µۿVqEe:\<2m,/Y.! 1g%JrX?NJԌkL閾0uTą7 gaT K!>T Dk02I~<1Rn`=kH{!{CFGdzܺ8W:6gm3 rWf']0FoJ*vmỳZ3WYkǐ 67lS:9ЎæhVTU$V.N^d\ \e"-:j&FOP<7;0ҟWpUxk4#e?GG#E2s !컠/S\_AER'r0i`in36wF>1Zn7h.X(9M |HU踽&iKiL{9uIBiG,}^wA&|J~7qR$?" >o/HAtIG- U-[I)`XLY)Fero,O*OZʑkf=`ËxEw$-!WgqMk !5Hsu*Ys8yLn4/iSČ+k(d (TA۵H~5Tv("x<*0]*qzevv[hs @i\2W[UF݇4$](#AE _u|`A uv5mN(Lej}ׂ"#)D=Q ݁t:<,Zf*cA* ^yYX ÏNvP^ߗuUřL7,cTyK?h|I tت> -j=Ykp8u<V>aGLP^?|kϰ_̾D(ʤ[ٻBu{,EN_ ,ԃT}@h.;Nqh2Mߏ$-xmxeiNC5ٳZWIC #l럊-|_939hWua*mECLb@)-FnlqM^yPBY4i0-r2w| J]x{9_ L Ņt%ĝIGi8ABQKП?zCA0FBl&k[w}'Bbg 3 zu}!O:+n endstream endobj 105 0 obj 113085 endobj 106 0 obj <> endobj 107 0 obj <> stream x]n8ཟBvQXO HYi@#WGt>R4uwϷ?oytnW/^}cZNy:Շo|v/yUjNi%]O| _sՖ㆔_cs^mzWmasM]ǧôڶcsS1疹EYY٘ w#rbNsmܳGn@?@?@?@?~_~_~_~_~_~_~_~_W~_W~_W~_W~_W~_W~_W~_W~_ᷚs~7~7~7~R~7~7~7~9w~w~w~w~w~w~w~tF8#Hg3ٶ l+ڲr Y,h6;сDt8. Pi|Fv +KdDTguNm-^F ̸>-AāNą,ua`ʼnALt&8eM<#art˄F{ǁN tޮLvqpvvΙK2=n=azf1OOg$@;<) bwW<}ynS~y.XG) 3,ud@ژ4͛rPvc1Kzp endstream endobj 108 0 obj <> endobj 109 0 obj <> endobj 110 0 obj <> stream x]PAj0{LAs*A!iԒXЃ 3.ϭF3_H#8ZǪqgד 'o iKi!dKxI sS&ulMm\7j9(܈BBsJN}RL*Id\oT2霖i z!J MJ\:=[!\r4 endstream endobj 111 0 obj <> endobj 112 0 obj <> stream xystdmQǶ*cFŶѱضmc6^.wyƨs{ͽsSc2P֙ gacdg#g%C4st6aD]l.@%1Љ`dITp7?Ζ ; D )d &.n&VnfN3##?'9rD M=LL@'ZZZ2a;{G 3sgnnJT440qqq<DNf uZ=@O`fao041šfh YX[۹(OLta@[9 4wvf`KYӿ z'Sz[3N2Q[a;q+YhG Vvn^ 553Z8%E': aW`jh0x9Ύ.@  `ba 0YOh;@ƿ> ;[kO3[훝; @`bbbp1|_ZSE -Q')%mML珐 w(r<?S1RF6?sa?y϶q o \*UGY /iؿ0߹6-MW) _TcbgGIh`llw[P5:Z[,zIcdAs c+[ӟ]5JDmL,loh_msljN h ,zkl]PFHFu2VoG[׈ySi ,,r2o'ĈXO';L>GU.%mܝSs$$8:>vGl+ʏ#qǓiE3'Z wm(DJ5 obM Lw_]>pŃkƟO۸y!aY ?˜er&KB{8- 52bY\oALT=3n]);]ym^U@LRGQW~PgWC瓞h^m+< K? -<1DkYEӹA^C}ql/HZzjW߱)G˰ppѭ|\gYxc|U`e8|S`s >_&IƓ:j=h}(}l83"ٺEB@לGiwu~e]7qi/iv^ƨZzDz^xIE{DŽ^\O84,JKҔ!<މ 0>Źvqxj'C  #*uތ+j3\:Q" -$KzïF>m sNI;(ΞyKU$ 3eQ aQ. ee>$G,h#ŹTky`h c 5 `DOF7AecH^[яM dEh(T奝tCva-?~YGƌ,m<>$۽dG6`;CxDO]L=#D]ObET$s3>ez|A D de kX}u)Nڟ?"2bA7ҧI3v/ͳNZ2ޘ FgE7wdbYr)ݳǔ~;bPu{~pj΀_gZv^Lj`$YƄQnungruNJ u@}\<Uo^f1R-F.Дldnޱx(%HTl)* f4K NHػQ˹7Ш LY@I`qf 0PA#0 OUu; Y-=ʩ-mTkMj_klLW8jv,W/Xś }iR|{ 4{!Ov3~rt&?$57-Z `@CYŖ_|<]ܥ`mIƼǟ"8ӳу?] cJ }dL2u5}Ŝ>bI*a^QC$b:sh- F)CT3(Sd&Ea?qN.J𴌘Qt牍@2=u녷u:SKJV  jt>}B:,*)#L&jĸn, mNǂ+j /}=L'b4F =.C4}ֻWk{=cXHX[fA:pMf*5Gפ^&[_%1*!.>)5Y>8mF[iQ8 U?9&} ؖMݔZnrK;V͆l;;o" u7)nʞYGh/u6;Bmyyqj*4BQ[\M!&4 턷1wZ$TB,|D\8$Gw$7To^D @oU7wnv*zQϋT,o.HV C ZO@WGtvj E&k-a4 lPke,x)y䥟PSj8+3p(c%Ta}HjuKŔ( @:Q|V6ZLy/#:s=,–i 0";&GKy?"-"~Oj>₅CK͊02/c)i C`TL"bpIfwvB(Xt_lf%Mt1np?TbͼOpo|!OS#~íyĕr!˞m':BIzJj%AXo<41hnzU:<. $Q\cqI4 B9/VR?bE]iJ#jU?p au#fʚ1`U<ѳq@Һ>Nz~ݛ@J \A"K7B3.x]."TMg Ip[)) &Rq29F[}efYR`G*S-YHDl_L~1Mp:xVΡ%b8j7 l`WOC6$^'%:_^(sev0>_Z<2:7f`冲dҊ~㽺J6v5^u qU4ώ>Lq(M\`x+f~As?&X'3ۢ04jS`2aU}GgպU 96? uK!$ј0]hGчܴBٱL!JP2jb/?'V[634ϢHHFNIOXci ; ]2%xWPm/:R[5  [TG((Hdmo VZL~¶av:2y=ȀniW$MG,u97yc/|ON4 ]6I!ڶ\m&UBra$xSHӜI+uer]ƴ]);7j,orGKGIG$COk*oN[ S?PUP.8RX&\LfBgBj$[3X.fɳ)VuA~@IѼy 9Pay})y:/鹛u^q ?2ɤx]^c\MP i#:7}EA> AF/ +ۊoS=ᵐz.K#_y=ʍ9'F6Sv Ju\$υ^J.tnv h А/N=2z7mt(2dr+?nt&!m${H{? -g{أ71(#vԾXWA,o_6S.|&a~LL^7"~/[mt`%pgTTEB)swDn݉ GwI'$wQ_qBRaN "d|[x8촯m\ѭէ{u `M%E*~QN2ltۯ"Bj BVwFá(3^H*TrS|!`70|%p37ͺ>$ CjRρ'T Gׄ:<V8FD{1RS*`h{Vǁ%8۔XЛNZ&:v18u8vw}G~>z)RJJæ'DvewӚ@%ϩ j m 9@2QhvȗmrXUQ$ 1lne96@z|ո0ſE,'$yzPwf\&jXrWZM8zr(bY,e+M j عA{śY}>5R2kS9Ż*]nʌ&$/slޔj LANqMhn0 XTGm1 FCStdP}go},_Ro.`L7ߠ~0)Vo 47QlL3{j $4>4d3b|>mo& 1)Q=ׂOQp[cn2WiΣVhqw}o5zoǽj<P#&Z/z%8}_|x&TkQgtۤ%3֛S~C=M~uf0t>MdXY$zWH?&Cܸ,T ^yĶhr}ÝwFחuW_ڄ>Q9`RoMg'$a&1t·O7 EvZd>S^5!>3DuOvvE-|#\lWiY+l4+g<SJNQh.VLkrݵ=jbYȹT[ð. Oh<2eSЭ.<&IVxIP]cK DģDt z ȧpdoNx!Q?uJ s\T="cou ! ^7ԔR:Pe1hj!5Q)w <"Cq@a,r {l fktf맋߮m4˼I~Vt*OHŞ#14N_{Tr׶֍ k]TV91@(fS050uZ;Pl׎`C{*SpIq,8,93JC|m.%|zMˢ0/x )ƊfIlA*49@ ]^amq H(T߃(=lgSh0r5h ]xP%| /Q:H,n&aD f  >$Qy3 a `CTh  xY,#UP] ܆:w -G`X&a0jk;^ UJ*hG9cЬw߷ZvidHm6xRw5%K0"YIE[Isǐ\"ӡ!>&WZ:%P!|>n ?0F;z=$+*90x3.OF*t"_{~W xpXNwe+'hDO\i_U?] =tKKlF?/^YeYG<[))2xJqs4mȮKAqbxib^cb`RÓkX{i]Z5Rl#Ь0:D<B.)UXn"Tʣ40]pC,eGw+{ Hl=dX1n=m BZ# F O\_&yuoTTgq欄_1F=DIf$y&iMU:P&3ey78s$S?Οx86ਞ&<p׎X8EZDN"r˼~8L#mk*giQ21p@tQ  o[I|582Cg϶C x~Rz;dNw 3?)fP bkiĿhͭRfԀU5&8I%)l\~eD;`))\AItdʸ1( ٮVjoXvĉTiKi0msf7sV~7CK>8ZY/PfOJ6QE)h"nk}m܄Oj|Y}4P||J4y_ۋUk3øCHܴV&Y&υ,7x=N܈%{CPd\Mu VO)'4ut[`fc d 6*f )MtM~~e&ac8"ItJ(VN5Q~46_.1OKh*K=cF FS"a l0TXLb#v"nV+qyj\ş3pic~}&{yLeK@q"R9<^|&ҚZ&7!iIwl?K&/&a-+=䯀i _Uᮃo֣O, 2a voWU!'.quo+yo)( QJ$δq\Rsrn]_k .Cގ'OZMf$L[=1ԑN2 ˜$ DTasoUԍD*lUP`qrGkY6![H-dI7p/7MxFEњ;HVAݧԺN_BIIےH?V#V횠}ic{U$&୧$pCJm$IQXv߫(^E81EW?o!9uk[7y.ܓ%܂t:eMh?7ݟ@n+SRdX'cw6'SrJ1Vd٭0($bi?joS}a솎4?5qm{#* 0&a: 'ꦃw[tTnjJ ܤ;`Xj G`ɲ Uzlb8Z֜x#8rp=YCG#Ldb?OSJ@NX=aCrKm~(`!IVjtv6cHT4jJ)`}h=CƓ%ŜN_I&n:d](W`*'eМn(}Z>J93"P^6xFg}J`v4^R/\߰:YṊs5KKb 6q5&=,f @ ˃-^1QrO8!(\vLxSa~i j)/"_ =Hy([$4[nN!tp`s(@ި0 w$+Md_tbC 3Q2h1;}][ mZEJ G)H]YS{vx`Vda Xa`7u5 l$],Yr)sz =EKGg9hEQՇߖR&\ِP)bV;t*7sk̕T~,U2"C#bg0veIwmX Oc<)@[7h]6= ?咈{oA])?wl<0ZJH#+ h*'J__06X +~+>]olA'"|Jg!}YBɎ:7Zqa(tHh{rbmo=Ԉҡ/M{:XN Ixh^T8cj7'9b,Zk+CV<5_gĀm".]4_[f*IO}Q鎡x=/B'WNl龔~ ߊ)"6?\Am!Efjp,JfN՝]_y_LQdS5S% duHAX"BQ&?D6+PqzD&)ݮ$9ԫK v, ) bI;YM2óܵw^k{fa9ج%Q=`*h*-o݋k*ffBӂXC% yttbS1* \L VOHjo9buIڜs#:'}בR. '# TGZYUt/IB-M:WN?L0ͬ`۔τc\%۳G!ۂxQ!X V<3!ҴScϠbk]NV`^c4]rvlc2F]*z!"`:I?EHr@(轏`؎ W]e/,c1w:}gI~~(PG9Z 7{l3U*4E[.֙WΏMZwl1iT6Kv-J|ko tt?'LMɍ 5O=|3l[QMFvB͌՟cIc˕̛&U'/5krf}ă46i:Lu~F&\Fv49~N ǘ,f1-n3H=jҊɶê~,,Cq$?pܷ$x-wBF1ugZH/x.j_=Ky d/K2W"n;\ҭjmlTFpN,fnnx6tQxxX6(_9{ ŮȰG5^ÏIs e)ྼ}rn@Ejm*0͡^ 5\L͊rҭ 9tP(oy+((6`T_ЫI!2 P R>Tϙ"~\z*|oeOT'9e$0]} gE"q5 a:Aw$X焥3)g0}L aPsPB~t5;bNqu ߌ2LZ5AFQ61 OP{jFgC5n=]pʊĬgq.a_+]hcX2:li ?HM6íjo4̶&yϟ~R\: {I:JBn_k;TtOQcD&|[h=vu1ؒ)o=F {-) !o}~up ρݕ Zx;?ۤ^PrsDscuöc "uRd%#܆tdFc2ּJKud"kk?g%τnnmLL҄&Yl}9CI뚂sku LYɫ+5,K}_Z< Vu" 1 l9ob"eh+uQMItr`? i$'b5L7ͦ]*m!:N#Jε,C M/?|#QˀU$ϡܙMRW&d!بuߋ#`w,t1 W'i )Ĝ A~R2|m.' ᥠf *x+${f5zADz2,,y-3y|lx66}skFbE$͈ƬBUl}Ԋvpi ".Q,Hy̩0R@-A=kYSF+ͤSן#I<)Rb/1O)uןEQS 'K~ U%7uqE9 [paJGObecT4z3M]צ O޶vd E[dq Z+Ӈ^x 2hhle IGa1N:.,K$#룱Ʈ 쾸yN;;ʖysiۑcbgVPm+1XO\\.!aнn&d̀a:R* r]`mU>a6558]PZ=ߛCS< Czъ5IGL:-#` {V;McX;B JFcta"Zlwzǫ`@037L?{Չ*PJ38qԎ5,Fsp(յtE|!\5Si^O |H2Sgt*z5#m9legB˸BHvCIdwp%-r=\? Io"W7fypw2>óIT؟pG/\wi}TCeM\IlCaV KP4bh* HUK1-S\asr߲~l xb臐i.lDHĜ˯`Z8jAևNY/kT΍ӧ̯-#6 W2_;MM0 i ,Ect*aa[?ua>jW h};Qgr%HnyRN2ލXMj B&\P{5~j󁖆<y94rאpYh+E0eVƖ9L}o),U}AÏd^cwmL A:3֦Y4e;IU?4W7 U+7Q 4%"yON3((~%+PM?9M,m2+U-3f-Nԣ[f@F.P>< rodI0Sd9^vϓC&rG{MW)8٠Ҋd}ض59[50sO*{ONqK|5 3M,og CH fV% +tGzлSDꇞIy` 5* i^mpo iG 0njI4''&}ڡZK_Gy _>֗ڎdj UN3+\;ᗊ#YkaF-(;Vo uI='S0>Z 8U~ KI!s4˧#}K#x`G1Gs-&׷@ohA*. nz')}5~x }#=.Su}lšClbV,l~&d2[r df/e (7F5!m ~/+T. Udm͵Z rțGϥK2ViS`Sċ9tUy > B1><>w` Fɶ)‚^A5uo186g_R%7+Оɝ=?t];R9̻6̄6#$qZ DlurehBY'NjJ8oo/s_9!N6jDnv=f*i hSׄ7dZicЕTnrHtt 2"lfXtC/4'a7A[l{9>4IOaf&gHeSgʜO;^^YcA,PX;XܜÂ_#.P}RDʟXNǼ"wV?eq@|+g$uA)(D"<1zmRRlDtQ;(uok(RX]6}rrm5#+dO}'ri(B\XSXV *m]yY A#+Eъ\-Θj&+B:0T TytE%ԫNωKH+jqPwW uI/]HV%;y 6YmK $e^Xv***v0ctv[~%x{LwPXE4b*nɱH!r oMX,09v`GܐZVx́so#9vl5ȜV{Do~¼'x, u(_ֵM`id㚤|\n/ 1zp.Op9Loec}&k`WeWǃOi?P;i2<9[W ѓ 9\,uQ<~Ԍ5Nk ,|bG"5'g-Ŏ F9mA}MI~Ik=ZUevEA>kFD>yuj1;q+;lS~geJBTmXЂ_ ]م2M'c>qb.jo!O]p[׹jĀʢAfs!@!xsekt/6[ uŃY7@:((Bc Q`%ey2l*3͉pfvC-ȤOxOC),9 P[n]7PSoy9b[)N٣g8!c]ME>Njurإby^T! fx~">id]Rңw2:i";:*TeRq`%0NۍE[]2&ކf憉̋ N>4XDx(?p߮7jfnSm0JwF-ii1[77my]Jk 0VY[Klkkc'> d+bC2SԼ]fʺ$XqU|&3(mz=kSE,oW@ j:qۅe|Q5ˉ:/D!(7\f8kAĮ t4u-%XeGÅeov<\ڇi"0;ʛgߣTNZLJ|4^uLu߬k003_:yL t' ul*G_1pA^zKkh8esI$*Db7W3l +AUM9L|2VRByu<];y La~%E2eњꝸ8j?vwQ!Eqj`Ny62ddU"IT8~]:DX`b uD=ybܪ0GFP0Jz ePy 3&4)p-fm<݉=+ hXsN9Zo_aV4:[0:\jPVM|`,n7o Q* 0.yW9W& +9,$1As xk-̍CeAAs'խf5A ,)<Kmc?F(m jg/~H!+;GVg^?$> V1(ek8MɺLEQz{<)< 0 ,} ~fOտsv (z,E9c2mSʤ5^dˍ娤kYe A F5YD7W\3^RwaoF`AuD!eI5{,V{j#lg _ WYŒ~fn&\HjG|%-@6!*fm3LcȊdpp 5G'Lq j,}2aoR\¸ttzN%Q%vD(z@zHCzk$u0rvj<?e|GiOrV䧺'XhX+ 1ne[9ib&:!b=JgLCA%])"vK?&/1aak)J1F 511 ʜ5tp fQ;my o.ݗ۲mbf.qw PpE` طƸoጛ7R- ݬ]KA*d<=?t8(+;GVgEI<nؑk8υpn6IA1y|%Oj;E.$y&|喌#eK _o<^V īEFiΟ=TVpa0I =2e\q]L!4iS$ J.E#S ŗߒlrUx !.-X[To h.`/Vg bM;2)v+JnvQD{6mΆwZ apQ~,5IAMص)%b+)벮=yFC"Bm뢮 M' xeτM$.t3Mr6>C󡵝ܿyj)?{ⶽ3~!.Fư:߀[^QG20 qjSj4`&D)'YCi̒7 G&O{ d .6,j\ 4Q=+WE$Fsz6I 1v^s{#Q++Cvj{F^1FAE zπvN= ^#boD9+&T큤\oƒ03_lGIĿhTrf KE8tzF 58wpܽC[,2Pv!(Sɋn$ 2;,傊 <*[=BaP=dհvooQ,]Eӛ^i 9r8G'A`& ]zͽߐc6t^gc&|NEYdvC!ё#]saO^E~f:&v)"j uم]JW1gv]|z-5WnF|ʢƢA&0O"gP\+7ާΟ!`!âk.wuK͈"J_?tsRcb4[HM @vi*0SPˁY@` 5p2*LW܁(IHGu۷BGj\y#ۢnӐ,ג.Vͅ%%̵w 2}N+x0jY1P흶k_A@c88zz a*yq7a k7roJk=dL?]8ضSb}u!l\x3&M)>Pq…H%< ,ݢQAÍˎHHs|U9pCEŢQb) OH5 U8&?$n 'FC&MܑpeY/mϽa$T&W Qrxxͣ)ԋӫ/S.M\D:.e_L0'c ˧1 }t*e|fwsYGk(IB ]"5:C9A yhF^ Y9n iI5B#3} Ub^ 8`9 dݸ=˞1nx(#8W=:lTIchQ3В~TE2Nu`d#;m[0pSi(8CC"Rۧ8LB6{[4Ӗ82m*!rX4D nWlEWь~FD95ԯnx\O9n 0d fzlWvR&I r҂c"֦b-czTx{2,,Nχ0Sn&nX /;/@FXvπ`h-V0%T Q-9MJaT!jW.=[.Riǎ(fe' zQۻ(]egg=IU: 5[Kv(Gߍ?=0,4ܳϪp4"z4d+2u"K(BnW^tZk>Rӹva rֺ߸T:BٳKn_@)1o%VXbyu|{ ~*/Oj6gtHZƃc&ԠCQڍfbl]˵L`_r ' Sk~par-\f x6K6qɊnEE軈T>߅cL";X:{\n%G ̥3w`T4}Ah|% n;Txn:UۃhRb8gWC껞JR mH,+ƬMuw9{tz+g݁qŦFsKTHr0NֲpW|)$-qGɔ Veesn" pMjmӟ cw1'~%4fDke}W(p8PNbih} Jw–)Tr0 baubEJ~pDyXni5J/?N r:='AR{W.ӌ.ℾkŲ.3m1 r-1c"3mp-]44^IЌ$Ur a嫰 N̢jeq07c%wʓ,gjl@}hƺ̦d&g4T:+b\ҷ'ER>"!]79!v=,GӮzdS Sa<mҶ`T;GEX\Y4]]IdE(]`݅xߪilxl~v IV |K'FRJgȎB9ŵ2Vߒ:F'v\-O0Cב3q,7gx'0R(6V~FB*H3laeHӞMV\/M]#UN$ wNqxԋ"~ -jhc+k~*D~AfsQ7BmgiU6z1z D 0vS6:ݒl43,LL;N6Q yoaړscC|`TIx΍b]QLKuF:ʓɺsJC7J!ʹ!6pZ=-#3{0v +ee)IR΄$UfB5'M˔B+imBYURT!qf! bם-Pޚv-_-EY[t!s;1+7$$'|V-p[gQ 0LwӢtAJeLt\mf5(r?.B!e^kS {'֗kZK(W,90J221USs0m9+oC.*c,S]'Gx% Yʂ@ܑ0:LܷO$i 鈮) jxU.:0WHa> C5< CdSBsz}C8: av{xEF黾P𽓑uIfBQ|oT)M0n,##S4%P#3o?3{{ [!a+4o|LWmJ mAغPCZ/MiuڏAyԦk{H`ohpgON T%DhSC̪6Cc>)r2t(&ZM*L(7;3\{ 3QD҇!bCbޞkvbd#"هgr u}Z|Cۻ9 a ʳ^er(c>&_Uc G?p2eH(%Wc( A񾫞GsAp!ukge1ask}BW M3;Z'v&p X0Ln/9(4t 5\=t=ƫi轄P\<]'/=TPE[^h8 < ;͒)ԊB @̞KT /ˑRY< j aIVI}NlїqO ͡FׅmŞS~9k BxNKxbQs ӱu)V%Opq߬UmKS6KE1!8+g޹F7oN"IA"8yJu&ϸ1=\yetU68Exd>;YR@/+V8÷WssjϨdTq4PUy)9љ'?٠5AJSvWMZλ .d2&j( d cޯLh]y6W53i 1x:ZY We"C,WeِAhAԙhPg5é¦BHWׁF~iy/8jkJ)l8l>Mv pCe ]ɮ$ t }N~E$Z0  Ǫv'*bTGq.a@Ȩl~<(GJ_IK =$TT߆֊|l,9 ScdUet=I:֫^|a -ܕKEB@ko)Z|"$*ɥ{n>.^8DCۛQooDZ4E>\wPHO5sߐjԽ2S HLy_O|CCsg$`ߑp`&#o; ItXbQ)y[$`772B;B5EbN;Aj16 i@M ^O끥,B(Sv}u"hq,o͇2O`ʍWB8 7W9Pb8 63B^aÀt!gm?@* Ge+ %.vYȞѪ,o=\!9?[!EG*mRA C5#q'4 X2eI!o+r C^crx='j[GVu_u3_ig$|~W=}LoM)`hn7ۄqJ eNY~[7ik&\F#NV"qӗ4\N_[搎l.4LǑ ɲJ-v.Qc} S3NtoAU8\vDByڟ'O$.}1_SWik%vZz ͚Fg[q7 kz̬NTg!S>G-dM5o|Bေg_cb'DC+ٮXܧ` Vvd< Y!?T'G?Ԗ^DFHWmO,Dg CCNO '@cCGBJz}Ur;Di Ae A)Rz7S:mmAͮRzH[1zG3c2Bm|I*\+];L?3X濍N<1*K. 3RFKN.v3u\ }@EXjHB҄YsP(W4 z1D`2RXQHõnҿUu"ǿ[xeFthzkyG=?lB_)"/|.Mر-tNc/W2#C?=([EWȓ*d/^%`j-+g;)iDٞ-27zb3*VpV&_ni[,>UZ".?*@4O YH N^{Sӯ\Lj0NPN%4X}tGU^aP [3^wC {f8#k:G@A["!Ů1@Z?[ف(KGAq-<\dG!ݙ:gC> _ @b >ҝ^(thS<|&D~X:$_he-:݆9<>|1 %S5V#K~tX霫iX ڋ!8m0B=ef#bټK}U@5 )[y4n8IHuMk9]i);:E2 -3a4 9`a@Jm6f ZKloIKǍvӒ^poHoCzTrb =fuw5Os?1އϱj4{&2U|=I+8W f5O}wLȚj_HTCJXML*QIx\Bv 迏X!]4pq鎡=ǿ<: CYﵧRJє[_8+F.wL5Tq LÈ kl둉S37K"A<>i뵥' Awqz`a-@/֧u?QKyK.`CYbS9x$}( -q/;>uډ@r݀&_ ,GAc73u>~bBK]A ʒOHI2'j%hpVP%o\xkcjt `2Ct1X { ;&3.5K?ORK{wb,;Y; Ԙ}=ij`X~=ILoYB':}Wq{{5DLk3w I?5ddK $,m6&dH:>!!~ zxI$7KÈ{i٨l=5R5s[0p){9<]WV6ޢ3o,?auߤ 䯋 s|PI^bXa?d<͡ϸO7M:t!C^IG $ap@ Xjgm*Hq+vS ꋨT([[ly\~Ci=/DHa]Y MK]Yi&Qaȑ([(LZCĨ1Q!!0m= nCׄ,Im"MH /`Nݵ\QKg^!<7ڝ#ۛß-Ț OiC,7T]?.|*HO8gY_1WP)nkv)2*^K ,a\`r1sꄞe \a=kq8]?g䪠PŁc*|T嬮%`֦&Ci fZWlg/-_);BׇUf@WTG6%pT %[0m,Xrk~#-T7~Xx};B+!kR |̇Hj; O. t{;&O&X'[A|:vjFNF2'1t騗>DM7cpڳnrہ޵N,z6r 4*ujm 0CXg"5fXRdD&=I k&07!HQA2Ⱦ<͔yDR+wbL֗h~8,) jVC+k\. H7 e#'tJSd=pv}%5@6ot[&(0ٮT\_`ԍGxǴ`S[RΑoVAj)gI S~KśQ#pPpPGt?Y3?Ҩ pBlD-[ s>vFLN֚5/=GJ8 iaTg EGrb|jeD#J]YbNb1ͯ&cZ-xh 9 m|2>YPŃ3ᰒ&P|:Vz><*FezLUKn* bb،4L_*l ܐ r҉g`r(m٠)P3d#)qQdaM9W9= I5a6`w>a4BQo 19'N#(,K(Q:aEGDK"u67wu_bw9';x2gcy$fNuǎs~Q-1/z &o<{E5Z"EطMlQu!{&Y>%;52覥(lΤq\X|4$ zYwϳuz>SFk~Յ 9@7 O{J2Ȣ: 4)/zlrƸ kL9#& kLc5t?:Up2%Bs31\ڨp$ɬ!i, e4MYӵ A~5KG8aTVrde"܁DabpYbК_[?B_fm㧪oJ/Ĥ( Lhqȡ0aQ^],Mӝ1`$>mHwpґ.Ɣ[JuׂKK<;\ЁuRJ$rT)x#E{Qas8`lډv dq^ ]~hC/ #+zRVI)6K^Vk! Z.+&+ak$:vت԰\2S4 0̈Bg,\<佷ɻx_*. lҴ*^> *mۙR$?DMEK '%#x>7As?;k <-ͼΗ @۫7ҎqNDNnK`Mc7H# 0 uF{+Hۅpo_ܘjh] CT\J` 7ϷLigp>Qٌ4a\R.Zy8?Ԅ xٷ!d3Uڔkf;f ̬VH4"L7TQP#ЙQs'WL/Y(]a$9>!!,WfQMd٬ S/H, `R9.} z5@HG:.f>D0Po:Ût%3c]4[|xTЅc O 4mg Qs8# @i/ $XE?[e ':e JRybᦩh[^CStC)|i>hfϰZXLP&\)(Ł62^~HRVF?D.Y9]fJIi[G^{W 7M7 z[ mJB4F«qT )7~CbLٜ.u&?)i\D]-:0\^M}-q3ҽUQ7f;nV,a?-,_4vTi*' /t9+<; 9˻Yabs33XI}k<;¾,\HM'չ؄τ @+j65g*n3ya< ^AiP2y05^WRCr &v:8NK$DyTծ '<@H}u;ږ*{G·kQP!l ;}Q>c.K> @8J:^17y.#ONqvˮEZXyѸ& p8g1+OQ(w<\QR3D`12 :n,|lsR!/5ӹJKP I᧭ǽv6u'{ %;' nGA/OLvWLlV8h3$ssS8mޠWO?'kK #ȃޅ2-02j?9MbDMo"d{wiِ|PgɟK|Wج =W=ٽ IHQW*t4p&[<&hkaD<|m08%߾ <א_k]gilЎCe }cV4& j*5$*X%$d悈fqQodm#QJ!p}ޏWzfud~ Rzcnf-&:^;os 4_n\Nƥ @7)PYd)Kg]mxƸ';nw#)9{i"Tzs%4bL_O=bE}Zh ʍ~1QGmp`SxRr?0ΒdkSHTιǡL!r.#KAC$g'ĩ+8|^4HxMN1x`y\X%n& kxLZ*x3oQ )I/AaSR'^-ةMvvq|Ⓘz4%eͣ;sNS! J?ؾ4"ӺH(δ9{rj(fsFzuy& XOmtܪKR T_E Gwwp$$ $$^=NHd7%%Ą)Ep|#n*܄@\WG뫣w._Q\,ty^i~C2N =b*63~5꣜.i+h^슂p恦(|WUnLHH~$ .Ra͂#myVBbM8sHLuq2m=xKt\iE?0y씑h@T&'OS?e@I/^6E=&2\PgH^OSe8`c[Z?!5US4P=C3X-Y> Ɵ+ܜpZx~ɑljbq|P83!NLuvX*;B6@Q\ ujA}S#vmV]*.bRpӚd\S.=Ǚۯ9A ;>ٳ@zTvw%P-M:v^ pw )Ϋ^ݰsW9 \l!lA xͣ؋Jp\@\!.Maq15_/tp&2P.吶]K3θޞJ%ư=~Q7@J7x4u["WII{Hv׆oyD1>8Oޫ)ۺy']mq'\CqPs `lERflf$xb1b܎?(4 }-|zـDWȫ!mB=DBhZk kR 8;Ökeo~M:ҋT 7Fթu1ElH"NW]VkΡ Gtq O[P K{AXA+"c1֦鑐،Բ1d%ß 7׆7ik5F]{:ajR"RHfh:t7ae*9Hʹ@V.;%3yj}|HMQ\썞ZD`>].}z HD4 (`^С 줟)r{ӌ'sㄧ uT7ɐTǕvW^}7f(z5C{ Ɏ>L1Ψ iiiR',c̚,ҢnR%iјӣ1aqU-x;Q%Luz w2ۆ7b?7g/ h 0#dbvlxϷ$zP"G%`. U0E?e:۰eEN'k'7>P1d73:9ޚJ$tt)g:H7.9l 2AH?7RAV ¾=ZgЭ,y|s5 ;G!,I9i5n۫H+9`ul'8Lڧ3&-hT)Tj&4*9ܴ f$K|bÎS*\dm ;zՊl 0&07Hm"P^QN¨(:1UߔFXΆd|MzJh7g i |+]-fz}*Ե=}+$wnMCv}oBf=4StiS׹S:U^0 -Yp.3\j mƍoKJȚo.am a~I'G c~!GhaktvĊ.|<@yn&L<3!5ԉ>c ^WxUɬla^r[KΞR"JJ˛k+3ˆZlY@kS S9xJz MB37iM|"7"Pp; L5V_FTk yY ;ޔG$Bl ܂>c?iiI1B9}/r[SQ٠EcLX>a#<^c@ۃX|pG+$IcȜyJ~`퐾FhDsjauvJrlʌ jMPr ˜ {ilKDiSQYۖⶢi(nYz1'o\7+f25 eͧ-GY_= [w7- Sc."{ 5ɢ$z$O6B0'Q/P]|2X8uX~ ޭrQ ?$_.YV{;H)QA7% 7eImT38TGpE!-y4DdI a>r>["uDz Np#1 Ӱ!`h0U(-|GxgwlT|Uy͵u8iKەu]uaPWRl1R7:_"Jn'MU:D_t,Vkǃ%xBQÏ'^=9.{ՂTeL IF7X\fm A>fN+0('}fu)֩1RGYHnwmj30BSMU|VQWjts9r\hO߼]ɀ2 MK0mf.ASw@t8qKSUވ+s|Ig#h0l|̬+z߅ v&R ʽHeTCg㮉LAG ] `O5'(&n [ Y2~64zUio|s}JkDb Yx_Wҹb"ܲ[oSa'|;tpyg31 Yqq]A ž4WwiHڊ q z5<#wFd>z.avaedi8MuQ-z~.K֧Q ҵwJDgx[9/]hh׉{Ҫjn3VO'łjd| ;|q;oe6+n=ƹ6fw'M^1&HPD%4{D~zA[QCͪEZ;&شO o'%(.H/t QIqXHWOVG$"k0r,1E< Ka%Yy~-Cj:#/(&"SKl[f aq=ArPb_8<{$!(p`8u,gXR?)*ahK{XNrtRsJt_ρt݄}c2߉pY(R)g<0OuDcDF{jvSpjU3lG7 aŔ؀!Jټ ˜$na!v(#OK^_Jyn"" Bpm%|D.ChkX-0 ۲4a%lX[(9eoTSg6w<Ԅ+7 ff& zG6q<-2մ[CKg7і#ӎQhb >ᨉpV/M!!./Pn_Ԕt̸!sR,jF~615c+Q5C3 (G*9-$95StNpͲ ->P!uQ=`*Z喝v=ψ4Ѡƛ`])Xd6Vϓ`XIY e9ɦEQE2<a)նwa;HGg =}BT[+/Yq3d˗~񹰙$CN"bp>3m:`h9 >m.]TRaN۝2l˼tK1N Iy+K^9j1Sb_8`u*5g=C' %fUH?`8榭l]mv>E[6ӱ P]î~/}8i#݁قT)qjo g\Β&`'ao)=]H):o칋!;UVQO\=yHc}ܪmh]X!% {4&sɸ_1{I[cƭGxۃ~^EDw6f6 S7 I[s.m ӉJ3zwPKV42v1+R.so`P.b4pS$ěMCd\Dy+4+ p#v,1hWfI8(KcE$dJ,kgSkSQ`hЕN~'t7W1s^N{੅]l31xW!zj_\\Dq+P&ATZ!G]ˀDd Dk{6y,k>KzLUT56l٧9(D!"r_9]ݍ@3( Hdm 8u ˾moKTQhbнGԾن wzSS [ǿ[d)y[ ="8T6AUkP$U_† 9à) cB=*P J@ҝ3pĢvtBIgg9W&Lue>٠BTZ(!2zdYJ}0 dH49c'y϶#9gH4:O: @ J}#YT2kd% صbfX@_/ CWIB }Cnuko:K8TZRqST9Q]v~7,nE*xB#!r.:6_iUo]#oald]RL"\©6OlossE ٫ ~)G |V>&Pg^qEؤۭjh^9'jLҵbd˲%s( ͈\ui1/78۪ 1\ד$"N~N5"ɥlviScS) 2-+Ӑtlǰ1߰S4|M@#J&{vb6zD.c\~8/hs1U^C>=ekZy.3:t mz0E`:H+ڐ\/EaMtDEHr%PMj5wFJ0 ]y^ȝ}4Bʃ"MQTo+r>cĢtLM$=[KUʄ62'R> W0 rF^sjm4^e~nrBIܫL!8ڙʏ{#װ/rhR,qGn@eV>Y9ݖl\C}$肒?6zGjd݈cX wv(-aoG|aɲ #O&)l= k_.kWso2Z8UekJVnQ0 cn9Lza=*%f5 "7Üҟ+ {[2""a:mH_MBQYK]Pxg7M d|Q;E&zmrA*ey6H=EQ҃Tw_[eL}}{ E,}z ZaeiSDEzNi܏Z0*0Nr#2/tib pWMހ WHe-s ɽ`y" 䱕ږP0Zg=dK'W" etG8Gv$!rɲiTJ„ϓf͚Cd(Cqtu|0//O|JSl|u{vu?1b;tPm4UegeV.E(|(׮<31&;qXq`4/m=Ͳ1Rb龚K/ons=J4,iQ*7fv x+5ct*l¢"5 A*ܥ7 A_;rSzE aaM92$geXy* oZY-zԟ0+E KM+X. f3!3cz*\{'oq#|A!HM3MPr1"XPaIa`&!>Q]=>Pdƻ >VkxwbEVukŵIQwnJ0Uoc-6WKlci:blNhɕQ|ctu_+Yji3s\HCh7>r7CĈdJ n ŨOXBŠZ8ͷGDnޗ>^ :Tfo{,j(ђQ$`\{❾CҖ;7 (`G>'~4'F Tu0g3O!.%J צ5O&FAT3Z7wI )2Um5-k߂y}9yx,,)ʨfkoԻRDF> ߪ*=#e;%ko~$?4S.ʳ-ld#Xs!C2=]t5v/‰́CޢI)s_G$x#ZqN+!m RpS. l" 2~z Wڻyu? 3[ͶRħ; 4^,;2~)b3^MÁ( 7Md!*'а''2̝P}Hv3BOUr0_0Muv?V,|o5Ws>]ci-׿0:3\5i\Z" hW*; !w!KO+nWֆqG R#8%duܕr/]N'>)c=ڢ vɪiҭ.` j"*j;#>o;r A.D(t Ai laQI$@K*Gdqh1(Q6'[ȘeI3zؕl_XYp║25QgNP2O3Q&klpúX<>*_X [Iӿ9YbGۻy!^QX}3Z@Ҭ,dB'Nj (5YQNiUVf:sa0ӧĖ+ nKRX;ݙdgQo,Z"|&yR;1sgE+^;n_nc&|*VX${LgdeL=cYkH;J2nE\0wB@a(A4agd~$o'`ɢm3:$FBRu+`)1'; E1 r)j%p'LJ}@'_'eٸqjWe;+BQTu{t"5g g6`dVڒt1@kl Ղ )9sϔʦkEF՞xFL/׵8$2K޲(S}ݾȦ`)>F _ ˯`q59>oB' YJroF5Lׄajg).~c lrv}ɶ~`xe!n7cnqȢ/,¿׼fkq#ΰ[z? bYP@GE'-~6 ~~(_\:yq¥ębzw蟾dJZڸXx Mw3O"t4"_?\]t ZjPH]u.1G5 ]״yr8*:L(w-pL-n57~Hf?h]WP]bF3cc VUz)t݀puKHHab[PD\xrq *A➏*a~0m9wwp\ߚlo)F<64K!04dgv%HӢ];IvB,KP~Tg"܋*8 )rUߘTUw- C \Hw~ey%C]#$~fIA-i+n_ p&|;Xjjlm( )hTZpFaHe\} =r`wY76 [u/vQ*mg4dC]#[`|)sgzxک<˳`'uU 0O ll{]=N=yZ3W#>bo? 8 8#%1o(tƮ[G 66OCb=6x}IFkhXI8#=:BxQN.z Pz h&Aat||aTJ4 b1\z uk(ԛ|+ԷYl5y~X#ĨNobT{/\-L8pmP9l܊o\@;B!=Z!=@^`}:(x-\Y+bzC {uqXk~ZpYgr;ϪW~/AЗ4iCAB?7SF ,[snbcW+ ُF2VU-^DJ@Ճs \YhJQtHIkV+XaE>k"vMFΟ0E;ILmtnv%^:a-U*9ygIdã\IB2} I Z'[!n$|UgmTLn$jj3;*Ɨ*cm[0!s>3x(KCHH]~n1 B\fĵO.A ۂ!oT$[ LA*J:D"*${ BYy ʱCjPɊku9:fn{WJ(KL!6"-L}o~l[tBV'Y0݅`{tSR4r%1I{F~8ui (bxqdT HYۨ,A@5:6ss.QiOYY*BR QdE ^{okgt`#6m š,2x yiۮyvb@q*=Ys__Ԃ샇J@J\j8{hQ͍eqN\2޿K2]g/@XJE/K(EBG"LY_cYm8GXb=-#@43%ۉSȴ>IH= 4H;!oԡ!W720Zdlu-|k{֩~>-&fW5do+uuS8mܪn HWNw= P0|E,x4s阒JʦM)ښ ADst=S L9Fa$饠B03cvjԙgL`簆'=kg d:ﰣ[[c̅Gĝ SJ\-UI ;)mlE}mYLzF;H0(nѶ6GrAk|ÒT0_u>#pz(ГҴe$SמT~Vx M}0#|pGAgS睆0ٮly.v$wCFzWli  x6ЗgZyn2tRjW"+SZBg>18н?'R=HyDd6kPNxЙQX4ӬIsH-1rdh̡"Vp^۴f|D/o?*æp+S3Gk KvW'9L0e/ ƎrGA:f 9;X՚}&`0B墧0HۆSPϯls{ (+Q0CB[ A d9 ҈*ۦEGYօ?p+$8U=f{;?vȼ|p$Ndt'Pڟh}un~Φ1&h;¶iuHAvD.8Z?d.,hގns9UdӅq2hۅk qMw)q=w?Sȳ|~]+&Da).'`c i휝 nd|>rk!CYOwQ%%X(fPKt}!D,^4;>!1!x=K&ԟڇY R߮!x(cGK[zeX Xw-b|7>& J]McFfE*XS`YKc.Pckg["s0ޘ*fBO7ݽ</陀GЙ5S|&%h"(ขz[G w ΆGzF:Zt >̿%t^!uGn)0/k_I>_lRhf͞ϸ[k0S iИؾcZ]6Ki϶e$/$)jW @pn>)UJޣc`Yd?{`)CyXa4^ ;[ܱr ~%NOvȟq湠 ?Ifx"j D$~iSn)",HJ0s [zM/JyRsD@;<<|W+gc ";xfTWY=ϟe6aŜ[:}?Op=@|gs%/W-WהrIuY{?EYtsLHK&ۺSK*ʤ]2 Zrj% >g4tM[%U:nyE౎`;Vܨm (fRwvek5F8ExE2efQT9zx {*/:_+7Ğ\ZQ內ӖyZCzs2D[{XDb"c l{S"jUTmA ōsndrx5wǎy>qcPOĞ7QWESĀ]]@M\Q^k[<pCӦ1lHՅA^tiu( roTS$9C_{殮WlY@ZZ*KOpQ@[ 32Xn5x=b(w<V}Ŗa70PŦɺ(7u^d+9_,)g`KY_uwV[#ډQMUːgtzoV5^w jf3-f1_0f|0;S;8 *zS ŏ K 7p<y]e,# jy9gŪ]${{]/gꖷiƸT4WJ 1ǏLϰ/k)2಴ܖIkl5u L4&U1N66Ds0VVWL $W@ҜSc!?%Dw[3 4OC{µ5$␌WH*5~ZKIg5K8`){ͻ\[$FؒMcoF2˓u gZOEo' 4ʯDT w(E,nnA aHᦋ57-/ɹ9JNaܻH(X5w8 `,AiD͡EԒ 7_H쥶f ^6vus0IwޑTo zEQBdZ;2pk:.>Xa[iܣ+9ldKq{߬3zWڈ z{ !(NW0 :'EclD0^I3mBG:} >!isROuv +ff (!{iss9ֻx)YC ;OW`\Rr[K9 ih@Y;ÚC6Y̍wn;/.%@ٙ&}&h%ݻ Hݺp`&af v_#av\Tz: ݳ KWsj̎C4i殷 7E4+qG2ϛB9gcM%p8P_aQc- 2i_X%Ȧj_ ZP`NM1)7ZثZ]#3O  MoAZxџIyD  ^v)DLQ-5Yǀ p7$1p'Ճ Gok+ؓVlr+@lg{4kSMZkulDPX$j#~T~xWOϮ8-܍1@].3V*f0 BX@LvJ5kζsv֣$nFU=7Lly:hQIq{ūD豄p_4q[_0 BѰ$ND1p=ɂQx01D .jtwq*oߏF.6Nƈ %QR|4ÁK^lB'{[+}9ұFWԆ06ܶ$Hj Ŧ2W8 \(>ia~DSf3ѣݛFi2cHp݂–uLy1ɸ։Rۃth ooqAԅ]^O6eur=u\nHJp%׋2nαgԠ::*Y?菪, n0<'tɗjsqg:UskYp5Hlnaxlه3* ?*%܎eηa+UZ M`64e(gϮ۞ :Iw)eCPr'9Xf{Er`٫\K(>QQiͶfX۷i4~rs,)AEbHЧ..$tmI5 rkŋQs@UT5AGP0gJƄ5x|i'ճ Iy"1p!Mu- 1kc爝RVkFi("ISw>N{3sfʀ~?yWCV f^xK'&̸KԹ2;}D+:ȅ]`kt 6=ӃĂU b겗)4DT NĵBR8FUҬu MGP6Ta_[얧(_tQÐۧixoJHL-k'$j ]f@CP9c!7S&{8ʽZ@ "9z*rG ~LV#esM%f'F[k |E97E(sJ8~iǐF~b9$mbV@lR\%A7l L{ H(\#5\[CSl;R\7K''ĞTI5+<6BӍ qGq16;ݹ%1 pHyE"4# ;Q+s(ŇtlخFT9FFmG,oAYUieK)GDqTM•yˏ]6WKlD =EJ4N<693ʾpMY^m_IhCÊ)CftRo)4 !YVCu@ 6Y0e 0QI[r  JK{߈ڒ, 4V&V3~0X{_)fM pWKކm |Z SvxW)겨KƭRET~/0 ͹ݲ‡So>2J TЅ1>L C 0!_GgHäu{iQL0%As`nKQ Ia 9^ѾP&5wWѡo.ٚOF| A h@9%Yty@${VxujIt$z%Y*#D+ӕSl)hYТx]ܞv9kzܔ i/N"n4L4zHdA9OQxJN2$.ИZmvt1}cQg\ Vg 5r7cv\Io+q-saQ6]ցaAMͬލjD)[P:e~'Yjk.ёX-`,] *.Yrf𸲈)Yvcn⮬kȕA젥 l!:Trwo٘`w0emUsc!e\ UԬԤQbRS6?cap^AE6.>xٴ61\@XEc?1G`P~A*{W`@4*$OG3*ZINDFiU )=m9҃iA TC¯w.<]U43-IbR(J*/`˝%""/#Ӆ E5VOU]R',Bgr^"T)Ltq-!1!\4e Ʀ̷m)fVNzsup҄j0lN3yrTTOkQ^#\ n$@xu((rSZ;îs$TaQƸ$J_گ^.y'CP-3_FĴcPoR&d^ 0M"ufAD Ǻ(ھMS[WW3bG?PX~^+Ifn7S0킃oV,y̡/qB^jj +æR^Kc3)d؋[qѩ_sWp=[X}˚wT&mzV9)Xqy% 9 Ay70(lwōiG"NH&%- h<W.ْF̫`WO O1SMvjгqssj)DrT i? kXIQ٘ +|7W\伝Wd_01Ij]A/?i !,gSQ\˙ m$f ׂХ~GEpRd)W(+%-uh ’ˡqd&h[)mn u*]os]W%DT\ #^@;;] ۣb*¡hǦT4柸~s jfwCBPHZ*Lʃw" R[MhO ԱJR%) AJ`TAD.Zyl\= AB wj@:V 1ʏ pba_AY+*$T=->-ʢAVDlsLo%HK:bWkPf*H&D!IR088KSLR Xq7JP ]UzCIPIwK O%=KޥNPbt%P _ӪjϮIáUD/O[3zE/`lI:s SJ؀j9bUWf`lsEEٮjVv L9$QμF^5%`h($s0Lcf7blBrD?pA.:UW?oA$QQ5(CWvhK+Qp3ErsJJ1F31Go|.r_!3V]C6|~]VF)a:^"RjʩY 00|ї͆0gࣨ dҌcH6t8}l! cd9 ryy\@&7u)FĆJ(m_\Z6,ϵwҺL5f嚤|/ƉsnhqTy"2eaK(eiOͰg!YD^_@sg KKf; xa9iZJ}QR\,YՄsOm5pI[V/F}o쐦3BE,=.+1;V8afva-VQMՠFOI}ĺ\FG:#湮{?/WS9)9TT> Ebm(.Ia_Je PX^0aA+󱣫 T\"as %*#bv'n>+v-A20,^5NG|tt-#QDKi(v=ZCJ ]nԸ<ăO L% *kWT_ D_eN\\\F?v& wp#($v~fwRYƳhV+t4O/CHpSHB7[qB'):<(9dDi#|@KWFv[ⵟڶݑu3L3IGpү5H(~#bFZڒ=R9^$GW5d VQ-@$ɍ͕%4Ex?X7+Ieް~;H!|+hLJ4H#,`X9JS%=yiLsMGxLŜXO~9v,XK] hdo0yϼ(W#_IB6.4kkjibz6u޲3hԭprF{霔CkG>NSD 8+$\FTΩi`4ty$>߰TXux,̫S9'-I).>%r+raTU/+i w_0G"Hml8F/sSwb3%rAs?*-냍`|.)3; pqFɔ8K8({5VTK&Tڵ1ޣ}Fb1b>>t!+5h-գ .3Pcon$%-X9*2a!W"#}Q4!\;W\Ttr15QW{޸^6{Tl2xtXvp'?eC7Y]Dƹ0X&*'Z$5;D1j?J!q1 >]҇CudDp&n7Ca8k]jHVT0!Jx^EmR6…(wdlPٺn[G[vp! 5[RP#C|vwCbKwvuͽO)WElR4vP7~Ww]IE σ,z|nR y2''?_D}ZNU$̸)I pTN/` _Y'YoxIi((/ko8%Rw` z)U1xLG!Ie`U{ѯu4 ߼h^ ܆e08K^Y7q]GPC܀h;2$_ 'c4X3S]".[SVܰ9S=I.?Z h_JSkr̒ۋ)g?]i87BpR L !9m,@ #ȃ-m`g؇8,ʂ*_H I }>Dϋ&kF}$DZk 8R ~Ո! Qҙӊ-@BYKNu--(W8WIX! 4CM\AV?H¢9n?qqe;xl82H DZ0v1T?18ҭR@RzRSj$|~6m(/'4I#MS7YK899Eŭ#}'+Pvq xkMS)q}M@.̅$f< -5,L%^Lt4xi\Jr}\\|s,"LTbj-n.%]+-KRbyr e5@d$y{ǫLu+^'Jy=|sE4 - o-ݶ_#B.9?7$ݧ{ha$^|,WTA"e=kZry-l KlBcv0$)[@ ;Y9~wKnbX2ScdBH>!EIЈgkn~FKA[tg#~{ hlOQ^ " XR}Mߡ{_ov7Xe*'x܇8j9jU$ot鲘b?׾춧eo Ţ+EnE"=81pm\4ijv9$uYU~ i$N bHMa{l$1 ["bڛ[] {3' 9b &=lIq2˲ZuJrcsБf5#S{Zhӽ\;/@Vl~K5j8o$Ou#:H%O(piMr_ \B ?MFIwgͧ9>Q2 ;ڬG0݂)K l*}? G(62c9zDD {$>h5e+;fh]3k7/c5)eng)'InM!O3eYlzUҥ(zLɿO*iI{?f!=7$S{8oښ0/ݽZtȃd荘9!=&]Ɓ[ 1E#ױvΜuP״t:+Ef10,}1^H# a|16c-@Z*y4Mp|Zz D6M/P1=ՁV<5r?eA~oJhS%5!zR)W-1fhI99r5 gM{ҷK8PIơi8˟QsQ؈"Nf"0 Orz#iB +7,>rNKW,?t/.[hFp/CD 0tƷ86yP Wr#Mm=,!Cغ_2;Z|9c"sr# 9b9|X2[.&ѡ'zoGY7qj0.o~>RDG'.(n(D^}H;X{C@o5ϬܥIԒȓlEe& ;llYKC}i,5 3nbrP.~RWAsaNxdU4,Ec%3%N_vgUe6Ǹn@ʉl/Qr5,$7(CΔɁc:BzeOLr/1O#ͷLШksK(pHD;Bj >kAcy- ՛_mۛ}*Zק.8BD݋E8wM 3Z"( %*nRz6zP` &9U, e4澇K9ʯ*zV1b Es@/P'ء\{Te M0~aƕQ/K H23u? R5I #9e BΘi mGL&i77g:^rj黪$v# 4|TFx$ dq.-KjK 6pSz󃑋v9:1􁒫wX1y[+W3nX(H7_E{KQ6:`U=zKȣ4MnsUԥMu*o6h#Eĩa(QR~;8PBxΓrݯkO պ:d.#=0p"c6+"68+Ʃ^VZ+( 8*+ [7>![Bğ+^8vP<ox.) WZ~qa"Q _w~3r+/$s-'H"kZCrU:~hjGr}Mػ 8l^O/P:oJwaV4pnr7]Eo$Pa <襣Lx- $i jE?}q m_Տfw3^v?iQml!: 11d8 {-d]TUA}pZ nr!j$YA|\Lvek)b,tQB"ؑfwrq@DCrLh $IϚǢN#`<8Ic.zv4g R ;>)^^:jQx4d;G.O[İww* P1 ֈ\2|z'c lew7 # "*!G{(?HHRi5#@2A'9__hۻi!N $W玫z^6I᧧VbcE]o`(W=8ةL+m}_5m@Qs1Wa*LV٣>9- "CIT39!({&%UZ_Sq+ +WsaݯGEEnɢΌ^ܾqh/ތ$k?A&H;wYb}Я_ȟFflɩIU1|`8+zR f-v^9{Rj$%PSh>[iq٦m̢[-i0_·T՞6dS47_ryFMT!dpLɬyK啛Y_"5Z焟`#~CZھ5J~rWe\S!o1 9aI'j,WuRA]>7zΠxRgك s9v@`v:tth(QvTɷvnٞ4*hdٛ:s0A`ҤohD0 }, wgRCUljq0ھ p1UId&l*zJZ1%buJZD20!ك'3C15">Sէ!LgHQ -Rs5MVt vhq̫2\kw[-5X J}ڪqޫGa}ҔKD{N\$PO3K(пxnXޅo蓨kj'\xF٪!]ZC1a҇~Q!EF9~jxdBaʞy;~c/™Jwz=87DM % KR/7]S),@ C2L`05v1_ѩnUDfy @]PvV0N?Q^ w=))orv$اI.YY*ԇ_12w3ZB+}#a kLrW;<O'YFK] h籜"8XM^.hDuezTqbȃx/Eu[qs,?Try׼֒#6,}"qq $es31Ԅ6xȫ%Q_8ڝX'ȶg&!@KjGA&uɏH*tQB=u&Q8p@I_y-{ٓu˹]HC2?üѡZ hr?We41 kwl] )2  XDN_5T .f=PV ɤf"y#f9{EopJfP[IKv9iAb)n ף1Yad b$,XSI ?M&8[M1š'//hh #:n4-76Y,lSBϯ ]/ˮf{SJEG?  R`tBZ6H'F+zc A̮c̅%0A.[z`ϯxJןG!=+d?uХ[m}+<쐀@Y<1(b>42a#^Eq hy'#P_j?'ғz=0O9BZkS`)N,\*Ew*1􏃍fauop@gS\B*Lj.00|!5ȓhJ7NᗽQ_ VrJ3$5ԯQն%Sz-H^E|ha;R=C"zb#'3fzd/J:6:pĄFcDl4hACWCL"GnP\H L@ 7}Qq?^%e=-Qv's~C)~9E/"GM\VI>`M6jkV0+^?Um1!U\rr o-ɰjl҅npWj#Ҕx JO $8.=]e=$qKllnBAعn 4V:|s'Jd3?4 їN9qtЏ"豠0T'b.jHd5K%*KzGMcљ~Ѣx?^a L<sJ?ky ֱ0tj 钿ܳPLjr%5 c7F]ك\:4Ǘ#5 :(g ӄd裏vWoE7 uP6N.LcIl NS;΀\x3x^=`pZdVuD;^p+{Y ^N.xy'V>Uwk>˯˘)SiUCApe mLc L'']oYOh:qp =>Cx~-(Ζg~Z0vkT[$1)E=LS,v Y})ٙdXFKU,G/e)9]"X%7&dl4P*EK/y+7`ɟ}2 8q@ÂI3}9?AOnֻ6iQ'⭟ᆞEs Lqŋs$hvȪ?y4jy[I ZGjsZ,oimWьb-Ei~|iJѐ Co9vjI]Cޱf% Y7O{Z}Zm} SzM;KC?5a䥄ȡDScƕ "&1mNQ>!鋐k5'eק{r֠\ t%~-/StQQi6h?xi*p羁/]4yVN˜eStp<[ Kh"}Y"XL{-tǣP W,ujKƊcn}[xJq@#so CSZ` >_]VdYA'?TIPg}Z٪B/ʮ,ZrlIg5Ƴh4ƊJ4 9xqQR;2ZA g_ lol\Tl6Ӂt"B.-Rk=eA s0gW|ۓ¨o%S};il[+d'Tk|'(f~WsqI;K~{Zyg K#~eR {zD9fXɔ 4n U& 9"b"3,d;i|&?p 79d_JO ʤICĎO6$MzݱGh& n75cJY͋Am4]])lhHRP^AM´FW}(ku>qdL+3 MDUoa8Xk[jdl[}#U0鱍d]Y4z ?zmȠ:}< 6: d&zsD ,?39?0r GzR{-B76]/[<eA=a-#δpxpZ0l][`HP9e B>-v5C'+7Dɽ}ijR{*ɀ(įAj/ts*~V"ל20fᔢ깎ⲡ$P{=D9.o`)! Ng B#tj|1K]H*ƌc2shs6r>U.WlVїvY1;koۖ!=΄!Q>Lsmѧ%*v&8^ax "Ռeƍ "9qzú%=k8eL=%|h.&T<7I}f y;y0{f={Ic6 {j"ݴ*iF=-vE3BL." qI* r-URw&"鴞{sCC]IK 흰/"Q9Պ5n=^K hȋ*@ }5luxq\Nl.aT.L&䬽63y.EGkz%!'K+7 YZ8-2,ُ&\ o}h*# 0^lIE.4e:skaƜd>.pEhx$Ófm(~q \bҰn 'g).E{z/V4ǀEI0Kw)ilD}T_vz]PW`>P UiS%aQ%Ii_}TJjWkZR|Iގ߄]Q8ȸc{Dk㱊Zp wFčY{$ ..D\V] l W#uF,hW &]6r+LL@= S\stb ! @ƒ_R%AvKŶpF o'"|Bp楫ŵ'?^,\Pix:R%^.-Hdq/Ty?HGdhj9c^ |3 eIY)p' ߹tz]ZyO\ݦ+ TcJ~Nvn|cq8='*tT(XL4 3J-tU N;R@ x eL0[IoJ옦2mqO{d em(4IP\_UGw a2g0Cna=E$]H.܊|+C$3??e9 ;;)A^_4^ ^>Uv%s3vokt^jCs ]=᫸}pM ]%+RZt#k'q^I8Z[q&} rJ˱;dw//CVU#PrA/..JK, _g֧ٔxǔb'_c^pNnFVC&o]1`)RzP8pƾ]K2yo柩~WR-*ѧ_QGC腐יI"%~q{T@ݚ[j뛬+IE44mX-g)87K k-ȡ˩ }#aѢgE,hfH`CeoNdԱk! iO'm0A Ho"}a:F0'HCBn%b#ŏW Kڌí/3Sˑ6]gd~D(?Gz8^<#? YSCEW|y*ѵ.^:y*\hqG<\wrH0HPas[ñ{cܷ{[+M.g~XAH}Js葕)HK=ł[ 㓍Xԯ(&2˝CLwlSnbBy[ٜNqXxYrBcI=r4"ݶM?<׬45;}UrԉH)I;Q&3F@^5zLΝmUeh 7~E٩O1=P"vRIF"c(SK6?ůztAM̤&R^9{R+ gN9Q‘HG"Ԃ* E0X'n{9Qيa 1^sT]l]X@ 4IVmLta8)M@j׸߬u X",m~TR K0o,B}x.08O 5c[?v*8_™AVz\'1۹ކ~GG,A6?DTD (ZHɔ}^0f`k\-=C UU^͂F)9[zp #x]sH`ݕEf_M"' H]}uSxŞ oJN ,LhuRm2qU- K5 V6`M~Y =$1Hl+k=x'HGozeZo8*1g04#<|&Zlr֡o#) ?Hl@uwɐHDz!ߣc @rolB<h '*US^8h15pmmCXW )7E C{D[yu?~L _{x~'9 &,W)|gXp~(a`Sexbv7PN7]BGG(h>DQFrf5\[ߓKST>}3!)E:^&* X~iYC(h&4ey8:nTh#M\x{ޓohSyQoWcj|92a>5$Xu%S~mKwng*Th Aއ;h^:$ ܲ,7SNdjy j3dHHA"Ƿ 2,.!ABl wM&Swˮ导'at%3shv0lo͡=:t,.^x{5/Ҙo,!*\RV`rB RvQ@?MȋsPZLhNmx S [A0@u*<_ *eVa_o9I^T+reXj#MH~6"My }+ hm!_ZD!N"TU\BlQ#UQ=vYI]HiS4.*9ԏ/9zqlCw- c(}&yk}(2@@ӵQ a/m10 OIc &!4jBiQ^n<}ό.CPE&9W[]-?8E6ßzTo% nqc6GyQ 5o- 7] ?}i& yq%yӳ8%>ƝBRe'4WIDzu1/Dh'KRfx[Mp6 Z 8C9OYӵ3<[$Zy#RaG "\ Կ=n5]4=4k2 H#d8[@Y3#a NYլ2/c[St n"@}e;C?;e-#&=||꤁e䗎eVqbZj\r}]Hʅ@dnM8DVf {1)m뇐n`f4}^#5#7!>b5`c*?# [L>J4J̼:&l<סCqlb,^=-t'p=R>v 96n:(ֵ^Pjvz7/MuagkuUORH$"` 7.HU#/x*;ӢjSTn%TC+P#<JR#p]d6E {^o'r:ʗ0po6hH75p!u7F$urߙҬ@jZϧù_. V-)ohf r4yϼGNC9:Ss  ?\cdIѶҡUVd2Ǩ gH#7N@=<ةvHN@1ݙ<.u™|FIpҊC(a*)a:JZb@!pѷ@H%|SscaqEƹ㈺Jx#rJFنGs.-?d!iαQ$~Kx6lUF._UuW K &`uj[0!i1H[)q>G~8 j]a{_eBXs.x/ .2ӻP5t [?Gsȣ.Kh9NY{g:_np\6Kz݅RN"*&Q<|{=oF!̔59Dؚ~ccM?۽ɩj:GFƇ|[UD6uz8%8S|/Я1,4"0Qr[#Es7ş|G⵾\pۇRvMQmKrK 5@i`{B?Ӷ nO#룋 UUoZP&ZLo2iK_J="%kg-.$w۟u 5щdxSɐ| Eyĩx5=gH~4` lusj z>=n]0S]-4^vmՠZ>X~#~f9u nkϙƫ24#+-upU5'wQ#՛#MgݎWEc+:($n?4.z0ÜB@#١>Gu_y'|CB.՛[!~aEA(7.6}.GI(zT%o_%@_Zӝqf3ԋl`cάPr Yl6ۣC9' h4 *vA{dG P=*!Gǖs8c~fF\nAсY^ԩ%1IFACh A!T_оL :%MO@`a]\qHJHq/!8Zޘ.\6?)d^?E9}9A$ k*!տ8BL 6ݜ s9G9H~"O/p%{,*fDm/cPspZu䏭D؀{,ueo5YmU:èP}걤>} dR$pI NNg5(c <lDMϹw+mnMTxCvތָe*Xy11*ya|aWJég~TbQ?=7i]4 LNGd̴=z]CP.ʻ̥j0oWk\BKNDQ%>LLAg!Q"W٘;Ay 6;ŷ5%X̀D0/(d}7Y-[wCeN3ԅ_g2׊O#7J~|$fRH/tyhC4>i@ G A`Fh$Hrg,`1|ŭ3瞺:}2!w-^2͜P w?FS&[w}Ɔ׏TiS29PQ#R:b(HNFgkZp*>Mu 3̟kY0ElNԙ#LDuM/\ {Xn#~S^^ 2[qKy.uL`Q[Lܕ ͊RSI%f3빪[Y\~g S( ZP6"x'8{"o7}t"NQU=>>Ov4;`S92KqXx,avB/C"[Gr1OzC=ܰiy\ 5gzG蠟Gkda8;[mTe3) Xu4_uLR`-l_‘@Y@,d a}taIBȧz.6x:l`0)ۯ]l!AiXt_@q2h,nB' ]85X^(5>/  eW0/oZr닉̿Ɣ =<= *dP&qDA1Yt*EꞚ3JP2mR=&#$ l_4_NNY-U_5;#yϐ/ry' )LsZE0 ԇf84OjidOYkDvNA.p5} X?K<в!1xЇa=p.AND"]P^X"="%]w#F1i/&~JZ?~_sG3;Blt@A3H ;3ܨP-X mŋZ9LiX*$r Xax[mp} n`RԲYt/8##<BeLҨ:a';_VHk ^i~Lw%)JlkBJ[y=s?ߨb`ȃ>*=OF -vDM6 ?!Q3 Œx}Z&BtMјp"fEB3(bK6h2uԊ@Zh:?9DY}d±0Wua1br9T*0ZpӢ3g LnJV+GxRx*?5qsҗ<4:?9r '.[פm}@E)zUm5,Ъi[鲩Z>Էx(c}5䝆K  =)xN>6|2Sג$f+?E-l(H YT ({ 9K%X3׃daAl^#]n3| 9ꊔvZ iNP,,lz7Y?;QYѹ!okyNI *\LAGow,l -=殚Qp]Ds9~M3$!_evHwu?^\g_yX(GRA2SJ^$ƶ)&u1'轵3b|XIe7\XzTOWq-p,BiUfg:-"2 <7ֶO砓co!8+Rw!c-n'ByggRv0bg}J /ul 6؇910 =Wp6^2R]huǴT@tP(TL;c^X&uZ/cJ[sM&zɴҥ R@_oBa1ɣUn@P43:X%fP5: hܰ~=nCh熠s5:QZFZۦɸ|j6aXl0# Xp֡h |C5/R?CxZc{a+#%':}@erOϙF9};yyg}{"aR) ^P+ZrA}C!> @JS+NXT*f"zx3߹HK)Y++簒=XrO[ڳIKu`Onc$i-/1nB:}bg(ɵFŐ?F_37'J7piZҝj4';8Vfij;J Z1&cZY5O_ :<Xk-ads h'~,ؔ jIR9Eg1%*.&=զu0V y+v.p-`+IHJb?1L%^wElסzʤTy]]2&㘟uL񚞈vIQMH2[Q )3p|wm͇N&a~HνZb $!ͳaS'}7'Z$H¢S4gݜhPJkzGcӚ%:/ݎVG¬;ED l®Hc~F+"}V&LK"sﷴ巙;Ո]i.;/& v(B8e1!6L8M|ASEՑ=m:U1- ʜZ5K㚥Ϲu D+ow*bakB[.Ncif3ߐZ0@Ex4 </EC\O} qI[}I~w8bQFјo)(8]8_ J S0qgql`oK(aj6|I,wTJA2R"dgLu6/|gy} agiGJ2iW(8   [@gyH>K58R0.ǡRsz_bc$>ŀs6 FK .,ni!腟he3A&?qsaFp>ݢ0\X| R7S]cZSޙcd{)َ sR/ &dɈ66[#YLb9K4uXU}|f9R|sTɯ!+QB䚥xϑI)"j2݂"EYl7VqUy#i~aI1HVL cq N2|8V47Uÿ"㽿ӆ"eHiaZ*xV*R7Z#sN~D_`is{Z{q xM%;Q,o94qǖMtN@w- |Y CUW6ˆa4"ҷrrbY iSUN첺ݛNܹEw;In_K8@U0*3'}1qߍ/f>e E!Ɂڞ{GJ(a͑ڞ3b ~pW)ްX ݞyO坮lP}RNuhH{lu%d _NjGeY;X _g`PEmQWn?JIj^:("qu`ϊ T-:"&y)KTxqL\=O @PBGjeb{uK5Nqd%K`[_ 7Xv 1NǏ+VbԢLXw7qDԜ~q= 5>z[q5dĹ~ tM j-TqIR!tlu zj#[PCeB fאؿ4^M`n5">\u- &vrvtzdvRcخ7zf7t݃~}5qj b)Gzc;>+Xeo{OX0P| wwF\ t n%_nv ភ}9W.7.ZX?xF _~O(r%n^^2*4;Y2^יQvn)ZAC.1w-SL[*,hZ!pl)mqdL8z ,_Ehq?m^;_(Eퟬa~HY/CP$gڂMM A6Od4֥]J8H4Fs~}i=MWU `:`Յk 4ߺ_<*#*>.M˔,o-u/ê ݤ8hf8<qR_DO8;~8\oGsR$%|3Bz3AA|I0 /tm㻯ɾ$aWa^R_$ fx2}.H"}$o1"] ;kВRuSq NEé-BNb 7 RzjPڬ" 7W,(PBd%4—Ih~>&n}%_AgJ?Es,vdqYeU`}‚>EnINٲULej.֡K#QU5>"*4wXWp bPxt-Z,g}4RB:`h!W/anz@gSVφr$cltjlHRM Ν&⃯"k5zs#}Kӈ8)6Ԏ''5(yԍY[,֎:!ew.vf%ze_3h$q)e A<~Ṷ;C:7?8ȱaPIy~/$&,>}l):~W*.kU#F"e*70㙡UYDsQOVOޟ?8%F\!Lm +HblJ QaYu4lB(}SCWKp0S%%`KB_0|kg qC>.?Pq}f>W Ddm {V<6l=]2VM"[ $; 3Q@ ʲ[;\[IxWʋIGLC;M2-dyvWHDj6Ox>X64`hnU> >ʣ,l 8,_6nԫhmC2q?SMfм+[ݢRƞ~Bn ]!5s"H=WVL`x['fI3qb!<#Sv0}1-k8pœhcxBԧY Y*eW9>iHDg#Wi}+2zL)2t N&U#ZJDc4Řu1+2ܒ+>,`"כbcLpfGxWq鿉_5#/C[O4=3 , (LP<FNO,1Ydk3m_GAt.8P4RKIwiA\]Lf7) W72f8bu &ubjSqԭ#d?f ,r<г{7Z3:"ڣ= N K Ӗ;V@tY˸c+#iK JS<*yC"$d޼ OFz};PaU %Zb8gtGq^YH3?.%6niAzJhaRaVa'`:D\ [(; =[E|* Z}z%aV:f?˵l|vA"3odL*9zgb{,`2~,vH%vt7B'+,\b3xu v1'J9H7)cYüu+!́ɂ J vgp"N;26D$RR4fʊUȅ(!ĺmpL -u@iıJVԫJ{eSAe% =Gn z&f D$=A'˹fmP^RS)nNm[ Iz%d^|q*=?8sms;FhpXg"d6dQ3K4` D!#]=' yzB A:+rcWG4BeïI _4YQ"6E+\( [ ^m0Gym_7T-T׺aF MPNꞕ^T5i*ق!m<3P~*-q7BuFmkٜ&|EG,nD>!~k.!kZb HyjZ#-mD0< ]P{n:w`"v ⦚Q[ 3u;;t~j&>4nex}, g3c}ƙ>1<(MϤ@0wTxQ?w t"hJ]ƃ_|iKR >ovqҼ$kJ &%eɕhPo#$j]_q"NM75OWK@8{uĈn|\z+7yd|{_$Y`6+pBhLz4UE:}1٦aV8 GqP0{M|Q6z PCLmFI+ XYI%crAG';MK\C y%o<_JPpRtt|+\>Ϛ!jVciҷVKV 02pzEgoֽ:yΕSR 7a#8"m#FF+7%u uqֹt|-[şBYDzzJ8u,cW,/$<(XBJ9)RxMfA(n6*ɜ;m~=F=wBe a?.ցR{7XږoPk`A}`OSs |^Y\4 AR8߹KO@ԛX7%KhH, 1z>HWw ef3$!n`.2J7iR*!R!eLQ7?ּMHG\}#js尹n J/" |&#%vCZ8AutE$d by:V8Jk4 o{N{` l6ga?}x_c6VDd9ҵ}Y,< g.HK>ֶ( Tq1o! Ra,T&f~`= ji"S?RZ1섓"C5OHYQ;'tOJӲJ6E쵸5ݶ+pz(j e=IGc{u`f3|!\ ; ʿD)r2(-bAS{i. Z=b8߮]DکK!dm\ XZK)bCRgu-r@|q%H6Y hr;\z.PH'XѨ1*lXHxޡt܏eqx$-kvq#d ۝iPYV42JTX=Vu8`低2 /4H} wbp4s9dĤC/<>aRe4nrL`{rZ1?;CI:a#D҂?¶)p.璦u%7r^FV|ÞU6(:/ӯiz*ɡ$z9"*2WS/R;uW#09L*ں  ,qae{CKbxC@S¨Q3t񰇬 N_=⭲b9$TKF.Zlu..hKO+C*) ;~D--I:{C`rvH=Sg$N*0!>J@@/Vy5KBu#2lDc VO>5ַ@m$Ibbx|͞l֥gC^OVHK)nSn4_Ե#jadrХ@0S8e{30%=3iFk1(~Ӥt󻛸 åV0TA^@$[,BD;f^ewA-W'"Fx31}dp:O(Y~Oy\Jj0M :;\A6I@#9a"a]u Lh ݖ\s-#>'a:hQm|>'1USF0uI9`\U C$Vm(_k~#dśn&ɽ QPOi+So֦G݇Va>F,!ph`yxnCt|f0/]J/eIY8VV+VAGS!Q& sT:Ysٯw G}O# [5YJ;BH;Og`~sJ/x)oVSF-6|ܸ=S":B(֔mIPk[<~=uV"n eWo٭&3["%X|+k)' Z!Rӄֶkhɰ F?h,۫*&/2Ao=@7BULVR8M JKZ8J ȳi 3:i;hu4r|Q>FcH9Cϡ] 7- aQ)q$Ӧ), u𱾉J J]BG >&M=gvA3Gw*Y˙^~I;iBǓ)T"(/wFLf&QbNR{SsSmڝW.x"ǼiX Yu!>/YLO4ESa$ .~tXf&$~4E;AT?U7TOn^[ ?^BFG͞E~;>>UofjaHK7|c1a+)vuQk2٧Q{l5PZZ81ld[lP5_ϗ J"!8t5i ,D[L)R<3B:ho~9d~1jAVe@ =H$Eߗn ^h’ h&W^g̤x y B $!ZK8H]NLؑۓGlin k)'#/[6>X8[>˱ wa)M(*_%풲S`Bdbf̡fGh I;q>2 @հ-[4vvӪ0gA=#;`-`u!=(vQzZMhQG?P j}.\ϨpMv~$-Oscȹc6<|fR,7QO(Ԛ pVF@mv3a~tw zG|r!e΅ z h.bM w0lHF6LU=a#.PW=7رQMii+U/|]r/$'^bL_8$Q9-$ߓT.qeUqEݧZ:||gI2< ݨ+#Dd 87ϕmuTPt=˟VTQ~Yz397zV ?Oׂ._tфX7t?ͩi$< Z$4Hp*)@ e y芏8k )5$d?6&*>K$"C$hh[ZAC.IKә݋V$Mpz6_i22Nƺ XEJiӔ1я)@s/b9s5~f){1%Pe:S&;'a,e+ +`Z+m =Y8™r{ThQM[,Vor@+ЬorM /P1Om E9kG~r{eHyg*/{A9a~쫭[Ty*0>b-#n!QF f(h.9yEIE9I6p!D^4YT^x}|s' cphٮ PWAsUkG_djJ3H _ٽԂkJHBg UrK] mEԧ;KwvcGP]x+.{"ZOeS}o-F5ȀSGGY'|TfiX9饂eM@8{p0)3qfꬳuF GyM5 ۑCy?jg;L"Qj!=ؠ9J8gjASM0?^!LGHmLlZ!!7TszŅ|?D^@d hGh p״ b_#LUuWo \hǠ-;J GA!ť)p>}ys~8wH}.)iRo͘Y'k9@rV樢68zwm̈3+ vYXxoPJ>*-;G*lZ@o]_KE5$\i6F 0o \ 8ғLJ yX hW9md}'c~] ЬQK/ť獘0J;lDֱ8zj]m;s9Cv2h$;xP1 &?IQc:pӶ:+w I| .>c ;’rKO56{ = oq&Y@<[0w #p fU-dKUC0)Є_Sl:gVoݣ%{#`B.k(ZpF{R̄qVgViL4-mJKa Zaty}Ů#p`:Is&bJ޹Ji|3NR/l5Ёfqq9)S\]WԮg;m %6thO\d-$Mx59xtuͽS4u# &7`#jvV#d9|#LEc⤒*,KukUt" fe)5gD_=J$3)BARG6Gv烁^剺gj /*)؆qx aU f}J/Z7#}^[>pkmdAN] +LWJz3V6Q$$OO쓫+FdvrE ɴ j5[,'J|cs[/Q0)WzA@Y~NʗL(-N? ,ڢk"o$;;!1]"; !Z[" L:Z2dˢ(?D(al|ph6fػ dh3p8 l/7MHe:j-})C*{k s 1G s1 2"iV!S59D\OVGr .!=@ig_Ž'Bj*LFFyKzA36? 5eS[nr-Ghx*n) q" VڅhZm9Qbđ) W;Yx>4M3idXB?2+r{;UJTӯ$t$B2A.)v`uօxLB棋-T q j3$K%– <^89KW}tLN0iv 8u7c&-3XjA\/E{I[잌t{ܸ?⎉Br9ƶČ>R z/_Y޻=SW_݌PDmٶJԡU01vz-Vf1Y&C <{Lp]jj&lfihF0eMNsNp5ӉW c-}ZԱ̺},x~K`$I+iyM6Э_sI;0<ɟ h3 Hc,_CcQeyEPPGO\E*ڥi\B/UHL1zu4D1Ј|>(C4ᒐ*M%ynk{̓`~XJoeg wN3wܸBFUJ6 ?;Tn"Zt4 y>Q|5xl_|OQtwTta>r՘HS>v;xTB[N `k&* $ՅrQck D3M|y>yPE^V^I_.2E{/a\rӼg4亽eL>K5B *֠"8cXYmZdONC?4^8DZé*OMHÐ_J8*vJ/hU(> ~t`kK=VJh6k`,eW߉Dg}pJ9K]ib%Ӿ?_ƥˤUS,u%'50_pw~\'3F^>ĹoL|لORy$@I(g(/lt %(}$b o=DQtWjD+ڛ[`~.ɫS-y;L-vz\57hi$zjOM@2ZN,zytGqZ7H$d4Gh4w[NU0 V&#-EYa\ >m y$" fxVC?` ۯ iQ&̧w|q6O\?+O.z׋u!HYI &țLCZ?],(BvpV&Ǒ~! uv(]}0+H.ZNm&Fa::Zb_ ZĽdlH8|`nڂ~hV:Zn/PePn-h׶}wDSVwY58lwN{Zx☯laJ 37d?tc&\*xA9`k,'J2csYZE 598'Jzg06 9پO_+ z! \4\'JHv&Φ v44#6*>:ZTO3#Fqܯ)Gܺ3t[۩'Mvy1U'We9hث}XbKa") &B My%+67^Tlb4I&@dWF~D-IFqytNV5MIB0DK !gs31ӁES47Zb2CCN}[awb\+h%qv7W)

81:E$b+߻1q,ރA#)SzFddKSX07Ԝ],nO$uEģ 5kNތPO9z$'f}WpXA <ϰJ_4t"(p igДâkffavBJQ0$k >MT hH/~Jx_N,I㘿~6g0lQ.#P:U+`ВX-@{(8CyeRr-%{›_۾ ޳{J7RD0AI5 DL[iӓbRW#J.pmL|b3 Cd,;d^CzY)g gms /$1 rvPπH9?d.5={Qe9h=Z(YbZ%=}{>>+3papQ } ōH PMx-o ` .m5st#{UI^jW#S/=;``8)$li(~O_Ue份ܧ.M[W*&%7+>(6,'|@/',ǧ~UjѭoaXds r/ 4Ro@|ksj{d4#=\KHQM 3|i;|JCX4s1Oɽiq/\o[ )oWzWr+0uŝz h(g:@&\Kt_:-C˹.thq9 5?SD9`!ViXVp-2+WIڦ V5b;Py{c,aa=vp%Oːⱑ:XB1]t(8plQ v|ie#7nY\ pf1i!:^3Uf7sX)ĝT>rRg+I":`:~: Ze MIa ?2x4Q}ү!V?GZI`"~~Ȼ{*j~ npa*GٍTP8DSVX=1DO^ZY U@քǢ5[R(ޠI>܉_]'Sc eR焇kƕ P:P[O QU_|i_ҁB j>Γa̭Bt*Dz\z?Enlƥ1Y<ծrp@*˾I`S(6/+tЁS6$</nӽgx6\,ʬPd9nU|QFc4(; E{h쿞^ÞڔeYr_-nCל sM͏*jN{&Le wDil[W0 $8'?x-;Q@m y LFXjuDEx-U '& ͤ$P5\$ jA"ˣ Calhz1pG!^Ye5+L˗ժVv:D M_!ͳroBDrN%dNR*~as I/9DGs]~ Mʞpų#!3Mfo 6+Jgi!7Y  Ė&-Š^}> 䴨M|N4LB?Rsty`W6'WtbGK͵/)La1 #rZ9WM9˻PF\3T2'deQOJu@O / 38;a4c֡~-T3|Y۬vt4ejKJpA?1Lnb|n3Qnj҈{OH B|!8T+<-rL+rk?Bp4ЦΰW;RYWb'Њ[ zb7Zz"pҠܜs?'PWyj{ا.4{!5)Pwa+cnXhQ$}98@ե66B4&'pg 9lg#|[;tVB4c̗ŸKJΦV-r*t4ĜZ,:Rlo*<`"/g;{/FJ ʛlC@sg~R\xݾTiVw~3(GB!<֮AEH_>֖6u|lȷ ..侐CḾ0Do=r-IżC7HvhDW0M#!'|)\4`1ggXQ=FfG4 mxhvpԿx")gΈ]ֵ Fܭ#Ze;DIC(mA6}`DS(܄X.j\`y4rkQ_,YLd-}wEV}[^ˍJ|M[O2'ڟo!p8;i/|zW2a gvTfLcK܇?忻 2}eǟB+~io*k)dR@s=IM/~1V{ܒ1+p?u6/?k ٴ!}XBuYJф"LɢtD\AE9cR) }jٴ{ R a㖩y*0=э |=i7:s0 d{L.ezW\ehAc!ARwI.G<`D%9'f_ b?3_̧̇ms(~n7wҍ*3*HǁJD4ѐyTٌ($'݉}fTFԞqrh@b6@z,VUQD}\u{7 v*19]4&HaՓ) Z2,7 t>be*=DՍsHքn!q5i: !勉\By27$_IA mi9Wl|?[23lnƏ( Ʋh>./[7aFw6Nr;kA8pk,^b20RΔGk; z䍊" f1"6Uaa3Mi~W {[ ^%Go>1x?33[ /틴3M8ZJB2jIQbŪj6w#(|N5(/ 隂Q)1N̈́x-18J@dIHO= .!k<_n&>;kU;eM%ǣ)ޘPqvLQ-4;gd",_%XB@s~MC8b~dSQ=# Ex> iMTV5359 jCv]k}P@S}i3Wmh(& 4Eg]K/l7ByAg*^gsE+ygY3}i{w)Ɗudc"M]f"g>/S ?eq:+MCcӹ}b,[;?6Vꁯ6Qa0c~fxCS 5\v'P)L [^IϞU$MKlf_{QD"> ⓥm85ey`ľSϽj ?ANC3$kkvp֍b~E/tEE Egk#9Kԛ|L"1<ܣÆ/x&31Cy'A(j2wRCwrNFf#g3b9paIh/ŏiM=E%Xk9d2!S xVPN.`5R2TYTI?RZ2]5z5ľ3'P>{ 4ۿ9wrOu"O@& `V1FX _C3b9EM"([K]!op0419k&6Zd#$]|hn0+ȴK3L÷ vvgKKIX+TXT;t^y?˙m%*Zw"_ړq+9Q'Й`WE(r%Rd,NxB {L#=:'H,˿mMC]w!Py"VC~ay~D1YRn,A/wDu׬0j2hHF #GSP []s{Y;#뒹|BjND$ 'Q_ £FuMLb#Y2cf_je"HAELh) GbnZej# CaU&J'smyZ(Ҵ$Z嬋VqP* XNceq'.6C"N\vdo_%$fO;Hf㰪'nF舭{UnlE9 ̃FPq{R7B@RcؤNk| -@pURLO0?j1FT5`w(af Djd%^~=iE`$0$A.sR$`38碙#=a^Q~_|)@^NZSTNnz Tx6kl?Yl00M$-֨*;Xj%Lyrvzm^_ $2nPñ^ Si:LϿYzm%CmwQ|\9wܼq$=RvO*ۯ4- AEU3s'./. '[CȎR/Un_HG-B9c3V[E^I9 e\!ݶ,`a!ރgt/UQXe@FLS 9p#fI{QwEEO9[8/0 مy,$q(~nwϩ%q̋!%( B5@G7]\C <9:.C n !!@6m x@IF}%[ljxZ/{эI1~xy%^}&yuhmRwBuWl|:us=:xUjD) n$x~2"gfժ_nXeqE) 2l0N?r*ģ-~|M5U'CHүC %4 n_7'\ ՗#J]y9ie@[rQmzjASB=ϷpI[4t[KFYx{GZڕ_[0p(vΠ+,iu˹N2ӍfuУ+yHk/Y)YS561}|4Og;bΠ󬰞[ *@ѽDz_tSD{楰r|/]U `Fv5-i5oS\-4dnNŌ!nV<8tFQ"z9nՃI}BI|ن8\*d`FhtIT: 8ٓ[/wU8~㫧|M(]WJ/NQ,kT%"}/5&SEۺu_-BWR7 zIW+nկX.d#ޡZmk9\p_r?%8Y Nq )L(稳"g^Nf a`.ǖ[P;>U`"/0#n]fi6 䁧4 3%Kն^5 ɭNzBy6 )!xRRnfoMzReIr ?-i4/~60<,k[ dAʯXoEP%.0)R]ֱ?2nPYD([Oi&*O^qR= y%~|Y"O^L7>sE% K j)rl_Ds!O^':Z3& `}Wy0@,Epôe$ɥ/;<=d~kcGkM8yn̋ŀڜoV^Q]20_x_hMgDL$]4.EJ\(okip*(a`("spGj I*~Jhx^.%՜N;K'8#Rp]4ؠHa4"~uнyUbT l27w S3X b=V|w X0젚TmIQ9\pu -> \&|0CChg`ےsi(JZ㈾1ld<+t4mE+fiWvUjilK/Z<҄ ݨh.I[ v:ZUIsQV|)6VǪ3XK;0Mz49ln]:Tڵې6 B^} r^H]y@G\kgd|2Ľ1"ǿ@okPdq!+IF7Ca%lMgݺWur.wQqyFyW&8$(vQk6]ꆈiX>:Sz͋J {m`c|Sy<>^Wź])c I]5̔vf Uf^ֆJi^ H|ɎS_PO-}1X|ؔ<$ltt5_ ,zi5űڰ%aar]HoJ `fr)EPh_l*!H)ZװA D'53V)ɏ3pڑ6tA|L~UpuIm}8y#hܙ+Z_g 'o"J H 8 t F<:rܝfqG;L2u/zёYmBX%,Om zDw O"~ {ΰC bߺ\;3&ygkB7k_ ޤE.!PkIܔ"xpTfqTYL3'H[9[XN:js[lXOQH"fȻmaHSXFlbwENm喤,`M~쒨|PZj쯤"TL3Cf~,O (V:xY"Fc'%$r 0","_j콇=ew. UFOEҺ}M$wol;8˼7d 0X%W_S/>c&~Y-Uɟ=Y )$Z4 ' xm$l(ɽD-b[r@ƀs^CԝBa{ 'mŊEI77k/LǰLA 6Fy#/{3Y!ξ]ڀT[K( \oY,دj}ضd2 \ Օ endstream endobj 113 0 obj 109498 endobj 114 0 obj <> endobj 115 0 obj <> stream x]n8ཟBvQXO HYi@#WGt>R4uwϷ?oytnW/^}cZNy:Շo|v/yUjNi%]O| _sՖ㆔_cs^mzWmasM]ǧôڶcsS1疹EYY٘ w#rbNsmܳGn@?@?@?@?~_~_~_~_~_~_~_~_W~_W~_W~_W~_W~_W~_W~_W~_ᷚs~7~7~7~R~7~7~7~9w~w~w~w~w~w~w~tF8#Hg3ٶ l+ڲr Y,h6;сDt8. Pi|Fv +KdDTguNm-^F ̸>-AāNą,ua`ʼnALt&8eM<#art˄F{ǁN tޮLvqpvvΙK2=n=azf1OOg$@;<) bwW<}ynS~y.XG) 3,ud@ژ4͛rPvc1Kzp endstream endobj 116 0 obj <> endobj 117 0 obj <> stream xsxO5v:mkbulLl[kbLl۶3m'g~9{9W_WUk^7*1P΅`ikbo`# 49((M\mv.6@S Й`7fbX4NΖv/ f7E Xyxٸ9{/@ kc wp4p@ICGG/`@o@{ Xm<,F@84l KKjQg[5 /V8 $HGu {'s?KYXY..LL(jOٌBTjItUƒ96k;{7;-bfigGfng !a@3+3X0?,Fv>^3#g ?>caZvpb s,:̌0_/xk-?+DD^ ,6v<g[@,FQJۙ^_~o3L]f濦`_o?%ӿ<U(jcR #cdki-TR?0ImL_;T?=_u;SPYXXĀv^9@ٍL'lW8=7[#4s F3)|SjhbA} 2^{`O_߄}[e,, q A(́L8N._Țԡ2卆Gf6g4[d}s%:¥ck`(@C,@dCQ&7}#h[o||*vuv BAᄇrk~/R*N> r]X&AyU&Fb/-ވD=XX `з{mu۪Yp3q +ȟ@" ~[.8h jNxy7;c3~K9j7|"]v35w#SeqɘuůX b9f6=mE+HeРHl"b߅@\fey\:eRAy[</]d;Cwnj$J/]YbmgNy!aF4`rb9\"Ũrz*wpK`>/7ϜiJ:~|D4۫ΰf٤ȅAlW?HveHʖ#Yp 1ݩ'HWx'M4Îxe;"B/29,՜f/Q\Ss >m WNhy>QP'So35~&^U(xkzEO^F9 ?C,W՘@Bf=+.izcs'};6p${eRA fvz $3yWWPL&CȒOzGs7@3ƚeBcrJ;>+$Ez A {˔Y{GN0W7Iaʱn9"| T:{xnfTQ}/IwKGK;[@"OŅ#*d7-C aF;DΑ}02ux?-k}̡y^Wm@zs_ U?2Jxu=57TU())3:ђ3I$RWaA7Že $^G qe7 ̘n-*w?D$ 4xJTZw-|.4W2Uр=F%XƤ"q]K9,W7lS=r5׫8u{~ |F92un<[#%b#,H& '%ߚiǘd!͔=uYj)"~VE|uga[pz<-|2ęEڔᏴ(8L%Q zl1 ,6ho2RTŖ{6:,uÅQCꑨ*\2]WJ̃N>?0 Fp}G4 pZy=CLP˜lB՟-/tagfUY,3%fm*^1jeM"/Zʤ #ڽt5S9A5ʗ*Kb] ZqέuېJTK]ڲ z߸[of<%ܮu7pŎA_wmRR= S|WǣvKYn[; =byQ$1f"2`avCv GO&7 AQ99KպXx8oZ~3{f25|BRD#]23[)e[f\[?ms˧;?Rr~Ep@P\-G(?~nה50-B8jZYXl~WhuȾo yX~BbȚeN?О9Y]` pq{@ѧ&玔0h&]A .LPl8hfPvsipJHy /̙uRK7[ٛvVxc=ݙ[#G@`UV0 ٱ* \2n 3 (>Vuث>>єrd ;6}A~ ͵tVк~ɐ thGK_Eɏ7wq 0 @Փk{4>nLӚ%ca $߭HH1$Jb8E L&"'$?}ͽ姌ə@\x|ͼJv{g. 3xFN%Ht= Ԕ_'|ϖVI?o hVh9ӊ⭔Ŀr 4;YRIל*þOiib]J+l\wلJx:eQ˞9$m4TИ "StNڋ1U!{i[t (AM<7PL2$mfeʮKAnݕBtՉLQ Sܢ^|.(٧Q K֥^Hv|2Is|׾e~}_6(rmɕ7n'1Tr}^{děDaA8OO f3/JBrܘŤGFV1нpV4QrPʀYI#!]*1!LF5an߇Ӌ@=$@unCmظ-_];GTlb0H&[>wWv2x9EivjI5`#.Wv`?7&b)%_p J&ys8HG}8ᅨ)/'err{M2,lGd %M?2ؐ-uĢ~SAafQ5fTس́#SYиF*:&\XZ$OWL/d]<=SHyy4S5p{ 9pcX~z9y5OE"equ8P}M*L @p'1Ob7%BwѐƝpsc[A%$xJhA~{\/l_+, T-]3Coč׎rH$::~?*?R|{y|$)(ʺpwcs L(ڷA!ʻjS&t'+Fwq%z#x==qap4qW%{ =:5/J!{'\vZ/~P'>Wlr ?PZ^cg90'f:'рA{ٽsR@#3J`1e ()cr vHXV#',3ŴSx|ԵH9%Ҝ᝶W: ;u3NdUgG@,QFOR=>r:g| -FC!dKBRWDÖv).gWXfU\I>.bBf,|oW>B| X}+F )6#0޹+Agͼ&Ƶs+)g]٬ؑ02Zf Q¤1 1 3sѼ6,X!l'-%$j<^Ps(dt *#Eh p`w5iQ[{/ ,YXT=_g"7bzO?|#Q撍#j)8|*2;/_CtJ!pkL4aY1=Wv]RMjZfg(K{'vvHF4ąwPF voIa^e~͙m;{L:֞ TdaD` s>ϙܨR"=08d8Ӭ* }Y$~6J٭rrԶ=RrNRJѶgE J&VϵJsHq-ǍY4vc 8ʀ,T|PJ1;m8F @n'd tN2NPҵZZzʱ e6JJsRSRäGTna>V%N X"*{ $9Fn%sQ y]uiqϭ˨TLHH-1W8H};฻jk^ڥ6ҥs׀O[_=,џ8n೶Hߵ48֐9FNIX1 HKn`v^^{W鶺nRTfGT"ꗸEl'BTRnNEXؑ&{.eꨒ ryDɍLŰm[`C*,X3CkVA遁c R/p H]iDdR)|"_>Ħm+uU&EkXݠ<"Nb:0N+:}P(| , rmpD5dv+]/p7 H-b;-_g. qr\ˈtMMG}4ӵyja֝Rimm;˜}ɱ[Q7^*x$hdu^>|+g|R?q9~*3jϤ~TǾFI0;@XlN6L1[AdqSW!X{jmzx|~j*^Gx~ɰ`XR'QKV v5{~|G# cxokK5Q+axk 09(|8r’%{$2֙xT6{'>w㲣:N-$jTuz:hw.8^ad _ .G3A-%n,m$kCa?y0Z7F9~Ÿ55%"<_ HGif(4i;kR D2;}sŞ}ŭvlFxu)/<:P.ԊD 'i[g'aO=jOIؑe_"oI!#;1LQɚ<OE $rv 興 lLw?n iM^&` d x(.mpv$r "Ǎ7w~'n%C'uGQK9mǏ#I mIB1(j EKa' 9vl)#]F*E2!Ä(|f|=a;0V]D%>b E'?P"\WÚ$B`[/z5} eW#4:ocڛdAD?;]|wX~)2k.">ZM8Ws ޙCxFo>n/q1E2%?֠&BZi X"9%xdEP!Bt*R ZHW ̩ܿ/;7zXr_@[ưc2 EԎRLj9{v@7wf_X `f}4HuB5 *!@T|]!0_Ó"1#c*?xV6 Vs =l'("vTsH>Q(~++WAzoŌΗW`@#(1L\»X>}@'j2$Bt{FAd{8|!LNRxȌI)[lE)y,L :nʏSJ9v/V>AlďT^+] xt'D?F#ṉC֯1oAa\1||x^:ϻjdU$'?M >p!So=* +m`JTt(An FfD_LG)-@K"zUkv4,0 ⃍ @`RNVbS1ķ |3UoG}uvƞ4ޜXA9utO PHjoEr#v.HTzlR /]vΕi/HuOjaSWlŶFigc$*x]͘f=rFoTEt3 1V4 %Im&"fӢn?O/ZH=Xf[Gd7n*M*s׶E6;|[p$[d}FIQ3kZh99Ly­CzV WcrqH-I2mk4Zhë GY4aj*?u'}2֭M_o7ѬGQA<9cI8MF JP_1Vs-EC",\rT%"A"6ṼɲS:}՚3)Rڙb~LVu8ynJǹva|QOĈRyCGxҟ lf_ve!bI_ pvٮF7횂m[lR+Y"~p'Ș,([U̇+s%#9 F& 4\hAykeUohVZ'/\|E1 P()z,V* UAk.W%H0:'1P3Gɰ@ fh? \A-Ļë5YEKA֟צ,ϦD{J=`/KdÒSɧpٿtԹajIHy- _zUŶ2:3%μL7lIo/i6Kġ8hݡ U{c1%makb]Y'k,Wt>::dK@(H;)/6Mz٥Yz?Y:Q+xc7BēWƘdoI# ki?n X#h(0rqЪ̞MU(c,?v{`q*0L$جN 2BNR `|Wkf, iutttyXHp0vK8E4LJr2+ j@'p R U%㲸adeO֝c]iϮP|N+~C'NՊHLպ!ɞ+DIgx6r ,Wm/8>,]Ro]]o^b֞tI}Y:RW.Ú>cn=b´{7Zs{1_!ˤ[ zߡb%I\:?{v0yWgi|g/y Ҋ}kauo?]8DȽʑb.Zn+%\hwI+/,YHUnp)vBP?֚֕ILJ;K9_7y>x߼ '}⽳/L[`WGO y(LHxqzb6dis#E_j9M%dɩ_J_n|"?oKr. R(0֎pxD&7[٠4˲佞s \7+8ӀjsT{378Cr?SU#YA@C>tRKEaěU L.*?1G-7<JeJyDskz}>*B[Zy+]տ:P AKLXhwظNw)DV/z>U \/=[~uc{RyC*7c:UwQo^3)"*Y"[H:$Yz+gl^uX)J}2LCi[\G!)otyQh&jWo܈%Bҥ]rفg(}uisv*RVN-+ot ;`"jaw|lwJeH_;z=%f>#t.tK]va`d)V]qLFcG%ݕB>'*hFt\~*7eqaSF(:]OV3s{U-Q@:"ߙ{ODr (08Tء[ϭToƣgip]kk:XolҰQHD c\*諮jv=4J*8o5\{18(TihF'`& a,qKGJ0u'07[4- `_V(=è{agnPxZzȧG!4o]|42^:)+Kbyx:蠗x *fN%gh^{QY>[- DQKuj'دwh탎<,>a> }N-0}gzԚT6hwryY)G~q6PmgX}3"?i}ƅvVU_|,ѳ)jgo+)kvB=/Wpz&Kl})Fu2J,D4ƷhG1#ބܲ ٖ P4S\g(n. J5ك\fEaU >r1sšWn%1'^F+ bH7ڶg:妊K˲ Wv :cEv4ful+ʒ\9M ?1Κᖍu\l >aQow-0]3-'\g&6zS( }]qPwRoasʙ?&x?\$q&vU)4+ΰC D9uQ > d .W,'wXd`TE`qP xf Ûl;MM 0X <^ VLun$؂rftwT { ExEN1,Cqw"^],듺4`5_\%W(TO+','%Vy;< ܈ojk+k2L!uR1rNfjHNɾEu>mR#H\WD~j-E/_bJQ.8V1*GQH#nJgVfgj-2O$l2\SuCw_eStm(p᠖Qٰ4!I ^M!5kŀZ\E@WAC*fFN'>XPoeΚޖ6cR!n2*\U [R%E糬܏QLll~1@*KzwSׂǕrHS5~LʅZ= C?s }ii@3D@4`:7KU2Mf5#xz!YΗIdvBwWR$K}No4xe2!3 :{"IxԀtY[~ JRRq鯈A6;Z^̂&-cA;C[-MHf3մ>uw\PcUOS ֚f0܋5&.'N<΃0G\W390\c1KK0K>k|E>.HMV[-K¼T^Z3IZyeX4.k`GMHW*҂@vjj 3Qܴ%$~5mfvTW;aIN/.<ކCWd-ahS4|&䰹CY]v5&Z\NUʕxF+Njbz ݇t}r@ 3#vŶsPv;kN}nX'mo.ۜ[Sh[kl z3 B8mYTѣҶd -C@,xğs:tO E kl@+Yn.@YBɒam I)5ޒ:}RT\pܳEP7oX @-5rpIc/lS2ENMqQmn)$=$M>KzLihI>\!ޒ[ ^>ݐ'EMZ^[L:o"SǢkC#rx戊]bS& tDzzݩH;:e͹{Ÿ0`_ؾrʲsv3NO#<[rb0FA`3%~NDXe҅n<֥T M8NF8ޜl>)kb3#^\M-nS Kث*n~ztU`!Vdd5k"6MCʦ6?ꊿ+fKtKܘ="qjSFX=A\$W*Qo䴯)GSN+g6}2Rj_ft5d*u>;h񖞩exBھY)9xs<5/Oa4DžlҪ!3GRAshuoR/~ h6A, VcV"\&á Lj=#2mw>MY6`> p:zrOg;$\x"bf Xl݇!J7c+hwؖq;tB)a "ܫˣq}bm՞,k"&>'s #6.%c0`?ܫ63=?4tr$%sjx~E- Vtăѱ7!`%jq]*MF_a*`6f `Tf=% 34Yaa1*$qˆ#2V%A٪s/F*HHЀ˭?? ; [-)3<ňX*vXYwT5Eg,}e}4;>z~*-oh?kWo"\ۋ>okO xJ_!& Hς4Ⱑc?Pׇe);~a1(~_>u x%.X e)}6b~掄o4Gr?Q\V|0:%[6Y ːw OXC--\ϒihY4'yUfBok^(_j _jBUM^82$j$?Kwַvv|~n,*rm@&KWnڥN=%  n\](f&-kV"F&53n)SfKt8lOm.[.`gN/2GT`[7PX{Ұ}#ZER:2XDP;ӫR?Ҁ``"в g8ؠ\ޕV(eсTܳr]xwJ|Lهk%>xt;;5-6"2Nsfz& )Tt7 Isvܳ- [`qPjAޝYc˥>*v 0<ر SAr+fZC`>c!ۇ&> wܭ)VGh@x 'Z!:Es᎓ 00Vm2u3MQ:z*[T9מ f2r(zkxϖK^QkvfNO4j PN;;O#ş06e%…JV$wxsJGnUK(w,r7yCKW@N-` h2Bd,S-ƲK9DfwlRX+̫r ܶwN )~C5 ­u74u&I~8Bk,M-15[6ڧ8~ԺŔyеհI*nUb>Lg'-+eT6E@; }02 _ Hd㋩Sv@$)c:][j*ʰt 9d.nv:&@ET$qCgwT7icE==TS)6hmNTo/^EJR!*tɆ{{i$/sxeq$p $]@3< zM``kWc& tK^_;|Xj-./@ܫñ;ڇ歐-3@Zn@_DzX}"]Zq#=1KAEt?lNvpՙP9ve߼^CqQ7^ջzy17b>sRn#CjYoΕ#+CxnzU=06f '[O" SOߌG?=^ʐ*QہT+tp_q"Xݵ'MDtkmjqeM7"7*}.q`זeݏY-^3l; jp5[DȀOm Sd.khofz{o,]r\#>z}-oeOga9'bβ:cO^k_EK3mXƩp„a;Uhe.=TIng$]\9F_(O >pH]q05Vۺ;` hOJ0`0D9ݻ1IV?i1yuPά݀څ j_(;Wf" _}Sn0thTi|:B\S̛fh}}'&$`j{6=tu4]Ah]DMMS =%.sfmӲQpcbZSF۞x Y70GMiFo|gڅ,+>{<4O|xr7 [I넢2LsDlQbYc!yYǞe˷84TRw NuAҶ\؍w%r3xi[7ԾOc:7 y St LcDY[ը 89Ր9YkW8rS]b7ǛfCf#ƐwP\( t| 'FHZo0:m-&Rilcrwh%]c3-u婪NO; ,->5ϝ9]14+zG'hL6H{YV'>n`K](@jh<^{CU{ƃIak$6A8*讧yX2zzI 0F4`Xo5$S 'kijbYgf8>T-IDW3 -S+ܤ4_nV./X2afS JX%%q."/ #T_C? jY52Wwϕwx [ҫsvƛw _F3꒖Seu8cmkZH?C=H'4ɘ`շun-K,H.찿@f @i]jR5jc }7`/ܱ܋t#{ b(́MhNAAyё>M' G~Z"?d H8zpNJOm Eܡ:r?IRE]3ڟz##مV -Ʃޞt;ֶ{hS Ot|ݐ5:K)Gۭ_ۊ+Rau}<{(阜AN|^jF/s&YR]4wN˶F˂U2h$c )G8]NpmҞcEU_WH[GAtsjD<1l倄d{* ;PL.l_o=^hͱgŃHJ gҔq%Me ڬY# :M,Tm3̉pA5nm6SA"f,027Ң">7/ۓwO0fK3+S8L $4Z-hmxt41 3O;oQtj% HMOI@ uE$Uн"Z!Թp('mɁXqI&Xc=6Hi;[_nUL0J/xDZ wh6.K3x S>笀"_^ %C$7H,J b9+# Ja/`o mk3/m*pP ?|׸vմ9t:SX 5^uR5|"bh~gn&xF1^=\EI #Ow00I4WvCI;_dRm@ An?=Qz7e.$8:\@( _,eӮ:2 'GB[0g})sBz[}C, Z~?$'r UsE7 &5ra$mx4Z$uH rܿ]Z skʦj.I)0d98t)fG0NTӘ1 i7v'x.3٣Ɣ'609Vq`/7r gKPGb`D 0)}+@bYIeX~%B((p۠Q~UgIdGߣEщ=YP-Q2]~lx 8*g{=k%+rsG5ENIowa)ُl-AaL[u2q5m2 IUxLK{\$TQCh ;Lʛ%cB%ő] LV9D.fOd"{98,ڷszR÷tc !ٶkJ_ l69mLu>JxNh[|,ob;O7%;Z[eQv )@hSydް';W>K`Dr&WtڙflbX "oŃE T:(u_C5Ѽ#< E< ABoOJs\ߜVQ I}v H _}uQ mEeDVhe 0J' nu$cdds0ьpDiُKρo.ycaU)2]+y/҇Dh?HĬ,gK맇kJ?"Β$̐Eg$1h!vwŠPD7`#gю =?E#QO0{xC5' ٧>'BG6`@MkB@܃>j6ޛxO~9[ʙo8>`_ڨ']N^ x/i%!>HZ=qd6}2E y-a:^nLs7vFd* l7oS:Y ԰J53*iȞ3ꈦ"${$μG=<Ԩ|nųTL-X*C "Ԧ[!2R߈xUTݪ9l (Wch8)`(Y Pyڦ#蝹=z8 sGٚìp,U m} ZZVQ]뒫~#rgJ-R,#K#ܗ\$BkIi/-k%bmPJY}u|3Fsqx[if H2HZl~(r&y5#>zIVp 8DD$Ӎq\ >8/a |#dK/_TFT_fd(DAn=_lY!*`/Xȩ]`[SpwɤF1t:*pT@5|ёxW%|B)?t%;cm(.SY*@tSy<>G^%Ď*qʌT{c9j3>`1i#$S>iR* ;0S;/=Cv ݤѥ!]O_Rx2+L*^"lF)| m$>nPBtT;եAGodԁ? y<;i2xuNߖ2lp=BM35nq>U/K >xƼH❸6mdi#SqټO5 GjO> 3 lO8` Esi`ĥγohC%.{E% d~];]):=K#=81!jYk#vk;jE=JYSzj;]̝]Y7mfU}96 n 8&c(>UmcӘlt2NNXz,br[Sk..hD7%=QXM SDxCVi~X,m0\V疰U׼+.X5CDԜ][wB4xv;])p<_][(qDxE%caҹ EbRDfHoIaϟ_&c>Cl@uɞw.;?z~Ks>[y}@`c֠;BGjJkQh߁i65G$1iZUjKBa.iUqM۬F ȵPLJZE'Fo7d^>^ CfpϓR؂{[@ T'>S'JgqJeS J]uf?bS)^B+<莘_F WOێKJ`rn93kiaok˧pQx@Ŵ{ެgcߴĵ;Q%9ղPr/I:A̓""sl(c_b~>R rՒ3W ʄêf%?%(KP|l\24)a"F+·t)9ôAF!:z-N[_[ .&{ i.* ?nb,jVi1'Q DU^R 4C)FCOO䧽4bVLI¾i?T~g B6/ӔU<m\ʸp/oF<fjexQB5/rwl䏺35#]/P>=!Xmu)>1<>$b5rڐ_]]v)DJ;A'gA8 f' o+'R͞G8FZ4r>̔3YivęS 0#;uʟksn?tB|-߷ EQ ľ p w%g0V5aQ#Hx/B}z9ygRY1Ⴝ}ɾ4`L{>Vg\xf'Т/6giLնR. m \pr}q+?kE$v)`f{ QhsѪ㊶7M{ qދG-!o2sȈ @ ryˈIbG3RIҖBD4[zr6n K~SZ̊b}vur3$zq'+S oſw!Hes\pܧJ`pq?QqJ,=V]UKRm)xd2ZڿT8CN[jDf?V5Dy;d*cE째0hH%cAi);j[ؔ}l: Mwłf딺'q(0g'la)O28fEG̘0J˫Ԩ; ֒e[2L4OdF3~[ă lzAgxհ-A}E1#!OoDKhS֋)rw4?7f27xJ[+ٜ ۅ m~ŕ` ύ܃Xj'T0bZ6ɶT xTG^/?Ze_J_3I,<SeSu{Y84gF ly`~b< b_MY:9Gk!6U}G& Ecy ,I;_|6jMsģ ދ9ڋ-c:o&s`ջeY._ZȂk5U W-ßuK*O& 3xmNepu k/,V EQ%pV2B{\,$`v"Q٪3wf(Wҡ9d5a]j/3,z#Eďj"Y ;nKؿ"Fw+{ͥ9HS #a./.=JÄFI H ~ "ys4N݋؝$f $ ӇOjpڏ,⻈_iXiܶ-{NgcyOyп|6^js.ظ:Q彍\@a'͛&D;YͿU(TmLM]($^57d*G~y)g3*_ ӜDz$Md6^iz;ѓ [Q Q,QOK`(6:U3>MdpIH%:ɟiðBQhB*ꥆxnl4 %:M|a>f:7eC:AY|x&u Qq^IonS1+Q h I+oP_爨IICvx#0 kۊL-z}]Ff0+ۯ1Z[֙"[dr Q$j\3B)"4xc~8p񋢽 q?ZG BNt\kAwYh,^ =Th v&ô)0b53ޠAGl8&j"rb`i) q$6CKrv'ZCPC&0DL^:_onƝ38GT߾P; kX?dd|$\$/93p9B:찊;H`&% xE)o_ǖ(9 ʱQe!%J˖pFOŘtmMw@~3H!үODڎ]vmOԫ2|%@&&uYe Y 5ڴh2jP8l[ {2 yz㔢8.U0ik)ց*tGO_(m뾛C6rw&[zBOϽYx`vv6{8Hv$ NM֤BL{ '0D>wړ&?snJ|e+fcR/1C4avzηl\|TJZ[)wYIXVa|H+|œ$;cƾ#wAj:='+!I9ƫ!gNZ݉bIe.xm o'r ާu 5x~I&DW{2kkÍf`Mr߮T5 ^5-z#CXWWG⇓/H<3(I Iɺ1laA^3 jand>@i?_;hc'h˜s< |}}]wRkۛq-zV"E-ѭX^A1eA赱Si/Ձ^z4,E4ْWcPF%C"* `rm_K R ʏK6rɡ{ oΆu2IXd,<_iՒt/2ր?j@8>K'g6& ?hN{rN&iIrn_AB=ɦK}HzpٿzxBGb9Br/(Do[ķeP␣,N#r1}̺b]%LOwL޶VįAB&gОFȼMRs =2rgᳺV̋Nެ{w+4X$f|wq[;|M KBz"ti%c 3@F\I0.CC5נ"{qdA)Q~Eg|f$%?㔷sqVF=2 <_0x1ה a [SQ_NV-ؾp̝_I5'ߤ cO+{7-}_qʅWԫ>&j< k%](dljN* rKtI3.y6{Cj~*)Twsz %E~iF =f\Ï]n$/[c5ts3*w}4 Wxs5/yQ@U1 Rl@N8A5`$ފѐuS=/ѐѱhЙ]_ /WJ)yu:vz 9G3Lc aZ@xMlNݾ+'twk0Y&CP*֙A-͈)@#3ԡqZ)}P(i==KdCtIC%_҅Og wGoasJIK\':k ^lz.uMzyճVlT1{[;^LgKگ3lUWc+kqs?F*8%am"t3 ŽՃma*j%jQf?k\^m$o:mT+rl"tbS8C\$bZ` )p($bb׾&;e)IVXv9`=稭P(W(zx2&U"39K_z@ܶ <8pƱRK=28}:R䃱νkwy˰+[pE7";6p3M@YrT`S%䶱zxӠj#Z]>- $o㰯O/NKȠr\=O}Sĥ "Uep/ʸfmXzpK<điAVh#U;|3@>VY…N5b)T(YDJh1hwbO_/fVjw6f`7(O^]iF}=y ضboĄSli_Pmyj^ݲI sƤB NSbĚKm4 2[}jH='qSόkoŨ>~/%57JcTU}$/֒w >iJI!1>e(5Т餝ډܲfa9fv1#Mp[$j%'K;1;Ib+9#詢}m`&Ս4T1%DN5h˅2*$Kr1~@:cul趶=/2tke#;9ԣg"ݺgbTX' kOx t܆(*׸Ըf5W)\4?mʑs!D:{-m; A#N0)j丂] QAYLN8 LKB=ɗqp=+8(R#.[N{v{U3x|`U&t/";gS׶UgA0ևi drCt<())qJٔ#gu.! DT֐!xkhnh+Ytt@dJ'3jJ )ǔ㖜mi.ύ~X&kQ^Dډ A,LĩﮏTD ;,n$_ aoA5`%_FC5HVސ28:{(Ѹ~?Ugܬf5A ou Y<;nv5_5bHCzN0hK?s Far hࢺ`Kp{ro,],ƥ QAXNxT/R7{8JS+UQ(h\E|Zt5v*(*,Z lG}eiނpՖ_'[vc#UBcKa:漣|*]{'hO/J?RD,rBpD9O}x:8A)0,XeDI"VIڲ8 ,@}jh˭UHr?}-?f/#7-ѱy|*n&}*//x*Zcz_rL.0jy!?ȁO-@)j(!& yJ5~h,f*to&i,ʝff^ /Yw(v۰n\*>m^ܚX,!/ERGj'9ECpRū i * $GeSGV[%hx֪ 'LE"Xh|wr>9 Aݥw3y7wˮ-,5]XV){UD C&۠p! |WEA-LJ @l4KhvDn(|>C.Ѡבk^NRա?ߐVJ2P1+CT{zOGKO1 7OK멖A4tVArm{/F7p`̃O5IG:0^gKXG3;mki5b;d# - >TD >NGeҚ٨R%Oxb.<QMFa6Gz@&:DZ=vE0ɤy 8 }{l6MdXO`|Ah" GMP킔xGeI,'ud0S8B qCo)o@:P]a4'~LTf>P% aja?)7h֓3|ksk@:GelrAB+6s-AR\aQf#l,*3ʳPԴUn7!ձPsfP玕Wo{-z%AXwjlQ3M*~oHHh޹{rFjTy2 T%(l'_m7;\M{Þhx̳Vf[5\+8((nQ@ 8tVGMfwq&BHcU>ݿD e /`_tl1Ф*($1"JGq8OhKa ,?Ɇg=| -+yG}\u'QnDόDl ȼ.(ʛ((NV7`cUY͗>tYnĞZ]R>%Gv}i_탄G]KsA4}_IZZQ[RMB lУdl]$F&9ּ0l"Y[\YhoǞükJW4{\-VD45:(.z zȤ/K(w%Ԣmk]y$J\Cof8MI{7ծ-~GPz{]T؅H87#rBxPi K38~pqB/DύLy4ewh.yaA?|AmW#gBY @dUj)(vP 2  )+WPi0&;X~4=Yؗc8o.='FQc^iUWZweᤈ; ~F[ImO4 IF}7I,?^ 3(f$qr3$`⿖3ջj{ [4;J=W1S)8 +%ؘ@x-DjDjۧ#)mu3wHùLKd2|pBkxiCD3 $ Q}9ǺLټT6n xe>tpσeWFyw[u.=dr Uu7_eikjj\C-/"kBl#yѱ'$ClTf lZRԖҏ(~n{zjQGnQNʼyp,JuΦ1뜅;bi<.G~k2zG꨽dp(aΩ" [Afq -LNy:Veupl2OoAgW^9ED,t|׿Oω; VwV @Cw#k0xp勤B7c<Љ̷ Ry7Y'C$WW"vW_%S&^:JosPkXBeMb T5W$f}]'$I?l 5*1>x8ϯqԹ2q՛'-1-!φ H5(<;o_=C)_FHޤoitA}=S;Ds @f4TNg%|Vh5VSW Aeb8f69E}Wj[<7~`[?,\ 9;=)J5bˮ3D;D7%45eݶK=|q09s!.S\r}\mwS :`F^TT'lJ.Ǒ(䰒B|g8߼~WSx(B7➲.Y& uu_s\A1WH0V%ռdz<~N.v|^/e .8e1JNʣ j[@ށ !i,C8LSIvU6:I]l:fbQ.t2\;}X20?;8q)il0_( |Sä`e[R +u{Y(Dv(J3]Lw)L4j %-#HTf2b0Ye (IAq_ J8TŃPķ$%a!sH <@1˫AknI.ՖĊbGc> |3k}rQ6.$ϺHm͋nAhۚ?H7sۏîHl^Cr7}G/㿸28}w"'lU"w6لHHp(WJ~f 'ey<*VQn{H 8/Dy7JnD'U9mwL*8u1ӏX pٶJ(8wGʛ3\`D ؋}8@]V3"ƖҾ.tUc{P,^ 1:6l+OŔk>U]/Q76id? {nHh{Ht0X81=%:-'w[s͡]\̆xyhЃ-g``BpaAߍn}ݲSFʂ~)6! ;ȎA8;r}g^=ʮ Ƣ׷Ũ[<%15CE ϫ]b"%"h?nPO vTꘙݿ}|_¹$&|X Uئ_[egNvR,^C؀X:_d9,KA|?.ρ %Ʃ^FPe< ,ٽf16$#]HK:LԊ={ǎw 6~{8Zo,fW/-%ΏB*/o1CI |ML=.(ǭ8,ԺjOemM!A5rmx C*}"h,/*kpZa5u?V((W 1S%<EH$UBYK)̥plf,ӭ$Oai` &>zFQRbJv86# J ] ˛cmڶsH(t6TᫌtQ-Iƶv`ЪE Il0#N}q\C\c Qy Ԏ u_\𕍎&<ϝ] 3ĦM" uFe)D,C踈Q@1dnJ: .ݱm6τ޺+31=YqnC?eqdj%P*ͿǒwR|[zuЍmjMʁ9VIUmF /ƌv- qhgNѨ;em_sgNO32V;(@",d3PJ C?ӐRYX%w%ot)f am50 8jqcdCӛ`,_6s}v w59Nq=oc''P{y 4!X5&7o5o'Ϋˮ>bǪӧUh]ڃn瑐7Zoq9sjEN7WA?MPTx S̓d>Tl#+a2Zw {e+ٝX&bt8 @ɰ]i}p~FLbk yI'Ln }>}ftd [kuC <~f/>6'ƶƧg )7k PoU3 '%zzű:)u:Vk8x Uyq\,5]+3x,Z9Jľ9l`sqGW(Eohl|.ܠm5ե{+e֒I|5pzs2 jӥ5BY$V/M 4gf@4=J4/c=5bĎ,.WΝncI8L/P}BAj?pϦ_ %CgpjeІ7ײ^ e;h%J9h\g<sǼlbpbLX03I|tL!UZ ?#T[4Bwf#N3AVP(kJI4aǍ@g LE%.ۣᛆ%J+ Ͼ[MíS}Y<*e~e z]PVodT39Tɶ%NLC:ݒb#L)Y} v+&ֳ ZR(;橎}$ '$\AAiĊ&ĸw/YTW6 "7c7]]1*1ճøY"\`M;_":y)=)mU,p0T6 x#gliT0A͵z*i|fEqPo4ԔG=75\B8Q<(Fޯ 9 M315yU9ق侚HG@B\Wddx5rA~+4 X'i{e_qGTu1SN '$̱C#rj5n$wө^YY?OԹionc\MBFLW8@o-˃}eJ0F/Ȗ#)RL@dwϜrS4I\K?}pJ {IbC{O)]L/|bQmv,Vn]szD"^T={+ YGtQ{La8aʾN";^AaxgQCh ;j̰Ro2 5r!ZΉԘ(4H$k fyL@D ٱrkN-Gϔ|As1*5kRj<ЧF nvUHcYu_2QzQI^SHTOyK?s+w;Pqe끥`ew t鮝4T314,;eewkǏf/] !d_bd;M @ɯ[\7k~:=%u[T %8 `Bh՟>6۲zⳌ]x 束+m ʑ^6zaRۅ%%bt7̧9 Py7inۛ^zrV@Q`'ICH Q;<4ޙ{O5h!<3$;և|\:sc%*;1R򮏰H) 15l)l~s 7PL:$3(,ʮ:Ѓ_˪{ͥGž>>v»s?IC5j?֏`{C$$Ĩ)Ѽ8GToqYtreh|ب/me]DUBn6'xg@δs}P?IavN5α͍e֫;Im@EC)?O-'\ ,hf3vv쩑"mكCUSO\lG\2I'8 [@BNַm')7dtnKQnuwMk5.b>6TY' dƤt%>cܺz>f;?Illjc}^X8X&X ]/*wٴ)|]ƍN"( 5P5 㴐c:cۢъEZ:ƟR`J♜s" ӹm|Dqvz ľN>N 5M p$C%.W1hJ1ox|'67,84=`Rx[ {څ]E+s1 nkޭbOJZ濖 Pf"DuQ9AۙŶ$­S[j!SjBÄĻr/I}rќ@5_^l9. G$I(k==y@Sy 3T4壚$5{=JH4p#e:reơ"4VߛA+>ơx&])$xLx LJV/~\+2qo NA(*yr/Si^w^1@4=Zv_/SWsbWDV&r=ͬL\X7Qt&BMa9Ek7>O^@a, h4a] ݱ1.vPKcſXt"bX j&2=Q?s-_5k²[q-Q{`KV훕?2j6FM*Kxh'iVt/~!\TBɸ3PJ6*g:_ `W}8X.0<ɱ[_2]h5ѓg:朳{0D 2I3N>.&z3m[{䎴2JQ=s'=N:R( os}h}ʔ$-|?AٹT6@P5zYT7 FT(Kze@ͺDWbnP>mC/~Ke6=òe(uG[~s^^?LҐI"US> d);v2bkumRLRdl:`/t Ӛ(虜Au𕯚pUe9N2 :?!ca}<4*lD?F#N"6e1ErCDȾ4kM.;RNI"mw%V0"9{*nqhCZXl/W(7ĕY-lb+yx./Rg3.1o=}hE=i-ʛ!*{Jӛhh*U#X߲,vcM ٝsF sSҀ,YsF*idTke>]ewhh l(PZgIqn(+]-uEXwH.:XOӹ^np:,EM*T '8%m8ȓ"~ CBH S[nZ:q-]F+PR8jH-{S}sʼn.G֒kh(>%΋6B,aQ|ŀJCI Oq}8w^`Ͳ 1#3h`#:B9ZIk.\8˧ eZ^) }` ܹ~JeY.C\Ƽ_b%G>sr֎Oԯx G< u>ϻ־n ݕu>s =r9|!q:TAVd`5ExZ ys^WSF/ ;KktsJ0\MN{= J4:jՎ\yg:,v}f6OVqwl-~F9 &v8w,FNGP cD$p6YtXrA:~`cQ"vH H88 #>¸$rZΛ~\!m5f`Hob#r0NjE5방CTͥ{D!)+1B h~/KȒ6ҟGSBUܗH*J> m^U@U3R%+ػّ߄y<$S1w>ŕp\QNt2W(" :X{Cxډt|>hǔY~YU0RfaC7l$,uK*'R3<(_};y#fiە&ReLjg[S+ 洳|Yf y➝_!i U`}fS9A`9C_9@+@;("da,muS]j°x"FM,rɦ2<^=JODz 6z@/ר[ȴ qvv ;xp]"ѓeN]P{)U\S%]mj5Ƙ֑55·T~?=14# r _:${Dl=c/K&R?t F?G&}CӝnLbjk3ܸ'w)mlgbU:K*&v4@@sX_l_J!-=xHsS#Rohr&{,!A#K<*Xl t Ag?1hԿٱ·zu'Ke3([[R|"}oŬ wIcRC$r^BK327t!G/?)(`hG˪GZ#+:][("Cwc5W6߷=0sv[W̢;hW1#5UuNk|mW:!I:ۊW˝BC~S#KeO.ǕwY~{sc>ijRwQ 0sF{$ƦKZ``^B,ě˶w K a>00jW3n/mx}U]\}= !${ ]vIdݽxeKuDtGPV$4D͟& ]@ gt`eL$Rw ZFL9eG0})4~ ͷhȝ`x_D Yr h7e)DW9u %"KRVOarFHob9Nv2r) ྨ -Vr):8 \z:8!Mda rH}P# r19x_4erN6 6 |dMꔔ',l;5d6Aug(ev' M L|) & Ô Ss Ni?q;x8yWipKղͯOu3GxJȺ8N|k2Պeؖ+״t)uOҢVybݳq_5B#FQy0-ex鮋 Ü?RplMШ@o]NmhƒؕR˿LNӱV&Rѩ_M9dK^YZw]H^Llڰ RQ9Z>'pO6%Z#@B&>k 3\t% .|Y'.e6xX["CxQeF#=o{T`/3DI|˄6 _r:vhX7T$JP$0Ž /ÕG,+n+V#I`'pl( ps\k L+YOD^)s_f};5FIZ}H]j_ꠒK OH}^zf.%d&F̵c>C *tB' >b$;8FY}-߉\/c|¦^\"ulwNʌekyk6K3,,)-ss`]&ۜ0auvw$(@7d w t3֦WfT~׃i"v[g\K^Pf1,;-=M\ExA(ZH29 u Í"8:޺ ZD:JQIBψL}X [xR]+Xo\z,8&6.ZwSgcQ(LER a@#ޟ1rqZ+;S6rjn|Ӗ7~*v{]/7* 9Nj>8_č? 8Mt'0'rr.zjpO2!2.xuj8r#v2,w%TB(ΧnEgAW0;-`~l0#/jVLEWɏ5TXǏ;wzr4)h#hT,VwI' POh)Ը,:JȋWN|A_6/, al,.{qw$E UjlJvz^b3qKympLUT}vT\uQI˟Xg]!6@u4$r->BNDc8K%>#(p7^_;c5"Z5l@حIJb@B$.i?i䤿8>["˷K\K>,oX&(SK& U1R[\:RYDL7a}H@Kx]5qAl_.]6-39gFYЎ]npӆWT{]z&q^! w=}_JECG'(dGrB`>dql>~J8V̨b$ђU4ѕAhl`h|B~@ _*i s枬#yK9bR&@GjJGt$ u}Q5ȪąåI)uE۰w./xTxHq3,@Rk|5w~$*[Ht,5SaqE΃-c̚|=6@_tmZ`o;$u'J0&+L:;s&>G iP,x*^0X@Y䖮jkt,!C$1} 0[WxgJM'{GJ`% % f- %n3 );Ia>rH~'}byo&j|y80z8ꭲj<`r輱kA#uF2Zc'д*?^ J0QR-w&tG@h|緉QCcQ_hT;jϓ6/,E P~%|Mù"-oEҾ+&\`DC ?u74EXxIک)}nUt ^}Z=ouA"x\vM86 ) #TP'XE C9n;s^J9- ɲgWU?q.Z—B4u%z9M̦.í .DzA\ވ_ޢ*XGu/:0"_.S5 1ub>s",AU '#W,u>RySjoy.AArw5n@*^TcK …î@@Qu K];qkϺ #!0Y/ w: 8.X01vˣ>,.%6rxSөH(>>Ѯ/0V(EبcD%16\.!t ohp*¾&#ܒ' F6vN>B8[Vf' 6gmܾSͨAt@1cI:icbMiĔ*ks`}s9d`e1gwO:;Bi}Z4LY'Wd= Ɓfdևn:P߫ BG-tՁu%S0J`;$7-x)ys)/C u MZu ORv\z6\|q*XJ޾-6-D.+JefoeVa=hg2L=PR6 ^KeMŰdIl)#]z#X@~|Yh@)WUuz^є&4s=V}BI^05;BٿS6+6Y1A'VP }< ^73?#94[WT j\Nnkv=HrɎK2f֮xFH\ԉvz:+Z0W磓+~ ~e ϥ:hjbaGMmhswG_;X`4_eyNѩm-W-]_Ȥ^CHHͣ´z*Q(U:q^qb;Q RUkeJ-¢-laN@uĺ+|uDʩUPA^O@*ۄv0xW\63|yY7 O I'6FeUص'_zT%]^'J5 / Mca3z:qšskspMu48+- ˀ-)L sĩD$ǷD3#:EcUaHYVuBs?u/ϼGW(дD=P> źl5f;رlPD7 \՘rAO|WG,:HD v05rvG\,-)mΒnJAJ{-램 Unӈ>9WQ³R.OFqHF4b56;Pd<5HDed7E7hvdYk.:A/v^о)0p}лLnZ|VT_ug=$>Murk }Zson7 ~zxp`>h?i۴2UhCR1~MA> .;|v-{6ޓJຆN$+Whg"48gd';H*Oh֓ Բ2:7{<| pi0AJa,uK6M爽VV'I53;,sr.gg/M uPnW0]`;61ťI:ךEyiy!8MF=9!CӼaZn&P2[]w'" 潢_~2< n0/Q$"!L'EVE)p&"*bASS ƾ|k^E[=w\CM\,Ǥ8<8hfa5e$qcQ_Rqk>vǻqH 3쌲9a5"hV}AUw)y{}T vw})0~L- lnW1d/[D(z+Nպ dbpF5nQ٭_a@^</=5f#>ٲS5rg'ZpaC* QFDҺq¨KGW6Opw:qfOPY@#9wE%&+[t4zt{,I8I)Њrz*t|#LK !?%5ҿ.:OI b;kIMDn5rK05 c|*]}3LWS+طƁwX־JQN"]]o /ŭ%hqj0eTQ% $osAh Yv {G@~3U A !.;ԵҠG@ `e*ּV`bcAay/֭ጬRmk(y~a^sjdW_iTy2 и ]lfN'49mP..O=0K0D}-(9>>dm17G'p+<-]V3@lhA_e>%N{S^EtٗeQN𓕠xV790Y+b*΋jg<[@LE2 rF}hF iE}d1 ]cl,pb{pqia !P)QXG5W|t]?= IŁK+²%3˜r3S {`3l2?Ho:}}Fj}J$চrc-5C ٍk ?r]Iݱw7Omy5CHL(tb`HmԢ5NN5JiwMHV]snaͯ)^Œ̵@zވ»sM9?Ҭ?DTMls+-mmq7DH S5AwLOHF>ֲ92nd1}U#KI\ѕg-A153 ]^vLu>(P=[ܰ39l‰{7`O8rU^:`QCa7EƮ)ň~6kvd ǷSuDS̡Bd$5.cCILn7PmDIWah(t˿zH/-e X3c#rto߂fܸǗ [#j^FNfkj 01 't20xhhrϞp9c[."0Qg.YuDWqH7~y({S,"`Ɔ_E:P/7ܠ8 Al']Y;HtqsH8(e~"7&Y~3uU=Ξri|)BH[L፞_1I"Z4#`%yMI&)R!I:cpӒOj{>\}RhN07n/OwSxfs g&\A{ҋE7b1m q&w_R#)PoOO G$d㰨o:y[+VDI9bַVeC:nCFN*`S!w F9}1h,TZO%ϜT.}LW{ zkDtoq]m?[MHhQ¥@؟IPWh&}$}mן*n2Vʶ[]~ &[C\HXq4hm33|4d囧`|yNw1blb<6ĸ2t>,;/@ɳG0?h-`-74 C~֥8;OOqay3uiAbe 3ņ{L8_.,$o, _q^;%P)=}<5[lbz9*~BF- L6wx;]$- f2Kҕ{*RgObo!rGUPwݔ"i!%&P_#X͛2'iXAeY[2=(7 3dHp$I? ? (ܐjd0'˝ԛa  J5׷Z2.ݑvI-Ap4^j-'c|ug2M&b >uug|ĵ2[1k(to)h%YNdlїpKvg^z7I.d?[ rxb x| ?HU7XL_ %/y9FT$zu#iz:M9XC[p)K˒UܝaFXrgQCHe,o>u-_'Z5CЂ䋊ݬ*!/Uh0g{䘝N<.˘׹.UZ\#X^byh1[O a-xmnMjgOb"6s) GS*^>0w wns#> Wd}//=ȳH5|>QV@_*xa;YlBaqM Y;X8~/m3 HUl[6³KI^uGB;C ;=75Eog_Zȓt3ku׺yy!H|CKxC 28~(}wԷ7Ȩ'j1E=$nC#8=);I`b-OvNy["DEC :w>ܫ\i 6mw/0k\- i9s3VQA-n#!2dmَϧqZu1+Y.O};35ŀ[X}e]|e)HJvs5cEOAqm|T{-.iZsiȰ;,eMrbgUZu ˔AMpwjRnQMVaG_x9^M.ӴKvZ8?ރSIU/*/bC}]]A7`C\Z)]'Ye:vuV{QC] ݗj79 WtK1r<4;pmNthkD;@yyj|I^,_}uz.mƊV*Vw~!"!;~:eo%!sg2ΩƗn'_} y-O^ApZas7m筼gdؔ krN@yw ar\)t`^"modb7*ڸX9[Xj36>wH9F) @wUj ő\*-Sr>4Tt\BAJVSNOhY㼄ֿk J?)Tp PxC6m+x_p>dj\^cUjWByyhZpJ+Op,1OwDsx$c."{2uh&zߢ0*yY8<^&b/@CŊ }H4hPrXŲ 2 ȆP*d(N۸fw'so,DV8mx}{*2w68˷&m$Vr[32i]1%zZ(qŗ7T$pdz\9dp"ߟ{h-ґe%-)4Sk\fi")smu-G>vހ G#*~s0. ' +3[ۤBaf[="F0ҐÿUl~[-+- G}9$-w y/N-)by0I!CLzK+rb 8l޿l͍ ̺&L37ڰ%R1 ۿw%ߝ8{x5.L^שU$)eEgNG(=X1]Rk*lm>BwIN"dv܉By_Dtc&m\NG?5! MݽxwWjDoK==jgq,ē#yE*_u_jU@d8 .EZgLSPƧڥc.Fnw8TxN|YgqGp%D*8` O),LTr`!Wڽ=I۸Tl@1J|FjejLVf]W<:"@MM\jZ92nnbЃk)J>/=]Y]6.AӒa$+Q"]m@zPBf2sJ&I6՛ ҡI\D!)$4qj䮈ΣT]'%u1-B`Sa;Im{ts$#GzbVw<(kj57wPT \t ,~4d,B%0s VsCB z*6Н=6Rz[~;":.㜮;H {p |>rĈKc-/{h2;.ե0r77 $@c!XcksoKɂa<21oBvx^b ݶgcoBd"*|B ɄSރ̳:u¢uT I ]bg4.,4%`" _񠧖Hod @Ibjǔ7V"q >]@GVa v_ڃt#TvB ,|1.89 fV%i@i\Ut l)dP+0жXDxXY؋)ݍ vSʗh/n`r(dk$\FiE-HUU|8E`Cz!YqB11.{ &s;0}y0wC%p 0LK/E!RL#_~j'*JM]0R2$/ υe -nG?-!KдN@p+NK&U199tPGP  i[j(Xg~ uT {!TI馅wIw(=Gvxj\ar-zcdRQ:>}T Շ]܁8 ,U3"leuĠb sA*_=\$)8[Ia׀z2&#^KTZ 獿oxmF\%tw\^Ӷ<]v&_T1SJD}2k KjTvM{m\P`:K[ ω Pi_ǿW XWMkT)EJSr Gga:O]( QVC-|#vqmeSBtPHq~MY3 .W[J|fKI;, O;dƒЌ))[>#T1&$~iCKaFXZU ]f-% n p/XDq8#{G~22hV XEDvbLQل|8ytlX Ů}b. hںǥ6 590E@j#ݴZVcbC 5 ;,qy+%̠hAY3VtD@h}A* axߢk @oɇZ5Ř D> cnB ]μͭwIp}r9z"{h{`IB'7RB!0`{,%tՋPA\W2@B>I(g%KrOstI-Pw $!H9vU؜{CW7Pehq脽~åYiXMu5ۙ0YcXd ̍ n} D/ 1|ʾXGU~2+QaR/ !QL.n5D#`kd6WGVߦ@\1'K$`R96QwsEηP582nt ,j9fU4?yYaF{Iu{PV!큻ī+ yvJUSle7rS"4 ‰-4Gt A;\7ƢБ E$:Rq#̋沮lzk]i+(c9K}~->9Y Fwg I׺«fX< 1|!CU);/joJWxxZ *|ͥ/I!q O%ȨIWoZ ӝ|2m@4gShRF.IܭǺ%0C|eV1ZOo #0Zc~uQCՍ5&Ϧpw esǷ ۼ_aCuH('jFOX]Y/UNHvaMt>Fre H2'ڤ*;]ݓHgaRE)Iss$S vĒN1,qy TʚKFSj"~J NUy$Zp) 7k?5Q; >ϟ$+xI9KfL37yf(QvG6vHY`i6ݿ6VF U7O͘=b:!h< W~3Od-S$z+[Swc6'΁F+vZ;~:Va<؞;9X!k,7Tn[S5u}gtR;U @@*e9(kϕx7Wݶ pWCmPB6~evi"A/kwrSP,fŁb2Z^6*uN41D{/O6cPtre K>wxZ}T`6=|Q=N.LgD7{*%۟[r{˖ksHKz{RUͭ@Q~;5z=RdBny3zAf;KA7h:գuw☳p'X^:ٹp 2uofcf,-).07r+a>Ta~3)oltox:!GS!ؚg.O7 /):ͪuZtxzWi3j2hg IDtu$A{xj=+[ {q \gV¢)o 3@Z~((P!W<9Y"4ZΡjYX+YϚ;+~[}$Co%sTg$#hѯ'8?6Dsf1|JY+p9J#ɦ62JbqvsoF##D(0#ŋ[GUx )wa 0ѓzM|ٖ[]tb| 2<|'tS`p"T<Ըʓ f=odxEKa#;# ˙5ߠtΔMkKJˣ{I3tUش6 ͗Iq,LeFF" t\왢ɠlSѪ]7|_PV*2PN Fݘ^X'{>UImi=vK1K \ sC $t/\INK2&[aHj:[bqPd?e;y BRt-FL? )ݮ=A=rhs^Y IP˧f]v1 (' pc0cA!dDyY?SGdY3}H cnSHu65̥4]yVWA3khg]p'mI?OKYܘt;8R ̟[~nѻ`w{Z*mXϠ34FcitAi[lfuYG# ltJ-=Cm`ظNSN%dw?t0i$W4axx([v0j 8}$A9V)!!Ex0v1c(W)YZKY^*Hs^;i|c0FtEPha3#:"Fx('] L=S@\mFXz\:{ bBpM2dޛQ1M2rjgW:މ>^h7;";hp-{QSj((<~m!t^0j+O_tcf[G+/n5Ð.K|‰5D$z4k,@0Ya-Jɜ@34&ZqvoLC.d΁SNJ.vl[żE<ʉ<9`.#%<`F{&w/IlZ_/ʲ_Q͛/](!b E>簍UmHO9gNPsI^/ qf=ew*n_0[g2g-~rU7?cc7~޽rN 3&˙ x0p>ni=a]]" MRVY}M"E-F^E 'K*3pei[fNgZBaΞ= VP,O)q ߯7߄2%qOH!},f^"&}~rjYWܕ kсYVK6+Y].a1Egrw} qH#SdȽs:2qFF]xp̌|Yh V?,{V;(}; (pd|j7;SrkyNg>-gH; y^1 ?oɠoyO]o <`/WrgKKy*N%N\.Pv!1+Ǐ5M2?K631uO+?Œ 6~Ic1Qa!cFE4s @h\5!d@d5h$=% (<%LFU\b.0_%ݸ$)(G1DP8wa=5#S;! z}xA_= 0.. (6zTt ,jTx0+7LxϿ¤#ȕa\ڴtm?=&RÞdzOqB= )^@ՓccF;=tp IGUqيHB;!q^tK]t1ؿ˝mCJ[c0ݡZ~~#%Q(hbyvc'f蟛(HaHZ/~7olJ>CBjXtk0\i %ujXIg$o,MreSt| lAV]eG+XnԈ*yYHZnJ4A@z^ya5Ywb ͿN|ahoR,k7u3AwN֓T05¬& H=+6a:A Q֌}8D#E2qõU L8')wMBc7v{U6*zyW$J(-Ũ102j+Oh,_͠P@Cҧ^Q<@E !F.+K2PwFG=Bto j2(ӢTtd?q{xH8GTqFh7TbthZ7b}q{[ 8Ѓ Ӈu03 rtfAjV4bSV-n>l\r`ٽ}ث#(d_-\5e脸 3wZ$l~y lq=eE-Yp<@P9] '1{d9h-w./d/(mIm,U!5yB a(^rvTLQ |x r c^NDu_od#-"xF:L2Dxїg&O+1 7iV4psa |uWU}C8ǭVP>v;-0+r:}D$b9}hk.ASA3h6Mr\BR]M^cc%-Wlv .g6ȋ?5,b$;Œb{D|wLv^z(d@kjEH&QQH B}RJޅĦZ]Esԉ: aJ)H^ ',m}`~ʮ_& (PĝDrd7G{CjlJ[Nlm:I/Ǎ%Z,bHXxr3§s:V;7-iD/]m6mOFbҪ޲7/@Љe]rҴ1iXN97nVIk,]A6wͭ8 <"J_ "_ԛS½ؙd4 Qjuo03cQ'Ġ5m]igTPj)}am -tV_vKnpeTLJH68DIw?$cMbm˗8Gj4Rq]65]Fٌ~,(9=Lf3KE/>&rlLN`Dtv ްn,mPOD2et"eVm:2[-)T9. `RuؗD3?_ Ku"M*vv5cJt=H[v8Uԯ$ȝeQeAS/ԊEu]JYʮu{"%'6 Zu5L: QgyĽ`ؗsmUzLbƲj>C~lVG+@ F dv ejy&k4 v`ԁ%c9ӯּ /K󴞍̦ -d5G;9q֔qήuJH Lr{o[(ӰŶ)"xZ#?%G/Ka=7zvqx(³b\yk CSUڟ4wV x;#3̣_` `!L į&03yNi\AWO)Te/0cjwByOई,KšS|WvbC;|H.+ p'Sҟ\H^4,:Cs,#vn=R yq*u_)2ѳW(-D:>.%8)(5.u5͙\(/WoF A8m/)Cu(n Y8`"&]_b _Y_E-7m&D!eW)}FOH^ -y@P{Ca(cX!JhPt5u2ےLl:/oMEIK sZ9HŕKPNBeϹ}>tzB_jpzٮ6dQ RSI{9MžD}Gv_aqq O{DCCWP\J7eMO4!x90M9F҈f1}_kc,z#_N< 2e{`0"<ˎp Z wxOtQ:Tt\S9vؘy+nb2_Aչ3xIG9 zǻ) Z9 8ºNJYC:L@=U}E۹u9Ο۝BNLI8ĉ?YcfA %&z6xl?I[%_<ܡ$@5qaηơ֮AYz ZCf{|w|;20JNM1qgMNp#!B̻ԝ2.`Mϥsu RD?kC2@+&Xw"dЄPHJ|#+v# l%Fj;OmLЎzImMM!i^3Èj4t6 c:5 yRhOY|j \_|VSʦ0˚Vka'؀}Z:^`XSg0(%::>cy쏰Pu$kIMr.`c{[N*+,-Hj3~e`7E.*|'dc\Vy].JhYQ#B!>=8O9تΕJ\$2q2μaL ~Qн;d3*$yVj$25%BKy=q"-xXjP-qZ@EUB B]: 3~}r\ۡI)&Ve 5A>4<+Fz3Pk v,766YdCxcq n p_"Th aže 3ƉBs Nd2r(:?*Lp%k]DԣwE ~Ra|18x ?7I^V h<ɔG%\T];14ja^ʘ;97a b$\M)o[s:'Y^j56BUT (X|<#ٶ1=(]c͗s/Gn 4kn+'OvWZibk6a)Hw"LtnA@/YGsmqG(pd螫]>-C;́p7V)^O[wnEҍI Y8FH1eq?}{H6ġs݄8ٷ-f?A/B•i& -Y+W-#:9ω}76̯ՇE/L)~d.]]"ϵ~̂w`F4N$;D%#{7+;T*+nA @;rJI?zKHK | 3&h,ᘀș*]OݍZS[okXe`C^hb Z-%`G*:8;*0 _ ~Z0Q J&\t2peDs8>JC 4+I$io D Lx |9Nw=IuHQlLb.əzQ1T.+Mp.~̿5/YFfbPP{P7&'dx ˆ֮#i .Z3thC5AΗhcс h.&^`2x3p/[` :1xEs*S*STԛ/Ў)VR _IVԌ.$#1-LsF zLԪl<|q<0('½j^8:V[E$sEB|-K,szuϦ1XLH^M &sRZ#=Qvi!N?.S-N_w/Ef v˷l7]&RJ(P' G͜4["A xPBNu5rF6BN>ja 3ާz޽FNr9TQ(1{>CiG!j2yƮ!U",TmfDy!}[.'W 3H~ޭf&؂v7J?kٯ^/kL5 vv(eAa?2$e~P+ tlRvU".x~UR1ohJ0Zdk)hv{[Hs\@lOEv BØKˬxeFrmYr0Pvӳ% FO.sx2\)Q|UO%-P b\Z[s%ۧBK3k`lBfUQ&lݡ@Z u;9AGpē(gqa*[\mZ!i]6=Z9ij}_fnpSw~V.mlx.#_uk@^E}l C{D# -}햇vu&gPkGmcJ2*7޿%/4 {1u eɻt++?dxomg$Z (0'}5EyG^6)L\=eX+S9$U9`6g!\B vM}~6&L&@_X!E" ^~(`" _9:&?_s2ޜqJjGPHvEiU Ӄm,2 TH]Z݆*0^ƼhV%Z|9#WOXv_8_Q2p?+ ~dY=O|7/6Gҭea,_^BQF So P[  /Z(y kMi鸦!Du&7mG8Vt5%j#e; @?jV ]JٞVZIXJ7/ݔ2UJXW(LT}/i2p_/M5A&dNdkCTn8}14iI Zv-<_ O[4u&[?L⟡܏\16jX-j "2cUheyJua "3ۢC+8g`QQ0}bt mR$sH /f 97(١g?;|[W҆K21{H؁"Dbw5\a<v$PA < AkX_S6u$CN"_Dxõ7vpX9$r-P az׶d%ş`DvЗauGο햸lG}0d_{-z[q6 ej6Dϋ5yO-g |}p^G$m5Oc -cǦA# %Zo$ՏFa vBJo`Okj-⇢2YZƄkh9&ͮL.y'TCWJHĠ~:Zy:!9 U*pJ1H'} {ŧH<Ԁ0,XUCk\3,͇`~$ a*հ<}[D֡ƽs`^pZQ΄Eݒ<\i\1)(] :0W{z-yÌeg) S[\ֹ("̞ )]pso2fh[`]mW5gqI W疩zx?חEjOOe}iXHDY_= ،gqǔQ]a'XD!q1Bn]'P¨>;mۦ=5_!I5 `>cV` e(NaQ^y'~"aq!+i9H ;9,ڲ1\lO瀮QӰ忑g_RV~{kbtZQIR ;Q)^`6aBmpyA7w}"D^+ "W^; 4NZTHNןb~lH9`qcK-px|G&d [LxKsYamaf[O1.P-vSjv$SM?w) "HQҘ`nV,mKY g-Wj!| tYݼPWf=X~T:SK4.bm%|O$w~vO?l#B3cWunIR2*+g)Xm "۠.o ѕc6ͧ9cAs.*Q8JXF0h]<@Op$n`耯%|P_ٟN?HUM)d t*GA,2]d]K)_i9$ RlCc/7ưb4QOu! UIDFfK) XHY D!d= FPZgߔg6#K2H~Yit\MF׿`z G^VYRMWQ+u!Mvt"oB Veɑ"@W9S"f-i) J*~(BMuhPp~5$aT~Adckڲl:WcZ3 " ? 4[d,k $-H_6tsO_lPOd0*ģgq_cقu>q:?r`]{uݞ.uG;t߮_rP.$1C'װ|GVLKK2(e Zr!QUޙe8), 8ɜNTBMpQ/TCo< Kݼ,d@VS"gMZIelKj;,J\1Y9R;ɰc>03*X{} @gAΨIcdO%7Ri~y ~&`:R&oU z?fc>P aJI :eL^TU?$ra^KiIr i*Cm}`6X/=3,: C<Җ#n~,w=MURFOw4y~V .3t&q[9]tx#87>۔e0vY՘o':;*0U)4G,hN;oG;R$M(Vcm>T^ދr&K9 ʾErdFHY]XN'ܣ ͦN/4+ j: Ct՞9ރ̏T fUut& ;H' ڢtV]ͪYn; |Ѹ5娳˳YgfK:))^&a٧[[T XTJd|]C)OmfQtd4Bhnf]+v YmM?OE@x^:!)Ȥ]+ͮJꞏh@{,2-ุ,[VOaFE*yeF[w,b&L`\%eRW\;U vR]KX.0kĊ?bq~#"`VԯfH՝#piE i˖yh eE30UK7ϚuD[p}*\ÎntgUک{yx9:SI˝: )Cb@khWd)rE QQP"LQ]"M@HBh;6=292Ym5˧jSMtx? qCʩd3EcPeٸfd0P/yvs?S*Ȉ{f{l&{D 2SQ #|m0U˪.W$>;3 > 2 'g5Xr?2&s8'^s6[֥Q23h_Wӧ%6e…w>(ȝ.J tz\Ϊ+<nLan/+ yC]b+~7x®n|^-|6©febv#6:' - ^cOܕK,lg斕9sG߰GYJMY*+vt `nG AVͯK4[ |qZ YPNr sqfVg30ipjZm8iyQxGN@ǃ%ؼ"#*ήl*c3o{S#VV Jڦ;ٷ5[l@p/&E͡-TtuZaPPvVr,<kBzz;3Bڅ,|N6MS^ϷJyTz} }\2 7TR4b+A\6!?U';(q]1Yhfs 1d[hLV欯m+uVË40(0+dNK6.jDPV!*xk㱫ʶh.11]N<[{]ƒ%Lx* [~z|4BP ns5(_G 8UɨECnih+z׽Y8`M?Kȣ͌zd)PVv4Y{_ֶ(jHg1R >gؙ 6ėfdVJ]9Kc=R"n6gp=8!qc) JdC2`= *[|FQ݆mZȏ@M8RͲ&p9npBOё7* )c2 ];ؚl3䨺CSl:iуĺR#M;|W0`p3Z \,\Y]M9nto@l_ BJT4-DX9tƿW ?jrQhgo(Rz\fW8}f7Xj=Bq랜Ѿ\@d:}1mgr:|[ `.}]z#:Us`x'8ֲ?nrge.;5=U?cwQ=΅0ZԮE0^8j0vư3T{ĒBO2ym,_+ZS W<:L#{B8 Cɵ8HZ7`hMxm.(6ah}(T//Hh#WCRD8ϖ2x7`))TenmrM=İm`0٫%K pz.E:n [RKq'g)%vYP ,*EC5VH!9i|7H4=]ݾbV ?g2Tc=!݅m2BQ@ݰpaqq$Yk8a_ype0GCi 7FY 9h׳`zkZ>t+c([ ?q"K7Jji9KbQqvPgapvA`YXa 김ϰjE H!4\/a1#ݔ%-ZƤhJeAli&y}5`MzE'?A@SIqW~hf=]4Ld-SZB?ܚU"v"Q CÆk$1xQǠp|ֆY#hb8/&Eryfc$4&fiq*`ՐГ3لgmqER:3tteUo)0FɂUjQ@ܑHU`U Mԭl)'4?Z,yBo$B_x6+(Ʃ1HMZFGu 7#*"[5[А*ηbϣ _p5 ǹ=ǂ4w΀Vg\E3I̸R2ߝzMXs6k( q~Jۢ|"43@S}o'G#T΅Uw {l2%m-yNc>$o=}f7zPJAФ_Qn󦱑VT3}>]c\?p(ВĤ Y.Tokҝl)Bq4?CZRMД]sQXQťObй8ZEv-BF%X>Szȍ|ZTUUn*wlWn{-[%P+`q7Zo1lrm zzjj&xI]&0i t݌AH̟ *M;8[H 1\"Ս.nƵl,KA.R6#T_k"|e;1;;7T!lݯNnp+qcV.x z~Ymo:hkxIX晤[H#e@B,;T;CM*pΗd_Ա8/=Tq.mw7j#ؿ <_+oWtk*<4^50Zѧ=UD miX=ĤjGw1۴oJ#@7"wͿtޮ_Dl-w8@fqr@9Yff-N3sAJ5$w7 lU>"5Nk/lq D8p5M Scy.'ԓr5S#Dd% KYĉ zsDYyās8w-\Ի1n (vjŅ<46"%_$ղH!ݚ9)g*=.d#:?+RΨj5{{!—\t[#xR9^A{fr>̧f'`J9W|&o{xFz99z}Onb-IĩDkX2!o}ׂUF<!wOf`.wFrhtx֧(= O%$?AWT.Ju*TEsxF5wbZ,[dkl7W{֜-q=X ΌOPn|bH+װ_B[f\2 1RA`N:iYҫb!RZsH^nbcrae|67hYdI9vن3{_YBSZ0nK6ww'm^Ӽ)}ii.BTtͣ$Qv#+F:g`_(gD؛^<m޷o߾D_r9{4ɐ+[˭޲bx~h|o&X=ٵ(.GHH}Z1璙\g$4fu2xh]1,s~ÜdCA)q0F`1\|sc5Nrhyc.kJ`{eAE:h߭3j>-.bݹDU՗/nz3]8hؽR 4yT  S_Flùf gSGV̱~yba6tR wеt^wLYZY|J]6&,(U5>;$$dK'E.vl޹p}v[yL9TBmj}>>˗2A HJЎldas"  ;bjt] l=Itjo>}iKNW1$&T?{Ԛ)K޽h;/Y L VDtQ1Gz5I#;+}Z+M;>{R/ӏRtzoS;;J5<< QR&ҧmU% N,u#*`RĦ ϵwez]ˣT1o'}XFU-K{ B5t},9Gfqȶ~,Rշ;-ٰڻ{Rut؜igO @_oCKns;`,2S+/٧ќt&!#Ȁ15jVyQt>z bƃNH":nLɛZ|Ɗ X'4~Nw7 tPyeDD.;},J8 P63d)GɈ+4.E!Jha ]QK!_7BK8,{gYª E<J1@:n3ώ<:FIq9m9And cV\b{D6M/gjV?멓N7D^;JHy)8\X{WDƊA|Z6-JsuȾf{HSE8GL!s^P_)>M]ʋ1ِ8cZXBMɾ$SШ.Xq}BQYy3u U'=WJ#6]7.ѻŻ4[hnϻ90- Z埳Q;Lt`41 F1KSMJr[aԤ5E8>bRiIT@ZO9=9]Ǖ\_ cj*Risܪ'aDz9җR <[`"w`9 G8 u2?FxC#fu^'+Fc 811@I`m^M.Bm[3ڂĂ\t(eX%J"?_\II$ze ¬On;1!h~䴉jIV~dޑ͹LuԺU" ,ؿ̝xȵĸɦ.44 \$?R!6A %{F>ͪ!㶨H RXzC@+F`t)9,[Yɪ[pɩ .+*g?snJQظwo[\oƃ3q䀘wHq9rRmӭ3Ux,~gyUeƷ߬>Z7$tˁh-t+G?kQrh2Q!f3NxLZEʰP.ŏAr%0=JJao0ᤁrE+`A/U{?Ю1OjFIhcsjЂx 2\d=|v$$T],b\nspY9l (w\7Ni> 6@PPFk&Z30VB:28oK+S cĿWŴ8^HhӐVf&I$\&*RI=\aE*X=e9eQ$~م3 z GDZ[kIH2@FlԯSX0JTS#n7$|QY#liJ@u{r-,Ĺpt_6%)<%7dARPeHR K.bɹE=W3%]_ҼWCԲ9Qs+Hj8 {0H~>4nJ˪}Nح/ۯ"`#9n%_K?r&2؄?Ǒ9ϴԈ1]M,%t9([b& ON #{p"z=Jx83|1ҊO*efw͈#grG9nk8uDv^8KY# O \"4&2ě@̳}}Ӭ`hs^r7d7P-\͌H-yA#!#ZЧєr~-q)i9bKS֠jMF1#LKH3?³:K.0|][NEy6j˜ඖYGPqyOwBg?AÕ41`jgQ q·ƦC 4ְWU UTx_5QLeJ[ϩ973ν| ҉ɿ<;(E±ܰ죢s,D.|ڻiV +?Ȩc~ Xaf}5,(tPyO͛F 7H̻]K}\|VV_nCֈf%0mV)S9O,qr2S19Z[6Po\&FI ^G?;Qf ӅaX+vN&zI'Gvo[n"e Q흤<#lEMb:IwN^"6sD?m9) kHx=\9Mkă܅dF=- EDlUϿE=JL~F@Pq8z rry_&pC`A>ATϔ Qr05q h& U90O9쩦 %Mg,Sg+cږ;?; I-1lpԨK.61o;BX>牜~X%舖.J`w5ԴQ8N(,}Ф^N6~ծ Y=Q&[DT]G=Y^B&i%!yM,u7UI&϶d}&}#^Wc\R{)Nvd7ϱ?1rfj*Tfn׵=5;\hLeš Dᆮ3!{Wxu_`5(+sQqщ_;›5a_%>;Z.&pR;If J, NI/ix X)ǤxZVsxZ= L T`a\]E0.$3}jCY/腝+]˱u'P*uXM:Ѭӻ\hO6Qswūxw5DG Cyϐ 4ɝxnKq}04ĢC(94PRIsVi#-Gb`DBjvD &t6wZWW18|%!cθ'H!o!EjuЕLv,cspm[R)Q66s |kdOSR/R۟O?w?t `հ< yڧ}4F*-"溢;.4N|y Ig$Vhvc/ޒ*_<\%WǦgfc:R1YĩA'VCVƣYKl|':E7$gWITP@TxL;!M*^?s|mEdNF&?ejFq8恓cDCx-O'br$4J_gcˎ ӹzI-ic޵vCj5;3h+s xSggC_t}|>]R<{=jGfgւpܥfSqtY AS[i5VݫnqnE BVs%쀿JFĹVz!2_/+-g9E8j t)c+.I8m'nIvCHQ)B]dGl U A(t2̙]Y-̖$ wrF1`1J◊)Ľl(hfS2`+()y,X+xE@[fqAd~,/ЫFo"0zZ.w$SԼ;C~]bXM,󅆺-G?C[ 7 %OrdOq3s£}zɫ=I"AЦ~,{e)+;*hm%>2e3wxfl4fTF -}k̉ᲲwDOkg%]rRxti9Yz]S9pVmz~-g G˄z)()\oh2fd=C QrFvnXHs~*~!pg $m:MQN"_4HA"<j^rGs{K^~!Xe Օ=R;69H><2,ߟ12}-7S%X'QdFĴC2M!uiGdtȘݪ\bz}H@Qq5}6F:H1VawƓgևb\L%fM$u6&f\#r֘/S:y:=i!rbݐ̗9.Տ4Yre$u \[ *B1Z5̥~)40-:֨}ekdmDz,~͙=h#xpOrX.0~HƦw:<}9*M߻|ÕBo {1 `Titė%+,Ggmz!.$N-M<7RmPM&xƠDZ@ HRiwe@ukdцm"kiV'ӹO2D_kjØ^yt˃D|H#&KIX Z =Jߒ@S5V0k sAO_P,&M qٿKn݈pD&<l`ĵ:жX,Fp6_1 x; ?$54EnE Mpi 9ifjtm9o׋@Bf Cջ\x2-x>ulEc\/5c /:d2w&=roR>Hml=[YHӊ ydhenwe q4Sqd/'ՙW+Q6SD#\i ;<'k"|4 s u~hcRޤ ѠD{jyY/{F,AC ٲ >OMue|J62xX73?0ߠyxʇBNT! S" Ǭ(-VӘ" kK³s$Sm>OS|@9pLdY (h9,} ǵE %T7{vKQ<~DsƼ-D(jk 8P^#3^\z:_4 Ƥz@WJ? i F 0m&mx;`_ԎFV] kP!*qEhD1cizvZi`=&g Jw@ZI̧Mx t%ܠ 7# 6]bToH˕KA^FT=†ǚ|޾1_U,`yiUNuk?{gp }D=z9Kgsg_9'Y:55weAb8#GNꡇٜ0ASC;bSE^vlNE(V7=P;3t' E,On>*2Kc2ts=ԑzlpSdMG]o:CkPɟTPT XL@qT7q).Ud>TxɄkbd;[KXUͬr ^ yoo5f,=Ԭ+sƠˢ,H3zXr˺ыkpiwd)*V  z-$0+u Ce~KZU5la2KpIyI!eJקo2ueXn*ou-k6FYәH%^M!Gte՟W RcV<ś~wn2 6K5|7/ eWQIʀs5qM*1 WM\'h\|#WHdt6&BJ[xUO}ʝw% $fR5u7Nuuʃq-9ૈ{t(Vd[RiI5Aذ'GK! P&8a,u1;T`d鍟ݐ7"_ViyL0>OD@Fdw]f|` Hg9Qe{XB07,J)EleYHpw `5zQu+6Bu:o/Pp/~+KP)xAr9aaeAm5X!V8!‹ Q5Q^5PXdl;:gu(@7od٘Ӥ \zΟ3?,L(as"-TlD%0Bʂ?Ow{SY6* y:IЏ?[N(]G26;"@%I*' m*.s?{Hq2iL ՈKp*O-mTzBX' UuLp̉.@Fl` b3X %]z L\C=5/?~K8Hhb9d}p+s(&1.qmG!w‘0'&J;2-ijk:\h* > n0ڻ+3p "!BU GqP笺 '0re : 0ý{.iնAfRcL^fG6ɝwT[p[30˕+ǓFUCM'__<_`ØL/H@>6r]lavo|Y9L5Z{S51*M甸Y- :?\AEz!GC.v{XE?^ ׎T/1p"0KQ8鵾F{VZ؇ oIJd)55H먗4]7ap6ҿ[C|jLdRѷ/$#q#Ё4wN#)cѝdVCh|-UcI,% ȅpZw?V]?xf*2ki"aRR YG*dHiFa=ҍʨطr,swI:/m{ڢMX飽Eg'~CYp}F `bTS^ӹC0:andEpo+2BPj ; `9FvJkߥr(0Ce1~zԣ[L El\ZOrDph3/чBR6 H KË С0ˏhC`R.uV0jv͹>+=:? $4{pMjT6I8uz(+27{[D!E뤗j8L٘`q˃<:9oq |Px n|ZMd ų_煩AFVcVSzK%`.Qv5<:Y.}-yB/5qnyD)a :/gklu뷮¹Ll.ϪMh X( {}AD<w˾3Q^&>Hf=omoǮO_d˲{BxcSNϡY ݧމKXFISו_Y֎NG"~D 5'+7w"nMr'q'!_ta4cdxh;V8 ̢jo5\I=S!Ih 2lxqLƼdӮXe˽A W<*k:e6525lky y; ȔFƈ% t1qG[[lH8߶ףI4lEhLģ /uVV19̡uN6t&e J~42fU!L'ĒqEqv}7puDJҽ&{{\+T57bCjuY#>нm#π2111F^?hh* [75RS |O_,nMn~Yl$uſ6FFB ?in+f*FJi^1*Ql/  5[I]14wl'n0TtX$څye ۼW00rEh93#T 9ǀR观뢘 5Re8^磻Wr=FMw\"D^r"h5!twP} lOp:^l[E-i:<*ZCWWN:h@h]1?ZjY+z.С+B2SLlefm,nUC߀2)c-]n Bw/ςpϥ:/AsZj_BvGb 5nHj!im~*sŧ[|E'C@7bT3doԌ˦ܴ[8q h&DN9+Bhh$q}o BPeq>2oJ]m+7,[ح9׼ WՒ6b#j(E^ouS鶇-CXO(@x*֐E[37kzB`SCv=rx,࠽c%%2 lU1z$P-rͽLnwAep@xVz *DYHۚDKByzzk }%' GrM&rrroW +! l 7g˹UJa>2_]Qfo^ Z.Ag16OG dx oXGQ?X}oME#BUk*c'OisK)׌&Ʀ2fɸm&ޏ 򭉽Ud/3vV:UE a0{WZp}Q總bS@lIhepKicGUnqkkrL?AL< q;->8F0t[)%XG_gi;\S/MM 43>/n'ߜ@}>L~fi9č'I= v<ů+ Nor湔O6>W(L2SZq͜Sv S"Y9A0%If&>H>5 %db@GO^ xSt)睈WF͑1>Opvarc*g޽F6J9qo'kA2+~7~W˕y盅dgi>@)aϵnB 9k2QY| Q` ^u'֥kNNu;"6n9|*>sg{ kd]i Ù @ ?"F{=i8{T҇$\9zntAf/p5 g[9 N&<ylWdyO=+8`VI/ w]IvAkDt"7I2T@j"艭WMKj,Ly6!͒/WMbA%;fFDxtDoOtH] L4q6pVIf&oa-߶{buOcaUk#5>jwgo=WMV )/ũ>}єR47׆G,rWzrk!"7]Pm,Mlҝ џD؍,B(*yd~F+}cDD{zTIQP*rzc蒚K$,#sc1bpi5Er\ >\YּZI 8R7#"@0&"35+$A-RQ* 7|=m;8<>V Ƣ"@:d.ρj% p 6%rEf)뱑lXeA<<_#|p?56"$k#yDշ1n{1 8p6][N@Hl[Jv;JaE7^BSBk zvu:Y'E W _ѫ ۘ'm9#=(! I$%m+Yʒ""j]9vGERɕB _všFsps 5HS_b.m/ .}y aLҕA.Id%lO/%Usx*5%Tm*Qg#rfw7-Pj@.ZH'5G7^2RӺ"bN!PQ/f\h._FO.:EȘ^% ӟL76-_p &_QnWGd\ -_(["ҙ?~*G'V;}AG" :ƙ2qxSt#wb Kb~59M!ۂȉ[e…2OͲ9B ճ;|W[U0# ΧVg:JnF,uq_o^ _T. v\<|{mHkc/B:2 坽5@H~ofAjohuV዆f^wʚ90`ԡdD泗RT U3zF'Id$l4zG ˔>3e06yJ![fvq4P #\\2Hc $) /mUI2} O}Tgu"]c5#Vi!  Aob 5ok+(.Ċr n ռ=5V9u {E JC/e !o.KQqm4{(K?]☥uEFPPZ2\0;But@fԮfbf'Xzn<+wC5^:N=ĕno #tG 9; k1(yUFVm6A<`͜([shѳFk=L\߀^x?GCv'_x0X:~lU%Eotz:Mv1)IQpv3.]l2! "T߶{Xk^#1ݏ(dԅ]6 1'%2>⨤ڃh`?UE> V[WfQ IaN<6=7c v_]FkiGw` xe]2{`EVd5YFTb^݌ \$+ǥC.׍[w*HB%ɠ_: `g"єڶI?t4S_ɰ=)29_+'4%do`>za0^ vLd9* QU;H^Z Na*&Q5*@Kbc9{mV-6=> Ng6ϖFZG6&9[|Wfsj/"]bP݋#(t*bB?nO{޴rxZMq] V!TrXb&-P.嫕#ie1=Rr/[;,,܇mi1݀Q$(P$IZ#fR=;gÅ;S)1%y;O{Oi\a1 XJRzbJ:HaM]b8#F%P Hƛ$,OU"4B1g G&%\xtӫz: =|)#31Ya7?﹬5B,! BtZFx.hud\#bgN`k\h T[Ս[nٳ7߹.]aAZ'kNt "זB_o[B-*5GMM.k{EF1|9iW{ԧW(EW74njUdhץ<2!]:Q[W+tIZUu'UUVe>TDA#/!ۻq!zEN?h8"uʷp֊.CY Ⱦ o͍noTsc '\j@6lS>&<ᛛaص(gKygxli^qI&O5T$ʬattꏢ5$z;?ndASiKǑUF"Tp{c%=({S.]gMMd'ʥ=*e.he=P1"LW H )4!3s4d&HK޽J/@$}N]~-IQ=1q$cxFdf !FO|P:kR}3.VvE/O)3Z6>@ 8C| cj.*6X{sJC k S3L˵ ^;N4HUv ++dߗNMyf|>rev2tBѶfTrhƒΧEN~._8o_lތ嵘)AOX )O E*es<)'k<[.To= CpkGc^fJpp|7YI~K燂5~*DL4NƘrUuaHY |Rw9 NȡdS(%/b^T<@_O[i&N̬hr{i](U[DBHQ*l\O&{v궗 xJıChATfƒ~)1fSݢ/eC39xvyWa,ȕS<.SsxR[D,drW|hbVh ~8\0KXwjRuءQCR~X|FrgfhxpLA_GPͣ9OW৳m-/EKmF!]%+n;/|$Trm: CVK2x赞dHI-(M^ˤvjT磆Ӂ5ʨAҞu9a{O3}M$)&AyqjȽ;G̯}/Ns1̳!cQRNgif8iS}2).LjhQB|aLYrTS6"卭 µ\r$z:.DbPd578D|0n y _H:5f8hL <6LP̈́ԏNlᨑ(yKFQcxTQ'=jE7>{~n ]I{/4G)Zwh)"{FdIUoxk5-$i\RܲXwfk uؤ/s0YzJ]Src>|'=!Զcnkd'eޅ$^yrO+Uk(zg8lZ;A3Vĥ iϤm*Vv珌0S\ٖED7Ȣr7}bhڅ$Yo>^/m؟,ۉVnpSmp-*\Y$!-Kn[b5PZ­Ҥd*ӱW/ЎZ,*>55y{L3j?HmamZѡiԋ뭾4huwY0~[O;{IY;7%8i׫m},Lv8X+xzE4i˃ܻ4;jlyBdiiqvz$ңgVTFށN2#H\Cfob:G#]ɹw];ܜG}H:'sBN)quvf2Ewl/yJ"S'aT_PTA)M2F9SXWqcfAKƈnP .s/%&{&{ ңN|r/)C ' 2\anpʏU'ZԽk8L#{ R p" n|yXudF7"8wgG̕^|_F_/uD3..2s~E.*MYXԗ35MgΝ`]CY"R"Nk1k.W}ž xIHQ^ NyExYcgVīVʨ!Oׇr󡾇`CzS<_OőkP.NRKAK)TNm/k`fHǦ98^8 SC'psO*8xN>E3 [9ÝqZKQz+}B' z-),6\J}`^Lr+#fq[V&.t%[%j_%(1n!abgM+2Bi:<+ /uRl З$H%M~V6ӼLMPwB;P.ldz21euAۉ^ACntaQqk_B<ll`!l%BnnDxGLSG3;8 W[8 znzxDh&;[ڦ±#'/bkmj.c &k8ZDzMqХYY,*Vh~sK]RXƟ[؉*EqPuH/p$gHR~'K!n(&ofQiс#8~nUVMβ|Jڬ>,vpJ<zl=m ڎf-ەSf|S)x5*6)Ƹ޳sĶK/XQ'{偙dЖa$fBV䑷-b~ؖ ͎A7S:5ᒑo8Ρ-+wk P5K F?Ӏ&F9_c<ūY0RL~1b)Q*p0pi. r(G:Ȟ}zǴIL3F}}1Jׂkq*B]f6WSXWNnmϣ #o<ö=<1d/oO~_9k˲vWk )6gS3UK?ƛz&`;wVM#wkһʞej㑿Zx6M(\9%,g9K;UșB`qkQkգeXvfx*OZq@2}n#b6Y˪4^b11ŨY7OYm9ڑ(ݫ>￞{!߰*4 N5wS1cEz]!9ZgO0u]f""fZ0bu>U}KsHʎbޑ$EaN鮟Wߧ)D㪬YXx-"a`h od 6Wg3! Ц(sNeGêj>>tU%-){cT%h2?„:X0JCt{at=骏k~~*Oe}p8 k3*U]$+H-Et S |sSVIn 5YwCAb%U.(nyKdJX*3bĸߤw5o$XVkca#t ''xxGgUB-G6eE7`X.@q<Ҽ~ZRRmy,&KbbefVjŒ'Ҥ(\F1|SqhTΤ!vHq#wb@Y./"j*m,[׼4ɩ/Z\$RŁ#{dLIjPس#Zh(<(^'\\CCbpltFB԰nܿ#,q`y?Fe5 㪔è^$B,7`ZaX8Xu]-H #i8җD:ww2Bϋ(:$A,R ű ^tڒseevcIcWs2:l>T,Bζ51}D bDvȄleMy>&O*ʔj% T0\!J4i4 : 2ĒIS𳛂qX Ӊ? חݘ XtH Rz]Dr'%+.3kt=+%[B@%.ۊZpuro{+6hebxrIU0\aW6{t^hו֣r \%x)˪!>M9_w&RW5#5m0xjVvSt*㨵pc鐑S-c!.%NpIP"4O6ĂUS7g}vJt8!=/(5 ڤg: y4ͦoWRMY dbk9}6A){n*TUMa@SnRH4'w&LZRД^21I\6 xr҈v`'"dLFs՞|,XpHȿRi}@ :RNHwڋiJWuڍ c -w&㲩)@/iP|Uj́0-}i_Ag L]ok cM7\;\sJ 7;G\_he3GO٦;9ؘ0jxDZc184 @ "g,#lSf=$0GEm ffߛޝ7Gs+5Y w8;3F@QСjz1\գ>'ќbR]6fࠐ`^lʪ( ]FۍF~kh;঩Q3 Gql%{/tC".谮(Gc5-~ Hd.fuj"_^/N.ᒺ(ښ'/mG;lW8 1VHXd#x/f"<6LU(`24$8|g3>l|E \9d(񎜟Ԯ{WA? tINߧOȶ WԌIr:C̵kixrHմXx^OXa}0"&r.L5C0~9fHpH?St8ly9\Jh뀸CI^sX22'hBz+lj*swQ'}`#IjH'k6.S1 ]̭t.AlDbpNɔNŽnL4(t' n0RCN˛c&0Y(puΉ( n4|/ T)&`7 v5 yYL;פXمdD8&5Q!fWPw4r]&sMɽ8-Yv9u&…t|)Cy2iIy Xj52%tڍtp:M4խ.$sЅnv;1JV̺ e lŪIitM"郬d>a$OFڠH׹b7ŚEDB2ҝ0FOa\ 2>QAJ;8xPґY)=By.yF?xۓd2v:)B͹fd"cv6s3NoS[b' N~w~Eܞ67>F ٧LIs\31 F#)CK/RQY`.n_gd;pn nN܎3^ZqYf.D^O%ވZ&9nlQhrЙy4#EROJ Ϣ?ژXcek<5$(F[ rYUZ ~D<{Vp1 *O W7?F ~ TR]T)' Qie wRiZǴJM[g9mn8.!kVι} F&x V܃:y*Nةzdض 0chiP)PcSU IM-ɠ߷N3,, ڑE4y`-5;x-}=F2=5԰KѪ`sVz_{1a0@iͪ娇W3,^GG4Lhe?IoƇqsZiDZ6((8R_ni^hS"7J{ЭdY7I![v *:H\iz-y "}ǒ'jnU̯Tڂ蒗@XyZCƑB6pߎ]>ؠUC*`uɣNk8ܷ Z&fqsꫩy|Y2t/acK._^-?0 X%+FG_p`WE?;zn"D·~ dUZQmb,Ay쪴aL'ag `'Z8 9 \Dvk26E籠XZv촴E%אbCL 3an~dؔӱN_[ܲj?hÁr(ahsӿ+1˷S,~.'Jk4yݤ7][‚{x^K}ҹ e3|7m@ \/$(j,"2fvmhn͟{k" L~>R> ta$GVS`Bn'`0G_ endstream endobj 118 0 obj 110085 endobj 119 0 obj <> endobj 120 0 obj <> stream x]n8ཟBvQXO HYi@#WGt>R4uwϷ?oytnW/^}cZNy:Շo|v/yUjNi%]O| _sՖ㆔_cs^mzWmasM]ǧôڶcsS1疹EYY٘ w#rbNsmܳGn@?@?@?@?~_~_~_~_~_~_~_~_W~_W~_W~_W~_W~_W~_W~_W~_ᷚs~7~7~7~R~7~7~7~9w~w~w~w~w~w~w~tF8#Hg3ٶ l+ڲr Y,h6;сDt8. Pi|Fv +KdDTguNm-^F ̸>-AāNą,ua`ʼnALt&8eM<#art˄F{ǁN tޮLvqpvvΙK2=n=azf1OOg$@;<) bwW<}ynS~y.XG) 3,ud@ژ4͛rPvc1Kzp endstream endobj 121 0 obj <> endobj 122 0 obj << /F1 98 0 R /F2 108 0 R /F3 111 0 R /F4 103 0 R /F5 121 0 R /F6 116 0 R /F7 88 0 R /F8 93 0 R >> endobj 123 0 obj <> endobj 1 0 obj <>/Contents 2 0 R>> endobj 4 0 obj <>/Contents 5 0 R>> endobj 7 0 obj <>/Contents 8 0 R>> endobj 10 0 obj <>/Contents 11 0 R>> endobj 13 0 obj <>/Contents 14 0 R>> endobj 16 0 obj <>/Contents 17 0 R>> endobj 19 0 obj <>/Contents 20 0 R>> endobj 22 0 obj <>/Contents 23 0 R>> endobj 25 0 obj <>/Contents 26 0 R>> endobj 28 0 obj <>/Contents 29 0 R>> endobj 31 0 obj <>/Contents 32 0 R>> endobj 34 0 obj <>/Contents 35 0 R>> endobj 37 0 obj <>/Contents 38 0 R>> endobj 40 0 obj <>/Contents 41 0 R>> endobj 43 0 obj <>/Contents 44 0 R>> endobj 46 0 obj <>/Contents 47 0 R>> endobj 49 0 obj <>/Contents 50 0 R>> endobj 52 0 obj <>/Contents 53 0 R>> endobj 55 0 obj <>/Contents 56 0 R>> endobj 58 0 obj <>/Contents 59 0 R>> endobj 61 0 obj <>/Contents 62 0 R>> endobj 64 0 obj <>/Contents 65 0 R>> endobj 67 0 obj <>/Contents 68 0 R>> endobj 70 0 obj <>/Contents 71 0 R>> endobj 73 0 obj <>/Contents 74 0 R>> endobj 76 0 obj <>/Contents 77 0 R>> endobj 79 0 obj <>/Contents 80 0 R>> endobj 124 0 obj <> endobj 125 0 obj < /Dest[1 0 R/XYZ 56.7 773.3 0]/Parent 124 0 R>> endobj 126 0 obj < /Dest[1 0 R/XYZ 56.7 673.3 0]/Parent 125 0 R/Next 127 0 R>> endobj 127 0 obj < /Dest[1 0 R/XYZ 56.7 273.6 0]/Parent 125 0 R/Prev 126 0 R/Next 128 0 R>> endobj 128 0 obj < /Dest[7 0 R/XYZ 56.7 258.4 0]/Parent 125 0 R/Prev 127 0 R/Next 132 0 R>> endobj 129 0 obj < /Dest[10 0 R/XYZ 56.7 785.3 0]/Parent 128 0 R/Next 130 0 R>> endobj 130 0 obj < /Dest[10 0 R/XYZ 56.7 332.2 0]/Parent 128 0 R/Prev 129 0 R/Next 131 0 R>> endobj 131 0 obj < /Dest[13 0 R/XYZ 56.7 465.7 0]/Parent 128 0 R/Prev 130 0 R>> endobj 132 0 obj < /Dest[16 0 R/XYZ 56.7 481.8 0]/Parent 125 0 R/Prev 128 0 R/Next 133 0 R>> endobj 133 0 obj < /Dest[19 0 R/XYZ 56.7 448.3 0]/Parent 125 0 R/Prev 132 0 R/Next 137 0 R>> endobj 134 0 obj < /Dest[19 0 R/XYZ 56.7 391.8 0]/Parent 133 0 R/Next 135 0 R>> endobj 135 0 obj < /Dest[19 0 R/XYZ 56.7 134.5 0]/Parent 133 0 R/Prev 134 0 R/Next 136 0 R>> endobj 136 0 obj < /Dest[22 0 R/XYZ 56.7 581.3 0]/Parent 133 0 R/Prev 135 0 R>> endobj 137 0 obj < /Dest[22 0 R/XYZ 56.7 242.8 0]/Parent 125 0 R/Prev 133 0 R/Next 144 0 R>> endobj 138 0 obj < /Dest[22 0 R/XYZ 56.7 186.2 0]/Parent 137 0 R/Next 139 0 R>> endobj 139 0 obj < /Dest[25 0 R/XYZ 56.7 717.9 0]/Parent 137 0 R/Prev 138 0 R/Next 140 0 R>> endobj 140 0 obj < /Dest[25 0 R/XYZ 56.7 533.5 0]/Parent 137 0 R/Prev 139 0 R/Next 141 0 R>> endobj 141 0 obj < /Dest[25 0 R/XYZ 56.7 412.9 0]/Parent 137 0 R/Prev 140 0 R/Next 142 0 R>> endobj 142 0 obj < /Dest[25 0 R/XYZ 56.7 271.9 0]/Parent 137 0 R/Prev 141 0 R/Next 143 0 R>> endobj 143 0 obj < /Dest[25 0 R/XYZ 56.7 238.6 0]/Parent 137 0 R/Prev 142 0 R>> endobj 144 0 obj < /Dest[28 0 R/XYZ 56.7 305.1 0]/Parent 125 0 R/Prev 137 0 R>> endobj 145 0 obj < /Dest[28 0 R/XYZ 56.7 269 0]/Parent 144 0 R/Next 146 0 R>> endobj 146 0 obj < /Dest[31 0 R/XYZ 56.7 373.6 0]/Parent 144 0 R/Prev 145 0 R/Next 147 0 R>> endobj 147 0 obj < /Dest[34 0 R/XYZ 56.7 622.8 0]/Parent 144 0 R/Prev 146 0 R>> endobj 148 0 obj < /Dest[34 0 R/XYZ 56.7 566.4 0]/Parent 147 0 R/Next 149 0 R>> endobj 149 0 obj < /Dest[34 0 R/XYZ 56.7 419.8 0]/Parent 147 0 R/Prev 148 0 R/Next 150 0 R>> endobj 150 0 obj < /Dest[34 0 R/XYZ 56.7 95.1 0]/Parent 147 0 R/Prev 149 0 R/Next 151 0 R>> endobj 151 0 obj < /Dest[37 0 R/XYZ 56.7 636.6 0]/Parent 147 0 R/Prev 150 0 R/Next 152 0 R>> endobj 152 0 obj < /Dest[37 0 R/XYZ 56.7 428.7 0]/Parent 147 0 R/Prev 151 0 R/Next 153 0 R>> endobj 153 0 obj < /Dest[37 0 R/XYZ 56.7 261.7 0]/Parent 147 0 R/Prev 152 0 R/Next 154 0 R>> endobj 154 0 obj < /Dest[40 0 R/XYZ 56.7 785.3 0]/Parent 147 0 R/Prev 153 0 R/Next 155 0 R>> endobj 155 0 obj < /Dest[40 0 R/XYZ 56.7 460.5 0]/Parent 147 0 R/Prev 154 0 R/Next 156 0 R>> endobj 156 0 obj < /Dest[40 0 R/XYZ 56.7 197.2 0]/Parent 147 0 R/Prev 155 0 R/Next 157 0 R>> endobj 157 0 obj < /Dest[40 0 R/XYZ 56.7 97 0]/Parent 147 0 R/Prev 156 0 R/Next 158 0 R>> endobj 158 0 obj < /Dest[43 0 R/XYZ 56.7 686 0]/Parent 147 0 R/Prev 157 0 R/Next 159 0 R>> endobj 159 0 obj < /Dest[43 0 R/XYZ 56.7 597.3 0]/Parent 147 0 R/Prev 158 0 R/Next 160 0 R>> endobj 160 0 obj < /Dest[43 0 R/XYZ 56.7 508.7 0]/Parent 147 0 R/Prev 159 0 R/Next 161 0 R>> endobj 161 0 obj < /Dest[43 0 R/XYZ 56.7 420 0]/Parent 147 0 R/Prev 160 0 R/Next 162 0 R>> endobj 162 0 obj < /Dest[43 0 R/XYZ 56.7 331.4 0]/Parent 147 0 R/Prev 161 0 R/Next 163 0 R>> endobj 163 0 obj < /Dest[43 0 R/XYZ 56.7 196.3 0]/Parent 147 0 R/Prev 162 0 R/Next 164 0 R>> endobj 164 0 obj < /Dest[46 0 R/XYZ 56.7 732.5 0]/Parent 147 0 R/Prev 163 0 R/Next 165 0 R>> endobj 165 0 obj < /Dest[46 0 R/XYZ 56.7 583 0]/Parent 147 0 R/Prev 164 0 R/Next 166 0 R>> endobj 166 0 obj < /Dest[46 0 R/XYZ 56.7 441.9 0]/Parent 147 0 R/Prev 165 0 R/Next 167 0 R>> endobj 167 0 obj < /Dest[46 0 R/XYZ 56.7 298.4 0]/Parent 147 0 R/Prev 166 0 R/Next 168 0 R>> endobj 168 0 obj < /Dest[46 0 R/XYZ 56.7 154.8 0]/Parent 147 0 R/Prev 167 0 R/Next 169 0 R>> endobj 169 0 obj < /Dest[49 0 R/XYZ 56.7 752.8 0]/Parent 147 0 R/Prev 168 0 R/Next 170 0 R>> endobj 170 0 obj < /Dest[49 0 R/XYZ 56.7 606.8 0]/Parent 147 0 R/Prev 169 0 R/Next 171 0 R>> endobj 171 0 obj < /Dest[49 0 R/XYZ 56.7 471.7 0]/Parent 147 0 R/Prev 170 0 R/Next 172 0 R>> endobj 172 0 obj < /Dest[49 0 R/XYZ 56.7 342.6 0]/Parent 147 0 R/Prev 171 0 R/Next 173 0 R>> endobj 173 0 obj < /Dest[49 0 R/XYZ 56.7 213.6 0]/Parent 147 0 R/Prev 172 0 R/Next 174 0 R>> endobj 174 0 obj < /Dest[52 0 R/XYZ 56.7 752.8 0]/Parent 147 0 R/Prev 173 0 R/Next 175 0 R>> endobj 175 0 obj < /Dest[52 0 R/XYZ 56.7 652.7 0]/Parent 147 0 R/Prev 174 0 R/Next 176 0 R>> endobj 176 0 obj < /Dest[52 0 R/XYZ 56.7 598.9 0]/Parent 147 0 R/Prev 175 0 R/Next 177 0 R>> endobj 177 0 obj < /Dest[52 0 R/XYZ 56.7 422.9 0]/Parent 147 0 R/Prev 176 0 R/Next 178 0 R>> endobj 178 0 obj < /Dest[52 0 R/XYZ 56.7 302.3 0]/Parent 147 0 R/Prev 177 0 R/Next 179 0 R>> endobj 179 0 obj < /Dest[52 0 R/XYZ 56.7 167.3 0]/Parent 147 0 R/Prev 178 0 R/Next 180 0 R>> endobj 180 0 obj < /Dest[55 0 R/XYZ 56.7 785.3 0]/Parent 147 0 R/Prev 179 0 R/Next 181 0 R>> endobj 181 0 obj < /Dest[55 0 R/XYZ 56.7 696.6 0]/Parent 147 0 R/Prev 180 0 R/Next 182 0 R>> endobj 182 0 obj < /Dest[55 0 R/XYZ 56.7 608 0]/Parent 147 0 R/Prev 181 0 R/Next 183 0 R>> endobj 183 0 obj < /Dest[55 0 R/XYZ 56.7 504.9 0]/Parent 147 0 R/Prev 182 0 R/Next 184 0 R>> endobj 184 0 obj < /Dest[55 0 R/XYZ 56.7 239.2 0]/Parent 147 0 R/Prev 183 0 R/Next 185 0 R>> endobj 185 0 obj < /Dest[58 0 R/XYZ 56.7 785.3 0]/Parent 147 0 R/Prev 184 0 R/Next 186 0 R>> endobj 186 0 obj < /Dest[58 0 R/XYZ 56.7 597.8 0]/Parent 147 0 R/Prev 185 0 R/Next 187 0 R>> endobj 187 0 obj < /Dest[58 0 R/XYZ 56.7 456.8 0]/Parent 147 0 R/Prev 186 0 R/Next 188 0 R>> endobj 188 0 obj < /Dest[58 0 R/XYZ 56.7 301.2 0]/Parent 147 0 R/Prev 187 0 R/Next 189 0 R>> endobj 189 0 obj < /Dest[58 0 R/XYZ 56.7 113.7 0]/Parent 147 0 R/Prev 188 0 R/Next 190 0 R>> endobj 190 0 obj < /Dest[61 0 R/XYZ 56.7 686 0]/Parent 147 0 R/Prev 189 0 R/Next 191 0 R>> endobj 191 0 obj < /Dest[61 0 R/XYZ 56.7 565.4 0]/Parent 147 0 R/Prev 190 0 R/Next 192 0 R>> endobj 192 0 obj < /Dest[61 0 R/XYZ 56.7 444.8 0]/Parent 147 0 R/Prev 191 0 R/Next 193 0 R>> endobj 193 0 obj < /Dest[61 0 R/XYZ 56.7 132.2 0]/Parent 147 0 R/Prev 192 0 R/Next 194 0 R>> endobj 194 0 obj < /Dest[64 0 R/XYZ 56.7 558.3 0]/Parent 147 0 R/Prev 193 0 R/Next 195 0 R>> endobj 195 0 obj < /Dest[64 0 R/XYZ 56.7 370.8 0]/Parent 147 0 R/Prev 194 0 R/Next 196 0 R>> endobj 196 0 obj < /Dest[64 0 R/XYZ 56.7 113.5 0]/Parent 147 0 R/Prev 195 0 R/Next 197 0 R>> endobj 197 0 obj < /Dest[67 0 R/XYZ 56.7 706.4 0]/Parent 147 0 R/Prev 196 0 R/Next 198 0 R>> endobj 198 0 obj < /Dest[67 0 R/XYZ 56.7 516 0]/Parent 147 0 R/Prev 197 0 R/Next 199 0 R>> endobj 199 0 obj < /Dest[67 0 R/XYZ 56.7 427.4 0]/Parent 147 0 R/Prev 198 0 R/Next 200 0 R>> endobj 200 0 obj < /Dest[67 0 R/XYZ 56.7 353.2 0]/Parent 147 0 R/Prev 199 0 R/Next 201 0 R>> endobj 201 0 obj < /Dest[67 0 R/XYZ 56.7 264.5 0]/Parent 147 0 R/Prev 200 0 R/Next 202 0 R>> endobj 202 0 obj < /Dest[67 0 R/XYZ 56.7 190.3 0]/Parent 147 0 R/Prev 201 0 R/Next 203 0 R>> endobj 203 0 obj < /Dest[70 0 R/XYZ 56.7 785.3 0]/Parent 147 0 R/Prev 202 0 R/Next 204 0 R>> endobj 204 0 obj < /Dest[70 0 R/XYZ 56.7 397.3 0]/Parent 147 0 R/Prev 203 0 R/Next 205 0 R>> endobj 205 0 obj < /Dest[70 0 R/XYZ 56.7 268.2 0]/Parent 147 0 R/Prev 204 0 R/Next 206 0 R>> endobj 206 0 obj < /Dest[73 0 R/XYZ 56.7 732.5 0]/Parent 147 0 R/Prev 205 0 R/Next 207 0 R>> endobj 207 0 obj < /Dest[73 0 R/XYZ 56.7 466.8 0]/Parent 147 0 R/Prev 206 0 R/Next 208 0 R>> endobj 208 0 obj < /Dest[73 0 R/XYZ 56.7 366.7 0]/Parent 147 0 R/Prev 207 0 R/Next 209 0 R>> endobj 209 0 obj < /Dest[73 0 R/XYZ 56.7 217.1 0]/Parent 147 0 R/Prev 208 0 R/Next 210 0 R>> endobj 210 0 obj < /Dest[76 0 R/XYZ 56.7 785.3 0]/Parent 147 0 R/Prev 209 0 R/Next 211 0 R>> endobj 211 0 obj < /Dest[76 0 R/XYZ 56.7 623.8 0]/Parent 147 0 R/Prev 210 0 R/Next 212 0 R>> endobj 212 0 obj < /Dest[76 0 R/XYZ 56.7 474.2 0]/Parent 147 0 R/Prev 211 0 R/Next 213 0 R>> endobj 213 0 obj < /Dest[76 0 R/XYZ 56.7 353.6 0]/Parent 147 0 R/Prev 212 0 R/Next 214 0 R>> endobj 214 0 obj < /Dest[76 0 R/XYZ 56.7 99.3 0]/Parent 147 0 R/Prev 213 0 R/Next 215 0 R>> endobj 215 0 obj < /Dest[79 0 R/XYZ 56.7 401.2 0]/Parent 147 0 R/Prev 214 0 R>> endobj 83 0 obj <> endobj 82 0 obj <> >> endobj 216 0 obj <> endobj 217 0 obj < /Producer /CreationDate(D:20080402001650+02'00')>> endobj xref 0 218 0000000000 65535 f 0000584238 00000 n 0000000019 00000 n 0000004281 00000 n 0000584401 00000 n 0000004302 00000 n 0000007961 00000 n 0000584546 00000 n 0000007982 00000 n 0000012022 00000 n 0000584691 00000 n 0000012043 00000 n 0000016200 00000 n 0000584838 00000 n 0000016222 00000 n 0000019884 00000 n 0000584985 00000 n 0000019906 00000 n 0000024460 00000 n 0000585132 00000 n 0000024482 00000 n 0000028570 00000 n 0000585279 00000 n 0000028592 00000 n 0000031582 00000 n 0000585426 00000 n 0000031604 00000 n 0000033763 00000 n 0000585573 00000 n 0000033785 00000 n 0000038293 00000 n 0000585720 00000 n 0000038315 00000 n 0000044322 00000 n 0000585867 00000 n 0000044344 00000 n 0000047275 00000 n 0000586014 00000 n 0000047297 00000 n 0000049409 00000 n 0000586161 00000 n 0000049431 00000 n 0000051674 00000 n 0000586308 00000 n 0000051696 00000 n 0000054050 00000 n 0000586455 00000 n 0000054072 00000 n 0000056417 00000 n 0000586602 00000 n 0000056439 00000 n 0000058558 00000 n 0000586749 00000 n 0000058580 00000 n 0000061111 00000 n 0000586896 00000 n 0000061133 00000 n 0000063750 00000 n 0000587043 00000 n 0000063772 00000 n 0000065577 00000 n 0000587190 00000 n 0000065599 00000 n 0000067904 00000 n 0000587337 00000 n 0000067926 00000 n 0000070707 00000 n 0000587484 00000 n 0000070729 00000 n 0000073398 00000 n 0000587631 00000 n 0000073420 00000 n 0000076267 00000 n 0000587778 00000 n 0000076289 00000 n 0000078898 00000 n 0000587925 00000 n 0000078920 00000 n 0000081163 00000 n 0000588072 00000 n 0000081185 00000 n 0000083812 00000 n 0000603757 00000 n 0000603475 00000 n 0000083834 00000 n 0000084495 00000 n 0000084516 00000 n 0000084707 00000 n 0000084999 00000 n 0000085160 00000 n 0000091724 00000 n 0000091746 00000 n 0000091940 00000 n 0000092240 00000 n 0000092405 00000 n 0000165475 00000 n 0000165498 00000 n 0000165686 00000 n 0000166631 00000 n 0000167595 00000 n 0000241931 00000 n 0000241955 00000 n 0000242151 00000 n 0000243097 00000 n 0000244068 00000 n 0000357268 00000 n 0000357293 00000 n 0000357486 00000 n 0000358432 00000 n 0000359400 00000 n 0000359488 00000 n 0000359791 00000 n 0000359975 00000 n 0000469588 00000 n 0000469613 00000 n 0000469813 00000 n 0000470759 00000 n 0000471729 00000 n 0000581929 00000 n 0000581954 00000 n 0000582147 00000 n 0000583093 00000 n 0000584065 00000 n 0000584182 00000 n 0000588219 00000 n 0000588278 00000 n 0000588510 00000 n 0000588679 00000 n 0000588857 00000 n 0000589095 00000 n 0000589249 00000 n 0000589424 00000 n 0000589622 00000 n 0000589773 00000 n 0000589976 00000 n 0000590162 00000 n 0000590361 00000 n 0000590551 00000 n 0000590758 00000 n 0000590920 00000 n 0000591095 00000 n 0000591270 00000 n 0000591445 00000 n 0000591620 00000 n 0000591786 00000 n 0000592000 00000 n 0000592192 00000 n 0000592427 00000 n 0000592610 00000 n 0000592732 00000 n 0000592871 00000 n 0000593045 00000 n 0000593192 00000 n 0000593339 00000 n 0000593486 00000 n 0000593625 00000 n 0000593764 00000 n 0000593955 00000 n 0000594087 00000 n 0000594292 00000 n 0000594483 00000 n 0000594694 00000 n 0000594879 00000 n 0000595018 00000 n 0000595157 00000 n 0000595292 00000 n 0000595429 00000 n 0000595564 00000 n 0000595699 00000 n 0000595834 00000 n 0000595985 00000 n 0000596120 00000 n 0000596259 00000 n 0000596394 00000 n 0000596537 00000 n 0000596676 00000 n 0000596819 00000 n 0000596990 00000 n 0000597177 00000 n 0000597312 00000 n 0000597559 00000 n 0000597790 00000 n 0000598045 00000 n 0000598274 00000 n 0000598477 00000 n 0000598612 00000 n 0000598743 00000 n 0000598874 00000 n 0000599025 00000 n 0000599160 00000 n 0000599323 00000 n 0000599488 00000 n 0000599655 00000 n 0000599838 00000 n 0000599993 00000 n 0000600128 00000 n 0000600283 00000 n 0000600418 00000 n 0000600589 00000 n 0000600794 00000 n 0000600977 00000 n 0000601184 00000 n 0000601363 00000 n 0000601514 00000 n 0000601689 00000 n 0000601824 00000 n 0000601983 00000 n 0000602142 00000 n 0000602281 00000 n 0000602416 00000 n 0000602555 00000 n 0000602694 00000 n 0000602829 00000 n 0000602968 00000 n 0000603143 00000 n 0000603313 00000 n 0000603913 00000 n 0000603981 00000 n trailer < <0A732FB73B32C7492D73F37B7FC17159> ] >> startxref 604169 %%EOF speedcrunch-0.10.1/doc/speedcrunch-manual.odt0000644000175000001440000010050011015364561020307 0ustar helderusersPK 8^2 ''mimetypeapplication/vnd.oasis.opendocument.textPK 8Configurations2/statusbar/PK 8'Configurations2/accelerator/current.xmlPKPK 8Configurations2/floater/PK 8Configurations2/popupmenu/PK 8Configurations2/progressbar/PK 8Configurations2/menubar/PK 8Configurations2/toolbar/PK 8Configurations2/images/Bitmaps/PK 8 layout-cachecd`d(fd`e`c``N} ƈb+2a0, L&X14`p22`aU0tcq% e(v0FQ9HPKazyPK 8 content.xml}rY_(ăOUjbU*H@ tb^x1Ǝ;G/yG E" dǹ׿YLVey&_tZJ0JƯ_Ջ߼NGh^ |9H~vo_gɫ4̣UNUJg*or~Es'yw~v.Ԣe|n}fz}{wPG//9JYXD+XQIQ^ݵz4vO[yn6bzj88UNs"u}d>lgЄEvxg$v z|Nbrϙ\{ t׹Y4y~f_PZn>;忝|. 9||t h\h[DSy8;?5 QaVo4d(P ͯOEEFüyN$x^oW,o_ X%*3|,*pn,Bmߨa&+saI],Im?9@s(P-BM->yXPD&c[‡KV= p>@Ah[S!%OzpbsyɊH(%N h iVyha(.̀08=:K~`*K;i~ܩh<jWMTac0쾽G۞iGvo_<͟yy,Cw_<{*oqXuΫك_?Ni?\_yiQc3p^SQ29Cypa ^8Lp +*|Γ"]~~q)(|E3XfO˼WX^,\{x"'X|ʋ$i>Ec=AXvb8mg\M}akC遝q&z-)dk%oί<5?7FO<oUݧ[#;aiInIw䥰4hVŚ~=/s$b&CCY3dz#7ÈkJއV౾3__왯♯꙯Ϛ4>w9{yNǪX9+TMv>"7Z"D.g+!w !e'k\hnHu N{;,RgO{V @|g˧{g/WPO[/P~wzBSEH:G(E H"gG(E/"Q?GyC(EH"Q?G @H"Qސ:G(?Hq"QP(EH7"Q?O*_EH:G(E H"WG(E/"Q?GyC(EH"齝 nםlKRgSQ:纚|9P8iNӡr3/sX2Q>e3q>Twq<ϋ,bߛgn(ރ|0!od?h]ke΋7?͔6'h[ve<0rś_oْ:$HQ}8$W2!~T s5 Pe߽96S*F0FCv<*~$ b9o &9-q\姣aܚś]Յo*([+kpDNÂM}Dq2HGwl^l?"D=8e:FQAɻX_N, F 8" qIa7̖,|")qXY#(&aDy0F͂i|RYH#mp3b Z[(`v!tskcZaG l6F֘F3 H >ya2 yF{t;X:aaL RC\ \i*o G\.+Lx…'k͒ #I~x <W! OM?|(V)|;a9.!< I [~͠,2؀+: 8Xv0^aoj΂Au}u ^8NV;͛,$X'"{^>wM"l4{L ۜ"2I$b&§|Jһ _xY \ly% eAt[yb$Un28_]~DtKnxI8F'lY 8ԴL19ۥS.\B'm5F @'vt7 [eqI`8k_1\uLMySaB3+AT#B""\ffY w t }h7]$/C;o~Dv鯗;FF<.Pbj4Rg qp= G=b"oFwKeR o&V@{D}"2CyQ*&(kYU.JԈr$%Q pX}9}hV5 7< 3V~B}vWL}vp``Js z. #fo Q@'HʂD _$`Y3y!A- ?~0(ZxI,ea"au㸁UW fd6Q P]}{xq} 18Ȇ4UrIV Q rszOi ѹ绣>T &x;2'ݗ _D3X8-7ăg@S(KA>i1A4vtlt0? ? C-,cE޲>Veh aA[NO#8GT2F*7X^ȦYGA%$ge.1f$,O+E:H^6H&Db(J@E @mDQ4 E%;M(:KFQvF^l|-9od"z wA΄l0 >sIV4Ax` sQ<y04߾AJxL~,)A Zh 0o(ﳝ^9 EhdepsEw@a^\V#BmT,dlPm 摳JgK֓jӽ )rm"j#mDJ'ĒPG\zPlb!Ł~4FQE(Fz2+'1ON<څz3NU^@ aC\s?#ݎMɡOw+Φ1c$Ha o#SOwFZ EbIǤH/hTa?a3|E %b)'"q86XM@ ֒[ 1ot[ 8EsjtqRփ~v)[e@3S+i4HcYsySgh[ Jc%**>Ak nm[4A1Th [hك CAj-Xs@O@5HI?yHID|#%i ʡ4B!jd$I2*xAkq:+wd: Xr o,'lF7U@w|>&)T.VxeصJb3|rb7. .qeG,|[|O y! VأeAdj[_!4%/\Fg_ ޢx^,$+ [ l1`qՋcV-p%*"h_?zxi!(݆蒲ɑA*:ݞs^zZYD2IT;no/f,YgeJ!y.#*clU0y9GEE=ZYK @D&xst3RXbɁ*֙Ä@ `D[ UTFs4%՘vهFH<ٹ״`P4eUy"zEF1b ghXY$ms ac3V#(kLZy 6Or@g3="1fq(EXFr(nW08es/%H,Z!7dD&08d" lV^p\W\C [CB @pYeMj.žTa)~("G4V 6o*kɶK|vtߡDE; _PyP5C&%!nu._K2Gl0Q@S~Qgf+8@ E%Eǂ$7%FC(r(PN3r 6puPݦ64Z1S)P3zPš׬F!x ^gZ[#1Al2Jl2|zQ@(Aio I$0e;{Fi|[baWK$JYV`KR2Čq>8B Tx +@^zsBb!呱9".5&95y5.5(aly$6\p : )ld|> [XrO `e$z>.iQfhMnw9k]yOҼs*kMzCyR5w'X :;$hM q8e\Kǣ(:u'p`66f 5|m3~2tHf̒\n})kCшWvl"Xn '$1k4}Lي}D ,OS r%RhLBFc Vis(蹓HC)G&]>soL-daPCs.7D>Jgsnl]JU$q%R,L&h߉bφhǫ7=_) )*D=no9\*t0,R}f)-f)kwܰ25Vmܪ{~îIv\|Fz-5 *$n2X(2BL4ʧ>{5o/ܸ+OV]1zL@f#HiE-:]Y*A>+xl#YPi.L+Sڬc]Gkg?BÕ|,@۵`jG#4%6T<,JK$9Ӑk˦m'GؔOέy'Ұ;+Ū0oyHj3MrT*ELx; "92Fyc߾ءn}2-^v;݋τsV(79 9#eg ט p"5;x#א LHn^FɊxuPo$UdKwp}^=Ű+msɗm`I%5׀e0Ie(BJUv(rbh}OVdndL^uv g& oc$Bm}Ċk_ǒ7IՉ\'LKPTWmkk8j ;ƪpb-XAFտAwU*{c)^A]ue2lE q]*r-C}L%K7hƬL:xAX4Yk& 9P6Jеw$jйJ(.y^kgڙ5 P4;#-A9TƂFUB cƊt2Őa&!3cCO[qjOOLYHE (Qcs}]YuQR3.1J{DYs]h<"yˆeq,?U_KĄ655P@(.y.J* fYtK1VݔiaGA8TvIC`: 5L`R @1)da!dl 0wcBSw95-̈́8Cz^cQ 惉"{nSO| QFkU[\٨i7i1:AJ5T!%VsoXk ?)c=&G@ tխmI0˱&^[D5x-4l[t*X gl0HXa+_ #@lucEJIr;,Tf-xeg>jՋ7b4_ny\4cSŷIȱY\9]!xX܌UX=J zdb$ļ>TSKbJ\TDŷf,a}LAD>hQp(u.hn$C~~Lb>UR8b\_qjڷ@2KRkP ˅DѸq'e@7ڀ{hS>RCѤ9ə8*̯$Z.²T,I'Q) v#99oS0|H5LX5w6ID ,x5;P1|1:77Y{3XH>9E<-UcX*yt9Wt}yX6b6!\Hck晃]f&H51Lbh=D®r%JA=,dԓyC\ MDjaG+4~h F`;Ɯ Wb_ :g4rn)zfbP9(3T Цcx={hij,#b卷nL@UM$]Q}5Y 1BSjsHBwOON.O.NONz'ݓNuл^]=!Hdug3la EQp* GXP+.qHaZiDzz֤4ށTBE ,d$bs\ haW4MZdq DZɆ Ԅax(' E;F^YFZ{3ѻDM*0Vk/ςu2qJacdsЪ+Ǯn6L8)̞o.ZG d"}M%d[l&cc(7_G멲T3|eCqS*8RT3G^ۃ<8oy׎8)"LzGR6J&gON3AoqGȈċQ3jRh.%PzPa%pY/ByEnC: "uaH56dBNDrV$BB:`cȨ2Ϧ čد pz'ַO$hۤS48;S 6`هJUZ91 Qe)ʹr[ fsFWQ/ֳ,JM ˋsNy.&9uc\jXb 82Cs[NV* Mvh٩;ҐOM8~8n)v9D@h(g  ')bI!7u ڶ y$рKjY۫d S R3.#IQ\B?2||c ]#JCi\/N1')7}#v0ǰU0ЉsneJ*$-t>79N-w$h,{C&]6$"IF `eW$zCKvY3*St:6PZAKpILX̖s[5MFmv&>ܪf+&BUtMVY"K+8ƃ`ʔ1NWuîtyt,sS@'D1#ݟo/Uk.庘sxՉJ6uX36~BnD2^OIB _Sds|>^\,w*M`l 8 Nkב`fFBICj0)n@.Vа`p&}V?mm%me5RD]T|C-ՙ˫ͦ st ,^DQO2INa8D#&_xطݔ@$T_SDGH(F:^S "uЗٗ [dzȥ2Ie aTMp'5KU:Sw.2*cIćmmLF @QY l`;0rܝɥPJ8|#Єe-Ce*L60B넚9neXz\ MSdI߸i)a* ¢ >odWnqsGp 3: BsصԌ%߽rsy̧TVm, eI4ć-x{di; `5E)ɮahϥȂ1T )#LmXA^aZ'xg e 'Jh4[`X#\sK0*#lΙ©#E+5V=yE(+-9kT.*h06 (oü&)6)I,c.|ZK/aK*tU܋VީGS$k <3f津APg>Fw:$*#zU;{'uJ.\'%>Rd B$`l۹܉;/%Y >3D!nlԔ~K"qNP0!ؕ!!PVOX՚:k259Dlu[91ADtSjf(5JmmvKMBf %E7Ar5PL Z#\tMKn[- ݍVlMT .kV8r2oj#^6rZ1ʩ<&DT*g1zl3䙽_n'QOyp9Kpu r$aTV`)A.#%fl̔WaFTLӍST΢l6C@W~,L/렺I\ c*<..Yȃl;B<U~#*A Q}u 8m^eNxC-&0Ց 2IT"jEniei]yfcY;}'tz@/+Bd,P_9(=@{P=ìY/2`z^eXn6 A]&N6s=TYEwݚyg`R[o-4YL)8" b`|UUw]2|f;Ҷ yI(mut# !f,8ȘkŰqf ׊5՘T'54n4מ56*hZ)-Udtڍ@Ź̃ś/;+og쇎9CP9SIID RlX%5l|k^ze|k(xtO?hNžqcxy} #^:wp|)^!,.A##7~.B>-`>L؄/QźA:s4]@̈́{DfBW9]27@E&XtoV͖>T6HTGHh ;^ky܄pW!'"p1+|K-*ԤcR5DfŁ4~K) iK5 eK N$暣рڽ _ ~g3M .鍀;<-(&,UjoCwiǺԺ7A{`%W?MˀJNby״Zi7xPT풍U+WDhۦ§NCo ۄK*J" vՒ, -nAW7eg˃p |CފǓ3_ [Wr%G*_ x36ۭCc [V>nȟ8|^F/ )p亇 (#碉!݃nZ܋|]!qn!Lt2L!2eo% ]Ds}|iwMQmzUMGgWսԏ>(ط:K4he1ɏVvHVn2̃RؗEnomt7DDuɕ]kb7]WPBP(,QBI$|f/DY)' УNT9bNu~N8z4>D,xi&}8NMA :QnoJFQ 1RqZnDFbHhkM qTqoT@7†N>}#j)S'MM@`Ѕ4%ȥjqFPsG1›*-ɨ(r2ߚSscuݜ^ql"x⠲U65ec'huw2Wũz *ھբu$7!(^[Ldf" \'l{]WƊLEw0A\*2ѱ4}Gғt=M<&aeCi B )@J 6m-pK )UK8$ Cv՞&9/-o$ L)n_+-|gO!ygA(]t׭n孢?ٳs#luh`$lR38 g' Cšfmu]Y%둙)bAt*ᩱ/PeA"1V8q94`9&rn11}֗njp;ȱ$FF;4D W8XY$& twΙTe|qvr)#b ;ML6RQx' q3.M|4c4,:ԅ1ʡ$h Q*y6vkq2 5[Ͱ]8 *MN†)ױ#,i@Egqqn=*pPJtm– (!R|{M[ 7%a[Tׇ΅4%`фyueP~T& {(?m]vW=T6n A ^ޱOW`mqn_z;- G X(.l Gױrs|em=LVqiRISkQm. |.67ۭ9FtV6+PXcBmmԿ:>àtn{S%R 5W^PSX(ҰӀ00 R=Ub3]"qόжh7C< 7%QHߟ35 VRGy7_,YNy^nl6)HrR^ &XAI·w&Rzml|vu5B:ggø.7buNrf0TݣAuj܄E.imj(>Mf&PYoSX J'7˃Y)pP$eJ(wLLj'NhZMƦyJ-00aP(FQj+npw6t?YkD}y\6 H$S3Yaer=DR&a,@  T Oi-$7^G2><-2o5vKm76vG6T0\L1fP-||(@'jU2*7+.,t?`5nk-zOqT'i<6fW1^,X"Mݨ$gCm0(gs:Ǫ2O l韥0smN_gD0QB각r,yU)2dx_6Jߓ&Co͠W*qHRІ[06=5r `qH7X :c`,`R/ط[-S+/\oa7 mY2 Qu.i$|Pmk$h=l.^ڽj!t7M՗ډ5 Yc8{Ft=C\W ]'NÔl&ǃ0r_}%-֩ &0k&r %4J9D3:ֿh:|D: j;q@!y(]#wb @ ʐMNyR:VS,s]Z#F+u/Qͤ+zh]-CCTV)zS e[`l''ȀLF7fU*w1YZpuDؒ5$O*_1 RӕmktVeaqE`YahٯL dM$̵ޡ4[x}}b%4D3caM@Sʫ?%0/kA?YK3uBZk4sJT2KQE ,| 33xad6yJhDeXE-/I׵ț)Bg"4(tٱ!vN)^/\8} j+T<7H?:j]fp^BD?WVFQ%Lr>(rQ&EwT{!s4ـ{d ^ksn]lxÈdbP6myyP$P˞svuW=CʴfKtf ת(!;%T$\kfD)ۋuą^p exLc÷WWZڹ/&&y#䍉 :`2 SS`S i*|Z' LPԟTvu&8#VF7T*0fLY0 ħ$>u/ژ ۾ک GͲt8:GMm1v6yWZ@) - T{頒HQiA,)]|lBYN猝Ԓf;x?0N؇kl0_i &jL5,(Mnvn at 4STޯ|By)nrN=Ɲl d1R֬\񁤜\) ȔnΜZpœcv}MixUdm`,u(3=31uIdvt)-ZP['@}HL,Ŕ. VG_Š?cR/B%lp!hzjCH#ځNq-xJAXM~yߠ.޽j]^lJ_JKjǂ[0-hʙ?a1s§3'qPK~Ddc6j!kWΓ .b2 \{_&0h"|vc_4( J?P\AveB#∕[% ED$ʍKiiw=!Ub/ *{)zOHfA|}~/hdnƑ6? y &VcϞ:yfTjY6*'J{ˣ  E n -n@(aaQrFm@Pm@1Wf/sNiQI\I< E%)i&i''!&v9_k#( Rա$6Ύ`r4s}βk0-ll}H6RQ@Y{@_Mt H~VyZ,p/ PAGs0[>fR2w=e'UAJTvNԸpؠ>@)\m>6 ,ͶW尿V3-[\N\^jt6$ \N,F(j_"E fK\u7YJNK)ZĶ" ΂Z+CEEǭMc #IXHla3!v[Rgn&e4l4EteRjW 5"͙"h9*,e{086dLDg 0l%4zEM8͚U͎O=j;ogyys(ŕr4b{f]8/ :UEtCNH-٭vho@_^6յ;*>`u\D^{Y..K mF<إ }gP۴6F+Z+!AK ٌvRUfXt 3gP|{ I8{,`s/?yǷ[u2LR)R5G5C9kyf);bn 5ok.ڌ_03c'k^?}N~40y9sWXGpS.vQZ"CNkpei)֋(ƑͱBcӼJ7X6 R̫e7/Ӥ{$Fc0;ƻwss=>YFhǮy[J)For9絪z Pn2-"> QXx {hZ[]F8h*{8pJw[6z>+$> prB-b4,7s&jCP?Yx0i-;̰ `?[Q)  %ψ^<**C.rjyVTGp~Iո=rޢV\ؓ4pB8q{C%Vs0Sгx~:m6\hkTAPTH {?,#'!;E=t]Z_YDf< Z9&_7<;Eǰ%annu}. '`1-3 WJp zC+1kˆt|)(B,n!n++sjWV\"֥8+Q{_F.E2LbBQs~Y4iS^KqwB8&-08A(pUْ:oHq0|O .&zF;w,G8gv`d؋y1Y6E#Yՠҹhw[Q^3.rD/޿BRq D?DBW_=ŰH'-d|w.OruAz¯Л]4s-w>} RbR-r]'*t"ЕuSA;f e}U`(*#l}뺓J}<*ѐ71w+G(7Jfjm˜ mpǫU?oo/NdVK>+j [}uR.c]>ۙ`5Yv'uL V?3ֳL&>(˙w3Y.( ƢLrJs9Qܲ$Wt*NYnegB޶>-ס6@i)̦el/G<^kz==^>^PAgbm- K8;ؖJaNjBXy[Εݥx\ծ ֪teXpIye s+B-Ͻ@;!fY[A'^[Ѡkr>w1_8loJHc] W4RaT1Қ'= $ ;6:w[NAIb(U̦6}u lZ,B.lU:ZJdxaH^(< sZF7 ͻA‰֘MgYą\so:YP>vR*m;. X aCݦoG<tP*T<PO^殊#Y˨WO]|]_D'mx?PKG11PK 8Ź**meta.xml OpenOffice.org/2.0$Linux OpenOffice.org_project/680m5$Build-90732008-01-30T18:14:032008-04-02T00:16:22de-DE63P5DT21H17M8SPK 8Thumbnails/thumbnail.pngWEPi醥QfIFYAFrnd[dI%ngμ3/̙U'&# P1/zB| g3 CMEcCK=WՎWLd8OW\ `>ԏ,6CZLԋ9)BCߩH8>֗R|$д {A/)~SGo9ԇpQvT@c ?e桘 ohЏ޻2cɰy}z.LB &RT/\~% +ɭuk#11Hbg2u_˰[QW?j?z {쐊6z5)_~x¤XzݶhTJ &|Aw#ࣕ\ZZ2h։@;mI@#N z8OMS3g?դSz@2m&ddF@o+`RB\gm'"yT&z3 `}?㑷ƎbJ~KT,$^(NQ#!$HVxnB "[e?Tє+Ճ>r{z1zQ߉y. )|Y,6(bW^J!YJ]T }I}$b/zl׬40OrwdGBggzsHYk쐹Upe-4$@!:r?ԺdWA~pqT֮t_8WQspL(yMUf|2W sG){褊PY19K)@ƫoꑪDO.93;@7s'[s"k-hz%9(=<$`ТRP'Y[No6j"c4M3g 9y9S ڪЇd"BWmUλPv{pk߼,?}sHqLߟ*u`1/މ@93$=SD;w̽Wp9LAU?4ú1XLk.!n)2 bn."a~%IlA'mUsk$N-)Wh:joq;=pb>V}W=ϒ]\Eσe/WQמK7Ǭ< 9D!qǯSSH :1a{%$1C$vğoD5ƫy{fZϙkvgmvr3t.c鈇4o Ԏ[8,OA[ "!RV"&+MqfvdaP̸-\nG!:0.mN&x=Bar 8c;F}簻%N"\ku, y%=nFtM2F%#J9&aN^1&mZ(؈O LkKXG49T9/tuȰ72g㰶C鐲M0[1<6d/IZ%f[ti+p5X#Faq]Q[bcy@p6E\D3~pO8ty8C,e{k"ϱ"UW%O;n5(}/> .t.3Q0l&?Q/N`%2Y{feǴjRSdRKidzfu--3 X`jLv'x:9旽]^EM*8W]To-v~-M41n{1MN[5I Ha\&z 1=Ό`#njpPH`7WҐ+xNm BEٮZ6ΐ'ge7C>"مvn맪SJCF$U'߿ʥWf,ۦ,dڍh5teNjǾ؊=D+PU"g T)0*`<.+;# 'Baι+oTWl}D31S.-$g_)ի100"jg 2 8m$˰89WKae WoBn[`  }@Iq(zJK_ב8qz՘T[aJȸSʩa\,2xجmn `쿜v>9,'?da|ZD g}r]*wqbSƧ_7b *OHͯ~E'nG?0о^/,T?+GsAnwK.\wsYLπ<9(;OJw*NJnFܳ Tl7nbEE y.핧##TPbmO!mNFmi=[%A`E"&9[JO ƨ^T>!_̢jG!ΟwՀ%'8Fd@>w?pD,_b XSW E6@އobm/>[֐.c\o\p= Jc*C` T6@IqW9Ơ}; >>2ݸџ=8qp909a ]|CBېL*˝#)\iqprڼ̃oٌ5fΫDg~٣ZLIk8~ꂞaG^"XzTG0 [`Ee#Q 1*M \z-ҁ g{^hWݣlEqp8s"cl|ٶ ̈Da7LGqr.wQb|ajBlWwP6K(?Tg]q*}"~5'mrס-t60CsLis(#+G*44q lقܕ ޞ9CðJ؞Χ$J;_ FsCW vt-9g/=u yUT+Ml}5!9I&Uf0p4ŕ9!UoX-4@g>-?jqB(6~-Yl xwgVg,N~)>YKk YYDC/}0əp6+h7} (X/shLE Q#qmJG{ ѓT 5eѼ?.{ATZg5oyl[.g*!jXz}o1U AͼM?Rυ7iSIژ}$&Er/.OrW cRt>*9Ĭ/h+#&#BMapvui쎵saH(RVxHSpqy7ĕj#q]'o*Xr8E l4؁͉ۜ ӆΠ1K8ԍkH%4{YщRo0ӭSX (6N*qb6= >hJKYWQPP@cPTn)QW`#H5a.|m??J\U Dv"gևRNvK/mbK2] xiwR3Ԗ6)}8ap^7%ϴ9}9 EO E>_= ^5)F& ot٤ctqK ?{pyY94NQ *l* 0 ?zO)Up1{JMG&Ǘo~0*2L)|h"1laRz7~_~,IS Cyn+[-Z A\)jZE:DqP8탺_`֔e=ͳn@x.}+_@ͤmFޛ5Gv L?2J_WDa=79x)냆*+aN[awS*Dp$+n$mnDQW[JApY#9x~[$>XXaʉPy0HӢN,g][|Euo ]5Bܪ,M0)(v[0jPcuo:W<0^#ezQZdlAawo O@S;sEވC' 3x$ag2(h o !x#M~r[j|zm<&[CZ VTqRوbG.՞xzLJr!FYNJ:L&F4S}59Z% .%oo4 iIjV {,e *vŶsbQ1 |eQ]YzšK;sY 3?pl]*.2~UDwEBv Xn6N''BxuY XvpXl;4M?c M(uv)3l'uc#$L%kk1y2^Fu:$r~[N=8Gq3V4>m\socjDuoסD{lw=թrB.:Ryau/Co^I*U{Xo]A]0"*=ݏ1:L)jobW*5cǽ +&UaP'%k~ ^caV_ JHͯ]=Ā?dԆ<(y1 Jٷ:U]TU| Q`x׭S+yWm2[ۍ|`DLۉXʏӻ2;ȿ:`ݟeJ O}'k'na#c&zGd%9kXe_R|dSn(vnĂ5$[HNk Hqr}iui@# Ai:B5^*ETCTC L@l5>nXeٓ%7:iTtqqrV=Uv4@1fVT̆Vf{'k#?ZAS4&6'ƴ{T6"XGyOZK`cLJM$<]Uw.S'VNKy77d lkE19.RA{ Ԗ "&)- ?0}ҧWbT"XgC!WEn&ϋ;_TnbU4pJR +o6ӛ{nR~{rWPKOPK 8^2 ''mimetypePK 8MConfigurations2/statusbar/PK 8'Configurations2/accelerator/current.xmlPK 8Configurations2/floater/PK 8Configurations2/popupmenu/PK 8JConfigurations2/progressbar/PK 8Configurations2/menubar/PK 8Configurations2/toolbar/PK 8Configurations2/images/Bitmaps/PK 8azy -layout-cachePK 8ZJ content.xmlPK 8G11 sMstyles.xmlPK 8Ź**Umeta.xmlPK 8i&,ZThumbnails/thumbnail.pngPK 8J vsettings.xmlPK 8Op{META-INF/manifest.xmlPK(}speedcrunch-0.10.1/README0000644000175000001440000001203211015364561014136 0ustar helderusersSpeedCrunch is a simple but powerful calculator. Among its features are: - high precision, up to 50 decimal digits - to be enjoyed using keyboard - result shown in scrollable window - history of last expressions (use up and down arrow) - built-in functions: abs, sqrt, pi, log, exp, ln, sin, cos, tan, sinh, cosh, tanh, asin, acos, atan, arsinh, arcosh, artanh - postfix operator ! lets you compute factorials - support for variables, e.g try x=pi/3 and then sin(x) - special variable ans holds the last calculation result - percent operator, try e.g. 45%*75 or price/80% - angle mode: Alt+D for degrees, Alt+R for radians - automatic parentheses closing, e.g. cos(pi/4 becomes cos(pi/4) Using SpeedCrunch ------------------ SpeedCrunch is easy to use, just type the expression that you want to calculate and press Enter. Result is shown in the scrollable display. And, you can quickly copy the last calculation result to the clipboard using Ctrl+R. If you want to reuse again the expression which you typed before, then press up and down arrow to access the expression history. Beside standard algebraic operators like + (addition), - (substraction), * (multiplication), * (division), ^ or ** (power), there is support for some functions, for example sin, log, abs, and many more. You do not need to memorize function names, use Ctrl+F to pop up a dialog where you can choose the function that you need. Or take advantage of auto-completion feature, for example type s only and in less than a second you will be automagically given with choices of sin, sinh, and sqrt. Advanced calculation sometimes needs memory feature. SpeedCrunch allows a variable to hold calculation result. Using assignment, such as x=0.3 means that variable named x has the value of 0.3, which you can always later on, for example sin(x). You can define as many variables as you want. When you want to use a variable but you can not recall its exact name, use Ctrl+I to show a list of variables that you can pick easily. There is a special variable, ans, which always holds the last calculation result. Another variable pi holds one of the most important constant in math world. Your expression history (maximum last 100 expressions), as well as variables you have defined, are saved between sessions. This means, you can still recall those calculations you have done yesterday or last week. Often, SpeedCrunch can still understand an incomplete expression. For example, just typing sin followed by Enter - likely means taking the sine of last value - is automatically translated as sin(ans). Also, for such function you may skip the parentheses if you pass simple number or variable, sin 0.1 is as valid as sin(0.1). Speaking about parentheses, closing them can be left to SpeedCrunch, e.g. cos(pi/4 is automatically corrected to cos(pi/4). For your convenience, it is even possible to customize the font and color used for the display. Keyboard Shortcuts ------------------ Up/Down recall last expression Ctrl+I insert variable Ctrl+F insert function Ctrl+R copy last result to clipboard Ctrl+S save current session to text file Alt+D degrees mode for trigonometric functions Alt+R radians mode for trigonometric functions Installation ------------ Download is available from http://www.speedcrunch.org, the official website. If you are installing SpeedCrunch from a disk image on an Apple Mac, all you need do is drag the SpeedCrunch application icon to your Applications folder. The application, and Qt itself, is in the bundle represented by the icon. You need Qt (from Trolltech) at least version 4.2 to be able to compile SpeedCrunch. Most Linux distributions normally already package the latest version of Qt, so it is likely that you need to worry about this. However, you need the development package as well (sometimes named as qt-devel or qt4-devel, it varies depends on the distributions). You also need CMake (from Kitware) at least version 2.4.4. CMake is available for Windows, Linux, and Mac OS X. To compile, simply extract the source tarball. Then create a build directory (where the program will be compiled and linked). From the build directory, first run: cmake \src and then: make Note: the build directory can not be the same as the source directory. License ------- Copyright (C) 2004-2005 Ariya Hidayat 2005-2006 Johan Thelin 2007 Helder Correia 2007 Wolf Lammen Portions Copyright (C) 1991-1994, 1997, 2000 Free Software Foundation, Inc. SpeedCrunch is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. speedcrunch-0.10.1/PACKAGERS0000644000175000001440000000043611015364561014506 0ustar helderusersGentoo ebuild | Marco Wegner | marco.wegner@informatik.uni-luebeck.de Mac OS X bundle | Alessandro Portale | alessandro.portale@googlemail.com Source tarball | Helder Correia | helder.pereira.correia@gmail.com Win32 installer | Christian Ehrlicher | Ch.Ehrlicher@gmx.de speedcrunch-0.10.1/src/0000755000175000001440000000000011015364704014046 5ustar helderusersspeedcrunch-0.10.1/src/base/0000755000175000001440000000000011015364704014760 5ustar helderusersspeedcrunch-0.10.1/src/base/evaluator.hxx0000644000175000001440000000666011015364561017524 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef EVALUATOR_HXX #define EVALUATOR_HXX // #define _BISON #include "math/hmath.hxx" #include #include #include #ifdef _BISON # include "bison/bisonparser.hxx" #endif class Token { public: enum Op { InvalidOp = 0, Plus, Minus, Asterisk, Slash, Caret, LeftPar, RightPar, Semicolon, Percent, Exclamation, Equal, Modulo, Div }; enum Type { stxUnknown, stxNumber, stxIdentifier, stxOperator, stxOpenPar, stxClosePar, stxSep, }; static const Token null; Token( Type type = stxUnknown, const QString & text = QString::null, int pos = -1 ); Token( const Token & ); Token & operator=( const Token & ); Type type() const { return m_type; } QString text() const { return m_text; } int pos() const { return m_pos; }; bool isNumber() const { return m_type == stxNumber; } bool isOperator() const { return m_type >= stxOperator; } bool isIdentifier() const { return m_type == stxIdentifier; } HNumber asNumber() const; Op asOperator() const; QString description() const; protected: Type m_type; QString m_text; int m_pos; }; class Tokens : public QVector { public: Tokens() : QVector(), m_valid(true) {}; bool valid() const { return m_valid; } void setValid( bool v ){ m_valid = v; } protected: bool m_valid; }; class Variable { public: QString name; HNumber value; }; class Functions; class Evaluator : public QObject { Q_OBJECT public: Evaluator( Functions *, char radixChar = 'C', QObject * parent = 0 ); ~Evaluator(); bool has( const QString & id ); bool isValid() const; HNumber eval(); HNumber evalNoAssign(); HNumber evalUpdateAns(); HNumber get( const QString & id ); char radixChar() const; QString autoFix( const QString & ); QString dump() const; QString error() const; QString expression() const; Tokens scan( const QString & ) const; Tokens tokens() const; void clear(); void clearVariables(); void remove( const QString & id ); void set( const QString & id, HNumber value ); void setExpression( const QString& expr ); QVector variables() const; public slots: void setRadixChar( char ); protected: void compile( const Tokens & ) const; private: struct Private; Private * const d; Evaluator(); Evaluator( const Evaluator & ); Evaluator & operator=( const Evaluator & ); }; #endif speedcrunch-0.10.1/src/base/settings.hxx0000644000175000001440000000604511015364561017357 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2005-2006 Johan Thelin // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef SETTINGS_HXX #define SETTINGS_HXX #include #include #include #include #include #include class Settings { public: char radixChar; // 'C': locale (default); char angleMode; // 'r': radian; 'd': degree char format; // see HMath documentation int precision; // see HMath documentation bool autoCalc; bool autoComplete; bool minimizeToTray; bool saveSession; bool saveVariables; bool showBook; bool showConstants; bool showFullScreen; bool showFunctions; bool showHistory; bool showKeypad; bool showMenuBar; bool showStatusBar; bool showVariables; bool stayAlwaysOnTop; bool hiliteSyntax; bool bookDockFloating; int bookDockTop; int bookDockLeft; int bookDockWidth; int bookDockHeight; bool constantsDockFloating; int constantsDockTop; int constantsDockLeft; int constantsDockWidth; int constantsDockHeight; bool functionsDockFloating; int functionsDockHeight; int functionsDockLeft; int functionsDockTop; int functionsDockWidth; bool historyDockFloating; int historyDockHeight; int historyDockLeft; int historyDockTop; int historyDockWidth; bool variablesDockFloating; int variablesDockTop; int variablesDockHeight; int variablesDockLeft; int variablesDockWidth; QStringList history; QStringList historyResults; QString language; QSize mainWindowSize; QByteArray mainWindowState; QStringList variables; //static QString escape; //reftbl Settings(); void load(); void save(); private: Settings( const Settings & ); Settings & operator=( const Settings & ); }; #endif speedcrunch-0.10.1/src/base/functions.cpp0000644000175000001440000012313611015364561017503 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004-2006 Ariya Hidayat // Copyright (C) 2007 Wolf Lammen // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "functions.hxx" #include "math/hmath.hxx" #include #include #include #include #include #include #include struct Function::Private { Functions * functions; int argc; QString desc; QString error; QString name; FunctionPtr ptr; Private() : argc( 0 ), desc(), error(), name(), ptr( 0 ) {} }; // public (Function) Function::Function( const QString & name, int argc, FunctionPtr ptr, Functions * parent ) : d( new Function::Private ) { d->functions = parent; d->name = name; d->argc = argc; d->ptr = ptr; } Function::Function( const QString & name, FunctionPtr ptr, Functions * parent ) : d( new Function::Private ) { d->functions = parent; d->name = name; d->argc = -1; d->ptr = ptr; } QString Function::description() const { return d->desc; } void Function::setDescription( const QString & description ) { d->desc = description; } QString Function::error() const { return d->error; } QString Function::name() const { return d->name; } HNumber Function::exec( const QVector & args ) { d->error = QString(); if ( ! d->ptr ) { setError( QString("error"), QString( Functions::tr( "cannot execute function %1") ).arg( name() ) ); return HNumber(0); } if ( d->argc >= 0 && args.count() != d->argc ) { if ( d->argc == 1 ) setError( d->name, QString( Functions::tr( "function accepts 1 argument" ) ) ); else setError( d->name, QString( Functions::tr( "function accepts %1 arguments" ) ).arg( d->argc ) ); return HNumber(0); } return (*d->ptr)( this, args ); } Functions * Function::functions() const { return d->functions; } void Function::setError( const QString & context, const QString & error ) { d->error = context + ": " + error; } Function::~Function() { delete d; } struct Functions::Private { Functions * p; QHash functions; char angleMode; void createBuiltInFunctions(); static HNumber abs( Function *, const QVector & args ); static HNumber integer( Function *, const QVector & args ); static HNumber trunc( Function *, const QVector & args ); static HNumber frac( Function *, const QVector & args ); static HNumber floor( Function *, const QVector & args ); static HNumber ceil( Function *, const QVector & args ); static HNumber gcd( Function *, const QVector& args ); static HNumber round( Function *, const QVector& args ); static HNumber sqrt( Function *, const QVector & args ); static HNumber cbrt( Function *, const QVector& args ); static HNumber exp( Function *, const QVector& args ); static HNumber ln( Function *, const QVector& args ); static HNumber log( Function *, const QVector & args ); static HNumber lg( Function *, const QVector& args ); static HNumber sin( Function *, const QVector & args ); static HNumber cos( Function *, const QVector & args ); static HNumber tan( Function *, const QVector & args ); static HNumber cot( Function *, const QVector & args ); static HNumber sec( Function *, const QVector & args ); static HNumber csc( Function *, const QVector & args ); static HNumber asin( Function *, const QVector & args ); static HNumber acos( Function *, const QVector & args ); static HNumber atan( Function *, const QVector & args ); static HNumber sinh( Function *, const QVector & args ); static HNumber cosh( Function *, const QVector & args ); static HNumber tanh( Function *, const QVector & args ); static HNumber arsinh( Function *, const QVector & args ); static HNumber arcosh( Function *, const QVector & args ); static HNumber artanh( Function *, const QVector & args ); static HNumber erf( Function *, const QVector & args ); static HNumber erfc( Function *, const QVector & args ); static HNumber Gamma( Function *, const QVector & args ); static HNumber lnGamma( Function *, const QVector & args ); static HNumber sign( Function *, const QVector & args ); static HNumber nCr( Function *, const QVector & args ); static HNumber nPr( Function *, const QVector & args ); static HNumber degrees( Function *, const QVector & args ); static HNumber radians( Function *, const QVector & args ); static HNumber max( Function *, const QVector & args ); static HNumber min( Function *, const QVector & args ); static HNumber sum( Function *, const QVector & args ); static HNumber product( Function *, const QVector & args ); static HNumber average( Function *, const QVector & args ); static HNumber geomean( Function *, const QVector & args ); static HNumber dec( Function *, const QVector & args ); static HNumber hex( Function *, const QVector & args ); static HNumber oct( Function *, const QVector & args ); static HNumber bin( Function *, const QVector & args ); static HNumber binompmf( Function *, const QVector & args ); static HNumber binomcdf( Function *, const QVector & args ); static HNumber binommean( Function *, const QVector & args ); static HNumber binomvar( Function *, const QVector & args ); static HNumber hyperpmf( Function *, const QVector & args ); static HNumber hypercdf( Function *, const QVector & args ); static HNumber hypermean( Function *, const QVector & args ); static HNumber hypervar( Function *, const QVector & args ); static HNumber poipmf( Function *, const QVector & args ); static HNumber poicdf( Function *, const QVector & args ); static HNumber poimean( Function *, const QVector & args ); static HNumber poivar( Function *, const QVector & args ); static HNumber mask( Function *, const QVector & args ); static HNumber unmask( Function *, const QVector & args ); static HNumber not_( Function *, const QVector & args ); static HNumber and_( Function *, const QVector & args ); static HNumber or_( Function *, const QVector & args ); static HNumber xor_( Function *, const QVector & args ); static HNumber ashl( Function *, const QVector & args ); static HNumber ashr( Function *, const QVector & args ); static HNumber idiv( Function *, const QVector & args ); static HNumber mod( Function *, const QVector & args ); }; HNumber Functions::Private::abs( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber num = args[0]; return HMath::abs( num ); } HNumber Functions::Private::integer( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber num = args[0]; return HMath::integer( num ); } HNumber Functions::Private::trunc( Function * f, const QVector & args ) { int nArgs = args.count(); if ( nArgs != 1 && nArgs != 2 ) { f->setError( f->name(), Functions::tr( "function requires 1 or 2 arguments" ) ); return HNumber::nan(); } HNumber num = args[0]; if ( nArgs == 2){ int prec = 0; HNumber argprec = args[1]; if ( argprec != 0 ) { if ( ! argprec.isInteger() ) { f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return HNumber::nan(); } if ( (prec = argprec.toInt()) != 0 ) return HMath::trunc( num, prec ); // the 2. parameter exceeds the integer limits if ( argprec < 0 ) return HNumber(0); return num; } } return HMath::trunc( num ); } HNumber Functions::Private::frac( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; return HMath::frac( x ); } HNumber Functions::Private::floor( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber num = args[0]; return HMath::floor( num ); } HNumber Functions::Private::ceil( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber num = args[0]; return HMath::ceil( num ); } HNumber Functions::Private::gcd( Function * f, const QVector & args ) { int nArgs = args.count(); if ( nArgs < 2 ) { f->setError( f->name(), Functions::tr( "function requires at least 2 arguments" ) ); return HNumber::nan(); } for ( int i = 0; i < args.count(); i++ ) if ( ! args[i].isInteger() ) { f->setError( f->name(), Functions::tr( "function requires integer arguments" ) ); return HNumber::nan(); } HNumber result = HMath::gcd( args[0], args[1] ); for ( int i = 2; i < nArgs; i++ ) { result = HMath::gcd( result, args[i] ); } return result; } HNumber Functions::Private::round( Function * f, const QVector & args ) { int nArgs = args.count(); if ( nArgs != 1 && nArgs != 2 ) { f->setError( f->name(), Functions::tr( "function requires 1 or 2 arguments" ) ); return HNumber::nan(); } HNumber num = args[0]; if( nArgs == 2){ int prec = 0; HNumber argprec = args[1]; if (argprec != 0) { if( !argprec.isInteger() ) { f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return HNumber::nan(); } if ((prec = argprec.toInt()) != 0) return HMath::round( num, prec ); // the 2. parameter exceeds the integer limits if (argprec < 0) return HNumber(0); return num; } } return HMath::round( num ); } HNumber Functions::Private::sqrt( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber num = args[0]; if( num < HNumber(0) ) { f->setError( f->name(), Functions::tr( "function undefined for specified argument" ) ); return HNumber::nan(); } return HMath::sqrt( num ); } HNumber Functions::Private::cbrt( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber num = args[0]; return HMath::cbrt( num ); } HNumber Functions::Private::exp( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber num = args[0]; return HMath::exp( num ); } HNumber Functions::Private::ln( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; HNumber result = HMath::ln( x ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified argument" ) ); return result; } HNumber Functions::Private::log( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; HNumber result = HMath::log( x ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified argument" ) ); return result; } HNumber Functions::Private::lg( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; HNumber result = HMath::lg( x ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified argument" ) ); return result; } HNumber Functions::Private::sin( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber angle = args[0]; if ( f->functions()->angleMode() == 'd' ) angle = HMath::deg2rad( angle ); return HMath::sin( angle ); } HNumber Functions::Private::cos( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber angle = args[0]; if ( f->functions()->angleMode() == 'd' ) angle = HMath::deg2rad( angle ); return HMath::cos( angle ); } HNumber Functions::Private::tan( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber angle = args[0]; if ( f->functions()->angleMode() == 'd' ) angle = HMath::deg2rad( angle ); HNumber result = HMath::tan( angle ); if ( result.isNan() ) { f->setError( f->name(), Functions::tr( "function undefined for specified argument" ) ); return HNumber::nan(); } return result; } HNumber Functions::Private::cot( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber angle = args[0]; if ( f->functions()->angleMode() == 'd' ) angle = HMath::deg2rad( angle ); HNumber result = HMath::cot( angle ); if ( result.isNan() ) { f->setError( f->name(), Functions::tr( "function undefined for specified argument" ) ); return HNumber::nan(); } return result; } HNumber Functions::Private::sec( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber angle = args[0]; if ( f->functions()->angleMode() == 'd' ) angle = HMath::deg2rad( angle ); HNumber result = HMath::sec( angle ); if ( result.isNan() ) { f->setError( f->name(), Functions::tr( "function undefined for specified argument" ) ); return HNumber::nan(); } return result; } HNumber Functions::Private::csc( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber angle = args[0]; if ( f->functions()->angleMode() == 'd' ) angle = HMath::deg2rad( angle ); HNumber result = HMath::csc( angle ); if ( result.isNan() ) { f->setError( f->name(), Functions::tr( "function undefined for specified argument" ) ); return HNumber::nan(); } return result; } HNumber Functions::Private::asin( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; HNumber result = HMath::asin( x ); if ( result.isNan() ) { f->setError( f->name(), Functions::tr( "function undefined for specified argument" ) ); return HNumber::nan(); } if ( f->functions()->angleMode() == 'd' ) result = HMath::rad2deg( result ); return result; } HNumber Functions::Private::acos( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; HNumber result = HMath::acos( x ); if ( result.isNan() ) { f->setError( f->name(), Functions::tr( "function undefined for specified argument" ) ); return HNumber::nan(); } if ( f->functions()->angleMode() == 'd' ) result = HMath::rad2deg( result ); return result; } HNumber Functions::Private::atan( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber num = args[0]; HNumber result = HMath::atan( num ); if ( f->functions()->angleMode() == 'd' ) result = HMath::rad2deg( result ); return result; } HNumber Functions::Private::sinh( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; return HMath::sinh( x ); } HNumber Functions::Private::cosh( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; return HMath::cosh( x ); } HNumber Functions::Private::tanh( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; return HMath::tanh( x ); } HNumber Functions::Private::arsinh( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); return HMath::arsinh( args[0] ); } HNumber Functions::Private::arcosh( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; HNumber result = HMath::arcosh( x ); if ( result.isNan() ) { f->setError( f->name(), Functions::tr( "function undefined for specified argument" ) ); return HNumber::nan(); } return result; } HNumber Functions::Private::artanh( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; HNumber result = HMath::artanh( x ); if ( result.isNan() ) { f->setError( f->name(), Functions::tr( "function undefined for specified argument" ) ); return HNumber::nan(); } return result; } HNumber Functions::Private::erf( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; return HMath::erf( x ); } HNumber Functions::Private::erfc( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; HNumber result = HMath::erfc( x ); if ( result.isNan() && ! x.isNan() ) { f->setError( f->name(), Functions::tr( "underflow" ) ); } return result; } HNumber Functions::Private::Gamma( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; HNumber result = HMath::gamma( x ); if ( result.isNan() ) { f->setError( f->name(), Functions::tr( "function undefined for specified argument" ) ); return HNumber::nan(); } return result; } HNumber Functions::Private::lnGamma( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber x = args[0]; HNumber result = HMath::lnGamma( x ); if ( result.isNan() ) { f->setError( f->name(), Functions::tr( "function undefined for specified argument" ) ); return HNumber::nan(); } return result; } HNumber Functions::Private::sign( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); return HMath::sign( args[0] ); } HNumber Functions::Private::nCr( Function * f, const QVector & args ) { if ( args.count() != 2 ) return HNumber::nan(); // n = args[0]; r = args[1] HNumber result = HMath::nCr( args[0], args[1] ); // FIX ME: overflow causes a NaN, too, so the message is sometimes // misleading if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return result; } HNumber Functions::Private::nPr( Function * f, const QVector & args ) { if ( args.count() != 2 ) return HNumber::nan(); // n = args[0]; r = args[1] HNumber result = HMath::nPr( args[0], args[1] ); // FIX ME: overflow causes a NaN, too, so the message is sometimes // misleading if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return result; } HNumber Functions::Private::degrees( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber angle = args[0]; return HMath::rad2deg(angle); } HNumber Functions::Private::radians( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber angle = args[0]; return HMath::deg2rad(angle); } HNumber Functions::Private::max( Function * f, const QVector & args ) { if ( args.count() < 1 ) { f->setError( f->name(), Functions::tr( "function requires at least 1 argument" ) ); return HNumber::nan(); } int totalParams = args.count(); HNumber result = args[0]; if ( totalParams > 1 ) for ( int i = 1; i < totalParams; i++ ) result = HMath::max( result, args[i] ); return result; } HNumber Functions::Private::min( Function * f, const QVector & args ) { if ( args.count() < 1 ) { f->setError( f->name(), Functions::tr( "function requires at least 1 argument" ) ); return HNumber::nan(); } int totalParams = args.count(); HNumber result = args[0]; if ( totalParams > 1 ) for ( int i = 1; i < totalParams; i++ ) result = HMath::min( result, args[i] ); return result; } HNumber Functions::Private::sum( Function *, const QVector & args ) { if ( args.count() <= 0 ) return HNumber(0); HNumber result = args[0]; for ( int c = 1; c < args.count(); c++ ) result = result + args[c]; return result; } HNumber Functions::Private::product( Function *, const QVector & args ) { if ( args.count() <= 0 ) return HNumber(0); HNumber result = args[0]; for ( int c = 1; c < args.count(); c++ ) result = result * args[c]; return result; } HNumber Functions::Private::average( Function *, const QVector & args ) { if ( args.count() <= 0 ) return HNumber("NaN"); HNumber result = args[0]; for ( int c = 1; c < args.count(); c++ ) result = result + args[c]; result = result / HNumber(args.count()); return result; } HNumber Functions::Private::geomean( Function *, const QVector & args ) { if ( args.count() <= 0 ) return HNumber("NaN"); HNumber result = args[0]; for ( int c = 1; c < args.count(); c++ ) result = result * args[c]; if ( result <= HNumber(0)) return HNumber("NaN"); if ( args.count() == 1 ) return result; if ( args.count() == 2 ) return HMath::sqrt( result ); result = HMath::exp( HMath::ln(result) / HNumber(args.count()) ); return result; } HNumber Functions::Private::dec( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber("NaN"); HNumber result = args[0]; result.setFormat( 'g' ); return result; } HNumber Functions::Private::hex( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber("NaN"); HNumber result = args[0]; result.setFormat( 'h' ); return result; } HNumber Functions::Private::oct( Function *, const QVector & args ) { if( args.count() != 1 ) return HNumber("NaN"); HNumber result = args[0]; result.setFormat( 'o' ); return result; } HNumber Functions::Private::bin( Function *, const QVector & args ) { if ( args.count() != 1 ) return HNumber("NaN"); HNumber result = args[0]; result.setFormat( 'b' ); return result; } HNumber Functions::Private::binompmf( Function * f, const QVector & args ) { if ( args.count() != 3 ) return HNumber::nan(); HNumber k = args[0]; HNumber n = args[1]; HNumber p = args[2]; HNumber result = HMath::binomialPmf( k, n, p ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return result; } HNumber Functions::Private::binomcdf( Function * f, const QVector & args ) { if ( args.count() != 3 ) return HNumber::nan(); HNumber k = args[0]; HNumber n = args[1]; HNumber p = args[2]; HNumber result = HMath::binomialCdf( k, n, p ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return result; } HNumber Functions::Private::binommean( Function * f, const QVector & args ) { if ( args.count() != 2 ) return HNumber::nan(); HNumber n = args[0]; HNumber p = args[1]; HNumber result = HMath::binomialMean( n, p ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return result; } HNumber Functions::Private::binomvar( Function * f, const QVector & args ) { if ( args.count() != 2 ) return HNumber::nan(); HNumber n = args[0]; HNumber p = args[1]; HNumber result = HMath::binomialVariance( n, p ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return result; } HNumber Functions::Private::hyperpmf( Function * f, const QVector & args ) { if ( args.count() != 4 ) return HNumber::nan(); HNumber k = args[0]; HNumber N = args[1]; HNumber M = args[2]; HNumber n = args[3]; HNumber result = HMath::hypergeometricPmf( k, N, M, n ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return result; } HNumber Functions::Private::hypercdf( Function * f, const QVector & args ) { if ( args.count() != 4 ) return HNumber::nan(); HNumber k = args[0]; HNumber N = args[1]; HNumber M = args[2]; HNumber n = args[3]; HNumber result = HMath::hypergeometricCdf( k, N, M, n ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return result; } HNumber Functions::Private::hypermean( Function * f, const QVector & args ) { if ( args.count() != 3 ) return HNumber::nan(); HNumber N = args[0]; HNumber M = args[1]; HNumber n = args[2]; HNumber result = HMath::hypergeometricMean( N, M, n ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return result; } HNumber Functions::Private::hypervar( Function * f, const QVector & args ) { if ( args.count() != 3 ) return HNumber::nan(); HNumber N = args[0]; HNumber M = args[1]; HNumber n = args[2]; HNumber result = HMath::hypergeometricVariance( N, M, n ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return result; } HNumber Functions::Private::poipmf( Function * f, const QVector & args ) { if ( args.count() != 2 ) return HNumber::nan(); HNumber k = args[0]; HNumber l = args[1]; HNumber result = HMath::poissonPmf( k, l ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return result; } HNumber Functions::Private::poicdf( Function * f, const QVector & args ) { if ( args.count() != 2 ) return HNumber::nan(); HNumber k = args[0]; HNumber l = args[1]; HNumber result = HMath::poissonCdf( k, l ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return result; } HNumber Functions::Private::poimean( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber l = args[0]; HNumber result = HMath::poissonMean( l ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return result; } HNumber Functions::Private::poivar( Function * f, const QVector & args ) { if ( args.count() != 1 ) return HNumber::nan(); HNumber l = args[0]; HNumber result = HMath::poissonVariance( l ); if ( result.isNan() ) f->setError( f->name(), Functions::tr( "function undefined for specified arguments" ) ); return result; } HNumber Functions::Private::mask( Function *, const QVector & args ) { HNumber val = args[0]; HNumber bits = args[1]; return HMath::mask( val, bits ); } HNumber Functions::Private::unmask( Function *, const QVector & args ) { HNumber val = args[0]; HNumber bits = args[1]; return HMath::sgnext( val, bits ); } HNumber Functions::Private::not_( Function *, const QVector & args ) { HNumber val = args[0]; return ~val; } HNumber Functions::Private::and_( Function *, const QVector & args ) { if ( args.count() <= 0 ) return HNumber("NaN"); HNumber result = args[0]; for( int c = 1; c < args.count(); c++ ) result = result & args[c]; return result; } HNumber Functions::Private::or_( Function *, const QVector & args ) { if ( args.count() <= 0 ) return HNumber("NaN"); HNumber result = args[0]; for ( int c = 1; c < args.count(); c++ ) result = result | args[c]; return result; } HNumber Functions::Private::xor_( Function *, const QVector & args ) { if ( args.count() <= 0 ) return HNumber("NaN"); HNumber result = args[0]; for ( int c = 1; c < args.count(); c++ ) result = result ^ args[c]; return result; } HNumber Functions::Private::ashl( Function *, const QVector & args ) { HNumber bits = args[1]; HNumber val = args[0]; return HMath::ashr( val, -bits ); } HNumber Functions::Private::ashr( Function *, const QVector & args ) { HNumber bits = args[1]; HNumber val = args[0]; return HMath::ashr(val, bits); } HNumber Functions::Private::idiv( Function *, const QVector & args ) { HNumber dividend = args[0]; HNumber divisor = args[1]; return HNumber::idiv(dividend, divisor); } HNumber Functions::Private::mod( Function *, const QVector & args ) { HNumber dividend = args[0]; HNumber divisor = args[1]; return dividend % divisor; } void Functions::Private::createBuiltInFunctions() { // ANALYSIS p->add( new Function( "abs", 1, abs, p ) ); p->add( new Function( "average", average, p ) ); p->add( new Function( "bin", bin, p ) ); p->add( new Function( "cbrt", 1, cbrt, p ) ); p->add( new Function( "ceil", 1, ceil, p ) ); p->add( new Function( "dec", dec, p ) ); p->add( new Function( "floor", 1, floor, p ) ); p->add( new Function( "frac", 1, frac, p ) ); p->add( new Function( "gamma", Gamma, p ) ); p->add( new Function( "geomean", geomean, p ) ); p->add( new Function( "hex", hex, p ) ); p->add( new Function( "int", 1, integer, p ) ); p->add( new Function( "lngamma", lnGamma, p ) ); p->add( new Function( "max", max, p ) ); p->add( new Function( "min", min, p ) ); p->add( new Function( "oct", oct, p ) ); p->add( new Function( "product", product, p ) ); p->add( new Function( "round", round, p ) ); p->add( new Function( "sign", 1, sign, p ) ); p->add( new Function( "sqrt", 1, sqrt, p ) ); p->add( new Function( "sum", sum, p ) ); p->add( new Function( "trunc", trunc, p ) ); // LOGARITHM p->add( new Function( "arcosh", 1, arcosh, p ) ); p->add( new Function( "arsinh", 1, arsinh, p ) ); p->add( new Function( "artanh", 1, artanh, p ) ); p->add( new Function( "cosh", 1, cosh, p ) ); p->add( new Function( "exp", 1, exp, p ) ); p->add( new Function( "lg", 1, lg, p ) ); p->add( new Function( "ln", 1, ln, p ) ); p->add( new Function( "log", 1, log, p ) ); p->add( new Function( "sinh", 1, sinh, p ) ); p->add( new Function( "tanh", 1, tanh, p ) ); // DISCRETE p->add( new Function( "gcd", gcd, p ) ); p->add( new Function( "ncr", 2, nCr, p ) ); p->add( new Function( "npr", 2, nPr, p ) ); // PROBABILITY p->add( new Function( "binomcdf", 3, binomcdf, p ) ); p->add( new Function( "binommean", 2, binommean, p ) ); p->add( new Function( "binompmf", 3, binompmf, p ) ); p->add( new Function( "binomvar", 2, binomvar, p ) ); p->add( new Function( "erf", 1, erf, p ) ); p->add( new Function( "erfc", 1, erfc, p ) ); p->add( new Function( "hypercdf", 4, hypercdf, p ) ); p->add( new Function( "hypermean", 3, hypermean, p ) ); p->add( new Function( "hyperpmf", 4, hyperpmf, p ) ); p->add( new Function( "hypervar", 3, hypervar, p ) ); p->add( new Function( "poicdf", 2, poicdf, p ) ); p->add( new Function( "poimean", 1, poimean, p ) ); p->add( new Function( "poipmf", 2, poipmf, p ) ); p->add( new Function( "poivar", 1, poivar, p ) ); // TRIGONOMETRY p->add( new Function( "acos", 1, acos, p ) ); p->add( new Function( "asin", 1, asin, p ) ); p->add( new Function( "atan", 1, atan, p ) ); p->add( new Function( "cos", 1, cos, p ) ); p->add( new Function( "cot", 1, cot, p ) ); p->add( new Function( "csc", 1, csc, p ) ); p->add( new Function( "degrees", 1, degrees, p ) ); p->add( new Function( "radians", 1, radians, p ) ); p->add( new Function( "sec", 1, sec, p ) ); p->add( new Function( "sin", 1, sin, p ) ); p->add( new Function( "tan", 1, tan, p ) ); // LOGIC p->add( new Function( "mask", 2, mask, p ) ); p->add( new Function( "unmask", 2, unmask, p ) ); p->add( new Function( "not", 1, not_, p ) ); p->add( new Function( "and", and_, p ) ); p->add( new Function( "or", or_, p ) ); p->add( new Function( "xor", xor_, p ) ); p->add( new Function( "shl", 2, ashl, p ) ); p->add( new Function( "shr", 2, ashr, p ) ); p->add( new Function( "idiv", 2, idiv, p ) ); p->add( new Function( "mod", 2, mod, p ) ); } // public (Functions) Functions::Functions( char angleMode, QObject * parent ) : QObject( parent ), d( new Functions::Private ) { d->p = this; setAngleMode( angleMode ); d->createBuiltInFunctions(); retranslateText(); } void Functions::add( Function * f ) { if ( f ) d->functions.insert( f->name().toUpper(), f ); } Function * Functions::function( const QString & name ) const { return d->functions.value( name.toUpper(), 0 ); } QStringList Functions::functionNames() const { QStringList result; QHashIterator it( d->functions ); while ( it.hasNext() ) { it.next(); result.append( it.key().toLower() ); } return result; } Functions::~Functions() { QList values = d->functions.values(); for ( int i = 0; i < values.size(); i++ ) delete values[i]; delete d; } char Functions::angleMode() { return d->angleMode; } void Functions::setAngleMode( char c ) { d->angleMode = c; } void Functions::retranslateText() { // ANALYSIS function( "abs" )->setDescription( tr( "Absolute Value" ) ); function( "average" )->setDescription( tr( "Average (Arithmetic Mean)" ) ); function( "bin" )->setDescription( tr( "Binary Representation" ) ); function( "cbrt" )->setDescription( tr( "Cube Root" ) ); function( "ceil" )->setDescription( tr( "Ceiling" ) ); function( "dec" )->setDescription( tr( "Decimal Representation" ) ); function( "floor" )->setDescription( tr( "Floor" ) ); function( "frac" )->setDescription( tr( "Fractional Part" ) ); function( "gamma" )->setDescription( tr( "Extension of Factorials [= (x-1)!]" ) ); function( "geomean" )->setDescription( tr( "Geometric Mean" ) ); function( "hex" )->setDescription( tr( "Hexadecimal Representation" ) ); function( "int" )->setDescription( tr( "Integer Part" ) ); function( "lngamma" )->setDescription( tr( "ln(abs(Gamma))" ) ); function( "max" )->setDescription( tr( "Maximum" ) ); function( "min" )->setDescription( tr( "Minimum" ) ); function( "oct" )->setDescription( tr( "Octal Representation" ) ); function( "product" )->setDescription( tr( "Product" ) ); function( "round" )->setDescription( tr( "Rounding" ) ); function( "sign" )->setDescription( tr( "Signum" ) ); function( "sqrt" )->setDescription( tr( "Square Root" ) ); function( "sum" )->setDescription( tr( "Sum" ) ); function( "trunc" )->setDescription( tr( "Truncation" ) ); //// LOGARITHM function( "arcosh" )->setDescription( tr( "Area Hyperbolic Cosine" ) ); function( "arsinh" )->setDescription( tr( "Area Hyperbolic Sine" ) ); function( "artanh" )->setDescription( tr( "Area Hyperbolic Tangent" ) ); function( "cosh" )->setDescription( tr( "Hyperbolic Cosine" ) ); function( "exp" )->setDescription( tr( "Exponential" ) ); function( "lg" )->setDescription( tr( "Base-2 Logarithm" ) ); function( "ln" )->setDescription( tr( "Natural Logarithm" ) ); function( "log" )->setDescription( tr( "Base-10 Logarithm" ) ); function( "sinh" )->setDescription( tr( "Hyperbolic Sine" ) ); function( "tanh" )->setDescription( tr( "Hyperbolic Tangent" ) ); //// DISCRETE function( "gcd" )->setDescription( tr( "Greatest Common Divisor" ) ); function( "ncr" )->setDescription( tr( "Combination (Binomial Coefficient)" ) ); function( "npr" )->setDescription( tr( "Permutation (Arrangement)" ) ); //// PROBABILITY function( "binomcdf" )->setDescription( tr( "Binomial Cumulative Distribution Function" ) ); function( "binommean" )->setDescription( tr( "Binomial Distribution Mean" ) ); function( "binompmf" )->setDescription( tr( "Binomial Probability Mass Function" ) ); function( "binomvar" )->setDescription( tr( "Binomial Distribution Variance" ) ); function( "erf" )->setDescription( tr( "Error Function" ) ); function( "erfc" )->setDescription( tr( "Complementary Error Function" ) ); function( "hypercdf" )->setDescription( tr( "Hypergeometric Cumulative Distribution Function" ) ); function( "hypermean" )->setDescription( tr( "Hypergeometric Distribution Mean" ) ); function( "hyperpmf" )->setDescription( tr( "Hypergeometric Probability Mass Function" ) ); function( "hypervar" )->setDescription( tr( "Hypergeometric Distribution Variance" ) ); function( "poicdf" )->setDescription( tr( "Poissonian Cumulative Distribution Function" ) ); function( "poimean" )->setDescription( tr( "Poissonian Distribution Mean" ) ); function( "poipmf" )->setDescription( tr( "Poissonian Probability Mass Function" ) ); function( "poivar" )->setDescription( tr( "Poissonian Distribution Variance" ) ); //// TRIGONOMETRY function( "acos" )->setDescription( tr( "Arc Cosine" ) ); function( "asin" )->setDescription( tr( "Arc Sine" ) ); function( "atan" )->setDescription( tr( "Arc Tangent" ) ); function( "cos" )->setDescription( tr( "Cosine" ) ); function( "cot" )->setDescription( tr( "Cotangent" ) ); function( "csc" )->setDescription( tr( "Cosecant" ) ); function( "degrees" )->setDescription( tr( "Degrees of Arc" ) ); function( "radians" )->setDescription( tr( "Radians" ) ); function( "sec" )->setDescription( tr( "Secant" ) ); function( "sin" )->setDescription( tr( "Sine" ) ); function( "tan" )->setDescription( tr( "Tangent" ) ); //// LOGIC function( "mask" )->setDescription( tr( "Mask to a bit size" ) ); function( "unmask" )->setDescription( tr( "Sign-extent a value" ) ); function( "not" )->setDescription( tr( "Logical NOT" ) ); function( "and" )->setDescription( tr( "Logical AND" ) ); function( "or" )->setDescription( tr( "Logical OR" ) ); function( "xor" )->setDescription( tr( "Logical XOR" ) ); function( "shl" )->setDescription( tr( "Arithmetic Shift Left" ) ); function( "shr" )->setDescription( tr( "Arithmetic Shift Right" ) ); function( "idiv" )->setDescription( tr( "Integer Quotient" ) ); function( "mod" )->setDescription( tr( "Modulo" ) ); } speedcrunch-0.10.1/src/base/constants.cpp0000644000175000001440000002122011015364561017476 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "constants.hxx" #include struct Constants::Private { QList constantList; QStringList categoryList; void createConstants(); }; void Constants::Private::createConstants() { constantList.clear(); categoryList.clear(); // http://en.wikipedia.org/wiki/Physical_constant#Table_of_universal_constants constantList += Constant( Constants::tr( "Characteristic Impedance of Vacuum" ), "376.730313461", "ohm", Constants::tr( "General Physics" ) ); constantList += Constant( Constants::tr( "Electric Constant" ), "8.854187817e-12", "F/m", Constants::tr( "General Physics" ) ); constantList += Constant( Constants::tr( "Magnetic Constant" ), "1.256637061e-6", "N/A^2", Constants::tr( "General Physics" ) ); constantList += Constant( Constants::tr( "Gravitation Constant" ), "6.67428e-11", "m^3/(kg s^2)", Constants::tr( "General Physics" ) ); constantList += Constant( Constants::tr( "Planck's Constant" ), "6.62606896e-34", "J s", Constants::tr( "General Physics" ) ); constantList += Constant( Constants::tr( "Dirac's Constant" ), "1.054571628e-34", "J s", Constants::tr( "General Physics" ) ); constantList += Constant( Constants::tr( "Speed of Light in Vacuum" ), "299792458", "m/s", Constants::tr( "General Physics" ) ); // http://en.wikipedia.org/wiki/Physical_constant#Table_of_electromagnetic_constants constantList += Constant( Constants::tr( "Bohr-Procopiu Magneton" ), "927.400949e-26", "J/T", Constants::tr( "Electromagnetic" ) ); constantList += Constant( Constants::tr( "Conductance Quantum" ), "7.748091733e-5", "S", Constants::tr( "Electromagnetic" ) ); constantList += Constant( Constants::tr( "Coulomb's Constant" ), "8.987742438e9", "N m^2/C^2", Constants::tr( "Electromagnetic" ) ); constantList += Constant( Constants::tr( "Elementary Charge" ), "1.60217653e-19", "C", Constants::tr( "Electromagnetic" ) ); constantList += Constant( Constants::tr( "Josephson Constant" ), "483597.879e9", "Hz/V", Constants::tr( "Electromagnetic" ) ); constantList += Constant( Constants::tr( "Magnetic Flux Quantum" ), "2.06783372e-15", "Wb", Constants::tr( "Electromagnetic" ) ); constantList += Constant( Constants::tr( "Nuclear Magneton" ), "5.05078343e-27", "J/T", Constants::tr( "Electromagnetic" ) ); constantList += Constant( Constants::tr( "Resistance Quantum" ), "12906.403725", "ohm", Constants::tr( "Electromagnetic" ) ); constantList += Constant( Constants::tr( "von Klitzing Constant" ), "25812.807449", "ohm", Constants::tr( "Electromagnetic" ) ); // http://en.wikipedia.org/wiki/Physical_constant#Table_of_atomic_and_nuclear_constants constantList += Constant( Constants::tr( "Bohr Radius" ), "0.5291772108e-10", "m", Constants::tr( "Atomic & Nuclear" ) ); constantList += Constant( Constants::tr( "Fermi Coupling Constant" ), "1.16639e-5", "Ge/V^2", Constants::tr( "Atomic & Nuclear" ) ); constantList += Constant( Constants::tr( "Fine-structure Constant" ), "7.297352568e-3", QString(), Constants::tr( "Atomic & Nuclear" ) ); constantList += Constant( Constants::tr( "Hartree Energy" ), "4.35974417e-18", "J", Constants::tr( "Atomic & Nuclear" ) ); constantList += Constant( Constants::tr( "Quantum of Circulation" ), "3.636947550e-4", "m^2/s", Constants::tr( "Atomic & Nuclear" ) ); constantList += Constant( Constants::tr( "Rydberg Constant" ), "10973731.568525", "m^(-1)", Constants::tr( "Atomic & Nuclear" ) ); constantList += Constant( Constants::tr( "Thomson Cross Section" ), "0.665245873e-28", "m^2", Constants::tr( "Atomic & Nuclear" ) ); constantList += Constant( Constants::tr( "Weak Mixing Angle" ), "0.22215", QString(), Constants::tr( "Atomic & Nuclear" ) ); // http://en.wikipedia.org/wiki/Physical_constant#Table_of_physico-chemical_constants constantList += Constant( Constants::tr( "Atomic Mass Unit" ), "1.66053886e-27", "kg", Constants::tr( "Physico-chemical" ) ); constantList += Constant( Constants::tr( "Avogadro's Number" ), "6.0221415e23", QString(), Constants::tr( "Physico-chemical" ) ); constantList += Constant( Constants::tr( "Boltzmann Constant" ), "1.3806505e-23", "J/K", Constants::tr( "Physico-chemical" ) ); constantList += Constant( Constants::tr( "Faraday Constant" ), "96485.3383", "C/mol", Constants::tr( "Physico-chemical" ) ); constantList += Constant( Constants::tr( "First Radiation Constant" ), "3.74177138e-16", "W m^2", Constants::tr( "Physico-chemical" ) ); constantList += Constant( Constants::tr( "Loschmidt Constant" ), "2.6867773e25", "m^(-3)", Constants::tr( "Physico-chemical" ) ); constantList += Constant( Constants::tr( "Gas Constant" ), "8.314472", "J/(K mol)", Constants::tr( "Physico-chemical" ) ); constantList += Constant( Constants::tr( "Molar Planck Constant" ), "3.990312716e-10", "J s/mol", Constants::tr( "Physico-chemical" ) ); constantList += Constant( Constants::tr( "Second Radiation Constant" ), "1.4387752e-2", "m K", Constants::tr( "Physico-chemical" ) ); constantList += Constant( Constants::tr( "Stefan-Boltzmann Constant" ), "5.670400e-8", "W/(m^2 K^4)", Constants::tr( "Physico-chemical" ) ); // http://www.astronomynotes.com/tables/tablesa.htm constantList += Constant( Constants::tr( "Astronomical Unit" ), "149597870691", "m", Constants::tr( "Astronomy" ) ); constantList += Constant( Constants::tr( "Light Year" ), "9.4607304725808e15", "m", Constants::tr( "Astronomy" ) ); constantList += Constant( Constants::tr( "Parsec" ), "3.08567802e16", "m", Constants::tr( "Astronomy" ) ); constantList += Constant( Constants::tr( "Sidereal Year" ), "365.2564", Constants::tr( "days" ), Constants::tr( "Astronomy" ) ); constantList += Constant( Constants::tr( "Tropical Year" ), "365.2422", Constants::tr( "days" ), Constants::tr( "Astronomy" ) ); constantList += Constant( Constants::tr( "Gregorian Year" ), "365.2425", Constants::tr( "days" ), Constants::tr( "Astronomy" ) ); constantList += Constant( Constants::tr( "Earth Mass" ), "5.9736e24", "kg", Constants::tr( "Astronomy" ) ); constantList += Constant( Constants::tr( "Sun Mass" ), "1.9891e30", "kg", Constants::tr( "Astronomy" ) ); constantList += Constant( Constants::tr( "Mean Earth Radius" ), "6371000", "m", Constants::tr( "Astronomy" ) ); constantList += Constant( Constants::tr( "Sun Radius" ), "6.96265e8", "m", Constants::tr( "Astronomy" ) ); constantList += Constant( Constants::tr( "Sun Luminosity" ), "3.827e26", "W", Constants::tr( "Astronomy" ) ); for ( int k = 0; k < constantList.count(); k++ ) { QStringList cats = constantList[k].categories; for ( int i = 0; i < cats.count(); i++ ) if ( ! categoryList.contains( cats[i] ) ) categoryList += cats[i]; } categoryList.sort(); } Constants::Constants( QObject * parent ) : QObject( parent ), d( new Constants::Private ) { setObjectName( "Constants" ); d->createConstants(); } Constants::~Constants() { delete d; } QList Constants::constantList() const { return d->constantList; } QStringList Constants::categoryList() const { return d->categoryList; } // public slots void Constants::retranslateText() { d->createConstants(); } speedcrunch-0.10.1/src/base/errors.h0000644000175000001440000001103411015364561016445 0ustar helderusers/* errors.h global list of error codes Copyright (C) 2007, 2008 Wolf Lammen ookami1 gmx de This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _ERRORS_H #define _ERRORS_H #ifdef __cplusplus extern "C"{ #endif typedef enum { Success, /* a NaN or an empty Variant was submitted as a parameter. Only a few functions in the math engine accept such a value. All arithmetic functions fail on such an operand */ NoOperand, /* This error is returned if a result is mathematically defined, but cannot be computed reliably without extending the working precision considerably and/or requiring considerable computing time */ EvalUnstable, /* the result is in absolute value smaller than the smallest non-zero value the math engine can handle */ Underflow, /* the result is in absolute value bigger than the biggest number the math engine can handle */ Overflow, /* operation requests a division by zero, or a function was evaluated at a pole */ ZeroDivide, /* One or more parameters to a function lie outside of the function's domain */ OutOfDomain, /* a number exceeds the logic number range, so logic operations cannot be applied */ OutOfLogicRange, /* a number or a result exceeds the integer range */ OutOfIntegerRange, /* This error indicates a failed conversion from an ASCII string. Functions setting this error may also report a more detailed IO... error code*/ BadLiteral, /* A request to calculate something to more places than is (currently) acceptable */ InvalidPrecision, /* A parameter violates the limitations of the engine, or is completely meaningless, e.g. the evaluation of a quotient and a remainder in the same variable. This error indicates a bug, because the calling program should never submit such a parameter (combinations) */ InvalidParam, /* returned when an operation request is mathematically valid, but would require too much time */ TooExpensive, /* For correct conversion of a digit sequence, the IO routines need information about the radix to use. This error is returned if none was specified. This error indicates a bug, because a calling routine should always supply this information */ IONoBase, /* This error occurs if you request a two's complement conversion, and either additionally specify a sign, or gave a non-zero fraction */ IOInvalidComplement, /* You must specify at least one digit of the significant */ IONoSignificand, /* invalid characters in exponent, e.g. a decimal dot */ IOBadExp, /* the exponent exceeds the allowed range */ IOExpOverflow, /* internal (string) buffer overflow in a conversion. This indicates a bug because range checking should be done in advance */ IOBufferOverflow, /* request to convert more digits to another base than internal buffers can hold. This occurs when you try to convert huge values in fixpoint format */ IOConversionOverflow, /* request to convert a tiny number in fixpoint format, so that only leading zeros are displayed. */ IOConversionUnderflow, /* a function was called with the wrong count of parameters e.g. sin(12;13) (sin takes only 1 parameter) */ InvalidParamCount, /* parameter type mismatch */ TypeMismatch, /* cannot overwrite an existing key in a table */ // KeyExists, /* could not retrieve a symbol by the submitted key */ // SymbolNotFound, /* no matching close token for an open token */ // CloseSymbolMissing, /* unable to clone a symbol, most probably because it was of a special type, like a close parenthesis */ // SymbolCloneError, /* unable to perform a requested type cast */ // BadCast, /* used with variants, when an operation is not implemented for a particular data type */ // NotImplemented, /* this value is used internally to indicate the absence of any error information altogether */ NotAnError, } Error; #ifdef __cplusplus } #endif #endif /* _ERRORS_H */ speedcrunch-0.10.1/src/base/evaluator.cpp0000644000175000001440000012476411015364561017505 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2005-2006 Johan Thelin // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "evaluator.hxx" #include "functions.hxx" #ifdef _BISON # include "bison/bisonparser.cpp" #endif #include #include #include #include #include #include #include // #define EVALUATOR_DEBUG #ifdef EVALUATOR_DEBUG #include #include QTextStream& operator<<( QTextStream& s, HNumber num ) { char* str = HMath::formatFixed( num ); s << str; delete[] str; return s; } #endif class Opcode { public: enum { Nop = 0, Load, Ref, Function, Add, Sub, Neg, Mul, Div, Pow, Fact, Modulo, IntDiv }; unsigned type; unsigned index; Opcode(): type(Nop), index(0) {}; Opcode( unsigned t ): type(t), index(0) {}; Opcode( unsigned t, unsigned i ): type(t), index(i) {}; }; struct Evaluator::Private { Evaluator * p; Functions * functions; char radixChar; bool dirty; bool valid; QString expression; QString error; QString assignId; QVector codes; QStringList identifiers; QVector constants; QMap variables; }; class TokenStack : public QVector { public: TokenStack(); bool isEmpty() const; unsigned itemCount() const; void push( const Token& token ); Token pop(); const Token& top(); const Token& top( unsigned index ); private: void ensureSpace(); int topIndex; }; // for null token const Token Token::null; // helper function: return operator of given token text // e.g. "*" yields Operator::Asterisk, and so on static Token::Op matchOperator( const QString& text ) { Token::Op result = Token::InvalidOp; if( text.length() == 1 ) { QChar p = text[0]; switch( p.unicode() ) { case '+': result = Token::Plus ; break; case '-': result = Token::Minus ; break; case '*': result = Token::Asterisk ; break; case '/': result = Token::Slash ; break; case '^': result = Token::Caret ; break; case ';': result = Token::Semicolon ; break; case '(': result = Token::LeftPar ; break; case ')': result = Token::RightPar ; break; case '%': result = Token::Percent ; break; case '!': result = Token::Exclamation; break; case '=': result = Token::Equal ; break; default : result = Token::InvalidOp ; break; } } else if( text.length() == 2 ) { if( text == "**" ) result = Token::Caret; } #if 0 else if( text.length() == 3 ) { if (text == "mod") result = Token::Modulo; else if (text == "div") result = Token::Div; } #endif return result; } // helper function: give operator precedence // e.g. "+" is 1 while "*" is 3 static int opPrecedence( Token::Op op ) { int prec = -1; switch( op ) { case Token::Exclamation : prec = 8; break; case Token::Percent : prec = 8; break; case Token::Caret : prec = 7; break; case Token::Asterisk : prec = 5; break; case Token::Slash : prec = 6; break; case Token::Modulo : prec = 6; break; case Token::Div : prec = 6; break; case Token::Plus : prec = 3; break; case Token::Minus : prec = 3; break; case Token::RightPar : prec = 0; break; case Token::LeftPar : prec = -1; break; case Token::Semicolon : prec = 0; break; default : prec = -1; break; } return prec; } // creates a token Token::Token( Type type, const QString& text, int pos ) { m_type = type; m_text = text; m_pos = pos; } // copy constructor Token::Token( const Token& token ) { m_type = token.m_type; m_text = token.m_text; m_pos = token.m_pos; } // assignment operator Token& Token::operator=( const Token& token ) { m_type = token.m_type; m_text = token.m_text; m_pos = token.m_pos; return *this; } HNumber Token::asNumber() const { if( isNumber() ) return HNumber( (const char*) m_text.toLatin1() ); else return HNumber( 0 ); } Token::Op Token::asOperator() const { if( isOperator() ) return matchOperator( m_text ); else return InvalidOp; } QString Token::description() const { QString desc; switch ( m_type ) { case stxNumber : desc = "Number" ; break; case stxIdentifier : desc = "Identifier"; break; case stxOpenPar : //refty case stxClosePar : case stxSep : case stxOperator : desc = "Operator" ; break; default : desc = "Unknown" ; break; } while( desc.length() < 10 ) desc.prepend( ' ' ); desc.prepend( " " ); desc.prepend( QString::number( m_pos ) ); desc.append( " : " ).append( m_text ); return desc; } TokenStack::TokenStack(): QVector() { topIndex = 0; ensureSpace(); } bool TokenStack::isEmpty() const { return topIndex == 0; } unsigned TokenStack::itemCount() const { return topIndex; } void TokenStack::push( const Token& token ) { ensureSpace(); (*this)[ topIndex++ ] = token; } Token TokenStack::pop() { return (topIndex > 0 ) ? Token( at( --topIndex ) ) : Token(); } const Token& TokenStack::top() { return top( 0 ); } const Token& TokenStack::top( unsigned index ) { if( topIndex > (int)index ) return at( topIndex-index-1 ); return Token::null; } void TokenStack::ensureSpace() { while( topIndex >= size() ) resize( size() + 10 ); } // helper function: return true for valid identifier character static bool isIdentifier( QChar ch ) { return (ch.unicode() == '_') || (ch.unicode() == '$') || (ch.isLetter()); } // Constructor Evaluator::Evaluator( Functions * f, char radixChar, QObject * parent ) : QObject( parent ), d( new Evaluator::Private ) { d->p = this; d->functions = f; if ( radixChar == 'C' ) d->radixChar = QLocale().decimalPoint().toAscii(); else d->radixChar = radixChar; clear(); #ifdef _BISON QStringList script; script << "\\escape \\(\\\"@\\\"\\)" << "@def @(@\"\"@\"@;@\"\"@\"@;@\"\"@\"@)" << "@def @(\"(\"@;\"(\"@;\")\"@)" << "@def (\";\"@;\";\")" << "@def (\"def\";\"def\")" << "def(\"escape\";\"esc\")" << "esc \"\\\"" << "def(\",\";\"0,\")" << "\\undef (\"esc\"; 0,00)" << "\\def (\".\";\".\")" << "\\def (\".\";\"0.\")" << "\\def (\"e\";\"0e\")" << "\\def (\"p\";\"0p\")" << "\\def (\"x\";\"0x\")" << "\\def (\"xs\";\"0xs\")" << "\\sin 0.3e1" << "0x2Fp2" << "0xsF0" << "\\def (\"posscale\"; \"1+\")" << "\\def (\"negscale\"; \"1-\")" << "2e-1" << "\\def (\"-\";\"-\")" << "-1" << "\\overload (\"add\";\"-\")" << "-1-2" << "\\def (\"!\";\"!\")" << "-1!" << "\\def (\"pi\";\"pi\")" << "\\def (\"sin\";\"sin\")" << "sin pi" ; SglExprLex::self().run(script); #endif } // Destructor Evaluator::~Evaluator() { delete d; } // Sets a new expression // note that both the real lex and parse processes will happen later on // when needed (i.e. "lazy parse"), for example during evaluation. void Evaluator::setExpression( const QString& expr ) { #ifdef _BISON SglExprLex::self().setExpression(expr); #endif d->expression = expr; d->dirty = true; d->valid = false; d->error = QString(); } // Returns the expression QString Evaluator::expression() const { return d->expression; } // Returns the validity // note: empty expression is always invalid. bool Evaluator::isValid() const { if( d->dirty ) { Tokens tokens = scan( d->expression ); if( !tokens.valid() ) compile( tokens ); else d->valid = false; } return d->valid; } // Clears everything, also mark it as invalid. void Evaluator::clear() { d->expression = QString(); d->dirty = true; d->valid = false; d->error = QString(); d->constants.clear(); d->codes.clear(); d->assignId = QString(); clearVariables(); } // Returns error message QString Evaluator::error() const { return d->error; } // Returns list of token for the expression. // this triggers again the lexical analysis step. it is however preferable // (even when there's small performance penalty) because otherwise we need to // store parsed tokens all the time which serves no good purpose. Tokens Evaluator::tokens() const { return scan( d->expression ); } Tokens Evaluator::scan( const QString& expr ) const { // to hold the result Tokens tokens; // auto-detect, always dot, or always comma QChar wrongDecimalPoint; //decimalPoint = Settings::self()->dot(); // sanity check for wrong decimal separator usage if ( d->radixChar == ',' ) wrongDecimalPoint = '.'; else wrongDecimalPoint = ','; int size = expr.size(); for ( int i = 0; i < size; i++ ) if ( expr[i] == wrongDecimalPoint ) return tokens; // parsing state enum { Start, Finish, Bad, InNumber, InHexa, InOctal, InBinary, InDecimal, InExpIndicator, InExponent, InIdentifier } state; // initialize variables state = Start; int i = 0; QString ex = expr; QString tokenText; int tokenStart = 0; Token::Type type; // force a terminator ex.append( QChar() ); // main loop while( (state != Bad) && (state != Finish) && (i < ex.length()) ) { QChar ch = ex.at(i); switch( state ) { case Start: tokenStart = i; // skip any whitespaces if( ch.isSpace() ) i++; // check for number else if( ch.isDigit() ) { state = InNumber; } else if ( ch == '#' ) // simple hexadec notation { tokenText.append( "0x" ); state = InHexa; i++; } // decimal dot ? else if ( ch == d->radixChar ) { tokenText.append( ex.at(i++) ); state = InDecimal; } // terminator character else if ( ch.isNull() ) state = Finish; // look for operator match else { int op; QString s; #if 0 // check for three-chars operator s.append( ch ).append( ex.at(i+1) ).append( ex.at(i+2) ); op = matchOperator( s ); // check for two-chars operator if( op == Token::InvalidOp ) #endif { s = QString( ch ).append( ex.at(i+1) ); op = matchOperator( s ); } // check for one-char operator if( op == Token::InvalidOp ) { s = QString( ch ); op = matchOperator( s ); } // any matched operator ? if( op != Token::InvalidOp ) { switch(op) //refty { case Token::LeftPar: type = Token::stxOpenPar; break; case Token::RightPar: type = Token::stxClosePar; break; case Token::Semicolon: type = Token::stxSep; break; default: type = Token::stxOperator; } int len = s.length(); i += len; tokens.append( Token( type, s.left( len ), tokenStart ) ); } else state = Bad; } // beginning with unknown alphanumeric ? // could be identifier, or function... if( state == Bad && isIdentifier( ch ) ) { state = InIdentifier; } break; case InIdentifier: // consume as long as alpha, dollar sign, underscore, or digit if( isIdentifier( ch ) || ch.isDigit() ) tokenText.append( ex.at( i++ ) ); // we're done with identifier else { tokens.append( Token( Token::stxIdentifier, tokenText, tokenStart ) ); tokenStart = i; tokenText = ""; state = Start; } break; case InNumber: // consume as long as it's digit if( ch.isDigit() ) tokenText.append( ex.at(i++) ); // convert decimal separator to '.' else if( ch == d->radixChar ) { tokenText.append( '.' ); i++; state = InDecimal; } // exponent ? else if( ch.toUpper() == 'E' ) { tokenText.append( 'E' ); i++; state = InExpIndicator; } else if (ch.toUpper() == 'X' && tokenText == "0") // normal hexadec notation { tokenText.append( 'x' ); i++; state = InHexa; } else if (ch.toUpper() == 'B' && tokenText == "0") // binary notation { tokenText.append( 'b' ); i++; state = InBinary; } else if (ch.toUpper() == 'O' && tokenText == "0") // octal notation { tokenText.append( 'o' ); i++; state = InOctal; } else if (ch.toUpper() == 'D' && tokenText == "0") // explicit decimal notation { // we also need to get rid of the leading zero tokenText = ""; i++; } // we're done with integer number else { tokens.append( Token( Token::stxNumber, tokenText, tokenStart ) ); tokenText = ""; state = Start; } break; case InHexa: if (ch.isDigit() || (ch >= 'A' && ch < 'G') || (ch >= 'a' && ch < 'g')) tokenText.append( ex.at(i++).toUpper() ); else // we're done with hexa number { tokens.append( Token( Token::stxNumber, tokenText, tokenStart ) ); tokenText = ""; state = Start; } break; case InBinary: if (ch == '0' || ch == '1') // very strict rule ;) tokenText.append( ex.at(i++) ); else // we're done with binary number { tokens.append( Token( Token::stxNumber, tokenText, tokenStart ) ); tokenText = ""; state = Start; } break; case InOctal: if (ch >= '0' && ch < '8') // octal has only 8 digits, 8 & 9 are invalid tokenText.append( ex.at(i++) ); else // we're done with octal number { tokens.append( Token( Token::stxNumber, tokenText, tokenStart ) ); tokenText = ""; state = Start; } break; case InDecimal: // consume as long as it's digit if( ch.isDigit() ) tokenText.append( ex.at(i++) ); // exponent ? else if( ch.toUpper() == 'E' ) { tokenText.append( 'E' ); i++; state = InExpIndicator; } // we're done with floating-point number else { tokens.append( Token( Token::stxNumber, tokenText, tokenStart ) ); tokenText = ""; state = Start; }; break; case InExpIndicator: // possible + or - right after E, e.g 1.23E+12 or 4.67E-8 if( ( ch == '+' ) || ( ch == '-' ) ) tokenText.append( ex.at(i++) ); // consume as long as it's digit else if( ch.isDigit() ) state = InExponent; // invalid thing here else state = Bad; break; case InExponent: // consume as long as it's digit if( ch.isDigit() ) tokenText.append( ex.at(i++) ); // we're done with floating-point number else { tokens.append( Token( Token::stxNumber, tokenText, tokenStart ) ); tokenText = ""; state = Start; }; break; case Bad: // bad bad bad tokens.setValid( false ); break; default: break; }; }; return tokens; } void Evaluator::compile( const Tokens& tokens ) const { #ifdef EVALUATOR_DEBUG QFile debugFile( "eval.log" ); debugFile.open( QIODevice::WriteOnly ); QTextStream dbg( &debugFile ); #endif // initialize variables d->dirty = false; d->valid = false; d->codes.clear(); d->constants.clear(); d->identifiers.clear(); d->error = QString(); // sanity check if( tokens.count() == 0 ) return; TokenStack syntaxStack; QStack argStack; unsigned argCount = 1; for( int i = 0; i <= tokens.count(); i++ ) { // helper token: InvalidOp is end-of-expression Token token = ( i < tokens.count() ) ? tokens[i] : Token( Token::stxOperator ); Token::Type tokenType = token.type(); if (tokenType >= Token::stxOperator) tokenType = Token::stxOperator; #ifdef EVALUATOR_DEBUG dbg << "\n"; dbg << "Token: " << token.description() << "\n"; #endif // unknown token is invalid if( tokenType == Token::stxUnknown ) break; // for constants, push immediately to stack // generate code to load from a constant if ( tokenType == Token::stxNumber ) { syntaxStack.push( token ); d->constants.append( token.asNumber() ); d->codes.append( Opcode( Opcode::Load, d->constants.count()-1 ) ); #ifdef EVALUATOR_DEBUG dbg << " Push " << token.asNumber() << " to constant pools" << "\n"; #endif } // for identifier, push immediately to stack // generate code to load from reference if( tokenType == Token::stxIdentifier ) { syntaxStack.push( token ); d->identifiers.append( token.text() ); d->codes.append( Opcode( Opcode::Ref, d->identifiers.count()-1 ) ); #ifdef EVALUATOR_DEBUG dbg << " Push " << token.text() << " to identifier pools" << "\n"; #endif } // special case for percentage if( tokenType == Token::stxOperator ) if( token.asOperator() == Token::Percent ) if( syntaxStack.itemCount() >= 1 ) if( !syntaxStack.top().isOperator() ) { d->constants.append( HNumber("0.01") ); d->codes.append( Opcode( Opcode::Load, d->constants.count()-1 ) ); d->codes.append( Opcode( Opcode::Mul ) ); #ifdef EVALUATOR_DEBUG dbg << " Handling percentage" << "\n"; #endif } // for any other operator, try to apply all parsing rules if( tokenType == Token::stxOperator ) if( token.asOperator() != Token::Percent ) { #ifdef EVALUATOR_DEBUG dbg << " Checking rules..." << "\n"; #endif // repeat until no more rule applies bool argHandled = false; for( ; ; ) { bool ruleFound = false; // rule for function last argument: // id ( arg ) -> arg if( !ruleFound ) if( syntaxStack.itemCount() >= 4 ) { Token par2 = syntaxStack.top(); Token arg = syntaxStack.top( 1 ); Token par1 = syntaxStack.top( 2 ); Token id = syntaxStack.top( 3 ); if( par2.asOperator() == Token::RightPar ) if( !arg.isOperator() ) if( par1.asOperator() == Token::LeftPar ) if( id.isIdentifier() ) { ruleFound = true; syntaxStack.pop(); syntaxStack.pop(); syntaxStack.pop(); syntaxStack.pop(); syntaxStack.push( arg ); d->codes.append( Opcode( Opcode::Function, argCount ) ); #ifdef EVALUATOR_DEBUG dbg << " Rule for function last argument " << argCount << " \n"; #endif argCount = argStack.empty() ? 0 : argStack.pop(); } } // are we entering a function ? // if token is operator, and stack already has: id ( arg if( !ruleFound ) if( !argHandled ) if( tokenType == Token::stxOperator ) if( syntaxStack.itemCount() >= 3 ) { Token arg = syntaxStack.top(); Token par = syntaxStack.top( 1 ); Token id = syntaxStack.top( 2 ); if( !arg.isOperator() ) if( par.asOperator() == Token::LeftPar ) if( id.isIdentifier() ) { ruleFound = true; argStack.push( argCount ); argCount = 1; #ifdef EVALUATOR_DEBUG dbg << " Entering function " << argCount << " \n"; #endif break; } } // rule for postfix operators if( !ruleFound ) if( syntaxStack.itemCount() >= 2 ) { Token postfix = syntaxStack.top(); Token y = syntaxStack.top( 1 ); if ( postfix.isOperator() ) if ( !y.isOperator() ) switch ( postfix.asOperator() ) { case Token::Exclamation: ruleFound = true; syntaxStack.pop(); syntaxStack.pop(); syntaxStack.push(y); d->codes.append( Opcode( Opcode::Fact ) ); #ifdef EVALUATOR_DEBUG dbg << " Rule for postfix operator" << "\n"; #endif break; default:; } } // rule for parenthesis: ( Y ) -> Y if( !ruleFound ) if( syntaxStack.itemCount() >= 3 ) { Token right = syntaxStack.top(); Token y = syntaxStack.top( 1 ); Token left = syntaxStack.top( 2 ); if( right.isOperator() ) if( !y.isOperator() ) if( left.isOperator() ) if( right.asOperator() == Token::RightPar ) if( left.asOperator() == Token::LeftPar ) { ruleFound = true; syntaxStack.pop(); syntaxStack.pop(); syntaxStack.pop(); syntaxStack.push( y ); #ifdef EVALUATOR_DEBUG dbg << " Rule for (Y) -> Y" << "\n"; #endif } } // rule for simplified syntax for function e.g. "sin pi" or "cos 1.2" // i.e no need for parentheses like "sin(pi)" or "cos(1.2)" if( !ruleFound ) if( syntaxStack.itemCount() >= 2 ) { Token arg = syntaxStack.top(); Token id = syntaxStack.top( 1 ); if( !arg.isOperator() ) if( id.isIdentifier() ) if( d->functions->function( id.text() ) ) { ruleFound = true; d->codes.append( Opcode( Opcode::Function, 1 ) ); syntaxStack.pop(); syntaxStack.pop(); syntaxStack.push( arg ); #ifdef EVALUATOR_DEBUG dbg << " Rule for simplified function syntax" << "\n"; #endif } } // rule for unary operator in simplified function syntax // this handles case like "sin -90" if( !ruleFound ) if( syntaxStack.itemCount() >= 3 ) { Token x = syntaxStack.top(); Token op = syntaxStack.top( 1 ); Token id = syntaxStack.top( 2 ); if( !x.isOperator() ) if( op.isOperator() ) if( id.isIdentifier() ) if( d->functions->function( id.text() ) ) if( ( op.asOperator() == Token::Plus ) || ( op.asOperator() == Token::Minus ) ) { ruleFound = true; syntaxStack.pop(); syntaxStack.pop(); syntaxStack.push( x ); if( op.asOperator() == Token::Minus ) d->codes.append( Opcode( Opcode::Neg ) ); #ifdef EVALUATOR_DEBUG dbg << " Rule for unary operator in simplified function syntax" << "\n"; #endif } } #if 0 // rule for unary postfix operator in simplified function syntax // this handles case like "sin 90!" if( !ruleFound ) if( syntaxStack.itemCount() >= 3 ) { Token op = syntaxStack.top(); Token x = syntaxStack.top( 1 ); Token id = syntaxStack.top( 2 ); if( id.isIdentifier() && d->functions->function( id.text() ) ) { if( !x.isOperator() && op.isOperator() && op.asOperator() == Token::Exclamation ) { ruleFound = true; syntaxStack.pop(); syntaxStack.pop(); syntaxStack.push( x ); d->codes.append( Opcode( Opcode::Fact ) ); #ifdef EVALUATOR_DEBUG dbg << " Rule for unary operator in simplified function syntax" << "\n"; #endif } } } #endif // rule for function arguments, if token is , or ) // id ( arg1 ; arg2 -> id ( arg if( !ruleFound ) if( syntaxStack.itemCount() >= 5 ) if( ( token.asOperator() == Token::RightPar ) || ( token.asOperator() == Token::Semicolon ) ) { Token arg2 = syntaxStack.top(); Token sep = syntaxStack.top( 1 ); Token arg1 = syntaxStack.top( 2 ); Token par = syntaxStack.top( 3 ); Token id = syntaxStack.top( 4 ); if( !arg2.isOperator() ) if( sep.asOperator() == Token::Semicolon ) if( !arg1.isOperator() ) if( par.asOperator() == Token::LeftPar ) if( id.isIdentifier() ) { ruleFound = true; argHandled = true; syntaxStack.pop(); syntaxStack.pop(); argCount++; #ifdef EVALUATOR_DEBUG dbg << " Rule for function argument " << argCount << " \n"; #endif } } // rule for function call with parentheses, but without argument // e.g. "2*PI()" if( !ruleFound ) if( syntaxStack.itemCount() >= 3 ) { Token par2 = syntaxStack.top(); Token par1 = syntaxStack.top( 1 ); Token id = syntaxStack.top( 2 ); if( par2.asOperator() == Token::RightPar ) if( par1.asOperator() == Token::LeftPar ) if( id.isIdentifier() ) { ruleFound = true; syntaxStack.pop(); syntaxStack.pop(); syntaxStack.pop(); syntaxStack.push( Token( Token::stxNumber ) ); d->codes.append( Opcode( Opcode::Function, 0 ) ); #ifdef EVALUATOR_DEBUG dbg << " Rule for function call with parentheses, but without argument" << "\n"; #endif } } // rule for binary operator: A (op) B -> A // conditions: precedence of op >= precedence of token // action: push (op) to result // e.g. "A * B" becomes "A" if token is operator "+" // exception: for caret (power operator), if op is another caret // then the rule doesn't apply, e.g. "2^3^2" is evaluated as "2^(3^2)" if( !ruleFound ) if( syntaxStack.itemCount() >= 3 ) { Token b = syntaxStack.top(); Token op = syntaxStack.top( 1 ); Token a = syntaxStack.top( 2 ); if( !a.isOperator() ) if( !b.isOperator() ) if( op.isOperator() ) if( token.asOperator() != Token::LeftPar ) if( token.asOperator() != Token::Caret ) if( opPrecedence( op.asOperator() ) >= opPrecedence( token.asOperator() ) ) { ruleFound = true; syntaxStack.pop(); syntaxStack.pop(); syntaxStack.pop(); syntaxStack.push( b ); switch( op.asOperator() ) { // simple binary operations case Token::Plus: d->codes.append( Opcode::Add ); break; case Token::Minus: d->codes.append( Opcode::Sub ); break; case Token::Asterisk: d->codes.append( Opcode::Mul ); break; case Token::Slash: d->codes.append( Opcode::Div ); break; case Token::Caret: d->codes.append( Opcode::Pow ); break; case Token::Modulo: d->codes.append( Opcode::Modulo ); break; case Token::Div: d->codes.append( Opcode::IntDiv ); break; default: break; }; #ifdef EVALUATOR_DEBUG dbg << " Rule for binary operator" << "\n"; #endif } } // rule for unary operator: (op1) (op2) X -> (op1) X // conditions: op2 is unary, token is not '(' // action: push (op2) to result // e.g. "* - 2" becomes "*" if( !ruleFound ) if( token.asOperator() != Token::LeftPar ) if( syntaxStack.itemCount() >= 3 ) { Token x = syntaxStack.top(); Token op2 = syntaxStack.top( 1 ); Token op1 = syntaxStack.top( 2 ); if( !x.isOperator() && op1.isOperator() && op2.isOperator() && ( op2.asOperator() == Token::Plus || op2.asOperator() == Token::Minus ) ) { ruleFound = true; if( op2.asOperator() == Token::Minus ) d->codes.append( Opcode( Opcode::Neg ) ); } #if 0 else // maybe postfix { x = op2; op2 = syntaxStack.top(); if( !x.isOperator() && op1.isOperator() && op2.isOperator() && op2.asOperator() == Token::Exclamation ) { ruleFound = true; d->codes.append( Opcode( Opcode::Fact ) ); } } #endif if (ruleFound) { syntaxStack.pop(); syntaxStack.pop(); syntaxStack.push( x ); #ifdef EVALUATOR_DEBUG dbg << " Rule for unary operator" << "\n"; #endif } } // auxiliary rule for unary operator: (op) X -> X // conditions: op is unary, op is first in syntax stack, token is not '(' or '^' or '!' // action: push (op) to result if( !ruleFound ) if( token.asOperator() != Token::LeftPar ) // if( token.asOperator() != Token::Caret ) if( token.asOperator() != Token::Exclamation) if( syntaxStack.itemCount() == 2 ) { Token x = syntaxStack.top(); Token op = syntaxStack.top( 1 ); if( !x.isOperator() && op.isOperator() && ( op.asOperator() == Token::Plus || op.asOperator() == Token::Minus ) ) { ruleFound = true; if( op.asOperator() == Token::Minus ) d->codes.append( Opcode( Opcode::Neg ) ); } else { x = op; op = syntaxStack.top(); if( !x.isOperator() && op.isOperator() && ( op.asOperator() == Token::Exclamation ) ) { ruleFound = true; d->codes.append( Opcode( Opcode::Fact ) ); } } if (ruleFound) { syntaxStack.pop(); syntaxStack.pop(); syntaxStack.push( x ); #ifdef EVALUATOR_DEBUG dbg << " Rule for unary operator (auxiliary)" << "\n"; #endif } } if( !ruleFound ) break; } // can't apply rules anymore, push the token if( token.asOperator() != Token::Percent ) syntaxStack.push( token ); } } // syntaxStack must left only one operand and end-of-expression (i.e. InvalidOp) d->valid = false; if( syntaxStack.itemCount() == 2 ) if( syntaxStack.top().isOperator() ) if( syntaxStack.top().asOperator() == Token::InvalidOp ) if( !syntaxStack.top(1).isOperator() ) d->valid = true; #ifdef EVALUATOR_DEBUG dbg << "Dump: " << dump() << "\n"; debugFile.close(); #endif // bad parsing ? clean-up everything if( !d->valid ) { d->constants.clear(); d->codes.clear(); d->identifiers.clear(); } } HNumber Evaluator::evalNoAssign() { QStack stack; QStack refs; int index; HNumber val1, val2; QVector args; QString fname; Function* function; if( d->dirty ) { Tokens tokens = scan( d->expression ); // invalid expression ? if( !tokens.valid() ) { d->error = tr( "invalid expression" ); return HNumber( 0 ); } // variable assignment? d->assignId = QString(); if( tokens.count() > 2 ) if( tokens[0].isIdentifier() ) if( tokens[1].asOperator() == Token::Equal ) { d->assignId = tokens[0].text(); tokens.erase( tokens.begin() ); tokens.erase( tokens.begin() ); } compile( tokens ); } for( int pc = 0; pc < d->codes.count(); pc++ ) { Opcode& opcode = d->codes[pc]; index = opcode.index; switch( opcode.type ) { // no operation case Opcode::Nop: break; // load a constant, push to stack case Opcode::Load: val1 = d->constants[index]; stack.push( val1 ); break; // unary operation case Opcode::Neg: if( stack.count() < 1 ) { d->error = tr( "invalid expression" ); return HNumber( 0 ); } val1 = stack.pop(); val1 = -val1; stack.push( val1 ); break; // binary operation: take two values from stack, do the operation, // push the result to stack case Opcode::Add: if( stack.count() < 2 ) { d->error = tr( "invalid expression" ); return HNumber( 0 ); } val1 = stack.pop(); val2 = stack.pop(); val2 += val1; stack.push( val2 ); break; case Opcode::Sub: if( stack.count() < 2 ) { d->error = tr( "invalid expression" ); return HNumber( 0 ); } val1 = stack.pop(); val2 = stack.pop(); val2 -= val1; stack.push( val2 ); break; case Opcode::Mul: if( stack.count() < 2 ) { d->error = tr( "invalid expression" ); return HNumber( 0 ); } val1 = stack.pop(); val2 = stack.pop(); val2 *= val1; stack.push( val2 ); break; case Opcode::Div: if( stack.count() < 2 ) { d->error = tr( "invalid expression" ); return HNumber( 0 ); } val1 = stack.pop(); val2 = stack.pop(); if( val1.isZero() ) { d->error = tr( "division by zero" ); return HNumber( 0 ); } val2 /= val1; stack.push( val2 ); break; case Opcode::Pow: if( stack.count() < 2 ) { d->error = tr( "invalid expression" ); return HNumber( 0 ); } val1 = stack.pop(); val2 = stack.pop(); val2 = HMath::raise( val2, val1 ); stack.push( val2 ); break; case Opcode::Fact: if( stack.count() < 1 ) { d->error = tr( "invalid expression" ); return HNumber( 0 ); } val1 = stack.pop(); val1 = HMath::factorial( val1 ); stack.push( val1 ); break; case Opcode::Modulo: if( stack.count() < 2 ) { d->error = tr( "invalid expression" ); return HNumber( 0 ); } val1 = stack.pop(); val2 = stack.pop(); if( val1.isZero() ) { d->error = tr( "division by zero" ); return HNumber( 0 ); } val2 = val2 % val1; stack.push( val2 ); break; case Opcode::IntDiv: if( stack.count() < 2 ) { d->error = tr( "invalid expression" ); return HNumber( 0 ); } val1 = stack.pop(); val2 = stack.pop(); if( val1.isZero() ) { d->error = tr( "division by zero" ); return HNumber( 0 ); } val2 /= val1; stack.push( HMath::integer(val2) ); break; // reference case Opcode::Ref: fname = d->identifiers[index]; if( has( fname ) ) { // variable stack.push( get( fname ) ); } else { // function function = d->functions->function( fname ); if( function ) refs.push( fname ); else { d->error = fname + ": " + tr( "unknown function or variable" ); return HNumber( 0 ); } } break; // calling function case Opcode::Function: // must do this first to avoid crash when using vars like functions if ( refs.isEmpty() ) break; fname = refs.pop(); function = d->functions->function( fname ); if( !function ) { d->error = fname + ": " + tr( "unknown function or variable" ); return HNumber( 0 ); } if( stack.count() < index ) { d->error = tr( "invalid expression" ); return HNumber( 0 ); } args.clear(); for( ; index; index-- ) args.insert( args.begin(), stack.pop() ); stack.push( function->exec( args ) ); if( !function->error().isEmpty() ) { d->error = function->error(); return HNumber( 0 ); } break; default: break; } } // more than one value in stack ? unsuccesfull execution... if( stack.count() != 1 ) { d->error = tr( "invalid expression" ); return HNumber( 0 ); } HNumber result = stack.pop(); return result; } HNumber Evaluator::eval() { HNumber result = evalNoAssign(); // this sets d->assignId // can not overwrite built-in variables if ( d->assignId == QString("pi") || d->assignId == QString("phi") || d->assignId == QString("ans") ) { d->error = d->assignId + ": " + tr( "variable cannot be overwritten" ); return HNumber::nan(); } // variable can't have the same name as function if ( d->functions->function( d->assignId ) ) { d->error = d->assignId + ": " + tr( "identifier matches an existing function name" ); return HNumber::nan(); } // handle variable assignment, e.g. "x=2*4" if ( ! d->assignId.isEmpty() ) set( d->assignId, result ); return result; } HNumber Evaluator::evalUpdateAns() { HNumber result = eval(); // "ans" is default variable to hold calculation result if ( d->error.isEmpty() ) set( QString("ans"), result ); return result; } void Evaluator::set( const QString& id, HNumber value ) { if( !id.isEmpty() ) { d->variables[ id ].name = id; d->variables[ id ].value = value; } } HNumber Evaluator::get( const QString& id ) { if( id.isEmpty() ) return HNumber( 0 ); if( !d->variables.contains( id ) ) set( id, HNumber( 0 ) ); return d->variables[ id ].value; } bool Evaluator::has( const QString& id ) { return id.isEmpty() ? false : d->variables.contains( id ); } void Evaluator::remove( const QString& id ) { d->variables.remove( id ); } QVector Evaluator::variables() const { QVector result; QMap::Iterator it; for ( it = d->variables.begin(); it != d->variables.end(); ++it ) { Variable var; const char* ASCII; var.name = it.value().name; ASCII = var.name.toLatin1(); var.value = it.value().value; result.append( var ); } return result; } void Evaluator::clearVariables() { HNumber ansBackup = get( QString("ans") ); d->variables.clear(); set( QString("ans"), ansBackup ); set( QString("pi"), HMath::pi() ); set( QString("phi"), HMath::phi() ); } QString Evaluator::autoFix( const QString& expr ) { #ifdef _BISON // SglExprLex::self().autoFix(expr); #endif int par = 0; QString result; // strip off all funny characters for( int c = 0; c < expr.length(); c++ ) if( expr[c] >= QChar(32) ) result.append( expr[c] ); // no extra whitespaces at the beginning and at the end result = result.trimmed(); // strip trailing equal sign (=) while( result.endsWith("=") ) result = result.left( result.length()-1 ); // automagically close all parenthesis Tokens tokens = Evaluator::scan( result ); if(tokens.count()) { for( int i=0; i= result.length()) while(par--) result.append( ')' ); } // special treatment for simple function // e.g. "cos" is regarded as "cos(ans)" if( !result.isEmpty() ) { Tokens tokens = Evaluator::scan( result ); if( tokens.count() == 1 ) { if( tokens[0].isIdentifier() ) { Function* f = d->functions->function( tokens[0].text() ); if( f ) result.append( "(ans)" ); } } } return result; } char Evaluator::radixChar() const { return d->radixChar; } void Evaluator::setRadixChar( char c ) { if ( c == 'C' ) c = QLocale().decimalPoint().toAscii(); if ( d->radixChar != c ) { d->radixChar = c; } } // Debugging aid QString Evaluator::dump() const { QString result; int c; if( d->dirty ) { Tokens tokens = scan( d->expression ); compile( tokens ); } result = QString("Expression: [%1]\n").arg( d->expression ); result.append(" Constants:\n"); for( c = 0; c < d->constants.count(); c++ ) { QString vtext; HNumber val = d->constants[c]; char* ss = HMath::formatFixed( val ); result += QString(" #%1 = %2\n").arg(c).arg( ss ); free( ss ); } result.append("\n"); result.append(" Identifiers:\n"); for( c = 0; c < d->identifiers.count(); c++ ) { QString vtext; result += QString(" #%1 = %2\n").arg(c).arg( d->identifiers[c] ); } result.append("\n"); result.append(" Code:\n"); for( int i = 0; i < d->codes.count(); i++ ) { QString ctext; switch( d->codes[i].type ) { case Opcode::Load : ctext = QString( "Load #%1" ).arg( d->codes[i].index ); break; case Opcode::Ref : ctext = QString( "Ref #%1" ).arg( d->codes[i].index ); break; case Opcode::Function: ctext = QString( "Function (%1)" ).arg( d->codes[i].index ); break; case Opcode::Add : ctext = "Add" ; break; case Opcode::Sub : ctext = "Sub" ; break; case Opcode::Mul : ctext = "Mul" ; break; case Opcode::Div : ctext = "Div" ; break; case Opcode::Neg : ctext = "Neg" ; break; case Opcode::Pow : ctext = "Pow" ; break; case Opcode::Fact : ctext = "Fact" ; break; default : ctext = "Unknown"; break; } result.append( " " ).append( ctext ).append("\n"); } return result; } speedcrunch-0.10.1/src/base/functions.hxx0000644000175000001440000000455511015364561017533 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef FUNCTIONS_HXX #define FUNCTIONS_HXX #include "math/hmath.hxx" #include #include #include class Function; class Functions; typedef HNumber (*FunctionPtr)( Function *, const QVector & ); class Function { public: Function( const QString & name, int argc, FunctionPtr ptr, Functions * parent ); Function( const QString & name, FunctionPtr ptr, Functions * parent ); ~Function(); QString description() const; void setDescription( const QString & ); QString error() const; HNumber exec( const QVector & args ); QString name() const; Functions * functions() const; void setError( const QString & context, const QString & error ); private: struct Private; Private * const d; Function(); Function( const Function & ); Function & operator=( const Function & ); }; class Functions : public QObject { Q_OBJECT public: Functions( char angleMode = 'r', QObject * parent = 0 ); ~Functions(); void add( Function * ); Function * function( const QString & ) const; QStringList functionNames() const; char angleMode(); public slots: void setAngleMode( char ); // 'r': radian (default) / 'd': degree void retranslateText(); private: struct Private; Private * const d; Functions( const Functions & ); Functions & operator=( const Functions & ); }; #endif speedcrunch-0.10.1/src/base/constants.hxx0000644000175000001440000000412111015364561017524 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef CONSTANTS_HXX #define CONSTANTS_HXX #include #include #include #include class Constant { public: QString name; QString value; QString unit; QStringList categories; Constant( const QString & n, const QString & v, const QString & u, const QStringList & cat ) : name( n ), value( v ), unit( u ), categories( cat ) {} Constant( const QString & n, const QString & v, const QString & u, const QString & cat ) : name( n ), value( v ), unit( u ) { categories << cat; } Constant( const QString & n, const QString & v, const QString & u, const QString & cat1, const QString & cat2 ) : name( n ), value( v ), unit( u ) { categories << cat1; categories << cat2; } }; class Constants : public QObject { Q_OBJECT public: Constants( QObject * parent = 0 ); ~Constants(); QList constantList() const; QStringList categoryList() const; public slots: void retranslateText(); private: struct Private; Private * const d; Constants( const Constants & ); Constants & operator=( const Constants & ); }; #endif speedcrunch-0.10.1/src/base/settings.cpp0000644000175000001440000003734611015364561017342 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004, 2005, 2007, 2008 Ariya Hidayat // Copyright (C) 2005-2006 Johan Thelin // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "settings.hxx" #include "3rdparty/util/binreloc.h" #include "math/floatconfig.h" #include #include #include #include QSettings * createQSettings( const QString & key ); // public Settings::Settings() { //escape = "\\"; //reftbl } void Settings::load() { const QString KEY = "SpeedCrunch"; QSettings * settings = createQSettings( KEY ); if ( ! settings ) return; QString key; key = KEY + "/General/"; // angle mode special case QString angleModeStr; angleModeStr = settings->value( key + "AngleMode", "r" ).toString(); if ( angleModeStr != "r" && angleModeStr != "d" ) angleMode = 'r'; else angleMode = angleModeStr[0].toAscii(); // radix character special case QString radixCharStr; radixCharStr = settings->value( key + "RadixChar", 'C' ).toString(); if ( radixCharStr != "C" && radixCharStr != "," && radixCharStr != "." ) radixChar = 'C'; else radixChar = radixCharStr[0].toAscii(); saveSession = settings->value( key + "RestoreLastSession", true ).toBool(); saveVariables = settings->value( key + "SaveVariables", true ).toBool(); autoComplete = settings->value( key + "AutoComplete", true ).toBool(); autoCalc = settings->value( key + "AutoCalc", true ).toBool(); minimizeToTray = settings->value( key + "MinimizeToTray", false ).toBool(); hiliteSyntax = settings->value( key + "HiliteSyntax", true ).toBool(); language = settings->value( key + "Language", "C" ).toString(); key = KEY + "/Format/"; // format special case QString formatStr; formatStr = settings->value( key + "Type", 'g' ).toString(); if ( formatStr != "g" && formatStr != "f" && formatStr != "e" && formatStr != "n" && formatStr != "h" && formatStr != "o" && formatStr != "b" ) format = 'g'; else format = formatStr[0].toAscii(); precision = settings->value( key + "Precision", -1 ).toInt(); if ( precision > DECPRECISION ) precision = DECPRECISION; key = KEY + "/Layout/"; showFullScreen = settings->value( key + "ShowFullScreen", false ).toBool(); showKeypad = settings->value( key + "ShowKeypad", true ).toBool(); showMenuBar = settings->value( key + "ShowMenuBar", true ).toBool(); showStatusBar = settings->value( key + "ShowStatusBar", false ).toBool(); showHistory = settings->value( key + "ShowHistory", false ).toBool(); showFunctions = settings->value( key + "ShowFunctions", false ).toBool(); showVariables = settings->value( key + "ShowVariables", false ).toBool(); showBook = settings->value( key + "ShowBook", false ).toBool(); showConstants = settings->value( key + "ShowConstants", false ).toBool(); mainWindowState = settings->value( key + "State" ).toByteArray(); stayAlwaysOnTop = settings->value( key + "StayAlwaysOnTop", false ).toBool(); historyDockFloating = settings->value( key + "HistoryDockFloating", false ).toBool(); historyDockTop = settings->value( key + "HistoryDockTop", 0 ).toInt(); historyDockLeft = settings->value( key + "HistoryDockLeft", 0 ).toInt(); historyDockWidth = settings->value( key + "HistoryDockWidth", 150 ).toInt(); historyDockHeight = settings->value( key + "HistoryDockHeight", 350 ).toInt(); functionsDockFloating = settings->value( key + "FunctionsDockFloating", false ).toBool(); functionsDockTop = settings->value( key + "FunctionsDockTop", 0 ).toInt(); functionsDockLeft = settings->value( key + "FunctionsDockLeft", 0 ).toInt(); functionsDockWidth = settings->value( key + "FunctionsDockWidth", 150 ).toInt(); functionsDockHeight = settings->value( key + "FunctionsDockHeight", 350 ).toInt(); bookDockFloating = settings->value( key + "BookDockFloating", false ).toBool(); bookDockTop = settings->value( key + "BookDockTop", 0 ).toInt(); bookDockLeft = settings->value( key + "BookDockLeft", 0 ).toInt(); bookDockWidth = settings->value( key + "BookDockWidth", 150 ).toInt(); bookDockHeight = settings->value( key + "BookDockHeight", 350 ).toInt(); variablesDockFloating = settings->value( key + "VariablesDockFloating", false ).toBool(); variablesDockTop = settings->value( key + "VariablesDockTop", 0 ).toInt(); variablesDockLeft = settings->value( key + "VariablesDockLeft", 0 ).toInt(); variablesDockWidth = settings->value( key + "VariablesDockWidth", 150 ).toInt(); variablesDockHeight = settings->value( key + "VariablesDockHeight", 350 ).toInt(); constantsDockFloating = settings->value( key + "ConstantsDockFloating", false ).toBool(); constantsDockTop = settings->value( key + "ConstantsDockTop", 0 ).toInt(); constantsDockLeft = settings->value( key + "ConstantsDockLeft", 0 ).toInt(); constantsDockWidth = settings->value( key + "ConstantsDockWidth", 150 ).toInt(); constantsDockHeight = settings->value( key + "ConstantsDockHeight", 350 ).toInt(); mainWindowSize = QSize( settings->value ( key + "WindowWidth", 300 ).toInt(), settings->value ( key + "WindowHeight", 400 ).toInt() ); // load history key = KEY + "/History/"; history.clear(); int count = settings->value( key + "Count", 0 ).toInt(); for ( int i = 0; i < count; i++ ) { QString keyname = QString( key + "Expression%1" ).arg( i ); QString str = settings->value( keyname ).toString(); if ( ! str.isEmpty() ) { QString expr; for ( int c = 0; c < str.length(); c++ ) if ( str[c] >= 32 ) expr.append( str[c] ); history.append( expr ); } } // load results historyResults.clear(); for ( int i = 0; i < count; i++ ) { QString keyname = QString( key + "Expression%1Result" ).arg( i ); QString str = settings->value( keyname ).toString(); if ( ! str.isEmpty() ) historyResults.append( str ); } if ( history.count() != historyResults.count() ) { // avoid application crash because of new features with old settings files history.clear(); historyResults.clear(); } // load variables key = KEY + "/Variables/"; variables.clear(); settings->beginGroup( key ); QStringList names = settings->childKeys(); settings->endGroup(); for ( int k = 0; k < names.count(); k++ ) { QString name = names[k]; QString keyname = QString( key + "%1" ).arg( name ); QString value = settings->value( keyname ).toString(); // treat upper case escape code int length = name.length(); for ( int c = 0; c < length; c++ ) { if ( name[c] == '_' ) { name.remove( c, 1 ); if ( name[c] != '_' ) name[c] = name[c].toUpper(); } } // load if ( ! value.isEmpty() && name != "pi" && name != "phi" ) variables.append( QString( "%1=%2" ).arg( name ).arg( value ) ); } delete settings; } void Settings::save() { const QString KEY = "SpeedCrunch"; QSettings * settings = createQSettings( KEY ); if ( ! settings ) return; QString key; int k, i; key = KEY + "/General/"; settings->setValue( key + "AngleMode", QString( QChar( angleMode ) ) ); settings->setValue( key + "RadixChar", QString( QChar( radixChar ) ) ); settings->setValue( key + "RestoreLastSession", saveSession ); settings->setValue( key + "SaveVariables", saveVariables ); settings->setValue( key + "AutoComplete", autoComplete ); settings->setValue( key + "AutoCalc", autoCalc ); settings->setValue( key + "MinimizeToTray", minimizeToTray ); settings->setValue( key + "HiliteSyntax", hiliteSyntax ); settings->setValue( key + "Language", language ); key = KEY + "/Format/"; settings->setValue( key + "Type", QString( QChar( format ) ) ); settings->setValue( key + "Precision", precision ); key = KEY + "/Layout/"; settings->setValue( key + "ShowBook", showBook ); settings->setValue( key + "ShowConstants", showConstants ); settings->setValue( key + "ShowFunctions", showFunctions ); settings->setValue( key + "ShowHistory", showHistory ); settings->setValue( key + "ShowFullScreen", showFullScreen ); settings->setValue( key + "ShowKeypad", showKeypad ); settings->setValue( key + "ShowMenuBar", showMenuBar ); settings->setValue( key + "ShowStatusBar", showStatusBar ); settings->setValue( key + "ShowVariables", showVariables ); settings->setValue( key + "WindowHeight", mainWindowSize.height() ); settings->setValue( key + "WindowWidth", mainWindowSize.width() ), settings->setValue( key + "ConstantsDockFloating", constantsDockFloating ); settings->setValue( key + "ConstantsDockHeight", constantsDockHeight ); settings->setValue( key + "ConstantsDockLeft", constantsDockLeft ); settings->setValue( key + "ConstantsDockTop", constantsDockTop ); settings->setValue( key + "ConstantsDockWidth", constantsDockWidth ); settings->setValue( key + "FunctionsDockFloating", functionsDockFloating ); settings->setValue( key + "FunctionsDockHeight", functionsDockHeight ); settings->setValue( key + "FunctionsDockLeft", functionsDockLeft ); settings->setValue( key + "FunctionsDockTop", functionsDockTop ); settings->setValue( key + "FunctionsDockWidth", functionsDockWidth ); settings->setValue( key + "BookDockFloating", bookDockFloating ); settings->setValue( key + "BookDockHeight", bookDockHeight ); settings->setValue( key + "BookDockLeft", bookDockLeft ); settings->setValue( key + "BookDockTop", bookDockTop ); settings->setValue( key + "BookDockWidth", bookDockWidth ); settings->setValue( key + "HistoryDockFloating", historyDockFloating ); settings->setValue( key + "HistoryDockHeight", historyDockHeight ); settings->setValue( key + "HistoryDockLeft", historyDockLeft ); settings->setValue( key + "HistoryDockTop", historyDockTop ); settings->setValue( key + "HistoryDockWidth", historyDockWidth ); settings->setValue( key + "State", mainWindowState ); settings->setValue( key + "StayAlwaysOnTop", stayAlwaysOnTop ); settings->setValue( key + "VariablesDockFloating", variablesDockFloating ); settings->setValue( key + "VariablesDockHeight", variablesDockHeight ); settings->setValue( key + "VariablesDockLeft", variablesDockLeft ); settings->setValue( key + "VariablesDockTop", variablesDockTop ); settings->setValue( key + "VariablesDockWidth", variablesDockWidth ); // save history key = KEY + "/History/"; QStringList realHistory = history; QStringList realHistoryResults = historyResults; if ( history.count() > 100 ) { realHistory.clear(); realHistoryResults.clear(); unsigned start = history.count() - 100; for ( int j = start; j < history.count(); j++ ) { realHistory.append( history[j] ); realHistoryResults.append( historyResults[j] ); } } settings->beginGroup( key ); QStringList hkeys = settings->childKeys(); settings->endGroup(); for ( k = 0; k < hkeys.count(); k++ ) { settings->remove( QString( key + "Expression%1" ).arg( k ) ); settings->remove( QString( key + "Expression%1Result" ).arg( k ) ); } settings->setValue( key + "/Count/", (int) history.count() ); for ( i = 0; i < realHistory.count(); i++ ) { settings->setValue( QString( key + "Expression%1" ).arg( i ), realHistory[i] ); settings->setValue( QString( key + "Expression%1Result" ).arg( i ), realHistoryResults[i] ); } // save variables key = KEY + "/Variables/"; settings->beginGroup( key ); QStringList vkeys = settings->childKeys(); settings->endGroup(); for ( k = 0; k < vkeys.count(); k++ ) settings->remove( QString( key + "%1" ).arg( vkeys[k] ) ); for ( i = 0; i < variables.count(); i++ ) { QStringList s = variables[i].split( '=' ); if ( s.count() == 2 && s[0] != "pi" && s[0] != "phi" ) { QString name = ""; QString value = s[1]; int length = s[0].length(); for ( int c = 0; c < length; c++ ) { if ( s[0].at(c).isUpper() || s[0].at(c) == '_' ) { name += '_'; name += s[0][c].toLower(); } else { name += s[0][c]; } } settings->setValue( QString( key + "%1").arg( name ), value ); } } delete settings; } QSettings * createQSettings( const QString & KEY ) { QSettings * settings = 0; #ifdef Q_WS_WIN #ifdef SPEEDCRUNCH_PORTABLE // Portable Windows version: settings are from INI file in the same directory QString appPath = QApplication::applicationFilePath(); int ii = appPath.lastIndexOf( '/' ); if ( ii > 0) appPath.remove(ii, appPath.length()); QString iniFile = appPath + '/' + KEY + ".ini"; settings = new QSettings( iniFile, QSettings::IniFormat ); #else // Regular Windows version: // settings are from the registry HKEY_CURRENT_USER\Software\SpeedCrunch settings = new QSettings( QSettings::NativeFormat, QSettings::UserScope, KEY, KEY ); #endif // SPEEDCRUNCH_PORTABLE #endif // Q_WS_WIN #ifdef Q_WS_MAC settings = new QSettings( QSettings::NativeFormat, QSettings::UserScope, KEY, KEY ); #endif // Q_WS_MAC #ifdef Q_WS_X11 #ifdef SPEEDCRUNCH_PORTABLE // Portable X11 version: settings are from INI file in the same directory BrInitError error; if ( br_init( & error ) == 0 && error != BR_INIT_ERROR_DISABLED ) { qDebug( "Warning: BinReloc failed to initialize (error code %d)", error ); qDebug( "Will fallback to hardcoded default path." ); } char * prefix = br_find_prefix( 0 ); QString iniFile = QString( prefix ) + '/' + KEY + ".ini"; free( prefix ); settings = new QSettings( iniFile, QSettings::IniFormat ); #else // Regular Unix (not Mac) version: settings from $HOME/.conf/SpeedCrunch settings = new QSettings( QSettings::NativeFormat, QSettings::UserScope, KEY, KEY ); #endif // SPEEDCRUNCH_PORTABLE #endif // Q_WS_X11 return settings; } speedcrunch-0.10.1/src/books/0000755000175000001440000000000011015364704015163 5ustar helderusersspeedcrunch-0.10.1/src/books/pl/0000755000175000001440000000000011015364704015576 5ustar helderusersspeedcrunch-0.10.1/src/books/pl/cube.html0000644000175000001440000000120411015364561017400 0ustar helderusers Sześcian

Sześcian


speedcrunch-0.10.1/src/books/pl/circle.html0000644000175000001440000000111411015364561017723 0ustar helderusers Koło

Koło


speedcrunch-0.10.1/src/books/pl/sphere.html0000644000175000001440000000115211015364561017752 0ustar helderusers Kula

Kula


speedcrunch-0.10.1/src/books/pl/math_index.html0000644000175000001440000000135311015364561020607 0ustar helderusers Książka SpeedCrunch

Bryły trójwymiarowe


Kula
Sześcian
Stożek
Walec

Figury płaskie


Koło
Trójkąt prostokątny
Wycinek koła

Różne


Równanie kwadratowe
speedcrunch-0.10.1/src/books/pl/right_triangle.html0000644000175000001440000000335211015364561021472 0ustar helderusers Trójkąt prostokątny

Trójkąt prostokątny

speedcrunch-0.10.1/src/books/pl/sector.html0000644000175000001440000000110611015364561017762 0ustar helderusers Wycinek koła

Wycinek koła


speedcrunch-0.10.1/src/books/pl/index.html0000644000175000001440000000035211015364561017574 0ustar helderusers Podręcznik SpeedCrunch speedcrunch-0.10.1/src/books/pl/cone.html0000644000175000001440000000117611015364561017416 0ustar helderusers Stożek

Stożek


speedcrunch-0.10.1/src/books/pl/cylinder.html0000644000175000001440000000077511015364561020307 0ustar helderusers Walec

Walec


speedcrunch-0.10.1/src/books/pl/quadratic_equation.html0000644000175000001440000000122211015364561022344 0ustar helderusers Równanie kwadratowe

Równanie kwadratowe

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/zh_CN/0000755000175000001440000000000011015364704016164 5ustar helderusersspeedcrunch-0.10.1/src/books/zh_CN/cube.html0000644000175000001440000000120411015364561017766 0ustar helderusers 正方体

正方体


speedcrunch-0.10.1/src/books/zh_CN/circle.html0000644000175000001440000000111011015364561020305 0ustar helderusers


speedcrunch-0.10.1/src/books/zh_CN/sphere.html0000644000175000001440000000115611015364561020344 0ustar helderusers 球体

球体


speedcrunch-0.10.1/src/books/zh_CN/math_index.html0000644000175000001440000000132111015364561021170 0ustar helderusers SpeedCrunch 图书

三维对象


球体
正方体
圆锥体
圆柱体

二维对象



直角三角形
扇形

杂项


一元二次方程
speedcrunch-0.10.1/src/books/zh_CN/right_triangle.html0000644000175000001440000000333411015364561022060 0ustar helderusers 直角三角形

直角三角形

speedcrunch-0.10.1/src/books/zh_CN/sector.html0000644000175000001440000000107011015364561020350 0ustar helderusers 扇形

扇形


speedcrunch-0.10.1/src/books/zh_CN/cone.html0000644000175000001440000000120211015364561017772 0ustar helderusers 圆锥体

圆锥体


speedcrunch-0.10.1/src/books/zh_CN/cylinder.html0000644000175000001440000000100511015364561020660 0ustar helderusers 圆柱体

圆柱体


speedcrunch-0.10.1/src/books/zh_CN/quadratic_equation.html0000644000175000001440000000121611015364561022735 0ustar helderusers 一元二次方程

一元二次方程

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/pt/0000755000175000001440000000000011015364704015606 5ustar helderusersspeedcrunch-0.10.1/src/books/pt/cube.html0000644000175000001440000000117211015364561017414 0ustar helderusers Cubo

Cubo


speedcrunch-0.10.1/src/books/pt/circle.html0000644000175000001440000000112211015364561017732 0ustar helderusers Círculo

Círculo


speedcrunch-0.10.1/src/books/pt/sphere.html0000644000175000001440000000115611015364561017766 0ustar helderusers Esfera

Esfera


speedcrunch-0.10.1/src/books/pt/math_index.html0000644000175000001440000000133211015364561020614 0ustar helderusers Livro do SpeedCrunch

Objectos 3D


Esfera
Cubo
Cone
Cilindro

Objectos 2D


Círculo
Triângulo Rectângulo
Sector

Miscelâneo


Equação Quadrática
speedcrunch-0.10.1/src/books/pt/right_triangle.html0000644000175000001440000000335211015364561021502 0ustar helderusers Triângulo Rectângulo

Triângulo Rectângulo

speedcrunch-0.10.1/src/books/pt/sector.html0000644000175000001440000000107011015364561017772 0ustar helderusers Sector

Sector


speedcrunch-0.10.1/src/books/pt/index.html0000644000175000001440000000035011015364561017602 0ustar helderusers Manual do SpeedCrunch speedcrunch-0.10.1/src/books/pt/cone.html0000644000175000001440000000117011015364561017420 0ustar helderusers Cone

Cone


speedcrunch-0.10.1/src/books/pt/cylinder.html0000644000175000001440000000100311015364561020300 0ustar helderusers Cilindro

Cilindro


speedcrunch-0.10.1/src/books/pt/quadratic_equation.html0000644000175000001440000000122411015364561022356 0ustar helderusers Equação Quadrática

Equação Quadrática

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/eu/0000755000175000001440000000000011015364704015574 5ustar helderusersspeedcrunch-0.10.1/src/books/eu/cube.html0000644000175000001440000000117211015364561017402 0ustar helderusers Kubo

Kubo


speedcrunch-0.10.1/src/books/eu/circle.html0000644000175000001440000000112011015364561017716 0ustar helderusers Zirkulu

Zirkulu


speedcrunch-0.10.1/src/books/eu/sphere.html0000644000175000001440000000115611015364561017754 0ustar helderusers Esfera

Esfera


speedcrunch-0.10.1/src/books/eu/math_index.html0000644000175000001440000000131511015364561020603 0ustar helderusers SpeedCrunch Liburua

3D Objektuak


Esfera
Kubo
Kono
Zilindro

2D Objektuak


Zirkulu
Triangelu Zuzen
Sektore

Hainbat


Ekuazio Koadratiko
speedcrunch-0.10.1/src/books/eu/right_triangle.html0000644000175000001440000000333411015364561021470 0ustar helderusers Triangelu Zuzen

Triangelu Zuzen

speedcrunch-0.10.1/src/books/eu/sector.html0000644000175000001440000000107211015364561017762 0ustar helderusers Sektore

Sektore


speedcrunch-0.10.1/src/books/eu/cone.html0000644000175000001440000000117011015364561017406 0ustar helderusers Kono

Kono


speedcrunch-0.10.1/src/books/eu/cylinder.html0000644000175000001440000000100311015364561020266 0ustar helderusers Zilindro

Zilindro


speedcrunch-0.10.1/src/books/eu/quadratic_equation.html0000644000175000001440000000121611015364561022345 0ustar helderusers Ekuazio Koadratiko

Ekuazio Koadratiko

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/cs/0000755000175000001440000000000011015364704015570 5ustar helderusersspeedcrunch-0.10.1/src/books/cs/cube.html0000644000175000001440000000117211015364561017376 0ustar helderusers Cube

Cube


speedcrunch-0.10.1/src/books/cs/circle.html0000644000175000001440000000111611015364561017717 0ustar helderusers Circle

Circle


speedcrunch-0.10.1/src/books/cs/sphere.html0000644000175000001440000000115611015364561017750 0ustar helderusers Sphere

Sphere


speedcrunch-0.10.1/src/books/cs/math_index.html0000644000175000001440000000130011015364561020571 0ustar helderusers SpeedCrunch Book

3D Objects


Sphere
Cube
Cone
Cylinder

2D Objects


Circle
Right Triangle
Sector

Misc


Quadratic Equation
speedcrunch-0.10.1/src/books/cs/right_triangle.html0000644000175000001440000000333211015364561021462 0ustar helderusers Right Triangle

Right Triangle

speedcrunch-0.10.1/src/books/cs/sector.html0000644000175000001440000000107011015364561017754 0ustar helderusers Sector

Sector


speedcrunch-0.10.1/src/books/cs/index.html0000644000175000001440000000034511015364561017570 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/cs/cone.html0000644000175000001440000000117011015364561017402 0ustar helderusers Cone

Cone


speedcrunch-0.10.1/src/books/cs/cylinder.html0000644000175000001440000000100311015364561020262 0ustar helderusers Cylinder

Cylinder


speedcrunch-0.10.1/src/books/cs/quadratic_equation.html0000644000175000001440000000121611015364561022341 0ustar helderusers Quadratic Equation

Quadratic Equation

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/fr/0000755000175000001440000000000011015364704015572 5ustar helderusersspeedcrunch-0.10.1/src/books/fr/cube.html0000644000175000001440000000117211015364561017400 0ustar helderusers Cube

Cube


speedcrunch-0.10.1/src/books/fr/circle.html0000644000175000001440000000111611015364561017721 0ustar helderusers Circle

Circle


speedcrunch-0.10.1/src/books/fr/sphere.html0000644000175000001440000000115611015364561017752 0ustar helderusers Sphere

Sphere


speedcrunch-0.10.1/src/books/fr/math_index.html0000644000175000001440000000130011015364561020573 0ustar helderusers SpeedCrunch Book

3D Objects


Sphere
Cube
Cone
Cylinder

2D Objects


Circle
Right Triangle
Sector

Misc


Quadratic Equation
speedcrunch-0.10.1/src/books/fr/right_triangle.html0000644000175000001440000000333211015364561021464 0ustar helderusers Right Triangle

Right Triangle

speedcrunch-0.10.1/src/books/fr/sector.html0000644000175000001440000000107011015364561017756 0ustar helderusers Sector

Sector


speedcrunch-0.10.1/src/books/fr/index.html0000644000175000001440000000034511015364561017572 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/fr/cone.html0000644000175000001440000000117011015364561017404 0ustar helderusers Cone

Cone


speedcrunch-0.10.1/src/books/fr/cylinder.html0000644000175000001440000000100311015364561020264 0ustar helderusers Cylinder

Cylinder


speedcrunch-0.10.1/src/books/fr/quadratic_equation.html0000644000175000001440000000121611015364561022343 0ustar helderusers Quadratic Equation

Quadratic Equation

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/id/0000755000175000001440000000000011015364704015557 5ustar helderusersspeedcrunch-0.10.1/src/books/id/cube.html0000644000175000001440000000117211015364561017365 0ustar helderusers Cube

Cube


speedcrunch-0.10.1/src/books/id/circle.html0000644000175000001440000000111611015364561017706 0ustar helderusers Circle

Circle


speedcrunch-0.10.1/src/books/id/sphere.html0000644000175000001440000000115611015364561017737 0ustar helderusers Sphere

Sphere


speedcrunch-0.10.1/src/books/id/math_index.html0000644000175000001440000000130011015364561020560 0ustar helderusers SpeedCrunch Book

3D Objects


Sphere
Cube
Cone
Cylinder

2D Objects


Circle
Right Triangle
Sector

Misc


Quadratic Equation
speedcrunch-0.10.1/src/books/id/right_triangle.html0000644000175000001440000000333211015364561021451 0ustar helderusers Right Triangle

Right Triangle

speedcrunch-0.10.1/src/books/id/sector.html0000644000175000001440000000107011015364561017743 0ustar helderusers Sector

Sector


speedcrunch-0.10.1/src/books/id/index.html0000644000175000001440000000034511015364561017557 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/id/cone.html0000644000175000001440000000117011015364561017371 0ustar helderusers Cone

Cone


speedcrunch-0.10.1/src/books/id/cylinder.html0000644000175000001440000000100311015364561020251 0ustar helderusers Cylinder

Cylinder


speedcrunch-0.10.1/src/books/id/quadratic_equation.html0000644000175000001440000000121611015364561022330 0ustar helderusers Quadratic Equation

Quadratic Equation

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/ru/0000755000175000001440000000000011015364704015611 5ustar helderusersspeedcrunch-0.10.1/src/books/ru/cube.html0000644000175000001440000000117211015364561017417 0ustar helderusers Cube

Cube


speedcrunch-0.10.1/src/books/ru/circle.html0000644000175000001440000000111611015364561017740 0ustar helderusers Circle

Circle


speedcrunch-0.10.1/src/books/ru/sphere.html0000644000175000001440000000115611015364561017771 0ustar helderusers Sphere

Sphere


speedcrunch-0.10.1/src/books/ru/math_index.html0000644000175000001440000000130011015364561020612 0ustar helderusers SpeedCrunch Book

3D Objects


Sphere
Cube
Cone
Cylinder

2D Objects


Circle
Right Triangle
Sector

Misc


Quadratic Equation
speedcrunch-0.10.1/src/books/ru/right_triangle.html0000644000175000001440000000333211015364561021503 0ustar helderusers Right Triangle

Right Triangle

speedcrunch-0.10.1/src/books/ru/sector.html0000644000175000001440000000107011015364561017775 0ustar helderusers Sector

Sector


speedcrunch-0.10.1/src/books/ru/index.html0000644000175000001440000000034511015364561017611 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/ru/cone.html0000644000175000001440000000117011015364561017423 0ustar helderusers Cone

Cone


speedcrunch-0.10.1/src/books/ru/cylinder.html0000644000175000001440000000100311015364561020303 0ustar helderusers Cylinder

Cylinder


speedcrunch-0.10.1/src/books/ru/quadratic_equation.html0000644000175000001440000000121611015364561022362 0ustar helderusers Quadratic Equation

Quadratic Equation

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/nl/0000755000175000001440000000000011015364704015574 5ustar helderusersspeedcrunch-0.10.1/src/books/nl/cube.html0000644000175000001440000000117411015364561017404 0ustar helderusers Kubus

Kubus


speedcrunch-0.10.1/src/books/nl/circle.html0000644000175000001440000000111611015364561017723 0ustar helderusers Cirkel

Cirkel


speedcrunch-0.10.1/src/books/nl/sphere.html0000644000175000001440000000115011015364561017746 0ustar helderusers Bol

Bol


speedcrunch-0.10.1/src/books/nl/math_index.html0000644000175000001440000000131511015364561020603 0ustar helderusers SpeedCrunch Boek

3D Objecten


Bol
Kubus
Kegel
Cylinder

2D Objecten


Cirkel
Rechthoekige Driehoek
Sector

Overig


Vierkantsvergelijking
speedcrunch-0.10.1/src/books/nl/right_triangle.html0000644000175000001440000000335011015364561021466 0ustar helderusers Rechthoekige Driehoek

Rechthoekige Driehoek

speedcrunch-0.10.1/src/books/nl/sector.html0000644000175000001440000000107011015364561017760 0ustar helderusers Sector

Sector


speedcrunch-0.10.1/src/books/nl/index.html0000644000175000001440000000034511015364561017574 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/nl/cone.html0000644000175000001440000000117211015364561017410 0ustar helderusers Kegel

Kegel


speedcrunch-0.10.1/src/books/nl/cylinder.html0000644000175000001440000000100311015364561020266 0ustar helderusers Cylinder

Cylinder


speedcrunch-0.10.1/src/books/nl/quadratic_equation.html0000644000175000001440000000122411015364561022344 0ustar helderusers Vierkantsvergelijking

Vierkantsvergelijking

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/books.css0000644000175000001440000000033111015364561017010 0ustar helderusersbody { background-color: #ffffff; color: #000000; } img { display: block; margin-left: auto; margin-right: auto } a:link { text-decoration: none; color: blue; font-size: 12pt; font-weight: bold; } speedcrunch-0.10.1/src/books/images/0000755000175000001440000000000011015364704016430 5ustar helderusersspeedcrunch-0.10.1/src/books/images/sphere.png0000644000175000001440000001315411015364561020431 0ustar helderusersPNG  IHDR<qsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATxyՕǿ@₊T@gMantbK\ψPH4h81j`̸B2* 20QQ99tOꮺu{{U%##i;I&TȄ 2Raz'H``[݁}E"`0Z=K!PDvvD^J e`~F0! +u ,Jپ}@(lc77Ҿ Zo`oɻ29`:&YZ\U("#NŌ:x+b^w.~7L`;C0q `<LR⤣YhKDbb l9t`_=Tkl ,l"1S= JPL 4;Au*ṕ?Xzp~j6t43bI@t.I,vwLN@p?8^&tgy΅q "2x{# x 8IUPuLbrU {װgxGDƊHz1 -,~l ڢʟqW-,~iXRX"Lzb~>VU}LUb 0MDM]aJX"ED2sb`>]5<ˣ"rw7 x <Ʃʺ&PՕ:k=M ACKDfÁU0m´PwT0p,φ3=/N]U_VbS뙮fjg,zWu7:.VzY<;UX>]φ}]%"^TZŒQZ"y y]sj.,[lHo{hUWiRMkxQ`9RD6wZmŻ|[LEXw0PoODnnz?} JK{{@Kᜤ4>t`%uNVlM$쪪&yDK,\F~ TUMRzMFD;Ť )DT_:Ϻ+1ms ˒~b_cԣG}lwٖ>-8f&9&az5؟/;밹g^L[ڸ.lwWRvX lԗ "=U kdVql*ն( 7sd @U,$Vm6L3fUGuz6Iyq۝WW;I!N \badp:Dd4ge8V$,wμiZehR;%9<*23y\W4$W|X? lZaycza)r~}I,XW+U3r$JE4U"/+}LU_/>RSzZ0 "5 b_**,ϐJUߍ|[+6cC`bhaʻep_~ r̯`ko]["]Obqt35TPY[ĸ.W莚 U餱}U/>`U="wx"BU}; 4 F(6V55{ 9+ya 4ļT0+oTu>fbj%_p}m͑ v7W3_`S{/V~e(Jk, G|[cΚ6EOX[U_O ,&P^$"/sI[;vEdCm ZNC. %ݰw +t^'"m ۀs+>pn~fEd4ptGĚͭ*uL1R]oڷ$Wux|Gla~oꡪ DXY$^?{߷5yim''mEd)ub1=BXcLDveXC?2KLV~nF{&y]؂жuU]woGVSLXavHW-p6>NDɪ'fi=V̴R`^{FYņt8Uy=0OD݊?VF#;_nm-p> <)"?~#"cSi63`<~ŸDIܿm`&GUuI4- s< k2"q*Xb*5N ?~sX}5F5My 7T /?MX+췡}l g؛Bl ~x߇}$l_[hmqY[ <a[l{^4}/`HzCߣ}^#4x߸XeQaE~5Gja7\17|qEEX9k7?^GkNDŽ5Y HVnHXvjrt,YX; щq 41wK ˻XQ2Z;K'Qd9N~vC +oVgfy-&'* \[N\aM"<s3:n#0 ĊKX>ca6E ӗѼ~F54ƃجyp[.^'{2~L-, .,+iL [݉l""ی&m f;mY9?!E/wW%۱if nˎ4R6Z7όmzdJ &` Vx\̶1[ME ?} 3Z%~xFs+g"flzW5 Uۃ~.C9ke1VĩJX,"xf4!n~xI4\%$1w 4lm6ӘMja:EFrf1W RDN㶺 I-yx/0lvUNWu%ȸ5w+ߠml5]b$*,º5I d2fZh5_SB!TS,jkU] H4Q?a} )"t8nIRgjqpֽ26 nTH?[3q[nHan˪y~f&R76UNZ){[L""7Nw[N͌%G z5J {5ԏEIi"z1r] ݦʧՑ %׉:3˙:?WsdWr?ElMq!<vM#րX.8l`x=a,Oѣy6,{53ϫSmIKCtD}XDf?"2f~ԗjhaɂg"rQ-CDER`_ #,X]5ތ9KײkY;jYX@UU_> %~#`)y3r#"Xࡼg );L"WEVᘣDUQr t ƙ4aTuc6ɭஈt6֧Uղ /EU'`!7N%l寁EdیN$g<觪*Y^ +xcXklN~ml/Ms"?Vlۀ{!Fa%4x׉H,@f`61^M0$A$E~0IDoTZBXQDd0&#ND6M=GUWļntêulc77u&W=ajhYa1wÄ;fȅM/m.L}JʭFV!TYoE ARlyd+V-ЩMdHLX +#7qNIENDB`speedcrunch-0.10.1/src/books/images/cylinder.svgz0000644000175000001440000000342511015364561021161 0ustar helderusersXێ6}Ъ`(YjAv}mDȢ@m{>EnL`nt[bSU^~{>3u.ʕM-^"7¶jʌ+8Jrxfr/)rTtBy+DBܯ-y²,ض,]( 3/K]^/UD\{O|$Qi:)0<9yfԥԁN});;e02L)0f%5Yo?-qTrut0T6Zrx]n'7a4,M8ӟkuz^Qp#I̎:c+ |cwRO(؅l @8݈tzY'Vȯ78Ayӭa~Ft8}̨ON%R|䚖C)tԌf#`-+ ^bSlHNu(4okeI$MZԭPb2Y]*>,,۵V\?(כYm ut۝ҌvW`lËNB)AdM-{MvG4 V@;ZV%Fh$LTɤDT+UdL$Փf6=a૧QPfcmH=aGVZ)T]dsTo N:ke$+Y+臚f8G}Gڍ|4"z@PI7W /mqWn[˥k, ?m>Sڄ(.ҙ̉9UW3&OCM+:wFpxuP!n\,9c4n:j@evİ+;Y6!%LrCKYo> FofnxF\A -mE ; [? {yzc׮Z7E᱀ח9m[:lY[a7/~GkxphCD oZg⣅oy”<YQl+( Cΰܴ&o pjqAK<BǀOoR7# "#3&~jwy?v/ .#hЕymSh0L6Rp|l2@\2-w9~xGX\e~~Q|Û) !8ˍ|԰)(hk@ QG1EaDYꙹcѸ.xKOVy`CcF i)x֨`ȟBpX`<17jx.ZoF5.p14f.G@{}Np܃4 6G߇)̿?Hw{m%7܉>MK}@B6 ] 6? FaPx[>Kw~] speedcrunch-0.10.1/src/books/images/sector.png0000644000175000001440000000472311015364561020444 0ustar helderusersPNG  IHDR<qsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< PIDATx{erj0-EXN $ITP" A&4^!$ * 7-P!b)d9l{vϙ瓜dٙw}7("0M7Fe),K`Y R8Xp,e),K`Y R8Xp,e),K`Y R8Xp,e),K`Y R8X֐qmXkHRU*I7ݞuq+KzMN^*$m | K% Xl_7ZNA`s`vD,#|8Wؕ{p!083"n\vDlxc}oR]CUY*锁4GZX|2"s{DĿ3%$Gē}~ LF`5vw6p.p^D\>21Pfp$i*@iIo!uD|M tp/pɆ8Qn5kRc XuʺPD<\? sr5@NsU2`3X i;,`^D,O>|qTq=V2I'oUj`7IX]J"iKXW>'kJ pJ/CU8B8{:U-_N̞p{kz=0xBj"PU.Kö~ YǁIQ5}8-I;zZ8XPxe,uSMf1pVuM'tjuiB  #┈xvuw+c{.2IL中,o)N$Jԛ{vmD,4 Xꑊ)cDıC*끣%möt^^/z igl6I:*&"tp]M;^o^QH}-M`:b:)o4ܤI&ofE?&&{=c#Ѿ`ZU޲:pqD}*h#IKn`G੘`@Uy7x 6.1VKyHx %m\  nRX+6$x'eJXUy `(-c򖹔_4ܤ-fLt`ދ)culF)o2W<<Δ VUr1圈pDl] 2J3%5evD,iIM9㬑cIڐ&ǁ# 7$mF!"VgcdQ[nRkD*IRnSaGy%(-O4؜[XN#0j\=ޫ^-}xLE^ < l{CcU-)9U"y[2?c,IRVoy3pTDj~?YSrxDy|э:eъxo+]޳W[ lRNv*SrhX%>FYSҭAÔufH0"ί^}$};ZZ+Ī@f'zہiqo |f`xv $\{ֹewBvXϲQ>IeĤXiceed1VGy;Sn_if2Jϔ\[4{&^<tmrZq<ɦOaZȶl <S6B^/<`׉~z̩?wLH۴Y8'{Z$ҕ!Mr!t:M:xlEk> Lf{Ygb!hQ5)mkJȾ#X!sl<ʂ$UzbOM<.vS{*QT/z4] JEۀ ƅI3Z8WkjvRdxS]{M)˕Ҝ 'I j1DZyZ`E+ LF F2ƣ J|nLRqͦ 4)pc/A$~5v֐9/w$an3/uD#sv|\wA=MQ*YF\qЫ89QhٷNor:Zcǥ.xE i{IZ řKxQ0Ƌy!K&RpMvåNx|AdRT27gI8Mg >t[g oPjg${k Ķ vS=g #?_p_W:3硃0C`Y7!/p&B5 ڮ^-?VԂDspeedcrunch-0.10.1/src/books/images/cylinder.png0000644000175000001440000000704311015364561020754 0ustar helderusersPNG  IHDR<qsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATx{U?_ -6B  [R4AC L+j Pސ ޢBWj B-?8gٽ{wsqdf̜ΙZS4[;qa9Ipa9Ipa9Ipa9Iغ$&qF`}; I; bäm~X1뀵q߯Asb:1CE-#pNc&sc<\ef>CoIcS9%vy;qO pJr.3tfpCA`IC›Y<߮[ ƵPl 4Ώy[ M.1A0ت?!Y_H׭cI2̮mu:IW.< |SZ’)!B)fd;#Nˁ٪VV|%}Ex;8^Kf1H Kh X fUDTkߙQpQ9Q G1֩q{WysbPi5QǏV;VQ0vh/3{=9qf`+i$ l\e|-4gRU+M8*!C-1ˑU 4'؛Gf80jp7\8"$4PMf>, LV7$-Tk!H i!o *BOh,-`fU/FdI%X34N$sGdnV) +wMWOTa5"ª&vFr "bnj)t|2ϔTmQɔ}r ݲ(HaC|"q%fߡ <(i-4`?23[+V ךٛ1Ej%]`f #]cJ8$7GC(m<݀Cw?s< 7YάkЈ*1ȥˀy /=ZN[K)_+oǛ٭]0$!nZW-#RJ%x\|ۯ^DQIcw_RG ̮zntI#Py Z: UYݮ hZ +&808xлvI[3nR`}p9kyftGs-nJ稢ۇ0G2U o5eE`n:Հ6x$m " oC 9mCvY.GxLgf p5p}ܰrƌ~dӌn!~ֽXgv8p"!o'ĨW/n ]iaaJ׏YwG!Icy80 ";ǖg3wJBy9bi:A<d`SH*:/^%,q4Aiq7 lT Ïu0bۏ$BjBݺlik,&^h.P.ZTXՈ?rdNN)kZ7^,sAm6pl'EߟwLX,.ɳmo=Lm'z/L)PY,;VGR$,VH{USݻ ս`)yuEu]),rN\XN\XN\XN\XN\XN7i#IENDB`speedcrunch-0.10.1/src/books/images/cone.png0000644000175000001440000001134511015364561020067 0ustar helderusersPNG  IHDR<qsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<bIDATx{ŕ?DMwtnkMFˀi 3yv%,wV>w;0 KUtf]笤#,98XM<݆#%"}(;/U՗*p>64G,{7^X"2PϪi'sx M}[Uou[?)D  ܌ `VX +,ٚu~iտD{U^1b# Qշj3 @Uŕo#`l~z_Xl;Iơm(p2_Qa'ki镍Ԫ.ϛME5< \w d6}Ϲ&=)SMH,"CDdld><+LrM9d{7# /6%k lp~ ~3VwRZX"r20XI:4SSTu4ߦg3h/ܒ[aG(5֯yx Jgz [7p{\ )0^fz#UKQL'sk^V#wrXk1CUM!qQQ"rNI,^&32:Sr."|KUuMBV=X]ɪyj}Q9!/#^6|R/ܐ+aa~OTެ;^F?,Wr#, :|k&beva.ȅ}߽HU_Ҟv"߽2sr!,[K9ҎnW,3'sa^XoL vx/L\XXfMYӮx݄#P5  #c.P/LX>-E{q&db] PdhG|++#aȧS1Gj3=:uRf2 p> E*{J-D`EXCT%"C(^k̿-9/O[-U8o R+9p;E˺?!iXCNs87?sJy$D$.,Lp2gFzI$*,NXje?wR{$F-֗CH8@|CIĄ%"WdU}'u0w:J$[퀟'^?檤IDX"7Wy nu; |>w:IX/cuq]Ddgpg_L?^7הb#kMU;1utVgNMX"r,p I?:;0b, ˸PUWđn y.㊻Wu138mx5 ۙrLhYX" lOAVR䤞u- +dS'Z5( ^wlIRD?; `OU}cBDv Tuem~oG'V{)W/D#x4Ͱ_2%"xSUuAꮰDd;9XA{wh"{hp.)"SۣNq_'ea<"Ƿb+X_,ǣEDK }/}#EoVZ.7=v6vkn Q#^@fb+`^8~`81 PڛÁ<g==c~[FZ,9t"7,E(.im}կapU+yOmlǀGG9x n6_Ed3N͈JDv*}6lST1U}:+QU]DEon6ACD'"4W[rRom&K}D, `!0&GJ > {NlkXcu}8|z[/0LUl v!GalYEMDT/U? Ѽ}DDd*"`|Nj.M; X$"x9:oIݰD؋by-t>׌P[i,S&cu~k!zH?zhb -sKADFa}seTkŚOoeimNN~.RX"R;|8%DdU,"'IV}1 LtMԥ9 v #f,MX@OR:U@]]L rRwb}45?(k{'U=AUSSm9;DdʡQUq6*ūkߝ-":^u'6>U t]ZjWUX"r8;dPN'vvK:JK0M'Z.ו [/Z}EޱuP&zy,vj,FPy""Ga&Ü`!G VADc3W? P:{0w=H*mc"[?PdZ/c#D_Ʋn&ya[ ,֜t߳UMΩ!,ƆRv5ZXBu- ^ϰaԿȯ]GU8!>yoQn] Z/Edkz`^Łn'ʏJRnv3Lf`b3jr،O8?z 1xa.nPlZ&u0is_ U[ M/ `BoA ]*Zj?*bWT edX_,Xbˁm [˝9oF^}I {ǻJS6apбxG1<`3zf7HKܰ#?1 iLd )n'qx&c1T z3eZև يGa:)-kl AhBV8C+6~!pKIԯZc`u~,i$:K<6-dž,~|%"2(7b3,D|kb B~͍d/1دG}{^MVLEP(@j6&BWH/ L8% lP7 M+ aUG[չl-h%vwfnޕlJG_Ro!ª6H^?P->Z57,lxֺt?Toͺ(lKt*#+AXD $BV H @"?R(QIENDB`speedcrunch-0.10.1/src/books/images/cone.svgz0000644000175000001440000000324411015364561020273 0ustar helderusersXmo6_)bEYbt(}Y@SFwYa ;=wM؀W3r"EZh_nI 39-SϘM 3rϜ3& 1*m 穄^WB(DOͻNK+¹0سCif/if('i_PU-*VN,`p* b!I!U)m*W$Nfl__V**V#o"J6T$ 'Uc?J:GCj[|֐U$}%p})Tv$m\jGԙX5 ]Z~ DjAF`#I?t`]`UhocfK:v(X)fm)(\ISlZ8;[C5ǀ9~[ cb~q L}p}̀Ӓؾ!P%iO1XZI +@{S K;$=,iZF+;% q -~ UA.Kp!p7z4hzډ}/嶷[ }qm^j{:xpLCN4[fU]Shc{NnC %U^&taeRپtĻFO7:W=XS#^/4:XN.l/$*TZk?e.7i$i=I ~KIk5z`I[W~(,g{[i$iS৤kVkk6i`8`qyp p=4`kۖtp1 dU^|1d6}9ppl/ӀIGi=ʡ ` /Vե? \+X#PLXPyG`$]#N^˰`ho988o'iqnG/AҡO3c0koN,v0$M!]x!xBRqkGGJq<\]zhit+5N[BҚqTآ~'%].iNЫ>cH:8txĢbO"8I uMtdLKxI}헪W$M&uf|*4N_lOfcc.X|YH8Ul3I3;ؘQl&ic X:Z!}>bc"X[邍J-t[Vez9 -GFO#+(!4b zKCSF%[5[o+Xno}W?UŊtsE'BվbE{Km*ݜ(?vDa$jixHajQX9Bl3#T6+[r%Vhoi*V4ۨWhoFb-&`RJ-Hk2Ԓ@Cx"bPSكU\q پh<<[|l<)?nEmmX<)m/PsN}R/^CO'[=5TŢH_0߿O0x8kǫzR{˺yw[jœMKZ %uJ 8A"C*,WI15pYz{I-#DxGP;+|X4tOP3el_>X~`O_ \ Ӎ;8o5*`F`ۻF*wp2iN5Kz"w1f2@ 5NJZ t5;jj϶mߓs0r=[C3EBE+d$!IGT=`/ PX"բaRwľ&&?]LGR-lI ;oׇ`vUmEKt/ 1]@kE;~xh< #7v6^-V:> -H>AzK8"\+dsE+d YDBE+d YDBE+d YDBE+d YDBE+d YDBE+d YDBE+d YDBK9`IENDB`speedcrunch-0.10.1/src/books/images/right_triangle.svgz0000644000175000001440000000356411015364561022356 0ustar helderusersXm~Bբ@wimR~Ic@K, wz =/v- 93/oxud(2͊w_Ch$/RؚEi~{zm"5<_WI*JNHhXy91 -8Mfg_]\٥%rql,Feh~{RI;}L-0B$WG(,j[us/$i \mJw0~BZ{7(ה2Lc9[upϢx"+k֣jx$qnMV~x%N眪\01h6QZ&{@֩< +NVS'VS &HNj/ęE ܚ5&3^sA yEVIQFZZV\\KNH.{A9V{;PoRqhЬ\UyPQk68v>Ȳm8y!t2/@Sg%*.}á@:)cCX?gGjkB@,V+NжA}:žSQ*_}f.q\ԼH o?.Y*fNQi`jh͉ukڏײ!H+"0]LT#v?b0G9,O#3aSd+ ^Yݺƒg$~$][铖d ±bkÑ08 |S2@  *C;d( A$ V/F s#E OXV  ;$ÒM|G-"ydQ wQ慔u FlOS54?r4\ UJZJ䅆;ifٳgfa,$.c|L8 51 <.S@$D шDBG2D@[8,jv5C_.uR7p(٪6> ,bP#DζCwȂH}x_ VR-"銩+-%ZZa,} zcc0Cgrs4;#b#O.߅'Vx㦏o7|]+/oƴ`eqm*tCw~⛪;gpSm'i~֞}FX7ez YĻ 7 ߀o@@q k6qfY޽55speedcrunch-0.10.1/src/books/images/circle.png0000644000175000001440000000745511015364561020413 0ustar helderusersPNG  IHDR<qsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATxW}_oY*[ #X~Df)jܔl%)di7۪M6FIԭ ƚ' DSDJ4F3*V')<<~y%77<|y?s﹟9M"56 QMȅ$D.\E"i0L8` 06?!gxl_ %Lf4 Bywυb;m3ql +-XC,`xxUv~~x*ASKDUW/rK`.az6mAl/Ӂ VneKD: m-ҮDa?$M4X J:EI |m/)Fh N)Ķ9aI݄(up텶k]j{!p&ᚮvKQ҇uzFX>,['鳶>VyaXe%4Ӂl_e;i*{Jo\jaIBx5wlVױ5ńx%Mi)%}afk 6 \)i.2Ή} 6mXNu`[$>9G;$}=Y( OoovV Qj`cRP aI <̲z& fnk)+> ~H{zEoqxU"a X$ }ӊ?4!4ibN#DžP$""\lfhCfľз/ƾ:]K mUtڈ"m"=tUX"ٟgn{[ZՒ>Vyxx5aI2 cn-ˁg%}=X}T}tISwJz h;=%}=y3waſQS۶w~Gҫ۔;Fqm<_Š }$bz&l)iA\uYnXECx! IN /~b.+Ν GŠ뀛~$>R!~NM:It./Sawˊj@_jOH<*ifǺP9|w&n̲"VLטOx\* cے$=o,$bPNA|࡬;VLJT=J2ViYD J/o贡b5?rv-`$=IOORzu mvĊ3eHjq'7@[+N.'}z3rv›D%eZVc\V:js E GZb;k@Do %ZV\웤9~b Vk5b}U?.%ԯD_o%iV\V[3-Q&j+Z7aDhEX,mըDeXJ@S4%$`}F%z4TiuDkD߯!h! kaD4Vܛh//ΟȆQui&bhLSQls}Vs6j(b*Y|@QFšE/̳m$ + + lH f#0^X5{WKN>FF0Gᰞ.^ܜDUx'ITZB(,JA\O ȉPȲ (iHUtS`i80g2{wk k K$ 9IlLaaպǚLV9LTIR_'heIXmZ8@n$VQk p87s-!o+#3]2ZKXI7Ql Yv P89LCXƼKCaX;isZ5#VyoT^.)-|/HQ][dowߤi( Hc`a{j $,N7{s1 Px8-7sU4j܋@J$r:DXƜFCaXFԜ% g2ZL͜DUJ0вvhTjTr>`Ss3)Dm#he# +։AD3Skgz/w4K 42"4ssURFF% KH7Q ² ig&)jdDe01uAHJGz+iBF%zmԤbZZ1Qy6JnJg%0?U`>Aui(,[ђgaUw5Qf SJ@ #\|7mÏb;inuPi0?t Uf7RtH&`zfd[K*I#_(/g/E_vLfE&2.V3!Eto˸D~FYF>^YI'W]Dh-2a_3~oϑImϺ\lF_qDD}9Mj |x*藇苧FB\J^%|H`=/y_~x؜"Wqľ <}+])@}wn7TO"U. B;4/=-v'uޮf$ xZ|7ݏ>x뚨kۛ%dv_FהB= ɡzp:;b_з!*(HXf li}Ч3QoB>m};p=;)u$o_‰1]c:0Mjg H ${6N=BO C_&IzYPaAHsCB'RQpbFsm0t,)ҏBdrI]ig*tR7XCw"~\BIҹ2 J.,8x0 <-~XYP҅&\D DE$BUZY~AH jU3;*+H: FO:w\C( `c`[&2o5x&cA(c13Al?$h!}[R6ZXDoȅ$D.$a%r8sCRIENDB`speedcrunch-0.10.1/src/books/images/circle.svgz0000644000175000001440000000304711015364561020611 0ustar helderusersWo6_)bDIe)mAmMRY(*H}ʐbڇ)H7~w'^D|m62 N|6ZF)qNqs6snܬ,'d8roJ f|x.-;ýN%箁ZQ˜o/¥xdhiTeb+NwQ\e+)X8#QlD*`[ Ycx_NM.(R бLXr(ڃYk[}LOT9k$v WaC1h]}wT{&ҤKIM;/ p]F}bzGܬ$ieWRA+}@j#V'D?``h /QYpIXBSqmbA.2H*NEEQT x9m ʄ0(jUFT],x(!y E_btUQT>|w]K_,B;ਆ I1\ʒ񃡘dcYVԙV KskDQ0Cӟ,wnAν偑(UrrK/I11H il 3W!2Utd@zh6ASrOVݦuϯlY=\K?W m͡3uӪv5vf^&VS繞mVgvu?<<ϟps;@(fa0QpbC3ˤjGTQe 'Rt_ܬ7_]speedcrunch-0.10.1/src/books/images/sector.svgz0000644000175000001440000000324111015364561020643 0ustar helderusersXێ6}P4X Z)J֥mL`nDȢ@m>Eni`AXVa׷sa=sYae*l I yq8G2C^hOFy};]gÏ4o~!!ħk(m\+o M9ׁ|z{+q&~}0V2SgjSe%4QpC5KUϰ4~90Z'/BvpLQ޶v̤h :E72R ΄6sH v瀞=oԟ{Y}W V\VtsͳlM3ZG}Asr*zԴ+} R w`˘b;;I7pp'~di$ahF;nQ{fjg}JV$bb&mn,=AE2nnh_Gظ*V5q,2R\xK-{Zb-:dw =N"yF!8S#/sϼY JUfuCݫ R/gT rY,cdKX4w>~y%kߞa^`.11{+VXaCd{:/Z-ju έZ᱀W/!y_}&U( ~p|#hE2 Vq`i(0J t.&Z)^ Qh| )pcߏȋ"/"(DAVy #WbÓEc5 1XQ~Z4B` #"J&P-3}-Ƒod'5zX %&-݊Rk p̐z1@g^ťbn-Qp&Mw\oC01 ^ 0"i2c1 ^_gmJײQ4L]&g o K'īnOPp#*39+Dv5Wɉ(Uzd:!LjŤzWDt8Q֩LOx5Yc¶RbQj+FqY΁|zX;[w.H̿\p7ۻQ9z1yp$֫/Nn\cok0KI]orxn旍.݄!?%8.o)cK| 0_S 16=^m/42speedcrunch-0.10.1/src/books/images/quadratic_equation.png0000644000175000001440000001232511015364561023024 0ustar helderusersPNG  IHDR2"sRGBbKGD pHYs  :ݙtIME 4WtEXtCommentCreated with GIMPW0IDATx\wXSKӟ@(!!顉)V@AlXѫ .ׂXVbET(4QJ MN r7ٝgxW:r0cx"I;xC[拎gFoj0En@96xp89ҔPf2^@ 0g9N9FFFz+yڬ3[ EE_/iDPa'a_T %f>6ع9,e R罧NGi'T첓ji )0vx}SkeNSЭ_%u!KU?8?n]P ӪQlk -b{3,_8ȁr|(Ԗd-cz"aǁ"fOdϝjN28-X!RͼQBF̶2x`|cCGse2?6vGVtLa޹Z /M_1TFn ږ> Hc}j_bP!ܲ|DSuz"(xTįFPoC46@PCXI:Z_amX -Wou8sNxw$s;Q/d^ ;3ɪ _mKn7E881(b5W?+Fy] #ijriŗ|}˄@$i[dX߉/@ t/B& =WV( Rg]CY,4m8PiUƪj){|ޛXyׯ .pun~hCK\c}<&l4z R ;l,ٚ;ΡX)CW"k_J%V ȯf>6uY:4J57^=s#9[QhWuhOPSj5{bR_QP[x4m{ˋkÒ ΍Ͱ9 5ԾxHKRd DQ4is׽NJ/1)(onQDae&P+8xk(4 ^ x`,-X}`#HM;"Ϝyͳvqw^>vxcI7}5D'?QN^?>6M^YbtBuE'-T;G^Ѧ^H4*.8R(!AY9}iNHO5"pOk{&^IL4{qz\e@-,gx}J ؆HHu+02uwu$CkS&~75 v\ҏ˕4PcȜ}sn@=_OTҚ{<&fڞ+z #˼2It\xݑs*mMd8ai^e]C@KG;Pն M =>X?&Fis*cH闷81f8)~ZwL7qng#BDnRt#ŗJ݁7Y ?ߟǪK\@(!u7/Uq=fכ$Lg$J"@ˣېpik%qab,=(-+aKoJLk9x7]m,gB7bK2>ӌA_ 2LF58ȓH/ 9PUL$mvIN/,X>ኛ4C}Ny! /aH t@=f><FqjZ7 ^t KP"'f}Op*AuLs,FK?)^f-HOz("[v|t5 >&.}n!tt@[K+j,3r:vK/46˱_ Du&l077u$&+  o}uijlLLՕjD2 / +-`hΔ=\/ F/.@>O3s ] \aB͗бhǓ 3BF8Cvo۹JDDLE[NUk/,? }-_Z.I4Rٷ9ܵq۶ή*L[~QȕiCPpgY6HNY dNv~Xd}7mm垎 M!)}P;&6熓vzNbU7yF69oX8yFn^8Or-,-ŚvS (c9M=?]_ ɩl!~׼}ׅP@لWBZK<3G}]{}-}`k\oN,k0ݍP*dSJ02oӾQD%PL`RbfwȀl֟V '!< 7&j&rtU s.0ASI'u`[~t@]V VDto2.kgo~oEږ>d}2[h篽 Qc=9Vx4u7!$k,a|$a#t:ZtQ6Z/vW1mيV2KR%Dd%i 벞2{Lq?Ψotмm}>f׾xȟ{k[}k;ٴ_"xP$jëYF}ug͏v.A 2 yfe`,*rSƩ/֎X?<JO!?m]#w!H.<_͝!,EJ9IQX]p?x#6EBx,-rZs#pޚݎxa@DXEpDd2 aO蠩"C+?ˊ ڮ"!9;<0 rZHp[SjZ7NP%%F!}ܓN&#!/yȹ`VIL٬}Rs2A+8d874ӦQG>qu$R^ZxgiF ?P6S N;h2UU\]tWjjU}y&`xӢ5G&k 3-:ʘ}E3 E%>d0Qf' ,a |U"Q lQ$ݙJ.^@͉ɏj (T Z(ZVd!ϰxm?MȬ5 :忂o.ęc"@Ff_,(1w IENDB`speedcrunch-0.10.1/src/books/images/cube.svgz0000644000175000001440000000276111015364561020270 0ustar helderusersX[o6~ϯ ذBɲ,v-hQyYqEV#E_C~yH(, 9L.i(/bmtdںF8;l?7VVn7 CS,(α8j"9~: u>͸&5t4 fEH^%O,Дf,:3ݙQu|%9wUB(v,1@(#+n{c۶NeRa_+=Q3z2 $ir9:HpSZ8Е9&l=p>&Nhe網gY ɡfז}!ŪB1$TBؐ:UZ`y# \D#b &K۾W$ 5Dz,MA4\LJ`}XC֜gɌXsV \{jƎqByZ5`wִ qA|*cBv_i$8-R5ۜGLy;c3cFL;pF *<ϙ0ᦕe ue^r.|=Գ9^ﴴ2] 5$,%Z{̺ΰOFLFsMi.$kJqc`o_uJ&X o.> %/Ɵ!ZFo/%Q#$b>ȀK2fNcT>8I>J#f`Վ6jT(Y d4SFh -] bű (EնyTtPhu'_mM߫(L(!8{᭭V@"3Pkj貛Ax!>+mHS.8ʿڶ6QCAe~uz'-bEjI#w69΃%shZ}Cc?*Ῠ:_^`ѭѝ}Y/6&T L%˼A+KGh#8TOs^KN`3 _dēr<ƙj HѱIW ć,常 &~?XD3d n]OrxUZMm:js1ݮbR:UIAp8k+7Y=ᢛ=~bBJ x y /"I?UKFXsŤ^9VӢ*Bh\tFxRU /šQaLhVVXAx~U4{(^Tqp$2¸.&mb󿽞mš ǒ;p "__ i!pppn,~a1ժ<ձA?I>yt-"#z>;8E5jw~k*moְ'Ŷj0ۄ}kw(:xWi}5c5KCo wXh=PF$Cb=jjC,6smj×2 ,Z䅊ЖqEXM}.y"ETPCUחd`UP,3Iܑ|9)aմ{"D4U˖B\:느&}*PXm%fy!_v%"ڃ *EF{%|M&`5p4BHAT_XG`7BeoѫElSgHET9ƚV2ELhf3#D JQ>x( 1ԌgYeJuNxU{A\e{]6z򗜰rS#6:Tai +;7al+b3Y3]^za>xI+HZ \3|؝4 o\՗ʅ(jX[ 58wL|j5!eFI/'@U9?ބ-U}y4 {YXY\FxV*d&KL7xg8G3eLSuVXBP&{7E3.U{ؾ8X')Z!zih(BU୶ޙߙ$Ǫ76^L^ܰI=%hloK%]$M3V k_$d )6g14 1Vؾ0߳p[O2M8sI֞f}%pp4p6'#iatۀqΐ*S䅕UB+/IZҰ=SM퍄!NM/$sfi=5?FY괰f"Gߵ}|ʵauR8>~BXl. $*J aIɚD. ʥ8x%!f;C'U8= CY M,8wLH ;Uږ:S-,ۏ>YZIv^߇b`LtCQUǑt2~TBͯՄ+btC/!\?[GkE:",:Θ>;#Fa>է㔤u8&TXQ?ǚ&qnj|VAqVIOM/6m o8י"NǙK <ߏeH Iyu&+{0bJX`{cUǹPV1E.^\iR2)$,>%0=CbӲ~ˁt:8 +\Ңt+t!kNqͪR SaT:N̟\u7u:N/ɥN/ 2CL/m-XeLi֚tBX)3lMN^X-!KǙ%t^X8IWgKҒ[D~l%]WG_t;_KaHYJ:NZĤt,qZ7\Ju,CqjؤtBX@u5QQza%mVB:! %-[ӶԁmVuaw%Uu*xSg7~M.ۘ8UYDU:N%ht6'aca;elW̡sǏL2ǒ3 ;/:W9Fa4^c{e ?¦(W:Nﱶ X<ˀǁ.8'ح#݀^;#v6~myp.p?:~dcԑxr.e/ vr}V@Șؔ7<JzEv#yQ [,.8ul$=,IIH:H#8Pqu$Ev%4QI(a #m7V=qv6'TXi;3nN@NX$nDF,OUO%iOBٶڴ=]CB:Tf6vьJ*.F@–x~2v?[k)qT8#wGyZu)fQU_Du?SU**h$BWtIgS(c̞Hz-pN+L9d7N}OSvtIGKVx{U #o*xyJۗE3 q"/!d$aZ+gCzy!,F®!O+U|i5Q؄faI:F -xQ]N "$ VP(Us ٸWU"ڃ,f];F_ϭʎ9XHXk/Yji SܴVXN(GJ*C~/W״] l$ gIZz)9]SxZ!{d$p"4*X [E=[*R'm_ TzUVٮlAd)$}x3AHz .oQgEw(?PDXF؏{3pk|\avPs`Z(P7 \j}\ pƄ= o$ 1w `k#%ZV6p <V(KtaMH +p#al.IL־0S^"XNX[B$'I,$1|Za K^l?6ϷVx$20dtXM56~c4&6ȴ(Rև /LBȳJݑ{_ HIX'*|MJAB HFX'<_I؎M*-pz Ӏl?D,pk{J9X&ӄ(k{Q x = - b ± b 2 - 4 a c 2 a speedcrunch-0.10.1/src/books/images/make_math_pngs.sh0000755000175000001440000000043711015364561021751 0ustar helderusers#!/bin/bash SIZE="150" PICS=( "cube" "sphere" "cone" "cylinder" "circle" "right_triangle" "sector" ) for PIC in "${PICS[@]}"; do inkscape --without-gui --file="$PIC.svgz" --export-png="$PIC.png" \ --export-width=$SIZE --export-height=$SIZE done speedcrunch-0.10.1/src/books/tr/0000755000175000001440000000000011015364704015610 5ustar helderusersspeedcrunch-0.10.1/src/books/tr/cube.html0000644000175000001440000000117211015364561017416 0ustar helderusers Cube

Cube


speedcrunch-0.10.1/src/books/tr/circle.html0000644000175000001440000000111611015364561017737 0ustar helderusers Circle

Circle


speedcrunch-0.10.1/src/books/tr/sphere.html0000644000175000001440000000115611015364561017770 0ustar helderusers Sphere

Sphere


speedcrunch-0.10.1/src/books/tr/math_index.html0000644000175000001440000000130011015364561020611 0ustar helderusers SpeedCrunch Book

3D Objects


Sphere
Cube
Cone
Cylinder

2D Objects


Circle
Right Triangle
Sector

Misc


Quadratic Equation
speedcrunch-0.10.1/src/books/tr/right_triangle.html0000644000175000001440000000333211015364561021502 0ustar helderusers Right Triangle

Right Triangle

speedcrunch-0.10.1/src/books/tr/sector.html0000644000175000001440000000107011015364561017774 0ustar helderusers Sector

Sector


speedcrunch-0.10.1/src/books/tr/index.html0000644000175000001440000000034511015364561017610 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/tr/cone.html0000644000175000001440000000117011015364561017422 0ustar helderusers Cone

Cone


speedcrunch-0.10.1/src/books/tr/cylinder.html0000644000175000001440000000100311015364561020302 0ustar helderusers Cylinder

Cylinder


speedcrunch-0.10.1/src/books/tr/quadratic_equation.html0000644000175000001440000000121611015364561022361 0ustar helderusers Quadratic Equation

Quadratic Equation

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/it/0000755000175000001440000000000011015364704015577 5ustar helderusersspeedcrunch-0.10.1/src/books/it/cube.html0000644000175000001440000000117211015364561017405 0ustar helderusers Cubo

Cubo


speedcrunch-0.10.1/src/books/it/circle.html0000644000175000001440000000113411015364561017726 0ustar helderusers Circonferenza

Circonferenza


speedcrunch-0.10.1/src/books/it/sphere.html0000644000175000001440000000115411015364561017755 0ustar helderusers Sfera

Sfera


speedcrunch-0.10.1/src/books/it/math_index.html0000644000175000001440000000135411015364561020611 0ustar helderusers Libro di SpeedCrunch

Oggetti tridimensionali


Sfera
Cubo
Cono
Cilindro

Oggetti bidimensionali


Circonferenza
Triangolo Rettangolo
Settore

Vari


Equazione Quadratica
speedcrunch-0.10.1/src/books/it/right_triangle.html0000644000175000001440000000334611015364561021476 0ustar helderusers Triangolo Rettangolo

Triangolo Rettangolo

speedcrunch-0.10.1/src/books/it/sector.html0000644000175000001440000000107211015364561017765 0ustar helderusers Settore

Settore


speedcrunch-0.10.1/src/books/it/index.html0000644000175000001440000000034511015364561017577 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/it/cone.html0000644000175000001440000000117011015364561017411 0ustar helderusers Cono

Cono


speedcrunch-0.10.1/src/books/it/cylinder.html0000644000175000001440000000100311015364561020271 0ustar helderusers Cilindro

Cilindro


speedcrunch-0.10.1/src/books/it/quadratic_equation.html0000644000175000001440000000122211015364561022345 0ustar helderusers Equazione Quadratica

Equazione Quadratica

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/ca/0000755000175000001440000000000011015364704015546 5ustar helderusersspeedcrunch-0.10.1/src/books/ca/cube.html0000644000175000001440000000117011015364561017352 0ustar helderusers Cub

Cub


speedcrunch-0.10.1/src/books/ca/circle.html0000644000175000001440000000111611015364561017675 0ustar helderusers Cercle

Cercle


speedcrunch-0.10.1/src/books/ca/sphere.html0000644000175000001440000000115611015364561017726 0ustar helderusers Esfera

Esfera


speedcrunch-0.10.1/src/books/ca/math_index.html0000644000175000001440000000132111015364561020552 0ustar helderusers Llibre de SpeedCrunch

Objectes 3D


Esfera
Cub
Con
Cilindre

Objectes 2D


Cercle
Triangle Recte
Sector

Miscel·lània


Equació Quadràtica
speedcrunch-0.10.1/src/books/ca/right_triangle.html0000644000175000001440000000333211015364561021440 0ustar helderusers Triangle Recte

Triangle Recte

speedcrunch-0.10.1/src/books/ca/sector.html0000644000175000001440000000107011015364561017732 0ustar helderusers Sector

Sector


speedcrunch-0.10.1/src/books/ca/cone.html0000644000175000001440000000116611015364561017365 0ustar helderusers Con

Con


speedcrunch-0.10.1/src/books/ca/cylinder.html0000644000175000001440000000100311015364561020240 0ustar helderusers Cilindre

Cilindre


speedcrunch-0.10.1/src/books/ca/quadratic_equation.html0000644000175000001440000000122211015364561022314 0ustar helderusers Equació Quadràtica

Equació Quadràtica

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/genbooks.sh0000755000175000001440000000416611015364561017341 0ustar helderusers#! /usr/bin/env bash #------------------------------------------------------------------------------# # This file is part of the SpeedCrunch project. # # # # It generates the whole book pages (including translations). # # It makes use of the template2pot and po2final template translation tools, # # as well as the msgmerge tool. # # # # Helder Correia # #------------------------------------------------------------------------------# #------------------------------------------------------------------------------# # macros # #------------------------------------------------------------------------------# T2P="python ../../../../tools/template2pot.py -l """" -r """" -s """" -e """"" P2H="python ../../../../tools/po2final.py -l """" -r """" -s """" -e """"" MSM="msgmerge -U --quiet" #------------------------------------------------------------------------------# # extract marked strings and create POT # #------------------------------------------------------------------------------# $T2P -o i18n/books.pot templates/*.template #------------------------------------------------------------------------------# # merge and generate pages # #------------------------------------------------------------------------------# LANGS="ca cs de en es es_AR eu fi fr he id it nb nl pl pt pt_BR ro ru sv tr zh_CN" for lang in $LANGS do touch i18n/books.$lang.po mkdir -p $lang $MSM i18n/books.$lang.po i18n/books.pot for temp in templates/* do woSuffix=${temp%.template} final=${woSuffix#templates/} $P2H -t $temp -i i18n/books.$lang.po -o $lang/$final done done speedcrunch-0.10.1/src/books/de/0000755000175000001440000000000011015364704015553 5ustar helderusersspeedcrunch-0.10.1/src/books/de/cube.html0000644000175000001440000000120011015364561017351 0ustar helderusers Würfel

Würfel


speedcrunch-0.10.1/src/books/de/circle.html0000644000175000001440000000111411015364561017700 0ustar helderusers Kreis

Kreis


speedcrunch-0.10.1/src/books/de/sphere.html0000644000175000001440000000115411015364561017731 0ustar helderusers Kugel

Kugel


speedcrunch-0.10.1/src/books/de/math_index.html0000644000175000001440000000133611015364561020565 0ustar helderusers Das SpeedCrunch-Buch

3D-Objekte


Kugel
Würfel
Kegel
Zylinder

2D-Objekte


Kreis
Rechtwinkliges Dreieck
Abschnitt

Verschiedenes


Quadratische Gleichung
speedcrunch-0.10.1/src/books/de/right_triangle.html0000644000175000001440000000335211015364561021447 0ustar helderusers Rechtwinkliges Dreieck

Rechtwinkliges Dreieck

speedcrunch-0.10.1/src/books/de/sector.html0000644000175000001440000000107611015364561017745 0ustar helderusers Abschnitt

Abschnitt


speedcrunch-0.10.1/src/books/de/index.html0000644000175000001440000000034511015364561017553 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/de/cone.html0000644000175000001440000000117211015364561017367 0ustar helderusers Kegel

Kegel


speedcrunch-0.10.1/src/books/de/cylinder.html0000644000175000001440000000100311015364561020245 0ustar helderusers Zylinder

Zylinder


speedcrunch-0.10.1/src/books/de/quadratic_equation.html0000644000175000001440000000122611015364561022325 0ustar helderusers Quadratische Gleichung

Quadratische Gleichung

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/nb/0000755000175000001440000000000011015364704015562 5ustar helderusersspeedcrunch-0.10.1/src/books/nb/cube.html0000644000175000001440000000120011015364561017360 0ustar helderusers Terning

Terning


speedcrunch-0.10.1/src/books/nb/circle.html0000644000175000001440000000111611015364561017711 0ustar helderusers Sirkel

Sirkel


speedcrunch-0.10.1/src/books/nb/sphere.html0000644000175000001440000000115211015364561017736 0ustar helderusers Kule

Kule


speedcrunch-0.10.1/src/books/nb/math_index.html0000644000175000001440000000131111015364561020565 0ustar helderusers SpeedCrunch bok

3D figur


Kule
Terning
Kjegle
Sylinder

2D figur


Sirkel
Rettvinklet Trekant
Sirkelsektor

Annet


Andregradsligning
speedcrunch-0.10.1/src/books/nb/right_triangle.html0000644000175000001440000000334411015364561021457 0ustar helderusers Rettvinklet Trekant

Rettvinklet Trekant

speedcrunch-0.10.1/src/books/nb/sector.html0000644000175000001440000000110411015364561017744 0ustar helderusers Sirkelsektor

Sirkelsektor


speedcrunch-0.10.1/src/books/nb/index.html0000644000175000001440000000034511015364561017562 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/nb/cone.html0000644000175000001440000000117411015364561017400 0ustar helderusers Kjegle

Kjegle


speedcrunch-0.10.1/src/books/nb/cylinder.html0000644000175000001440000000100311015364561020254 0ustar helderusers Sylinder

Sylinder


speedcrunch-0.10.1/src/books/nb/quadratic_equation.html0000644000175000001440000000121411015364561022331 0ustar helderusers Andregradsligning

Andregradsligning

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/he/0000755000175000001440000000000011015364704015557 5ustar helderusersspeedcrunch-0.10.1/src/books/he/cube.html0000644000175000001440000000120711015364561017364 0ustar helderusers קוביה

קוביה


speedcrunch-0.10.1/src/books/he/circle.html0000644000175000001440000000112311015364561017704 0ustar helderusers מעגל

מעגל


speedcrunch-0.10.1/src/books/he/sphere.html0000644000175000001440000000116311015364561017735 0ustar helderusers כדור

כדור


speedcrunch-0.10.1/src/books/he/math_index.html0000644000175000001440000000143211015364561020566 0ustar helderusers ספר SpeedCrunch

עצמים תלת-מימדיים


כדור
קוביה
חרוט
גליל

עצמים דו-מימדיים


מעגל
משולש ישר-זוית
גיזרה

שונות


משוואה ריבועית
speedcrunch-0.10.1/src/books/he/right_triangle.html0000644000175000001440000000336311015364561021455 0ustar helderusers משולש ישר-זוית

משולש ישר-זוית

speedcrunch-0.10.1/src/books/he/sector.html0000644000175000001440000000110111015364561017736 0ustar helderusers גיזרה

גיזרה


speedcrunch-0.10.1/src/books/he/index.html0000644000175000001440000000037511015364561017562 0ustar helderusers המדריך למשתמש של SpeedCrunch speedcrunch-0.10.1/src/books/he/cone.html0000644000175000001440000000120111015364561017364 0ustar helderusers חרוט

חרוט


speedcrunch-0.10.1/src/books/he/cylinder.html0000644000175000001440000000100411015364561020252 0ustar helderusers גליל

גליל


speedcrunch-0.10.1/src/books/he/quadratic_equation.html0000644000175000001440000000124111015364561022326 0ustar helderusers משוואה ריבועית

משוואה ריבועית

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/ro/0000755000175000001440000000000011015364704015603 5ustar helderusersspeedcrunch-0.10.1/src/books/ro/cube.html0000644000175000001440000000117211015364561017411 0ustar helderusers Cube

Cube


speedcrunch-0.10.1/src/books/ro/circle.html0000644000175000001440000000111611015364561017732 0ustar helderusers Circle

Circle


speedcrunch-0.10.1/src/books/ro/sphere.html0000644000175000001440000000115611015364561017763 0ustar helderusers Sphere

Sphere


speedcrunch-0.10.1/src/books/ro/math_index.html0000644000175000001440000000130011015364561020604 0ustar helderusers SpeedCrunch Book

3D Objects


Sphere
Cube
Cone
Cylinder

2D Objects


Circle
Right Triangle
Sector

Misc


Quadratic Equation
speedcrunch-0.10.1/src/books/ro/right_triangle.html0000644000175000001440000000333211015364561021475 0ustar helderusers Right Triangle

Right Triangle

speedcrunch-0.10.1/src/books/ro/sector.html0000644000175000001440000000107011015364561017767 0ustar helderusers Sector

Sector


speedcrunch-0.10.1/src/books/ro/index.html0000644000175000001440000000034511015364561017603 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/ro/cone.html0000644000175000001440000000117011015364561017415 0ustar helderusers Cone

Cone


speedcrunch-0.10.1/src/books/ro/cylinder.html0000644000175000001440000000100311015364561020275 0ustar helderusers Cylinder

Cylinder


speedcrunch-0.10.1/src/books/ro/quadratic_equation.html0000644000175000001440000000121611015364561022354 0ustar helderusers Quadratic Equation

Quadratic Equation

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/es_AR/0000755000175000001440000000000011015364704016154 5ustar helderusersspeedcrunch-0.10.1/src/books/es_AR/cube.html0000644000175000001440000000117211015364561017762 0ustar helderusers Cube

Cube


speedcrunch-0.10.1/src/books/es_AR/circle.html0000644000175000001440000000111611015364561020303 0ustar helderusers Circle

Circle


speedcrunch-0.10.1/src/books/es_AR/sphere.html0000644000175000001440000000115611015364561020334 0ustar helderusers Sphere

Sphere


speedcrunch-0.10.1/src/books/es_AR/math_index.html0000644000175000001440000000130011015364561021155 0ustar helderusers SpeedCrunch Book

3D Objects


Sphere
Cube
Cone
Cylinder

2D Objects


Circle
Right Triangle
Sector

Misc


Quadratic Equation
speedcrunch-0.10.1/src/books/es_AR/right_triangle.html0000644000175000001440000000333211015364561022046 0ustar helderusers Right Triangle

Right Triangle

speedcrunch-0.10.1/src/books/es_AR/sector.html0000644000175000001440000000107011015364561020340 0ustar helderusers Sector

Sector


speedcrunch-0.10.1/src/books/es_AR/index.html0000644000175000001440000000034511015364561020154 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/es_AR/cone.html0000644000175000001440000000117011015364561017766 0ustar helderusers Cone

Cone


speedcrunch-0.10.1/src/books/es_AR/cylinder.html0000644000175000001440000000100311015364561020646 0ustar helderusers Cylinder

Cylinder


speedcrunch-0.10.1/src/books/es_AR/quadratic_equation.html0000644000175000001440000000121611015364561022725 0ustar helderusers Quadratic Equation

Quadratic Equation

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/en/0000755000175000001440000000000011015364704015565 5ustar helderusersspeedcrunch-0.10.1/src/books/en/cube.html0000644000175000001440000000117211015364561017373 0ustar helderusers Cube

Cube


speedcrunch-0.10.1/src/books/en/circle.html0000644000175000001440000000111611015364561017714 0ustar helderusers Circle

Circle


speedcrunch-0.10.1/src/books/en/sphere.html0000644000175000001440000000115611015364561017745 0ustar helderusers Sphere

Sphere


speedcrunch-0.10.1/src/books/en/math_index.html0000644000175000001440000000130011015364561020566 0ustar helderusers SpeedCrunch Book

3D Objects


Sphere
Cube
Cone
Cylinder

2D Objects


Circle
Right Triangle
Sector

Misc


Quadratic Equation
speedcrunch-0.10.1/src/books/en/right_triangle.html0000644000175000001440000000333211015364561021457 0ustar helderusers Right Triangle

Right Triangle

speedcrunch-0.10.1/src/books/en/sector.html0000644000175000001440000000107011015364561017751 0ustar helderusers Sector

Sector


speedcrunch-0.10.1/src/books/en/index.html0000644000175000001440000000034511015364561017565 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/en/cone.html0000644000175000001440000000117011015364561017377 0ustar helderusers Cone

Cone


speedcrunch-0.10.1/src/books/en/cylinder.html0000644000175000001440000000100311015364561020257 0ustar helderusers Cylinder

Cylinder


speedcrunch-0.10.1/src/books/en/quadratic_equation.html0000644000175000001440000000121611015364561022336 0ustar helderusers Quadratic Equation

Quadratic Equation

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/es/0000755000175000001440000000000011015364704015572 5ustar helderusersspeedcrunch-0.10.1/src/books/es/cube.html0000644000175000001440000000117211015364561017400 0ustar helderusers Cubo

Cubo


speedcrunch-0.10.1/src/books/es/circle.html0000644000175000001440000000112211015364561017716 0ustar helderusers Círculo

Círculo


speedcrunch-0.10.1/src/books/es/sphere.html0000644000175000001440000000115611015364561017752 0ustar helderusers Esfera

Esfera


speedcrunch-0.10.1/src/books/es/math_index.html0000644000175000001440000000132211015364561020577 0ustar helderusers Libro de SpeedCrunch

Objetos 3D


Esfera
Cubo
Cono
Cilindro

Objetos 2D


Círculo
Triángulo Recto
Sector

Miscelánea


Ecuación Cuadrática
speedcrunch-0.10.1/src/books/es/right_triangle.html0000644000175000001440000000333611015364561021470 0ustar helderusers Triángulo Recto

Triángulo Recto

speedcrunch-0.10.1/src/books/es/sector.html0000644000175000001440000000107011015364561017756 0ustar helderusers Sector

Sector


speedcrunch-0.10.1/src/books/es/index.html0000644000175000001440000000034511015364561017572 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/es/cone.html0000644000175000001440000000117011015364561017404 0ustar helderusers Cono

Cono


speedcrunch-0.10.1/src/books/es/cylinder.html0000644000175000001440000000100311015364561020264 0ustar helderusers Cilindro

Cilindro


speedcrunch-0.10.1/src/books/es/quadratic_equation.html0000644000175000001440000000122411015364561022342 0ustar helderusers Ecuación Cuadrática

Ecuación Cuadrática

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/i18n/0000755000175000001440000000000011015364704015742 5ustar helderusersspeedcrunch-0.10.1/src/books/i18n/books.sv.po0000644000175000001440000000312111015364561020044 0ustar helderusers# translation of books.pot to Swedish # msgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2007-03-25 15:42+0100\n" "Last-Translator: \n" "Language-Team: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "Cirkel" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "Kon" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "Kub" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "Cylinder" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "SpeedCrunch boken" #: math_index.html.template msgid "3D Objects" msgstr "3D-objekt" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "Sfär" #: math_index.html.template msgid "2D Objects" msgstr "2D-object" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "Höger triangel" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "Sektor" #: math_index.html.template msgid "Misc" msgstr "Övrigt" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "Kvadratisk ekvation" speedcrunch-0.10.1/src/books/i18n/books.es_AR.po0000644000175000001440000000270111015364561020410 0ustar helderusersmsgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2007-03-25 15:42+0100\n" "Last-Translator: \n" "Language-Team: es_AR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "" #: math_index.html.template msgid "3D Objects" msgstr "" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "" #: math_index.html.template msgid "2D Objects" msgstr "" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "" #: math_index.html.template msgid "Misc" msgstr "" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "" speedcrunch-0.10.1/src/books/i18n/books.pl.po0000644000175000001440000000353711015364561020042 0ustar helderusers# translation of books.po to polski # Header entry was created by KBabel! # # Witold Wysota , 2008. msgid "" msgstr "" "Project-Id-Version: books\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2008-03-13 11:28+0100\n" "Last-Translator: Witold Wysota \n" "Language-Team: polski \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "Koło" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "Stożek" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "Sześcian" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "Walec" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "Książka SpeedCrunch" #: math_index.html.template msgid "3D Objects" msgstr "Bryły trójwymiarowe" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "Kula" #: math_index.html.template msgid "2D Objects" msgstr "Figury płaskie" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "Trójkąt prostokątny" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "Wycinek koła" #: math_index.html.template msgid "Misc" msgstr "Różne" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "Równanie kwadratowe" #~ msgid "SpeedCrunch Manual" #~ msgstr "Podręcznik SpeedCrunch" speedcrunch-0.10.1/src/books/i18n/books.cs.po0000644000175000001440000000274611015364561020035 0ustar helderusers# translation of books.fi.po to Czech # msgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2007-03-25 15:42+0100\n" "Last-Translator: \n" "Language-Team: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "" #: math_index.html.template msgid "3D Objects" msgstr "" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "" #: math_index.html.template msgid "2D Objects" msgstr "" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "" #: math_index.html.template msgid "Misc" msgstr "" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "" speedcrunch-0.10.1/src/books/i18n/books.fi.po0000644000175000001440000000362211015364561020020 0ustar helderusers# translation of books.pot to Finnish # Petri Damstén , 2007. # msgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2007-12-13 16:37+0200\n" "Last-Translator: Petri Damstén \n" "Language-Team: Finnish\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "Ympyrä" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "Ympyräkartio" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "Kuutio" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "Ympyrälieriö" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "SpeedCrunch Opas" #: math_index.html.template msgid "3D Objects" msgstr "3D Kappaleet" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "Pallo" #: math_index.html.template msgid "2D Objects" msgstr "2D Kappaleet" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "Suorakulmainen Kolmio" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "Ympyränsektori" #: math_index.html.template msgid "Misc" msgstr "Muuta" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "Toisen Asteen Yhtälö" #~ msgid "Chapters" #~ msgstr "Kappaleet" #~ msgid "SpeedCrunch Functions" #~ msgstr "SpeedCrunch Functiot" #~ msgid "Mathematics" #~ msgstr "Matematiikkaa" speedcrunch-0.10.1/src/books/i18n/books.pot0000644000175000001440000000313511015364561017606 0ustar helderusers# This template has been generated by template2pot.py which is # part of the Universal Template Translation Tools (UT3) # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-04-16 23:34+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "" #: cube.html.template, circle.html.template, right_triangle.html.template, math_index.html.template, cone.html.template, sphere.html.template, sector.html.template, cylinder.html.template, quadratic_equation.html.template msgid "align=\"left\"" msgstr "" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "" #: math_index.html.template msgid "3D Objects" msgstr "" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "" #: math_index.html.template msgid "2D Objects" msgstr "" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "" #: math_index.html.template msgid "Misc" msgstr "" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "" speedcrunch-0.10.1/src/books/i18n/books.pt_BR.po0000644000175000001440000000332411015364561020427 0ustar helderusers# translation of books.pot to Brazilian Portuguese # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2008-03-24 16:01-0300\n" "Last-Translator: Fabio Margarido \n" "Language-Team: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "Crculo" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "Cone" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "Cubo" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "Cilindro" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "Livro da SpeedCrunch" #: math_index.html.template msgid "3D Objects" msgstr "Objetos 3D" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "Esfera" #: math_index.html.template msgid "2D Objects" msgstr "Objetos 2D" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "Tringulo Direito" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "Setor" #: math_index.html.template msgid "Misc" msgstr "Miscelnea" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "Equao Quadrtica" #~ msgid "SpeedCrunch Manual" #~ msgstr "Manual da SpeedCrunch" speedcrunch-0.10.1/src/books/i18n/books.es.po0000644000175000001440000000312711015364561020031 0ustar helderusersmsgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2008-04-16 12:07+0100\n" "Last-Translator: Francesc \n" "Language-Team: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "Círculo" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "Cono" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "Cubo" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "Cilindro" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "Libro de SpeedCrunch" #: math_index.html.template msgid "3D Objects" msgstr "Objetos 3D" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "Esfera" #: math_index.html.template msgid "2D Objects" msgstr "Objetos 2D" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "Triángulo Recto" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "Sector" #: math_index.html.template msgid "Misc" msgstr "Miscelánea" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "Ecuación Cuadrática" speedcrunch-0.10.1/src/books/i18n/books.zh_CN.po0000644000175000001440000000336611015364561020430 0ustar helderusers# translation of books.po to simplified Chinese # # Liang QI , 2008. msgid "" msgstr "" "Project-Id-Version: books\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-04-14 14:45+0000\n" "PO-Revision-Date: 2008-04-11 13:46+0200\n" "Last-Translator: Liang QI \n" "Language-Team: zh_CN \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "圆" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "圆锥体" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "正方体" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "圆柱体" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "SpeedCrunch 图书" #: math_index.html.template msgid "3D Objects" msgstr "三维对象" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "球体" #: math_index.html.template msgid "2D Objects" msgstr "二维对象" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "直角三角形" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "扇形" #: math_index.html.template msgid "Misc" msgstr "杂项" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "一元二次方程" speedcrunch-0.10.1/src/books/i18n/books.id.po0000644000175000001440000000275111015364561020020 0ustar helderusers# translation of books.pot to Indonesian # msgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2007-03-25 15:42+0100\n" "Last-Translator: \n" "Language-Team: id\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "" #: math_index.html.template msgid "3D Objects" msgstr "" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "" #: math_index.html.template msgid "2D Objects" msgstr "" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "" #: math_index.html.template msgid "Misc" msgstr "" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "" speedcrunch-0.10.1/src/books/i18n/books.fr.po0000644000175000001440000000267611015364561020041 0ustar helderusersmsgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2007-03-25 15:42+0100\n" "Last-Translator: \n" "Language-Team: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "" #: math_index.html.template msgid "3D Objects" msgstr "" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "" #: math_index.html.template msgid "2D Objects" msgstr "" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "" #: math_index.html.template msgid "Misc" msgstr "" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "" speedcrunch-0.10.1/src/books/i18n/books.ro.po0000644000175000001440000000274711015364561020051 0ustar helderusers# translation of books.pot to Romanian # msgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2007-03-25 15:42+0100\n" "Last-Translator: \n" "Language-Team: ro\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "" #: math_index.html.template msgid "3D Objects" msgstr "" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "" #: math_index.html.template msgid "2D Objects" msgstr "" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "" #: math_index.html.template msgid "Misc" msgstr "" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "" speedcrunch-0.10.1/src/books/i18n/books.pt.po0000644000175000001440000000376111015364561020051 0ustar helderusers# translation of books.pot to Portuguese # Helder Correia , 2007-2008. # msgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2007-03-25 15:42+0100\n" "Last-Translator: Helder Correia \n" "Language-Team: pt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "Círculo" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "Cone" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "Cubo" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "Cilindro" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "Livro do SpeedCrunch" #: math_index.html.template msgid "3D Objects" msgstr "Objectos 3D" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "Esfera" #: math_index.html.template msgid "2D Objects" msgstr "Objectos 2D" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "Triângulo Rectângulo" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "Sector" #: math_index.html.template msgid "Misc" msgstr "Miscelâneo" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "Equação Quadrática" #~ msgid "SpeedCrunch Manual" #~ msgstr "Manual do SpeedCrunch" #~ msgid "Chapters" #~ msgstr "Capítulos" #~ msgid "SpeedCrunch Functions" #~ msgstr "Funções do SpeedCrunch" #~ msgid "Mathematics" #~ msgstr "Matemática" speedcrunch-0.10.1/src/books/i18n/books.it.po0000644000175000001440000000343611015364561020041 0ustar helderusers# translation of books.pot to Italian # Alessio Sclocco , 2008. # msgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2007-03-25 15:42+0100\n" "Last-Translator: Alessio Sclocco \n" "Language-Team: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "Circonferenza" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "Cono" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "Cubo" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "Cilindro" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "Libro di SpeedCrunch" #: math_index.html.template msgid "3D Objects" msgstr "Oggetti tridimensionali" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "Sfera" #: math_index.html.template msgid "2D Objects" msgstr "Oggetti bidimensionali" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "Triangolo Rettangolo" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "Settore" #: math_index.html.template msgid "Misc" msgstr "Vari" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "Equazione Quadratica" #~ msgid "SpeedCrunch Manual" #~ msgstr "Manuale di SpeedCrunch" speedcrunch-0.10.1/src/books/i18n/books.nb.po0000644000175000001440000000314411015364561020020 0ustar helderusers# translation of books.pot to Norwegian Bookmål # msgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2007-03-25 15:42+0100\n" "Last-Translator: \n" "Language-Team: nb\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "Sirkel" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "Kjegle" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "Terning" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "Sylinder" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "SpeedCrunch bok" #: math_index.html.template msgid "3D Objects" msgstr "3D figur" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "Kule" #: math_index.html.template msgid "2D Objects" msgstr "2D figur" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "Rettvinklet Trekant" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "Sirkelsektor" #: math_index.html.template msgid "Misc" msgstr "Annet" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "Andregradsligning" speedcrunch-0.10.1/src/books/i18n/books.nl.po0000644000175000001440000000341611015364561020034 0ustar helderusers# translation of books.pot to Dutch # Maarten Fonville , 2008. # msgid "" msgstr "" "Project-Id-Version: books.nl\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2008-03-29 01:20+0100\n" "Last-Translator: Maarten Fonville \n" "Language-Team: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "Cirkel" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "Kegel" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "Kubus" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "Cylinder" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "SpeedCrunch Boek" #: math_index.html.template msgid "3D Objects" msgstr "3D Objecten" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "Bol" #: math_index.html.template msgid "2D Objects" msgstr "2D Objecten" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "Rechthoekige Driehoek" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "Sector" #: math_index.html.template msgid "Misc" msgstr "Overig" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "Vierkantsvergelijking" speedcrunch-0.10.1/src/books/i18n/books.ru.po0000644000175000001440000000274611015364561020056 0ustar helderusers# translation of books.pot to Russian # msgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2007-03-25 15:42+0100\n" "Last-Translator: \n" "Language-Team: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "" #: math_index.html.template msgid "3D Objects" msgstr "" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "" #: math_index.html.template msgid "2D Objects" msgstr "" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "" #: math_index.html.template msgid "Misc" msgstr "" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "" speedcrunch-0.10.1/src/books/i18n/books.de.po0000644000175000001440000000354111015364561020012 0ustar helderusers# translation of books.po to German # This template has been generated by template2pot.py which is # part of the Universal Template Translation Tools (UT3) # # Marco Wegner , 2008. msgid "" msgstr "" "Project-Id-Version: books\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2008-02-21 11:52+0100\n" "Last-Translator: Marco Wegner \n" "Language-Team: German\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "Kreis" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "Kegel" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "Würfel" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "Zylinder" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "Das SpeedCrunch-Buch" #: math_index.html.template msgid "3D Objects" msgstr "3D-Objekte" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "Kugel" #: math_index.html.template msgid "2D Objects" msgstr "2D-Objekte" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "Rechtwinkliges Dreieck" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "Abschnitt" #: math_index.html.template msgid "Misc" msgstr "Verschiedenes" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "Quadratische Gleichung" speedcrunch-0.10.1/src/books/i18n/books.he.po0000644000175000001440000000353111015364561020015 0ustar helderusers# translation of books.pot to Hebrew # Yonatan Avraham , 2008. # msgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2007-03-25 15:42+0100\n" "Last-Translator: Yonatan Avraham \n" "Language-Team: he\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "מעגל" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"right\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "חרוט" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "קוביה" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "גליל" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "ספר SpeedCrunch" #: math_index.html.template msgid "3D Objects" msgstr "עצמים תלת-מימדיים" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "כדור" #: math_index.html.template msgid "2D Objects" msgstr "עצמים דו-מימדיים" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "משולש ישר-זוית" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "גיזרה" #: math_index.html.template msgid "Misc" msgstr "שונות" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "משוואה ריבועית" #~ msgid "SpeedCrunch Manual" #~ msgstr "המדריך למשתמש של SpeedCrunch" speedcrunch-0.10.1/src/books/i18n/books.eu.po0000644000175000001440000000334411015364561020034 0ustar helderusers# translation of books.pot to Basque # Iñigo Salvador Azurmendi , 2008. # msgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2008-04-13 04:20+0200\n" "Last-Translator: Iñigo Salvador Azurmendi \n" "Language-Team: eu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "Zirkulu" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "Kono" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "Kubo" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "Zilindro" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "SpeedCrunch Liburua" #: math_index.html.template msgid "3D Objects" msgstr "3D Objektuak" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "Esfera" #: math_index.html.template msgid "2D Objects" msgstr "2D Objektuak" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "Triangelu Zuzen" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "Sektore" #: math_index.html.template msgid "Misc" msgstr "Hainbat" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "Ekuazio Koadratiko" speedcrunch-0.10.1/src/books/i18n/books.tr.po0000644000175000001440000000274611015364561020055 0ustar helderusers# translation of books.pot to Turkish # msgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2007-03-25 15:42+0100\n" "Last-Translator: \n" "Language-Team: tr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "" #: math_index.html.template msgid "3D Objects" msgstr "" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "" #: math_index.html.template msgid "2D Objects" msgstr "" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "" #: math_index.html.template msgid "Misc" msgstr "" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "" speedcrunch-0.10.1/src/books/i18n/books.en.po0000644000175000001440000000270611015364561020026 0ustar helderusersmsgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2007-01-09 00:00+0100\n" "Last-Translator: SpeedCrunch Developers\n" "Language-Team: en\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "" #: math_index.html.template msgid "3D Objects" msgstr "" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "" #: math_index.html.template msgid "2D Objects" msgstr "" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "" #: math_index.html.template msgid "Misc" msgstr "" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "" speedcrunch-0.10.1/src/books/i18n/books.ca.po0000644000175000001440000000312611015364561020004 0ustar helderusersmsgid "" msgstr "" "Project-Id-Version: books.pot\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-28 15:49+0000\n" "PO-Revision-Date: 2008-04-16 12:12+0100\n" "Last-Translator: Francesc \n" "Language-Team: ca\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: circle.html.template, math_index.html.template msgid "Circle" msgstr "Cercle" #: cube.html.template, circle.html.template, right_triangle.html.template, #: math_index.html.template, cone.html.template, sphere.html.template, #: sector.html.template, cylinder.html.template, #: quadratic_equation.html.template msgid "align=\"left\"" msgstr "align=\"left\"" #: cone.html.template, math_index.html.template msgid "Cone" msgstr "Con" #: cube.html.template, math_index.html.template msgid "Cube" msgstr "Cub" #: cylinder.html.template, math_index.html.template msgid "Cylinder" msgstr "Cilindre" #: math_index.html.template msgid "SpeedCrunch Book" msgstr "Llibre de SpeedCrunch" #: math_index.html.template msgid "3D Objects" msgstr "Objectes 3D" #: sphere.html.template, math_index.html.template msgid "Sphere" msgstr "Esfera" #: math_index.html.template msgid "2D Objects" msgstr "Objectes 2D" #: math_index.html.template, right_triangle.html.template msgid "Right Triangle" msgstr "Triangle Recte" #: math_index.html.template, sector.html.template msgid "Sector" msgstr "Sector" #: math_index.html.template msgid "Misc" msgstr "Miscel·lània" #: quadratic_equation.html.template, math_index.html.template msgid "Quadratic Equation" msgstr "Equació Quadràtica" speedcrunch-0.10.1/src/books/templates/0000755000175000001440000000000011015364704017161 5ustar helderusersspeedcrunch-0.10.1/src/books/templates/cube.html.template0000644000175000001440000000124111015364561022576 0ustar helderusers <i18n>Cube</i18n> align="left">

Cube


speedcrunch-0.10.1/src/books/templates/sphere.html.template0000644000175000001440000000122511015364561023150 0ustar helderusers <i18n>Sphere</i18n> align="left">

Sphere


speedcrunch-0.10.1/src/books/templates/right_triangle.html.template0000644000175000001440000000340111015364561024662 0ustar helderusers <i18n>Right Triangle</i18n> align="left">

Right Triangle

speedcrunch-0.10.1/src/books/templates/circle.html.template0000644000175000001440000000116511015364561023126 0ustar helderusers <i18n>Circle</i18n> align="left">

Circle


speedcrunch-0.10.1/src/books/templates/sector.html.template0000644000175000001440000000113711015364561023163 0ustar helderusers <i18n>Sector</i18n> align="left">

Sector


speedcrunch-0.10.1/src/books/templates/cone.html.template0000644000175000001440000000123711015364561022611 0ustar helderusers <i18n>Cone</i18n> align="left">

Cone


speedcrunch-0.10.1/src/books/templates/cylinder.html.template0000644000175000001440000000105211015364561023471 0ustar helderusers <i18n>Cylinder</i18n> align="left">

Cylinder


speedcrunch-0.10.1/src/books/templates/math_index.html.template0000644000175000001440000000155111015364561024004 0ustar helderusers <i18n>SpeedCrunch Book</i18n> align="left">

3D Objects


Sphere
Cube
Cone
Cylinder

2D Objects


Circle
Right Triangle
Sector

Misc


Quadratic Equation
speedcrunch-0.10.1/src/books/templates/quadratic_equation.html.template0000644000175000001440000000126511015364561025550 0ustar helderusers <i18n>Quadratic Equation</i18n> align="left">

Quadratic Equation

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/pt_BR/0000755000175000001440000000000011015364704016171 5ustar helderusersspeedcrunch-0.10.1/src/books/pt_BR/cube.html0000644000175000001440000000117211015364561017777 0ustar helderusers Cubo

Cubo


speedcrunch-0.10.1/src/books/pt_BR/circle.html0000644000175000001440000000112011015364561020313 0ustar helderusers Crculo

Crculo


speedcrunch-0.10.1/src/books/pt_BR/sphere.html0000644000175000001440000000115611015364561020351 0ustar helderusers Esfera

Esfera


speedcrunch-0.10.1/src/books/pt_BR/math_index.html0000644000175000001440000000131511015364561021200 0ustar helderusers Livro da SpeedCrunch

Objetos 3D


Esfera
Cubo
Cone
Cilindro

Objetos 2D


Crculo
Tringulo Direito
Setor

Miscelnea


Equao Quadrtica
speedcrunch-0.10.1/src/books/pt_BR/right_triangle.html0000644000175000001440000000334011015364561022062 0ustar helderusers Tringulo Direito

Tringulo Direito

speedcrunch-0.10.1/src/books/pt_BR/sector.html0000644000175000001440000000106611015364561020362 0ustar helderusers Setor

Setor


speedcrunch-0.10.1/src/books/pt_BR/index.html0000644000175000001440000000035011015364561020165 0ustar helderusers Manual da SpeedCrunch speedcrunch-0.10.1/src/books/pt_BR/cone.html0000644000175000001440000000117011015364561020003 0ustar helderusers Cone

Cone


speedcrunch-0.10.1/src/books/pt_BR/cylinder.html0000644000175000001440000000100311015364561020663 0ustar helderusers Cilindro

Cilindro


speedcrunch-0.10.1/src/books/pt_BR/quadratic_equation.html0000644000175000001440000000121611015364561022742 0ustar helderusers Equao Quadrtica

Equao Quadrtica

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/fi/0000755000175000001440000000000011015364704015561 5ustar helderusersspeedcrunch-0.10.1/src/books/fi/cube.html0000644000175000001440000000117611015364561017373 0ustar helderusers Kuutio

Kuutio


speedcrunch-0.10.1/src/books/fi/circle.html0000644000175000001440000000112011015364561017703 0ustar helderusers Ympyrä

Ympyrä


speedcrunch-0.10.1/src/books/fi/sphere.html0000644000175000001440000000115411015364561017737 0ustar helderusers Pallo

Pallo


speedcrunch-0.10.1/src/books/fi/math_index.html0000644000175000001440000000135211015364561020571 0ustar helderusers SpeedCrunch Opas

3D Kappaleet


Pallo
Kuutio
Ympyräkartio
Ympyrälieriö

2D Kappaleet


Ympyrä
Suorakulmainen Kolmio
Ympyränsektori

Muuta


Toisen Asteen Yhtälö
speedcrunch-0.10.1/src/books/fi/right_triangle.html0000644000175000001440000000335011015364561021453 0ustar helderusers Suorakulmainen Kolmio

Suorakulmainen Kolmio

speedcrunch-0.10.1/src/books/fi/sector.html0000644000175000001440000000111211015364561017742 0ustar helderusers Ympyränsektori

Ympyränsektori


speedcrunch-0.10.1/src/books/fi/index.html0000644000175000001440000000034511015364561017561 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/fi/cone.html0000644000175000001440000000121211015364561017370 0ustar helderusers Ympyräkartio

Ympyräkartio


speedcrunch-0.10.1/src/books/fi/cylinder.html0000644000175000001440000000101711015364561020260 0ustar helderusers Ympyrälieriö

Ympyrälieriö


speedcrunch-0.10.1/src/books/fi/quadratic_equation.html0000644000175000001440000000122611015364561022333 0ustar helderusers Toisen Asteen Yhtälö

Toisen Asteen Yhtälö

ax² + bx + c = 0


speedcrunch-0.10.1/src/books/sv/0000755000175000001440000000000011015364704015613 5ustar helderusersspeedcrunch-0.10.1/src/books/sv/cube.html0000644000175000001440000000117011015364561017417 0ustar helderusers Kub

Kub


speedcrunch-0.10.1/src/books/sv/circle.html0000644000175000001440000000111611015364561017742 0ustar helderusers Cirkel

Cirkel


speedcrunch-0.10.1/src/books/sv/sphere.html0000644000175000001440000000115411015364561017771 0ustar helderusers Sfär

Sfär


speedcrunch-0.10.1/src/books/sv/math_index.html0000644000175000001440000000130111015364561020615 0ustar helderusers SpeedCrunch boken

3D-objekt


Sfär
Kub
Kon
Cylinder

2D-object


Cirkel
Höger triangel
Sektor

Övrigt


Kvadratisk ekvation
speedcrunch-0.10.1/src/books/sv/right_triangle.html0000644000175000001440000000333411015364561021507 0ustar helderusers Höger triangel

Höger triangel

speedcrunch-0.10.1/src/books/sv/sector.html0000644000175000001440000000107011015364561017777 0ustar helderusers Sektor

Sektor


speedcrunch-0.10.1/src/books/sv/index.html0000644000175000001440000000034511015364561017613 0ustar helderusers SpeedCrunch Manual speedcrunch-0.10.1/src/books/sv/cone.html0000644000175000001440000000116611015364561017432 0ustar helderusers Kon

Kon


speedcrunch-0.10.1/src/books/sv/cylinder.html0000644000175000001440000000100311015364561020305 0ustar helderusers Cylinder

Cylinder


speedcrunch-0.10.1/src/books/sv/quadratic_equation.html0000644000175000001440000000122011015364561022357 0ustar helderusers Kvadratisk ekvation

Kvadratisk ekvation

ax² + bx + c = 0


speedcrunch-0.10.1/src/resources/0000755000175000001440000000000011015364704016060 5ustar helderusersspeedcrunch-0.10.1/src/resources/speedcrunch.icns0000644000175000001440000014531011015364561021246 0ustar helderusersicnsics#H~~??~~??ics8_:__4 _ ^VV;^V+++V__3+++++++4 3+++:4++++++++++++++++++++++++is32hQտ?y)Hrut~<򼟛wyvΖ7ɸ. Ⱥ. mԽʬε˺. ~mǴ. ūͭɳ. 'ã. +Ȧ. +. *ʿ̪1 |v"Z?3}r?`ѽX1,yʹvyxI hzkz{x΢D\Ukv; RêۯƱ; Fش; NKͮϯ; ƾӺڼ; :ĶijӴϷ; 7ϮҬԸ; 7ͷ; 6: ) >%C09'>,$xzyL |{xΥGV> '3Pȴ> %E޹> ®ҳԳ> (ؾ> :ɻʸعԽ> >ǵղرپ> 7Ӽ> <= )s8mkL lɠ?P5RSR RmRuR8R'R)R)R*SC(DBBBBBD; ICN#00icl8_4_4_;4_44 __4 _+++++++++++++++_ ;_4 ^44;54,+4;__4__43_3+4 ,++++2++2+_ ,+22+22_44++++++++4^33++V4;V+V+2++++++++V+V+++++V+VV+2+++++++++++++V++V++++V+V+V+++++O+++O++++++++++++++++OO+2O++++2++++++VVVVVVVVVVVVVVVVil32]ܕPc䈔F 'R~t>sފhI|fvurppqphnF뻯k9B ACk}q{{\p zjo nr맦n A񻏁)6 鼬m"5v͵h~cde˹ǵe]ܹܺƿdm՘╥d@һ2֒z̖yՁھdnAӗ{ˬسѻd(ɸc*֚Εշd*͗tvɵiӳe*Իʾֹֿc*ֳҶԽc*ɏ|Đƴgනe*ǡñd*ν˼ͼ̿c*¿Ȼν˿a*Ωۮеc(̲÷þc qD SUs`1ZAtdiXv. Y¥l eNJyġ[{o¨=l|{xvvwvnĀ,Ths9B ACk}r{{^ N}in mqꩴ )x\S.  x"idR Ļz SAmw[ɲ㿘زƭytչޯИy=fǾwFv㨬쥵v*v-嚂ޞ␎իv G(㧋۽ųʳv3v5槢ݤɎv5~ϟrȕw5γϷѹĥu5Žϴu5ޙؘpw5۰ԳƗҾw5u5u5êǺ̯Ȃu3dz²ָҴwU   !),$#! 4F@4#iQ %)  @^qމ30s2 9r2t2<2Ӗ2.2%22g2r2*2/4_2Z2[2[2[2[2[2[2[2[2Y19' ej  %%%%%%%%%%%%%%%#it32tb #~q' #~q' 0f[7'*#Dռ_&$ -30#"Fʼn<6 $DJG=9*"Cϳ= ITiznAM&UbĽ" #BeG9&'37Kpz$  %Lڹnj% $ #(N̻ɋ$ $ #(NǺݿz#(NшtL %*OydA " .8XgM3 " 7EcQ4#   -%-MZsI*$'&('(&%! ,htŸ- :EQlponnonk_ZP .p}ⶢALYy}|}|xhaW &.NSn⮘~Vcuzk#.Odzi7 ƴ35Vaᬕ!9żǵ7Bo|)$?||~|{ǵ;#Huȼ4$>߲}ywxxyxwvzƶ:"U gJ9%<ý|;KVyۿv;4;>>?.==?EI`v{zmlz}}pIGt: $+Rvͻ|HBKN.LLPZbȾʭe[~: Cfxֿ~MHQU.TSWaiʲعla:1 '9wɾ\Yflkhhkv|߀|q:Ylc`outs.qqt}˃w:Q`ɾǾigx~~|.zy|͈}:+7:t̂b`[WI98@BDHJWbmyy/Ȼט:+-/luVTRN:%#$%'-0黆r*%9Œ-ص:*Uʻt%0ʛ@ -BŒа:*FoW4 #Νs7.Lfzƶ Ͼ:(B{G*绥F:_~о8'D|ذ="ȹyIJ8Q򸟀"؄ՀօՀրԎñ8 W稍q"ބ݄܄݁ހڎۀ ı8 B]ciXG&Ё̀̄˃ʁ ñ8 &+* )āǿñ8!  ?-ŀ ñ8! COjQѻк̷°8!Ta~QͳشмѰҿƵ8!"'H=δسѾήѿՁπ DZ7!_jкذ̀/ƦȢ8!'s~RкׯŤȠ7! HQηҭĢοͿ7! +.]Q̵ͪͼšͽ¶7! ).ZSϺŪϿÿ7!*is1ͷҼ7!!27Zկ.صĹ7!,0N2ٸغ7!  2CRHƿ¼7!(9}ǁ&翯7!b)Yg¿ȿ{wĿ¯z羮7!a +1jĝuy̾˱5-wǴߵ60võɻ羮7!_"&c۾ciƬ˰Ͽ,#m߲.'kîʿɷ羮7!_ \t_H2?ǧVOѰͿǜ0"S߷9/RtǞʭ罬7!_ [U;,,{ѻĚ4+|ӱ̿͡2"Io|෨?3G\oȘʨ转7!_ VΫG0'/~Ѻ4)o˽̩QDc߷[ScsŘɧ罬7!8C颃j !6к0#Luȸ˿ܵ!ξǼĤ罬7!\:tnZ$9Ϲ7)Jkvȸܵȹǻ缬7!\1V_]@6 %;ѽd]ky̾޽ź弬7!\'*CSL'>ĽĺĹ㻬7!"6B=R&?Ľ§ȿǽ⻬7!  *@Áͽͽຬ7!!(@؀͂ހɀ߀ ߀ߺ7!"*@ހ ހ ߀ߺ7!R#(@ҿߺ7!$*@ȁÀ ߺ7!R$*@̼~̿~zÿŬݺ8"R#*@ÿ=7~˴92xĴƸeANð۹8"R#*@2+tð0'nķ`6B«ָ8"R#*@˺."\ś3%Vžc$*wŠ8"R#*@ʷǛ-Q̠4$Ltüd!hƜ:"R#*@ʷĠHsƾß8"R#*@ȶ¹ɾѶ8"#*@ɸ#¹ɀ Ļַ8"R#*@ûȿĽط8"?#*@ξ»Ū̿ٷ8"R#*@»žǭٷ8"#*@Ѐ¿źրοɰ ٶ8"#*@րҀ øր ̶ׁ ض8"?#*@ķʹɺӵ8"R#*@ůkhǹwtʻrydz8"R#*@«[WŸgcȷtckij8" #*@ȺDLE~ŽãRIºsLTԿ8"R#*@­ͣ;0u¸̿ө=1ps5=ҺΣ8",#*@̢<0qʾө@3m"s5<ҷΤ8"R#*@®LBf˾ŦZOh{LNwҷɡ8"R#*@®SHa{ɽeYfs~½}TTny~ѷǠ8"B#*@òjbsʿyqxͽkkyѹȀ 8"#*@ǽ?Ŀʰ;8"R#*@ʮ8"R#*@Ľƾ̽8"2#*@ĹźǻȾ˲8"9#*@Ĺúɺʁƽ̲7"#*@ɺˀ ɽ̀&õͲ8"#*@Ǵǁɸ̲7"#*@ ʲ7"R#*@ͽױսӼǻƦɸͬǰ8$R#*@ͻܫٻ׼ǹơȶЧƯ8$R#*@ͺԉֻֻƸšȶ̧8$R#*@͹fZҺռŷϾȶǦ8$R#*@͹dXεѹŷ˻ȷå8$#*@˼շmd7½Ÿȶ8$#*@˾ʱqi0ŸǷ®8$R$(@ï}vƼƻï8$R$)@ööïžƮ8$"&>€/ĶŵĭĀƮ7"1º'µ-#w% o}{" }ö5#  -2:JǼ}/"../101//+)&*BK^lsľ}v` GUcvod GPh{ЁƿthVP^oxl!/ 25GafuƿoaQ!iz*0'6dq{ŽcOD=Ƭ;8 )4BmyŽbNC@ϲ>88>_sxŽo_R'H¾ϱC#8)HPxƾzq`0NǤϰG,%.LV~.ƿxf 1N㹏ϰG-$8]e,>,.0MÄDEwefԳG+% >?.==?EI`v{zmlz}}pJJyִG+" 5LXNGLN.LLPZbȾʮg^ִG+" ,BNv SLRU.TSWaiʲ׺ndִG+"$NZj d_hkhhkv|߀t׵G+" 9E\ ieots.qqt}̅{׵G+") 4=Wzyyxwvvyz{z{|~plw|.zy|Ό׵G+"+ "$IT@>;9/%$)**+-R¾/Ÿٟ׵G+"? rXSXY]hfP80%5L۰׵G+" 6q{W!'dzyVJ+D͒-صH+"* 4kuyKe~dY*1IΒ ؼִG+"*.Ya~I9"d}gWJ"8N^ ѯG+"&)PX{}.c|yk],$C\hέF+"(,QZ}r( d|wnPK]muͬF+"4T\xgRf| ܃܁ۀ܅܁ۀܖ ˫F+" 6S\n\Ig|˫F+" (=AXhcE9. i}ނ܀݀˫F+"  :l~ـ!˫F+"G    )nـ׀րԂр˫F+"i-5CQ]ϵϵȱ˫F+"d6?Qbjº̧̧߷ƺ˫F+"L.U]isyĺɾְرպ˫F+"g=D\ʷټǻٿzslqT^âl^_berլʪF+"IRh^˷׺ƺڽwphmԾNXfWZ`cq~ԨʪF+"i1qʼÿĹ´ĝuyͦʪF+"i >ʿáàֹɯǤʪF+"i;Ļäå׿̴¿ũʪF+" ELZt{4Żȃ¿ʪF+"g !$:hq~ͽʪF+"g 3V^iswǽ¾ʪF+"f   *4^kwʪF+"%R`o؀&ʪF+"O 8BZuyͺԿʪF+"a C~lX_?7ȼ?8ɩF+"_@ysaNYº̴ǿÚ4*vȺ5,sɩF+">G:73EπDYSƽϣ3%V>0UzիдȨF+" ;|T|3#%'<ɟ6-ƽԦ3"JrÞA2I_tԢğz|ȨF+"^ 8q{n*"'>Ɲ5+tհTFfç`TfxҡɩǨD+"\(T]~jVF+Dþ3&R}ʨ¼ΟųºȨF+"\$KSw^H: +E:-Ps͸ʠȻøǩD+$ \7,3NIJЫ׀ǩD+$ *,3Nսqnuqހ$ϥw̾ǩD+$ R,3NäWOͬ[SвV`DZӼȩF+$ R,3Nѧ=2y٭A4tʸt5@ںɪF+$ R,3NЦ=2tٮD7q˷t5?źںɪF+$ ,3NODj׀9̬]QjͷѸ|LPΫֹɪF+$ ,3NɿUJeÀ:Ȭh\ivϹеUWȟԹɪF+$ R,3Nqi|ƳyŻ̹tuƧ̴ɪF+$ R,3NȩF+$ R,3NǿȹʽȩF+$ R,3NĿƨD+$ 2,3NÿۀĦD+$ ),3Nڀ¼ۀ½ĦD+$ ),3NځӀĦD+$ ,3Nҁ ЀæD+$ ,3N׀ӀքæD+$ ,3N༸́7Ϳ׶æD+$ ,3NᲭс9þʺհع¾æD+$ R,3NٍˮʶǿצuyÿæD+$ R,3Ni\ƸŏʴƲĸu17ĦD+$ R,3Nh[ĸɴýĸv49ĦD+$ R,3N{r˽¾ܿû̞psĦF,$ R,3Nń{ƶ̼ԴêծïæF,$ R-4OđζžαžæF,% R*2M²¥E,$ +1MԀGºƷÿ£D+#Q>þſģ8)ڂׂԀՅׂԀՁՀւՂ Ţ- &ǂĂÈĂÊăÇăÁ¸) IPUbcb_`_`_`_`_`_`_`_][L &)-5754, $%(./-,+,%                   "#" !"',+%"! "#(.-&$"  %'-2300-)' &&%"!     (+289;<91/.--+%#!   (+3:;>?=653210/-&$! %11231+)&) +/7?AFGFBA?=;640(%"JXh~ui! ,09BEIJJHHEA?962(%"Sbt~r!2 "-1;DFJLKIIEB@:73(%" #n-/   %36>FINQPONJED;83)%# ?ͳA  '""'47?GIOQPONJED<94)%#  D غC  +!%(,7:?EHNQPNMHDC;83)%"+K׹H("+!+/29?BDCBA?=;630)&"2SņFGxiiۺJ-%  !!$&)027;>==:862/-'%" 2Qƺr**avwxyxyx{|nNN~ݺI,$ +"$+2479887532-+)" !4Nƻv2)4789:99887788;99878778787608rݺI,$  +!)015665520/+)'!"3Mƻx6,--./0/0/0014787876556789854674468765308qݺI,$ 7  %*,.0/0/,)(&%# ".DżC:<==?.==?EI`v{{nmz}}qML{ݺI,$ / !#%*++((%!!  #*?ƾOHKMMN.LLPZbȾʮh`ݺI,$  !#&(''%# !&:ƿTMRTTU.TSWaiʲ׺oeݺI,$  !!   &d_hkhhkv|߀uݺI,$    Öjfpts.qqt}̅{ݺI,$   &™plw|.zy|ΌݺI,$  "9/Ⱥ֛޻I,$   &=/Źء޻I,$   *Dðݱ޻I,$  0KǽБ.ü޻I,$ )  .GБ.ۿݺI,$   &/PZXQQ_lw ׶H,$ (  #&.1.)*>RaմH,$  !#),)#%>VfԲH,$ !! ;]r߁ހހ߅ހ߂ޓ݁ ұH,$  >dy ұH,$    "$$!!T ұH,$  &,+#K)kұH,$ !(//'$#-"! &2t߀ށۃڀұH,$ d !/<=<<931.*&$N^ӷҶɲýŮѰH,$ d  #1@BDEB:82,(%]nͨΧ๱ɽѰH,$ K$'5CFHIE=:2+&&^r¡ĞְٳھѰH,$  \"-1=ILPRNC?3($'dw³Ĺ|uns÷U_Ʀm`agiuڱѰI.' \$.2>KMRSOC?3'#'at忰¶yrjoOXçfX[eht٭ѰI.'  ^ $/23)%#ETķƷƝuzijӪѰI.'    + $/29@AEFD><4,)*5oɥǣ.ػ̲ͧѰI.'  , #-/6=?BCA:81*'%-bȨǨ܁"Ϸ˭ѰI.' A #$*01452*)%"!2GXɿۀ΀ѰI.'   %*,.0,$!! &!(9ķځ!ľѰI.'  #'(++)" O$7ĺþѰI.' P   ""! 2ѰI.' 4ހ0ѰI.'  T!'>GHGHD@QѾĒЯI.'  T'1^oprrjboş@8ÞB:ЯI.'  T)6lwͶƝ4+y8.vϯH.'  T*?έZTҥ5&XȠ?1V{گҷЯI.'  T,Eˡ6-֨4#KsʣB2Jav٣ơ|~ϯH.' ^ -FȞ6+v׳VHhʬaTgzף˭ϯH.' \0K5'SͬñԢɷϯH.' 9 /JžԧtO^޼ήH.' R,5S;5Ĝ;2|Ԧk@OֶϯH.' R,5Sɞ3&cҦ8)]ʿַg'0ȯұI.' R,5SϢ. Vžת6%Pzɹ׾e$~ӲI.' R,5SͨL@kľհSEfɾֿx>DƽұI.' R,5SȺýռϯH.' R,5SȿūþԺήH.' ,5Sƴ>̺þԸήH.' (,5Sú&ľԷͭH.' R,5SúʿýջͭH.' 9,5SͭH.' ,5S2ͭH.' ?,5SҀͭH.' *,5SǾǵ֯ۀϯH.' *,5SùvsĮws$ԩ}ЯI.' R,5SƧYSЯ]TֶZdθÿЯI.' R,5Qө>3{ݱB6vҿõv7CǨЯI.' R,5SҨ>3vܰD7rӽõv6AѰI.' R,5QâPEkϯ]Qlּ׺}MRҮЯI.' R,5S½VLgʮh\ky׽ַVXˡЯI.' R,5Qtlʶ{ӼtuʫмϯH.' ,,5Sľρ!ЯI.' R,5QĶĭƿϯH.' ,5Qڀ7µƿƾͭH.' ,5Qÿ Ŀ߁%̬H.' *,5Q߀$̬H.' ,5Q߀ ހҁ̬݁H.' ,5Qڂ߂ ށˬH.' ,5Q܀݀݀ځ ߀܄ˬH.' ,5Q⾹Ԁ9ݼˬH.' R,5Q⴯ٷڼˬH.' E,5Q܏ϯӽî٧v{Ȁ ˬH.' R,5Qk_οǑҺɶƹv38̬H.' R,5Qj^˾đмǺx5:̬H.' R/7S̀wſĻĦ­ѣtxù̬H.' R/7Sˈ;ûۻʯڴ˶ˬH.' R07S˗ǹռŲշŴˬH.' 1-4QɹȹڀˬI/' R+3P̽¿ÿˬG,% 9@̩݀; +߅݁ށ݀܁ބބރ Ϊ. (ˀ̂ˀ̂ˀ̊˂̋̃ˁ* NUZfhfedededededededeedededeededed`_O *,18::866- &)+11/.-& t8mk@ /Odը{j2 /Odը{j2 5Yn߽N6+   Drדxc0# (29T^ZOJ4 Hx禌u@IagysG9Jyܚua`gjxݢgT K{櫝vu}q\# N̾s+ OƔ~/ OĔ~/ P辔1R廒}2  +^٭p;&(,.023222222222222222222222222222222222222222222222222222222222222221.! *7j˞pbD7?QUY]]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\[ZU=3*=IyŘlcPIRhmprsrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrqlSI< io.% *J_o.%"[wxicX;;co.%$=VVLG?+.[o.%/BC;73&+Zo.%  "Vo.%  !Uo.%!Uo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%"Vo.%!Un-$ T±o,#Rm+"Guk*!=e{빧g(  7Zq紡d' !8L՝S*=ϔM 0xθoB  >PaRE'  0>Ow~nD9 "-GMTZ[ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ[[YOLA& "################################################################" speedcrunch-0.10.1/src/resources/book_home.png0000644000175000001440000000162211015364561020532 0ustar helderusersPNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<$IDAT8m_h[uϽO$K״6eQiZ2%Ե#`XIT|RTV-R,(ZEA)6ʮk`dqmɚ{>̖y^/|(RJUT !_!IJb%zBblV "w@ p1VXuJQ–S?bUjP>O=#A7Yd2p(JUUoP6itGwwLS5a{zz::11M[~9 ]z୳awBu|㺮j.q&j 6k#QZ҈!j%! R.FD}t(?8^zhpq~7޽[EMJDD? T؃@Dp1{ [chmm}F= X5{8 cDn{&iǩShYG۽2.}DWG!>I<jc iV82qr~s o;d±Orz9_m"~ U-M,ဈ0ollDoxwn*RJ,..zLxj m؎D|6FeL& ø@"{xԣ͂v3\y ߼C1>>a7S*jn7A 333SSS/g2]うb೎ r:0i8IENDB`speedcrunch-0.10.1/src/resources/speedcrunch.png0000644000175000001440000001034611015364561021076 0ustar helderusersPNG  IHDR00WbKGD pHYs  ~tIME :ia,sIDATx͚y\u^lii43hCٍ BD$`;*v]*lq ^q\Nʆ Fy!$FHݳO{HX223J~|swmx%_zGnCm;ؙ1> t{!y~Ρe,љ1܍-X=hRM*h2KpbBHX뙮 P̮BWJ5[E/+?=v_"r[VF M3- 4i]͊$Vڷ?}pQ(ai"jjr  (0"(2z @pVHoOTKu)s GݭF4eB4AnEd!"_m2Qt 3"0,Dc=G8 z}@J"`;_ `FA=ec q߼瓫/|T QRR #~'7|uGnHߴqInK05q 4L {`=K58oaOϟ}9w6z{R- H4bR`^6 p<śZ֗~D4kEQkjz1R,ikF w#d@}p"+y PT% (?%!uHӰߊuO5d {̧>݆sK  G0l3F/u2h(&i~@(|p4\2)Ҵ?-1!t"CMH)!#TPJ!@I4)ψ0[𾺯P.+WDM&S jLݤY *h $c]o_zi0 IFL^K]A@6e1>>N"V100e]Fdjj>"|?=alx}Ԧ;7ev%.!' n L{Tƨή.:2izL*$H`eڊiu (l|J3 ̜?sBQ C SnJyJ#徢W[BX/_}٤|)_a@&fժUcqoXѣLjXi H$IWI18I#Xc\OڔόuL?,c@]WuI"dLUj,=5ݶM0'M5!д._Iijqxgro;(‰)(MUk=me=ZzOVCE3U}B#xUHo?lt;MHuBM4VzMGú'ueK}=Q ZU˭.s=i"+]}!HeRhx3L EګHĢx] wpk_iٟKi(/ hf_1 },l2\fh2M/7gA2Nq -4QR"B!GkI')F4c&5`;6_,+Ǥhap+L%>L駞A:knD) VB0fK5Sn mD_v>Lj'%AZ8xK,\o:N|ӍT|m.0ZW:x%lL\Qc †m&iL9(:_^X*,h#ϓ44`"D༕ɷw90Y1ӻR2EadRK3A#L152̅-'pd|ؖ_)^A+e|kձxPE3HW Q-)q"x)hJN*jyY=k8Ez qpt]H$Rqz$c>_RmׅQJvpDe_ۭXf:'2}qCc8K\2ZK/!`qJ5~ܰq^a4 l%ђ%xj^<ɮ]C/FIw|++5\һT$ov +ص*8A j @:[pܑ1ړq|w?u!&&&=@ 8fXB$H&IZ@Xq%CEhB d޼NlcQ{fY1`h+R!D)W*dJ8hJJ Tx#&zRJ@0ѴrEmÞ^jbOszj{+&G,ijh;?a6( C&w{"# |ʥijbzv.ŗP@HRhL~Uߧ1Z%cA*"T$>9 Uֆ5/2x :&lw:ޅ ^sKF bhx!͡ j@JHo< ͆  A`=rrk46R $2d:_0]o̚hE<$B{EZ qZoq`V '{ #t,]) "V#qRcdld2 J"P*rW1dp)%r$1bc3:s2PJɀta.*ǐ3%r}=HkcAm.vHtT/A:FK:E QÔ^V8' -^9;NU uɵ5\pt2M*Wz$:(!h(hEqiH]xP >TXyW$ c ll?RՅhᴛsL0l~z.o5 Y5l =+IENDB`speedcrunch-0.10.1/src/resources/speedcrunch.ico0000644000175000001440000000137611015364561021067 0ustar helderusers ( @wwwwwwwwpwwwwwxwxwpwwwwwwywpwwwwwwwwwpwwwwwwwwwpwxwxwxwwpwwwwwpwpwwwwwwpwwwwwpwxwxpxwpwwwwpwpwwpwxxwwp wwxxxp3wwwwp3xwwwwp7wwwwwwp;7wwwwp;;7wwwwwp ;38wwwwwwwp 03wwwwp;3;xwwp;33xwp 3pp ;0xp;0;;3;3000speedcrunch-0.10.1/src/resources/speedcrunch.qrc0000644000175000001440000000033311015364561021072 0ustar helderusers speedcrunch.png book_back.png book_forward.png book_home.png speedcrunch-0.10.1/src/resources/book_back.png0000644000175000001440000000162411015364561020504 0ustar helderusersPNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<&IDAT8mOhuǿo/m6eef&5IGQFPӁAE&x-cPz]{0[vX- l'n\:0M?Z a`}ς}}}fn-r6av&lDbApEDǩC>+6kkvDRI &Aʸm:qxvm再u_DXR )pjEG{a&VVVZk|bh^~ M[K(5İ|2\LZcuul66 |t9\ Ct%hi+(G#>ԅKcTdX6D"Q8ա}xЂIU:&C^cjsssʔJKx|vC~tzaa\.mWSSSHdZ&!n< pw5ۜIENDB`speedcrunch-0.10.1/src/resources/book_forward.png0000644000175000001440000000163511015364561021252 0ustar helderusersPNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org</IDAT8m_h[eƟI[M2WlFڑtmTs)cBESBlol 읠 *Fs̥ڀֆ^ K#]INys>/06}/<-|U4M R/o8rT:>Ѡ]mOaAp0!^7Ǝbz\`bnH*3!Z#!"j>\BÞN0I²,! @8h/=1,o#Rv-0MD h]!!|`۶"v әU_c}}=ljhI)OczK|~˿ tY bp8f02̷}}&J*ij}^|-cmFKB'<ïǕ+22|"8t:9oG9G&ٝ}P(\6h4: _mY,s|Ro$줙|IENDB`speedcrunch-0.10.1/src/resources/speedcrunchico.rc0000644000175000001440000000006711015364561021410 0ustar helderusersIDI_ICON1 ICON DISCARDABLE "resources\speedcrunch.ico" speedcrunch-0.10.1/src/3rdparty/0000755000175000001440000000000011015364704015616 5ustar helderusersspeedcrunch-0.10.1/src/3rdparty/util/0000755000175000001440000000000011015364704016573 5ustar helderusersspeedcrunch-0.10.1/src/3rdparty/util/binreloc.c0000644000175000001440000004622411015364561020545 0ustar helderusers/* * BinReloc - a library for creating relocatable executables * Written by: Hongli Lai * http://autopackage.org/ * * This source code is public domain. You can relicense this code * under whatever license you want. * * See http://autopackage.org/docs/binreloc/ for * more information and how to use this. */ #ifndef __BINRELOC_C__ #define __BINRELOC_C__ #ifdef ENABLE_BINRELOC #include #include #include #endif /* ENABLE_BINRELOC */ #include #include #include #include #include "binreloc.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** @internal * Find the canonical filename of the executable. Returns the filename * (which must be freed) or NULL on error. If the parameter 'error' is * not NULL, the error code will be stored there, if an error occured. */ static char * _br_find_exe (BrInitError *error) { #ifndef ENABLE_BINRELOC if (error) *error = BR_INIT_ERROR_DISABLED; return NULL; #else char *path, *path2, *line, *result; size_t buf_size; ssize_t size; struct stat stat_buf; FILE *f; /* Read from /proc/self/exe (symlink) */ if (sizeof (path) > SSIZE_MAX) buf_size = SSIZE_MAX - 1; else buf_size = PATH_MAX - 1; path = (char *) malloc (buf_size); if (path == NULL) { /* Cannot allocate memory. */ if (error) *error = BR_INIT_ERROR_NOMEM; return NULL; } path2 = (char *) malloc (buf_size); if (path2 == NULL) { /* Cannot allocate memory. */ if (error) *error = BR_INIT_ERROR_NOMEM; free (path); return NULL; } strncpy (path2, "/proc/self/exe", buf_size - 1); while (1) { int i; size = readlink (path2, path, buf_size - 1); if (size == -1) { /* Error. */ free (path2); break; } /* readlink() success. */ path[size] = '\0'; /* Check whether the symlink's target is also a symlink. * We want to get the final target. */ i = stat (path, &stat_buf); if (i == -1) { /* Error. */ free (path2); break; } /* stat() success. */ if (!S_ISLNK (stat_buf.st_mode)) { /* path is not a symlink. Done. */ free (path2); return path; } /* path is a symlink. Continue loop and resolve this. */ strncpy (path, path2, buf_size - 1); } /* readlink() or stat() failed; this can happen when the program is * running in Valgrind 2.2. Read from /proc/self/maps as fallback. */ buf_size = PATH_MAX + 128; line = (char *) realloc (path, buf_size); if (line == NULL) { /* Cannot allocate memory. */ free (path); if (error) *error = BR_INIT_ERROR_NOMEM; return NULL; } f = fopen ("/proc/self/maps", "r"); if (f == NULL) { free (line); if (error) *error = BR_INIT_ERROR_OPEN_MAPS; return NULL; } /* The first entry should be the executable name. */ result = fgets (line, (int) buf_size, f); if (result == NULL) { fclose (f); free (line); if (error) *error = BR_INIT_ERROR_READ_MAPS; return NULL; } /* Get rid of newline character. */ buf_size = strlen (line); if (buf_size <= 0) { /* Huh? An empty string? */ fclose (f); free (line); if (error) *error = BR_INIT_ERROR_INVALID_MAPS; return NULL; } if (line[buf_size - 1] == 10) line[buf_size - 1] = 0; /* Extract the filename; it is always an absolute path. */ path = strchr (line, '/'); /* Sanity check. */ if (strstr (line, " r-xp ") == NULL || path == NULL) { fclose (f); free (line); if (error) *error = BR_INIT_ERROR_INVALID_MAPS; return NULL; } path = strdup (path); free (line); fclose (f); return path; #endif /* ENABLE_BINRELOC */ } /** @internal * Find the canonical filename of the executable which owns symbol. * Returns a filename which must be freed, or NULL on error. */ static char * _br_find_exe_for_symbol (const void *symbol, BrInitError *error) { #ifndef ENABLE_BINRELOC if (error) *error = BR_INIT_ERROR_DISABLED; return (char *) NULL; #else #define SIZE PATH_MAX + 100 FILE *f; size_t address_string_len; char *address_string, line[SIZE], *found; if (symbol == NULL) return (char *) NULL; f = fopen ("/proc/self/maps", "r"); if (f == NULL) return (char *) NULL; address_string_len = 4; address_string = (char *) malloc (address_string_len); /* Handle OOM (Tracker issue #35) */ if (!address_string) { if (error) *error = BR_INIT_ERROR_NOMEM; return (char *) NULL; } found = (char *) NULL; while (!feof (f)) { char *start_addr, *end_addr, *end_addr_end, *file; void *start_addr_p, *end_addr_p; size_t len; if (fgets (line, SIZE, f) == NULL) break; /* Sanity check. */ if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL) continue; /* Parse line. */ start_addr = line; end_addr = strchr (line, '-'); file = strchr (line, '/'); /* More sanity check. */ if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-')) continue; end_addr[0] = '\0'; end_addr++; end_addr_end = strchr (end_addr, ' '); if (end_addr_end == NULL) continue; end_addr_end[0] = '\0'; len = strlen (file); if (len == 0) continue; if (file[len - 1] == '\n') file[len - 1] = '\0'; /* Get rid of "(deleted)" from the filename. */ len = strlen (file); if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0) file[len - 10] = '\0'; /* I don't know whether this can happen but better safe than sorry. */ len = strlen (start_addr); if (len != strlen (end_addr)) continue; /* Transform the addresses into a string in the form of 0xdeadbeef, * then transform that into a pointer. */ if (address_string_len < len + 3) { address_string_len = len + 3; address_string = (char *) realloc (address_string, address_string_len); /* Handle OOM (Tracker issue #35) */ if (!address_string) { if (error) *error = BR_INIT_ERROR_NOMEM; return (char *) NULL; } } memcpy (address_string, "0x", 2); memcpy (address_string + 2, start_addr, len); address_string[2 + len] = '\0'; sscanf (address_string, "%p", &start_addr_p); memcpy (address_string, "0x", 2); memcpy (address_string + 2, end_addr, len); address_string[2 + len] = '\0'; sscanf (address_string, "%p", &end_addr_p); if (symbol >= start_addr_p && symbol < end_addr_p) { found = file; break; } } free (address_string); fclose (f); if (found == NULL) return (char *) NULL; else return strdup (found); #endif /* ENABLE_BINRELOC */ } #ifndef BINRELOC_RUNNING_DOXYGEN #undef NULL #define NULL ((char *) 0) /* typecasted as char* for C++ type safeness */ #endif static char *exe = (char *) NULL; /** Initialize the BinReloc library (for applications). * * This function must be called before using any other BinReloc functions. * It attempts to locate the application's canonical filename. * * @note If you want to use BinReloc for a library, then you should call * br_init_lib() instead. * @note Initialization failure is not fatal. BinReloc functions will just * fallback to the supplied default path. * * @param error If BinReloc failed to initialize, then the error code will * be stored in this variable. Set to NULL if you want to * ignore this. See #BrInitError for a list of error codes. * * @returns 1 on success, 0 if BinReloc failed to initialize. */ int br_init (BrInitError *error) { exe = _br_find_exe (error); return exe != NULL; } /** Initialize the BinReloc library (for libraries). * * This function must be called before using any other BinReloc functions. * It attempts to locate the calling library's canonical filename. * * @note The BinReloc source code MUST be included in your library, or this * function won't work correctly. * @note Initialization failure is not fatal. BinReloc functions will just * fallback to the supplied default path. * * @param error If BinReloc failed to initialize, then the error code will * be stored in this variable. Set to NULL if you want to * ignore this. See #BrInitError for a list of error codes. * * @returns 1 on success, 0 if a filename cannot be found. */ int br_init_lib (BrInitError *error) { exe = _br_find_exe_for_symbol ((const void *) "", error); return exe != NULL; } /** Find the canonical filename of the current application. * * @param default_exe A default filename which will be used as fallback. * @returns A string containing the application's canonical filename, * which must be freed when no longer necessary. If BinReloc is * not initialized, or if br_init() failed, then a copy of * default_exe will be returned. If default_exe is NULL, then * NULL will be returned. */ char * br_find_exe (const char *default_exe) { if (exe == (char *) NULL) { /* BinReloc is not initialized. */ if (default_exe != (const char *) NULL) return strdup (default_exe); else return (char *) NULL; } return strdup (exe); } /** Locate the directory in which the current application is installed. * * The prefix is generated by the following pseudo-code evaluation: * \code * dirname(exename) * \endcode * * @param default_dir A default directory which will used as fallback. * @return A string containing the directory, which must be freed when no * longer necessary. If BinReloc is not initialized, or if the * initialization function failed, then a copy of default_dir * will be returned. If default_dir is NULL, then NULL will be * returned. */ char * br_find_exe_dir (const char *default_dir) { if (exe == NULL) { /* BinReloc not initialized. */ if (default_dir != NULL) return strdup (default_dir); else return NULL; } return br_dirname (exe); } /** Locate the prefix in which the current application is installed. * * The prefix is generated by the following pseudo-code evaluation: * \code * dirname(dirname(exename)) * \endcode * * @param default_prefix A default prefix which will used as fallback. * @return A string containing the prefix, which must be freed when no * longer necessary. If BinReloc is not initialized, or if * the initialization function failed, then a copy of default_prefix * will be returned. If default_prefix is NULL, then NULL will be returned. */ char * br_find_prefix (const char *default_prefix) { char *dir1, *dir2; if (exe == (char *) NULL) { /* BinReloc not initialized. */ if (default_prefix != (const char *) NULL) return strdup (default_prefix); else return (char *) NULL; } dir1 = br_dirname (exe); dir2 = br_dirname (dir1); free (dir1); return dir2; } /** Locate the application's binary folder. * * The path is generated by the following pseudo-code evaluation: * \code * prefix + "/bin" * \endcode * * @param default_bin_dir A default path which will used as fallback. * @return A string containing the bin folder's path, which must be freed when * no longer necessary. If BinReloc is not initialized, or if * the initialization function failed, then a copy of default_bin_dir will * be returned. If default_bin_dir is NULL, then NULL will be returned. */ char * br_find_bin_dir (const char *default_bin_dir) { char *prefix, *dir; prefix = br_find_prefix ((const char *) NULL); if (prefix == (char *) NULL) { /* BinReloc not initialized. */ if (default_bin_dir != (const char *) NULL) return strdup (default_bin_dir); else return (char *) NULL; } dir = br_build_path (prefix, "bin"); free (prefix); return dir; } /** Locate the application's superuser binary folder. * * The path is generated by the following pseudo-code evaluation: * \code * prefix + "/sbin" * \endcode * * @param default_sbin_dir A default path which will used as fallback. * @return A string containing the sbin folder's path, which must be freed when * no longer necessary. If BinReloc is not initialized, or if the * initialization function failed, then a copy of default_sbin_dir will * be returned. If default_bin_dir is NULL, then NULL will be returned. */ char * br_find_sbin_dir (const char *default_sbin_dir) { char *prefix, *dir; prefix = br_find_prefix ((const char *) NULL); if (prefix == (char *) NULL) { /* BinReloc not initialized. */ if (default_sbin_dir != (const char *) NULL) return strdup (default_sbin_dir); else return (char *) NULL; } dir = br_build_path (prefix, "sbin"); free (prefix); return dir; } /** Locate the application's data folder. * * The path is generated by the following pseudo-code evaluation: * \code * prefix + "/share" * \endcode * * @param default_data_dir A default path which will used as fallback. * @return A string containing the data folder's path, which must be freed when * no longer necessary. If BinReloc is not initialized, or if the * initialization function failed, then a copy of default_data_dir * will be returned. If default_data_dir is NULL, then NULL will be * returned. */ char * br_find_data_dir (const char *default_data_dir) { char *prefix, *dir; prefix = br_find_prefix ((const char *) NULL); if (prefix == (char *) NULL) { /* BinReloc not initialized. */ if (default_data_dir != (const char *) NULL) return strdup (default_data_dir); else return (char *) NULL; } dir = br_build_path (prefix, "share"); free (prefix); return dir; } /** Locate the application's localization folder. * * The path is generated by the following pseudo-code evaluation: * \code * prefix + "/share/locale" * \endcode * * @param default_locale_dir A default path which will used as fallback. * @return A string containing the localization folder's path, which must be freed when * no longer necessary. If BinReloc is not initialized, or if the * initialization function failed, then a copy of default_locale_dir will be returned. * If default_locale_dir is NULL, then NULL will be returned. */ char * br_find_locale_dir (const char *default_locale_dir) { char *data_dir, *dir; data_dir = br_find_data_dir ((const char *) NULL); if (data_dir == (char *) NULL) { /* BinReloc not initialized. */ if (default_locale_dir != (const char *) NULL) return strdup (default_locale_dir); else return (char *) NULL; } dir = br_build_path (data_dir, "locale"); free (data_dir); return dir; } /** Locate the application's library folder. * * The path is generated by the following pseudo-code evaluation: * \code * prefix + "/lib" * \endcode * * @param default_lib_dir A default path which will used as fallback. * @return A string containing the library folder's path, which must be freed when * no longer necessary. If BinReloc is not initialized, or if the initialization * function failed, then a copy of default_lib_dir will be returned. * If default_lib_dir is NULL, then NULL will be returned. */ char * br_find_lib_dir (const char *default_lib_dir) { char *prefix, *dir; prefix = br_find_prefix ((const char *) NULL); if (prefix == (char *) NULL) { /* BinReloc not initialized. */ if (default_lib_dir != (const char *) NULL) return strdup (default_lib_dir); else return (char *) NULL; } dir = br_build_path (prefix, "lib"); free (prefix); return dir; } /** Locate the application's libexec folder. * * The path is generated by the following pseudo-code evaluation: * \code * prefix + "/libexec" * \endcode * * @param default_libexec_dir A default path which will used as fallback. * @return A string containing the libexec folder's path, which must be freed when * no longer necessary. If BinReloc is not initialized, or if the initialization * function failed, then a copy of default_libexec_dir will be returned. * If default_libexec_dir is NULL, then NULL will be returned. */ char * br_find_libexec_dir (const char *default_libexec_dir) { char *prefix, *dir; prefix = br_find_prefix ((const char *) NULL); if (prefix == (char *) NULL) { /* BinReloc not initialized. */ if (default_libexec_dir != (const char *) NULL) return strdup (default_libexec_dir); else return (char *) NULL; } dir = br_build_path (prefix, "libexec"); free (prefix); return dir; } /** Locate the application's configuration files folder. * * The path is generated by the following pseudo-code evaluation: * \code * prefix + "/etc" * \endcode * * @param default_etc_dir A default path which will used as fallback. * @return A string containing the etc folder's path, which must be freed when * no longer necessary. If BinReloc is not initialized, or if the initialization * function failed, then a copy of default_etc_dir will be returned. * If default_etc_dir is NULL, then NULL will be returned. */ char * br_find_etc_dir (const char *default_etc_dir) { char *prefix, *dir; prefix = br_find_prefix ((const char *) NULL); if (prefix == (char *) NULL) { /* BinReloc not initialized. */ if (default_etc_dir != (const char *) NULL) return strdup (default_etc_dir); else return (char *) NULL; } dir = br_build_path (prefix, "etc"); free (prefix); return dir; } /*********************** * Utility functions ***********************/ /** Concatenate str1 and str2 to a newly allocated string. * * @param str1 A string. * @param str2 Another string. * @returns A newly-allocated string. This string should be freed when no longer needed. */ char * br_strcat (const char *str1, const char *str2) { char *result; size_t len1, len2; if (str1 == NULL) str1 = ""; if (str2 == NULL) str2 = ""; len1 = strlen (str1); len2 = strlen (str2); result = (char *) malloc (len1 + len2 + 1); /* Handle OOM (Tracker issue #35) */ if (result) { memcpy (result, str1, len1); memcpy (result + len1, str2, len2); result[len1 + len2] = '\0'; } return result; } char * br_build_path (const char *dir, const char *file) { char *dir2, *result; size_t len; int must_free = 0; len = strlen (dir); if (len > 0 && dir[len - 1] != '/') { dir2 = br_strcat (dir, "/"); must_free = 1; } else dir2 = (char *) dir; result = br_strcat (dir2, file); if (must_free) free (dir2); return result; } /* Emulates glibc's strndup() */ static char * br_strndup (const char *str, size_t size) { char *result = (char *) NULL; size_t len; if (str == (const char *) NULL) return (char *) NULL; len = strlen (str); if (len == 0) return strdup (""); if (size > len) size = len; result = (char *) malloc (len + 1); /* Handle OOM (Tracker issue #35) */ if (result) { memcpy (result, str, size); result[size] = '\0'; } return result; } /** Extracts the directory component of a path. * * Similar to g_dirname() or the dirname commandline application. * * Example: * \code * br_dirname ("/usr/local/foobar"); --> Returns: "/usr/local" * \endcode * * @param path A path. * @returns A directory name. This string should be freed when no longer needed. */ char * br_dirname (const char *path) { char *end, *result; if (path == (const char *) NULL) return (char *) NULL; end = strrchr (path, '/'); if (end == (const char *) NULL) return strdup ("."); while (end > path && *end == '/') end--; result = br_strndup (path, end - path + 1); if (result[0] == 0) { free (result); return strdup ("/"); } else return result; } #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __BINRELOC_C__ */ speedcrunch-0.10.1/src/3rdparty/util/binreloc.h0000644000175000001440000000565411015364561020554 0ustar helderusers/* * BinReloc - a library for creating relocatable executables * Written by: Hongli Lai * http://autopackage.org/ * * This source code is public domain. You can relicense this code * under whatever license you want. * * See http://autopackage.org/docs/binreloc/ for * more information and how to use this. */ #ifndef __BINRELOC_H__ #define __BINRELOC_H__ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** These error codes can be returned by br_init(), br_init_lib(), gbr_init() or gbr_init_lib(). */ typedef enum { /** Cannot allocate memory. */ BR_INIT_ERROR_NOMEM, /** Unable to open /proc/self/maps; see errno for details. */ BR_INIT_ERROR_OPEN_MAPS, /** Unable to read from /proc/self/maps; see errno for details. */ BR_INIT_ERROR_READ_MAPS, /** The file format of /proc/self/maps is invalid; kernel bug? */ BR_INIT_ERROR_INVALID_MAPS, /** BinReloc is disabled (the ENABLE_BINRELOC macro is not defined). */ BR_INIT_ERROR_DISABLED } BrInitError; #ifndef BINRELOC_RUNNING_DOXYGEN /* Mangle symbol names to avoid symbol * collisions with other ELF objects. */ #define br_init FRTf54694648844913_br_init #define br_init_lib FRTf54694648844913_br_init_lib #define br_find_exe FRTf54694648844913_br_find_exe #define br_find_exe_dir FRTf54694648844913_br_find_exe_dir #define br_find_prefix FRTf54694648844913_br_find_prefix #define br_find_bin_dir FRTf54694648844913_br_find_bin_dir #define br_find_sbin_dir FRTf54694648844913_br_find_sbin_dir #define br_find_data_dir FRTf54694648844913_br_find_data_dir #define br_find_locale_dir FRTf54694648844913_br_find_locale_dir #define br_find_lib_dir FRTf54694648844913_br_find_lib_dir #define br_find_libexec_dir FRTf54694648844913_br_find_libexec_dir #define br_find_etc_dir FRTf54694648844913_br_find_etc_dir #define br_strcat FRTf54694648844913_br_strcat #define br_build_path FRTf54694648844913_br_build_path #define br_dirname FRTf54694648844913_br_dirname #endif int br_init (BrInitError *error); int br_init_lib (BrInitError *error); char *br_find_exe (const char *default_exe); char *br_find_exe_dir (const char *default_dir); char *br_find_prefix (const char *default_prefix); char *br_find_bin_dir (const char *default_bin_dir); char *br_find_sbin_dir (const char *default_sbin_dir); char *br_find_data_dir (const char *default_data_dir); char *br_find_locale_dir (const char *default_locale_dir); char *br_find_lib_dir (const char *default_lib_dir); char *br_find_libexec_dir (const char *default_libexec_dir); char *br_find_etc_dir (const char *default_etc_dir); /* Utility functions */ char *br_strcat (const char *str1, const char *str2); char *br_build_path (const char *dir, const char *file); char *br_dirname (const char *path); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __BINRELOC_H__ */ speedcrunch-0.10.1/src/gui/0000755000175000001440000000000011015364704014632 5ustar helderusersspeedcrunch-0.10.1/src/gui/insertvardlg.cpp0000644000175000001440000001127411015364561020050 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2006 Johan Thelin // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "insertvardlg.hxx" #include "base/evaluator.hxx" #include #include #include #include #include #include #include #include #include struct InsertVariableDlg::Private { char radixChar; QPushButton * cancelButton; Evaluator * eval; QPushButton * insertButton; QTreeWidget * list; QString formatValue( const HNumber & value ); }; QString InsertVariableDlg::Private::formatValue( const HNumber & value ) { char * str = HMath::format( value, 'g' ); QString s; if ( radixChar == '.' ) s = QString::fromLatin1( str ); else s = QString::fromLatin1( str ).replace( '.', ',' ); free( str ); return s; } // public InsertVariableDlg::InsertVariableDlg( Evaluator * eval, char radixChar, QWidget * parent ) : QDialog( parent ), d( new InsertVariableDlg::Private ) { setWindowTitle( tr( "Insert Variable" ) ); setModal( true ); d->eval = eval; if ( radixChar == 'C' ) d->radixChar = QLocale().decimalPoint().toAscii(); else d->radixChar = radixChar; QVBoxLayout* layout = new QVBoxLayout; setLayout( layout ); d->list = new QTreeWidget( this ); d->list->setColumnCount( 2 ); d->list->setAlternatingRowColors( true ); d->list->setRootIsDecorated( false ); d->list->setEditTriggers( QTreeWidget::NoEditTriggers ); d->list->setSelectionBehavior( QTreeWidget::SelectRows ); QStringList titles; titles << tr( "Name" ); titles << tr( "Value" ); d->list->setHeaderLabels( titles ); d->insertButton = new QPushButton( this ); d->insertButton->setText( tr("&Insert") ); d->insertButton->setDefault( true ); d->cancelButton = new QPushButton( this ); d->cancelButton->setText( tr("Cancel") ); QWidget* box = new QWidget( this ); QHBoxLayout* boxLayout = new QHBoxLayout; boxLayout->setMargin( 0 ); box->setLayout( boxLayout ); boxLayout->addWidget( d->insertButton ); boxLayout->addItem( new QSpacerItem( 50, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Minimum ) ); boxLayout->addWidget( d->cancelButton ); layout->addWidget( d->list ); layout->addWidget( box ); connect( d->insertButton, SIGNAL( clicked() ), this, SLOT( accept() ) ); connect( d->cancelButton, SIGNAL( clicked() ), this, SLOT( reject() ) ); connect( d->list, SIGNAL( itemActivated( QTreeWidgetItem *, int ) ), this, SLOT(accept()) ); connect( d->list, SIGNAL( itemDoubleClicked( QTreeWidgetItem *, int ) ), this, SLOT(accept()) ); d->list->setLayoutDirection( Qt::LeftToRight ); updateList(); adjustSize(); } void InsertVariableDlg::updateList() { d->list->setUpdatesEnabled( false ); d->list->clear(); QVector variables = d->eval->variables(); for ( int k = 0; k < variables.count(); k++ ) { QStringList str; str << variables[k].name; str << d->formatValue( variables[k].value ); QTreeWidgetItem * item = 0; item = new QTreeWidgetItem( d->list, str ); item->setTextAlignment( 0, Qt::AlignLeft | Qt::AlignVCenter ); item->setTextAlignment( 1, Qt::AlignLeft | Qt::AlignVCenter ); } d->list->sortItems( 0, Qt::AscendingOrder ); d->list->setUpdatesEnabled( true ); } QString InsertVariableDlg::variableName() const { QTreeWidgetItem* item = d->list->currentItem(); return item ? item->text(0) : QString(); } InsertVariableDlg::~InsertVariableDlg() { delete d; } // public slots void InsertVariableDlg::setRadixChar( char c ) { if ( c == 'C' ) c = QLocale().decimalPoint().toAscii(); if ( d->radixChar != c ) { d->radixChar = c; updateList(); } } speedcrunch-0.10.1/src/gui/mainwindow.hxx0000644000175000001440000000736311015364561017551 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2005-2006 Johan Thelin // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef CRUNCH_HXX #define CRUNCH_HXX #include "keypad.hxx" #include #include #include class Keypad; class Settings; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); ~MainWindow(); signals: void angleModeChanged( char ); void formatChanged( char ); void radixCharChanged( char ); void precisionChanged( int ); void retranslateText(); public slots: void about(); void aboutQt(); void clearHistory(); void clearExpression(); void copyResult(); void degree(); void deleteAllVariables(); void deleteVariable(); void digits2(); void digits3(); void digits8(); void digits15(); void digits50(); void digitsAuto(); void exportSession(); void selectExpression(); void gotoWebsite(); void hideAutoCalc(); void insertFunction(); void insertVariable(); void loadSession(); void alwaysOnTopToggled( bool ); void autoCalcToggled( bool ); void autoCompletionToggled( bool ); void minimizeToTrayToggled( bool ); void hiliteSyntaxToggled( bool ); void radian(); void saveSession(); void setWidgetsDirection(); void showAutoCalc( const QString & ); void showBook( bool ); void showConstants( bool ); void showInFullScreen( bool ); void showFunctions( bool ); void showHistory( bool ); void showKeypad( bool ); void showMenuBarTip(); void showTipOfTheDay(); void showVariables( bool ); void scrollDown(); void scrollUp(); void showMenuBar(); void showStatusBar( bool ); void formatBinary(); void formatEngineering(); void formatFixed(); void formatGeneral(); void formatHexadec(); void formatOctal(); void formatScientific(); void radixCharAutoActivated(); void radixCharDotActivated(); void radixCharCommaActivated(); void changeLanguage(); void setAllText(); protected slots: void activate(); void constantSelected( const QString & ); void importSession(); void expressionSelected( const QString & ); void functionSelected( const QString & ); void keypadButtonPressed( Keypad::Button ); void minimizeToTray(); void returnPressed(); void showTrayMessage(); void textChanged(); void trayIconActivated( QSystemTrayIcon::ActivationReason ); void variableSelected( const QString & ); void setPrecision( int ); void setFormat( char ); void setRadixChar( char ); protected: virtual void closeEvent( QCloseEvent * ); virtual bool event( QEvent * ); virtual bool eventFilter( QObject *, QEvent * ); private: struct Private; Private * const d; MainWindow( const MainWindow & ); MainWindow & operator=( const MainWindow & ); }; #endif speedcrunch-0.10.1/src/gui/autohidelabel.cpp0000644000175000001440000000450611015364561020146 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "autohidelabel.hxx" #include #include #include #define TIMER_INTERVAL 25 #define FADE_STEP 16 struct AutoHideLabel::Private { QTimer * fadeTimer; int alpha; }; AutoHideLabel::AutoHideLabel( QWidget * parent ): QLabel( parent ), d( new AutoHideLabel::Private ) { d->fadeTimer = new QTimer( this ); d->fadeTimer->setInterval( TIMER_INTERVAL ); connect( d->fadeTimer, SIGNAL( timeout() ), SLOT( fade() ) ); d->alpha = 255; setPalette( QToolTip::palette() ); setAutoFillBackground( true ); setFrameShape( QFrame::Box ); } AutoHideLabel::~AutoHideLabel() { delete d; } void AutoHideLabel::showText( const QString & msg ) { setText( msg ); adjustSize(); show(); raise(); // 5 seconds display + fading d->alpha = 5*(1000/TIMER_INTERVAL*FADE_STEP) + 300; d->fadeTimer->stop(); d->fadeTimer->start(); fade(); } void AutoHideLabel::hideText() { if( d->alpha > 255 ) d->alpha = 255; } void AutoHideLabel::fade() { if( d->alpha <= 0) { d->fadeTimer->stop(); hide(); } else { d->alpha = qMax( 0, d->alpha-FADE_STEP ); int a = qMin( 255, d->alpha ); QPalette pal = QToolTip::palette(); QColor c1 = pal.window().color(); QColor c2 = pal.windowText().color(); c1.setAlpha(a); c2.setAlpha(a); pal.setBrush( QPalette::Window, c1 ); pal.setBrush( QPalette::WindowText, c2 ); setPalette(pal); } } speedcrunch-0.10.1/src/gui/keypad.hxx0000644000175000001440000000535511015364561016651 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2005-2006 Johan Thelin // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef KEYPAD_HXX #define KEYPAD_HXX #include class Keypad : public QWidget { Q_OBJECT public: enum Button { Key0, Key1, Key2, Key3, Key4, Key5, Key6, Key7, Key8, Key9, KeyEquals, KeyPlus, KeyMinus, KeyTimes, KeyDivide, KeyRadixChar, KeyClear, KeyEE, KeyLeftPar, KeyRightPar, KeyRaise, KeySqrt, KeyPercent, KeyFactorial, KeyPi, KeyAns, KeyX, KeyXEquals, KeyExp, KeyLn, KeySin, KeyAsin, KeyCos, KeyAcos, KeyTan, KeyAtan }; explicit Keypad( char radixChar = 'C', QWidget * parent = 0 ); ~Keypad(); char radixChar() const; signals: void buttonPressed( Keypad::Button ); public slots: void setRadixChar( char ); void retranslateText(); protected slots: void key0Pressed(); void key1Pressed(); void key2Pressed(); void key3Pressed(); void key4Pressed(); void key5Pressed(); void key6Pressed(); void key7Pressed(); void key8Pressed(); void key9Pressed(); void keyAcosPressed(); void keyAddPressed(); void keyAnsPressed(); void keyAsinPressed(); void keyAtanPressed(); void keyCPressed(); void keyCosPressed(); void keyDivPressed(); void keyDotPressed(); void keyEEPressed(); void keyEqPressed(); void keyExpPressed(); void keyFactPressed(); void keyLnPressed(); void keyLParPressed(); void keyMulPressed(); void keyPercPressed(); void keyPiPressed(); void keyRaisePressed(); void keyRParPressed(); void keySinPressed(); void keySqrtPressed(); void keySubPressed(); void keyTanPressed(); void keyXPressed(); void keyXEqPressed(); private: struct Private; Keypad::Private * const d; Keypad( const Keypad & ); Keypad & operator=( const Keypad & ); }; #endif speedcrunch-0.10.1/src/gui/tipwidget.cpp0000644000175000001440000000773111015364561017347 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include #include #include #include #include #include #include struct TipWidget::Private { QLabel * tipLabel; //QPushButton * nextButton; QTimer * hideTimer; QTimeLine * fadeTimeLine; }; TipWidget::TipWidget( QWidget * parent ) : QFrame( parent ), d( new TipWidget::Private ) { setObjectName( "TipWidget" ); d->tipLabel = new QLabel( this ); d->tipLabel->setWordWrap( true ); // d->tipLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ); // d->nextButton = new QPushButton( this ); // d->nextButton->setText( tr("Next") ); // d->nextButton->hide(); d->hideTimer = new QTimer( this ); d->hideTimer->setInterval( 4000 ); d->hideTimer->setSingleShot( true ); connect( d->hideTimer, SIGNAL( timeout() ), SLOT( disappear() ) ); d->fadeTimeLine = new QTimeLine( 750, this ); d->fadeTimeLine->setFrameRange( 0, 100 ); //d->fadeTimeLine->setUpdateInterval( 25 ); d->fadeTimeLine->setCurveShape( QTimeLine::EaseInCurve ); connect( d->fadeTimeLine, SIGNAL( frameChanged( int ) ), this, SLOT( animateFade( int ) ) ); // QPalette normal = palette(); setPalette( QToolTip::palette() ); // d->nextButton->setPalette( normal ); // d->tipLabel->setPalette( yellow ); // d->tipLabel->setAutoFillBackground( true ); setFrameShape( QFrame::Box ); setAutoFillBackground( true ); setFixedWidth( fontMetrics().width( 'X' ) * 50 ); setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ); } TipWidget::~TipWidget() { delete d; } void TipWidget::showText( const QString & msg, const QString & title ) { setPalette( QToolTip::palette() ); QString text = QString( "%1
%2" ).arg( title ).arg( msg ); d->tipLabel->setText( text ); int spacing = 4; int margin = 10; d->tipLabel->adjustSize(); d->tipLabel->move( margin, 0 ); d->tipLabel->resize( width() - spacing - margin, d->tipLabel->sizeHint().height() ); QTimer::singleShot( 0, this, SLOT( appear() ) ); } void TipWidget::hideText() { if( d->fadeTimeLine->state() == QTimeLine::NotRunning ) { d->hideTimer->stop(); QTimer::singleShot( 0, this, SLOT(disappear()) ); } } void TipWidget::appear() { resize( width(), sizeHint().height() ); show(); raise(); d->fadeTimeLine->stop(); d->fadeTimeLine->setFrameRange( 0, height() ); animateFade( 0 ); d->hideTimer->stop(); d->hideTimer->start(); } void TipWidget::disappear() { d->fadeTimeLine->setFrameRange( 0, height() ); d->fadeTimeLine->start(); } void TipWidget::animateFade( int v ) { resize( width(), d->fadeTimeLine->endFrame() - v ); d->tipLabel->move( 10, -v ); int a = qMax( 0, 240 - v*4 ); QPalette pal = QToolTip::palette(); QColor c1 = pal.window().color(); QColor c2 = pal.windowText().color(); c1.setAlpha(a); c2.setAlpha(a); pal.setBrush( QPalette::Window, c1 ); pal.setBrush( QPalette::WindowText, c2 ); setPalette( pal ); } QSize TipWidget::sizeHint() const { return d->tipLabel->sizeHint() + QSize( 100, 0 ); } speedcrunch-0.10.1/src/gui/autohidelabel.hxx0000644000175000001440000000257111015364561020173 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef AUTOHIDELABEL_HXX #define AUTOHIDELABEL_HXX #include class AutoHideLabel: public QLabel { Q_OBJECT public: explicit AutoHideLabel( QWidget * parent ); ~AutoHideLabel(); public slots: void showText( const QString & ); void hideText(); private slots: void fade(); private: struct Private; Private * const d; AutoHideLabel( const AutoHideLabel & ); AutoHideLabel& operator=( const AutoHideLabel & ); }; #endif speedcrunch-0.10.1/src/gui/variablesdock.hxx0000644000175000001440000000330111015364561020172 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef VARIABLESDOCK_HXX #define VARIABLESDOCK_HXX #include class Evaluator; class QTreeWidgetItem; class VariablesDock : public QDockWidget { Q_OBJECT public: VariablesDock( char radixChar = 'C', QWidget * parent = 0 ); ~VariablesDock(); char radixChar() const; void updateList( const Evaluator * ); signals: void variableSelected( const QString & ); public slots: void setRadixChar( char ); void retranslateText(); protected slots: void filter(); void handleItem( QTreeWidgetItem * ); void triggerFilter(); protected: virtual void changeEvent( QEvent * ); private: struct Private; Private * const d; VariablesDock( const VariablesDock & ); VariablesDock & operator=( const VariablesDock & ); }; #endif speedcrunch-0.10.1/src/gui/bookdock.cpp0000644000175000001440000001421011015364561017130 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Petri Damstén // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include #include #include #include #include #include #include #include #include #include struct BookDock::Private { BookDock * p; QTextBrowser * sheet; QString path; QString index; QString file; QString language; QPushButton * backButton; QPushButton * forwardButton; QPushButton * indexButton; QWidget * buttonLayoutWidget; QHBoxLayout * buttonLayout; void handleLayoutDirection(); }; void BookDock::Private::handleLayoutDirection() { if ( p->layoutDirection() == Qt::RightToLeft ) { backButton->setIcon( QPixmap( ":/book_forward.png" ) ); forwardButton->setIcon( QPixmap( ":/book_back.png" ) ); } else { backButton->setIcon( QPixmap( ":/book_back.png" ) ); forwardButton->setIcon( QPixmap( ":/book_forward.png" ) ); } } BookDock::BookDock( const QString & directory, const QString & file, const QString & language, QWidget * parent ) : QDockWidget( parent ), d( new BookDock::Private ) { d->p = this; d->path = directory; d->file = file; d->index = file; QWidget* widget = new QWidget( this ); QVBoxLayout* bookLayout = new QVBoxLayout; d->sheet = new QTextBrowser( this ); d->sheet->setLineWrapMode( QTextEdit::NoWrap ); //d->sheet->setOpenLinks( false ); // remove to stick with Qt 4.2 d->sheet->setSearchPaths( QStringList() << d->path ); connect( d->sheet, SIGNAL( anchorClicked( const QUrl & ) ), this, SLOT( anchorClicked( const QUrl & ) ) ); d->buttonLayoutWidget = new QWidget; d->buttonLayout = new QHBoxLayout( d->buttonLayoutWidget ); d->buttonLayout->setSpacing( 0 ); d->buttonLayout->setMargin( 0 ); d->backButton = new QPushButton( "", this ); d->backButton->setIcon( QPixmap( ":/book_back.png" ) ); d->backButton->setFlat( true ); connect( d->backButton, SIGNAL( clicked() ), d->sheet, SLOT( backward() ) ); connect( d->sheet, SIGNAL( backwardAvailable( bool ) ), d->backButton, SLOT( setEnabled( bool ) ) ); d->buttonLayout->addWidget( d->backButton ); d->forwardButton = new QPushButton( "", this ); d->forwardButton->setIcon( QPixmap( ":/book_forward.png" ) ); d->forwardButton->setFlat( true ); connect( d->forwardButton, SIGNAL( clicked() ), d->sheet, SLOT( forward() ) ); connect( d->sheet, SIGNAL( forwardAvailable( bool ) ), d->forwardButton, SLOT( setEnabled( bool ) ) ); d->buttonLayout->addWidget( d->forwardButton ); d->indexButton = new QPushButton( "", this ); d->indexButton->setIcon( QPixmap( ":/book_home.png" ) ); d->indexButton->setFlat( true ); connect( d->indexButton, SIGNAL( clicked() ), this, SLOT( home() ) ); d->buttonLayout->addWidget( d->indexButton ); d->buttonLayout->addStretch(); bookLayout->addWidget( d->buttonLayoutWidget ); bookLayout->addWidget( d->sheet ); widget->setLayout( bookLayout ); setWidget( widget ); setMinimumWidth( 150 ); setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea ); setWindowIcon( QIcon() ); // no icon setLanguage( language ); } BookDock::~BookDock() { delete d; } // public slots void BookDock::anchorClicked ( const QUrl & link ) { if ( link.toString().startsWith( "file:#" ) ) { // avoid appended history garbage after clicking on a formula (unknown) d->sheet->backward(); d->sheet->forward(); QString expr = link.toString().mid( 6 ); #if QT_VERSION < 0x040400 // Qt 4.3 and earlier do not properly decode the URL // and thus %5E does not become ^ // We do it manually here expr.replace( QLatin1String( "%5E" ), QLatin1String( "^" ), Qt::CaseInsensitive ); #endif emit expressionSelected( expr ); } else { d->sheet->setSource( link ); d->file = QFileInfo( link.path() ).fileName(); } // necessary for QTextBrowser to always draw correctly (why?) // causes a bug on Window or maybe just about the version number //d->sheet->adjustSize(); } void BookDock::home() { d->sheet->setSource( d->index ); d->file = d->index; setLanguage( d->language ); } void BookDock::setLanguage( const QString & languageCode ) { d->language = languageCode; // buttons d->backButton ->setText( tr( "Back" ) ); d->forwardButton->setText( tr( "Forward" ) ); d->indexButton ->setText( tr( "Index" ) ); // page QString locale = (languageCode == "C") ? QLocale().name() : languageCode; // fallback to English if ( locale == "C" ) locale = "en"; d->language = locale; QString path = d->path + d->language + "/"; QString src = path + d->file; if ( ! QDir( path ).isReadable() ) { QString localeShort = locale.left( 2 ).toLower(); src = d->path + localeShort + "/" + d->file; if ( ! QDir( d->path + localeShort ).isReadable() ) src = d->path + "en" + "/" + d->file; } d->sheet->setSource( QUrl::fromLocalFile( src ) ); d->handleLayoutDirection(); } void BookDock::setTitle( const QString & title ) { setWindowTitle( title ); } // protected void BookDock::changeEvent( QEvent * e ) { if ( e->type() == QEvent::LayoutDirectionChange ) d->handleLayoutDirection(); else QDockWidget::changeEvent( e ); } speedcrunch-0.10.1/src/gui/constantsdock.cpp0000644000175000001440000002101411015364561020212 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "constantsdock.hxx" #include "base/constants.hxx" #include #include #include #include #include #include #include #include #include #include #include struct ConstantsDock::Private { Constants * constants; char radixChar; QComboBox * category; QLineEdit * filter; QTimer * filterTimer; QTreeWidget * list; QLabel * label; QLabel * categoryLabel; QLabel * noMatchLabel; }; // public ConstantsDock::ConstantsDock( Constants * c, char radixChar, QWidget * parent ) : QDockWidget( parent ), d( new ConstantsDock::Private ) { if ( radixChar == 'C' ) d->radixChar = QLocale().decimalPoint().toAscii(); else d->radixChar = radixChar; d->constants = c; d->categoryLabel = new QLabel( this ); d->category = new QComboBox( this ); d->category->setEditable( false ); d->category->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ); connect( d->category, SIGNAL( activated( int ) ), SLOT( filter() ) ); QWidget * categoryBox = new QWidget( this ); QHBoxLayout * categoryLayout = new QHBoxLayout; categoryBox->setLayout( categoryLayout ); categoryLayout->addWidget( d->categoryLabel ); categoryLayout->addWidget( d->category ); categoryLayout->setMargin( 0 ); d->label = new QLabel( this ); d->filter = new QLineEdit( this ); d->filter->setMinimumWidth( fontMetrics().width('X') * 10 ); connect( d->filter, SIGNAL( textChanged( const QString & ) ), this, SLOT( triggerFilter() ) ); QWidget * searchBox = new QWidget( this ); QHBoxLayout * searchLayout = new QHBoxLayout; searchBox->setLayout( searchLayout ); searchLayout->addWidget( d->label ); searchLayout->addWidget( d->filter ); searchLayout->setMargin( 0 ); d->list = new QTreeWidget( this ); d->list->setAutoScroll( true ); d->list->setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded ); d->list->setHorizontalScrollMode( QAbstractItemView::ScrollPerPixel ); d->list->setColumnCount( 5 ); d->list->setColumnHidden( 3, true ); d->list->setRootIsDecorated( false ); d->list->header()->hide(); d->list->setMouseTracking( true ); d->list->setEditTriggers( QTreeWidget::NoEditTriggers ); d->list->setSelectionBehavior( QTreeWidget::SelectRows ); connect( d->list, SIGNAL( itemActivated( QTreeWidgetItem *, int ) ), this, SLOT( handleItem( QTreeWidgetItem * ) ) ); QWidget * widget = new QWidget( this ); QVBoxLayout * layout = new QVBoxLayout; widget->setLayout( layout ); setWidget( widget ); layout->setMargin( 3 ); layout->addWidget( categoryBox ); layout->addWidget( searchBox ); layout->addWidget( d->list ); d->filterTimer = new QTimer( this ); d->filterTimer->setInterval( 500 ); d->filterTimer->setSingleShot( true ); connect( d->filterTimer, SIGNAL( timeout() ), SLOT( filter() ) ); d->noMatchLabel = new QLabel( this ); d->noMatchLabel->setText( tr("No match found") ); d->noMatchLabel->setAlignment( Qt::AlignCenter ); d->noMatchLabel->adjustSize(); d->noMatchLabel->hide(); setMinimumWidth( 200 ); setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea ); setWindowIcon( QIcon() ); // no icon retranslateText(); } ConstantsDock::~ConstantsDock() { d->filterTimer->stop(); delete d; } char ConstantsDock::radixChar() const { return d->radixChar; } // public slots void ConstantsDock::setRadixChar( char c ) { if ( c == 'C' ) c = QLocale().decimalPoint().toAscii(); if ( d->radixChar != c ) { d->radixChar = c; updateList(); } } void ConstantsDock::retranslateText() { setWindowTitle( tr( "Constants" ) ); d->categoryLabel->setText( tr( "Category" ) ); d->label->setText( tr( "Search" ) ); updateList(); } // protected slots void ConstantsDock::filter() { Constants * c = d->constants; QString term = d->filter->text(); d->filterTimer->stop(); setUpdatesEnabled( false ); QString chosenCategory = d->category->currentText(); d->list->clear(); for ( int k = 0; k < c->constantList().count(); k++ ) { QStringList str; str << c->constantList().at( k ).name; QString radCh = (d->radixChar == ',' ? QString( c->constantList().at( k ).value ).replace( '.', ',' ) : c->constantList().at( k ).value); if ( layoutDirection() == Qt::RightToLeft ) { str << c->constantList().at( k ).unit + QChar( 0x200e ); // Unicode LRM str << radCh; } else { str << radCh; str << c->constantList().at( k ).unit; } str << c->constantList().at( k ).name.toUpper(); str << QString( "" ); bool include = (chosenCategory == tr( "All" )) ? true : c->constantList().at( k ).categories.contains( chosenCategory ); if ( ! include ) continue; QTreeWidgetItem * item = 0; if ( term.isEmpty() ) item = new QTreeWidgetItem( d->list, str ); else { if ( str[0].contains( term, Qt::CaseInsensitive ) ) item = new QTreeWidgetItem( d->list, str ); } if ( item ) { QString tip; tip += QString( QChar( 0x200E ) ); tip += QString( "%1
%2" ) .arg( c->constantList().at( k ).name, c->constantList().at( k ).value ); tip += QString( QChar( 0x200E ) ); if ( ! c->constantList().at( k ).unit.isEmpty() ) tip.append( " " ).append( c->constantList().at( k ).unit ); if ( d->radixChar == ',' ) tip.replace( '.', ',' ); tip += QString( QChar( 0x200E ) ); item->setToolTip( 0, tip ); item->setToolTip( 1, tip ); item->setToolTip( 2, tip ); if ( layoutDirection() == Qt::RightToLeft ) { item->setTextAlignment( 1, Qt::AlignRight ); item->setTextAlignment( 2, Qt::AlignLeft ); } else { item->setTextAlignment( 1, Qt::AlignLeft ); item->setTextAlignment( 2, Qt::AlignLeft ); } } } d->list->resizeColumnToContents( 0 ); d->list->resizeColumnToContents( 1 ); d->list->resizeColumnToContents( 2 ); if ( d->list->topLevelItemCount() > 0 ) { d->noMatchLabel->hide(); d->list->sortItems( 0, Qt::AscendingOrder ); int group = 3; if ( d->list->topLevelItemCount() >= 2 * group ) for ( int i = 0; i < d->list->topLevelItemCount(); i++ ) { QTreeWidgetItem * item = d->list->topLevelItem( i ); QBrush c = ((int)(i / group)) & 1 ? palette().base() : palette().alternateBase(); item->setBackground( 0, c ); item->setBackground( 1, c ); item->setBackground( 2, c ); item->setBackground( 4, c ); } } else { d->noMatchLabel->setGeometry( d->list->geometry() ); d->noMatchLabel->show(); d->noMatchLabel->raise(); } setUpdatesEnabled( true ); } void ConstantsDock::handleItem( QTreeWidgetItem * item ) { Constants * c = d->constants; for ( int k = 0; k < c->constantList().count(); k++ ) if ( c->constantList().at( k ).name == item->text( 0 ) ) emit constantSelected( c->constantList().at( k ).value ); } void ConstantsDock::triggerFilter() { d->filterTimer->stop(); d->filterTimer->start(); } void ConstantsDock::updateList() { Constants * c = d->constants; d->category->clear(); d->category->addItems( c->categoryList() ); d->category->insertItem( 0, tr( "All" ) ); d->category->setCurrentIndex( 0 ); filter(); } // protected void ConstantsDock::changeEvent( QEvent * e ) { if ( e->type() == QEvent::LayoutDirectionChange ) retranslateText(); else QDockWidget::changeEvent( e ); } speedcrunch-0.10.1/src/gui/tipwidget.hxx0000644000175000001440000000270311015364561017366 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef TIPWIDGET_HXX #define TIPWIDGET_HXX #include class TipWidget: public QFrame { Q_OBJECT public: explicit TipWidget( QWidget * parent ); ~TipWidget(); QSize sizeHint() const; public slots: void hideText(); void showText( const QString & msg, const QString & title ); private slots: void animateFade( int ); void appear(); void disappear(); private: struct Private; Private * const d; TipWidget( const TipWidget & ); TipWidget & operator=( const TipWidget & ); }; #endif speedcrunch-0.10.1/src/gui/functionsdock.hxx0000644000175000001440000000323411015364561020237 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef FUNCTIONSDOCK_HXX #define FUNCTIONSDOCK_HXX #include class Functions; class QTreeWidgetItem; class FunctionsDock : public QDockWidget { Q_OBJECT public: explicit FunctionsDock( const Functions *, QWidget * parent ); ~FunctionsDock(); const Functions * functions() const; signals: void functionSelected( const QString & ); public slots: void retranslateText(); protected slots: void filter(); void handleItem( QTreeWidgetItem * ); void triggerFilter(); protected: virtual void changeEvent( QEvent * ); private: struct Private; Private * const d; FunctionsDock(); FunctionsDock( const FunctionsDock & ); FunctionsDock & operator=( const FunctionsDock & ); }; #endif speedcrunch-0.10.1/src/gui/insertvardlg.hxx0000644000175000001440000000306111015364561020070 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef INSERTVARDLG_HXX #define INSERTVARDLG_HXX #include class Evaluator; class InsertVariableDlg : public QDialog { Q_OBJECT public: InsertVariableDlg( Evaluator * eval, char radixChar, QWidget * parent = 0 ); ~InsertVariableDlg(); void updateList(); char radixChar() const; QString variableName() const; public slots: void setRadixChar( char ); private: struct Private; Private * const d; InsertVariableDlg(); InsertVariableDlg( const InsertVariableDlg & ); InsertVariableDlg & operator=( const InsertVariableDlg & ); }; #endif speedcrunch-0.10.1/src/gui/functionsdock.cpp0000644000175000001440000001377011015364561020220 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "functionsdock.hxx" #include "base/functions.hxx" #include #include #include #include #include #include #include #include struct FunctionsDock::Private { const Functions * functions; QLineEdit * filter; QTimer * filterTimer; QStringList functionDesc; QStringList functionNames; QTreeWidget * list; QLabel * label; QLabel * noMatchLabel; }; // public FunctionsDock::FunctionsDock( const Functions * f, QWidget * parent ) : QDockWidget( parent ), d( new FunctionsDock::Private ) { d->functions = f; d->label = new QLabel( this ); d->filter = new QLineEdit( this ); connect( d->filter, SIGNAL( textChanged( const QString & ) ), SLOT( triggerFilter()) ); QWidget * searchBox = new QWidget( this ); QHBoxLayout * searchLayout = new QHBoxLayout; searchBox->setLayout( searchLayout ); searchLayout->addWidget( d->label ); searchLayout->addWidget( d->filter ); searchLayout->setMargin( 0 ); d->list = new QTreeWidget( this ); d->list->setAutoScroll( true ); d->list->setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded ); d->list->setHorizontalScrollMode( QAbstractItemView::ScrollPerPixel ); d->list->setColumnCount( 3 ); d->list->setRootIsDecorated( false ); d->list->header()->hide(); d->list->setEditTriggers( QTreeWidget::NoEditTriggers ); d->list->setSelectionBehavior( QTreeWidget::SelectRows ); connect( d->list, SIGNAL( itemActivated( QTreeWidgetItem *, int ) ), this, SLOT( handleItem( QTreeWidgetItem * ) ) ); QWidget * widget = new QWidget( this ); QVBoxLayout * layout = new QVBoxLayout; widget->setLayout( layout ); setWidget( widget ); layout->setMargin( 3 ); layout->addWidget( searchBox ); layout->addWidget( d->list ); d->filterTimer = new QTimer( this ); d->filterTimer->setInterval( 500 ); d->filterTimer->setSingleShot( true ); connect( d->filterTimer, SIGNAL( timeout() ), SLOT( filter() ) ); d->noMatchLabel = new QLabel( this ); d->noMatchLabel->setAlignment( Qt::AlignCenter ); d->noMatchLabel->adjustSize(); d->noMatchLabel->hide(); setMinimumWidth( 200 ); setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea ); setWindowIcon( QIcon() ); // no icon retranslateText(); } FunctionsDock::~FunctionsDock() { d->filterTimer->stop(); delete d; } const Functions * FunctionsDock::functions() const { return d->functions; } // public slots void FunctionsDock::retranslateText() { setWindowTitle( tr( "Functions" ) ); d->label->setText( tr( "Search" ) ); d->noMatchLabel->setText( tr( "No match found" ) ); d->functionNames.clear(); d->functionDesc.clear(); QStringList functionNames = d->functions->functionNames(); for ( int i = 0; i < functionNames.count(); i++ ) { Function * f = d->functions->function( functionNames[i] ); if ( f ) { d->functionNames << f->name(); d->functionDesc << f->description(); } } filter(); } // protected slots void FunctionsDock::filter() { QString term = d->filter->text(); setUpdatesEnabled( false ); d->list->clear(); for ( int k = 0; k < d->functionNames.count(); k++ ) { QStringList str; str << d->functionNames[k]; str << d->functionDesc[k]; str << QString( "" ); QTreeWidgetItem * item = 0; if ( term.isEmpty() ) { item = new QTreeWidgetItem( d->list, str ); } else { if ( str[0].contains( term, Qt::CaseInsensitive ) || str[1].contains( term, Qt::CaseInsensitive ) ) item = new QTreeWidgetItem( d->list, str ); } if ( item && layoutDirection() == Qt::RightToLeft ) { item->setTextAlignment( 0, Qt::AlignRight | Qt::AlignVCenter ); item->setTextAlignment( 1, Qt::AlignLeft | Qt::AlignVCenter ); } } d->list->resizeColumnToContents( 0 ); d->list->resizeColumnToContents( 1 ); d->list->resizeColumnToContents( 2 ); if ( d->list->topLevelItemCount() > 0 ) { d->noMatchLabel->hide(); d->list->sortItems( 0, Qt::AscendingOrder ); int group = 3; if ( d->list->topLevelItemCount() >= 2 * group ) for ( int i = 0; i < d->list->topLevelItemCount(); i++ ) { QTreeWidgetItem * item = d->list->topLevelItem( i ); QBrush c = ((int)(i / group)) & 1 ? palette().base() : palette().alternateBase(); item->setBackground( 0, c ); item->setBackground( 1, c ); item->setBackground( 2, c ); } } else { d->noMatchLabel->setGeometry( d->list->geometry() ); d->noMatchLabel->show(); d->noMatchLabel->raise(); } setUpdatesEnabled( true ); } void FunctionsDock::handleItem( QTreeWidgetItem * item ) { d->list->clearSelection(); emit functionSelected( item->text( 0 ) ); } void FunctionsDock::triggerFilter() { d->filterTimer->stop(); d->filterTimer->start(); } // protected void FunctionsDock::changeEvent( QEvent * e ) { if ( e->type() == QEvent::LayoutDirectionChange ) retranslateText(); else QDockWidget::changeEvent( e ); } speedcrunch-0.10.1/src/gui/variablesdock.cpp0000644000175000001440000001476311015364561020163 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "variablesdock.hxx" #include "base/evaluator.hxx" #include "base/functions.hxx" #include "base/settings.hxx" #include #include #include #include #include #include #include #include struct VariablesDock::Private { char radixChar; QLineEdit * filter; QTimer * filterTimer; QTreeWidget * list; QLabel * label; QLabel * noMatchLabel; QVector variables; QString formatValue( const HNumber & value ); }; QString VariablesDock::Private::formatValue( const HNumber & value ) { char * str = HMath::format( value, 'g' ); QString s; if ( radixChar == '.' ) s = QString::fromLatin1( str ); else s = QString::fromLatin1( str ).replace( '.', ',' ); free( str ); return s; } // public VariablesDock::VariablesDock( char radixChar, QWidget * parent ) : QDockWidget( parent ), d( new VariablesDock::Private ) { if ( radixChar == 'C' ) d->radixChar = QLocale().decimalPoint().toAscii(); else d->radixChar = radixChar; d->label = new QLabel( this ); d->filter = new QLineEdit( this ); connect( d->filter, SIGNAL( textChanged( const QString & ) ), this, SLOT( triggerFilter() ) ); QWidget * searchBox = new QWidget( this ); QHBoxLayout * searchLayout = new QHBoxLayout; searchBox->setLayout( searchLayout ); searchLayout->addWidget( d->label ); searchLayout->addWidget( d->filter ); searchLayout->setMargin( 0 ); d->list = new QTreeWidget( this ); d->list->setAutoScroll( true ); d->list->setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded ); d->list->setHorizontalScrollMode( QAbstractItemView::ScrollPerPixel ); d->list->setColumnCount( 3 ); d->list->setRootIsDecorated( false ); d->list->header()->hide(); d->list->setEditTriggers( QTreeWidget::NoEditTriggers ); d->list->setSelectionBehavior( QTreeWidget::SelectRows ); connect( d->list, SIGNAL( itemActivated( QTreeWidgetItem *, int ) ), this, SLOT( handleItem( QTreeWidgetItem * ) ) ); QWidget * widget = new QWidget( this ); QVBoxLayout * layout = new QVBoxLayout; widget->setLayout( layout ); setWidget( widget ); layout->setMargin( 3 ); layout->addWidget( searchBox ); layout->addWidget( d->list ); d->filterTimer = new QTimer( this ); d->filterTimer->setInterval( 500 ); d->filterTimer->setSingleShot( true ); connect( d->filterTimer, SIGNAL( timeout() ), SLOT( filter() ) ); d->noMatchLabel = new QLabel( this ); d->noMatchLabel->setAlignment( Qt::AlignCenter ); d->noMatchLabel->adjustSize(); d->noMatchLabel->hide(); setMinimumWidth( 200 ); setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea ); setWindowIcon( QIcon() ); retranslateText(); } char VariablesDock::radixChar() const { return d->radixChar; } void VariablesDock::updateList( const Evaluator * eval ) { d->variables = eval->variables(); filter(); } VariablesDock::~VariablesDock() { d->filterTimer->stop(); delete d; } // public slots void VariablesDock::setRadixChar( char c ) { if ( c == 'C' ) c = QLocale().decimalPoint().toAscii(); if ( d->radixChar != c ) { d->radixChar = c; filter(); } } void VariablesDock::retranslateText() { setWindowTitle( tr( "Variables" ) ); d->label->setText( tr( "Search" ) ); d->noMatchLabel->setText( tr( "No match found" ) ); d->list->setLayoutDirection( Qt::LeftToRight ); filter(); } // protected slots void VariablesDock::filter() { QString term = d->filter->text(); d->filterTimer->stop(); setUpdatesEnabled( false ); d->list->clear(); for ( int k = 0; k < d->variables.count(); k++ ) { QStringList str; str << d->variables[k].name; str << d->formatValue( d->variables[k].value ); str << QString( "" ); if ( str[0] == "PI" || str[0] == "PHI" ) continue; QTreeWidgetItem * item = 0; if ( term.isEmpty() ) item = new QTreeWidgetItem( d->list, str ); else { if ( str[0].contains( term, Qt::CaseInsensitive ) || str[1].contains( term, Qt::CaseInsensitive ) ) item = new QTreeWidgetItem( d->list, str ); } if ( item ) { item->setTextAlignment( 0, Qt::AlignLeft | Qt::AlignVCenter ); item->setTextAlignment( 1, Qt::AlignLeft | Qt::AlignVCenter ); } } d->list->resizeColumnToContents( 0 ); d->list->resizeColumnToContents( 1 ); d->list->resizeColumnToContents( 2 ); if ( d->list->topLevelItemCount() > 0 ) { d->noMatchLabel->hide(); d->list->sortItems( 0, Qt::AscendingOrder ); int group = 3; if ( d->list->topLevelItemCount() >= 2 * group ) for ( int i = 0; i < d->list->topLevelItemCount(); i++ ) { QTreeWidgetItem * item = d->list->topLevelItem(i); QBrush c = (((int)(i / group)) & 1) ? palette().base() : palette().alternateBase(); item->setBackground( 0, c ); item->setBackground( 1, c ); item->setBackground( 2, c ); } } else { d->noMatchLabel->setGeometry( d->list->geometry() ); d->noMatchLabel->show(); d->noMatchLabel->raise(); } setUpdatesEnabled( true ); } void VariablesDock::handleItem( QTreeWidgetItem * item ) { d->list->clearSelection(); emit variableSelected( item->text( 0 ) ); } void VariablesDock::triggerFilter() { d->filterTimer->stop(); d->filterTimer->start(); } // protected void VariablesDock::changeEvent( QEvent * e ) { if ( e->type() == QEvent::LayoutDirectionChange ) retranslateText(); else QDockWidget::changeEvent( e ); } speedcrunch-0.10.1/src/gui/bookdock.hxx0000644000175000001440000000320511015364561017157 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Petri Damstén // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef BOOKDOCK_HXX #define BOOKDOCK_HXX #include class QUrl; class BookDock : public QDockWidget { Q_OBJECT public: explicit BookDock( const QString & directory, const QString & file, const QString & language = "C", QWidget * parent = 0 ); ~BookDock(); public slots: void home(); void setLanguage( const QString & languageCode ); void setTitle( const QString & ); signals: void expressionSelected( const QString & ); protected slots: void anchorClicked ( const QUrl & ); virtual void changeEvent( QEvent * e ); private: struct Private; Private * const d; BookDock( const BookDock & ); BookDock & operator=( const BookDock & ); }; #endif speedcrunch-0.10.1/src/gui/constantsdock.hxx0000644000175000001440000000332711015364561020246 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef CONSTANTSDOCK_HXX #define CONSTANTSDOCK_HXX #include class Constants; class QTreeWidgetItem; class ConstantsDock : public QDockWidget { Q_OBJECT public: ConstantsDock( Constants *, char radixChar = 'C', QWidget * parent = 0 ); ~ConstantsDock(); char radixChar() const; signals: void constantSelected( const QString & c ); public slots: void setRadixChar( char ); void retranslateText(); protected slots: void filter(); void handleItem( QTreeWidgetItem * item ); void triggerFilter(); void updateList(); protected: virtual void changeEvent( QEvent * ); private: struct Private; Private * const d; ConstantsDock(); ConstantsDock( const ConstantsDock & ); ConstantsDock & operator=( const ConstantsDock & ); }; #endif speedcrunch-0.10.1/src/gui/resultdisplay.cpp0000644000175000001440000002440211015364561020245 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2005-2006 Johan Thelin // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "resultdisplay.hxx" #include "base/functions.hxx" #include "math/hmath.hxx" #include #include #include #include #include #include struct ResultDisplay::Private { QStringList contents; int count; bool customAppearance; QColor customBackgroundColor1; QColor customBackgroundColor2; QColor customErrorColor; QColor customTextColor; char format; int precision; char radixChar; }; class BaseItem : public QListWidgetItem { public: BaseItem( ResultDisplay * r ) : QListWidgetItem( r ) {} virtual void updateItem() {} }; class ExprItem : public BaseItem { public: ExprItem( ResultDisplay * r, int i, const QString & e ) : BaseItem( r ) { expr = e; result = r; index = i; setTextAlignment( Qt::AlignLeft ); setText( e ); //printf( "%s\n", qPrintable(e) ); updateItem(); } void updateItem() { if ( result->customAppearance() ) { setForeground( result->customTextColor() ); setBackground( (index & 1) ? result->customBackgroundColor1() : result->customBackgroundColor2() ); } else { const QPalette & pal = result->palette(); setForeground( pal.text() ); setBackground( (index & 1) ? pal.base() : pal.alternateBase() ); } } private: QString expr; int index; ResultDisplay * result; }; class ResultDisplayItem : public BaseItem { public: ResultDisplayItem( ResultDisplay * r, int i, const HNumber & v ) : BaseItem( r ) { value = v; result = r; index = i; setTextAlignment( Qt::AlignLeft ); QFont f = font(); f.setBold( true ); f.setPointSize( f.pointSize() + 2 ); setFont( f ); updateItem(); } void updateItem() { setText( QString( " " ) + result->formatNumber( value ) ); if ( result->customAppearance() ) { setForeground( result->customTextColor() ); setBackground( (index & 1) ? result->customBackgroundColor1() : result->customBackgroundColor2() ); } else { const QPalette & pal = result->palette(); setForeground( pal.text() ); setBackground( (index & 1) ? pal.base() : pal.alternateBase() ); } } private: int index; HNumber value; ResultDisplay * result; }; class ErrorItem: public BaseItem { public: ErrorItem( ResultDisplay * r, int i, const QString& m ) : BaseItem( r ) { msg = m; result = r; index = i; setTextAlignment( Qt::AlignRight ); setText( m ); //printf( "%s\n", qPrintable(msg) ); updateItem(); } void updateItem() { if ( result->customAppearance() ) { setForeground( result->customErrorColor() ); setBackground( (index & 1) ? result->customBackgroundColor1() : result->customBackgroundColor2() ); } else { const QPalette & pal = result->palette(); setForeground( Qt::red ); setBackground( (index & 1) ? pal.base() : pal.alternateBase() ); } } private: int index; QString msg; ResultDisplay * result; }; // public ResultDisplay::ResultDisplay( char radixChar, char format, int precision, QWidget * parent, const char * name ) : QListWidget( parent ), d( new ResultDisplay::Private ) { if ( radixChar == 'C' ) d->radixChar = QLocale().decimalPoint().toAscii(); else d->radixChar = radixChar; d->format = format; d->precision = precision; d->customAppearance = false; d->count = 0; d->customTextColor = QColor( 255, 255, 255 ); d->customBackgroundColor1 = QColor( 0, 0, 0 ); d->customBackgroundColor2 = QColor( 21, 21, 21 ); d->customErrorColor = QColor( 255, 0, 0 ); setObjectName( name ); setBackgroundRole( QPalette::Base ); setSelectionMode( NoSelection ); setMinimumWidth( 150 ); connect( this, SIGNAL( itemClicked( QListWidgetItem * ) ), this, SLOT( copyToClipboard( QListWidgetItem * ) ) ); connect( this, SIGNAL( itemDoubleClicked( QListWidgetItem * ) ), this, SLOT( selectItem( QListWidgetItem * ) ) ); setFocusPolicy( Qt::NoFocus ); setHorizontalScrollMode( QAbstractItemView::ScrollPerPixel ); setVerticalScrollMode ( QAbstractItemView::ScrollPerPixel ); setResizeMode( QListView::Adjust ); // ensure scrollbars background get system background color QString colorName = QApplication::palette().background().color().name(); verticalScrollBar()->setStyleSheet ( QString("QVerticalScrollBar { background: %1; }").arg( colorName ) ); horizontalScrollBar()->setStyleSheet( QString("QHorizontalScrollBar { background: %1; }").arg( colorName ) ); setCursor( QCursor( Qt::PointingHandCursor ) ); setLayoutDirection( Qt::LeftToRight ); } QString ResultDisplay::asText() const { return d->contents.join( "\n" ); } void ResultDisplay::append( const QString & expr, const HNumber & value ) { ++d->count; new ExprItem( this, d->count, expr ); new ResultDisplayItem( this, d->count, value ); d->contents.append( expr ); d->contents.append( HMath::format( value ) ); QTimer::singleShot( 0, this, SLOT( scrollEnd() ) ); } void ResultDisplay::appendError( const QString & expr, const QString & msg ) { ++d->count; new ExprItem( this, d->count, expr ); new ErrorItem( this, d->count, msg ); d->contents.append( expr ); d->contents.append( msg ); QTimer::singleShot( 0, this, SLOT( scrollEnd() ) ); } void ResultDisplay::appendHistory( const QStringList & history, const QStringList & results ) { for ( int i = 0 ; i < history.count(); i++ ) { QByteArray a = results[i].toLatin1(); const char * resultStr = a.constData(); HNumber result( resultStr ); if ( results[i] == "NaN" || ! result.isNan() ) append( history[i], result ); else appendError( history[i], resultStr ); } } int ResultDisplay::count() const { return d->count; } bool ResultDisplay::customAppearance() const { return d->customAppearance; } char ResultDisplay::format() const { return d->format; } char ResultDisplay::radixChar() const { return d->radixChar; } int ResultDisplay::precision() const { return d->precision; } QColor ResultDisplay::customBackgroundColor1() const { return d->customBackgroundColor1; } QColor ResultDisplay::customBackgroundColor2() const { return d->customBackgroundColor2; } QColor ResultDisplay::customErrorColor() const { return d->customErrorColor; } QColor ResultDisplay::customTextColor() const { return d->customTextColor; } QString ResultDisplay::formatNumber( const HNumber & value ) const { char * str = HMath::format( value, value.format() ? value.format() : d->format, d->precision ); QString s = QString::fromLatin1( str ); free( str ); if ( d->radixChar == ',' ) s.replace( '.', ',' ); return s; } void ResultDisplay::setCustomAppearance( bool custom ) { d->customAppearance = custom; QColor bgcolor = QApplication::palette().base().color(); if ( custom ) bgcolor = customBackgroundColor1(); QPalette pal = palette(); pal.setColor( QPalette::Background, bgcolor ); setPalette( pal ); refresh(); } void ResultDisplay::setCustomBackgroundColor( const QColor & bg1, const QColor & bg2 ) { d->customBackgroundColor1 = bg1; d->customBackgroundColor2 = bg2; if( d->customAppearance ) { QPalette pal = palette(); pal.setColor( QPalette::Base, bg1 ); setPalette( pal ); } refresh(); } void ResultDisplay::setCustomErrorColor( const QColor & e ) { d->customErrorColor = e; refresh(); }; void ResultDisplay::setCustomTextColor( const QColor & c ) { d->customTextColor = c; refresh(); } ResultDisplay::~ResultDisplay() { delete d; } // public slots void ResultDisplay::clear() { d->count = 0; d->contents.clear(); QListWidget::clear(); } void ResultDisplay::scrollEnd() { //QScrollBar * hBar = horizontalScrollBar(); //hBar->setValue( hBar->maximum() ); scrollToBottom(); } void ResultDisplay::setFormat( char c ) { if ( d->format != c ) { d->format = c; refresh(); } } void ResultDisplay::setPrecision( int p ) { if ( d->precision != p ) { d->precision = p; refresh(); } } void ResultDisplay::setRadixChar( char c ) { if ( c == 'C' ) c = QLocale().decimalPoint().toAscii(); if ( d->radixChar != c ) { d->radixChar = c; refresh(); } } // private slots void ResultDisplay::copyToClipboard( QListWidgetItem * item ) { if ( ! item ) return; QClipboard * cb = QApplication::clipboard(); QString text = item->text().trimmed(); cb->setText( text, QClipboard::Clipboard ); emit textCopied( text ); } void ResultDisplay::selectItem( QListWidgetItem * item ) { if ( ! item ) return; QString text = item->text().trimmed(); copyToClipboard( item ); emit textSelected( text ); } void ResultDisplay::refresh() { for ( int c = 0; c < d->count * 2; c++ ) dynamic_cast( item(c) )->updateItem(); } speedcrunch-0.10.1/src/gui/historydock.cpp0000644000175000001440000000531111015364561017701 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "historydock.hxx" #include struct HistoryDock::Private { QListWidget * list; }; HistoryDock::HistoryDock( QWidget * parent ) : QDockWidget( parent ), d( new HistoryDock::Private ) { d->list = new QListWidget( this ); connect( d->list, SIGNAL( itemActivated( QListWidgetItem * ) ), this, SLOT( handleItem( QListWidgetItem * ) ) ); setWidget( d->list ); setMinimumWidth( 200 ); setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea ); setWindowIcon( QIcon() ); retranslateText(); } HistoryDock::~HistoryDock() { delete d; } void HistoryDock::clear() { d->list->clear(); } void HistoryDock::append( const QString & h ) { d->list->addItem( h ); recolor(); d->list->clearSelection(); d->list->scrollToBottom(); } void HistoryDock::appendHistory( const QStringList & h ) { d->list->insertItems( 0, h ); d->list->setCurrentRow( h.count() - 1 ); recolor(); d->list->scrollToItem( d->list->item( h.count() ), QListWidget::PositionAtTop ); d->list->clearSelection(); } void HistoryDock::setHistory( const QStringList & h ) { d->list->clear(); appendHistory( h ); } void HistoryDock::retranslateText() { setWindowTitle( tr( "History" ) ); d->list->setLayoutDirection( Qt::LeftToRight ); } void HistoryDock::handleItem( QListWidgetItem * item ) { d->list->clearSelection(); emit expressionSelected( item->text() ); } void HistoryDock::recolor() { int group = 3; d->list->setUpdatesEnabled( false ); for ( int i = 0; i < d->list->count(); i++ ) { QListWidgetItem* item = d->list->item(i); QBrush c = (((int) (i / group)) & 1) ? palette().base() : palette().alternateBase(); item->setBackground( c ); } d->list->setUpdatesEnabled( true ); } speedcrunch-0.10.1/src/gui/keypad.cpp0000644000175000001440000004511211015364561016617 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2005-2006 Johan Thelin // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "keypad.hxx" #include #include #include #if QT_VERSION >= 0x040400 && defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) #include #endif #include #include #include struct Keypad::Private { // parent Keypad * p; // attributes char radixChar; // widgets QPushButton * key0; QPushButton * key1; QPushButton * key2; QPushButton * key3; QPushButton * key4; QPushButton * key5; QPushButton * key6; QPushButton * key7; QPushButton * key8; QPushButton * key9; QPushButton * keyAcos; QPushButton * keyAdd; QPushButton * keyAns; QPushButton * keyAsin; QPushButton * keyAtan; QPushButton * keyC; QPushButton * keyCos; QPushButton * keyDiv; QPushButton * keyDot; QPushButton * keyEE; QPushButton * keyEq; QPushButton * keyExp; QPushButton * keyFact; QPushButton * keyLn; QPushButton * keyLPar; QPushButton * keyMul; QPushButton * keyPerc; QPushButton * keyPi; QPushButton * keyRaise; QPushButton * keyRPar; QPushButton * keySin; QPushButton * keySqrt; QPushButton * keySub; QPushButton * keyTan; QPushButton * keyX; QPushButton * keyXEq; // methods void createButtons(); void disableButtonFocus(); void layoutButtons(); void setButtonTooltips(); void setUpButtonPressedSignal(); void sizeButtons(); }; // public Keypad::Keypad( char radixChar, QWidget * parent ) : QWidget( parent ), d( new Keypad::Private ) { d->p = this; if ( radixChar == 'C' ) d->radixChar = QLocale().decimalPoint().toAscii(); else d->radixChar = radixChar; d->createButtons(); d->sizeButtons(); d->layoutButtons(); d->setButtonTooltips(); d->setUpButtonPressedSignal(); d->disableButtonFocus(); setLayoutDirection( Qt::LeftToRight ); } Keypad::~Keypad() { delete d; } char Keypad::radixChar() const { return d->radixChar; } // public slots void Keypad::setRadixChar( char c ) { if ( c == 'C' ) c = QLocale().decimalPoint().toAscii(); if ( d->radixChar != c ) { d->radixChar = c; d->keyDot->setText( QString( c ) ); } } void Keypad::retranslateText() { d->setButtonTooltips();; } // protected slots void Keypad::key0Pressed() { emit buttonPressed( Keypad::Key0 ); }; void Keypad::key1Pressed() { emit buttonPressed( Keypad::Key1 ); }; void Keypad::key2Pressed() { emit buttonPressed( Keypad::Key2 ); }; void Keypad::key3Pressed() { emit buttonPressed( Keypad::Key3 ); }; void Keypad::key4Pressed() { emit buttonPressed( Keypad::Key4 ); }; void Keypad::key5Pressed() { emit buttonPressed( Keypad::Key5 ); }; void Keypad::key6Pressed() { emit buttonPressed( Keypad::Key6 ); }; void Keypad::key7Pressed() { emit buttonPressed( Keypad::Key7 ); }; void Keypad::key8Pressed() { emit buttonPressed( Keypad::Key8 ); }; void Keypad::key9Pressed() { emit buttonPressed( Keypad::Key9 ); }; void Keypad::keyAcosPressed() { emit buttonPressed( Keypad::KeyAcos ); }; void Keypad::keyAddPressed() { emit buttonPressed( Keypad::KeyPlus ); }; void Keypad::keyAnsPressed() { emit buttonPressed( Keypad::KeyAns ); }; void Keypad::keyAsinPressed() { emit buttonPressed( Keypad::KeyAsin ); }; void Keypad::keyAtanPressed() { emit buttonPressed( Keypad::KeyAtan ); }; void Keypad::keyCosPressed() { emit buttonPressed( Keypad::KeyCos ); }; void Keypad::keyCPressed() { emit buttonPressed( Keypad::KeyClear ); }; void Keypad::keyDivPressed() { emit buttonPressed( Keypad::KeyDivide ); }; void Keypad::keyDotPressed() { emit buttonPressed( Keypad::KeyRadixChar ); }; void Keypad::keyEEPressed() { emit buttonPressed( Keypad::KeyEE ); }; void Keypad::keyEqPressed() { emit buttonPressed( Keypad::KeyEquals ); }; void Keypad::keyExpPressed() { emit buttonPressed( Keypad::KeyExp ); }; void Keypad::keyFactPressed() { emit buttonPressed( Keypad::KeyFactorial ); }; void Keypad::keyLnPressed() { emit buttonPressed( Keypad::KeyLn ); }; void Keypad::keyLParPressed() { emit buttonPressed( Keypad::KeyLeftPar ); }; void Keypad::keyMulPressed() { emit buttonPressed( Keypad::KeyTimes ); }; void Keypad::keyPercPressed() { emit buttonPressed( Keypad::KeyPercent ); }; void Keypad::keyPiPressed() { emit buttonPressed( Keypad::KeyPi ); }; void Keypad::keyRaisePressed() { emit buttonPressed( Keypad::KeyRaise ); }; void Keypad::keyRParPressed() { emit buttonPressed( Keypad::KeyRightPar ); }; void Keypad::keySinPressed() { emit buttonPressed( Keypad::KeySin ); }; void Keypad::keySqrtPressed() { emit buttonPressed( Keypad::KeySqrt ); }; void Keypad::keySubPressed() { emit buttonPressed( Keypad::KeyMinus ); }; void Keypad::keyTanPressed() { emit buttonPressed( Keypad::KeyTan ); }; void Keypad::keyXPressed() { emit buttonPressed( Keypad::KeyX ); }; void Keypad::keyXEqPressed() { emit buttonPressed( Keypad::KeyXEquals ); }; // private void Keypad::Private::createButtons() { key0 = new QPushButton( "0", p ); key1 = new QPushButton( "1", p ); key2 = new QPushButton( "2", p ); key3 = new QPushButton( "3", p ); key4 = new QPushButton( "4", p ); key5 = new QPushButton( "5", p ); key6 = new QPushButton( "6", p ); key7 = new QPushButton( "7", p ); key8 = new QPushButton( "8", p ); key9 = new QPushButton( "9", p ); keyAcos = new QPushButton( "acos", p ); keyAdd = new QPushButton( "+", p ); keyAns = new QPushButton( "ans", p ); keyAsin = new QPushButton( "asin", p ); keyAtan = new QPushButton( "atan", p ); keyC = new QPushButton( "C", p ); keyCos = new QPushButton( "cos", p ); keyDiv = new QPushButton( "/", p ); keyEE = new QPushButton( "E", p ); keyEq = new QPushButton( "=", p ); keyExp = new QPushButton( "exp", p ); keyFact = new QPushButton( "!", p ); keyLn = new QPushButton( "ln", p ); keyLPar = new QPushButton( "(", p ); keyMul = new QPushButton( "*", p ); keyPerc = new QPushButton( "%", p ); keyRaise = new QPushButton( "^", p ); keyRPar = new QPushButton( ")", p ); keySin = new QPushButton( "sin", p ); keySub = new QPushButton( "-", p ); keyTan = new QPushButton( "tan", p ); keyXEq = new QPushButton( "x=", p ); keyX = new QPushButton( "x", p ); keyDot = new QPushButton( QString( radixChar ), p ); keyPi = new QPushButton( QString::fromUtf8( "π" ), p ); keySqrt = new QPushButton( QString::fromUtf8( "√" ), p ); QFont f = key0->font(); f.setBold( true ); f.setPointSize( f.pointSize() + 3 ); key0->setFont( f ); key1->setFont( f ); key2->setFont( f ); key3->setFont( f ); key4->setFont( f ); key5->setFont( f ); key6->setFont( f ); key7->setFont( f ); key8->setFont( f ); key9->setFont( f ); keyEq->setFont( f ); keyMul->setFont( f ); keyDiv->setFont( f ); keyAdd->setFont( f ); keySub->setFont( f ); keyDot->setFont( f ); } void Keypad::Private::disableButtonFocus() { key0->setFocusPolicy ( Qt::NoFocus ); key1->setFocusPolicy ( Qt::NoFocus ); key2->setFocusPolicy ( Qt::NoFocus ); key3->setFocusPolicy ( Qt::NoFocus ); key4->setFocusPolicy ( Qt::NoFocus ); key5->setFocusPolicy ( Qt::NoFocus ); key6->setFocusPolicy ( Qt::NoFocus ); key7->setFocusPolicy ( Qt::NoFocus ); key8->setFocusPolicy ( Qt::NoFocus ); key9->setFocusPolicy ( Qt::NoFocus ); keyAcos->setFocusPolicy ( Qt::NoFocus ); keyAdd->setFocusPolicy ( Qt::NoFocus ); keyAns->setFocusPolicy ( Qt::NoFocus ); keyAsin->setFocusPolicy ( Qt::NoFocus ); keyAtan->setFocusPolicy ( Qt::NoFocus ); keyCos->setFocusPolicy ( Qt::NoFocus ); keyC->setFocusPolicy ( Qt::NoFocus ); keyDiv->setFocusPolicy ( Qt::NoFocus ); keyDot->setFocusPolicy ( Qt::NoFocus ); keyEE->setFocusPolicy ( Qt::NoFocus ); keyEq->setFocusPolicy ( Qt::NoFocus ); keyExp->setFocusPolicy ( Qt::NoFocus ); keyFact->setFocusPolicy ( Qt::NoFocus ); keyLn->setFocusPolicy ( Qt::NoFocus ); keyLPar->setFocusPolicy ( Qt::NoFocus ); keyMul->setFocusPolicy ( Qt::NoFocus ); keyPerc->setFocusPolicy ( Qt::NoFocus ); keyPi->setFocusPolicy ( Qt::NoFocus ); keyRaise->setFocusPolicy( Qt::NoFocus ); keyRPar->setFocusPolicy ( Qt::NoFocus ); keySin->setFocusPolicy ( Qt::NoFocus ); keySqrt->setFocusPolicy ( Qt::NoFocus ); keySub->setFocusPolicy ( Qt::NoFocus ); keyTan->setFocusPolicy ( Qt::NoFocus ); keyXEq->setFocusPolicy ( Qt::NoFocus ); keyX->setFocusPolicy ( Qt::NoFocus ); } void Keypad::Private::layoutButtons() { int layoutSpacing = 3; #if QT_VERSION >= 0x040400 && defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) // Workaround for a layouting bug in QMacStyle, Qt 4.4.0. Buttons would overlap if ( qobject_cast(p->style()) ) layoutSpacing = -1; #endif QGridLayout * layout = new QGridLayout( p ); layout->setMargin( 3 ); layout->setSpacing( layoutSpacing ); layout->addWidget( key0, 3, 0 ); layout->addWidget( key1, 2, 0 ); layout->addWidget( key2, 2, 1 ); layout->addWidget( key3, 2, 2 ); layout->addWidget( key4, 1, 0 ); layout->addWidget( key5, 1, 1 ); layout->addWidget( key6, 1, 2 ); layout->addWidget( key7, 0, 0 ); layout->addWidget( key8, 0, 1 ); layout->addWidget( key9, 0, 2 ); layout->addWidget( keyAcos, 2, 8 ); layout->addWidget( keyAdd, 3, 3 ); layout->addWidget( keyAns, 1, 6 ); layout->addWidget( keyAsin, 1, 8 ); layout->addWidget( keyAtan, 3, 8 ); layout->addWidget( keyC, 0, 4 ); layout->addWidget( keyCos, 2, 7 ); layout->addWidget( keyDiv, 0, 3 ); layout->addWidget( keyDot, 3, 1 ); layout->addWidget( keyEE, 1, 4 ); layout->addWidget( keyEq, 3, 2 ); layout->addWidget( keyExp, 0, 7 ); layout->addWidget( keyFact, 3, 5 ); layout->addWidget( keyLn, 0, 8 ); layout->addWidget( keyLPar, 2, 4 ); layout->addWidget( keyMul, 1, 3 ); layout->addWidget( keyPerc, 3, 4 ); layout->addWidget( keyPi, 0, 6 ); layout->addWidget( keyRaise, 1, 5 ); layout->addWidget( keyRPar, 2, 5 ); layout->addWidget( keySin, 1, 7 ); layout->addWidget( keySqrt, 0, 5 ); layout->addWidget( keySub, 2, 3 ); layout->addWidget( keyTan, 3, 7 ); layout->addWidget( keyX, 2, 6 ); layout->addWidget( keyXEq, 3, 6 ); } void Keypad::Private::setButtonTooltips() { keyAcos->setToolTip( Keypad::tr( "Inverse cosine" ) ); keyAns->setToolTip ( Keypad::tr( "The last result" ) ); keyAsin->setToolTip( Keypad::tr( "Inverse sine" ) ); keyAtan->setToolTip( Keypad::tr( "Inverse tangent" ) ); keyC->setToolTip ( Keypad::tr( "Clear expression" ) ); keyCos->setToolTip ( Keypad::tr( "Cosine" ) ); keyEE->setToolTip ( Keypad::tr( "Scientific notation" ) ); keyExp->setToolTip ( Keypad::tr( "Exponential" ) ); keyLn->setToolTip ( Keypad::tr( "Natural logarithm" ) ); keySin->setToolTip ( Keypad::tr( "Sine" ) ); keySqrt->setToolTip( Keypad::tr( "Square root" ) ); keyTan->setToolTip ( Keypad::tr( "Tangent" ) ); keyXEq->setToolTip ( Keypad::tr( "Assign variable x" ) ); keyX->setToolTip ( Keypad::tr( "The variable x" ) ); } void Keypad::Private::setUpButtonPressedSignal() { connect( key0, SIGNAL( clicked() ), p, SLOT( key0Pressed() ) ); connect( key1, SIGNAL( clicked() ), p, SLOT( key1Pressed() ) ); connect( key2, SIGNAL( clicked() ), p, SLOT( key2Pressed() ) ); connect( key3, SIGNAL( clicked() ), p, SLOT( key3Pressed() ) ); connect( key4, SIGNAL( clicked() ), p, SLOT( key4Pressed() ) ); connect( key5, SIGNAL( clicked() ), p, SLOT( key5Pressed() ) ); connect( key6, SIGNAL( clicked() ), p, SLOT( key6Pressed() ) ); connect( key7, SIGNAL( clicked() ), p, SLOT( key7Pressed() ) ); connect( key8, SIGNAL( clicked() ), p, SLOT( key8Pressed() ) ); connect( key9, SIGNAL( clicked() ), p, SLOT( key9Pressed() ) ); connect( keyAcos, SIGNAL( clicked() ), p, SLOT( keyAcosPressed() ) ); connect( keyAdd, SIGNAL( clicked() ), p, SLOT( keyAddPressed() ) ); connect( keyAns, SIGNAL( clicked() ), p, SLOT( keyAnsPressed() ) ); connect( keyAsin, SIGNAL( clicked() ), p, SLOT( keyAsinPressed() ) ); connect( keyAtan, SIGNAL( clicked() ), p, SLOT( keyAtanPressed() ) ); connect( keyC, SIGNAL( clicked() ), p, SLOT( keyCPressed() ) ); connect( keyCos, SIGNAL( clicked() ), p, SLOT( keyCosPressed() ) ); connect( keyDiv, SIGNAL( clicked() ), p, SLOT( keyDivPressed() ) ); connect( keyEE, SIGNAL( clicked() ), p, SLOT( keyEEPressed() ) ); connect( keyEq, SIGNAL( clicked() ), p, SLOT( keyEqPressed() ) ); connect( keyExp, SIGNAL( clicked() ), p, SLOT( keyExpPressed() ) ); connect( keyFact, SIGNAL( clicked() ), p, SLOT( keyFactPressed() ) ); connect( keyLn, SIGNAL( clicked() ), p, SLOT( keyLnPressed() ) ); connect( keyLPar, SIGNAL( clicked() ), p, SLOT( keyLParPressed() ) ); connect( keyMul, SIGNAL( clicked() ), p, SLOT( keyMulPressed() ) ); connect( keyPerc, SIGNAL( clicked() ), p, SLOT( keyPercPressed() ) ); connect( keyRaise, SIGNAL( clicked() ), p, SLOT( keyRaisePressed()) ); connect( keyRPar, SIGNAL( clicked() ), p, SLOT( keyRParPressed() ) ); connect( keySin, SIGNAL( clicked() ), p, SLOT( keySinPressed() ) ); connect( keySub, SIGNAL( clicked() ), p, SLOT( keySubPressed() ) ); connect( keyTan, SIGNAL( clicked() ), p, SLOT( keyTanPressed() ) ); connect( keyXEq, SIGNAL( clicked() ), p, SLOT( keyXEqPressed() ) ); connect( keyX, SIGNAL( clicked() ), p, SLOT( keyXPressed() ) ); connect( keyDot, SIGNAL( clicked() ), p, SLOT( keyDotPressed() ) ); connect( keyPi, SIGNAL( clicked() ), p, SLOT( keyPiPressed() ) ); connect( keySqrt, SIGNAL( clicked() ), p, SLOT( keySqrtPressed() ) ); } void Keypad::Private::sizeButtons() { // The same font in all buttons, so just pick one QFontMetrics fm = key0->fontMetrics(); int maxWidth = fm.width( keyAcos->text() ); int textHeight = qMax( fm.lineSpacing(), 14 ); //int ls = fm.lineSpacing(); QStyle::ContentsType type = QStyle::CT_ToolButton; QStyleOptionButton opt; opt.initFrom(keyAcos); QSize size = keyAcos->style()->sizeFromContents( type, &opt, QSize( int(maxWidth), int(textHeight) ).expandedTo( QApplication::globalStrut() ), keyAcos ); #ifdef Q_WS_X11 // we would like to use the button size as indicated by the widget style, // but in some cases, e.g. KDE's Plastik or Oxygen, another few pixels // (typically 5) are added as the content margin, thereby making the button // incredibly wider than necessary // workaround: take only the hinted height, adjust the width ourselves (with our own margin) maxWidth += 6; int hh = size.height(); int ww = hh * 162 / 100; // use golden ratio size = QSize(qMax(ww, maxWidth), hh); #endif // limit the size of the buttons key0->setMaximumSize ( size ); key0->setMinimumSize ( size ); key1->setMaximumSize ( size ); key1->setMinimumSize ( size ); key2->setMaximumSize ( size ); key2->setMinimumSize ( size ); key3->setMaximumSize ( size ); key3->setMinimumSize ( size ); key4->setMaximumSize ( size ); key4->setMinimumSize ( size ); key5->setMaximumSize ( size ); key5->setMinimumSize ( size ); key6->setMaximumSize ( size ); key6->setMinimumSize ( size ); key7->setMaximumSize ( size ); key7->setMinimumSize ( size ); key8->setMaximumSize ( size ); key8->setMinimumSize ( size ); key9->setMaximumSize ( size ); key9->setMinimumSize ( size ); keyAcos->setMaximumSize ( size ); keyAcos->setMinimumSize ( size ); keyAdd->setMaximumSize ( size ); keyAdd->setMinimumSize ( size ); keyAns->setMaximumSize ( size ); keyAns->setMinimumSize ( size ); keyAsin->setMaximumSize ( size ); keyAsin->setMinimumSize ( size ); keyAtan->setMaximumSize ( size ); keyAtan->setMinimumSize ( size ); keyC->setMaximumSize ( size ); keyC->setMinimumSize ( size ); keyCos->setMaximumSize ( size ); keyCos->setMinimumSize ( size ); keyDiv->setMaximumSize ( size ); keyDiv->setMinimumSize ( size ); keyDot->setMaximumSize ( size ); keyDot->setMinimumSize ( size ); keyEE->setMaximumSize ( size ); keyEE->setMinimumSize ( size ); keyEq->setMaximumSize ( size ); keyEq->setMinimumSize ( size ); keyExp->setMaximumSize ( size ); keyExp->setMinimumSize ( size ); keyFact->setMaximumSize ( size ); keyFact->setMinimumSize ( size ); keyLn->setMaximumSize ( size ); keyLn->setMinimumSize ( size ); keyLPar->setMaximumSize ( size ); keyLPar->setMinimumSize ( size ); keyMul->setMaximumSize ( size ); keyMul->setMinimumSize ( size ); keyPerc->setMaximumSize ( size ); keyPerc->setMinimumSize ( size ); keyPi->setMaximumSize ( size ); keyPi->setMinimumSize ( size ); keyRaise->setMaximumSize ( size ); keyRaise->setMinimumSize ( size ); keyRPar->setMaximumSize ( size ); keyRPar->setMinimumSize ( size ); keySin->setMaximumSize ( size ); keySin->setMinimumSize ( size ); keySqrt->setMaximumSize ( size ); keySqrt->setMinimumSize ( size ); keySub->setMaximumSize ( size ); keySub->setMinimumSize ( size ); keyTan->setMaximumSize ( size ); keyTan->setMinimumSize ( size ); keyXEq->setMaximumSize ( size ); keyXEq->setMinimumSize ( size ); keyX->setMaximumSize ( size ); keyX->setMinimumSize ( size ); } speedcrunch-0.10.1/src/gui/insertfunctiondlg.hxx0000644000175000001440000000274111015364561021131 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef INSERTFUNCTIONDLG_HXX #define INSERTFUNCTIONDLG_HXX #include class Functions; class InsertFunctionDlg : public QDialog { Q_OBJECT public: InsertFunctionDlg( Functions *, QWidget * parent = 0 ); QString functionName() const; ~InsertFunctionDlg(); private slots: void initUI(); private: struct Private; Private * const d; InsertFunctionDlg(); InsertFunctionDlg( const InsertFunctionDlg & ); InsertFunctionDlg & operator=( const InsertFunctionDlg & ); }; #endif speedcrunch-0.10.1/src/gui/deletevardlg.hxx0000644000175000001440000000265211015364561020033 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2005 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef DELETEVARDLG_HXX #define DELETEVARDLG_HXX #include class Evaluator; class DeleteVariableDlg : public QDialog { Q_OBJECT public: explicit DeleteVariableDlg( Evaluator * eval, QWidget * parent = 0 ); ~DeleteVariableDlg(); void updateList(); private slots: void deleteVar(); private: struct Private; Private * const d; DeleteVariableDlg(); DeleteVariableDlg( const DeleteVariableDlg & ); DeleteVariableDlg & operator=( const DeleteVariableDlg & ); }; #endif speedcrunch-0.10.1/src/gui/editor.hxx0000644000175000001440000001220511015364561016652 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004-2005 Ariya Hidayat // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef EDITOR_HXX #define EDITOR_HXX #include "math/hmath.hxx" #include class Constants; class Evaluator; class Functions; class QEvent; class QKeyEvent; class QWheelEvent; class QWidget; class Editor : public QTextEdit { Q_OBJECT public: enum HighlightScheme { AutoScheme }; //enum ColorType { Number = 0, Function, Variable, MatchedPar }; enum ColorType { Variable = 0, Number, Function, MatchedPar }; explicit Editor( Evaluator *, Functions *, Constants *, char format = 'g', int precision = -1, char radixChar = 'C', QWidget * parent = 0 ); ~Editor(); bool autoCalcEnabled() const; bool autoCompleteEnabled() const; void clearHistory(); int cursorPosition() const; void doBackspace(); Evaluator * evaluator() const; Functions * functions() const; Constants * constants() const; QStringList history() const; QStringList historyResults() const; QColor highlightColor( ColorType type ); bool syntaxHighlight() const; char radixChar() const; void setAnsAvailable( bool avail ); void setAutoCalcEnabled( bool enable ); void setAutoCompleteEnabled( bool enable ); void setCursorPosition( int pos ); void setHighlightColor( ColorType type, QColor color ); void setSyntaxHighlight( bool enable ); void setHighlightScheme( Editor::HighlightScheme ); void setText( const QString & ); void setHistory( const QStringList & history ); void setHistoryResults( const QStringList & results ); QSize sizeHint() const; void stopAutoCalc(); void stopAutoComplete(); QString text() const; signals: void autoCalcEnabled( const QString & ); void autoCalcDisabled(); void returnPressed(); public slots: void appendHistory( const QString & result, const QString & expression ); void appendHistory( const QStringList & h, const QStringList & r ); void cancelConstantCompletion(); void evaluate(); void insertConstant( const QString & ); void insert( const QString & ); void setPrecision( int ); void setFormat( char ); void setRadixChar( char ); protected slots: void autoCalc(); void autoCalcSelection(); void autoComplete( const QString & item ); void checkAutoCalc(); void checkAutoComplete(); void startSelAutoCalcTimer(); void checkMatching(); void doMatchingLeft(); void doMatchingPar(); void doMatchingRight(); void historyBack(); void historyForward(); void triggerAutoComplete(); void triggerEnter(); protected: QString formatNumber( const HNumber & value ) const; void keyPressEvent( QKeyEvent * ); void wheelEvent( QWheelEvent * ); private: struct Private; Private * const d; Editor(); Editor( const Editor & ); Editor & operator=( const Editor & ); }; class EditorCompletion : public QObject { Q_OBJECT public: EditorCompletion( Editor * ); ~EditorCompletion(); bool eventFilter( QObject *, QEvent * ); void showCompletion( const QStringList & choices ); signals: void selectedCompletion( const QString & item ); public slots: void doneCompletion(); void selectItem( const QString & item ); // WORKAROUND 76 private slots: void fade( int ); private: struct Private; Private * d; EditorCompletion( const EditorCompletion & ); EditorCompletion & operator=( const EditorCompletion & ); }; class ConstantCompletion : public QObject { Q_OBJECT public: ConstantCompletion( Editor * ); ~ConstantCompletion(); bool eventFilter( QObject *, QEvent * ); void showCompletion(); signals: void selectedCompletion( const QString & item ); void canceledCompletion(); public slots: void doneCompletion(); private slots: void showCategory(); void showConstants(); void slide( int ); private: struct Private; Private * const d; ConstantCompletion( const ConstantCompletion & ); ConstantCompletion & operator=( const ConstantCompletion & ); }; #endif speedcrunch-0.10.1/src/gui/mainwindow.cpp0000644000175000001440000030431411015364561017520 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2005-2006 Johan Thelin // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "mainwindow.hxx" #include "aboutbox.hxx" #include "autohidelabel.hxx" #include "bookdock.hxx" #include "constantsdock.hxx" #include "deletevardlg.hxx" #include "editor.hxx" #include "functionsdock.hxx" #include "historydock.hxx" #include "insertfunctiondlg.hxx" #include "insertvardlg.hxx" #include "keypad.hxx" #include "resultdisplay.hxx" #include "tipwidget.hxx" #include "variablesdock.hxx" #include "3rdparty/util/binreloc.h" #include "base/constants.hxx" #include "base/evaluator.hxx" #include "base/functions.hxx" #include "base/settings.hxx" #include "math/hmath.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct Actions { QAction * clearExpression; QAction * clearHistory; QAction * degree; QAction * deleteAllVariables; QAction * deleteVariable; QAction * digits15; QAction * digits2; QAction * digits3; QAction * digits50; QAction * digits8; QAction * digitsAuto; QAction * editCopy; QAction * editCopyResult; QAction * editPaste; QAction * helpAbout; QAction * helpAboutQt; QAction * helpGotoWebsite; QAction * helpTipOfTheDay; QAction * insertFunction; QAction * insertVariable; QAction * optionAlwaysOnTop; QAction * optionAutoCalc; QAction * optionAutoCompletion; QAction * optionDotAuto; QAction * optionDotComma; QAction * optionDotPoint; QAction * optionMinimizeToTray; QAction * optionHiliteSyntax; QAction * radian; QAction * radixCharAuto; QAction * radixCharComma; QAction * radixCharDot; QAction * scrollDown; QAction * scrollUp; QAction * selectExpression; QAction * sessionImport; QAction * sessionLoad; QAction * sessionQuit; QAction * sessionSave; QAction * sessionExport; QAction * showBook; QAction * showConstants; QAction * showFullScreen; QAction * showFunctions; QAction * showHistory; QAction * showKeypad; QAction * showMenuBar; QAction * showStatusBar; QAction * showVariables; QAction * formatBinary; QAction * formatEngineering; QAction * formatFixed; QAction * formatGeneral; QAction * formatHexadec; QAction * formatOctal; QAction * formatScientific; QAction * languageDefault; QAction * languageCa; QAction * languageCs; QAction * languageDe; QAction * languageEn; QAction * languageEs; QAction * languageEsAr; QAction * languageEu; QAction * languageFi; QAction * languageFr; QAction * languageHe; QAction * languageId; QAction * languageIt; QAction * languageNb; QAction * languageNl; QAction * languagePl; QAction * languagePt; QAction * languagePtBr; QAction * languageRo; QAction * languageRu; QAction * languageSv; QAction * languageTr; QAction * languageZhCn; }; struct ActionGroups { QActionGroup * angle; QActionGroup * digits; QActionGroup * format; QActionGroup * language; QActionGroup * radixChar; }; struct Menus { QMenu * angle; QMenu * behavior; QMenu * decimal; QMenu * edit; QMenu * format; QMenu * help; QMenu * language; QMenu * radixChar; QMenu * session; QMenu * settings; QMenu * trayIcon; QMenu * view; }; struct Layouts { QVBoxLayout * root; QHBoxLayout * keypad; }; struct Widgets { QWidget * root; ResultDisplay * display; Editor * editor; Keypad * keypad; AutoHideLabel * autoCalcLabel; TipWidget * tip; QSystemTrayIcon * trayIcon; }; struct Docks { BookDock * book; ConstantsDock * constants; FunctionsDock * functions; HistoryDock * history; VariablesDock * variables; }; struct Conditions { bool notifyMenuBarHidden; bool trayNotify; bool autoAns; }; struct Status { QLabel * angleUnit; QLabel * format; }; struct MainWindow::Private { MainWindow * p; QTranslator * translator; Constants * constants; Evaluator * evaluator; Functions * functions; Settings settings; Actions actions; ActionGroups actionGroups; Menus menus; Layouts layouts; Widgets widgets; Docks docks; Conditions conditions; Status status; Private(); ~Private(); void createUi(); void createActions(); void createActionGroups(); void createActionShortcuts(); void createMenus(); void createStatusBar(); void createFixedWidgets(); void createKeypad(); void createBookDock(); void createConstantsDock(); void createFunctionsDock(); void createHistoryDock(); void createVariablesDock(); void createFixedConnections(); void applySettings(); void checkInitialFormat(); void checkInitialPrecision(); void checkInitialLanguage(); void restoreFloatingDocks(); void restoreHistory(); void restoreVariables(); void deleteKeypad(); void deleteStatusBar(); void deleteBookDock(); void deleteConstantsDock(); void deleteFunctionsDock(); void deleteHistoryDock(); void deleteVariablesDock(); void syncWindowStateToSettings(); void saveSettings(); void setActionsText(); void setMenusText(); void setStatusBarText(); static QTranslator * createTranslator( const QString & langCode ); }; MainWindow::Private::Private() { translator = 0; widgets.keypad = 0; widgets.trayIcon = 0; menus.trayIcon = 0; conditions.autoAns = false; conditions.trayNotify = true; conditions.notifyMenuBarHidden = true; docks.book = 0; docks.history = 0; docks.constants = 0; docks.functions = 0; docks.variables = 0; status.angleUnit = 0; status.format = 0; }; MainWindow::Private::~Private() { if ( widgets.trayIcon ) widgets.trayIcon->hide(); if ( docks.book ) deleteBookDock(); if ( docks.constants ) deleteConstantsDock(); if ( docks.variables ) deleteVariablesDock(); if ( docks.functions ) deleteFunctionsDock(); if ( docks.history ) deleteHistoryDock(); } QTranslator * MainWindow::Private::createTranslator( const QString & langCode ) { QTranslator * translator = new QTranslator; QString localeFile = (langCode == "C") ? QLocale().name() : langCode; // fallback to English if ( localeFile == "C" ) localeFile = "en"; #if defined(Q_OS_WIN32) || defined(Q_OS_MAC) QString appPath = QApplication::applicationFilePath(); int ii = appPath.lastIndexOf( '/' ); if ( ii > 0 ) appPath.remove( ii, appPath.length() ); QString fname = appPath + '/' + QString( "locale/" ) + localeFile; translator->load( fname ); return translator; #else BrInitError error; if ( br_init( & error ) == 0 && error != BR_INIT_ERROR_DISABLED ) { qDebug( "Warning: BinReloc failed to initialize (error code %d)", error ); qDebug( "Will fallback to hardcoded default path." ); } char * dataDir = br_find_data_dir( 0 ); QString localeDir = QString( dataDir ) + "/speedcrunch/locale"; free( dataDir ); if ( translator->load( localeFile, localeDir ) ) return translator; else return 0; #endif } void MainWindow::Private::createUi() { createActions(); createActionGroups(); createActionShortcuts(); createMenus(); createFixedWidgets(); createFixedConnections(); p->setWindowTitle( "SpeedCrunch" ); p->setWindowIcon( QPixmap( ":/speedcrunch.png" ) ); } void MainWindow::Private::createActions() { actions.clearExpression = new QAction( p ); actions.clearHistory = new QAction( p ); actions.degree = new QAction( p ); actions.deleteAllVariables = new QAction( p ); actions.deleteVariable = new QAction( p ); actions.digits15 = new QAction( p ); actions.digits2 = new QAction( p ); actions.digits3 = new QAction( p ); actions.digits50 = new QAction( p ); actions.digits8 = new QAction( p ); actions.digitsAuto = new QAction( p ); actions.editCopy = new QAction( p ); actions.editCopyResult = new QAction( p ); actions.editPaste = new QAction( p ); actions.helpAbout = new QAction( p ); actions.helpAboutQt = new QAction( p ); actions.helpGotoWebsite = new QAction( p ); actions.helpTipOfTheDay = new QAction( p ); actions.insertFunction = new QAction( p ); actions.insertVariable = new QAction( p ); actions.optionAutoCalc = new QAction( p ); actions.optionAutoCompletion = new QAction( p ); actions.optionAlwaysOnTop = new QAction( p ); actions.optionMinimizeToTray = new QAction( p ); actions.optionHiliteSyntax = new QAction( p ); actions.radixCharAuto = new QAction( p ); actions.radixCharDot = new QAction( p ); actions.radixCharComma = new QAction( p ); actions.radian = new QAction( p ); actions.scrollDown = new QAction( p ); actions.scrollUp = new QAction( p ); actions.selectExpression = new QAction( p ); actions.sessionImport = new QAction( p ); actions.sessionLoad = new QAction( p ); actions.sessionQuit = new QAction( p ); actions.sessionSave = new QAction( p ); actions.sessionExport = new QAction( p ); actions.showBook = new QAction( p ); actions.showConstants = new QAction( p ); actions.showFullScreen = new QAction( p ); actions.showFunctions = new QAction( p ); actions.showHistory = new QAction( p ); actions.showKeypad = new QAction( p ); actions.showMenuBar = new QAction( p ); actions.showStatusBar = new QAction( p ); actions.showVariables = new QAction( p ); actions.formatBinary = new QAction( p ); actions.formatEngineering = new QAction( p ); actions.formatFixed = new QAction( p ); actions.formatGeneral = new QAction( p ); actions.formatHexadec = new QAction( p ); actions.formatOctal = new QAction( p ); actions.formatScientific = new QAction( p ); actions.languageDefault = new QAction( p ); actions.languageCa = new QAction( QString::fromUtf8( "Català" ), p ); actions.languageCs = new QAction( QString::fromUtf8( "Česky" ), p ); actions.languageDe = new QAction( QString::fromUtf8( "Deutsch" ), p ); actions.languageEn = new QAction( QString::fromUtf8( "English" ), p ); actions.languageEs = new QAction( QString::fromUtf8( "Español" ), p ); actions.languageEsAr = new QAction( QString::fromUtf8( "Español Argentino" ), p ); actions.languageEu = new QAction( QString::fromUtf8( "Euskara" ), p ); actions.languageFi = new QAction( QString::fromUtf8( "Suomi" ), p ); actions.languageFr = new QAction( QString::fromUtf8( "Français" ), p ); actions.languageHe = new QAction( QString::fromUtf8( "עברית" ), p ); actions.languageId = new QAction( QString::fromUtf8( "Bahasa Indonesia" ), p ); actions.languageIt = new QAction( QString::fromUtf8( "Italiano" ), p ); actions.languageNb = new QAction( QString::fromUtf8( "Norsk (Bokmål)" ) + QChar( 0x200E ), p ); actions.languageNl = new QAction( QString::fromUtf8( "Nederlands" ), p ); actions.languagePl = new QAction( QString::fromUtf8( "Polski" ), p ); actions.languagePt = new QAction( QString::fromUtf8( "Português" ), p ); actions.languagePtBr = new QAction( QString::fromUtf8( "Português do Brasil" ), p ); actions.languageRo = new QAction( QString::fromUtf8( "Română" ), p ); actions.languageRu = new QAction( QString::fromUtf8( "Русский" ), p ); actions.languageSv = new QAction( QString::fromUtf8( "Svenska" ), p ); actions.languageTr = new QAction( QString::fromUtf8( "Türkçe" ), p ); actions.languageZhCn = new QAction( QString::fromUtf8( "简化字" ), p ); actions.languageDefault->setData( QString( "C" ) ); actions.languageCa ->setData( QString( "ca" ) ); actions.languageCs ->setData( QString( "cs" ) ); actions.languageDe ->setData( QString( "de" ) ); actions.languageEn ->setData( QString( "en" ) ); actions.languageEs ->setData( QString( "es" ) ); actions.languageEsAr ->setData( QString( "es_AR" ) ); actions.languageEu ->setData( QString( "eu" ) ); actions.languageFi ->setData( QString( "fi" ) ); actions.languageFr ->setData( QString( "fr" ) ); actions.languageHe ->setData( QString( "he" ) ); actions.languageId ->setData( QString( "id" ) ); actions.languageIt ->setData( QString( "it" ) ); actions.languageNb ->setData( QString( "nb" ) ); actions.languageNl ->setData( QString( "nl" ) ); actions.languagePl ->setData( QString( "pl" ) ); actions.languagePt ->setData( QString( "pt" ) ); actions.languagePtBr ->setData( QString( "pt_BR" ) ); actions.languageRo ->setData( QString( "ro" ) ); actions.languageRu ->setData( QString( "ru" ) ); actions.languageSv ->setData( QString( "sv" ) ); actions.languageTr ->setData( QString( "tr" ) ); actions.languageZhCn ->setData( QString( "zh_CN" ) ); actions.degree ->setCheckable( true ); actions.digits15 ->setCheckable( true ); actions.digits2 ->setCheckable( true ); actions.digits3 ->setCheckable( true ); actions.digits50 ->setCheckable( true ); actions.digits8 ->setCheckable( true ); actions.digitsAuto ->setCheckable( true ); actions.optionAlwaysOnTop ->setCheckable( true ); actions.optionAutoCalc ->setCheckable( true ); actions.optionAutoCompletion->setCheckable( true ); actions.optionMinimizeToTray->setCheckable( true ); actions.optionHiliteSyntax ->setCheckable( true ); actions.radian ->setCheckable( true ); actions.radixCharAuto ->setCheckable( true ); actions.radixCharComma ->setCheckable( true ); actions.radixCharDot ->setCheckable( true ); actions.showStatusBar ->setCheckable( true ); actions.showBook ->setCheckable( true ); actions.showConstants ->setCheckable( true ); actions.showFullScreen ->setCheckable( true ); actions.showFunctions ->setCheckable( true ); actions.showHistory ->setCheckable( true ); actions.showKeypad ->setCheckable( true ); actions.showVariables ->setCheckable( true ); actions.formatBinary ->setCheckable( true ); actions.formatEngineering ->setCheckable( true ); actions.formatFixed ->setCheckable( true ); actions.formatGeneral ->setCheckable( true ); actions.formatHexadec ->setCheckable( true ); actions.formatOctal ->setCheckable( true ); actions.formatScientific ->setCheckable( true ); actions.languageDefault ->setCheckable( true ); actions.languageCa ->setCheckable( true ); actions.languageCs ->setCheckable( true ); actions.languageDe ->setCheckable( true ); actions.languageEn ->setCheckable( true ); actions.languageEs ->setCheckable( true ); actions.languageEsAr ->setCheckable( true ); actions.languageEu ->setCheckable( true ); actions.languageFi ->setCheckable( true ); actions.languageFr ->setCheckable( true ); actions.languageHe ->setCheckable( true ); actions.languageId ->setCheckable( true ); actions.languageIt ->setCheckable( true ); actions.languageNb ->setCheckable( true ); actions.languageNl ->setCheckable( true ); actions.languagePl ->setCheckable( true ); actions.languagePt ->setCheckable( true ); actions.languagePtBr ->setCheckable( true ); actions.languageRo ->setCheckable( true ); actions.languageRu ->setCheckable( true ); actions.languageSv ->setCheckable( true ); actions.languageTr ->setCheckable( true ); actions.languageZhCn ->setCheckable( true ); } void MainWindow::setAllText() { QTranslator * tr = 0; tr = d->createTranslator( d->settings.language ); if ( tr ) { if ( d->translator ) { qApp->removeTranslator( d->translator ); delete d->translator; } qApp->installTranslator( tr ); d->translator = tr; } else { qApp->removeTranslator( d->translator ); d->translator = 0; } d->setMenusText(); d->setActionsText(); d->setStatusBarText(); d->functions->retranslateText(); // can't be signal/slot to ensure order d->constants->retranslateText(); // same as above if ( d->docks.book ) { d->docks.book->setLanguage( d->settings.language ); d->docks.book->setWindowTitle( MainWindow::tr( "Math Book" ) ); } // layout direction setWidgetsDirection(); } void MainWindow::Private::setStatusBarText() { if ( status.angleUnit ) { QString angleUnit = (settings.angleMode == 'r') ? MainWindow::tr( "Radian" ) : MainWindow::tr( "Degree" ); QString format; switch ( settings.format ) { case 'b' : format = MainWindow::tr( "Binary" ); break; case 'o' : format = MainWindow::tr( "Octal" ); break; case 'h' : format = MainWindow::tr( "Hexadecimal" ); break; case 'f' : format = MainWindow::tr( "Fixed decimal" ); break; case 'n' : format = MainWindow::tr( "Engineering decimal" ); break; case 'e' : format = MainWindow::tr( "Scientific decimal" ); break; case 'g' : format = MainWindow::tr( "General decimal" ); break; default : break; } status.angleUnit->setText( angleUnit ); status.format ->setText( format ); status.angleUnit->setToolTip( MainWindow::tr( "Angle unit" ) ); status.format ->setToolTip( MainWindow::tr( "Result format" ) ); } } void MainWindow::Private::setActionsText() { actions.clearExpression ->setText( MainWindow::tr( "Clear E&xpression" ) ); actions.clearHistory ->setText( MainWindow::tr( "Clear &History" ) ); actions.degree ->setText( MainWindow::tr( "&Degree" ) ); actions.deleteAllVariables ->setText( MainWindow::tr( "Delete All V&ariables" ) ); actions.deleteVariable ->setText( MainWindow::tr( "D&elete Variable..." ) ); actions.digits15 ->setText( MainWindow::tr( "&15 Decimal Digits" ) ); actions.digits2 ->setText( MainWindow::tr( "&2 Decimal Digits" ) ); actions.digits3 ->setText( MainWindow::tr( "&3 Decimal Digits" ) ); actions.digits50 ->setText( MainWindow::tr( "&50 Decimal Digits" ) ); actions.digits8 ->setText( MainWindow::tr( "&8 Decimal Digits" ) ); actions.digitsAuto ->setText( MainWindow::tr( "&Automatic Precision" ) ); actions.editCopy ->setText( MainWindow::tr( "&Copy" ) ); actions.editCopyResult ->setText( MainWindow::tr( "Copy Last &Result" ) ); actions.editPaste ->setText( MainWindow::tr( "&Paste" ) ); actions.helpAbout ->setText( MainWindow::tr( "&About" ) ); actions.helpAboutQt ->setText( MainWindow::tr( "About &Qt" ) ); actions.helpGotoWebsite ->setText( MainWindow::tr( "SpeedCrunch &Web Site..." ) ); actions.helpTipOfTheDay ->setText( MainWindow::tr( "&Tip of the Day" ) ); actions.insertFunction ->setText( MainWindow::tr( "Insert &Function..." ) ); actions.insertVariable ->setText( MainWindow::tr( "Insert &Variable..." ) ); actions.optionAutoCalc ->setText( MainWindow::tr( "&Partial Results" ) ); actions.optionAutoCompletion->setText( MainWindow::tr( "Automatic &Completion" ) ); actions.optionAlwaysOnTop ->setText( MainWindow::tr( "Always On &Top" ) ); actions.optionMinimizeToTray->setText( MainWindow::tr( "&Minimize To System Tray" ) ); actions.optionHiliteSyntax ->setText( MainWindow::tr( "Syntax &Highlighting" ) ); actions.radixCharAuto ->setText( MainWindow::tr( "&System Default" ) ); actions.radixCharDot ->setText( MainWindow::tr( "&Dot" ) ); actions.radixCharComma ->setText( MainWindow::tr( "&Comma" ) ); actions.radian ->setText( MainWindow::tr( "&Radian" ) ); actions.scrollDown ->setText( MainWindow::tr( "Scroll Display Down" ) ); actions.scrollUp ->setText( MainWindow::tr( "Scroll Display Up" ) ); actions.selectExpression ->setText( MainWindow::tr( "&Select Expression" ) ); actions.sessionImport ->setText( MainWindow::tr( "&Import..." ) ); actions.sessionLoad ->setText( MainWindow::tr( "&Load..." ) ); actions.sessionQuit ->setText( MainWindow::tr( "&Quit" ) ); actions.sessionSave ->setText( MainWindow::tr( "&Save..." ) ); actions.sessionExport ->setText( MainWindow::tr( "&Export..." ) ); actions.showBook ->setText( MainWindow::tr( "Math &Book" ) ); actions.showConstants ->setText( MainWindow::tr( "&Constants" ) ); actions.showFullScreen ->setText( MainWindow::tr( "Full &Screen Mode" ) ); actions.showFunctions ->setText( MainWindow::tr( "&Functions" ) ); actions.showHistory ->setText( MainWindow::tr( "&History" ) ); actions.showKeypad ->setText( MainWindow::tr( "&Keypad" ) ); actions.showMenuBar ->setText( MainWindow::tr( "Hide &Menu Bar" ) ); actions.showStatusBar ->setText( MainWindow::tr( "&Status Bar" ) ); actions.showVariables ->setText( MainWindow::tr( "&Variables" ) ); actions.formatBinary ->setText( MainWindow::tr( "&Binary" ) ); actions.formatEngineering ->setText( MainWindow::tr( "&Engineering" ) ); actions.formatFixed ->setText( MainWindow::tr( "&Fixed Decimal" ) ); actions.formatGeneral ->setText( MainWindow::tr( "&General" ) ); actions.formatHexadec ->setText( MainWindow::tr( "&Hexadecimal" ) ); actions.formatOctal ->setText( MainWindow::tr( "&Octal" ) ); actions.formatScientific ->setText( MainWindow::tr( "&Scientific" ) ); actions.languageDefault ->setText( MainWindow::tr( "System &Default" ) ); } void MainWindow::Private::createActionGroups() { actionGroups.format = new QActionGroup( p ); actionGroups.format->addAction( actions.formatBinary ); actionGroups.format->addAction( actions.formatGeneral ); actionGroups.format->addAction( actions.formatFixed ); actionGroups.format->addAction( actions.formatEngineering ); actionGroups.format->addAction( actions.formatScientific ); actionGroups.format->addAction( actions.formatOctal ); actionGroups.format->addAction( actions.formatHexadec ); actionGroups.digits = new QActionGroup( p ); actionGroups.digits->addAction( actions.digitsAuto ); actionGroups.digits->addAction( actions.digits2 ); actionGroups.digits->addAction( actions.digits3 ); actionGroups.digits->addAction( actions.digits8 ); actionGroups.digits->addAction( actions.digits15 ); actionGroups.digits->addAction( actions.digits50 ); actionGroups.angle = new QActionGroup( p ); actionGroups.angle->addAction( actions.radian ); actionGroups.angle->addAction( actions.degree ); actionGroups.radixChar = new QActionGroup( p ); actionGroups.radixChar->addAction( actions.radixCharAuto ); actionGroups.radixChar->addAction( actions.radixCharDot ); actionGroups.radixChar->addAction( actions.radixCharComma ); actionGroups.language = new QActionGroup( p ); actionGroups.language->addAction( actions.languageDefault ); actionGroups.language->addAction( actions.languageCa ); actionGroups.language->addAction( actions.languageCs ); actionGroups.language->addAction( actions.languageDe ); actionGroups.language->addAction( actions.languageEn ); actionGroups.language->addAction( actions.languageEs ); actionGroups.language->addAction( actions.languageEsAr ); actionGroups.language->addAction( actions.languageEu ); actionGroups.language->addAction( actions.languageFi ); actionGroups.language->addAction( actions.languageFr ); actionGroups.language->addAction( actions.languageHe ); actionGroups.language->addAction( actions.languageId ); actionGroups.language->addAction( actions.languageIt ); actionGroups.language->addAction( actions.languageNb ); actionGroups.language->addAction( actions.languageNl ); actionGroups.language->addAction( actions.languagePl ); actionGroups.language->addAction( actions.languagePt ); actionGroups.language->addAction( actions.languagePtBr ); actionGroups.language->addAction( actions.languageRo ); actionGroups.language->addAction( actions.languageRu ); actionGroups.language->addAction( actions.languageSv ); actionGroups.language->addAction( actions.languageTr ); actionGroups.language->addAction( actions.languageZhCn ); } void MainWindow::Private::createActionShortcuts() { actions.clearExpression ->setShortcut( Qt::Key_Escape ); actions.clearHistory ->setShortcut( Qt::CTRL + Qt::ALT + Qt::Key_N ); actions.degree ->setShortcut( Qt::Key_F10 ); actions.deleteVariable ->setShortcut( Qt::CTRL + Qt::Key_D ); actions.editCopyResult ->setShortcut( Qt::CTRL + Qt::Key_R ); actions.editCopy ->setShortcut( Qt::CTRL + Qt::Key_C ); actions.editPaste ->setShortcut( Qt::CTRL + Qt::Key_V ); actions.helpTipOfTheDay ->setShortcut( Qt::CTRL + Qt::Key_T ); actions.insertFunction ->setShortcut( Qt::CTRL + Qt::Key_F ); actions.insertVariable ->setShortcut( Qt::CTRL + Qt::Key_I ); actions.radian ->setShortcut( Qt::Key_F9 ); actions.scrollDown ->setShortcut( Qt::SHIFT + Qt::Key_PageDown ); actions.scrollUp ->setShortcut( Qt::SHIFT + Qt::Key_PageUp ); actions.selectExpression->setShortcut( Qt::CTRL + Qt::Key_A ); actions.sessionLoad ->setShortcut( Qt::CTRL + Qt::Key_L ); actions.sessionQuit ->setShortcut( Qt::CTRL + Qt::Key_Q ); actions.sessionSave ->setShortcut( Qt::CTRL + Qt::Key_S ); actions.showFullScreen ->setShortcut( Qt::Key_F11 ); actions.showKeypad ->setShortcut( Qt::CTRL + Qt::ALT + Qt::Key_K ); actions.showBook ->setShortcut( Qt::CTRL + Qt::Key_1 ); actions.showConstants ->setShortcut( Qt::CTRL + Qt::Key_2 ); actions.showFunctions ->setShortcut( Qt::CTRL + Qt::Key_3 ); actions.showVariables ->setShortcut( Qt::CTRL + Qt::Key_4 ); actions.showHistory ->setShortcut( Qt::CTRL + Qt::Key_5 ); #ifndef Q_OS_MAC actions.showMenuBar ->setShortcut( Qt::CTRL + Qt::ALT + Qt::Key_M ); #endif actions.showStatusBar ->setShortcut( Qt::CTRL + Qt::ALT + Qt::Key_B ); actions.formatBinary ->setShortcut( Qt::Key_F5 ); actions.formatGeneral ->setShortcut( Qt::Key_F7 ); actions.formatHexadec ->setShortcut( Qt::Key_F8 ); actions.formatOctal ->setShortcut( Qt::Key_F6 ); } void MainWindow::Private::createMenus() { // session menus.session = new QMenu( "", p ); p->menuBar()->addMenu( menus.session ); menus.session->addAction( actions.sessionLoad ); menus.session->addAction( actions.sessionSave ); menus.session->addSeparator(); menus.session->addAction( actions.sessionImport ); menus.session->addAction( actions.sessionExport ); menus.session->addSeparator(); menus.session->addAction( actions.sessionQuit ); // edit menus.edit = new QMenu( "", p ); p->menuBar()->addMenu( menus.edit ); menus.edit->addAction( actions.editCopy ); menus.edit->addAction( actions.editCopyResult ); menus.edit->addAction( actions.editPaste ); menus.edit->addAction( actions.selectExpression ); menus.edit->addSeparator(); menus.edit->addAction( actions.insertFunction ); menus.edit->addAction( actions.insertVariable ); menus.edit->addSeparator(); menus.edit->addAction( actions.deleteVariable ); menus.edit->addAction( actions.deleteAllVariables ); menus.edit->addSeparator(); menus.edit->addAction( actions.clearExpression ); menus.edit->addAction( actions.clearHistory ); // view menus.view = new QMenu( "", p ); p->menuBar()->addMenu( menus.view ); menus.view->addAction( actions.showKeypad ); menus.view->addSeparator(); menus.view->addAction( actions.showBook ); menus.view->addAction( actions.showConstants ); menus.view->addAction( actions.showFunctions ); menus.view->addAction( actions.showVariables ); menus.view->addAction( actions.showHistory ); menus.view->addSeparator(); #ifndef Q_OS_MAC menus.view->addAction( actions.showMenuBar ); #endif menus.view->addAction( actions.showStatusBar ); menus.view->addSeparator(); menus.view->addAction( actions.showFullScreen ); // settings menus.settings = new QMenu( "", p ); p->menuBar()->addMenu( menus.settings ); // settings / result format menus.format = menus.settings->addMenu( "" ); menus.format->addAction( actions.formatBinary ); menus.format->addAction( actions.formatOctal ); // settings / result format / decimal menus.decimal = menus.format->addMenu( "" ); menus.decimal->addAction( actions.formatGeneral ); menus.decimal->addAction( actions.formatFixed ); menus.decimal->addAction( actions.formatEngineering ); menus.decimal->addAction( actions.formatScientific ); menus.decimal->addSeparator(); menus.decimal->addAction( actions.digitsAuto ); menus.decimal->addAction( actions.digits2 ); menus.decimal->addAction( actions.digits3 ); menus.decimal->addAction( actions.digits8 ); menus.decimal->addAction( actions.digits15 ); menus.decimal->addAction( actions.digits50 ); // settings / result format (continued) menus.format->addAction( actions.formatHexadec ); // settings / angle mode menus.angle = menus.settings->addMenu( "" ); menus.angle->addAction( actions.radian ); menus.angle->addAction( actions.degree ); // settings / behavior menus.behavior = menus.settings->addMenu( "" ); menus.behavior->addAction( actions.optionAutoCalc ); menus.behavior->addAction( actions.optionAutoCompletion ); menus.behavior->addAction( actions.optionHiliteSyntax ); menus.behavior->addAction( actions.optionAlwaysOnTop ); menus.behavior->addAction( actions.optionMinimizeToTray ); // settings / radix character menus.radixChar = menus.settings->addMenu( "" ); menus.radixChar->addAction( actions.radixCharAuto ); menus.radixChar->addSeparator(); menus.radixChar->addAction( actions.radixCharDot ); menus.radixChar->addAction( actions.radixCharComma ); // settings / language menus.language = menus.settings->addMenu( "" ); menus.language->addAction( actions.languageDefault ); menus.language->addSeparator(); menus.language->addAction( actions.languageCa ); menus.language->addAction( actions.languageCs ); menus.language->addAction( actions.languageDe ); menus.language->addAction( actions.languageEn ); menus.language->addAction( actions.languageEs ); menus.language->addAction( actions.languageEsAr ); menus.language->addAction( actions.languageEu ); menus.language->addAction( actions.languageFi ); menus.language->addAction( actions.languageFr ); menus.language->addAction( actions.languageHe ); menus.language->addAction( actions.languageId ); menus.language->addAction( actions.languageIt ); menus.language->addAction( actions.languageNb ); menus.language->addAction( actions.languageNl ); menus.language->addAction( actions.languagePl ); menus.language->addAction( actions.languagePt ); menus.language->addAction( actions.languagePtBr ); menus.language->addAction( actions.languageRo ); menus.language->addAction( actions.languageRu ); menus.language->addAction( actions.languageSv ); menus.language->addAction( actions.languageTr ); menus.language->addAction( actions.languageZhCn ); // help menus.help = new QMenu( "", p ); p->menuBar()->addMenu( menus.help ); menus.help->addAction( actions.helpTipOfTheDay ); menus.help->addAction( actions.helpGotoWebsite ); menus.help->addSeparator(); menus.help->addAction( actions.helpAbout ); menus.help->addAction( actions.helpAboutQt ); // necessary after hiding the menu bar, so shortcuts still recognized p->addActions( p->menuBar()->actions() ); p->addAction( actions.scrollDown ); p->addAction( actions.scrollUp ); } void MainWindow::Private::setMenusText() { menus.session ->setTitle( MainWindow::tr( "&Session" ) ); menus.edit ->setTitle( MainWindow::tr( "&Edit" ) ); menus.view ->setTitle( MainWindow::tr( "&View" ) ); menus.settings ->setTitle( MainWindow::tr( "Se&ttings" ) ); menus.format ->setTitle( MainWindow::tr( "Result &Format" ) ); menus.decimal ->setTitle( MainWindow::tr( "&Decimal" ) ); menus.angle ->setTitle( MainWindow::tr( "&Angle Unit" ) ); menus.behavior ->setTitle( MainWindow::tr( "&Behavior" ) ); menus.radixChar->setTitle( MainWindow::tr( "Radix &Character" ) ); menus.language ->setTitle( MainWindow::tr( "&Language" ) ); menus.help ->setTitle( MainWindow::tr( "&Help" ) ); } void MainWindow::Private::createStatusBar() { QStatusBar * bar = p->statusBar(); status.angleUnit = new QLabel( bar ); status.format = new QLabel( bar ); status.angleUnit->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken ); status.format ->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken ); bar->addWidget( status.angleUnit ); bar->addWidget( status.format ); setStatusBarText(); } void MainWindow::Private::createFixedWidgets() { // necessary objects constants = new Constants( p ); functions = new Functions( settings.angleMode, p ); evaluator = new Evaluator( functions, settings.radixChar, p ); // outer widget and layout widgets.root = new QWidget( p ); p->setCentralWidget( widgets.root ); layouts.root = new QVBoxLayout( widgets.root ); layouts.root->setMargin( 0 ); layouts.root->setSpacing( 0 ); // display QHBoxLayout * displayLayout = new QHBoxLayout(); displayLayout->setMargin( 5 ); widgets.display = new ResultDisplay( settings.radixChar, settings.format, settings.precision, widgets.root ); displayLayout->addWidget( widgets.display ); layouts.root->addLayout( displayLayout ); // editor QHBoxLayout * editorLayout = new QHBoxLayout(); editorLayout->setMargin( 5 ); widgets.editor = new Editor( evaluator, functions, constants, settings.format, settings.precision, settings.radixChar, widgets.root ); widgets.editor->setFocus(); QString editorStyle( "QTextEdit { font: bold %1pt }" ); int editorPointSize = widgets.editor->font().pointSize(); widgets.editor->setStyleSheet( editorStyle.arg( editorPointSize + 3 ) ); widgets.editor->setFixedHeight( widgets.editor->sizeHint().height() ); editorLayout->addWidget( widgets.editor ); layouts.root->addLayout( editorLayout ); // for autocalc widgets.autoCalcLabel = new AutoHideLabel( p ); widgets.autoCalcLabel->hide(); // for tip of the day and menu bar hiding message widgets.tip = new TipWidget( p ); widgets.tip->hide(); } void MainWindow::Private::createKeypad() { widgets.keypad = new Keypad( settings.radixChar, widgets.root ); widgets.keypad->setFocusPolicy( Qt::NoFocus ); connect( widgets.keypad, SIGNAL( buttonPressed( Keypad::Button ) ), p, SLOT( keypadButtonPressed( Keypad::Button ) ) ); connect( p, SIGNAL( radixCharChanged( char ) ), widgets.keypad, SLOT( setRadixChar( char ) ) ); connect( p, SIGNAL( retranslateText() ), widgets.keypad, SLOT( retranslateText() ) ); layouts.keypad = new QHBoxLayout(); layouts.keypad->addStretch(); layouts.keypad->addWidget( widgets.keypad ); layouts.keypad->addStretch(); layouts.root->addLayout( layouts.keypad ); widgets.keypad->show(); widgets.display->scrollEnd(); } void MainWindow::Private::createBookDock() { QString booksDir; #if defined(Q_OS_WIN32) || defined(Q_OS_MAC) QString appPath = QApplication::applicationFilePath(); int ii = appPath.lastIndexOf( '/' ); if ( ii > 0 ) appPath.remove( ii, appPath.length() ); booksDir = appPath + '/' + QString( "books/" ); #else BrInitError error; if ( br_init( & error ) == 0 && error != BR_INIT_ERROR_DISABLED ) { qDebug( "Warning: BinReloc failed to initialize (error code %d)", error ); qDebug( "Will fallback to hardcoded default path." ); } char * dataDir = br_find_data_dir( 0 ); booksDir = QString( dataDir ) + "/speedcrunch/books/"; free( dataDir ); #endif docks.book = new BookDock( booksDir, "math_index.html", settings.language, p ); docks.book->setObjectName( "BookDock" ); docks.book->setTitle( MainWindow::tr( "Math Book" ) ); docks.book->installEventFilter( p ); p->addDockWidget( Qt::RightDockWidgetArea, docks.book ); connect( docks.book, SIGNAL( expressionSelected( const QString & ) ), p, SLOT( expressionSelected( const QString & ) ) ); if ( docks.functions ) p->tabifyDockWidget( docks.functions, docks.book ); else if ( docks.variables ) p->tabifyDockWidget( docks.variables, docks.book ); else if ( docks.history ) p->tabifyDockWidget( docks.history, docks.book ); else if ( docks.constants ) p->tabifyDockWidget( docks.constants, docks.book ); settings.showBook = true; } void MainWindow::Private::createConstantsDock() { docks.constants = new ConstantsDock( constants, settings.radixChar, p ); docks.constants->setObjectName( "ConstantsDock" ); docks.constants->installEventFilter( p ); p->addDockWidget( Qt::RightDockWidgetArea, docks.constants ); connect( docks.constants, SIGNAL( constantSelected( const QString & ) ), p, SLOT( constantSelected( const QString & ) ) ); connect( p, SIGNAL( radixCharChanged( char ) ), docks.constants, SLOT( setRadixChar( char ) ) ); connect( p, SIGNAL( retranslateText() ), docks.constants, SLOT( retranslateText() ) ); if ( docks.functions ) p->tabifyDockWidget( docks.functions, docks.constants ); else if ( docks.variables ) p->tabifyDockWidget( docks.variables, docks.constants ); else if ( docks.history ) p->tabifyDockWidget( docks.history, docks.constants ); else if ( docks.book ) p->tabifyDockWidget( docks.book, docks.constants ); settings.showConstants = true; } void MainWindow::Private::createFunctionsDock() { docks.functions = new FunctionsDock( functions, p ); docks.functions->setObjectName( "FunctionsDock" ); docks.functions->installEventFilter( p ); p->addDockWidget( Qt::RightDockWidgetArea, docks.functions ); connect( docks.functions, SIGNAL( functionSelected( const QString & ) ), p, SLOT( functionSelected( const QString & ) ) ); connect( p, SIGNAL( retranslateText() ), docks.functions, SLOT( retranslateText() ) ); if ( docks.history ) p->tabifyDockWidget( docks.history, docks.functions ); else if ( docks.variables ) p->tabifyDockWidget( docks.variables, docks.functions ); else if ( docks.constants ) p->tabifyDockWidget( docks.constants, docks.functions ); else if ( docks.book ) p->tabifyDockWidget( docks.book, docks.functions ); settings.showFunctions = true; } void MainWindow::Private::createHistoryDock() { docks.history = new HistoryDock( p ); docks.history->setObjectName( "HistoryDock" ); docks.history->installEventFilter( p ); p->addDockWidget( Qt::RightDockWidgetArea, docks.history ); connect( docks.history, SIGNAL( expressionSelected( const QString & ) ), p, SLOT( expressionSelected( const QString & ) ) ); connect( p, SIGNAL( retranslateText() ), docks.history, SLOT( retranslateText() ) ); docks.history->setHistory( widgets.editor->history() ); if ( docks.functions ) p->tabifyDockWidget( docks.functions, docks.history ); else if ( docks.variables ) p->tabifyDockWidget( docks.variables, docks.history ); else if ( docks.constants ) p->tabifyDockWidget( docks.constants, docks.history ); else if ( docks.book ) p->tabifyDockWidget( docks.book, docks.history ); settings.showHistory = true; } void MainWindow::Private::createVariablesDock() { docks.variables = new VariablesDock( settings.radixChar, p ); docks.variables->setObjectName( "VariablesDock" ); docks.variables->installEventFilter( p ); p->addDockWidget( Qt::RightDockWidgetArea, docks.variables ); connect( docks.variables, SIGNAL( variableSelected( const QString & ) ), p, SLOT( variableSelected( const QString & ) ) ); connect( p, SIGNAL( radixCharChanged( char ) ), docks.variables, SLOT( setRadixChar( char ) ) ); connect( p, SIGNAL( retranslateText() ), docks.variables, SLOT( retranslateText() ) ); docks.variables->updateList( evaluator ); if ( docks.functions ) p->tabifyDockWidget( docks.functions, docks.variables ); else if ( docks.history ) p->tabifyDockWidget( docks.history, docks.variables ); else if ( docks.constants ) p->tabifyDockWidget( docks.constants, docks.variables ); else if ( docks.book ) p->tabifyDockWidget( docks.book, docks.variables ); settings.showVariables = true; } void MainWindow::Private::createFixedConnections() { connect( actions.clearHistory, SIGNAL( triggered() ), p, SLOT( clearHistory() ) ); connect( actions.clearExpression, SIGNAL( triggered() ), p, SLOT( clearExpression() ) ); connect( actions.degree, SIGNAL( triggered() ), p, SLOT( degree() ) ); connect( actions.deleteAllVariables, SIGNAL( triggered() ), p, SLOT( deleteAllVariables() ) ); connect( actions.deleteVariable, SIGNAL( triggered() ), p, SLOT( deleteVariable() ) ); connect( actions.digits15, SIGNAL( triggered() ), p, SLOT( digits15() ) ); connect( actions.digits2, SIGNAL( triggered() ), p, SLOT( digits2() ) ); connect( actions.digits3, SIGNAL( triggered() ), p, SLOT( digits3() ) ); connect( actions.digits50, SIGNAL( triggered() ), p, SLOT( digits50() ) ); connect( actions.digits8, SIGNAL( triggered() ), p, SLOT( digits8() ) ); connect( actions.digitsAuto, SIGNAL( triggered() ), p, SLOT( digitsAuto() ) ); connect( actions.editCopyResult, SIGNAL( triggered() ), p, SLOT( copyResult() ) ); connect( actions.editCopy, SIGNAL( triggered() ), widgets.editor, SLOT( copy() ) ); connect( actions.editPaste, SIGNAL( triggered() ), widgets.editor, SLOT( paste() ) ); connect( actions.selectExpression, SIGNAL( triggered() ), p, SLOT( selectExpression() ) ); connect( actions.helpAboutQt, SIGNAL( triggered() ), p, SLOT( aboutQt() ) ); connect( actions.helpAbout, SIGNAL( triggered() ), p, SLOT( about() ) ); connect( actions.helpGotoWebsite, SIGNAL( triggered() ), p, SLOT( gotoWebsite() ) ); connect( actions.helpTipOfTheDay, SIGNAL( triggered() ), p, SLOT( showTipOfTheDay() ) ); connect( actions.insertFunction, SIGNAL( triggered() ), p, SLOT( insertFunction() ) ); connect( actions.insertVariable, SIGNAL( triggered() ), p, SLOT( insertVariable() ) ); connect( actions.radian, SIGNAL( triggered() ), p, SLOT( radian() ) ); connect( actions.scrollDown, SIGNAL( triggered() ), p, SLOT( scrollDown() ) ); connect( actions.scrollUp, SIGNAL( triggered() ), p, SLOT( scrollUp() ) ); connect( actions.sessionImport, SIGNAL( triggered() ), p, SLOT( importSession() ) ); connect( actions.sessionLoad, SIGNAL( triggered() ), p, SLOT( loadSession() ) ); connect( actions.sessionQuit, SIGNAL( triggered() ), p, SLOT( close() ) ); connect( actions.sessionSave, SIGNAL( triggered() ), p, SLOT( saveSession() ) ); connect( actions.sessionExport, SIGNAL( triggered() ), p, SLOT( exportSession() ) ); connect( actions.showBook, SIGNAL( toggled( bool ) ), p, SLOT( showBook( bool ) ) ); connect( actions.showConstants, SIGNAL( toggled( bool ) ), p, SLOT( showConstants( bool ) ) ); connect( actions.showFullScreen, SIGNAL( toggled( bool ) ), p, SLOT( showInFullScreen( bool ) ) ); connect( actions.showFunctions, SIGNAL( toggled( bool ) ), p, SLOT( showFunctions( bool ) ) ); connect( actions.showHistory, SIGNAL( toggled( bool ) ), p, SLOT( showHistory( bool ) ) ); connect( actions.showKeypad, SIGNAL( toggled( bool ) ), p, SLOT( showKeypad( bool ) ) ); connect( actions.showMenuBar, SIGNAL( triggered() ), p, SLOT( showMenuBar() ) ); connect( actions.showStatusBar, SIGNAL( toggled( bool ) ), p, SLOT( showStatusBar( bool ) ) ); connect( actions.showVariables, SIGNAL( toggled( bool ) ), p, SLOT( showVariables( bool ) ) ); connect( actions.formatBinary, SIGNAL( triggered() ), p, SLOT( formatBinary() ) ); connect( actions.formatEngineering, SIGNAL( triggered() ), p, SLOT( formatEngineering() ) ); connect( actions.formatFixed, SIGNAL( triggered() ), p, SLOT( formatFixed() ) ); connect( actions.formatGeneral, SIGNAL( triggered() ), p, SLOT( formatGeneral() ) ); connect( actions.formatHexadec, SIGNAL( triggered() ), p, SLOT( formatHexadec() ) ); connect( actions.formatOctal, SIGNAL( triggered() ), p, SLOT( formatOctal() ) ); connect( actions.formatScientific, SIGNAL( triggered() ), p, SLOT( formatScientific() ) ); connect( actions.optionAutoCalc, SIGNAL( toggled( bool ) ), p, SLOT( autoCalcToggled( bool ) ) ); connect( actions.optionAutoCompletion, SIGNAL( toggled( bool ) ), p, SLOT( autoCompletionToggled( bool ) ) ); connect( actions.optionAlwaysOnTop, SIGNAL( toggled( bool ) ), p, SLOT( alwaysOnTopToggled( bool ) ) ); connect( actions.optionMinimizeToTray, SIGNAL( toggled( bool ) ), p, SLOT( minimizeToTrayToggled( bool ) ) ); connect( actions.optionHiliteSyntax, SIGNAL( toggled( bool ) ), p, SLOT( hiliteSyntaxToggled( bool ) ) ); connect( actions.radixCharAuto, SIGNAL( triggered() ), p, SLOT( radixCharAutoActivated() ) ); connect( actions.radixCharDot, SIGNAL( triggered() ), p, SLOT( radixCharDotActivated() ) ); connect( actions.radixCharComma, SIGNAL( triggered() ), p, SLOT( radixCharCommaActivated() ) ); connect( actions.languageDefault, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageCa, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageCs, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageDe, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageEn, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageEs, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageEsAr, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageEu, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageFi, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageFr, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageHe, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageId, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageIt, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageNb, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageNl, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languagePl, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languagePt, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languagePtBr, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageRo, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageRu, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageSv, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageTr, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( actions.languageZhCn, SIGNAL( triggered() ), p, SLOT( changeLanguage() ) ); connect( widgets.editor, SIGNAL( autoCalcEnabled( const QString & ) ), p, SLOT( showAutoCalc( const QString & ) ) ); connect( widgets.editor, SIGNAL( autoCalcDisabled() ), p, SLOT( hideAutoCalc() ) ); connect( widgets.editor, SIGNAL( returnPressed() ), p, SLOT( returnPressed() ) ); connect( widgets.editor, SIGNAL( textChanged() ), p, SLOT( textChanged() ) ); connect( widgets.display, SIGNAL( textSelected( const QString & ) ), widgets.editor, SLOT( paste() ) ); connect( widgets.display, SIGNAL( textSelected( const QString & ) ), widgets.editor, SLOT( setFocus() ) ); connect( p, SIGNAL( formatChanged( char ) ), widgets.editor, SLOT( setFormat( char ) ) ); connect( p, SIGNAL( precisionChanged( int ) ), widgets.editor, SLOT( setPrecision( int ) ) ); connect( p, SIGNAL( radixCharChanged( char ) ), widgets.editor, SLOT( setRadixChar( char ) ) ); connect( p, SIGNAL( formatChanged( char ) ), widgets.display, SLOT( setFormat( char ) ) ); connect( p, SIGNAL( precisionChanged( int ) ), widgets.display, SLOT( setPrecision( int ) ) ); connect( p, SIGNAL( radixCharChanged( char ) ), widgets.display, SLOT( setRadixChar( char ) ) ); connect( p, SIGNAL( radixCharChanged( char ) ), evaluator, SLOT( setRadixChar( char ) ) ); connect( p, SIGNAL( angleModeChanged( char ) ), functions, SLOT( setAngleMode( char ) ) ); connect( p, SIGNAL( retranslateText() ), p, SLOT( setAllText() ) ); } void MainWindow::Private::applySettings() { // window size if ( settings.mainWindowSize != QSize(0, 0) ) p->resize( settings.mainWindowSize ); // window state p->restoreState( settings.mainWindowState ); // full screen actions.showFullScreen->setChecked( settings.showFullScreen ); // always-on-top actions.optionAlwaysOnTop->setChecked( settings.stayAlwaysOnTop ); // angle mode if ( settings.angleMode == 'r' ) actions.radian->setChecked( true ); else if ( settings.angleMode == 'd' ) actions.degree->setChecked( true ); // language checkInitialLanguage(); // history if ( settings.saveSession ) restoreHistory(); else p->clearHistory(); // variables if ( settings.saveVariables ) restoreVariables(); // format checkInitialFormat(); // precision checkInitialPrecision(); // radix character if ( settings.radixChar == 'C' ) actions.radixCharAuto->setChecked( true ); else if ( settings.radixChar == '.' ) actions.radixCharDot->setChecked( true ); else if ( settings.radixChar == ',' ) actions.radixCharComma->setChecked( true ); // keypad actions.showKeypad->setChecked( settings.showKeypad ); // menu bar p->menuBar()->setVisible( settings.showMenuBar ); // autocalc if ( settings.autoCalc ) actions.optionAutoCalc->setChecked( true ); else p->autoCalcToggled( false ); // autocomplete if ( settings.autoComplete ) actions.optionAutoCompletion->setChecked( true ); else p->autoCompletionToggled( false ); // minimize to system tray actions.optionMinimizeToTray->setChecked( settings.minimizeToTray ); // syntax hilite if ( settings.hiliteSyntax ) actions.optionHiliteSyntax->setChecked( true ); else p->hiliteSyntaxToggled( false ); // docks actions.showBook ->setChecked( settings.showBook ); actions.showConstants->setChecked( settings.showConstants ); actions.showFunctions->setChecked( settings.showFunctions ); actions.showHistory ->setChecked( settings.showHistory ); actions.showVariables->setChecked( settings.showVariables ); restoreFloatingDocks(); // status bar actions.showStatusBar->setChecked( settings.showStatusBar ); } void MainWindow::Private::checkInitialFormat() { if ( settings.format == 'g' ) actions.formatGeneral->setChecked( true ); else if ( settings.format == 'f' ) actions.formatFixed->setChecked( true ); else if ( settings.format == 'n' ) actions.formatEngineering->setChecked( true ); else if ( settings.format == 'e' ) actions.formatScientific->setChecked( true ); else if ( settings.format == 'h' ) actions.formatHexadec->setChecked( true ); else if ( settings.format == 'o' ) actions.formatOctal->setChecked( true ); else if ( settings.format == 'b' ) actions.formatBinary->setChecked( true ); } void MainWindow::Private::checkInitialPrecision() { if ( settings.precision < 0 ) actions.digitsAuto->setChecked( true ); else if ( settings.precision == 2 ) actions.digits2->setChecked( true ); else if ( settings.precision == 3 ) actions.digits3->setChecked( true ); else if ( settings.precision == 8 ) actions.digits8->setChecked( true ); else if ( settings.precision == 15 ) actions.digits15->setChecked( true ); else if ( settings.precision == 50 ) actions.digits50->setChecked( true ); } void MainWindow::Private::checkInitialLanguage() { if ( settings.language == "ca" ) actions.languageCa->setChecked( true ); else if ( settings.language == "cs" ) actions.languageCs->setChecked( true ); else if ( settings.language == "de" ) actions.languageDe->setChecked( true ); else if ( settings.language == "en" ) actions.languageEn->setChecked( true ); else if ( settings.language == "es" ) actions.languageEs->setChecked( true ); else if ( settings.language == "es_AR" ) actions.languageEsAr->setChecked( true ); else if ( settings.language == "eu" ) actions.languageEu->setChecked( true ); else if ( settings.language == "fi" ) actions.languageFi->setChecked( true ); else if ( settings.language == "fr" ) actions.languageFr->setChecked( true ); else if ( settings.language == "he" ) actions.languageHe->setChecked( true ); else if ( settings.language == "id" ) actions.languageId->setChecked( true ); else if ( settings.language == "it" ) actions.languageIt->setChecked( true ); else if ( settings.language == "nb" ) actions.languageNb->setChecked( true ); else if ( settings.language == "nl" ) actions.languageNl->setChecked( true ); else if ( settings.language == "pl" ) actions.languagePl->setChecked( true ); else if ( settings.language == "pt" ) actions.languagePt->setChecked( true ); else if ( settings.language == "pt_BR" ) actions.languagePtBr->setChecked( true ); else if ( settings.language == "ro" ) actions.languageRo->setChecked( true ); else if ( settings.language == "ru" ) actions.languageRu->setChecked( true ); else if ( settings.language == "sv" ) actions.languageSv->setChecked( true ); else if ( settings.language == "tr" ) actions.languageTr->setChecked( true ); else if ( settings.language == "zh_CN" ) actions.languageZhCn->setChecked( true ); else actions.languageDefault->setChecked( true ); } void MainWindow::Private::saveSettings() { // history settings.history = widgets.editor->history(); settings.historyResults = widgets.editor->historyResults(); // variables if ( settings.saveVariables ) { settings.variables.clear(); QVector vars = evaluator->variables(); for ( int i = 0; i < vars.count(); i++ ) { QString name = vars[i].name; char * value = HMath::formatScientific( vars[i].value, DECPRECISION ); settings.variables.append( QString( "%1=%2" ).arg( name ) .arg( QString( value ) ) ); free( value ); } } syncWindowStateToSettings(); settings.save(); } void MainWindow::Private::syncWindowStateToSettings() { // main window settings.mainWindowState = p->saveState(); settings.mainWindowSize = p->size(); // docks if ( docks.book ) { settings.bookDockFloating = docks.book->isFloating(); settings.bookDockLeft = docks.book->x(); settings.bookDockTop = docks.book->y(); settings.bookDockWidth = docks.book->width(); settings.bookDockHeight = docks.book->height(); } if ( docks.history ) { settings.historyDockFloating = docks.history->isFloating(); settings.historyDockLeft = docks.history->x(); settings.historyDockTop = docks.history->y(); settings.historyDockWidth = docks.history->width(); settings.historyDockHeight = docks.history->height(); } if ( docks.functions ) { settings.functionsDockFloating = docks.functions->isFloating(); settings.functionsDockLeft = docks.functions->x(); settings.functionsDockTop = docks.functions->y(); settings.functionsDockWidth = docks.functions->width(); settings.functionsDockHeight = docks.functions->height(); } if ( docks.variables ) { settings.variablesDockFloating = docks.variables->isFloating(); settings.variablesDockLeft = docks.variables->x(); settings.variablesDockTop = docks.variables->y(); settings.variablesDockWidth = docks.variables->width(); settings.variablesDockHeight = docks.variables->height(); } if ( docks.constants ) { settings.constantsDockFloating = docks.constants->isFloating(); settings.constantsDockLeft = docks.constants->x(); settings.constantsDockTop = docks.constants->y(); settings.constantsDockWidth = docks.constants->width(); settings.constantsDockHeight = docks.constants->height(); } } // public MainWindow::MainWindow() : QMainWindow(), d( new MainWindow::Private ) { d->p = this; d->settings.load(); d->createUi(); d->applySettings(); emit retranslateText(); QTimer::singleShot( 0, this, SLOT( activate() ) ); } MainWindow::~MainWindow() { delete d; } bool MainWindow::event( QEvent * e ) { if ( e->type() == QEvent::WindowStateChange ) if ( windowState() & Qt::WindowMinimized ) if ( d->settings.minimizeToTray ) { QTimer::singleShot( 100, this, SLOT( minimizeToTray() ) ); return true; } return QMainWindow::event( e ); } // public slots void MainWindow::about() { AboutBox dlg; dlg.exec(); } void MainWindow::aboutQt() { QMessageBox::aboutQt( this, tr( "About Qt" ) ); } void MainWindow::clearHistory() { d->widgets.display->clear(); d->widgets.editor->clearHistory(); if ( d->settings.showHistory ) d->docks.history->clear(); d->settings.history.clear(); d->settings.historyResults.clear(); QTimer::singleShot( 0, d->widgets.editor, SLOT( setFocus() ) ); } void MainWindow::clearExpression() { d->widgets.editor->clear(); QTimer::singleShot( 0, d->widgets.editor, SLOT( setFocus() ) ); } void MainWindow::copyResult() { QClipboard * cb = QApplication::clipboard(); HNumber num = d->evaluator->get( "ans" ); char * strToCopy = HMath::format( num, d->settings.format, d->settings.precision ); QString final( strToCopy ); if ( d->widgets.display->radixChar() == ',' ) final.replace( '.', ',' ); cb->setText( final, QClipboard::Clipboard ); free( strToCopy ); } void MainWindow::degree() { if ( d->settings.angleMode == 'd' ) return; d->settings.angleMode = 'd'; if ( d->status.angleUnit ) d->status.angleUnit->setText( tr( "Degree" ) ); emit angleModeChanged( 'd' ); } void MainWindow::deleteAllVariables() { d->evaluator->clearVariables(); if ( d->settings.showVariables ) d->docks.variables->updateList( d->evaluator ); } void MainWindow::deleteVariable() { DeleteVariableDlg dlg( d->evaluator ); dlg.exec(); if ( d->settings.showVariables ) d->docks.variables->updateList( d->evaluator ); } void MainWindow::digits2() { setPrecision( 2 ); } void MainWindow::digits3() { setPrecision( 3 ); } void MainWindow::digits8() { setPrecision( 8 ); } void MainWindow::digits15() { setPrecision( 15 ); } void MainWindow::digits50() { setPrecision( 50 ); } void MainWindow::digitsAuto() { setPrecision( -1 ); } void MainWindow::selectExpression() { activateWindow(); d->widgets.editor->selectAll(); d->widgets.editor->setFocus(); } void MainWindow::gotoWebsite() { QDesktopServices::openUrl( QUrl( QString::fromLatin1("http://www.speedcrunch.org") ) ); } void MainWindow::hideAutoCalc() { d->widgets.autoCalcLabel->hideText(); } void MainWindow::insertFunction() { InsertFunctionDlg dlg( d->functions ); if ( dlg.exec() == InsertFunctionDlg::Accepted ) { QString funcName = dlg.functionName(); if ( ! funcName.isEmpty() ) d->widgets.editor->insert( funcName ); } } void MainWindow::insertVariable() { InsertVariableDlg dlg( d->evaluator, d->settings.radixChar ); if ( dlg.exec() == InsertVariableDlg::Accepted ) { QString varName = dlg.variableName(); if ( ! varName.isEmpty() ) d->widgets.editor->insert( varName ); } } void MainWindow::loadSession() { QString errMsg = tr( "File %1 is not a valid session" ); QString filters = tr( "SpeedCrunch Sessions (*.sch);;All Files (*)" ); QString fname = QFileDialog::getOpenFileName( this, tr( "Load Session" ), QString::null, filters ); if ( fname.isEmpty() ) return; QFile file( fname ); if ( ! file.open( QIODevice::ReadOnly ) ) { QMessageBox::critical( this, tr( "Error" ), tr( "Can't read from file %1" ).arg( fname ) ); return; } QTextStream stream( & file ); // version of the format QString version = stream.readLine(); if ( version != "0.10" ) { QMessageBox::critical( this, tr( "Error" ), errMsg.arg( fname ) ); return; } // number of calculations bool ok; int noCalcs = stream.readLine().toInt( &ok ); if ( ok == false || noCalcs < 0 ) { QMessageBox::critical( this, tr( "Error" ), errMsg.arg( fname ) ); return; } // ask for merge with current session QString mergeMsg = tr( "Merge session being loaded with current session?\n" "If no, current variables and display will be " "cleared." ); QMessageBox::StandardButton but = QMessageBox::question( this, tr( "Question" ), mergeMsg, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Yes ); if ( but == QMessageBox::Cancel ) { return; } else if ( but == QMessageBox::No ) { d->widgets.display->clear(); deleteAllVariables(); clearHistory(); } // expressions and results QStringList expLs; QStringList resLs; for ( int i = 0; i < noCalcs; i++ ) { QString exp = stream.readLine(); QString res = stream.readLine(); if ( exp.isNull() || res.isNull() ) { QMessageBox::critical( this, tr( "Error" ), errMsg.arg( fname ) ); return; } expLs.append( exp ); resLs.append( res ); } // FIXME: this keeps the history in three (finally even four) different places. // There should be just one central history and result list, and the clients // editor, display, settings and historyDock should retrieve their data from there. // FIXME: Actually there should be three lists: expressions, values and formats. d->widgets.display->appendHistory( expLs, resLs ); d->widgets.editor->appendHistory( expLs, resLs ); if ( d->settings.showHistory ) d->docks.history->appendHistory( expLs ); // variables int noVars = stream.readLine().toInt( &ok ); if ( ok == false || noVars < 0 ) { QMessageBox::critical( this, tr( "Error" ), errMsg.arg( fname ) ); return; } for ( int i = 0; i < noVars; i++ ) { QString var = stream.readLine(); QString val = stream.readLine(); if ( var.isNull() || val.isNull() ) { QMessageBox::critical( this, tr( "Error" ), errMsg.arg( fname ) ); return; } HNumber num( val.toAscii().data() ); if ( num != HNumber::nan() ) d->evaluator->set( var, num ); } file.close(); } void MainWindow::importSession() { QString filters = tr( "All Files (*)" ); QString fname = QFileDialog::getOpenFileName( this, tr( "Import Session" ), QString::null, filters ); if ( fname.isEmpty() ) return; QFile file( fname ); if ( ! file.open( QIODevice::ReadOnly ) ) { QMessageBox::critical( this, tr( "Error" ), tr( "Can't read from file %1" ).arg( fname ) ); return; } // ask for merge with current session QString mergeMsg = tr( "Merge session being imported with current session?\n" "If no, current variables and display will be " "cleared." ); QMessageBox::StandardButton but = QMessageBox::question( this, tr( "Question" ), mergeMsg, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Yes ); if ( but == QMessageBox::Cancel ) { return; } else if ( but == QMessageBox::No ) { d->widgets.display->clear(); deleteAllVariables(); clearHistory(); } QTextStream stream( & file ); QString exp = stream.readLine(); bool ignoreAll = false; while ( ! exp.isNull() ) { d->widgets.editor->setText( exp ); QString str = d->evaluator->autoFix( exp ); d->evaluator->setExpression( str ); HNumber result = d->evaluator->evalUpdateAns(); if ( ! d->evaluator->error().isEmpty() ) { if ( ! ignoreAll ) { QMessageBox::StandardButton but = QMessageBox::warning( this, tr( "Error" ), tr( "Ignore error?" ) + "\n" + d->evaluator->error(), QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::Cancel, QMessageBox::Yes ); if ( but == QMessageBox::Cancel ) return; else if ( but == QMessageBox::YesToAll ) ignoreAll = true; } } else { d->widgets.display->append( str, result ); char * num = HMath::formatScientific( result, DECPRECISION ); d->widgets.editor->appendHistory( str, num ); free( num ); d->widgets.editor->setAnsAvailable( true ); if ( d->settings.showVariables ) d->docks.variables->updateList( d->evaluator ); if ( d->settings.showHistory ) d->docks.history->append( str ); d->widgets.editor->setText( str ); d->widgets.editor->selectAll(); d->widgets.editor->stopAutoCalc(); d->widgets.editor->stopAutoComplete(); d->conditions.autoAns = true; } exp = stream.readLine(); } file.close(); QTimer::singleShot( 0, d->widgets.editor, SLOT( setFocus() ) ); if ( ! isActiveWindow() ) activateWindow(); } void MainWindow::alwaysOnTopToggled( bool b ) { d->settings.stayAlwaysOnTop = b; QPoint cur = mapToGlobal( QPoint(0, 0) ); if ( b ) setWindowFlags( windowFlags() | Qt::WindowStaysOnTopHint ); else setWindowFlags( windowFlags() & (~ Qt::WindowStaysOnTopHint) ); move( cur ); show(); } void MainWindow::autoCalcToggled( bool b ) { d->settings.autoCalc = b; d->widgets.editor->setAutoCalcEnabled( b ); } void MainWindow::autoCompletionToggled( bool b ) { d->settings.autoComplete = b; d->widgets.editor->setAutoCompleteEnabled( b ); } void MainWindow::minimizeToTrayToggled( bool b ) { if ( b && ! d->widgets.trayIcon && QSystemTrayIcon::isSystemTrayAvailable() ) { d->conditions.trayNotify = true; d->widgets.trayIcon = new QSystemTrayIcon( this ); d->widgets.trayIcon->setToolTip( "SpeedCrunch" ); d->widgets.trayIcon->setIcon( QPixmap( ":/speedcrunch.png" ) ); d->menus.trayIcon = new QMenu( this ); d->menus.trayIcon->addAction( d->actions.editCopyResult ); d->menus.trayIcon->addSeparator(); d->menus.trayIcon->addAction( d->actions.sessionQuit ); d->widgets.trayIcon->setContextMenu( d->menus.trayIcon ); connect( d->widgets.trayIcon, SIGNAL( activated( QSystemTrayIcon::ActivationReason ) ), this, SLOT( trayIconActivated( QSystemTrayIcon::ActivationReason ) ) ); } else { if ( d->widgets.trayIcon ) delete d->widgets.trayIcon; d->widgets.trayIcon = 0; } d->settings.minimizeToTray = b; } void MainWindow::hiliteSyntaxToggled( bool b ) { d->widgets.editor->setSyntaxHighlight( b ); d->settings.hiliteSyntax = b; } void MainWindow::radian() { if ( d->settings.angleMode == 'r' ) return; d->settings.angleMode = 'r'; if ( d->status.angleUnit ) d->status.angleUnit->setText( tr( "Radian" ) ); emit angleModeChanged( 'r' ); } void MainWindow::saveSession() { QString filters = tr( "SpeedCrunch Sessions (*.sch);;All Files (*)" ); QString fname = QFileDialog::getSaveFileName( this, tr( "Save Session" ), QString::null, filters ); if ( fname.isEmpty() ) return; QFile file( fname ); if ( ! file.open( QIODevice::WriteOnly ) ) { QMessageBox::critical( this, tr( "Error" ), tr( "Can't write to file %1" ).arg( fname ) ); return; } QTextStream stream( & file ); // version of the format stream << "0.10" << "\n"; // number of calculations stream << d->widgets.display->count() << "\n"; // expressions and results stream << d->widgets.display->asText() << "\n"; // number of variables int noVars = d->evaluator->variables().count(); stream << noVars - 2 << "\n"; // exclude pi and phi // variables for ( int i = 0; i < noVars; i++ ) { Variable var = d->evaluator->variables()[i]; if ( var.name != "pi" && var.name != "phi" ) { char * value = HMath::format( var.value ); stream << var.name << "\n" << value << "\n"; free( value ); } } file.close(); } void MainWindow::exportSession() { QString filters = tr( "All Files (*)" ); QString fname = QFileDialog::getSaveFileName( this, tr( "Export Session" ), QString::null, filters ); if ( fname.isEmpty() ) return; QFile file( fname ); if ( ! file.open( QIODevice::WriteOnly ) ) { QMessageBox::critical( this, tr( "Error" ), tr( "Can't write to file %1" ).arg( fname ) ); return; } QTextStream stream( & file ); // expressions and results stream << d->widgets.display->asText() << "\n"; file.close(); } void MainWindow::setWidgetsDirection() { if ( (d->settings.language == "C" && QLocale().language() == QLocale::Hebrew) || d->settings.language == "he" ) { qApp->setLayoutDirection( Qt::RightToLeft ); } else { qApp->setLayoutDirection( Qt::LeftToRight ); } } void MainWindow::scrollDown() { QScrollBar * sb = d->widgets.display->verticalScrollBar(); int value = sb->value() + 40; sb->setValue( value ); } void MainWindow::scrollUp() { QScrollBar * sb = d->widgets.display->verticalScrollBar(); int value = sb->value() - 40; sb->setValue( value ); } void MainWindow::showMenuBar() { menuBar()->setVisible( ! menuBar()->isVisible() ); d->settings.showMenuBar = menuBar()->isVisible(); if ( ! menuBar()->isVisible() && d->conditions.notifyMenuBarHidden ) { showMenuBarTip(); d->conditions.notifyMenuBarHidden = false; } d->widgets.display->scrollEnd(); } void MainWindow::showStatusBar( bool b ) { b ? d->createStatusBar() : d->deleteStatusBar(); d->settings.showStatusBar = b; } void MainWindow::showAutoCalc( const QString & msg ) { QPoint p = d->widgets.editor->mapToParent( QPoint(0, 0) ); d->widgets.autoCalcLabel->move( p ); d->widgets.autoCalcLabel->showText( msg ); } void MainWindow::showInFullScreen( bool b ) { d->settings.showFullScreen = b; b ? showFullScreen() : showNormal(); } bool MainWindow::eventFilter( QObject * o, QEvent * e ) { if ( o == d->docks.book ) { if ( e->type() == QEvent::Close ) { d->deleteBookDock(); return true; } return false; } if ( o == d->docks.constants ) { if ( e->type() == QEvent::Close ) { d->deleteConstantsDock(); return true; } return false; } if ( o == d->docks.functions ) { if ( e->type() == QEvent::Close ) { d->deleteFunctionsDock(); return true; } return false; } if ( o == d->docks.history ) { if ( e->type() == QEvent::Close ) { d->deleteHistoryDock(); return true; } return false; } if ( o == d->docks.variables ) { if ( e->type() == QEvent::Close ) { d->deleteVariablesDock(); return true; } return false; } return QMainWindow::eventFilter( o, e ); } void MainWindow::Private::deleteKeypad() { p->disconnect( widgets.keypad ); delete widgets.keypad; widgets.keypad = 0; layouts.root->removeItem( layouts.keypad ); delete layouts.keypad; layouts.keypad = 0; } void MainWindow::Private::deleteStatusBar() { delete status.angleUnit; status.angleUnit = 0; delete status.format; status.format = 0; p->setStatusBar( 0 ); } void MainWindow::Private::deleteBookDock() { Q_ASSERT( docks.book ); p->removeDockWidget( docks.book ); p->disconnect( docks.book ); delete docks.book; docks.book = 0; actions.showBook->blockSignals( true ); actions.showBook->setChecked( false ); actions.showBook->blockSignals( false ); settings.showBook = false; } void MainWindow::Private::deleteConstantsDock() { Q_ASSERT( docks.constants ); p->removeDockWidget( docks.constants ); p->disconnect( docks.constants ); delete docks.constants; docks.constants = 0; actions.showConstants->blockSignals( true ); actions.showConstants->setChecked( false ); actions.showConstants->blockSignals( false ); settings.showConstants = false; } void MainWindow::Private::deleteFunctionsDock() { Q_ASSERT( docks.functions ); p->removeDockWidget( docks.functions ); p->disconnect( docks.functions ); delete docks.functions; docks.functions = 0; actions.showFunctions->blockSignals( true ); actions.showFunctions->setChecked( false ); actions.showFunctions->blockSignals( false ); settings.showFunctions = false; } void MainWindow::Private::deleteHistoryDock() { Q_ASSERT( docks.history ); p->removeDockWidget( docks.history ); p->disconnect( docks.history ); delete docks.history; docks.history = 0; actions.showHistory->blockSignals( true ); actions.showHistory->setChecked( false ); actions.showHistory->blockSignals( false ); settings.showHistory = false; } void MainWindow::Private::deleteVariablesDock() { Q_ASSERT( docks.variables ); p->removeDockWidget( docks.variables ); p->disconnect( docks.variables ); delete docks.variables; docks.variables = 0; actions.showVariables->blockSignals( true ); actions.showVariables->setChecked( false ); actions.showVariables->blockSignals( false ); settings.showVariables = false; } void MainWindow::showFunctions( bool b ) { if ( b ) d->createFunctionsDock(); else d->deleteFunctionsDock(); } void MainWindow::showBook( bool b ) { if ( b ) d->createBookDock(); else d->deleteBookDock(); } void MainWindow::showConstants( bool b ) { if ( b ) d->createConstantsDock(); else d->deleteConstantsDock(); } void MainWindow::showHistory( bool b ) { if ( b ) d->createHistoryDock(); else d->deleteHistoryDock(); } void MainWindow::showVariables( bool b ) { if ( b ) d->createVariablesDock(); else d->deleteVariablesDock(); } void MainWindow::showKeypad( bool b ) { d->settings.showKeypad = b; if ( b ) d->createKeypad(); else d->deleteKeypad(); } void MainWindow::showMenuBarTip() { QString msg = tr( "The menu bar is now hidden. " "To make it visible again, press Ctrl+Alt+M." ); //QPoint p = mapFromGlobal( d->widgets.display->mapToGlobal( QPoint(0, 0) ) ) // += QPoint(5, 5); d->widgets.tip->move( 0, 0 ); d->widgets.tip->showText( msg, tr( "Warning" ) ); } void MainWindow::showTipOfTheDay() { //QPoint p = mapFromGlobal( d->widgets.display->mapToGlobal( QPoint(0, 0) ) ) // += QPoint(5, 5); d->widgets.tip->move( 0, 0 ); int tipNo = qrand() % 4; QString msg; switch ( tipNo ) { case 0: msg = tr( "To insert a function using keyboard, use Ctrl+F shorcut. " "From the dialog, you can choose the function you want to " "insert." ); break; case 1: msg = tr( "To insert a variable using keyboard, use Ctrl+I shorcut. " "From the dialog, you can choose the variable you want to " "insert." ); break; case 2: msg = tr( "Use variable pi to use pi constant." ); break; case 3: msg = tr( "Use ; (semicolon) to separate the parameters in " "functions." ); break; default: break; } d->widgets.tip->showText( msg, tr( "Tip of the day" ) ); } void MainWindow::formatBinary() { d->actionGroups.digits->setDisabled( true ); setFormat( 'b' ); if ( d->status.format ) d->status.format->setText( tr( "Binary" ) ); } void MainWindow::formatEngineering() { d->actionGroups.digits->setEnabled( true ); setFormat( 'n' ); if ( d->status.format ) d->status.format->setText( tr( "Engineering decimal" ) ); } void MainWindow::formatFixed() { d->actionGroups.digits->setEnabled( true ); setFormat( 'f' ); if ( d->status.format ) d->status.format->setText( tr( "Fixed decimal" ) ); } void MainWindow::formatGeneral() { d->actionGroups.digits->setEnabled( true ); setFormat( 'g' ); if ( d->status.format ) d->status.format->setText( tr( "General decimal" ) ); } void MainWindow::formatHexadec() { d->actionGroups.digits->setDisabled( true ); setFormat( 'h' ); if ( d->status.format ) d->status.format->setText( tr( "Hexadecimal" ) ); } void MainWindow::formatOctal() { d->actionGroups.digits->setDisabled( true ); setFormat( 'o' ); if ( d->status.format ) d->status.format->setText( tr( "Octal" ) ); } void MainWindow::formatScientific() { d->actionGroups.digits->setEnabled( true ); setFormat( 'e' ); if ( d->status.format ) d->status.format->setText( tr( "Scientific decimal" ) ); } // protected slots void MainWindow::activate() { activateWindow(); raise(); d->widgets.editor->setFocus(); } void MainWindow::constantSelected( const QString & c ) { if ( c.isEmpty() ) return; QString str( c ); str.replace( '.', d->widgets.editor->radixChar() ); d->widgets.editor->insert( str ); QTimer::singleShot( 0, d->widgets.editor, SLOT( setFocus() ) ); if ( ! isActiveWindow () ) activateWindow(); } void MainWindow::expressionSelected( const QString & expr ) { QTextCursor cursor = d->widgets.editor->textCursor(); d->widgets.editor->blockSignals( true ); cursor.insertText( expr ); d->widgets.editor->blockSignals( false ); QTimer::singleShot( 0, d->widgets.editor, SLOT( setFocus() ) ); d->widgets.editor->setTextCursor( cursor ); if ( ! isActiveWindow () ) activateWindow(); } void MainWindow::functionSelected( const QString & e ) { if ( e.isEmpty() ) return; d->widgets.editor->insert( e ); d->widgets.editor->insert( "(" ); QTimer::singleShot( 0, d->widgets.editor, SLOT( setFocus() ) ); if ( ! isActiveWindow () ) activateWindow(); } void MainWindow::keypadButtonPressed( Keypad::Button b ) { d->widgets.editor->blockSignals( true ); // prevent completion switch ( b ) { case Keypad::Key0 : d->widgets.editor->insert( "0" ); break; case Keypad::Key1 : d->widgets.editor->insert( "1" ); break; case Keypad::Key2 : d->widgets.editor->insert( "2" ); break; case Keypad::Key3 : d->widgets.editor->insert( "3" ); break; case Keypad::Key4 : d->widgets.editor->insert( "4" ); break; case Keypad::Key5 : d->widgets.editor->insert( "5" ); break; case Keypad::Key6 : d->widgets.editor->insert( "6" ); break; case Keypad::Key7 : d->widgets.editor->insert( "7" ); break; case Keypad::Key8 : d->widgets.editor->insert( "8" ); break; case Keypad::Key9 : d->widgets.editor->insert( "9" ); break; case Keypad::KeyPlus : d->widgets.editor->insert( "+" ); break; case Keypad::KeyMinus : d->widgets.editor->insert( "-" ); break; case Keypad::KeyTimes : d->widgets.editor->insert( "*" ); break; case Keypad::KeyDivide : d->widgets.editor->insert( "/" ); break; case Keypad::KeyEE : d->widgets.editor->insert( "e" ); break; case Keypad::KeyLeftPar : d->widgets.editor->insert( "(" ); break; case Keypad::KeyRightPar : d->widgets.editor->insert( ")" ); break; case Keypad::KeyRaise : d->widgets.editor->insert( "^" ); break; case Keypad::KeyPercent : d->widgets.editor->insert( "%" ); break; case Keypad::KeyFactorial: d->widgets.editor->insert( "!" ); break; case Keypad::KeyX : d->widgets.editor->insert( "x" ); break; case Keypad::KeyXEquals : d->widgets.editor->insert( "x=" ); break; case Keypad::KeyPi : d->widgets.editor->insert( "pi" ); break; case Keypad::KeyAns : d->widgets.editor->insert( "ans" ); break; case Keypad::KeyLn : d->widgets.editor->insert( "ln(" ); break; case Keypad::KeyExp : d->widgets.editor->insert( "exp(" ); break; case Keypad::KeySin : d->widgets.editor->insert( "sin(" ); break; case Keypad::KeyCos : d->widgets.editor->insert( "cos(" ); break; case Keypad::KeyTan : d->widgets.editor->insert( "tan(" ); break; case Keypad::KeyAcos : d->widgets.editor->insert( "acos(" ); break; case Keypad::KeyAtan : d->widgets.editor->insert( "atan(" ); break; case Keypad::KeyAsin : d->widgets.editor->insert( "asin(" ); break; case Keypad::KeySqrt : d->widgets.editor->insert( "sqrt(" ); break; case Keypad::KeyRadixChar: d->widgets.editor->insert( QString( d->widgets.keypad->radixChar() ) ); break; case Keypad::KeyClear: clearExpression(); break; default: break; } QTimer::singleShot( 0, d->widgets.editor, SLOT( setFocus() ) ); d->widgets.editor->blockSignals( false ); if ( b == Keypad::KeyEquals) d->widgets.editor->evaluate(); } void MainWindow::minimizeToTray() { if ( d->widgets.trayIcon ) { hide(); d->widgets.trayIcon->show(); if ( d->conditions.trayNotify ) QTimer::singleShot( 500, this, SLOT( showTrayMessage() ) ); d->conditions.trayNotify = false; } } void MainWindow::Private::restoreVariables() { for ( int k = 0; k < settings.variables.count(); k++ ) { evaluator->setExpression( settings.variables[k] ); evaluator->eval(); QStringList list = settings.variables[k].split( "=" ); evaluator->set( list[0], HNumber( list[1].toAscii().data() ) ); } // free memory settings.variables.clear(); } void MainWindow::Private::restoreFloatingDocks() { if ( settings.showBook && settings.bookDockFloating && ! docks.book->isFloating() ) { docks.book->hide(); docks.book->setFloating( true ); docks.book->move( settings.bookDockLeft, settings.bookDockTop ); docks.book->resize( settings.bookDockWidth, settings.bookDockHeight ); docks.book->show(); } if ( settings.showHistory && settings.historyDockFloating && ! docks.history->isFloating() ) { docks.history->hide(); docks.history->setFloating( true ); docks.history->move( settings.historyDockLeft, settings.historyDockTop ); docks.history->resize( settings.historyDockWidth, settings.historyDockHeight ); docks.history->show(); } if ( settings.showFunctions && settings.functionsDockFloating && ! docks.functions->isFloating() ) { docks.functions->hide(); docks.functions->setFloating( true ); docks.functions->move( settings.functionsDockLeft, settings.functionsDockTop ); docks.functions->resize( settings.functionsDockWidth, settings.functionsDockHeight ); docks.functions->show(); } if ( settings.showVariables && settings.variablesDockFloating && ! docks.variables->isFloating() ) { docks.variables->hide(); docks.variables->setFloating( true ); docks.variables->move( settings.variablesDockLeft, settings.variablesDockTop ); docks.variables->resize( settings.variablesDockWidth, settings.variablesDockHeight ); docks.variables->show(); } if ( settings.showConstants && settings.constantsDockFloating && ! docks.constants->isFloating() ) { docks.constants->hide(); docks.constants->setFloating( true ); docks.constants->move( settings.constantsDockLeft, settings.constantsDockTop ); docks.constants->resize( settings.constantsDockWidth, settings.constantsDockHeight ); docks.constants->show(); } } void MainWindow::Private::restoreHistory() { if ( settings.historyResults.count() != settings.history.count() ) { p->clearHistory(); return; } widgets.editor->setHistory( settings.history ); widgets.editor->setHistoryResults( settings.historyResults ); widgets.display->appendHistory( settings.history, settings.historyResults ); if ( docks.history ) docks.history->setHistory( widgets.editor->history() ); // free some useless memory settings.history.clear(); settings.historyResults.clear(); } void MainWindow::returnPressed() { QString str = d->evaluator->autoFix( d->widgets.editor->text() ); if ( str.isEmpty() ) return; d->evaluator->setExpression( str ); HNumber result = d->evaluator->evalUpdateAns(); if ( ! d->evaluator->error().isEmpty() ) { QMessageBox::warning( this, tr( "Error" ), d->evaluator->error() ); } else { d->widgets.display->append( str, result ); char * num = HMath::formatScientific( result, DECPRECISION ); d->widgets.editor->appendHistory( str, num ); free( num ); d->widgets.editor->setAnsAvailable( true ); if ( d->settings.showVariables ) d->docks.variables->updateList( d->evaluator ); if ( d->settings.showHistory ) d->docks.history->append( str ); } d->widgets.editor->setText( str ); d->widgets.editor->selectAll(); d->widgets.editor->stopAutoCalc(); d->widgets.editor->stopAutoComplete(); d->conditions.autoAns = true; QTimer::singleShot( 0, d->widgets.editor, SLOT( setFocus() ) ); if ( ! isActiveWindow() ) activateWindow(); } void MainWindow::showTrayMessage() { QString msg = tr( "SpeedCrunch is minimized.\nLeft click the icon to " "restore it or right click for options." ); if ( menuBar()->layoutDirection() == Qt::RightToLeft ) msg += QChar( 0x200E ); if ( d->widgets.trayIcon ) d->widgets.trayIcon->showMessage( QString(), msg, QSystemTrayIcon::NoIcon, 4000 ); } void MainWindow::textChanged() { if ( d->conditions.autoAns ) { QString expr = d->evaluator->autoFix( d->widgets.editor->text() ); if ( expr.isEmpty() ) return; Tokens tokens = d->evaluator->scan( expr ); if ( tokens.count() == 1 ) { if ( tokens[0].asOperator() == Token::Plus || tokens[0].asOperator() == Token::Minus || tokens[0].asOperator() == Token::Asterisk || tokens[0].asOperator() == Token::Slash || tokens[0].asOperator() == Token::Caret ) { d->conditions.autoAns = false; expr.prepend( "ans" ); d->widgets.editor->setText( expr ); d->widgets.editor->setCursorPosition( expr.length() ); } } } } void MainWindow::trayIconActivated( QSystemTrayIcon::ActivationReason r ) { if ( r == QSystemTrayIcon::Context ) { d->menus.trayIcon->show(); } else { showNormal(); activateWindow(); d->widgets.editor->setFocus(); QTimer::singleShot( 0, d->widgets.trayIcon, SLOT( hide() ) ); // work around docks do not reappear if floating if ( d->docks.history ) if ( d->docks.history->isFloating() ) { d->docks.history->hide(); d->docks.history->show(); } if ( d->docks.functions ) if ( d->docks.functions->isFloating() ) { d->docks.functions->hide(); d->docks.functions->show(); } if ( d->docks.variables ) if ( d->docks.variables->isFloating() ) { d->docks.variables->hide(); d->docks.variables->show(); } if ( d->docks.constants ) if ( d->docks.constants->isFloating() ) { d->docks.constants->hide(); d->docks.constants->show(); } } } void MainWindow::variableSelected( const QString & v ) { if ( v.isEmpty() ) return; d->widgets.editor->blockSignals( true ); d->widgets.editor->insert( v ); d->widgets.editor->blockSignals( false ); QTimer::singleShot( 0, d->widgets.editor, SLOT( setFocus() ) ); if ( ! isActiveWindow () ) activateWindow(); } void MainWindow::radixCharAutoActivated() { char c = 'C'; d->settings.radixChar = c; emit radixCharChanged( c ); } void MainWindow::radixCharDotActivated() { char c = '.'; d->settings.radixChar = c; emit radixCharChanged( c ); } void MainWindow::radixCharCommaActivated() { char c = ','; d->settings.radixChar = c; emit radixCharChanged( c ); } // protected void MainWindow::closeEvent( QCloseEvent * e ) { d->saveSettings(); e->accept(); } void MainWindow::setPrecision( int p ) { if ( d->settings.precision == p ) return; d->settings.precision = p; emit precisionChanged( p ); } void MainWindow::setFormat( char c ) { if ( d->settings.format == c ) return; d->settings.format = c; emit formatChanged( c ); } void MainWindow::setRadixChar( char c ) { if ( d->settings.radixChar == c ) return; d->settings.radixChar = c; emit radixCharChanged( c ); } void MainWindow::changeLanguage() { QAction * a = d->actionGroups.language->checkedAction(); QString lang = a->data().toString(); if ( d->settings.language != lang ) d->settings.language = lang; emit retranslateText(); } speedcrunch-0.10.1/src/gui/deletevardlg.cpp0000644000175000001440000001010011015364561017771 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2005 Ariya Hidayat // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "deletevardlg.hxx" #include "base/evaluator.hxx" #include "math/hmath.hxx" #include #include #include #include #include #include #include #include struct DeleteVariableDlg::Private { Evaluator * eval; QTreeWidget * list; QPushButton * deleteButton; QPushButton * closeButton; }; static QString formatValue( const HNumber & value ) { char* str = HMath::format( value, 'g' ); QString s = QString::fromLatin1( str ); free( str ); return s; } DeleteVariableDlg::DeleteVariableDlg( Evaluator * eval, QWidget * parent ) : QDialog( parent ), d( new DeleteVariableDlg::Private ) { setWindowTitle( tr( "Delete Variable" ) ); setModal( true ); d->eval = eval; QVBoxLayout * layout = new QVBoxLayout; setLayout( layout ); d->list = new QTreeWidget( this ); d->list->setColumnCount( 2 ); d->list->setAlternatingRowColors( true ); d->list->setRootIsDecorated( false ); d->list->setEditTriggers( QTreeWidget::NoEditTriggers ); d->list->setSelectionBehavior( QTreeWidget::SelectRows ); QStringList titles; titles << tr( "Name" ); titles << tr( "Value" ); d->list->setHeaderLabels( titles ); d->deleteButton = new QPushButton( this ); d->deleteButton->setText( tr( "&Delete" ) ); d->deleteButton->setDefault( true ); d->closeButton = new QPushButton( this ); d->closeButton->setText( tr( "Close" ) ); QWidget * box = new QWidget( this ); QHBoxLayout* boxLayout = new QHBoxLayout; boxLayout->setMargin( 0 ); box->setLayout( boxLayout ); boxLayout->addWidget( d->deleteButton ); boxLayout->addItem( new QSpacerItem( 50, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Minimum ) ); boxLayout->addWidget( d->closeButton ); layout->addWidget( d->list ); layout->addWidget( box ); connect( d->deleteButton, SIGNAL( clicked() ), this, SLOT( deleteVar() ) ); connect( d->closeButton, SIGNAL( clicked() ), this, SLOT( reject() ) ); d->list->setLayoutDirection( Qt::LeftToRight ); updateList(); adjustSize(); } DeleteVariableDlg::~DeleteVariableDlg() { delete d; } void DeleteVariableDlg::updateList() { d->list->setUpdatesEnabled( false ); d->list->clear(); QVector variables = d->eval->variables(); for ( int k = 0; k < variables.count(); k++ ) { QStringList str; str << variables[k].name; str << formatValue( variables[k].value ); if( str[0].toUpper() == "ANS" ) continue; if( str[0].toUpper() == "PI" ) continue; if( str[0].toUpper() == "PHI" ) continue; QTreeWidgetItem * item = 0; item = new QTreeWidgetItem( d->list, str ); item->setTextAlignment( 0, Qt::AlignLeft | Qt::AlignVCenter ); item->setTextAlignment( 1, Qt::AlignLeft | Qt::AlignVCenter ); } d->list->sortItems( 0, Qt::AscendingOrder ); d->list->setUpdatesEnabled( true ); } void DeleteVariableDlg::deleteVar() { if ( d->list->selectedItems().count() > 0 ) { QTreeWidgetItem * item = d->list->selectedItems()[0]; d->eval->remove( item->text( 0 ) ); delete item; } } speedcrunch-0.10.1/src/gui/editor.cpp0000644000175000001440000011431711015364561016634 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2004,2005 Ariya Hidayat // Copyright (C) 2005-2006 Johan Thelin // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "editor.hxx" #include "base/constants.hxx" #include "base/evaluator.hxx" #include "base/functions.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include class EditorHighlighter : public QSyntaxHighlighter { public: EditorHighlighter( Editor * e ): QSyntaxHighlighter( e ), editor( e ) {} void highlightBlock( const QString & text ) { if ( ! editor->syntaxHighlight() ) { setFormat( 0, text.length(), editor->palette().text().color() ); return; } Tokens tokens = editor->evaluator()->scan( text ); for ( int i = 0; i < tokens.count(); i++ ) { Token & token = tokens[i]; QString text = token.text().toLower(); QColor color; QStringList fnames; switch ( token.type() ) { case Token::stxOperator: case Token::stxUnknown: case Token::stxOpenPar: case Token::stxClosePar: color = QApplication::palette().windowText().color(); break; case Token::stxNumber: case Token::stxSep: color = editor->highlightColor( Editor::Number ); break; case Token::stxIdentifier: color = editor->highlightColor( Editor::Variable ); fnames = editor->functions()->functionNames(); for ( int i = 0; i < fnames.count(); i++ ) { if ( fnames[i].toLower() == text ) color = editor->highlightColor( Editor::Function ); } break; default: break; }; if ( token.pos() >= 0 ) setFormat( token.pos(), token.text().length(), color ); } } private: Editor * editor; }; struct Editor::Private { bool ansAvailable; bool autoCalcEnabled; QTimer * autoCalcTimer; QTimer * autoCalcSelTimer; bool autoCompleteEnabled; EditorCompletion * completion; QTimer * completionTimer; ConstantCompletion * constantCompletion; int precision; Constants * constants; Evaluator * eval; Functions * functions; char format; QStringList history; QStringList historyResults; EditorHighlighter * highlighter; HighlightScheme scheme; int index; QTimer * matchingTimer; char radixChar; bool syntaxHighlightEnabled; QMap highlightColors; QList generateColors( const QColor & bg, const QColor & fg, int noColors ); }; QList Editor::Private::generateColors( const QColor & bg, const QColor & fg, int noColors ) { QList cols; const int HUE_BASE = (bg.hue() == -1) ? 90 : bg.hue(); int h, s, v; for ( int i = 0; i < noColors; i++ ) { // generate "normal" colors h = int( HUE_BASE + (360.0 / noColors * i) ) % 360; s = 240; v = int( qMax( bg.value(), fg.value() ) * 0.85 ); // adjust particular cases const int M = 35; if ( (h < bg.hue() + M && h > bg.hue() - M ) || (h < fg.hue() + M && h > fg.hue() - M ) ) { h = ((bg.hue() + fg.hue()) / (i+1) ) % 359; s = ((bg.saturation() + fg.saturation() + 2*i) / 2 ) % 255; v = ((bg.value() + fg.value() + 2*i) / 2 ) % 255; } // insert into result list cols.append( QColor::fromHsv( h, s, v ) ); } return cols; } Editor::Editor( Evaluator * e, Functions * f, Constants * c, char format, int precision, char radixChar, QWidget * parent ) : QTextEdit( parent ), d( new Editor::Private ) { if ( radixChar == 'C' ) d->radixChar = QLocale().decimalPoint().toAscii(); else d->radixChar = radixChar; d->format = format; d->precision = precision; d->eval = e; d->functions = f; d->constants = c; d->index = 0; d->autoCompleteEnabled = true; d->completion = new EditorCompletion( this ); d->constantCompletion = 0; d->completionTimer = new QTimer( this ); d->autoCalcEnabled = true; d->syntaxHighlightEnabled = true; d->highlighter = new EditorHighlighter( this ); d->autoCalcTimer = new QTimer( this ); d->autoCalcSelTimer = new QTimer( this ); d->matchingTimer = new QTimer( this ); d->ansAvailable = false; d->scheme = Editor::AutoScheme; setHighlightScheme( Editor::AutoScheme ); setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ); setLineWrapMode( QTextEdit::NoWrap ); setTabChangesFocus( true ); setWordWrapMode( QTextOption::NoWrap ); setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); setAcceptRichText( false ); setAutoFormatting( QTextEdit::AutoNone ); connect( d->autoCalcTimer, SIGNAL( timeout() ), SLOT( autoCalc() ) ); connect( d->autoCalcSelTimer, SIGNAL( timeout() ), SLOT( autoCalcSelection() ) ); connect( d->completion, SIGNAL( selectedCompletion( const QString & ) ), SLOT( autoComplete( const QString & ) ) ); connect( d->completionTimer, SIGNAL( timeout() ), SLOT( triggerAutoComplete() ) ); connect( d->matchingTimer, SIGNAL( timeout() ), SLOT( doMatchingPar() ) ); connect( this, SIGNAL( selectionChanged() ), SLOT( startSelAutoCalcTimer() ) ); connect( this, SIGNAL( textChanged() ), SLOT( checkAutoCalc() ) ); connect( this, SIGNAL( textChanged() ), SLOT( checkAutoComplete() ) ); connect( this, SIGNAL( textChanged() ), SLOT( checkMatching() ) ); adjustSize(); } Editor::~Editor() { delete d; } QString Editor::text() const { return toPlainText(); } char Editor::radixChar() const { return d->radixChar; } void Editor::setText( const QString & str ) { setPlainText( str ); } void Editor::insert( const QString & str ) { insertPlainText( str ); } void Editor::setRadixChar( char c ) { if ( c == 'C' ) c = QLocale().decimalPoint().toAscii(); if ( d->radixChar != c ) { d->radixChar = c; if ( syntaxHighlight() ) d->highlighter->rehighlight(); } } void Editor::doBackspace() { QTextCursor cursor = textCursor(); cursor.deletePreviousChar(); setTextCursor( cursor ); } Constants * Editor::constants() const { return d->constants; } Evaluator * Editor::evaluator() const { return d->eval; } Functions * Editor::functions() const { return d->functions; } int Editor::cursorPosition() const { return textCursor().position(); } void Editor::setCursorPosition( int pos ) { QTextCursor cursor = textCursor(); cursor.setPosition( pos ); setTextCursor( cursor ); } QSize Editor::sizeHint() const { ensurePolished(); QFontMetrics fm = fontMetrics(); int h = qMax( fm.lineSpacing() + 2, 14 ); int w = fm.width( 'x' ) * 20; int m = frameWidth() * 2; return style()->sizeFromContents( QStyle::CT_LineEdit, 0, QSize( w + m, h + m ). expandedTo( QApplication::globalStrut() ), this ); } QStringList Editor::history() const { return d->history; } QStringList Editor::historyResults() const { return d->historyResults; } void Editor::setHistory( const QStringList & h ) { d->history = h; d->index = d->history.count(); } void Editor::setHistoryResults( const QStringList & results ) { d->historyResults = results; } void Editor::appendHistory( const QStringList & h, const QStringList & r ) { d->history += h; d->historyResults += r; d->index = d->history.count(); } void Editor::clearHistory() { d->history.clear(); d->historyResults.clear(); } bool Editor::autoCompleteEnabled() const { return d->autoCompleteEnabled; } void Editor::setAutoCompleteEnabled( bool enable ) { d->autoCompleteEnabled = enable; } bool Editor::autoCalcEnabled() const { return d->autoCalcEnabled; } void Editor::setAutoCalcEnabled( bool enable ) { d->autoCalcEnabled = enable; } void Editor::setFormat( char format ) { d->format = format; } void Editor::setPrecision( int digits ) { d->precision = digits; } void Editor::appendHistory( const QString & expression, const QString & result ) { if ( expression.isEmpty() || result.isEmpty() ) return; d->history.append( expression ); d->historyResults.append( result ); d->index = d->history.count() - 1; } void Editor::checkAutoComplete() { if ( ! d->autoCompleteEnabled ) return; d->completionTimer->stop(); d->completionTimer->setSingleShot( true ); d->completionTimer->start( 500 ); } void Editor::checkMatching() { if ( ! d->syntaxHighlightEnabled ) return; d->matchingTimer->stop(); d->matchingTimer->setSingleShot( true ); d->matchingTimer->start( 200 ); } void Editor::checkAutoCalc() { // Calc-As-You-Type if ( ! d->autoCalcEnabled ) return; d->autoCalcTimer->stop(); d->autoCalcTimer->setSingleShot( true ); d->autoCalcTimer->start( 1000 ); emit autoCalcDisabled(); } void Editor::startSelAutoCalcTimer() { if ( ! d->autoCalcEnabled ) return; d->autoCalcSelTimer->stop(); d->autoCalcSelTimer->setSingleShot( true ); d->autoCalcSelTimer->start( 1000 ); } void Editor::doMatchingPar() { // clear previous setExtraSelections( QList() ); if ( ! d->syntaxHighlightEnabled ) return; doMatchingLeft(); doMatchingRight(); } void Editor::doMatchingLeft() { // tokenize the expression int curPos = textCursor().position(); // check for right par QString subtext = text().left( curPos ); Tokens tokens = d->eval->scan( subtext ); if ( ! tokens.valid() ) return; if ( tokens.count() < 1 ) return; Token lastToken = tokens[tokens.count()-1]; // right par ? //if( lastToken.isOperator() ) // refty //if( lastToken.asOperator() == Token::RightPar ) if( lastToken.type() == Token::stxClosePar ) if( lastToken.pos() == curPos-1 ) { // find the matching left par unsigned par = 1; int k = 0; Token matchToken; int matchPos = -1; /* for( k = tokens.count()-2; k >= 0; k-- ) //refty { if( par < 1 ) break; Token matchToken = tokens[k]; if( matchToken.isOperator() ) { if( matchToken.asOperator() == Token::RightPar ) par++; if( matchToken.asOperator() == Token::LeftPar ) par--; if( par == 0 ) matchPos = matchToken.pos(); } }*/ for ( k = tokens.count() - 2; k >= 0 && par > 0; k-- ) { Token matchToken = tokens[k]; switch ( matchToken.type() ) { case Token::stxOpenPar : --par; break; case Token::stxClosePar: ++par; break; default:; } matchPos = matchToken.pos(); } // if( matchPos >= 0 ) //refty if ( par == 0 ) { ExtraSelection hilite1; hilite1.cursor = textCursor(); hilite1.cursor.setPosition( matchPos ); hilite1.cursor.setPosition( matchPos + 1, QTextCursor::KeepAnchor ); hilite1.format.setBackground( highlightColor( Editor::MatchedPar ) ); ExtraSelection hilite2; hilite2.cursor = textCursor(); hilite2.cursor.setPosition( lastToken.pos() ); hilite2.cursor.setPosition( lastToken.pos() + 1, QTextCursor::KeepAnchor ); hilite2.format.setBackground( highlightColor( Editor::MatchedPar ) ); QList extras; extras << hilite1; extras << hilite2; setExtraSelections( extras ); } } } void Editor::doMatchingRight() { // tokenize the expression int curPos = textCursor().position(); // check for left par QString subtext = text().right( text().length() - curPos ); Tokens tokens = d->eval->scan( subtext ); if ( ! tokens.valid() ) return; if ( tokens.count() < 1 ) return; Token firstToken = tokens[0]; // left par ? //if( firstToken.isOperator() ) //refty //if( firstToken.asOperator() == Token::LeftPar ) if ( firstToken.type() == Token::stxOpenPar ) if ( firstToken.pos() == 0 ) { // find the matching right par unsigned par = 1; int k = 0; Token matchToken; int matchPos = -1; // for( k = 1; k < tokens.count(); k++ ) //refty // { // if( par < 1 ) break; // Token matchToken = tokens[k]; // if( matchToken.isOperator() ) // { // if( matchToken.asOperator() == Token::LeftPar ) // par++; // if( matchToken.asOperator() == Token::RightPar ) // par--; // if( par == 0 ) matchPos = matchToken.pos(); // } // } for ( k = 1; k < tokens.count() && par > 0; k++ ) //refty { Token matchToken = tokens[k]; switch ( matchToken.type() ) { case Token::stxOpenPar : ++par; break; case Token::stxClosePar: --par; break; default:; } matchPos = matchToken.pos(); } // if( matchPos >= 0 ) //refty if ( par == 0 ) { ExtraSelection hilite1; hilite1.cursor = textCursor(); hilite1.cursor.setPosition( curPos+matchPos ); hilite1.cursor.setPosition( curPos+matchPos + 1, QTextCursor::KeepAnchor ); hilite1.format.setBackground( highlightColor( Editor::MatchedPar ) ); ExtraSelection hilite2; hilite2.cursor = textCursor(); hilite2.cursor.setPosition( curPos+firstToken.pos() ); hilite2.cursor.setPosition( curPos+firstToken.pos() + 1, QTextCursor::KeepAnchor ); hilite2.format.setBackground( highlightColor( Editor::MatchedPar ) ); QList extras; extras << hilite1; extras << hilite2; setExtraSelections( extras ); } } } void Editor::triggerAutoComplete() { if ( ! d->autoCompleteEnabled ) return; // tokenize the expression (don't worry, this is very fast) int curPos = textCursor().position(); QString subtext = text().left( curPos ); Tokens tokens = d->eval->scan( subtext ); if ( ! tokens.valid() ) return; if ( tokens.count() < 1 ) return; Token lastToken = tokens[ tokens.count()-1 ]; // last token must be an identifier if ( ! lastToken.isIdentifier() ) return; QString id = lastToken.text(); if ( id.length() < 1 ) return; // no space after identifier if ( lastToken.pos() + id.length() < subtext.length() ) return; // find matches in function names QStringList fnames = d->functions->functionNames(); QStringList choices; for ( int i = 0; i < fnames.count(); i++ ) { if ( fnames[i].startsWith( id, Qt::CaseInsensitive ) ) { QString str = fnames[i]; //::Function * f = Functions::self()->function( str ); ::Function * f = d->functions->function( str ); if ( f ) str.append( ':' ).append( f->description() ); choices.append( str ); } } choices.sort(); // find matches in variables names QStringList vchoices; for ( int i = 0; i < d->eval->variables().count(); i++ ) if ( d->eval->variables()[i].name.startsWith( id, Qt::CaseInsensitive ) ) vchoices.append( QString("%1: %2"). arg( d->eval->variables().at(i).name ). arg( formatNumber( d->eval->variables().at(i).value ) ) ); vchoices.sort(); choices += vchoices; // no match, don't bother with completion if ( ! choices.count() ) return; // single perfect match, no need to give choices if ( choices.count() == 1 ) if ( choices[0].toLower() == id.toLower() ) return; // one match, complete it for the user if ( choices.count() == 1 ) { QString str = choices[0].split( ':' )[0]; str = str.remove( 0, id.length() ); int curPos = textCursor().position(); if ( textCursor().selectionStart() == textCursor().selectionEnd() ) { blockSignals( true ); QTextCursor cursor = textCursor(); cursor.clearSelection(); cursor.insertText( str ); cursor.setPosition( curPos ); cursor.setPosition( curPos+str.length(), QTextCursor::KeepAnchor ); setTextCursor( cursor ); blockSignals( false ); } return; } // present the user with completion choices d->completion->showCompletion( choices ); } void Editor::autoComplete( const QString & item ) { if ( ! d->autoCompleteEnabled || item.isEmpty() ) return; int curPos = textCursor().position(); QString subtext = text().left( curPos ); Tokens tokens = d->eval->scan( subtext ); if ( ! tokens.valid() || tokens.count() < 1 ) return; Token lastToken = tokens[tokens.count()-1]; if ( ! lastToken.isIdentifier() ) return; QStringList str = item.split( ':' ); blockSignals( true ); QTextCursor cursor = textCursor(); cursor.setPosition( lastToken.pos() ); cursor.setPosition( lastToken.pos() + lastToken.text().length(), QTextCursor::KeepAnchor ); setTextCursor( cursor ); insert( str[0] ); blockSignals( false ); } void Editor::autoCalc() { if ( ! d->autoCalcEnabled ) return; QString str = d->eval->autoFix( text() ); if ( str.isEmpty() ) return; // very short (just one token) and still no calculation, then skip if ( ! d->ansAvailable ) { Tokens tokens = d->eval->scan( text() ); if ( tokens.count() < 2 ) return; } // too short even after autofix ? do not bother either... Tokens tokens = d->eval->scan( str ); if ( tokens.count() < 2 ) return; // strip off assignment operator, e.g. "x=1+2" becomes "1+2" only // the reason is that we want only to evaluate (on the fly) the expression, // not to update (put the result in) the variable //if( tokens.count() > 2 ) // reftk //if( tokens[0].isIdentifier() ) //if( tokens[1].asOperator() == Token::Equal ) // str.remove( 0, tokens[1].pos()+1 ); // same reason as above, do not update "ans" d->eval->setExpression( str ); HNumber num = d->eval->evalNoAssign(); if ( d->eval->error().isEmpty() ) { QString ss = QString( tr( "Current result: %1" ) .arg( formatNumber( num ) ) ); emit autoCalcEnabled( ss ); } else { // invalid expression emit autoCalcDisabled(); } } void Editor::autoCalcSelection() { if ( ! d->autoCalcEnabled ) return; QString str = d->eval->autoFix( textCursor().selectedText() ); if ( str.isEmpty() ) return; // very short (just one token) and still no calculation, then skip if ( ! d->ansAvailable ) { Tokens tokens = d->eval->scan( text() ); if ( tokens.count() < 2 ) return; } // too short even after autofix ? do not bother either... Tokens tokens = d->eval->scan( str ); if ( tokens.count() < 2 ) return; // strip off assignment operator, e.g. "x=1+2" becomes "1+2" only // the reason is that we want only to evaluate (on the fly) the expression, // not to update (put the result in) the variable //if( tokens.count() > 2 ) // reftk //if( tokens[0].isIdentifier() ) //if( tokens[1].asOperator() == Token::Equal ) // str.remove( 0, tokens[1].pos()+1 ); // same reason as above, do not update "ans" d->eval->setExpression( str ); HNumber num = d->eval->evalNoAssign(); if ( d->eval->error().isEmpty() ) { QString ss = QString( tr( "Selection result: %1" ) .arg( formatNumber( num ) ) ); emit autoCalcEnabled( ss ); } else { // invalid expression emit autoCalcDisabled(); } } void Editor::insertConstant( const QString & c ) { QString s( c ); if ( d->radixChar == ',' ) s.replace( '.', ',' ); if ( ! c.isNull() ) insert( s ); if ( d->constantCompletion ) { disconnect( d->constantCompletion ); d->constantCompletion->deleteLater(); d->constantCompletion = 0; } } void Editor::cancelConstantCompletion() { if ( d->constantCompletion ) { disconnect( d->constantCompletion ); d->constantCompletion->deleteLater(); d->constantCompletion = 0; } } void Editor::evaluate() { triggerEnter(); } QString Editor::formatNumber( const HNumber & value ) const { char * str = HMath::format( value, d->format, d->precision ); QString s = QString::fromLatin1( str ); if ( d->radixChar == ',' ) s.replace( '.', ',' ); free( str ); return s; } void Editor::historyBack() { if ( d->history.count() ) { d->index--; if ( d->index < 0 ) d->index = 0; setText( d->history[d->index] ); QTextCursor cursor = textCursor(); cursor.movePosition( QTextCursor::EndOfBlock ); setTextCursor( cursor ); ensureCursorVisible(); return; } } void Editor::historyForward() { if ( d->history.count() ) { d->index++; if( d->index >= (int) d->history.count() ) d->index = d->history.count() - 1; setText( d->history[d->index] ); QTextCursor cursor = textCursor(); cursor.movePosition( QTextCursor::EndOfBlock ); setTextCursor( cursor ); return; } } void Editor::triggerEnter() { d->completionTimer->stop(); d->matchingTimer->stop(); d->autoCalcTimer->stop(); d->autoCalcSelTimer->stop(); emit returnPressed(); } void Editor::keyPressEvent( QKeyEvent * e ) { if ( e->key() == Qt::Key_Enter ) { QTimer::singleShot( 0, this, SLOT( triggerEnter() ) ); e->accept(); return; } if ( e->key() == Qt::Key_Return ) { QTimer::singleShot( 0, this, SLOT( triggerEnter() ) ); e->accept(); return; } if ( e->key() == Qt::Key_Up ) { historyBack(); e->accept(); } if ( e->key() == Qt::Key_Down ) { historyForward(); e->accept(); } if ( e->key() == Qt::Key_Left ) checkMatching(); if ( e->key() == Qt::Key_Right ) checkMatching(); if ( e->key() == Qt::Key_Home ) checkMatching(); if ( e->key() == Qt::Key_End ) checkMatching(); if ( e->key() == Qt::Key_Space && e->modifiers() == Qt::ControlModifier && ! d->constantCompletion ) { d->constantCompletion = new ConstantCompletion( this ); connect( d->constantCompletion, SIGNAL( selectedCompletion( const QString & ) ), this, SLOT( insertConstant( const QString & ) ) ); connect( d->constantCompletion, SIGNAL( canceledCompletion() ), this, SLOT( cancelConstantCompletion() ) ); d->constantCompletion->showCompletion(); e->accept(); return; } QTextEdit::keyPressEvent( e ); } void Editor::wheelEvent( QWheelEvent * e ) { if ( e->delta() > 0 ) historyBack(); else if ( e->delta() < 0 ) historyForward(); e->accept(); } void Editor::setSyntaxHighlight( bool enable ) { d->syntaxHighlightEnabled = enable; d->highlighter->rehighlight(); } void Editor::setHighlightScheme( Editor::HighlightScheme hs ) { d->scheme = hs; if ( hs == Editor::AutoScheme ) { const int NO_COLORS = 3; QColor bg( palette().color( QPalette::Base ) ); QColor fg( palette().color( QPalette::Text ) ); QList list = d->generateColors( bg, fg, NO_COLORS ); for ( int i = 0; i < NO_COLORS; i++ ) d->highlightColors[static_cast( i )] = list[i]; // generate special case matched parenthesis int h = ((bg.hue() + fg.hue()) / 2 ) % 359; int s = ((bg.saturation() + fg.saturation()) / 2 ) % 255; int v = ((bg.value() + fg.value()) / 2 ) % 255; d->highlightColors[Editor::MatchedPar] = QColor::fromHsv( h, s, v ); } } bool Editor::syntaxHighlight() const { return d->syntaxHighlightEnabled; } void Editor::setHighlightColor( ColorType type, QColor color ) { d->highlightColors[type] = color; d->highlighter->rehighlight(); doMatchingPar(); } QColor Editor::highlightColor( ColorType type ) { return d->highlightColors[ type ]; } void Editor::setAnsAvailable( bool avail ) { d->ansAvailable = avail; } // typically called by the main window, just after the user evaluates something // useful so we don't pop up the autocalc tooltip again void Editor::stopAutoCalc() { d->autoCalcTimer->stop(); d->autoCalcSelTimer->stop(); emit autoCalcDisabled(); } void Editor::stopAutoComplete() { d->completionTimer->stop(); d->completion->selectItem( QString() ); // WORKAROUND 76 d->completion->doneCompletion(); setFocus(); } // uncomment to activate fade-away effect when the completion pop-up disappears //#define COMPLETION_FADE_EFFECT struct EditorCompletion::Private { Editor * editor; #ifdef COMPLETION_FADE_EFFECT QTimeLine * fader; #endif QTreeWidget * popup; }; EditorCompletion::EditorCompletion( Editor * editor ) : QObject( editor ), d( new EditorCompletion::Private ) { d->editor = editor; d->popup = new QTreeWidget; d->popup->setFrameShape( QFrame::NoFrame ); d->popup->setColumnCount( 2 ); d->popup->setRootIsDecorated( false ); d->popup->header()->hide(); d->popup->setEditTriggers( QTreeWidget::NoEditTriggers ); d->popup->setSelectionBehavior( QTreeWidget::SelectRows ); d->popup->setMouseTracking( true ); d->popup->installEventFilter( this ); connect( d->popup, SIGNAL( itemClicked( QTreeWidgetItem *, int ) ), SLOT( doneCompletion() ) ); d->popup->hide(); d->popup->setParent( 0, Qt::Popup ); d->popup->setFocusPolicy( Qt::NoFocus ); d->popup->setFocusProxy( editor ); d->popup->setFrameStyle( QFrame::Box | QFrame::Plain ); #ifdef COMPLETION_FADE_EFFECT d->fader = new QTimeLine( 500, this ); d->fader->setFrameRange( 0, 100 ); d->fader->setCurveShape( QTimeLine::EaseInCurve ); connect( d->fader, SIGNAL( frameChanged( int ) ), SLOT( fade( int ) ) ); #endif } EditorCompletion::~EditorCompletion() { delete d->popup; delete d; } bool EditorCompletion::eventFilter( QObject * obj, QEvent * ev ) { if ( obj == d->popup ) { if ( ev->type() == QEvent::KeyPress ) { QKeyEvent * ke = (QKeyEvent *) ev; if ( ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Tab ) { doneCompletion(); return true; } else if ( ke->key() == Qt::Key_Up || ke->key() == Qt::Key_Down || ke->key() == Qt::Key_Home || ke->key() == Qt::Key_End || ke->key() == Qt::Key_PageUp || ke->key() == Qt::Key_PageDown ) { return false; } d->popup->hide(); d->editor->setFocus(); if ( ke->key() != Qt::Key_Escape ) QApplication::sendEvent( d->editor, ev ); return true; } else if ( ev->type() == QEvent::MouseButtonPress ) { d->popup->hide(); d->editor->setFocus(); return true; } } return false; } void EditorCompletion::doneCompletion() { #ifdef COMPLETION_FADE_EFFECT d->fader->start(); QTimer::singleShot( 750, d->popup, SLOT( hide() ) ); // sentinel #else d->popup->hide(); #endif d->editor->setFocus(); QTreeWidgetItem * item = d->popup->currentItem(); emit selectedCompletion( item ? item->text( 0 ) : QString() ); } void EditorCompletion::showCompletion( const QStringList & choices ) { if ( ! choices.count() ) return; #ifdef COMPLETION_FADE_EFFECT d->fader->stop(); fade( 0 ); #endif d->popup->setUpdatesEnabled( false ); d->popup->clear(); for ( int i = 0; i < choices.count(); i++ ) { QTreeWidgetItem * item = new QTreeWidgetItem( d->popup, choices[i].split( ':' ) ); if ( item && d->editor->layoutDirection() == Qt::RightToLeft ) item->setTextAlignment( 0, Qt::AlignRight ); } d->popup->sortItems( 0, Qt::AscendingOrder ); d->popup->sortItems( 1, Qt::AscendingOrder ); d->popup->setCurrentItem( d->popup->topLevelItem( 0 ) ); d->popup->adjustSize(); d->popup->setUpdatesEnabled( true ); // size of the pop-up d->popup->adjustSize(); int h = d->popup->sizeHintForRow( 0 ) * qMin(7, choices.count()) + 3; int w = d->popup->width(); d->popup->resize( w, h ); // position, reference is editor's cursor position in global coord QFontMetrics fm( d->editor->font() ); int curPos = d->editor->textCursor().position(); int pixelsOffset = fm.width( d->editor->text(), curPos ); QPoint pos = d->editor->mapToGlobal( QPoint( pixelsOffset, d->editor->height() ) ); // if popup is partially invisible, move to other position const QRect screen = QApplication::desktop()->availableGeometry( d->editor ); if ( pos.y() + h > screen.y() + screen.height() ) pos.setY( pos.y() - h - d->editor->height() ); if ( pos.x() + w > screen.x() + screen.width() ) pos.setX( screen.x() + screen.width() - w ); d->popup->move( pos ); d->popup->setFocus(); d->popup->show(); } void EditorCompletion::selectItem( const QString & item ) // WORKAROUND 76 { if ( item.isNull() ) { d->popup->setCurrentItem( 0 ); } else { QList targets = d->popup->findItems( item, Qt::MatchExactly ); if ( targets.count() > 0 ) d->popup->setCurrentItem( targets[0] ); } } void EditorCompletion::fade( int v ) { d->popup->setWindowOpacity( (qreal) (100 - v) / 100 ); } struct ConstantCompletion::Private { QTreeWidget * categoryList; QList constants; QTreeWidget * constantList; Editor * editor; QString lastCategory; QFrame * popup; QTimeLine * slider; }; ConstantCompletion::ConstantCompletion( Editor * editor ) : QObject( editor ), d( new ConstantCompletion::Private ) { d->editor = editor; d->popup = new QFrame; d->popup->setParent( 0, Qt::Popup ); d->popup->setFocusPolicy( Qt::NoFocus ); d->popup->setFocusProxy( editor ); d->popup->setFrameStyle( QFrame::Box | QFrame::Plain ); d->categoryList = new QTreeWidget( d->popup ); d->categoryList->setFrameShape( QFrame::NoFrame ); d->categoryList->setColumnCount( 1 ); d->categoryList->setRootIsDecorated( false ); d->categoryList->header()->hide(); d->categoryList->setEditTriggers( QTreeWidget::NoEditTriggers ); d->categoryList->setSelectionBehavior( QTreeWidget::SelectRows ); d->categoryList->setMouseTracking( true ); d->categoryList->installEventFilter( this ); d->categoryList->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded ); connect( d->categoryList, SIGNAL( itemClicked( QTreeWidgetItem *, int ) ), this, SLOT( showConstants() ) ); d->constantList = new QTreeWidget( d->popup ); d->constantList->setFrameShape( QFrame::NoFrame ); d->constantList->setColumnCount( 2 ); d->constantList->setColumnHidden( 1, true ); d->constantList->setRootIsDecorated( false ); d->constantList->header()->hide(); d->constantList->setEditTriggers( QTreeWidget::NoEditTriggers ); d->constantList->setSelectionBehavior( QTreeWidget::SelectRows ); d->constantList->setMouseTracking( true ); d->constantList->installEventFilter( this ); d->constantList->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded ); // FIXME: why does it crash when clicking a constant description? connect( d->constantList, SIGNAL( itemClicked( QTreeWidgetItem *, int ) ), this, SLOT( doneCompletion() ) ); d->slider = new QTimeLine( 250, d->popup ); d->slider->setCurveShape( QTimeLine::EaseInCurve ); connect( d->slider, SIGNAL( frameChanged( int ) ), this, SLOT( slide( int ) ) ); Constants * ct = d->editor->constants(); d->constants = ct->constantList(); // populate categories QStringList str; str << tr( "All" ); QTreeWidgetItem * all = new QTreeWidgetItem( d->categoryList, str ); for ( int k = 0; k < ct->categoryList().count(); k++ ) { str.clear(); str << ct->categoryList().at( k ); new QTreeWidgetItem( d->categoryList, str ); } d->categoryList->setCurrentItem( all ); // populate constants d->lastCategory = tr( "All" ); for ( int k = 0; k < ct->constantList().count(); k++ ) { QStringList str; str << ct->constantList().at( k ).name; str << ct->constantList().at( k ).name.toUpper(); new QTreeWidgetItem( d->constantList, str ); } d->constantList->sortItems( 0, Qt::AscendingOrder ); // find size, the biggest between both d->constantList->resizeColumnToContents( 0 ); d->categoryList->resizeColumnToContents( 0 ); int ww = qMax( d->constantList->width(), d->categoryList->width() ); int h1 = d->constantList->sizeHintForRow( 0 ) * qMin(7, d->constants.count()) + 3; int h2 = d->categoryList->sizeHintForRow( 0 ) * qMin(7, ct->categoryList().count()) + 3; int hh = qMax( h1, h2 ); ww += 200; // extra space (FIXME scrollbar size?) // adjust dimensions d->popup->resize( ww, hh ); d->constantList->resize( ww, hh ); d->categoryList->resize( ww, hh ); } ConstantCompletion::~ConstantCompletion() { delete d->popup; delete d; d->editor->setFocus(); } void ConstantCompletion::showCategory() { d->slider->setFrameRange( d->popup->width(), 0 ); d->slider->stop(); d->slider->start(); d->categoryList->setFocus(); } void ConstantCompletion::showConstants() { d->slider->setFrameRange( 0, d->popup->width() ); d->slider->stop(); d->slider->start(); d->constantList->setFocus(); QString chosenCategory; if ( d->categoryList->currentItem() ) chosenCategory = d->categoryList->currentItem()->text( 0 ); if ( d->lastCategory == chosenCategory ) return; d->constantList->clear(); for ( int k = 0; k < d->constants.count(); k++ ) { QStringList str; str << d->constants[k].name; str << d->constants[k].name.toUpper(); bool include = (chosenCategory == tr( "All" )) ? true : d->constants[k].categories.contains( chosenCategory ); if ( ! include ) continue; new QTreeWidgetItem( d->constantList, str ); } d->constantList->sortItems( 0, Qt::AscendingOrder ); d->constantList->setCurrentItem( d->constantList->itemAt( 0, 0 ) ); d->lastCategory = chosenCategory; } bool ConstantCompletion::eventFilter( QObject * obj, QEvent * ev ) { if ( ev->type() == QEvent::Hide ) { emit canceledCompletion(); return true; } if ( obj == d->constantList ) { if ( ev->type() == QEvent::KeyPress ) { QKeyEvent * ke = (QKeyEvent *) ev; if ( ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Tab ) { doneCompletion(); return true; } else if ( ke->key() == Qt::Key_Left ) { showCategory(); return true; } else if ( ke->key() == Qt::Key_Right || ke->key() == Qt::Key_Up || ke->key() == Qt::Key_Down || ke->key() == Qt::Key_Home || ke->key() == Qt::Key_End || ke->key() == Qt::Key_PageUp || ke->key() == Qt::Key_PageDown ) { return false; } if ( ke->key() != Qt::Key_Escape ) QApplication::sendEvent( d->editor, ev ); emit canceledCompletion(); return true; } } if ( obj == d->categoryList ) { if ( ev->type() == QEvent::KeyPress ) { QKeyEvent * ke = (QKeyEvent *) ev; if ( ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Right ) { showConstants(); return true; } else if ( ke->key() == Qt::Key_Up || ke->key() == Qt::Key_Down || ke->key() == Qt::Key_Home || ke->key() == Qt::Key_End || ke->key() == Qt::Key_PageUp || ke->key() == Qt::Key_PageDown ) { return false; } if ( ke->key() != Qt::Key_Escape ) QApplication::sendEvent( d->editor, ev ); emit canceledCompletion(); return true; } } return false; } void ConstantCompletion::doneCompletion() { d->editor->setFocus(); QTreeWidgetItem * item = 0; item = d->constantList->currentItem(); QString c; if ( item ) for ( int k = 0; k < d->constants.count(); k++ ) if ( d->constants[k].name == item->text( 0 ) ) { c = d->constants[k].value; break; } emit selectedCompletion( item ? c : QString() ); } void ConstantCompletion::showCompletion() { // position, reference is editor's cursor position in global coord QFontMetrics fm( d->editor->font() ); int curPos = d->editor->textCursor().position(); int pixelsOffset = fm.width( d->editor->text(), curPos ); QPoint pos = d->editor->mapToGlobal( QPoint( pixelsOffset, d->editor->height() ) ); int h = d->popup->height(); int w = d->popup->width(); // if popup is partially invisible, move to other position const QRect screen = QApplication::desktop()->availableGeometry( d->editor ); if ( pos.y() + h > screen.y() + screen.height() ) pos.setY( pos.y() - h - d->editor->height() ); if ( pos.x() + w > screen.x() + screen.width() ) pos.setX( screen.x() + screen.width() - w ); // start with category d->categoryList->setFocus(); slide( 0 ); d->popup->move( pos ); d->popup->show(); } void ConstantCompletion::slide( int v ) { d->categoryList->move( -v, 0 ); d->constantList->move( d->popup->width() - v, 0 ); } speedcrunch-0.10.1/src/gui/aboutbox.cpp0000644000175000001440000003116311015364561017166 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004-2006 Ariya Hidayat // Copyright (C) 2005-2006 Johan Thelin // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "aboutbox.hxx" #include #define MAKE_STRING(a) DO_MAKE_STRING(a) #define DO_MAKE_STRING(a) # a class MarqueeTextPrivate { public: QTextEdit * editor; QTextDocument * doc; QPixmap * buffer; unsigned pos; unsigned scrollStep; unsigned scrollTick; unsigned sideMargin; }; MarqueeText::MarqueeText( QWidget * parent, const char * name ): QFrame( parent ) { d = new MarqueeTextPrivate; d->scrollStep = 1; d->scrollTick = 40; d->sideMargin = 20; d->buffer = new QPixmap; d->editor = new QTextEdit( this ); d->editor->hide(); d->doc = d->editor->document(); d->pos = 50; setFrameStyle( Panel | Sunken ); setLineWidth( 1 ); QTimer * scrollTimer = new QTimer( this ); connect( scrollTimer, SIGNAL(timeout()), this, SLOT(scroll()) ); scrollTimer->start( d->scrollTick ); setBackgroundRole( QPalette::Base ); } MarqueeText::~MarqueeText() { delete d->buffer; delete d; } QSizePolicy MarqueeText::sizePolicy() const { return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); } void MarqueeText::setText( const QString & text ) { d->doc->clear(); d->doc->setHtml( text ); layout(); d->pos = height(); update(); } void MarqueeText::paintEvent( QPaintEvent * e ) { QPainter painter( this ); painter.fillRect( this->rect(), painter.background().color() ); painter.end(); QFrame::paintEvent( e ); if( d->buffer ) { QPainter p( this ); QPixmap pix = d->buffer->copy(); QRegion clip( 2, 2, (width() - 4), (height() - 4) ); p.setClipRegion( clip ); p.drawPixmap( 0, d->pos, pix ); } } void MarqueeText::resizeEvent( QResizeEvent * e ) { layout(); e->accept(); update(); } void MarqueeText::scroll() { d->pos -= d->scrollStep; int offset = d->pos + d->buffer->height(); if ( offset < 0 ) d->pos = height() + 2 * d->scrollStep; update(); } void MarqueeText::layout() { QList layouts; int leading = fontMetrics().leading(); double lineWidth = width() - d->sideMargin; double hh = 10; int c = 0; // layouting lines, also to find total height QTextBlock block = d->doc->begin(); while ( block.isValid() ) { QTextLayout * textLayout = new QTextLayout( block ); layouts.append( textLayout ); textLayout->beginLayout(); while ( true ) { QTextLine line = textLayout->createLine(); if ( ! line.isValid() ) break; line.setLineWidth( lineWidth ); double x = (lineWidth - line.naturalTextWidth()) / 2; line.setPosition( QPointF( x - 3, hh ) ); hh += line.height() / 2; hh += leading; c++; } textLayout->endLayout(); block = block.next(); hh += 10; // paragraph-spacing } // recreate off-screen buffer QPixmap * oldbuf = d->buffer; d->buffer = 0; delete oldbuf; d->buffer = new QPixmap( QSize( int(lineWidth + 5), int(2 * hh + 50) ) ); d->buffer->fill( QBrush( palette().base() ).color() ); // paint the lines QPainter painter( d->buffer ); double ypos = 0; for ( int k = 0; k < layouts.count(); k++ ) { QTextLayout * textLayout = layouts[k]; if ( ! textLayout ) continue; for ( int i = 0; i < textLayout->lineCount(); ++i ) { QTextLine line = textLayout->lineAt( i ); QPointF pos = QPointF( (d->sideMargin / 2), ypos ); line.draw( & painter, pos, 0 ); ypos += line.height() / 2; ypos += leading; } ypos += 10; // paragraph-spacing } } AboutBox::AboutBox( QWidget * parent ) : QDialog( parent ) { setObjectName( "AboutBox" ); setWindowTitle( tr("About SpeedCrunch") ); QString website = "http://www.speedcrunch.org"; QLabel * infoLabel = new QLabel( this ); QString info = ""; info += tr("SpeedCrunch version %1").arg( MAKE_STRING(SPEEDCRUNCH_VERSION) ); info += "
"; info += QString( "%2" ).arg( website ).arg( website ); infoLabel->setText( info ); infoLabel->setOpenExternalLinks( true ); QLabel * iconLabel = new QLabel( this ); iconLabel->setPixmap( QPixmap( ":/crunch.png" ) ); iconLabel->setAlignment( Qt::AlignVCenter | Qt::AlignRight ); MarqueeText * marqueeText = new MarqueeText( this ); QString msg = "




"; msg += "

"; msg += tr( "SpeedCrunch version %1").arg( MAKE_STRING(SPEEDCRUNCH_VERSION) ); msg += "
"; #ifdef SPEEDCRUNCH_PORTABLE msg += "(Portable Edition)"; msg += "
"; #endif msg += "

"; const char * mainFmt = "

%1
%2"; msg += QString( mainFmt ).arg( tr("Based on original idea from") ).arg( "Roberto Alsina" ); msg += QString( mainFmt ).arg( tr("Original author") ).arg( "Ariya Hidayat" ); msg += QString( mainFmt ).arg( tr("Current maintainer") ).arg( "Helder Correia" ); msg += QString( mainFmt ).arg( tr("Developers") ).arg( "Alessandro Portale
" "Ariya Hidayat
" "Helder Correia
" "Johan Thelin
" "Petri Damstén
" "Wolf Lammen" ); msg += QString( mainFmt ).arg( tr("Special thanks to") ).arg( "Marco Wegner
" "Michael Pyne
" "Jonathan Avraham
" "Jonathan Riddell
" "Witold Wysota
" ); msg += QString( mainFmt ).arg( tr("Graphics") ).arg( "Kuswanto (Zeus)
" "Oxygen Project" ); msg += "

"; msg += QString( "%1
" ).arg( tr( "Thanks to" ) ); msg += "Alejandro Villarreal
" "Alexey Kouznetsov
" "Anders Lund
" "Bart Martens
" "Bernhard Schiffner
" "Damir Perisa
" "Derek O'Connor
" "Eugeniu Plamadeala
" "F Chris Carrera
" "Francesco di Cugno
" "Gary Cramblitt
" "Henrique Pinto
" "Jean-Remy Falleri
" "Lars Ivar Igesund
" "Maciek Borowka
" "Matthew J Smith
" "Melchior Franz
" "Mohamed Eldesoky
" "Philippe Fremy
" "Pieter Pareit
" "Roland \"liquidat\" Wolters
" "Sarah Hobbs
" "Stephan Binner
" "Thomas Luebking
" "Thomas Nagy
" "Vibet Alexis
" "Vladimir Pouzanov
" ; msg += QString( "%1
" ).arg( tr("...and many others...") ); msg += "

"; msg += "

"; msg += QString( "%1

" ).arg( tr("Translations") ); const char * i18nFmt = "%1
%2

"; msg += QString( i18nFmt ).arg( tr( "Argentinian Spanish" ) ).arg( "Lucas Sallovitz" ); msg += QString( i18nFmt ).arg( tr( "Basque" ) ).arg( "Iñigo Salvador Azurmendi" ); msg += QString( i18nFmt ).arg( tr( "Brazilian Portuguese" ) ).arg( "Fábio Margarido" ); msg += QString( i18nFmt ).arg( tr( "Catalan" ) ).arg( "Francesc Farfán" ); msg += QString( i18nFmt ).arg( tr( "Czech" ) ).arg( "Blond'ák" ); msg += QString( i18nFmt ).arg( tr( "Dutch" ) ).arg( "Maarten Fonville" ); msg += QString( i18nFmt ).arg( tr( "French" ) ).arg( "Grégory Treiber" ); msg += QString( i18nFmt ).arg( tr( "Finnish" ) ).arg( "J-P Nurmi" ); msg += QString( i18nFmt ).arg( tr( "German" ) ).arg( "Wolf Lammen" ); msg += QString( i18nFmt ).arg( tr( "Hebrew" ) ).arg( "Jonathan Avraham" ); msg += QString( i18nFmt ).arg( tr( "Indonesian" ) ).arg( "Yolla Indria" ); msg += QString( i18nFmt ).arg( tr( "Italian" ) ).arg( "Alessio Sclocco" ); msg += QString( i18nFmt ).arg( tr( "Norwegian" ) ).arg( "Thomas Finneid" ); msg += QString( i18nFmt ).arg( tr( "Polish" ) ).arg( "Witold Wysota" ); msg += QString( i18nFmt ).arg( tr( "Portuguese" ) ).arg( "Helder Correia" ); msg += QString( i18nFmt ).arg( tr( "Romanian" ) ).arg( "Iulia Taulescu" ); msg += QString( i18nFmt ).arg( tr( "Russian" ) ).arg( "Irek Khasyanov" ); msg += QString( i18nFmt ).arg( tr( "Simplified Chinese" ) ).arg( "Liang Qi" ); msg += QString( i18nFmt ).arg( tr( "Spanish" ) ).arg( "Francesc Farfán" ); msg += QString( i18nFmt ).arg( tr( "Swedish" ) ).arg( "Johan Thelin" ); msg += QString( i18nFmt ).arg( tr( "Turkish" ) ).arg( "Serdar Soytetir" ); msg += "

"; msg += "

"; const char * copyFmt = "%1 %2 %3
%4

"; msg += QString( copyFmt ).arg( tr("Copyright (C)") ).arg( "2004-2007" ).arg( "Ariya Hidayat" ).arg( "ariya@kde.org" ); msg += QString( copyFmt ).arg( tr("Copyright (C)") ).arg( "2005-2006" ).arg( "Johan Thelin" ).arg( "e8johan@gmail.com" ); msg += QString( copyFmt ).arg( tr("Copyright (C)") ).arg( "2007-2008" ).arg( "Helder Correia" ).arg( "helder.pereira.correia@gmail.com" ); msg += QString( copyFmt ).arg( tr("Copyright (C)") ).arg( "2007-2008" ).arg( "Wolf Lammen" ).arg( "ookami1@gmx.de" ); msg += QString( copyFmt ).arg( tr("Copyright (C)") ).arg( "2008" ).arg( "Alessandro Portale" ).arg( "alessandro.portale@googlemail.com" ); msg += "

"; msg += "

"; msg += tr("This program is free software; you can redistribute it and/or " "modify it under the terms of the GNU General Public License " "as published by the Free Software Foundation; either version 2 " "of the License, or (at your option) any later version" ); msg += "

"; msg += "

"; msg += tr("This program is distributed in the hope that it will be useful, " "but WITHOUT ANY WARRANTY; without even the implied warranty of " "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the " "GNU General Public License for more details."); msg += "

"; msg += "

 

"; msg += QString( "

%1

" ) .arg( tr("Visit http://www.speedcrunch.org for more information!") ); marqueeText->setText( msg ); QPushButton * closeButton = new QPushButton( this ); closeButton->setObjectName( "CloseButton" ); closeButton->setText( tr("Close") ); QObject::connect( closeButton, SIGNAL( clicked() ), this, SLOT( accept() ) ); QSpacerItem * buttonSpacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum ); // --- layout handling --- QVBoxLayout * mainLayout = new QVBoxLayout( this ); QHBoxLayout * topLayout = new QHBoxLayout(); QHBoxLayout * buttonLayout = new QHBoxLayout(); mainLayout->addLayout( topLayout ); mainLayout->addWidget( marqueeText ); mainLayout->addLayout( buttonLayout ); mainLayout->setStretchFactor( marqueeText, 1 ); topLayout->addWidget( infoLabel ); topLayout->addWidget( iconLabel ); buttonLayout->addItem( buttonSpacer ); buttonLayout->addWidget( closeButton ); setWindowTitle( tr("About SpeedCrunch") ); setMinimumSize( 350, 400 ); setMaximumSize( 350, 400 ); } speedcrunch-0.10.1/src/gui/aboutbox.hxx0000644000175000001440000000327611015364561017217 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004-2006 Ariya Hidayat // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef ABOUTBOX_HXX #define ABOUTBOX_HXX #include #include #include class QPaintEvent; class QResizeEvent; class MarqueeTextPrivate; class MarqueeText: public QFrame { Q_OBJECT public: MarqueeText( QWidget* parent = 0, const char* name = 0 ); ~MarqueeText(); void setText( const QString& text ); virtual QSizePolicy sizePolicy() const; protected: void paintEvent( QPaintEvent* ); void resizeEvent( QResizeEvent* ); private slots: void scroll(); void layout(); private: MarqueeTextPrivate *d; MarqueeText( const MarqueeText& ); MarqueeText& operator=( const MarqueeText& ); }; class AboutBox : public QDialog { Q_OBJECT public: AboutBox( QWidget* parent = 0 ); private: AboutBox( const AboutBox& ); AboutBox& operator=( const AboutBox& ); }; #endif speedcrunch-0.10.1/src/gui/historydock.hxx0000644000175000001440000000304711015364561017732 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef HISTORYDOCK_HXX #define HISTORYDOCK_HXX #include class QListWidgetItem; class HistoryDock : public QDockWidget { Q_OBJECT public: explicit HistoryDock( QWidget * parent = 0 ); ~HistoryDock(); public slots: void clear(); void append( const QString & ); void appendHistory( const QStringList & ); void setHistory( const QStringList & ); signals: void expressionSelected( const QString & ); public slots: void retranslateText(); protected slots: void handleItem( QListWidgetItem * item ); private: struct Private; Private * const d; void recolor(); }; #endif speedcrunch-0.10.1/src/gui/resultdisplay.hxx0000644000175000001440000000522011015364561020267 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef RESULTDISPLAY_HXX #define RESULTDISPLAY_HXX #include #include class HNumber; class QListWidgetItem; class ResultDisplay : public QListWidget { Q_OBJECT public: ResultDisplay( char radixChar = 'C', char format = 'g', int precision = -1, QWidget * parent = 0, const char * name = 0 ); ~ResultDisplay(); void append( const QString & expr, const HNumber & value ); void appendError( const QString & expr, const QString & msg ); void appendHistory( const QStringList & history, const QStringList & results ); void setCustomAppearance( bool ); void setCustomBackgroundColor( const QColor & bg1, const QColor & bg2 ); void setCustomErrorColor( const QColor & ); void setCustomTextColor( const QColor & ); bool customAppearance() const; char format() const; char radixChar() const; int count() const; int precision() const; QColor customBackgroundColor1() const; QColor customBackgroundColor2() const; QColor customErrorColor() const; QColor customTextColor() const; QString asText() const; QString formatNumber( const HNumber & ) const; signals: void textCopied( const QString & ); void textSelected( const QString & ); public slots: void clear(); void scrollEnd(); void setFormat( char ); void setPrecision( int ); void setRadixChar( char ); private slots: void copyToClipboard( QListWidgetItem * ); void selectItem( QListWidgetItem * ); void refresh(); private: struct Private; Private * const d; ResultDisplay( const ResultDisplay & ); ResultDisplay & operator=( const ResultDisplay & ); }; #endif speedcrunch-0.10.1/src/gui/insertfunctiondlg.cpp0000644000175000001440000000775511015364561021116 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2006 Johan Thelin // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "insertfunctiondlg.hxx" #include "base/functions.hxx" #include #include #include #include #include #include #include #include struct InsertFunctionDlg::Private { Functions * functions; QPushButton * cancelButton; QPushButton * insertButton; QTreeWidget * list; }; // public InsertFunctionDlg::InsertFunctionDlg( Functions * f, QWidget * parent ) : QDialog( parent ), d( new InsertFunctionDlg::Private ) { d->functions = f; setWindowTitle( tr( "Insert Function" ) ); setModal( true ); QVBoxLayout * layout = new QVBoxLayout; setLayout( layout ); d->list = new QTreeWidget( this ); d->list->setColumnCount( 2 ); d->list->setAlternatingRowColors( true ); d->list->setRootIsDecorated( false ); d->list->setEditTriggers( QTreeWidget::NoEditTriggers ); d->list->setSelectionBehavior( QTreeWidget::SelectRows ); QStringList titles; titles << tr( "Name" ); titles << tr( "Description" ); d->list->setHeaderLabels( titles ); d->insertButton = new QPushButton( this ); d->insertButton->setText( tr( "&Insert" ) ); d->insertButton->setDefault( true ); d->cancelButton = new QPushButton( this ); d->cancelButton->setText( tr( "Cancel" ) ); QWidget * box = new QWidget( this ); QHBoxLayout * boxLayout = new QHBoxLayout; boxLayout->setMargin( 0 ); box->setLayout( boxLayout ); boxLayout->addWidget( d->insertButton ); boxLayout->addItem( new QSpacerItem( 50, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Minimum ) ); boxLayout->addWidget( d->cancelButton ); layout->addWidget( d->list ); layout->addWidget( box ); connect( d->insertButton, SIGNAL(clicked()), this, SLOT(accept()) ); connect( d->cancelButton, SIGNAL(clicked()), this, SLOT(reject()) ); connect( d->list, SIGNAL( itemActivated( QTreeWidgetItem *, int ) ), this, SLOT( accept() ) ); connect( d->list, SIGNAL( itemDoubleClicked( QTreeWidgetItem *, int ) ), this, SLOT( accept() ) ); QTimer::singleShot( 0, this, SLOT(initUI()) ); } QString InsertFunctionDlg::functionName() const { QTreeWidgetItem * item = d->list->currentItem(); return item ? item->text( 0 ).toLower() : QString(); } InsertFunctionDlg::~InsertFunctionDlg() { delete d; } // private slots void InsertFunctionDlg::initUI() { QStringList functionNames = d->functions->functionNames(); for ( int i = 0; i < functionNames.count(); i++ ) { Function * f = d->functions->function( functionNames[i] ); if ( f ) { QStringList str; str << f->name(); str << f->description(); QTreeWidgetItem * item = new QTreeWidgetItem( d->list, str ); if ( item && layoutDirection() == Qt::RightToLeft ) item->setTextAlignment( 0, Qt::AlignRight ); } } d->list->sortItems( 0, Qt::AscendingOrder ); d->list->setFocus(); d->list->setCurrentItem( d->list->itemAt( 0, 0 ) ); adjustSize(); } speedcrunch-0.10.1/src/speedcrunch.pro0000644000175000001440000000452511015364561017102 0ustar helderusersHEADERS += base/constants.hxx HEADERS += base/evaluator.hxx HEADERS += base/functions.hxx HEADERS += gui/aboutbox.hxx HEADERS += gui/autohidelabel.hxx HEADERS += gui/bookdock.hxx HEADERS += gui/constantsdock.hxx HEADERS += gui/deletevardlg.hxx HEADERS += gui/resultdisplay.hxx HEADERS += gui/editor.hxx HEADERS += gui/functionsdock.hxx HEADERS += gui/historydock.hxx HEADERS += gui/insertfunctiondlg.hxx HEADERS += gui/insertvardlg.hxx HEADERS += gui/keypad.hxx HEADERS += gui/mainwindow.hxx HEADERS += gui/tipwidget.hxx HEADERS += gui/variablesdock.hxx SOURCES += base/constants.cpp HEADERS += base/evaluator.cpp SOURCES += base/functions.cpp SOURCES += gui/aboutbox.cpp SOURCES += gui/autohidelabel.cpp SOURCES += gui/bookdock.cpp SOURCES += gui/constantsdock.cpp SOURCES += gui/deletevardlg.cpp SOURCES += gui/resultdisplay.cpp SOURCES += gui/editor.cpp SOURCES += gui/functionsdock.cpp SOURCES += gui/historydock.cpp SOURCES += gui/insertfunctiondlg.cpp SOURCES += gui/insertvardlg.cpp SOURCES += gui/keypad.cpp SOURCES += gui/mainwindow.cpp SOURCES += gui/tipwidget.cpp SOURCES += gui/variablesdock.cpp TRANSLATIONS += i18n/ca.ts TRANSLATIONS += i18n/cs.ts TRANSLATIONS += i18n/de.ts TRANSLATIONS += i18n/es.ts TRANSLATIONS += i18n/es_AR.ts TRANSLATIONS += i18n/eu.ts TRANSLATIONS += i18n/fi.ts TRANSLATIONS += i18n/fr.ts TRANSLATIONS += i18n/he.ts TRANSLATIONS += i18n/id.ts TRANSLATIONS += i18n/it.ts TRANSLATIONS += i18n/nb.ts TRANSLATIONS += i18n/nl.ts TRANSLATIONS += i18n/pl.ts TRANSLATIONS += i18n/pt.ts TRANSLATIONS += i18n/pt_BR.ts TRANSLATIONS += i18n/ro.ts TRANSLATIONS += i18n/ru.ts TRANSLATIONS += i18n/sv.ts TRANSLATIONS += i18n/tr.ts TRANSLATIONS += i18n/zh_CN.ts translations.files += i18n/ca.qm translations.files += i18n/cs.qm translations.files += i18n/de.qm translations.files += i18n/es.qm translations.files += i18n/es_AR.qm translations.files += i18n/eu.qm translations.files += i18n/fi.qm translations.files += i18n/fr.qm translations.files += i18n/he.qm translations.files += i18n/id.qm translations.files += i18n/it.qm translations.files += i18n/nb.qm translations.files += i18n/nl.qm translations.files += i18n/pl.qm translations.files += i18n/pt.qm translations.files += i18n/pt_BR.qm translations.files += i18n/ro.qm translations.files += i18n/ru.qm translations.files += i18n/sv.qm translations.files += i18n/tr.qm translations.files += i18n/zh_CN.qm speedcrunch-0.10.1/src/main/0000755000175000001440000000000011015364704014772 5ustar helderusersspeedcrunch-0.10.1/src/main/main.cpp0000644000175000001440000000226511015364561016430 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "gui/mainwindow.hxx" #include int main( int argc, char * argv[] ) { QApplication app( argc, argv ); MainWindow win; win.show(); app.connect( & app, SIGNAL( lastWindowClosed() ), & app, SLOT( quit() ) ); return app.exec(); } speedcrunch-0.10.1/src/test/0000755000175000001440000000000011015364704015025 5ustar helderusersspeedcrunch-0.10.1/src/test/testhmath.cpp0000644000175000001440000015450311015364561017543 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004-2006 Ariya Hidayat // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "math/hmath.hxx" #include #include #include using namespace std; #define CHECK(x,y) check_value(__FILE__,__LINE__,#x,x,y) #define CHECK_FORMAT(f,p,x,y) check_format(__FILE__,__LINE__,#x,x,f,p,y) #define CHECK_PRECISE(x,y) check_precise(__FILE__,__LINE__,#x,x,y) static int hmath_total_tests = 0; static int hmath_failed_tests = 0; static const HNumber PI = HMath::pi(); static const HNumber PHI = HMath::phi(); static void check_value( const char * file, int line, const char * msg, const HNumber & n, const char * expected ) { hmath_total_tests++; char * result = HMath::formatFixed( n ); if ( strcmp( result, expected ) ) { hmath_failed_tests++; cerr << file << "[" << line << "]: " << msg << endl << " Result : " << result << endl << " Expected: " << expected << endl << endl; } free( result ); } static void check_format( const char * file, int line, const char * msg, const HNumber & n, char format, int prec, const char * expected ) { hmath_total_tests++; char * result = HMath::format( n, format, prec ); if ( strcmp( result, expected ) ) { hmath_failed_tests++; cerr << file << "[" << line << "]: " << msg << endl << " Result : " << result << endl << " Expected: " << expected << endl << endl; } free( result ); } static void check_precise( const char * file, int line, const char * msg, const HNumber & n, const char * expected ) { hmath_total_tests++; char * result = HMath::formatFixed( n, 50 ); if ( strcmp( result, expected ) ) { hmath_failed_tests++; cerr << file << "[" << line << "]: " << msg << endl << " Result : " << result << endl << " Expected: " << expected << endl << endl; } free( result ); } void test_create() { CHECK( HNumber( "1.0" ), "1" ); CHECK( HNumber( "2.0" ), "2" ); CHECK( HNumber( "1e-3" ), "0.001" ); // too large or too small CHECK( HNumber( "1e1000000000" ), "NaN" ); CHECK( HNumber( "1e-1000000000" ), "NaN" ); CHECK_FORMAT( 'e', 2, HNumber( "1e1000000000" ), "NaN" ); CHECK_FORMAT( 'e', 2, HNumber( "1e-1000000000" ), "NaN" ); } void test_format() { // fixed decimal digits CHECK_FORMAT( 'f', 0, HNumber( "NaN" ), "NaN" ); CHECK_FORMAT( 'f', 0, HNumber( "0" ), "0" ); CHECK_FORMAT( 'f', 0, HNumber( "1.1" ), "1" ); CHECK_FORMAT( 'f', 1, HNumber( "2.11" ), "2.1" ); CHECK_FORMAT( 'f', 2, HNumber( "3.111" ), "3.11" ); CHECK_FORMAT( 'f', 1, HNumber( "4.001" ), "4.0" ); CHECK_FORMAT( 'f', 3, HNumber( "4.1111" ), "4.111" ); CHECK_FORMAT( 'f', 2, HNumber( "3.14" ), "3.14" ); CHECK_FORMAT( 'f', 3, HNumber( "3.14" ), "3.140" ); CHECK_FORMAT( 'f', 5, HNumber( "3.14" ), "3.14000" ); CHECK_FORMAT( 'f', 7, HNumber( "3.14" ), "3.1400000" ); CHECK_FORMAT( 'f', 7, HNumber( "-0.001" ), "-0.0010000" ); CHECK_FORMAT( 'f', 8, HNumber( "-0.001" ), "-0.00100000" ); CHECK_FORMAT( 'f', 9, HNumber( "-0.001" ), "-0.001000000" ); CHECK_FORMAT( 'f', -1, HNumber( "4.000000000000000000000000000000000000000000001" ), "4" ); // engineering notation CHECK_FORMAT( 'n', 0, HNumber( "NaN" ), "NaN" ); CHECK_FORMAT( 'n', 0, HNumber( "0" ), "0" ); CHECK_FORMAT( 'n', 0, HNumber( "3.14" ), "3.14e0" ); CHECK_FORMAT( 'n', 1, HNumber( "3.14" ), "3.14e0" ); CHECK_FORMAT( 'n', 2, HNumber( "3.14" ), "3.14e0" ); CHECK_FORMAT( 'n', 3, HNumber( "3.14" ), "3.140e0" ); CHECK_FORMAT( 'n', 5, HNumber( "3.14" ), "3.14000e0" ); CHECK_FORMAT( 'n', 7, HNumber( "3.14" ), "3.1400000e0" ); CHECK_FORMAT( 'n', 3, HNumber( "-0.001" ), "-1.000e-3" ); CHECK_FORMAT( 'n', 2, HNumber( "0.0001" ), "100.e-6" ); CHECK_FORMAT( 'n', 2, HNumber( "0.001" ), "1.00e-3" ); CHECK_FORMAT( 'n', 2, HNumber( "0.01" ), "10.0e-3" ); CHECK_FORMAT( 'n', 2, HNumber( "0.1" ), "100.e-3" ); CHECK_FORMAT( 'n', 2, HNumber( "1" ), "1.00e0" ); CHECK_FORMAT( 'n', 2, HNumber( "10" ), "10.0e0" ); CHECK_FORMAT( 'n', 2, HNumber( "100" ), "100.e0" ); CHECK_FORMAT( 'n', 2, HNumber( "1000" ), "1.00e3" ); CHECK_FORMAT( 'n', 2, HNumber( "10000" ), "10.0e3" ); CHECK_FORMAT( 'n', 2, HNumber( "100000" ), "100.e3" ); CHECK_FORMAT( 'n', 2, HNumber( "1000000" ), "1.00e6" ); CHECK_FORMAT( 'n', 2, HNumber( "10000000" ), "10.0e6" ); // scientific notation CHECK_FORMAT( 'e', 0, HNumber( "NaN" ), "NaN" ); CHECK_FORMAT( 'e', 0, HNumber( "0" ), "0" ); CHECK_FORMAT( 'e', 0, HNumber( "3.14" ), "3e0" ); CHECK_FORMAT( 'e', 1, HNumber( "3.14" ), "3.1e0" ); CHECK_FORMAT( 'e', 2, HNumber( "3.14" ), "3.14e0" ); CHECK_FORMAT( 'e', 3, HNumber( "3.14" ), "3.140e0" ); CHECK_FORMAT( 'e', 5, HNumber( "3.14" ), "3.14000e0" ); CHECK_FORMAT( 'e', 7, HNumber( "3.14" ), "3.1400000e0" ); CHECK_FORMAT( 'e', 3, HNumber( "-0.001" ), "-1.000e-3" ); CHECK_FORMAT( 'e', 2, HNumber( "0.0001" ), "1.00e-4" ); CHECK_FORMAT( 'e', 2, HNumber( "0.001" ), "1.00e-3" ); CHECK_FORMAT( 'e', 2, HNumber( "0.01" ), "1.00e-2" ); CHECK_FORMAT( 'e', 2, HNumber( "0.1" ), "1.00e-1" ); CHECK_FORMAT( 'e', 2, HNumber( "1" ), "1.00e0" ); CHECK_FORMAT( 'e', 2, HNumber( "10" ), "1.00e1" ); CHECK_FORMAT( 'e', 2, HNumber( "100" ), "1.00e2" ); CHECK_FORMAT( 'e', 2, HNumber( "1000" ), "1.00e3" ); CHECK_FORMAT( 'e', 2, HNumber( "10000" ), "1.00e4" ); CHECK_FORMAT( 'e', 2, HNumber( "100000" ), "1.00e5" ); CHECK_FORMAT( 'e', 2, HNumber( "1000000" ), "1.00e6" ); CHECK_FORMAT( 'e', 2, HNumber( "10000000" ), "1.00e7" ); // general format CHECK_FORMAT( 'g', -1, PI, "3.14159265358979323846" ); CHECK_FORMAT( 'g', -1, PHI, "1.6180339887498948482" ); CHECK_FORMAT( 'g', 3, HNumber( "0" ), "0" ); CHECK_FORMAT( 'g', 3, HNumber( "0.000000001" ), "1.000e-9" ); CHECK_FORMAT( 'g', 3, HNumber( "0.00000001" ), "1.000e-8" ); CHECK_FORMAT( 'g', 3, HNumber( "0.0000001" ), "1.000e-7" ); CHECK_FORMAT( 'g', 3, HNumber( "0.000001" ), "1.000e-6" ); CHECK_FORMAT( 'g', 3, HNumber( "0.00001" ), "1.000e-5" ); CHECK_FORMAT( 'g', 3, HNumber( "0.0001" ), "1.000e-4" ); CHECK_FORMAT( 'g', 3, HNumber( "0.001" ), "0.001" ); CHECK_FORMAT( 'g', 3, HNumber( "0.01" ), "0.010" ); CHECK_FORMAT( 'g', 3, HNumber( "0.1" ), "0.100" ); CHECK_FORMAT( 'g', 3, HNumber( "10" ), "10.000" ); CHECK_FORMAT( 'g', 3, HNumber( "100" ), "100.000" ); CHECK_FORMAT( 'g', 3, HNumber( "1000" ), "1000.000" ); CHECK_FORMAT( 'g', 3, HNumber( "10000" ), "10000.000" ); CHECK_FORMAT( 'g', 3, HNumber( "100000" ), "100000.000" ); CHECK_FORMAT( 'g', 3, HNumber( "1000000" ), "1.000e6" ); CHECK_FORMAT( 'g', 3, HNumber( "10000000" ), "1.000e7" ); CHECK_FORMAT( 'g', 3, HNumber( "100000000" ), "1.000e8" ); CHECK_FORMAT( 'g', 3, HNumber( "1403.1977" ), "1403.198" ); CHECK_FORMAT( 'g', 3, HNumber( "2604.1980" ), "2604.198" ); CHECK_FORMAT( 'g', 3, HNumber( "2.47e4" ), "24700.000" ); } void test_op() { // addition CHECK( HNumber( 0 ) + HNumber( 0 ), "0" ); CHECK( HNumber( 1 ) + HNumber( 0 ), "1" ); CHECK( HNumber( 1 ) + HNumber( 1 ), "2" ); CHECK( HNumber( 1 ) + HNumber( 2 ), "3" ); CHECK( HNumber( 1 ) + HNumber( 10 ), "11" ); CHECK( HNumber( 1 ) + HNumber( 100 ), "101" ); CHECK( HNumber( 1 ) + HNumber( 1000 ), "1001" ); // subtraction CHECK( HNumber( 0 ) - HNumber( 0 ), "0" ); CHECK( HNumber( 1 ) - HNumber( 0 ), "1" ); CHECK( HNumber( 1 ) - HNumber( 2 ), "-1" ); // division CHECK( HNumber( 1 ) / HNumber( 2 ), "0.5" ); CHECK( HNumber( 1 ) / HMath::sin( PI ), "NaN" ); // division by zero CHECK( HNumber( 1 ) / HNumber( 0 ), "NaN" ); CHECK( HNumber( 1 ) / HMath::sin( 0 ), "NaN" ); CHECK( HNumber( 1 ) / HMath::sin( PI ), "NaN" ); CHECK( HNumber( 1 ) / HMath::cos( PI/2 ), "NaN" ); CHECK( HNumber( 1 ) / HMath::tan( 0 ), "NaN" ); CHECK( HNumber( 1 ) / HMath::tan( PI ), "NaN" ); CHECK( HNumber( 1 ) / HMath::trunc( "0.123" ), "NaN" ); CHECK( HNumber( 1 ) / HMath::round( "0.456" ), "NaN" ); CHECK( HNumber( 1 ) / HMath::binomialPmf( 1, 10, 0 ), "NaN" ); CHECK_PRECISE( HNumber( 1 ) / HNumber( 3 ), "0.33333333333333333333333333333333333333333333333333" ); CHECK_PRECISE( HNumber( 2 ) / HNumber( 3 ), "0.66666666666666666666666666666666666666666666666667" ); CHECK_PRECISE( HNumber( 1 ) / HNumber( 7 ), "0.14285714285714285714285714285714285714285714285714" ); CHECK_PRECISE( HNumber( 2 ) / HNumber( 7 ), "0.28571428571428571428571428571428571428571428571429" ); CHECK_PRECISE( HNumber( 3 ) / HNumber( 7 ), "0.42857142857142857142857142857142857142857142857143" ); CHECK_PRECISE( HNumber( 4 ) / HNumber( 7 ), "0.57142857142857142857142857142857142857142857142857" ); CHECK_PRECISE( HNumber( 1 ) / HNumber( 9 ), "0.11111111111111111111111111111111111111111111111111" ); // multiplication CHECK( HNumber( 0 ) * HNumber( 0 ), "0" ); CHECK( HNumber( "1.0" ) * HNumber( "0.0" ), "0" ); CHECK( HNumber( 1 ) * HNumber( 1 ), "1" ); CHECK( HNumber( 3 ) * HNumber( -4 ), "-12" ); CHECK( HNumber( -2 ) * HNumber( 5 ), "-10" ); CHECK( HNumber( 6 ) * HNumber( 7 ), "42" ); CHECK( HNumber( "1.5" ) * HNumber( "1.5" ), "2.25" ); } void test_functions() { // pi CHECK( PI, "3.14159265358979323846" ); CHECK_PRECISE( PI, "3.14159265358979323846264338327950288419716939937511" ); // phi CHECK( PHI, "1.6180339887498948482" ); CHECK_PRECISE( PHI, "1.61803398874989484820458683436563811772030917980576" ); // abs CHECK( HMath::abs( "NaN" ), "NaN" ); CHECK( HMath::abs( "0" ), "0" ); CHECK( HMath::abs( "1" ), "1" ); CHECK( HMath::abs( "100" ), "100" ); CHECK( HMath::abs( "-100" ), "100" ); CHECK( HMath::abs( "-3.14159" ), "3.14159" ); CHECK( HMath::abs( "-0.00000014159" ), "0.00000014159" ); // floor CHECK( HMath::floor( "NaN" ), "NaN" ); CHECK( HMath::floor( "0" ), "0" ); CHECK( HMath::floor( "5" ), "5" ); CHECK( HMath::floor( "-5" ), "-5" ); CHECK( HMath::floor( "3.14" ), "3" ); CHECK( HMath::floor( "1.77" ), "1" ); CHECK( HMath::floor( "-2.6041980" ), "-3" ); CHECK( HMath::floor( "2.6041980" ), "2" ); CHECK( HMath::floor( "0.000001" ), "0" ); CHECK( HMath::floor( "-0.000001" ), "-1" ); // ceil CHECK( HMath::ceil( "NaN" ), "NaN" ); CHECK( HMath::ceil( "0" ), "0" ); CHECK( HMath::ceil( "5" ), "5" ); CHECK( HMath::ceil( "-5" ), "-5" ); CHECK( HMath::ceil( "3.14" ), "4" ); CHECK( HMath::ceil( "1.77" ), "2" ); CHECK( HMath::ceil( "-2.6041980" ), "-2" ); CHECK( HMath::ceil( "2.6041980" ), "3" ); CHECK( HMath::ceil( "0.000001" ), "1" ); CHECK( HMath::ceil( "-0.000001" ), "0" ); // gcd CHECK( HMath::gcd( "NaN", "NaN" ), "NaN" ); CHECK( HMath::gcd( "NaN", "5" ), "NaN" ); CHECK( HMath::gcd( "5", "NaN" ), "NaN" ); CHECK( HMath::gcd( "0", "0" ), "0" ); CHECK( HMath::gcd( "0", "5" ), "5" ); CHECK( HMath::gcd( "5", "0" ), "5" ); CHECK( HMath::gcd( "0", "-5" ), "5" ); CHECK( HMath::gcd( "-5", "0" ), "5" ); CHECK( HMath::gcd( "9", "-27" ), "9" ); CHECK( HMath::gcd( "99", "103" ), "1" ); CHECK( HMath::gcd( "-102", "306" ), "102" ); // round/1 CHECK( HMath::round( "NaN" ), "NaN" ); CHECK( HMath::round( "3.14" ), "3" ); CHECK( HMath::round( "-1.77" ), "-2" ); // round/2 CHECK( HMath::round( "NaN", 3 ), "NaN" ); CHECK( HMath::round( "0.005", -3 ), "0" ); CHECK( HMath::round( "0.005", 2 ), "0" ); CHECK( HMath::round( "3.14159", 4 ), "3.1416" ); CHECK( HMath::round( "3.14159", 3 ), "3.142" ); CHECK( HMath::round( "3.14159", 2 ), "3.14" ); CHECK( HMath::round( "3.14159", 1 ), "3.1" ); CHECK( HMath::round( "3.14159", 0 ), "3" ); CHECK( HMath::round( "-2.6041980", 4 ), "-2.6042" ); CHECK( HMath::round( "-2.6041980", 3 ), "-2.604" ); CHECK( HMath::round( "-2.6041980", 2 ), "-2.6" ); CHECK( HMath::round( "-2.6041980", 1 ), "-2.6" ); CHECK( HMath::round( "-2.6041980", 0 ), "-3" ); // trunc/1 CHECK( HMath::trunc( "NaN" ), "NaN" ); CHECK( HMath::trunc( "0" ), "0" ); CHECK( HMath::trunc( "3.14" ), "3" ); CHECK( HMath::trunc( "1.77" ), "1" ); // trunc/2 CHECK( HMath::trunc( "NaN", 3 ), "NaN" ); CHECK( HMath::trunc( "0.00013", -3 ), "0" ); CHECK( HMath::trunc( "0.00013", 4 ), "0.0001" ); CHECK( HMath::trunc( "3.14159", 4 ), "3.1415" ); CHECK( HMath::trunc( "3.14159", 3 ), "3.141" ); CHECK( HMath::trunc( "3.14159", 2 ), "3.14" ); CHECK( HMath::trunc( "3.14159", 1 ), "3.1" ); CHECK( HMath::trunc( "3.14159", 0 ), "3" ); CHECK( HMath::trunc( "-2.6041980", 4 ), "-2.6041" ); CHECK( HMath::trunc( "-2.6041980", 3 ), "-2.604" ); CHECK( HMath::trunc( "-2.6041980", 2 ), "-2.6" ); CHECK( HMath::trunc( "-2.6041980", 1 ), "-2.6" ); CHECK( HMath::trunc( "-2.6041980", 0 ), "-2" ); CHECK( HMath::trunc( "-2.6041980", 999 ), "-2.604198" ); CHECK( HMath::trunc( "-2.6041980", -2 ), "0" ); // integer CHECK( HMath::integer( "NaN" ), "NaN" ); CHECK( HMath::integer( "0" ), "0" ); CHECK( HMath::integer( "0.25" ), "0" ); CHECK( HMath::integer( "0.85" ), "0" ); CHECK( HMath::integer( "14.0377" ), "14" ); CHECK( HMath::integer( "-0.25" ), "0" ); CHECK( HMath::integer( "-0.85" ), "0" ); CHECK( HMath::integer( "-14.0377" ), "-14" ); // frac CHECK( HMath::frac( "NaN" ), "NaN" ); CHECK( HMath::frac( "0" ), "0" ); CHECK( HMath::frac( "3.14159" ), "0.14159" ); CHECK( HMath::frac( "0.14159" ), "0.14159" ); CHECK( HMath::frac( "-3.14159" ), "-0.14159" ); CHECK( HMath::frac( "-0.14159" ), "-0.14159" ); // sqrt CHECK( HMath::sqrt( "NaN" ), "NaN" ); CHECK( HMath::sqrt( -1 ), "NaN" ); CHECK( HMath::sqrt( 0 ), "0" ); CHECK( HMath::sqrt( 1 ), "1" ); CHECK( HMath::sqrt( 4 ), "2" ); CHECK( HMath::sqrt( 9 ), "3" ); CHECK( HMath::sqrt( 16 ), "4" ); CHECK( HMath::sqrt( "0.04" ), "0.2" ); CHECK( HMath::sqrt( "0.09" ), "0.3" ); CHECK( HMath::sqrt( "0.16" ), "0.4" ); CHECK_PRECISE( HMath::sqrt( 2 ), "1.41421356237309504880168872420969807856967187537695" ); CHECK_PRECISE( HMath::sqrt( 3 ), "1.73205080756887729352744634150587236694280525381038" ); CHECK_PRECISE( HMath::sqrt( 5 ), "2.23606797749978969640917366873127623544061835961153" ); CHECK_PRECISE( HMath::sqrt( 7 ), "2.64575131106459059050161575363926042571025918308245" ); CHECK_PRECISE( HMath::sqrt( 8 ), "2.82842712474619009760337744841939615713934375075390" ); CHECK_PRECISE( HMath::sqrt( 10 ), "3.16227766016837933199889354443271853371955513932522" ); CHECK_PRECISE( HMath::sqrt( 11 ), "3.31662479035539984911493273667068668392708854558935" ); CHECK_PRECISE( HMath::sqrt( 12 ), "3.46410161513775458705489268301174473388561050762076" ); CHECK_PRECISE( HMath::sqrt( 13 ), "3.60555127546398929311922126747049594625129657384525" ); CHECK_PRECISE( HMath::sqrt( 14 ), "3.74165738677394138558374873231654930175601980777873" ); CHECK_PRECISE( HMath::sqrt( 15 ), "3.87298334620741688517926539978239961083292170529159" ); CHECK_PRECISE( HMath::sqrt( 17 ), "4.12310562561766054982140985597407702514719922537362" ); CHECK_PRECISE( HMath::sqrt( 18 ), "4.24264068711928514640506617262909423570901562613084" ); CHECK_PRECISE( HMath::sqrt( 19 ), "4.35889894354067355223698198385961565913700392523244" ); CHECK_PRECISE( HMath::sqrt( 20 ), "4.47213595499957939281834733746255247088123671922305" ); // cbrt CHECK( HMath::cbrt( "NaN" ), "NaN" ); CHECK( HMath::cbrt( 0 ), "0" ); CHECK( HMath::cbrt( 1 ), "1" ); CHECK( HMath::cbrt( -1 ), "-1" ); CHECK( HMath::cbrt( 8 ), "2" ); CHECK( HMath::cbrt( -8 ), "-2" ); CHECK( HMath::cbrt( 27 ), "3" ); CHECK( HMath::cbrt( -27 ), "-3" ); CHECK( HMath::cbrt( 64 ), "4" ); CHECK( HMath::cbrt( -64 ), "-4" ); CHECK( HMath::cbrt( "0.008" ), "0.2" ); CHECK( HMath::cbrt( "-0.008" ), "-0.2" ); CHECK( HMath::cbrt( "0.027" ), "0.3" ); CHECK( HMath::cbrt( "-0.027" ), "-0.3" ); CHECK( HMath::cbrt( "0.064" ), "0.4" ); CHECK( HMath::cbrt( "-0.064" ), "-0.4" ); CHECK_PRECISE( HMath::cbrt( 2 ), "1.25992104989487316476721060727822835057025146470151" ); CHECK_PRECISE( HMath::cbrt( 3 ), "1.44224957030740838232163831078010958839186925349935" ); CHECK_PRECISE( HMath::cbrt( -20 ), "-2.71441761659490657151808946967948920480510776948910" ); // sign CHECK( HMath::sign( "NaN" ), "NaN" ); CHECK( HMath::sign( 0 ), "0" ); CHECK( HMath::sign( 1 ), "1" ); CHECK( HMath::sign( -1 ), "-1" ); CHECK( HMath::sign( 2 ), "1" ); CHECK( HMath::sign( -2 ), "-1" ); // factorial/1 CHECK( HMath::factorial( "NaN" ), "NaN" ); CHECK( HMath::factorial( -1 ), "NaN" ); CHECK( HMath::factorial( 0 ), "1" ); CHECK( HMath::factorial( 1 ), "1" ); CHECK( HMath::factorial( 2 ), "2" ); CHECK( HMath::factorial( 3 ), "6" ); CHECK( HMath::factorial( 4 ), "24" ); CHECK( HMath::factorial( 5 ), "120" ); CHECK( HMath::factorial( 6 ), "720" ); CHECK( HMath::factorial( 7 ), "5040" ); CHECK( HMath::factorial( 8 ), "40320" ); CHECK_PRECISE( HMath::factorial( "5.23" ), "178.50732778544229114185259335979946974446422321576241" ); CHECK( HMath::factorial( "-5" ), "NaN" ); // factorial/2 CHECK( HMath::factorial( "NaN", "NaN" ), "NaN" ); CHECK( HMath::factorial( "NaN", 7 ), "NaN" ); CHECK( HMath::factorial( 8, "NaN" ), "NaN" ); CHECK( HMath::factorial( 8, 0 ), "0" ); CHECK( HMath::factorial( 8, 6 ), "336" ); CHECK( HMath::factorial( 8, 7 ), "56" ); CHECK( HMath::factorial( 8, 8 ), "8" ); // nCr CHECK( HMath::nCr( "NaN", "NaN" ), "NaN" ); CHECK( HMath::nCr( "NaN", 5 ), "NaN" ); CHECK( HMath::nCr( 5, "NaN" ), "NaN" ); CHECK( HMath::nCr( 21, -1 ), "0" ); CHECK( HMath::nCr( -21, 2 ), "231" ); CHECK( HMath::nCr( 21, 0 ), "1" ); CHECK( HMath::nCr( 21, 1 ), "21" ); CHECK( HMath::nCr( 21, 2 ), "210" ); CHECK( HMath::nCr( 21, 3 ), "1330" ); CHECK( HMath::nCr( 21, 19 ), "210" ); CHECK( HMath::nCr( 21, 20 ), "21" ); CHECK( HMath::nCr( 21, 21 ), "1" ); CHECK( HMath::nCr( 21, 22 ), "0" ); CHECK( HMath::nCr( 0, 0 ), "1" ); // nPr CHECK( HMath::nPr( "NaN", "NaN" ), "NaN" ); CHECK( HMath::nPr( "NaN", 5 ), "NaN" ); CHECK( HMath::nPr( 5, "NaN" ), "NaN" ); CHECK( HMath::nPr( 21, 22 ), "0" ); CHECK( HMath::nPr( -21, 2 ), "462" ); CHECK( HMath::nPr( 21, -1 ), "0.04545454545454545455" ); CHECK( HMath::nPr( 0, 0 ), "1" ); CHECK( HMath::nPr( 21, 0 ), "1" ); CHECK( HMath::nPr( 21, 1 ), "21" ); CHECK( HMath::nPr( 21, 2 ), "420" ); CHECK( HMath::nPr( 21, 3 ), "7980" ); CHECK( HMath::nPr( 21, 4 ), "143640" ); CHECK( HMath::nPr( 21, 5 ), "2441880" ); CHECK( HMath::nPr( 21, 6 ), "39070080" ); CHECK( HMath::nPr( 21, 7 ), "586051200" ); // raise CHECK( HMath::raise( "NaN", "NaN" ), "NaN" ); CHECK( HMath::raise( "NaN", "0" ), "NaN" ); CHECK( HMath::raise( "-1", "NaN" ), "NaN" ); CHECK( HMath::raise( 10, -3 ), "0.001" ); CHECK( HMath::raise( 10, -2 ), "0.01" ); CHECK( HMath::raise( 10, -1 ), "0.1" ); CHECK( HMath::raise( 10, 0 ), "1" ); CHECK( HMath::raise( 10, 1 ), "10" ); CHECK( HMath::raise( 10, 2 ), "100" ); CHECK( HMath::raise( 10, 3 ), "1000" ); CHECK( HMath::raise( 10, 4 ), "10000" ); CHECK( HMath::raise( "2", "2" ), "4" ); CHECK( HMath::raise( "3", "3" ), "27" ); CHECK( HMath::raise( "4", "4" ), "256" ); CHECK_PRECISE( HMath::raise( "2", "0.1" ), "1.07177346253629316421300632502334202290638460497756" ); CHECK_PRECISE( HMath::raise( "2", "0.2" ), "1.14869835499703500679862694677792758944385088909780" ); CHECK_PRECISE( HMath::raise( "2", "0.3" ), "1.23114441334491628449939306916774310987613776110082" ); // exp CHECK( HMath::exp( "NaN" ), "NaN" ); CHECK( HMath::exp( "0" ), "1" ); CHECK_PRECISE( HMath::exp( "0.1" ), "1.10517091807564762481170782649024666822454719473752" ); CHECK_PRECISE( HMath::exp( "0.2" ), "1.22140275816016983392107199463967417030758094152050" ); CHECK_PRECISE( HMath::exp( "0.3" ), "1.34985880757600310398374431332800733037829969735937" ); CHECK_PRECISE( HMath::exp( "0.4" ), "1.49182469764127031782485295283722228064328277393743" ); CHECK_PRECISE( HMath::exp( "0.5" ), "1.64872127070012814684865078781416357165377610071015" ); CHECK_PRECISE( HMath::exp( "0.6" ), "1.82211880039050897487536766816286451338223880854644" ); CHECK_PRECISE( HMath::exp( "0.7" ), "2.01375270747047652162454938858306527001754239414587" ); CHECK_PRECISE( HMath::exp( "0.8" ), "2.22554092849246760457953753139507675705363413504848" ); CHECK_PRECISE( HMath::exp( "0.9" ), "2.45960311115694966380012656360247069542177230644008" ); CHECK_PRECISE( HMath::exp( "1.0" ), "2.71828182845904523536028747135266249775724709369996" ); CHECK_PRECISE( HMath::exp( "100" ), "26881171418161354484126255515800135873611118." "773741922415191608615280287034909564" "00000000000000" /*"91415887109722"*/ ); // binom * CHECK( HMath::binomialPmf( "NaN", "NaN", "NaN" ), "NaN" ); CHECK( HMath::binomialPmf( "NaN", "NaN", "0.5" ), "NaN" ); CHECK( HMath::binomialPmf( "NaN", "10", "NaN" ), "NaN" ); CHECK( HMath::binomialPmf( "NaN", "10", "0.5" ), "NaN" ); CHECK( HMath::binomialPmf( "5", "NaN", "NaN" ), "NaN" ); CHECK( HMath::binomialPmf( "5", "NaN", "0.5" ), "NaN" ); CHECK( HMath::binomialPmf( "5", "10", "NaN" ), "NaN" ); CHECK( HMath::binomialPmf( "5", "10", "0.5" ), "0.24609375" ); CHECK( HMath::binomialPmf( "-5", "10", "0.5" ), "NaN" ); CHECK_PRECISE( HMath::binomialPmf( "5", "10", "0.5" ), "0.24609375000000000000000000000000000000000000000000" ); CHECK( HMath::binomialCdf( "NaN", "NaN", "NaN" ), "NaN" ); CHECK( HMath::binomialCdf( "NaN", "NaN", "0.5" ), "NaN" ); CHECK( HMath::binomialCdf( "NaN", "10", "NaN" ), "NaN" ); CHECK( HMath::binomialCdf( "NaN", "10", "0.5" ), "NaN" ); CHECK( HMath::binomialCdf( "5", "NaN", "NaN" ), "NaN" ); CHECK( HMath::binomialCdf( "5", "NaN", "0.5" ), "NaN" ); CHECK( HMath::binomialCdf( "5", "10", "NaN" ), "NaN" ); CHECK( HMath::binomialCdf( "5", "10", "0.5" ), "0.623046875" ); CHECK( HMath::binomialCdf( "-5", "10", "0.5" ), "NaN" ); CHECK_PRECISE( HMath::binomialCdf( "5", "10", "0.5" ), "0.62304687500000000000000000000000000000000000000000" ); CHECK( HMath::binomialMean( "NaN", "NaN" ), "NaN" ); CHECK( HMath::binomialMean( "NaN", "0.5" ), "NaN" ); CHECK( HMath::binomialMean( "10", "NaN" ), "NaN" ); CHECK( HMath::binomialMean( "10", "0.5" ), "5" ); CHECK( HMath::binomialMean( "-10", "0.5" ), "NaN" ); CHECK_PRECISE( HMath::binomialMean( "10", "0.5" ), "5.00000000000000000000000000000000000000000000000000" ); CHECK( HMath::binomialVariance( "NaN", "NaN" ), "NaN" ); CHECK( HMath::binomialVariance( "NaN", "0.5" ), "NaN" ); CHECK( HMath::binomialVariance( "10", "NaN" ), "NaN" ); CHECK( HMath::binomialVariance( "10", "0.5" ), "2.5" ); CHECK( HMath::binomialVariance( "-10", "0.5" ), "NaN" ); CHECK_PRECISE( HMath::binomialVariance( "10", "0.5" ), "2.50000000000000000000000000000000000000000000000000" ); // hyper * CHECK( HMath::hypergeometricPmf( "NaN", "NaN", "NaN", "NaN" ), "NaN" ); CHECK( HMath::hypergeometricPmf( "NaN", "NaN", "NaN", "5" ), "NaN" ); CHECK( HMath::hypergeometricPmf( "NaN", "NaN", "10", "NaN" ), "NaN" ); CHECK( HMath::hypergeometricPmf( "NaN", "NaN", "10", "5" ), "NaN" ); CHECK( HMath::hypergeometricPmf( "1", "15", "NaN", "NaN" ), "NaN" ); CHECK( HMath::hypergeometricPmf( "1", "15", "NaN", "5" ), "NaN" ); CHECK( HMath::hypergeometricPmf( "1", "15", "10", "NaN" ), "NaN" ); CHECK( HMath::hypergeometricPmf( "-1", "15", "10", "5" ), "NaN" ); CHECK( HMath::hypergeometricPmf( "1", "15", "10", "5" ), "0.01665001665001665002" ); CHECK_PRECISE( HMath::hypergeometricPmf( "1", "15", "10", "5" ), "0.01665001665001665001665001665001665001665001665002" ); CHECK( HMath::hypergeometricCdf( "NaN", "NaN", "NaN", "NaN" ), "NaN" ); CHECK( HMath::hypergeometricCdf( "NaN", "NaN", "NaN", "5" ), "NaN" ); CHECK( HMath::hypergeometricCdf( "NaN", "NaN", "10", "NaN" ), "NaN" ); CHECK( HMath::hypergeometricCdf( "NaN", "NaN", "10", "5" ), "NaN" ); CHECK( HMath::hypergeometricCdf( "1", "15", "NaN", "NaN" ), "NaN" ); CHECK( HMath::hypergeometricCdf( "1", "15", "NaN", "5" ), "NaN" ); CHECK( HMath::hypergeometricCdf( "1", "15", "10", "NaN" ), "NaN" ); CHECK( HMath::hypergeometricCdf( "-1", "15", "10", "5" ), "NaN" ); CHECK( HMath::hypergeometricCdf( "1", "15", "10", "5" ), "0.01698301698301698302" ); CHECK_PRECISE( HMath::hypergeometricCdf( "1", "15", "10", "5" ), "0.01698301698301698301698301698301698301698301698302" ); CHECK( HMath::hypergeometricMean( "NaN", "NaN", "NaN" ), "NaN" ); CHECK( HMath::hypergeometricMean( "NaN", "NaN", "5" ), "NaN" ); CHECK( HMath::hypergeometricMean( "15", "10", "NaN" ), "NaN" ); CHECK( HMath::hypergeometricMean( "15", "10", "5" ), "3.33333333333333333333" ); CHECK_PRECISE( HMath::hypergeometricMean( "15", "10", "5" ), "3.33333333333333333333333333333333333333333333333333" ); CHECK( HMath::hypergeometricVariance( "NaN", "NaN", "NaN" ), "NaN" ); CHECK( HMath::hypergeometricVariance( "NaN", "NaN", "5" ), "NaN" ); CHECK( HMath::hypergeometricVariance( "15", "10", "NaN" ), "NaN" ); CHECK( HMath::hypergeometricVariance( "15", "10", "5" ), "0.79365079365079365079" ); CHECK_PRECISE( HMath::hypergeometricVariance( "15", "10", "5" ), "0.79365079365079365079365079365079365079365079365079" ); // poi * CHECK( HMath::poissonPmf( "NaN", "NaN" ), "NaN" ); CHECK( HMath::poissonPmf( "NaN", "5" ), "NaN" ); CHECK( HMath::poissonPmf( "2", "NaN" ), "NaN" ); CHECK( HMath::poissonPmf( "-2", "5" ), "NaN" ); CHECK( HMath::poissonPmf( "2", "5" ), "0.08422433748856833871" ); CHECK_PRECISE( HMath::poissonPmf( "2", "5" ), "0.08422433748856833870795060528935530311061981284194" ); CHECK( HMath::poissonCdf( "NaN", "NaN" ), "NaN" ); CHECK( HMath::poissonCdf( "NaN", "5" ), "NaN" ); CHECK( HMath::poissonCdf( "2", "NaN" ), "NaN" ); CHECK( HMath::poissonCdf( "-2", "5" ), "NaN" ); CHECK( HMath::poissonCdf( "2", "5" ), "0.12465201948308114129" ); CHECK_PRECISE( HMath::poissonCdf( "2", "5" ), "0.12465201948308114128776689582824584860371732300607" ); CHECK( HMath::poissonMean( "NaN" ), "NaN" ); CHECK( HMath::poissonMean( "5" ), "5" ); CHECK( HMath::poissonMean( "-5" ), "NaN" ); CHECK_PRECISE( HMath::poissonMean( "5" ), "5.00000000000000000000000000000000000000000000000000" ); CHECK( HMath::poissonVariance( "NaN" ), "NaN" ); CHECK( HMath::poissonVariance( "5" ), "5" ); CHECK( HMath::poissonVariance( "-5" ), "NaN" ); CHECK_PRECISE( HMath::poissonVariance( "5" ), "5.00000000000000000000000000000000000000000000000000" ); // ln CHECK( HMath::ln( "NaN" ), "NaN" ); CHECK( HMath::ln( "-0.1" ), "NaN" ); CHECK( HMath::ln( "0" ), "NaN" ); CHECK( HMath::ln( "0.00000000001"), "-25.3284360229345025242" ); CHECK_PRECISE( HMath::ln( "0.1" ), "-2.30258509299404568401799145468436420760110148862877" ); CHECK_PRECISE( HMath::ln( "0.2" ), "-1.60943791243410037460075933322618763952560135426852" ); CHECK_PRECISE( HMath::ln( "0.3" ), "-1.20397280432593599262274621776183850295361093080602" ); CHECK_PRECISE( HMath::ln( "0.4" ), "-0.91629073187415506518352721176801107145010121990826" ); CHECK_PRECISE( HMath::ln( "0.5" ), "-0.69314718055994530941723212145817656807550013436026" ); CHECK_PRECISE( HMath::ln( "0.6" ), "-0.51082562376599068320551409630366193487811079644577" ); CHECK_PRECISE( HMath::ln( "0.7" ), "-0.35667494393873237891263871124118447796401675904691" ); CHECK_PRECISE( HMath::ln( "0.8" ), "-0.22314355131420975576629509030983450337460108554801" ); CHECK_PRECISE( HMath::ln( "0.9" ), "-0.10536051565782630122750098083931279830612037298327" ); CHECK_PRECISE( HMath::ln( "1.0" ), "0" ); CHECK_PRECISE( HMath::ln( "1.1" ), "0.09531017980432486004395212328076509222060536530864" ); CHECK_PRECISE( HMath::ln( "1.2" ), "0.18232155679395462621171802515451463319738933791449" ); CHECK_PRECISE( HMath::ln( "1.3" ), "0.26236426446749105203549598688095439720416645613143" ); CHECK_PRECISE( HMath::ln( "1.4" ), "0.33647223662121293050459341021699209011148337531334" ); CHECK_PRECISE( HMath::ln( "1.5" ), "0.40546510810816438197801311546434913657199042346249" ); CHECK_PRECISE( HMath::ln( "1.6" ), "0.47000362924573555365093703114834206470089904881225" ); CHECK_PRECISE( HMath::ln( "1.7" ), "0.53062825106217039623154316318876232798710152395697" ); CHECK_PRECISE( HMath::ln( "1.8" ), "0.58778666490211900818973114061886376976937976137698" ); CHECK_PRECISE( HMath::ln( "1.9" ), "0.64185388617239477599103597720348932963627777267036" ); CHECK_PRECISE( HMath::ln( "2.0" ), "0.69314718055994530941723212145817656807550013436026" ); CHECK_PRECISE( HMath::ln( "3.0" ), "1.09861228866810969139524523692252570464749055782275" ); CHECK_PRECISE( HMath::ln( "4.0" ), "1.38629436111989061883446424291635313615100026872051" ); CHECK_PRECISE( HMath::ln( "100" ), "4.60517018598809136803598290936872841520220297725755" ); // log CHECK( HMath::log( "NaN" ), "NaN" ); CHECK( HMath::log( "-1" ), "NaN" ); CHECK( HMath::log( "0" ), "NaN" ); CHECK( HMath::log( "1e-5" ), "-5" ); CHECK( HMath::log( "1e-4" ), "-4" ); CHECK( HMath::log( "1e-3" ), "-3" ); CHECK( HMath::log( "10" ), "1" ); CHECK( HMath::log( "100" ), "2" ); CHECK( HMath::log( "1000" ), "3" ); CHECK( HMath::log( "10000" ), "4" ); CHECK( HMath::log( "1e5" ), "5" ); CHECK( HMath::log( "1e6" ), "6" ); CHECK( HMath::log( "1e7" ), "7" ); CHECK( HMath::log( "1e8" ), "8" ); CHECK( HMath::log( "1e9" ), "9" ); CHECK( HMath::log( "1e10" ), "10" ); CHECK( HMath::log( "0.00000000001" ), "-11" ); // lg CHECK( HMath::lg( "NaN" ), "NaN" ); CHECK( HMath::lg( "-1" ), "NaN" ); CHECK( HMath::lg( "0" ), "NaN" ); CHECK( HMath::lg( "1" ), "0" ); CHECK( HMath::lg( "2" ), "1" ); CHECK( HMath::lg( "4" ), "2" ); CHECK( HMath::lg( "8" ), "3" ); CHECK( HMath::lg( "16" ), "4" ); CHECK( HMath::lg( "32" ), "5" ); CHECK( HMath::lg( "32" ), "5" ); CHECK( HMath::lg( "0.00000000001" ), "-36.54120904376098582657" ); // sin CHECK( HMath::sin( "NaN" ), "NaN" ); CHECK( HMath::sin( "0" ), "0" ); CHECK( HMath::sin( PI ), "0" ); CHECK( HMath::sin( PI*2 ), "0" ); CHECK( HMath::sin( PI*(-1) ), "0" ); CHECK( HMath::sin( PI*(-3) ), "0" ); CHECK( HMath::sin( PI*6/3 ), "0" ); CHECK( HMath::sin( PI*9/3 ), "0" ); CHECK( HMath::sin( PI/2 ), "1" ); CHECK( HMath::sin( PI/4 ), "0.7071067811865475244" ); CHECK( HMath::sin( PI/3 ), "0.86602540378443864676" ); CHECK( HMath::sin( PI*2/3 ), "0.86602540378443864676" ); CHECK( HMath::sin( PI*4/3 ), "-0.86602540378443864676" ); CHECK( HMath::sin( PI*5/3 ), "-0.86602540378443864676" ); CHECK( HMath::sin( PI*7/3 ), "0.86602540378443864676" ); CHECK_PRECISE( HMath::sin( "0.0" ), "0" ); CHECK_PRECISE( HMath::sin( "0.1" ), "0.09983341664682815230681419841062202698991538801798" ); CHECK_PRECISE( HMath::sin( "0.2" ), "0.19866933079506121545941262711838975037020672954021" ); CHECK_PRECISE( HMath::sin( "0.3" ), "0.29552020666133957510532074568502737367783211174262" ); CHECK_PRECISE( HMath::sin( "0.4" ), "0.38941834230865049166631175679570526459306018344396" ); CHECK_PRECISE( HMath::sin( "0.5" ), "0.47942553860420300027328793521557138808180336794060" ); CHECK_PRECISE( HMath::sin( "0.6" ), "0.56464247339503535720094544565865790710988808499415" ); CHECK_PRECISE( HMath::sin( "0.7" ), "0.64421768723769105367261435139872018306581384457369" ); CHECK_PRECISE( HMath::sin( "0.8" ), "0.71735609089952276162717461058138536619278523779142" ); CHECK_PRECISE( HMath::sin( "0.9" ), "0.78332690962748338846138231571354862314014792572031" ); CHECK_PRECISE( HMath::sin( "1.0" ), "0.84147098480789650665250232163029899962256306079837" ); CHECK_PRECISE( HMath::sin( "2.0" ), "0.90929742682568169539601986591174484270225497144789" ); CHECK_PRECISE( HMath::sin( "3.0" ), "0.14112000805986722210074480280811027984693326425227" ); CHECK_PRECISE( HMath::sin( "4.0" ), "-0.75680249530792825137263909451182909413591288733647" ); CHECK_PRECISE( HMath::sin( "5.0" ), "-0.95892427466313846889315440615599397335246154396460" ); CHECK_PRECISE( HMath::sin( "1e22" ), "-0.85220084976718880177270589375302936826176215041004" ); // cos CHECK( HMath::cos( "NaN" ), "NaN" ); CHECK( HMath::cos( PI/2 ), "0" ); CHECK( HMath::cos( PI*3/2 ), "0" ); CHECK( HMath::cos( PI/2*(-1)*9 ), "0" ); CHECK( HMath::cos( 0 ), "1" ); CHECK( HMath::cos( PI*6/3 ), "1" ); CHECK( HMath::cos( PI*9/3 ), "-1" ); CHECK( HMath::cos( PI/1 ), "-1" ); CHECK( HMath::cos( PI/3 ), "0.5" ); CHECK( HMath::cos( PI*2/3 ), "-0.5" ); CHECK( HMath::cos( PI*4/3 ), "-0.5" ); CHECK( HMath::cos( PI*5/3 ), "0.5" ); CHECK( HMath::cos( PI*7/3 ), "0.5" ); CHECK( HMath::cos( PI/4 ), "0.7071067811865475244" ); CHECK_PRECISE( HMath::cos( "0.0" ), "1.00000000000000000000000000000000000000000000000000" ); CHECK_PRECISE( HMath::cos( "0.1" ), "0.99500416527802576609556198780387029483857622541508" ); CHECK_PRECISE( HMath::cos( "0.2" ), "0.98006657784124163112419651674816887739352436080657" ); CHECK_PRECISE( HMath::cos( "0.3" ), "0.95533648912560601964231022756804989824421408263204" ); CHECK_PRECISE( HMath::cos( "0.4" ), "0.92106099400288508279852673205180161402585956931985" ); CHECK_PRECISE( HMath::cos( "0.5" ), "0.87758256189037271611628158260382965199164519710974" ); CHECK_PRECISE( HMath::cos( "0.6" ), "0.82533561490967829724095249895537603887809103918847" ); CHECK_PRECISE( HMath::cos( "0.7" ), "0.76484218728448842625585999019186490926821055037370" ); CHECK_PRECISE( HMath::cos( "0.8" ), "0.69670670934716542092074998164232492610178601370806" ); CHECK_PRECISE( HMath::cos( "0.9" ), "0.62160996827066445648471615140713350872176136659124" ); CHECK_PRECISE( HMath::cos( "1.0" ), "0.54030230586813971740093660744297660373231042061792" ); CHECK_PRECISE( HMath::cos( "2.0" ), "-0.41614683654714238699756822950076218976600077107554" ); CHECK_PRECISE( HMath::cos( "3.0" ), "-0.98999249660044545727157279473126130239367909661559" ); CHECK_PRECISE( HMath::cos( "4.0" ), "-0.65364362086361191463916818309775038142413359664622" ); CHECK_PRECISE( HMath::cos( "1e22" ), "0.52321478539513894549759447338470949214091997243939" ); // tan CHECK( HMath::tan( "NaN" ), "NaN" ); CHECK( HMath::tan( PI/2 ), "NaN" ); CHECK( HMath::tan( PI/2*3 ), "NaN" ); CHECK( HMath::tan( PI/2*5 ), "NaN" ); CHECK( HMath::tan( PI/2*(-3) ), "NaN" ); CHECK( HMath::tan( PI/2*(-5) ), "NaN" ); CHECK( HMath::tan( PI/1 ), "0" ); CHECK( HMath::tan( PI*(-3) ), "0" ); CHECK( HMath::tan( PI*11 ), "0" ); CHECK( HMath::tan( PI/4 ), "1" ); CHECK( HMath::tan( PI/3 ), "1.73205080756887729353" ); CHECK_PRECISE( HMath::tan( "0.0" ), "0" ); CHECK_PRECISE( HMath::tan( "0.1" ), "0.10033467208545054505808004578111153681900480457644" ); CHECK_PRECISE( HMath::tan( "0.2" ), "0.20271003550867248332135827164753448262687566965163" ); CHECK_PRECISE( HMath::tan( "0.3" ), "0.30933624960962323303530367969829466725781590680046" ); CHECK_PRECISE( HMath::tan( "0.4" ), "0.42279321873816176198163542716529033394198977271569" ); CHECK_PRECISE( HMath::tan( "0.5" ), "0.54630248984379051325517946578028538329755172017979" ); CHECK_PRECISE( HMath::tan( "0.6" ), "0.68413680834169231707092541746333574524265408075678" ); CHECK_PRECISE( HMath::tan( "0.7" ), "0.84228838046307944812813500221293771718722125080420" ); CHECK_PRECISE( HMath::tan( "0.8" ), "1.02963855705036401274636117282036528416821960677231" ); CHECK_PRECISE( HMath::tan( "0.9" ), "1.26015821755033913713457548539574847783362583439629" ); CHECK_PRECISE( HMath::tan( "1.0" ), "1.55740772465490223050697480745836017308725077238152" ); CHECK_PRECISE( HMath::tan( "2.0" ), "-2.18503986326151899164330610231368254343201774622766" ); CHECK_PRECISE( HMath::tan( "3.0" ), "-0.14254654307427780529563541053391349322609228490180" ); CHECK_PRECISE( HMath::tan( "4.0" ), "1.15782128234957758313734241826732392311976276736714" ); // cot CHECK( HMath::cot( "NaN" ), "NaN" ); CHECK( HMath::cot( 0 ), "NaN" ); CHECK( HMath::cot( PI ), "NaN" ); CHECK( HMath::cot( PI*2 ), "NaN" ); CHECK( HMath::cot( PI*3 ), "NaN" ); CHECK( HMath::cot( PI*(-1) ), "NaN" ); CHECK( HMath::cot( PI*(-2) ), "NaN" ); CHECK( HMath::cot( PI*(-3) ), "NaN" ); CHECK( HMath::cot( PI/2 ), "0" ); CHECK( HMath::cot( PI/2*3 ), "0" ); CHECK( HMath::cot( PI/2*5 ), "0" ); CHECK( HMath::cot( PI/(-2) ), "0" ); CHECK( HMath::cot( PI/(-2)*3 ), "0" ); CHECK( HMath::cot( PI/(-2)*5 ), "0" ); CHECK_PRECISE( HMath::cot( "0.1" ), "9.96664442325923785979411268927059390763024832915145" ); CHECK_PRECISE( HMath::cot( "0.2" ), "4.93315487558689365736801632174474118540562176228750" ); CHECK_PRECISE( HMath::cot( "0.3" ), "3.23272814376582751371392053451257979612306377207793" ); CHECK_PRECISE( HMath::cot( "0.4" ), "2.36522242003911058702332902504860335138937304631794" ); CHECK_PRECISE( HMath::cot( "0.5" ), "1.83048772171245191926801943896881662375810794801613" ); CHECK_PRECISE( HMath::cot( "0.6" ), "1.46169594707810214033930842740714256443262393263873" ); CHECK_PRECISE( HMath::cot( "0.7" ), "1.18724183212667935367236269369115744209994867903861" ); CHECK_PRECISE( HMath::cot( "0.8" ), "0.97121460065047441252084679894165650872369163680112" ); CHECK_PRECISE( HMath::cot( "0.9" ), "0.79355114784231712550449309982343541572162687887550" ); CHECK_PRECISE( HMath::cot( "1.0" ), "0.64209261593433070300641998659426562023027811391817" ); CHECK_PRECISE( HMath::cot( "2.0" ), "-0.45765755436028576375027741043204727642848632923167" ); CHECK_PRECISE( HMath::cot( "3.0" ), "-7.01525255143453346942855137952647657829310335209635" ); CHECK_PRECISE( HMath::cot( "4.0" ), "0.86369115445061661394651434594081763350176570849799" ); // sec CHECK( HMath::sec( "NaN" ), "NaN" ); CHECK( HMath::sec( 0 ), "1" ); CHECK( HMath::sec( PI ), "-1" ); CHECK( HMath::sec( PI*2 ), "1" ); CHECK( HMath::sec( PI*3 ), "-1" ); CHECK( HMath::sec( PI*(-1) ), "-1" ); CHECK( HMath::sec( PI*(-2) ), "1" ); CHECK( HMath::sec( PI*(-3) ), "-1" ); CHECK( HMath::sec( PI/2 ), "NaN" ); CHECK( HMath::sec( PI/2*3 ), "NaN" ); CHECK( HMath::sec( PI/2*5 ), "NaN" ); CHECK( HMath::sec( PI/(-2) ), "NaN" ); CHECK( HMath::sec( PI/(-2)*3 ), "NaN" ); CHECK( HMath::sec( PI/(-2)*5 ), "NaN" ); CHECK_PRECISE( HMath::sec( "0.1" ), "1.00502091840045542846511410131163581939665289709269" ); CHECK_PRECISE( HMath::sec( "0.2" ), "1.02033884494119268979243277684919018946197757380999" ); CHECK_PRECISE( HMath::sec( "0.3" ), "1.04675160153808560093279084558703692841456893499328" ); CHECK_PRECISE( HMath::sec( "0.4" ), "1.08570442838323870311392995515876310121797526730283" ); CHECK_PRECISE( HMath::sec( "0.5" ), "1.13949392732454912231332776820494992842372524604900" ); CHECK_PRECISE( HMath::sec( "0.6" ), "1.21162831451231670461455512137241473057527998567989" ); CHECK_PRECISE( HMath::sec( "0.7" ), "1.30745925973359386987467283530531145422836345495873" ); CHECK_PRECISE( HMath::sec( "0.8" ), "1.43532419967223980049695240816284402319218304405383" ); CHECK_PRECISE( HMath::sec( "0.9" ), "1.60872581046604951302401286230639310432053967212693" ); CHECK_PRECISE( HMath::sec( "1.0" ), "1.85081571768092561791175324139865019347039665509401" ); CHECK_PRECISE( HMath::sec( "2.0" ), "-2.40299796172238098975460040142006622624512109315453" ); CHECK_PRECISE( HMath::sec( "3.0" ), "-1.01010866590799375130303648146319295518501902819060" ); CHECK_PRECISE( HMath::sec( "4.0" ), "-1.52988565646639757462951092293735504703880002436905" ); // csc CHECK( HMath::csc( "NaN" ), "NaN" ); CHECK( HMath::csc( 0 ), "NaN" ); CHECK( HMath::csc( PI ), "NaN" ); CHECK( HMath::csc( PI*2 ), "NaN" ); CHECK( HMath::csc( PI*3 ), "NaN" ); CHECK( HMath::csc( PI*(-1) ), "NaN" ); CHECK( HMath::csc( PI*(-2) ), "NaN" ); CHECK( HMath::csc( PI*(-3) ), "NaN" ); CHECK( HMath::csc( PI/2 ), "1" ); CHECK( HMath::csc( PI/2*3 ), "-1" ); CHECK( HMath::csc( PI/2*5 ), "1" ); CHECK( HMath::csc( PI/(-2) ), "-1" ); CHECK( HMath::csc( PI/(-2)*3 ), "1" ); CHECK( HMath::csc( PI/(-2)*5 ), "-1" ); CHECK_PRECISE( HMath::csc( "0.1" ), "10.01668613163477664870635254208068373689462246452006" ); CHECK_PRECISE( HMath::csc( "0.2" ), "5.03348954767234420242609636752585272222462656686394" ); CHECK_PRECISE( HMath::csc( "0.3" ), "3.38386336182412258496047655147742034395467222595556" ); CHECK_PRECISE( HMath::csc( "0.4" ), "2.56793245554778307034468729669613783401624871596957" ); CHECK_PRECISE( HMath::csc( "0.5" ), "2.08582964293348818577250167545929030196230958681696" ); CHECK_PRECISE( HMath::csc( "0.6" ), "1.77103219668772537337461210710543723169043983943920" ); CHECK_PRECISE( HMath::csc( "0.7" ), "1.55227032695710391198997364095492783063640855362864" ); CHECK_PRECISE( HMath::csc( "0.8" ), "1.39400781938863617450248222610694684266568140951681" ); CHECK_PRECISE( HMath::csc( "0.9" ), "1.27660621345889549601564565223201364314354454128779" ); CHECK_PRECISE( HMath::csc( "1.0" ), "1.18839510577812121626159945237455100352782983409796" ); CHECK_PRECISE( HMath::csc( "2.0" ), "1.09975017029461646675669739702631289665876444314985" ); CHECK_PRECISE( HMath::csc( "3.0" ), "7.08616739573718591821753227246127986736644022513951" ); CHECK_PRECISE( HMath::csc( "4.0" ), "-1.32134870881090237769679175637286490993025203772967" ); // atan CHECK( HMath::atan( "NaN" ), "NaN" ); CHECK( HMath::atan( "0.10033467208545054505808004578111153681900480457644" ), "0.1" ); CHECK( HMath::atan( "0.20271003550867248332135827164753448262687566965163" ), "0.2" ); CHECK( HMath::atan( "0.30933624960962323303530367969829466725781590680046" ), "0.3" ); CHECK( HMath::atan( "0.42279321873816176198163542716529033394198977271569" ), "0.4" ); CHECK( HMath::atan( "0.54630248984379051325517946578028538329755172017979" ), "0.5" ); CHECK( HMath::atan( "0.68413680834169231707092541746333574524265408075678" ), "0.6" ); CHECK( HMath::atan( "0.84228838046307944812813500221293771718722125080420" ), "0.7" ); CHECK( HMath::atan( "1.02963855705036401274636117282036528416821960677231" ), "0.8" ); CHECK( HMath::atan( "1.26015821755033913713457548539574847783362583439629" ), "0.9" ); CHECK( HMath::atan( "1.55740772465490223050697480745836017308725077238152" ), "1" ); CHECK_PRECISE( HMath::atan( "0.0" ), "0" ); CHECK_PRECISE( HMath::atan( "0.1" ), "0.09966865249116202737844611987802059024327832250431" ); CHECK_PRECISE( HMath::atan( "0.2" ), "0.19739555984988075837004976519479029344758510378785" ); CHECK_PRECISE( HMath::atan( "0.3" ), "0.29145679447786709199560462143289119350316759901207" ); CHECK_PRECISE( HMath::atan( "0.4" ), "0.38050637711236488630358791681043310449740571365810" ); CHECK_PRECISE( HMath::atan( "0.5" ), "0.46364760900080611621425623146121440202853705428612" ); CHECK_PRECISE( HMath::atan( "0.6" ), "0.54041950027058415544357836460859991013514825146259" ); CHECK_PRECISE( HMath::atan( "1.0" ), "0.78539816339744830961566084581987572104929234984378" ); CHECK_PRECISE( HMath::atan( "-0.1" ), "-0.09966865249116202737844611987802059024327832250431" ); CHECK_PRECISE( HMath::atan( "-0.2" ), "-0.19739555984988075837004976519479029344758510378785" ); CHECK_PRECISE( HMath::atan( "-0.3" ), "-0.29145679447786709199560462143289119350316759901207" ); CHECK_PRECISE( HMath::atan( "-0.4" ), "-0.38050637711236488630358791681043310449740571365810" ); CHECK_PRECISE( HMath::atan( "-0.5" ), "-0.46364760900080611621425623146121440202853705428612" ); CHECK_PRECISE( HMath::atan( "-0.6" ), "-0.54041950027058415544357836460859991013514825146259" ); CHECK_PRECISE( HMath::atan( "-1.0" ), "-0.78539816339744830961566084581987572104929234984378" ); // asin CHECK( HMath::asin( "NaN" ), "NaN" ); CHECK( HMath::asin( "-1" ), "-1.57079632679489661923" ); CHECK( HMath::asin( "0" ), "0" ); CHECK( HMath::asin( "1" ), "1.57079632679489661923" ); CHECK( HMath::asin( "0.09983341664682815230681419841062202698991538801798" ), "0.1" ); CHECK( HMath::asin( "0.19866933079506121545941262711838975037020672954021" ), "0.2" ); CHECK( HMath::asin( "0.29552020666133957510532074568502737367783211174262" ), "0.3" ); CHECK( HMath::asin( "0.38941834230865049166631175679570526459306018344396" ), "0.4" ); CHECK( HMath::asin( "0.47942553860420300027328793521557138808180336794060" ), "0.5" ); CHECK( HMath::asin( "0.56464247339503535720094544565865790710988808499415" ), "0.6" ); CHECK( HMath::asin( "0.64421768723769105367261435139872018306581384457369" ), "0.7" ); CHECK( HMath::asin( "0.71735609089952276162717461058138536619278523779142" ), "0.8" ); CHECK_PRECISE( HMath::asin( "0.0" ), "0" ); CHECK_PRECISE( HMath::asin( "0.1" ), "0.10016742116155979634552317945269331856867597222963" ); CHECK_PRECISE( HMath::asin( "0.2" ), "0.20135792079033079145512555221762341024003808140223" ); CHECK_PRECISE( HMath::asin( "0.3" ), "0.30469265401539750797200296122752916695456003170678" ); CHECK_PRECISE( HMath::asin( "0.4" ), "0.41151684606748801938473789761733560485570113512703" ); // acos CHECK( HMath::acos( "NaN" ), "NaN" ); CHECK( HMath::acos( "-1" ), "3.14159265358979323846" ); CHECK( HMath::acos( "0" ), "1.57079632679489661923" ); CHECK( HMath::acos( "1" ), "0" ); CHECK_PRECISE( HMath::acos( "0.1" ), "1.47062890563333682288579851218705812352990872745792" ); CHECK_PRECISE( HMath::acos( "0.2" ), "1.36943840600456582777619613942212803185854661828532" ); CHECK_PRECISE( HMath::acos( "0.3" ), "1.26610367277949911125931873041222227514402466798078" ); CHECK_PRECISE( HMath::acos( "0.4" ), "1.15927948072740859984658379402241583724288356456053" ); // sinh CHECK( HMath::sinh( "NaN" ), "NaN" ); CHECK_PRECISE( HMath::sinh( "0.1" ), "0.10016675001984402582372938352190502351492091687856" ); CHECK_PRECISE( HMath::sinh( "0.2" ), "0.20133600254109398762556824301031737297449484262574" ); CHECK_PRECISE( HMath::sinh( "0.3" ), "0.30452029344714261895843526700509522909802423268018" ); CHECK_PRECISE( HMath::sinh( "0.4" ), "0.41075232580281550854021001384469810435315092436331" ); CHECK_PRECISE( HMath::sinh( "0.5" ), "0.52109530549374736162242562641149155910592898261148" ); CHECK_PRECISE( HMath::sinh( "0.6" ), "0.63665358214824127112345437546514831902496342592790" ); CHECK_PRECISE( HMath::sinh( "0.7" ), "0.75858370183953350345987464759276815415493761421703" ); CHECK_PRECISE( HMath::sinh( "0.8" ), "0.88810598218762300657471757318975698055970959688815" ); CHECK_PRECISE( HMath::sinh( "0.9" ), "1.02651672570817527595833616197842235379403446513485" ); CHECK_PRECISE( HMath::sinh( "1.0" ), "1.17520119364380145688238185059560081515571798133410" ); // cosh CHECK( HMath::cosh( "NaN" ), "NaN" ); CHECK_PRECISE( HMath::cosh( "0.1" ), "1.00500416805580359898797844296834164470962627785896" ); CHECK_PRECISE( HMath::cosh( "0.2" ), "1.02006675561907584629550375162935679733308609889476" ); CHECK_PRECISE( HMath::cosh( "0.3" ), "1.04533851412886048502530904632291210128027546467919" ); CHECK_PRECISE( HMath::cosh( "0.4" ), "1.08107237183845480928464293899252417629013184957412" ); CHECK_PRECISE( HMath::cosh( "0.5" ), "1.12762596520638078522622516140267201254784711809867" ); CHECK_PRECISE( HMath::cosh( "0.6" ), "1.18546521824226770375191329269771619435727538261853" ); CHECK_PRECISE( HMath::cosh( "0.7" ), "1.25516900563094301816467474099029711586260477992884" ); CHECK_PRECISE( HMath::cosh( "0.8" ), "1.33743494630484459800481995820531977649392453816033" ); CHECK_PRECISE( HMath::cosh( "0.9" ), "1.43308638544877438784179040162404834162773784130523" ); CHECK_PRECISE( HMath::cosh( "1.0" ), "1.54308063481524377847790562075706168260152911236586" ); } int main( int argc, char * * argv ) { hmath_total_tests = 0; hmath_failed_tests = 0; test_create(); test_format(); test_op(); test_functions(); std::cerr << hmath_total_tests << " total, " << hmath_failed_tests << " failed" << endl; return hmath_failed_tests; } speedcrunch-0.10.1/src/test/testfloatnum.c0000644000175000001440000056043111015364561017730 0ustar helderusers/* testfloatnum.c: regression test for floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ /*====================================================================== REGRESSION TESTS =======================================================================*/ /* a few tests depend on 32 bit integer size, fix this in future!! */ #include "base/errors.h" #include "math/floatconfig.h" #include "math/floatconst.h" #include "math/floatcommon.h" #include "math/floatseries.h" #include "math/floatlog.h" #include "math/floatexp.h" #include "math/floattrig.h" #include "math/floathmath.h" #include "math/floatlong.h" #include "math/floatconvert.h" #include "math/floatipower.h" #include "math/floatpower.h" #include "math/floatgamma.h" #include "math/floatlogic.h" #include "math/floaterf.h" #include #include #ifdef _FLOATNUMTEST #define msbu (1u << (sizeof(unsigned)*8-1)) #define maxu (msbu + (msbu-1)) #define msbi (1 << (sizeof(int)*8-2)) #define maxi (msbi + (msbi -1)) #define mini (-maxi - 1) static char logequiv(int v1, int v2) { return ((v1 == 0) && (v2 == 0)) || ((v1 != 0) && (v2 != 0)); } static unsigned rol(unsigned u) { return (u << 1) | (u >> (sizeof(unsigned)*8-1)); } static unsigned hash(floatnum x) { unsigned result; bc_num bc; char* p; int i; result = 0; if (x) { bc = x->significand; result = rol(x->exponent) ^ (unsigned)(bc); if (bc) { result = rol(result) ^ bc->n_sign; result = rol(result) ^ bc->n_len; result = rol(result) ^ bc->n_scale; p = bc->n_value; result = rol(result) ^ (unsigned)p; for (i = 0; i++ <= bc->n_scale;) result = rol(result) ^ *(p++); } } return result; } static char istruenan(floatnum x) { return x->exponent == EXPNAN && x->significand == NULL; } static signed char _cmp(floatnum v1, floatnum v2) { if (float_isnan(v1) && float_isnan(v2)) return 0; return float_cmp(v1, v2); } static char mantcmp(bc_num b, const char* s) { char* p; int lg, i; p = b->n_value; lg = strlen(s); if (maxdigits < lg) lg = maxdigits; while (s[lg-1] == '0') --lg; if (lg != b->n_scale + 1) return 0; for (i = -1; ++i < lg;) if (s[i] - '0' != *(p++)) return 0; return 1; } static int scmp(floatnum v, char* s) { char buf[30]; float_getscientific(buf, 30, v); return strcmp(buf, s) == 0; } static char* maxexp(char* buf, char* significand) { int lg; lg = strlen(significand); memcpy(buf, significand, lg); sprintf(buf + lg, "%d", float_getrange()); return buf; } static char* minexp(char* buf, char* significand) { int lg; lg = strlen(significand); memcpy(buf, significand, lg); sprintf(buf+lg, "%d", -float_getrange()-1); return buf; } static int tc_fail(int i) { printf("test case %d failed", i + 1); return 0; } static int tc_longadd(unsigned v1, unsigned v2, unsigned r1, unsigned r2) { unsigned x1, x2, y1, y2; x1 = v1; x2 = v2; y1 = v2; y2 = v1; _longadd(&x1, &x2); _longadd(&y1, &y2); return x1 == r1 && x2 == r2 && y1 == r1 && y2 == r2; } static int test_longadd() { static struct{ unsigned v1; unsigned v2; unsigned r1; unsigned r2; } testcases[] = { {0, 0, 0, 0}, {1, 2, 3, 0}, {msbu, 2, msbu+2, 0}, {1, msbu, msbu+1, 0}, {maxu-1, 1, maxu, 0}, {maxu, 1, 0, 1}, {maxu, maxu, maxu-1, 1}, }; int i; printf("testing _longadd\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_longadd(testcases[i].v1, testcases[i].v2, testcases[i].r1, testcases[i].r2)) return tc_fail(i); return 1; } static int tc_longmul(unsigned v1, unsigned v2, unsigned r1, unsigned r2) { unsigned x1, x2, y1, y2; x1 = v1; x2 = v2; y1 = v2; y2 = v1; _longmul(&x1, &x2); _longmul(&y1, &y2); return x1 == r1 && x2 == r2 && y1 == r1 && y2 == r2; } static int test_longmul() { static struct{ unsigned v1; unsigned v2; unsigned r1; unsigned r2; } testcases[] = { {0, 0, 0, 0}, {0, 1, 0, 0}, {1, 2, 2, 0}, {msbu, 2, 0, 1}, {1, msbu, msbu, 0}, {maxu-1, 1, maxu-1, 0}, {maxu, 2, maxu-1, 1}, {maxu, maxu, 1, maxu-1}, }; int i; printf("testing _longmul\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_longmul(testcases[i].v1, testcases[i].v2, testcases[i].r1, testcases[i].r2)) return tc_fail(i); return 1; } static int tc_longshr(unsigned v1, unsigned v2, char shift, unsigned result) { unsigned r; r = _longshr(v1, v2, shift); return r == result; } static int test_longshr() { static struct{ unsigned v1; unsigned v2; char shift; unsigned r; } testcases[] = { {0, 0, 5, 0}, {47, 12, 3, msbu+5}, }; int i; printf("testing _longshr\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_longshr(testcases[i].v1, testcases[i].v2, testcases[i].shift, testcases[i].r)) return tc_fail(i); return 1; } static int tc_checkadd(int v1, int v2, char ok, int result) { int x, y; x = v1; y = v2; return _checkadd(&x, v2) == ok && _checkadd(&y, v1) == ok && x == result && y == result; } static int test_checkadd() { static struct{ int v1; int v2; char ok; int r; } testcases[] = { {0, 0, 1, 0}, {1, 0, 1, 1}, {maxi, 0, 1, maxi}, {0, mini, 1, mini}, {maxi, 1, 0, mini}, {mini, -1, 0, maxi}, }; int i; printf("testing _checkadd\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_checkadd(testcases[i].v1, testcases[i].v2, testcases[i].ok, testcases[i].r)) return tc_fail(i); return 1; } static int tc_checkmul(int v1, int v2, char ok, int result) { int x, y; x = v1; y = v2; return _checkmul(&x, v2) == ok && _checkmul(&y, v1) == ok && x == result && y == result; } static int test_checkmul() { int i; static struct{ int v1; int v2; char ok; int r; } testcases[] = { {0, 0, 1, 0}, {1, 1, 1, 1}, {-1, 1, 1, -1}, {-1, -1, 1, 1}, {maxi, 1, 1, maxi}, {maxi, 2, 0, -2}, {1, mini, 1, mini}, {-1, mini, 0, mini}, {2, mini, 0, 0}, }; printf("testing _checkmul\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_checkmul(testcases[i].v1, testcases[i].v2, testcases[i].ok, testcases[i].r)) return tc_fail(i); return 1; } static int tc_longarrayadd(unsigned x1, unsigned x2, unsigned x3, unsigned smd, unsigned r1, unsigned r2, unsigned r3, unsigned r4, int length) { unsigned a[3]; unsigned r; a[0] = x1; a[1] = x2; a[2] = x3; r = _longarrayadd(a, length, smd); return a[0] == r1 && a[1] == r2 && a[2] == r3 && r == r4; } static int test_longarrayadd() { int i; static struct{ unsigned x1; unsigned x2; unsigned x3; unsigned smd; unsigned r1; unsigned r2; unsigned r3; unsigned r4; int lg; } testcases[] = { {0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,3}, {1,2,3,4,5,2,3,0,3}, {maxu,2,3,4,3,3,3,0,3}, {maxu,maxu,3,4,3,0,4,0,3}, {maxu,maxu,maxu,4,3,0,0,1,3}, {0,0,0,1,0,0,0,1,0}, {1,0,0,1,2,0,0,0,1}, {maxu,0,0,1,0,0,0,1,1}, }; printf("testing _longarrayadd\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_longarrayadd(testcases[i].x1, testcases[i].x2, testcases[i].x3, testcases[i].smd, testcases[i].r1, testcases[i].r2, testcases[i].r3, testcases[i].r4, testcases[i].lg)) return tc_fail(i); return 1; } static int tc_longarraymul(unsigned x1, unsigned x2, unsigned x3, unsigned factor, unsigned r1, unsigned r2, unsigned r3, unsigned r4, int lg) { unsigned a[3]; unsigned r; a[0] = x1; a[1] = x2; a[2] = x3; r = _longarraymul(a, lg, factor); return a[0] == r1 && a[1] == r2 && a[2] == r3 && r == r4; } static int test_longarraymul() { int i; static struct{ unsigned x1; unsigned x2; unsigned x3; unsigned smd; unsigned r1; unsigned r2; unsigned r3; unsigned r4; int lg; } testcases[] = { {0,0,0,0,0,0,0,0,0}, {0,0,0,7,0,0,0,0,0}, {7,0,0,7,49,0,0,0,1}, {0,0,0,3,0,0,0,0,3}, {1,2,3,4,4,8,12,0,3}, {maxu,0,0,4,maxu-3,0,0,3,1}, {maxu,2,3,4,maxu-3,11,12,0,3}, {maxu,maxu,3,4,maxu-3,maxu,15,0,3}, {maxu,maxu,maxu,4,maxu-3,maxu,maxu,3,3}, {maxu,0,0,maxu,1,maxu-1,0,0,3}, {maxu,maxu,maxu,maxu,1,maxu,maxu,maxu-1,3}, }; printf("testing _longarraymul\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_longarraymul(testcases[i].x1, testcases[i].x2, testcases[i].x3, testcases[i].smd, testcases[i].r1, testcases[i].r2, testcases[i].r3, testcases[i].r4, testcases[i].lg)) return tc_fail(i); return 1; } static int tc_isnan(void* s, int exp, char result) { floatstruct f; float_geterror(); f.significand = s; f.exponent = exp; return float_isnan(&f) == result && exp == f.exponent && f.significand == s && float_geterror() == Success; } static int test_isnan() { static struct{ void* s; int exp; char result; } testcases[] = { {NULL, EXPNAN, 1}, {NULL, EXPZERO, 0}, {NULL, 0, 1}, {(void*)1, 0, 0}, {(void*)1, EXPNAN, 0}, }; int i; printf("testing float_isnan\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_isnan(testcases[i].s, testcases[i].exp, testcases[i].result)) return tc_fail(i); return 1; } static int tc_iszero(void* s, int exp, char result) { floatstruct f; float_geterror(); f.significand = s; f.exponent = exp; return float_iszero(&f) == result && exp == f.exponent && f.significand == s && float_geterror() == Success; } static int test_iszero() { static struct{ void* s; int exp; char result; } testcases[] = { {NULL, EXPNAN, 0}, {NULL, EXPZERO, 1}, {NULL, 0, 0}, {(void*)1, 0, 0}, {(void*)1, EXPZERO, 0}, }; int i; printf("testing float_iszero\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_iszero(testcases[i].s, testcases[i].exp, testcases[i].result)) return tc_fail(i); return 1; } static int tc_create(void* s, int exp) { floatstruct f; float_geterror(); f.significand = s; f.exponent = exp; float_create(&f); return istruenan(&f) && float_geterror() == Success; } static int test_create() { static struct{ void* s; int exp; } testcases[] = { {NULL, EXPNAN}, {NULL, EXPZERO}, {NULL, 0}, {(void*)1, 0}, {(void*)1, EXPNAN}, {(void*)1, EXPZERO}, }; int i; printf("testing float_create\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_create(testcases[i].s, testcases[i].exp)) return tc_fail(i); return 1; } static int tc_setnan(char one, int exp) { floatstruct f; int refs; float_geterror(); refs = _one_->n_refs; f.significand = NULL; if (one) f.significand = bc_copy_num(_one_); f.exponent = exp; float_setnan(&f); return istruenan(&f) && refs == _one_->n_refs && float_geterror() == Success; } static int test_setnan() { static struct{ char one; int exp; } testcases[] = { {0, EXPNAN}, {0, EXPZERO}, {0, 0}, {1, 0}, {1, EXPNAN}, {1, EXPZERO}, }; int i; printf("testing float_setnan\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_setnan(testcases[i].one, testcases[i].exp)) return tc_fail(i); return 1; } static int tc_setzero(char one, int exp) { floatstruct f; int refs; float_geterror(); refs = _one_->n_refs; f.significand = NULL; if (one) f.significand = bc_copy_num(_one_); f.exponent = exp; float_setzero(&f); return float_iszero(&f) && refs == _one_->n_refs && float_geterror() == Success; } static int test_setzero() { static struct{ char one; int exp; } testcases[] = { {0, EXPNAN}, {0, EXPZERO}, {0, 0}, {1, 0}, {1, EXPNAN}, {1, EXPZERO}, }; int i; printf("testing float_setzero\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_setzero(testcases[i].one, testcases[i].exp)) return tc_fail(i); return 1; } static int tc_setsignificand(const char* mant, int mlg, const char* result, int dot, int zeros) { floatstruct f; int refs; int save; int z, d, i; char retvalue; retvalue = 1; float_geterror(); /* test zero or NaN cases */ if (result == NULL || result[0] == '0') { z = -1; refs = _one_->n_refs; f.exponent = 12; f.significand = bc_copy_num(_one_); f.significand->n_sign = MINUS; d = float_setsignificand(&f, &z, mant, mlg); if (result == NULL) retvalue = istruenan(&f); else if (result[0] == '0') retvalue = float_iszero(&f); retvalue = retvalue && refs == _one_->n_refs && dot == d && z == zeros && float_geterror() == Success; } if (retvalue) { /* test NULL zeros pointer */ d = float_setsignificand(&f, NULL, mant, mlg); if (result == NULL) retvalue = istruenan(&f); else if (result[0] == '0') retvalue = float_iszero(&f); else retvalue = f.significand != NULL && f.exponent == 0 && f.significand->n_len == 1 && f.significand->n_sign == PLUS && mantcmp(f.significand, result); retvalue = retvalue && dot == d && float_geterror() == Success; } if (retvalue && result != NULL && result[0] != '0') { save = maxdigits; for (i = 0; retvalue && ++i <= save;) { maxdigits = i; refs = _one_->n_refs; f.exponent = 12; f.significand = bc_copy_num(_one_); f.significand->n_sign = MINUS; z = -1; d = float_setsignificand(&f, &z, mant, mlg); retvalue = f.significand != NULL && refs == _one_->n_refs && f.significand->n_len == 1 && f.significand->n_sign == PLUS && mantcmp(f.significand, result) && dot == d && z == zeros && f.exponent == 0 && float_geterror() == Success; } maxdigits = save; } _one_->n_sign = PLUS; float_setnan(&f); return retvalue; } static int test_setsignificand() { static struct{ const char* mant; int lg; const char* result; int dot; int zeros; } testcases[] = { {NULL, -1, NULL, -1, 0}, {NULL, 0, NULL, -1, 0}, {"", NULLTERMINATED, NULL, -1, 0}, {".", NULLTERMINATED, NULL, -1, 0}, {"x", NULLTERMINATED, NULL, -1, 0}, {"-1", NULLTERMINATED, NULL, -1, 0}, {"+1", NULLTERMINATED, NULL, -1, 0}, {"1E", NULLTERMINATED, NULL, -1, 0}, {"1.E", NULLTERMINATED, NULL, -1, 0}, {"-1.E", NULLTERMINATED, NULL, -1, 0}, {"1E1", NULLTERMINATED, NULL, -1, 0}, {"1.E1", NULLTERMINATED, NULL, -1, 0}, {"1.1E1", NULLTERMINATED, NULL, -1, 0}, {"1.1e1", NULLTERMINATED, NULL, -1, 0}, {"1E+1", NULLTERMINATED, NULL, -1, 0}, {"1.E+1", NULLTERMINATED, NULL, -1, 0}, {"1.1E+1", NULLTERMINATED, NULL, -1, 0}, {"1.1e+1", NULLTERMINATED, NULL, -1, 0}, {"1.1(1)", NULLTERMINATED, NULL, -1, 0}, {"1.1(+1)", NULLTERMINATED, NULL, -1, 0}, {"+1E1", NULLTERMINATED, NULL, -1, 0}, {"+1.E1", NULLTERMINATED, NULL, -1, 0}, {"+1.1E1", NULLTERMINATED, NULL, -1, 0}, {"+1.1e1", NULLTERMINATED, NULL, -1, 0}, {"+1.1(1)", NULLTERMINATED, NULL, -1, 0}, {"+1.1(+1)", NULLTERMINATED, NULL, -1, 0}, {"-1.E1", NULLTERMINATED, NULL, -1, 0}, {"1.E-1", NULLTERMINATED, NULL, -1, 0}, {"-1.E-1", NULLTERMINATED, NULL, -1, 0}, {"1111111111111111111111E1", NULLTERMINATED, NULL, -1, 0}, {"E1", NULLTERMINATED, NULL, -1, 0}, {".e", NULLTERMINATED, NULL, -1, 0}, {".1e", NULLTERMINATED, NULL, -1, 0}, {"1.e1", NULLTERMINATED, NULL, -1, 0}, {"e1.", NULLTERMINATED, NULL, -1, 0}, {".1.", NULLTERMINATED, NULL, -1, 0}, {"1..", NULLTERMINATED, NULL, -1, 0}, {"1.000000000000000000.0", NULLTERMINATED, NULL, -1, 0}, {"0", NULLTERMINATED, "0", -1, 0}, {"0.", NULLTERMINATED, "0", -1, 0}, {".0", NULLTERMINATED, "0", -1, 0}, {"000", NULLTERMINATED, "0", -1, 0}, {"00000000000", NULLTERMINATED, "0", -1, 0}, {".00000000000", NULLTERMINATED, "0", -1, 0}, {"00000000000.", NULLTERMINATED, "0", -1, 0}, {"000000.00000", NULLTERMINATED, "0", -1, 0}, {"1", -1, NULL, -1, 0}, {"1", 0, NULL, -1, 0}, {"1", 1, "1", -1, 0}, {"1", NULLTERMINATED, "1", -1, 0}, {"12", 1, "1", -1, 0}, {"12", NULLTERMINATED, "12", -1, 0}, {".1", NULLTERMINATED, "1", 0, 0}, {"1.", NULLTERMINATED, "1", 1, 0}, {"1.2", NULLTERMINATED, "12", 1, 0}, {"01.2", NULLTERMINATED, "12", 2, 1}, {"00.000000000000012", NULLTERMINATED, "12", 2, 15}, {"12.3456789000", NULLTERMINATED, "123456789", 2, 0}, {"12345678900.0", NULLTERMINATED, "123456789", 11, 0}, {"12345678901", NULLTERMINATED, "12345678901", -1, 0}, {"123456789012", NULLTERMINATED, "12345678901", -1, 0}, {"1.2345678901", NULLTERMINATED, "12345678901", 1, 0}, {"0.12345678901", NULLTERMINATED, "12345678901", 1, 1}, {"0.012345678901", NULLTERMINATED, "12345678901", 1, 2}, {"1234567890183456789", NULLTERMINATED, "12345678901", -1, 0}, {"12345678900123456789", NULLTERMINATED, "123456789", -1, 0}, {"12345678901234567.89", NULLTERMINATED, "12345678901", 17, 0}, }; int i, save; printf("testing float_setsignificand\n"); save = maxdigits; maxdigits = 11; for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_setsignificand(testcases[i].mant, testcases[i].lg, testcases[i].result, testcases[i].dot, testcases[i].zeros)) return tc_fail(i); maxdigits = save; return 1; } static int tc_getsignificand(const char* value, int bufsz, const char* result) { char buf[30]; int lg, i, j; unsigned h; floatstruct f; char retvalue; static int exp[] = {-2, -1, 0, 1, 2, EXPNAN, EXPZERO, MAXEXP, -MAXEXP-1}; static int sign[] = {PLUS, MINUS}; float_create(&f); float_setsignificand(&f, NULL, value, NULLTERMINATED); float_geterror(); if (float_isnan(&f) || float_iszero(&f)) { memset(buf, '?', 30); h = hash(&f); lg = strlen(result); retvalue = float_getsignificand(buf+1, bufsz, &f) == lg && buf[0] == '?' && buf[lg + 1] == '?' && memcmp(buf + 1, result, lg) == 0 && h == hash(&f) && float_geterror() == Success; } else for (i = sizeof(exp)/sizeof(int); --i >= 0;) for (j = -1; ++j < 2;) { lg = strlen(result); memset(buf, '?', 30); f.significand->n_sign = sign[j]; f.exponent = exp[i]; h = hash(&f); retvalue = float_getsignificand(buf+1, bufsz, &f) == lg && h == hash(&f) && buf[0] == '?' && buf[lg + 1] == '?' && memcmp(buf + 1, result, lg) == 0 && float_geterror() == Success; } float_free(&f); return retvalue; } static int test_getsignificand() { static const char v1[] = "1"; static const char v2[] = "12345678901"; static struct{ const char* value; int bufsz; const char* result; } testcases[] = { {v1, -1, ""}, {v1, 0, ""}, {v1, 1, "1"}, {v1, 2, "1"}, {"N", 0, ""}, {"N", 1, "N"}, {"N", 2, "N"}, {"0", 0, ""}, {"0", 1, "0"}, {"0", 2, "0"}, {v2, 1, "1"}, {v2, 2, "12"}, {v2, 10, "1234567890"}, {v2, 11, "12345678901"}, {v2, 12, "12345678901"}, }; int i; printf("testing float_getsignificand\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_getsignificand(testcases[i].value, testcases[i].bufsz, testcases[i].result)) return tc_fail(i); return 1; } static int tc_setexponent(const char* value, int exp, int range, int result, char valid) { floatstruct f; int save, i; char buf[30]; static int sign[] = {PLUS, MINUS}; save = float_setrange(range); float_geterror(); float_create(&f); for (i = -1; ++i < 2;) { float_setsignificand(&f, NULL, value, NULLTERMINATED); if (!float_isnan(&f) && !float_iszero(&f)) { f.exponent = -123; f.significand->n_sign = sign[i]; } float_setexponent(&f, exp); buf[float_getsignificand(buf, 30, &f)] = '\0'; if (valid) { if (strcmp(buf, value) != 0 || f.exponent != result || (f.significand && f.significand->n_sign != sign[i])) return 0; } else if(!istruenan(&f)) return 0; } float_free(&f); float_setrange(save); return float_geterror() == Success; } static int test_setexponent() { int i; static struct{ const char* mant; int exp; int range; int result; char valid; } testcases[] = { {"N", 0, 100, EXPNAN, 1}, {"N", 1, 100, EXPNAN, 1}, {"N", -1, 100, EXPNAN, 1}, {"N", EXPNAN, 100, EXPNAN, 1}, {"N", 100, 100, EXPNAN, 1}, {"N", EXPZERO, 100, EXPNAN, 1}, {"0", 0, 100, EXPZERO, 1}, {"0", 1, 100, EXPZERO, 1}, {"0", -1, 100, EXPZERO, 1}, {"0", EXPNAN, 100, EXPZERO, 1}, {"0", EXPNAN - 1, 100, EXPZERO, 1}, {"0", EXPZERO, 100, EXPZERO, 1}, {"1", 0, 100, 0, 1}, {"12", 100, 100, 100, 1}, {"12", 101, 100, 0, 0}, {"13", -101, 100, -101, 1}, {"121", -102, 100, 0, 0}, {"1432", EXPNAN, 100, 0, 0}, {"1432", EXPZERO, 100, 0, 0}, {"1432", MAXEXP, MAXEXP, MAXEXP, 1}, {"1432", -MAXEXP-1, MAXEXP, -MAXEXP-1, 1}, }; printf("testing float_setexponent\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_setexponent(testcases[i].mant, testcases[i].exp, testcases[i].range, testcases[i].result, testcases[i].valid)) return tc_fail(i); return 1; } static int tc_getexponent(const char* value, int exp, int result) { floatstruct f; unsigned h; char retvalue; float_create(&f); float_setsignificand(&f, NULL, value, NULLTERMINATED); if (!float_isnan(&f) && !float_iszero(&f)) float_setexponent(&f, exp); h = hash(&f); float_geterror(); retvalue = float_getexponent(&f) == result && hash(&f) == h && float_geterror() == Success; float_free(&f); return retvalue; } static int test_getexponent() { static struct{ const char* value; int exp; int result; } testcases[] = { {"N", 0, 0}, {"0", 0, 0}, {"1", 0, 0}, {"1234", 5, 5}, {"24413", -7, -7}, {"623", MAXEXP, MAXEXP}, {"6355", -MAXEXP-1, -MAXEXP-1}, }; int i, save; printf("testing float_getexponent\n"); save = float_setrange(MAXEXP); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_getexponent(testcases[i].value, testcases[i].exp, testcases[i].result)) return tc_fail(i); float_setrange(save); return 1; } static int tc_setsign(const char* value, int exp) { floatstruct f; unsigned h, hm; int i; static signed char invsign[] = {2, -2, 127, 126, -128, -127}; float_create(&f); float_setsignificand(&f, NULL, value, NULLTERMINATED); float_setexponent(&f, exp); h = hash(&f); if (f.significand) f.significand->n_sign = MINUS; hm = hash(&f); float_geterror(); float_setsign(&f, 0); if ((f.significand && f.significand->n_sign != MINUS) || hm != hash(&f)) return 0; float_setsign(&f, 1); if ((f.significand && f.significand->n_sign != PLUS) || h != hash(&f)) return 0; float_setsign(&f, 0); if ((f.significand && f.significand->n_sign != PLUS) || h != hash(&f)) return 0; float_setsign(&f, 1); if ((f.significand && f.significand->n_sign != PLUS) || h != hash(&f)) return 0; float_setsign(&f, -1); if ((f.significand && f.significand->n_sign != MINUS) || hm != hash(&f)) return 0; float_setsign(&f, -1); if ((f.significand && f.significand->n_sign != MINUS) || hm != hash(&f)) return 0; for (i = sizeof(invsign)/sizeof(signed char); --i >= 0;) { float_setsignificand(&f, NULL, value, NULLTERMINATED); float_setexponent(&f, exp); float_setsign(&f, invsign[i]); if (!istruenan(&f)) return 0; } return float_geterror() == Success; } static int test_setsign() { int i; static struct{ const char* value; int exp; } testcases[] = { {"N", 0}, {"0", 0}, {"1", 0}, {"123", 12}, {"18766", -12}, }; printf("testing float_setsign\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_setsign(testcases[i].value, testcases[i].exp)) return tc_fail(i); return 1; } static int tc_getsign(const char* value, int exp, signed char sign, signed char result) { floatstruct f; unsigned h; char retvalue; float_create(&f); float_setsignificand(&f, NULL, value, NULLTERMINATED); float_setsign(&f, sign); float_setexponent(&f, exp); h = hash(&f); float_geterror(); retvalue = float_getsign(&f) == result && hash(&f) == h && float_geterror() == Success; float_free(&f); return retvalue; } static int test_getsign() { int i; static struct{ const char* mant; int exp; signed char sign; signed char result; } testcases[] = { {"N", 0, 0, 0}, {"0", 0, 0, 0}, {"1", 0, 1, 1}, {"123", 0, -1, -1}, {"281", 3772, 1, 1}, {"373", 31912, -1, -1}, {"232", -233, 1, 1}, {"123", -1442, -1, -1}, }; printf("testing float_getsign\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_getsign(testcases[i].mant, testcases[i].exp, testcases[i].sign, testcases[i].result)) return tc_fail(i); return 1; } static int tc_getlength(const char* value, int result) { floatstruct f; int i; int save; unsigned h; static int exp[] = {0, -1, 1, MAXEXP, -MAXEXP-1}; save = float_setrange(MAXEXP); float_create(&f); float_setsignificand(&f, NULL, value, NULLTERMINATED); float_geterror(); if (float_isnan(&f) || float_iszero(&f)) { h = hash(&f); if (float_getlength(&f) != 0 || h != hash(&f)) return 0; } else { for (i = sizeof(exp)/sizeof(int); --i >= 0;) { float_setexponent(&f, exp[i]); h = hash(&f); if (float_getlength(&f) != result || h != hash(&f)) return 0; float_setsign(&f, -1); h = hash(&f); if (float_getlength(&f) != result || h != hash(&f)) return 0; } } float_free(&f); float_setrange(save); return float_geterror() == Success; } static int test_getlength() { int i; static struct{ const char* mant; int result; } testcases[] = { {"N", 0}, {"0", 0}, {"1", 1}, {"12", 2}, {"123", 3}, {"1234", 4}, {"12345", 5}, {"123456", 6}, {"1234567", 7}, {"12345678", 8}, {"123456789", 9}, }; printf("testing float_getlength\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_getlength(testcases[i].mant, testcases[i].result)) return tc_fail(i); return 1; } static int tc_getdigit(const char* value) { floatstruct f; int i, j, k, save, lg; unsigned h; static signed char sign[] = {1, -1}; static int exp[] = {0, -1, 1, MAXEXP, -MAXEXP-1}; float_create(&f); float_setsignificand(&f, NULL, value, NULLTERMINATED); float_geterror(); if (float_getlength(&f) == 0) { h = hash(&f); for (k = -5; ++k < 5;) if (float_getdigit(&f, k) != 0 || h != hash(&f)) return 0; } else { lg = strlen(value); save = float_setrange(MAXEXP); for (i = sizeof(exp)/sizeof(exp[0]); --i >= 0;) for (j = -1; ++j < 2;) { float_setexponent(&f, exp[i]); float_setsign(&f, sign[j]); h = hash(&f); for (k = lg + 3; --k > -3;) if (k < 0 || k >= lg) { if (float_getdigit(&f, k) != 0 || h != hash(&f)) return 0; } else if (float_getdigit(&f, k) != value[k] - '0' || h != hash(&f)) return 0; } float_setrange(save); } float_free(&f); return float_geterror() == Success; } static int test_getdigit() { int i; static struct{ const char* mant; } testcases[] = { {"N"}, {"0"}, {"1"}, {"12"}, {"123"}, {"123456789"}, {"104"}, }; printf("testing float_getdigit\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_getdigit(testcases[i].mant)) return tc_fail(i); return 1; } static int tc_getscientific(const char* s, int exp, int sz, const char* result) { floatstruct f; char r[30]; char buf[30]; int lg; unsigned h; float_create(&f); float_setsignificand(&f, NULL, s, NULLTERMINATED); float_setexponent(&f, exp); memset(buf, '?', 30); h = hash(&f); float_geterror(); lg = strlen(result); r[0] = '\0'; if (lg == 0) { if (float_getscientific(buf+1, sz, &f) != -1 || h != hash(&f) || buf[0] != '?' || buf[1] != '?') return 0; } else { memcpy(r, result, lg+1); if (float_getlength(&f) != 0) sprintf(r + lg, "%d", exp); lg = strlen(r); if (float_getscientific(buf+1, sz, &f) != lg || h != hash(&f) || buf[0] != '?' || buf[lg + 2] != '?' || memcmp(buf + 1, r, lg) != 0) return 0; if (float_getlength(&f) != 0) { float_setsign(&f, -1); h = hash(&f); if (float_getscientific(buf+1, sz+1, &f) != lg+1 || h != hash(&f) || buf[0] != '?' || buf[lg + 3] != '?' || buf[1] != '-' || memcmp(buf + 2, r, lg) != 0) return 0; } } float_free(&f); return float_geterror() == Success; } static int test_getscientific() { int i; static struct{ const char* mant; int exp; int sz; const char* result; } testcases[] = { {"N", 0, -1, ""}, {"N", 0, 0, ""}, {"N", 0, 1, ""}, {"N", 0, 2, ""}, {"N", 0, 3, ""}, {"N", 0, 4, "NaN"}, {"N", 0, 5, "NaN"}, {"0", 0, -1, ""}, {"0", 0, 0, ""}, {"0", 0, 1, ""}, {"0", 0, 2, "0"}, {"0", 0, 3, "0"}, {"1", 0, -1, ""}, {"1", 0, 0, ""}, {"1", 0, 1, ""}, {"1", 0, 2, ""}, {"1", 0, 3, ""}, {"1", 0, 4, ""}, {"1", 0, 5, "1.e"}, {"1", 0, 6, "1.e"}, {"12", 0, 4, ""}, {"12", 0, 5, "1.e"}, {"12", 0, 6, "1.2e"}, {"12", 0, 7, "1.2e"}, {"12", 10, 5, ""}, {"12", 10, 6, "1.e"}, {"12", 10, 7, "1.2e"}, {"12", 10, 8, "1.2e"}, {"12345678001", 10, 12, "1.234567e"}, {"12345678001", 10, 13, "1.2345678e"}, {"12345678001", 10, 14, "1.23456780e"}, {"12345678001", 10, 15, "1.234567800e"}, {"12345678001", 10, 16, "1.2345678001e"}, {"12345678001", -10, 13, "1.234567e"}, {"12345678001", -10, 14, "1.2345678e"}, {"12345678001", -10, 15, "1.23456780e"}, {"12345678001", -10, 16, "1.234567800e"}, {"12345678001", -10, 17, "1.2345678001e"}, {"12", 1, 6, "1.2e"}, {"12", -1, 7, "1.2e"}, {"12", MAXEXP, 25, "1.2e"}, {"12", -MAXEXP-1, 25, "1.2e"}, }; int save; printf("testing float_getscientific\n"); save = float_setrange(MAXEXP); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_getscientific(testcases[i].mant, testcases[i].exp, testcases[i].sz, testcases[i].result)) return tc_fail(i); float_setrange(save); return 1; } static int tc_setscientific(const char* value, const char* result) { floatstruct f; char v[40]; char buf[30]; int sz, refs; signed char sign; float_create(&f); float_geterror(); refs = _one_->n_refs; f.exponent = 12; f.significand = bc_copy_num(_one_); float_setscientific(&f, value, NULLTERMINATED); float_getscientific(buf, sizeof(buf), &f); if (refs != _one_->n_refs || strcmp(buf, result) != 0) return 0; sz = strlen(value); memset(v, '1', sizeof(v)); memcpy(v+1, value, sz); float_setscientific(&f, v+1, sz); float_getscientific(buf, sizeof(buf), &f); if (strcmp(buf, result) != 0) return 0; v[0] = '+'; float_setscientific(&f, v, sz+1); float_getscientific(buf, sizeof(buf), &f); if (strcmp(buf, result) != 0) return 0; v[0] = '-'; float_setscientific(&f, v, sz+1); sign = float_getsign(&f); float_setsign(&f, 1); float_getscientific(buf, sizeof(buf), &f); if (sign > 0 || strcmp(buf, result) != 0) return 0; float_free(&f); return float_geterror() == Success; } static int test_setscientific() { int i; static struct{ const char* value; const char* result; } testcases[] = { {"", "NaN"}, {"E", "NaN"}, {".", "NaN"}, {"x", "NaN"}, {"0Ex", "NaN"}, {"0xEx", "NaN"}, {"EE0", "NaN"}, {"00.0.0", "NaN"}, {"0", "0"}, {"0E0", "0"}, {"0E+0", "0"}, {"0E-0", "0"}, {"0E+999999999999999999999999999999", "0"}, {"0E-999999999999999999999999999999", "0"}, {"0000", "0"}, {".0000", "0"}, {"0000.", "0"}, {"00.00", "0"}, {"0000E1", "0"}, {".0000E-1", "0"}, {"0000.E+12", "0"}, {"00.00E-13", "0"}, {"1", "1.e0"}, {"9", "9.e0"}, {"1.", "1.e0"}, {"1.0", "1.e0"}, {"10", "1.e1"}, {"0.1", "1.e-1"}, {"100", "1.e2"}, {"0.01", "1.e-2"}, {"1E0", "1.e0"}, {"1e0", "1.e0"}, {"01e0", "1.e0"}, {"01.e0", "1.e0"}, {"1e1", "1.e1"}, {"1e-1", "1.e-1"}, {"1.e-1", "1.e-1"}, {"1.0e-1", "1.e-1"}, {"01.0e-1", "1.e-1"}, {"0.1e-1", "1.e-2"}, {"10e-1", "1.e0"}, {"100e-1", "1.e1"}, {"1e1000", "1.e1000"}, {"1e-1000", "1.e-1000"}, {"1.234567890123456789e0", "1.23456789012345e0"}, {"1E3000000000000000000000000000000", "NaN"}, {"1E-3000000000000000000000000000000", "NaN"}, }; int save; char buf[30]; printf("testing float_setscientific, 1. block\n"); save = float_setrange(MAXEXP); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_setscientific(testcases[i].value, testcases[i].result)) return tc_fail(i); float_setrange(save); printf("testing float_setscientific, 2. block\n"); maxexp(buf, "2.e"); /* maximum exponent 2.eMAXEXP */ if (!tc_setscientific(buf, buf)) return tc_fail(0); buf[1] = '0'; /* combined overflow 20eMAXEXP */ if (!tc_setscientific(buf, "NaN")) return tc_fail(1); ++buf[strlen(buf)-1]; buf[1] = '.'; /* overflow limit 2.e(MAXEXP+1) */ if (!tc_setscientific(buf, "NaN")) return tc_fail(2); minexp(buf, "1.e"); /* minimum exponent */ if (!tc_setscientific(buf, buf)) return tc_fail(3); buf[0] = '.'; buf[1] = '1'; /* combined underflow */ if (!tc_setscientific(buf, "NaN")) return tc_fail(4); buf[0] = '1'; buf[1] = '.'; ++buf[strlen(buf)-1]; /* underflow limit */ if (!tc_setscientific(buf, "NaN")) return tc_fail(5); return 1; } static int tc_setinteger(int value) { floatstruct f, g; char buf[50]; char r[50]; int err; sprintf(r, "%d", value); float_create(&f); float_create(&g); float_geterror(); float_setinteger(&f, value); err = float_geterror(); float_setasciiz(&g, r); float_getscientific(buf, 50, &f); float_getscientific(r, 50, &g); float_free(&f); float_free(&g); return strcmp(buf, r) == 0 && err == Success; } static int test_setinteger() { int i; static struct{ int value; } testcases[] = { {0}, {1}, {9}, {10}, {-1}, {-9}, {-10}, {maxi}, {mini}, }; printf("testing float_setinteger\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_setinteger(testcases[i].value)) return tc_fail(i); return 1; } static int tc_neg(const char* value, signed char result, int error) { floatstruct f; unsigned h; int errcode; signed char sign; char retvalue; char err; float_create(&f); float_setasciiz(&f, value); h = hash(&f); float_geterror(); err = float_neg(&f); errcode = float_geterror(); sign = float_getsign(&f); if (sign != 0) float_neg(&f); retvalue = result == sign && h == hash(&f) && errcode == error && logequiv(errcode, !err); float_free(&f); return retvalue; } static int test_neg() { int i; static struct{ const char* value; signed char result; int error; } testcases[] = { {"NaN", 0, NoOperand}, {"0", 0, Success}, {"1.23", -1, Success}, {"-1.23", 1, Success}, }; printf("testing float_changesign\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_neg(testcases[i].value, testcases[i].result, testcases[i].error)) return tc_fail(i); return 1; } static int tc_abs(const char* value, int error) { floatstruct f; unsigned h; int errcode; signed char sign; char err, retvalue; float_create(&f); float_setasciiz(&f, value); sign = float_getsign(&f); h = hash(&f); float_geterror(); err = float_abs(&f); errcode = float_geterror(); if (sign) retvalue = float_getsign(&f) == 1; else retvalue = float_getsign(&f) == 0; float_setsign(&f, sign); retvalue = retvalue && h == hash(&f) && error == errcode && logequiv(!err, errcode); float_free(&f); return retvalue; } static int test_abs() { int i; static struct{ const char* value; int error; } testcases[] = { {"NaN", NoOperand}, {"0", Success}, {"1.23", Success}, {"-1.23", Success}, }; printf("testing float_abs\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_abs(testcases[i].value, testcases[i].error)) return tc_fail(i); return 1; } static int tc_cmp(const char* val1, const char* val2, signed char result) { floatstruct v1; floatstruct v2; signed char revres, res; float_create(&v1); float_create(&v2); float_setscientific(&v1, val1, NULLTERMINATED); float_setscientific(&v2, val2, NULLTERMINATED); float_geterror(); revres = float_cmp(&v2, &v1); if (revres != UNORDERED) revres = -revres; else if (float_geterror() != NoOperand) return 0; res = float_cmp(&v1, &v2); if (res == UNORDERED && float_geterror() != NoOperand) return 0; float_free(&v1); float_free(&v2); return res == result && revres == result && float_geterror() == Success; } static int test_cmp() { int i; static struct{ const char* value1; const char* value2; signed char result; } testcases[] = { {"NaN", "NaN", UNORDERED}, {"NaN", "0", UNORDERED}, {"NaN", "1", UNORDERED}, {"NaN", "-1", UNORDERED}, {"0", "0", 0}, {"1", "0", 1}, {"10", "0", 1}, {".1", "0", 1}, {"-1", "0", -1}, {"-10", "0", -1}, {"-.1", "0", -1}, {"1", "10", -1}, {"1", "1", 0}, {"1", ".1", 1}, {"1", "-10", 1}, {"1", "-1", 1}, {"1", "-.1", 1}, {"-1", "10", -1}, {"-1", ".1", -1}, {"-1", "-10", 1}, {"-1", "-.1", -1}, {"-1", "-1", 0}, {"1.01", "1", 1}, {"1.01", "1.02", -1}, {"1.021", "1.011", 1}, {"1.011", "1.01", 1}, {"1.011", "1.011", 0}, {"-1.01", "-1", -1}, {"-1.01", "-1.02", 1}, {"-1.021", "-1.011", -1}, {"-1.011", "-1.01", -1}, {"-1.011", "-1.011", 0}, }; printf("testing float_cmp\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_cmp(testcases[i].value1, testcases[i].value2, testcases[i].result)) return tc_fail(i); return 1; } static int tc_copy(const char* source, int digits, int error, const char* result) { floatstruct src, dest; floatnum s, d; int refs, save, code; char err, retvalue; char buf[60]; refs = _one_->n_refs; float_create(&src); float_create(&dest); s = &src; d = &dest; dest.significand = bc_copy_num(_one_); dest.exponent = 12; save = float_setprecision(50); float_setasciiz(s, source); float_setprecision(save); float_geterror(); err = float_copy(d, s, digits); code = float_geterror(); float_getscientific(buf, sizeof(buf), d); retvalue = refs == _one_->n_refs && code == error && logequiv(code, !err) && strcmp(result, buf) == 0; if (retvalue) { err = float_copy(s, s, digits); code = float_geterror(); float_getscientific(buf, sizeof(buf), d); retvalue = code == error && logequiv(code, !err) && strcmp(result, buf) == 0; } float_free(s); float_free(d); return retvalue; } static int test_copy() { int i; static struct{ const char* src; int digits; const char* result; int error; } testcases[] = { {"NaN", -10, "NaN", InvalidPrecision}, {"NaN", EXACT, "NaN", Success}, {"NaN", 0, "NaN", InvalidPrecision}, {"NaN", 1, "NaN", Success}, {"NaN", 15, "NaN", Success}, {"NaN", 16, "NaN", InvalidPrecision}, {"0", -10, "NaN", InvalidPrecision}, {"0", EXACT, "0", Success}, {"0", 0, "NaN", InvalidPrecision}, {"0", 1, "0", Success}, {"0", 15, "0", Success}, {"0", 16, "NaN", InvalidPrecision}, {"12305", EXACT, "1.2305e4", Success}, {"12305", -1, "NaN", InvalidPrecision}, {"12305", 0, "NaN", InvalidPrecision}, {"12305", 1, "1.e4", Success}, {"12305", 2, "1.2e4", Success}, {"12305", 3, "1.23e4", Success}, {"12305", 4, "1.23e4", Success}, {"12305", 5, "1.2305e4", Success}, {"12305", 6, "1.2305e4", Success}, {"-12305", 5, "-1.2305e4", Success}, {"1.234567890123456789", 0, "NaN", InvalidPrecision}, {"1.234567890123456789", 1, "1.e0", Success}, {"1.234567890123456789", 14, "1.2345678901234e0", Success}, {"1.234567890123456789", 15, "1.23456789012345e0", Success}, {"1.23456789012345006789", 16, "NaN", InvalidPrecision}, {"1.23456789012345006789", EXACT, "NaN", InvalidPrecision}, }; printf("testing float_copy\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_copy(testcases[i].src, testcases[i].digits, testcases[i].error, testcases[i].result)) return tc_fail(i); return 1; } static int tc_move(const char* value) { floatstruct f, g; int save, refs, code; char retvalue; char buf[50]; float_create(&f); refs = _one_->n_refs; g.significand = bc_copy_num(_one_); g.exponent = 12; save = float_setprecision(50); float_setasciiz(&f, value); float_setprecision(save); float_geterror(); float_move(&g, &f); code = float_geterror(); float_getscientific(buf, sizeof(buf), &g); retvalue = refs == _one_->n_refs && float_isnan(&f) && strcmp(buf, value) == 0 && code == Success; float_free(&g); return retvalue; } static int test_move() { int i; static struct{ const char* value; } testcases[] = { {"NaN"}, {"0"}, {"1.e0"}, {"1.e-1"}, {"1.e1"}, {"-1.e1"}, {"1.234567890123456789e0"}, }; printf("testing float_move\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_move(testcases[i].value)) return tc_fail(i); return 1; } static int tc_round(const char* value, int digits, const char* up, const char* down, int roundflags, Error error) { floatstruct f, g; Error code; int flag, refs, save, cmp, cd; char buf[50]; roundmode rm; char err; float_create(&f); flag = 1; refs = _one_->n_refs; g.significand = bc_copy_num(_one_); g.exponent = 0; save = float_setprecision(50); float_setasciiz(&f, value); float_setprecision(save); float_geterror(); err = float_round(&g, &f, digits, 5); code = float_geterror(); if (err != 0 || code != InvalidParam || !float_isnan(&g) || refs != _one_->n_refs) return 0; for (rm = TONEAREST; rm <= TOMINUSINFINITY; ++rm) { refs = _one_->n_refs; g.significand = bc_copy_num(_one_); g.exponent = 0; save = float_setprecision(50); float_setasciiz(&f, value); float_setprecision(save); float_geterror(); err = float_round(&g, &f, digits, rm); code = float_geterror(); float_getscientific(buf, sizeof(buf), &g); cd = Success; if ((flag & roundflags) != 0) { if (*up == 'N') cd = error; cmp = strcmp(buf, up); } else { if (*down == 'N') cd = error; cmp = strcmp(buf, down); } if (cmp != 0 || code != cd || !logequiv(code, !err)) return 0; float_geterror(); err = float_round(&f, &f, digits, rm); code = float_geterror(); float_getscientific(buf, sizeof(buf), &f); cd = Success; if ((flag & roundflags) != 0) { if (*up == 'N') cd = error; cmp = strcmp(buf, up); } else { if (*down == 'N') cd = error; cmp = strcmp(buf, down); } if (cmp != 0 || code != cd || !logequiv(code, !err)) return 0; flag *=2; } float_free(&f); float_free(&g); return 1; } #define FN 1 #define FZ 2 #define FI 4 #define FU 8 #define FD 16 static int test_round() { int i; static struct{ const char* value; int digits; const char* up; const char* down; int roundflags; Error error; } testcases[] = { {"NaN", -1, "NaN", "NaN", 0, InvalidPrecision}, {"NaN", 0, "NaN", "NaN", 0, InvalidPrecision}, {"NaN", 16, "NaN", "NaN", 0, InvalidPrecision}, {"NaN", 1, "NaN", "NaN", 0, NoOperand}, {"0", -1, "NaN", "NaN", 0, InvalidPrecision}, {"0", 0, "NaN", "NaN", 0, InvalidPrecision}, {"0", 16, "NaN", "NaN", 0, InvalidPrecision}, {"0", 1, "0", "0", 0, Success}, {"1", -1, "NaN", "NaN", 0, InvalidPrecision}, {"1", 0, "NaN", "NaN", 0, InvalidPrecision}, {"1", 16, "NaN", "NaN", 0, InvalidPrecision}, {"1", 1, "1.e0", "1.e0", 0, Success}, {"1", 2, "1.e0", "1.e0", 0, Success}, {"1", 15, "1.e0", "1.e0", 0, Success}, {"-1", -1, "NaN", "NaN", 0, InvalidPrecision}, {"-1", 0, "NaN", "NaN", 0, InvalidPrecision}, {"-1", 16, "NaN", "NaN", 0, InvalidPrecision}, {"-1", 1, "-1.e0", "-1.e0", 0, Success}, {"-1", 2, "-1.e0", "-1.e0", 0, Success}, {"-1", 15, "-1.e0", "-1.e0", 0, Success}, {"1.903", 1, "2.e0", "1.e0", FN+FI+FU, Success}, {"1.903", 2, "2.e0", "1.9e0", FI+FU, Success}, {"1.903", 3, "1.91e0", "1.9e0", FI+FU, Success}, {"1.903", 4, "1.903e0", "1.903e0", 0, Success}, {"1.903", 5, "1.903e0", "1.903e0", 0, Success}, {"19.03", 1, "2.e1", "1.e1", FN+FI+FU, Success}, {"19.03", 2, "2.e1", "1.9e1", FI+FU, Success}, {"19.03", 3, "1.91e1", "1.9e1", FI+FU, Success}, {"19.03", 4, "1.903e1", "1.903e1", 0, Success}, {"19.03", 5, "1.903e1", "1.903e1", 0, Success}, {"0.1903", 1, "2.e-1", "1.e-1", FN+FI+FU, Success}, {"0.1903", 2, "2.e-1", "1.9e-1", FI+FU, Success}, {"0.1903", 3, "1.91e-1", "1.9e-1", FI+FU, Success}, {"0.1903", 4, "1.903e-1", "1.903e-1", 0, Success}, {"0.1903", 5, "1.903e-1", "1.903e-1", 0, Success}, {"-1.903", 1, "-1.e0", "-2.e0", FZ+FU, Success}, {"-1.903", 2, "-1.9e0", "-2.e0", FN+FZ+FU, Success}, {"-1.903", 3, "-1.9e0", "-1.91e0", FN+FZ+FU, Success}, {"-1.903", 4, "-1.903e0", "-1.903e0", 0, Success}, {"-1.903", 5, "-1.903e0", "-1.903e0", 0, Success}, {"1.29903", 1, "2.e0", "1.e0", FI+FU, Success}, {"1.29903", 2, "1.3e0", "1.2e0", FN+FI+FU, Success}, {"1.29903", 3, "1.3e0", "1.29e0", FN+FI+FU, Success}, {"1.29903", 4, "1.3e0", "1.299e0", FI+FU, Success}, {"1.29903", 5, "1.2991e0", "1.299e0", FI+FU, Success}, {"1.29903", 6, "1.29903e0", "1.29903e0", 0, Success}, {"9.99", 1, "1.e1", "9.e0", FN+FI+FU, Success}, {"9.99", 2, "1.e1", "9.9e0", FN+FI+FU, Success}, {"9.99", 3, "9.99e0", "9.99e0", 0, Success}, {"1.5", 1, "2.e0", "1.e0", FN+FI+FU, Success}, {"2.5", 1, "3.e0", "2.e0", FI+FU, Success}, {"9.99e100", 1, "NaN", "9.e100", FN+FI+FU, Overflow}, {"9.99e100", 2, "NaN", "9.9e100", FN+FI+FU, Overflow}, {"9.99e100", 3, "9.99e100", "9.99e100", 0, Success}, {"9.995e100", 3, "NaN", "9.99e100", FN+FI+FU, Overflow}, }; int save; printf("testing float_round\n"); save = float_setrange(100); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_round(testcases[i].value, testcases[i].digits, testcases[i].up, testcases[i].down, testcases[i].roundflags, testcases[i].error)) return tc_fail(i); float_setrange(save); return 1; } static int tc_add(char* msg, char* val1, char* val2, int digits, char* result) { floatstruct v1; floatstruct v2; floatstruct b1; floatstruct b2; floatstruct sum; int lg; char ok; char buf[30]; float_create(&v1); float_create(&v2); float_create(&b1); float_create(&b2); float_create(&sum); printf("%s", msg); float_setscientific(&v1, val1, NULLTERMINATED); float_setscientific(&v2, val2, NULLTERMINATED); float_copy(&b1, &v1, EXACT); float_copy(&b2, &v2, EXACT); float_add(&sum, &v1, &v2, digits); float_getscientific(buf, 30, &sum); lg = strlen(result); ok = _cmp(&v1, &b1) == 0 && _cmp(&v2, &b2) == 0 && lg == strlen(buf) && memcmp(buf, result, lg) == 0? TRUE : FALSE; float_free(&v1); float_free(&v2); float_free(&b1); float_free(&b2); float_free(&sum); return ok; } static int test_add() { floatstruct v1; floatstruct v2; floatstruct save; char nmb[30]; char nmb2[30]; printf("\ntesting float_add\n"); float_create(&v1); float_create(&v2); float_create(&save); maxexp(nmb, "+9.9e"); if (!tc_add("invalid length\n", "0", "0", 0, "NaN")) return FALSE; if (!tc_add("NaN, both op\n", "NaN", "NaN", 3, "NaN")) return FALSE; if (!tc_add("NaN, first op\n", "NaN", "0", 3, "NaN")) return FALSE; if (!tc_add("NaN, second op\n", "0", "NaN", 3, "NaN")) return FALSE; if (!tc_add("0 + 0\n", "0", "0", 3, "0")) return FALSE; if (!tc_add("0 + 1\n", "0", "1", 3, "1.e0")) return FALSE; if (!tc_add("1 + 0\n", "1", "0", 3, "1.e0")) return FALSE; if (!tc_add("1 + 1\n", "1", "1", EXACT, "2.e0")) return FALSE; if (!tc_add("1 + 0.1\n", "1", "0.1", EXACT, "1.1e0")) return FALSE; if (!tc_add("0.1 + 1\n", "0.1", "1", EXACT, "1.1e0")) return FALSE; if (!tc_add("scale overflow, 1E-20 + 1\n", "1.E-20", "1", EXACT, "NaN")) return FALSE; if (!tc_add("1E-20 + 1\n", "1.E-20", "1", 10, "1.e0")) return FALSE; if (!tc_add("1.234 + 0.1\n", "1.234", "0.1", EXACT, "1.334e0")) return FALSE; if (!tc_add("1.234 + 0.12345\n", "1.234", "0.12345", EXACT, "1.35745e0")) return FALSE; if (!tc_add("1.234 + 0.12345, lg 5\n", "1.234", "0.12345", 5, "1.3574e0")) return FALSE; if (!tc_add("1.234 + 0.12345, lg 4\n", "1.234", "0.12345", 4, "1.357e0")) return FALSE; if (!tc_add("1.234 + 0.12345, lg 3\n", "1.234", "0.12345", 3, "1.35e0")) return FALSE; if (!tc_add("1.234 + 0.12345, lg 2\n", "1.234", "0.12345", 2, "1.3e0")) return FALSE; if (!tc_add("1.234 + 0.12345, lg 1\n", "1.234", "0.12345", 1, "1.e0")) return FALSE; if (!tc_add("123.001 + (-122.85)\n", "123.001", "-122.85", 1, "2.e-1")) return FALSE; if (!tc_add("123.0014 + (-122.954)\n", "123.0014", "-122.954", 1, "5.e-2")) return FALSE; if (!tc_add("123.0014 + (-122.9954)\n", "123.0014", "-122.9954", 1, "6.e-3")) return FALSE; if (!tc_add("123 + (-122.9954)\n", "123", "-122.9954", 1, "5.e-3")) return FALSE; if (!tc_add("2 + (-1.9954)\n", "2", "-1.9954", 1, "5.e-3")) return FALSE; if (!tc_add("(-1.9954) + 2\n", "-1.9954", "2", 1, "5.e-3")) return FALSE; if (!tc_add("1 + (-0.9954)\n", "1", "-0.9954", 1, "5.e-3")) return FALSE; if (!tc_add("1.00001 + (-0.9954)\n", "1.00001", "-0.9954", 1, "5.e-3")) return FALSE; if (!tc_add("1.00001 + (-0.99)\n", "1.00001", "-0.99", 1, "1.e-2")) return FALSE; if (!tc_add("1.00001 + (-0.9999999)\n", "1.00001", "-0.9999999", 1, "2.e-5")) return FALSE; if (!tc_add("max + 1E-10000\n", nmb, "1E-10000", 2, nmb+1)) return FALSE; if (!tc_add("overflow\n", nmb, nmb, 2, "NaN")) return FALSE; if (!tc_add("2 + (-1)\n", "2", "-1", 2, "1.e0")) return FALSE; if (!tc_add("(-1) + 2\n", "-1", "2", 2, "1.e0")) return FALSE; if (!tc_add("2 + (-0.1)\n", "2", "-0.1", EXACT, "1.9e0")) return FALSE; if (!tc_add("1 + (-0.1)\n", "1", "-0.1", EXACT, "9.e-1")) return FALSE; if (!tc_add("1 + (-0.1), lg 1\n", "1", "-0.1", 1, "9.e-1")) return FALSE; if (!tc_add("123 + (-100)\n", "123", "-100", EXACT, "2.3e1")) return FALSE; if (!tc_add("(-123) + 100\n", "-123", "100", EXACT, "-2.3e1")) return FALSE; if (!tc_add("123 + (-120)\n", "123", "-120", EXACT, "3.e0")) return FALSE; if (!tc_add("123 + (-124)\n", "123", "-124", EXACT, "-1.e0")) return FALSE; if (!tc_add("123 + (-123)\n", "123", "-123", EXACT, "0")) return FALSE; if (!tc_add("123.04 + (-123)\n", "123.04", "-123", EXACT, "4.e-2")) return FALSE; if (!tc_add("123.04 + (-123)\n", "123.04", "-123", 1, "4.e-2")) return FALSE; if (!tc_add("123.24 + (-123.11)\n", "123.24", "-123.11", 1, "1.3e-1")) return FALSE; if (!tc_add("123.046 + (-123.115)\n", "123.046", "-123.115", 1, "-7.e-2")) return FALSE; if (!tc_add("123 + (-120), lg 1\n", "123", "-120", 1, "3.e0")) return FALSE; if (!tc_add("underflow\n", minexp(nmb, "1.1e"), minexp(nmb2, "-1e"), 5, "NaN")) return FALSE; if (!tc_add("underflow due to borrow\n", minexp(nmb, "2.0001e"), minexp(nmb2, "-1.99955e"), 5, "NaN")) return FALSE; if (!tc_add("underflow due to cancel\n", minexp(nmb, "1.234e"), minexp(nmb2, "-1.231e"), 5, "NaN")) return FALSE; printf("%s\n", "in place add, first"); float_setscientific(&v1, "120", NULLTERMINATED); float_setscientific(&v2, "-3.4e-1", NULLTERMINATED); float_copy(&save, &v2, EXACT); float_add(&v1, &v1, &v2, EXACT); float_getscientific(nmb, 30, &v1); if (memcmp("1.1966e2", nmb, 9) != 0 || _cmp(&v2, &save) != 0) return FALSE; printf("%s\n", "in place add, second"); float_copy(&save, &v1, EXACT); float_add(&v2, &v1, &v2, EXACT); float_getscientific(nmb, 30, &v2); if (memcmp("1.1932e2", nmb, 9) != 0 || _cmp(&v1, &save) != 0) return FALSE; printf("%s\n", "in place add, both"); float_add(&v2, &v2, &v2, EXACT); float_getscientific(nmb, 30, &v2); if (memcmp("2.3864e2", nmb, 9) != 0) return FALSE; float_free(&v1); float_free(&v2); float_free(&save); return TRUE; } static int tc_sub(char* msg, char* val1, char* val2, int digits, char* result) { floatstruct v1; floatstruct v2; floatstruct b1; floatstruct b2; floatstruct diff; int lg; char ok; char buf[30]; float_create(&v1); float_create(&v2); float_create(&b1); float_create(&b2); float_create(&diff); printf("%s", msg); float_setscientific(&v1, val1, NULLTERMINATED); float_setscientific(&v2, val2, NULLTERMINATED); float_copy(&b1, &v1, EXACT); float_copy(&b2, &v2, EXACT); float_sub(&diff, &v1, &v2, digits); float_getscientific(buf, 30, &diff); lg = strlen(result); ok = _cmp(&v1, &b1) == 0 && _cmp(&v2, &b2) == 0 && lg == strlen(buf) && memcmp(buf, result, lg) == 0? TRUE : FALSE; float_free(&v1); float_free(&v2); float_free(&b1); float_free(&b2); float_free(&diff); return ok; } static int test_sub() { floatstruct v1; floatstruct v2; floatstruct save; char nmb[30]; printf("\ntesting float_sub\n"); float_create(&v1); float_create(&v2); float_create(&save); if (!tc_sub("invalid length\n", "0", "0", 0, "NaN")) return FALSE; if (!tc_sub("NaN, both op\n", "NaN", "NaN", 3, "NaN")) return FALSE; if (!tc_sub("NaN, first op\n", "NaN", "0", 3, "NaN")) return FALSE; if (!tc_sub("NaN, second op\n", "0", "NaN", 3, "NaN")) return FALSE; if (!tc_sub("0 - 0\n", "0", "0", 3, "0")) return FALSE; if (!tc_sub("0 - 1\n", "0", "1", 3, "-1.e0")) return FALSE; if (!tc_sub("1 - 0\n", "1", "0", 3, "1.e0")) return FALSE; if (!tc_sub("1 - 1\n", "1", "1", EXACT, "0")) return FALSE; if (!tc_sub("1 - 0.1\n", "1", "0.1", EXACT, "9.e-1")) return FALSE; if (!tc_sub("0.1 - 1\n", "0.1", "1", EXACT, "-9.e-1")) return FALSE; printf("%s\n", "in place sub, first"); float_setscientific(&v1, "120", NULLTERMINATED); float_setscientific(&v2, "-3.4e-1", NULLTERMINATED); float_copy(&save, &v2, EXACT); float_sub(&v1, &v1, &v2, EXACT); float_getscientific(nmb, 30, &v1); if (memcmp("1.2034e2", nmb, 9) != 0 || _cmp(&v2, &save) != 0) return FALSE; printf("%s\n", "in place sub, second"); float_copy(&save, &v1, EXACT); float_sub(&v2, &v1, &v2, EXACT); float_getscientific(nmb, 30, &v2); if (memcmp("1.2068e2", nmb, 9) != 0 || _cmp(&v1, &save) != 0) return FALSE; printf("%s\n", "in place sub, both"); float_sub(&v2, &v2, &v2, EXACT); if (!float_iszero(&v2)) return FALSE; float_free(&v1); float_free(&v2); float_free(&save); return TRUE; } static int tc_mul(char* msg, char* val1, char* val2, int digits, char* result) { floatstruct v1; floatstruct v2; floatstruct b1; floatstruct b2; floatstruct prod; int lg; char ok; char buf[30]; float_create(&v1); float_create(&v2); float_create(&b1); float_create(&b2); float_create(&prod); printf("%s", msg); float_setscientific(&v1, val1, NULLTERMINATED); float_setscientific(&v2, val2, NULLTERMINATED); float_copy(&b1, &v1, EXACT); float_copy(&b2, &v2, EXACT); float_mul(&prod, &v1, &v2, digits); float_getscientific(buf, 30, &prod); lg = strlen(result); ok = _cmp(&v1, &b1) == 0 && _cmp(&v2, &b2) == 0 && lg == strlen(buf) && memcmp(buf, result, lg) == 0? TRUE : FALSE; float_free(&v1); float_free(&v2); float_free(&b1); float_free(&b2); float_free(&prod); return ok; } static int test_mul() { floatstruct v1; floatstruct v2; floatstruct save; char nmb[30]; char nmb2[30]; printf("\ntesting float_mul\n"); float_create(&v1); float_create(&v2); float_create(&save); if (!tc_mul("invalid length\n", "0", "0", 0, "NaN")) return FALSE; if (!tc_mul("NaN, both op\n", "NaN", "NaN", 3, "NaN")) return FALSE; if (!tc_mul("NaN, first op\n", "NaN", "0", 3, "NaN")) return FALSE; if (!tc_mul("NaN, second op\n", "0", "NaN", 3, "NaN")) return FALSE; if (!tc_mul("0 * 0\n", "0", "0", 3, "0")) return FALSE; if (!tc_mul("0 * 1\n", "0", "1", 3, "0")) return FALSE; if (!tc_mul("1 * 0\n", "1", "0", 3, "0")) return FALSE; if (!tc_mul("1 * 1\n", "1", "1", EXACT, "1.e0")) return FALSE; if (!tc_mul("1 * -1\n", "1", "-1", EXACT, "-1.e0")) return FALSE; if (!tc_mul("-1 * 1\n", "-1", "1", EXACT, "-1.e0")) return FALSE; if (!tc_mul("-1 * -1\n", "-1", "-1", EXACT, "1.e0")) return FALSE; if (!tc_mul("2 * 3\n", "2", "3", EXACT, "6.e0")) return FALSE; if (!tc_mul("3 * 4\n", "3", "4", EXACT, "1.2e1")) return FALSE; if (!tc_mul("123 * 456\n", "123", "456", EXACT, "5.6088e4")) return FALSE; if (!tc_mul("3E100 * 4E-100\n", "3E100", "4E-100", EXACT, "1.2e1")) return FALSE; if (!tc_mul("big exp diff\n", maxexp(nmb, "5e"), minexp(nmb2, "2e"), EXACT, "1.e0")) return FALSE; if (!tc_mul("almost overflow\n", maxexp(nmb, "4.9e"), "2", EXACT, maxexp(nmb2, "9.8e"))) return FALSE; if (!tc_mul("overflow\n", maxexp(nmb, "5e"), "2", EXACT, "NaN")) return FALSE; if (!tc_mul("big overflow\n", maxexp(nmb, "5e"), nmb, EXACT, "NaN")) return FALSE; if (!tc_mul("almost underflow\n", minexp(nmb, "5e"), "0.2", EXACT, minexp(nmb2, "1.e"))) return FALSE; if (!tc_mul("underflow\n", minexp(nmb, "4e"), "0.2", EXACT, "NaN")) return FALSE; if (!tc_mul("big underflow\n", minexp(nmb, "1e"), nmb, EXACT, "NaN")) return FALSE; if (!tc_mul("scale overflow\n", "1.2345678901", "1.2345678901", EXACT, "NaN")) return FALSE; printf("%s\n", "in place mul, first"); float_setscientific(&v1, "2", NULLTERMINATED); float_setscientific(&v2, "-3", NULLTERMINATED); float_copy(&save, &v2, EXACT); float_mul(&v1, &v1, &v2, EXACT); float_getscientific(nmb, 30, &v1); if (memcmp("-6.e0", nmb, 6) != 0 || _cmp(&v2, &save) != 0) return FALSE; printf("%s\n", "in place mul, second"); float_copy(&save, &v1, EXACT); float_mul(&v2, &v1, &v2, EXACT); float_getscientific(nmb, 30, &v2); if (memcmp("1.8e1", nmb, 6) != 0 || _cmp(&v1, &save) != 0) return FALSE; printf("%s\n", "in place mul, both"); float_mul(&v2, &v2, &v2, EXACT); float_getscientific(nmb, 30, &v2); if (memcmp("3.24e2", nmb, 7) != 0) return FALSE; float_free(&v1); float_free(&v2); float_free(&save); return TRUE; } static int tc_div(char* msg, char* val1, char* val2, int digits, char* result) { floatstruct v1; floatstruct v2; floatstruct b1; floatstruct b2; floatstruct quot; int lg; char ok; char buf[30]; float_create(&v1); float_create(&v2); float_create(&b1); float_create(&b2); float_create("); printf("%s", msg); float_setscientific(", "1.823452", NULLTERMINATED); float_setscientific(&v1, val1, NULLTERMINATED); float_setscientific(&v2, val2, NULLTERMINATED); float_copy(&b1, &v1, EXACT); float_copy(&b2, &v2, EXACT); float_div(", &v1, &v2, digits); float_getscientific(buf, 30, "); lg = strlen(result); ok = _cmp(&v1, &b1) == 0 && _cmp(&v2, &b2) == 0 && lg == strlen(buf) && memcmp(buf, result, lg) == 0? TRUE : FALSE; float_free(&v1); float_free(&v2); float_free(&b1); float_free(&b2); float_free("); return ok; } static int test_div() { floatstruct v1; floatstruct v2; floatstruct save; char nmb[30]; char nmb2[30]; printf("\ntesting float_div\n"); float_create(&v1); float_create(&v2); float_create(&save); if(!tc_div("invalid digits\n", "1", "1", EXACT, "NaN")) return FALSE; if(!tc_div("NaN, both\n", "NaN", "NaN", 5, "NaN")) return FALSE; if(!tc_div("NaN, first\n", "NaN", "1", 5, "NaN")) return FALSE; if(!tc_div("NaN, second\n", "1", "NaN", 5, "NaN")) return FALSE; if(!tc_div("0/1\n", "0", "1", 5, "0")) return FALSE; if(!tc_div("1/0\n", "1", "0", 5, "NaN")) return FALSE; if(!tc_div("0/0\n", "0", "0", 5, "NaN")) return FALSE; if(!tc_div("1/1\n", "1", "1", 5, "1.e0")) return FALSE; if(!tc_div("(-1)/1\n", "-1", "1", 5, "-1.e0")) return FALSE; if(!tc_div("1/(-1)\n", "1", "-1", 5, "-1.e0")) return FALSE; if(!tc_div("(-1)/(-1)\n", "-1", "-1", 5, "1.e0")) return FALSE; if(!tc_div("1/2\n", "1", "2", 5, "5.e-1")) return FALSE; if(!tc_div("1/3\n", "1", "3", 5, "3.3333e-1")) return FALSE; if(!tc_div("4/3\n", "4", "3", 5, "1.33333e0")) return FALSE; if(!tc_div("40/0.3\n", "40", "0.3", 5, "1.33333e2")) return FALSE; if(!tc_div("0.4/0.03\n", "0.4", "0.03", 5, "1.33333e1")) return FALSE; if(!tc_div("400/30\n", "400", "30", 5, "1.33333e1")) return FALSE; if(!tc_div("400/30000\n", "400", "30000", 5, "1.33333e-2")) return FALSE; if(!tc_div("0.0004/0.3\n", "0.0004", "0.3", 5, "1.33333e-3")) return FALSE; if(!tc_div("integer quotient, 1/3\n", "1", "3", INTQUOT, "0")) return FALSE; if(!tc_div("integer quotient, 4/3\n", "4", "3", INTQUOT, "1.e0")) return FALSE; if(!tc_div("integer quotient, 4/3\n", "4", "3", INTQUOT, "1.e0")) return FALSE; if(!tc_div("integer quotient, 4/3\n", "4", "0.3", INTQUOT, "1.3e1")) return FALSE; if(!tc_div("integer quotient, 1/3\n", "1", "0.3", INTQUOT, "3.e0")) return FALSE; if(!tc_div("integer quotient, 1/30\n", "1", "30", INTQUOT, "0")) return FALSE; if(!tc_div("almost overflow\n", maxexp(nmb, "1.e"), "0.3", 5, maxexp(nmb2, "3.3333e"))) return FALSE; if(!tc_div("overflow\n", maxexp(nmb, "4.e"), "0.3", 5, "NaN")) return FALSE; if(!tc_div("big overflow\n", maxexp(nmb, "4.e"), minexp(nmb2, "1.e"), 5, "NaN")) return FALSE; if(!tc_div("almost underflow\n", minexp(nmb, "4.e"), "3", 5, minexp(nmb2, "1.33333e"))) return FALSE; if(!tc_div("underflow\n", minexp(nmb, "1.e"), "3", 5, "NaN")) return FALSE; if(!tc_div("big underflow\n", minexp(nmb, "1.e"), maxexp(nmb2, "1.e"), 5, "NaN")) return FALSE; if(!tc_div("scale overflow\n", "1", "2", 20, "NaN")) return FALSE; printf("%s\n", "in place div, first"); float_setscientific(&v1, "1", NULLTERMINATED); float_setscientific(&v2, "-2", NULLTERMINATED); float_copy(&save, &v2, EXACT); float_div(&v1, &v1, &v2, 5); float_getscientific(nmb, 30, &v1); if (memcmp("-5.e-1", nmb, 7) != 0 || _cmp(&v2, &save) != 0) return FALSE; printf("%s\n", "in place div, second"); float_copy(&save, &v1, EXACT); float_div(&v2, &v1, &v2, 5); float_getscientific(nmb, 30, &v2); if (memcmp("2.5e-1", nmb, 7) != 0 || _cmp(&v1, &save) != 0) return FALSE; printf("%s\n", "in place div, both"); float_div(&v2, &v2, &v2, 5); float_getscientific(nmb, 30, &v2); if (memcmp("1.e0", nmb, 5) != 0) return FALSE; float_free(&v1); float_free(&v2); float_free(&save); return TRUE; } static int tc_sqrt(char* msg, char* val, int digits, char* result) { floatstruct v; int lg; char buf[30]; printf("%s", msg); float_create(&v); float_setscientific(&v, val, NULLTERMINATED); float_sqrt(&v, digits); float_round(&v, &v, digits - 1, TONEAREST); float_getscientific(buf, 30, &v); float_free(&v); lg = strlen(result); return strlen(buf) == lg && memcmp(buf, result, lg) == 0? TRUE : FALSE; } static int test_sqrt() { printf("\ntesting float_sqrt\n"); if (!tc_sqrt("invalid length\n", "1", 0, "NaN")) return FALSE; if (!tc_sqrt("NaN\n", "NaN", 5, "NaN")) return FALSE; if (!tc_sqrt("negative value\n", "-1", 5, "NaN")) return FALSE; if (!tc_sqrt("0\n", "0", 5, "0")) return FALSE; if (!tc_sqrt("1\n", "1", 5, "1.e0")) return FALSE; if (!tc_sqrt("4\n", "4", 5, "2.e0")) return FALSE; if (!tc_sqrt("16\n", "16", 5, "4.e0")) return FALSE; if (!tc_sqrt("0.64\n", "0.64", 5, "8.e-1")) return FALSE; if (!tc_sqrt("0.04\n", "0.04", 5, "2.e-1")) return FALSE; return TRUE; } static int tc_int(char* msg, char* value, char* result) { floatstruct f; int lg; char buf[30]; printf("%s", msg); float_create(&f); float_setscientific(&f, value, NULLTERMINATED); float_int(&f); float_getscientific(buf, 30, &f); lg = strlen(result); float_free(&f); return (lg == strlen(buf) && memcmp(buf, result, lg) == 0); } static int test_int() { printf("\ntesting float_int\n"); if (!tc_int("NaN\n", "NaN", "NaN")) return FALSE; if (!tc_int("0\n", "0", "0")) return FALSE; if (!tc_int("1\n", "1", "1.e0")) return FALSE; if (!tc_int("10\n", "10", "1.e1")) return FALSE; if (!tc_int("10.1\n", "10.1", "1.e1")) return FALSE; if (!tc_int("0.1\n", "0.1", "0")) return FALSE; if (!tc_int("-1\n", "-1", "-1.e0")) return FALSE; if (!tc_int("-10\n", "-10", "-1.e1")) return FALSE; if (!tc_int("-10.1\n", "-10.1", "-1.e1")) return FALSE; if (!tc_int("-0.1\n", "-0.1", "0")) return FALSE; return TRUE; } static int tc_frac(char* msg, char* value) { floatstruct f, r; printf("%s", msg); float_create(&f); float_create(&r); float_setscientific(&f, value, NULLTERMINATED); float_copy(&r, &f, EXACT); float_int(&r); float_sub(&r, &f, &r, EXACT); float_frac(&f); return _cmp(&f, &r) == 0; } static int test_frac() { printf("\ntesting float_frac\n"); if (!tc_frac("NaN\n", "NaN")) return FALSE; if (!tc_frac("0\n", "0")) return FALSE; if (!tc_frac("1\n", "1")) return FALSE; if (!tc_frac("10\n", "10")) return FALSE; if (!tc_frac("10.1\n", "10.1")) return FALSE; if (!tc_frac("0.1\n", "0.1")) return FALSE; if (!tc_frac("-1\n", "-1")) return FALSE; if (!tc_frac("-10\n", "-10")) return FALSE; if (!tc_frac("-10.1\n", "-10.1")) return FALSE; if (!tc_frac("-0.1\n", "-0.1")) return FALSE; if (!tc_frac("10.000000001\n", ".000000001")) return FALSE; return TRUE; } static int tc_divmod(char* msg, char* dvd, char* dvs, int dig, char* q, char* r) { int result; floatstruct v1; floatstruct v2; floatstruct b1; floatstruct b2; floatstruct r1; floatstruct r2; printf("%s", msg); float_create(&v1); float_create(&v2); float_create(&b1); float_create(&b2); float_create(&r1); float_create(&r2); float_setscientific(&r1, "-1.821923", NULLTERMINATED); float_setscientific(&r2, "-1.821923", NULLTERMINATED); float_setscientific(&v1, dvd, NULLTERMINATED); float_setscientific(&v2, dvs, NULLTERMINATED); float_copy(&b1, &v1, EXACT); float_copy(&b2, &v2, EXACT); float_divmod(&r1, &r2, &v1, &v2, dig); result = (scmp(&r1, q) && scmp(&r2, r) && _cmp(&v1, &b1) == 0 && _cmp(&v2, &b2) == 0); float_free(&v1); float_free(&v2); float_free(&b1); float_free(&b2); float_free(&r1); float_free(&r2); return result; } static int test_divmod() { floatstruct f1; floatstruct f2; floatstruct f3; floatstruct vlg; int save; char nmb1[30]; char nmb2[30]; printf("\ntesting float_divmod\n"); float_create(&f1); float_create(&f2); float_create(&f3); float_create(&vlg); float_setinteger(&f1, 1); printf("%s", "test rem == quot\n"); float_divmod(&f1, &f1, &f1, &f1, 5); if (!float_isnan(&f1)) return FALSE; if (!tc_divmod("NaN, both\n", "NaN", "NaN", 5, "NaN", "NaN")) return FALSE; if (!tc_divmod("NaN, 1. op\n", "NaN", "1", 5, "NaN", "NaN")) return FALSE; if (!tc_divmod("NaN, 2. op\n", "1", "NaN", 5, "NaN", "NaN")) return FALSE; if (!tc_divmod("invalid digits\n", "1", "1", -5, "NaN", "NaN")) return FALSE; if (!tc_divmod("test divide by 0\n", "1", "0", 5, "NaN", "NaN")) return FALSE; if (!tc_divmod("test scale too long\n", "1", "1", 100, "NaN", "NaN")) return FALSE; if (!tc_divmod("0/1\n", "0", "1", 5, "0", "0")) return FALSE; if (!tc_divmod("1/100, INTQUOT\n", "1", "100", INTQUOT, "0", "1.e0")) return FALSE; if (!tc_divmod("INTQUOT, scale too long\n", "1e100", "1", INTQUOT, "NaN", "NaN")) return FALSE; if (!tc_divmod("1/2, INTQUOT\n", "1", "2", INTQUOT, "0", "1.e0")) return FALSE; if (!tc_divmod("3/2, INTQUOT\n", "3", "2", INTQUOT, "1.e0", "1.e0")) return FALSE; if (!tc_divmod("4/2, INTQUOT\n", "4", "2", INTQUOT, "2.e0", "0")) return FALSE; if (!tc_divmod("213/13, lg 3\n", "213", "13", 3, "1.63e1", "1.1e0")) return FALSE; if (!tc_divmod("17/16, INTQUOT\n", "17", "16", INTQUOT, "1.e0", "1.e0")) return FALSE; if (!tc_divmod("1.7/1.6, INTQUOT\n", "1.7", "1.6", INTQUOT, "1.e0", "1.e-1")) return FALSE; if (!tc_divmod("1.7/1.6, lg 3\n", "1.7", "1.6", 3, "1.06e0", "4.e-3")) return FALSE; if (!tc_divmod("underflow in quot\n", minexp(nmb1, "1.7e"), "1.6e1", 3, "NaN", "NaN")) return FALSE; if (!tc_divmod("overflow in quot\n", maxexp(nmb1, "1.7e"), "1.6e-1", 3, "NaN", "NaN")) return FALSE; if (!tc_divmod("underflow in rem\n", minexp(nmb1, "1.7e"), minexp(nmb2, "1.6e"), INTQUOT, "NaN", "NaN")) return FALSE; printf("%s", "long divisor\n"); float_setzero(&f1); float_setzero(&f2); save = float_setprecision(20); float_setasciiz(&f3, "12345678901234567890"); float_copy(&vlg, &f3, EXACT); float_setprecision(save); float_divmod(&f1, &f2, &f3, &f3, 3); if (!float_isnan(&f1) || !float_isnan(&f2) || float_cmp(&vlg, &f3) != 0) return FALSE; printf("%s", "dividend and divisor overwritten by quotient\n"); float_setinteger(&f1, 2); float_setnan(&f2); float_divmod(&f1, &f2, &f1, &f1, 3); if (!scmp(&f1, "1.e0") || !scmp(&f2, "0")) return FALSE; printf("%s", "dividend and divisor overwritten by remainder\n"); float_setinteger(&f1, 2); float_setnan(&f2); float_divmod(&f2, &f1, &f1, &f1, 3); if (!scmp(&f2, "1.e0") || !scmp(&f1, "0")) return FALSE; printf("%s", "dividend overwritten by quotient, divisor by remainder\n"); float_setinteger(&f1, 213); float_setinteger(&f2, 13); float_divmod(&f1, &f2, &f1, &f2, 3); if (!scmp(&f1, "1.63e1") || !scmp(&f2, "1.1e0")) return FALSE; printf("%s", "dividend overwritten by remainder, divisor by quotient\n"); float_setinteger(&f1, 213); float_setinteger(&f2, 13); float_divmod(&f2, &f1, &f1, &f2, 3); if (!scmp(&f2, "1.63e1") || !scmp(&f1, "1.1e0")) return FALSE; float_free(&f1); float_free(&f2); float_free(&f3); float_free(&vlg); return TRUE; } static void _relerror(floatnum x1, floatnum x2) { float_sub(x1, x1, x2, 3); if (!float_iszero(x1)) float_div(x1, x1, x2, 3); float_abs(x1); } static char _cmprelerror(floatnum x1, floatnum x2, int exp) { _relerror(x1, x2); return (float_iszero(x1) || float_getexponent(x1) < exp); } static void _sub_ulp(floatnum x, int sz) { floatstruct delta; if (!float_iszero(x)) { float_create(&delta); float_setinteger(&delta, 1); float_setexponent(&delta, float_getexponent(x)-sz); float_setsign(&delta, float_getsign(x)); float_sub(x, x, &delta, EXACT); float_free(&delta); } } static int test_coshminus1near0() { floatstruct x, x1, tmp, max; int i; char buf[50]; float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("%s\n", "testing coshminus1near0"); printf("verifying special argument x == 0:\n"); float_setzero(&x); coshminus1near0(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } /* testing the validity of the series evaluation */ printf("verifying result:\n"); float_setasciiz(&x, "0.005"); float_setasciiz(&tmp, ".000012500026041688368065243678286383060391" "9872831398280829063464786043942297654015309" "5900368700065231210065496027359337789353280" "9524874015321513239965"); coshminus1near0(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".00001"); for (i = -1; ++i <= 1000;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); coshminus1near0(&x,100); coshminus1near0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _coshminus1near0: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_artanhnear0() { floatstruct x, x1, tmp, max; int i; char buf[50]; float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("%s\n", "testing artanhnear0"); printf("verifying special argument x == 0:\n"); float_setzero(&x); artanhnear0(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } /* testing correct replacement of artanh by id */ printf("small x handling:\n"); float_setasciiz(&x, "6.7e-51"); float_copy(&x1, &x, EXACT); artanhnear0(&x, 100); artanhnear0(&x1, 110); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED\n"); return 0; } /* testing the validity of the series evaluation */ printf("verifying result:\n"); float_setasciiz(&x, "0.01"); artanhnear0(&x, 100); float_setasciiz(&x1,".0100003333533347620158821075514042238870" "97308807344335621654492648224836625944612" "34119694455592889442890269461918262602394" "9110421598243"); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setscientific(&tmp, ".0001", NULLTERMINATED); for (i = -101; ++i <= 100;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); artanhnear0(&x,100); artanhnear0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error artanhnear0: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_arctannear0() { floatstruct x, x1, tmp, max; int i; char buf[50]; float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("%s\n", "testing arctannear0"); printf("verifying special argument x == 0:\n"); float_setzero(&x); arctannear0(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } /* testing correct replacement of arctan by id */ printf("small x handling:\n"); float_setasciiz(&x, "6.7e-51"); float_copy(&x1, &x, EXACT); arctannear0(&x, 100); arctannear0(&x1, 110); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED\n"); return 0; } /* testing the validity of the series evaluation */ printf("verifying result:\n"); float_setasciiz(&x, "0.01"); arctannear0(&x, 100); float_setasciiz(&x1,".00999966668666523820634011620927954856136935" "254437663962793941819645655320405877997944664" "518667409041670798128407565295492085345632123"); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED for x == 0.01\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setscientific(&tmp, ".0001", NULLTERMINATED); for (i = -101; ++i <= 100;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); arctannear0(&x,100); arctannear0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error arctannear0: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_cosminus1near0() { floatstruct x, x1, tmp, max; int i; char buf[50]; float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("%s\n", "testing cosminus1near0"); printf("verifying special argument x == 0:\n"); float_setzero(&x); cosminus1near0(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } /* testing the validity of the series evaluation */ printf("verifying result:\n"); float_setasciiz(&x, "0.01"); cosminus1near0(&x, 100); float_setasciiz(&x1,"-.4999958333472221974206624779332678752941601" "972288887772423135353991187035650836487445623" "870262734376943805848695816541718420700624513737e-4"); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED for x == 0.01\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setscientific(&tmp, ".0001", NULLTERMINATED); for (i = -1; ++i <= 100;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); cosminus1near0(&x,100); cosminus1near0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error cosminus1near0: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_lnxplus1near0() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("testing _lnxplus1near0\n"); float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); /* verifying function result */ printf("verifying result:\n"); float_setasciiz(&x, "0.01"); float_setasciiz(&tmp,".009950330853168082848215357544260741688" "6796099400587978646095597668666642476389" "1103268569656276016116452560517384648478"); _lnxplus1near0(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("verifying special argument x == 0:\n"); float_setzero(&x); _lnxplus1near0(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } /* overall scan for maximum relative error */ printf("testing error limit:\n"); float_setzero(&max); float_setscientific(&tmp, ".0002", NULLTERMINATED); for (i = -100; ++i <= 100;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _lnxplus1near0(&x,100); _lnxplus1near0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _lnxplus1near0: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_lnreduce() { floatstruct max, x, step, delta, ofs, tmp, lnfactor, cmp; int i; char buf[50]; printf("testing _reduce\n"); float_create(&x); float_create(&max); float_create(&step); float_create(&delta); float_create(&ofs); float_create(&tmp); float_create(&lnfactor); float_create(&cmp); float_setzero(&max); float_setasciiz(&step, "0.01"); float_setasciiz(&ofs, "0.005"); float_setasciiz(&delta, "0.0049999999"); float_setasciiz(&cmp, "0.01"); printf("testing boundary case -0.4\n"); float_setasciiz(&x, "-.4"); _lnreduce(&x, &lnfactor, 10); float_abs(&x); if (float_cmp(&x, &cmp) > 0) { float_getscientific(buf, 50, &x); printf("reduction failed for x=-0.4: %s\n", buf); return 0; } float_abs(&lnfactor); float_getsignificand(buf, 1, &lnfactor); if (float_getexponent(&lnfactor) >= 0 || (float_getexponent(&lnfactor) == -1 && buf[0] >= '7')) { printf("guess incorrect for x=-0.4\n"); return 1; } for (i = -41; ++i < 100;) { if (i == -1 || i == 0) continue; float_muli(&tmp, &step, i, EXACT); float_add(&tmp, &tmp, &ofs, EXACT); float_sub(&x, &tmp, &delta, EXACT); _lnreduce(&x, &lnfactor, 10); float_abs(&x); if(float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_cmp(&x, &cmp) > 0) { float_getscientific(buf, 50, &x); printf("reduction failed for test case %d: %s\n", i, buf); return 0; } } float_abs(&lnfactor); float_getsignificand(buf, 1, &lnfactor); if (float_getexponent(&lnfactor) >= 0 || (float_getexponent(&lnfactor) == -1 && buf[0] >= '7')) { printf("guess incorrect for test case %d\n", i); return 1; } float_add(&x, &tmp, &delta, EXACT); _lnreduce(&x, &lnfactor, 10); float_abs(&x); if(float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_cmp(&x, &cmp) >0) { float_getscientific(buf, 50, &x); printf("reduction failed for test case %d: %s\n", i, buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max reduced value: %s\n", buf); float_free(&x); float_free(&max); float_free(&step); float_free(&delta); float_free(&ofs); float_free(&tmp); float_free(&lnfactor); float_free(&cmp); return 1; } static int test_lnxplus1lt1() { floatstruct x, x1, max, step, ofs, tmp, ref; int i; char buf[50]; printf("testing _lnxplus1lt1\n"); float_create(&x); float_create(&max); float_create(&step); float_create(&ofs); float_create(&tmp); float_create(&ref); printf("verifying special argument x == 0:\n"); float_setzero(&x); _lnxplus1lt1(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } printf("verifying special argument x == -0.4:\n"); float_copy(&x, &cMinus0_4, EXACT); _lnxplus1lt1(&x, 100); float_setasciiz(&x1, "-.510825623765990683205514096303661934878110" "79644576827017795355783668469448904879775651" "81232794475220119962739557576971573560010034"); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED\n"); return 0; } printf("verifying function results\n"); float_setasciiz(&step, "0.005"); float_copy(&ref, &step, EXACT); float_copy(&x, &step, EXACT); _lnxplus1near0(&ref, 130); i = 1; while(float_cmp(&x, &c1) < 0) { float_copy(&x1, &x, EXACT); _lnxplus1lt1(&x, 100); float_muli(&tmp, &ref, i, 130); _relerror(&tmp, &x); if (float_getexponent(&tmp) >= -99) { float_getscientific(buf, 50, &tmp); printf("%s\n", buf); printf("FAILED for test case %d\n", i); return 0; } float_mul(&tmp, &step, &x1, 130); float_add(&tmp, &tmp, &step, EXACT); float_add(&x, &x1, &tmp, 130); ++i; } float_setasciiz(&step, "-0.005"); float_copy(&ref, &step, EXACT); float_copy(&x, &step, EXACT); _lnxplus1near0(&ref, 130); i = 1; while(float_cmp(&x, &cMinus0_4) >= 0) { float_copy(&x1, &x, EXACT); _lnxplus1lt1(&x, 100); float_muli(&tmp, &ref, i, 130); _relerror(&tmp, &x); if (float_getexponent(&tmp) >= -99) { float_getscientific(buf, 50, &tmp); printf("%s\n", buf); printf("FAILED for test case %d\n", i); return 0; } float_mul(&tmp, &step, &x1, 130); float_add(&tmp, &tmp, &step, EXACT); float_add(&x, &x1, &tmp, 130); ++i; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.01"); float_setasciiz(&ofs, "0.00117436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = -41; ++i < 100;) { float_setinteger(&tmp, i); float_mul(&tmp, &tmp, &step, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _lnxplus1lt1(&x, 100); _lnxplus1lt1(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _lnxplus1: %s\n", buf); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); float_free(&tmp); float_free(&ref); return 1; } static int test_ln() { floatstruct x, max, step, ofs, tmp; int i; char buf[50]; printf("testing _ln\n"); float_create(&x); float_create(&max); float_create(&step); float_create(&ofs); float_create(&tmp); printf("verifying special argument x == 1:\n"); float_copy(&x, &c1, EXACT); _ln(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } printf("verifying function results:\n"); for (i = 1; ++i < 10;) { switch(i) { case 2: float_copy(&tmp, &cLn2, 110); break; case 3: float_copy(&tmp, &cLn3, 110); break; case 4: float_muli(&tmp, &cLn2, 2, 110); break; case 5: float_sub(&tmp, &cLn10, &cLn2, 110); break; case 6: float_add(&tmp, &cLn2, &cLn3, 110); break; case 7: float_copy(&tmp, &cLn7, 110); break; case 8: float_muli(&tmp, &cLn2, 3, 110); break; case 9: float_muli(&tmp, &cLn3, 2, 110); break; } float_setinteger(&x, i); _ln(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { float_getscientific(buf, 50, &tmp); printf("FAILED for argument %d: %s\n", i, buf); return 0; } } printf("testing exponent handling\n"); float_setinteger(&x, 20); _ln(&x, 100); float_add(&tmp, &cLn2, &cLn10, 110); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for exponent 1\n"); return 0; } float_setasciiz(&x, "0.2"); _ln(&x, 100); float_sub(&tmp, &cLn2, &cLn10, 110); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for exponent -1\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.05"); float_setasciiz(&ofs, "0.00147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 19; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); if (i > 63) float_setexponent(&tmp, -1); float_copy(&tmp, &x, EXACT); _ln(&x, 100); _ln(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _ln: %s\n", buf); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); float_free(&tmp); return 1; } static int test_lnxplus1() { floatstruct x, x1; printf("testing _lnxplus1\n"); float_create(&x); float_create(&x1); printf("verifying function results:\n"); float_setasciiz(&x, "-.3"); _lnxplus1(&x, 100); float_copy(&x1, &cLn7, 110); float_sub(&x1, &x1, &cLn10, 110); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED x == -0.3\n"); return 0; } float_setasciiz(&x, "6"); _lnxplus1(&x, 100); if (!_cmprelerror(&x, &cLn7, -99)) { printf("FAILED x == 6\n"); return 0; } float_free(&x); float_free(&x1); return 1; } static int test_artanh1minusx() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _artanh1minusx\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_copy(&x, &c1Div2, EXACT); _artanh1minusx(&x, 100); float_copy(&tmp, &cLn3, 110); float_mul(&tmp, &tmp, &c1Div2, 110); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.01"); float_setasciiz(&ofs, "0.00147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 50;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _artanh1minusx(&x, 100); _artanh1minusx(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _artanh1minusx: %s\n", buf); float_free(&x); float_free(&tmp); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_artanhlt0_5() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _artanhlt0_5\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_copy(&x, &c1Div2, EXACT); _artanhlt0_5(&x, 100); float_copy(&tmp, &cLn3, 110); float_mul(&tmp, &tmp, &c1Div2, 110); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.01"); float_setasciiz(&ofs, "0.00147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 50;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _artanhlt0_5(&x, 100); _artanhlt0_5(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _artanh1minusx: %s\n", buf); float_free(&x); float_free(&tmp); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_arsinh() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arsinh\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _arsinh(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "1e-1000"); float_copy(&tmp, &x, EXACT); _arsinh(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==1e-1000\n"); return 0; } float_setasciiz(&x, "0.1"); float_setasciiz(&tmp, ".099834078899207563327303124704769443267712" "9117088250107423826956515917683936134651063" "484492769032061884984061246778732266658350084462074"); _arsinh(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==0.1\n"); return 0; } float_setasciiz(&x, "4"); float_setasciiz(&tmp, "2.09471254726110129424482284606552865345315" "1048198673265886805979926247949695627249150" "4293654887408011476586881386829965289261091"); _arsinh(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==4\n"); return 0; } float_setasciiz(&x, "1e100"); float_muli(&tmp, &cLn10, 100, 110); float_add(&tmp, &tmp, &cLn2, 110); _arsinh(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==1e100\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.05"); float_setasciiz(&ofs, "0.00147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arsinh(&x, 100); _arsinh(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arsinh: %s\n", buf); float_free(&x); float_free(&tmp); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_arcoshxplus1() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arcoshxplus1\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _arcoshxplus1(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setinteger(&x, 10); float_setasciiz(&tmp, "3.08896990484460301791647985373629509453345" "4441136435131225532448209215351305027698930" "521085626874864770396311532541165684221072841899917"); _arcoshxplus1(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==10\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.05"); float_setasciiz(&ofs, "0.00147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arcoshxplus1(&x, 100); _arcoshxplus1(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } for(i = 0; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arcoshxplus1(&x, 100); _arcoshxplus1(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arcoshxplus1: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_coshminus1lt1() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _coshminus1lt1"); float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("verifying special argument x == 0:\n"); float_setzero(&x); _coshminus1lt1(&x, 100); if (!float_iszero(&x)) { printf("FAILED x== 0\n"); return 0; } /* testing the validity of the reduction */ printf("verifying result:\n"); float_setasciiz(&x, "0.5"); float_copy(&tmp, &x, EXACT); float_arcoshxplus1(&x, 110); _coshminus1lt1(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for arcosh(1.5)-1\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".001"); for (i = -1; ++i <= 1000;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _coshminus1lt1(&x,100); _coshminus1lt1(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _coshminus1lt1: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_sinhlt1() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _sinhlt1"); float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("verifying special argument x == 0:\n"); float_setzero(&x); _sinhlt1(&x, 100); if (!float_iszero(&x)) { printf("FAILED for x== 0\n"); return 0; } printf("verifying positive result:\n"); float_setasciiz(&x, "1"); float_copy(&tmp, &x, EXACT); float_arsinh(&x, 110); _sinhlt1(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("verifying negative result:\n"); float_setasciiz(&x, "-1"); float_copy(&tmp, &x, EXACT); float_arsinh(&x, 110); _sinhlt1(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".001"); for (i = -1; ++i <= 1000;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _sinhlt1(&x,100); _sinhlt1(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _sinhlt1: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_expminus1lt1() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _expminus1lt1"); float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("verifying special argument x == 0:\n"); float_setzero(&x); _expminus1lt1(&x, 100); if (!float_iszero(&x)) { printf("FAILED for x== 0\n"); return 0; } printf("verifying positive result:\n"); float_setasciiz(&x, "1"); float_copy(&tmp, &x, EXACT); float_lnxplus1(&x, 110); _expminus1lt1(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("verifying negative result:\n"); float_setasciiz(&x, "-.5"); float_copy(&tmp, &x, EXACT); float_lnxplus1(&x, 110); _expminus1lt1(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".001"); for (i = -1001; ++i <= 1000;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _expminus1lt1(&x,100); _expminus1lt1(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _expminus1lt1: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_expltln10() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _expltln10"); float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("verifying special argument x == 0:\n"); float_setzero(&x); _expltln10(&x, 100); if (float_cmp(&x, &c1) != 0) { printf("FAILED\n"); return 0; } float_setasciiz(&tmp, ".1"); for (i = 0; ++i < 24;) { float_muli(&x1, &tmp, i, EXACT); float_copy(&x, &x1, EXACT); _expltln10(&x, 100); float_ln(&x, 110); if(!_cmprelerror(&x, &x1, -99)) { float_getscientific(buf, 50, &x1); printf("FAILED for x == %s\n", buf); return 0; } } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".005"); for (i = -1; ++i <= 460;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _expltln10(&x,100); _expltln10(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _expltln10: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_exp() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _exp"); float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("verifying special argument x == 0:\n"); float_setzero(&x); _exp(&x, 100); if (float_cmp(&x, &c1) != 0) { printf("FAILED\n"); return 0; } printf("verifying results:\n"); float_setasciiz(&tmp, "1"); for (i = -2; ++i < 9;) { float_setexponent(&tmp, i); float_copy(&x, &tmp, EXACT); _exp(&x, 100); float_ln(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { float_getscientific(buf, 50, &tmp); printf("FAILED for x == %s\n", buf); return 0; } } float_setasciiz(&tmp, "-1"); for (i = -2; ++i < 9;) { float_setexponent(&tmp, i); float_copy(&x, &tmp, EXACT); _exp(&x, 100); float_ln(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { float_getscientific(buf, 50, &tmp); printf("FAILED for x == %s\n", buf); return 0; } } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".005"); for (i = -461; ++i <= 0;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _exp(&x,100); _exp(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_muli(&x, &cLn10, EXPMAX, 110); float_copy(&x1, &x, EXACT); _exp(&x,100); _exp(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for near overflow case: "); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } float_getscientific(buf, 50, &max); printf("max error _exp: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_expminus1() { floatstruct x, tmp; printf("%s\n", "testing _expminus1"); float_create(&x); float_create(&tmp); printf("verifying special argument x == 0:\n"); float_setzero(&x); _expminus1(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } printf("verifying results:\n"); float_setasciiz(&x, "-1e100000"); float_setinteger(&tmp, -1); _expminus1(&x, 100); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == -1e100000\n"); return 0; } float_setasciiz(&x, "-1"); float_setinteger(&tmp, -1); _expminus1(&x, 100); float_lnxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == -1\n"); return 0; } float_setasciiz(&x, "-1e-10"); float_copy(&tmp, &x, EXACT); _expminus1(&x, 100); float_lnxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == -1e-10\n"); return 0; } float_setasciiz(&x, "1e-10"); float_copy(&tmp, &x, EXACT); _expminus1(&x, 100); float_lnxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 1e-10\n"); return 0; } float_setasciiz(&x, "1"); float_copy(&tmp, &x, EXACT); _expminus1(&x, 100); float_lnxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 1\n"); return 0; } float_setasciiz(&x, "100000"); float_copy(&tmp, &x, EXACT); _expminus1(&x, 100); float_lnxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 100000\n"); return 0; } float_free(&tmp); float_free(&x); return 1; } static int test_coshminus1() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _coshminus1"); float_create(&x); float_create(&tmp); float_create(&x1); float_create(&max); float_setzero(&max); printf("verifying function results:\n"); float_setzero(&x); _coshminus1(&x, 100); if (!float_iszero(&x)) { printf("FAILED for x == 0\n"); return 0; } float_setasciiz(&x, ".1"); float_copy(&tmp, &x, EXACT); _coshminus1(&x, 100); float_arcoshxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 0.1\n"); return 0; } float_setasciiz(&x, "2"); float_copy(&tmp, &x, EXACT); _coshminus1(&x, 100); float_arcoshxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 2\n"); return 0; } float_setasciiz(&x, "10000"); float_copy(&tmp, &x, EXACT); _coshminus1(&x, 100); float_arcoshxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 10000\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".005"); for (i = 200; ++i <= 500;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _coshminus1(&x,100); _coshminus1(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _coshminus1: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_tanhlt0_5() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _tanhlt0_5"); float_create(&x); float_create(&tmp); float_create(&x1); float_create(&max); float_setzero(&max); printf("verifying function results:\n"); float_setzero(&x); _tanhlt0_5(&x, 100); if (!float_iszero(&x)) { printf("FAILED for x == 0\n"); return 0; } float_setasciiz(&x, ".1"); float_copy(&tmp, &x, EXACT); _tanhlt0_5(&x, 100); float_artanh(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 0.1\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".005"); for (i = 0; ++i <= 100;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _tanhlt0_5(&x,100); _tanhlt0_5(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _tanhlt0_5: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_tanhminus1gt0() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _tanhminus1gt0"); float_create(&x); float_create(&tmp); float_create(&x1); float_create(&max); float_setzero(&max); float_setasciiz(&x, "1"); float_copy(&tmp, &x, EXACT); _tanhminus1gt0(&x, 100); float_artanhxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 1\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".005"); for (i = 0; ++i <= 300;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _tanhminus1gt0(&x,100); _tanhminus1gt0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } for (i = 1; i <= EXPMAX;) { float_setinteger(&x, 1); _sub_ulp(&x, 101); float_setexponent(&x, i); i*=10; float_copy(&x1, &x, EXACT); _tanhminus1gt0(&x,100); _tanhminus1gt0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _tanhminus1gt0: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_arctanlt1() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arctanlt1\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _arctanlt1(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "-0.5"); float_setasciiz(&tmp, "-.46364760900080611621425623146121440202853" "7054286120263810933088720197864165741705300" "60028398488789255652985225119083751350581818162501"); _arctanlt1(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-0.5\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arctanlt1(&x, 100); _arctanlt1(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arctanlt1: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_arctan() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arctan\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); float_setasciiz(&x, "-1.5"); float_setasciiz(&tmp, "-.98279372324732906798571061101466601449687" "7453631628556761425088317988071549796035389" "70653437281731110816513970201193676622994103918188"); _arctan(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-1.5\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 200; ++i < 400;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arctan(&x, 100); _arctan(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arctan: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_arccosxplus1lt0_5() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arccosxplus1lt0_5\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _arccosxplus1lt0_5(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "-0.5"); float_setasciiz(&tmp, "1.04719755119659774615421446109316762806572" "3133125035273658314864102605468762069666209" "34494178070568932738269550442743554903128153651686"); _arccosxplus1lt0_5(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-0.5\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 100;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arccosxplus1lt0_5(&x, 100); _arccosxplus1lt0_5(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arccosxplus1lt0_5: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_arcsinlt0_5() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arcsinlt0_5\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _arccosxplus1lt0_5(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "-0.5"); float_setasciiz(&tmp, "-.52359877559829887307710723054658381403286" "1566562517636829157432051302734381034833104" "67247089035284466369134775221371777451564076825843"); _arcsinlt0_5(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-0.5\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 100;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arcsinlt0_5(&x, 100); _arcsinlt0_5(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arcsinlt0_5: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_arccos() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arccos\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setinteger(&x, 1); _arccos(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==1\n"); return 0; } float_setasciiz(&x, "0.5"); float_setasciiz(&tmp, "1.04719755119659774615421446109316762806572" "3133125035273658314864102605468762069666209" "34494178070568932738269550442743554903128153651686"); _arccos(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==0.5\n"); return 0; } float_setzero(&x); _arccos(&x, 100); if (!_cmprelerror(&x, &cPiDiv2, -99)) { printf("FAILED for x==0\n"); return 0; } float_setinteger(&x, -1); _arccos(&x, 100); if (!_cmprelerror(&x, &cPi, -99)) { printf("FAILED for x==-1\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.01"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = -100; ++i < 100;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arccos(&x, 100); _arccos(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arccos: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_arcsin() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arcsin\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _arcsin(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "-0.5"); float_setasciiz(&tmp, "-.52359877559829887307710723054658381403286" "1566562517636829157432051302734381034833104" "67247089035284466369134775221371777451564076825843"); _arcsin(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-0.5\n"); return 0; } float_setinteger(&x, 1); _arcsin(&x, 100); if (!_cmprelerror(&x, &cPiDiv2, -99)) { printf("FAILED for x==1\n"); return 0; } float_setinteger(&x, -1); _arcsin(&x, 100); float_neg(&x); if (!_cmprelerror(&x, &cPiDiv2, -99)) { printf("FAILED for x==-1\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arcsin(&x, 100); _arcsin(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arcsin: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_cosminus1ltPiDiv4() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _cosminus1ltPiDiv4\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _cosminus1ltPiDiv4(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "-0.5"); float_setasciiz(&tmp, "-.12241743810962728388371841739617034800835" "4802890255947002389131684049236725786052594" "205815915317741644521599406890946006586172"); _cosminus1ltPiDiv4(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-0.5\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 158;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _cosminus1ltPiDiv4(&x, 100); _cosminus1ltPiDiv4(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _cosminus1ltPiDiv4: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_sinltPiDiv4() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _sinltPiDiv4\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _sinltPiDiv4(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "-0.5"); float_setasciiz(&tmp, "-.47942553860420300027328793521557138808180" "3367940600675188616613125535000287814832209" "63127468434826908613209108450571741781109374860994"); _sinltPiDiv4(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-0.5\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 158;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _sinltPiDiv4(&x, 100); _sinltPiDiv4(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _sinltPiDiv4: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_tanltPiDiv4() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _tanltPiDiv4\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _tanltPiDiv4(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "-0.5"); float_setasciiz(&tmp, "-.54630248984379051325517946578028538329755" "1720179791246164091385932907510518025815715" "1806482706562185891048626002641142654932300911684"); _tanltPiDiv4(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-0.5\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 158;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _tanltPiDiv4(&x, 100); _tanltPiDiv4(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _tanltPiDiv4: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_cos() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _cos\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _cos(&x, 100); if(float_cmp(&x, &c1)!=0) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&step, "0.1"); for (i = 0; ++i < 15;) { float_muli(&x, &step, i, EXACT); float_add(&tmp, &x, &x, EXACT); _cos(&x, 100); _cos(&tmp, 100); float_mul(&x, &x, &x, 110); float_add(&x, &x, &x, EXACT); float_sub(&x, &x, &c1, EXACT); if (!_cmprelerror(&tmp, &x, -95)) { printf("FAILED for testcase %d\n", i); return 0; } } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.05"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = -63; ++i < 63;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _cos(&x, 100); _cos(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _cos: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_sin() { floatstruct x, tmp, max, step, ofs; int i; printf("testing _sin\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _sin(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&step, "0.1"); for (i = 0; ++i < 32;) { float_muli(&x, &step, i, EXACT); float_sub(&tmp, &x, &cPiDiv2, 110); _sin(&x, 100); _cos(&tmp, 100); if (!_cmprelerror(&tmp, &x, -95)) { printf("FAILED for testcase %d\n", i); return 0; } } float_setasciiz(&step, "0.5"); for (i = -7; ++i < 0;) { float_muli(&x, &step, i, EXACT); float_copy(&tmp, &x, EXACT); float_abs(&tmp); _sin(&x, 100); _sin(&tmp, 100); float_neg(&tmp); if (!_cmprelerror(&tmp, &x, -95)) { printf("FAILED for testcase %d\n", i); return 0; } } float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_tan() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _tan\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _tan(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&step, "0.1"); for (i = -32; ++i < 32;) { if (i == 0) continue; float_muli(&x, &step, i, EXACT); float_copy(&tmp, &x, EXACT); float_copy(&ofs, &x, EXACT); _sin(&x, 100); _cos(&tmp, 100); float_div(&tmp, &x, &tmp, 110); _tan(&ofs, 100); if (!_cmprelerror(&tmp, &ofs, -95)) { printf("FAILED for testcase %d\n", i); return 0; } } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.05"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = -63; ++i < 63;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _tan(&x, 100); _tan(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _tan: %s\n", buf); return 1; } static int tc_floatnum2longint(char* value, int lg, unsigned x0, unsigned x1, unsigned x2) { floatstruct x; t_longint longint; float_create(&x); float_setasciiz(&x, value); _floatnum2longint(&longint, &x); float_free(&x); return lg == longint.length && (lg == 0 || x0 == longint.value[0]) && (lg < 32 || x1 == longint.value[1]) && (lg < 64 || x2 == longint.value[2]); } static int test_floatnum2longint() { /* depends on wordsize!! */ printf("testing floatnum2longint\n"); if (!tc_floatnum2longint("0", 0, 0, 0, 0)) return 0; if (!tc_floatnum2longint("1", 1, 1, 0, 0)) return 0; if (!tc_floatnum2longint("1234567890", 1, 1234567890, 0, 0)) return 0; if (!tc_floatnum2longint("8589934592", 2, 0, 2, 0)) return 0; return 1; } static int tc_longint2floatnum(unsigned x0, unsigned x1, unsigned x2, int lg, char* value) { /* depends on wordsize!! */ floatstruct x, y; t_longint l; int i; float_create(&x); float_create(&y); for (i = 0; i < UARRAYLG; ++i) l.value[i] = 0; l.value[0] = x0; l.value[1] = x1; l.value[2] = x2; l.length = lg; float_setasciiz(&y, value); _longint2floatnum(&x, &l); if (float_cmp(&x, &y) != 0) { printf("conversion FAILED"); return 0; } float_free(&x); float_free(&y); return 1; } static int test_longint2floatnum() { printf("testing longint2floatnum\n"); if (!tc_longint2floatnum(0, 0, 0, 0, "0")) return 0; if (!tc_longint2floatnum(1, 0, 0, 1, "1")) return 0; if (!tc_longint2floatnum(2000000000, 0, 0, 1, "2000000000")) return 0; if (!tc_longint2floatnum(0, 2, 0, 2, "8589934592")) return 0; if (!tc_longint2floatnum(1000000, 2, 0, 2, "8590934592")) return 0; return 1; } static int tc_raiseposi(char* base, unsigned exponent) { floatstruct x, y; int expx, r, result; float_create(&x); float_create(&y); float_setasciiz(&x, base); float_copy(&y, &x, EXACT); float_abs(&y); float_log(&y, 100); r = _raiseposi(&x, &expx, exponent, 100); float_abs(&x); float_log(&x, 199); float_addi(&x, &x, expx, 100); float_divi(&x, &x, exponent, 100); result = _cmprelerror(&x, &y, 95); float_free(&x); float_free(&y); return result; } static int test_raiseposi() { floatstruct x, tmp, max, step, ofs; int expx; int i, j; char buf[50]; printf("testing _raiseposi\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); if (!tc_raiseposi("1", 1)) return 0; if (!tc_raiseposi("2", 1)) return 0; if (!tc_raiseposi("2", 2)) return 0; if (!tc_raiseposi("2", 3)) return 0; float_setinteger(&x, -1); _raiseposi(&x, &expx, 3, 100); if (float_cmp(&x, &cMinus1) != 0 || expx != 0) { printf("test case -1 ^ 3 FAILED"); return 0; } _raiseposi(&x, &expx, 2, 100); if (float_cmp(&x, &c1) != 0 || expx != 0) { printf("test case -1 ^ 2 FAILED"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "1"); float_setasciiz(&ofs, "1.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for (j = 0; j++ < 30;) for(i = 0; ++i < 10;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _raiseposi(&x, &expx, (1 << j)-1, 100); _raiseposi(&tmp, &expx, (1 << j)-1, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _raiseposi: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_raisei() { floatstruct x, y; printf ("testing _raisei\n"); float_create(&x); float_create(&y); float_copy(&x, &c1, EXACT); _raisei(&x, 0, 100); if (float_cmp(&x, &c1) != 0) { printf("test case 1^0 FAILED\n"); return 0; } _raisei(&x, 1, 100); if (float_cmp(&x, &c1) != 0) { printf("test case 1^1 FAILED\n"); return 0; } _raisei(&x, 100, 100); if (float_cmp(&x, &c1) != 0) { printf("test case 1^100 FAILED\n"); return 0; } float_copy(&x, &c2, EXACT); _raisei(&x, 0, 100); if (float_cmp(&x, &c1) != 0) { printf("test case 2^0 FAILED\n"); return 0; } float_copy(&x, &c2, EXACT); _raisei(&x, 1, 100); if (float_cmp(&x, &c2) != 0) { printf("test case 2^1 FAILED\n"); return 0; } float_setinteger(&y, 4); _raisei(&x, 2, 100); if (float_cmp(&x, &y) != 0) { printf("test case 2^2 FAILED\n"); return 0; } float_copy(&x, &c2, EXACT); _raisei(&x, -1, 100); if (float_cmp(&x, &c1Div2) != 0) { printf("test case 2^-1 FAILED\n"); return 0; } float_free(&y); float_free(&x); return 1; } static int test_lngammaasymptotic() { floatstruct x, y, tmp; int i; printf("testing lngammaseries\n"); float_create(&x); float_create(&y); float_create(&tmp); printf("verifying result\n"); float_setinteger(&tmp, 77); float_ln(&tmp, 110); float_setasciiz(&y, "76.5"); float_mul(&tmp, &tmp, &y, 110); float_setinteger(&y, 2); for (i = 2; ++i < 77;) float_muli(&y, &y, i, EXACT); float_ln(&y, 110); float_sub(&y, &y, &tmp, 110); float_addi(&y, &y, 77, 110); float_sub(&y, &y, &cLnSqrt2PiMinusHalf, 110); float_sub(&y, &y, &c1Div2, 110); float_setinteger(&x, 77); lngammaasymptotic(&x, 100); if (!_cmprelerror(&y, &x, -95)) { printf("verification FAILED\n"); return 0; } float_free(&x); float_free(&y); float_free(&tmp); return 1; } static int tc_pochhammer(char* x, char* n, char* result) { floatstruct fx, fn, fr; float_create(&fx); float_create(&fn); float_create(&fr); float_setasciiz(&fx, x); float_setasciiz(&fn, n); float_setasciiz(&fr, result); float_pochhammer(&fx, &fn, 100); if (float_isnan(&fr)) return float_isnan(&fx); if (!_cmprelerror(&fr, &fx, -95)) { printf("verification FAILED\n"); return 0; } return 1; } static int test_pochhammer() { printf("testing _pochhammer\n"); printf("verifying results\n"); if (!tc_pochhammer("0", "0", "1")) return 0; if (!tc_pochhammer("1", "0", "1")) return 0; if (!tc_pochhammer("-1", "0", "1")) return 0; if (!tc_pochhammer("1e100000", "0", "1")) return 0; if (!tc_pochhammer("-1e100000", "0", "1")) return 0; if (!tc_pochhammer("0.5", "0", "1")) return 0; if (!tc_pochhammer("-0.5", "0", "1")) return 0; if (!tc_pochhammer("0", "1", "0")) return 0; if (!tc_pochhammer("1", "1", "1")) return 0; if (!tc_pochhammer("-1", "1", "-1")) return 0; if (!tc_pochhammer("1e100000", "1", "1e100000")) return 0; if (!tc_pochhammer("-1e100000", "1", "-1e100000")) return 0; if (!tc_pochhammer("0.5", "1", "0.5")) return 0; if (!tc_pochhammer("-0.5", "1", "-0.5")) return 0; if (!tc_pochhammer("0", "2", "0")) return 0; if (!tc_pochhammer("1", "2", "2")) return 0; if (!tc_pochhammer("-1", "2", "0")) return 0; if (!tc_pochhammer("1e100000", "2", "1e200000")) return 0; if (!tc_pochhammer("-1e100000", "2", "1e200000")) return 0; if (!tc_pochhammer("0.5", "2", "0.75")) return 0; if (!tc_pochhammer("-0.5", "2", "-0.25")) return 0; if (!tc_pochhammer("1", "100", "93326215443944152681699238856266700490715968264381621468592963895217" "59999322991560894146397615651828625369792082722375825118521091686400" "0000000000000000000000")) return 0; if (!tc_pochhammer("-100", "101", "0")) return 0; if (!tc_pochhammer("-100", "100", "93326215443944152681699238856266700490715968264381621468592963895217" "59999322991560894146397615651828625369792082722375825118521091686400" "0000000000000000000000")) return 0; if (!tc_pochhammer("1", "-1", "NaN")) return 0; if (!tc_pochhammer("2", "-1", "1")) return 0; if (!tc_pochhammer("2", "-2", "NaN")) return 0; if (!tc_pochhammer("1.5", "-1", "2")) return 0; if (!tc_pochhammer("1.5", "-2", "-4")) return 0; if (!tc_pochhammer("1.5", "-100", "-.000000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000378414024807910640737099845525006763221785165860" "06641218189552393913245454474853055919575212143764296945522753626016" "300639832411419246985800884362")) return 0; if (!tc_pochhammer("-1.5", "100", "40242764267707289912333641217950774848709656376758843494819950464847" "04420564703857828107982141126998570896720926829585700250010032188267" "20546901916750645.18900647214084211566623156559209401240552373723543")) return 0; if (!tc_pochhammer("-3", "-1", "-0.25")) return 0; if (!tc_pochhammer("-1e100000", "-1", "-1e-100000")) return 0; if (!tc_pochhammer("-2.2", "1.3", "4.793948981105061902495028514824576929486499142574590370996037700670" "07956370445687178188113235399766021571905874962934089400569549735499" "47062783690929661636680480933415006255499710782394427770555172981506")) return 0; return 1; } static int test_lngamma() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _lngamma\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying results\n"); float_copy(&x, &c3, EXACT); _lngamma(&x, 100); if(!_cmprelerror(&x, &cLn2, -95)) { printf("verification FAILED\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.05"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 100; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _lngamma(&x, 100); _lngamma(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _lngamma: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_gamma() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _gamma\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying results\n"); float_setasciiz(&x, "0.2"); float_setasciiz(&tmp, "4.590843711998803053204758275929152003434109998293403" "01778885313623003927310644499897403940828778507456912"); _gamma(&x, 100); if(!_cmprelerror(&x, &tmp, -95)) { printf("verification FAILED\n"); return 0; } float_setasciiz(&x, "-30.2"); float_setasciiz(&tmp, "-1.0165368282364803216788184978362164979757349922035594" "1791712115025420329582124053302476303836291973429411315e-32"); _gamma(&x, 100); if(!_cmprelerror(&x, &tmp, -95)) { printf("verification FAILED\n"); return 0; } float_setasciiz(&x, "-1.5"); float_setasciiz(&tmp, "0.75"); float_div(&tmp, &cSqrtPi, &tmp, 110); _gamma(&x, 100); if(!_cmprelerror(&x, &tmp, -95)) { printf("verification FAILED\n"); return 0; } float_setasciiz(&x, "10"); float_setasciiz(&tmp, "362880"); _gamma(&x, 100); if(!_cmprelerror(&x, &tmp, -95)) { printf("verification FAILED\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.05"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 100; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _gamma(&x, 100); _gamma(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } printf("testing asymptotic series of gamma:\n"); for(i = 0; ++i < 100;) { float_setasciiz(&x, "1.01"); printf("testing precision %d: ", i); _gamma(&x, i); printf("asymptotic series converging\n"); } float_getscientific(buf, 50, &max); printf("max error _gamma: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_gammaint() { floatstruct x, y; printf("testing _gammaint\n"); float_create(&x); float_create(&y); printf("verifying results\n"); float_setinteger(&x, 1); float_setinteger(&y, 1); _gammaint(&x, 100); if (float_cmp(&x, &y) != 0) { printf("verification FAILED\n"); return 0; } float_setinteger(&x, 2); float_setinteger(&y, 1); _gammaint(&x, 100); if (float_cmp(&x, &y) != 0) { printf("verification FAILED\n"); return 0; } float_setinteger(&x, 3); float_setinteger(&y, 2); _gammaint(&x, 100); if (float_cmp(&x, &y) != 0) { printf("verification FAILED\n"); return 0; } float_free(&x); float_free(&y); return 1; } static int tc_gamma0_5(char* value) { floatstruct x, y; float_create(&x); float_create(&y); float_setasciiz(&x, value); float_copy(&y, &x, EXACT); _gamma0_5(&x, 100); _gamma(&y, 100); if (!_cmprelerror(&x, &y, -95)) { printf("verification FAILED\n"); return 0; } float_free(&x); float_free(&y); return 1; } static int test_gamma0_5() { printf("testing _gamma0_5\n"); printf("verifying results\n"); if (!tc_gamma0_5(".5")) return 0; if (!tc_gamma0_5("-.5")) return 0; if (!tc_gamma0_5("1.5")) return 0; if (!tc_gamma0_5("-1.5")) return 0; if (!tc_gamma0_5("-30.5")) return 0; if (!tc_gamma0_5("30.5")) return 0; return 1; } static int tc_floatnum2logic(char* value, unsigned x0, unsigned x1, unsigned x2) { floatstruct x; t_longint r; float_create(&x); float_setasciiz(&x, value); _floatnum2logic(&r, &x); float_free(&x); return r.value[0] == x0 && r.value[1] == x1 && r.value[2] == x2; } static int test_floatnum2logic() { /* based on the size of unsigned */ printf("testing _floatnum2logic\n"); if(!tc_floatnum2logic("0", 0, 0, 0)) return 0; if(!tc_floatnum2logic("1", 1, 0, 0)) return 0; if(!tc_floatnum2logic("-1", ~0, ~0, ~0)) return 0; if(!tc_floatnum2logic("-2147483648", ~2147483647, ~0, ~0)) return 0; if(!tc_floatnum2logic("8589934592", 0, 2, 0)) return 0; return 1; } static int tc_logic2floatnum(char* value) { t_longint l; floatstruct x, y; float_create(&x); float_create(&y); float_setasciiz(&x, value); _floatnum2logic(&l, &x); _logic2floatnum(&y, &l); if (float_cmp(&x, &y) != 0) { printf("test case %s FAILED\n", value); return 0; } float_free(&x); float_free(&y); return 1; } static int test_logic2floatnum() { printf("testing _logic2floatnum\n"); if(!tc_logic2floatnum("0")) return 0; if(!tc_logic2floatnum("1")) return 0; if(!tc_logic2floatnum("-1")) return 0; if(!tc_logic2floatnum("-2147483648")) return 0; if(!tc_logic2floatnum("-2147483649")) return 0; if(!tc_logic2floatnum("4294967295")) return 0; if(!tc_logic2floatnum("-4294967296")) return 0; if(!tc_logic2floatnum("8589934592")) return 0; return 1; } static int tc_not(char* value, char* result) { floatstruct x, y; float_create(&x); float_create(&y); float_setasciiz(&x, value); float_setasciiz(&y, result); float_not(&x); if (float_cmp(&x, &y) != 0) return 0; float_free(&x); float_free(&y); return 1; } static int test_not() { printf("testing float_not\n"); if (!tc_not("0", "-1")) return 0; if (!tc_not("1", "-2")) return 0; if (!tc_not("-1", "0")) return 0; if (!tc_not("-2", "1")) return 0; return 1; } static int test_and() { floatstruct x, y; printf("testing float_and\n"); float_create(&x); float_create(&y); float_setasciiz(&x, "5"); float_setasciiz(&y, "6"); float_and(&x, &x, &y); float_setasciiz(&y, "4"); if (float_cmp(&x, &y) != 0) return 0; float_free(&x); float_free(&y); return 1; } static int test_or() { floatstruct x, y; printf("testing float_or\n"); float_create(&x); float_create(&y); float_setasciiz(&x, "5"); float_setasciiz(&y, "6"); float_or(&x, &x, &y); float_setasciiz(&y, "7"); if (float_cmp(&x, &y) != 0) return 0; float_free(&x); float_free(&y); return 1; } static int test_xor() { floatstruct x, y; printf("testing float_xor\n"); float_create(&x); float_create(&y); float_setasciiz(&x, "5"); float_setasciiz(&y, "6"); float_xor(&x, &x, &y); float_setasciiz(&y, "3"); if (float_cmp(&x, &y) != 0) return 0; float_free(&x); float_free(&y); return 1; } static int tc_shl(char* value, char* shift, char* result) { floatstruct x, y; float_create(&x); float_create(&y); float_setasciiz(&x, value); float_setasciiz(&y, shift); float_shl(&x, &x, &y); float_setasciiz(&y, result); if(float_cmp(&x, &y) != 0) return 0; float_free(&x); float_free(&y); return 1; } static int test_shl() { printf("testing float_shl\n"); if (!tc_shl("0", "0", "0")) return 0; if (!tc_shl("-1", "0", "-1")) return 0; if (!tc_shl("1", "1", "2")) return 0; if (!tc_shl("1", "32", "4294967296")) return 0; if (!tc_shl("1", "64", "18446744073709551616")) return 0; if (!tc_shl("1", "96", "0")) return 0; if (!tc_shl("1", "95", "-39614081257132168796771975168")) return 0; if (!tc_shl("1", "1000", "0")) return 0; if (!tc_shl("4294967295", "1", "8589934590")) return 0; return 1; } static int tc_shr(char* value, char* shift, char* result) { floatstruct x, y; float_create(&x); float_create(&y); float_setasciiz(&x, value); float_setasciiz(&y, shift); float_shr(&x, &x, &y); float_setasciiz(&y, result); if(float_cmp(&x, &y) != 0) return 0; float_free(&x); float_free(&y); return 1; } static int test_shr() { printf("testing float_shr\n"); if (!tc_shr("0", "0", "0")) return 0; if (!tc_shr("1", "1", "0")) return 0; if (!tc_shr("2", "1", "1")) return 0; if (!tc_shr("4294967296", "32", "1")) return 0; if (!tc_shr("-1", "32", "-1")) return 0; if (!tc_shr("-4", "1", "-2")) return 0; if (!tc_shr("-39614081257132168796771975168", "94", "-2")) return 0; return 1; } static int tc_out(char* value, int digits, char base, char mode, char* result) { char intbuf[150]; char fracbuf[150]; char buffer[350]; t_otokens tokens; floatstruct x; float_create(&x); float_setasciiz(&x, value); tokens.intpart.sz = sizeof(intbuf); tokens.intpart.buf = intbuf; tokens.fracpart.sz = 150; tokens.fracpart.buf = fracbuf; if (float_out(&tokens, &x, digits, base, base != 2? base : 16, mode) != Success) return result == NULL || *result == '\0'; cattokens(buffer, 350, &tokens, IO_FLAG_SHOW_BASE + IO_FLAG_SHOW_EXPBASE + IO_FLAG_SUPPRESS_DOT + IO_FLAG_SUPPRESS_LDG_ZERO); float_free(&x); return strcmp(buffer, result) == 0; } static int test_out() { t_ioparams iop; t_ioparams saveiop; iop.base = 10; iop.expbase = 10; iop.dot = '.'; iop.basetag = "0d"; iop.expbegin = "("; iop.expend = ")"; iop.cmpltag = NULL; iop.maxdigits = 70; saveiop = *getioparams(10); setioparams(&iop); printf("testing float_out\n"); if (!tc_out("NaN", 0, 10, IO_MODE_SCIENTIFIC, "NaN")) return 0; if (!tc_out("0", 0, IO_BASE_NAN, IO_MODE_SCIENTIFIC, "")) return 0; if (!tc_out("0", 0, IO_BASE_ZERO, IO_MODE_SCIENTIFIC, "")) return 0; if (!tc_out("1", 0, IO_BASE_NAN, IO_MODE_SCIENTIFIC, "")) return 0; if (!tc_out("0", 0, 5, IO_MODE_SCIENTIFIC, "")) return 0; if (!tc_out("0", 0, 10, -1, "")) return 0; if (!tc_out("0", 0, 10, IO_MODE_SCIENTIFIC, "0")) return 0; if (!tc_out("1", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(+0d0)")) return 0; if (!tc_out("-1", 0, 10, IO_MODE_SCIENTIFIC, "-0d1(+0d0)")) return 0; if (!tc_out("1.000000002", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(+0d0)")) return 0; if (!tc_out("1.0002", 1, 10, IO_MODE_SCIENTIFIC, "+0d1.0(+0d0)")) return 0; if (!tc_out("1.07", 1, 10, IO_MODE_SCIENTIFIC, "+0d1.1(+0d0)")) return 0; if (!tc_out("1.2", 1, 10, IO_MODE_SCIENTIFIC, "+0d1.2(+0d0)")) return 0; if (!tc_out("1.2", 2, 10, IO_MODE_SCIENTIFIC, "+0d1.20(+0d0)")) return 0; if (!tc_out("10", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(+0d1)")) return 0; if (!tc_out("100", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(+0d2)")) return 0; if (!tc_out("1e12345678", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(+0d12345678)")) return 0; if (!tc_out("1.234e12345678", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(+0d12345678)")) return 0; if (!tc_out("1.234e12345678", 1, 10, IO_MODE_SCIENTIFIC, "+0d1.2(+0d12345678)")) return 0; if (!tc_out("1.234e12345678", 3, 10, IO_MODE_SCIENTIFIC, "+0d1.234(+0d12345678)")) return 0; if (!tc_out("1.234e12345678", 4, 10, IO_MODE_SCIENTIFIC, "+0d1.2340(+0d12345678)")) return 0; if (!tc_out("0.1", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(-0d1)")) return 0; if (!tc_out("1.234e-12345678", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(-0d12345678)")) return 0; if (!tc_out("1.234e-12345678", 1, 10, IO_MODE_SCIENTIFIC, "+0d1.2(-0d12345678)")) return 0; if (!tc_out("1.234e-12345678", 3, 10, IO_MODE_SCIENTIFIC, "+0d1.234(-0d12345678)")) return 0; if (!tc_out("1.234e-12345678", 4, 10, IO_MODE_SCIENTIFIC, "+0d1.2340(-0d12345678)")) return 0; if (!tc_out("1", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(+0d0)")) return 0; if (!tc_out("15", 0, 16, IO_MODE_SCIENTIFIC, "+0xF(+0d0)")) return 0; if (!tc_out("16", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(+0d1)")) return 0; if (!tc_out("17", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(+0d1)")) return 0; if (!tc_out("18", 1, 16, IO_MODE_SCIENTIFIC, "+0x1.2(+0d1)")) return 0; if (!tc_out("4096", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(+0d3)")) return 0; if (!tc_out("6144", 0, 16, IO_MODE_SCIENTIFIC, "+0x2(+0d3)")) return 0; if (!tc_out("1099511627776", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(+0d10)")) return 0; if (!tc_out("18446744073709551616", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(+0d16)")) return 0; if (!tc_out("18446744073709551616", 15, 16, IO_MODE_SCIENTIFIC, "+0x1.000000000000000(+0d16)")) return 0; if (!tc_out("1.8", 0, 16, IO_MODE_SCIENTIFIC, "+0x2(+0d0)")) return 0; if (!tc_out("-1.5", 1, 16, IO_MODE_SCIENTIFIC, "-0x1.8(+0d0)")) return 0; if (!tc_out("0.5", 0, 16, IO_MODE_SCIENTIFIC, "+0x8(-0d1)")) return 0; if (!tc_out("0.25", 0, 16, IO_MODE_SCIENTIFIC, "+0x4(-0d1)")) return 0; if (!tc_out("0.125", 0, 16, IO_MODE_SCIENTIFIC, "+0x2(-0d1)")) return 0; if (!tc_out("0.0625", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(-0d1)")) return 0; if (!tc_out("0.03125", 0, 16, IO_MODE_SCIENTIFIC, "+0x8(-0d2)")) return 0; if (!tc_out("0.75", 0, 16, IO_MODE_SCIENTIFIC, "+0xC(-0d1)")) return 0; if (!tc_out("0.96875", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(+0d0)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 16, 16, IO_MODE_SCIENTIFIC, "+0x1.0000000000000000(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 15, 16, IO_MODE_SCIENTIFIC, "+0x1.000000000000000(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 14, 16, IO_MODE_SCIENTIFIC, "+0x1.00000000000000(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 13, 16, IO_MODE_SCIENTIFIC, "+0x1.0000000000000(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 12, 16, IO_MODE_SCIENTIFIC, "+0x1.000000000000(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 11, 16, IO_MODE_SCIENTIFIC, "+0x1.00000000000(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 10, 16, IO_MODE_SCIENTIFIC, "+0x1.0000000000(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 9, 16, IO_MODE_SCIENTIFIC, "+0x1.000000000(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 8, 16, IO_MODE_SCIENTIFIC, "+0x1.00000000(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 7, 16, IO_MODE_SCIENTIFIC, "+0x1.0000000(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 6, 16, IO_MODE_SCIENTIFIC, "+0x1.000000(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 5, 16, IO_MODE_SCIENTIFIC, "+0x1.00000(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 4, 16, IO_MODE_SCIENTIFIC, "+0x1.0000(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 3, 16, IO_MODE_SCIENTIFIC, "+0x1.000(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 2, 16, IO_MODE_SCIENTIFIC, "+0x1.00(-0d16)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 1, 16, IO_MODE_SCIENTIFIC, "+0x1.0(-0d16)")) return 0; if (!tc_out("1", 0, 2, IO_MODE_SCIENTIFIC, "+0b1(+0d0)")) return 0; if (!tc_out("2", 0, 2, IO_MODE_SCIENTIFIC, "+0b1(+0d1)")) return 0; if (!tc_out("3", 0, 2, IO_MODE_SCIENTIFIC, "+0b1(+0d2)")) return 0; if (!tc_out("3", 1, 2, IO_MODE_SCIENTIFIC, "+0b1.1(+0d1)")) return 0; if (!tc_out("3", 2, 2, IO_MODE_SCIENTIFIC, "+0b1.10(+0d1)")) return 0; if (!tc_out("0.5", 0, 2, IO_MODE_SCIENTIFIC, "+0b1(-0d1)")) return 0; if (!tc_out("0.25", 0, 2, IO_MODE_SCIENTIFIC, "+0b1(-0d2)")) return 0; if (!tc_out("0.75", 0, 2, IO_MODE_SCIENTIFIC, "+0b1(-0d1)")) return 0; if (!tc_out("-0.75", 1, 2, IO_MODE_SCIENTIFIC, "-0b1.1(-0d1)")) return 0; if (!tc_out("1", 0, 8, IO_MODE_SCIENTIFIC, "+0o1(+0d0)")) return 0; if (!tc_out("2", 0, 8, IO_MODE_SCIENTIFIC, "+0o2(+0d0)")) return 0; if (!tc_out("4", 0, 8, IO_MODE_SCIENTIFIC, "+0o4(+0d0)")) return 0; if (!tc_out("8", 0, 8, IO_MODE_SCIENTIFIC, "+0o1(+0d1)")) return 0; if (!tc_out("16", 0, 8, IO_MODE_SCIENTIFIC, "+0o2(+0d1)")) return 0; if (!tc_out("0.5", 0, 8, IO_MODE_SCIENTIFIC, "+0o4(-0d1)")) return 0; if (!tc_out("0.75", 0, 8, IO_MODE_SCIENTIFIC, "+0o6(-0d1)")) return 0; if (!tc_out("0.875", 0, 8, IO_MODE_SCIENTIFIC, "+0o7(-0d1)")) return 0; if (!tc_out("0.9375", 1, 8, IO_MODE_SCIENTIFIC, "+0o7.4(-0d1)")) return 0; if (!tc_out("0.9375", 0, 8, IO_MODE_SCIENTIFIC, "+0o1(+0d0)")) return 0; if (!tc_out("NaN", 1, 10, IO_MODE_FIXPOINT, "NaN")) return 0; if (!tc_out("0", 1, IO_BASE_NAN, IO_MODE_FIXPOINT, "")) return 0; if (!tc_out("0", 1, IO_BASE_ZERO, IO_MODE_FIXPOINT, "")) return 0; if (!tc_out("1", 1, IO_BASE_NAN, IO_MODE_FIXPOINT, "")) return 0; if (!tc_out("0", 1, 5, IO_MODE_FIXPOINT, "")) return 0; if (!tc_out("0", 1, 10, IO_MODE_FIXPOINT, "0")) return 0; if (!tc_out("1", 0, 10, IO_MODE_FIXPOINT, "+0d1(+0d0)")) return 0; if (!tc_out("1", 1, 10, IO_MODE_FIXPOINT, "+0d1.0(+0d0)")) return 0; if (!tc_out("10", 0, 10, IO_MODE_FIXPOINT, "+0d10(+0d0)")) return 0; if (!tc_out("-10", 0, 10, IO_MODE_FIXPOINT, "-0d10(+0d0)")) return 0; if (!tc_out("10", 3, 10, IO_MODE_FIXPOINT, "+0d10.000(+0d0)")) return 0; if (!tc_out("10.1", 0, 10, IO_MODE_FIXPOINT, "+0d10(+0d0)")) return 0; if (!tc_out("10.1", 1, 10, IO_MODE_FIXPOINT, "+0d10.1(+0d0)")) return 0; if (!tc_out("10.1", 2, 10, IO_MODE_FIXPOINT, "+0d10.10(+0d0)")) return 0; if (!tc_out("10.12", 1, 10, IO_MODE_FIXPOINT, "+0d10.1(+0d0)")) return 0; if (!tc_out("10.16", 1, 10, IO_MODE_FIXPOINT, "+0d10.2(+0d0)")) return 0; if (!tc_out("10.86", 0, 10, IO_MODE_FIXPOINT, "+0d11(+0d0)")) return 0; if (!tc_out("0.1", 1, 10, IO_MODE_FIXPOINT, "+0d.1(+0d0)")) return 0; if (!tc_out("0.12", 1, 10, IO_MODE_FIXPOINT, "+0d.1(+0d0)")) return 0; if (!tc_out("0.0123", 2, 10, IO_MODE_FIXPOINT, "+0d.01(+0d0)")) return 0; if (!tc_out("18446744073709551616", 0, 10, IO_MODE_FIXPOINT, "+0d18446744073709551616(+0d0)")) return 0; if (!tc_out("0.75", 1, 16, IO_MODE_FIXPOINT, "+0x.C(+0d0)")) return 0; if (!tc_out("18446744073709551616", 0, 16, IO_MODE_FIXPOINT, "+0x10000000000000000(+0d0)")) return 0; if (!tc_out("18446744073709551615", 0, 16, IO_MODE_FIXPOINT, "+0xFFFFFFFFFFFFFFFF(+0d0)")) return 0; if (!tc_out("18446744073709551615", 1, 16, IO_MODE_FIXPOINT, "+0xFFFFFFFFFFFFFFFF.0(+0d0)")) return 0; if (!tc_out("5.42101086242752217003726400434970855712890625e-20", 16, 16, IO_MODE_FIXPOINT, "+0x.0000000000000001(+0d0)")) return 0; if (!tc_out("-0.75", 2, 2, IO_MODE_FIXPOINT, "-0b.11(+0d0)")) return 0; if (!tc_out("0.9375", 2, 8, IO_MODE_FIXPOINT, "+0o.74(+0d0)")) return 0; if (!tc_out("4.9375", 2, 8, IO_MODE_FIXPOINT, "+0o4.74(+0d0)")) return 0; if (!tc_out("4.9375", 1, 8, IO_MODE_FIXPOINT, "+0o5.0(+0d0)")) return 0; if (!tc_out("4.9375", 0, 10, IO_MODE_FIXPOINT, "+0d5(+0d0)")) return 0; if (!tc_out("4.9375", 0, 16, IO_MODE_FIXPOINT, "+0x5(+0d0)")) return 0; if (!tc_out("4.9375", 0, 8, IO_MODE_FIXPOINT, "+0o5(+0d0)")) return 0; if (!tc_out("4.9375", 0, 2, IO_MODE_FIXPOINT, "+0b101(+0d0)")) return 0; if (!tc_out("1.23", 2, 10, IO_MODE_ENG, "+0d1.23(+0d0)")) return 0; if (!tc_out("12.3", 2, 10, IO_MODE_ENG, "+0d12.3(+0d0)")) return 0; if (!tc_out("123", 2, 10, IO_MODE_ENG, "+0d123(+0d0)")) return 0; if (!tc_out("1234", 2, 10, IO_MODE_ENG, "+0d1.23(+0d3)")) return 0; if (!tc_out("0.1234", 2, 10, IO_MODE_ENG, "+0d123(-0d3)")) return 0; if (!tc_out("0.0123", 2, 10, IO_MODE_ENG, "+0d12.3(-0d3)")) return 0; if (!tc_out("0.00123", 2, 10, IO_MODE_ENG, "+0d1.23(-0d3)")) return 0; if (!tc_out("0.000123", 2, 10, IO_MODE_ENG, "+0d123(-0d6)")) return 0; if (!tc_out("-0.000123", 2, 10, IO_MODE_ENG, "-0d123(-0d6)")) return 0; if (!tc_out("0", 0, 16, IO_MODE_COMPLEMENT, "0")) return 0; if (!tc_out("1", 0, 16, IO_MODE_COMPLEMENT, "0x1(+0d0)")) return 0; if (!tc_out("-1", 0, 16, IO_MODE_COMPLEMENT, "0xsF(+0d0)")) return 0; if (!tc_out("-2", 0, 16, IO_MODE_COMPLEMENT, "0xsFE(+0d0)")) return 0; if (!tc_out("-16", 0, 16, IO_MODE_COMPLEMENT, "0xsF0(+0d0)")) return 0; if (!tc_out("-17", 0, 16, IO_MODE_COMPLEMENT, "0xsFEF(+0d0)")) return 0; setioparams(&saveiop); return 1; } static int tc_in(const char* text, char* result) { t_itokens tokens; floatstruct x; floatstruct r; int cmp; float_create(&x); float_create(&r); float_setasciiz(&r, result); parse(&tokens, &text); float_in(&x, &tokens); if (float_isnan(&r) && float_isnan(&x)) cmp = 0; else cmp = float_cmp(&x, &r); float_free(&x); float_free(&r); return cmp == 0; } static int test_in() { printf("testing float_in\n"); if (!tc_in("", "NaN")) return 0; if (!tc_in("NaN", "NaN")) return 0; if (!tc_in("0", "0")) return 0; if (!tc_in("0.", "0")) return 0; if (!tc_in(".0", "0")) return 0; if (!tc_in("+0", "0")) return 0; if (!tc_in("0d0", "0")) return 0; if (!tc_in("+0d0", "0")) return 0; if (!tc_in("-0", "0")) return 0; if (!tc_in("0000", "0")) return 0; if (!tc_in(".0000", "0")) return 0; if (!tc_in("00.00", "0")) return 0; if (!tc_in("1", "1")) return 0; if (!tc_in("0d1", "1")) return 0; if (!tc_in("1.", "1")) return 0; if (!tc_in("1.00", "1")) return 0; if (!tc_in("001.00", "1")) return 0; if (!tc_in("+1", "1")) return 0; if (!tc_in("-1", "-1")) return 0; if (!tc_in("10", "10")) return 0; if (!tc_in("010", "10")) return 0; if (!tc_in("010.00", "10")) return 0; if (!tc_in("123456789", "123456789")) return 0; if (!tc_in("0.1", "0.1")) return 0; if (!tc_in(".1", "0.1")) return 0; if (!tc_in(".1000", "0.1")) return 0; if (!tc_in("000.1000", "0.1")) return 0; if (!tc_in(".01000", "0.01")) return 0; if (!tc_in(".0123456789000", "0.0123456789")) return 0; if (!tc_in("2.1", "2.1")) return 0; if (!tc_in("001234.567800", "1234.5678")) return 0; if (!tc_in("0012340.567800", "12340.5678")) return 0; if (!tc_in("001234.0567800", "1234.05678")) return 0; if (!tc_in("0012340.0567800", "12340.05678")) return 0; if (!tc_in("1e0", "1")) return 0; if (!tc_in("1(0)", "1")) return 0; if (!tc_in("1e+0", "1")) return 0; if (!tc_in("1e-0", "1")) return 0; if (!tc_in("0d1e-0d0", "1")) return 0; if (!tc_in("1e1", "10")) return 0; if (!tc_in("1e+1", "10")) return 0; if (!tc_in("1e-1", "0.1")) return 0; if (!tc_in("1.e-1", "0.1")) return 0; if (!tc_in("1.2e-1", "0.12")) return 0; if (!tc_in("0.2e-1", "0.02")) return 0; if (!tc_in("12e-1", "1.2")) return 0; if (!tc_in("12e-2", "0.12")) return 0; if (!tc_in("12e1", "120")) return 0; if (!tc_in("0.12e1", "1.2")) return 0; if (!tc_in("0.12e2", "12")) return 0; if (!tc_in("0x0", "0")) return 0; if (!tc_in("0x1", "1")) return 0; if (!tc_in("0x1.0", "1")) return 0; if (!tc_in("0x0001", "1")) return 0; if (!tc_in("0x0001.00", "1")) return 0; if (!tc_in("-0x1", "-1")) return 0; if (!tc_in("+0x1", "1")) return 0; if (!tc_in("0xA", "10")) return 0; if (!tc_in("0xa", "10")) return 0; if (!tc_in("0x10", "16")) return 0; if (!tc_in("0x10000000000000000", "18446744073709551616")) return 0; if (!tc_in("0xFFFFFFFFFFFFFFFF", "18446744073709551615")) return 0; if (!tc_in("0x.8", "0.5")) return 0; if (!tc_in("0x.4", "0.25")) return 0; if (!tc_in("0x.08", "0.03125")) return 0; if (!tc_in("0x1.2", "1.125")) return 0; if (!tc_in("0x10.C", "16.75")) return 0; if (!tc_in("0x1(1)", "16")) return 0; if (!tc_in("0x1(-1)", "0.0625")) return 0; if (!tc_in("0x1(A)", "1099511627776")) return 0; if (!tc_in("0x1(0d10)", "1099511627776")) return 0; if (!tc_in("0x1(10)", "18446744073709551616")) return 0; if (!tc_in("0x1.1(1)", "17")) return 0; if (!tc_in("0b0", "0")) return 0; if (!tc_in("0b1", "1")) return 0; if (!tc_in("0b1.0", "1")) return 0; if (!tc_in("-0b1", "-1")) return 0; if (!tc_in("0b10", "2")) return 0; if (!tc_in("0b11", "3")) return 0; if (!tc_in("0b.11", ".75")) return 0; if (!tc_in("0b1.1", "1.5")) return 0; if (!tc_in("0b1.1(-1)", "0.75")) return 0; if (!tc_in("0b1.1(1)", "3")) return 0; if (!tc_in("0b1.1(0b1)", "3")) return 0; if (!tc_in("0b1.1(10)", "6")) return 0; if (!tc_in("0o0", "0")) return 0; if (!tc_in("0o1", "1")) return 0; if (!tc_in("0o1.0", "1")) return 0; if (!tc_in("-0o1", "-1")) return 0; if (!tc_in("0o10", "8")) return 0; if (!tc_in("0o14", "12")) return 0; if (!tc_in("0o.6", ".75")) return 0; if (!tc_in("0o1.1", "1.125")) return 0; if (!tc_in("0o1.4(-1)", "0.1875")) return 0; if (!tc_in("0o1.4(1)", "12")) return 0; if (!tc_in("0o1.4(0o1)", "12")) return 0; if (!tc_in("0o2(10)", "33554432")) return 0; if (!tc_in("0xsF", "-1")) return 0; if (!tc_in("0xsFF", "-1")) return 0; if (!tc_in("0xsFE", "-2")) return 0; if (!tc_in("0xsFFE", "-2")) return 0; if (!tc_in("0xsF0", "-16")) return 0; if (!tc_in("0xsF01", "-255")) return 0; if (!tc_in("0bs1", "-1")) return 0; if (!tc_in("0bs11", "-1")) return 0; if (!tc_in("0bs10", "-2")) return 0; if (!tc_in("0bs110", "-2")) return 0; if (!tc_in("0bs101", "-3")) return 0; if (!tc_in("0os7", "-1")) return 0; if (!tc_in("0os77", "-1")) return 0; if (!tc_in("0os76", "-2")) return 0; if (!tc_in("0os70", "-8")) return 0; if (!tc_in("0os767", "-9")) return 0; if (!tc_in("0os701", "-63")) return 0; return 1; } static int test_erfnear0() { floatstruct x, x1, tmp, max; int i; char buf[50]; float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("%s\n", "testing erfnear0"); printf("verifying special argument x == 0:\n"); float_setzero(&x); erfnear0(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } /* testing the validity of the series evaluation */ printf("verifying result:\n"); float_setasciiz(&x, "2.7"); float_ln(&x, 100); erfnear0(&x, 100); float_setasciiz(&x1,".7443248085801137476495167988933711046591685164758118184461636179213" "12059356598790281111307476902061005913670963660509168"); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED for x == ln 2.7\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setscientific(&tmp, ".005", NULLTERMINATED); for (i = -1; ++i <= 100;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); erfnear0(&x,100); erfnear0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error erfnear0: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_erfcasymptotic() { floatstruct x, x1, tmp, max; int i; char buf[50]; float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); printf("%s\n", "testing erfcasymptotic"); /* testing the validity of the series evaluation */ printf("verifying result:\n"); float_setasciiz(&x, "16"); erfcasymptotic(&x, 100); float_setasciiz(&x1,".99805820883474330725563527001359438444222962655197" "570407974747783849037252552071214598018034509890346" "673633987464964958201780044076702727433644232998947" "151419098605560850226039542578816264384967072263818"); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED for x == 16\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setzero(&max); float_setscientific(&tmp, ".005", NULLTERMINATED); for (i = -1; ++i <= 100;) { float_muli(&x, &tmp, i, EXACT); float_addi(&x, &x, 16, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); erfcasymptotic(&x,100); erfcasymptotic(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error erfcasymptotic: %s\n", buf); printf("testing convergence:\n"); float_copy(&x, &c2, EXACT); if (!erfcasymptotic(&x, 1)) { printf("convergence failed for 1 digit"); return 0; } float_setasciiz(&max, "0.92"); float_copy(&tmp, &max, EXACT); float_ln(&max, 100); float_sub(&max, &c1, &max, 100); float_mul(&max, &tmp, &max, 100); float_mul(&x1, &c1Div2, &cLn2, 100); for (i = 1; ++i <= 100;) { float_muli(&x, &cLn10, i, 100); float_add(&x, &x, &x1, 100); float_div(&x, &x, &max, 100); float_sqrt(&x, 100); if (!erfcasymptotic(&x, i)) { printf("convergence failed for %d digits", i); return 0; } } printf("convergence ok\n"); float_free(&max); float_free(&tmp); float_free(&x); float_free(&x1); return 1; } static int test_erfcsum() { floatstruct x, x1, tmp, max; int i, prec; char buf[50]; float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); printf("testing erfcsum\n"); printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setscientific(&tmp, ".4", NULLTERMINATED); for (prec = 1; ++prec <= 100;) { float_muli(&tmp, &cLn10, prec, 4); float_setasciiz(&x, "0.3466"); float_add(&tmp, &tmp, &x, 4); float_setasciiz(&x, "0.9967"); float_div(&tmp, &tmp, &x, 4); float_sqrt(&tmp, 4); float_sub(&tmp, &tmp, &c1Div2, 4); float_divi(&tmp, &tmp, 20, 4); float_setzero(&max); for (i = -1; ++i <= 20;) { float_muli(&x, &tmp, i, EXACT); float_add(&x, &x, &c1Div2, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); if (!erfcsum(&x1, prec+1) || !erfcsum(&x, prec)) { printf("no convergence test case %d, prec %d: ", i, prec); return 0; } _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -prec+1) { printf("exceeding error for test case %d, prec %d: ", i, prec); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } } float_getscientific(buf, 50, &max); printf("max error erfcsum: %s\n", buf); /* testing the validity of the series evaluation */ printf("verifying result:\n"); float_setasciiz(&tmp, "20"); float_divi(&tmp, &tmp, 7, 110); float_mul(&x, &tmp, &tmp, 110); erfcsum(&x, 100); /* we cannot know the free parameter alpha earlier, as it might be changed during the last series evaluation */ float_mul(&x1, &tmp, &c2Pi, 110); float_div(&x1, &x1, &erfcalpha, 110); _exp(&x1, 110); float_sub(&x1, &c1, &x1, 110); float_div(&x1, &c2, &x1, 110); /* erfc (20/7) */ float_setasciiz(&max,"0.00005331231138832281466765963565935" "9917631684842756273950127577016997393" "623370565496031160355771016945224924345871"); float_sub(&x1, &max, &x1, 110); float_div(&x1, &x1, &tmp, 110); float_div(&x1, &x1, &erfcalpha, 110); float_mul(&x1, &x1, &cPi, 110); float_mul(&max, &tmp, &tmp, 110); float_copy(&tmp, &max, EXACT); _exp(&tmp, 110); float_reciprocal(&max, 110); float_mul(&x1, &x1, &tmp, 110); float_sub(&x1, &x1, &max, 110); float_mul(&x1, &x1, &c1Div2, 110); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED for x == 20/7\n"); return 0; } float_free(&x); float_free(&x1); float_free(&tmp); float_free(&max); return 1; } static int test_erfc() { int prec, i; floatstruct x, x1, step1; floatstruct results[40]; printf("testing erfc\n"); float_create(&x); float_create(&x1); float_create(&step1); for (i = -1; ++i < 40;) float_create(&results[i]); printf("testing special values\n"); float_setzero(&x); float_erfc(&x, 100); if (float_cmp(&x, &c1) != 0) return 0; float_setasciiz(&x, "-1e1000000"); float_erfc(&x, 100); if (float_cmp(&x, &c2) != 0) return 0; printf("verifying results\n"); float_setinteger(&x, 7); float_reciprocal(&x, 110); float_erfc(&x, 100); float_setasciiz(&step1, "0.83989287327126887336609000468499807511227817903" "914160714981066604747285032020973498955714529213539694928510963"); if (!_cmprelerror(&step1, &x, -99)) { printf("FAILED for x == 1/7\n"); return 0; } float_setinteger(&x, 20); float_divi(&x, &x, 7, 110); float_erfc(&x, 100); float_setasciiz(&step1, "0.00005331231138832281466765963565935991763168484275" "6273950127577016997393623370565496031160355771016945224924345871"); if (!_cmprelerror(&step1, &x, -99)) { printf("FAILED for x == 20/7\n"); return 0; } float_setinteger(&x, 93); float_divi(&x, &x, 7, 110); float_erfc(&x, 100); float_setasciiz(&step1, "9.31989223711981967164397263120561981131962901479240254614838756" "73754394641320672442272563375006637085970867544e-79"); if (!_cmprelerror(&step1, &x, -98)) { printf("FAILED for x == 93/7\n"); return 0; } float_setasciiz(&x, "283.6"); float_erfc(&x, 100); float_setasciiz(&step1, "2.787423261346745115871691439975638770369249289940553698308352" "9939376478760274499258439317477920123004576049401e-34933"); if (!_cmprelerror(&step1, &x, -95)) { printf("FAILED for x == 283.6\n"); return 0; } float_setasciiz(&step1, "0.1"); printf("precision test for erfc\n"); for (prec = 0; ++prec <= 100;) { printf("%d\n", prec); /* clear all cached coefficients */ erfcdigits = 0; for (i = 0; ++i < 100;); { float_setinteger(&x, 1); float_setexponent(&x, -i); _sub_ulp(&x, prec); float_copy(&x1, &x, EXACT); float_erfc(&x, prec); float_erfc(&x1, prec+4); if (!_cmprelerror(&x, &x1, -prec)) { printf("evaluation IMPRECICE for 1e-%d\n", i); return 0; } } for (i = 0; ++i <= 39;) { if (i < 10) float_muli(&x, &step1, i, EXACT); else if (i < 30) float_setinteger(&x, i-9); else float_setinteger(&x, (i-25)*(i-25)); _sub_ulp(&x, prec); if(!float_erfc(&x, prec)) { printf("evaluation FAILED for case %d\n", i); return 0; } float_move(&results[i], &x); } for (i = 0; ++i <= 39;) { if (i < 10) float_muli(&x, &step1, i, EXACT); else if (i < 30) float_setinteger(&x, i-9); else float_setinteger(&x, (i-25)*(i-25)); _sub_ulp(&x, prec); if(!float_erfc(&x, prec+4)) { printf("evaluation FAILED for case %d\n", i); return 0; } if (!_cmprelerror(&x, &results[i], -prec)) { printf("evaluation IMPRECICE for case %d\n", i); return 0; } } } float_free(&x); float_free(&step1); float_free(&x1); for (i = -1; ++i < 40;) float_free(&results[i]); return 1; } static int test_erf() { int prec, i; floatstruct x, x1, step; printf("testing erf\n"); float_create(&x); float_create(&step); float_create(&x1); printf("verifying special x"); float_setzero(&x); if (!float_erf(&x,100) || !float_iszero(&x)) return 0; float_setasciiz(&x, "1e1000000"); if (!float_erf(&x, 100) || float_cmp(&x, &c1) != 0) return 0; float_copy(&x1, &c1, EXACT); float_copy(&x, &cMinus1, EXACT); if (!float_erf(&x, 100) || !float_erf(&x1, 100)) return 0; float_neg(&x); if (float_cmp(&x, &x1) != 0) return 0; float_setasciiz(&step, "0.05"); printf("precision test for erf\n"); for (prec = 0; ++prec <= 100;) { printf("%d\n", prec); for (i = 0; ++i <= 39;) { if (i < 10) { float_copy(&x, &c1, EXACT); float_setexponent(&x, -3-i*i); } else if (i < 30) float_muli(&x, &step, i-9, EXACT); else float_setinteger(&x, 2 + (i-30)*(i-30)); _sub_ulp(&x, prec); float_copy(&x1, &x, EXACT); if(!float_erf(&x, prec) || !float_erf(&x1, prec+4)) { printf("evaluation FAILED for case %d\n", i); return 0; } if (!_cmprelerror(&x, &x1, -prec)) { printf("evaluation IMPRECICE for case %d\n", i); return 0; } } } float_free(&x); float_free(&step); float_free(&x1); return 1; } static int testfailed(char* msg) { printf("\n%s FAILED, tests aborted\n", msg); return 1; } #endif /* _FLOATNUMTEST */ int main(int argc, char** argv) { #ifdef _FLOATNUMTEST int scalesave; printf("\ntest of floatlong\n"); floatmath_init(); float_stdconvert(); maxdigits = 150; if(!test_longadd()) return testfailed("_longadd"); if(!test_longmul()) return testfailed("_longmul"); if(!test_longshr()) return testfailed("_longshr"); if(!test_checkadd()) return testfailed("_checkadd"); if(!test_checkmul()) return testfailed("_checkmul"); if(!test_longarrayadd()) return testfailed("_longarrayadd"); if(!test_longarraymul()) return testfailed("_longarrayadd"); printf("\ntest of setting/modifying values \n"); scalesave = maxdigits; maxdigits = 15; if(!test_create()) return testfailed("float_create"); if(!test_isnan()) return testfailed("float_isnan"); if(!test_iszero()) return testfailed("float_iszero"); if(!test_setnan()) return testfailed("float_setnan"); if(!test_setzero()) return testfailed("float_setzero"); if(!test_setsignificand()) return testfailed("float_setsignificand"); if(!test_getsignificand()) return testfailed("float_getsignificand"); if(!test_setexponent()) return testfailed("float_setexponent"); if(!test_getexponent()) return testfailed("float_getexponent"); if(!test_setsign()) return testfailed("float_setsign"); if(!test_getsign()) return testfailed("float_getsign"); if(!test_getlength()) return testfailed("float_getlength"); if(!test_getdigit()) return testfailed("float_getdigit"); if(!test_getscientific()) return testfailed("float_getscientific"); if(!test_setscientific()) return testfailed("float_setscientific"); if(!test_setinteger()) return testfailed("float_setinteger"); printf("\ntest of basic arithmetic \n"); if(!test_neg()) return testfailed("float_changesign"); if(!test_abs()) return testfailed("float_abs"); if(!test_cmp()) return testfailed("float_cmp"); if(!test_copy()) return testfailed("float_copy"); if(!test_move()) return testfailed("float_move"); if(!test_round()) return testfailed("float_round"); if(!test_add()) return testfailed("float_add"); if(!test_sub()) return testfailed("float_sub"); if(!test_mul()) return testfailed("float_mul"); if(!test_div()) return testfailed("float_div"); if(!test_sqrt()) return testfailed("float_sqrt"); if(!test_int()) return testfailed("float_int"); if(!test_frac()) return testfailed("float_frac"); if(!test_divmod()) return testfailed("float_divmod"); printf("\nall floatnum tests PASSED\n\n"); maxdigits = scalesave; if(!test_floatnum2longint()) return testfailed("_floatnum2longint"); if(!test_longint2floatnum()) return testfailed("_longint2floatnum"); if(!test_out()) return testfailed("float_out"); if(!test_in()) return testfailed("float_in"); if(!test_floatnum2logic()) return testfailed("_floatnum2logic"); if(!test_logic2floatnum()) return testfailed("_logic2floatnum"); if(!test_not()) return testfailed("float_not"); if(!test_and()) return testfailed("float_and"); if(!test_or()) return testfailed("float_or"); if(!test_xor()) return testfailed("float_xor"); if(!test_shl()) return testfailed("float_shl"); if(!test_shr()) return testfailed("float_shr"); if(!test_raisei()) return testfailed("_raisei"); if(!test_raiseposi()) return testfailed("_raiseposi"); if(!test_coshminus1near0()) return testfailed("coshminus1near0"); if(!test_artanhnear0()) return testfailed("artanhnear0"); if(!test_cosminus1near0()) return testfailed("cosminus1near0"); if(!test_arctannear0()) return testfailed("arctannear0"); if(!test_lnxplus1near0()) return testfailed("_lnxplus1near0"); if(!test_lnreduce()) return testfailed("_lnreduce"); if(!test_lnxplus1lt1()) return testfailed("_lnxplus1lt1"); if(!test_ln()) return testfailed("_ln"); if(!test_lnxplus1()) return testfailed("_lnxplus1"); if(!test_artanh1minusx()) return testfailed("_artanh1minusx"); if(!test_artanhlt0_5()) return testfailed("_artanhlt0_5"); if(!test_arsinh()) return testfailed("_arsinh"); if(!test_arcoshxplus1()) return testfailed("_arcoshxplus1"); if(!test_coshminus1lt1()) return testfailed("_coshminus1lt1"); if(!test_sinhlt1()) return testfailed("_sinhlt1"); if(!test_expminus1lt1()) return testfailed("_expminus1lt1"); if(!test_expltln10()) return testfailed("_expltln10"); if(!test_exp()) return testfailed("_exp"); if(!test_expminus1()) return testfailed("_expminus1"); if(!test_coshminus1()) return testfailed("_coshminus1"); if(!test_tanhlt0_5()) return testfailed("_tanhlt0_5"); if(!test_tanhminus1gt0()) return testfailed("_tanhminus1gt0"); if(!test_arctanlt1()) return testfailed("_arctanlt1"); if(!test_arctan()) return testfailed("_arctan"); if(!test_arccosxplus1lt0_5()) return testfailed("_arccosxplus1lt0_5"); if(!test_arcsinlt0_5()) return testfailed("_arcsinlt0_5"); if(!test_arccos()) return testfailed("_arccos"); if(!test_arcsin()) return testfailed("_arcsin"); if(!test_cosminus1ltPiDiv4()) return testfailed("_cosminus1ltPiDiv4"); if(!test_sinltPiDiv4()) return testfailed("_sinltPiDiv4"); if(!test_tanltPiDiv4()) return testfailed("_tanltPiDiv4"); if(!test_cos()) return testfailed("_cos"); if(!test_sin()) return testfailed("_sin"); if(!test_tan()) return testfailed("_tan"); if(!test_lngammaasymptotic()) return testfailed("lngammaseries"); if(!test_pochhammer()) return testfailed("_pochhammer"); if(!test_lngamma()) return testfailed("_lngamma"); if(!test_gamma()) return testfailed("_gamma"); if(!test_gammaint()) return testfailed("_gammaint"); if(!test_gamma0_5()) return testfailed("_gamma0_5"); if(!test_erfnear0()) return testfailed("erfnear0"); if(!test_erfcasymptotic()) return testfailed("erfcasymptotic"); if(!test_erfcsum()) return testfailed("erfcsum"); if(!test_erfc()) return testfailed("erfc"); if(!test_erf()) return testfailed("erf"); printf("\nall tests PASSED\n"); #endif /* _FLOATNUMTEST */ return 0; }; speedcrunch-0.10.1/src/test/testevaluator.cpp0000644000175000001440000003263311015364561020443 0ustar helderusers// This file is part of the SpeedCrunch project // Copyright (C) 2004-2006 Ariya Hidayat // Copyright (C) 2007-2008 Helder Correia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "base/evaluator.hxx" #include "math/hmath.hxx" #include #include #include #include using namespace std; static Evaluator * eval = 0; static int eval_total_tests = 0; static int eval_failed_tests = 0; #define CHECK_AUTOFIX(s,p) checkAutoFix(__FILE__,__LINE__,#s,s,p) #define CHECK_DIV_BY_ZERO(s) checkDivisionByZero(__FILE__,__LINE__,#s,s) #define CHECK_EVAL(x,y) checkEval(__FILE__,__LINE__,#x,x,y) #define CHECK_EVAL_PRECISE(x,y) checkEvalPrecise(__FILE__,__LINE__,#x,x,y) static void checkAutoFix( const char * file, int line, const char * msg, const QString & expr, const QString & fixed ) { eval_total_tests++; QString r = eval->autoFix( expr ); if ( r != fixed ) { eval_failed_tests++; cerr << file << "[" << line << "]: " << msg << endl << " Result: \"" << qPrintable( r ) << "\"" << endl << " Expected: \"" << qPrintable( fixed ) << "\"" << endl << endl; } } static void checkDivisionByZero( const char * file, int line, const char * msg, const QString & expr ) { eval_total_tests++; eval->setExpression( expr ); HNumber rn = eval->evalUpdateAns(); if ( eval->error().isEmpty() ) { eval_failed_tests++; cerr << file << "[" << line << "]: " << msg << " Error: " << "division by zero not caught" << endl; } } static void checkEval( const char * file, int line, const char * msg, const QString & expr, const char * expected ) { eval_total_tests++; //Settings::self()->angleMode = Settings::Radian; //refan eval->setExpression( expr ); HNumber rn = eval->evalUpdateAns(); if ( ! eval->error().isEmpty() ) { eval_failed_tests++; cerr << file << "[" << line << "]: " << msg << " Error: " << qPrintable( eval->error() ) << endl; } else { char * result = HMath::formatFixed( rn ); if ( strcmp( result, expected ) ) { eval_failed_tests++; cerr << file << "[" << line << "]: " << msg << " Result: " << result << ", " << "Expected: " << expected << endl; } free( result ); } } static void checkEvalPrecise( const char * file, int line, const char * msg, const QString & expr, const char * expected ) { eval_total_tests++; eval->setExpression( expr ); HNumber rn = eval->evalUpdateAns(); // we compare up to 50 decimals, not exact number because it's often difficult // to represent the result as an irrational number, e.g. PI char * result = HMath::formatFixed( rn, 50 ); if ( strcmp( result, expected ) ) { eval_failed_tests++; cerr << file << "[" << line <<"]: " << msg << " Result: " << result << ", " << "Expected: " << expected << endl; } free( result ); } void test_constants() { CHECK_EVAL( "1", "1" ); } void test_unary() { CHECK_EVAL( "-0", "0" ); CHECK_EVAL( "-1", "-1" ); CHECK_EVAL( "--1", "1" ); CHECK_EVAL( "---1", "-1" ); CHECK_EVAL( "----1", "1" ); CHECK_EVAL( "-----1", "-1" ); CHECK_EVAL( "------1", "1" ); CHECK_EVAL( "-ABS(1)", "-1" ); CHECK_EVAL( "-ABS(-2)", "-2" ); CHECK_EVAL( "--ABS(-3)", "3" ); CHECK_EVAL( "---ABS(-4)", "-4" ); // see http://en.wikipedia.org/wiki/Empty_product CHECK_EVAL( "0^0", "NaN" ); CHECK_EVAL( "1^0", "1" ); CHECK_EVAL( "1^1", "1" ); CHECK_EVAL( "1^2", "1" ); CHECK_EVAL( "1^3", "1" ); // operator ^ has higher precedence than unary minus CHECK_EVAL( "-1^0", "-1" ); CHECK_EVAL( "-1^1", "-1" ); CHECK_EVAL( "-1^2", "-1" ); CHECK_EVAL( "-1^3", "-1" ); CHECK_EVAL( "2^0", "1" ); CHECK_EVAL( "2^1", "2" ); CHECK_EVAL( "2^2", "4" ); CHECK_EVAL( "2^3", "8" ); CHECK_EVAL( "2^4", "16" ); CHECK_EVAL( "2^5", "32" ); CHECK_EVAL( "2^6", "64" ); CHECK_EVAL( "2^7", "128" ); CHECK_EVAL( "2^8", "256" ); CHECK_EVAL( "2^9", "512" ); CHECK_EVAL( "2^10", "1024" ); CHECK_EVAL( "-2^0", "-1" ); CHECK_EVAL( "-2^1", "-2" ); CHECK_EVAL( "-2^2", "-4" ); CHECK_EVAL( "-2^3", "-8" ); CHECK_EVAL( "-2^4", "-16" ); CHECK_EVAL( "-2^5", "-32" ); CHECK_EVAL( "-2^6", "-64" ); CHECK_EVAL( "-2^7", "-128" ); CHECK_EVAL( "-2^8", "-256" ); CHECK_EVAL( "-2^9", "-512" ); CHECK_EVAL( "-2^10", "-1024" ); CHECK_EVAL( "(5-7)^2", "4" ); CHECK_EVAL( "-(5-7)^2", "-4" ); CHECK_EVAL( "0!", "1" ); CHECK_EVAL( "1!", "1" ); CHECK_EVAL( "2!", "2" ); CHECK_EVAL( "3!", "6" ); CHECK_EVAL( "4!", "24" ); CHECK_EVAL( "5!", "120" ); CHECK_EVAL( "6!", "720" ); CHECK_EVAL( "7!", "5040" ); // factorial has higher precedence than unary minus CHECK_EVAL( "-1!", "-1" ); CHECK_EVAL( "-2!", "-2" ); CHECK_EVAL( "-3!", "-6" ); } void test_binary() { CHECK_EVAL( "0+0", "0" ); CHECK_EVAL( "1+0", "1" ); CHECK_EVAL( "0+1", "1" ); CHECK_EVAL( "1+1", "2" ); } void test_divide_by_zero() { CHECK_DIV_BY_ZERO( "1/0" ); CHECK_DIV_BY_ZERO( "1 / sin 0" ); CHECK_DIV_BY_ZERO( "1/sin(pi)" ); CHECK_DIV_BY_ZERO( "1/sin ( pi" ); CHECK_DIV_BY_ZERO( "1/sin pi" ); CHECK_DIV_BY_ZERO( "1 / cos (pi/2)" ); CHECK_DIV_BY_ZERO( "1 / cos(pi/2" ); CHECK_DIV_BY_ZERO( "1/cos(pi/2)" ); CHECK_DIV_BY_ZERO( "1/tan(0)" ); CHECK_DIV_BY_ZERO( "1/tan 0 " ); CHECK_DIV_BY_ZERO( "-1/trunc(0.123)" ); CHECK_DIV_BY_ZERO( "1/round(0.456)" ); CHECK_DIV_BY_ZERO( "-1/binompmf(1;10;0)" ); CHECK_DIV_BY_ZERO( "-345.3 / binompmf ( 1 ; 10 ; 0 ) " ); } void test_function_basic() { CHECK_EVAL( "ABS(0)", "0" ); CHECK_EVAL( "ABS(1)", "1" ); CHECK_EVAL( "ABS(-1)", "1" ); CHECK_EVAL( "ABS(--1)", "1" ); CHECK_EVAL( "ABS(---1)", "1" ); CHECK_EVAL( "ABS((1))", "1" ); CHECK_EVAL( "ABS((-1))", "1" ); CHECK_EVAL( "ABS(1/2)", "0.5" ); CHECK_EVAL( "ABS(-1/2)", "0.5" ); CHECK_EVAL( "ABS(-1/-2)", "0.5" ); CHECK_EVAL( "ABS(1/-2)", "0.5" ); CHECK_EVAL( "INT(0)", "0" ); CHECK_EVAL( "INT(1)", "1" ); CHECK_EVAL( "INT(-1)", "-1" ); CHECK_EVAL( "INT(0.5)", "0" ); CHECK_EVAL( "INT(-0.75)", "0" ); CHECK_EVAL( "INT(-0.9999*1)", "0" ); CHECK_EVAL( "INT(0.9999*1)", "0" ); CHECK_EVAL( "INT(2.1)", "2" ); CHECK_EVAL( "INT(-3.4)", "-3" ); CHECK_EVAL_PRECISE( "exp((1)/2) + exp((1)/2)", "3.29744254140025629369730157562832714330755220142030" ); } void test_function_trig() { CHECK_EVAL_PRECISE( "pi", "3.14159265358979323846264338327950288419716939937511" ); CHECK_EVAL( "sin(0)", "0" ); CHECK_EVAL( "cos(0)", "1" ); CHECK_EVAL( "tan(0)", "0" ); CHECK_EVAL( "sin(pi)", "0" ); CHECK_EVAL( "cos(pi)", "-1" ); CHECK_EVAL( "tan(pi)", "0" ); CHECK_EVAL( "sin(-pi)", "0" ); CHECK_EVAL( "cos(-pi)", "-1" ); CHECK_EVAL( "tan(-pi)", "0" ); CHECK_EVAL( "sin(--pi)", "0" ); CHECK_EVAL( "cos(--pi)", "-1" ); CHECK_EVAL( "tan(--pi)", "0" ); CHECK_EVAL( "sin(pi/2)", "1" ); CHECK_EVAL( "cos(pi/2)", "0" ); CHECK_EVAL( "sin(-pi/2)", "-1" ); CHECK_EVAL( "cos(-pi/2)", "0" ); CHECK_EVAL( "sin(-pi/2) + sin(pi/2)", "0" ); CHECK_EVAL( "sin(-pi/2) - sin(pi/2)", "-2" ); CHECK_EVAL( "cos(-pi/2) + cos(pi/2)", "0" ); CHECK_EVAL( "cos(-pi/2) - cos(pi/2)", "0" ); CHECK_EVAL( "asin(sin(1))", "1" ); CHECK_EVAL( "acos(cos(1))", "1" ); CHECK_EVAL( "degrees(0)", "0" ); CHECK_EVAL( "degrees(pi/2)", "90" ); CHECK_EVAL( "degrees(pi)", "180" ); CHECK_EVAL( "degrees(3*pi/2)", "270" ); CHECK_EVAL( "degrees(2*pi)", "360" ); CHECK_EVAL( "radians(0)", "0" ); CHECK_EVAL( "radians(90)/pi", "0.5" ); CHECK_EVAL( "radians(180)/pi", "1" ); CHECK_EVAL( "radians(270)/pi", "1.5" ); CHECK_EVAL( "radians(360)/pi", "2" ); } void test_function_stat() { CHECK_EVAL( "MIN(0)", "0" ); CHECK_EVAL( "MIN(0; 1)", "0" ); CHECK_EVAL( "MIN(0; 2)", "0" ); CHECK_EVAL( "MIN(-1; 0)", "-1" ); CHECK_EVAL( "MIN(-1; 1)", "-1" ); CHECK_EVAL( "MIN(-0.01; 0)", "-0.01" ); CHECK_EVAL( "MIN(0; 1; 2)", "0" ); CHECK_EVAL( "MIN(-1; 0; 1; 2)", "-1" ); CHECK_EVAL( "MIN(-2; -1; 0; 1; 2)", "-2" ); CHECK_EVAL( "MAX(0)", "0" ); CHECK_EVAL( "MAX(0; 1)", "1" ); CHECK_EVAL( "MAX(0; 2)", "2" ); CHECK_EVAL( "MAX(-1; 0)", "0" ); CHECK_EVAL( "MAX(-1; 1)", "1" ); CHECK_EVAL( "MAX(0.01; 0)", "0.01" ); CHECK_EVAL( "MAX(0; 1; 2)", "2" ); CHECK_EVAL( "MAX(-1; 0; 1; 2)", "2" ); CHECK_EVAL( "MAX(-2; -1; 0; 1; 2)", "2" ); CHECK_EVAL( "SUM()", "0" ); CHECK_EVAL( "SUM(0)", "0" ); CHECK_EVAL( "SUM(1)", "1" ); CHECK_EVAL( "SUM(-1)", "-1" ); CHECK_EVAL( "SUM(100)", "100" ); CHECK_EVAL( "SUM(-100)", "-100" ); CHECK_EVAL( "SUM(100;1)", "101" ); CHECK_EVAL( "SUM(-100;1)", "-99" ); CHECK_EVAL( "SUM(0;0;0)", "0" ); CHECK_EVAL( "SUM(100;-1)", "99" ); CHECK_EVAL( "SUM(-100;-1)", "-101" ); CHECK_EVAL( "SUM(1;2;3;4;5;6)", "21" ); CHECK_EVAL( "SUM(1;-2;3;-4;5;-6)", "-3" ); CHECK_EVAL( "AVERAGE()", "NaN" ); CHECK_EVAL( "AVERAGE(0)", "0" ); CHECK_EVAL( "AVERAGE(0;0)", "0" ); CHECK_EVAL( "AVERAGE(0;0;0)", "0" ); CHECK_EVAL( "AVERAGE(0;1)", "0.5" ); CHECK_EVAL( "AVERAGE(0;1;2)", "1" ); CHECK_EVAL( "AVERAGE(0;1;0)*3", "1" ); CHECK_EVAL( "AVERAGE(1;1;1)", "1" ); CHECK_EVAL( "AVERAGE(2;2;2)", "2" ); CHECK_EVAL( "AVERAGE(3;3;3)", "3" ); CHECK_EVAL( "AVERAGE(0.25;0.75)", "0.5" ); CHECK_EVAL( "AVERAGE(2.25;4.75)", "3.5" ); CHECK_EVAL( "AVERAGE(1/3;2/3)", "0.5" ); CHECK_EVAL( "GEOMEAN()", "NaN" ); CHECK_EVAL( "GEOMEAN(0)", "NaN" ); CHECK_EVAL( "GEOMEAN(-1)", "NaN" ); CHECK_EVAL( "GEOMEAN(-1e20)", "NaN" ); CHECK_EVAL( "GEOMEAN(1)", "1" ); CHECK_EVAL( "GEOMEAN(2)", "2" ); CHECK_EVAL( "GEOMEAN(3)", "3" ); CHECK_EVAL( "GEOMEAN(4)", "4" ); CHECK_EVAL( "GEOMEAN(5)", "5" ); CHECK_EVAL( "GEOMEAN(1;1)", "1" ); CHECK_EVAL( "GEOMEAN(1;4)", "2" ); CHECK_EVAL( "GEOMEAN(4;9)", "6" ); CHECK_EVAL( "GEOMEAN(3.6;8.1)", "5.4" ); CHECK_EVAL( "GEOMEAN(3;4;18)", "6" ); CHECK_EVAL( "GEOMEAN(1;1;1)", "1" ); CHECK_EVAL( "GEOMEAN(1;1;1;1)", "1" ); CHECK_EVAL( "GEOMEAN(1;1;1;-1)", "NaN" ); } void test_auto_fix_parentheses() { CHECK_AUTOFIX( "sin(1)", "sin(1)" ); CHECK_AUTOFIX( "sin(1", "sin(1)" ); CHECK_AUTOFIX( "x+(8-2", "x+(8-2)" ); CHECK_AUTOFIX( "x+(8-2)", "x+(8-2)" ); CHECK_AUTOFIX( "x+(8-(2*1", "x+(8-(2*1))" ); CHECK_AUTOFIX( "x+(8-(2*1)", "x+(8-(2*1))" ); CHECK_AUTOFIX( "x+(8-(2*1))", "x+(8-(2*1))" ); CHECK_AUTOFIX( "x + sin ( pi", "x + sin ( pi)" ); } void test_auto_fix_ans() { CHECK_AUTOFIX( "sin", "sin(ans)" ); CHECK_AUTOFIX( "cos", "cos(ans)" ); CHECK_AUTOFIX( "tan", "tan(ans)" ); CHECK_AUTOFIX( "abs", "abs(ans)" ); CHECK_AUTOFIX( "exp", "exp(ans)" ); CHECK_AUTOFIX( "log", "log(ans)" ); } void test_auto_fix_trailing_equal() { CHECK_AUTOFIX ( "1+2=", "1+2" ); CHECK_AUTOFIX ( "1==", "1" ); CHECK_AUTOFIX ( "1/3====", "1/3" ); CHECK_AUTOFIX ( "sin(x+y)=", "sin(x+y)" ); } void test_auto_fix_untouch() { // all expressions are not touched because they are valid already CHECK_AUTOFIX( "sin(x)", "sin(x)" ); CHECK_AUTOFIX( "sin((x/y))", "sin((x/y))" ); CHECK_AUTOFIX( "ans", "ans" ); CHECK_AUTOFIX( "sin(ans)", "sin(ans)" ); CHECK_AUTOFIX( "tan(ans)", "tan(ans)" ); CHECK_AUTOFIX( "x=1.2", "x=1.2" ); CHECK_AUTOFIX( "1/sin pi", "1/sin pi" ); } int main( int argc, char * * argv ) { QApplication app( argc, argv ); HMath::setAngleMode( 'r' ); eval = new Evaluator( '.' ); test_constants(); test_unary(); test_binary(); test_divide_by_zero(); test_function_basic(); test_function_trig(); test_function_stat(); test_auto_fix_parentheses(); test_auto_fix_ans(); test_auto_fix_trailing_equal(); test_auto_fix_untouch(); cerr << eval_total_tests << " total, " << eval_failed_tests << " failed" << endl; delete eval; return app.exec(); } speedcrunch-0.10.1/src/math/0000755000175000001440000000000011015364704014777 5ustar helderusersspeedcrunch-0.10.1/src/math/floatconvert.h0000644000175000001440000000553211015364561017664 0ustar helderusers/* floatconvert.h: radix conversion, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATCONVERT_H # define _FLOATCONVERT_H #include "floatnum.h" #include "floatio.h" #include "floatlong.h" #ifdef __cplusplus extern "C" { #endif #define IO_MODE_SCIENTIFIC 0 #define IO_MODE_FIXPOINT 1 #define IO_MODE_ENG 2 #define IO_MODE_COMPLEMENT 3 /* converts the integer part of f to a binary coded bigint. Returns IOConversionOverflow, if the bigint overflows */ Error _floatnum2longint(t_longint* longint, floatnum f); /* converts a binary coded bigint into a floatnum */ void _longint2floatnum(floatnum f, t_longint* longint); /* the output process destroys x 'digits' are the number of digits after the dot. Regardless of the value of 'digits', a conversion is always done to DECPRECISION places Before reducing to 'digits' places the (converted) value is rounded. Trailing zeros are padded, if necessary, to fill to the right size. Errors: InvalidParam (if any of the parameters makes no sense like digits <= 0, or a not supported base) IOBufferOverflow (if the caller does not provide enough buffer in tokens) IOConversionOverflow (request requires too much buffer space for radix conversion) IOConversionUnderflow (request would produce leading zeros only) IOInvalidComplement (two's complement cannot be generated) */ Error float_out(p_otokens tokens, floatnum x, int digits, signed char base, /*signed char expbase,*/ char outmode); /* returns Success or one of the IO... codes Errors: BadLiteral, set in addition to the returned result */ Error float_in(floatnum x, p_itokens tokens); #ifdef __cplusplus } #endif #endif /* _FLOATCONVERT_H */ speedcrunch-0.10.1/src/math/floatconst.h0000644000175000001440000000430011015364561017322 0ustar helderusers/* floatconst.h: constants for higher math functions */ /* Copyright (C) 2007 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATCONST_H #define _FLOATCONST_H #include "floatnum.h" #define MAXBERNOULLIIDX 68 #define MAXERFCIDX 80 #ifdef __cplusplus extern "C" { #endif extern floatstruct c1; extern floatstruct c2; extern floatstruct c3; extern floatstruct c12; extern floatstruct cMinus1; extern floatstruct cMinus20; extern floatstruct c1Div2; extern floatstruct cLn2; extern floatstruct cLn3; extern floatstruct cLn7; extern floatstruct cLn10; extern floatstruct cPi; extern floatstruct cPiDiv2; extern floatstruct cPiDiv4; extern floatstruct c2Pi; extern floatstruct c1DivPi; extern floatstruct cSqrtPi; extern floatstruct c1DivSqrtPi; extern floatstruct cLnSqrt2PiMinusHalf; extern floatstruct c2DivSqrtPi; extern floatstruct cMinus0_4; extern floatstruct cBernoulliNum[68]; extern floatstruct cBernoulliDen[68]; extern floatstruct cUnsignedBound; extern int erfcdigits; extern floatstruct erfccoeff[MAXERFCIDX]; extern floatstruct erfcalpha; extern floatstruct erfcalphasqr; extern floatstruct erfct2; extern floatstruct erfct3; void floatmath_init(); void floatmath_exit(); #ifdef __cplusplus } #endif #endif /* _FLOATCONST_H */ speedcrunch-0.10.1/src/math/floatpower.c0000644000175000001440000000343511015364561017333 0ustar helderusers/* floatpower.c: power operation, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatpower.h" #include "floatipower.h" #include "floatcommon.h" #include "floatlog.h" #include "floatexp.h" char _raise( floatnum x, cfloatnum exponent, int digits) { int iexp; int extra; extra = float_getexponent(exponent); if (digits + extra > maxdigits) extra = maxdigits - digits; if (float_isinteger(exponent)) { iexp = leadingdigits(exponent, float_getexponent(exponent) + 1); if (float_iszero(exponent) || iexp != 0) return _raisei(x, iexp, digits+extra); } if (digits + extra > MATHPRECISION) extra = MATHPRECISION - digits; _ln(x, digits+extra); if (!float_mul(x, x, exponent, digits+extra)) return 0; return _exp(x, digits); } speedcrunch-0.10.1/src/math/hmath.cpp0000644000175000001440000012512011015364561016606 0ustar helderusers// HMath: C++ high precision math routines // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2007-2008 Helder Correia // Copyright (C) 2008 Wolf Lammen // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "hmath.hxx" #include "floatcommon.h" #include "floatconst.h" #include "floatconvert.h" #include "floathmath.h" #include "floatio.h" #include "floatnum.h" #include "base/errors.h" #include #include #include #include #include #define HMATH_WORKING_PREC (DECPRECISION + 3) #define HMATH_EVAL_PREC (HMATH_WORKING_PREC + 2) // default scale for fall back in formatting #define HMATH_MAX_SHOWN 20 #define HMATH_BIN_MAX_SHOWN ((33219*HMATH_MAX_SHOWN)/10000 + 1) #define HMATH_OCT_MAX_SHOWN ((11073*HMATH_MAX_SHOWN)/10000 + 1) #define HMATH_HEX_MAX_SHOWN ((8305*HMATH_MAX_SHOWN)/10000 + 1) /*------------------------ Helper routines -------------------------*/ void static checkfullcancellation( cfloatnum op1, cfloatnum op2, floatnum r ) { int expr; if (float_getlength(op1) != 0 && float_getlength(op2) != 0 && float_getlength(r) != 0) { /* NaN or zero not involved in computation */ expr = float_getexponent(r); if (float_getexponent(op1) - expr >= HMATH_WORKING_PREC - 1 || float_getexponent(op2) - expr >= HMATH_WORKING_PREC - 1) float_setzero(r); } } static char checkAdd(floatnum dest, cfloatnum s1, cfloatnum s2, int digits) { if (float_add(dest, s1, s2, digits) && float_getsign(s1) + float_getsign(s2) == 0) checkfullcancellation(s1, s2, dest); return float_isnan(dest); } static char checkSub(floatnum dest, cfloatnum s1, cfloatnum s2, int digits) { if (float_sub(dest, s1, s2, digits) && float_getsign(s1) - float_getsign(s2) == 0) checkfullcancellation(s1, s2, dest); return float_isnan(dest); } static void h_init() { static bool h_initialized = false; if( !h_initialized ) { h_initialized = true; floatmath_init(); float_stdconvert(); } } static void checkpoleorzero( floatnum result, floatnum x ) { int expx, expr; if (float_getlength(result) == 0 || float_getlength(x) == 0) return; expx = float_getexponent(x)-HMATH_WORKING_PREC+1; expr = float_getexponent(result); if (expr <= expx) float_setzero(result); else if (expr >= -expx) { float_setnan(result); float_seterror(EvalUnstable); } } static char roundResult( floatnum x ) { if (float_isnan(x)) /* avoids setting float_error */ return 0; return float_round(x, x, HMATH_WORKING_PREC, TONEAREST); } /*--------------------------- HNumberPrivate --------------------*/ class HNumberPrivate { public: HNumberPrivate(); ~HNumberPrivate(); floatstruct fnum; Error error; char format; }; HNumberPrivate::HNumberPrivate() : error(Success), format(0) { h_init(); float_create(&fnum); } HNumberPrivate::~HNumberPrivate() { float_free(&fnum); } typedef char (*Float1ArgND)(floatnum x); typedef char (*Float1Arg)(floatnum x, int digits); typedef char (*Float2ArgsND)(floatnum result, cfloatnum p1, cfloatnum p2); typedef char (*Float2Args)(floatnum result, cfloatnum p1, cfloatnum p2, int digits); static Error checkNaNParam(const HNumberPrivate& v1, const HNumberPrivate* v2 = 0) { if ( !float_isnan(&v1.fnum) && (!v2 || !float_isnan(&v2->fnum))) return Success; Error error = v1.error; if ( error == Success && v2 ) error = v2->error; return error == 0? NoOperand : error; } void roundSetError(HNumberPrivate* dest) { dest->error = float_geterror(); floatnum dfnum = &dest->fnum; if (dest->error != Success) float_setnan(dfnum); if (!float_isnan(dfnum)) float_round(dfnum, dfnum, HMATH_WORKING_PREC, TONEAREST); } void call2Args(HNumberPrivate* dest, HNumberPrivate* n1, HNumberPrivate* n2, Float2Args func) { dest->error = checkNaNParam(*n1, n2); if (dest->error == Success) { floatnum dfnum = &dest->fnum; func(dfnum, &n1->fnum, &n2->fnum, HMATH_EVAL_PREC); roundSetError(dest); } } void call2ArgsND(HNumberPrivate* dest, HNumberPrivate* n1, HNumberPrivate* n2, Float2ArgsND func) { dest->error = checkNaNParam(*n1, n2); if (dest->error == Success) { floatnum dfnum = &dest->fnum; func(dfnum, &n1->fnum, &n2->fnum); roundSetError(dest); } } void call1Arg(HNumberPrivate* dest, HNumberPrivate* n, Float1Arg func) { dest->error = checkNaNParam(*n); if (dest->error == Success) { floatnum dfnum = &dest->fnum; float_copy(dfnum, &n->fnum, HMATH_EVAL_PREC); func(dfnum, HMATH_EVAL_PREC); roundSetError(dest); } } void call1ArgPoleCheck(HNumberPrivate* dest, HNumberPrivate* n, Float1Arg func) { dest->error = checkNaNParam(*n); if (dest->error == Success) { floatnum dfnum = &dest->fnum; float_copy(dfnum, &n->fnum, HMATH_EVAL_PREC); if (func(dfnum, HMATH_EVAL_PREC)) checkpoleorzero(dfnum, &n->fnum); roundSetError(dest); } } void call1ArgND(HNumberPrivate* dest, HNumberPrivate* n, Float1ArgND func) { dest->error = checkNaNParam(*n); if (dest->error == Success) { floatnum dfnum = &dest->fnum; float_copy(dfnum, &n->fnum, HMATH_EVAL_PREC); func(dfnum); roundSetError(dest); } } static char modwrap(floatnum result, cfloatnum p1, cfloatnum p2, int digits) { char ok; floatstruct tmp; float_create(&tmp); ok = float_divmod(&tmp, result, p1, p2, INTQUOT); float_free(&tmp); return ok; } char idivwrap(floatnum result, cfloatnum p1, cfloatnum p2) { char ok; floatstruct tmp; int save = float_setprecision(DECPRECISION); float_create(&tmp); ok = float_divmod(result, &tmp, p1, p2, INTQUOT); float_free(&tmp); float_setprecision(save); return ok; } /*-------------------------- HNumber -------------------*/ /** * Creates a new number. */ HNumber::HNumber() { d = new HNumberPrivate; } /** * Copies from another number. */ HNumber::HNumber( const HNumber& hn ) { d = new HNumberPrivate; operator=( hn ); } /** * Creates a new number from an integer value. */ HNumber::HNumber( int i ) { d = new HNumberPrivate; float_setinteger(&d->fnum, i); } /** * Creates a new number from a string. */ HNumber::HNumber( const char* str ) { t_itokens tokens; d = new HNumberPrivate; if ((d->error = parse(&tokens, &str)) == Success && *str == 0) d->error = float_in(&d->fnum, &tokens); float_geterror(); } /** * Destroys this number. */ HNumber::~HNumber() { delete d; } /** * Returns the error code kept with a NaN. */ Error HNumber::error() const { return d->error; } /** * Returns true if this number is Not a Number (NaN). */ bool HNumber::isNan() const { return float_isnan(&d->fnum) != 0; } /** * Returns true if this number is zero. */ bool HNumber::isZero() const { return float_iszero(&d->fnum) != 0; } /** * Returns true if this number is more than zero. */ bool HNumber::isPositive() const { return float_getsign(&d->fnum) > 0; } /** * Returns true if this number is less than zero. */ bool HNumber::isNegative() const { return float_getsign(&d->fnum) < 0; } /** * Returns true if this number is integer. */ bool HNumber::isInteger() const { return float_isinteger(&d->fnum) != 0; } /** * Returns the preferred format (base/precision), default is 0 */ char HNumber::format() const { return d->format; } /** * Sets the preferred format (base/precision), default is 0 */ void HNumber::setFormat(char c) { d->format = float_isnan(&d->fnum)?0:c; } /** * Returns a NaN (Not a Number) with error set to * passed parameter. */ HNumber HNumber::nan(Error error) { HNumber result; result.d->error = error; return result; } /** * Returns the number as an int. * It is meant to convert small (integer) numbers only and no * checking is done whatsoever. */ int HNumber::toInt() const { return float_asinteger(&d->fnum); } /** * Assigns from another number. */ HNumber& HNumber::operator=( const HNumber & hn ) { d->format = hn.format(); d->error = hn.error(); float_copy(&d->fnum, &hn.d->fnum, EXACT); return *this; } /** * Adds another number. */ HNumber HNumber::operator+( const HNumber & num ) const { HNumber result; call2Args(result.d, d, num.d, checkAdd); return result; } /** * Adds another number. */ HNumber& HNumber::operator+=( const HNumber & num ) { return operator=( *this + num ); } /** * Subtract from another number. */ HNumber operator-( const HNumber & n1, const HNumber & n2 ) { HNumber result; call2Args(result.d, n1.d, n2.d, checkSub); return result; } /** * Subtract from another number. */ HNumber& HNumber::operator-=( const HNumber & num ) { return operator=( *this - num ); } /** * Multiplies with another number. */ HNumber HNumber::operator*( const HNumber & num ) const { HNumber result; call2Args(result.d, d, num.d, float_mul); return result; } /** * Multiplies with another number. */ HNumber& HNumber::operator*=( const HNumber & num ) { return operator=( *this * num ); } /** * Divides with another number. */ HNumber HNumber::operator/( const HNumber & num ) const { HNumber result; call2Args(result.d, d, num.d, float_div); return result; } /** * Divides with another number. */ HNumber& HNumber::operator/=( const HNumber & num ) { return operator=( *this / num ); } /** * Modulo (rest of integer division) */ HNumber HNumber::operator%( const HNumber & num ) const { HNumber result; call2Args(result.d, d, num.d, modwrap); return result; } /** * Performs an integer divide */ HNumber HNumber::idiv( const HNumber & dividend, const HNumber& divisor) { HNumber result; call2ArgsND(result.d, dividend.d, divisor.d, idivwrap); if (result.error() == TooExpensive) result.d->error = Overflow; return result; } /** * Returns true if this number is greater than n. */ bool HNumber::operator>( const HNumber & n ) const { return HMath::compare( *this, n ) > 0; } /** * Returns true if this number is less than n. */ bool HNumber::operator<( const HNumber & n ) const { return HMath::compare( *this, n ) < 0; } /** * Returns true if this number is greater than or equal to n. */ bool HNumber::operator>=( const HNumber & n ) const { return HMath::compare( *this, n ) >= 0; } /** * Returns true if this number is less than or equal to n. */ bool HNumber::operator<=( const HNumber & n ) const { return HMath::compare( *this, n ) <= 0; } /** * Returns true if this number is equal to n. */ bool HNumber::operator==( const HNumber & n ) const { return HMath::compare( *this, n ) == 0; } /** * Returns true if this number is not equal to n. */ bool HNumber::operator!=( const HNumber & n ) const { return HMath::compare( *this, n ) != 0; } /** * Bitwise ANDs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber HNumber::operator&( const HNumber & num ) const { HNumber result; call2ArgsND(result.d, d, num.d, float_and); return result; } /** * Bitwise ANDs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber& HNumber::operator&=( const HNumber & num ) { return operator=( *this & num ); } /** * Bitwise ORs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber HNumber::operator|( const HNumber & num ) const { HNumber result; call2ArgsND(result.d, d, num.d, float_or); return result; } /** * Bitwise ORs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber& HNumber::operator|=( const HNumber & num ) { return operator=( *this | num ); } /** * Bitwise XORs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber HNumber::operator^( const HNumber & num ) const { HNumber result; call2ArgsND(result.d, d, num.d, float_xor); return result; } /** * Bitwise XORs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber& HNumber::operator^=( const HNumber& num ) { return operator=( *this ^ num ); } /** * Bitwise NOTs the integral part *this. * Yields NaN, if *this exeeds the logic range */ HNumber HNumber::operator~() const { HNumber result; call1ArgND(result.d, d, float_not); return result; } /** * Changes the sign. */ HNumber operator-( const HNumber & x ) { HNumber result; call1ArgND(result.d, x.d, float_neg); return result; } /** * Shifts the integral part of <*this> to the left by * the parameters value's bits. Zeros are shifted in * to the right, shifted out bits are dropped. * Yields NaN, if the operand exeeds the logic range, * or the shift count is not a non-negative integer. */ HNumber HNumber::operator<<( const HNumber & num ) const { HNumber result; call2ArgsND(result.d, d, num.d, float_shl); return result; } /** * Shifts the integral part of <*this> to the right by * the parameters value's bits. The most significand * bit is duplicated to the left, shifted out bits are dropped * (signed or arithmethic shift right). * Yields NaN, if the operand exeeds the logic range, * or the shift count is not a non-negative integer. */ HNumber HNumber::operator>>( const HNumber & num ) const { HNumber result; call2ArgsND(result.d, d, num.d, float_shr); return result; } static char* _doFormat( floatnum x, signed char base, signed char expbase, char outmode, int prec, unsigned flags) { floatstruct tmp; t_otokens tokens; int sz; char* str; char intbuf[BINPRECISION+1]; char fracbuf[BINPRECISION+1]; str = NULL; float_create(&tmp); switch (base) { case 2: sz = BINPRECISION+1; break; case 8: sz = OCTPRECISION+1; break; case 10: sz = DECPRECISION+1; break; case 16: sz = HEXPRECISION+1; break; } tokens.intpart.sz = sz; tokens.intpart.buf = intbuf; tokens.fracpart.sz = sz; tokens.fracpart.buf = fracbuf; float_copy(&tmp, x, DECPRECISION + 2); if (float_out(&tokens, &tmp, prec, base, outmode) == Success) { sz = cattokens(NULL, -1, &tokens, expbase, flags); str = (char*)malloc( sz ); cattokens(str, sz, &tokens, expbase, flags); } float_free(&tmp); return str; } /** * Formats the given number as string, using specified decimal digits. * Note that the returned string must be freed. */ char * HMath::formatFixed( const HNumber & hn, int prec ) { unsigned flags; int scale; char* result; scale = float_getlength(&hn.d->fnum) - float_getexponent(&hn.d->fnum) - 1; if (scale < 0) scale = 0; flags = IO_FLAG_SUPPRESS_PLUS + IO_FLAG_SUPPRESS_DOT + IO_FLAG_SUPPRESS_EXPZERO; if( prec < 0 ) { flags |= IO_FLAG_SUPPRESS_TRL_ZERO; prec = HMATH_MAX_SHOWN; if( scale < HMATH_MAX_SHOWN ) prec = scale; } result = _doFormat(&hn.d->fnum, 10, 10, IO_MODE_FIXPOINT, prec, flags); if (!result) result = _doFormat(&hn.d->fnum, 10, 10, IO_MODE_SCIENTIFIC, HMATH_MAX_SHOWN, flags); return result; } /** * Formats the given number as string, in scientific format. * Note that the returned string must be freed. */ char * HMath::formatScientific( const HNumber & hn, int prec ) { unsigned flags; flags = IO_FLAG_SUPPRESS_PLUS + IO_FLAG_SUPPRESS_DOT + IO_FLAG_SUPPRESS_EXPPLUS; if( prec < 0 ) { flags |= IO_FLAG_SUPPRESS_TRL_ZERO; prec = HMATH_MAX_SHOWN; } return _doFormat(&hn.d->fnum, 10, 10, IO_MODE_SCIENTIFIC, prec, flags); } /** * Formats the given number as string, in engineering notation. * Note that the returned string must be freed. */ char * HMath::formatEngineering( const HNumber & hn, int prec ) { unsigned flags; flags = IO_FLAG_SUPPRESS_PLUS + IO_FLAG_SUPPRESS_EXPPLUS; if( prec <= 1 ) { flags |= IO_FLAG_SUPPRESS_TRL_ZERO + IO_FLAG_SUPPRESS_DOT; prec = HMATH_MAX_SHOWN; } return _doFormat(&hn.d->fnum, 10, 10, IO_MODE_ENG, prec, flags); } /** * Formats the given number as string, using specified decimal digits. * Note that the returned string must be freed. */ char * HMath::formatGeneral( const HNumber & hn, int prec ) { // find the exponent and the factor int expd = float_getexponent(&hn.d->fnum); char* str; if( expd > 5 ) str = formatScientific( hn, prec ); else if( expd < -4 ) str = formatScientific( hn, prec ); else if ( (expd < 0) && (prec>0) && (expd < -prec) ) str = formatScientific( hn, prec ); else str = formatFixed( hn, prec ); return str; } char* formathexfp( floatnum x, char base, char expbase, int scale ) { char* result; int tmpscale; #if 0 // SpeedCrunch 0.8 behaviour floatstruct tmp; int exp; float_create(&tmp); exp = float_getexponent(x); float_copy(&tmp, x, exp <= 0? 1 : exp + 1); float_int(&tmp); result = _doFormat(&tmp, base, expbase, IO_MODE_FIXPOINT, 0, IO_FLAG_SUPPRESS_PLUS + IO_FLAG_SUPPRESS_DOT + IO_FLAG_SHOW_BASE); float_free(&tmp); #else tmpscale = scale; if (float_isinteger(x)) tmpscale = 0; result = _doFormat(x, base, expbase, IO_MODE_FIXPOINT, tmpscale, IO_FLAG_SUPPRESS_PLUS + IO_FLAG_SUPPRESS_DOT + IO_FLAG_SHOW_BASE + IO_FLAG_SUPPRESS_EXPZERO); #endif if (result != NULL) return result; return _doFormat(x, base, expbase, IO_MODE_SCIENTIFIC, scale, IO_FLAG_SUPPRESS_PLUS + IO_FLAG_SUPPRESS_DOT + IO_FLAG_SHOW_BASE + IO_FLAG_SHOW_EXPBASE); } /** * Formats the given number as string, using hexadecimal digits. * Note that the returned string must be freed. */ char * HMath::formatHexadec( const HNumber & hn ) { return formathexfp (&hn.d->fnum, 16, 10, HMATH_HEX_MAX_SHOWN); } /** * Formats the given number as string, using octal digits. * Note that the returned string must be freed. */ char * HMath::formatOctal( const HNumber & hn ) { return formathexfp (&hn.d->fnum, 8, 10, HMATH_OCT_MAX_SHOWN); } /** * Formats the given number as string, using binary digits. * Note that the returned string must be freed. */ char * HMath::formatBinary( const HNumber & hn ) { return formathexfp (&hn.d->fnum, 2, 10, HMATH_BIN_MAX_SHOWN); } /** * Formats the given number as string, using specified decimal digits. * Note that the returned string must be freed. */ char* HMath::format( const HNumber& hn, char format, int prec ) { if( format=='g' ) return formatGeneral( hn, prec ); else if( format=='f' ) return formatFixed( hn, prec ); else if( format=='e' ) return formatScientific( hn, prec ); else if( format=='n' ) return formatEngineering( hn, prec ); else if( format=='h' ) return formatHexadec( hn ); else if( format=='o' ) return formatOctal( hn ); else if( format=='b' ) return formatBinary( hn ); // fallback to 'g' return formatGeneral( hn, prec ); } /** * Converts radians to degrees. */ HNumber HMath::rad2deg( const HNumber & angle ) { return angle * (HNumber(180) / HMath::pi()); } /** * Converts degrees to radians. */ HNumber HMath::deg2rad( const HNumber & angle ) { return angle * (HMath::pi() / HNumber(180)); } /** * Returns the constant pi. */ HNumber HMath::pi() { HNumber value; float_copy(&value.d->fnum, &cPi, HMATH_EVAL_PREC); return value; } /** * Returns the constant phi (golden number). */ HNumber HMath::phi() { return HNumber("1.61803398874989484820458683436563811772030917980576" "28621354486227052604628189024497072072041893911374" "84754088075386891752"); } /** * Returns -1, 0, 1 if n1 is less than, equal to, or more than n2. */ int HMath::compare( const HNumber & n1, const HNumber & n2 ) { int result = float_relcmp(&n1.d->fnum, &n2.d->fnum, HMATH_EVAL_PREC-1); float_geterror(); // clears error, if one operand was a NaN return result; } /** * Returns the maximum of two numbers. */ HNumber HMath::max( const HNumber & n1, const HNumber & n2 ) { switch ( float_cmp(&n1.d->fnum, &n2.d->fnum) ) { case 0: case 1: return n1; case -1: return n2; default: return HNumber::nan(checkNaNParam(*n1.d, n2.d)); } } /** * Returns the minimum of two numbers. */ HNumber HMath::min( const HNumber & n1, const HNumber & n2 ) { switch ( float_cmp(&n1.d->fnum, &n2.d->fnum) ) { case 0: case 1: return n2; case -1: return n1; default: return HNumber::nan(checkNaNParam(*n1.d, n2.d)); } } /** * Returns the absolute value of n. */ HNumber HMath::abs( const HNumber & n ) { HNumber result; call1ArgND(result.d, n.d, float_abs); return result; } /** * Rounds n to the specified decimal digits. */ HNumber HMath::round( const HNumber & n, int prec ) { if (n.isNan()) return HNumber::nan(checkNaNParam(*n.d)); int exp; floatnum rnum; HNumber result(n); rnum = &result.d->fnum; exp = float_getexponent(rnum); /* avoid exponent overflow later */ if (prec > HMATH_WORKING_PREC && exp > 0) prec = HMATH_WORKING_PREC; if (prec < 0 && -exp-1 > prec) float_setzero(rnum); else if (exp + prec < HMATH_WORKING_PREC) { float_addexp(rnum, prec); float_roundtoint(rnum, TONEAREST); float_addexp(rnum, -prec); } return result; } /** * Truncates n to the specified decimal digits. */ HNumber HMath::trunc( const HNumber & n, int prec ) { if (n.isNan()) return HNumber::nan(checkNaNParam(*n.d)); int exp; floatnum rnum; HNumber result(n); rnum = &result.d->fnum; exp = float_getexponent(rnum); /* avoid exponent overflow later on */ if (prec > HMATH_WORKING_PREC && exp > 0) prec = HMATH_WORKING_PREC; if (prec < 0 && -exp-1 > prec) float_setzero(rnum); else if (exp + prec < HMATH_WORKING_PREC) { float_addexp(rnum, prec); float_roundtoint(rnum, TOZERO); float_addexp(rnum, -prec); } return result; } /** * Returns the integer part of n. */ HNumber HMath::integer( const HNumber & n ) { HNumber result; call1ArgND(result.d, n.d, float_int); return result; } /** * Returns the fraction part of n. */ HNumber HMath::frac( const HNumber & n ) { HNumber result; call1ArgND(result.d, n.d, float_frac); return result; } /** * Returns the floor of n. */ HNumber HMath::floor( const HNumber & n ) { if (n.isNan()) return HNumber::nan(checkNaNParam(*n.d)); HNumber r(n); float_roundtoint(&r.d->fnum, TOMINUSINFINITY); return r; } /** * Returns the ceiling of n. */ HNumber HMath::ceil( const HNumber & n ) { if (n.isNan()) return HNumber::nan(checkNaNParam(*n.d)); HNumber r(n); float_roundtoint(&r.d->fnum, TOPLUSINFINITY); return r; } /** * Returns the greatest common divisor of n1 and n2. */ HNumber HMath::gcd( const HNumber & n1, const HNumber & n2 ) { if( !n1.isInteger() || !n2.isInteger() ) { Error error = checkNaNParam(*n1.d, n2.d); if (error != Success) return HNumber::nan(error); return HNumber::nan(TypeMismatch); } HNumber a = abs( n1 ); HNumber b = abs( n2 ); if ( a == 0 ) return b; if ( b == 0 ) return a; // run Euclidean algorithm while ( true ) { a = a % b; if ( a == 0 ) return b; b = b % a; if ( b == 0 ) return a; } } /** * Returns the square root of n. If n is negative, returns NaN. */ HNumber HMath::sqrt( const HNumber & n ) { HNumber result; call1Arg(result.d, n.d, float_sqrt); return result; } /** * Returns the cube root of n. */ HNumber HMath::cbrt( const HNumber & n ) { int expn, digits; floatstruct a, q; floatnum rnum; signed char sign; if (n.isNan()) return HNumber::nan(checkNaNParam(*n.d)); if( n.isZero() ) return n; HNumber r; rnum = &r.d->fnum; // iterations to approximate result // X[i+1] = (2/3)X[i] + n / (3 * X[i]^2)) // initial guess = sqrt( n ) // r = X[i], q = X[i+1], a = n float_create(&a); float_create(&q); float_copy(&a, &n.d->fnum, HMATH_EVAL_PREC); sign = float_getsign(&a); float_abs(&a); expn = float_getexponent(&a); float_setexponent(&a, expn % 3); expn /= 3; if (float_cmp(&a, &c2) < 0) { float_sub(&q, &a, &c1, 3); digits = -float_getexponent(&q); float_div(&q, &q, &c3, 3); float_add(&q, &q, &c1, digits+2); } else { digits = 0; float_copy(&q, &a, 2); float_sqrt(&q, 2); } while (!float_iszero(rnum) && digits < HMATH_EVAL_PREC/2 + 1) { digits = 4 * digits + 2; if (digits > HMATH_EVAL_PREC+2) digits = HMATH_EVAL_PREC+2; float_move(rnum, &q); float_mul(&q, rnum, rnum, digits); float_div(&q, &a, &q, digits); float_add(&q, &q, rnum, digits); float_add(&q, &q, rnum, digits); float_div(&q, &q, &c3, digits); float_sub(rnum, rnum, &q, 3); digits = float_getexponent(&q) - float_getexponent(rnum); } float_move(rnum, &q); float_free(&q); float_free(&a); float_setsign(rnum, sign); float_addexp(rnum, expn); roundResult(&r.d->fnum); return r; } /** * Raises n1 to an integer n. */ HNumber HMath::raise( const HNumber & n1, int n ) { if (n1.isNan()) return HNumber::nan(checkNaNParam(*n1.d)); HNumber r; float_raisei(&r.d->fnum, &n1.d->fnum, n, HMATH_EVAL_PREC); roundSetError(r.d); return r; } /** * Raises n1 to n2. */ HNumber HMath::raise( const HNumber & n1, const HNumber & n2 ) { HNumber result; call2Args(result.d, n1.d, n2.d, float_raise); return result; } /** * Returns e raised to x. */ HNumber HMath::exp( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_exp); return result; }; /** * Returns the natural logarithm of x. * If x is non positive, returns NaN. */ HNumber HMath::ln( const HNumber & x ) { HNumber result; call1ArgPoleCheck(result.d, x.d, float_ln); return result; } /** * Returns the base-10 logarithm of x. * If x is non positive, returns NaN. */ HNumber HMath::log( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_log); return result; } /** * Returns the base-2 logarithm of x. * If x is non positive, returns NaN. */ HNumber HMath::lg( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_lg); return result; } /** * Returns the sine of x. Note that x must be in radians. */ HNumber HMath::sin( const HNumber & x ) { HNumber result; call1ArgPoleCheck(result.d, x.d, float_sin); return result; } /** * Returns the cosine of x. Note that x must be in radians. */ HNumber HMath::cos( const HNumber & x ) { HNumber result; call1ArgPoleCheck(result.d, x.d, float_cos); return result; } /** * Returns the tangent of x. Note that x must be in radians. */ HNumber HMath::tan( const HNumber & x ) { HNumber result; call1ArgPoleCheck(result.d, x.d, float_tan); return result; } /** * Returns the cotangent of x. Note that x must be in radians. */ HNumber HMath::cot( const HNumber & x ) { return cos(x) / sin(x); } /** * Returns the secant of x. Note that x must be in radians. */ HNumber HMath::sec( const HNumber & x ) { return HNumber(1) / cos(x); } /** * Returns the cosecant of x. Note that x must be in radians. */ HNumber HMath::csc( const HNumber & x ) { return HNumber(1) / sin(x); } /** * Returns the arc tangent of x. */ HNumber HMath::atan( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_arctan); return result; }; /** * Returns the arc sine of x. */ HNumber HMath::asin( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_arcsin); return result; }; /** * Returns the arc cosine of x. */ HNumber HMath::acos( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_arccos); return result; }; /** * Returns the hyperbolic sine of x. */ HNumber HMath::sinh( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_sinh); return result; } /** * Returns the hyperbolic cosine of x. */ HNumber HMath::cosh( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_cosh); return result; } /** * Returns the hyperbolic tangent of x. */ HNumber HMath::tanh( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_tanh); return result; } /** * Returns the area hyperbolic sine of x. */ HNumber HMath::arsinh( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_arsinh); return result; } /** * Returns the area hyperbolic cosine of x. */ HNumber HMath::arcosh( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_arcosh); return result; } /** * Returns the area hyperbolic tangent of x. */ HNumber HMath::artanh( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_artanh); return result; } /** * Returns the Gamma function. */ HNumber HMath::gamma( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_gamma); return result; } /** * Returns ln(abs(Gamma(x))). */ HNumber HMath::lnGamma( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_lngamma); return result; } /** * Returns the sign of x. */ HNumber HMath::sign( const HNumber & x ) { if (x.isNan()) return HNumber::nan(checkNaNParam(*x.d)); return float_getsign(&x.d->fnum); } /** * Returns the binomial coefficient of n and r. * Is any of n and r negative or a non-integer, * 1/(n+1)*B(r+1, n-r+1)) is returned, where * B(x,y) is the complete Beta function */ HNumber HMath::nCr( const HNumber & n, const HNumber & r ) { floatstruct fn, fr; floatnum rnum; Error error = checkNaNParam(*n.d, r.d); if (error != Success) return HNumber::nan(error); HNumber r1; // use symmetry nCr(n, r) == nCr(n, n-r) to find r1 such // 2*r1 <= n and nCr(n, r) == nCr(n, r1) if ( r + r > n ) r1 = n - r; else r1 = r; HNumber r2 = n - r1; if ( r1 >= 0 ) { if ( n.isInteger() && r1.isInteger() && n <= 1000 && r1 <= 50 ) return factorial(n, r2+1) / factorial(r1, 1); HNumber result(n); rnum = &result.d->fnum; float_create(&fn); float_create(&fr); float_copy(&fr, &r1.d->fnum, HMATH_EVAL_PREC); float_copy(&fn, rnum, EXACT); float_sub(rnum, rnum, &fr, HMATH_EVAL_PREC) && float_add(&fn, &fn, &c1, HMATH_EVAL_PREC) && float_add(&fr, &fr, &c1, HMATH_EVAL_PREC) && float_add(rnum, rnum, &c1, HMATH_EVAL_PREC) && float_lngamma(&fn, HMATH_EVAL_PREC) && float_lngamma(&fr, HMATH_EVAL_PREC) && float_lngamma(rnum, HMATH_EVAL_PREC) && float_add(rnum, rnum, &fr, HMATH_EVAL_PREC) && float_sub(rnum, &fn, rnum, HMATH_EVAL_PREC) && float_exp(rnum, HMATH_EVAL_PREC); float_free(&fn); float_free(&fr); roundSetError(result.d); return result; } else if ( r2 >= 0 || !r2.isInteger() ) return factorial(n, r1+1)/factorial(r2, 1); else return 0; } /** * Returns the permutation of n elements chosen r elements. */ HNumber HMath::nPr( const HNumber & n, const HNumber & r ) { return factorial(n, (n-r+1)); } /** * Returns the falling Pochhammer symbol x*(x-1)*..*base. * For base == 1, this is the usual factorial x!, what this * function is named after. * This function has been extended using the Gamma function, * so that actually Gamma(x+1)/Gamma(base) is computed, a * value that equals the falling Pochhammer symbol, when * x - base is an integer, but allows other differences as well. */ HNumber HMath::factorial( const HNumber & x, const HNumber & base ) { floatstruct tmp; if (float_cmp(&c1, &base.d->fnum) == 0) { HNumber result; call1Arg(result.d, x.d, float_factorial); return result; } float_create(&tmp); HNumber r(base); float_sub(&tmp, &x.d->fnum, &base.d->fnum, HMATH_EVAL_PREC) && float_add(&tmp, &tmp, &c1, HMATH_EVAL_PREC) && float_pochhammer(&r.d->fnum, &tmp, HMATH_EVAL_PREC); roundSetError(r.d); float_free(&tmp); return r; } /** * Calculates the binomial discrete distribution probability mass function: * \f[X{\sim}B(n,p)\f] * \f[\Pr(X=k|n,p)={n\choose k}p^{k}(1-p)^{n-k}\f] * * \param[in] k the number of probed exact successes * \param[in] n the number of trials * \param[in] p the probability of success in a single trial * * \return the probability of exactly \p k successes, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::binomialPmf( const HNumber & k, const HNumber & n, const HNumber & p ) { if ( k.isNan() || ! k.isInteger() || k < 0 || k > n || n.isNan() || ! n.isInteger() || n < 0 || p.isNan() || p < 0 || p > 1 ) return HNumber::nan(); return HMath::nCr( n, k ) * HMath::raise( p, k ) * HMath::raise( HNumber(1)-p, n-k ); } /** * Calculates the binomial cumulative distribution function: * \f[X{\sim}B(n,p)\f] * \f[\Pr(X \leq k|n,p)=\sum_{i=0}^{k}{n\choose i}p^{i}(1-p)^{n-i}\f] * * \param[in] k the maximum number of probed successes * \param[in] n the number of trials * \param[in] p the probability of success in a single trial * * \return the probability of up to \p k successes, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::binomialCdf( const HNumber & k, const HNumber & n, const HNumber & p ) { // FIXME use the regularized incomplete Beta function to avoid // the potentially very expensive loop if ( k.isNan() || ! k.isInteger() || k < 0 || k > n || n.isNan() || ! n.isInteger() || n < 0 || p.isNan() || p < 0 || p > 1 ) return HNumber::nan(); HNumber one = HNumber(1); HNumber pcompl = one - p; HNumber summand = HMath::raise( pcompl, n ); HNumber result( summand ); for ( HNumber i( 0 ); i < k; ) { summand *= p * (n-i); i += one; summand /= (pcompl * i); result += summand; } return result; } /** * Calculates the expected value of a binomially distributed random variable: * \f[X{\sim}B(n,p)\f] * \f[E(X)=np\f] * * \param[in] n the number of trials * \param[in] p the probability of success in a single trial * * \return the expected value of the variable, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::binomialMean( const HNumber & n, const HNumber & p ) { if ( n.isNan() || ! n.isInteger() || n < 0 || p.isNan() || p < 0 || p > 1 ) return HNumber::nan(); return n * p; } /** * Calculates the variance of a binomially distributed random variable: * \f[X{\sim}B(n,p)\f] * \f[Var(X)=np(1-p)\f] * * \param[in] n the number of trials * \param[in] p the probability of success in a single trial * * \return the variance of the variable, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::binomialVariance( const HNumber & n, const HNumber & p ) { if ( n.isNan() || ! n.isInteger() || n < 0 || p.isNan() || p < 0 || p > 1 ) return HNumber::nan(); return n * p * ( HNumber(1) - p ); } /** * Calculates the hypergeometric discrete distribution probability mass * function: * \f[X{\sim}H(N,M,n)\f] * \f[\Pr(X=k|N,M,n)=\frac{{M\choose k}{N-M\choose n-k}}{{N\choose n}}\f] * * \param[in] k the number of probed exact successes * \param[in] N the number of total elements * \param[in] M the number of success elements * \param[in] n the number of selected elements * * \return the probability of exactly \p k successes, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::hypergeometricPmf( const HNumber & k, const HNumber & N, const HNumber & M, const HNumber & n ) { if ( k.isNan() || ! k.isInteger() || k < max( 0, M+n-N ) || k > min( M, n ) || N.isNan() || ! N.isInteger() || N < 0 || M.isNan() || ! M.isInteger() || M < 0 || M > N || n.isNan() || ! n.isInteger() || n < 0 || n > N ) return HNumber::nan(); return HMath::nCr( M, k ) * HMath::nCr( N-M, n-k ) / HMath::nCr( N, n ); } /** * Calculates the hypergeometric cumulative distribution function: * \f[X{\sim}H(N,M,n)\f] * \f[\Pr(X\leq k|N,M,n)= * \sum_{i=0}^{k}\frac{{M\choose k}{N-M\choose n-k}}{{N\choose n}}\f] * * \param[in] k the maximum number of probed successes * \param[in] N the number of total elements * \param[in] M the number of success elements * \param[in] n the number of selected elements * * \return the probability of up to \p k successes, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::hypergeometricCdf( const HNumber & k, const HNumber & N, const HNumber & M, const HNumber & n ) { if ( k.isNan() || ! k.isInteger() || k < max( 0, M+n-N ) || k > min( M, n ) || N.isNan() || ! N.isInteger() || N < 0 || M.isNan() || ! M.isInteger() || M < 0 || M > N || n.isNan() || ! n.isInteger() || n < 0 || n > N ) return HNumber::nan(); HNumber result( 0 ); for ( HNumber i( 0 ); i <= k; i += 1 ) result += HMath::nCr( M, i ) * HMath::nCr( N-M, n-i ) / HMath::nCr( N, n ); return result; } /** * Calculates the expected value of a hypergeometrically distributed random * variable: * \f[X{\sim}H(N,M,n)\f] * \f[E(X)=n\frac{M}{N}\f] * * \param[in] N the number of total elements * \param[in] M the number of success elements * \param[in] n the number of selected elements * * \return the expected value of the variable, otherwise \p NaN if the * function is not defined for the specified parameter. */ HNumber HMath::hypergeometricMean( const HNumber & N, const HNumber & M, const HNumber & n ) { if ( N.isNan() || ! N.isInteger() || N < 0 || M.isNan() || ! M.isInteger() || M < 0 || M > N || n.isNan() || ! n.isInteger() || n < 0 || n > N ) return HNumber::nan(); return n * M / N; } /** * * Calculates the variance of a hypergeometrically distributed random variable: * \f[X{\sim}H(N,M,n)\f] * \f[Var(X)=\frac{n\frac{M}{N}(1-\frac{M}{N})(N-n)}{N-1}\f] * * \param[in] N the number of total elements * \param[in] M the number of success elements * \param[in] n the number of selected elements * * \return the variance of the variable, otherwise \p NaN if the function is * not defined for the specified parameter. */ HNumber HMath::hypergeometricVariance( const HNumber & N, const HNumber & M, const HNumber & n ) { if ( N.isNan() || ! N.isInteger() || N < 0 || M.isNan() || ! M.isInteger() || M < 0 || M > N || n.isNan() || ! n.isInteger() || n < 0 || n > N ) return HNumber::nan(); return (n * (M/N) * (HNumber(1) - M/N) * (N-n)) / (N - HNumber(1)); } /** * * Calculates the poissonian discrete distribution probability mass function: * \f[X{\sim}P(\lambda)\f] * \f[\Pr(X=k|\lambda)=\frac{e^{-\lambda}\lambda^k}{k!}\f] * * \param[in] k the number of event occurrences * \param[in] l the expected number of occurrences that occur in an interval * * \return the probability of exactly \p k event occurrences, otherwise \p NaN * if the function is not defined for the specified parameters. */ HNumber HMath::poissonPmf( const HNumber & k, const HNumber & l ) { if ( k.isNan() || ! k.isInteger() || k < 0 || l.isNan() || l < 0 ) return HNumber::nan(); return exp( -l ) * raise( l, k ) / factorial( k ); } /** * Calculates the poissonian cumulative distribution function: * \f[X{\sim}P(\lambda)\f] * \f[\Pr(X\leq k|\lambda)=\sum_{i=0}^{k}\frac{e^{-\lambda}\lambda^k}{k!}\f] * * \param[in] k the maximum number of event occurrences * \param[in] l the expected number of occurrences that occur in an interval * * \return the probability of up to \p k event occurrences, otherwise \p NaN * if the function is not defined for the specified parameters. */ HNumber HMath::poissonCdf( const HNumber & k, const HNumber & l ) { if ( k.isNan() || ! k.isInteger() || k < 0 || l.isNan() || l < 0 ) return HNumber::nan(); HNumber result( 0 ); for ( HNumber i( 0 ); i <= k; i += 1 ) result += exp( -l ) * raise( l, i ) / factorial( i ); return result; } /** * Calculates the expected value of a Poisson distributed random variable: * \f[X{\sim}P(\lambda)\f] * \f[E(X)=\lambda\f] * * \param[in] l the expected number of occurrences that occur in an interval * * \return the expected value of the variable, otherwise \p NaN if the * function is not defined for the specified parameter. */ HNumber HMath::poissonMean( const HNumber & l ) { if ( l.isNan() || l < 0 ) return HNumber::nan(); return l; } /** * Calculates the variance of a Poisson distributed random variable: * \f[X{\sim}P(\lambda)\f] * \f[Var(X)=\lambda\f] * * \param[in] l the expected number of occurrences that occur in an interval * * \return the variance of the variable, otherwise \p NaN if the function is * not defined for the specified parameter. */ HNumber HMath::poissonVariance( const HNumber & l ) { if ( l.isNan() || l < 0 ) return HNumber::nan(); return l; } /** * Returns the erf function (related to normal distribution). */ HNumber HMath::erf( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_erf); return result; } /** * Returns the complementary erf function (related to normal distribution). */ HNumber HMath::erfc( const HNumber & x ) { HNumber result; call1Arg(result.d, x.d, float_erfc); return result; } /** * Restricts a logic value to a given bit size. */ HNumber HMath::mask ( const HNumber & val, const HNumber & bits ) { if ( val.isNan() || bits == 0 || bits >= LOGICRANGE || ! bits.isInteger() ) return HNumber::nan(); return val & ~(HNumber(-1) << HNumber(bits)); } /** * sign-extends an unsigned value */ HNumber HMath::sgnext( const HNumber & val, const HNumber & bits ) { if ( val.isNan() || bits == 0 || bits >= LOGICRANGE || ! bits.isInteger() ) return HNumber::nan(); HNumber ofs; ofs = HNumber(LOGICRANGE) - bits; return (val << ofs) >> ofs; } /** * For bits >= 0 does an arithmetic shift right, for bits < 0 a shift left. */ HNumber HMath::ashr( const HNumber & val, const HNumber & bits ) { if ( val.isNan() || bits <= -LOGICRANGE || bits >= LOGICRANGE || ! bits.isInteger() ) return HNumber::nan(); if (bits >= 0) return val >> bits; return val << -bits; } std::ostream& operator<<( std::ostream& s, const HNumber& n ) { char* str = HMath::formatFixed( n ); s << str; delete[] str; return s; } speedcrunch-0.10.1/src/math/floatexp.c0000644000175000001440000002120111015364561016762 0ustar helderusers/* floatexp.c: exponential function and friends, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatconst.h" #include "floatcommon.h" #include "floatseries.h" #include "floatexp.h" /* uses the addition theorem cosh(2x)-1 == 2*(cosh x - 1)*(cosh x + 1) to reduce the argument to the range |x| < 0.01. Starting with x == 1, you need 7 reduction steps to achieve the desired magnitude. The relative error is < 8e-100 for a 100 digit result. The return value is 0, if the result underflows. |x| < 1, otherwise the final process, where the reductions are unwinded, becomes too unstable */ char _coshminus1lt1( floatnum x, int digits) { floatstruct tmp; int reductions; if (float_iszero(x)) return 1; float_abs(x); reductions = 0; while(float_getexponent(x) >= -2) { float_mul(x, x, &c1Div2, digits+1); ++reductions; } if (!coshminus1near0(x, digits) && reductions == 0) return !float_iszero(x); float_create(&tmp); for(; reductions-- > 0;) { float_mul(&tmp, x, x, digits); float_add(x, x, x, digits+2); float_add(x, x, &tmp, digits+2); float_add(x, x, x, digits+2); } float_free(&tmp); return 1; } /* sinh x == sqrt((cosh x - 1) * (cosh x + 1)) */ static void _sinhfromcoshminus1( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); float_add(&tmp, x, &c2, digits); float_mul(x, &tmp, x, digits+1); float_sqrt(x, digits+1); float_free(&tmp); } /* sinh x for |x| < 1. Derived from cosh x - 1. The relative error is < 8e-100 for a 100 digit result */ void _sinhlt1( floatnum x, int digits) { signed char sgn; if (float_getexponent(x) < -digits) /* for very small x: sinh(x) approx. == x. */ return; sgn = float_getsign(x); _coshminus1lt1(x, digits); _sinhfromcoshminus1(x, digits); float_setsign(x, sgn); } /* evaluates exp(x) - 1. This value can be obtained by exp(x) - 1 == sinh(x) + cosh(x) - 1 relative error < 8e-100 for a 100 digit result */ void _expminus1lt1( floatnum x, int digits) { floatstruct tmp; signed char sgn; if (float_getexponent(x) < -digits || float_iszero(x)) /* for very small x: exp(x)-1 approx.== x */ return; float_create(&tmp); sgn = float_getsign(x); _coshminus1lt1(x, digits); float_copy(&tmp, x, EXACT); _sinhfromcoshminus1(x, digits); float_setsign(x, sgn); float_add(x, x, &tmp, digits+1); float_free(&tmp); } /* exp(x) for 0 <= x < ln 10 relative error < 5e-100 */ void _expltln10( floatnum x, int digits) { int expx; int factor; char sgnf; expx = float_getexponent(x); factor = 1; if (expx >= -1) { sgnf = leadingdigits(x, 2 + expx); if (sgnf > 4) { if (sgnf < 9) { factor = 2; float_sub(x, x, &cLn2, digits+1); } else if (sgnf < 14) { factor = 3; float_sub(x, x, &cLn3, digits+1); } else if (sgnf < 21) { factor = 7; float_sub(x, x, &cLn7, digits+1); } else { factor = 10; float_sub(x, x, &cLn10, digits+1); } } } _expminus1lt1(x, digits); float_add(x, x, &c1, digits+1); if (factor != 1) float_muli(x, x, factor, digits+1); } /* exp(x) for all x. Underflow or overflow is indicated by the return value (0, if error) relative error for 100 digit results is 5e-100 */ char _exp( floatnum x, int digits) { floatstruct exp, tmp; int expx, extra; char ok; if (float_iszero(x)) { float_copy(x, &c1, EXACT); return 1; } expx = float_getexponent(x); if (expx >= (int)(BITS_IN_EXP >> 1)) /* obvious overflow or underflow */ return 0; float_create(&exp); float_create(&tmp); float_setzero(&exp); if (expx >= 0) { float_div(&exp, x, &cLn10, expx+1); float_int(&exp); extra = float_getexponent(&exp)+1; float_mul(&tmp, &exp, &cLn10, digits+extra); float_sub(x, x, &tmp, digits+extra); if (float_cmp(x, &cLn10) >= 0) { float_add(&exp, &exp, &c1, EXACT); float_sub(x, x, &cLn10, digits); } } if (float_getsign(x) < 0) { float_sub(&exp, &exp, &c1, EXACT); float_add(x, x, &cLn10, digits); } /* when we get here 0 <= x < ln 10 */ _expltln10(x, digits); /* just in case rounding leads to a value >= 10 */ expx = float_getexponent(x); if (expx != 0) float_addi(&exp, &exp, expx, EXACT); ok = 1; if (!float_iszero(&exp)) { expx = float_asinteger(&exp); ok = expx != 0; float_setexponent(x, expx); } float_free(&exp); float_free(&tmp); return ok && !float_isnan(x); } static char _0_5exp( floatnum x, int digits) { float_sub(x, x, &cLn2, digits + (3*logexp(x)/10)+1); return _exp(x, digits); } /* exp(x)-1 for all x. Overflow is indicated by the return value (0, if error) relative error for 100 digit results is 8e-100 */ char _expminus1( floatnum x, int digits) { int expr; if (float_abscmp(x, &c1Div2) < 0) { _expminus1lt1(x, digits); return 1; } if (float_getsign(x) < 0) { expr = (2*float_getexponent(x)/5); if (expr >= digits) float_setinteger(x, -1); else { _exp(x, digits-expr); float_sub(x, x, &c1, digits); } return 1; } if (!_exp(x, digits)) return 0; float_sub(x, x, &c1, digits); return 1; } static void _addreciproc( floatnum x, int digits, signed char sgn) { floatstruct tmp; int expx; expx = float_getexponent(x); if (2*expx < digits) { float_create(&tmp); float_muli(&tmp, x, 4, digits-2*expx); float_reciprocal(&tmp, digits-2*expx); float_setsign(&tmp, sgn); float_add(x, x, &tmp, digits+1); float_free(&tmp); } } /* cosh(x)-1 for all x. Underflow or overflow is indicated by the return value (0, if error) relative error for 100 digit results is 6e-100 */ char _coshminus1( floatnum x, int digits) { if (float_getexponent(x) < 0 || float_iszero(x)) return _coshminus1lt1(x, digits); if(!_0_5exp(x, digits)) return 0; _addreciproc(x, digits, 1); float_sub(x, x, &c1, digits); return 1; } /* sinh(x) for all x. Overflow is indicated by the return value (0, if error) relative error for 100 digit results is < 8e-100 */ char _sinh( floatnum x, int digits) { if (float_getexponent(x) < 0 || float_iszero(x)) _sinhlt1(x, digits); else { if(!_0_5exp(x, digits)) return 0; _addreciproc(x, digits, -1); } return 1; } /* tanh(x) for |x| <= 0.5. relative error for 100 digit results is < 7e-100 */ void _tanhlt0_5( floatnum x, int digits) { floatstruct tmp; signed char sgn; float_create(&tmp); sgn = float_getsign(x); float_abs(x); float_add(x, x, x, digits+1); _expminus1lt1(x, digits); float_add(&tmp, x, &c2, digits); float_div(x, x, &tmp, digits); float_setsign(x, sgn); float_free(&tmp); } /* tanh(x)-1 for x > 0. relative error for 100 digit results is < 9e-100 */ char _tanhminus1gt0( floatnum x, int digits) { if (float_add(x, x, x, digits+1) && _0_5exp(x, digits)) { float_add(x, x, &c1Div2, digits+1); float_reciprocal(x, digits+1); float_setsign(x, -1); return 1; } return 0; } void _tanhgt0_5( floatnum x, int digits) { int expx; expx = float_getexponent(x); if (5*expx >= digits) float_copy(x, &c1, EXACT); else { _tanhminus1gt0(x, digits - 5*expx); float_add(x, x, &c1, digits); } } char _power10( floatnum x, int digits) { int exp; if (float_isinteger(x)) { exp = float_asinteger(x); if (exp == 0 && !float_iszero(x)) return 0; float_copy(x, &c1, EXACT); float_setexponent(x, exp); return !float_isnan(x); } return float_mul(x, x, &cLn10, digits+2) && _exp(x, digits); } speedcrunch-0.10.1/src/math/floaterf.h0000644000175000001440000000261011015364561016752 0ustar helderusers/* floaterf.h: normal distribution integrals erf and the like */ /* Copyright (C) 2007 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATERF_H #define _FLOATERF_H #include "math/floatseries.h" #ifdef __cplusplus extern "C" { #endif #define erfnear0 erfseries #define erfcbigx erfcasymptotic char _erf(floatnum x, int digits); char _erfc(floatnum x, int digits); #ifdef __cplusplus } #endif #endif /*_FLOATERF_H*/ speedcrunch-0.10.1/src/math/floatconst.c0000644000175000001440000002574211015364561017332 0ustar helderusers/* floatconst.c: constants for higher math functions */ /* Copyright (C) 2007 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatconst.h" static char sLn2[] = "0.6931471805""5994530941""7232121458""1765680755""0013436025" "5254120680""0094933936""2196969471""5605863326""9964186875" "4200148102""0570685734"; static char sLn3[] = "1.0986122886""6810969139""5245236922""5257046474""9055782274" "9451734694""3336374942""9321860896""6873615754""8137320887" "8797002906""5957865742"; static char sLn7[] = "1.9459101490""5531330510""5352743443""1797296370""8472958186" "1188459390""1499375798""6275206926""7787658498""5878715269" "9306169420""5851140912"; static char sLn10[] = "2.3025850929""9404568401""7991454684""3642076011""0148862877" "2976033327""9009675726""0967735248""0235997205""0895982983" "4196778404""2286248633"; static char sPi[] = "3.1415926535""8979323846""2643383279""5028841971""6939937510" "5820974944""5923078164""0628620899""8628034825""3421170679" "8214808651""3282306647""0938446095""5058223172""5359408128" "4811174502""8410270193""8521105559""6446229489""5493038196" "4428810976"; static char sPiDiv2[] = "1.5707963267""9489661923""1321691639""7514420985""8469968755" "2910487472""2961539082""0314310449""9314017412""6710585339" "9107404325""6641153324"; static char sPiDiv4[] = "0.7853981633""9744830961""5660845819""8757210492""9234984377" "6455243736""1480769541""0157155224""9657008706""3355292669" "9553702162""8320576662"; static char s2Pi[] = "6.2831853071""7958647692""5286766559""0057683943""3879875021" "1641949889""1846156328""1257241799""7256069650""6842341359" "6429617302""6564613294"; static char s1DivPi[] = "0.3183098861""8379067153""7767526745""0287240689""1929148091" "2897495334""6881177935""9526845307""0180227605""5325061719" "1214568545""3515916074"; static char sLnSqrt2PiMinusHalf[] = "0.4189385332""0467274178""0329736405""6176398613""9747363778" "3412817151""5404827656""9592726039""7694743298""6359541976" "2200564662""4634337446"; static char sSqrtPi[] = "1.7724538509""0551602729""8167483341""1451827975""4945612238" "7128213807""7898529112""8459103218""1374950656""7385446654" "1622682362""4282570666"; static char s1DivSqrtPi[] = "0.5641895835""4775628694""8079451560""7725858440""5062932899" "8856844085""7217106424""6844149341""4486743660""2021073634" "4302834790""6361707352"; static char s2DivSqrtPi[] = "1.1283791670""9551257389""6158903121""5451716881""0125865799" "7713688171""4434212849""3688298682""8973487320""4042147268" "8605669581""2723414703"; static char* sBernoulli[] = { "1", "6", "1", "-30", "1", "42", "1", "-30", "5", "66", "691", "-2730", "7", "6", "3617", "-510", "43867", "798", "174611", "-330", "854513", "138", "236364091", "-2730", "8553103", "6", "23749461029", "-870", "8615841276005", "14322", "7709321041217", "-510", "2577687858367", "6", "26315271553053477373", "-1919190", "2929993913841559", "6", "261082718496449122051", "-13530", "1520097643918070802691", "1806", "27833269579301024235023", "-690", "596451111593912163277961", "282", "5609403368997817686249127547", "-46410", "495057205241079648212477525", "66", "801165718135489957347924991853", "-1590", "29149963634884862421418123812691", "798", "2479392929313226753685415739663229", "-870", "84483613348880041862046775994036021", "354", "1215233140483755572040304994079820246041491", "-56786730", "12300585434086858541953039857403386151", "6", "106783830147866529886385444979142647942017", "-510", "1472600022126335654051619428551932342241899101", "64722", "78773130858718728141909149208474606244347001", "-30", "1505381347333367003803076567377857208511438160235", "4686", "5827954961669944110438277244641067365282488301844260429", "-140100870", "34152417289221168014330073731472635186688307783087", "6", "24655088825935372707687196040585199904365267828865801", "-30", "414846365575400828295179035549542073492199375372400483487", "3318", "4603784299479457646935574969019046849794257872751288919656867", "-230010", "1677014149185145836823154509786269900207736027570253414881613", "498", "2024576195935290360231131160111731009989917391198090877281083932477", "-3404310", "660714619417678653573847847426261496277830686653388931761996983", "6", "1311426488674017507995511424019311843345750275572028644296919890574047", "-61410", "1179057279021082799884123351249215083775254949669647116231545215727922535", "272118", "1295585948207537527989427828538576749659341483719435143023316326829946247", "-1410", "1220813806579744469607301679413201203958508415202696621436215105284649447", "6", "-4.70038339580357310785752555350060606545967373697590579151397635641e73", "1", "1.13180434454842492706751862577339342678903659547507479181789935417e76", "1", "-2.83822495706937069592641563364817647382846809280128821282285317145e78", "1", "7.40642489796788506297508271409209841768797317880887066731161003487e80", "1", "-2.00964548027566044834656196727153631868672708225328766243461301989e83", "1", "5.66571700508059414457193460305193569614194682875104206213875644522e85", "1", "-1.65845111541362169158237133743199123014949626147254647274024668156e88", "1", "5.03688599504923774192894219151801548124423742649032141415256513225e90", "1", "-1.58614682376581863693634015729664387827409784127789638804728645143e93", "1", "5.17567436175456269840732406825071225612408492359305508590621669403e95", "1", "-1.74889218402171173396900258776181591451414761618265448726273472159e98", "1", "6.11605199949521852558245252642641677807677268467832007168432401127e100", "1", "-2.2122776912707834942288323456712932445573185054987780150566552693e103", "1", "8.27227767987709698542210624599845957312046505184335662838488529886e105", "1", "-3.19589251114157095835916343691808148735262766710991122731845042431e108", "1", "1.27500822233877929823100243029266798669571917963897732951605857354e111", "1", "-5.25009230867741338994028246245651754469198940377552432607801345222e113", "1", "2.2301817894241625209869298198838728143738272150875878542490550781e116", "1", "-9.76845219309552044386335133989802393011669026749856789710001706619e118", "1", "4.40983619784529542722726228748131691918757542655281147353197591401e121", "1", "-2.05085708864640888397293377275830154864565966904008359530873982755e124", "1" }; floatstruct cBernoulliNum[68]; floatstruct cBernoulliDen[68]; floatstruct c1; floatstruct c2; floatstruct c3; floatstruct c12; floatstruct c16; floatstruct cMinus1; floatstruct cMinus20; floatstruct c1Div2; floatstruct cLn2; floatstruct cLn3; floatstruct cLn7; floatstruct cLn10; floatstruct cPi; floatstruct cPiDiv2; floatstruct cPiDiv4; floatstruct c2Pi; floatstruct c1DivPi; floatstruct cSqrtPi; floatstruct cLnSqrt2PiMinusHalf; floatstruct c1DivSqrtPi; floatstruct c2DivSqrtPi; floatstruct cMinus0_4; floatstruct cUnsignedBound; int erfcdigits = 0; floatstruct erfccoeff[MAXERFCIDX]; floatstruct erfcalpha; floatstruct erfcalphasqr; floatstruct erfct2; floatstruct erfct3; void floatmath_init() { int i, save; floatnum_init(); save = float_setprecision(MAXDIGITS); float_create(&c1); float_setinteger(&c1, 1); float_create(&c2); float_setinteger(&c2, 2); float_create(&c3); float_setinteger(&c3, 3); float_create(&c12); float_setinteger(&c12, 12); float_create(&c16); float_setinteger(&c16, 16); float_create(&cMinus1); float_setinteger(&cMinus1, -1); float_create(&cMinus20); float_setinteger(&cMinus20, -20); float_create(&c1Div2); float_setscientific(&c1Div2, ".5", NULLTERMINATED); float_create(&cLn2); float_setscientific(&cLn2, sLn2, NULLTERMINATED); float_create(&cLn3); float_setscientific(&cLn3, sLn3, NULLTERMINATED); float_create(&cLn7); float_setscientific(&cLn7, sLn7, NULLTERMINATED); float_create(&cLn10); float_setscientific(&cLn10, sLn10, NULLTERMINATED); float_create(&cPi); float_setscientific(&cPi, sPi, NULLTERMINATED); float_create(&cPiDiv2); float_setscientific(&cPiDiv2, sPiDiv2, NULLTERMINATED); float_create(&cPiDiv4); float_setscientific(&cPiDiv4, sPiDiv4, NULLTERMINATED); float_create(&c2Pi); float_setscientific(&c2Pi, s2Pi, NULLTERMINATED); float_create(&c1DivPi); float_setscientific(&c1DivPi, s1DivPi, NULLTERMINATED); float_create(&cSqrtPi); float_setscientific(&cSqrtPi, sSqrtPi, NULLTERMINATED); float_create(&cLnSqrt2PiMinusHalf); float_setscientific(&cLnSqrt2PiMinusHalf, sLnSqrt2PiMinusHalf, NULLTERMINATED); float_create(&c1DivSqrtPi); float_setscientific(&c1DivSqrtPi, s1DivSqrtPi, NULLTERMINATED); float_create(&c2DivSqrtPi); float_setscientific(&c2DivSqrtPi, s2DivSqrtPi, NULLTERMINATED); float_create(&cMinus0_4); float_setscientific(&cMinus0_4, "-.4", NULLTERMINATED); for (i = -1; ++i < MAXBERNOULLIIDX;) { float_create(&cBernoulliNum[i]); float_create(&cBernoulliDen[i]); float_setscientific(&cBernoulliNum[i], sBernoulli[2*i], NULLTERMINATED); float_setscientific(&cBernoulliDen[i], sBernoulli[2*i+1], NULLTERMINATED); } float_create(&cUnsignedBound); float_copy(&cUnsignedBound, &c1, EXACT); for (i = -1; ++i < 2*sizeof(unsigned);) float_mul(&cUnsignedBound, &c16, &cUnsignedBound, EXACT); for (i = -1; ++i < MAXERFCIDX;) float_create(&erfccoeff[i]); float_create(&erfcalpha); float_create(&erfcalphasqr); float_create(&erfct2); float_create(&erfct3); float_setprecision(save); } void floatmath_exit() { int i; float_free(&c1); float_free(&c2); float_free(&c3); float_free(&c12); float_free(&c16); float_free(&cMinus1); float_free(&cMinus20); float_free(&c1Div2); float_free(&cLn2); float_free(&cLn3); float_free(&cLn7); float_free(&cLn10); float_free(&cPi); float_free(&cPiDiv2); float_free(&cPiDiv4); float_free(&c2Pi); float_free(&c1DivPi); float_free(&cSqrtPi); float_free(&cLnSqrt2PiMinusHalf); float_free(&c1DivSqrtPi); float_free(&c2DivSqrtPi); float_free(&cMinus0_4); for (i = -1; ++i < MAXBERNOULLIIDX;) { float_free(&cBernoulliNum[i]); float_free(&cBernoulliDen[i]); } float_free(&cUnsignedBound); for (i = -1; ++i < MAXERFCIDX;) float_free(&erfccoeff[i]); float_free(&erfcalpha); float_free(&erfcalphasqr); float_free(&erfct2); float_free(&erfct3); } speedcrunch-0.10.1/src/math/floathmath.c0000644000175000001440000003047311015364561017302 0ustar helderusers/* floathmath.c: higher mathematical functions, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floathmath.h" #include "floatconst.h" #include "floatcommon.h" #include "floatlog.h" #include "floatexp.h" #include "floattrig.h" #include "floatpower.h" #include "floatipower.h" #include "floatgamma.h" #include "floaterf.h" #include "floatlogic.h" static char _cvtlogic( t_longint* lx, cfloatnum x) { if (float_isnan(x)) { float_seterror(NoOperand); return 0; } if (_floatnum2logic(lx, x)) return 1; float_seterror(OutOfLogicRange); return 0; } char float_lnxplus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) < 0 && float_getexponent(x) >= 0) return _seterror(x, OutOfDomain); _lnxplus1(x, digits); return 1; } char float_ln(floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) <= 0) return _seterror(x, OutOfDomain); _ln(x, digits); return 1; } char float_artanh( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getexponent(x) >= 0) return _seterror(x, OutOfDomain); _artanh(x, digits); return 1; } char float_artanhxplus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) >= 0 || float_abscmp(x, &c2) >= 0) return _seterror(x, OutOfDomain); if (float_cmp(x, &c1Div2) < 0) { float_neg(x); _artanh1minusx(x, digits); } else { float_sub(x, &c1, x, digits+1); _artanh(x, digits); } return 1; } char float_arsinh( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; _arsinh(x, digits); return 1; } char float_arcoshxplus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) < 0) return _seterror(x, OutOfDomain); _arcoshxplus1(x, digits); return 1; } char float_arcosh( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; float_sub(x, x, &c1, digits+1); return float_arcoshxplus1(x, digits); } char float_log( floatnum x, int digits) { floatstruct tmp; int expx; if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) <= 0) return _seterror(x, OutOfDomain); float_create(&tmp); expx = float_getexponent(x); float_setexponent(x, 0); _ln(x, digits); float_div(x, x, &cLn10, digits); float_setinteger(&tmp, expx); float_add(x, x, &tmp, digits); float_free(&tmp); return 1; } char float_lg( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) <= 0) return _seterror(x, OutOfDomain); _ln(x, digits); float_div(x, x, &cLn2, digits); return 1; } char float_exp( floatnum x, int digits) { signed char sgn; if (!chckmathparam(x, digits)) return 0; sgn = float_getsign(x); if (_exp(x, digits)) return 1; if (sgn < 0) return _seterror(x, Underflow); return _seterror(x, Overflow); } char float_expminus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (_expminus1(x, digits)) return 1; return _seterror(x, Overflow); } char float_cosh( floatnum x, int digits) { int expx; if (!chckmathparam(x, digits)) return 0; expx = float_getexponent(x); if (2*expx+2 <= -digits || !_coshminus1(x, digits+2*expx)) { if (expx > 0) return _seterror(x, Overflow); float_setzero(x); } return float_add(x, x, &c1, digits); } char float_coshminus1( floatnum x, int digits) { int expx; if (!chckmathparam(x, digits)) return 0; expx = float_getexponent(x); if (_coshminus1(x, digits)) return 1; if (expx < 0) return _seterror(x, Underflow); return _seterror(x, Overflow); } char float_sinh( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (_sinh(x, digits)) return 1; return _seterror(x, Overflow); } char float_tanh( floatnum x, int digits) { signed char sgn; if (!chckmathparam(x, digits)) return 0; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &c1Div2) >= 0) _tanhgt0_5(x, digits); else _tanhlt0_5(x, digits); float_setsign(x, sgn); return 1; } char float_tanhminus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_cmp(x, &c1Div2) >= 0) return _tanhminus1gt0(x, digits)? 1 : _seterror(x, Underflow); if (!float_iszero(x)) { if (float_abscmp(x, &c1Div2) <= 0) _tanhlt0_5(x, digits); else { float_setsign(x, 1); _tanhgt0_5(x, digits); float_setsign(x, -1); } } return float_sub(x, x, &c1, digits); } char float_arctan( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; _arctan(x, digits); return 1; } char float_arcsin( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_abscmp(x, &c1) > 0) return _seterror(x, OutOfDomain); _arcsin(x, digits); return 1; } char float_arccos( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_abscmp(x, &c1) > 0) return _seterror(x, OutOfDomain); _arccos(x, digits); return 1; } char float_arccosxplus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) > 0 || float_abscmp(x, &c2) > 0) return _seterror(x, OutOfDomain); _arccosxplus1(x, digits); return 1; } char float_cos( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getexponent(x) >= DECPRECISION - 1 || !_trigreduce(x, digits)) return _seterror(x, EvalUnstable); _cos(x, digits); return 1; } char float_cosminus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (!_trigreduce(x, digits)) return _seterror(x, EvalUnstable); return _cosminus1(x, digits)? 1 : _seterror(x, Underflow); } char float_sin( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getexponent(x) >= DECPRECISION - 1 || !_trigreduce(x, digits)) return _seterror(x, EvalUnstable); _sin(x, digits); return 1; } char float_tan( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; return float_getexponent(x) >= DECPRECISION - 1 || !_trigreduce(x, digits) || !_tan(x, digits)? _seterror(x, EvalUnstable) : 1; } char float_raisei( floatnum power, cfloatnum base, int exponent, int digits) { if (digits <= 0 || digits > maxdigits) return _seterror(power, InvalidPrecision); if (float_isnan(base)) return _seterror(power, NoOperand); if (float_iszero(base)) { if (exponent == 0) return _seterror(power, OutOfDomain); if (exponent < 0) return _seterror(power, ZeroDivide); return _setzero(power); } digits += 14; if (digits > maxdigits) digits = maxdigits; float_copy(power, base, digits); if (!_raisei(power, exponent, digits) || !float_isvalidexp(float_getexponent(power))) { if (float_getexponent(base) < 0) return _seterror(power, Underflow); return _seterror(power, Overflow); } return 1; } char float_raise( floatnum power, cfloatnum base, cfloatnum exponent, int digits) { signed char sgn; if (float_isnan(exponent) || float_isnan(base)) return _seterror(power, NoOperand); if (digits <= 0 || digits > MATHPRECISION) return _seterror(power, InvalidPrecision); if (float_iszero(base)) { switch(float_getsign(exponent)) { case 0: return _seterror(power, OutOfDomain); case -1: return _seterror(power, ZeroDivide); } return _setzero(power); } sgn = float_getsign(base); if (sgn < 0) { if (!float_isinteger(exponent)) return _seterror(power, OutOfDomain); if ((float_getdigit(exponent, float_getexponent(exponent)) & 1) == 0) sgn = 1; } float_copy(power, base, digits+1); float_abs(power); if (!_raise(power, exponent, digits)) { float_seterror(Overflow); if (float_getexponent(base) * float_getsign(exponent) < 0) float_seterror(Underflow); return _setnan(power); } float_setsign(power, sgn); return 1; } char float_power10( floatnum x, int digits) { signed char sign; if (!chckmathparam(x, digits)) return 0; sign = float_getsign(x); if (_power10(x, digits)) return 1; return sign > 0? _seterror(x, Overflow) : _seterror(x, Underflow); } char float_gamma( floatnum x, int digits) { signed char sign; char result; if (!chckmathparam(x, digits)) return 0; sign = float_getsign(x); if (float_isinteger(x)) { if (sign <= 0) return _seterror(x, ZeroDivide); result = _gammaint(x, digits); } else if (float_getlength(x) - float_getexponent(x) == 2 && float_getdigit(x, float_getlength(x) - 1) == 5) result = _gamma0_5(x, digits); else result = _gamma(x, digits); if (!result) { if (sign < 0) float_seterror(Underflow); else float_seterror(Overflow); float_setnan(x); } return result; } char float_lngamma( floatnum x, int digits) { if (x <= 0) return _seterror(x, OutOfDomain); return chckmathparam(x, digits) && _lngamma(x, digits)? 1 : _setnan(x); } char float_factorial( floatnum x, int digits) { if (!float_isnan(x)) float_add(x, x, &c1, digits); return float_gamma(x, digits); } char float_pochhammer( floatnum x, cfloatnum delta, int digits) { if (!chckmathparam(x, digits)) return 0; return float_isnan(delta)? _seterror(x, NoOperand) : _pochhammer(x, delta, digits); } char float_erf(floatnum x, int digits) { return chckmathparam(x, digits)? _erf(x, digits) : 0; } char float_erfc(floatnum x, int digits) { return chckmathparam(x, digits)? _erfc(x, digits) : 0; } char float_not( floatnum x) { t_longint lx; if(!_cvtlogic(&lx, x)) return _setnan(x); _not(&lx); _logic2floatnum(x, &lx); return 1; } char float_and( floatnum dest, cfloatnum x, cfloatnum y) { t_longint lx, ly; if(!_cvtlogic(&lx, x) || !_cvtlogic(&ly, y)) return _setnan(dest); _and(&lx, &ly); _logic2floatnum(dest, &lx); return 1; } char float_or( floatnum dest, cfloatnum x, cfloatnum y) { t_longint lx, ly; if(!_cvtlogic(&lx, x) || !_cvtlogic(&ly, y)) return _setnan(dest); _or(&lx, &ly); _logic2floatnum(dest, &lx); return 1; } char float_xor( floatnum dest, cfloatnum x, cfloatnum y) { t_longint lx, ly; if(!_cvtlogic(&lx, x) || !_cvtlogic(&ly, y)) return _setnan(dest); _xor(&lx, &ly); _logic2floatnum(dest, &lx); return 1; } char _doshift( floatnum dest, cfloatnum x, cfloatnum shift, char right) { int ishift; t_longint lx; if (float_isnan(shift)) return _seterror(dest, NoOperand); if (!float_isinteger(shift)) return _seterror(dest, OutOfDomain); if(!_cvtlogic(&lx, x)) return 0; if (float_iszero(shift)) { float_copy(dest, x, EXACT); return 1; } ishift = float_asinteger(shift); if (ishift == 0) ishift = (3*LOGICRANGE) * float_getsign(shift); if (!right) ishift = -ishift; if (ishift > 0) _shr(&lx, ishift); else _shl(&lx, -ishift); _logic2floatnum(dest, &lx); return 1; } char float_shr( floatnum dest, cfloatnum x, cfloatnum shift) { return _doshift(dest, x, shift, 1); } char float_shl( floatnum dest, cfloatnum x, cfloatnum shift) { return _doshift(dest, x, shift, 0); } speedcrunch-0.10.1/src/math/floatlogic.h0000644000175000001440000000322411015364561017275 0ustar helderusers/* floatlogic.h: logic functions, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATLOGIC_H # define _FLOATLOGIC_H #include "floatnum.h" #include "floatconvert.h" #ifdef __cplusplus extern "C" { #endif char _canconvert(cfloatnum x); char _floatnum2logic(t_longint* longint, cfloatnum x); void _logic2floatnum(floatnum f, t_longint* longint); void _not(t_longint* longint); void _and(t_longint* x1, t_longint* x2); void _or(t_longint* x1, t_longint* x2); void _xor(t_longint* x1, t_longint* x2); void _shr(t_longint* x, unsigned shift); void _shl(t_longint* x, unsigned shift); #ifdef __cplusplus } #endif #endif /* _FLOATLOGIC_H */ speedcrunch-0.10.1/src/math/floatlong.h0000644000175000001440000000451711015364561017145 0ustar helderusers/* floatlong.h: portable double size integer arithmetic */ /* Copyright (C) 2007 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATLONG_H # define _FLOATLONG_H #include "floatconfig.h" #ifdef __cplusplus extern "C" { #endif #define BITS_IN_UNSIGNED (sizeof(unsigned)*8) /* one unsigned extra, so that _bitsubstr() does not access parts outside of t_uarray */ #define UARRAYLG ((8305*(MATHPRECISION+5) + 1)/20000/sizeof(unsigned) + 2) typedef unsigned t_uarray[UARRAYLG]; typedef struct{ int length; t_uarray value; } t_longint; int _findfirstbit(unsigned value); char _longadd(unsigned* s1, unsigned* s2); char _longmul(unsigned* f1, unsigned* f2); char _checkadd(int* s1, int s2); char _checkmul(int* f1, int f2); unsigned _longshr(unsigned low, unsigned high, char shift); unsigned _longshl(unsigned low, unsigned high, char shift); unsigned _longarrayadd(unsigned* uarray, int lg, unsigned incr); unsigned _longarraymul(unsigned* uarray, int lg, unsigned factor); void _orsubstr(unsigned* uarray, int bitofs, unsigned value); unsigned _bitsubstr(unsigned* uarray, int ofs); unsigned _bitlength(t_longint* l); unsigned _lastnonzerobit(t_longint* l); char _longintsetsize(t_longint* l, unsigned bitlength); unsigned _longintadd(t_longint* l, unsigned summand); unsigned _longintmul(t_longint* l, unsigned factor); #ifdef __cplusplus } #endif #endif /* _FLOATLONG_H */ speedcrunch-0.10.1/src/math/floatipower.h0000644000175000001440000000267011015364561017511 0ustar helderusers/* floatpower.h: power operation, based on floatnum. */ /* Copyright (C) 2007 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATIPOWER_H # define _FLOATIPOWER_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif char __raiseposi(floatnum x, unsigned exponent, int digits); char _raiseposi(floatnum x, int* expx, unsigned exponent, int digits); char _raisei(floatnum x, int exponent, int digits); #ifdef __cplusplus } #endif #endif /* _FLOATIPOWER_H */ speedcrunch-0.10.1/src/math/floatexp.h0000644000175000001440000000336611015364561017003 0ustar helderusers/* floatexp.h: exponential function and friends, based on floatnum. */ /* Copyright (C) 2007 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATEXP_H # define _FLOATEXP_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif char _coshminus1lt1(floatnum x, int digits); void _sinhlt1(floatnum x, int digits); void _expminus1lt1(floatnum x, int digits); void _expltln10(floatnum x, int digits); char _exp(floatnum x, int digits); char _expminus1(floatnum x, int digits); char _coshminus1(floatnum x, int digits); void _tanhlt0_5(floatnum x, int digits); char _tanhminus1gt0(floatnum x, int digits); char _sinh(floatnum x, int digits); void _tanhgt0_5(floatnum x, int digits); char _power10(floatnum exponent, int digits); #ifdef __cplusplus } #endif #endif /* _FLOATEXP_H */ speedcrunch-0.10.1/src/math/number.c0000644000175000001440000012251711015364561016444 0ustar helderusers/* number.c: Implements arbitrary precision numbers. */ /* Copyright (C) 1991, 1992, 1993, 1994, 1997, 2000 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: philnelson@acm.org us-mail: Philip A. Nelson Computer Science Department, 9062 Western Washington University Bellingham, WA 98226-9062 !!!This is a patched file, the original file from bc 1.06 contains bugs in (a) bc_divide and (b) bc_int2num. A patch is applied here by Wolf Lammen, Oertzweg 45, 22307 Hamburg email ookami1 gmx de One patched line fixes a nasty bug, where a division by 1 may fail occasionly when an operand is overwritten by the result. The other one lets a conversion of an integer succeed, even if the most negative integer is passed as argument *************************************************************************/ #include "number.h" #include #include #include #include #include /* Prototypes needed for external utility routines. */ #define bc_rt_warn rt_warn #define bc_rt_error rt_error #define bc_out_of_memory out_of_memory _PROTOTYPE(void rt_warn, (char *mesg ,...)); _PROTOTYPE(void rt_error, (char *mesg ,...)); _PROTOTYPE(void out_of_memory, (void)); void out_of_memory(void){ return; } void rt_warn(char *mesg ,...){ return; } void rt_error(char *mesg ,...){ return; } /* Storage used for special numbers. */ bc_num _zero_; bc_num _one_; bc_num _two_; static bc_num _bc_Free_list = NULL; /* new_num allocates a number and sets fields to known values. */ bc_num bc_new_num (length, scale) int length, scale; { bc_num temp; if (_bc_Free_list != NULL) { temp = _bc_Free_list; _bc_Free_list = temp->n_next; } else { temp = (bc_num) malloc (sizeof(bc_struct)); if (temp == NULL) bc_out_of_memory (); } temp->n_sign = PLUS; temp->n_len = length; temp->n_scale = scale; temp->n_refs = 1; temp->n_ptr = (char *) malloc (length+scale+1); if (temp->n_ptr == NULL) bc_out_of_memory(); temp->n_value = temp->n_ptr; memset (temp->n_ptr, 0, length+scale); return temp; } /* "Frees" a bc_num NUM. Actually decreases reference count and only frees the storage if reference count is zero. */ void bc_free_num (num) bc_num *num; { if (*num == NULL) return; (*num)->n_refs--; if ((*num)->n_refs == 0) { if ((*num)->n_ptr) free ((*num)->n_ptr); (*num)->n_next = _bc_Free_list; _bc_Free_list = *num; } *num = NULL; } /* Intitialize the number package! */ void bc_init_numbers () { _zero_ = bc_new_num (1,0); _one_ = bc_new_num (1,0); _one_->n_value[0] = 1; _two_ = bc_new_num (1,0); _two_->n_value[0] = 2; } /* Make a copy of a number! Just increments the reference count! */ bc_num bc_copy_num (num) bc_num num; { num->n_refs++; return num; } /* Initialize a number NUM by making it a copy of zero. */ void bc_init_num (num) bc_num *num; { *num = bc_copy_num (_zero_); } /* For many things, we may have leading zeros in a number NUM. _bc_rm_leading_zeros just moves the data "value" pointer to the correct place and adjusts the length. */ static void _bc_rm_leading_zeros (num) bc_num num; { /* We can move n_value to point to the first non zero digit! */ while (*num->n_value == 0 && num->n_len > 1) { num->n_value++; num->n_len--; } } /* Compare two bc numbers. Return value is 0 if equal, -1 if N1 is less than N2 and +1 if N1 is greater than N2. If USE_SIGN is false, just compare the magnitudes. */ static int _bc_do_compare (n1, n2, use_sign, ignore_last) bc_num n1, n2; int use_sign; int ignore_last; { char *n1ptr, *n2ptr; int count; /* First, compare signs. */ if (use_sign && n1->n_sign != n2->n_sign) { if (n1->n_sign == PLUS) return (1); /* Positive N1 > Negative N2 */ else return (-1); /* Negative N1 < Positive N1 */ } /* Now compare the magnitude. */ if (n1->n_len != n2->n_len) { if (n1->n_len > n2->n_len) { /* Magnitude of n1 > n2. */ if (!use_sign || n1->n_sign == PLUS) return (1); else return (-1); } else { /* Magnitude of n1 < n2. */ if (!use_sign || n1->n_sign == PLUS) return (-1); else return (1); } } /* If we get here, they have the same number of integer digits. check the integer part and the equal length part of the fraction. */ count = n1->n_len + MIN (n1->n_scale, n2->n_scale); n1ptr = n1->n_value; n2ptr = n2->n_value; while ((count > 0) && (*n1ptr == *n2ptr)) { n1ptr++; n2ptr++; count--; } if (ignore_last && count == 1 && n1->n_scale == n2->n_scale) return (0); if (count != 0) { if (*n1ptr > *n2ptr) { /* Magnitude of n1 > n2. */ if (!use_sign || n1->n_sign == PLUS) return (1); else return (-1); } else { /* Magnitude of n1 < n2. */ if (!use_sign || n1->n_sign == PLUS) return (-1); else return (1); } } /* They are equal up to the last part of the equal part of the fraction. */ if (n1->n_scale != n2->n_scale) { if (n1->n_scale > n2->n_scale) { for (count = n1->n_scale-n2->n_scale; count>0; count--) if (*n1ptr++ != 0) { /* Magnitude of n1 > n2. */ if (!use_sign || n1->n_sign == PLUS) return (1); else return (-1); } } else { for (count = n2->n_scale-n1->n_scale; count>0; count--) if (*n2ptr++ != 0) { /* Magnitude of n1 < n2. */ if (!use_sign || n1->n_sign == PLUS) return (-1); else return (1); } } } /* They must be equal! */ return (0); } /* This is the "user callable" routine to compare numbers N1 and N2. */ int bc_compare (n1, n2) bc_num n1, n2; { return _bc_do_compare (n1, n2, TRUE, FALSE); } /* In some places we need to check if the number is negative. */ char bc_is_neg (num) bc_num num; { return num->n_sign == MINUS; } /* In some places we need to check if the number NUM is zero. */ char bc_is_zero (num) bc_num num; { int count; char *nptr; /* Quick check. */ if (num == _zero_) return TRUE; /* Initialize */ count = num->n_len + num->n_scale; nptr = num->n_value; /* The check */ while ((count > 0) && (*nptr++ == 0)) count--; if (count != 0) return FALSE; else return TRUE; } /* In some places we need to check if the number NUM is almost zero. Specifically, all but the last digit is 0 and the last digit is 1. Last digit is defined by scale. */ char bc_is_near_zero (num, scale) bc_num num; int scale; { int count; char *nptr; /* Error checking */ if (scale > num->n_scale) scale = num->n_scale; /* Initialize */ count = num->n_len + scale; nptr = num->n_value; /* The check */ while ((count > 0) && (*nptr++ == 0)) count--; if (count != 0 && (count != 1 || *--nptr != 1)) return FALSE; else return TRUE; } /* Perform addition: N1 is added to N2 and the value is returned. The signs of N1 and N2 are ignored. SCALE_MIN is to set the minimum scale of the result. */ static bc_num _bc_do_add (n1, n2, scale_min) bc_num n1, n2; int scale_min; { bc_num sum; int sum_scale, sum_digits; char *n1ptr, *n2ptr, *sumptr; int carry, n1bytes, n2bytes; int count; /* Prepare sum. */ sum_scale = MAX (n1->n_scale, n2->n_scale); sum_digits = MAX (n1->n_len, n2->n_len) + 1; sum = bc_new_num (sum_digits, MAX(sum_scale, scale_min)); /* Zero extra digits made by scale_min. */ if (scale_min > sum_scale) { sumptr = (char *) (sum->n_value + sum_scale + sum_digits); for (count = scale_min - sum_scale; count > 0; count--) *sumptr++ = 0; } /* Start with the fraction part. Initialize the pointers. */ n1bytes = n1->n_scale; n2bytes = n2->n_scale; n1ptr = (char *) (n1->n_value + n1->n_len + n1bytes - 1); n2ptr = (char *) (n2->n_value + n2->n_len + n2bytes - 1); sumptr = (char *) (sum->n_value + sum_scale + sum_digits - 1); /* Add the fraction part. First copy the longer fraction.*/ if (n1bytes != n2bytes) { if (n1bytes > n2bytes) while (n1bytes>n2bytes) { *sumptr-- = *n1ptr--; n1bytes--;} else while (n2bytes>n1bytes) { *sumptr-- = *n2ptr--; n2bytes--;} } /* Now add the remaining fraction part and equal size integer parts. */ n1bytes += n1->n_len; n2bytes += n2->n_len; carry = 0; while ((n1bytes > 0) && (n2bytes > 0)) { *sumptr = *n1ptr-- + *n2ptr-- + carry; if (*sumptr > (BASE-1)) { carry = 1; *sumptr -= BASE; } else carry = 0; sumptr--; n1bytes--; n2bytes--; } /* Now add carry the longer integer part. */ if (n1bytes == 0) { n1bytes = n2bytes; n1ptr = n2ptr; } while (n1bytes-- > 0) { *sumptr = *n1ptr-- + carry; if (*sumptr > (BASE-1)) { carry = 1; *sumptr -= BASE; } else carry = 0; sumptr--; } /* Set final carry. */ if (carry == 1) *sumptr += 1; /* Adjust sum and return. */ _bc_rm_leading_zeros (sum); return sum; } /* Perform subtraction: N2 is subtracted from N1 and the value is returned. The signs of N1 and N2 are ignored. Also, N1 is assumed to be larger than N2. SCALE_MIN is the minimum scale of the result. */ static bc_num _bc_do_sub (n1, n2, scale_min) bc_num n1, n2; int scale_min; { bc_num diff; int diff_scale, diff_len; int min_scale, min_len; char *n1ptr, *n2ptr, *diffptr; int borrow, count, val; /* Allocate temporary storage. */ diff_len = MAX (n1->n_len, n2->n_len); diff_scale = MAX (n1->n_scale, n2->n_scale); min_len = MIN (n1->n_len, n2->n_len); min_scale = MIN (n1->n_scale, n2->n_scale); diff = bc_new_num (diff_len, MAX(diff_scale, scale_min)); /* Zero extra digits made by scale_min. */ if (scale_min > diff_scale) { diffptr = (char *) (diff->n_value + diff_len + diff_scale); for (count = scale_min - diff_scale; count > 0; count--) *diffptr++ = 0; } /* Initialize the subtract. */ n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale -1); n2ptr = (char *) (n2->n_value + n2->n_len + n2->n_scale -1); diffptr = (char *) (diff->n_value + diff_len + diff_scale -1); /* Subtract the numbers. */ borrow = 0; /* Take care of the longer scaled number. */ if (n1->n_scale != min_scale) { /* n1 has the longer scale */ for (count = n1->n_scale - min_scale; count > 0; count--) *diffptr-- = *n1ptr--; } else { /* n2 has the longer scale */ for (count = n2->n_scale - min_scale; count > 0; count--) { val = - *n2ptr-- - borrow; if (val < 0) { val += BASE; borrow = 1; } else borrow = 0; *diffptr-- = val; } } /* Now do the equal length scale and integer parts. */ for (count = 0; count < min_len + min_scale; count++) { val = *n1ptr-- - *n2ptr-- - borrow; if (val < 0) { val += BASE; borrow = 1; } else borrow = 0; *diffptr-- = val; } /* If n1 has more digits then n2, we now do that subtract. */ if (diff_len != min_len) { for (count = diff_len - min_len; count > 0; count--) { val = *n1ptr-- - borrow; if (val < 0) { val += BASE; borrow = 1; } else borrow = 0; *diffptr-- = val; } } /* Clean up and return. */ _bc_rm_leading_zeros (diff); return diff; } /* Here is the full subtract routine that takes care of negative numbers. N2 is subtracted from N1 and the result placed in RESULT. SCALE_MIN is the minimum scale for the result. */ void bc_sub (n1, n2, result, scale_min) bc_num n1, n2, *result; int scale_min; { bc_num diff = NULL; int cmp_res; int res_scale; if (n1->n_sign != n2->n_sign) { diff = _bc_do_add (n1, n2, scale_min); diff->n_sign = n1->n_sign; } else { /* subtraction must be done. */ /* Compare magnitudes. */ cmp_res = _bc_do_compare (n1, n2, FALSE, FALSE); switch (cmp_res) { case -1: /* n1 is less than n2, subtract n1 from n2. */ diff = _bc_do_sub (n2, n1, scale_min); diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS); break; case 0: /* They are equal! return zero! */ res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale)); diff = bc_new_num (1, res_scale); memset (diff->n_value, 0, res_scale+1); break; case 1: /* n2 is less than n1, subtract n2 from n1. */ diff = _bc_do_sub (n1, n2, scale_min); diff->n_sign = n1->n_sign; break; } } /* Clean up and return. */ bc_free_num (result); *result = diff; } /* Here is the full add routine that takes care of negative numbers. N1 is added to N2 and the result placed into RESULT. SCALE_MIN is the minimum scale for the result. */ void bc_add (n1, n2, result, scale_min) bc_num n1, n2, *result; int scale_min; { bc_num sum = NULL; int cmp_res; int res_scale; if (n1->n_sign == n2->n_sign) { sum = _bc_do_add (n1, n2, scale_min); sum->n_sign = n1->n_sign; } else { /* subtraction must be done. */ cmp_res = _bc_do_compare (n1, n2, FALSE, FALSE); /* Compare magnitudes. */ switch (cmp_res) { case -1: /* n1 is less than n2, subtract n1 from n2. */ sum = _bc_do_sub (n2, n1, scale_min); sum->n_sign = n2->n_sign; break; case 0: /* They are equal! return zero with the correct scale! */ res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale)); sum = bc_new_num (1, res_scale); memset (sum->n_value, 0, res_scale+1); break; case 1: /* n2 is less than n1, subtract n2 from n1. */ sum = _bc_do_sub (n1, n2, scale_min); sum->n_sign = n1->n_sign; } } /* Clean up and return. */ bc_free_num (result); *result = sum; } /* Recursive vs non-recursive multiply crossover ranges. */ #if defined(MULDIGITS) #include "muldigits.h" #else #define MUL_BASE_DIGITS 80 #endif int mul_base_digits = MUL_BASE_DIGITS; #define MUL_SMALL_DIGITS mul_base_digits/4 /* Multiply utility routines */ static bc_num new_sub_num (length, scale, value) int length, scale; char *value; { bc_num temp; if (_bc_Free_list != NULL) { temp = _bc_Free_list; _bc_Free_list = temp->n_next; } else { temp = (bc_num) malloc (sizeof(bc_struct)); if (temp == NULL) bc_out_of_memory (); } temp->n_sign = PLUS; temp->n_len = length; temp->n_scale = scale; temp->n_refs = 1; temp->n_ptr = NULL; temp->n_value = value; return temp; } static void _bc_simp_mul (bc_num n1, int n1len, bc_num n2, int n2len, bc_num *prod, int full_scale) { char *n1ptr, *n2ptr, *pvptr; char *n1end, *n2end; /* To the end of n1 and n2. */ int indx, sum, prodlen; prodlen = n1len+n2len+1; *prod = bc_new_num (prodlen, 0); n1end = (char *) (n1->n_value + n1len - 1); n2end = (char *) (n2->n_value + n2len - 1); pvptr = (char *) ((*prod)->n_value + prodlen - 1); sum = 0; /* Here is the loop... */ for (indx = 0; indx < prodlen-1; indx++) { n1ptr = (char *) (n1end - MAX(0, indx-n2len+1)); n2ptr = (char *) (n2end - MIN(indx, n2len-1)); while ((n1ptr >= n1->n_value) && (n2ptr <= n2end)) sum += *n1ptr-- * *n2ptr++; *pvptr-- = sum % BASE; sum = sum / BASE; } *pvptr = sum; } /* A special adder/subtractor for the recursive divide and conquer multiply algorithm. Note: if sub is called, accum must be larger that what is being subtracted. Also, accum and val must have n_scale = 0. (e.g. they must look like integers. *) */ static void _bc_shift_addsub (bc_num accum, bc_num val, int shift, int sub) { signed char *accp, *valp; int count, carry; count = val->n_len; if (val->n_value[0] == 0) count--; assert (accum->n_len+accum->n_scale >= shift+count); /* Set up pointers and others */ accp = (signed char *)(accum->n_value + accum->n_len + accum->n_scale - shift - 1); valp = (signed char *)(val->n_value + val->n_len - 1); carry = 0; if (sub) { /* Subtraction, carry is really borrow. */ while (count--) { *accp -= *valp-- + carry; if (*accp < 0) { carry = 1; *accp-- += BASE; } else { carry = 0; accp--; } } while (carry) { *accp -= carry; if (*accp < 0) *accp-- += BASE; else carry = 0; } } else { /* Addition */ while (count--) { *accp += *valp-- + carry; if (*accp > (BASE-1)) { carry = 1; *accp-- -= BASE; } else { carry = 0; accp--; } } while (carry) { *accp += carry; if (*accp > (BASE-1)) *accp-- -= BASE; else carry = 0; } } } /* Recursive divide and conquer multiply algorithm. Based on Let u = u0 + u1*(b^n) Let v = v0 + v1*(b^n) Then uv = (B^2n+B^n)*u1*v1 + B^n*(u1-u0)*(v0-v1) + (B^n+1)*u0*v0 B is the base of storage, number of digits in u1,u0 close to equal. */ static void _bc_rec_mul (bc_num u, int ulen, bc_num v, int vlen, bc_num *prod, int full_scale) { bc_num u0, u1, v0, v1; int u0len, v0len; bc_num m1, m2, m3, d1, d2; int n, prodlen, m1zero; int d1len, d2len; /* Base case? */ if ((ulen+vlen) < mul_base_digits || ulen < MUL_SMALL_DIGITS || vlen < MUL_SMALL_DIGITS ) { _bc_simp_mul (u, ulen, v, vlen, prod, full_scale); return; } /* Calculate n -- the u and v split point in digits. */ n = (MAX(ulen, vlen)+1) / 2; /* Split u and v. */ if (ulen < n) { u1 = bc_copy_num (_zero_); u0 = new_sub_num (ulen,0, u->n_value); } else { u1 = new_sub_num (ulen-n, 0, u->n_value); u0 = new_sub_num (n, 0, u->n_value+ulen-n); } if (vlen < n) { v1 = bc_copy_num (_zero_); v0 = new_sub_num (vlen,0, v->n_value); } else { v1 = new_sub_num (vlen-n, 0, v->n_value); v0 = new_sub_num (n, 0, v->n_value+vlen-n); } _bc_rm_leading_zeros (u1); _bc_rm_leading_zeros (u0); u0len = u0->n_len; _bc_rm_leading_zeros (v1); _bc_rm_leading_zeros (v0); v0len = v0->n_len; m1zero = bc_is_zero(u1) || bc_is_zero(v1); /* Calculate sub results ... */ bc_init_num(&d1); bc_init_num(&d2); bc_sub (u1, u0, &d1, 0); d1len = d1->n_len; bc_sub (v0, v1, &d2, 0); d2len = d2->n_len; /* Do recursive multiplies and shifted adds. */ if (m1zero) m1 = bc_copy_num (_zero_); else _bc_rec_mul (u1, u1->n_len, v1, v1->n_len, &m1, 0); if (bc_is_zero(d1) || bc_is_zero(d2)) m2 = bc_copy_num (_zero_); else _bc_rec_mul (d1, d1len, d2, d2len, &m2, 0); if (bc_is_zero(u0) || bc_is_zero(v0)) m3 = bc_copy_num (_zero_); else _bc_rec_mul (u0, u0->n_len, v0, v0->n_len, &m3, 0); /* Initialize product */ prodlen = ulen+vlen+1; *prod = bc_new_num(prodlen, 0); if (!m1zero) { _bc_shift_addsub (*prod, m1, 2*n, 0); _bc_shift_addsub (*prod, m1, n, 0); } _bc_shift_addsub (*prod, m3, n, 0); _bc_shift_addsub (*prod, m3, 0, 0); _bc_shift_addsub (*prod, m2, n, d1->n_sign != d2->n_sign); /* Now clean up! */ bc_free_num (&u1); bc_free_num (&u0); bc_free_num (&v1); bc_free_num (&m1); bc_free_num (&v0); bc_free_num (&m2); bc_free_num (&m3); bc_free_num (&d1); bc_free_num (&d2); } /* The multiply routine. N2 times N1 is put int PROD with the scale of the result being MIN(N2 scale+N1 scale, MAX (SCALE, N2 scale, N1 scale)). */ void bc_multiply (n1, n2, prod, scale) bc_num n1, n2, *prod; int scale; { bc_num pval; int len1, len2; int full_scale, prod_scale; /* Initialize things. */ len1 = n1->n_len + n1->n_scale; len2 = n2->n_len + n2->n_scale; full_scale = n1->n_scale + n2->n_scale; prod_scale = MIN(full_scale,MAX(scale,MAX(n1->n_scale,n2->n_scale))); /* Do the multiply */ _bc_rec_mul (n1, len1, n2, len2, &pval, full_scale); /* Assign to prod and clean up the number. */ pval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS ); pval->n_value = pval->n_ptr; pval->n_len = len2 + len1 + 1 - full_scale; pval->n_scale = prod_scale; _bc_rm_leading_zeros (pval); if (bc_is_zero (pval)) pval->n_sign = PLUS; bc_free_num (prod); *prod = pval; } /* Some utility routines for the divide: First a one digit multiply. NUM (with SIZE digits) is multiplied by DIGIT and the result is placed into RESULT. It is written so that NUM and RESULT can be the same pointers. */ static void _one_mult (num, size, digit, result) unsigned char *num; int size, digit; unsigned char *result; { int carry, value; unsigned char *nptr, *rptr; if (digit == 0) memset (result, 0, size); else { if (digit == 1) memcpy (result, num, size); else { /* Initialize */ nptr = (unsigned char *) (num+size-1); rptr = (unsigned char *) (result+size-1); carry = 0; while (size-- > 0) { value = *nptr-- * digit + carry; *rptr-- = value % BASE; carry = value / BASE; } if (carry != 0) *rptr = carry; } } } /* The full division routine. This computes N1 / N2. It returns 0 if the division is ok and the result is in QUOT. The number of digits after the decimal point is SCALE. It returns -1 if division by zero is tried. The algorithm is found in Knuth Vol 2. p237. */ int bc_divide (n1, n2, quot, scale) bc_num n1, n2, *quot; int scale; { bc_num qval; unsigned char *num1, *num2; unsigned char *ptr1, *ptr2, *n2ptr, *qptr; int scale1, val; unsigned int len1, len2, scale2, qdigits, extra, count; unsigned int qdig, qguess, borrow, carry; unsigned char *mval; char zero; unsigned int norm; /* Test for divide by zero. */ if (bc_is_zero (n2)) return -1; /* Test for divide by 1. If it is we must truncate. */ if (n2->n_scale == 0) { if (n2->n_len == 1 && *n2->n_value == 1) { qval = bc_new_num (n1->n_len, scale); qval->n_sign = (n1->n_sign == n2->n_sign ? PLUS : MINUS); memset (&qval->n_value[n1->n_len],0,scale); memcpy (qval->n_value, n1->n_value, n1->n_len + MIN(n1->n_scale,scale)); bc_free_num (quot); *quot = qval; return 0; /* bug fix Wolf Lammen */ } } /* Set up the divide. Move the decimal point on n1 by n2's scale. Remember, zeros on the end of num2 are wasted effort for dividing. */ scale2 = n2->n_scale; n2ptr = (unsigned char *) n2->n_value+n2->n_len+scale2-1; while ((scale2 > 0) && (*n2ptr-- == 0)) scale2--; len1 = n1->n_len + scale2; scale1 = n1->n_scale - scale2; if (scale1 < scale) extra = scale - scale1; else extra = 0; num1 = (unsigned char *) malloc (n1->n_len+n1->n_scale+extra+2); if (num1 == NULL) bc_out_of_memory(); memset (num1, 0, n1->n_len+n1->n_scale+extra+2); memcpy (num1+1, n1->n_value, n1->n_len+n1->n_scale); len2 = n2->n_len + scale2; num2 = (unsigned char *) malloc (len2+1); if (num2 == NULL) bc_out_of_memory(); memcpy (num2, n2->n_value, len2); *(num2+len2) = 0; n2ptr = num2; while (*n2ptr == 0) { n2ptr++; len2--; } /* Calculate the number of quotient digits. */ if (len2 > len1+scale) { qdigits = scale+1; zero = TRUE; } else { zero = FALSE; if (len2>len1) qdigits = scale+1; /* One for the zero integer part. */ else qdigits = len1-len2+scale+1; } /* Allocate and zero the storage for the quotient. */ qval = bc_new_num (qdigits-scale,scale); memset (qval->n_value, 0, qdigits); /* Allocate storage for the temporary storage mval. */ mval = (unsigned char *) malloc (len2+1); if (mval == NULL) bc_out_of_memory (); /* Now for the full divide algorithm. */ if (!zero) { /* Normalize */ norm = 10 / ((int)*n2ptr + 1); if (norm != 1) { _one_mult (num1, len1+scale1+extra+1, norm, num1); _one_mult (n2ptr, len2, norm, n2ptr); } /* Initialize divide loop. */ qdig = 0; if (len2 > len1) qptr = (unsigned char *) qval->n_value+len2-len1; else qptr = (unsigned char *) qval->n_value; /* Loop */ while (qdig <= len1+scale-len2) { /* Calculate the quotient digit guess. */ if (*n2ptr == num1[qdig]) qguess = 9; else qguess = (num1[qdig]*10 + num1[qdig+1]) / *n2ptr; /* Test qguess. */ if (n2ptr[1]*qguess > (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10 + num1[qdig+2]) { qguess--; /* And again. */ if (n2ptr[1]*qguess > (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10 + num1[qdig+2]) qguess--; } /* Multiply and subtract. */ borrow = 0; if (qguess != 0) { *mval = 0; _one_mult (n2ptr, len2, qguess, mval+1); ptr1 = (unsigned char *) num1+qdig+len2; ptr2 = (unsigned char *) mval+len2; for (count = 0; count < len2+1; count++) { val = (int) *ptr1 - (int) *ptr2-- - borrow; if (val < 0) { val += 10; borrow = 1; } else borrow = 0; *ptr1-- = val; } } /* Test for negative result. */ if (borrow == 1) { qguess--; ptr1 = (unsigned char *) num1+qdig+len2; ptr2 = (unsigned char *) n2ptr+len2-1; carry = 0; for (count = 0; count < len2; count++) { val = (int) *ptr1 + (int) *ptr2-- + carry; if (val > 9) { val -= 10; carry = 1; } else carry = 0; *ptr1-- = val; } if (carry == 1) *ptr1 = (*ptr1 + 1) % 10; } /* We now know the quotient digit. */ *qptr++ = qguess; qdig++; } } /* Clean up and return the number. */ qval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS ); if (bc_is_zero (qval)) qval->n_sign = PLUS; _bc_rm_leading_zeros (qval); bc_free_num (quot); *quot = qval; /* Clean up temporary storage. */ free (mval); free (num1); free (num2); return 0; /* Everything is OK. */ } /* Division *and* modulo for numbers. This computes both NUM1 / NUM2 and NUM1 % NUM2 and puts the results in QUOT and REM, except that if QUOT is NULL then that store will be omitted. */ int bc_divmod (num1, num2, quot, rem, scale) bc_num num1, num2, *quot, *rem; int scale; { bc_num quotient = NULL; bc_num temp; int rscale; /* Check for correct numbers. */ if (bc_is_zero (num2)) return -1; /* Calculate final scale. */ rscale = MAX (num1->n_scale, num2->n_scale+scale); bc_init_num(&temp); /* Calculate it. */ bc_divide (num1, num2, &temp, scale); if (quot) quotient = bc_copy_num (temp); bc_multiply (temp, num2, &temp, rscale); bc_sub (num1, temp, rem, rscale); bc_free_num (&temp); if (quot) { bc_free_num (quot); *quot = quotient; } return 0; /* Everything is OK. */ } /* Modulo for numbers. This computes NUM1 % NUM2 and puts the result in RESULT. */ int bc_modulo (num1, num2, result, scale) bc_num num1, num2, *result; int scale; { return bc_divmod (num1, num2, NULL, result, scale); } /* Raise BASE to the EXPO power, reduced modulo MOD. The result is placed in RESULT. If a EXPO is not an integer, only the integer part is used. */ int bc_raisemod (base, expo, mod, result, scale) bc_num base, expo, mod, *result; int scale; { bc_num power, exponent, parity, temp; int rscale; /* Check for correct numbers. */ if (bc_is_zero(mod)) return -1; if (bc_is_neg(expo)) return -1; /* Set initial values. */ power = bc_copy_num (base); exponent = bc_copy_num (expo); temp = bc_copy_num (_one_); bc_init_num(&parity); /* Check the base for scale digits. */ if (base->n_scale != 0) bc_rt_warn ("non-zero scale in base"); /* Check the exponent for scale digits. */ if (exponent->n_scale != 0) { bc_rt_warn ("non-zero scale in exponent"); bc_divide (exponent, _one_, &exponent, 0); /*truncate */ } /* Check the modulus for scale digits. */ if (mod->n_scale != 0) bc_rt_warn ("non-zero scale in modulus"); /* Do the calculation. */ rscale = MAX(scale, base->n_scale); while ( !bc_is_zero(exponent) ) { (void) bc_divmod (exponent, _two_, &exponent, &parity, 0); if ( !bc_is_zero(parity) ) { bc_multiply (temp, power, &temp, rscale); (void) bc_modulo (temp, mod, &temp, scale); } bc_multiply (power, power, &power, rscale); (void) bc_modulo (power, mod, &power, scale); } /* Assign the value. */ bc_free_num (&power); bc_free_num (&exponent); bc_free_num (result); *result = temp; return 0; /* Everything is OK. */ } /* Raise NUM1 to the NUM2 power. The result is placed in RESULT. Maximum exponent is LONG_MAX. If a NUM2 is not an integer, only the integer part is used. */ void bc_raise (num1, num2, result, scale) bc_num num1, num2, *result; int scale; { bc_num temp, power; long exponent; int rscale; int pwrscale; int calcscale; char neg; /* Check the exponent for scale digits and convert to a long. */ if (num2->n_scale != 0) bc_rt_warn ("non-zero scale in exponent"); exponent = bc_num2long (num2); if (exponent == 0 && (num2->n_len > 1 || num2->n_value[0] != 0)) bc_rt_error ("exponent too large in raise"); /* Special case if exponent is a zero. */ if (exponent == 0) { bc_free_num (result); *result = bc_copy_num (_one_); return; } /* Other initializations. */ if (exponent < 0) { neg = TRUE; exponent = -exponent; rscale = scale; } else { neg = FALSE; rscale = MIN (num1->n_scale*exponent, MAX(scale, num1->n_scale)); } /* Set initial value of temp. */ power = bc_copy_num (num1); pwrscale = num1->n_scale; while ((exponent & 1) == 0) { pwrscale = 2*pwrscale; bc_multiply (power, power, &power, pwrscale); exponent = exponent >> 1; } temp = bc_copy_num (power); calcscale = pwrscale; exponent = exponent >> 1; /* Do the calculation. */ while (exponent > 0) { pwrscale = 2*pwrscale; bc_multiply (power, power, &power, pwrscale); if ((exponent & 1) == 1) { calcscale = pwrscale + calcscale; bc_multiply (temp, power, &temp, calcscale); } exponent = exponent >> 1; } /* Assign the value. */ if (neg) { bc_divide (_one_, temp, result, rscale); bc_free_num (&temp); } else { bc_free_num (result); *result = temp; if ((*result)->n_scale > rscale) (*result)->n_scale = rscale; } bc_free_num (&power); } /* Take the square root NUM and return it in NUM with SCALE digits after the decimal place. */ int bc_sqrt (num, scale) bc_num *num; int scale; { int rscale, cmp_res, done; int cscale; bc_num guess, guess1, point5, diff; /* Initial checks. */ cmp_res = bc_compare (*num, _zero_); if (cmp_res < 0) return 0; /* error */ else { if (cmp_res == 0) { bc_free_num (num); *num = bc_copy_num (_zero_); return 1; } } cmp_res = bc_compare (*num, _one_); if (cmp_res == 0) { bc_free_num (num); *num = bc_copy_num (_one_); return 1; } /* Initialize the variables. */ rscale = MAX (scale, (*num)->n_scale); bc_init_num(&guess); bc_init_num(&guess1); bc_init_num(&diff); point5 = bc_new_num (1,1); point5->n_value[1] = 5; /* Calculate the initial guess. */ if (cmp_res < 0) { /* The number is between 0 and 1. Guess should start at 1. */ guess = bc_copy_num (_one_); cscale = (*num)->n_scale; } else { /* The number is greater than 1. Guess should start at 10^(exp/2). */ bc_int2num (&guess,10); bc_int2num (&guess1,(*num)->n_len); bc_multiply (guess1, point5, &guess1, 0); guess1->n_scale = 0; bc_raise (guess, guess1, &guess, 0); bc_free_num (&guess1); cscale = 3; } /* Find the square root using Newton's algorithm. */ done = FALSE; while (!done) { bc_free_num (&guess1); guess1 = bc_copy_num (guess); bc_divide (*num, guess, &guess, cscale); bc_add (guess, guess1, &guess, 0); bc_multiply (guess, point5, &guess, cscale); bc_sub (guess, guess1, &diff, cscale+1); if (bc_is_near_zero (diff, cscale)) { if (cscale < rscale+1) cscale = MIN (cscale*3, rscale+1); else done = TRUE; } } /* Assign the number and clean up. */ bc_free_num (num); bc_divide (guess,_one_,num,rscale); bc_free_num (&guess); bc_free_num (&guess1); bc_free_num (&point5); bc_free_num (&diff); return 1; } /* The following routines provide output for bcd numbers package using the rules of POSIX bc for output. */ /* This structure is used for saving digits in the conversion process. */ typedef struct stk_rec { long digit; struct stk_rec *next; } stk_rec; /* The reference string for digits. */ static char ref_str[] = "0123456789ABCDEF"; /* A special output routine for "multi-character digits." Exactly SIZE characters must be output for the value VAL. If SPACE is non-zero, we must output one space before the number. OUT_CHAR is the actual routine for writing the characters. */ void bc_out_long (val, size, space, out_char) long val; int size, space; #ifdef NUMBER__STDC__ void (*out_char)(int); #else void (*out_char)(); #endif { char digits[40]; int len, ix; if (space) (*out_char) (' '); sprintf (digits, "%ld", val); len = strlen (digits); while (size > len) { (*out_char) ('0'); size--; } for (ix=0; ix < len; ix++) (*out_char) (digits[ix]); } /* Output of a bcd number. NUM is written in base O_BASE using OUT_CHAR as the routine to do the actual output of the characters. */ void bc_out_num (num, o_base, out_char, leading_zero) bc_num num; int o_base; #ifdef NUMBER__STDC__ void (*out_char)(int); #else void (*out_char)(); #endif int leading_zero; { char *nptr; int index, fdigit, pre_space; stk_rec *digits, *temp; bc_num int_part, frac_part, base, cur_dig, t_num, max_o_digit; /* The negative sign if needed. */ if (num->n_sign == MINUS) (*out_char) ('-'); /* Output the number. */ if (bc_is_zero (num)) (*out_char) ('0'); else if (o_base == 10) { /* The number is in base 10, do it the fast way. */ nptr = num->n_value; if (num->n_len > 1 || *nptr != 0) for (index=num->n_len; index>0; index--) (*out_char) (BCD_CHAR(*nptr++)); else nptr++; if (leading_zero && bc_is_zero (num)) (*out_char) ('0'); /* Now the fraction. */ if (num->n_scale > 0) { (*out_char) ('.'); for (index=0; indexn_scale; index++) (*out_char) (BCD_CHAR(*nptr++)); } } else { /* special case ... */ if (leading_zero && bc_is_zero (num)) (*out_char) ('0'); /* The number is some other base. */ digits = NULL; bc_init_num (&int_part); bc_divide (num, _one_, &int_part, 0); bc_init_num (&frac_part); bc_init_num (&cur_dig); bc_init_num (&base); bc_sub (num, int_part, &frac_part, 0); /* Make the INT_PART and FRAC_PART positive. */ int_part->n_sign = PLUS; frac_part->n_sign = PLUS; bc_int2num (&base, o_base); bc_init_num (&max_o_digit); bc_int2num (&max_o_digit, o_base-1); /* Get the digits of the integer part and push them on a stack. */ while (!bc_is_zero (int_part)) { bc_modulo (int_part, base, &cur_dig, 0); temp = (stk_rec *) malloc (sizeof(stk_rec)); if (temp == NULL) bc_out_of_memory(); temp->digit = bc_num2long (cur_dig); temp->next = digits; digits = temp; bc_divide (int_part, base, &int_part, 0); } /* Print the digits on the stack. */ if (digits != NULL) { /* Output the digits. */ while (digits != NULL) { temp = digits; digits = digits->next; if (o_base <= 16) (*out_char) (ref_str[ (int) temp->digit]); else bc_out_long (temp->digit, max_o_digit->n_len, 1, out_char); free (temp); } } /* Get and print the digits of the fraction part. */ if (num->n_scale > 0) { (*out_char) ('.'); pre_space = 0; t_num = bc_copy_num (_one_); while (t_num->n_len <= num->n_scale) { bc_multiply (frac_part, base, &frac_part, num->n_scale); fdigit = bc_num2long (frac_part); bc_int2num (&int_part, fdigit); bc_sub (frac_part, int_part, &frac_part, 0); if (o_base <= 16) (*out_char) (ref_str[fdigit]); else { bc_out_long (fdigit, max_o_digit->n_len, pre_space, out_char); pre_space = 1; } bc_multiply (t_num, base, &t_num, 0); } bc_free_num (&t_num); } /* Clean up. */ bc_free_num (&int_part); bc_free_num (&frac_part); bc_free_num (&base); bc_free_num (&cur_dig); bc_free_num (&max_o_digit); } } /* Convert a number NUM to a long. The function returns only the integer part of the number. For numbers that are too large to represent as a long, this function returns a zero. This can be detected by checking the NUM for zero after having a zero returned. */ long bc_num2long (num) bc_num num; { long val; char *nptr; int index; /* Extract the int value, ignore the fraction. */ val = 0; nptr = num->n_value; for (index=num->n_len; (index>0) && (val<=(LONG_MAX/BASE)); index--) val = val*BASE + *nptr++; /* Check for overflow. If overflow, return zero. */ if (index>0) val = 0; if (val < 0) val = 0; /* Return the value. */ if (num->n_sign == PLUS) return (val); else return (-val); } /* Convert an integer VAL to a bc number NUM. */ void bc_int2num (num, val) bc_num *num; int val; { char buffer[30]; char *bptr, *vptr; int ix = 1; char neg = 0; /* Sign. */ if (val < 0) { neg = 1; val = -val; } /* Get things going. */ bptr = buffer; *bptr++ = (unsigned)val % BASE; /* type cast to unsigned, bug fix Wolf Lammen */ val = (unsigned)val / BASE; /* type cast to unsigned, bug fix Wolf Lammen */ /* Extract remaining digits. */ while (val != 0) { *bptr++ = val % BASE; val = val / BASE; ix++; /* Count the digits. */ } /* Make the number. */ bc_free_num (num); *num = bc_new_num (ix, 0); if (neg) (*num)->n_sign = MINUS; /* Assign the digits. */ vptr = (*num)->n_value; while (ix-- > 0) *vptr++ = *--bptr; } /* Convert a numbers to a string. Base 10 only.*/ char *bc_num2str (num) bc_num num; { char *str, *sptr; char *nptr; int index, signch; /* Allocate the string memory. */ signch = ( num->n_sign == PLUS ? 0 : 1 ); /* Number of sign chars. */ if (num->n_scale > 0) str = (char *) malloc (num->n_len + num->n_scale + 2 + signch); else str = (char *) malloc (num->n_len + 1 + signch); if (str == NULL) bc_out_of_memory(); /* The negative sign if needed. */ sptr = str; if (signch) *sptr++ = '-'; /* Load the whole number. */ nptr = num->n_value; for (index=num->n_len; index>0; index--) *sptr++ = BCD_CHAR(*nptr++); /* Now the fraction. */ if (num->n_scale > 0) { *sptr++ = '.'; for (index=0; indexn_scale; index++) *sptr++ = BCD_CHAR(*nptr++); } /* Terminate the string and return it! */ *sptr = '\0'; return (str); } /* Convert strings to bc numbers. Base 10 only.*/ void bc_str2num (num, str, scale) bc_num *num; char *str; int scale; { int digits, strscale; char *ptr, *nptr; char zero_int; /* Prepare num. */ bc_free_num (num); /* Check for valid number and count digits. */ ptr = str; digits = 0; strscale = 0; zero_int = FALSE; if ( (*ptr == '+') || (*ptr == '-')) ptr++; /* Sign */ while (*ptr == '0') ptr++; /* Skip leading zeros. */ while (isdigit((int)*ptr)) ptr++, digits++; /* digits */ if (*ptr == '.') ptr++; /* decimal point */ while (isdigit((int)*ptr)) ptr++, strscale++; /* digits */ if ((*ptr != '\0') || (digits+strscale == 0)) { *num = bc_copy_num (_zero_); return; } /* Adjust numbers and allocate storage and initialize fields. */ strscale = MIN(strscale, scale); if (digits == 0) { zero_int = TRUE; digits = 1; } *num = bc_new_num (digits, strscale); /* Build the whole number. */ ptr = str; if (*ptr == '-') { (*num)->n_sign = MINUS; ptr++; } else { (*num)->n_sign = PLUS; if (*ptr == '+') ptr++; } while (*ptr == '0') ptr++; /* Skip leading zeros. */ nptr = (*num)->n_value; if (zero_int) { *nptr++ = 0; digits = 0; } for (;digits > 0; digits--) *nptr++ = CH_VAL(*ptr++); /* Build the fractional part. */ if (strscale > 0) { ptr++; /* skip the decimal point! */ for (;strscale > 0; strscale--) *nptr++ = CH_VAL(*ptr++); } } /* pn prints the number NUM in base 10. */ static void out_char (int c) { putchar(c); } void pn (num) bc_num num; { bc_out_num (num, 10, out_char, 0); out_char ('\n'); } /* pv prints a character array as if it was a string of bcd digits. */ void pv (name, num, len) char *name; unsigned char *num; int len; { int i; printf ("%s=", name); for (i=0; i gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatlogic.h" #include "floatconfig.h" #include "floatconst.h" #include "floatlong.h" #define MAXIDX ((LOGICRANGE-1) / BITS_IN_UNSIGNED) #define SIGNBIT (LOGICRANGE - 1 - MAXIDX * BITS_IN_UNSIGNED) static void _zeroextend( t_longint* longint) { int idx; idx = longint->length - 1; for (; ++idx <= MAXIDX;) longint->value[idx] = 0; } signed char _signof( t_longint* longint) { return (longint->value[MAXIDX] & (1 << SIGNBIT)) != 0? -1:1; } static char _signextend( t_longint* longint) { unsigned mask; signed char sign; sign = _signof(longint); mask = (~0) << SIGNBIT; if (sign < 0) longint->value[MAXIDX] |= mask; else longint->value[MAXIDX] &= ~mask; return sign; } static void _neg( t_longint* longint) { int idx; idx = -1; while (++idx <= MAXIDX && longint->value[idx] == 0); if (idx <= MAXIDX) longint->value[idx] = - longint->value[idx]; while (++idx <= MAXIDX) longint->value[idx] = ~longint->value[idx]; } char _floatnum2logic( t_longint* longint, cfloatnum x) { floatstruct tmp; int digits; digits = float_getexponent(x)+1; if (float_iszero(x) || digits <= 0) { longint->length = 1; longint->value[0] = 0; } else { if (digits > MATHPRECISION) return 0; float_create(&tmp); /* floatnum2longint rounds, we have to truncate first */ float_copy(&tmp, x, digits); if (float_getsign(x) < 0) float_add(&tmp, &tmp, &c1, EXACT); _floatnum2longint(longint, &tmp); float_free(&tmp); if (_bitlength(longint) > LOGICRANGE) return 0; } _zeroextend(longint); if (float_getsign(x) < 0) _not(longint); return 1; } void _logic2floatnum( floatnum f, t_longint* longint) { int idx; signed char sign; sign = _signextend(longint); if (sign < 0) _neg(longint); idx = MAXIDX; while (idx >= 0 && longint->value[idx] == 0) --idx; if (idx < 0) longint->length = 0; else longint->length = idx + 1; _longint2floatnum(f, longint); float_setsign(f, sign); } void _not( t_longint* longint) { int idx; for (idx = -1; ++idx <= MAXIDX;) longint->value[idx] = ~(longint->value[idx]); } void _and( t_longint* x1, t_longint* x2) { int idx; for (idx = -1; ++idx <= MAXIDX;) x1->value[idx] = x1->value[idx] & x2->value[idx]; } void _or( t_longint* x1, t_longint* x2) { int idx; for (idx = -1; ++idx <= MAXIDX;) x1->value[idx] = x1->value[idx] | x2->value[idx]; } void _xor( t_longint* x1, t_longint* x2) { int idx; for (idx = -1; ++idx <= MAXIDX;) x1->value[idx] = x1->value[idx] ^ x2->value[idx]; } void _shr( t_longint* x, unsigned shift) { int moves, idx; unsigned sign; sign = _signof(x) < 0? ~0 : 0; moves = shift/BITS_IN_UNSIGNED; if (moves > 0) { shift -= moves * BITS_IN_UNSIGNED; for (idx = moves-1; ++idx <= MAXIDX;) x->value[idx-moves] = x->value[idx]; idx = MAXIDX - moves + 1; if (idx < 0) idx = 0; for (; idx <= MAXIDX; ++idx) x->value[idx] = sign; } if (shift > 0) { for (idx = -1; ++idx < MAXIDX;) x->value[idx] = _longshr(x->value[idx], x->value[idx+1], shift); x->value[MAXIDX] = _longshr(x->value[MAXIDX], sign, shift); } } void _shl( t_longint* x, unsigned shift) { int moves, idx; moves = shift/BITS_IN_UNSIGNED; if (moves > 0) { shift -= moves * BITS_IN_UNSIGNED; for (idx = MAXIDX; idx >= moves; --idx) x->value[idx] = x->value[idx-moves]; if (moves > MAXIDX) moves = MAXIDX+1; for (idx = -1; ++idx < moves;) x->value[idx] = 0; } if (shift > 0) { for (idx = MAXIDX; idx > 0; --idx) x->value[idx] = _longshl(x->value[idx-1], x->value[idx], shift); x->value[0] <<= shift; } } speedcrunch-0.10.1/src/math/floatnum.h0000644000175000001440000004376111015364561017011 0ustar helderusers/* floatnum.h: Arbitrary precision floating point numbers header file. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATNUM_H_ #define _FLOATNUM_H_ #include "number.h" #include "floatconfig.h" #include "floatio.h" #include #define NULLTERMINATED (-20) #define UNORDERED (-2) #define EXACT (-101) #define INTQUOT (-102) #define float_free(f) float_setnan(f) #ifdef __cplusplus extern "C" { #endif extern int maxdigits; typedef struct { bc_num significand; int exponent; #ifdef FLOATDEBUG char value[110]; #endif /* FLOATDEBUG */ } floatstruct; typedef floatstruct* floatnum; typedef const floatstruct* cfloatnum; typedef enum {TONEAREST, TOZERO, TOINFINITY, TOPLUSINFINITY, TOMINUSINFINITY} roundmode; /* initializes this module. Has to be called prior to the first use of any of the following functions */ void floatnum_init(); /* sets the error to `code' unless it is already set */ void float_seterror(Error code); /* gets the last error and clears the error afterwards */ Error float_geterror(); /* returns the current overflow limit. It is the maximum possible exponent. The smallest exponent is -`return value' - 1. This function never reports an error */ int float_getrange(); /* sets the overflow/underflow limit. Subsequent arithmetic results with exponents between `maxexp' >= exponent >= -`maxexp'-1 are considered valid, all others trigger overflow/underflow errors. `maxexp' cannot be greater than MAXEXP and not less than 1. Exceeding arguments are replaced by the respective limit. The return value is the old overflow limit. This function affects future results only. Current stored values are not subject to overflow/underflow checking, even when they are used as parameters to an operation. This function never reports an error */ int float_setrange(int maxexp); /* returns the current precision limit. Arithmetic results may be cut off after this number of decimal digits */ int float_getprecision(); /* sets the current maximum precision (in decimal digits) that is used by basic arithmetic operations. The precision is at least 1 and at most MAXDIGITS. An exceeding argument is replaced by the respective limit. Setting a new precision affects future operations only; currently set variables are kept unmodified. The return value is the old precision limit. This function never reports an error */ int float_setprecision(int digits); /* checks whether the submitted exponent is within the current overflow and underflow limits. This function never reports an error */ char float_isvalidexp(int exp); /* initializes a new floatnum to NaN. Call this before the first use of a floatnum variable. The destructing function is float_setnan or its alias, float_free. This function never reports an error. */ void float_create(floatnum f); /* finalizes a variable. To avoid memory leaks, call this before a floatnum is freed. A special value (NaN = not a number) is loaded into `f', so any subsequent arithmetic operation on this variable will fail. However, a variable such finalized can still be re-used without prior initialization, by making it the destination of an operation. If you wish to deliberately "empty" a variable, without detroying it, call this function. An alias "float_free" to this function is defined that you may use anywhere as a replacement for float_setnan. This function never reports an error. */ void float_setnan(floatnum f); /* returns the base 10 exponent of the value in `f'. If `f' is zero or NaN, the returned exponent is 0. This function never reports an error. */ int float_getexponent(cfloatnum f); /* fills the buffer `buf' of size `bufsz' with an ASCII string representing the significand of `f'. No zeros are padded to the right to fill the buffer in case of a short significand. If `bufsz' <= 0, the function returns immediately with result 0. If the significand does not fit completely into the buffer, the output is stopped when the last buffer byte is written to. A non-zero significand yields a sequence of digits, without a decimal point; zero yields "0" and NaN "N". On truncation, no trailing zeros are removed. Exponent and sign are ignored, and no decimal point is written. No '\0' character is appended to the right. The return value are the number of characters written to the buffer. This function never reports an error. */ int float_getsignificand(char* buf, int bufsz, cfloatnum f); /* returns the number of digits in the significand, or 0 for NaN and zero. This function never reports an error. */ int float_getlength(cfloatnum f); /* returns 1, if `f' is positive, -1, if `f' is negative, and 0 if `f' is zero or NaN. This function never reports an error. */ signed char float_getsign(cfloatnum f); /* writes the value stored in `f' as an ASCIIZ string into a buffer of size `bufsz'. If the buffer is too small to hold the full value, the significand is truncated appropriately. If the buffer is too small to even store the most significant digit of the significand besides exponent and sign, nothing is stored at all, and -1 is returned. Else, the length of the output, but without the trailing \0 character, is returned. The output format is the usual scientific format. On truncation, no trailing zeros are removed from the output of the significand. Examples of an output: value output ----- ------ NaN NaN\0 0 0\0 1 1.e0\0 1.2 1.2e0\0 0.5 5.e-1\0 -1 -1.e0\0 1.009 1.00e0\0 (truncated to 3 digits) 10^10 1.e10\0 This function does not touch the adjacent bytes of the final output. If no reasonable output is possible, the complete buffer is left unchanged, not even the final \0 character is written. This function never reports an error. */ int float_getscientific(char* buf, int bufsz, cfloatnum f); /* gets the `ofs'-th digit from the decimal representation of the significand of `f'. If `ofs' is negative or greater equal to the length of the significand, 0 is returned. The return value is between 0 and 9 (not the ASCII representation of these digits (0x30 - 0x39)). This function never returns an error */ char float_getdigit(cfloatnum f, int ofs); /* sets the significand according to the the ASCII text in buffer buf of size `bufsz'. The buffer must contain digits '0' -'9' only, with one possible exception: A single decimal point ('.') may be placed anywhere in the buffer. It is skipped while encoding the significand. The function searches the buffer for the first non-zero digit, and starts the encoding from there. `f' is set to NaN, if the buffer fails to fulfill the above conditions. If the resulting significand exceeds digits, it is truncated. The exponent of `f' is set to 0, so the result is always NaN, 0 or a number between 1 and 9.99... If you want to set both the significand and the exponent of f, set the significand first. If `leadingzeros' is not NULL, and the result in `f' is neither zero nor NaN, the number of leading (and skipped) zeros are stored here. In case of NaN or zero, this value is 0. All trailing zeros in the significand of `f' are removed. The result is the position of the decimal point in `buf', or -1 if either none was found, or if it is not relevant (NaN or 0.0). This function never reports an error. */ int float_setsignificand(floatnum f, int* leadingzeros, const char* buf, int bufsz); /* sets the base 10 exponent of f to exponent. The significand is only changed when this operation fails. Integers greater than EXPMAX or smaller than EXPMIN are not accepted as exponent and let the operation fail, setting `f' to NaN. You cannot change the exponent of 0 or NaN, this is ignored. If you want to set both the significand and the exponent of `f', set the significand first. This function never reports an error. */ void float_setexponent(floatnum f, int exponent); /* converts an ASCII string of length `bufsz' in `buf' to `f'. `bufsz' may assume the special value NULLTERMINATED, in which case the first found \0 character terminates the input. The input format is [+|-][digit...][.[digit...][(e|E)[+|-]digit...]] At least one digit of the significand has to be present. Any non-valid input is converted into a NaN. This function never reports an error. */ void float_setscientific(floatnum f, const char* buf, int bufsz); /* if `s' is 1 or -1, the sign of `f' is set accordingly. Has no effect, if `f' == NaN or zero, or `s' == 0. `f' is set to NaN, if |s| > 1. This function never reports an error. */ void float_setsign(floatnum f, signed char s); /* sets dest to the value in `value'. This function never reports an error. */ void float_setinteger(floatnum dest, int value); /* sets a variable to the numerical value zero. This function never reports an error. */ void float_setzero (floatnum f); /* returns 1, if f contains the special NaN value, 0 otherwise. This function never reports an error. */ char float_isnan(cfloatnum f); /* returns 1, if f contains the value zero, 0 otherwise. This function never reports an error. */ char float_iszero(cfloatnum f); /* copies source to dest, limiting the significand to at most `digits' digits. The parameter `digits' may assume the value EXACT, in which case a full copy is made. If source and dest coincide, float_copy tries to re-use the significand. This prevents unnecessary copying. If a copy has to be made, the allocated space is just big enough to hold the significand, so no memory is wasted. A return value of 0 indicates an error. errors: InvalidPrecision, if `digits', or the length of the copy, exceeds `maxdigits' */ char float_copy(floatnum dest, cfloatnum source, int digits); /* transfers the contents of source to dest. source is assigned NaN afterwards. In contrast to float_copy, float_move does not create a copy of the significand (which employs memory allocation and copying), but transfers simply the data from the source to the destination. This function has been designed to implement, for example, swapping of variables in a fast way. If dest == source, nothing happens. This function never reports an error */ void float_move(floatnum dest, floatnum source); /* changes the value of `f' to -`f'. Has no effect on zero or NaN. A return value of 0 indicates an error. errors: NaNOperand */ char float_neg(floatnum f); /* changes the sign of `f', if `f' is negative. Has no effect on a NaN. A return value of 0 indicates an error. errors: NaNOperand */ char float_abs(floatnum f); /* compares two values and returns +1 if val1 > val2, 0 if val1 == val2 and -1 if val1 < val2. This function is not intended to be used with NaN's. If you pass it as an argument, UNORDERED is returned to indicate an error. errors: NaNOperand */ signed char float_cmp(cfloatnum val1, cfloatnum val2); /* rounds `f' to `digits' digits according to the submitted mode. If `digits' <= 0 or mode is not recognized, `f' is changed into a NaN. The same holds should the rounding operation overflow. mode == TONEAREST: checks whether the first cut off digit is a '5' or greater. In this case, the absolute value of the significand is rounded up, otherwise rounded down. If the part cut off is a single digit '5', the significand is rounded such that its last digit is even. mode == TOZERO: cuts off all digits after the `digits'th digit. This mode never overflows. mode = TOINFINITY: rounds positive numbers up, negative numbers down (towards greater magnitude). mode == TOPLUSINFINITY: always rounds up. So, negative values are effectively truncated. mode == TOMINUSINFINITY: always rounds down. So, negative values usually increase in magnitude. A return value of 0 indicates an error. errors: NaNOperand InvalidParam InvalidPrecision Overflow */ char float_round(floatnum dest, cfloatnum src, int digits, roundmode mode); /* cuts off the fractional part of `f'. The result is always less or equal in magnitude to the passed argument. A NaN yields a NaN. A return value of 0 indicates an error. errors: NaNOperand */ char float_int(floatnum f); /* cuts off the integer part of `f'. If the result is not equal to 0, it has the same sign as the argument. NaN yields NaN. A return value of 0 indicates an error. errors: NaNOperand */ char float_frac(floatnum f); /* adds the values in `summand1' and `summand2' and stores the result in `dest'. `dest' may coincide with either summand (or even both). The result is evaluated to `digits' or `digits'+1 digits. If `digits' is EXACT, the sum is evaluated to full scale (if possible). NaN is returned, if - (at least) one operand is NaN; - the result overflows or underflows; - `digits' is invalid, or the resulting digits exceed `maxdigits'. A return value of 0 indicates an error. errors: NaNOperand InvalidPrecision Overflow Underflow */ char float_add(floatnum dest, cfloatnum summand1, cfloatnum summand2, int digits); /* subtracts `subtrahend' from `minuend' and stores the result in `dest'. `dest' may coincide with either operand (or even both). The result is evaluated to `digits' or `digits'+1 digits. If `digits' is EXACT, the difference is evaluated to full scale (if possible). NaN is returned, if - (at least) one operand is NaN; - the result overflows or underflows; - `digits' is invalid, or the resulting digits exceed `maxdigits'. A return value of 0 indicates an error. errors: NaNOperand InvalidPrecision Overflow Underflow */ char float_sub(floatnum dest, cfloatnum minuend, cfloatnum subtrahend, int digits); /* multiplies both factors and stores the result in `dest'. `dest' may coincide with either factor (or even both). The result is evaluated to `digits' or `digits'+1 digits, or, if `digits' == EXACT, to full scale (if possible). NaN is returned, if - (at least) one operand is NaN; - the result overflows or underflows; - `digits' is invalid, or the resulting scale exceeds `maxdigits'. A return value of 0 indicates an error. errors: NaNOperand InvalidPrecision Overflow Underflow */ char float_mul(floatnum dest, cfloatnum factor1, cfloatnum factor2, int digits); /* divides `dividend' by `divisor' and stores the result in `dest'. `dest' may coincide with either operand (or even both). The result is evaluated to `digits' or `digits'+1 digits, or, if `digits' == INTQUOT, to the size of the integer part of the quotient. EXACT is not allowed, even in cases where the dividend is divisible by the divisor. NaN is returned, if - (at least) one operand is NaN; - the result overflows or underflows; - the divisor is zero; - `digits' is invalid, or the effective scale exceeds `maxdigits'. A return value of 0 indicates an error. errors: NaNOperand InvalidPrecision Overflow Underflow ZeroDivide */ char float_div(floatnum dest, cfloatnum dividend, cfloatnum divisor, int digits); /* evaluates the quotient, using `digits' steps of the schoolbook division algorithm. The quotient, thus, has `digits' or `digits'-1 digits, and is always truncated towards zero. The remainder fulfills the equation: remainder = dividend - quotient * divisor. `digits' may assume the special value INTQUOT, in which case the integer part of the quotient is calculated. This function is an exact operation anyway, so EXACT is not allowed here. `digits' is subject to the `maxdigits' limit. `remainder' and `quotient' have to be different variables, but apart from this, there are no other restrictions on the passed variables. If this function fails, both result variables are set to NaN. A return value of 0 indicates an error. errors: NaNOperand InvalidParam InvalidPrecision TooExpensive Overflow Underflow ZeroDivide */ char float_divmod(floatnum quotient, floatnum remainder, cfloatnum dividend, cfloatnum divisor, int digits); /* computes the sqare root of `value' to `digits' or `digits'+1 digits. `digits' == EXACT is not allowed, even if the argument is a square. NaN is returned, if - the operand is NaN, - `digits' exceeds `maxdigits' - the operand is negative. A return value 0 indicates an error. errors: NaNOperand InvalidPrecision OutOfDomain */ char float_sqrt(floatnum value, int digits); /* a few convenience functions used everywhere */ char _setnan(floatnum result); char _seterror(floatnum result, Error code); char _checknan(cfloatnum f); char _setzero(floatnum x); #ifdef __cplusplus } #endif #endif /* _FLOATNUM_H_ */ speedcrunch-0.10.1/src/math/floatlong.c0000644000175000001440000001405711015364561017140 0ustar helderusers/* floatlong.c: portable double size integer arithmetic. */ /* Copyright (C) 2007 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatlong.h" #define HALFSIZE (sizeof(unsigned) * 4) #define LOWMASK ((1 << HALFSIZE) - 1) #define MSB (1 << (2*HALFSIZE-1)) /*************** functions handling a single unsigned ********************/ int _findfirstbit( unsigned value) { int result; result = -1; while (value != 0) { value >>= 1; ++result; } return result; } /* pre: value != 0 */ static int _revfindfirstbit( unsigned value) { int result; result = 0; while ((value & 1) == 0) { value >>= 1; ++result; } return result; } /******************* double unsigned functions ********************/ static void _longsplit( unsigned value, unsigned* low, unsigned* high) { *high = value >> HALFSIZE; *low = value & LOWMASK; } static unsigned _longcat( unsigned low, unsigned high) { return (high << HALFSIZE) + low; } char _longadd( unsigned* s1, unsigned* s2) { unsigned s1h, s1l, s2h, s2l; _longsplit(*s1, &s1l, &s1h); _longsplit(*s2, &s2l, &s2h); s1l += s2l; _longsplit(s1l, &s1l, &s2l); s1h += s2h + s2l; _longsplit(s1h, &s1h, s2); *s1 = _longcat(s1l, s1h); return *s2 == 0; } char _longmul( unsigned* f1, unsigned* f2) { unsigned f1h, f1l, f2h, f2l; _longsplit(*f1, &f1l, &f1h); _longsplit(*f2, &f2l, &f2h); *f1 = f1l * f2l; *f2 = f1h * f2h; f1l *= f2h; f2l *= f1h; _longadd(&f1l, &f2l); _longsplit(f1l, &f1l, &f1h); f1l <<= HALFSIZE; _longadd(f1, &f1l); *f2 += f1l + (f2l << HALFSIZE) + f1h; return *f2 == 0; } unsigned _longshr( unsigned low, unsigned high, char shift) { if (shift == 0) return low; return (low >> shift) | (high << ((2*HALFSIZE)-shift)); } unsigned _longshl( unsigned low, unsigned high, char shift) { if (shift == 0) return high; return (low >> ((2*HALFSIZE)-shift)) | (high << shift); } /***************** unsigned array functions *****************/ unsigned _longarrayadd( unsigned* uarray, int lg, unsigned incr) { for(; lg-- > 0 && incr != 0;) _longadd(uarray++, &incr); return incr; } unsigned _longarraymul( unsigned* uarray, int lg, unsigned factor) { unsigned ovfl, carry; carry = 0; ovfl = 0; for (; lg-- > 0;) { carry += ovfl; ovfl = factor; _longmul(uarray, &ovfl); _longadd(uarray++, &carry); } return carry + ovfl; } unsigned _bitsubstr( unsigned* uarray, int ofs) { int idx; if (ofs <= 0) return *uarray << -ofs; idx = ofs / BITS_IN_UNSIGNED; return _longshr(*(uarray+idx), *(uarray+idx+1), ofs - idx * BITS_IN_UNSIGNED); } void _orsubstr( unsigned* uarray, int bitofs, unsigned value) { int idx; int ofs; idx = bitofs / BITS_IN_UNSIGNED; ofs = bitofs - idx * BITS_IN_UNSIGNED; if (ofs == 0) *(uarray + idx) |= value; else { *(uarray + idx) |= value << ofs; *(uarray + idx + 1) |= value >> (BITS_IN_UNSIGNED - ofs); } } /**************** longint functions ****************/ char _isfull( t_longint* l) { return l->length >= UARRAYLG - 1; } unsigned _bitlength( t_longint* l) { if (l->length == 0) return 0; return (l->length - 1) * BITS_IN_UNSIGNED + _findfirstbit(l->value[l->length-1]) + 1; } unsigned _lastnonzerobit( t_longint* l) { int i; if (l->length == 0) return -1; i = -1; for (; ++i < l->length && l->value[i] == 0;); return i * BITS_IN_UNSIGNED + _revfindfirstbit(l->value[i]); } unsigned _longintadd( t_longint* l, unsigned summand) { unsigned ovfl; ovfl = _longarrayadd(l->value, l->length, summand); if (ovfl != 0 && !_isfull(l)) { l->value[l->length] = ovfl; ++l->length; ovfl = 0; } return ovfl; } unsigned _longintmul( t_longint* l, unsigned factor) { unsigned ovfl; ovfl = _longarraymul(l->value, l->length, factor); if (ovfl != 0 && !_isfull(l)) { l->value[l->length] = ovfl; ++l->length; ovfl = 0; } return ovfl; } char _longintsetsize( t_longint* l, unsigned bitlength) { int i; if (bitlength == 0) l->length = 0; else l->length = (bitlength - 1) / BITS_IN_UNSIGNED + 1; if (l->length >= UARRAYLG) return 0; for(i = l->length; i >= 0; --i) l->value[i] = 0; return 1; } /**************** overflow checking integer functions *************/ char _checkadd( int* s1, int s2) { unsigned u1, u2; if ((*s1 < 0) ^ (s2 < 0)) { /* you can always add summands of opposite sign */ *s1 += s2; return 1; } if (s2 < 0) { u1 = -*s1; u2 = -s2; _longadd(&u1, &u2); *s1 = -(int)u1; return u2 == 0 && *s1 < 0; } u1 = *s1; u2 = s2; _longadd(&u1, &u2); *s1 = u1; return *s1 >= 0; } char _checkmul( int* f1, int f2) { unsigned x1, x2; signed char sgn; sgn = 1; if (*f1 >= 0) x1 = *f1; else { sgn = -1; x1 = -*f1; } if (f2 >= 0) x2 = f2; else { sgn = -sgn; x2 = -f2; } _longmul(&x1, &x2); if (sgn < 0) { *f1 = -(int)x1; return (x2 == 0 && x1 <= MSB); } *f1 = (int)x1; return (x2 == 0 && x1 < MSB); } speedcrunch-0.10.1/src/math/floatgamma.h0000644000175000001440000000273311015364561017266 0ustar helderusers/* floatgamma.h: Gamma function, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATGAMMA_H # define _FLOATGAMMA_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif char _lngamma(floatnum x, int digits); char _gamma(floatnum x, int digits); char _gammaint(floatnum integer, int digits); char _gamma0_5(floatnum x, int digits); char _pochhammer(floatnum x, cfloatnum n, int digits); #ifdef __cplusplus } #endif #endif /* _FLOATGAMMA_H */ speedcrunch-0.10.1/src/math/floattrig.h0000644000175000001440000000361411015364561017150 0ustar helderusers/* floattrig.h: trigonometry functions, based on floatnum. */ /* Copyright (C) 2007 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATTRIG_H # define _FLOATTRIG_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif void _arctanlt1(floatnum x, int digits); void _arctan(floatnum x, int digits); void _arccosxplus1lt0_5(floatnum x, int digits); void _arcsinlt0_5(floatnum x, int digits); void _arccos(floatnum x, int digits); void _arccosxplus1(floatnum x, int digits); void _arcsin(floatnum x, int digits); char _cosminus1ltPiDiv4(floatnum x, int digits); void _sinltPiDiv4(floatnum x, int digits); void _tanltPiDiv4(floatnum x, int digits); void _cos(floatnum x, int digits); void _sin(floatnum x, int digits); char _tan(floatnum x, int digits); char _cosminus1(floatnum x, int digits); char _trigreduce(floatnum x, int digits); void _sinpix(floatnum x, int digits); #ifdef __cplusplus } #endif #endif /* _FLOATTRIG_H */ speedcrunch-0.10.1/src/math/floatconvert.c0000644000175000001440000003720011015364561017654 0ustar helderusers/* floatconvert.c: radix conversion, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatconvert.h" #include "floatcommon.h" #include "floatconfig.h" #include "floatconst.h" #include "floatipower.h" #include #include typedef struct{ t_number_desc n; t_longint l; floatnum f; int bitlength; int trailing0; int lgbase; }t_ext_number; typedef t_ext_number* p_ext_number; /************************ conversion to/from longint *******************/ static unsigned _digitblock( floatnum f, int ofs, int count) { unsigned result; result = 0; for (; --count >= 0;) result = 10 * result + float_getdigit(f, ofs++); return result; } Error _floatnum2longint( t_longint* longint, floatnum f) { int digits; int i; unsigned factor; longint->length = 0; digits = float_getexponent(f) + 1; i = digits % 9; _longintadd(longint, _digitblock(f, 0, i)); factor = 1000000000; while (i < digits) { if (_longintmul(longint, factor) || _longintadd(longint, _digitblock(f, i, 9))) return IOConversionOverflow; i += 9; } /* extra element for floatlong operations */ *(longint->value+longint->length) = 0; return Success; } static void _setunsigned( floatnum f, unsigned value) { float_setinteger(f, value); if ((int)value < 0) float_add(f, f, &cUnsignedBound, EXACT); } void _longint2floatnum( floatnum f, t_longint* longint) { floatstruct tmp; int idx; float_setzero(f); if(longint->length == 0) return; float_create(&tmp); idx = longint->length - 1; for (; idx >= 0; --idx) { _setunsigned(&tmp, longint->value[idx]); float_mul(f, f, &cUnsignedBound, EXACT); float_add(f, f, &tmp, EXACT); } float_free(&tmp); } /************************** io routines **************************/ static int _max( int a, int b) { return a > b? a : b; } static char _validmode( char mode) { return mode >= IO_MODE_SCIENTIFIC && mode <= IO_MODE_COMPLEMENT; } static int _lg2( floatnum x) /* The evaluation of _lg2(x) is based on an approximation suggested by Abramowitz, Stegun, Handbook of mathematical functions. The returned base 2 logarithm is valid to 4 (decimal) digits after the decimal point. */ { int i; float t; char gtsqrt10; i = leadingdigits(x, 5); gtsqrt10 = i > 31622; if (gtsqrt10) t = ((float)(i - 100000))/(i + 100000); else t = ((float)(i - 10000))/(i + 10000); i = ((0.36415*t*t + 0.86304) * t + (float_getexponent(x)+(gtsqrt10?1:0)))*3.32192809488736235; return i >= 0? i : i - 1; } static int lgbase( signed char base) { switch(base) { case 2: return 1; case 8: return 3; case 16: return 4; } return 0; } static char _getfnintdigit( int ofs, p_seq_desc n) { if (ofs <= n->digits) return float_getdigit((floatnum)(n->param), ofs); return 0; } static char _getfnfracdigit( int ofs, p_seq_desc n) { floatnum x; int exp; x = (floatnum)(n->param); exp = float_getexponent(x); if (ofs >= 0) return float_getdigit(x, ofs + exp + 1); return 0; } static void _setfndesc( p_number_desc n, floatnum x) { int digits; n->intpart.seq.base = 10; digits = _max(float_getexponent(x) + 1, 0); n->intpart.seq.digits = digits; n->intpart.seq.trailing0 = _max(digits - float_getlength(x), 0); n->intpart.seq.param = x; n->intpart.getdigit = _getfnintdigit; n->fracpart.seq.base = 10; n->fracpart.seq.leadingSignDigits = _max(-float_getexponent(x) - 1, 0); n->fracpart.seq.digits = float_getlength(x) - digits + n->fracpart.seq.leadingSignDigits; n->fracpart.seq.param = x; n->fracpart.getdigit = _getfnfracdigit; } static Error _pack2longint( t_longint* l, p_ext_seq_desc n) { int bitofs; int ofs; int logbase; logbase = lgbase(n->seq.base); ofs = n->seq.leadingSignDigits; if (_significantdigits(&n->seq) == 0) /* can be true in complement case: 0xFF00 */ --ofs; bitofs = (n->seq.digits - ofs) * logbase; if (!_longintsetsize(l, bitofs)) return IOBufferOverflow; for (; bitofs > 0;) { bitofs -= logbase; _orsubstr(l->value, bitofs, n->getdigit(ofs++, &n->seq)); } return Success; } static char _getlongintdigit( int ofs, p_seq_desc n) { if (ofs < 0 || ofs >= n->digits) return 0; return _bitsubstr(((t_longint*)(n->param))->value, (n->digits - ofs - 1) * lgbase(n->base)) & (n->base - 1); } static char _getlongintofsdigit( int ofs, p_seq_desc n) { p_number_desc nmb; int digits; nmb = (p_number_desc)(n->param); digits = n->digits; if (ofs < 0 || ofs >= digits) return 0; digits += nmb->fracpart.seq.digits; return _bitsubstr(((t_longint*)(nmb->fracpart.seq.param))->value, (digits - ofs - 1) * lgbase(n->base)) & (n->base - 1); } static void _setlongintdesc( p_ext_seq_desc n, t_longint* l, signed char base) { int lg; n->seq.base = base; lg = lgbase(base); n->seq.digits = (_bitlength(l) + lg - 1) / lg; n->seq.leadingSignDigits = 0; n->seq.trailing0 = _lastnonzerobit(l) / lg; n->seq.param = l; n->getdigit = _getlongintdigit; } static Error _packdec2int( floatnum x, p_ext_seq_desc n) { int ofs; int exp; int bufsz; int i; char buf[DECPRECISION]; float_setnan(x); ofs = n->seq.leadingSignDigits; exp = n->seq.trailing0; bufsz = n->seq.digits - ofs - exp; if (bufsz > DECPRECISION) return IOBufferOverflow; if (bufsz == 0) float_setzero(x); else for (i = -1; ++i < bufsz;) buf[i] = n->getdigit(ofs++, &n->seq) + '0'; float_setsignificand(x, NULL, buf, bufsz); float_setexponent(x, exp + bufsz - 1); return Success; } static Error _packbin2int( floatnum x, p_ext_seq_desc n) { t_longint l; Error result; float_setnan(x); if ((result = _pack2longint(&l, n)) != Success) return result; _longint2floatnum(x, &l); return Success; } static Error _pack2int( floatnum x, p_ext_seq_desc n) { switch(n->seq.base) { case IO_BASE_NAN: float_setnan(x); break; case IO_BASE_ZERO: float_setzero(x); break; case 10: return _packdec2int(x, n); default: return _packbin2int(x, n); } return Success; } static Error _pack2frac( floatnum x, p_ext_seq_desc n, int digits) { floatstruct tmp; int exp; Error result; n->seq.digits -= n->seq.trailing0; n->seq.trailing0 = 0; switch(n->seq.base) { case IO_BASE_NAN: float_setnan(x); break; case IO_BASE_ZERO: float_setzero(x); break; default: if ((result = _pack2int(x, n)) != Success) return result; float_create(&tmp); float_setinteger(&tmp, n->seq.base); _raiseposi(&tmp, &exp, n->seq.digits, digits+2); float_div(x, x, &tmp, digits + 2); float_setexponent(x, float_getexponent(x) - exp); float_free(&tmp); } n->seq.digits += n->seq.trailing0; return Success; } Error pack2floatnum( floatnum x, p_number_desc n) { floatstruct tmp; int digits; int saveerr; int saverange; Error result; signed char base; if ((result = _pack2int(x, &n->intpart)) != Success) return result; if (float_isnan(x)) return Success; saveerr = float_geterror(); saverange = float_setrange(MAXEXP); float_create(&tmp); float_move(&tmp, x); float_setzero(x); digits = DECPRECISION - float_getexponent(&tmp); if (digits <= 0 || (result = _pack2frac(x, &n->fracpart, digits)) == Success) float_add(x, x, &tmp, DECPRECISION); if (result != Success) return result; if (!float_getlength(x) == 0) /* no zero, no NaN? */ { base = n->prefix.base; float_setinteger(&tmp, base); if (n->exp >= 0) { __raiseposi(&tmp, n->exp, DECPRECISION + 2); float_mul(x, x, &tmp, DECPRECISION + 2); } else { __raiseposi(&tmp, -n->exp, DECPRECISION + 2); float_div(x, x, &tmp, DECPRECISION + 2); } } float_free(&tmp); float_setsign(x, n->prefix.sign == IO_SIGN_COMPLEMENT? -1 : n->prefix.sign); float_geterror(); float_seterror(saveerr); float_setrange(saverange); if (!float_isvalidexp(float_getexponent(x))) float_setnan(x); return float_isnan(x)? IOExpOverflow : Success; } static Error _outscidec( p_otokens tokens, floatnum x, p_number_desc n, int scale) { float_checkedround(x, scale + 1); n->exp = float_getexponent(x); float_setexponent(x, 0); _setfndesc(n, x); return desc2str(tokens, n, scale); } static int _checkbounds( floatnum x, int digits, signed char base) { if (float_getexponent(x) < 0) { float_muli(x, x, base, digits); return -1; } else if (float_asinteger(x) >= base) { float_divi(x, x, base, digits); return 1; } return 0; } static void _scale2int( floatnum x, int scale, signed char base) { floatstruct pwr; int pwrexp; if (scale != 0) { float_create(&pwr); float_setinteger(&pwr, base); _raiseposi(&pwr, &pwrexp, scale, DECPRECISION+4); float_mul(x, x, &pwr, DECPRECISION+4); float_addexp(x, pwrexp); float_free(&pwr); } float_roundtoint(x, TONEAREST); } static Error _fixp2longint( p_number_desc n, t_longint* l, floatnum x, int scale) { Error result; _scale2int(x, scale, n->prefix.base); result = _floatnum2longint(l, x); if (result != Success) return result; _setlongintdesc(&n->fracpart, l, n->prefix.base); return Success; } static int _extractexp( floatnum x, int scale, signed char base) { floatstruct pwr; floatstruct fbase; int decprec; int pwrexp; int exp; int logbase; logbase = lgbase(base); decprec = DECPRECISION + 3; if (float_getexponent(x) < 0) exp = _lg2(x)-3; else exp = _lg2(x); exp /= logbase; if (exp != 0) { float_create(&fbase); float_setinteger(&fbase, base); float_create(&pwr); float_copy(&pwr, &fbase, EXACT); _raiseposi(&pwr, &pwrexp, exp < 0? -exp : exp, decprec); if (float_getexponent(x) < 0) { float_addexp(x, pwrexp); float_mul(x, x, &pwr, decprec); } else { float_addexp(x, -pwrexp); float_div(x, x, &pwr, decprec); } float_free(&pwr); float_free(&fbase); } exp += _checkbounds(x, decprec, base); return exp; } static void _setscale( p_number_desc n, t_longint* l, int scale) { n->intpart.seq.leadingSignDigits = 0; n->intpart.seq.trailing0 = n->fracpart.seq.trailing0 - scale; if (n->intpart.seq.trailing0 < 0) n->intpart.seq.trailing0 = 0; n->intpart.seq.base = n->fracpart.seq.base; n->intpart.seq.digits = n->fracpart.seq.digits - scale; n->intpart.getdigit = _getlongintofsdigit; n->intpart.seq.param = n; n->fracpart.seq.digits = scale; if (n->fracpart.seq.trailing0 >= scale) { n->fracpart.seq.base = IO_BASE_ZERO; n->fracpart.seq.trailing0 = scale; } } static Error _outscihex( p_otokens tokens, floatnum x, p_number_desc n, int scale) { t_longint l; Error result; n->exp = _extractexp(x, scale, n->prefix.base); result = _fixp2longint(n, &l, x, scale); if (result != Success) return result; /* rounding in _fixp2longint may have increased the exponent */ n->exp += n->fracpart.seq.digits - 1 - scale; _setscale(n, &l, n->fracpart.seq.digits - 1); return desc2str(tokens, n, scale); } static char _isvalidbase( signed char base) { return base == 10 || lgbase(base) != 0; } static Error _outsci( p_otokens tokens, floatnum x, p_number_desc n, int scale) { if (n->prefix.base == 10) return _outscidec(tokens, x, n, scale); return _outscihex(tokens, x, n, scale); } static Error _outfixpdec( p_otokens tokens, floatnum x, p_number_desc n, int scale) { int digits; digits = float_getexponent(x) + scale + 1; if (digits <= 0) /* underflow */ return IOConversionUnderflow; float_round(x, x, digits, TONEAREST); _setfndesc(n, x); return desc2str(tokens, n, scale); } static Error _outfixphex( p_otokens tokens, floatnum x, p_number_desc n, int scale) { t_longint l; Error result; float_copy(x, x, DECPRECISION+1); result = _fixp2longint(n, &l, x, scale); if (result != Success) return result; if (l.length == 0) return IOConversionUnderflow; _setscale(n, &l, scale); return desc2str(tokens, n, scale); } static Error _outfixp( p_otokens tokens, floatnum x, p_number_desc n, int scale) { if (n->prefix.base == 10) return _outfixpdec(tokens, x, n, scale); return _outfixphex(tokens, x, n, scale); } static Error _outengdec( p_otokens tokens, floatnum x, p_number_desc n, int scale) { int shift; float_checkedround(x, scale + 1); n->exp = float_getexponent(x); if (n->exp < 0) shift = 2 - (-n->exp-1) % 3; else shift = n->exp % 3; float_setexponent(x, shift); n->exp -= shift; _setfndesc(n, x); return desc2str(tokens, n, scale - shift); } static Error _outeng( p_otokens tokens, floatnum x, p_number_desc n, int scale) { if (n->prefix.base != 10 || scale < 2) return InvalidParam; return _outengdec(tokens, x, n, scale); } static Error _outcompl( p_otokens tokens, floatnum x, p_number_desc n, int scale) { if (!float_isinteger(x)) return IOInvalidComplement; if (n->prefix.sign == IO_SIGN_MINUS) n->prefix.sign = IO_SIGN_COMPLEMENT; else n->prefix.sign = IO_SIGN_NONE; return _outfixphex(tokens, x, n, 0); } static void _emptybuffer( p_buffer token) { if (token->sz > 0) *(token->buf) = '\0'; else token->buf = NULL; } static void _emptytokens( p_otokens tokens) { _emptybuffer(&tokens->intpart); _emptybuffer(&tokens->fracpart); tokens->sign = IO_SIGN_NONE; tokens->base = IO_BASE_NAN; tokens->exp = 0; } Error float_out( p_otokens tokens, floatnum x, int scale, signed char base, char outmode) { t_number_desc n; _emptytokens(tokens); /* do some sanity checks first */ if (!_validmode(outmode) || scale < 0 || !_isvalidbase(base)) return InvalidParam; _clearnumber(&n); if (float_iszero(x)) n.prefix.base = IO_BASE_ZERO; else if (!float_isnan(x)) n.prefix.base = base; if (!_isvalidbase(n.prefix.base)) /* NaN and 0 are handled here */ return desc2str(tokens, &n, 0); n.prefix.sign = float_getsign(x); float_abs(x); switch (outmode) { case IO_MODE_FIXPOINT: return _outfixp(tokens, x, &n, scale); case IO_MODE_ENG: return _outeng(tokens, x, &n, scale); case IO_MODE_COMPLEMENT: return _outcompl(tokens, x, &n, 0); default: return _outsci(tokens, x, &n, scale); } } Error float_in( floatnum x, p_itokens tokens) { t_number_desc n; Error result; if ((result = str2desc(&n, tokens)) == Success) result = pack2floatnum(x, &n); if (result != Success) { _seterror(x, BadLiteral); float_setnan(x); } return result; } speedcrunch-0.10.1/src/math/floattrig.c0000644000175000001440000002160011015364561017136 0ustar helderusers/* floattrig.c: trigonometry functions, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floattrig.h" #include "floatseries.h" #include "floatconst.h" #include "floatcommon.h" #include "floatconfig.h" /* evaluates arctan x for |x| <= 1 relative error for a 100 digit result is 6e-100 */ void _arctanlt1( floatnum x, int digits) { floatstruct tmp; int reductions; if (float_iszero(x)) return; float_create(&tmp); reductions = 0; while(float_getexponent(x) >= -2) { float_mul(&tmp, x, x, digits); float_add(&tmp, &tmp, &c1, digits+2); float_sqrt(&tmp, digits); float_add(&tmp, &tmp, &c1, digits+1); float_div(x, x, &tmp, digits); ++reductions; } arctannear0(x, digits); for (;reductions-- > 0;) float_add(x, x, x, digits+1); float_free(&tmp); } /* evaluates arctan x for all x. The result is in the range -pi/2 < result < pi/2 relative error for a 100 digit result is 9e-100 */ void _arctan( floatnum x, int digits) { signed char sgn; if (float_abscmp(x, &c1) > 0) { sgn = float_getsign(x); float_abs(x); float_reciprocal(x, digits); _arctanlt1(x, digits); float_sub(x, &cPiDiv2, x, digits+1); float_setsign(x, sgn); } else _arctanlt1(x, digits); } /* evaluates arccos(1+x) for -0.5 <= x <= 0 arccos(1+x) = arctan(sqrt(-x*(2+x))/(1+x)) the relative error of a 100 digit result is < 5e-100 */ void _arccosxplus1lt0_5( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); float_add(&tmp, x, &c2, digits+1); float_mul(x, x, &tmp, digits+1); float_setsign(x, 1); float_sqrt(x, digits); float_sub(&tmp, &tmp, &c1, digits); float_div(x, x, &tmp, digits+1); _arctan(x, digits); float_free(&tmp); } /* evaluates arcsin x for -0.5 <= x <= 0.5 arcsin x = arctan(x/sqrt(1-x*x)) the relative error of a 100 digit result is < 5e-100 */ void _arcsinlt0_5( floatnum x, int digits) { floatstruct tmp; if (2*float_getexponent(x) < -digits) return; float_create(&tmp); float_mul(&tmp, x, x, digits); float_sub(&tmp, &c1, &tmp, digits); float_sqrt(&tmp, digits); float_div(x, x, &tmp, digits+1); _arctanlt1(x, digits); float_free(&tmp); } /* evaluates arccos x for -1 <= x <= 1. The result is in the range 0 <= result <= pi. The relative error for a 100 digit result is < 5e-100 */ void _arccos( floatnum x, int digits) { signed char sgn; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &c1Div2) > 0) { float_sub(x, x, &c1, digits+1); _arccosxplus1lt0_5(x, digits); } else { _arcsinlt0_5(x, digits); float_sub(x, &cPiDiv2, x, digits+1); } if (sgn < 0) float_sub(x, &cPi, x, digits+1); } /* evaluates arccos (1+x) for -2 <= x <= 0. The result is in the range 0 <= x <= pi */ void _arccosxplus1( floatnum x, int digits) { if (float_abscmp(x, &c1Div2) <= 0) _arccosxplus1lt0_5(x, digits); else { float_add(x, x, &c1, digits); _arccos(x, digits); } } /* evaluates arcsin x for -1 <= x <= 1. The result is in the range -pi/2 <= result <= pi/2 The relative error for a 100 digit result is < 8e-100 */ void _arcsin( floatnum x, int digits) { signed char sgn; if (float_abscmp(x, &c1Div2) <= 0) _arcsinlt0_5(x, digits); else { sgn = float_getsign(x); float_abs(x); _arccos(x, digits); float_sub(x, &cPiDiv2, x, digits); float_setsign(x, sgn); } } /* evaluates cos x - 1 for x < |pi/4| relative error for 100 digit results is < 5e-100 */ char _cosminus1ltPiDiv4( floatnum x, int digits) { floatstruct tmp; int reductions; if (float_iszero(x)) return 1; float_abs(x); reductions = 0; while(float_getexponent(x) >= -2) { float_mul(x, x, &c1Div2, digits+1); ++reductions; } if (!cosminus1near0(x, digits) && reductions == 0) return !float_iszero(x); float_create(&tmp); for(; reductions-- > 0;) { float_mul(&tmp, x, x, digits); float_add(x, x, x, digits+2); float_add(x, x, &tmp, digits+2); float_add(x, x, x, digits+2); } float_free(&tmp); return 1; } /* evaluate sin x for |x| <= pi/4, using |sin x| = sqrt((1-cos x)*(2 + cos x-1)) relative error for 100 digit results is < 6e-100*/ void _sinltPiDiv4( floatnum x, int digits) { floatstruct tmp; signed char sgn; if (2*float_getexponent(x)+2 < -digits) /* for small x: sin x approx.== x */ return; float_create(&tmp); sgn = float_getsign(x); _cosminus1ltPiDiv4(x, digits); float_add(&tmp, x, &c2, digits+1); float_mul(x, x, &tmp, digits+1); float_abs(x); float_sqrt(x, digits); float_setsign(x, sgn); float_free(&tmp); } /* evaluates tan x for |x| <= pi/4. The relative error for a 100 digit result is < 6e-100 */ void _tanltPiDiv4( floatnum x, int digits) { floatstruct tmp; signed char sgn; if (2*float_getexponent(x)+2 < -digits) /* for small x: tan x approx.== x */ return; float_create(&tmp); sgn = float_getsign(x); _cosminus1ltPiDiv4(x, digits); float_add(&tmp, x, &c2, digits+1); float_mul(x, x, &tmp, digits+1); float_abs(x); float_sqrt(x, digits); float_sub(&tmp, &tmp, &c1, digits); float_div(x, x, &tmp, digits+1); float_setsign(x, sgn); float_free(&tmp); } /* evaluates cos x for |x| <= pi */ void _cos( floatnum x, int digits) { signed char sgn; float_abs(x); sgn = 1; if (float_cmp(x, &cPiDiv2) > 0) { sgn = -1; float_sub(x, &cPi, x, digits+1); } if (float_cmp(x, &cPiDiv4) <= 0) { if (2*float_getexponent(x)+2 < - digits) float_setzero(x); else _cosminus1ltPiDiv4(x, digits); float_add(x, x, &c1, digits); } else { float_sub(x, &cPiDiv2, x, digits+1); _sinltPiDiv4(x, digits); } float_setsign(x, sgn); } /* evaluates cos x - 1 for |x| <= pi. This function may underflow, which is indicated by the return value 0 */ char _cosminus1( floatnum x, int digits) { float_abs(x); if (float_cmp(x, &cPiDiv4) <= 0) return _cosminus1ltPiDiv4(x, digits); _cos(x, digits); float_sub(x, x, &c1, digits); return 1; } /* evaluates sin x for |x| <= pi. */ void _sin( floatnum x, int digits) { signed char sgn; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &cPiDiv2) > 0) float_sub(x, &cPi, x, digits+1); if (float_cmp(x, &cPiDiv4) <= 0) _sinltPiDiv4(x, digits); else { float_sub(x, &cPiDiv2, x, digits+1); if (2*float_getexponent(x)+2 < - digits) float_setzero(x); else _cosminus1ltPiDiv4(x, digits); float_add(x, x, &c1, digits); } float_setsign(x, sgn); } /* evaluates tan x for |x| <= pi. A return value of 0 indicates that x = +/- pi/2 within small tolerances, so that tan x cannot be reliable computed */ char _tan( floatnum x, int digits) { signed char sgn; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &cPiDiv2) > 0) { float_sub(x, &cPi, x, digits+1); sgn = -sgn; } if (float_cmp(x, &cPiDiv4) <= 0) _tanltPiDiv4(x, digits); else { float_sub(x, &cPiDiv2, x, digits+1); if (float_iszero(x) || float_getexponent(x) < -digits) return 0; _tanltPiDiv4(x, digits); float_reciprocal(x, digits); } float_setsign(x, sgn); return 1; } char _trigreduce( floatnum x, int digits) { floatstruct tmp; int expx, save; signed char sgn; char odd; if (float_abscmp(x, &cPi) <= 0) return 1; expx = float_getexponent(x); if (expx > float_getlength(&cPi) - digits) return 0; save = float_setprecision(MAXDIGITS); float_create(&tmp); sgn = float_getsign(x); float_abs(x); float_divmod(&tmp, x, x, &cPi, INTQUOT); float_setprecision(save); odd = float_isodd(&tmp); if (odd) float_sub(x, x, &cPi, digits+1); if (sgn < 0) float_neg(x); float_free(&tmp); return 1; } void _sinpix( floatnum x, int digits) { char odd; odd = float_isodd(x); float_frac(x); float_mul(x, &cPi, x, digits+1); _sin(x, digits); if (odd) float_neg(x); } speedcrunch-0.10.1/src/math/floatseries.c0000644000175000001440000003025411015364561017470 0ustar helderusers/* floatseries.c: basic series, based on floatnum. */ /* Copyright (C) 2007 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatseries.h" #include "floatconst.h" #include "floatcommon.h" #include "floatexp.h" /* Though all these serieses can be used with arguments |x| < 1 or even more, the computation time increases rapidly with x. Tests show, that for 100 digit results, it is best to limit x to |x| < 0.01..0.02, and use reduction formulas for greater x */ /* the Taylor series of arctan/arctanh x at x == 0. For small |x| < 0.01 this series converges very fast, yielding 4 or more digits of the result with every summand. The working precision is adjusted, so that the relative error for 100-digit arguments is around 5.0e-100. This means, the error is 1 in the 100-th place (or less) */ void arctanseries( floatnum x, int digits, char alternating) { int expx; int expsqrx; int pwrsz; int addsz; int i; floatstruct xsqr; floatstruct pwr; floatstruct smd; floatstruct sum; /* upper limit of log(x) and log(result) */ expx = float_getexponent(x)+1; /* the summands of the series from the second on are bounded by x^(2*i-1)/3. So the summation yields a result bounded by (x^3/(1-x*x))/3. For x < sqrt(1/3) approx.= 0.5, this is less than 0.5*x^3. We need to sum up only, if the first places of the result (roughly x) are touched. Ignoring the effect of a possile carry, this is only the case, if x*x >= 2*10^(-digits) > 10^(-digits) Example: for x = 9e-51, a 100-digits result covers the decimal places from 1e-51 to 1e-150. x^3/3 is roughly 3e-151, and so is the sum of the series. So we can ignore the sum, but we couldn't for x = 9e-50 */ if (float_iszero(x) || 2*expx < -digits) /* for very tiny arguments arctan/arctanh x is approx.== x */ return; float_create(&xsqr); float_create(&pwr); float_create(&smd); float_create(&sum); /* we adapt the working precision to the decreasing summands, saving time when multiplying. Unfortunately, there is no error bound given for the operations of bc_num. Tests show, that the last digit in an incomplete multiplication is usually not correct up to 5 ULP's. */ pwrsz = digits + 2*expx + 1; /* the precision of the addition must not decrease, of course */ addsz = pwrsz; i = 3; float_mul(&xsqr, x, x, pwrsz); float_setsign(&xsqr, alternating? -1 : 1); expsqrx = float_getexponent(&xsqr); float_copy(&pwr, x, pwrsz); float_setzero(&sum); for(; pwrsz > 0; ) { /* x^i */ float_mul(&pwr, &pwr, &xsqr, pwrsz+1); /* x^i/i */ float_divi(&smd, &pwr, i, pwrsz); /* The addition virtually does not introduce errors */ float_add(&sum, &sum, &smd, addsz); /* reduce the working precision according to the decreasing powers */ pwrsz = digits - expx + float_getexponent(&smd) + expsqrx + 3; i += 2; } /* add the first summand */ float_add(x, x, &sum, digits+1); float_free(&xsqr); float_free(&pwr); float_free(&smd); float_free(&sum); } /* series expansion of cos/cosh - 1 used for small x, |x| <= 0.01. The function returns 0, if an underflow occurs. The relative error seems to be less than 5e-100 for a 100-digit calculation with |x| < 0.01 */ char cosminus1series( floatnum x, int digits, char alternating) { floatstruct sum, smd; int expsqrx, pwrsz, addsz, i; expsqrx = 2 * float_getexponent(x); float_setexponent(x, 0); float_mul(x, x, x, digits+1); float_mul(x, x, &c1Div2, digits+1); float_setsign(x, alternating? -1 : 1); expsqrx += float_getexponent(x); if (float_iszero(x) || expsqrx < EXPMIN) { /* underflow */ float_setzero(x); return expsqrx == 0; } float_setexponent(x, expsqrx); pwrsz = digits + expsqrx + 2; if (pwrsz <= 0) /* for very small x, cos/cosh(x) - 1 = (-/+)0.5*x*x */ return 1; addsz = pwrsz; float_create(&sum); float_create(&smd); float_copy(&smd, x, pwrsz); float_setzero(&sum); i = 2; while (pwrsz > 0) { float_mul(&smd, &smd, x, pwrsz+1); float_divi(&smd, &smd, i*(2*i-1), pwrsz); float_add(&sum, &sum, &smd, addsz); ++i; pwrsz = digits + float_getexponent(&smd); } float_add(x, x, &sum, digits+1); float_free(&sum); float_free(&smd); return 1; } /* asymptotic series for ln Gamma(x) for x >= 77 and a 100 digit computation, the relative error is < 9e-100. the series converges, if x and digits comply to 100 >= digits >= 2 x >= sqrt((digits*ln 10 + 0.5*ln 2)/1.0033). As a special case, for digits == 1, convergence is guaranteed, if x >= 1.8. */ char lngammaasymptotic( floatnum x, int digits) { floatstruct recsqr; floatstruct sum; floatstruct smd; floatstruct pwr; int i, workprec; if (float_getexponent(x) >= digits) { /* if x is very big, ln(gamma(x)) is dominated by x*ln x and this asymptotic series does not contribute anything substantial to the final result */ float_setzero(x); return 1; } float_create(&recsqr); float_create(&sum); float_create(&smd); float_create(&pwr); float_copy(&pwr, &c1, EXACT); float_setzero(&sum); float_div(&smd, &c1, &c12, digits+1); workprec = digits - 2*float_getexponent(x)+3; i = 1; if (workprec > 0) { float_mul(&recsqr, x, x, workprec); float_reciprocal(&recsqr, workprec); while (float_getexponent(&smd) > -digits-1 && ++i <= MAXBERNOULLIIDX) { workprec = digits + float_getexponent(&smd) + 3; float_add(&sum, &sum, &smd, digits+1); float_mul(&pwr, &recsqr, &pwr, workprec); float_muli(&smd, &cBernoulliDen[i-1], 2*i*(2*i-1), workprec); float_div(&smd, &pwr, &smd, workprec); float_mul(&smd, &smd, &cBernoulliNum[i-1], workprec); } } else /* sum reduces to the first summand*/ float_move(&sum, &smd); if (i > MAXBERNOULLIIDX) /* x was not big enough for the asymptotic series to converge sufficiently */ float_setnan(x); else float_div(x, &sum, x, digits); float_free(&pwr); float_free(&smd); float_free(&sum); float_free(&recsqr); return i <= MAXBERNOULLIIDX; } /* The Taylor expansion of sqrt(pi)*erf(x)/2 around x = 0. converges only for small |x| < 1 sufficiently. erf(x) = SUM[i>=0] (x^(2*i+1)/(i! * (2*i+1))) relative error for 100-digit evaluation: < 3e-100 */ char erfseries( floatnum x, int digits) { floatstruct xsqr, smd, pwr; int i, workprec, expx; expx = float_getexponent(x); workprec = digits + 2*expx + 2; if (workprec <= 0 || float_iszero(x)) /* for tiny arguments approx. == x */ return 1; float_create(&xsqr); float_create(&smd); float_create(&pwr); float_mul(&xsqr, x, x, workprec + 1); workprec = digits + float_getexponent(&xsqr) + 1; float_copy(&pwr, x, workprec + 1); i = 1; while (workprec > 0) { float_mul(&pwr, &pwr, &xsqr, workprec + 1); float_divi(&pwr, &pwr, -i, workprec + 1); float_divi(&smd, &pwr, 2 * i++ + 1, workprec); float_add(x, x, &smd, digits + 3); workprec = digits + float_getexponent(&smd) + expx + 2; } float_free(&pwr); float_free(&smd); float_free(&xsqr); return 1; } /* the asymptotic expansion of erfc, the bigger x is, the better. returns sum( (2*i+1)! /i! / x^(2*i) Relative error for x >= 16 and 100-digit evaluation is less than 9e-100 */ char erfcasymptotic( floatnum x, int digits) { floatstruct smd, fct; int i, workprec, newprec; float_create(&smd); float_create(&fct); workprec = digits - 2 * float_getexponent(x) + 1; if (workprec <= 0) { float_copy(x, &c1, EXACT); return 1; } float_mul(&fct, x, x, digits + 1); float_div(&fct, &c1Div2, &fct, digits); float_neg(&fct); float_copy(&smd, &c1, EXACT); float_setzero(x); newprec = digits; workprec = newprec; i = 1; while (newprec > 0 && newprec <= workprec) { workprec = newprec; float_add(x, x, &smd, digits + 4); float_muli(&smd, &smd, i, workprec + 1); float_mul(&smd, &smd, &fct, workprec + 2); newprec = digits + float_getexponent(&smd) + 1; i += 2; } float_free(&fct); float_free(&smd); return newprec <= workprec; } /* this algorithm is based on a paper from Crandall, who in turn attributes to Chiarella and Reichel. Found this in a paper from Borwein, Bailey and Girgensohn, and added minor improvements such as the adaptive working precision. There is a restriction with this algorithm not mentioned in the paper: x must not be too large, because the correcting term 2/(1-exp(2*pi*x/alpha)) becomes dominant and renders the result incorrect for large x. Fortunately, the valid range seems to overlap with the range of the asymptotic formula. Picks a fixed alpha suitable for the desired precision and evaluates the sum f(t, alpha) = Sum[k>0](exp(-k*k*alpha*alpha)/(k*k*alpha*alpha + t) f(t, alpha) is used in the evaluation of erfc(sqrt(t)) alpha is dependent on the desired precision; For a precision of p places, alpha should be < pi/sqrt(p*ln 10). Unfortunately, the smaller alpha is, the worse is the convergence rate, so alpha is usually approximately its upper limit. relative error for 100-digit evaluation < 5e-100 */ char erfcsum( floatnum x, /* should be the square of the parameter to erfc */ int digits) { int i, workprec; floatstruct sum, smd; floatnum Ei; if (digits > erfcdigits) { /* cannot re-use last evaluation's intermediate results */ for (i = MAXERFCIDX; --i >= 0;) /* clear all exp(-k*k*alpha*alpha) to indicate their absence */ float_free(&erfccoeff[i]); /* current precision */ erfcdigits = digits; /* create new alpha appropriate for the desired precision This alpha need not be high precision, any alpha near the one evaluated here would do */ float_muli(&erfcalpha, &cLn10, digits + 4, 3); float_sqrt(&erfcalpha, 3); float_div(&erfcalpha, &cPi, &erfcalpha, 3); float_mul(&erfcalphasqr, &erfcalpha, &erfcalpha, EXACT); /* the exp(-k*k*alpha*alpha) are later evaluated iteratively. Initiate the iteration here */ float_copy(&erfct2, &erfcalphasqr, EXACT); float_neg(&erfct2); _exp(&erfct2, digits + 3); /* exp(-alpha*alpha) */ float_copy(erfccoeff, &erfct2, EXACT); /* start value */ float_mul(&erfct3, &erfct2, &erfct2, digits + 3); /* exp(-2*alpha*alpha) */ } float_create(&sum); float_create(&smd); float_setzero(&sum); for (i = 0; ++i < MAXERFCIDX;) { Ei = &erfccoeff[i-1]; if (float_isnan(Ei)) { /* if exp(-i*i*alpha*alpha) is not available, evaluate it from the coefficient of the last summand */ float_mul(&erfct2, &erfct2, &erfct3, workprec + 3); float_mul(Ei, &erfct2, &erfccoeff[i-2], workprec + 3); } /* Ei finally decays rapidly. save some time by adjusting the working precision */ workprec = digits + float_getexponent(Ei) + 1; if (workprec <= 0) break; /* evaluate the summand exp(-i*i*alpha*alpha)/(i*i*alpha*alpha+x) */ float_muli(&smd, &erfcalphasqr, i*i, workprec); float_add(&smd, x, &smd, workprec + 2); float_div(&smd, Ei, &smd, workprec + 1); /* add summand to the series */ float_add(&sum, &sum, &smd, digits + 3); } float_move(x, &sum); float_free(&smd); return 1; } speedcrunch-0.10.1/src/math/floatipower.c0000644000175000001440000000644511015364561017510 0ustar helderusers/* floatpower.c: power operation, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatipower.h" #include "floatconst.h" #include "floatcommon.h" #include "floatlong.h" /* for radix conversion, we need to get a result, even though it might slightly overflow or underflow. That is why we keep the exponent separate. For limited exponents (< 1024) the relative error for a 100 digit calculation is < 1e-99 x != 0 */ char _raiseposi( floatnum x, int* expx, unsigned exponent, int digits) { int exppwr, extra; floatstruct pwr; float_create(&pwr); float_move(&pwr, x); exppwr = float_getexponent(&pwr); float_setexponent(&pwr, 0); if ((exponent & 1) != 0) { float_copy(x, &pwr, digits+1); *expx = exppwr; } else { float_copy(x, &c1, EXACT); *expx = 0; } extra = _findfirstbit(exponent)/3+1; while((exponent >>= 1) != 0) { float_mul(&pwr, &pwr, &pwr, digits+extra); if (!_checkadd(&exppwr, exppwr)) break; exppwr += float_getexponent(&pwr); float_setexponent(&pwr, 0); if((exponent & 1) != 0) { float_mul(x, x, &pwr, digits+extra); *expx += exppwr + float_getexponent(x); float_setexponent(x, 0); } } float_free(&pwr); return exponent == 0; } char __raiseposi( floatnum x, unsigned exponent, int digits) { int exp; char result; result = _raiseposi(x, &exp, exponent, digits); float_setexponent(x, exp); return result; } /* raises a non-zero x to the exponent-th power */ char _raisei( floatnum x, int exponent, int digits) { int expx; signed char sgn; char negexp; switch (exponent) { case 0: float_copy(x, &c1, EXACT); /* fall through */ case 1: return 1; } if (float_getlength(x) == 1 && float_getdigit(x, 0) == 1) { /* power of ten */ if (!_checkmul(&exponent, float_getexponent(x)) || exponent < EXPMIN || exponent > EXPMAX) return 0; sgn = float_getsign(x) < 0? -(exponent & 1) : 1; float_setexponent(x, exponent); float_setsign(x, sgn); return 1; } negexp = exponent < 0; if (negexp) exponent = -exponent; if (!_raiseposi(x, &expx, exponent, digits) || expx < EXPMIN || expx > EXPMAX) return 0; float_setexponent(x, expx); return negexp? float_reciprocal(x, digits) : 1; } speedcrunch-0.10.1/src/math/floatio.c0000644000175000001440000005431011015364561016604 0ustar helderusers/* floatio.c: low level conversion, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatio.h" #include "floatlong.h" #include #include typedef enum { NmbNormal, NmbSpecial, NmbBufferOverflow } NmbType; /* Besides the regular bases 2, 8, 10 and 16, there are three others (IO_BASE_DEFAULT, IO_BASE_NAN and IO_BASE_ZERO) used internally to mark special situations. They are called pseudo-bases, because you cannot use them as parameter to floatnum functions */ static char _isspecial( signed char base) { switch (base) { case IO_BASE_NAN: case IO_BASE_ZERO: case IO_BASE_DEFAULT: return 1; } return 0; } /*-------------- ASCII based functions -------------*/ static char emptystr = '\0'; /* sort of alias for (strlen == 0). I don't have access to a POSIX manual, so I don't know how strlen reacts on NULL.*/ static char _isempty( const char* p) { return p == NULL || *p == '\0'; } /* copies the null-terminated ASCIIZ string src into the buffer dest. If the buffer is too small to hold src, 0 is returned */ static char _setstr( p_buffer dest, const char* src) { if (dest->sz > 0) { if (src == NULL) *(dest->buf) = '\0'; else if (dest->sz < strlen(src) + 1) return 0; else strcpy(dest->buf, src); } return 1; } /* looks, whether dest begins with the substring in pattern */ static int _match( const char* dest, const char* pattern) { int lg; if (_isempty(dest) || _isempty(pattern)) return 0; lg = strlen(pattern); return strncmp(dest, pattern, lg) == 0? lg : 0; } /* converts an ASCII encoded hexagesimal digit a corresponding value < 16 */ char _ascii2digit( char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'A' && c <= 'F') return (c - 'A') + 10; if (c >= 'a' && c <= 'f') return (c - 'a') + 10; return NO_DIGIT; } static char hexdigits[] = "0123456789ABCDEF"; /* converts a value 0 <=x < 16 into a hexdigit */ char _digit2ascii( int value) { return hexdigits[value]; } /* advances the pointer buf until it points to the first character not being a valid digit of base base. The return pointer is the initial value of buf, or NULL if no digit was found */ static const char* _scandigits( const char** buf, char base) { const char* p; const char* result; result = *buf; p = result - 1; while (_ascii2digit(*++p) < base); *buf = p; return p == result? NULL : result; } /*-------------------- t_seq_desc ---------------*/ /* returns the offset6 of the last significant digit */ static int _ofslastnz( p_seq_desc n) { return n->digits - n->trailing0 - 1; } /* number of significant digits in a number sequence */ int _significantdigits( p_seq_desc n) { return n->digits - n->leadingSignDigits - n->trailing0; } /* number of digits without leading zeros in a sequence. If the sequence describes an integer, these are the digits of this integer */ static int _intdigits( p_seq_desc n) { return n->digits - n->leadingSignDigits; } /* has a sequence significant digits? */ static char _iszero( p_seq_desc n) { return _significantdigits(n) == 0; } /* returns a digit from an ASCIIZ string containing digits only */ static char _getseqdigit( int ofs, p_seq_desc n) { if (ofs < 0 || ofs > _ofslastnz(n)) return 0; return _ascii2digit(*((char*)(n->param) + ofs)); } /* returns a digit from an ASCIIZ string containing digits only, but complements them */ static char _getcmpldigit( int ofs, p_seq_desc n) { int lastnz; char c; lastnz = _ofslastnz(n); if (ofs > lastnz) return 0; c = n->base - _getseqdigit(ofs, n) - (ofs == lastnz? 0 : 1); return c == n->base? 1 : c; } /* initializes a structure used for copying digit sequences */ static void _clearint( p_ext_seq_desc n) { n->seq.leadingSignDigits = 0; n->seq.digits = 0; n->seq.trailing0 = 0; n->seq.base = IO_BASE_ZERO; n->seq.param = NULL; n->getdigit = _getseqdigit; } /*---------------------- t_[io]token ------------------*/ /* initializes a structure used for describing a floating point number */ void _clearnumber( p_number_desc n) { n->prefix.sign = IO_SIGN_NONE; n->prefix.base = IO_BASE_NAN; _clearint(&n->intpart); _clearint(&n->fracpart); n->exp = 0; } /* creates a sequence descriptor from an ASCII digit sequence, not necessarily terminated by \0. After maxdigits digits, all following digits are assumed to be zero, regardless of their true value. */ static void _str2seq( p_ext_seq_desc n, const char* digits, int maxdigits, signed char base, char complement) { /* pre: n has to be initialized to describe a zero */ const char* p; const char* pz; char leadingdigit; unsigned char c; leadingdigit = 0; if (complement) { leadingdigit = base - 1; n->getdigit = _getcmpldigit; } p = digits; /* skip sign digits (usually 0, in complement mode F, 7 or 1 */ for (; _ascii2digit(*p) == leadingdigit; ++p); n->seq.leadingSignDigits = p - digits; /* pz is pointer to first trailing zero */ pz = p; for (; (c = _ascii2digit(*(p++))) < base;) { if (--maxdigits >= 0 && c != 0) pz = p; } n->seq.trailing0 = p - pz - 1; n->seq.digits = p - digits - 1; n->seq.param = (void*)digits; if (complement || _significantdigits(&n->seq) != 0) n->seq.base = base; } /* copy count digits (leading zeros included) from the digit sequence described by n to an ASCII buffer */ static Error _seq2str( p_buffer dest, int count, p_ext_seq_desc n) { int ofs; char* buf; ofs = 0; if (count >= dest->sz) return IOBufferOverflow; buf = dest->buf; for (; ofs < count; ++ofs) *(buf++) = _digit2ascii(n->getdigit(ofs, &n->seq)); *(buf) = '\0'; return Success; } /* copy all digits (leading zeros included) from the digit sequence described by n to an ASCII buffer, but complement the sequence before writing to the buffer */ static Error _cmplseq2str( p_buffer dest, p_ext_seq_desc n) { int bound; int ofs; int lastnz; char* buf; char c; buf = dest->buf; bound = _intdigits(&n->seq); if (bound + 1 > dest->sz) return IOBufferOverflow; lastnz = _ofslastnz(&n->seq); for (ofs = -1; ++ofs < lastnz;) { c = n->seq.base - n->getdigit(ofs, &n->seq) - 1; *(buf++) = _digit2ascii(c); } c = n->getdigit(ofs, &n->seq); if (c != 1 || _significantdigits(&n->seq) != 1) *(buf++) = _digit2ascii(n->seq.base - c); else { --bound; --ofs; } for (; ++ofs < bound;) *(buf++) = _digit2ascii(0); *(buf) = '\0'; return Success; } /* create a descriptor from a sequence of digits, assuming the sequence is an integer */ static Error str2int( p_ext_seq_desc n, const char* value, p_prefix prefix, int maxdigits) { char complement; if (prefix->base == IO_BASE_NAN) return IONoBase; complement = prefix->sign == IO_SIGN_COMPLEMENT; if (complement) { n->getdigit = _getcmpldigit; /* necessary, because when value is empty, base = IO_BASE_ZERO */ n->seq.base = prefix->base; } if (value) _str2seq(n, value, maxdigits, prefix->base, complement); return Success; } /* if base describes a special value (0 or NaN), the normal conversion routines fail. This routine creates special output values for these bases, and return nmbBufferOverflow: if the buffer is too small nmbSpecial: if it created output nmbNormal: if base stands for a usual number that the normal routines should deal with */ static NmbType _special2str( p_otokens tokens, signed char base) { const char* p; switch (base) { case IO_BASE_ZERO: p = "0"; break; case IO_BASE_NAN: p = "NaN"; break; default: return NmbNormal; } return _setstr(&tokens->intpart, p)? NmbSpecial : NmbBufferOverflow; } /* create an ASCIIZ sequence of the integer part, set sign and base. */ static Error int2str( p_otokens tokens, p_number_desc n, char complement) { tokens->sign = n->prefix.sign; tokens->base = n->prefix.base; switch (_special2str(tokens, n->prefix.base)) { case NmbSpecial: return Success; case NmbBufferOverflow: return IOBufferOverflow; default: break; /* NmbNormal */ } /* no special encodings */ if (complement) return _cmplseq2str(&tokens->intpart, &n->intpart); return _seq2str(&tokens->intpart, _intdigits(&n->intpart.seq), &n->intpart); } /* do some sanity checks, create descriptors of integer and fraction part in tokens, set sign and base */ static Error str2fixp( p_number_desc n, p_itokens tokens) { Error result; int maxdigits; maxdigits = tokens->maxdigits; n->prefix.base = tokens->base; n->prefix.sign = tokens->sign; if (tokens->sign == IO_SIGN_COMPLEMENT && (!_isempty(tokens->fracpart) || tokens->exp)) return IOInvalidComplement; result = str2int(&n->intpart, tokens->intpart, &n->prefix, maxdigits); if (_isspecial(n->prefix.base)) return result; if (!_isempty(tokens->fracpart)) _str2seq(&n->fracpart, tokens->fracpart, maxdigits - _intdigits(&n->intpart.seq), n->prefix.base, 0); if (n->prefix.sign != IO_SIGN_COMPLEMENT && n->intpart.seq.digits + n->fracpart.seq.digits == 0) return IONoSignificand; if (n->prefix.sign != IO_SIGN_COMPLEMENT && _iszero(&n->intpart.seq) && _iszero(&n->fracpart.seq)) n->prefix.base = IO_BASE_ZERO; return Success; } /* convert integer and fraction part into ASCIIZ sequences */ static Error fixp2str( p_otokens tokens, p_number_desc n, int scale) { Error result; result = int2str(tokens, n, n->prefix.sign == IO_SIGN_COMPLEMENT); if (result != Success || _isspecial(n->prefix.base)) return result; return _seq2str(&tokens->fracpart, scale, &n->fracpart); } /* create a descriptor from the digit sequence of the exponent */ static Error _exp2desc( p_number_desc n, p_itokens tokens) { if (tokens->expsign != IO_SIGN_NONE || tokens->exp) { unsigned upperLimit; signed char sign; switch (tokens->base) { case 2 : upperLimit = BITS_IN_BINEXP - 1; break; case 8 : upperLimit = BITS_IN_OCTEXP - 1; break; case 16: upperLimit = BITS_IN_HEXEXP - 1; break; default: upperLimit = BITS_IN_EXP - 1; break; } upperLimit = (1 << (upperLimit)) - 1; sign = tokens->expsign; switch (sign) { case IO_SIGN_COMPLEMENT: return IOBadExp; case IO_SIGN_NONE: sign = IO_SIGN_PLUS; break; case IO_SIGN_MINUS: ++upperLimit; break; default:; } if (tokens->exp > upperLimit) return IOExpOverflow; n->exp = sign < 0? -(int)(tokens->exp) : tokens->exp; } return Success; } /* create a descriptor from the floating point number given in tokens */ Error str2desc( p_number_desc n, p_itokens tokens) { Error result; _clearnumber(n); result = str2fixp(n, tokens); if (result == Success) result = _exp2desc(n, tokens); if (result != Success) n->prefix.base = IO_BASE_NAN; return result; } Error desc2str( p_otokens tokens, p_number_desc n, int scale) { Error result; result = fixp2str(tokens, n, scale); if (result != Success || _isspecial(n->prefix.base)) return result; tokens->exp = n->exp; return Success; } Error exp2str( p_buffer dest, int exp, char base) { char tmp[BITS_IN_EXP + 3]; int idx = 0; int di = 0; if (exp < 0) exp = -exp; while (exp != 0) { tmp[idx++] = hexdigits[exp % base]; exp /= base; } if (idx == 0) tmp[idx++] = hexdigits[0]; if (dest->sz <= idx) return IOBufferOverflow; for (; --idx >= 0;) dest->buf[di++] = tmp[idx]; dest->buf[di] = 0; return Success; } /* ***************** additional stuff, just to get started *************/ static t_ioparams stdioparams[4] = { {10, 10, '.', "0d", "eE(", " )", "", DECPRECISION}, {16, 10, '.', "0x", "(", ")", "sF", HEXPRECISION}, {2, 10, '.', "0b", "(", ")", "s1", BINPRECISION}, {8, 10, '.', "0o", "(", ")", "s7", OCTPRECISION} }; enum {idzero, idx10, idx16, idx2, idx8, idxcount}; static t_ioparams ioparams[idxcount] = { {IO_BASE_ZERO, IO_BASE_ZERO, '\0', "", "", "", "", 0x7FFFFFFF}, {IO_BASE_DEFAULT}, {IO_BASE_DEFAULT}, {IO_BASE_DEFAULT}, {IO_BASE_DEFAULT} }; static p_ioparams _defaultbase = NULL; static char _isvalidioparams( p_ioparams param) { return param != NULL && param->base != IO_BASE_DEFAULT; } static void _invalidateioparams( p_ioparams param) { if (param) param->base = IO_BASE_DEFAULT; } p_ioparams _base2ioparams( signed char base) { int idx; switch (base) { case 10: idx = idx10; break; case 16: idx = idx16; break; case 2: idx = idx2; break; case 8: idx = idx8; break; case IO_BASE_ZERO: idx = idzero; break; default: return NULL; } return &ioparams[idx]; } char setioparams( p_ioparams params) { p_ioparams dest; if (!_isvalidioparams(params)) return 0; dest = _base2ioparams(params->base); if (dest == NULL) return 0; *dest = *params; return 1; } char delioparams( signed char base) { p_ioparams dest; dest = _base2ioparams(base); _invalidateioparams(dest); return dest != NULL; } p_ioparams getioparams( signed char base) { p_ioparams result; if (base == IO_BASE_DEFAULT) return _defaultbase; result = _base2ioparams(base); return _isvalidioparams(result)? result : NULL; } static signed char _getdefaultbase() { p_ioparams param; param = getioparams(IO_BASE_DEFAULT); return param == NULL? IO_BASE_DEFAULT : param->base; } signed char setdefaultbase( signed char base) { char result; result = _getdefaultbase(); _defaultbase = _base2ioparams(base); return result; } void float_stdconvert() { int i; for (i = 0; i < 4; ++i) setioparams(&stdioparams[i]); setdefaultbase(10); } const char* basePrefix(char base) { return getioparams(base)->basetag; } static signed char _parsesign( const char** buf) { signed char result; result = IO_SIGN_NONE; if (!_isempty(*buf)) switch (**buf) { case '-': result = IO_SIGN_MINUS; break; case '+': result = IO_SIGN_PLUS; } if (result != IO_SIGN_NONE) (*buf)++; return result; } static signed char _parsebase( const char** buf, char defaultbase) { signed char base; int lg, i; lg = 0; base = IO_BASE_DEFAULT; if (!_isempty(*buf)) for (i = 0; i < idxcount; ++i) { lg = _match(*buf, ioparams[i].basetag); if (lg > 0) { base = ioparams[i].base; break; } } *buf += lg; return base == IO_BASE_DEFAULT? defaultbase : base; } static char _parsecmpl( const char** buf, char base) { int lg; p_ioparams param; param = getioparams(base); lg = 0; if (_isvalidioparams(param)) lg = _match(*buf, param->cmpltag); *buf += lg; return lg > 0; } Error parse( p_itokens tokens, const char** buffer) { p_ioparams params; const char* p; char* expchar; signed char base; int idx; char dot; char* expbegin; char* expend; tokens->fracpart = NULL; tokens->exp = 0; tokens->expsign = IO_SIGN_NONE; tokens->maxdigits = 0; dot = '.'; expbegin = "("; expend = ")"; p = *buffer; tokens->sign = _parsesign(&p); base = _parsebase(&p, _getdefaultbase()); params = getioparams(base); if (params != NULL) { dot = params->dot; if (params->expbegin != NULL); expbegin = params->expbegin; if (params->expend != NULL) expend = params->expend; tokens->maxdigits = params->maxdigits; } else base = 10; tokens->base = base; if (tokens->maxdigits <= 0) tokens->maxdigits = DECPRECISION; if (_parsecmpl(&p, tokens->base)) { if (tokens->sign != IO_SIGN_NONE) return IOInvalidComplement; tokens->sign = IO_SIGN_COMPLEMENT; } tokens->intpart = _scandigits(&p, base); if (*p == dot) { ++p; tokens->fracpart = _scandigits(&p, base); } if (!tokens->intpart && !tokens->fracpart && tokens->sign != IO_SIGN_COMPLEMENT) return IONoSignificand; expchar = strchr(expbegin, *p); if (!_isempty(expchar)) { const char* expptr; int i; int e = 0; int expbase; ++p; idx = expchar - expbegin; tokens->expsign = _parsesign(&p); expbase = _parsebase(&p, base); expptr = _scandigits(&p, expbase); if (!expptr || (*(expend + idx) != ' ' && *(expend + idx) != *p)) return IOBadExp; for (i = 0; i < p-expptr; ++i) { if (!_checkmul(&e, expbase) || !_checkadd(&e, _ascii2digit(*(expptr+i)))) return IOExpOverflow; } tokens->exp = e; } *buffer = p; return Success; } static char _decodesign( signed char s) { switch (s) { case IO_SIGN_PLUS: return '+'; case IO_SIGN_MINUS: return '-'; } return '\0'; } static char* _decodebase( signed char base) { p_ioparams param; param = getioparams(base); if (!_isvalidioparams(param) || _isempty(param->basetag)) return &emptystr; return param->basetag; } static char* _decodecomplement( signed char sign, signed char base) { p_ioparams param; param = getioparams(base); if (sign != IO_SIGN_COMPLEMENT || !_isvalidioparams(param) || _isempty(param->cmpltag)) return &emptystr; return param->cmpltag; } static void _cattoken( char* buf, char* token, char enable) { if (enable && !_isempty(token)) strcat(buf, token); } int cattokens( char* buf, int bufsz, p_otokens tokens, signed char expbase, unsigned flags) { int sz; int fraclg; p_ioparams ioparams; char* expbegin; char* expend; char* cmpltag; char* basetag; char* expbasetag; signed char base; char dot; char cbuf[2]; char printsign; char printbasetag; char printcmpl; char printleading0; char printdot; char printexp; char printexpsign; char printexpbase; char printexpbegin; char printexpend; char exp[BITS_IN_BINEXP+2]; t_buffer expBuf; expBuf.sz = sizeof(exp); expBuf.buf = exp; cbuf[1] = '\0'; fraclg = 0; if (!_isempty(tokens->fracpart.buf)) { fraclg = strlen(tokens->fracpart.buf) - 1; if ((flags & IO_FLAG_SUPPRESS_TRL_ZERO) != 0) while (fraclg >= 0 && tokens->fracpart.buf[fraclg] == '0') --fraclg; ++fraclg; } ioparams = getioparams(IO_BASE_DEFAULT); base = tokens->base; printbasetag = !_isspecial(base) && (flags & IO_FLAG_SUPPRESS_BASETAG) == 0 && (ioparams == NULL || ioparams->base != base); ioparams = getioparams(base); basetag = _decodebase(base); cmpltag = _decodecomplement(tokens->sign, base); expbasetag = NULL; if (base == IO_BASE_DEFAULT) flags |= IO_FLAG_SUPPRESS_DOT | IO_FLAG_SUPPRESS_LDG_ZERO; if ((flags & IO_FLAG_SHOW_BASE) != 0) printbasetag = 1; printcmpl = tokens->sign == IO_SIGN_COMPLEMENT && (flags & IO_FLAG_SUPPRESS_CMPL) == 0; printsign = !printcmpl && tokens->sign != IO_SIGN_NONE && (tokens->sign != IO_SIGN_PLUS || (flags & IO_FLAG_SUPPRESS_PLUS) == 0); printleading0 = _isempty(tokens->intpart.buf) && (flags & IO_FLAG_SUPPRESS_LDG_ZERO) == 0; printdot = fraclg > 0 || (flags & IO_FLAG_SUPPRESS_DOT) == 0; printexp = base != IO_BASE_NAN && base != IO_BASE_ZERO && ((flags & IO_FLAG_SUPPRESS_EXPZERO) == 0 || tokens->exp != 0); if (printexp) { if (expbase < 2) expbase = ioparams->expbase; expbasetag = _decodebase(expbase); printexpsign = tokens->exp < 0 || (flags & IO_FLAG_SUPPRESS_EXPPLUS) == 0; printexpbase = expbasetag != NULL && (flags & IO_FLAG_SUPPRESS_EXPBASE) == 0 && (_isempty(basetag) || strcmp(basetag, expbasetag) != 0); if ((flags & IO_FLAG_SHOW_EXPBASE) != 0) printexpbase = 1; } dot = '.'; expbegin = "("; expend = ")"; if (ioparams != NULL) { dot = ioparams->dot; expbegin = ioparams->expbegin; expend = ioparams->expend; } printexpbegin = *expbegin != '\0'; printexpend = *expend != '\0' && *expend != ' '; sz = 1; if (printsign) sz += 1; if (printbasetag) sz += strlen(basetag); if (printcmpl) sz += strlen(cmpltag); if (printleading0) ++sz; if (!_isempty(tokens->intpart.buf)) sz += strlen(tokens->intpart.buf); if (printdot) sz += 1; sz += fraclg; if (printexp) { exp2str(&expBuf, tokens->exp, expbase); if (printexpbegin) ++sz; if (printexpsign) sz += 1; if (printexpbase) sz += strlen(expbasetag); sz += strlen(expBuf.buf); if (printexpend) ++sz; } if (sz <= bufsz) { *buf = '\0'; cbuf[0] = _decodesign(tokens->sign); _cattoken(buf, cbuf, printsign); _cattoken(buf, basetag, printbasetag); _cattoken(buf, cmpltag, printcmpl); _cattoken(buf, "0", printleading0); _cattoken(buf, tokens->intpart.buf, 1); cbuf[0] = dot; _cattoken(buf, cbuf, printdot); if (fraclg > 0) strncat(buf, tokens->fracpart.buf, fraclg); if (printexp) { cbuf[0] = *expbegin; _cattoken(buf, cbuf, printexpbegin); cbuf[0] = _decodesign(tokens->exp < 0? -1:1); _cattoken(buf, cbuf, printexpsign); _cattoken(buf, expbasetag, printexpbase); strcat(buf, expBuf.buf); cbuf[0] = *expend; _cattoken(buf, cbuf, printexpend); } } return sz; } speedcrunch-0.10.1/src/math/floathmath.h0000644000175000001440000003321511015364561017304 0ustar helderusers/* floathmath.h: higher mathematical functions, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATHMATH_H #define _FLOATHMATH_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif /* evaluates ln(1+x) for x > -1. This function is especially useful for small x, where its computation is more precise than that of float_ln. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_lnxplus1(floatnum x, int digits); /* evaluates ln x for x > 0. Near x == 0, this function yields better results than float_lnxplus1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_ln(floatnum x, int digits); /* evaluates log x (the logarithm to base 10) for x > 0. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_log(floatnum x, int digits); /* evaluates lg x (the logarithm to base 2) for x > 0. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_lg(floatnum x, int digits); /* evaluates arsinh x, the inverse function of sinh. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arsinh(floatnum x, int digits); /* evaluates arcosh x, the inverse function of cosh, for x >= 1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_arcosh(floatnum x, int digits); /* evaluates artanh x, the inverse function of tanh, for |x| < 1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_artanh(floatnum x, int digits); /* evaluates artanh (1+x), for -2 < x <= 0. This function is especially useful, if you want to compute values near the pole at x == 1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_artanhxplus1(floatnum x, int digits); /* evaluates arcosh (1+x), for x >= 0. This function is especially useful, if you want to compute values near the singularity of cosh at x == 1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_arcoshxplus1(floatnum x, int digits); /* evaluates exp(x) In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_exp(floatnum x, int digits); /* evaluates exp(x)-1. Use this in the neighbourhood of x == 0. In case of an error, x is set to NaN and 0 is returned. Errors: Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_expminus1(floatnum x, int digits); /* evaluates cosh(x). In case of an error, x is set to NaN and 0 is returned. Errors: Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_cosh(floatnum x, int digits); /* evaluates cosh(x) - 1. Yields better results in the neighbourhood of x == 0 than float_cosh. In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_coshminus1(floatnum x, int digits); /* evaluates sinh(x). In case of an error, x is set to NaN and 0 is returned. Errors: Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_sinh(floatnum x, int digits); /* evaluates tanh(x). In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_tanh(floatnum x, int digits); /* evaluates tanh(x)-1. Yields better results for large x > 0, when tanh x approx.== 1, than float_tanh. In case of an error, x is set to NaN and 0 is returned. Errors: Underflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_tanhminus1(floatnum x, int digits); /* evaluates 10^x. No optimization is employed for integer exponents. In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_power10(floatnum x, int digits); /* evaluates arctan x, yielding a result -pi/2 < result < pi/2. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arctan(floatnum x, int digits); /* evaluates arcsin x for -1 <= x <= 1, yielding a result -pi/2 <= result <= pi/2. In case of an error, x is set to NaN and 0 is returned. Errors: OutOfDomain NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arcsin(floatnum x, int digits); /* evaluates arccos x for -1 <= x <= 1, yielding a result 0 <= result <= pi. In case of an error, x is set to NaN and 0 is returned. Errors: OutOfDomain NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arccos(floatnum x, int digits); /* evaluates arccos (1+x) for -2 <= x <= 0, yielding a result 0 <= result <= pi. This function is more precise in the neighbourhood of x == 0 than float_arccos. In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arccosxplus1(floatnum x, int digits); /* evaluates tan x. For extreme large x, the periodicity of tan is not recognized any more, and a FLOAT_UNSTABLE error is reported. The same holds, if x is too near to a pole of tan, more precise, if |x-0.5*n*pi| < 1e- for some n. In case of an error, x is set to NaN and 0 is returned. Errors: EvalUnstable NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_tan(floatnum x, int digits); /* evaluates sin x. For extreme large x, the periodicity of sin is not recognized any more, and a FLOAT_UNSTABLE error is reported. In case of an error, x is set to NaN and 0 is returned. Errors: EvalUnstable NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_sin(floatnum x, int digits); /* evaluates cos x. For extreme large x, the periodicity of sin is not recognized any more, and a FLOAT_UNSTABLE error is reported. In case of an error, x is set to NaN and 0 is returned. Errors: EvalUnstable NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_cos(floatnum x, int digits); /* evaluates cos x - 1. In the neighbourhood of x==0, when cos x approx.== 1, this function yields better results than float_cos. For extreme large x, the periodicity of sin is not recognized any more, and a FLOAT_UNSTABLE error is reported. In case of an error, x is set to NaN and 0 is returned. Errors: Undeflow EvalUnstable NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_cosminus1(floatnum x, int digits); /* evaluates base^exponent In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow OutOfDomain (base <= 0 and most exponents) ZeroDivide ( base == 0 and exponent negative) NaNOperand InvalidPrecision (digits > maxprecision-14) */ char float_raisei(floatnum power, cfloatnum base, int exponent, int digits); /* evaluates base^exponent In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow OutOfDomain (base <= 0 and most exponents) ZeroDivide (base == 0 and exponent negative) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_raise(floatnum power, cfloatnum base, cfloatnum exponent, int digits); /* evaluates Gamma(x) = (x-1)! In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow ZeroDivide (for integers <= 0) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_gamma(floatnum x, int digits); /* evaluates ln(Gamma(x)) = ln((x-1)!) In case of an error, x is set to NaN and 0 is returned. Errors: Overflow OutOfDomain (for x <= 0) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_lngamma(floatnum x, int digits); /* evaluates x! In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow ZeroDivide (for integers < 0) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_factorial(floatnum x, int digits); /* evaluates gamma(x+delta)/gamma(x). If delta is a positive integer, this is the Pochhammer symbol x*(x+1)*...*(x+delta-1). The poles of the gamma function are handled appropriately. Errors: Underflow Overflow ZeroDivide (not annihilated pole in the nominator) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_pochhammer(floatnum x, cfloatnum delta, int digits); /* evaluates erf(x). NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_erf(floatnum x, int digits); /* evaluates erfc(x). Underflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_erfc(floatnum x, int digits); /* cuts off the fraction part of and complements the bits in the 2's complement representation of then. The corresponding integer of the result is stored back in . In case of an error, is set to NaN and 0 is returned. Errors: OutOfLogicRange NaNOperand */ char float_not(floatnum x); /* uses the integer parts of and and builds their 2's complement representation. The resulting strings are and-ed and the corresponding integer is stored in dest. In case of an error, is set to NaN and 0 is returned. Errors: OutOfLogicRange NaNOperand */ char float_and(floatnum dest, cfloatnum x, cfloatnum y); /* uses the integer parts of x and y and builds their 2's complement representation. The resulting strings are or-ed and the corresponding integer is stored in dest. In case of an error, is set to NaN and 0 is returned. Errors: OutOfLogicRange NaNOperand */ char float_or(floatnum dest, cfloatnum x, cfloatnum y); /* uses the integer parts of and and builds their 2's complement representation. The resulting strings are xor-ed and the corresponding integer is stored in dest. In case of an error, is set to NaN and 0 is returned. Errors: OutOfLogicRange NaNOperand */ char float_xor(floatnum dest, cfloatnum x, cfloatnum y); /* uses the integer part of and builds its 2's complement representation as LOGICRANGE bits. The resulting bitstring is then shifted y times to the left. Shifted out bits are dropped, to the right 0 bits are fed in. The corresponding integer of the resulting bitstring is stored in . has to be an integer or an error is reported. If it is negative, this operation turns into a shift right. In case of an error, is set to NaN and 0 is returned. Errors: OutOfDomain (y not an integer) OutOfLogicRange NaNOperand */ char float_shl(floatnum dest, cfloatnum x, cfloatnum y); /* uses the integer part of and builds its 2's complement representation as LOGICRANGE bits. The resulting bitstring is then shifted y times to the right. Shifted out bits are dropped, to the left the sign bit is duplicated. The corresponding integer of the resulting bitstring is stored in . has to be an integer or an error is reported. If it is negative, this operation turns into a shift left. In case of an error, is set to NaN and 0 is returned. Errors: OutOfDomain (y not an integer) OutOfLogicRange NaNOperand */ char float_shr(floatnum dest, cfloatnum x, cfloatnum y); #ifdef __cplusplus } #endif #endif /* _FLOATLOG_H */ speedcrunch-0.10.1/src/math/floatseries.h0000644000175000001440000000345511015364561017500 0ustar helderusers/* floatseries.h: header file for basic series, based on floatnum. */ /* Copyright (C) 2007 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATSERIES_H #define _FLOATSERIES_H #include "floatnum.h" #define artanhnear0(x, digits) arctanseries(x, digits, 0) #define arctannear0(x, digits) arctanseries(x, digits, 1) #define coshminus1near0(x, digits) cosminus1series(x, digits, 0) #define cosminus1near0(x, digits) cosminus1series(x, digits, 1) #ifdef __cplusplus extern "C" { #endif void arctanseries(floatnum x, int digits, char alternating); char cosminus1series(floatnum x, int digits, char alternating); char lngammaasymptotic(floatnum x, int digits); char erfseries(floatnum x, int digits); char erfcasymptotic(floatnum x, int digits); char erfcsum(floatnum xsqr, int digits); #ifdef __cplusplus } #endif #endif /* _FLOATSERIES_H */ speedcrunch-0.10.1/src/math/floaterf.c0000644000175000001440000001347311015364561016756 0ustar helderusers/* floaterf.c: normal distribution integrals erf and the like */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floaterf.h" #include "floatconst.h" #include "floatcommon.h" #include "floatexp.h" /* checks the quality of the asymptotic series for erfc. If the ratio of two subsequent summands from the series (the convergence rate) should not fall below `ratio' for a desired result precision (represented by digits), the number of summands n must not be greater than n <= (`digits'*ln 10 + 0.5 * ln 2)/(1 - ln `ratio') and the parameter x has to fullfil x >= sqrt(n/`ratio') `ratio' must be a value < 1, If you pick a value close to 1, you finally have to add quite a lot of summands from the series (in low precision), that affect a few digits at the low end of the result only. On the other hand, choosing a good convergence rate pushes the validity range of the series towards larger x. Here, the convergence rate is chosen to be 0.5, meaning that the addition of a summand from the series at least halfs the magnitude of the tail of the series. The evaluation is carried out in low precision using interger arithmetic rather than floating point data. For a 100 digit result the lower boundary of the range of the asymptotic series (truncated when the convergence rate falls below 0.5) is x > approx. 16.5. The above formulas estimate the limit x slightly too small, especially when `digits' is small. So, to compensate for that, r should be at least <= 0.92 */ static char _asymptotic_good( floatnum x, int digits) { /* all constants scaled by 10000 */ /* 1/ratio */ #define RATIO 20000 /* (1 - ln ratio) */ #define C_RATIO 16931 /* ln 10 */ #define LN10 23026 /* 0.5*ln 2 */ #define LN2DIV2 3466 int n, ix; if (!float_isvalidexp(float_getexponent(x) + 2) || (digits == 1 && float_cmp(x, &c2) >= 0)) return 1; /* 10000 * n/ratio */ n = RATIO*((digits * LN10 + LN2DIV2) / C_RATIO); float_addexp(x, 2); ix = float_asinteger(x); float_addexp(x, -2); return ix == 0 || ix >= 0x10000 || ix * ix >= n; } static int _logexpxsqr(int exp) { if (exp < 0) exp = 0; if (exp >= 0x1000) exp = 0x1000; return ((exp * exp * 73) >> 5); } char _erf( floatnum x, int digits) { int workprec; signed char sign; sign = float_getsign(x); float_abs(x); if (float_cmp(x, &c1Div2) > 0) { workprec = digits - _logexpxsqr(float_getexponent(x)); if (workprec < 0 || !_erfc(x, workprec)) float_setzero(x); float_sub(x, &c1, x, digits + 1); } else { erfnear0(x, digits); float_mul(x, x, &c2DivSqrtPi, digits + 2); } float_setsign(x, sign); return 1; } char _erfc( floatnum x, int digits) { floatstruct tmp, t2, t3; int expx, prec; char result; if (float_cmp(x, &c1Div2) <= 0) { /* use erfc(x) = 1 - erf(x) for small or negative x */ prec = digits; /* default for negative x, result is approx. 1 */ expx = float_getexponent(x); if (expx < 0) { /* |x| < 1, but not 0 */ prec = expx + digits + 2; if (prec <= 0) { float_copy(x, &c1, EXACT); return 1; } } _erf(x, prec); float_sub(x, &c1, x, digits + 1); return 1; } float_create(&tmp); if (_asymptotic_good(x, digits)) { if (float_mul(&tmp, x, x, digits + 5) && _exp(&tmp, digits + 3) && float_mul(&tmp, &tmp, x, digits + 3) && float_div(&tmp, &c1DivSqrtPi, &tmp, digits + 3)) { if (!erfcbigx(x, digits)) result = _seterror(x, EvalUnstable); else result = float_mul(x, x, &tmp, digits + 4); } else result = _seterror(x, Underflow); } else { result = 1; float_create(&t2); float_create(&t3); float_mul(&t2, x, x, digits + 2); float_copy(&tmp, &t2, EXACT); erfcsum(&tmp, digits); float_add(&tmp, &tmp, &tmp, digits + 1); float_copy(&t3, &t2, EXACT); float_reciprocal(&t2, digits + 1); float_add(&tmp, &tmp, &t2, digits + 2); float_neg(&t3); _exp(&t3, digits + 2); float_mul(&t3, &t3, &tmp, digits + 2); float_mul(&tmp, &erfcalpha, x, digits + 2); float_mul(&t3, &tmp, &t3, digits + 3); float_mul(&t3, &c1DivPi, &t3, digits + 2); /* quick estimate to find the right working precision */ float_div(&tmp, x, &erfcalpha, 4); float_mul(&tmp, &tmp, &c2Pi, 4); float_div(&tmp, &tmp, &cLn10, 4); prec = digits - float_getexponent(&t3) - float_asinteger(&tmp) + 1; /* add correction term */ if (prec > 0) { float_div(&tmp, x, &erfcalpha, prec + 3); float_mul(&tmp, &tmp, &c2Pi, prec + 4); _exp(&tmp, prec); float_sub(&tmp, &c1, &tmp, prec); float_div(&tmp, &c2, &tmp, prec); float_add(&t3, &t3, &tmp, digits + 1); } float_free(&t2); float_move(x, &t3); } float_free(&tmp); return result; } speedcrunch-0.10.1/src/math/number.h0000644000175000001440000001074311015364561016446 0ustar helderusers/* number.h: Arbitrary precision numbers header file. */ /* Copyright (C) 1991, 1992, 1993, 1994, 1997, 2000 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. You may contact the author by: e-mail: philnelson@acm.org us-mail: Philip A. Nelson Computer Science Department, 9062 Western Washington University Bellingham, WA 98226-9062 *************************************************************************/ #ifndef _NUMBER_H_ #define _NUMBER_H_ #ifdef __cplusplus extern "C" { #endif #undef _PROTOTYPE #ifndef NUMBER__STDC__ #define NUMBER__STDC__ #endif typedef enum {PLUS, MINUS} sign; typedef struct bc_struct *bc_num; typedef struct bc_struct { sign n_sign; int n_len; /* The number of digits before the decimal point. */ int n_scale; /* The number of digits after the decimal point. */ int n_refs; /* The number of pointers to this number. */ bc_num n_next; /* Linked list for available list. */ char *n_ptr; /* The pointer to the actual storage. If NULL, n_value points to the inside of another number (bc_multiply...) and should not be "freed." */ char *n_value; /* The number. Not zero char terminated. May not point to the same place as n_ptr as in the case of leading zeros generated. */ } bc_struct; /* The base used in storing the numbers in n_value above. Currently this MUST be 10. */ #define BASE 10 /* Some useful macros and constants. */ #define CH_VAL(c) (c - '0') #define CH_HEX(c) ((c < ':') ? ( c - '0') : (c < 'G') ? ( c - 'A' + 10) : ( c - 'a' + 10)) #define BCD_CHAR(d) (d + '0') #ifdef MIN #undef MIN #undef MAX #endif #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)>(b)?(b):(a)) #define ODD(a) ((a)&1) #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef LONG_MAX #define LONG_MAX 0x7ffffff #endif /* Global numbers. */ extern bc_num _zero_; extern bc_num _one_; extern bc_num _two_; /* Function Prototypes */ /* Define the _PROTOTYPE macro if it is needed. */ #ifndef _PROTOTYPE #ifdef NUMBER__STDC__ #define _PROTOTYPE(func, args) func args #else #define _PROTOTYPE(func, args) func() #endif #endif _PROTOTYPE(void bc_init_numbers, (void)); _PROTOTYPE(bc_num bc_new_num, (int length, int scale)); _PROTOTYPE(void bc_free_num, (bc_num *num)); _PROTOTYPE(bc_num bc_copy_num, (bc_num num)); _PROTOTYPE(void bc_init_num, (bc_num *num)); _PROTOTYPE(void bc_str2num, (bc_num *num, char *str, int scale)); _PROTOTYPE(char *bc_num2str, (bc_num num)); _PROTOTYPE(void bc_int2num, (bc_num *num, int val)); _PROTOTYPE(long bc_num2long, (bc_num num)); _PROTOTYPE(int bc_compare, (bc_num n1, bc_num n2)); _PROTOTYPE(char bc_is_zero, (bc_num num)); _PROTOTYPE(char bc_is_near_zero, (bc_num num, int scale)); _PROTOTYPE(char bc_is_neg, (bc_num num)); _PROTOTYPE(void bc_add, (bc_num n1, bc_num n2, bc_num *result, int scale_min)); _PROTOTYPE(void bc_sub, (bc_num n1, bc_num n2, bc_num *result, int scale_min)); _PROTOTYPE(void bc_multiply, (bc_num n1, bc_num n2, bc_num *prod, int scale)); _PROTOTYPE(int bc_divide, (bc_num n1, bc_num n2, bc_num *quot, int scale)); _PROTOTYPE(int bc_modulo, (bc_num num1, bc_num num2, bc_num *result, int scale)); _PROTOTYPE(int bc_divmod, (bc_num num1, bc_num num2, bc_num *quot, bc_num *rem, int scale)); _PROTOTYPE(int bc_raisemod, (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale)); _PROTOTYPE(void bc_raise, (bc_num num1, bc_num num2, bc_num *result, int scale)); _PROTOTYPE(int bc_sqrt, (bc_num *num, int scale)); _PROTOTYPE(void bc_out_num, (bc_num num, int o_base, void (* out_char)(int), int leading_zero)); #ifdef __cplusplus } #endif #endif speedcrunch-0.10.1/src/math/floatlog.h0000644000175000001440000000325011015364561016760 0ustar helderusers/* floatlog.h: logarithms and friends, based on floatnum. */ /* Copyright (C) 2007 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATLOG_H #define _FLOATLOG_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif void _lnxplus1near0(floatnum x, int digits); void _lnreduce(floatnum x, floatnum lnguess, int digits); void _lnxplus1lt1(floatnum x, int digits); void _ln(floatnum x, int digits); void _lnxplus1(floatnum x, int digits); void _artanh1minusx(floatnum x, int digits); void _artanhlt0_5(floatnum x, int digits); void _artanh(floatnum x, int digits); void _arsinh(floatnum x, int digits); void _arcoshxplus1(floatnum x, int digits); #ifdef __cplusplus } #endif #endif /* _FLOATLOG_H */ speedcrunch-0.10.1/src/math/hmath.hxx0000644000175000001440000001674211015364561016644 0ustar helderusers// HMath: C++ high precision math routines // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2007-2008 Helder Correia // Copyright (C) 2008 Wolf Lammen // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef HMATH_HXX #define HMATH_HXX #include "floatconfig.h" #include "floatio.h" #include class HMath; class HNumberPrivate; class HNumber { friend class HMath; friend HNumber operator-( const HNumber & ); friend HNumber operator-( const HNumber &, const HNumber& ); public: HNumber(); HNumber( const HNumber& ); HNumber( int i ); HNumber( const char* ); ~HNumber(); bool isNan() const; bool isZero() const; bool isPositive() const; bool isNegative() const; bool isInteger() const; // 'g': decimal general (default) // 'f': decimal fixed // 'e': decimal scientific // 'n': decimal engineering // 'h': hexadecimal // 'o': octal // 'b': binary char format() const; void setFormat( char c = 0 ); int toInt() const; Error error() const; HNumber& operator=( const HNumber& ); HNumber operator+( const HNumber& ) const; HNumber& operator+=( const HNumber& ); HNumber& operator-=( const HNumber& ); HNumber operator*( const HNumber& ) const; HNumber& operator*=( const HNumber& ); HNumber operator/( const HNumber& ) const; HNumber& operator/=( const HNumber& ); HNumber operator%( const HNumber& ) const; HNumber operator&( const HNumber& ) const; HNumber& operator&=( const HNumber& ); HNumber operator|( const HNumber& ) const; HNumber& operator|=( const HNumber& ); HNumber operator^( const HNumber& ) const; HNumber& operator^=( const HNumber& ); HNumber operator~() const; HNumber operator>>( const HNumber& ) const; HNumber operator<<( const HNumber& ) const; bool operator>( const HNumber& n ) const; bool operator<( const HNumber& n ) const; bool operator>=( const HNumber& n ) const; bool operator<=( const HNumber& n ) const; bool operator==( const HNumber& n ) const; bool operator!=( const HNumber& n ) const; static HNumber idiv( const HNumber& n1, const HNumber& n2 ); static HNumber nan(Error error = Success); private: HNumberPrivate * d; }; HNumber operator-( const HNumber & ); HNumber operator-( const HNumber &, const HNumber & ); class HMath { public: // FORMAT static char * format( const HNumber & n, char format = 'g', int prec = -1 ); static char * formatFixed( const HNumber & n, int prec = -1 ); static char * formatScientific( const HNumber & n, int prec = -1 ); static char * formatEngineering( const HNumber & n, int prec = -1 ); static char * formatGeneral( const HNumber & n, int prec = -1 ); static char * formatHexadec( const HNumber & n ); static char * formatOctal( const HNumber & n ); static char * formatBinary( const HNumber & n ); // CONSTANTS static HNumber phi(); static HNumber pi(); // GENERAL MATH static HNumber rad2deg( const HNumber & angle ); static HNumber deg2rad( const HNumber & angle ); static int compare( const HNumber & n1, const HNumber & n2 ); static HNumber max( const HNumber & n1, const HNumber & n2 ); static HNumber min( const HNumber & n1, const HNumber & n2 ); static HNumber abs( const HNumber & n ); static HNumber integer( const HNumber & n ); static HNumber frac( const HNumber & n ); static HNumber floor( const HNumber & n ); static HNumber ceil( const HNumber & n ); static HNumber gcd( const HNumber & n1, const HNumber & n2 ); static HNumber round( const HNumber & n, int prec = 0 ); static HNumber trunc( const HNumber & n, int prec = 0 ); static HNumber sqrt( const HNumber & n ); static HNumber cbrt( const HNumber & n ); static HNumber raise( const HNumber & n1, int n ); static HNumber raise( const HNumber & n1, const HNumber & n2 ); static HNumber exp( const HNumber & x ); static HNumber ln( const HNumber & x ); static HNumber log( const HNumber & x ); static HNumber lg( const HNumber & x ); static HNumber sign( const HNumber & x ); // TRIGONOMETRY static HNumber sin( const HNumber & x ); static HNumber cos( const HNumber & x ); static HNumber tan( const HNumber & x ); static HNumber cot( const HNumber & x ); static HNumber sec( const HNumber & x ); static HNumber csc( const HNumber & x ); static HNumber asin( const HNumber & x ); static HNumber acos( const HNumber & x ); static HNumber atan( const HNumber & x ); static HNumber sinh( const HNumber & x ); static HNumber cosh( const HNumber & x ); static HNumber tanh( const HNumber & x ); static HNumber arsinh( const HNumber & x ); static HNumber arcosh( const HNumber & x ); static HNumber artanh( const HNumber & x ); // PROBABILITY static HNumber nCr( const HNumber & n, const HNumber & k ); static HNumber nPr( const HNumber & n, const HNumber & r ); static HNumber factorial( const HNumber & x, const HNumber & base = HNumber(1) ); static HNumber gamma( const HNumber & x); static HNumber lnGamma( const HNumber & x); static HNumber binomialPmf( const HNumber & k, const HNumber & n, const HNumber & p ); static HNumber binomialCdf( const HNumber & k, const HNumber & n, const HNumber & p ); static HNumber binomialMean( const HNumber & n, const HNumber & p ); static HNumber binomialVariance( const HNumber & n, const HNumber & p ); static HNumber hypergeometricPmf( const HNumber & k, const HNumber & N, const HNumber & M, const HNumber & n ); static HNumber hypergeometricCdf( const HNumber & k, const HNumber & N, const HNumber & M, const HNumber & n ); static HNumber hypergeometricMean( const HNumber & N, const HNumber & M, const HNumber & n ); static HNumber hypergeometricVariance( const HNumber & N, const HNumber & M, const HNumber & n ); static HNumber poissonPmf( const HNumber & k, const HNumber & l ); static HNumber poissonCdf( const HNumber & k, const HNumber & l ); static HNumber poissonMean( const HNumber & l ); static HNumber poissonVariance( const HNumber & l ); static HNumber erf( const HNumber & x ); static HNumber erfc( const HNumber & x ); // LOGIC static HNumber mask ( const HNumber & val, const HNumber & bits); static HNumber sgnext ( const HNumber & val, const HNumber & bits); static HNumber ashr( const HNumber & val, const HNumber & bits ); }; std::ostream & operator<<( std::ostream &, const HNumber & ); #endif speedcrunch-0.10.1/src/math/floatnum.c0000644000175000001440000011771011015364561017000 0ustar helderusers/* floatnum.c: Arbitrary precision floating point numbers, based on bc. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ /* a floating point engine based on bc's decimal fix point arithmetic. The speed is not overwhelming, but sufficient for calculators with limited demands. As bc's number.c is a portable engine, this should be portable as well. */ #include "floatnum.h" #include "floatlong.h" #include #include #include #define NOSPECIALVALUE 1 int maxdigits = MAXDIGITS; Error float_error; int expmax = EXPMAX; int expmin = EXPMIN; /* general helper routines */ static int _max(int x, int y) { return x > y? x : y; } static int _min(int x, int y) { return x < y? x : y; } /* the return value points to the first character different from accept. */ const char* _memskip( const char* buf, const char* end, char accept) { for(--buf; ++buf != end && *buf == accept;); return buf; } /* scans a value in a bc-num (or part of it) for the first occurence of a digit *different* from . The scan is limited to bytes. Returns the offset of the matching byte, or , if none was found */ static int _scan_digit( const char*p, int count, char digit) { const char* ps; ps = p; for (; count-- > 0 && *p == digit; ++p); return p - ps; } /* bc_num primitives */ #define _scaleof(f) (f->significand->n_scale) #define _lenof(f) (f->significand->n_len) #define _valueof(f) (f->significand->n_value) #define _digit(f, offset) (*(_valueof(f) + offset)) #define _setscale(f, value) (_scaleof(f) = value) /* converts floatnum's sign encodings (+1, -1) to bc_num sign encoding (PLUS, MINUS) */ static void _setsign( floatnum f, signed char value) { f->significand->n_sign = value < 0? MINUS : PLUS; #ifdef FLOATDEBUG f->value[0] = value < 0? '-' : '+'; #endif } /* modifies a bc_num significand such that the last (existing) digits of its value are not visible to bc_num operations any more. A negative reverts this operation (unhide). pre: <= n_scale*/ static void _hidelast( floatnum f, int count) { f->significand->n_scale -= count; } /* modifies a bc_num significand such that the first (existing) digits of its value are not visible to bc_num operations any more. A negative reverts this operation (unhide). pre: <= n_scale*/ static void _hidefirst( floatnum f, int count) { f->significand->n_value += count; f->significand->n_scale -= count; } /* Usually, significands are normalized, which means they fulfill 1 <= x < 10. This operation moves the decimal point places to the right, effectively multiplying the significand by a power of 10. A negative reverts such an operation. pre: < n_scale */ static void _movepoint( floatnum f, int digits) { f->significand->n_len += digits; f->significand->n_scale -= digits; } /* floatstruct primitives */ /* a quick check for NaN and 0 */ static char _is_special( cfloatnum f) { return f->significand == NULL; } /* creates a shallow working copy of in , using b as a container for the significand. On return, is equal in value to . may then be modified freely in the course of an operation, without effecting source, *except* that the digits in *(dest->significand->n_value) have to be retained (or restored). must *never* be the destination of a float_xxx operation, in particiular, it must not be freed. Neither must b be modified (or freed) in a bc_num operation */ static void _copyfn( floatnum dest, cfloatnum source, bc_num b) { *dest = *source; if (!_is_special(source)) { *b = *(source->significand); b->n_ptr = 0; dest->significand = b; } } /* If you want to execute a bc_num operation to a limited scale, it is a waste of computation time to pass operands with a longer scale, because bc lets the operand's scale override your limit. This function hides superfluous digits from bc, returning the original scale for restoring purposes */ static int _limit_scale( floatnum f, int newscale) { int oldscale; oldscale = _scaleof(f); _setscale(f, _min(oldscale, newscale)); return oldscale; } /*============================ floatnum routines ===================*/ int float_getrange() { return expmax; } int float_getprecision() { return maxdigits; } int float_setrange( int maxexp) { int result; result = expmax; expmax = _max(_min(maxexp, MAXEXP), 1); expmin = -expmax - 1; return result; } int float_setprecision( int digits) { int result; result = maxdigits; maxdigits = _max(_min(digits, MAXDIGITS), 1); return result; } /* checking the limits on exponents */ char float_isvalidexp( int exp) { return exp >= expmin && exp <= expmax; } /* clears the error state as well */ Error float_geterror() { Error tmp; tmp = float_error; float_error = Success; return tmp; } /* the first error blocks all others as it may be the source of a cascade of dependent errors */ void float_seterror( Error code) { if (float_error == Success) float_error = code; } void floatnum_init() { bc_init_numbers(); float_geterror(); } void float_create( floatnum f) { f->significand = NULL; f->exponent = EXPNAN; #ifdef FLOATDEBUG memcpy(f->value, "NaN", 4); #endif } void float_setnan ( floatnum f) { bc_free_num(&(f->significand)); float_create(f); } char _setnan( floatnum result) { float_setnan(result); return FALSE; } char _seterror( floatnum result, Error code) { float_seterror(code); return _setnan(result); } void float_setzero ( floatnum f) { bc_free_num(&(f->significand)); f->exponent = EXPZERO; #ifdef FLOATDEBUG f->value[0] ='0'; f->value[1] = 0; #endif } char _setzero( floatnum result) { float_setzero(result); return TRUE; } char float_isnan( cfloatnum f) { return _is_special(f) && f->exponent != EXPZERO; } char float_iszero( cfloatnum f) { return _is_special(f) && f->exponent == EXPZERO; } int float_getlength( cfloatnum f) { return _is_special(f)? 0 : _scaleof(f) + 1; } char float_getdigit( cfloatnum f, int ofs) { if (ofs >= float_getlength(f) || ofs < 0) return 0; return _digit(f, ofs); } /* checks whether f is a NaN and sets the float_error variable accordingly. Used in parameter checks when float_xxx calls are executed. FALSE is returned if a NaN is encountered. */ char _checknan( cfloatnum f) { if (!float_isnan(f)) return TRUE; float_seterror(NoOperand); return FALSE; } /* checks whether is positive and sets the float_error variable accordingly. Used in parameter checks when float_xxx calls are executed. Some operations accept a special value like EXACT, that has to pass this check, even though its numerical encoding violates the boundaries. If a function does not accept a special value, use NOSPECIALVALUE as a parameter for . TRUE is returned if the check is passed. The check for the limit MAXDIGITS is not executed here, because some intermediate operations have to succeed on more than MAXDIGITS digits */ static char _checkdigits( int digits, int specialval) { if ((digits > 0 && digits <= maxdigits) || digits == specialval) return TRUE; float_seterror(InvalidPrecision); return FALSE; } /* backward-scans the significand in . Returns the number of digits equal to beginning with the +1-th digit of f->significand->n_value. */ static int _bscandigit( cfloatnum f, int scale, char digit) { char* p; char* ps; ps = _valueof(f); for (p = ps + scale + 1; p-- != ps && *p == digit;); return scale - (p - ps); } /* scans two significands for the first occurence of a pair of differnt digits. Returns the number of equal digits at the beginning */ static int _scan_equal( floatnum v1, floatnum v2) { int count, i; char* p1; char* p2; count = _min(_scaleof(v1), _scaleof(v2)); p1 = _valueof(v1); p2 = _valueof(v2); i = 0; for (; *(p1++) == *(p2++) && ++i <= count;); return i; } /* scans two significands until it finds a digit different from 0 in the first significand, or a digit different from 9 in the second operand. The scan is limited by compares and starts with the *second* digit in the significands. Returns the number of found (0,9) pairs. */ static int _scan_09pairs( floatnum f1, floatnum f2, int count) { char* p; char* p1; char* p2; p1 = _valueof(f1) + 1; p2 = _valueof(f2) + 1; p = p1; for (; count-- > 0 && *p1 == 0 && *(p2++) == 9; ++p1); return p1 - p; } signed char float_getsign( cfloatnum f) { if(_is_special(f)) return 0; return f->significand->n_sign == PLUS? 1 : -1; } void float_setsign( floatnum f, signed char s) { if (s == 1 || s == -1) { if(!_is_special(f)) _setsign(f, s); } else if (s != 0) float_setnan(f); } char float_neg( floatnum f) { float_setsign(f, -float_getsign(f)); return _checknan(f); } char float_abs( floatnum f) { if(float_getsign(f) == -1) float_neg(f); return _checknan(f); } signed char float_cmp( cfloatnum val1, cfloatnum val2) { signed char sgn1; if (!_checknan(val1) || !_checknan(val2)) return UNORDERED; sgn1 = float_getsign(val1); if (float_getsign(val2) != sgn1) { if (sgn1 != 0) return sgn1; return -float_getsign(val2); } if (val1->exponent > val2->exponent) return sgn1; if (val1->exponent < val2->exponent) return -sgn1; if (_is_special(val1)) return 0; return (bc_compare(val1->significand, val2->significand)); } /* normalizing process: hides leading zeros in a significand and corrects the exponent accordingly */ static void _corr_lead_zero( floatnum f) { int count; count = _scan_digit(_valueof(f), float_getlength(f), 0); _hidefirst(f, count); f->exponent-=count; } /* normalizing process: if the significand is > 10 in magnitude, this function corrects this */ static void _corr_overflow( floatnum f) { int shift; shift = _lenof(f) - 1; _movepoint(f, -shift); f->exponent += shift; } /* cuts off trailing zeros at the end of a significand */ static void _corr_trailing_zeros( floatnum f) { _hidelast(f, _bscandigit(f, _scaleof(f), 0)); } static char hexdigits[] = "0123456789ABCDEF"; int float_getsignificand( char* buf, int bufsz, cfloatnum f) { int idx, lg; if (bufsz <= 0) return 0; if (float_isnan(f)) { *buf = 'N'; return 1; } if (float_iszero(f)) { *buf = '0'; return 1; } idx = -1; lg = _min(bufsz, float_getlength(f)); for(; ++idx < lg;) *(buf++) = hexdigits[(int)float_getdigit(f, idx)]; return lg; } int float_getexponent( cfloatnum f) { if (_is_special(f)) return 0; return f->exponent; } int float_getscientific( char* buf, int bufsz, cfloatnum f) { char b[42]; /* supports exponents encoded in up to 128 bits */ int sgnlg, explg, mlg; /* handle special cases */ if(float_isnan(f)) { if (bufsz < 4) return -1; memcpy(buf, "NaN\0", 4); return 3; } if(float_iszero(f)) { if (bufsz < 2) return -1; *buf = '0'; *(buf+1) = '\0'; return 1; } /* set one byte aside for sign? */ sgnlg = 0; if(float_getsign(f) < 0) sgnlg = 1; /* convert the exponent */ sprintf(b, "%d", float_getexponent(f)); explg = strlen(b); /* 3 extra bytes for dot, exp char and terminating \0 */ bufsz -= explg + sgnlg + 3; /* rest is for significand */ if (bufsz <= 0) /* buffer too small */ return-1; if(sgnlg > 0) *(buf++) = '-'; /* get the digit sequence of the significand, trailing zeros cut off */ mlg = float_getsignificand(++buf, bufsz, f) - 1; /* move the first digit one byte to the front and fill the gap with a dot */ *(buf-1) = *buf; *(buf++) = '.'; /* append the exponent */ *(buf+mlg) = 'e'; memcpy(buf+mlg+1, b, explg); /* the trailing \0 */ *(buf+mlg+explg+1) = '\0'; return sgnlg + mlg + explg + 3; } #ifdef FLOATDEBUG void _setvalue_(floatnum f) { f->value[float_getsignificand(f->value+2, sizeof(f->value)-3, f)+2] = 0; f->value[1] = f->value[2]; f->value[2] = '.'; f->value[0] = float_getsign(f) < 0? '-' : '+'; } #endif int float_setsignificand( floatnum f, int* leadingzeros, const char* buf, int bufsz) { const char* p; const char* dot; const char* last; const char* b; char* bcp; int zeros; int lg; char c; float_setnan(f); if (bufsz == NULLTERMINATED) bufsz = strlen(buf); /* initialize the output parameters for all early out branches */ if (leadingzeros != NULL) *leadingzeros = 0; if (bufsz <= 0) return -1; dot = memchr(buf, '.', bufsz); /* do not accept more than 1 dots */ if (dot != NULL && memchr(dot + 1, '.', bufsz - (dot - buf)) != NULL) return -1; last = buf + bufsz; /* points behind the input buffer */ /* skip all leading zeros */ b = _memskip(buf, last, '0'); /* is the first non-zero character found a dot? */ if (b == dot) /* then skip all zeros following the dot */ b = _memskip(b+1, last, '0'); /* the 'leading zeros' */ zeros = b - buf - (dot == NULL || dot >= b? 0:1); /* only zeros found? */ if (b == last) { /* indicate no dot, no leading zeros, because this does not matter in case of zero */ if (bufsz > (dot == NULL? 0:1)) float_setzero(f); /* do not accept a dot without any zero */ return -1; } /* size of the rest buffer without leading zeros */ bufsz -= b - buf; /* does the rest buffer contain a dot? */ lg = dot >= b && dot - b < maxdigits? 1 : 0; /* points behind the last significant digit */ p = b + _min(maxdigits + lg, bufsz); /* digits, limited by MAXDIGITS */ lg = _min(maxdigits, bufsz - lg); /* reduce lg by the number of trailing zeros */ for (; *--p == '0'; --lg); if (*(p--) == '.') for (; *(p--) == '0'; --lg); /* get a bc_num of sufficient size */ f->significand = bc_new_num(1, lg - 1); if (f->significand == NULL) return -1; /* exponent is forced to 0 */ f->exponent = 0; /* copy lg digits into bc_num buffer, scan the rest for invalid characters */ bcp = _valueof(f); for(; --bufsz >= 0;) { c = *(b++); if (c != '.') /* ignore a dot */ { if (c < '0' || c > '9') { /* invalid character */ float_setnan(f); return -1; } if (--lg >= 0) *(bcp++) = c - '0'; } } if (leadingzeros != NULL) *leadingzeros = zeros; #ifdef FLOATDEBUG _setvalue_(f); #endif return dot == NULL? -1 : dot - buf; } void float_setexponent( floatnum f, int exponent) { if (!_is_special(f)) { if (!float_isvalidexp(exponent)) float_setnan(f); else f->exponent = exponent; } } void float_setscientific( floatnum f, const char* buf, int bufsz) { int exppos; int zeros; int dotpos; unsigned exp, ovfl; signed char expsign, msign; const char* expptr; const char* last; char c; float_setnan(f); if (bufsz == NULLTERMINATED) bufsz = strlen(buf); /* find the offset of the exponent character, or -1, if not found */ for(exppos = bufsz; --exppos >= 0;) if ((c = *(buf+exppos)) == 'E' || c == 'e') break; /* marks the end of the exponent string */ last = buf + bufsz; /* pre-set exponent to +0, which is the right value, if there is no exponent. */ exp = 0; expsign = 1; ovfl = 0; if (exppos >= 0) { /* points behind the exponent character */ expptr = buf + (exppos + 1); if (expptr == last) /* do not accept an exponent char without an integer */ return; /* get the exponent sign */ switch(*expptr) { case '-': expsign = -1; /* and fall through */ case '+': ++expptr; } if (expptr == last) /* do not accept a sign without a digit following */ return; /* encode the sequence of digits into an unsignedeger */ for (;expptr != last ;) { if (*expptr < '0' || *expptr > '9') /* invalid char encountered */ return; ovfl = 10; if (_longmul(&exp, &ovfl)) { ovfl = *(expptr++) - '0'; _longadd(&exp, &ovfl); } if (ovfl != 0 || exp > EXPMAX+1) { /* do not return immediately, because the significand can be zero */ ovfl = 1; break; } } /* move the last pointer to the exponent char.*/ last = buf + exppos; } /* last points behind the significand part. exp is at most -EXPMIN */ /* get the sign of the significand */ msign = 1; if (buf != last) switch(*buf) { case '-': msign = -1; /* fall through */ case '+': ++buf; } /* let setsignificand convert the sequence of digits into a significand. If a dot is found, its position is given in dotpos, -1 otherwise. zeros are the count of leading '0' digits before the first non_zero digit. */ dotpos = float_setsignificand(f, &zeros, buf, last-buf); if (_is_special(f)) /* setsignificand either found a zero or encountered invalid characters */ return; /* if we did not find a dot, we assume an integer, and put the dot after last digit */ if (dotpos == -1) dotpos = last - buf; /* leading zeros shift the dot to the left. dotpos is now the exponent that results from the position of the dot in the significand. */ dotpos -= zeros+1; /* combine the dot position with the explicit exponent */ if (ovfl != 0 || !_checkadd(&dotpos, expsign * (int)exp)) /* exponent overflow */ float_setnan(f); float_setexponent(f, dotpos); float_setsign(f, msign); } /* normalizes a significand such that 1 <= x < 10. If the exponent overflows during this operation this is notified. */ static char _normalize( floatnum f) { _corr_lead_zero(f); if (f->significand != NULL && _lenof(f) > 1) _corr_overflow(f); if (f->significand != NULL) _corr_trailing_zeros(f); if (f->significand != NULL && !float_isvalidexp(f->exponent)) { float_seterror(Underflow); if (f->exponent > 0) float_seterror(Overflow); float_setnan(f); } #ifdef FLOATDEBUG if (f->significand != NULL) _setvalue_(f); #endif return f->significand != NULL; } void float_setinteger(floatnum dest, int value) { char buf[BITS_IN_UNSIGNED/3 + 3]; sprintf(buf, "%d", value); float_setscientific(dest, buf, NULLTERMINATED); } void float_move( floatnum dest, floatnum source) { if (dest != source) { float_setnan(dest); *dest = *source; float_create(source); } } /* creates a copy of and assigns it to . The significand is guaranteed to have +1 digits. The significand is truncated, or padded with zeros to the right, to achieve the desired length. may assume the special value EXACT, in which case a true copy is generated. This function allows an in-place copy (dest == source). */ static void _scaled_clone( floatnum dest, cfloatnum source, int scale) { /* dest == source allowed! */ bc_num mant; unsigned exp; signed char sign; mant = NULL; if(scale == EXACT) scale = _scaleof(source); if (dest == source && scale <= _scaleof(source)) { _setscale(dest, scale); return; } mant = bc_new_num(1, scale); scale = _min(scale, _scaleof(source)); memcpy(mant->n_value, _valueof(source), scale+1); sign = float_getsign(source); exp = source->exponent; float_setnan(dest); dest->exponent = exp; dest->significand = mant; #ifdef FLOATDEBUG _setvalue_(dest); #endif float_setsign(dest, sign); } char float_copy( floatnum dest, cfloatnum source, int digits) { int scale, save; if (digits == EXACT) digits = _max(1, float_getlength(source)); if (!_checkdigits(digits, NOSPECIALVALUE)) return _seterror(dest, InvalidPrecision); if (_is_special(source)) { if (dest != source) float_free(dest); *dest = *source; } else { // invariant: source has to be restored, if it is != dest scale = _min(digits - 1, _scaleof(source)); save = _limit_scale((floatnum)source, scale); _corr_trailing_zeros((floatnum)source); _scaled_clone(dest, source, EXACT); if (dest != source) _setscale(source, save); } return TRUE; } /* rounding a value towards zero */ static void _trunc( floatnum dest, cfloatnum x, int scale) { scale -= _bscandigit(x, scale, 0); _scaled_clone(dest, x, scale); #ifdef FLOATDEBUG _setvalue_(dest); #endif } /* rounding a value towards infinity */ static char _roundup( floatnum dest, cfloatnum x, int scale) { scale -= _bscandigit(x, scale, 9); _scaled_clone(dest, x, _max(0, scale)); if (scale < 0) { *_valueof(dest) = 1; if (!float_isvalidexp(++dest->exponent)) return FALSE; } else { ++*(_valueof(dest) + scale); } #ifdef FLOATDEBUG _setvalue_(dest); #endif return TRUE; } char float_round( floatnum dest, cfloatnum src, int digits, roundmode mode) { int scalediff, scale; char digit; signed char sign, updown; if (mode > TOMINUSINFINITY) return _seterror(dest, InvalidParam); if (!_checkdigits(digits, NOSPECIALVALUE)) return _setnan(dest); if (float_isnan(src)) return _seterror(dest, NoOperand); updown = 0; scale = digits - 1; if (float_getlength(src) > digits) { sign = float_getsign(src); switch(mode) { case TONEAREST: scalediff = _scaleof(src) - scale; if (scalediff > 0) { digit = _digit(src, digits); if (digit < 5 || (digit == 5 && scalediff == 1 && (_digit(src, scale) & 1) == 0)) updown = -1; else updown = 1; } break; case TOZERO: updown = -1; break; case TOINFINITY: updown = 1; break; case TOPLUSINFINITY: updown = sign; break; case TOMINUSINFINITY: updown = -sign; break; } } switch (updown) { case 1: if (!_roundup(dest, src, scale)) return _seterror(dest, Overflow); break; case 0: float_copy(dest, src, digits); break; case -1: _trunc(dest, src, scale); break; } return TRUE; } char float_int( floatnum f) { if (!_checknan(f)) return FALSE; if (f->exponent < 0) float_setzero(f); else if (!float_iszero(f)) float_round(f, f, f->exponent+1, TOZERO); return TRUE; } char float_frac( floatnum f) { if (!_checknan(f) || float_iszero(f) || f->exponent < 0) return !float_isnan(f); if (_scaleof(f) <= f->exponent) float_setzero(f); else { int leadingzeros = 0; _hidefirst(f, f->exponent + 1); leadingzeros = _scan_digit(_valueof(f), float_getlength(f), 0); _hidefirst(f, leadingzeros); f->exponent = -leadingzeros - 1; #ifdef FLOATDEBUG _setvalue_(f); #endif } return TRUE; } /* the general purpose add/subtract routine that deals with the ordinary case. */ static char _addsub_normal( floatnum dest, floatnum summand1, floatnum summand2, int digits) { floatstruct tmp; int expdiff; int scale; int fulllength; int extradigit; /* the operands are ordered by their exponent */ expdiff = (unsigned)(summand1->exponent - summand2->exponent); /* the full length of the sum (without carry) */ fulllength = _max(expdiff + _scaleof(summand2), _scaleof(summand1)) + 1; extradigit = 0; if (digits == EXACT || digits > fulllength) digits = fulllength; else { if (float_getsign(summand1) + float_getsign(summand2) == 0) extradigit = 1; /* a true subtraction needs no space for a carry */ if (expdiff > digits + extradigit) /* second operand underflows due to exponent diff */ return float_copy(dest, summand1, digits+extradigit); } if (digits > maxdigits) return _seterror(dest, InvalidPrecision); /* we cannot add the operands directly because of possibly different exponents. So we assume the second operand "to be OK" and shift the decimal point of the first appropriately to the right. There is a cheap way to do this: increment len by expdiff and decrement scale by the same amount. But: Check the operand is long enough to do this. */ float_create(&tmp); if (_scaleof(summand1) < expdiff) { _scaled_clone(&tmp, summand1, expdiff); summand1 = &tmp; } scale = digits + extradigit - (int)expdiff - 1; _movepoint(summand1, expdiff); /* truncate overly long operands */ _limit_scale(summand1, scale); _limit_scale(summand2, scale); /* add */ dest->exponent = summand2->exponent; bc_add(summand1->significand, summand2->significand, &(dest->significand), scale); float_free(&tmp); return _normalize(dest); } static char _sub_checkborrow( floatnum dest, floatnum summand1, floatnum summand2, int digits) { /* the operands have opposite signs, the same exponent, but their first digit of the significand differ. The operands are ordered by this digit. */ int result; int borrow; int scale1, scale2; char save; char* v1; char* v2; /* Cancellation occurs, when the operands are of type p.000...yyy - q.999...xxx, p-q == 1, because a borrow propagates from the difference ..0yyy.. - ..9xxx.., leaving zeros in the first part. We check for this here. */ borrow = 0; if (_digit(summand1, 0) - _digit(summand2, 0) == 1) { scale1 = _scaleof(summand1); scale2 = _scaleof(summand2); if (scale1 == 0) /* the special case of a one-digit first operand p. - q.999..xxx */ borrow = _scan_digit(_valueof(summand2) + 1, scale2, 9); else if (scale2 > 0) /* count the 0 - 9 pairs after the first digit, the area where a borrow can propagate */ borrow = _scan_09pairs(summand1, summand2, _min(scale1, scale2)); /* In case of a one-digit second operand (p.yyy.. - q. == 1.yyy..), nothing is cancelled out. Borrow is already set to 0, and this is the correct value for this case, so nothing has to be done here */ if (borrow > 0) { /* we have cancellation here. We skip all digits, that cancel out due to a propagating borrow. These include the first digit and all following (0,9) digit pairs, except the last one. The last pair may be subject to cancellation or not, we do not care, because the following digit pair either yields a non-zero difference, or creates no borrow. Our standard adder is good enough to deal with such a limited cancelling effect. We will replace the last (0,9) digit pair with a (9,8) pair. This prevents the creation of a borrow, and yet, will yield the correct result */ /* hide all digits until the last found 0 - 9 pair */ summand2->exponent -= borrow; summand1->exponent -= borrow; /* in case of a one-digit significand, there is nothing to hide */ if (scale1 > 0) _hidefirst(summand1, borrow); _hidefirst(summand2, borrow); /* we replace the last found 0 - 9 pair by a 9 - 8 pair, avoiding a carry, yet yielding the correct result */ save = *(v1 = _valueof(summand1)); *v1 = 9; *(v2 = _valueof(summand2)) = 8; } } result = _addsub_normal(dest, summand1, summand2, digits); /* restore the modified digits */ if (borrow > 0) { if (summand1 != dest) *v1 = save; if (summand2 != dest) *v2 = 9; } return result; } static char _sub_expdiff0( floatnum dest, floatnum summand1, floatnum summand2, int digits) { int eq; int result; /* the operands are ordered by their significand length, and have the same exponent, and different sign */ /* One type of cancellation is when both significands set out with the same digits. Since these digits cancel out during subtraction, we look out for the first pair of different digits. eq receives the number of equal digits, which may be 0 */ eq = _scan_equal(summand1, summand2); if (float_getlength(summand2) == eq) { /* the complete second operand is cancelled out */ if (float_getlength(summand1) == eq) /* op1 == -op2 */ return _setzero(dest); /* If xxx.. denotes the second operand, the (longer) first one is of form xxx..yyy.., since it has the same digits in the beginning. During subtraction the xxx... part is cancelled out, and this leaves yyy... as the subtraction result. By copying the yyy... to the result, we can shortcut the subtraction. But before doing so, we have to check yyy... for leading zeros, because the cancellation continues in this case. */ eq += _scan_digit(_valueof(summand1) + eq, float_getlength(summand1) - eq, 0); _hidefirst(summand1, eq); result = float_copy(dest, summand1, digits); dest->exponent -= eq; return result != 0 && _normalize(dest); } /* hide the identical digits, and do the subtraction without them. */ summand1->exponent -= eq; summand2->exponent -= eq; _hidefirst(summand1, eq); _hidefirst(summand2, eq); /* order the operands by their first digit */ if (_digit(summand1, 0) >= _digit(summand2, 0)) return _sub_checkborrow(dest, summand1, summand2, digits); return _sub_checkborrow(dest, summand2, summand1, digits); } static char _sub_expdiff1( floatnum dest, floatnum summand1, floatnum summand2, int digits) { /* Cancellation occurs when subtracting 0.9xxx from 1.0yyy */ int result; char singledigit; char* v1; char* v2; /* the operands have different sign, are ordered by their exponent, and the difference of the exponents is 1 */ /* 1.0yyy may be given as a single digit 1 or as a string of digits starting with 1.0 */ singledigit = _scaleof(summand1) == 0; if (_digit(summand1, 0) != 1 || _digit(summand2, 0) != 9 || (!singledigit && _digit(summand1, 1) != 0)) return _addsub_normal(dest, summand1, summand2, digits); /* we have cancellation here. We transform this case into that of equal exponents. */ /* we align both operands by hiding the first digit (1) of the greater operand. This leaves .0yyy which matches the second operand .9xxx. Unfortunately, if the first operand has only one digit, we cannot hide it, so we have to work around this then. */ if (!singledigit) _hidefirst(summand1, 1); /* we change the leading digits into a '9' and a '8' resp. So we finally subtract .8xxx from .9yyy, yielding the correct result. */ v1 = _valueof(summand1); v2 = _valueof(summand2); *v1 = 9; *v2 = 8; summand1->exponent--; result = _sub_checkborrow(dest, summand1, summand2, digits); /* restore the original digits */ if (summand1 != dest) *v1 = singledigit? 1 : 0; if (summand2 != dest) *v2 = 9; return result; } static char _sub_ordered( floatnum dest, floatnum summand1, floatnum summand2, int digits) { /* we have to check for cancellation when subtracting. Cancellation occurs when the operands are almost equal in magnitude. E.g. in 1.234 - 1.226 = 0.008, the result is on quite a different scale than the operands. Actually, this is a big problem, because it means that the (true) subtraction is numerically not stable. There is no way to get around this; you always have to take this into account, when subtracting. We make the best out of it, and check for cancellation in advance, so the result is at least valid to all digits, if the operands are known to be exact. Cancellation occurs only, if the difference between the exponents is 1 at most. We prepare the critical cases in specialized routines, and let the standard routine do the rest. */ /* the operands are ordered by their exponent */ unsigned expdiff; expdiff = (unsigned)(summand1->exponent - summand2->exponent); switch (expdiff) { case 0: /* order the operands by their length of the significands */ if (float_getlength(summand1) >= float_getlength(summand2)) return _sub_expdiff0(dest, summand1, summand2, digits); return _sub_expdiff0(dest, summand2, summand1, digits); case 1: return _sub_expdiff1(dest, summand1, summand2, digits); } return _addsub_normal(dest, summand1, summand2, digits); } static char _addsub_ordered( floatnum dest, floatnum summand1, floatnum summand2, int digits) { /* operands are ordered by their exponent */ /* handle a bunch of special cases */ if (!_checkdigits(digits, EXACT) || !_checknan(summand1)) return _setnan(dest); if (float_iszero(summand2)) return float_copy(dest, summand1, digits); /* separate true addition from true subtraction */ if (float_getsign(summand1) == float_getsign(summand2)) return _addsub_normal(dest, summand1, summand2, digits); return _sub_ordered(dest, summand1, summand2, digits); } char float_add( floatnum dest, cfloatnum summand1, cfloatnum summand2, int digits) { bc_struct bc1, bc2; floatstruct tmp1, tmp2; floatnum s1, s2; /* the adder may occasionally adjust operands to his needs. Hence we work on temporary structures */ s1 = dest; s2 = dest; if (dest != summand1) { _copyfn(&tmp1, summand1, &bc1); s1 = &tmp1; } if (dest != summand2) { _copyfn(&tmp2, summand2, &bc2); s2 = &tmp2; } /* order the operands by their exponent. This should bring a NaN always to the front, and keeps zeros after any other number. */ if (s1->exponent >= s2->exponent) return _addsub_ordered(dest, s1, s2, digits); return _addsub_ordered(dest, s2, s1, digits); } char float_sub( floatnum dest, cfloatnum minuend, cfloatnum subtrahend, int scale) { int result; if (minuend == subtrahend) { /* changing the sign of one operand would change that of the other as well. So this is a special case */ if(!_checknan(minuend)) return FALSE; _setzero(dest); } /* do not use float_neg, because it may change float_error */ float_setsign((floatnum)subtrahend, -float_getsign(subtrahend)); result = float_add(dest, minuend, subtrahend, scale); if (dest != subtrahend) float_setsign((floatnum)subtrahend, -float_getsign(subtrahend)); return result; } char float_mul( floatnum dest, cfloatnum factor1, cfloatnum factor2, int digits) { int result; int fullscale; int savescale1, savescale2; int scale; /* handle a bunch of special cases */ if (!_checkdigits(digits, EXACT) || !_checknan(factor1) || !_checknan(factor2)) /* invalid scale value or NaN operand */ return _setnan(dest); if (float_iszero(factor1) || float_iszero(factor2)) return _setzero(dest); scale = digits - 1; fullscale = _scaleof(factor1) + _scaleof(factor2); if (digits == EXACT || scale > fullscale) scale = fullscale; if (scale >= maxdigits) /* scale too large */ return _seterror(dest, InvalidPrecision); /* limit the scale of the operands to sane sizes */ savescale1 = _limit_scale((floatnum)factor1, scale); savescale2 = _limit_scale((floatnum)factor2, scale); /* multiply */ dest->exponent = factor1->exponent + factor2->exponent; bc_multiply(factor1->significand, factor2->significand, &(dest->significand), scale); result = _normalize(dest); /* reverse order is necessary in case factor1 == factor2 */ if (dest != factor2) _setscale(factor2, savescale2); if (dest != factor1) _setscale(factor1, savescale1); return result; } char float_div( floatnum dest, cfloatnum dividend, cfloatnum divisor, int digits) { int result; int savescale1, savescale2; int exp; /* handle a bunch of special cases */ if (!_checkdigits(digits, INTQUOT) || !_checknan(dividend) || !_checknan(divisor)) return _setnan(dest); if (float_iszero(divisor)) return _seterror(dest, ZeroDivide); if (float_iszero(dividend)) /* 0/x == 0 */ return _setzero(dest); exp = dividend->exponent - divisor->exponent; /* check for integer quotient */ if(digits == INTQUOT) { if (exp < 0) return _setzero(dest); digits = exp; } /* scale OK? */ if(digits > maxdigits) return _seterror(dest, InvalidPrecision); /* limit the scale of the operands to sane sizes */ savescale1 = _limit_scale((floatnum)dividend, digits); savescale2 = _limit_scale((floatnum)divisor, digits); /* divide */ result = TRUE; dest->exponent = exp; bc_divide(dividend->significand, divisor->significand, &(dest->significand), digits); if (bc_is_zero(dest->significand)) float_setzero(dest); else result = _normalize(dest); /* reverse order is necessary in case divisor == dividend */ if (dest != divisor) _setscale(divisor, savescale2); if (dest != dividend) _setscale(dividend, savescale1); return result; } char float_divmod( floatnum quotient, floatnum remainder, cfloatnum dividend, cfloatnum divisor, int digits) { int exp, exp1; if (!_checkdigits(digits, INTQUOT) || !_checknan(dividend) || !_checknan(divisor) || quotient == remainder || float_iszero(divisor) || float_getlength(divisor) > maxdigits) { if (quotient == remainder) float_seterror(InvalidParam); if (float_getlength(divisor) > maxdigits) float_seterror(TooExpensive); if (float_iszero(divisor)) float_seterror(ZeroDivide); float_setnan(quotient); return _setnan(remainder); } if (float_iszero(dividend)) { float_setzero(quotient); return _setzero(remainder); } exp1 = dividend->exponent; exp = exp1 - divisor->exponent; if(digits-- == INTQUOT) { if (exp < 0) { if (float_copy(remainder, dividend, EXACT)) return _setzero(quotient); return _setnan(quotient); } digits = exp; } if (digits > maxdigits) { float_setnan(quotient); return _seterror(remainder, TooExpensive); } /* divide */ quotient->exponent = exp; remainder->exponent = exp1; bc_divmod(dividend->significand, divisor->significand, &(quotient->significand), &(remainder->significand), digits); /* if something goes wrong (one of the results overflows or underflows), always set both quotient and remainder to NaN */ if (bc_is_zero(remainder->significand)) float_setzero(remainder); else if (!_normalize(remainder)) return _setnan(quotient); if (bc_is_zero(quotient->significand)) float_setzero(quotient); else if (!_normalize(quotient)) return _setnan(remainder); return TRUE; } char float_sqrt(floatnum value, int digits) { if (!_checkdigits(digits, NOSPECIALVALUE) || !_checknan(value)) return _setnan(value); switch (float_getsign(value)) { case -1: return _seterror(value, OutOfDomain); case 0: return TRUE; } if ((value->exponent & 1) != 0) { if (float_getlength(value) == 1) _scaled_clone(value, value, 1); _movepoint(value, 1); } bc_sqrt(&value->significand, digits - 1); #ifdef FLOATDEBUG _setvalue_(value); #endif if (value->exponent >= 0) value->exponent >>= 1; else value->exponent = -((1-value->exponent) >> 1); return TRUE; } speedcrunch-0.10.1/src/math/floatcommon.h0000644000175000001440000000750711015364561017500 0ustar helderusers/* floatcommon.h: header file for convenience functions, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATCOMMON_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif /* helper, checks parameters. Sets float_error to NaNOperand or InvalidPrecision and sets to NaN, if the parameters do not meet the requirements of routines for higher mathematical functions, and returns 0 in this case */ char chckmathparam(floatnum x, int digits); /* helper, determines, how many decimal digits the exponent of has. If the exponent is 0, -1 is returned */ int logexp(cfloatnum x); /* helper, returns the first decimal digits and the sign of a significand, encoded in an integer. */ int leadingdigits(cfloatnum x, int digits); /* convenience wrapper for float_setscientific, setting the last parameter to NULLTERMINATED */ void float_setasciiz(floatnum x, const char* asciiz); /* convenience wrapper for float_add, adds a signed integer to and places the result in */ char float_addi(floatnum sum, cfloatnum summand1, int summand2, int digits); /* convenience wrapper for float_mul, multiplies a signed integer with and places the result in */ char float_muli(floatnum product, cfloatnum factor1, int factor2, int digits); /* convenience wrapper for float_div, divides by a signed integer and places the result in */ char float_divi(floatnum quotient, cfloatnum dividend, int divisor, int digits); /* convenience wrapper for float_cmp: compares the absolute value of both operands */ int float_abscmp(floatnum x, floatnum y); /* convenience wrapper for float_div, returns 1/ */ char float_reciprocal(floatnum x, int digits); /* compares two numbers in a normal fashion, but returns equal, if their relative difference is less than 1e-, i.e. |(x-y)/max(x,y)| < 1e- */ int float_relcmp(floatnum x, floatnum y, int digits); /* returns whether x is an integer */ char float_isinteger(cfloatnum x); /* returns the integer part of x as integer. If x exceeds the integer range, 0 is returned */ int float_asinteger(cfloatnum x); /* rounds x in TONEAREST mode. If x overflows, the rounding is reverted. Does not report errors */ void float_checkedround(floatnum x, int digits); /* a fast way to multiply with a power of ten, does not set float_error on overflow or NaN, returns silently NaN instead*/ void float_addexp(floatnum x, int smd); /* returns 0, if the integer part of x is even */ char float_isodd(floatnum x); /* an extension of float_int: you can choose the round mode errors: FLOAT_NANOPERAND FLOAT_OVERFLOW (if EXP_MAX is really small) */ char float_roundtoint(floatnum x, roundmode mode); #ifdef __cplusplus } #endif #endif /* _FLOATCOMMON_H */ speedcrunch-0.10.1/src/math/floatpower.h0000644000175000001440000000247411015364561017342 0ustar helderusers/* floatpower.h: power operation, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef _FLOATPOWER_H # define _FLOATPOWER_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif char _raise(floatnum x, cfloatnum exponent, int digits); #ifdef __cplusplus } #endif #endif /* _FLOATPOWER_H */ speedcrunch-0.10.1/src/math/floatio.h0000644000175000001440000001337611015364561016620 0ustar helderusers/* floatio.h: low level conversion, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include #ifndef _FLOATIO_H # define _FLOATIO_H #define NO_DIGIT 0x7F #define IO_BASE_ZERO 1 #define IO_BASE_NAN 0 #define IO_BASE_DEFAULT (-1) #define IO_SIGN_PLUS 1 #define IO_SIGN_NONE 0 #define IO_SIGN_MINUS (-1) #define IO_SIGN_COMPLEMENT (-2) #define IO_FLAG_SUPPRESS_PLUS 0x001 #define IO_FLAG_SUPPRESS_BASETAG 0x002 #define IO_FLAG_SUPPRESS_CMPL 0x004 #define IO_FLAG_SUPPRESS_LDG_ZERO 0x008 #define IO_FLAG_SUPPRESS_TRL_ZERO 0x010 #define IO_FLAG_SUPPRESS_DOT 0x020 #define IO_FLAG_SUPPRESS_EXPPLUS 0x040 #define IO_FLAG_SUPPRESS_EXPBASE 0x080 #define IO_FLAG_SUPPRESS_EXPZERO 0x100 #define IO_FLAG_SHOW_BASE 0x200 #define IO_FLAG_SHOW_EXPBASE 0x400 #ifdef __cplusplus extern "C"{ #endif typedef struct{ int sz; char* buf; }t_buffer; typedef t_buffer* p_buffer; /* t_seq_desc describes the format of a sequence of digits. leadingSignDigits are the count of leading zeros (or for two's complement, F's, 7's or 1's), trailing0 are the number of zeros at the end of the sequence and digits are the total count of digits in the sequence. If a sequence contains only zeros, in some contexts, they are counted as sign digits, in others they are trailing zeros. base is the number base the sequence is coded in (one of 2, 8, 10 or 16) and is reserved for callback. */ typedef struct{ int leadingSignDigits; int trailing0; int digits; int base; void* param; } t_seq_desc; typedef t_seq_desc* p_seq_desc; /* the number of digits not being a leading sign digit or a trailing zero */ int _significantdigits(p_seq_desc n); /* sequences of digits can be encoded in various ways (ASCII, bc_num style, packed and so on). In order to access a single digit, a getter has to be supplied for each encoding. This is the common interface of these getters. ofs is the index of the digit in the sequence, the first (most significant) having an index 0. The getter should return a sign digit (mostly 0) for negative indices and 0 for indices greator or equal to the length of the sequence. Instances of t_getdigit usually access the param field of n to find the data structure where the digits are encoded in */ typedef char (*t_getdigit)(int ofs, p_seq_desc param); /* list of tokens that are created in an output process. Instead of returning a single ASCII string, all parts of a number are kept in separate places, so a post-processor can reorder or beautify them */ typedef struct{ signed char sign; signed char base; t_buffer intpart; t_buffer fracpart; int exp; } t_otokens; typedef t_otokens* p_otokens; /* list of tokens that are sources in an input process. Instead of using a single ASCII string, all parts of a number are kept in separate places, stripped off all grammar related information. The tokens need not be 0 terminated, as long as the token is delimited by something not mistaken as a part of it. */ typedef struct{ signed char sign; signed char base; const char* intpart; const char* fracpart; signed char expsign; unsigned exp; unsigned maxdigits; } t_itokens; typedef t_itokens* p_itokens; typedef struct{ t_seq_desc seq; t_getdigit getdigit; } t_ext_seq_desc; typedef t_ext_seq_desc* p_ext_seq_desc; typedef struct{ signed char sign; signed char base; } t_prefix; typedef t_prefix* p_prefix; typedef struct{ t_prefix prefix; t_ext_seq_desc intpart; t_ext_seq_desc fracpart; int exp; } t_number_desc; typedef t_number_desc* p_number_desc; void _clearnumber(p_number_desc n); Error str2desc(p_number_desc n, p_itokens tokens); Error desc2str(p_otokens tokens, p_number_desc n, int scale); Error exp2str(p_buffer dest, int exp, char base); /*------------ additional stuff ------------------*/ /* t_ioparams is a data structure that contains all necessary information to convert an ASCII character encoded number into a t_token and vice versa. Most information is grammar related like dot, basetag and so on. Others like maxdigits describe general limits of floatnums. */ typedef struct{ signed char base; signed char expbase; char dot; char* basetag; char* expbegin; char* expend; char* cmpltag; unsigned maxdigits; } t_ioparams; typedef t_ioparams* p_ioparams; const char* basePrefix(char base); Error parse(p_itokens tokens, const char** buf); int cattokens(char* buf, int bufsz, p_otokens tokens, signed char expbase, unsigned flags); void float_stdconvert(); char setioparams(p_ioparams params); char delioparams(signed char base); p_ioparams getioparams(signed char base); signed char setdefaultbase(signed char base); #ifdef __cplusplus } #endif #endif /* _FLOATIO_H */ speedcrunch-0.10.1/src/math/floatgamma.c0000644000175000001440000002362511015364561017264 0ustar helderusers/* floatgamma.c: Gamma function, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatconfig.h" #include "floatgamma.h" #include "floatconst.h" #include "floatcommon.h" #include "floatlog.h" #include "floatexp.h" #include "floattrig.h" #include "floatseries.h" /* returns the number of summands needed in the asymptotic series to guarantee precision. Each extra summand yields roughly extra 1.8 digits. This is derived under the assumption, that the costs of an extra factor in the rising pochhammer symbol are about the same than those of an extra summand in the series */ static int _findorder( int digits) { return (5*digits + 5)/9; } /* returns how big x has to be to let the asymptotic series converge to at least precision. Derived from an estimation of the Bernouilli number inserted in the formula of a summand. */ static int _minx( int digits) { return (4657*_findorder(digits)-2750)/5000; } /* returns how much x has to be increased to let the asymptotic series converge to places */ static int _ofs( floatnum x, int digits) { int result; if (float_getexponent(x) >= 8) return 0; result = _minx(digits) - float_asinteger(x); return result <= 0? 0 : result; } /* evaluates the rising pochhammer symbol x*(x+1)*...*(x+n-1) (n >= 0) by multiplying. This can be expensive when n is large, so better restrict n to something sane like n <= 100. su stands for "small" and "unsigned" n */ static char _pochhammer_su( floatnum x, int n, int digits) { floatstruct factor; char result; /* the rising pochhammer symbol is computed recursively, observing that pochhammer(x, n) == pochhammer(x, p) * pochhammer(x+p, n-p). p is choosen as floor(n/2), so both factors are somehow "balanced". This pays off, if x has just a few digits, since only some late multiplications are full scale then and Karatsuba boosting yields best results, because both factors are always almost the same size. */ result = 1; switch (n) { case 0: float_copy(x, &c1, EXACT); case 1: break; default: float_create(&factor); float_addi(&factor, x, n >> 1, digits+2); result = _pochhammer_su(x, n >> 1, digits) && _pochhammer_su(&factor, n - (n >> 1), digits) && float_mul(x, x, &factor, digits+2); float_free(&factor); } return result; } /* evaluates ln(Gamma(x)) for all those x big enough to let the asymptotic series converge directly. Returns 0, if the result overflows relative error for a 100 gigit calculation < 5e-100 */ static char _lngammabigx( floatnum x, int digits) { floatstruct tmp1, tmp2; char result; result = 0; float_create(&tmp1); float_create(&tmp2); /* compute (ln x-1) * (x-0.5) - 0.5 + ln(sqrt(2*pi)) */ float_copy(&tmp2, x, digits+1); _ln(&tmp2, digits+1); float_sub(&tmp2, &tmp2, &c1, digits+2); float_sub(&tmp1, x, &c1Div2, digits+2); if (float_mul(&tmp1, &tmp1, &tmp2, digits+2)) { /* no overflow */ lngammaasymptotic(x, digits); float_add(x, &tmp1, x, digits+3); float_add(x, x, &cLnSqrt2PiMinusHalf, digits+3); result = 1; } float_free(&tmp2); float_free(&tmp1); return result; } static char _lngamma_prim_xgt0( floatnum x, floatnum revfactor, int digits) { int ofs; ofs = _ofs(x, digits); float_copy(revfactor, x, digits+1); _pochhammer_su(revfactor, ofs, digits); float_addi(x, x, ofs, digits+2); return _lngammabigx(x, digits); } static char _lngamma_prim( floatnum x, floatnum revfactor, int* infinity, int digits) { floatstruct tmp; char result; char odd; *infinity = 0; if (float_getsign(x) > 0) return _lngamma_prim_xgt0(x, revfactor, digits); float_copy(revfactor, x, digits + 2); float_sub(x, &c1, x, digits+2); float_create(&tmp); result = _lngamma_prim_xgt0(x, &tmp, digits); if (result) { float_neg(x); odd = float_isodd(revfactor); _sinpix(revfactor, digits); if (float_iszero(revfactor)) { *infinity = 1; float_setinteger(revfactor, odd? -1 : 1); } else float_mul(&tmp, &tmp, &cPi, digits+2); float_div(revfactor, revfactor, &tmp, digits+2); } float_free(&tmp); return result; } char _lngamma( floatnum x, int digits) { floatstruct factor; int infinity; char result; if (float_cmp(x, &c1) == 0 || float_cmp(x, &c2) == 0) return _setzero(x); float_create(&factor); result = _lngamma_prim(x, &factor, &infinity, digits) && infinity == 0; if (result) { float_abs(&factor); _ln(&factor, digits + 1); result = float_sub(x, x, &factor, digits+1); } float_free(&factor); if (infinity != 0) return _seterror(x, ZeroDivide); if (!result) float_setnan(x); return result; } char _gammagtminus20( floatnum x, int digits) { floatstruct factor; int ofs; char result; float_create(&factor); ofs = _ofs(x, digits+1); float_copy(&factor, x, digits+1); _pochhammer_su(&factor, ofs, digits); float_addi(x, x, ofs, digits+2); result = _lngammabigx(x, digits) && _exp(x, digits) && float_div(x, x, &factor, digits+1); float_free(&factor); if (!result) float_setnan(x); return result; } char _gamma( floatnum x, int digits) { floatstruct tmp; int infinity; char result; if (float_cmp(&cMinus20, x) > 0) { float_create(&tmp); result = _lngamma_prim(x, &tmp, &infinity, digits) && infinity == 0 && _exp(x, digits) && float_div(x, x, &tmp, digits + 1); float_free(&tmp); if (infinity != 0) return _seterror(x, ZeroDivide); if (!result) float_setnan(x); return result; } return _gammagtminus20(x, digits); } char _gammaint( floatnum integer, int digits) { int ofs; if (float_getexponent(integer) >=2) return _gammagtminus20(integer, digits); ofs = float_asinteger(integer); float_copy(integer, &c1, EXACT); return _pochhammer_su(integer, ofs-1, digits); } char _gamma0_5( floatnum x, int digits) { floatstruct tmp; int ofs; if (float_getexponent(x) >= 2) return _gamma(x, digits); float_create(&tmp); float_sub(&tmp, x, &c1Div2, EXACT); ofs = float_asinteger(&tmp); float_free(&tmp); if (ofs >= 0) { float_copy(x, &c1Div2, EXACT); if(!_pochhammer_su(x, ofs, digits)) return 0; return float_mul(x, x, &cSqrtPi, digits); } if(!_pochhammer_su(x, -ofs, digits)) return 0; return float_div(x, &cSqrtPi, x, digits); } static char _pochhammer_si( floatnum x, int n, int digits) { /* this extends the rising Pochhammer symbol to negative integer offsets following the formula pochhammer(x,n-1) = pochhammer(x,n)/(x-n+1) */ if (n >= 0) return _pochhammer_su(x, n, digits); return float_addi(x, x, n, digits) && _pochhammer_su(x, -n, digits) && float_reciprocal(x, digits); } static char _pochhammer_g( floatnum x, cfloatnum n, int digits) { /* this generalizes the rising Pochhammer symbol using the formula pochhammer(x,n) = Gamma(x+1)/Gamma(x-n+1) */ floatstruct tmp, factor1, factor2; int inf1, inf2; char result; float_create(&tmp); float_create(&factor1); float_create(&factor2); inf2 = 0; float_add(&tmp, x, n, digits+1); result = _lngamma_prim(x, &factor1, &inf1, digits) && _lngamma_prim(&tmp, &factor2, &inf2, digits) && (inf2 -= inf1) <= 0; if (inf2 > 0) float_seterror(ZeroDivide); if (result && inf2 < 0) float_setzero(x); if (result && inf2 == 0) result = float_div(&factor1, &factor1, &factor2, digits+1) && float_sub(x, &tmp, x, digits+1) && _exp(x, digits) && float_mul(x, x, &factor1, digits+1); float_free(&tmp); float_free(&factor2); float_free(&factor1); if (!result) float_setnan(x); return result; } static char _pochhammer_i( floatnum x, cfloatnum n, int digits) { /* do not use the expensive Gamma function when a few multiplications do the same */ /* pre: n is an integer */ int ni; signed char result; if (float_iszero(n)) return float_copy(x, &c1, EXACT); if (float_isinteger(x)) { result = -1; float_neg((floatnum)n); if (float_getsign(x) <= 0 && float_cmp(x, n) > 0) /* x and x+n have opposite signs, meaning 0 is among the factors */ result = _setzero(x); else if (float_getsign(x) > 0 && float_cmp(x, n) <= 0) /* x and x+n have opposite signs, meaning at one point you have to divide by 0 */ result = _seterror(x, ZeroDivide); float_neg((floatnum)n); if (result >= 0) return result; } if (float_getexponent(x) < EXPMAX/100) { ni = float_asinteger(n); if (ni != 0 && ni < 50 && ni > -50) return _pochhammer_si(x, ni, digits+2); } return _pochhammer_g(x, n, digits); } char _pochhammer( floatnum x, cfloatnum n, int digits) { if (float_isinteger(n)) return _pochhammer_i(x, n, digits); return _pochhammer_g(x, n, digits); } speedcrunch-0.10.1/src/math/floatlog.c0000644000175000001440000003042611015364561016760 0ustar helderusers/* floatlog.c: logarithm and friends, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatlog.h" #include "floatconst.h" #include "floatcommon.h" #include "floatseries.h" typedef struct { char c2; char c3; char c5; char c7; char c10; } _lincomb; static _lincomb _lincombtbl[] = { {0,3,3,2,5},{12,4,0,2,7},{4,0,0,0,1},{0,2,2,1,3},{13,3,0,1,6}, /* -.40 */ {7,5,0,2,6},{10,1,0,2,5},{4,3,0,3,5},{1,6,0,0,3},{4,2,0,0,2}, /* -.35 */ {0,4,2,1,4},{1,0,0,1,1},{0,9,0,1,5},{3,5,0,1,4},{6,1,0,1,3}, /* -.30 */ {0,3,0,2,3},{8,6,0,1,6},{11,2,0,1,5},{0,6,2,1,5},{22,1,0,0,7}, /* -.25 */ {9,5,0,0,5},{0,0,2,2,3},{0,5,1,0,3},{2,1,0,0,1},{0,3,4,1,5}, /* -.20 */ {0,1,8,0,6},{0,3,3,3,6},{5,6,0,2,6},{8,2,0,2,5},{0,13,0,1,7}, /* -.15 */ {12,3,0,0,5},{0,7,1,0,4},{0,2,1,4,5},{0,7,0,2,5},{3,3,0,2,4}, /* -.10 */ {20,0,0,0,6},{7,4,0,0,4},{10,0,0,0,3},{8,4,0,2,6},{0,0,0,0,0}, /* -.05 */ {0,0,0,0,0},{0,9,1,0,5},{13,5,0,2,8},{9,3,0,1,5},{0,7,4,1,7}, /* 0.00 */ {10,3,0,3,7},{0,1,5,0,4},{0,12,2,1,8},{10,2,0,0,4},{8,6,0,2,7},/* 0.05 */ {8,1,0,6,8},{7,0,0,1,3},{5,4,0,3,6},{22,1,0,1,8},{2,7,0,0,4}, /* 0.10 */ {2,2,0,4,5},{0,0,2,3,4},{0,5,1,1,4},{0,3,5,0,5},{14,6,0,1,8}, /* 0.15 */ {10,4,0,0,5},{3,1,0,3,4},{4,6,0,1,5},{0,4,0,0,2},{14,0,0,2,6}, /* 0.20 */ {0,13,1,0,7},{8,2,0,3,6},{4,0,0,2,3},{2,4,0,4,6},{0,2,2,3,5}, /* 0.25 */ {0,0,6,2,6},{0,5,5,0,6},{23,2,0,0,8},{0,1,2,0,2},{17,4,0,1,8}, /* 0.30 */ {0,10,3,0,7},{11,6,0,2,8},{4,3,0,5,7},{14,2,0,2,7},{10,0,0,1,4},/* 0.35 */ {8,4,0,3,7},{1,1,0,6,6},{11,0,0,3,6},{12,5,0,1,7},{2,1,0,8,8}, /* 0.40 */ {15,1,0,1,6},{0,7,5,0,7},{6,2,0,6,8},{2,0,0,5,5},{1,14,0,1,8}, /* 0.45 */ {0,12,3,0,8},{20,2,0,1,8},{0,8,0,0,4},{14,4,0,2,8},{3,4,0,0,3},/* 0.50 */ {0,1,4,3,6},{6,0,0,0,2},{4,4,0,2,5},{0,2,0,1,2},{8,0,1,2,5}, /* 0.55 */ {8,5,0,0,5},{15,3,0,1,7},{0,9,5,0,8},{0,0,3,2,4},{0,5,2,0,4}, /* 0.60 */ {5,3,0,1,4},{0,0,2,4,5},{13,6,0,0,7},{3,2,0,7,8},{16,2,0,0,6}, /* 0.65 */ {0,1,9,0,7},{3,6,0,0,4},{10,4,0,1,6},{0,0,0,8,7},{13,0,0,1,5}, /* 0.70 */ {0,6,7,0,8},{0,4,0,1,3},{0,2,4,0,4},{3,0,0,1,2},{15,5,0,1,8}, /* 0.75 */ {8,2,0,4,7},{2,9,0,1,6},{4,0,0,3,4},{2,4,0,5,7},{12,3,0,2,7}, /* 0.80 */ {1,3,0,0,2},{0,0,6,3,7},{6,5,0,3,7},{16,4,0,0,7},{0,3,9,0,8}, /* 0.85 */ {0,1,2,1,3},{10,6,0,1,7},{0,2,0,8,8},{0,10,3,1,8},{0,1,1,3,4}, /* 0.90 */ {9,0,0,0,3},{4,3,0,6,8},{0,4,4,0,5},{8,9,0,0,7},{10,0,0,2,5} /* 0.95 */ }; /* artanh x and ln(x+1) are closely related. Evaluate the logarithm using the artanh series, which converges twice as fast as the logarithm series. With 100 digits, if -0.0198 <= x <= 0.02, the relative error is less than 5.0e-100, or at most 1 unit in the 100th place */ void _lnxplus1near0( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); float_add(&tmp, &c2, x, digits); float_div(x, x, &tmp, digits); artanhnear0(x, digits); float_add(x, x, x, EXACT); float_free(&tmp); } /* helpers */ static void _addcoef( floatnum x, int coef, floatnum cnst, int digits) { floatstruct tmp; if (coef != 0) { float_create(&tmp); float_muli(&tmp, cnst, coef, digits); float_add(x, x, &tmp, digits); float_free(&tmp); } } static int _factor( int idx) { int factor; char i; factor = 1; for (i = _lincombtbl[idx].c2; --i >= 0;) factor *= 2; for (i = _lincombtbl[idx].c3; --i >= 0;) factor *= 3; for (i = _lincombtbl[idx].c5; --i >= 0;) factor *= 5; for (i = _lincombtbl[idx].c7; --i >= 0;) factor *= 7; return factor; } static void _lnguess( floatnum dest, int digits, int idx) { _addcoef(dest, _lincombtbl[idx].c2-_lincombtbl[idx].c5, &cLn2, digits); _addcoef(dest, _lincombtbl[idx].c3, &cLn3, digits); _addcoef(dest, _lincombtbl[idx].c7, &cLn7, digits); _addcoef(dest, _lincombtbl[idx].c5-_lincombtbl[idx].c10, &cLn10, digits); } /* reduces x using a special factor whose primes factors are 2, 3, 5 and 7 only. x is multiplied by this factor, yielding a value near a power of ten. Then x is divided by this power of ten. The logarithm of this factor is returned in lnguess. Valid for -0.4 <= x < 1. Relative error < 5e-100 for 100 digit result. This algorithm reduces x to a value < 0.01, which is appropriate small for submitting to a series evaluation */ void _lnreduce( floatnum x, floatnum lnguess, int digits) { floatstruct tmp1, tmp2; int idx; int expx; signed char pos; float_setzero(lnguess); expx = float_getexponent(x); if (expx < -2) return; float_create(&tmp1); float_create(&tmp2); idx = leadingdigits(x, 3 + expx) + 39; if (idx < 0) idx = 0; pos = idx >= 40? 1 : 0; idx += pos; float_setinteger(&tmp1, _factor(idx)); float_setexponent(&tmp1, -pos); float_sub(&tmp1, &tmp1, &c1, EXACT); float_mul(&tmp2, x, &tmp1, digits); float_add(&tmp1, &tmp1, &tmp2, digits+1); float_add(x, x, &tmp1, digits); _lnguess(lnguess, digits+4, idx); float_free(&tmp1); float_free(&tmp2); return; } /* for -0.4 <= x < 1.0 */ void _lnxplus1lt1( floatnum x, int digits) { floatstruct lnfactor; float_create(&lnfactor); _lnreduce(x, &lnfactor, digits); _lnxplus1near0(x, digits); float_sub(x, x, &lnfactor, digits+1); float_free(&lnfactor); } /* the general purpose routine evaluating ln(x) for all positive arguments. It uses multiplication and division to reduce the argument to a value near 1. The factors are always small, so these operations do not take much time. -- One often sees an argument reduction by taking the square root several times in succession. But the square root is slow in number.c, so we avoid it best. -- Super-fast algorithm like the AGM based ones, do not pay off for limited lengths because of the same reason: They require taking square roots several times. A test showed, a hundred digits calculation using AGM is 8 times slower than the algorithm here. For extreme precision, of course, AGM will be superior. The relative error seems to be less than 7e-101 for 100-digits computations */ void _ln( floatnum x, int digits) { floatstruct tmp; int coef10; char coef3; char dgt; float_create(&tmp); coef10 = float_getexponent(x); /* reducing the significand to 0.6 <= x < 2 by simple multiplication */ dgt = leadingdigits(x, 1); coef3 = 0; if (dgt == 1) float_setexponent(x, 0); else { ++coef10; float_setexponent(x, - 1); coef3 = (dgt < 6); if (coef3) float_mul(x, x, &c3, digits+1); } float_sub(x, x, &c1, digits+1); _lnxplus1lt1(x, digits); if (coef10 != 0) { float_muli(&tmp, &cLn10, coef10, digits+1); float_add(x, x, &tmp, digits+1); } if (coef3) float_sub(x, x, &cLn3, digits); float_free(&tmp); } void _lnxplus1( floatnum x, int digits) { if (float_cmp(x, &cMinus0_4) >= 0 && float_cmp(x, &c1) < 0) _lnxplus1lt1(x, digits); else { float_add(x, x, &c1, digits+1); _ln(x, digits); } } /* The artanh function has a pole at x == 1. For values close to 1 the general purpose evaluation is too unstable. We use a dedicated algorithm here to get around the problems. Avoid using this function for values of x > 0.5, _artanh is the better choice then. Values near the other pole of artanh at -1 can be derived from this function using artanh(-1+x) = -artanh(1-x). For x < 0.5 and a 100-digit computation, the maximum relative error is in the order of 1e-99 */ void _artanh1minusx( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); float_sub(&tmp, &c2, x, digits); float_div(x, &tmp, x, digits); _ln(x, digits); float_mul(x, x, &c1Div2, digits); float_free(&tmp); } /* designed for |x| <= 0.5. The evaluation is not symmetric with respect to 0, i.e. it might be -artanh x != artanh -x. The difference is in the order of the last digit, of course. Evaluation of positive values yield a slightly better relative error than that of negative values. The maximum relative error is the maximum of that of artanhnear0 and 1e-99 */ void _artanhlt0_5( floatnum x, int digits) { floatstruct tmp; if (float_getexponent(x) < -2 || float_iszero(x)) artanhnear0(x, digits); else { float_create(&tmp); float_sub(&tmp, &c1, x, digits+1); float_add(x, x, x, digits); float_div(x, x, &tmp, digits); _lnxplus1(x, digits); float_mul(x, x, &c1Div2, digits); float_free(&tmp); } } /* the general purpose routine for evaluating artanh. The evaluation is symmetric with respect to 0, i.e. it is always -artanh(x) == artanh -x. Valid for |x| < 1, but unstable for |x| approx. == 1 */ void _artanh( floatnum x, int digits) { signed char sgn; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &c1Div2) <= 0) _artanhlt0_5(x, digits); else { float_sub(x, &c1, x, digits+1); _artanh1minusx(x, digits); } float_setsign(x, sgn); } /* evaluates ln(2*x), the asymptotic function of arsinh and arcosh for large x */ static void _ln2x( floatnum x, int digits) { _ln(x, digits); float_add(x, &cLn2, x, digits); } /* valid for all x. The relative error is less than 1e-99. The evaluation is symmetric with respect to 0: arsinh -x == - arsinh x */ void _arsinh( floatnum x, int digits) { floatstruct tmp; int expxsqr; signed char sgn; expxsqr = 2*float_getexponent(x)+2; /* for extreme small x, sqrt(1+x*x) is approx == 1 + x*x/2 - x^4/8, so arsinh x == ln(1 + x + x*x/2 - x^4/8 +...) approx == x - x*x*x/6 + ... If we approximate arsinh x by x, the relative error is roughly |x*x/6|. This is less than acceptable 10^(-), if log(x*x) < - */ if (expxsqr < -digits || float_iszero(x)) return; float_create(&tmp); /* arsinh -x = -arsinh x, so we can derive the arsinh for negative arguments from that of positive arguments */ sgn = float_getsign(x); float_abs(x); if (expxsqr-2 > digits) /* for very large x, use the asymptotic formula ln(2*x) */ _ln2x(x, digits); else { float_mul(&tmp, x, x, digits + (expxsqr>=0? 0 : expxsqr)); float_add(&tmp, &tmp, &c1, digits+1); float_sqrt(&tmp, digits); if (float_getexponent(x) < 0) { /* for small x, use arsinh x == artanh (x/sqrt(1+x*x)). Stable for x < 1, but not for large x*/ float_div(x, x, &tmp, digits); _artanh(x, digits+1); } else { /* arsinh x = ln(x+sqrt(1+x*x)), stable for x >= 1, but not for small x */ float_add(x, x, &tmp, digits); _ln(x, digits); } } float_setsign(x, sgn); float_free(&tmp); } /* arcosh(x+1), x >= 0, is the stable variant of arcosh(x), x >= 1. The relative error is less than 1e-99. */ void _arcoshxplus1( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); if (2*float_getexponent(x) > digits) { /* for very large x, use the asymptotic formula ln(2*(x+1)) */ float_add(x, x, &c1, digits+1); _ln2x(x, digits); } else { /* arcosh(x+1) = ln(1+(x+sqrt(x*(x+2)))), stable for all positive x, except for extreme large x, where x*(x+2) might overflow */ /* get sinh(arcosh (1+x)) = sqrt(x*(x+2)) */ float_add(&tmp, x, &c2, digits); float_mul(&tmp, x, &tmp, digits); float_sqrt(&tmp, digits); float_add(x, x, &tmp, digits); _lnxplus1(x, digits); } float_free(&tmp); } speedcrunch-0.10.1/src/math/floatcommon.c0000644000175000001440000001714211015364561017467 0ustar helderusers/* floatcommon.c: convenience functions, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatconfig.h" #include "floatcommon.h" #include "floatconst.h" #include "floatlong.h" #include #define MSB (1 << (sizeof(unsigned)*8 - 1)) #define LOGMSB ((301*(sizeof(unsigned)*8-1))/1000) static char _chckparam1( cfloatnum x, int digits, int limit, int specialval) { if (float_isnan(x)) { float_seterror(NoOperand); return 0; } if ((digits <= 0 || digits > limit) && digits != specialval) { float_seterror(InvalidPrecision); return 0; } return 1; } static char _chckparam( floatnum x, int digits, int limit, int specialval) { if (!_chckparam1(x, digits, limit, specialval)) return _setnan(x); return 1; } char chckmathparam( floatnum x, int digits) { return _chckparam(x, digits, MATHPRECISION, 1); } int logexp( cfloatnum x) { int expx, result; expx = float_getexponent(x); if (expx < 0) expx = -expx; result = -1; while (expx != 0) { expx <<= 1; ++result; } return result; } void float_setasciiz( floatnum x, const char* asciiz) { float_setscientific(x, asciiz, NULLTERMINATED); } char float_divi( floatnum quotient, cfloatnum dividend, int divisor, int digits) { floatstruct tmp; int result, expx; if (!_chckparam1(dividend, digits, maxdigits, INTQUOT)) return _setnan(quotient); if (digits != INTQUOT && (divisor == 1 || divisor == -1)) return float_muli(quotient, dividend, divisor, digits); if (divisor == 10 || divisor == -10) { expx = float_getexponent(dividend)-1; if (expx < -float_getrange() - 1) return _seterror(quotient, Underflow); } float_create(&tmp); float_setinteger(&tmp, divisor); result = float_div(quotient, dividend, &tmp, digits); float_free(&tmp); return result; } char float_addi( floatnum sum, cfloatnum summand1, int summand2, int digits) { floatstruct tmp; int result; if (!_chckparam1(summand1, digits, maxdigits, EXACT)) return _setnan(sum); if (summand2 == 0) return float_copy(sum, summand1, digits); float_create(&tmp); float_setinteger(&tmp, summand2); result = float_add(sum, summand1, &tmp, digits); float_free(&tmp); return result; } char float_muli( floatnum product, cfloatnum factor1, int factor2, int digits) { floatstruct tmp; int result; int expx; if (!_chckparam1(factor1, digits, maxdigits, EXACT)) return _setnan(product); switch(factor2) { case 0: return _setzero(product); case 1: case -1: case 10: case -10: expx = float_getexponent(factor1); if (factor2 != 1 && factor2 != -1 && ++expx > float_getrange()) return _seterror(product, Overflow); result = float_copy(product, factor1, digits); if (factor2 < 0) float_neg(product); float_setexponent(product, expx); return result; case 2: case -2: result = float_add(product, factor1, factor1, digits); if (factor2 < 0) float_neg(product); return result; } float_create(&tmp); float_setinteger(&tmp, factor2); result = float_mul(product, factor1, &tmp, digits); float_free(&tmp); return result; } int leadingdigits( cfloatnum x, int digits) { int i; unsigned tmp, ovfl; char buf[LOGMSB+1]; if (digits <= 0 || digits > LOGMSB+1 || float_isnan(x) || float_iszero(x)) return 0; memset(buf, '0', digits); float_getsignificand(buf, digits, x); tmp = 0; for(i = 0; i < digits; ++i) { ovfl = 10; if (_longmul(&tmp, &ovfl)) { ovfl = buf[i] - '0'; _longadd(&tmp, &ovfl); } if (ovfl != 0) return 0; } if (float_getsign(x) < 0) { if (tmp > MSB) return 0; if (tmp == MSB) return (int)tmp; return -(int)tmp; } if (tmp >= MSB) return 0; return (int)tmp; } int float_abscmp( floatnum x, floatnum y) { signed char sx, sy; int result; sx = float_getsign(x); sy = float_getsign(y); float_abs(x); float_abs(y); result = float_cmp(x, y); float_setsign(x, sx); float_setsign(y, sy); return result; } int float_relcmp( floatnum x, floatnum y, int digits) { /* do not simply use float_sub, because of overflow/underflow */ floatstruct tmp; int result; int expx, expy, expdiff; result = float_cmp(x, y); if (result == 0 || float_getlength(x) == 0 || float_getlength(y) == 0 || float_getsign(x) != float_getsign(y)) return result; expx = float_getexponent(x); expy = float_getexponent(y); expdiff = expx - expy; if (expdiff >= 2 || expdiff < -2) return result; float_create(&tmp); if (result > 0) float_setexponent(x, 0); float_setexponent(y, expy - expx); float_sub(&tmp, x, y, 2); if (result * float_getsign(x) > 0) float_div(&tmp, &tmp, x, 2); else float_div(&tmp, &tmp, y, 2); if (float_getexponent(&tmp) < -digits) result = 0; float_setexponent(x, expx); float_setexponent(y, expy); float_free(&tmp); return result; } char float_reciprocal( floatnum x, int digits) { return float_div(x, &c1, x, digits); } char float_isinteger( cfloatnum x) { return !float_isnan(x) && float_getlength(x) <= float_getexponent(x) + 1; } int float_asinteger( cfloatnum x) { return leadingdigits(x, float_getexponent(x)+1); } void float_checkedround( floatnum x, int digits) { floatstruct tmp; int saveerr; saveerr = float_geterror(); float_create(&tmp); if (float_round(&tmp, x, digits, TONEAREST)) float_move(x, &tmp); float_free(&tmp); float_geterror(); float_seterror(saveerr); } void float_addexp( floatnum x, int smd) { float_setexponent(x, float_getexponent(x) + smd); } char float_isodd( floatnum x) { return (float_getdigit(x, float_getexponent(x)) & 1) != 0; } char float_roundtoint( floatnum x, roundmode mode) { signed char value; signed char sign; char digit; if (float_isnan(x)) return float_int(x); /* sets float_error */ if (float_getexponent(x) >= 0) return float_round(x, x, float_getexponent(x) + 1, mode); sign = float_getsign(x); switch (mode) { case TONEAREST: digit = float_getdigit(x, 0); if (digit < 5 || (digit == 5 && float_getlength(x) == 1)) value = 0; else value = sign; break; case TOINFINITY: value = sign; break; case TOPLUSINFINITY: value = sign > 0? 1 : 0; break; case TOMINUSINFINITY: value = sign > 0? 0 : -1; break; case TOZERO: value = 0; break; } switch (value) { case 0: float_setzero(x); break; case 1: float_copy(x, &c1, EXACT); break; case -1: float_copy(x, &cMinus1, EXACT); break; } return 1; } speedcrunch-0.10.1/src/math/floatconfig.h0000644000175000001440000001570511015364561017454 0ustar helderusers/* floatdefines.h: basic settings in floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ /* this file contains the basic settings, that control the overall behaviour of floatnum and derivates. Uncomment or set any of the following defines according to your needs. */ #ifndef _FLOATCONFIG_H #define _FLOATCONFIG_H /* FLOATDEBUG introduces some extensions to floatnum, so you can easily follow operations of floatnum in a debugger like ddd. Uncomment this, if you develop code based on floatnum, and if you want to look into floatnum variables during a debugger session. */ // #define FLOATDEBUG /* enables a pre-defined set of macros so that a regression test suite of floatnum can be executed. These settings are such that corner cases can easily be triggered. The settings are not useful in a real application of floatnum. Uncomment this if you want to run the standard regression test suite of floatnum */ // #define _FLOATNUMTEST /* floatnum uses bc's bc_num format to store and operate on data. Since bc_num is an arbitrary precision format, operands may grow to extreme sizes, where complex operations take considerable time to execute, up to an hour or more. floatconfig defines a guard value to avoid extreme long operands. Any request to produce a result of more than MAXDIGITS digits is considered an error and yields a NaN result. When setting this value, bear in mind, this is a global value that effects internal operations as well as 'user' requests. When using the routines for transcendent mathematical functions, you should allow extra 14 digits, so that operations like float_exp do not fail when they compute something near maximum precision. */ #define MAXDIGITS 250 /* the number of bits into which an exponent of a floatnum is encoded. In order to avoid integer overflow, this should be at least two bits less than the bits in the integer type chosen for the exponent. The default is two bit less than the size of an int */ // #define BITS_IN_EXP 30 /* floatnum puts an upper limit on the base 10 exponent of its numbers that is based on the size of an integer, but even for 16 bit integers this limit is as big as 4095. Real applications usually do not need such big numbers. If you want to limit the range of possible numbers, set this value accordingly. An operation result exceeding this limit is converted into a NaN, and an overflow/underflow is reported. The default is the maximum positive value that can be encoded in BITS_IN_EXP bits. If you change EXPMAX, you might want to reduce BITS_IN_EXP as well. */ /* #define EXPMAX 5000 */ /* The precision of basic operations like + or * is limited by MAXDIGITS. In addition, some higher mathematical functions involve constants, that, of course, are stored to a limited precision only. This puts another bound on floatnum, described by the value MATHPRECISION. Since procedures for higher mathematical functions employ basic operations to determine their result, MATHPRECISION is <= MAXDIGITS. The current math library version of floatnum limits higher mathematical functions to 100 digits precision. One can say, MATHPRECISION describes the granularity of the number space, because higher functions do not (reliably) produce different results for values closer to each other than this granularity. You may re-define granularity by setting DECPRECISION. This will never bypass MATHPRECISION, being always the limit for the math library, but basic operations may benefit from finer granularity, up to the overall limit MAXDIGITS. If you lower granularity, that saves some memory and evaluation time in a few places. Granularity means that integers with more than DECPRECISION digits might not be saved without loss of digits. So DECPRECISION defines the integer range of floatnum. Because base convertion and logic operations are integer based, both are limited by DECPRECISION as well. By default, DECPRECISION is set to MATHPRECISION */ #define DECPRECISION 78 /* The integer domain of logical functions is a true subset of the integer range, because, according to their nature, they operate modulo a power of two, so the limit on their input is best chosen to be a power of 2. If you do not declare a limit here, an appropriate value is derived from DECPRECISION. If you change this value, make sure 2^LOGICRANGE is less than 10^DECPRECISION */ #define LOGICRANGE 256 /*************************************************************************** END OF USER SETABLE DEFINES ***************************************************************************/ /* the limit of the math library */ #define MATHPRECISION 100 #if defined(_FLOATNUMTEST) # undef MAXDIGITS # undef MATHPRECISION # undef DECPRECISION # undef LOGICRANGE # define MAXDIGITS 130 # define MATHPRECISION 130 # define LOGICRANGE 96 #endif #define MAXBITS_IN_EXP (sizeof(int)*8-2) #define MAXEXP ((1 << MAXBITS_IN_EXP) - 1) #ifndef BITS_IN_EXP /* we need 2 extra bits during conversion, so that the exponent does not overflow while computing a base 2 expression */ # define BITS_IN_EXP MAXBITS_IN_EXP #endif /* necessary width of an integer to hold all possible exponents after a conversion to another base */ #define BITS_IN_HEXEXP BITS_IN_EXP #define BITS_IN_OCTEXP (BITS_IN_EXP + 1) #define BITS_IN_BINEXP (BITS_IN_EXP + 2) #ifndef MAXDIGITS # define MAXDIGITS 500 #endif /* MAXDIGITS */ #ifndef EXPMAX # define EXPMAX ((1 << (BITS_IN_EXP-1)) - 1) #endif /* EXPMAX */ #define EXPMIN (-EXPMAX - 1) #define EXPZERO ((int)((-1) << (sizeof(int)*8-1))) #define EXPNAN ((int)(~EXPZERO)) #ifndef DECPRECISION #define DECPRECISION MATHPRECISION #endif #define BINPRECISION ((33219*DECPRECISION)/10000 + 1) #define OCTPRECISION ((11073*DECPRECISION)/10000 + 1) #define HEXPRECISION ((8305*DECPRECISION)/10000 + 1) #ifndef LOGICRANGE # define LOGICRANGE (16*((BINPRECISION-2)/16)) #endif #endif /* _FLOATCONFIG_H */ speedcrunch-0.10.1/src/Translations.cmake0000644000175000001440000000041711015364561017534 0ustar helderusersset(speedcrunch_TRANSLATIONS i18n/ca.qm i18n/cs.qm i18n/de.qm i18n/es_AR.qm i18n/es.qm i18n/eu.qm i18n/fi.qm i18n/fr.qm i18n/he.qm i18n/id.qm i18n/it.qm i18n/nb.qm i18n/nl.qm i18n/pl.qm i18n/pt_BR.qm i18n/pt.qm i18n/ro.qm i18n/ru.qm i18n/sv.qm i18n/tr.qm i18n/zh_CN.qm ) speedcrunch-0.10.1/src/CMakeLists.txt0000755000175000001440000001202611015364561016613 0ustar helderusersPROJECT(speedcrunch) # note: change this BEFORE making a release !! SET( speedcrunch_VERSION "0.10.1" ) IF( APPLE ) SET( PROGNAME SpeedCrunch ) SET( MACOSX_BUNDLE_ICON_FILE speedcrunch.icns ) SET( MACOSX_BUNDLE_SHORT_VERSION_STRING ${speedcrunch_VERSION} ) SET( MACOSX_BUNDLE_VERSION ${speedcrunch_VERSION} ) SET( MACOSX_BUNDLE_LONG_VERSION_STRING Version ${speedcrunch_VERSION} ) SET( CMAKE_OSX_ARCHITECTURES ppc;i386 ) #Comment out if not universal binary ELSE( APPLE ) SET( PROGNAME speedcrunch ) ENDIF( APPLE ) CMAKE_MINIMUM_REQUIRED(VERSION 2.4.4) SET(CMAKE_COLOR_MAKEFILE ON) SET(CMAKE_VERBOSE_MAKEFILE OFF) SET(CMAKE_INCLUDE_CURRENT_DIR TRUE) ADD_DEFINITIONS("-DSPEEDCRUNCH_VERSION=\\\"${speedcrunch_VERSION}\\\"") IF( NOT WIN32 ) IF( NOT APPLE ) # for BinReloc stuff ADD_DEFINITIONS( -DENABLE_BINRELOC ) ENDIF( NOT APPLE ) ENDIF( NOT WIN32 ) # sources INCLUDE(SourceFiles.cmake) # resources SET(speedcrunch_RESOURCES resources/speedcrunch.qrc) # translations INCLUDE(Translations.cmake) IF( MINGW ) # resource compilation for mingw ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/speedcrunchico.o COMMAND windres.exe -I${CMAKE_CURRENT_SOURCE_DIR} -i${CMAKE_CURRENT_SOURCE_DIR}/resources/speedcrunchico.rc -o ${CMAKE_CURRENT_BINARY_DIR}/speedcrunchico.o ) SET(speedcrunch_SOURCES ${speedcrunch_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/speedcrunchico.o) SET(LINK_FLAGS -Wl,-subsystem,windows) ELSE(MINGW) SET(speedcrunch_SOURCES ${speedcrunch_SOURCES} resources/speedcrunchico.rc) ENDIF(MINGW) # enable warnings IF(CMAKE_COMPILER_IS_GNUCXX ) ADD_DEFINITIONS( -g -Wall ) ENDIF(CMAKE_COMPILER_IS_GNUCXX ) # setup for Qt4 SET(QT_USE_QTXML TRUE) find_package(Qt4 REQUIRED) include(${QT_USE_FILE}) # build everything qt4_add_RESOURCES( speedcrunch_RESOURCES_SOURCES ${speedcrunch_RESOURCES} ) QT4_WRAP_UI( speedcrunch_FORMS_HEADERS ${speedcrunch_FORMS} ) QT4_WRAP_CPP( speedcrunch_HEADERS_MOC ${speedcrunch_HEADERS} ) IF( APPLE ) ADD_EXECUTABLE( ${PROGNAME} MACOSX_BUNDLE ${speedcrunch_SOURCES} ${speedcrunch_HEADERS_MOC} ${speedcrunch_RESOURCES_SOURCES} ${speedcruch_FORMS_HEADERS} ) SET( speedcrunch_RESOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/${PROGNAME}.app/Contents/Resources ) SET( speedcrunch_TRANSLATION_DIR ${CMAKE_CURRENT_BINARY_DIR}/${PROGNAME}.app/Contents/MacOS/locale ) SET( speedcrunch_BOOKSDIR ${CMAKE_CURRENT_BINARY_DIR}/${PROGNAME}.app/Contents/MacOS/books ) ADD_CUSTOM_COMMAND( TARGET ${PROGNAME} POST_BUILD COMMAND mkdir ARGS -p ${speedcrunch_RESOURCE_DIR} COMMAND mkdir ARGS -p ${speedcrunch_TRANSLATION_DIR} COMMAND mkdir ARGS -p ${speedcrunch_BOOKSDIR} COMMAND cp ARGS -f resources/${MACOSX_BUNDLE_ICON_FILE} ${speedcrunch_RESOURCE_DIR} COMMAND cp ARGS -f i18n/*.qm ${speedcrunch_TRANSLATION_DIR} COMMAND cp ARGS -Rf books/ ${speedcrunch_BOOKSDIR} COMMAND rm ARGS -f ${speedcrunch_BOOKSDIR}/genbooks.sh COMMAND rm ARGS -rf ${speedcrunch_BOOKSDIR}/i18n COMMAND for ARGS svnDir in `find ${speedcrunch_BOOKSDIR} -type d -name \".svn\"` \; do rm -rf $svnDir \; done COMMENT Setting up translations & resources ) ELSE( APPLE ) ADD_EXECUTABLE( ${PROGNAME} ${speedcrunch_SOURCES} ${speedcrunch_HEADERS_MOC} ${speedcrunch_RESOURCES_SOURCES} ${speedcrunch_FORMS_HEADERS} ) ENDIF( APPLE ) ADD_CUSTOM_TARGET( confclean COMMAND rm -rf Makefile CMakeFiles/ CMakeCache.txt cmake_install.cmake DartTestfile.txt install_manifest.txt ) TARGET_LINK_LIBRARIES(${PROGNAME} ${QT_LIBRARIES} ${LINK_FLAGS}) # set(EXECUTABLE_OUTPUT_PATH ${speedcrunch_BINARY_DIR}/../bin) # install executable and translation files # note: it will install to CMAKE_INSTALL_PREFIX, which can be set e.g # cmake ../trunk -DCMAKE_INSTALL_PREFIX=/usr INSTALL(TARGETS ${PROGNAME} DESTINATION bin) INSTALL(FILES ${speedcrunch_TRANSLATIONS} DESTINATION share/speedcrunch/locale) # required for regression tests ENABLE_TESTING() ADD_EXECUTABLE(testhmath ${testhmath_SOURCES}) ADD_TEST(testhmath ${EXECUTABLE_OUTPUT_PATH}/testhmath) #add_executable(testevaluator ${testevaluator_SOURCES}) #target_link_libraries(testevaluator ${QT_LIBRARIES}) #add_test(testevaluator ${EXECUTABLE_OUTPUT_PATH}/testevaluator) ADD_EXECUTABLE(testfloatnum ${testfloatnum_SOURCES}) ADD_TEST(testfloatnum ${EXECUTABLE_OUTPUT_PATH}/testfloatnum) INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} 3rdparty/util base gui main math) # books SET(BOOKSDIR "${CMAKE_INSTALL_PREFIX}/share/${PROGNAME}/books/") ADD_DEFINITIONS("-DBOOKSDIR=\\\"${BOOKSDIR}\\\"") INSTALL(FILES books/books.css DESTINATION ${BOOKSDIR} ) INSTALL(DIRECTORY books/images books/ca books/cs books/de books/en books/es books/es_AR books/eu books/fi books/fr books/he books/id books/it books/nb books/nl books/pt books/pt_BR books/pl books/ro books/ru books/sv books/tr books/zh_CN DESTINATION "${BOOKSDIR}" PATTERN ".svn" EXCLUDE ) # freedesktop file INSTALL(FILES speedcrunch.desktop DESTINATION "${CMAKE_INSTALL_PREFIX}/share/applications/" ) INSTALL(FILES resources/speedcrunch.png DESTINATION "${CMAKE_INSTALL_PREFIX}/share/pixmaps/" ) speedcrunch-0.10.1/src/SourceFiles.cmake0000644000175000001440000000544711015364561017306 0ustar helderusers# speedcrunch set(speedcrunch_HEADERS #3rdparty/util/binreloc.h base/constants.hxx base/evaluator.hxx base/functions.hxx #base/settings.hxx gui/aboutbox.hxx gui/autohidelabel.hxx gui/bookdock.hxx gui/constantsdock.hxx gui/deletevardlg.hxx gui/resultdisplay.hxx gui/editor.hxx gui/functionsdock.hxx gui/historydock.hxx gui/insertfunctiondlg.hxx gui/insertvardlg.hxx gui/keypad.hxx gui/tipwidget.hxx gui/variablesdock.hxx gui/mainwindow.hxx #math/floatcommon.h #math/floatconfig.h #math/floatconst.h #math/floatconvert.h #math/floaterf.h #math/floatexp.h #math/floatgamma.h #math/floathmath.h #math/floatio.h #math/floatipower.h #math/floatlog.h #math/floatlogic.h #math/floatlong.h #math/floatnum.h #math/floatpower.h #math/floatseries.h #math/floattrig.h #math/hmath.hxx #math/number.h ) set(speedcrunch_SOURCES 3rdparty/util/binreloc.c base/constants.cpp base/evaluator.cpp base/functions.cpp base/settings.cpp gui/aboutbox.cpp gui/autohidelabel.cpp gui/bookdock.cpp gui/constantsdock.cpp gui/deletevardlg.cpp gui/resultdisplay.cpp gui/editor.cpp gui/functionsdock.cpp gui/historydock.cpp gui/insertfunctiondlg.cpp gui/insertvardlg.cpp gui/keypad.cpp gui/tipwidget.cpp gui/variablesdock.cpp gui/mainwindow.cpp main/main.cpp math/floatcommon.c math/floatconst.c math/floatconvert.c math/floaterf.c math/floatexp.c math/floatgamma.c math/floathmath.c math/floatio.c math/floatipower.c math/floatlog.c math/floatlogic.c math/floatlong.c math/floatnum.c math/floatpower.c math/floatseries.c math/floattrig.c math/hmath.cpp math/number.c ) # regression test for HMath set(testhmath_SOURCES math/floatcommon.c math/floatconst.c math/floatconvert.c math/floaterf.c math/floatexp.c math/floathmath.c math/floatgamma.c math/floatio.c math/floatipower.c math/floatlog.c math/floatlogic.c math/floatlong.c math/floatnum.c math/floatpower.c math/floatseries.c math/floattrig.c math/hmath.cpp math/number.c test/testhmath.cpp ) # regression test for Evaluator #set(testevaluator_SOURCES #base/evaluator.hxx #) #set(testevaluator_SOURCES #base/evaluator.cpp #base/functions.cpp #base/variant.cpp #bison/exprparser.c #math/floatcommon.c #math/floatconst.c #math/floatconvert.c #math/floaterf.c #math/floatexp.c #math/floathmath.c #math/floatgamma.c #math/floatio.c #math/floatipower.c #math/floatlog.c #math/floatlogic.c #math/floatlong.c #math/floatnum.c #math/floatpower.c #math/floatseries.c #math/floattrig.c #math/numdata.cpp #math/hmath.cpp #math/number.c #test/testevaluator.cpp #) # regression test for floatnum set(testfloatnum_SOURCES math/floatcommon.c math/floatconst.c math/floatconvert.c math/floaterf.c math/floatexp.c math/floathmath.c math/floatgamma.c math/floatio.c math/floatipower.c math/floatlog.c math/floatlogic.c math/floatlong.c math/floatnum.c math/floatpower.c math/floatseries.c math/floattrig.c math/number.c test/testfloatnum.c ) speedcrunch-0.10.1/src/speedcrunch.desktop0000644000175000001440000000037211015364561017747 0ustar helderusers[Desktop Entry] Name=SpeedCrunch GenericName=High precision calculator GenericName[pt]=Calculadora de alta precisão GenericName[tr]=Yüksek duyarlıklı hesap makinesi Exec=speedcrunch Icon=speedcrunch.png Type=Application Categories=Qt;KDE;Utility speedcrunch-0.10.1/src/i18n/0000755000175000001440000000000011015364704014625 5ustar helderusersspeedcrunch-0.10.1/src/i18n/zh_CN.ts0000644000175000001440000017263511015364561016215 0ustar helderusers AboutBox About SpeedCrunch 关于 SpeedCrunch SpeedCrunch version %1 SpeedCrunch 版本 %1 Based on original idea from 最初概念来自于 Original author 最初作者 Current maintainer 当前维护者 Developers 开发人员 Special thanks to 特别感谢 Graphics 图像 Thanks to 感谢 ...and many others... ...和许多其他人... Translations 翻译 Argentinian Spanish 阿根廷西班牙语 Brazilian Portuguese 巴西葡萄牙语 Czech 捷克语 Dutch 荷兰语 French 法语 Finnish 芬兰语 German 德语 Hebrew 希伯来语 Indonesian 印度尼西亚语 Italian 意大利语 Norwegian 挪威语 Polish 波兰语 Portuguese 葡萄牙语 Romanian 罗马尼亚语 Russian 俄语 Spanish 西班牙语 Swedish 瑞典语 Turkish 土耳其语 Copyright (C) 版权所有 (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version 本程序是自由软件;您可以在由自由软件基金会发布的 GNU GPL 协议的版本 2 或者更新的版本(看您的选择了)下重新发布并且/或者修改它 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 本程序的发布希望对您是有用的,但是没有提供任何担保;甚至没有提供对任何目的的销售和健康的担保。 有关细节请查看 GNU GPL 协议。 Visit <b>http://www.speedcrunch.org</b> for more information! 更多信息请访问 <b>http://www.speedcrunch.org</b>! Close 关闭 Basque 巴斯克语 Simplified Chinese 简体中文 Catalan BookDock Back 后退 Forward 前进 Index 索引 ConstantCompletion All 全部 Constants Characteristic Impedance of Vacuum 真空的特性阻抗 General Physics 通用物理 Electric Constant 电常数 Magnetic Constant 磁常数 Gravitation Constant 万有引力常数 Planck's Constant 普朗克常数 Dirac's Constant 狄拉克常数 Speed of Light in Vacuum 真空中的光速 Bohr-Procopiu Magneton 玻尔磁子 Electromagnetic 电磁 Conductance Quantum 电导量子 Coulomb's Constant 库仑常数 Elementary Charge 基本电荷 Josephson Constant 约瑟夫逊常数 Magnetic Flux Quantum 磁通量子 Nuclear Magneton 核磁子 Resistance Quantum 电阻量子 von Klitzing Constant 克里青常数 Bohr Radius 玻尔半径 Atomic & Nuclear 原子与原子核 Fermi Coupling Constant 费米耦合常数 Fine-structure Constant 精细结构常数 Hartree Energy 哈特利能量 Quantum of Circulation 环流量子 Rydberg Constant 里德伯常数 Thomson Cross Section 汤姆逊散射截面 Weak Mixing Angle 弱混合角 Atomic Mass Unit 原子质量单位 Physico-chemical 物理化学 Avogadro's Number 阿伏加德罗常数 Boltzmann Constant 玻尔兹曼常数 Faraday Constant 法拉第常数 First Radiation Constant 第一辐射常数 Loschmidt Constant 劳施密特常数 Gas Constant 气体常数 Molar Planck Constant 摩尔普朗克常数 Second Radiation Constant 第二辐射常数 Stefan-Boltzmann Constant 斯特凡-玻尔兹曼常数 Astronomical Unit 天文单位 Astronomy 天文 Light Year 光年 Parsec 天体距离单位 Sidereal Year 恒星年 days Tropical Year 回归年 Gregorian Year 公历年 Earth Mass 地球质量 Sun Mass 太阳质量 Mean Earth Radius 平均地球半径 Sun Radius 太阳半径 Sun Luminosity 太阳光度 ConstantsDock No match found 没有找到匹配的 Constants 常量 Category 分类 Search 搜索 All 全部 DeleteVariableDlg Delete Variable 删除变量 Name 名称 Value &Delete 删除(&D) Close 关闭 Editor Current result: <b>%1</b> 当前的结果:<b>%1</b> Selection result: <b>%1</b> 选择的结果:<b>%1</b> Evaluator invalid expression 无效的表达式 division by zero 被零除 unknown function or variable 未知的函数或者变量 variable cannot be overwritten 变量不能被覆盖 identifier matches an existing function name 这个标识符和一个已经存在的函数重名了 Functions cannot execute function %1 无法执行函数 %1 function accepts 1 argument 函数接受 1 个参数 function accepts %1 arguments 函数接受 %1 个参数 function requires 1 or 2 arguments 函数需要 1 个或者 2 个参数 function undefined for specified arguments 函数对于特定参数没有定义 function requires at least 2 arguments 函数需要最少 2 个参数 function requires integer arguments 函数需要整型参数 function undefined for specified argument 函数对于特定参数没有定义 underflow 下溢出 function requires at least 1 argument 函数需要最少 1 个参数 Absolute Value 绝对值 Average (Arithmetic Mean) 平均值(算术意义) Binary Representation 二进制表示 Cube Root 立方根 Ceiling 求大于的最近整数 Decimal Representation 十进制表示 Floor 求小于的最近整数 Fractional Part 小数部分 Extension of Factorials [= (x-1)!] 阶乘的扩展 [= (x-1)!] Geometric Mean 几何意义 Hexadecimal Representation 十六进制表示 Integer Part 整数部分 ln(abs(Gamma)) ln(abs(Gamma)) Maximum 最大值 Minimum 最小值 Octal Representation 八进制表示 Product Product Rounding 求最近整数 Signum 符号 Square Root 平方根 Sum 求和 Truncation 去尾 Area Hyperbolic Cosine 反双曲余弦 Area Hyperbolic Sine 反双曲正弦 Area Hyperbolic Tangent 反双曲正切 Hyperbolic Cosine 双曲余弦 Exponential 指数 Base-2 Logarithm 以 2 为底的对数 Natural Logarithm 自然对数 Base-10 Logarithm 以 10 为底的对数 Hyperbolic Sine 双曲正弦 Hyperbolic Tangent 双曲正切 Greatest Common Divisor 最大公约数 Combination (Binomial Coefficient) 组合(二项系数) Permutation (Arrangement) 排列(安排) Binomial Cumulative Distribution Function 二项累积分布函数 Binomial Distribution Mean 二项分布平均值 Binomial Probability Mass Function 二项概率质量函数 Binomial Distribution Variance 二项分布方差 Error Function 误差函数 Complementary Error Function 互补误差函数 Hypergeometric Cumulative Distribution Function 超几何累积分布函数 Hypergeometric Distribution Mean 超几何分布平均值 Hypergeometric Probability Mass Function 超几何概率质量函数 Hypergeometric Distribution Variance 超几何分布方差 Poissonian Cumulative Distribution Function 泊松累积分布函数 Poissonian Distribution Mean 泊松分布平均值 Poissonian Probability Mass Function 泊松概率质量函数 Poissonian Distribution Variance 泊松分布方差 Arc Cosine 反余弦 Arc Sine 反正弦 Arc Tangent 反正切 Cosine 余弦 Cotangent 余切 Cosecant 余割 Degrees of Arc 弧的度数 Radians 弧度 Secant 正割 Sine 正弦 Tangent 正切 Mask to a bit size 反码 Sign-extent a value 反码逆运算 Logical NOT 逻辑非 Logical AND 逻辑与 Logical OR 逻辑或 Logical XOR 逻辑异或 Arithmetic Shift Left 算术左移 Arithmetic Shift Right 算术右移 Integer Quotient 整数商 Modulo 模数 FunctionsDock Functions 函数 Search 搜索 No match found 没有找到匹配的 HistoryDock History 历史 InsertFunctionDlg Insert Function 插入函数 Name 名称 Description 描述 &Insert 插入(&I) Cancel 取消 InsertVariableDlg Insert Variable 插入变量 Name 名称 Value &Insert 插入(&I) Cancel 取消 Keypad Inverse cosine 反余弦 The last result 上次计算的结果 Inverse sine 反正弦 Inverse tangent 反正切 Clear expression 清除表达式 Cosine 余弦 Scientific notation 科学记数法 Exponential 指数 Natural logarithm 自然对数 Sine 正弦 Square root 平方根 Tangent 正切 Assign variable x 对变量 x 赋值 The variable x 变量 x MainWindow Math Book 数学书 Radian 弧度 Degree 度数 Binary 二进制 Octal 八进制 Hexadecimal 十六进制 Fixed decimal 固定十进制 Engineering decimal 工程十进制 Scientific decimal 科学十进制 General decimal 通用十进制 Angle unit 角度单位 Result format 结果格式 Clear E&xpression 清除表达式(&X) Clear &History 清除历史(&H) &Degree 度数(&D) Delete All V&ariables 清除所有变量(&A) D&elete Variable... 删除变量(&E)... &15 Decimal Digits &15 位小数 &2 Decimal Digits &2 位小数 &3 Decimal Digits &3 位小数 &50 Decimal Digits &50 位小数 &8 Decimal Digits &8 位小数 &Automatic Precision 自动精度(&A) &Copy 复制(&C) Copy Last &Result 复制上次计算的结果(&R) &Paste 粘贴(&P) &About 关于(&A) About &Qt 关于 Qt(&Q) SpeedCrunch &Web Site... SpeedCrunch 网址(&W)... &Tip of the Day 每日提示(&T) Insert &Function... 插入函数(&F)... Insert &Variable... 插入变量(&V)... &Partial Results 部分结果(&P) Automatic &Completion 自动补全(&C) Always On &Top 总是在最上(&T) &Minimize To System Tray 最小化到系统托盘(&M) Syntax &Highlighting 语法高亮(&H) &System Default 系统默认(&S) &Dot 点(&D) &Comma 逗号(&C) &Radian 弧度(&R) Scroll Display Down 向下滚动显示 Scroll Display Up 向上滚动显示 &Select Expression 选择表达式(&S) &Import... 导入(&I)... &Load... 加载(&L)... &Quit 退出(&Q) &Save... 保存(&S)... &Export... 导出(&E)... Math &Book 数学书(&B) &Constants 常量(&C) Full &Screen Mode 全屏模式(&S) &Functions 函数(&F) &History 历史(&H) &Keypad 键盘(&K) Hide &Menu Bar 隐藏菜单栏(&M) &Status Bar 状态栏(&S) &Variables 变量(&V) &Binary 二进制(&B) &Engineering 工程(&E) &Fixed Decimal 固定(&F) &General 通用(&G) &Hexadecimal 十六进制(&H) &Octal 八进制(&O) &Scientific 科学(&S) System &Default 系统默认(&D) &Session 会话(&S) &Edit 编辑(&E) &View 查看(&V) Se&ttings 设置(&T) Result &Format 结果格式(&F) &Decimal 十进制(&D) &Angle Unit 角度单位(&A) &Behavior 行为(&B) Radix &Character 基数字符(&C) &Language 语言(&L) &Help 帮助(&H) About Qt 关于 Qt File %1 is not a valid session 文件 %1 不是一个有效的会话 SpeedCrunch Sessions (*.sch);;All Files (*) SpeedCrunch 会话文件 (*.sch);;全部文件 (*) Load Session 加载会话 Error 错误 Can't read from file %1 不能读取文件 %1 Merge session being loaded with current session? If no, current variables and display will be cleared. 您要把载入的会话和当前会话进行合并么? 如果不的话,当前的变量和显示将会被清空。 Question 问题 All Files (*) 所有文件 (*) Import Session 导入会话 Merge session being imported with current session? If no, current variables and display will be cleared. 您要把导入的会话和当前会话进行合并么?如果不的话,当前的变量和显示将会被清空。 Ignore error? 忽略错误? Save Session 保存会话 Can't write to file %1 不能写入文件 %1 Export Session 导出会话 The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. 菜单栏现在被隐藏。如果您想让它再次显示,请按 Ctrl+Alt+M。 Warning 警告 To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. 如果想要使用键盘插入函数,请使用 Ctrl+F 快捷键。从这个对话框中,您可以选择您要插入的函数。 To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. 如果想要使用键盘插入变量,请使用 Ctrl+I 快捷键。从这个对话框中,您可以选择您要插入的变量。 Use variable <i>pi</i> to use pi constant. 请使用变量<i>pi</i>来使用 PI 常量。 Use <i>;</i> (semicolon) to separate the parameters in functions. 请使用<i>;</i>(半角分号)来分隔函数中的参数。 Tip of the day 每日提示 SpeedCrunch is minimized. Left click the icon to restore it or right click for options. SpeedCrunch 最小化了。 左键点击它可以恢复它,或者右键点击它选择选项。 VariablesDock Variables 变量 Search 搜索 No match found 没有找到匹配的 speedcrunch-0.10.1/src/i18n/it.ts0000644000175000001440000017510011015364561015616 0ustar helderusers AboutBox Special thanks to Un ringraziamento particolare a French Francese German Tedesco Portuguese Portoghese Russian Russo Italian Italiano This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Questo programma è software libero; può essere ridistribuito e/o modificato sotto i termini della GNU General Public License come pubblicata dalla Free Software Foundation; sia la versione 2 della licenza che, a vostra discrezione, qualsiasi versione successiva This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Questo programma è stato distribuito nella speranza che possa essere utile ma SENZA NESSSUNA GARANZIA; senza neanche l'implicita garanzia di COMMERCIABILITÀ o IDONEITÀ PER UN PARTICOLARE SCOPO. Consultare la GNU General Public License per maggiori dettagli. SpeedCrunch version %1 SpeedCrunch versione %1 About SpeedCrunch Informazioni su SpeedCrunch Norwegian Norvegese Spanish Spagnolo Original author Autore originale Current maintainer Sviluppatore attuale Based on original idea from Basato su un'idea originale di Thanks to Grazie a ...and many others... ...e molti altri... Translations Traduzioni Brazilian Portuguese Portoghese brasiliano Copyright (C) Copyright (C) Visit <b>http://www.speedcrunch.org</b> for more information! Visita <b>http://www.speedcrunch.org</b> per più informazioni! Argentinian Spanish Spagnolo Argentino Dutch Nederlandese Hebrew Ebraico Swedish Svedese Finnish Finlandese Czech Ceco Romanian Rumeno Developers Sviluppatori Indonesian Indonesiano Polish Polacco Close Chiudi Graphics Grafica Turkish Turco Basque Simplified Chinese Catalan BookDock Back Indietro Forward Avanti Index Indice ConstantCompletion All Tutto Constants Characteristic Impedance of Vacuum Impedenza Caratteristica del Vuoto General Physics Fisica Generale Electric Constant Costante Elettrica Magnetic Constant Costante Magnetica Gravitation Constant Costante di Gravitazione Planck's Constant Costante di Planck Dirac's Constant Costante di Dirac Speed of Light in Vacuum Velocità della Luce nel Vuoto Bohr-Procopiu Magneton Magnetone di Bohr-Procopiu Electromagnetic Elettromagnetico Conductance Quantum Quanto di Conduttanza Coulomb's Constant Costante di Coulomb Elementary Charge Carica Elementare Josephson Constant Costante di Josephson Magnetic Flux Quantum Quantizzazione del Flusso Nuclear Magneton Magnetone Nucleare Resistance Quantum Quanto di Resistenza von Klitzing Constant Costante di von Klitzing Bohr Radius Raggio di Bohr Atomic & Nuclear Atomico & Nucleare Fermi Coupling Constant Costante di Coppia di Fermi Fine-structure Constant Costante di Struttura Fine Hartree Energy Energia di Hartree Quantum of Circulation Quanto di Circolazione Rydberg Constant Costante di Rydberg Thomson Cross Section Sezione Trasversale di Thomson Weak Mixing Angle Angolo Debole di Miscelazione Atomic Mass Unit Unità di Massa Atomica Physico-chemical Fisico-chimica Avogadro's Number Numero di Avogadro Boltzmann Constant Costante di Boltzmann Faraday Constant Costante di Faraday First Radiation Constant Prima Costante di Radiazione Loschmidt Constant Costante di Loschmidt Gas Constant Costante del Gas Molar Planck Constant Costante Molare di Planck Second Radiation Constant Seconda Costante di Radiazione Stefan-Boltzmann Constant Costante di Stefan-Boltzmann Astronomical Unit Unità Astronomica Astronomy Astronomia Light Year Anno Luce Parsec Parsec Sidereal Year Anno Siderale days giorni Tropical Year Anno Tropicale Gregorian Year Anno Gregoriano Earth Mass Massa della Terra Sun Mass Massa del Sole Mean Earth Radius Raggio Medio Terrestre Sun Radius Raggio Solare Sun Luminosity Luminosità Solare ConstantsDock Constants Costanti Category Categoria Search Cerca No match found Nessuna corrispondenza trovata All Tutto DeleteVariableDlg Name Nome Value Valore &Delete &Elimina Close Chiudi Delete Variable Elimina Variabile Editor Current result: <b>%1</b> Risultato corrente: <b>%1</b> Selection result: <b>%1</b> Risultato della selezione: <b>%1</b> Evaluator invalid expression espressione non valida division by zero divisione per zero unknown function or variable variabile o funzione sconosciute variable cannot be overwritten la variabile non può essere sovrascritta identifier matches an existing function name l'identificatore ha lo stesso nome di una funzione esistente Functions Absolute Value Valore Assoluto Average (Arithmetic Mean) Media Aritmetica Binary Representation Rappresentazione Binaria Cube Root Radice Cubica Ceiling Parte Intera Superiore Decimal Representation Rappresentazione Decimale Floor Parte Intera Inferiore Fractional Part Parte Frazionaria Extension of Factorials [= (x-1)!] Fattoriale Esteso [= (x-1)!] Geometric Mean Media Geometrica Hexadecimal Representation Rappresentazione Esadecimale Integer Part Parte Intera ln(abs(Gamma)) ln(abs(Gamma)) Maximum Massimo Minimum Minimo Octal Representation Rappresentazione Ottale Product Prodotto Rounding Arrotondamento Signum Segno Square Root Radice Quadrata Sum Somma Truncation Troncamento Area Hyperbolic Cosine Area Coseno Iperbolico Area Hyperbolic Sine Area Seno Iperbolico Area Hyperbolic Tangent Area Tangente Iperbolica Hyperbolic Cosine Coseno Iperbolico Exponential Esponenziale Base-2 Logarithm Logaritmo in Base 2 Natural Logarithm Logaritmo Naturale Base-10 Logarithm Logaritmo in Base 10 Hyperbolic Sine Seno Iperbolico Hyperbolic Tangent Tangente Iperbolica Greatest Common Divisor Massimo Comun Divisore Combination (Binomial Coefficient) Coefficente Binomiale Permutation (Arrangement) Permutazione Binomial Cumulative Distribution Function Funzione di Ripartizione Binomiale Binomial Distribution Mean Speranza della Distribuzione Binomiale Binomial Probability Mass Function Variabile Aleatoria Binomiale Binomial Distribution Variance Varianza della Distribuzione Binomiale Error Function Errore Complementary Error Function Complemento di Errore Hypergeometric Cumulative Distribution Function Funzione di Ripartizione Ipergeometrica Hypergeometric Distribution Mean Speranza della Distribuzione Ipergeometrica Hypergeometric Probability Mass Function Variabile Aleatoria Ipergeometrica Hypergeometric Distribution Variance Varianza della Distribuzione Ipergeometrica Poissonian Cumulative Distribution Function Funzione di Ripartizione di Poisson Poissonian Distribution Mean Speranza della Distribuzione di Poisson Poissonian Probability Mass Function Variabile Aleatoria di Poisson Poissonian Distribution Variance Varianza della Distribuzione di Poisson Arc Cosine Arcocoseno Arc Sine Arcoseno Arc Tangent Arcotangente Cosine Coseno Cotangent Cotangente Cosecant Cosecante Degrees of Arc Gradi di Arco Radians Radianti Secant Secante Sine Seno Tangent Tangente Mask to a bit size Maschera su una dimensione di bit Sign-extent a value Estensione di un valore con segno Logical NOT NOT logico Logical AND AND logico Logical OR OR logico Logical XOR XOR logico Arithmetic Shift Left Slittamento aritmetico a sinistra Arithmetic Shift Right Slittamento aritmetico a destra Integer Quotient Quoziente Intero Modulo Resto cannot execute function %1 impossibile eseguire la funzione %1 function accepts 1 argument la funzione accetta 1 argomento function accepts %1 arguments la funzione accetta %1 argomenti function requires 1 or 2 arguments la funzione richiede 1 o 2 parametri function undefined for specified arguments la funzione non è definita per i parametri specificati function requires at least 2 arguments la funzione richiede almeno 2 argomenti function requires integer arguments la funzione richiede argomenti di tipo intero function undefined for specified argument la funzione non è definita per l'argomento specificato underflow valore sotto la soglia di precisione function requires at least 1 argument la funzione richiede almeno 1 parametro FunctionsDock Functions Funzioni Search Cerca No match found Nessuna corrispondenza trovata HistoryDock History Cronologia InsertFunctionDlg Name Nome Description Descrizione &Insert &Inserisci Cancel Annulla Insert Function Inserisci una funzione InsertVariableDlg Name Nome Value Valore &Insert &Inserisci Cancel Annulla Insert Variable Inserisci una variabile Keypad Inverse cosine Coseno inverso The last result Ultimo risultato Inverse sine Seno inverso Inverse tangent Tangente inversa Clear expression Cancella l'espressione Cosine Coseno Scientific notation Notazione scientifica Exponential Esponenziale Natural logarithm Logaritmo naturale Sine Seno Square root Radice quadrata Tangent Tangente Assign variable x Assegna un valore alla variabile x The variable x Variabile x MainWindow About Qt Informazioni su Qt SpeedCrunch Sessions (*.sch);;All Files (*) Sessioni di SpeedCrunch (*.sch);;Tutti i file (*) Load Session Carica Sessione Error Errore Can't read from file %1 Impossibile leggere dal file %1 Question Domanda Save Session Salva la Sessione Can't write to file %1 Impossibile scrivere sul file %1 Warning Attenzione To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Per inserire una funzione usando la tastiera usa la scorciatoia Ctrl+F. È possibile scegliere dal pannello la funzione da inserire. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Per inserire una variabile usando la tastiera usa la scorciatoia Ctrl+I. È possibile scegliere dal pannello la variabile da inserire. Use variable <i>pi</i> to use pi constant. Usa la variabile <i>pi</i> per la costante pi. Use <i>;</i> (semicolon) to separate the parameters in functions. Usare <i>;</i> (il punto e virgola) per separare i parametri nelle funzioni. Tip of the day Suggerimento del giorno File %1 is not a valid session Il file %1 non contiene una sessione valida Merge session being loaded with current session? If no, current variables and display will be cleared. Si vuole mischiare la sessione da caricare con quella corrente? In caso di risposta negativa variabili e visualizzazione corrente saranno pulite. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. SpeedCrunch è stato minimizzato. Usare il tasto sinistro sull'icona per ripristinarlo o il tasto destro per le opzioni. Degree Gradi All Files (*) Tutti i file (*) Radian Radianti The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. La barra di menu è stata nascosta. Per renderla nuovamente visibile premere Ctrl+Alt+M. Binary Binario Engineering decimal Decimale ingegneristico Fixed decimal Decimale a precisione fissa General decimal Decimale generale Hexadecimal Esadecimale Octal Ottale Scientific decimal Decimale scientifico Import Session Importa Sessione Merge session being imported with current session? If no, current variables and display will be cleared. Si vuole mischiare la sessione da importare con quella corrente?In caso di risposta negativa variabili e visualizzazione corrente saranno pulite. Export Session Esporta Sessione Math Book Libro di Matematica Angle unit Unità d'Angolo Result format Formato del risultato Clear E&xpression Cancella l'E&spressione Clear &History Cancella la &Cronologia &Degree &Gradi Delete All V&ariables Elimina tutte le V&ariabili D&elete Variable... E&limina la Variabile... &15 Decimal Digits &15 Cifre Decimali &2 Decimal Digits &2 Cifre Decimali &3 Decimal Digits &3 Cifre Decimali &50 Decimal Digits &50 Cifre Decimali &8 Decimal Digits &8 Cifre Decimali &Automatic Precision Precisione &Automatica &Copy &Copia Copy Last &Result Copia l'Ultimo &Risultato &Paste &Incolla &About &Informazioni su About &Qt Informazioni su &Qt SpeedCrunch &Web Site... Sito &Web di SpeedCrunch... &Tip of the Day &Suggerimento del Giorno Insert &Function... Inserisci &Funzione... Insert &Variable... Inserisci &Variabile... &Partial Results Risultato &Parziale Automatic &Completion &Completamento Automatico Always On &Top Sempre in Primo &Piano &Minimize To System Tray &Minimizza nella System Tray Syntax &Highlighting &Evidenziatore Sintattico &System Default Predefinita di &Sistema &Dot &Punto &Comma &Virgola &Radian &Radianti Scroll Display Down Scorri in Basso la visualizzazione Scroll Display Up Scorri in Alto la visualizzazione &Select Expression &Seleziona l'Espressione &Import... &Importa... &Load... &Carica... &Quit &Esci &Save... &Salva... &Export... &Esporta... Math &Book &Libro di Matematica &Constants &Costanti Full &Screen Mode Modalità &Schermo Intero &Functions &Funzioni &History &Cronologia &Keypad &Tastierino Hide &Menu Bar Nascondi la Barra di &Menu &Status Bar Barra di &Stato &Variables &Variabili &Binary &Binario &Engineering &Ingegneristica &Fixed Decimal &Decimale a precisione Fissa &General &Generale &Hexadecimal &Esadecimale &Octal &Ottale &Scientific &Scientifica System &Default &Predefinita di Sistema &Session &Sessione &Edit &Modifica &View &Visualizza Se&ttings Im&postazioni Result &Format &Formato del Risultato &Decimal &Decimale &Angle Unit Unità d'&Angolo &Behavior &Comportamento Radix &Character &Carattere di Radice &Language &Lingua &Help &Aiuto Ignore error? Ignorare l'errore? VariablesDock Variables Variabili Search Cerca No match found Nessuna corrispondenza trovata speedcrunch-0.10.1/src/i18n/es_AR.ts0000644000175000001440000017346411015364561016206 0ustar helderusers AboutBox Special thanks to Agradecimientos especiales a French Francés German Alemán Portuguese Portugués Russian Ruso Italian Italiano This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Este programa es software libre; puede ser redistribuido y/o modificado bajo los términos de la GNU General Public License como fue publicada por la Free Software Foundation; ya sea la versión 2 de la Licencia, o (a su elección), cualquier versión posterior This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Este programa se distribuye con la idea de que será útil, pero SIN NINGUNA GARANTÍA; ni siquiera la garantía implícita de SER COMERCIAL o SER ADECUADO PARA ALGÚN PROPÓSITO PARTICULAR. Vea la GNU General Public LIcense para más detalles. SpeedCrunch version %1 SpeedCrunch versión %1 Norwegian Noruego Spanish Español About SpeedCrunch Acerca de SpeedCrunch Original author Autor original Current maintainer Mantenedor actual Based on original idea from Basado en la idea original de Thanks to Gracias a ...and many others... ...y muchos más... Translations Traducciones Brazilian Portuguese Portugués (Brasil) Copyright (C) Copyright (C) Visit <b>http://www.speedcrunch.org</b> for more information! Visite <b>http://www.speedcrunch.org</b> para más información! Argentinian Spanish Español Argentino Dutch Neerlandés Hebrew Hebreo Swedish Sueco Finnish Finés Czech Checo Romanian Rumano Developers Desarrolladores Indonesian Indonesio Polish Polaco Turkish Turco Close Cerrar Graphics Basque Simplified Chinese Catalan BookDock Back Forward Index ConstantCompletion All Todas Constants Characteristic Impedance of Vacuum Impedancia Característica del Vacío General Physics Física General Electric Constant Constante Eléctrica Magnetic Constant Constante Magnética Gravitation Constant Constante Gravitatoria Planck's Constant Constante de Planck Dirac's Constant Constante de Dirac Speed of Light in Vacuum Velocidad de la Luz en el Vacío Bohr-Procopiu Magneton Magnetón Bohr-Procopiu Electromagnetic Electromagnetismo Conductance Quantum Conductancia Quántica Coulomb's Constant Constante de Coulomb Elementary Charge Carga Elemental Josephson Constant Constante de Josephson Magnetic Flux Quantum Flujo Magnético Cuántico Nuclear Magneton Magnetón Nuclear Resistance Quantum Quanto de Resistencia von Klitzing Constant Constante de von Klitzing Bohr Radius Radio de Bohr Atomic & Nuclear Atómico & Nuclear Fermi Coupling Constant Constante de Acoplamiento de Fermi Fine-structure Constant Constante de Estructura-fina Hartree Energy Energía de Hartree Quantum of Circulation Quanto de Circulación Rydberg Constant Constante de Rydberg Thomson Cross Section Corte de Thomson Weak Mixing Angle Ángulo de Weinberg Atomic Mass Unit Unidad de Masa Atómica Physico-chemical Físico-química Avogadro's Number Número de Avogadro Boltzmann Constant Constante de Boltzmann Faraday Constant Constante de Faraday First Radiation Constant Constante de Primer Radiación Loschmidt Constant Constante de Loschmidt Gas Constant Constante de los Gases Molar Planck Constant Constante Molar de Planck Second Radiation Constant Segunda Constante de Radiación Stefan-Boltzmann Constant Constante de Stefan-Boltzmann Astronomical Unit Unidad Astronómica Astronomy Astronomía Light Year Año Luz Parsec Parsec Sidereal Year Año Sideral days días Tropical Year Año Tropical Gregorian Year Año Gregoriano Earth Mass Masa de la Tierra Sun Mass Masa del Sol Mean Earth Radius Radio Promedio de la Tierra Sun Radius Radio del Sol Sun Luminosity Luminosidad del Sol ConstantsDock Constants Constantes Category Categoria Search Buscar No match found Sin resultados All Todas DeleteVariableDlg Name Nombre Value Valor Absoluto &Delete &Borrar Close Cerrar Delete Variable Borrar variable Editor Current result: <b>%1</b> Selection result: <b>%1</b> Evaluator invalid expression division by zero unknown function or variable variable cannot be overwritten identifier matches an existing function name Functions Absolute Value Valor Absoluto Average (Arithmetic Mean) Promedio (Media Aritmética) Binary Representation Representación Binaria Cube Root Raiz Cúbica Ceiling Techo Decimal Representation Representación Decimal Floor Piso Fractional Part Parte Fraccional Geometric Mean Media Geométrica Hexadecimal Representation Representación Hexadecimal Integer Part Parte Entera Maximum Máximo Minimum Mínimo Octal Representation Representación Octal Product Producto Rounding Redondeo Signum Signo Square Root Raíz cuadrada Sum Suma Truncation Truncamiento Area Hyperbolic Cosine Arco Coseno Hiperbólico Area Hyperbolic Sine Arco Seno Hiperbólico Area Hyperbolic Tangent Arco Tangente Hiperbólica Hyperbolic Cosine Coseno Hiperbólico Exponential Exponencial Base-2 Logarithm Logaritmo Base 2 Natural Logarithm Logaritmo Natural Base-10 Logarithm Logaritmo Base 10 Hyperbolic Sine Seno Hiperbólico Hyperbolic Tangent Tangente Hiperbólica Greatest Common Divisor Máximo Común Divisor Combination (Binomial Coefficient) Combinación (Coeficiente Binomial) Permutation (Arrangement) Permutación (Ordenamiento) Binomial Cumulative Distribution Function Función Acumulativa de Distribución Biniomial Binomial Distribution Mean Media de Distribución Binomial Binomial Probability Mass Function Función de Masa de Probabilidad Binomial Binomial Distribution Variance Varianza de Distribución Binomial Hypergeometric Cumulative Distribution Function Función de Distribución Acumulativa Hipergeométrica Hypergeometric Distribution Mean Media de Distribución Hipergeométrica Hypergeometric Probability Mass Function Función de Masa de Probabilidad Hipergeométrica Hypergeometric Distribution Variance Varianza de Distribución Hipergeométrica Poissonian Cumulative Distribution Function Función de Distribución Acumulativa de Poisson Poissonian Distribution Mean Media de Distribución de Poisson Poissonian Probability Mass Function Función de Masa de Probabilidad de Poisson Poissonian Distribution Variance Varianza de Distribución de Poisson Arc Cosine Arco Coseno Arc Sine Arco Seno Arc Tangent Arco Tangente Cosine Coseno Cotangent Cotangente Cosecant Cosecante Radians Radianes Secant Secante Sine Seno Tangent Tangente cannot execute function %1 no se puede ejecutar la función %1 function accepts 1 argument La función acepta 1 argumento function accepts %1 arguments la función acepta %1 argumentos function requires 1 or 2 arguments la función requiere 1 o 2 argumentos function undefined for specified arguments función no definida para los argumentos especificados function requires at least 2 arguments la función requiere al menos 2 argumentos function requires integer arguments la función requiere argumentos enteros function undefined for specified argument función no definida para el argumento especificado underflow function requires at least 1 argument la función requiere al menos 1 argumento Extension of Factorials [= (x-1)!] ln(abs(Gamma)) Error Function Complementary Error Function Degrees of Arc Mask to a bit size Sign-extent a value Logical NOT Logical AND Logical OR Logical XOR Arithmetic Shift Left Arithmetic Shift Right Integer Quotient Modulo FunctionsDock Functions Funciones Search Buscar No match found Sin Resultados HistoryDock History Historia InsertFunctionDlg Name Nombre Description Descripción &Insert &Insertar Cancel Cancelar Insert Function Insertar Función InsertVariableDlg Name Nombre Value Valor &Insert &Insertar Cancel Cancelar Insert Variable Insertar Variable Keypad Inverse cosine coseno Inverso The last result Inverse sine seno Inverso Inverse tangent Tangente Inversa Clear expression Cosine Coseno Scientific notation Exponential Exponencial Natural logarithm Sine Seno Square root Raíz Cuadrada Tangent Tangente Assign variable x The variable x MainWindow About Qt Acerca de Qt SpeedCrunch Sessions (*.sch);;All Files (*) Load Session Error Error Can't read from file %1 Question Save Session Guardar Sesión Can't write to file %1 No se puede escribir al archivo %1 Warning To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Para insertar una función usando el teclado, use el atajo Ctrl+F. Desde el diálogo, puede seleccionar la función que desea insertar. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Para insertar una variable usando el teclado, use el atajo Ctrl+I. Desde el diálogo, puede seleccionar la variable que desea insertar. Use variable <i>pi</i> to use pi constant. Usar la variable <i>pi</i> para usar la constante pi. Use <i>;</i> (semicolon) to separate the parameters in functions. Use <i>;</i> (punto y coma) para separar los parámetros en las funciones. Tip of the day File %1 is not a valid session Merge session being loaded with current session? If no, current variables and display will be cleared. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. Degree All Files (*) Radian The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. Binary Engineering decimal Fixed decimal General decimal Hexadecimal Octal Scientific decimal Import Session Merge session being imported with current session? If no, current variables and display will be cleared. Export Session Math Book &Session &Sesión Clear E&xpression Clear &History Borrar &Historial &Degree Delete All V&ariables D&elete Variable... &Borrar Variable... &15 Decimal Digits &15 Dígitos Decimales &2 Decimal Digits &2 Dígitos Decimales &3 Decimal Digits &3 Dígitos Decimales &50 Decimal Digits &50 Dígitos Decimales &8 Decimal Digits &8 Dígitos Decimales &Automatic Precision Prec&isión Automática &Copy &Copiar Copy Last &Result &Paste &Pegar &About &Acerca de About &Qt Acerca de &Qt SpeedCrunch &Web Site... Sitio &Web de SpeedCrunch... &Tip of the Day &Sugerencia del Día Insert &Function... Insertar &Función... Insert &Variable... Insertar &Variable... &Partial Results Automatic &Completion Always On &Top &Minimize To System Tray Syntax &Highlighting &System Default &Dot &Comma &Radian Scroll Display Down Scroll Display Up &Select Expression &Import... &Load... &Quit &Salir &Save... &Guardar... &Export... Math &Book &Constants Full &Screen Mode &Functions &History &Keypad Hide &Menu Bar &Status Bar &Variables &Binary &Binario &Engineering &Ingeniería &Fixed Decimal Punto Decimal Fi&jo &General &Hexadecimal &Hexadecimal &Octal &Octal &Scientific &Científica System &Default &Edit &Editar &View &Ver Se&ttings &Configuración Result &Format &Decimal &Angle Unit &Behavior Radix &Character &Language &Help A&yuda Angle unit Result format Ignore error? VariablesDock Variables Variables Search Buscar No match found Sin resultados speedcrunch-0.10.1/src/i18n/eu.ts0000644000175000001440000017426011015364561015621 0ustar helderusers AboutBox About SpeedCrunch SpeedCrunch-i buruz SpeedCrunch version %1 SpeedCrunch %1 bertsioa Based on original idea from Jatorrizko ideia Original author Jatorrizko egilea Current maintainer Mantentze lanak Developers Garatzaileak Special thanks to Esker bereziak ondorengoei Graphics Grafikoak Thanks to Eskerrak hauei ...and many others... ...eta beste zenbaitzuei... Translations Itzulpenak Argentinian Spanish Argentinako Gaztelania Brazilian Portuguese Brasildar Portugalera Czech Txekiarra Dutch Holandera French Frantsesa Finnish Finlandiera German Alemana Hebrew Hebraiera Indonesian Indonesiera Italian Italiera Norwegian Norvegiera Polish Poloniera Portuguese Portugalera Romanian Errumaniera Russian Errusiera Spanish Gaztelera Swedish Suediera Turkish Turkiera Copyright (C) Egilearen eskubidea (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Programa hau software askea da; Free Software Foundation-ek argitaratutako GNU Lizentzia Publiko Orokorraren baldintzak jarraituz banatu eta/edo aldatu dezakezu; lizentziaren 2. bertsioa, edo (zure aukeran) ondorengo beste edozein bertsiorekin This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Programa hau erabilgarria izango delakoan banatzen da, baina INOLAKO BERMERIK GABE; ez da bermatzen beraren EGOKITASUNA MERKATURATZEKO edo HELBURU PARTIKULARRETARAKO ERABILTZEKO.(sp)(sp)Begiratu GNU Lizentzia Publiko Orokorra xehetasun gehiago izateko. Visit <b>http://www.speedcrunch.org</b> for more information! Bisitatu <b>http://www.speedcrunch.org</b> informazio gehiago eskuratzeko! Close Itxi Basque Euskara Catalan Katalana Simplified Chinese Txinera Erraztua BookDock Back Atzera Forward Aurrera Index Aurkibidea ConstantCompletion All Guztia Constants Characteristic Impedance of Vacuum Hutsaren Inpedantzia karakteristikoa General Physics Fisika Orokorra Electric Constant Konstante Elektrikoa Magnetic Constant Konstante Magnetikoa Gravitation Constant Grabitazio Konstantea Planck's Constant Planck-en Konstantea Dirac's Constant Dirac-en Konstantea Speed of Light in Vacuum Argiaren Abiadura Hutsean Bohr-Procopiu Magneton Bohr-Procopiu Magnetoia Electromagnetic Elektromagnetismoa Conductance Quantum Konduktantzia Kuantikoa Coulomb's Constant Coulomb-en Konstantea Elementary Charge Oinarrizko Karga Josephson Constant Josephson Konstantea Magnetic Flux Quantum Fluxu Magnetiko Kuantikoa Nuclear Magneton Magnetoi Nuklearra Resistance Quantum Erresistentzia Kantikoa von Klitzing Constant von Klitzing Konstantea Bohr Radius Bohrren Erradioa Atomic & Nuclear Atomikoa & Nuklearra Fermi Coupling Constant Fermi Coupling Konstantea Fine-structure Constant Egitura xehe Konstantea Hartree Energy Hartree Energia Quantum of Circulation Zirkulazio Kuantua Rydberg Constant Rydberg Konstantea Thomson Cross Section Thomsonen Sekzio Efikaza Weak Mixing Angle Weinberg-en Angelua Atomic Mass Unit Masa Atomikoaren Unitatea Physico-chemical Fisiko-kimikoa Avogadro's Number Avogadroren Zenbakia Boltzmann Constant Boltzmann Konstantea Faraday Constant Faraday Konstantea First Radiation Constant Erradiazioaren Lehen Konstantea Loschmidt Constant Loschmidt Konstantea Gas Constant Gas Konstantea Molar Planck Constant Planck-en Konstante Molarra Second Radiation Constant Erradiazioaren Bigarren Konstantea Stefan-Boltzmann Constant Stefan-Boltzmann Konstantea Astronomical Unit Unitate Astronomikoa Astronomy Astronomia Light Year Argi urtea Parsec Parsec Sidereal Year Eguzki Urte days egunak Tropical Year Urte Tropikala Gregorian Year Urte Gregoriarra Earth Mass Lurraren Masa Sun Mass Eguzki Masa Mean Earth Radius Lurraren Batez Besteko Erradioa Sun Radius Eguzki Erradioa Sun Luminosity Eguzkiaren Argitasuna ConstantsDock No match found Ez da bat datorrenik aurkitu Constants Konstanteak Category Kategoria Search Bilatu All Guztia DeleteVariableDlg Delete Variable Aldagaia Ezabatu Name Izena Value Balioa &Delete &Ezabatu Close Itxi Editor Current result: <b>%1</b> Uneko emaitza: <b>%1</b> Selection result: <b>%1</b> Aukeraketaren emaitza: <b>%1</b> Evaluator invalid expression Adierazpen baliogabea division by zero zergatiko zatiketa unknown function or variable funtzio edo aldagai ezezaguna variable cannot be overwritten ezin da aldagaia gainidatzi identifier matches an existing function name identifikatzailea funtzio baten izenarekin bat dator Functions cannot execute function %1 ezin da %1 funtzioa exekutatu function accepts 1 argument funtzioak argumentu 1 onartzen du function accepts %1 arguments funtzioak %1 argumentu onartzen ditu function requires 1 or 2 arguments funtzioak argumentu 1 edo 2 behar ditu function undefined for specified arguments funtzioa definitu gabe zehaztutako argumentuentzat function requires at least 2 arguments funtzioak gutxienez 2 argumentu behar ditu function requires integer arguments funtzioak argumentu osoak behar ditu function undefined for specified argument funtzioa definitu gabe zehaztutako argumentuarentzat underflow gainezkatze negatiboa function requires at least 1 argument funtzioak gutxienez argumentu 1 behar du Absolute Value Balio Absolutua Average (Arithmetic Mean) Batezbestekoa (Batezbesteko Aritmetikoa) Binary Representation Adierazpide Bitarra Cube Root Erro Kubikoa Ceiling Goruntz borobildu Decimal Representation Adierazpide Hamartarra Floor Beheruntz borobildu Fractional Part Zatiki Zatia Extension of Factorials [= (x-1)!] Faktorialen Hedapena [= (x-1)!] Geometric Mean Batezbesteko Geometrikoa Hexadecimal Representation Adierazpide Hamaseitarra Integer Part Zati Osoa ln(abs(Gamma)) ln(abs(Gamma)) Maximum Maximo Minimum Minimo Octal Representation Adierazpide Zortzitarra Product Biderkadura Rounding Biribiltze Signum Square Root Erro Karratu Sum Batura Truncation Moztu Area Hyperbolic Cosine Arku Cosinu Hiperbolikoa Area Hyperbolic Sine Arku Sinu Hiperbolikoa Area Hyperbolic Tangent Arku Tangente Hiperbolikoa Hyperbolic Cosine Cosinu Hiperbolikoa Exponential Esponentzial Base-2 Logarithm 2-oinarridun Logaritmoa Natural Logarithm Logaritmo Nepertarra Base-10 Logarithm 10-oinarridun Logaritmoa Hyperbolic Sine Sinu Hiperbolikoa Hyperbolic Tangent Tangente Hiperbolikoa Greatest Common Divisor Zatitzaile Komunetako Haundiena Combination (Binomial Coefficient) Konbiazioa (Koefiziente Binomiala) Permutation (Arrangement) Permutazio (Birrantolaketa) Binomial Cumulative Distribution Function Banaketa Binomial Metatuaren Funtzioa Binomial Distribution Mean Banaketa Binomialaren Batezbestekoa Binomial Probability Mass Function Probabilitate Masa Binomialaren Funtzioa Binomial Distribution Variance Banaketa Binomialaren Bariantza Error Function Akats Funtzioa Complementary Error Function Akats Funtzio Osagarria Hypergeometric Cumulative Distribution Function Banaketa Hipergeometriko Metatuaren Funtzioa Hypergeometric Distribution Mean Banaketa Hipergeometrikoaren Batezbestekoa Hypergeometric Probability Mass Function Probabilitate Masa Hipergeometrikoaren Funtzioa Hypergeometric Distribution Variance Banaketa Hipergeometrikoaren Bariantza Poissonian Cumulative Distribution Function Poissonen Banaketa Metatuaren Funtzioa Poissonian Distribution Mean Poissonen Banaketaren Batezbestekoa Poissonian Probability Mass Function Poissonen Probabilitate Masaren Funtzioa Poissonian Distribution Variance Poissonen Banaketa Bariantza Arc Cosine Arku Kosinu Arc Sine Arku Sinu Arc Tangent Arku Tangente Cosine Kosinu Cotangent Kotangente Cosecant Kosekante Degrees of Arc Arku Graduak Radians Radianak Secant Sekante Sine Sinu Tangent Tangente Mask to a bit size Maskaratu bit kopuru batera Sign-extent a value Logical NOT NOT logikoa Logical AND AND logikoa Logical OR OR logikoa Logical XOR XOR logikoa Arithmetic Shift Left Mugitu Ezkerrera Aritmetikoa Arithmetic Shift Right Mugitu Eskuinera Aritmetikoa Integer Quotient Zatidura Osoa Modulo Modulu FunctionsDock Functions Funtzioak Search Bilatu No match found Ez da bat datorrenik aurkitu HistoryDock History Historia InsertFunctionDlg Insert Function Funtzioa Sartu Name Izena Description Azalpena &Insert &Sartu Cancel Galarazi InsertVariableDlg Insert Variable Aldagaia Sartu Name Izena Value Balioa &Insert &Sartu Cancel Galarazi Keypad Inverse cosine Arku kosinu The last result Azken emaitza Inverse sine Arku sinu Inverse tangent Arku tangente Clear expression Adierazpena ezabatu Cosine Kosinu Scientific notation Notazio zientifikoa Exponential Esponentzial Natural logarithm Logaritmo Nepertarra Sine Sinu Square root Erro karratu Tangent Tangente Assign variable x Esleitu x aldagaia The variable x x aldagaia MainWindow Math Book Matematika Liburua Radian Degree Gradu Binary Bitarra Octal Zortzitarra Hexadecimal Hamaseitarra Fixed decimal Hamartar finkoa Engineering decimal Ingeniaritzako hamartarra Scientific decimal Hamartar zientifikoa General decimal Hamarar orokorra Angle unit Angelu unitatea Result format Emaitzaren formatua Clear E&xpression &Adierazpena Ezabatu Clear &History &Historia Garbitu &Degree &Gradu Delete All V&ariables &Aldagai Guztiak Ezabatu D&elete Variable... Aldagaia &Ezabatu... &15 Decimal Digits &15 digitu hamartar &2 Decimal Digits &2 digitu hamartar &3 Decimal Digits &3 digitu hamartar &50 Decimal Digits &50 digitu hamartar &8 Decimal Digits &8 digitu hamartar &Automatic Precision &Zehaztasun automatikoa &Copy &Kopiatu Copy Last &Result Kopiatu Azken &Emaitza &Paste &Itsatsi &About &Honi buruz About &Qt &QT-ri buruz SpeedCrunch &Web Site... SpeedCrunch &Web Gunea... &Tip of the Day Eguneko &Iradokizuna Insert &Function... &Funtzioa Sartu... Insert &Variable... &Aldagaia Sartu... &Partial Results &Tarteko Emaitzak Automatic &Completion Automatikoki &Osatu Always On &Top Beti &Gainean &Minimize To System Tray &Minimizatu Sistemaren Erretilura Syntax &Highlighting Sintaxia &Nabarmendu &System Default &Sistema Lehenetsia &Dot &Puntua &Comma &Koma &Radian &Radiana Scroll Display Down Labaindu Ikuspegia Beherantz Scroll Display Up Labaindu Ikuspegia Gorantz &Select Expression &Adierazpena Aukeratu &Import... &Inportatu... &Load... &Zamatu... &Quit &Irten &Save... &Gorde... &Export... &Esportatu... Math &Book Matematika &Liburua &Constants &Konstanteak Full &Screen Mode &Pantaila Bete Modua &Functions &Funtzioak &History &Historia &Keypad &Zenbakizko teklatua Hide &Menu Bar &Ezkutatu &Menu Barra &Status Bar &Egoera Barra &Variables &Aldagaiak &Binary &Bitarra &Engineering &Ingeniaritza &Fixed Decimal Hamartar &Finkoa &General &Orokorra &Hexadecimal &Hamaseitarra &Octal &Zortzitarra &Scientific &Zientifikoa System &Default Sistema &Lehenetsia &Session &Saioa &Edit &Editatu &View &Erakutsi Se&ttings &Ezarpenak Result &Format Emaitza &Formatua &Decimal &Hamartarra &Angle Unit &Angelu unitatea &Behavior &Portaera Radix &Character Hamartar Banatzeko &Karakterea &Language &Hizkuntza &Help &Laguntza About Qt Qt-ri buruz File %1 is not a valid session %1 fitxategia ez da saio balioduna SpeedCrunch Sessions (*.sch);;All Files (*) SpeedCrunch Saioak (*.sch);;Fitxategi Guztiak (*) Load Session Saioa Zamatu Error Akatsa Can't read from file %1 Ezin %1 fitxategitik irakurri Merge session being loaded with current session? If no, current variables and display will be cleared. Zamatzen ari den saioa uneko saioarekin bateratu? Ezezkotan, uneko aldagaiak eta bistaratzea garbitu egingo dira. Question Galdera All Files (*) Fitxategi Guztiak (*) Import Session Saioa Inportatu Merge session being imported with current session? If no, current variables and display will be cleared. Inportatzen ari den saioa uneko saioarekin bateratu?Ezezkotan, uneko aldagaiak eta bistaratzea garbitu egingo dira. Ignore error? Akatsak ezikusi? Save Session Saioa Gorde Can't write to file %1 Ezin %1 fitxategira idatzi Export Session Saioa Esportatu The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. Menu barra ezkutatuta dago. Berriz erakusteko, sakatu Ctrl+Alt+M. Warning Oharra To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Teklatua erailiz funtzio bat sartzeko, erabili Ktrl+F lasterbidea. Elkarrizketatik, sartu nahi duzun funtzioa aukeratu dezakezu. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Teklatua erailiz aldagai bat sartzeko, erabili Ktrl+I lasterbidea. Elkarrizketatik, sartu nahi duzun aldagaia aukeratu dezakezu. Use variable <i>pi</i> to use pi constant. Erabili <i>pi</i> aldagaia pi konstantea erabiltzeko. Use <i>;</i> (semicolon) to separate the parameters in functions. Erabili <i>;</i> (puntu eta koma) funtzioetako parametroak banatzeko. Tip of the day Eguneko iradokizuna SpeedCrunch is minimized. Left click the icon to restore it or right click for options. SpeedCrunch minimizatuta dago. Ezkerrez klikatu ikonoa leheneratzeko edo eskuinaz klikatu aukerak ikusteko. VariablesDock Variables Aldagaiak Search Bilatu No match found Ez da bat datorrenik aurkitu speedcrunch-0.10.1/src/i18n/he.ts0000644000175000001440000020042411015364561015574 0ustar helderusers AboutBox SpeedCrunch version %1 SpeedCrunch גירסה %1 Special thanks to תודה מיוחדת ל French צרפתית German גרמנית Portuguese פורטוגזית Russian רוסית Italian איטלקית This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version תכנית זו היא תוכנה חופשית; מותר להפיץ אותה ו/או לשנות אותה תחת תנאי הרישיון הציבורי הכללי של GNUהמפורסם על-ידי קרן התוכנה החופשית; גירסה 2 של הרישיון, או (לבחירתך) כל גירסה מאוחרת יותר This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. תכנית זו מופצת בתקווה שתהיה מועילה, אך ללא אחריות כלשהי; ואפילו ללא האחריות המשתמעת בדבר מסחריותה או התאמתה למטרה מסוימת. לפרטים נוספים, ראה את הרישיון הציבורי הכללי של GNU. About SpeedCrunch אודות SpeedCrunch Norwegian נורבגית Spanish ספרדית Original author יוצר מקורי Current maintainer מתחזק נוכחי Based on original idea from מבוסס על רעיון מקורי של Thanks to תודה ל ...and many others... ...ורבים אחרים... Translations תרגומים Brazilian Portuguese פורטוגזית ברזילאית Copyright (C) כל הזכויות שמורות (C) Visit <b>http://www.speedcrunch.org</b> for more information! בקרו ב-<b>http://www.speedcrunch.org</b> למידע נוסף! Argentinian Spanish ספרדית ארגנטינאית Dutch הולנדית Hebrew עברית Swedish שבדית Finnish פינית Czech צ'כית Romanian רומנית Developers מפתחים Indonesian אינדונזית Polish פולנית Turkish תורכית Close סגירה Graphics גרפיקה Basque Simplified Chinese Catalan BookDock Back אחורה Forward קדימה Index אינדקס ConstantCompletion All הכל Constants Characteristic Impedance of Vacuum היגב אופייני של ריק General Physics פיסיקה כללית Electric Constant קבוע חשמלי Magnetic Constant קבוע מגנטי Gravitation Constant קבוע כבידה Planck's Constant קבוע פלנק Dirac's Constant קבוע דירק Speed of Light in Vacuum מהירות האור בריק Bohr-Procopiu Magneton מגנטון בוהר-פרוקופיו Electromagnetic אלקטרומגנטי Conductance Quantum קוונט מוליכות Coulomb's Constant קבוע קולון Elementary Charge מטען יסודי Josephson Constant קבוע יוספסון Magnetic Flux Quantum קוונט שטף מגנטי Nuclear Magneton מגנטון גרעיני Resistance Quantum קוונט התנגדות von Klitzing Constant קבוע פון קליצינג Bohr Radius רדיוס בוהר Atomic & Nuclear אטומי וגרעיני Fermi Coupling Constant קבוע הצימוד של פרמי Fine-structure Constant קבוע המבנה העדין Hartree Energy אנרגיית הרטרי Quantum of Circulation קוונט סירקולציה Rydberg Constant קבוע רידברג Thomson Cross Section חתך פעולה של תומסון Weak Mixing Angle זווית ערבוב חלש Atomic Mass Unit יחידת מסה אטומית Physico-chemical פיסי-כימי Avogadro's Number מספר אבוגדרו Boltzmann Constant קבוע בולצמן Faraday Constant קבוע פארדי First Radiation Constant קבוע הקרינה הראשון Loschmidt Constant קבוע לושמידט Gas Constant קבוע הגזים Molar Planck Constant קבוע פלנק מולרי Second Radiation Constant קבוע הקרינה השני Stefan-Boltzmann Constant קבוע סטפן-בולצמן Astronomical Unit יחידה אסטרונומית Astronomy אסטרונומיה Light Year שנת אור Parsec פארסק Sidereal Year שנת שמש days ימים Tropical Year שנה טרופית Gregorian Year שנה גרגוריאנית Earth Mass מסה של כדור הארץ Sun Mass מסת השמש Mean Earth Radius רדיוס ממוצע של כדור הארץ Sun Radius רדיוס השמש Sun Luminosity בהירות השמש ConstantsDock Constants קבועים Category קטגוריה Search חיפוש No match found לא נמצאה אף התאמה All הכל DeleteVariableDlg Name שם Value ערך &Delete &מחיקה Close סגירה Delete Variable מחיקת משתנה Editor Current result: <b>%1</b> תוצאה נוכחית: <b>%1</b> Selection result: <b>%1</b> תוצאת הבחירה: <b>%1</b> Evaluator invalid expression ביטוי לא מובן division by zero חלוקה באפס unknown function or variable פונקציה או משתנה לא מזוהה variable cannot be overwritten לא ניתן להחליף את ערך המשתנה identifier matches an existing function name קיימת כבר פונקציה בשם זה Functions Absolute Value ערך מוחלט Average (Arithmetic Mean) ממוצע (מתימטי) Binary Representation ייצוג בינארי Cube Root שורש שלישי Ceiling עיגול מעלה Decimal Representation הצגה דצימלית Floor עיגול מטה Fractional Part החלק השבור Extension of Factorials [= (x-1)!] הרחבת עצרת [= (x-1)!] Geometric Mean ממוצע הנדסי Hexadecimal Representation הצגה הקסדצימלית Integer Part החלק השלם ln(abs(Gamma)) ln(abs(Gamma)) Maximum מקסימום Minimum מינימום Octal Representation הצגה אוקטאלית Product מכפלה Rounding עיגול Signum סימן Square Root שורש ריבועי Sum סכום Truncation קיצוץ Area Hyperbolic Cosine ארק קוסינוס היפרבולי Area Hyperbolic Sine ארק סינוס היפרבולי Area Hyperbolic Tangent ארק טנגנס היפרבולי Hyperbolic Cosine קוסינוס היפרבולי Exponential אקספוננט Base-2 Logarithm לוגריתם בבסיס 2 Natural Logarithm לוגריתם טבעי Base-10 Logarithm לוגריתם בבסיס 10 Hyperbolic Sine סינוס היפרבולי Hyperbolic Tangent טנגנס היפרבולי Greatest Common Divisor מחלק משותף גדול ביותר Combination (Binomial Coefficient) צירוף (מקדם בינומי) Permutation (Arrangement) תמורה (סידור) Binomial Cumulative Distribution Function פונקצית התפלגות בינומית מצטברת Binomial Distribution Mean ממוצע של התפלגות בינומית Binomial Probability Mass Function פונקצית מסה של הסתברות בינומית Binomial Distribution Variance שונות של התפלגות בינומית Error Function פונקצית שגיאה Complementary Error Function פונקצית שגיאה משלימה Hypergeometric Cumulative Distribution Function פונקצית התפלגות היפר גיאומטרית מצטברת Hypergeometric Distribution Mean ממוצע של התפלגות היפר גיאומטרית Hypergeometric Probability Mass Function פונקצית מסה של הסתברות היפר גיאומטרית Hypergeometric Distribution Variance שונות של התפלגות היפר גיאומטרית Poissonian Cumulative Distribution Function פונקצית התפלגות פואסונית מצטברת Poissonian Distribution Mean ממוצע של התפלגות פואסונית Poissonian Probability Mass Function פונקצית מסה של הסתברות פואסונית Poissonian Distribution Variance שונות של התפלגות פואסונית Arc Cosine ארק קוסינוס Arc Sine ארק סינוס Arc Tangent ארק טנגנס Cosine קוסינוס Cotangent קוטנגנס Cosecant קוסקנס Degrees of Arc מעלות קשת Radians רדיאנים Secant סקנס Sine סינוס Tangent טנגנס Mask to a bit size מיסוך לגודל בסיביות Sign-extent a value הרחבת-סימן לערך Logical NOT NOT לוגי Logical AND AND לוגי Logical OR OR לוגי Logical XOR XOR לוגי Arithmetic Shift Left הזזה אריתמטית שמאלה Arithmetic Shift Right הזזה אריתמטית ימינה Integer Quotient מנה שלמה Modulo מודולו cannot execute function %1 אי אפשר להפעיל את הפונקציה %1 function accepts 1 argument הפונקציה מקבלת פרמטר אחד function accepts %1 arguments הפונקציה מקבלת %1 פרמטרים function requires 1 or 2 arguments הפונקציה דורשת פרמטר או שני פרמטרים function undefined for specified arguments פונקציה לא מוגדרת בתחום הפרמטרים function requires at least 2 arguments הפונקציה דורשת לפחות שני פרמטרים function requires integer arguments הפונקציה דורשת פרמטרים שלמים function undefined for specified argument פונקציה לא מוגדרת בתחום הפרמטרים underflow חמיקה (underflow) function requires at least 1 argument הפונקציה דורשת פרמטר אחד לפחות FunctionsDock Functions פונקציות Search חיפוש No match found לא נמצאה אף התאמה HistoryDock History היסטוריה InsertFunctionDlg Name שם Description תיאור &Insert &הוספה Cancel ביטול Insert Function הוספת פונקציה InsertVariableDlg Name שם Value ערך &Insert &הוספה Insert Variable הכנסת משתנה Cancel ביטול Keypad Inverse cosine קוסינוס הפוך The last result התוצאה האחרונה Inverse sine סינוס הפוך Inverse tangent טנגנס הפוך Clear expression ניקוי ביטוי Cosine קוסינוס Scientific notation סימון מדעי Exponential אקספוננט Natural logarithm לוגריתם טבעי Sine סינוס Square root שורש ריבועי Tangent טנגנס Assign variable x הצב ערך למשתנה x The variable x המשתנה x MainWindow About Qt אודות Qt SpeedCrunch Sessions (*.sch);;All Files (*) חישובי SpeedCrunch (*.sch);;כל הקבצים (*) Load Session טעינת חישוב Error שגיאה Can't read from file %1 לא ניתן לקרוא מהקובץ %1 Question שאלה Save Session שמירת חישובים אחרונים Can't write to file %1 לא ניתן לכתוב לקובץ %1 Warning אזהרה To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. אפשר להוסיף פונקציה בעזרת המקלדת, באמצעות הקיצור Ctrl+F.ניתן לבחור את הפונקציה הרצויה מתוך החלון שייפתח. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. אפשר להוסיף משתנה בעזרת המקלדת, באמצעות הקיצור Ctrl+I. ניתן לבחור את המשתנה הרצוי מתוך החלון שייפתח. Use variable <i>pi</i> to use pi constant. כדי להשתמש בקבוע פיי, השתמשו ב-<i>pi</i>. Use <i>;</i> (semicolon) to separate the parameters in functions. ניתן להשתמש ב-<i>:</i> (נקודותיים) כדי להפריד בין פרמטרים של פונקציות. Tip of the day טיפ היום File %1 is not a valid session הקובץ %1 אינו מכיל חישוב Merge session being loaded with current session? If no, current variables and display will be cleared. להוסיף את החישוב שנטען לחישוב הנוכחי? אם לא, המשתנים הנוכחיים והתצוגה יימחקו. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. SpeedCrunch ממוזערת. לחץ על האיקון לחיצה שמאלית כדי לשחזר אותה או לחיצה ימנית לאפשרויות. Degree מעלה All Files (*) כל הקבצים (*) Radian רדיאן The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. פס התפריט הוסתר. כדי להחזיר אותו, לחץ Ctrl+Alt+M. Binary בינארי Engineering decimal נקודה עשרונית הנדסית Fixed decimal נקודה עשרונית קבועה General decimal נקודה עשרונית כללית Hexadecimal הקסדצימלי Octal אוקטלי Scientific decimal נקודה עשרונית מדעית Import Session יבוא חישוב Merge session being imported with current session? If no, current variables and display will be cleared. להוסיף את החישוב שמיובא לחישוב הנוכחי?אם לא, המשתנים הנוכחיים והתצוגה יימחקו. Export Session יצוא חישוב &Session &קובץ Clear E&xpression &ניקוי חישוב Clear &History ניקוי &היסטוריה &Degree &מעלה Delete All V&ariables &מחיקת כל המשתנים D&elete Variable... מ&חיקת משתנה... &15 Decimal Digits &15 ספרות עשרוניות &2 Decimal Digits &2 ספרות עשרוניות &3 Decimal Digits &3 ספרות עשרוניות &50 Decimal Digits &50 ספרות עשרוניות &8 Decimal Digits &8 ספרות עשרוניות &Automatic Precision &דיוק אוטומטי &Copy ה&עתקה Copy Last &Result העתקת &תוצאה אחרונה &Paste ה&דבקה &About &אודות About &Qt אודות &Qt SpeedCrunch &Web Site... אתר &SpeedCrunch... &Tip of the Day ה&טיפ היומי Insert &Function... הכנסת &פונקציה... Insert &Variable... הכנסת &משתנה... &Partial Results תוצאות &חלקיות Automatic &Completion השלמה &אוטומטית Always On &Top תמיד &עליון &Minimize To System Tray &מזעור לאזור ההודעות Syntax &Highlighting &הדגשת דקדוק &System Default &ברירת מחדל &Dot &נקודה &Comma &פסיק &Radian &רדיאן Scroll Display Down גלילת התצוגה מטה Scroll Display Up גלילת התצוגה מעלה &Select Expression &בחירת ביטוי &Import... י&בוא... &Load... &טעינה... &Quit &יציאה &Save... &שמירת חישובים אחרונים... &Export... י&צוא... Math &Book &ספר מתימטיקה &Constants &קבועים Full &Screen Mode מצב מסך מ&לא &Functions &פונקציות &History &היסטוריה &Keypad &מקשי ספרות Hide &Menu Bar הסתר פס &תפריט &Status Bar פס המ&צב &Variables מ&שתנים &Binary &בינארי &Engineering &הנדסי &Fixed Decimal &נקודה עשרונית קבועה &General &כללי &Hexadecimal ה&קסדצימלי &Octal &אוקטלי &Scientific &מדעי System &Default &ברירת מחדל &Edit &עריכה &View &תצוגה Se&ttings &הגדרות Result &Format &תסדיר תוצאה &Decimal &דצימלי &Angle Unit יחידות &זוית &Behavior &התנהגות Radix &Character &תו בסיס &Language &שפה &Help ע&זרה Angle unit יחידות זוית Result format תסדיר תוצאה Math Book ספר מתימטיקה Ignore error? להתעלם מהשגיאה? VariablesDock Variables משתנים Search חיפוש No match found לא נמצאה אף התאמה speedcrunch-0.10.1/src/i18n/es.ts0000644000175000001440000017475511015364561015630 0ustar helderusers AboutBox Special thanks to Agradecimientos especiales a French Francés German Alemán Portuguese Portugués Russian Ruso Italian Italiano This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Este programa es software libre; puede ser redistribuido y/o modificado bajo los términos de la GNU General Public License como fue publicada por la Free Software Foundation; ya sea la versión 2 de la Licencia, o (a su elección), cualquier versión posterior This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Este programa se distribuye con la idea de que será útil, pero SIN NINGUNA GARANTÍA; ni siquiera la garantía implícita de SER COMERCIAL o SER ADECUADO PARA ALGÚN PROPÓSITO PARTICULAR. Vea la GNU General Public LIcense para más detalles. SpeedCrunch version %1 SpeedCrunch versión %1 Norwegian Noruego Spanish Español About SpeedCrunch Acerca de SpeedCrunch Original author Autor original Current maintainer Responsable actual Based on original idea from Basado en una idea original de Thanks to Gracias a ...and many others... ...y muchos otros... Translations Traducciones Brazilian Portuguese Portugués Brasileño Copyright (C) Copyright (C) Visit <b>http://www.speedcrunch.org</b> for more information! ¡Para más información visite <b>http://www.speedcrunch.org</b>! Argentinian Spanish Español Argentino Dutch Neerlandés Hebrew Hebreo Swedish Sueco Finnish Finés Czech Checo Romanian Rumano Developers Desarrolladores Indonesian Indonesio Close Cerrar Graphics Gráficos Polish Polaco Turkish Turco Basque Vasco Simplified Chinese Catalan BookDock Back Atrás Forward Adelante Index Índice ConstantCompletion All Todo Constants Characteristic Impedance of Vacuum Impedancia Característica del Vacío General Physics Física General Electric Constant Constante Eléctrica Magnetic Constant Constante Magnética Gravitation Constant Constante Gravitacional Planck's Constant Constante de Planck Dirac's Constant Constante de Dirac Speed of Light in Vacuum Velocidad de la Luz en el Vacío Bohr-Procopiu Magneton Magneto Bohr-Procopiu Electromagnetic Electromagnetismo Conductance Quantum Conductancia Cuántica Coulomb's Constant Constante de Coulomb Elementary Charge Carga Elemental Josephson Constant Constante de Josephson Magnetic Flux Quantum Flujo Magnético Cuántico Nuclear Magneton Magneto Nuclear Resistance Quantum Resistencia Cuántica von Klitzing Constant Constante de von Klitzing Bohr Radius Radio de Bohr Atomic & Nuclear Atómico & Nuclear Fermi Coupling Constant Constante de Acoplamiento de Fermi Fine-structure Constant Constante de Estructura Fina Hartree Energy Energía Hartree Quantum of Circulation Cuanto de Circulación Rydberg Constant Constante de Rydberg Thomson Cross Section Sección Eficaz de Thomson Weak Mixing Angle Ángulo de Weinberg Atomic Mass Unit Unidad de Masa Atómica Physico-chemical Físico-químico Avogadro's Number Número de Avogadro Boltzmann Constant Constante de Boltzmann Faraday Constant Constante de Faraday First Radiation Constant Primera Constante de Radiación Loschmidt Constant Constante de Loschmidt Gas Constant Constante Universal de los Gases Ideales Molar Planck Constant Constante Molar de Planck Second Radiation Constant Segunda Constante de Radiación Stefan-Boltzmann Constant Constante de Stefan-Boltzmann Astronomical Unit Unidad Astronómica Astronomy Astronomía Light Year Año Luz Parsec Pársec Sidereal Year Año Sideral days días Tropical Year Año Tropical Gregorian Year Año Gregoriano Earth Mass Masa Terrestre Sun Mass Masa Solar Mean Earth Radius Radio Terrestre Sun Radius Radio Solar Sun Luminosity Luminosidad Solar ConstantsDock Constants Constantes Category Categoría Search Búsqueda No match found No se encontraron coincidencias All Todo DeleteVariableDlg Name Nombre Value Valor &Delete &Borrar Close Cerrar Delete Variable Borrar Variable Editor Current result: <b>%1</b> Resultado actual: <b>%1</b> Selection result: <b>%1</b> Resultado de la selección: <b>%1</b> Evaluator invalid expression expresión inválida division by zero división por cero unknown function or variable función o variable desconocida variable cannot be overwritten variable no puede ser sobrescrita identifier matches an existing function name identificador es igual al nombre de una función existente Functions Absolute Value Valor Absoluto Average (Arithmetic Mean) Promedio (Media Aritmética) Binary Representation Representación Binaria Cube Root Raiz Cúbica Ceiling Techo Decimal Representation Representación Decimal Floor Piso Fractional Part Parte Fraccional Geometric Mean Media Geométrica Hexadecimal Representation Representación Hexadecimal Integer Part Parte Entera Maximum Máximo Minimum Mínimo Octal Representation Representación Octal Product Producto Rounding Redondeo Signum Signum Square Root Raíz Cuadrada Sum Suma Truncation Truncar Hyperbolic Cosine Coseno Hiperbólico Exponential Exponencial Base-2 Logarithm Logaritmo Binario Natural Logarithm Logaritmo Natural Base-10 Logarithm Logaritmo Base 10 Hyperbolic Sine Seno Hiperbólico Hyperbolic Tangent Tangente Hiperbólica Greatest Common Divisor Mayor Común Divisor Combination (Binomial Coefficient) Combinación (Coeficiente Binomial) Permutation (Arrangement) Permutación (Reordenamiento) Binomial Cumulative Distribution Function Función de Distribución Acumulada Binomial Binomial Distribution Mean Media de Distribución Binomial Binomial Probability Mass Function Función de Probabilidad de Masa Binomial Binomial Distribution Variance Variación de Distribución Binomial Hypergeometric Cumulative Distribution Function Función de Distribución Acumulada Hipergeométrica Hypergeometric Distribution Mean Media de Distribución Hipergeométrica Hypergeometric Probability Mass Function Función de Masa de Probabilidad Hipergeométrica Hypergeometric Distribution Variance Variación de Distribución Hipergeométrica Poissonian Cumulative Distribution Function Función de Distribución Acumulada de Poisson Poissonian Distribution Mean Media de Distribución de Poisson Poissonian Probability Mass Function Función de Masa de Probabilidad de Poisson Poissonian Distribution Variance Variación de Distribución de Poisson Arc Cosine Arc Coseno Arc Sine Arc Seno Arc Tangent Arc Tangente Cosine Coseno Cotangent Cotangente Cosecant Cosecante Radians Radianes Secant Secante Sine Seno Tangent Tangente cannot execute function %1 no es posible ejecutar función %1 function accepts 1 argument la función acepta un argumento function accepts %1 arguments la función acepta %1 argumento function requires 1 or 2 arguments la función requiere 1 ó 2 argumentos function undefined for specified arguments la función no está definida para los argumentos especificados function requires at least 2 arguments la función requiere al menos 2 argumentos function requires integer arguments la función requiere argumentos enteros function undefined for specified argument la función no está definida para el argumento especificado underflow cantidad demasiado pequeña function requires at least 1 argument la función requiere al menos un argumento Extension of Factorials [= (x-1)!] Extensión de Factoriales [= (x-1)!] ln(abs(Gamma)) ln(abs(Gamma)) Area Hyperbolic Cosine Área de Coseno Hiperbólico Area Hyperbolic Sine Área de Seno Hiperbólico Area Hyperbolic Tangent Área de Tangente Hiperbólica Error Function Función errónea Complementary Error Function Función Complementaria Errónea Degrees of Arc Grados del Arco Mask to a bit size Máscara a tamaño de bit Sign-extent a value Extender el signo de un valor Logical NOT NOT Lógico Logical AND AND Lógico Logical OR OR Lógico Logical XOR XOR Lógico Arithmetic Shift Left Cambio Aritmético a Izquierda Arithmetic Shift Right Cambio Aritmético a Derecha Integer Quotient Cociente de un Entero Modulo Módulo FunctionsDock Functions Funciones Search Búsqueda No match found No se encontraron coincidencias HistoryDock History Historial InsertFunctionDlg Name Nombre Description Descripción &Insert &Insertar Cancel Cancelar Insert Function Insertar Función InsertVariableDlg Name Nombre Value Valor &Insert &Insertar Cancel Cancelar Insert Variable Insertar Variable Keypad Inverse cosine Coseno inverso The last result El último resultado Inverse sine Seno inverso Inverse tangent Tangente inversa Clear expression Borrar expresión Cosine Coseno Scientific notation Notación científica Exponential Exponencial Natural logarithm Logaritmo natural Sine Seno Square root Raíz cuadrada Tangent Tangente Assign variable x Asignar variable x The variable x La variable x MainWindow About Qt Acerca de Qt SpeedCrunch Sessions (*.sch);;All Files (*) Sesiones de SpeedCrunch (*.sch);;Todos los Ficheros (*) Load Session Cargar Sesión Error Error Can't read from file %1 No puede leerse desde el archivo %1 Question Pregunta Save Session Guardar Sesión Can't write to file %1 No se puede escribir en el archivo %1 Warning Advertencia To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Para insertar una función usando el teclado, pulse Ctrl+F. Desde la ventana, usted puede escoger la función que quiera insertar. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Para insertar una variable usando el teclado, pulse Ctrl+I. Desde la ventana, usted puede escoger la variable que quiera insertar. Use variable <i>pi</i> to use pi constant. Use la variable <i>pi</i> para usar la constante pi. Use <i>;</i> (semicolon) to separate the parameters in functions. Use <i>;</i> (punto y coma) para separar los parámetros en las funciones. Tip of the day Consejo del día File %1 is not a valid session Archivo %1 no es una sesión válida Merge session being loaded with current session? If no, current variables and display will be cleared. ¿Combinar sesión que está siendo cargada con la sesión actual? Si no es así, las variables actuales y la pantalla serán borradas. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. SpeedCrunch está minimizado. Hacer clic en el icono con el botón izquierdo para restaurarlo o con el botón derecho para mostrar opciones. Degree Grado All Files (*) Todos los Archivos (*) Radian Radian The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. La barra de menú ahora está oculta. Para hacerla visible de nuevo, pulsar Ctrl+Alt+M. Binary Binario Engineering decimal Decimal ingeniería Fixed decimal Decimal fija General decimal Decimal genérica Hexadecimal Hexadecimal Octal Octal Scientific decimal Decimal científica Import Session Importar Sesión Merge session being imported with current session? If no, current variables and display will be cleared. ¿Combinar sesión que está siendo importada con la sesión actual? Si no es así, las variables actuales y la pantalla serán borradas. Export Session Exportar Sesión Math Book Libro de Matemáticas &Session &Sesión Clear E&xpression Borrar E&xpresión Clear &History Borrar &Historial &Degree Gra&do Delete All V&ariables Borrar Todas las V&ariables D&elete Variable... &Borrar Variable... &15 Decimal Digits &15 Dígitos Decimales &2 Decimal Digits &2 Dígitos Decimales &3 Decimal Digits &3 Dígitos Decimales &50 Decimal Digits &50 Dígitos Decimales &8 Decimal Digits &8 Dígitos Decimales &Automatic Precision Prec&isión Automática &Copy &Copiar Copy Last &Result Copiar el Último &Resultado &Paste &Pegar &About &Acerca de About &Qt Acerca de &Qt SpeedCrunch &Web Site... Sitio &Web SpeedCrunch... &Tip of the Day &Consejo del Día Insert &Function... Insertar &Función... Insert &Variable... Insertar &Variable... &Partial Results Resultados &Parciales Automatic &Completion &Completado Automático Always On &Top Siempre &Encima &Minimize To System Tray &Minimizar a Área de Notificación del Sistema Syntax &Highlighting &Resaltado de la Sintaxis &System Default Defecto (&Sistema) &Dot &Punto &Comma &Coma &Radian &Radian Scroll Display Down Desplazar Pantalla Abajo Scroll Display Up Desplazar Pantalla Arriba &Select Expression &Seleccionar Expresión &Import... &Importar... &Load... &Cargar... &Quit &Salir &Save... &Guardar... &Export... &Exportar... Math &Book &Libro de Matemáticas &Constants &Constantes Full &Screen Mode Modo &Pantalla Completa &Functions &Funciones &History &Historial &Keypad &Teclado Numérico Hide &Menu Bar Ocultar Barra de &Menú &Status Bar Barra de &Estado &Variables &Variables &Binary &Binario &Engineering Ing&eniería &Fixed Decimal Punto Decimal Fi&jo &General Ge&neral &Hexadecimal &Hexadecimal &Octal &Octal &Scientific &Científica System &Default &Defecto (Sistema) &Edit &Editar &View &Ver Se&ttings &Configuración Result &Format &Formato del Resultado &Decimal &Decimal &Angle Unit Unidad &Angular &Behavior &Comportamiento Radix &Character &Carácter Separador Entero-Fracción &Language &Idioma &Help A&yuda Angle unit Unidad angular Result format Formato del resultado Ignore error? ¿Ignorar error? VariablesDock Variables Variables Search Búsqueda No match found No se encontraron coincidencias speedcrunch-0.10.1/src/i18n/cs.ts0000644000175000001440000017333711015364561015621 0ustar helderusers AboutBox Special thanks to Speciální poděkování French Francouzsky German Německy Portuguese Portugalsky Russian Rusky Italian Italsky This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Tento program je volný software; můžete jej šířit a/nebo modifikovat podle ustanovení Obecné veřejné licence GNU, vydávané Free Software Foundation; a to buď verze 2 této licence anebo (podle vašeho uvážení) kterékoli pozdější verze This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Tento program je rozšiřován v naději, že bude užitečný, avšak BEZ JAKÉKOLI ZÁRUKY; neposkytují se ani odvozené záruky PRODEJNOSTI anebo VHODNOSTI PRO URČITÝ ÚČEL. Další podrobnosti hledejte v Obecné veřejné licenci GNU (její české znění přikládáme, je dostupné též na http://www.gnu.cz, anglický originál na http://www.gnu.org/copyleft/gpl.html). SpeedCrunch version %1 Verze SpeedCrunch %1 About SpeedCrunch O SpeedCrunch Norwegian Norsky Spanish Španělsky Original author Původní autor Current maintainer Nynější správce Based on original idea from Založeno na původním nápadu Thanks to Poděkování ...and many others... ...a mnoho dalších... Translations Překlady Brazilian Portuguese Brazilská portugalština Copyright (C) Copyright (C) Visit <b>http://www.speedcrunch.org</b> for more information! Pro více informací navštivte <b>b>http://www.speedcrunch.org</b>! Argentinian Spanish Argentinská španělština Dutch Dánsky Hebrew Hebrejština Swedish Švédština Finnish Finština Czech Čeština Romanian Rumunština Developers Indonesian Close zavřít Graphics Polish Turkish Basque Simplified Chinese Catalan BookDock Back Forward Index ConstantCompletion All Vše Constants Characteristic Impedance of Vacuum Impedance vakua General Physics Obecná fyzika Electric Constant Elektrická konstanta Magnetic Constant magnetická konstanta Gravitation Constant Gravitační konstanta Planck's Constant Planckova konstanta Dirac's Constant Dirackova konstanta Speed of Light in Vacuum Rychlost světla ve vákuu Bohr-Procopiu Magneton Bohrův magneton Electromagnetic Elektromagmetismus Conductance Quantum Kvantum elektrické vodivosti Coulomb's Constant Coulombova konstanta Elementary Charge Elementární náboj Josephson Constant Magnetic Flux Quantum Kvantum magnetického toku Nuclear Magneton Jaderný magneton Resistance Quantum von Klitzing Constant Bohr Radius Bohrův poloměr Atomic & Nuclear atom & jádro Fermi Coupling Constant Fine-structure Constant Konstanta jemné struktury Hartree Energy Hartreejova energie Quantum of Circulation Rydberg Constant Rydbergova konstanta Thomson Cross Section Weak Mixing Angle Slabý směšovací ůhel Atomic Mass Unit Atomová hmotnostní konstanta Physico-chemical Fyzikálně-chemické Avogadro's Number Avogadrova konstanta Boltzmann Constant Boltzmannova konstanta Faraday Constant Faradayova konstanta First Radiation Constant Loschmidt Constant Gas Constant Molární plynová konstanta Molar Planck Constant Second Radiation Constant Stefan-Boltzmann Constant Stefanova-Boltzmannova konstanta Astronomical Unit Astronomická jednotka Astronomy Astronomie Light Year Světelný rok Parsec Parsek Sidereal Year Hvězdný (siderický) rok days dní Tropical Year Tropický rok Gregorian Year Gregoriánský rok Earth Mass Hmotnost Země Sun Mass Hmotnost slunce Mean Earth Radius Střední poloměr Země Sun Radius Poloměr slunce Sun Luminosity Světelnost slunce ConstantsDock Constants Konstanty Category Kategorie Search Hledání No match found Nenalezena žádná shoda All Vše DeleteVariableDlg Name Název Value Hodnota &Delete &Smazat Close zavřít Delete Variable Smazat proměnou Editor Current result: <b>%1</b> Selection result: <b>%1</b> Evaluator invalid expression division by zero unknown function or variable variable cannot be overwritten identifier matches an existing function name Functions Absolute Value Absolutní hodnota Average (Arithmetic Mean) Průměr (Aritmetický) Binary Representation Binární vyjádření Cube Root Třetí odmocnina Ceiling Zaokrouhlení zlomků nahoru Decimal Representation Desítkové vyjádření Floor Zaokrouhlení zlomků dolů Fractional Part Desetiná část Geometric Mean Geometrický průměr Hexadecimal Representation Hexadecimální vyjádření Integer Part Celočíselná část Maximum Maximum Minimum Minimum Octal Representation Osmičková vyjádření Product Násobení Rounding Zaokrouhlení Signum Signum Square Root Odmocnina Sum Suma Truncation Ořezání Hyperbolic Cosine Hyperbolic Cosine Base-2 Logarithm Dvojkový logaritmus Natural Logarithm Přilozený logaritmus Base-10 Logarithm Desítkový logaritmus Hyperbolic Sine Hyperbolic Sine Hyperbolic Tangent Hyperbolic Tangent Greatest Common Divisor Největší celočíselný dělitel Combination (Binomial Coefficient) Kombinace (Kombinační číslo) Permutation (Arrangement) Permutace Arc Cosine Arc Cosinus Arc Sine Arc Sinus Arc Tangent Arc Tangens Cosine Cosinus Cotangent Cotangent Cosecant Kosekans Radians Radiány Secant Sekans Sine Sinus cannot execute function %1 nelze spustit funkci %1 function accepts 1 argument funkce akceptuje 1 argument function accepts %1 arguments funkce akceptuje %1 argumentů function requires 1 or 2 arguments funkce vyžaduje 1 nebo 2 argumenty function undefined for specified arguments funkce není definována pro specifikované argumenty function requires at least 2 arguments funkce vyžaduje alespoň 2 argumenty function requires integer arguments funkce vyžaduje celočíselné argumenty function undefined for specified argument funkce není definována pro specifikovaný argument underflow function requires at least 1 argument funkce vyžaduje alespoň 1 argument Extension of Factorials [= (x-1)!] ln(abs(Gamma)) Area Hyperbolic Cosine Area Hyperbolic Sine Area Hyperbolic Tangent Exponential Binomial Cumulative Distribution Function Binomial Distribution Mean Binomial Probability Mass Function Binomial Distribution Variance Error Function Complementary Error Function Hypergeometric Cumulative Distribution Function Hypergeometric Distribution Mean Hypergeometric Probability Mass Function Hypergeometric Distribution Variance Poissonian Cumulative Distribution Function Poissonian Distribution Mean Poissonian Probability Mass Function Poissonian Distribution Variance Degrees of Arc Tangent Mask to a bit size Sign-extent a value Logical NOT Logical AND Logical OR Logical XOR Arithmetic Shift Left Arithmetic Shift Right Integer Quotient Modulo FunctionsDock Functions Funkce Search Hledání No match found Nenalezena žádná shoda HistoryDock History Historie' InsertFunctionDlg Name Název Description Popis &Insert Vlož&it Cancel Storno Insert Function Vložit funkci InsertVariableDlg Name Název Value Hodnota &Insert Vlož&it Cancel Storno Insert Variable Vložit proměnou Keypad Inverse cosine inverzní cosinus The last result Inverse sine Inverzní sinus Inverse tangent inverzní tangent Clear expression Cosine Cosinus Scientific notation Exponential Natural logarithm Sine Sinus Square root Odmocnina Tangent Assign variable x The variable x MainWindow About Qt O Qt SpeedCrunch Sessions (*.sch);;All Files (*) Load Session Error Chyba Can't read from file %1 Question Save Session Uložit sezení Can't write to file %1 Nemohu zapisovat do souboru %1 Warning To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Pro vložení funkce pomocí klávesnnice použijte klávesovou zkratku Ctrl+F. Z dialogu si můžete vybrat funkci, kterou chcete vložit. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Pro vložení proměnné pomocí klávesnnice použijte klávesovou zkratku Ctrl+I. Z dialogu si můžete vybrat proměnnou, kterou chcete vložit. Use variable <i>pi</i> to use pi constant. Použijte proměnou <i>pi</i> pro konstantu pí. Use <i>;</i> (semicolon) to separate the parameters in functions. Tip of the day File %1 is not a valid session Merge session being loaded with current session? If no, current variables and display will be cleared. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. Degree All Files (*) Radian The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. Binary Engineering decimal Fixed decimal General decimal Hexadecimal Octal Scientific decimal Import Session Merge session being imported with current session? If no, current variables and display will be cleared. Export Session Math Book &Session &Sezení Clear E&xpression Clear &History Smazat &historii &Degree Delete All V&ariables D&elete Variable... Smazat &proměnou... &15 Decimal Digits &15 Desetiných míst &2 Decimal Digits &2 Desetiná místa &3 Decimal Digits &3 Desetiná místa &50 Decimal Digits &50 Desetiných míst &8 Decimal Digits &8 Desetiných míst &Automatic Precision &Automatická přesnost &Copy K&opírovat Copy Last &Result &Paste &Vložit &About O &aplikaci About &Qt O &Qt SpeedCrunch &Web Site... &Webstránky SpeedCrunch... &Tip of the Day &Tip dne Insert &Function... Vložit &funkci... Insert &Variable... &Vložit proměnou... &Partial Results Automatic &Completion Always On &Top &Minimize To System Tray Syntax &Highlighting &System Default &Dot &Comma &Radian Scroll Display Down Scroll Display Up &Select Expression &Import... &Load... &Quit &Konec &Save... &Uložit... &Export... Math &Book &Constants Full &Screen Mode &Functions &History &Keypad Hide &Menu Bar &Status Bar &Variables &Binary &Binární &Engineering Inž&enýrský &Fixed Decimal &Pevný počet desetiných míst &General &Hexadecimal &Hexadecimální &Octal &Osmičková &Scientific &Vědecký System &Default &Edit &Editovat &View &Zobrazení Se&ttings Nas&tavení Result &Format &Decimal &Angle Unit &Behavior Radix &Character &Language &Help &Nápověda Angle unit Result format Ignore error? VariablesDock Variables Proměnné Search Hledání No match found Nenalezena žádná shoda speedcrunch-0.10.1/src/i18n/de.ts0000644000175000001440000017525311015364561015603 0ustar helderusers AboutBox Special thanks to Mit besonderem Dank an French Französisch German Deutsch Portuguese Portugiesisch Russian Russisch Italian Italienisch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU General Public License Version 2 (GPL), wie von der Free Software Foundation herausgegeben, weitergeben This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Dieses Programm ist frei erhältlich in der Hoffnung es könnte von Nutzen sein. Die Veröffentlichung dieses Programms erfolgt OHNE JEDE GEWAEHRLEISTUNG. Details finden Sie in der GNU General Public License (GPL). SpeedCrunch version %1 SpeedCrunch - Version %1 About SpeedCrunch Über SpeedCrunch Norwegian Norwegisch Spanish Spanisch Original author Ursprünglicher Autor Current maintainer Aktueller Betreuer Based on original idea from Basiert auf dem Konzept von Thanks to Vielen Dank an ...and many others... ... und viele andere... Translations Übersetzungen Brazilian Portuguese Portugiesisch (Brasilien) Copyright (C) Copyright (C) Visit <b>http://www.speedcrunch.org</b> for more information! Besuchen Sie <b>http://www.speedcrunch.org</b> für weitere Informationen! Argentinian Spanish Argentinisches Spanisch Dutch Niederländisch Hebrew Hebräisch Swedish Schwedisch Finnish Finnisch Czech Tschechisch Romanian Rumänisch Developers Entwickler Indonesian Indonesisch Polish Polnisch Turkish Türkisch Close Schließen Graphics Grafiken Basque Baskisch Simplified Chinese Chinesisch, Kurzzeichen Catalan Katalanisch BookDock Back Zurück Forward Vorwärts Index Index ConstantCompletion All Alle Constants Characteristic Impedance of Vacuum Charakteristische Impedanz des Vakuums General Physics Allgemeine Physik Electric Constant Elektrische Feldkonstante Magnetic Constant Magnetische Feldkonstante Gravitation Constant Gravitationskonstante Planck's Constant Plancksches Wirkungsquantum Dirac's Constant Diracsche Konstante Speed of Light in Vacuum Lichtgeschwindigkeit im Vakuum Bohr-Procopiu Magneton Bohrsches Magneton Electromagnetic Elektromagnetisch Conductance Quantum Quantum der Leitfähigkeit Coulomb's Constant Coulombsche Konstante Elementary Charge Elementarladung Josephson Constant Josephson-Konstante Magnetic Flux Quantum Magnetisches Flussquantum Nuclear Magneton Kern-Magneton Resistance Quantum Widerstandsquantum von Klitzing Constant von-Klitzing-Konstante Bohr Radius Bohrscher Radius Atomic & Nuclear Atomar & Nuklear Fermi Coupling Constant Fermi-Kopplungskonstante Fine-structure Constant Feinstrukturkonstante Hartree Energy Hartree-Energie Quantum of Circulation Quantum des Umlaufintegrals Rydberg Constant Rydberg-Konstante Thomson Cross Section Thomson-Wirkungsquerschnitt Weak Mixing Angle Elektroschwacher Mischungswinkel Atomic Mass Unit Atomare Masseneinheit Physico-chemical Physikalischen Chemie Avogadro's Number Avogadro-Konstante Boltzmann Constant Boltzmannkonstante Faraday Constant Faraday-Konstante First Radiation Constant Erste Strahlungskonstante Loschmidt Constant Loschmidt-Konstante Gas Constant Universelle Gaskonstante Molar Planck Constant Molare Planckkonstante Second Radiation Constant Zweite Strahlungskonstante Stefan-Boltzmann Constant Stefan-Boltzmann-Konstante Astronomical Unit Astronomische Einheit Astronomy Astronomie Light Year Lichtjahr Parsec Parsec Sidereal Year Siderisches Jahr days Tage Tropical Year Tropisches Jahr Gregorian Year Gregorianisches Jahr Earth Mass Masse der Erde Sun Mass Masse der Sonne Mean Earth Radius Mittlerer Radius der Erde Sun Radius Radius der Sonne Sun Luminosity Leuchtkraft der Sonne ConstantsDock Constants Konstanten Category Kategorie Search Suche No match found Keine Übereinstimmung All Alle DeleteVariableDlg Name Name Value Wert &Delete Lösch&e Close Schließen Delete Variable Lösche Variable Editor Current result: <b>%1</b> Aktuelles Ergebnis: <b>%1</b> Selection result: <b>%1</b> Auswahlergebnis: <b>%1</b> Evaluator invalid expression ungültiger Ausdruck division by zero Division durch null unknown function or variable Unbekannte Funktion oder Variable variable cannot be overwritten Variable kann nicht überschrieben werden identifier matches an existing function name Bezeichner ist identisch mit einem Funktionsnamen Functions Absolute Value Absolutwert Average (Arithmetic Mean) Durchschnitt (Arithmetisches Mittel) Binary Representation Binärdarstellung Cube Root Kubische Wurzel Ceiling Obere Gaußklammer Decimal Representation Dezimaldarstellung Floor Untere Gaußklammer Fractional Part Nachkommastellen Geometric Mean Geometrisches Mittel Hexadecimal Representation Hexadezimaldarstellung Integer Part Ganzzahliger Anteil Maximum Maximum Minimum Minimum Octal Representation Oktaldarstellung Product Produkt Rounding Runden Signum Signum Square Root Quadratwurzel Sum Summe Truncation Nachkommastellen abschneiden Area Hyperbolic Cosine Areakosinus Hyperbolicus Area Hyperbolic Sine Areasinus Hyperbolicus Area Hyperbolic Tangent Areatangens Hyperbolicus Hyperbolic Cosine Cosinus Hyperbolicus Exponential Exponentialfunktion Base-2 Logarithm Logarithmus zur Basis 2 Natural Logarithm Natürlicher Logarithmus Base-10 Logarithm 10er Logarithmus Hyperbolic Sine Sinus Hyperbolicus Hyperbolic Tangent Tangens Hyperbolicus Greatest Common Divisor Größter gemeinsamer Teiler Combination (Binomial Coefficient) Kombination (Binomialkoeffizient) Permutation (Arrangement) Permutation (Anordnung) Binomial Cumulative Distribution Function Kumulative Verteilungsfunktion der Binomialverteilung Binomial Distribution Mean Erwartungswert der Binomialverteilung Binomial Probability Mass Function Wahrscheinlichkeitsfunktion der Binomialverteilung Binomial Distribution Variance Variation der Binomialverteilung Hypergeometric Cumulative Distribution Function Kumulative Verteilungsfunktion der Hypergeometrischen Verteilung Hypergeometric Distribution Mean Erwartungswert der Hypergeometrischen Verteilung Hypergeometric Probability Mass Function Wahrscheinlichkeitsfunktion der Hypergeometrischen Verteilung Hypergeometric Distribution Variance Variation der Hypergeometrischen Verteilung Poissonian Cumulative Distribution Function Kumulative Verteilungsfunktion der Poisson-Verteilung Poissonian Distribution Mean Erwartungswert der Poisson-Verteilung Poissonian Probability Mass Function Wahrscheinlichkeitsfunktion der Poisson-Verteilung Poissonian Distribution Variance Variation der Poisson-Verteilung Arc Cosine Arcus Cosinus Arc Sine Arcus Sinus Arc Tangent Arcus Tangens Cosine Cosinus Cotangent Kotangens Cosecant Kosekans Radians Radiant Secant Sekans Sine Sinus Tangent Tangens cannot execute function %1 Die Funktion %1 kann nicht ausgeführt werden function accepts 1 argument Die Funktion akzeptiert 1 Argument function accepts %1 arguments Die Funktion akzeptiert %1 Argumente function requires 1 or 2 arguments Die Funktion benötigt 1 oder 2 Argumente function undefined for specified arguments Die Funktion ist für die angegebenen Argumente nicht definiert function requires at least 2 arguments Die Funktion benötigt mindestens 2 Argumente function requires integer arguments Die Funktion benötigt ganze Zahlen als Argumente function undefined for specified argument Die Funktion ist für das angegebene Argument nicht definiert underflow Ergebnis zu klein (Underflow) function requires at least 1 argument Die Funktion benötigt mindestens 1 Argument Extension of Factorials [= (x-1)!] Erweiterung der Fakultät [= (x-1)!] ln(abs(Gamma)) ln(abs(Gamma)) Error Function Fehlerfunktion Complementary Error Function komplementäre Fehlerfunktion Degrees of Arc Winkelmaß in Grad Mask to a bit size auf eine Bitlänge maskieren Sign-extent a value Vorzeichenerweiterung eines Wertes Logical NOT Logisches NICHT Logical AND Logisches UND Logical OR Logisches ODER Logical XOR Logisches ausschließendes ODER (XOR) Arithmetic Shift Left Arithmetisches Verschieben nach links Arithmetic Shift Right Arithmetisches Verschieben nach rechts Integer Quotient Ganzzahliger Quotient Modulo Modulo FunctionsDock Functions Funktionen Search Suchen No match found Keine Übereinstimmung HistoryDock History Verlauf InsertFunctionDlg Name Name Description Beschreibung &Insert E&infügen Cancel Abbrechen Insert Function Funktion einfügen InsertVariableDlg Name Name Value Wert &Insert &Einfügen Cancel Abbrechen Insert Variable Variabel einfügen Keypad Inverse cosine Arkuskosinus The last result Das letzte Ergebnis Inverse sine Arkussinus Inverse tangent Arkustangens Clear expression Lösche Ausdruck Cosine Cosinus Scientific notation Wissenschaftliche Darstellung Exponential Exponentialfunktion Natural logarithm natürlicher Logarithmus Sine Sinus Square root Quadratwurzel Tangent Tangens Assign variable x Zuweisung an die Variable x The variable x Die Variable x MainWindow About Qt Über Qt SpeedCrunch Sessions (*.sch);;All Files (*) SpeedCrunch Sitzungen (*.sch);;Alle Dateien (*) Load Session Sitzung laden Error Fehler Can't read from file %1 Kann Datei %1 nicht lesen Question Nachfrage Save Session Sitzung speichern Can't write to file %1 Kann nicht nach %1 schreiben Warning Warnung To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Um eine Funktion mittels der Tastatur einzufügen, kann man die Tastenkombination Strg+F verwenden. Im sich nun öffnenden Dialog lässt sich jede der vorhandenen Funktionen auswählen und einfügen. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Um eine variable mittels der Tastatur einzufügen, kann man die Tastenkombination Strg+I verwenden. Im sich nun öffnenden Dialog lässt sich jede der vorhandenen Variablen auswählen und einfügen. Use variable <i>pi</i> to use pi constant. Verwenden Sie die Variable <i>pi</i> für die Konstante Pi. Use <i>;</i> (semicolon) to separate the parameters in functions. Verwenden Sie <i>;</i> (Semikolon) um Parameter in Funktionen abzugrenzen. Tip of the day Tipp des Tages File %1 is not a valid session Datei %1 enthält keine gültigen Sitzungsdaten Merge session being loaded with current session? If no, current variables and display will be cleared. Zu ladende Sitzungsdaten mit aktueller Sitzung vereinigen? Falls nein, werden aktuelle Variablen und Anzeigen gelöscht. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. Das SpeedCrunch Fenster ist minimiert. Klicken Sie das Symbol mit links zur Wiederherstellung, oder rechts für weitere Optionen. Degree Grad All Files (*) Alle Dateien (*) Radian Bogenmaß The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. Die Menüleiste ist ausgeblendet. Zur Wiederherstellung Strg+Alt+M. Binary Binär Engineering decimal Ingenieursformat dezimal Fixed decimal Festkomma dezimal General decimal Allgemeines Format dezimal Hexadecimal Hexagesimal> Octal Octal Scientific decimal Wissenschaftlich dezimal Import Session Sitzung importieren Merge session being imported with current session? If no, current variables and display will be cleared. Zu ladende Sitzungsdaten mit aktueller Sitzung vereinigen? Falls nein, werden aktuelle Variablen und Anzeigen gelöscht. Export Session Sitzung exportieren Math Book Mathe Buch &Session &Sitzung Clear E&xpression &Ausdruck löschen Clear &History Verlau&f löschen &Degree &Grad Delete All V&ariables Alle &Variablen löschen D&elete Variable... Lösc&he Variable ... &15 Decimal Digits &15 Dezimalstellen &2 Decimal Digits &2 Dezimalstellen &3 Decimal Digits &3 Dezimalstellen &50 Decimal Digits &50 Dezimalstellen &8 Decimal Digits &8 Dezimalstellen &Automatic Precision A&utomatische Genauigkeit &Copy &Kopieren Copy Last &Result &Letztes Ergebnis kopieren &Paste &Einfügen &About &Info About &Qt Über &Qt SpeedCrunch &Web Site... SpeedCrunch &Webseite... &Tip of the Day &Tipp des Tages Insert &Function... &Funktion einfügen... Insert &Variable... &Variable einfügen... &Partial Results laufende &Berechnung Automatic &Completion Auto&matische Vervollständigung Always On &Top &Immer im Vordergrund &Minimize To System Tray Zu Kontrollleisten-Symbol minimieren Syntax &Highlighting Synta&xauszeichnung &System Default S&ystemeinstellungen &Dot &Dezimalkomma &Comma K&omma &Radian &Bogenmaß Scroll Display Down Anzeigefenster herunter bewegen Scroll Display Up Anzeigefenster herauf bewegen &Select Expression Ausdruck &markieren &Import... &Importieren... &Load... &Laden... &Quit &Beenden &Save... Spei&chern... &Export... &Exportieren Math &Book &Mathe Buch &Constants &Konstanten Full &Screen Mode &Ganzer Bildschirm &Functions &Funktionen &History &Verlauf &Keypad &Tastenfeld Hide &Menu Bar Menü&leiste ausblenden &Status Bar &Statusleiste &Variables Varia&ble &Binary &Binär &Engineering &Ingenieurwissenschaftlich &Fixed Decimal &Feste Anzahl Dezimalstellen &General &Allgemein &Hexadecimal &Hexadezimal &Octal &Oktal &Scientific &Wissenschaftlich System &Default S&ystemeinstellung &Edit &Bearbeiten &View &Ansicht Se&ttings &Einstellungen Result &Format Ergebnis&format &Decimal &Dezimal &Angle Unit &Winkelmaß &Behavior &Verhalten Radix &Character &Dezimalkomma &Language &Sprache &Help &Hilfe Angle unit Winkelmaß Result format Ergebnisformat Ignore error? Fehler ignorieren? VariablesDock Variables Variablen Search Suchen No match found Keine Übereinstimmung speedcrunch-0.10.1/src/i18n/pt_BR.ts0000644000175000001440000017500311015364561016212 0ustar helderusers AboutBox Special thanks to Agradecimentos especiais a French Francês German Alemão Portuguese Português Russian Russo Italian Italiano This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Este programa é software livre; você pode redistribuí-lo e/ou modificá-lo sob os termos da Licença Pública Geral GNU, publicada pela Free Software Foundation, tanto a versão 2 da licença como (a sua escolha) qualquer versão mais recente This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Este programa é distribuído com a expectativa de que será útil, mas SEM GARANTIA ALGUMA, nem mesmo a garantia implícita de APTIDÃO AO MERCADO ou APTIDÃO A UM PROPÓSITO ESPECÍFICO. Consulte a Licença Pública Geral GNU para maiores detalhes. SpeedCrunch version %1 SpeedCrunch versão %1 About SpeedCrunch Sobre o SpeedCrunch Norwegian Norueguês Spanish Espanhol Original author Autor original Current maintainer Mantenedor atual Based on original idea from Baseado em uma idéia original de Thanks to Agradecimentos a ...and many others... ...e muitos outros... Translations Traduções Brazilian Portuguese Português do Brasil Copyright (C) Copyright (C) Visit <b>http://www.speedcrunch.org</b> for more information! Visite <b>http://www.speedcrunch.org</b> para maiores informações! Argentinian Spanish Espanhol da Argentina Dutch Neerlandês Hebrew Hebreu Swedish Sueco Finnish Finlandês Czech Tcheco Romanian Romeno Developers Desenvolvedores Indonesian Indonésio Polish Polonês Turkish Turco Close Fechar Graphics Gráficos Basque Basco Simplified Chinese Chinës Simplificado Catalan Catalão BookDock Back Anterior Forward Próximo Index Índice ConstantCompletion All Todas Constants Characteristic Impedance of Vacuum Impedância Característica do Vácuo General Physics Física Geral Electric Constant Constante Elétrica Magnetic Constant Constante Magnética Gravitation Constant Constante Gravitacional Universal Planck's Constant Constante de Planck Dirac's Constant Constante de Dirac Speed of Light in Vacuum Velocidade da Luz no Vácuo Bohr-Procopiu Magneton Magnéton de Bohr-Procopiu Electromagnetic Eletromagnéticas Conductance Quantum Quantum de Condutância Coulomb's Constant Constante de Coulomb Elementary Charge Carga Elétrica Elementar Josephson Constant Constante de Josephson Magnetic Flux Quantum Quantum de Fluxo Magnético Nuclear Magneton Magnéton Nuclear Resistance Quantum Quantum de Resistência von Klitzing Constant Constante de von Klitzing Bohr Radius Raio de Bohr Atomic & Nuclear Atômicas & Nucleares Fermi Coupling Constant Constante de Acoplamento de Fermi Fine-structure Constant Constante de Estrutura Fina Hartree Energy Energia de Hartree Quantum of Circulation Quantum de Circulação Rydberg Constant Constante de Rydberg Thomson Cross Section Seção de Choque de Thomson Weak Mixing Angle Ângulo de Weinberg Atomic Mass Unit Unidade de Massa Atômica Physico-chemical Físico-Química Avogadro's Number Constante de Avogadro Boltzmann Constant Constante de Boltzmann Faraday Constant Constante de Faraday First Radiation Constant Constante Primária de Radiação Loschmidt Constant Constante de Loschmidt Gas Constant Constante dos Gases Ideais Molar Planck Constant Constante Molar de Planck Second Radiation Constant Constante Secundária de Radiação Stefan-Boltzmann Constant Constante de Stefan-Boltzmann Astronomical Unit Unidade Astronômica Astronomy Astronomia Light Year Ano-luz Parsec Parsec Sidereal Year Ano Sideral days dias Tropical Year Ano Tropical Gregorian Year Ano Gregoriano Earth Mass Massa da Terra Sun Mass Massa do Sol Mean Earth Radius Raio Médio da Terra Sun Radius Raio do Sol Sun Luminosity Luminosidade do Sol ConstantsDock Constants Constantes Category Categoria Search Pesquisar No match found Nenhum resultado encontrado All Todas DeleteVariableDlg Name Nome Value Valor &Delete Apa&gar Close Fechar Delete Variable Apagar Variável Editor Current result: <b>%1</b> Resultado atual: <b>%1</b> Selection result: <b>%1</b> Resultado da seleção: <b>%1</b> Evaluator invalid expression expressão inválida division by zero divisão por zero unknown function or variable função ou variável desconhecida variable cannot be overwritten variável não pode ser sobrescrita identifier matches an existing function name identificador coincide com um nome de função já existente Functions Absolute Value Valor Absoluto Average (Arithmetic Mean) Média Binary Representation Representação Binária Cube Root Raiz Cúbica Ceiling Teto Decimal Representation Representação Decimal Floor Chão Fractional Part Parte Fracionária Geometric Mean Média Geométrica Hexadecimal Representation Representação Hexadecimal Integer Part Parte Inteira Maximum Máximo Minimum Mínimo Octal Representation Representação Octal Product Produto Rounding Arredondamento Signum Sinal Square Root Raiz Quadrada Sum Soma Truncation Truncamento Area Hyperbolic Cosine Arco Cosseno Hiperbólico Area Hyperbolic Sine Arco Seno Hiperbólico Area Hyperbolic Tangent Arco Tangente Hiperbólico Hyperbolic Cosine Cosseno Hiperbólico Exponential Exponencial Base-2 Logarithm Logaritmo em Base 2 Natural Logarithm Logaritmo Natural Base-10 Logarithm Logaritmo em Base 10 Hyperbolic Sine Seno Hiperbólico Hyperbolic Tangent Tangente Hiperbólica Greatest Common Divisor Máximo Divisor Comum Combination (Binomial Coefficient) Combinação (Coeficiente Binomial) Permutation (Arrangement) Permutação (Arranjo) Binomial Cumulative Distribution Function Função Distribuição Cumulativa Binomial Binomial Distribution Mean Média da Distribuição Binomial Binomial Probability Mass Function Função Massa de Probabilidade Binomial Binomial Distribution Variance Variância da Distribuição Binomial Hypergeometric Cumulative Distribution Function Função Distribuição Cumulativa Hipergeométrica Hypergeometric Distribution Mean Média da Distribuição Hipergeométrica Hypergeometric Probability Mass Function Função Massa de Probabilidade Hipergeométrica Hypergeometric Distribution Variance Variância da Distribuição Hipergeométrica Poissonian Cumulative Distribution Function Função Distribuição Cumulativa de Poisson Poissonian Distribution Mean Média da Distribuição de Poisson Poissonian Probability Mass Function Função Massa de Probabilidade de Poisson Poissonian Distribution Variance Variância da Distribuição de Poisson Arc Cosine Arco Cosseno Arc Sine Arco Seno Arc Tangent Arco Tangente Cosine Cosseno Cotangent Cotangente Cosecant Cossecante Radians Radianos Secant Secante Sine Seno Tangent Tangente cannot execute function %1 não foi possível executar a função %1 function accepts 1 argument função aceita 1 argumento function accepts %1 arguments função aceita %1 argumentos function requires 1 or 2 arguments função requer 1 ou 2 argumentos function undefined for specified arguments função não definida para os argumentos especificados function requires at least 2 arguments função requer pelo menos 2 argumentos function requires integer arguments função requer argumentos inteiros function undefined for specified argument função não definida para o argumento especificado underflow estouro de valor mínimo function requires at least 1 argument função requer pelo menos 1 argumento Extension of Factorials [= (x-1)!] Extensão dos Fatoriais [= (x-1)!] ln(abs(Gamma)) ln(abs(Gamma)) Error Function Função de Erro Complementary Error Function Função de Erro Complementar Degrees of Arc Graus de Arco Mask to a bit size Mascarar para um número de bits Sign-extent a value Extender sinal de um valor Logical NOT NÃO lógico (NOT) Logical AND E lógico (AND) Logical OR OU lógico (OR) Logical XOR OU exclusivo lógico (XOR) Arithmetic Shift Left Deslocamento aritmético (shift) à esquerda Arithmetic Shift Right Deslocamento aritmético (shift) à direita Integer Quotient Quociente Inteiro Modulo Módulo FunctionsDock Functions Funções Search Pesquisar No match found Nenhum resultado encontrado HistoryDock History Histórico InsertFunctionDlg Name Nome Description Descrição &Insert &Inserir Cancel Cancelar Insert Function Inserir uma função InsertVariableDlg Name Nome Value Valor &Insert &Inserir Cancel Cancelar Insert Variable Inserir uma variável Keypad Inverse cosine Inverso do cosseno The last result Último resultado Inverse sine Inverso do seno Inverse tangent Inverso da tangente Clear expression Limpar expressão Cosine Cosseno Scientific notation Notação científica Exponential Exponencial Natural logarithm Logaritmo natural Sine Seno Square root Raiz quadrada Tangent Tangente Assign variable x Atribuir valor à variável x The variable x A variável x MainWindow About Qt Sobre a Qt SpeedCrunch Sessions (*.sch);;All Files (*) Sessões SpeedCrunch (*.sch);;Todos os Arquivos (*) Load Session Carregar Sessão Error Erro Can't read from file %1 Não foi possível ler o arquivo %1 Question Pergunta Save Session Salvar a Sessão Can't write to file %1 Não foi possível escrever no arquivo %1 Warning Advertência To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Para inserir uma função utilizando o teclado, digite Ctrl+F. Da caixa de diálogo que aparecerá você pode escolher a função que deseja inserir. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Para inserir uma variável utilizando o teclado, digite Ctrl+I. Da caixa de diálogo que aparecerá você pode escolher a variável que deseja inserir. Use variable <i>pi</i> to use pi constant. Utilize a variável <i>pi</i> para usar a constante pi. Use <i>;</i> (semicolon) to separate the parameters in functions. Utiliza <i>;</i> (ponto-e-vírgula) para separar os parâmetros de funções. Tip of the day Dica do dia File %1 is not a valid session O arquivo %1 não é uma sessão válida Merge session being loaded with current session? If no, current variables and display will be cleared. Unir a sessão a ser carregada com a sessão atual? Em caso negativo, as variáveis e a tela atuais serão apagadas. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. SpeedCrunch foi minimizada. Clique com o botão esquerdo para restaurar ou com o botão direito para outras opções. Degree Grau All Files (*) Todos os Arquivos (*) Radian Radianos The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. A barra de menus agora está oculta. Para torná-la visível novamente, pressione Ctrl+Alt+M. Binary Binário Engineering decimal Decimal para engenharia Fixed decimal Decimal fixo General decimal Decimal geral Hexadecimal Hexadecimal Octal Octal Scientific decimal Decimal científico Import Session Importar Sessão Merge session being imported with current session? If no, current variables and display will be cleared. Unir a sessão a ser importada com a sessão atual? Em caso negativo, as variáveis e a tela atuais serão apagadas. Export Session Exportar Sessão Math Book Livro de Matemática &Session &Sessão Clear E&xpression Limpar E&xpressão Clear &History Limpar &Histórico &Degree &Grau Delete All V&ariables Deletar Todas as V&ariáveis D&elete Variable... Apa&gar Variável... &15 Decimal Digits &15 Casas Decimais &2 Decimal Digits &2 Casas Decimais &3 Decimal Digits &3 Casas Decimais &50 Decimal Digits &50 Casas Decimais &8 Decimal Digits &8 Casas Decimais &Automatic Precision Precisão &Automática &Copy &Copiar Copy Last &Result Copiar Último &Resultado &Paste Co&lar &About &Sobre About &Qt Sobre a &Qt SpeedCrunch &Web Site... &Página do SpeedCrunch na Internet... &Tip of the Day &Dica do Dia Insert &Function... Inserir &Função... Insert &Variable... Inserir &Variável... &Partial Results Resultados &Parciais Automatic &Completion &Completamento Automático Always On &Top Sempre no &Topo &Minimize To System Tray &Minimizar Para Barra de Tarefas Syntax &Highlighting Desta&que de Sintaxe &System Default Padrão do &Sistema &Dot &Ponto &Comma &Vírgula &Radian &Radiano Scroll Display Down Rolar Tela Para Baixo Scroll Display Up Rolar Tela Para Cima &Select Expression &Selecionar Expressão &Import... &Importar... &Load... &Carregar... &Quit &Sair &Save... &Salvar... &Export... &Exportar... Math &Book &Livro de Matemática &Constants &Constantes Full &Screen Mode Modo de &Tela Cheia &Functions &Funções &History &Histórico &Keypad Teclado &Numérico Hide &Menu Bar Ocultar Barra de &Menus &Status Bar Barra de &Status &Variables &Variáveis &Binary &Binária &Engineering &Engenharia &Fixed Decimal Ponto Decimal &Fixo &General &Geral &Hexadecimal &Hexadecimal &Octal &Octal &Scientific C&ientífica System &Default Padrão do &Sistema &Edit &Editar &View &Visualizar Se&ttings &Preferências Result &Format &Formato do Resultado &Decimal &Decimal &Angle Unit Unid&ade dos Ângulos &Behavior C&omportamento Radix &Character &Caracter Separador das Partes Inteira e Fracionária &Language &Língua &Help &Ajuda Angle unit Unidade dos ângulos Result format Formato do resultado Ignore error? Ignorar erro? VariablesDock Variables Variáveis Search Pesquisar No match found Nenhum resultado encontrado speedcrunch-0.10.1/src/i18n/fi.ts0000644000175000001440000017335111015364561015606 0ustar helderusers AboutBox About SpeedCrunch Tietoja SpeedCrunchista SpeedCrunch version %1 SpeedCrunch versio %1 Original author Alkuperäinen tekijä Current maintainer Nykyinen ylläpitäjä Based on original idea from Alkuperäinen idea Special thanks to Erityiskiitokset Thanks to Kiitokset ...and many others... ...ja monet muut... Translations Käännökset French Ranska German Saksa Italian Italia Norwegian Norja Portuguese Portugali Brazilian Portuguese Brasilian portugali Russian Venäjä Spanish Espanja Copyright (C) Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Tämä ohjelma on vapaa; tätä ohjelmaa on sallittu levittää edelleen ja muuttaa GNU yleisen lisenssin (GPL lisenssin) ehtojen mukaan sellaisina kuin Free Software Foundation on ne julkaissut; joko Lisenssin version 2, tai (valinnan mukaan) minkä tahansa myöhemmän version mukaisesti This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Tätä ohjelmaa levitetään siinä toivossa, että se olisi hyödyllinen, mutta ilman mitään takuuta; ilman edes hiljaista takuuta kaupallisesti hyväksyttävästä laadusta tai soveltuvuudesta tiettyyn tarkoitukseen. Katso GPL lisenssistä lisää yksityiskohtia. Visit <b>http://www.speedcrunch.org</b> for more information! Lisätietoa osoitteessa <b>http://www.speedcrunch.org</b>! Argentinian Spanish Argentiinan espanja Dutch Hollanti Hebrew Heprea Swedish Ruotsi Finnish Suomi Czech Tšekki Romanian Romania Developers Kehittäjät Indonesian Indonesia Polish Puola Turkish Turkki Close Sulje Graphics Grafiikat Basque Simplified Chinese Catalan BookDock Back Edellinen Forward Seuraava Index Hakemisto ConstantCompletion All Kaikki Constants Characteristic Impedance of Vacuum Tyhjiön ominaisimpedanssi General Physics Yleinen fysiikka Electric Constant Sähkövakio Magnetic Constant Magneettivakio Gravitation Constant Gravitaatiovakio Planck's Constant Planckin vakio Dirac's Constant Diracin vakio Speed of Light in Vacuum Valon nopeus tyhjiössä Bohr-Procopiu Magneton Bohrin-Procopiun magnetoni Electromagnetic Sähkömagnetiikka Conductance Quantum Konduktanssin kvanttiluku Coulomb's Constant Coulombin vakio Elementary Charge Alkeisvaraus Josephson Constant Josephsonin vakio Magnetic Flux Quantum Magneettisen sähkövuon kvanttiluku Nuclear Magneton Ydinmagnetoni Resistance Quantum Resistanssin kvanttiluku von Klitzing Constant von Klitzingin vakio Bohr Radius Bohrin säde Atomic & Nuclear Atomi- & ydinfysiikka Fermi Coupling Constant Fermin kytkentävakio Fine-structure Constant Hienorakennevakio Hartree Energy Hartreen energia Quantum of Circulation Kiertokvanttiluku Rydberg Constant Rydbergin vakio Thomson Cross Section Thomsonin poikkileikkaus Weak Mixing Angle Weinbergin kulma Atomic Mass Unit Atomimassayksikkö Physico-chemical Fysikaalinen kemia Avogadro's Number Avogadron vakio Boltzmann Constant Boltzmannin vakio Faraday Constant Faradayn vakio First Radiation Constant Ensimmäinen säteilyvakio Loschmidt Constant Loschmidtin vakio Gas Constant Kaasuvakio Molar Planck Constant Planckin moolivakio Second Radiation Constant Toinen säteilyvakio Stefan-Boltzmann Constant Stefanin-Boltzmannin vakio Astronomical Unit Astronominen yksikkö Astronomy Tähtitiede Light Year Valovuosi Parsec Parsek Sidereal Year Sideerinen vuosi days päivää Tropical Year Trooppinen vuosi Gregorian Year Gregoriaaninen vuosi Earth Mass Maan massa Sun Mass Auringon massa Mean Earth Radius Maan keskisäde Sun Radius Auringon säde Sun Luminosity Auringon luminositeetti ConstantsDock Constants Vakiot Category Kategoria Search Etsi No match found Ei tuloksia All Kaikki DeleteVariableDlg Delete Variable Poista Muuttuja Name Nimi Value Arvo &Delete &Poista Close Sulje Editor Current result: <b>%1</b> Tämänhetkinen tulos: <b>%1</b> Selection result: <b>%1</b> Valinnan tulos: <b>%1</b> Evaluator invalid expression epäkelpo lauseke division by zero jako nollalla unknown function or variable tuntematon funktio tai muuttuja variable cannot be overwritten muuttujaa ei voi korvata identifier matches an existing function name tunnus täsmää olemassaolevaan funktion nimeen Functions Absolute Value Itseisarvo Average (Arithmetic Mean) Aritmeettinen keskiarvo Binary Representation Binäärimerkintä Cube Root Kuutiojuuri Ceiling Kattofunktio Decimal Representation Desimaalimerkintä Floor Lattiafunktio Fractional Part Murto-osa Geometric Mean Geometrinen keskiarvo Hexadecimal Representation Heksadesimaalimerkintä Integer Part Kokonaisosa Maximum Maksimi Minimum Minimi Octal Representation Oktaalimerkintä Product Tulo Rounding Pyöristys Signum Etumerkki Square Root Neliöjuuri Sum Summa Truncation Katkaisu Area Hyperbolic Cosine Hyperbolinen arkuskosini Area Hyperbolic Sine Hyperbolinen arkussini Area Hyperbolic Tangent Hyperbolinen arkustangentti Hyperbolic Cosine Hyperbolinen kosini Base-2 Logarithm 2-kantainen logaritmi Natural Logarithm Luonnollinen logaritmi Base-10 Logarithm 10-kantainen logaritmi Hyperbolic Sine Hyperbolinen sini Hyperbolic Tangent Hyperbolinen tangentti Greatest Common Divisor Suurin yhteinen tekijä Combination (Binomial Coefficient) Kombinaatio (binomikerroin) Permutation (Arrangement) Permutaatio (järjestys) Binomial Cumulative Distribution Function Binomikertymäfunktio Binomial Distribution Mean Binomijakauman keskiarvo Binomial Probability Mass Function Binomipistetodennäköisyysfunktio Binomial Distribution Variance Binomijakauman varianssi Hypergeometric Cumulative Distribution Function Hypergeometrinen kertymäfunktio Hypergeometric Distribution Mean Hypergeometrisen jakauman keskiarvo Hypergeometric Probability Mass Function Hypergeometrinen pistetodennäköisyysfunktio Hypergeometric Distribution Variance Hypergeometrisen jakauman varianssi Poissonian Cumulative Distribution Function Poissonin kertymäfunktio Poissonian Distribution Mean Poissonin jakauman keskiarvo Poissonian Probability Mass Function Poissonin pistetodennäköisyysfunktio Poissonian Distribution Variance Poissonin jakauman varianssi Arc Cosine Arkuskosini Arc Sine Arkussini Arc Tangent Arkustangentti Cosine Kosini Cotangent Kotangentti Cosecant Kosekantti Radians Radiaanit Secant Sekantti Sine Sini Tangent Tangentti cannot execute function %1 funktion %1 suorittaminen ei onnistu function accepts 1 argument funktio hyväksyy 1 parametrin function accepts %1 arguments funktio hyväksyy %1 parametria function requires 1 or 2 arguments funktio vaatii 1 tai 2 parametria function undefined for specified arguments funktion toiminta on määrittelemätön annetuilla parametreilla function requires at least 2 arguments funktio vaatii vähintään 2 parametria function requires integer arguments funktio vaatii kokonaislukuparametrit function undefined for specified argument funktion toiminta on määrittelemätön annetulla parametrilla underflow alivuoto function requires at least 1 argument funktio vaatii vähintään 1 parametrin Extension of Factorials [= (x-1)!] Kertoman laajennos [= (x-1)!] ln(abs(Gamma)) ln(abs(Gamma)) Exponential Eksponentti Error Function Virhefunktio Complementary Error Function Virhefunktion komplementti Degrees of Arc Radiaanit asteina Mask to a bit size Sovita bittimäärään Sign-extent a value Etumerkitse arvo Logical NOT Looginen EI Logical AND Looginen JA Logical OR Looginen TAI Logical XOR Looginen poissulkeva TAI Arithmetic Shift Left Aritmeettinen siirto vasemmalle Arithmetic Shift Right Aritmeettinen siirto oikealle Integer Quotient Osamäärän osoittaja Modulo Jakojäännös FunctionsDock Functions Funktiot Search Etsi No match found Ei tuloksia HistoryDock History Historia InsertFunctionDlg Insert Function Lisää Funktio Name Nimi Description Kuvaus &Insert &Lisää Cancel Peruuta InsertVariableDlg Insert Variable Lisää Muuttuja Name Nimi Value Arvo &Insert &Lisää Cancel Peruuta Keypad Inverse cosine Arkuskosini The last result Edellinen tulos Inverse sine Arkussini Inverse tangent Arkustangentti Clear expression Tyhjennä lauseke Cosine Kosini Scientific notation Tieteellinen merkintä Exponential Eksponentti Natural logarithm Luonnollinen logaritmi Sine Sini Square root Neliöjuuri Tangent Tangentti Assign variable x Sijoita muuttujaan x The variable x Muuttuja x MainWindow About Qt Tietoja Qt:sta SpeedCrunch Sessions (*.sch);;All Files (*) SpeedCrunch Istunnot (*.sch);;Kaikki Tiedostot (*) Load Session Avaa Istunto Error Virhe Can't read from file %1 Tiedoston %1 lukeminen ei onnistu Question Kysymys Save Session Tallenna Istunto Can't write to file %1 Tiedostoon %1 ei voida kirjoittaa Warning Varoitus To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Voit lisätä funtion pikanäppäimellä Ctrl+F. Valitse funktio avautuvasta valintaikkunasta. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Voit lisätä muuttujan pikanäppäimellä Ctrl+I. Valitse muuttuja avautuvasta valintaikkunasta. Use variable <i>pi</i> to use pi constant. Voit käyttää muuttujaa <i>pi</i> piin arvona. Use <i>;</i> (semicolon) to separate the parameters in functions. Käytä <i>;</i> (puolipistettä) erottamaan funktioiden parametrit. Tip of the day Päivän vihje File %1 is not a valid session Tiedosto %1 ei ole kelvollinen istunto Merge session being loaded with current session? If no, current variables and display will be cleared. Yhdistetäänkö avattava istunto nykyiseen istuntoon? Jos ei, nykyiset muuttujat ja näyttö tyhjennetään. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. SpeedCrunch on pienennetty. Palauta ikonista vasemmalla painikkeella tai näytä valikko oikealla painikkeella. Degree Asteet All Files (*) Kaikki Tiedostot (*) Radian Radiaanit The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. Valikkopalkki on nyt piilossa. Tuo se näkyviin painamalla Ctrl+Alt+M. Binary Binääri Engineering decimal Tekninen desimaali Fixed decimal Kiintopistedesimaali General decimal Yleinen desimaali Hexadecimal Heksadesimaali Octal Oktaali Scientific decimal Tieteellinen desimaali Import Session Tuo Istunto Merge session being imported with current session? If no, current variables and display will be cleared. Yhdistetäänkö tuotava istunto nykyiseen istuntoon? Jos ei, nykyiset muuttujat ja näyttö tyhjennetään. Export Session Vie Istunto Math Book Matematiikkaopas &Session &Istunto Clear E&xpression Tyhjennä L&auseke Clear &History Tyhjennä &Historia &Degree &Asteet Delete All V&ariables Poista &Kaikki Muuttujat D&elete Variable... &Poista Muuttuja... &15 Decimal Digits &15 Desimaalia &2 Decimal Digits &2 Desimaalia &3 Decimal Digits &3 Desimaalia &50 Decimal Digits &50 Desimaalia &8 Decimal Digits &8 Desimaalia &Automatic Precision &Automaattinen Tarkkuus &Copy &Kopioi Copy Last &Result Kopioi &Tulos &Paste &Liitä &About &Tietoja About &Qt Tietoja &Qt:sta SpeedCrunch &Web Site... SpeedCrunch &WWW-sivusto... &Tip of the Day Päivän &Vihje Insert &Function... Lisää &Funktio... Insert &Variable... Lisää &Muuttuja... &Partial Results &Osittaiset Tulokset Automatic &Completion Automaattinen &Täydennys Always On &Top Aina &Päällä &Minimize To System Tray Pienennä &Järjestelmäpalkkiin Syntax &Highlighting &Syntaksin Merkkaus &System Default &Järjestelmän Oletus &Dot Pil&kku &Comma Pi&ste &Radian &Radiaanit Scroll Display Down Vieritä Näyttöä Alas Scroll Display Up Vieritä Näyttöä Ylös &Select Expression &Valitse Lauseke &Import... T&uo... &Load... &Avaa... &Quit &Lopeta &Save... &Tallenna... &Export... &Vie... Math &Book Matematiikka&opas &Constants &Vakiot Full &Screen Mode Koko&ruututila &Functions &Funktiot &History &Historia &Keypad &Näppäimistö Hide &Menu Bar &Piilota Valikkopalkki &Status Bar &Tilapalkki &Variables &Muuttujat &Binary &Binääri &Engineering T&ekninen &Fixed Decimal &Kiintopiste &General &Yleinen &Hexadecimal &Heksadesimaali &Octal &Oktaali &Scientific &Tieteellinen System &Default &Järjestelmän Oletus &Edit &Muokkaa &View &Näkymä Se&ttings &Asetukset Result &Format &Tulosmuoto &Decimal &Desimaali &Angle Unit &Kulmayksikkö &Behavior &Toiminta Radix &Character &Juurimerkki &Language &Kieli &Help A&pua Angle unit Kulmayksikkö Result format Tulosmuoto Ignore error? Sivuuta virhe? VariablesDock Variables Muuttujat Search Etsi No match found Ei tuloksia speedcrunch-0.10.1/src/i18n/ca.ts0000644000175000001440000017460411015364561015575 0ustar helderusers AboutBox Special thanks to Agraïments especials a French Francès German Alemany Portuguese Portuguès Russian Rus Italian Italià This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Aquest programari és software lliure; pot ésser redistribuit i/o modificat sota els termes de la GNU General Public License com fou publicada per la Free Software Foundation; ja sigui la versió 2 de la Llicència, o (a la seva elecció), qualsevol versió posterior This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Aquest programari es distribueix amb l'idea de que serà útil, pero SENSE CAP GARANTIA; ni tan sols la garantia implícita de SER COMERCIAL o SER ADEQUAT PER ALGUN PROPÒSIT PARTICULAR. Vegi la GNU General Public License per a més detalls. SpeedCrunch version %1 SpeedCrunch versió %1 Norwegian Noruec Spanish Espanyol About SpeedCrunch Quant a SpeedCrunch Original author Autor original Current maintainer Responsable actual Based on original idea from Basat en una idea original de Thanks to Gràcies a ...and many others... ...y molts altres... Translations Traduccions Brazilian Portuguese Portuguès Brasiler Copyright (C) Copyright (C) Visit <b>http://www.speedcrunch.org</b> for more information! Per a més informació visiti <b>http://www.speedcrunch.org</b>! Argentinian Spanish Espanyol Argentí Dutch Neerlandès Hebrew Hebreu Swedish Suec Finnish Finès Czech Txec Romanian Romanès Developers Desenvolupadors Indonesian Indonesi Close Tancar Graphics Gràfics Polish Polonès Turkish Turc Basque Basc Simplified Chinese Catalan BookDock Back Enrera Forward Endavant Index Índex ConstantCompletion All Tot Constants Characteristic Impedance of Vacuum Impedància Característica del Buit General Physics Física General Electric Constant Constant Elèctrica Magnetic Constant Constant Magnètica Gravitation Constant Constant Gravitacional Planck's Constant Constant de Planck Dirac's Constant Constant de Dirac Speed of Light in Vacuum Velocitat de la Llum en el Buit Bohr-Procopiu Magneton Magnetó de Bohr-Procopiu Electromagnetic Electromagnetisme Conductance Quantum Conductància Quàntica Coulomb's Constant Constant de Coulomb Elementary Charge Càrrega Elemental Josephson Constant Constant de Josephson Magnetic Flux Quantum Flux Quàntic Magnètic Nuclear Magneton Magnetó Nuclear Resistance Quantum Resistència Quàntica von Klitzing Constant Constant de von Klitzing Bohr Radius Radi de Bohr Atomic & Nuclear Atòmic i Nuclear Fermi Coupling Constant Constant d'Acoblament de Fermi Fine-structure Constant Constant d'Estructura Fina Hartree Energy Energia Hartree Quantum of Circulation Quàntum de Circulació Rydberg Constant Constant de Rydberg Thomson Cross Section Secció Eficaç de Thomson Weak Mixing Angle Angle de Weinberg Atomic Mass Unit Unitat de Massa Atòmica Physico-chemical Físic-químic Avogadro's Number Nombre d'Avogadro Boltzmann Constant Constant de Boltzmann Faraday Constant Constant de Faraday First Radiation Constant Primera Constant de Radiació Loschmidt Constant Constant de Loschmidt Gas Constant Constant Universal dels Gasos Ideals Molar Planck Constant Constant Molar de Planck Second Radiation Constant Segona Constant de Radiació Stefan-Boltzmann Constant Constant de Stefan-Boltzmann Astronomical Unit Unitat Astronòmica Astronomy Astronomia Light Year Any Llum Parsec Parsec Sidereal Year Any Sideral days dies Tropical Year Any Tropical Gregorian Year Any Gregorià Earth Mass Massa Terrestre Sun Mass Massa Solar Mean Earth Radius Radi Terrestre Sun Radius Radi Solar Sun Luminosity Lluminositat Solar ConstantsDock Constants Constants Category Categoria Search Recerca No match found No s'han trobat coincidències All Tot DeleteVariableDlg Name Nom Value Valor &Delete &Esborrar Close Tancar Delete Variable Esborrar Variable Editor Current result: <b>%1</b> Resultat actual: <b>%1</b> Selection result: <b>%1</b> Resultat de la selecció: <b>%1</b> Evaluator invalid expression expressió invàlida division by zero divisió per cero unknown function or variable funció o variable desconeguda variable cannot be overwritten variable no es pot sobreescriure identifier matches an existing function name identificador és igual al nom d'una funció existent Functions Absolute Value Valor Absolut Average (Arithmetic Mean) Promig (Mitja Aritmètica) Binary Representation Representació Binària Cube Root Arrel Cúbica Ceiling Sostre Decimal Representation Representació Decimal Floor Pis Fractional Part Part Fraccional Geometric Mean Mitja Geomètrica Hexadecimal Representation Representació Hexadecimal Integer Part Part Sencera Maximum Màxim Minimum Mínim Octal Representation Representació Octal Product Producte Rounding Arrodoniment Signum Signum Square Root Arrel Quadrada Sum Suma Truncation Truncar Hyperbolic Cosine Cosinus Hiperbòlic Exponential Exponencial Base-2 Logarithm Logaritme Binari Natural Logarithm Logaritme Natural Base-10 Logarithm Logaritme Base 10 Hyperbolic Sine Sinus Hiperbòlic Hyperbolic Tangent Tangent Hiperbòlica Greatest Common Divisor Màxim Comú Divisor Combination (Binomial Coefficient) Combinació (Coeficient Binomial) Permutation (Arrangement) Permutació (Reendreçament) Binomial Cumulative Distribution Function Funció de Distribució Acumulativa Binomial Binomial Distribution Mean Mitja de Distribució Binomial Binomial Probability Mass Function Funció de Probabilitat de Massa Binomial Binomial Distribution Variance Variació de Distribució Binomial Hypergeometric Cumulative Distribution Function Funció de Distribució Acumulativa Hipergeomètrica Hypergeometric Distribution Mean Mitja de Distribució Hipergeomètrica Hypergeometric Probability Mass Function Funció de Massa de Probabilitat Hipergeomètrica Hypergeometric Distribution Variance Variació de Distribució Hipergeomètrica Poissonian Cumulative Distribution Function Funció de Distribució Acumulativa de Poisson Poissonian Distribution Mean Mitja de Distribució de Poisson Poissonian Probability Mass Function Funció de Massa de Probabilitat de Poisson Poissonian Distribution Variance Variació de Distribució de Poisson Arc Cosine Arc Cosinus Arc Sine Arc Sinus Arc Tangent Arc Tangent Cosine Cosinus Cotangent Cotangent Cosecant Cosecant Radians Radians Secant Secant Sine Sinus Tangent Tangent cannot execute function %1 no és posible executar funció %1 function accepts 1 argument la funció accepta un argument function accepts %1 arguments la funció accepta %1 arguments function requires 1 or 2 arguments la funció requereix 1 o 2 arguments function undefined for specified arguments la funció no està definida pels arguments especificats function requires at least 2 arguments la funció requereix com a mínim 2 arguments function requires integer arguments la funció requereix arguments sencers function undefined for specified argument la funció no està definida per l'argument especificat underflow quantitat massa petita function requires at least 1 argument la funció requereix com a mínim un argument Extension of Factorials [= (x-1)!] Extensió de Factorials [= (x-1)!] ln(abs(Gamma)) ln(abs(Gamma)) Area Hyperbolic Cosine Àrea de Cosinus Hiperbòlic Area Hyperbolic Sine Àrea de Sinus Hiperbòlic Area Hyperbolic Tangent Àrea de Tangent Hiperbòlica Error Function Funció errònia Complementary Error Function Funció Complementària Errònia Degrees of Arc Graus de l'Arc Mask to a bit size Màscara a grandària de bit Sign-extent a value Extendre el signe d'un valor Logical NOT NOT Lògic Logical AND AND Lògic Logical OR OR Lògic Logical XOR XOR Lògic Arithmetic Shift Left Cambi Aritmètic a l'Esquerra Arithmetic Shift Right Cambi Aritmètic a la Dreta Integer Quotient Quocient d'un Sencer Modulo Mòdul FunctionsDock Functions Funcions Search Recerca No match found No s'han tobat coincidències HistoryDock History Historial InsertFunctionDlg Name Nom Description Descripció &Insert &Inserir Cancel Cancel·lar Insert Function Inserir Funció InsertVariableDlg Name Nom Value Valor &Insert &Inserir Cancel Cancel·lar Insert Variable Inserir Variable Keypad Inverse cosine Cosinus invers The last result El darrer resultat Inverse sine Sinus invers Inverse tangent Tangent inversa Clear expression Esborrar expressió Cosine Cosinus Scientific notation Notació científica Exponential Exponencial Natural logarithm Logaritme Natural Sine Sinus Square root Arrel quadrada Tangent Tangent Assign variable x Assignar variable x The variable x La variable x MainWindow About Qt Quant a Qt SpeedCrunch Sessions (*.sch);;All Files (*) Sessions de SpeedCrunch (*.sch);;Tots els fitxers (*) Load Session Carregar Sessió Error Errada Can't read from file %1 No pot llegirse des de l'arxiu %1 Question Pregunta Save Session Salvar Sessió Can't write to file %1 No es pot escriure en l'arxiu %1 Warning Advertiment To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Per inserir una funció fent servir el teclat, prémer Ctrl+F. Des de la finestra, pot escollir la funció que vulgui inserir. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Per inserir una variable fent servir el teclat, prémer Ctrl+I. Des de la finestra, pot escollir la variable que vulgui inserir. Use variable <i>pi</i> to use pi constant. Façi servir la variable <i>pi</i> per usar la constant pi. Use <i>;</i> (semicolon) to separate the parameters in functions. Façi servir <i>;</i> (punt i coma) per a separar els paràmetres en les funcions. Tip of the day Consell del dia File %1 is not a valid session Arxiu %1 no és una sessió vàlida Merge session being loaded with current session? If no, current variables and display will be cleared. Combinar sessió que s'està carregant amb la sessió actual? Si no és així, les variables actuals i la pantalla seran esborrades. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. SpeedCrunch está minimitzat. Fer clic en la icona amb el botó esquerre per restablir-ho o amb el botó dret per mostrar opcions. Degree Grau All Files (*) Tots els Arxius (*) Radian Radian The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. La barra de menú ara està amagada. Para fer-la visible novament, prémer Ctrl+Alt+M. Binary Binari Engineering decimal Decimal enginyeria Fixed decimal Decimal fixa General decimal Decimal genèrica Hexadecimal Hexadecimal Octal Octal Scientific decimal Decimal científica Import Session Importar Sessió Merge session being imported with current session? If no, current variables and display will be cleared. Combinar sessió que s'està carregant amb la sessió actual? Si no és així, les variables actuals i la pantalla seran esborrades. Export Session Exportar Sessió Math Book Llibre de Matemàtiques &Session &Sessió Clear E&xpression Esborrar E&xpressió Clear &History Esborrar &Historial &Degree &Grau Delete All V&ariables Esborrar Totes les V&ariables D&elete Variable... Es&borrar Variable... &15 Decimal Digits &15 Dígits Decimals &2 Decimal Digits &2 Dígits Decimals &3 Decimal Digits &3 Dígits Decimals &50 Decimal Digits &50 Dígits Decimals &8 Decimal Digits &8 Dígits Decimals &Automatic Precision Prec&isió Automàtica &Copy &Copiar Copy Last &Result Copiar l'Últim &Resultat &Paste &Pegar &About &Quant a About &Qt Quant a &Qt SpeedCrunch &Web Site... Lloc &Web SpeedCrunch... &Tip of the Day &Consell del dia Insert &Function... Inserir &Funció... Insert &Variable... Inserir &Variable... &Partial Results Resultats &Parcials Automatic &Completion &Completat Automàtic Always On &Top Sempre &Damunt &Minimize To System Tray &Minimitzar a Àrea de Notificació del Sistema Syntax &Highlighting &Resaltat de la Sintaxis &System Default Defecte (&Sistema) &Dot &Punt &Comma &Coma &Radian &Radian Scroll Display Down Desplaçar Pantalla Avall Scroll Display Up Desplaçar Pantalla a Dalt &Select Expression &Seleccionar Expressió &Import... &Importar... &Load... &Carregar... &Quit &Sortir &Save... &Salvar... &Export... &Exportar... Math &Book &Llibre de Matemàtiques &Constants &Constants Full &Screen Mode &Pantalla Completa &Functions &Funcions &History &Historial &Keypad &Teclat Numèric Hide &Menu Bar Amagar Barra de &Menú &Status Bar Barra d'&Estat &Variables &Variables &Binary &Binari &Engineering &Enginyeria &Fixed Decimal Punt Decimal &Fix &General Ge&neral &Hexadecimal &Hexadecimal &Octal &Octal &Scientific &Científica System &Default &Defecte (Sistema) &Edit &Editar &View &Veure Se&ttings &Configuració Result &Format &Format del Resultat &Decimal &Decimal &Angle Unit Unitat &Angular &Behavior &Comportament Radix &Character &Caracter Separador Sencer-Fracció &Language &Idioma &Help A&juda Angle unit Unitat angular Result format Format del resultat Ignore error? Ignorar errada? VariablesDock Variables Variables Search Recerca No match found No s'han trobat coincidències speedcrunch-0.10.1/src/i18n/nl.ts0000644000175000001440000017403711015364561015623 0ustar helderusers AboutBox SpeedCrunch version %1 SpeedCrunch versie %1 Special thanks to Met dank aan French Frans German Duits Portuguese Portugees Russian Russisch Italian Italiaans This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Dit Programma is vrije software; U kan het verspreiden en/of wijzigen onder de bepalingen van de GNU Algemene Publieke Licentie, zoals uitgegeven door de Free Software Foundation; oftewel versie 2 van de Licentie, of (naar vrije keuze) een latere versie This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Dit Programma is verspreid met de hoop dat het nuttig zal zijn maar ZONDER EENDER WELKE GARANTIE; zelfs zonder de impliciete garantie van VERKOOPBAARHEID of GESCHIKTHEID VOOR EEN BEPAALD DOEL. Zie de GNU Algemene Publieke Licentie voor meer details. About SpeedCrunch Over SpeedCrunch Norwegian Noors Spanish Spaans Original author Originele auteur Current maintainer Huidige beheerder Based on original idea from Gebaseerd op het idee van Thanks to Met dank aan ...and many others... ... en vele anderen... Translations Vertalingen Brazilian Portuguese Braziliaans Portugees Copyright (C) Auteursrecht (C) Visit <b>http://www.speedcrunch.org</b> for more information! Bezoek <b>http://www.spreedcrunch.org</b> voor meer informatie! Argentinian Spanish Argentijnse Spaans Dutch Nederlands Hebrew Hebreeuws Swedish Zweeds Finnish Fins Czech Tsjechisch Romanian Roemeens Developers Ontwikkelaars Indonesian Indonesisch Polish Pools Turkish Turks Close Afsluiten Graphics Grafische Werk Basque Simplified Chinese Catalan BookDock Back Vorige Forward Volgende Index Index ConstantCompletion All Alle Constants Characteristic Impedance of Vacuum Karakteristieke Impedantie van Vacuüm General Physics Natuurkundig Electric Constant Electrische Constante Magnetic Constant Magnetische Constante Gravitation Constant Gravitatie Constante Planck's Constant Constante van Planck Dirac's Constant Constante van Dirac Speed of Light in Vacuum Lichtsneldheid in Vacuüm Bohr-Procopiu Magneton Borh-Procopiu Magneton Electromagnetic Elektromagnetisch Conductance Quantum Geleidend Quantum Coulomb's Constant Constante van Coulomb Elementary Charge Elementaire Lading Josephson Constant Constante van Josephson Magnetic Flux Quantum Magnetisch Flux-quantum Nuclear Magneton Atomair Magneton Resistance Quantum Tegenwerkend Quantum von Klitzing Constant Constante van von Klitzing Bohr Radius Bohr Straal Atomic & Nuclear Atomair & Nucleair Fermi Coupling Constant Koppelings Constante Fermi Fine-structure Constant Fijnstructuur Constante Hartree Energy Hartree Energie Quantum of Circulation Quantum van Circulatie Rydberg Constant Constante Rydberg Thomson Cross Section Thomson Kruissectie Weak Mixing Angle Zwakke Hoek Combinatie Atomic Mass Unit Atomaire Massa-eenheid Physico-chemical Scheikundig Avogadro's Number Getal van Avogadro Boltzmann Constant Constante van Boltzmann Faraday Constant Constante van Faraday First Radiation Constant Eerste Radiatie Constante Loschmidt Constant Constante van Loschmidt Gas Constant Gasconstante Molar Planck Constant Molaire Constante van Planck Second Radiation Constant Tweede Radiatie Constante Stefan-Boltzmann Constant Stefan-Boltzmann Constante Astronomical Unit Astronomische Eenheid Astronomy Sterrenkunde Light Year Lichtjaar Parsec Parsec Sidereal Year Siderisch Jaar days dagen Tropical Year Tropisch Jaar Gregorian Year Gregoriaans Jaar Earth Mass Massa van de Aarde Sun Mass Massa van de Zon Mean Earth Radius Gemiddelde Radius van de Aarde Sun Radius Radius van de Zon Sun Luminosity Lichtkracht van de Zon ConstantsDock Constants Constanten Category Categorie Search Zoeken No match found Geen resultaten gevonden All Alle DeleteVariableDlg Name Naam Value Waarde &Delete &Verwijderen Close Afsluiten Delete Variable Verwijder Variabele Editor Current result: <b>%1</b> Huidige resultaat: <b>%1</b> Selection result: <b>%1</b> Geselecteerde resultaat: <b>%1</b> Evaluator invalid expression ongeldige expressie division by zero deling door nul unknown function or variable onbekende functie of variabele variable cannot be overwritten variabele kan niet overschreven worden identifier matches an existing function name identifier komt overeen met een al bestaande functienaam Functions Absolute Value Absolute Waarde Average (Arithmetic Mean) Gemiddelde (Arimetisch Gemiddelde) Binary Representation Binaire Weergave Cube Root Derdemachtswortel Ceiling Afronding (Plafond) Decimal Representation Decimale Weergave Floor Entier Fractional Part Breuk deel Geometric Mean Geomterisch Gemiddelde Hexadecimal Representation Hexadecimale Weergave Integer Part Gehele deel Maximum Maximum Minimum Minimum Octal Representation Ocatle Weergave Product Product Rounding Afronding Signum Signum Square Root Vierkantswortel Sum Som Truncation Afronding (Afbreken) Area Hyperbolic Cosine Inverse Hyperbolische Cosinus Area Hyperbolic Sine Inverse Hyperbolische Sinus Area Hyperbolic Tangent Inverse Hyperbolische Tangus Hyperbolic Cosine Hyperbolische Cosinus Exponential Exponentieel Base-2 Logarithm Grondtal-2 Logaritme Natural Logarithm Natuurlijk Logaritme Base-10 Logarithm Grondtal-10 Logaritme Hyperbolic Sine Hyperbolische Sinus Hyperbolic Tangent Hyperbolische Tangens Greatest Common Divisor Grootste Gemene Deler Combination (Binomial Coefficient) Combinatie (Binomiaal Coëfficient) Permutation (Arrangement) Permutatie (Rangschikking) Binomial Cumulative Distribution Function Binomiale Cumulatieve Kansfunctie Binomial Distribution Mean Binomiale Verdeling Binomial Probability Mass Function Binomiale Kansfunctie Binomial Distribution Variance Binomiale Variantie Hypergeometric Cumulative Distribution Function Hypergeometrische Cumulatieve Kansfunctie Hypergeometric Distribution Mean Hypergeometrische Verdeling Hypergeometric Probability Mass Function Hypergeometische Kansfunctie Hypergeometric Distribution Variance Hypergeometrische Variantie Poissonian Cumulative Distribution Function Poisson Cumulatieve Kansfunctie Poissonian Distribution Mean Poisson Verdeling Poissonian Probability Mass Function Poisson Kansfunctie Poissonian Distribution Variance Poisson Variantie Arc Cosine Arccosinus Arc Sine Arcsinus Arc Tangent Arctangens Cosine Cosinus Cotangent Cotangens Cosecant Cosecans Radians Radiaal Secant Secans Sine Sinus Tangent Tangens cannot execute function %1 functie %1 kan niet uitgevoerd worden function accepts 1 argument functie accepteert 1 argument function accepts %1 arguments functie accepteert %1 argumenten function requires 1 or 2 arguments functie heeft 1 of 2 parameters nodig function undefined for specified arguments functie ongedefinieerd voor gegeven parameters function requires at least 2 arguments functie heeft minstens 2 parameters nodig function requires integer arguments functie heeft gehele getallen als parameter nodig function undefined for specified argument functie niet gedefineerd voor gegeven parameter underflow onder het bereik function requires at least 1 argument functie heeft minstens 1 parameter nodig Extension of Factorials [= (x-1)!] Uitbreiding van Faculteiten [= (x-1)!] ln(abs(Gamma)) ln(abs(Gamma)) Error Function Foutfunctie Complementary Error Function Complementaire Foutfunctie Degrees of Arc Graden van Arc Mask to a bit size Maskeer tot de grootte van een bit Sign-extent a value Teken-uitbreiding van een waarde Logical NOT Logische NOT Logical AND Logische AND Logical OR Logische OR Logical XOR Logische XOR Arithmetic Shift Left Arimetische Verschuiving naar Links Arithmetic Shift Right Arimetische Verschuiving naar Rechts Integer Quotient Gehele Quotiënt Modulo Modulo FunctionsDock Functions Functies Search Zoeken No match found Geen resultaten gevonden HistoryDock History Geschiedenis InsertFunctionDlg Name Naam Description Beschrijving &Insert &Invoegen Cancel Annuleren Insert Function Voeg Functie toe InsertVariableDlg Name Naam Value Waarde &Insert &Invoegen Insert Variable Voeg Variabele toe Cancel Annuleren Keypad Inverse cosine Inverse cosinus The last result Het laatste resultaat Inverse sine Inverse sinus Inverse tangent Inverse tangens Clear expression Wis expressie Cosine Cosinus Scientific notation Wetenschappelijke notering Exponential Exponentieel Natural logarithm Natuurlijk logaritme Sine Sinus Square root Vierkantswortel Tangent Tangens Assign variable x Ken variabele x toe The variable x De variabele x MainWindow About Qt Over Qt SpeedCrunch Sessions (*.sch);;All Files (*) SpeedCrunch Sessies (*.sch);;Alle Bestanden (*) Load Session Laad Sessie Error Fout Can't read from file %1 Kan niet van bestand %1 lezen Question Vraag Save Session Sessie Opslaan Can't write to file %1 Kan niet naar bestand %1 schrijven Warning Waarschuwing To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Voeg een functie toe met het toetsenbord met sneltoets Ctrl+F. Vanuit het venster kan je kiezen welke functie je wilt invoegen. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Voeg een variabele toe met het toetsenbord met sneltoets Ctrl+I. Vanuit het venster kan je kiezen welke variabele je wilt invoegen. Use variable <i>pi</i> to use pi constant. Gebruik variabele <i>pi</i> om constante pi te gebruiken. Use <i>;</i> (semicolon) to separate the parameters in functions. Gebruik <i>;</i> (puntkomma) om de parameters in fucties te scheiden. Tip of the day Tip van de dag File %1 is not a valid session Bestand %1 is geen geldige sessie Merge session being loaded with current session? If no, current variables and display will be cleared. Moet de geladen sessie worden samengevoeg met de huidige sessie?Zo niet, worden de huidige variabelen en weergave gewist. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. SpeedCrunch is geminimaliseerd.Klik met links op het icoon om het te herstellen of met rechts voor opties. Degree Graden All Files (*) Alle Bestanden (*) Radian Radiaal The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. De menubalk is nu verborgen. Om hem weer zichtbaar te maken, druk op Ctrl+Alt+M. Binary Binair Engineering decimal Technische decimaal Fixed decimal Gefixeerde decimaal General decimal Algemene decimaal Hexadecimal Hexadecimaal Octal Octaal Scientific decimal Wetenschappelijke decimaal Import Session Importeer Sessie Merge session being imported with current session? If no, current variables and display will be cleared. Moet de geïmporteerde sessie worden samengevoeg met de huidige sessie?Zo niet, worden de huidige variabelen en weergave gewist. Export Session Exporteer Sessie Math Book Wiskunde Boek &Session &Sessie Clear E&xpression Wis E&xpressie Clear &History Wis &Geschiedenis &Degree &Graden Delete All V&ariables Verwijder alle V&ariabelen D&elete Variable... V&erwijder Variabele... &15 Decimal Digits &15 Decimalen &2 Decimal Digits &2 Decimalen &3 Decimal Digits &3 Decimalen &50 Decimal Digits &50 Decimalen &8 Decimal Digits &8 Decimalen &Automatic Precision &Automatische Precisie &Copy &Kopiëren Copy Last &Result Kopieer Laatste &Resultaat &Paste &Plakken &About &Over About &Qt Over &Qt SpeedCrunch &Web Site... SpeedCrunch &Web Site... &Tip of the Day &Tip van de Dag Insert &Function... Voeg &Functie in... Insert &Variable... Voeg &Variabele in... &Partial Results &Gedeeltelijke Resultaten Automatic &Completion Automatische &Aanvulling Always On &Top Altijd &Bovenaan &Minimize To System Tray &Minimaliseer Naar De Systeemtray Syntax &Highlighting Syntax &Oplichting &System Default &Systeem Standaard &Dot &Punt &Comma &Komma &Radian &Radiaal Scroll Display Down Scroll Het Scherm Naar Beneden Scroll Display Up Scroll Het Scherm Naar Boven &Select Expression &Selecteer Expressie &Import... &Importeer... &Load... &Laad... &Quit &Afsluiten &Save... &Opslaan... &Export... &Exporteer... Math &Book Wiskunde &Boek &Constants &Constanten Full &Screen Mode Volledige &Scherm Modus &Functions &Functies &History &Geschiedenis &Keypad &Toetsenpaneel Hide &Menu Bar Verberg &Menubalk &Status Bar &Statusbalk &Variables &Variabelen &Binary &Binair &Engineering &Technisch &Fixed Decimal &Gefixeerde Decimaal &General &Algemeen &Hexadecimal &Hexadecimaal &Octal &Octaal &Scientific &Wetenschappelijk System &Default Systeem &Standaard &Edit &Bewerken &View &Beeld Se&ttings &Instellingen Result &Format Resultaat &Opmaak &Decimal &Decimaal &Angle Unit &Hoek Eenheid &Behavior &Gedrag Radix &Character Grondtal &Teken &Language &Taal &Help &Help Angle unit Hoek eenheid Result format Resultaat opmaak Ignore error? Fout negeren? VariablesDock Variables Variabelen Search Zoeken No match found Geen resultaten gevonden speedcrunch-0.10.1/src/i18n/tr.ts0000644000175000001440000017260311015364561015634 0ustar helderusers AboutBox About SpeedCrunch SpeedCrunch Hakkında SpeedCrunch version %1 SpeedCrunch sürüm %1 Original author İlk Yazar Current maintainer Projeyi Yürüten Based on original idea from Orijinal fikri veren Special thanks to Özel Teşekkür Thanks to Teşekkürler ...and many others... ...ve daha birçokları... Translations Çeviriler Argentinian Spanish Arjantin İspanyolcası Brazilian Portuguese Brezilya Portekizcesi Czech Çekçe Dutch Flamanca French Fransızca Finnish German Almanca Hebrew İbranice Italian İtalyanca Norwegian Norveççe Portuguese Portekizce Romanian Romence Russian Rusça Spanish İspanyolca Swedish İsveççe Copyright (C) Telif hakları (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Bu uygulama bir özgür yazılımdır; Free Software Foundation tarafından yayınlanan GNU Genel Kamu Lisansı'nın 2.sürümünün ya da daha yeni bir sürümünün belirlediği şartlar altında bu uygulamayı değiştirebilir ve/veya yeniden dağıtabilirsiniz This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Bu uygulama kullanışlı olması umuduyla dağıtıldı ama HİÇBİR GARANTİ VERMİYORUZ; önceki cümlede kastedilen garanti içerisine BELİRLİ BİR AMACA UYGUNLUK ve TİCARİ garanti de dahildir. Daha fazla ayrıntı için Genel Kamu Lisansına bakınız. Visit <b>http://www.speedcrunch.org</b> for more information! Daha fazla bilgi için <b>http://www.speedcrunch.org</b> adresini ziyaret edin! Developers Geliştiriciler Indonesian Endonezyaca Polish Polonyaca Turkish Türkçe Close Kapat Graphics Basque Simplified Chinese Catalan BookDock Back Forward Index ConstantCompletion All Tümü Constants Characteristic Impedance of Vacuum ' General Physics Genel Fizik Electric Constant Elektrik Sabiti Magnetic Constant Manyetik Sabit Gravitation Constant Gravitation Sabiti Planck's Constant Planck Sabiti Dirac's Constant Dirac Sabiti Speed of Light in Vacuum Bohr-Procopiu Magneton Electromagnetic Elektromanyetik Conductance Quantum İletkenlik Kuantumu Coulomb's Constant Coulomb Sabiti Elementary Charge Josephson Constant Josephson Sabiti Magnetic Flux Quantum Nuclear Magneton Resistance Quantum von Klitzing Constant von Klitzing Sabiti Bohr Radius Atomic & Nuclear Atomik & Nükleer Fermi Coupling Constant Fermi Coupling Sabiti Fine-structure Constant Hartree Energy Quantum of Circulation Sirkülasyon Kuantumu Rydberg Constant Rydberg Sabiti Thomson Cross Section Weak Mixing Angle Atomic Mass Unit Atomik Kütle Birimi Physico-chemical Fiziko-kimyasal Avogadro's Number Avogadro Sabiti Boltzmann Constant Boltzmann Sabiti Faraday Constant Faraday Sabiti First Radiation Constant İlk Radyasyon Sabiti Loschmidt Constant Loschmidt Sabiti Gas Constant Gaz Sabiti Molar Planck Constant Planck Kütlesi Sabiti Second Radiation Constant İkinci Radyasyon Sabiti Stefan-Boltzmann Constant Stefan-Boltzmann Sabiti Astronomical Unit Astronomik Birim Astronomy Astronomi Light Year Işık Yılı Parsec Parsec (3.26 Işık yılı) Sidereal Year Yıldız Yılı days gün Tropical Year Tropikal Yıl Gregorian Year Miladi Yıl Earth Mass Dünya'nın Kütlesi Sun Mass Güneş'in Kütlesi Mean Earth Radius Sun Radius Güneş'in Yarıçapı Sun Luminosity Güneş Parlaklığı ConstantsDock Constants Sabitler Category Kategori Search Ara No match found Eşleşen bulunamadı All Tümü DeleteVariableDlg Delete Variable Değişken Sil Name İsim Value Değer &Delete &Sil Close Kapat Editor Current result: <b>%1</b> Selection result: <b>%1</b> Evaluator invalid expression division by zero unknown function or variable variable cannot be overwritten identifier matches an existing function name Functions Absolute Value Mutlak Değer Average (Arithmetic Mean) Ortamala (Aritmetik Ortalama) Binary Representation İkilik Gösterim Cube Root Küp Kök Ceiling Tavan Decimal Representation Ondalık Gösterim Floor Taban Fractional Part Kesirli Bölüm Geometric Mean Geometrik Anlamı Hexadecimal Representation Onaltılık Gösterim Integer Part Tamsayı Bölümü Maximum En fazla Minimum En az Octal Representation Sekizlik Gösterim Product Ürün Rounding Yuvarlama Square Root Kare kök Sum Toplama Truncation Kesme Hyperbolic Cosine Hiperbolik Kosinüs Exponential Üstel Base-2 Logarithm 2'lik Taban Logaritma Natural Logarithm Doğal Logaritma Base-10 Logarithm 10'luk Taban Logaritma Hyperbolic Sine Hiperbolik Sinüs Hyperbolic Tangent Hiperbolik Tanjant Greatest Common Divisor Ortak Blenlerin En Büyüğü Combination (Binomial Coefficient) Kombinasyon (İki Terimli Katsayı) Permutation (Arrangement) Permütasyon (Sıralama) Arc Cosine Kosinüs Açısı Arc Sine Sinüs Açısı Arc Tangent Tanjant Açısı Cosine Kosinüs Cotangent Kotanjant Cosecant Kosekant Radians Radyan Secant Sekant Sine Sinüs Tangent Tanjant cannot execute function %1 %1 fonksiyonu çalıştırılamadı function accepts 1 argument fonksiyon 1 argüman kabul ediyor function accepts %1 arguments fonksiyon %1 argüman kabul ediyor function requires 1 or 2 arguments fonksiyon 1 ya da 2 argüman gerektiriyor function undefined for specified arguments belirtilen argümanlar için fonksiyon tanımlanmadı function requires at least 2 arguments fonksiyon en az 2 argüman gerektiriyor function requires integer arguments fonksiyon tamsayı argümanlar gerektiriyor function undefined for specified argument belirtilen argüman için fonksiyon tanımlanmadı underflow function requires at least 1 argument fonksiyon en az 1 argüman gerektiriyor Extension of Factorials [= (x-1)!] ln(abs(Gamma)) Signum Area Hyperbolic Cosine Area Hyperbolic Sine Area Hyperbolic Tangent Binomial Cumulative Distribution Function Binomial Distribution Mean Binomial Probability Mass Function Binomial Distribution Variance Error Function Complementary Error Function Hypergeometric Cumulative Distribution Function Hypergeometric Distribution Mean Hypergeometric Probability Mass Function Hypergeometric Distribution Variance Poissonian Cumulative Distribution Function Poissonian Distribution Mean Poissonian Probability Mass Function Poissonian Distribution Variance Degrees of Arc Mask to a bit size Sign-extent a value Logical NOT Logical AND Logical OR Logical XOR Arithmetic Shift Left Arithmetic Shift Right Integer Quotient Modulo FunctionsDock Functions Fonksiyonlar Search Ara No match found Eşleşen bulunamadı HistoryDock History Geçmiş InsertFunctionDlg Insert Function Fonksiyon Ekle Name İsim Description Tanım &Insert &Ekle Cancel İptal InsertVariableDlg Insert Variable Değişken Ekle Name İsim Value Değer &Insert &Ekle Cancel İptal Keypad Inverse cosine Ters kosinüs The last result Inverse sine Ters sinüs Inverse tangent Ters tanjant Clear expression Cosine Kosinüs Scientific notation Exponential Üstel Natural logarithm Sine Sinüs Square root Kare kök Tangent Tanjant Assign variable x The variable x MainWindow About Qt Qt Hakkında File %1 is not a valid session SpeedCrunch Sessions (*.sch);;All Files (*) Load Session Error Hata Can't read from file %1 Merge session being loaded with current session? If no, current variables and display will be cleared. Question Save Session Oturumu Kaydet Can't write to file %1 %1 dosyasına yazılamıyor Warning To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Klavyeyi kullanarak fonksiyon girmek için Ctrl+F kısayolunu kullanın. Girmek istediğiniz fonksiyonu pencereden seçebilirsiniz. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Klavyeyi kullanarak değişken girmek için Ctrl+I kısayolunu kullanın. Girmek istediğiniz değişkeni pencereden seçebilirsiniz. Use variable <i>pi</i> to use pi constant. Pi sabiti için <i>pi</i> değişkenini kullan. Use <i>;</i> (semicolon) to separate the parameters in functions. Fonksiyonlarda parametreleri ayırmak için <i>;</i> (noktalı virgül) kullanın. Tip of the day SpeedCrunch is minimized. Left click the icon to restore it or right click for options. Degree All Files (*) Radian The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. Binary Engineering decimal Fixed decimal General decimal Hexadecimal Octal Scientific decimal Import Session Merge session being imported with current session? If no, current variables and display will be cleared. Export Session Math Book &Session &Oturum Clear E&xpression Clear &History Ge&çmişi Temizle &Degree Delete All V&ariables D&elete Variable... Değişk&en Sil... &15 Decimal Digits &15 Ondalık Basamak &2 Decimal Digits &2 Ondalık Basamak &3 Decimal Digits &3 Ondalık Basamak &50 Decimal Digits &50 Ondalık Basamak &8 Decimal Digits &8 Ondalık Basamak &Automatic Precision Otomatik &Hassasiyet &Copy &Kopyala Copy Last &Result &Paste &Yapıştır &About H&akkında About &Qt &Qt Hakkında SpeedCrunch &Web Site... SpeedCrunch &Web Sitesi... &Tip of the Day Günün İpuc&u Insert &Function... &Fonksiyon Ekle... Insert &Variable... &Değişken Ekle... &Partial Results Automatic &Completion Always On &Top &Minimize To System Tray Syntax &Highlighting &System Default &Dot &Comma &Radian Scroll Display Down Scroll Display Up &Select Expression &Import... &Load... &Quit &Çık &Save... &Kaydet... &Export... Math &Book &Constants Full &Screen Mode &Functions &History &Keypad Hide &Menu Bar &Status Bar &Variables &Binary &İkilik &Engineering &Mühendislik &Fixed Decimal &Sabit Ondalık &General &Genel &Hexadecimal &Onaltılık &Octal &Sekizlik &Scientific &Bilimsel System &Default &Edit &Düzenle &View &Görünüm Se&ttings &Ayarlar Result &Format &Decimal &Angle Unit &Behavior Radix &Character &Language &Help &Yardım Angle unit Result format Ignore error? VariablesDock Variables Değişkenler Search Ara No match found Eşleşen bulunamadı speedcrunch-0.10.1/src/i18n/sv.ts0000644000175000001440000017332411015364561015640 0ustar helderusers AboutBox About SpeedCrunch Om SpeedCrunch SpeedCrunch version %1 SpeedCrunch version %1 Original author Ursprunglig skapare Current maintainer Nuvarande projektledare Based on original idea from Baserad kring en ursprunlig ide av Special thanks to Särskilt tack till Thanks to Tack till ...and many others... ...och många fler... Translations Översättningar French Franska German Tyska Italian Italienska Norwegian Norska Portuguese Portugisiska Brazilian Portuguese Brasilians portugisiska Russian Ryska Spanish Spanska Copyright (C) Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Detta program är fri mjukvara; du får sprida det vidare och/eller ändra det enligt reglerna i GNU General Public License som publicerat av Free Software Foundation; antingen version 2 av licensen, eller (om du så önskar) valfri senare version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Detta program distribueras i hopp om att det skall vara användbart, men UTAN NÅGON FORM AV GARANTI; utan ens en underförstådd garanti vid KÖP eller LÄMPLIGHET FÖR NÅGOT SÄRSKILT SYFTE. Detaljer återfinns i GNU General Public License. Visit <b>http://www.speedcrunch.org</b> for more information! Besök <b>http://www.speedcrunch.org</b> för mer information! Argentinian Spanish Argentisk Spanska Dutch Hollänska Hebrew Hebreiska Swedish Svenska Finnish Finska Czech Tjeckiska Romanian Rumänska Developers Utvecklare Indonesian Indonesiska Polish Polska Turkish Turkiska Close Stäng Graphics Grafik Basque Simplified Chinese Catalan BookDock Back Tillbaka Forward Nästa Index Index ConstantCompletion All Samtliga Constants Characteristic Impedance of Vacuum Typisk Impedans i Vakuum General Physics Allmän fysik Electric Constant Permittiviteten i Vakuum Magnetic Constant Magnetisk konstant Gravitation Constant Gravitationskonstanten Planck's Constant Plancks Konstant Dirac's Constant Diracs Konstant Speed of Light in Vacuum Ljushastigheten i Vakuum Bohr-Procopiu Magneton Bohrmagneton Electromagnetic Elektromagnetism Conductance Quantum Konduktivitetskvantum Coulomb's Constant Coulomb's Konstant Elementary Charge Elementarladdningen Josephson Constant Josephsons Constant Magnetic Flux Quantum Magnetiskt flödeskvantum Nuclear Magneton Nukleär Magneton Resistance Quantum Resistivt kvantum von Klitzing Constant von Klitzings Konstant Bohr Radius Bohrradie Atomic & Nuclear Atom- & kärnfysik Fermi Coupling Constant Fermis bindningskonstant Fine-structure Constant Fin-strukturkonstanten Hartree Energy Hartree-energi Quantum of Circulation Omloppskvanta Rydberg Constant Rydbergs Konstant Thomson Cross Section Thomsons tvärsnitt Weak Mixing Angle Svag blandningsvinkel Atomic Mass Unit Atomära Masskonstanten Physico-chemical Fysisk kemi Avogadro's Number Avogadros Tal Boltzmann Constant Boltzmanns Konstant Faraday Constant Faradays Konstant First Radiation Constant Första Stråliningskonstanten Loschmidt Constant Loschmidts Konstant Gas Constant Gaskonstanten Molar Planck Constant Plancks Konstant Second Radiation Constant Andra Strålningskonstanten Stefan-Boltzmann Constant Stefan-Boltzmanns Konstant Astronomical Unit Astronomisk Enhet Astronomy Astronomi Light Year Ljusår Parsec Parsec Sidereal Year Sideriskt År days dagar Tropical Year Tropiskt År Gregorian Year Gregorianskt År Earth Mass Jordens Massa Sun Mass Solens Massa Mean Earth Radius Jordens Genomsnittliga Radie Sun Radius Solens Radie Sun Luminosity Solens Luminositet ConstantsDock Constants Konstanter Category Kategori Search Sök No match found Ingen träff All Samtliga DeleteVariableDlg Delete Variable Ta bort variabel Name Namn Value Värde &Delete &Ta bort Close Stäng Editor Current result: <b>%1</b> Nuvarande resultat: <b>%1</b> Selection result: <b>%1</b> Valt resultat: <b>%1</b> Evaluator invalid expression ogiltigt uttryck division by zero division med noll unknown function or variable okänd funktion eller variabel variable cannot be overwritten variabelvärde kan ej ändras identifier matches an existing function name identifierare matchar en existerande funtion Functions Absolute Value Absolutvärde Average (Arithmetic Mean) Medelvärde (Aritmetiskt Medelvärde) Binary Representation Binär Representation Cube Root Kubikroten Ceiling Tak Decimal Representation Decimal Representation Floor Golv Fractional Part Fraktion Geometric Mean Geometriskt Medelvärde Hexadecimal Representation Hexadecimal Representation Integer Part Heltal Maximum Max Minimum Minimum Octal Representation Oktal Representation Product Produkt Rounding Avrundning Signum Tecken Square Root Kvadratrot Sum Summa Truncation Trunkering Area Hyperbolic Cosine Invers Hyperbolisk Cosinus Area Hyperbolic Sine Invers Hyperbolisk Sinus Area Hyperbolic Tangent Invers Hyperbolisk Tangent Hyperbolic Cosine Hyperbolisk Cosinus Exponential Exponential Base-2 Logarithm 2-bas Logaritm Natural Logarithm Naturlig Logaritm Base-10 Logarithm 10-bas Logaritm Hyperbolic Sine Hyperbolisk Sinus Hyperbolic Tangent Hyperbolisk Tangent Greatest Common Divisor Största Gemensamma Nämnare Combination (Binomial Coefficient) Biominal Koeficient Permutation (Arrangement) Permutation Binomial Cumulative Distribution Function Binomial Kumulativ distributionsfunktion Binomial Distribution Mean Binomial distributionssnitt Binomial Probability Mass Function Binomial sannolikhetsmassfunktion Binomial Distribution Variance Binomial distributionsvarians Hypergeometric Cumulative Distribution Function Hypergeometrisk kumulativ distributionsfunktion Hypergeometric Distribution Mean Hypergeometrisk distributionsgenomsnitt Hypergeometric Probability Mass Function Hypergeometrisk sannolikhetsmassfunktion Hypergeometric Distribution Variance Hypergeometrisk distributionsvarians Poissonian Cumulative Distribution Function Poissonsk kumulativ distributionsfunktion Poissonian Distribution Mean Poissonsk distributionsgenomsnitt Poissonian Probability Mass Function Poissonsk sannolikhetsmassfunktion Poissonian Distribution Variance Poissonsk distrubutionsvarians Arc Cosine Arcuscosinus Arc Sine Arcussinus Arc Tangent Argustangens Cosine Cosinus Cotangent Cotangens Cosecant Cosecant Radians Radianer Secant Sekant Sine Sinus Tangent Tangens cannot execute function %1 kan ej genomföra funktion %1 function accepts 1 argument funktionen tar 1 argument function accepts %1 arguments funktionen at %1 argument function requires 1 or 2 arguments funktionen förväntar 1 eller 2 argument function undefined for specified arguments funktionen är odefinierad för givet antal argument function requires at least 2 arguments funktionen kräver minst 2 argument function requires integer arguments funktionen kräver heltalsargument function undefined for specified argument funktionen är odefinierad för givet argument underflow underflöde function requires at least 1 argument funktionen kräver minst 1 argument Extension of Factorials [= (x-1)!] Förlängning av faktorial [= (x-1)!] ln(abs(Gamma)) In(abs(Gamma)) Error Function Felfunktion Complementary Error Function Komplementär felfunktion Degrees of Arc Grader Mask to a bit size Maska till bitstorlek Sign-extent a value Tecken-utöka värde Logical NOT Logiskt ICKE Logical AND Logiskt OCH Logical OR Logiskt ELLER Logical XOR Logiskt EXKLUSIVT ELLER Arithmetic Shift Left Aritmetisk vänstershift Arithmetic Shift Right Aritmetisk högershift Integer Quotient Heltalskvot Modulo Modulo FunctionsDock Functions Funktioner Search Sök No match found Ingen träff HistoryDock History Historik InsertFunctionDlg Insert Function Infoga Funktion Name Namn Description Beskrivning &Insert &Infoga Cancel Avbryt InsertVariableDlg Insert Variable Infoga variabel Name Namn Value Värde &Insert &Infoga Cancel Avbryt Keypad Inverse cosine Arcusconsinus The last result Senaste resultat Inverse sine Arcussinus Inverse tangent Arcustangens Clear expression Rensa uttryck Cosine Cosinus Scientific notation Vetenskaplig notation Exponential Exponential Natural logarithm Naturlig logaritm Sine Sinus Square root Kvadratrot Tangent Tangens Assign variable x Tilldela variabel x The variable x Variabeln x MainWindow About Qt Om Qt SpeedCrunch Sessions (*.sch);;All Files (*) SpeedCrunch-sessioner (*.sch);;Alla filtyper (*) Load Session Öppna session Error Fel Can't read from file %1 Kan inte läsa från filen %1 Question Fråga Save Session Spara Session Can't write to file %1 Kan inte skriva till filen %1 Warning Varning To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Du kan infoga en funktion med hjälp av tangentbordet genom att trycka Ctrl+F. I dialogrutan väljer du sedan den funktion du vill infoga. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Du kan infoga en variabel med hjälp av tangentbordet genom att trycka Ctrl+I. I dialogrutan väljer du sedan vilken variabel du vill infoga. Use variable <i>pi</i> to use pi constant. Använd variabeln <i>pi</i> för att ange värdet pi. Use <i>;</i> (semicolon) to separate the parameters in functions. Använd -<i>;</i> (semikolon) för att separera funktionsparametrar. Tip of the day Dagens tips File %1 is not a valid session Filen %1 är inte en giltig session Merge session being loaded with current session? If no, current variables and display will be cleared. Sammanfoga sessionen som öppnas med nuvarande session? Om nej kommer nuvarande variabler och historik rensas. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. SpeedCrunch är minimerad. Klicka med vänster musknapp på ikonen för att återställa, eller använd höger musknapp för alternativ. Degree Grader All Files (*) Alla filtyper (*) Radian Radian The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. Menyn är nu dåld. För att visa den igen, tryck Ctrl+Alt+M. Binary Binär Engineering decimal Ingenjörsdecimal Fixed decimal Fixerad decimal General decimal Allmän decimal Hexadecimal Hexadecimal Octal Oktal Scientific decimal Vetenskaplig decimal Import Session Importera session Merge session being imported with current session? If no, current variables and display will be cleared. Sammanfoga sessionen som importeras med nuvarande session?Om nej kommer nuvarande variabler och historik rensas. Export Session Exportera session Math Book Matematikbok &Session &Session Clear E&xpression Rensa &Uttryck Clear &History Rensa &Historik &Degree &Grader Delete All V&ariables Rensa &alla variabler D&elete Variable... &Ta bort Variabel... &15 Decimal Digits &15 Decimaler &2 Decimal Digits &2 Decimaler &3 Decimal Digits &3 Decimaler &50 Decimal Digits &50 Decimaler &8 Decimal Digits &8 Decimaler &Automatic Precision &Automatisk Precision &Copy &Kopiera Copy Last &Result Kopiera senaste &resultat &Paste Klistra &In &About &Om About &Qt Om &Qt SpeedCrunch &Web Site... SpeedCrunch &Hemsida... &Tip of the Day &Dagens tips Insert &Function... Infoga &Funktion... Insert &Variable... Infoga &Variabel... &Partial Results &Partiella resultat Automatic &Completion Automatisk &Komplettering Always On &Top Alltid &överst &Minimize To System Tray &Minimera till systemlisten Syntax &Highlighting F&ärgkoda syntax &System Default &Systeminställningar &Dot &Punkt &Comma &Komma &Radian &Radian Scroll Display Down Skrolla neråt Scroll Display Up Skrolla uppåt &Select Expression &Valt uttryck &Import... &Importera... &Load... &Öppna... &Quit A&vsluta &Save... &Spara... &Export... &Exportera... Math &Book Matematik&bok &Constants &Konstanter Full &Screen Mode Full&skärm &Functions &Funktioner &History &Historik &Keypad &Knappsats Hide &Menu Bar Dölj &menylist &Status Bar &Statuslist &Variables &Variabler &Binary &Binärt &Engineering &Ingenjörsdecimaler &Fixed Decimal &Fixerade Decimaler &General &Generellt &Hexadecimal &Hexadecimal &Octal &Oktal& &Scientific &Vetenskapliga Decimaler System &Default System&inställning &Edit &Redigera &View &Visa Se&ttings &Inställningar Result &Format Resultat&formattering &Decimal &Decimal &Angle Unit &Vinkelenheter &Behavior &Uppträdande Radix &Character Talbaste&cken &Language &Språk &Help &Hjälp Angle unit Vinkelenheter Result format Resultatformattering Ignore error? Ignorera fel? VariablesDock Variables Variabler Search Sök No match found Ingen träff speedcrunch-0.10.1/src/i18n/fr.ts0000644000175000001440000017426311015364561015622 0ustar helderusers AboutBox Special thanks to Grands remerciements à French Français German Allemand Portuguese Portugais Russian Russe Italian Italien This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version SpeedCrunch est un logiciel libre; vous pouvez le redistribuer et le modifier conformément à la licence "GNU General Public License" telle que publiée à la "Free Software Foundation"; soit la version deuxième, soit selon votre convenance n'importe quelle version ultérieure à cette dernière This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Ce programme est distribué dans l'espoir qu'il sera utile et plaisant, mais SANS GARANTIE AUCUNE; même avec le concept implicite de VALEUR MARCHANDE. Référez-vous pour plus de détails à la "GNU General Public License". SpeedCrunch version %1 Version de SpeedCrunch : %1 About SpeedCrunch À propos de SpeedCrunch Norwegian Norvégien Spanish Espagnol Original author Auteur initial Current maintainer Mainteneur actuel Based on original idea from Basé sur une idée originale de Thanks to Merci à ...and many others... ... et beaucoup d'autres... Translations Traductions Brazilian Portuguese Brésilien Portugais Copyright (C) Copyright (C) Visit <b>http://www.speedcrunch.org</b> for more information! Allez sur <b>http://www.speedcrunch.org</b> pour de plus amples informations ! Argentinian Spanish Espagnol Argentin Dutch Néerlandais Hebrew Hébreu Swedish Suédois Finnish Finnois Czech Tchèque Romanian Roumain Developers Développeurs Indonesian Indonésien Polish Polonais Turkish Turque Close Fermer Graphics Basque Simplified Chinese Catalan BookDock Back Forward Index ConstantCompletion All Tout Constants Characteristic Impedance of Vacuum Impédence Caractéristique du Vide General Physics Physique Générale Electric Constant Constante Éléctrique Magnetic Constant Constante Magnétique Gravitation Constant Constante Gravitationnelle Planck's Constant Constante de Planck Dirac's Constant Constante de Dirac Speed of Light in Vacuum Vitesse de la Lumière dans le Vide Bohr-Procopiu Magneton Magneton de Bohr-Procopiu Electromagnetic Eléctromagnétique Conductance Quantum Quantum de Conductibilité Coulomb's Constant Constante de Coulomb Elementary Charge Charge Élémentaire Josephson Constant Constante de Josephson Magnetic Flux Quantum Quantum de Flux Magnétique Nuclear Magneton Magneton Nucléaire Resistance Quantum Quantum de Résistance von Klitzing Constant Constante de von Klitzing Bohr Radius Rayon de Bohr Atomic & Nuclear Atomique & Nucléaire Fermi Coupling Constant Constante de Fermi Coupling Fine-structure Constant Constante de Structure Fine Hartree Energy Énergie de Hartree Quantum of Circulation Quantum de Circulation Rydberg Constant Constante de Rydberg Thomson Cross Section Section Croisée de Thomson Weak Mixing Angle Angle de Weinberg Atomic Mass Unit Unité de Masse Atomique Physico-chemical Physico-chimique Avogadro's Number Nombre d'Avogadro Boltzmann Constant Constante de Boltzmann Faraday Constant Constante de Faraday First Radiation Constant Constante de Première Radiation Loschmidt Constant Constante de Loschmidt Gas Constant Constante Universelle des Gaz Parfaits Molar Planck Constant Constante Molaire de Planck Second Radiation Constant Constante de Seconde Radiation Stefan-Boltzmann Constant Constante de Stefan-Boltzmann Astronomical Unit Unité Astronomique Astronomy Astronomie Light Year Année Lumière Parsec Parsec Sidereal Year Année Sidérale days jours Tropical Year Année Tropicale Gregorian Year Année Grégorienne Earth Mass Masse de la Terre Sun Mass Masse du Soleil Mean Earth Radius Rayon Moyen de la Terre Sun Radius Rayon du soleil Sun Luminosity Luminosité du Soleil ConstantsDock Constants Constantes Category Catégorie Search Recherche No match found Aucun élément trouvé All Tout DeleteVariableDlg Name Nom Value Valeur &Delete E&ffacer Close Fermer Delete Variable Effacer la variable Editor Current result: <b>%1</b> Selection result: <b>%1</b> Evaluator invalid expression division by zero unknown function or variable variable cannot be overwritten identifier matches an existing function name Functions Absolute Value Valeur Absolue Average (Arithmetic Mean) Moyenne (Arithmétique) Binary Representation Représentation Binaire Cube Root Racine Cubique Ceiling Plafond Decimal Representation Représentation Décimale Floor Plancher Fractional Part Partie Fractionnée Geometric Mean Géométrique Hexadecimal Representation Représentation Hexadécimale Integer Part Partie Entière Maximum Maximum Minimum Minimum Octal Representation Représentation Octale Product Produit Rounding Arrondi Signum Signum Square Root Racine Carrée Sum Somme Truncation Troncation Area Hyperbolic Cosine Area-cosinus hyperbolique Area Hyperbolic Sine Area-sinus hyperbolique Area Hyperbolic Tangent Area-tangente hyperbolique Hyperbolic Cosine Cosinus Hyperbolique Exponential Exponentiel Base-2 Logarithm Logarithme de Base 2 Natural Logarithm Logarithme Népérien Base-10 Logarithm Logarithme de Base 10 Hyperbolic Sine Sinus Hyperbolique Hyperbolic Tangent Tangente Hyperbolique Greatest Common Divisor Plus Grand Diviseur Commun Combination (Binomial Coefficient) Combinaison (Coefficient Binomial) Permutation (Arrangement) Permutation (Arrangement) Binomial Cumulative Distribution Function Fonction de Distribution Cumulative Binomiale Binomial Distribution Mean Moyenne de Distribution Binomiale Binomial Probability Mass Function Fonction Binomiale de Probabilité de Masse Binomial Distribution Variance Variance de Distribution Binomiale Hypergeometric Cumulative Distribution Function Fonction de Distribution Cumulative Hypergéométrique Hypergeometric Distribution Mean Moyenne de Distribution Hypergéométrique Hypergeometric Probability Mass Function Fonction Hypergéométrique de Probabilité de Masse Hypergeometric Distribution Variance Variance de Distribution Hypergéométrique Poissonian Cumulative Distribution Function Fonction de Distribution Cumulative Poissonienne Poissonian Distribution Mean Moyenne de Distribution Poissonienne Poissonian Probability Mass Function Fonction Poissonienne de Probabilité de Masse Poissonian Distribution Variance Variance de Distribution Poissonienne Arc Cosine Arc Cosinus Arc Sine Arc Sinus Arc Tangent Arc Tangente Cosine Cosinus Cotangent Cotangente Cosecant Cosécante Radians Radians Secant Sécante Sine Sinus Tangent Tangente cannot execute function %1 ne peut exécuter la fonction %1 function accepts 1 argument La fonctionaccepte 1 argument function accepts %1 arguments La fonctionaccepte %1 arguments function requires 1 or 2 arguments la fonction doit avoir 1 ou 2 arguments function undefined for specified arguments fonction indéfinie pour les arguments spécifiés function requires at least 2 arguments la fonction doit avoir au moins 2 arguments function requires integer arguments la fonction doit avoir des arguments entiers function undefined for specified argument fonction indéfinie pour l'argument spécifié underflow function requires at least 1 argument la fonction doit avoir au moins 1 argument Extension of Factorials [= (x-1)!] ln(abs(Gamma)) Error Function Complementary Error Function Degrees of Arc Mask to a bit size Sign-extent a value Logical NOT Logical AND Logical OR Logical XOR Arithmetic Shift Left Arithmetic Shift Right Integer Quotient Modulo FunctionsDock Functions Fonctions Search Recherche No match found Aucun élément trouvé HistoryDock History Historique InsertFunctionDlg Name Nom Description Description &Insert &Insérer Cancel Annuler Insert Function Insérer une fonction InsertVariableDlg Name Nom Value Valeur &Insert &Insérer Cancel Annuler Insert Variable Insérer une variable Keypad Inverse cosine Cosinus Inverse The last result Inverse sine Sinus Inverse Inverse tangent Tangente Inverse Clear expression Cosine Cosinus Scientific notation Exponential Exponentiel Natural logarithm Sine Sinus Square root Racine Carrée Tangent Tangente Assign variable x The variable x MainWindow About Qt À Propos de Qt SpeedCrunch Sessions (*.sch);;All Files (*) Load Session Error Erreur Can't read from file %1 Question Save Session Sauvergarder la Session Can't write to file %1 Ne peut écrire dans le fichier %1 Warning To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Pour insérer une fonction avec le clavier, utilisez le raccourci Ctrl+F. À partir de la boite de dialogue, vous pouvez choisir la fonction que vous voulez insérer. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Pour insérer une variable avec le clavier, utilisez le raccourci Ctrl+I. À partir de la boite de dialogue, vous pouvez choisir la variable que vous voulez insérer. Use variable <i>pi</i> to use pi constant. Servez-vous de la variable <i>pi</i> pour utiliser la constante pi. Use <i>;</i> (semicolon) to separate the parameters in functions. Utiliser <i>;</i> (point-virgule) pour séparer les paramètres dans les fonctions. Tip of the day File %1 is not a valid session Merge session being loaded with current session? If no, current variables and display will be cleared. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. Degree All Files (*) Radian The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. Binary Engineering decimal Fixed decimal General decimal Hexadecimal Octal Scientific decimal Import Session Merge session being imported with current session? If no, current variables and display will be cleared. Export Session Math Book &Session &Session Clear E&xpression Clear &History Effacer l'&Historique &Degree Delete All V&ariables D&elete Variable... &Effacer la Variable... &15 Decimal Digits Précision à 10^-&15 &2 Decimal Digits Précision à 10^-&2 &3 Decimal Digits Précision à 10^-&3 &50 Decimal Digits Précision à 10^-&50 &8 Decimal Digits Précision à 10^-&8 &Automatic Precision Précision &Automatique &Copy &Copier Copy Last &Result &Paste C&oller &About &À Propos About &Qt À Propos de &Qt SpeedCrunch &Web Site... Site &Web de SpeedCrunch... &Tip of the Day As&tuce du Jour Insert &Function... Insérer une &Fonction... Insert &Variable... Insérer une &Variable... &Partial Results Automatic &Completion Always On &Top &Minimize To System Tray Syntax &Highlighting &System Default &Dot &Comma &Radian Scroll Display Down Scroll Display Up &Select Expression &Import... &Load... &Quit &Quitter &Save... &Sauvegarder... &Export... Math &Book &Constants Full &Screen Mode &Functions &History &Keypad Hide &Menu Bar &Status Bar &Variables &Binary &Binaire &Engineering &Technologique &Fixed Decimal Décimale &Fixée &General &Hexadecimal &Hexadécimal &Octal &Octal &Scientific &Scientifique System &Default &Edit &Édition &View &Affichage Se&ttings Op&tions Result &Format &Decimal &Angle Unit &Behavior Radix &Character &Language &Help &Aide Angle unit Result format Ignore error? VariablesDock Variables Variables Search Recherche No match found Aucun élément trouvé speedcrunch-0.10.1/src/i18n/pl.ts0000644000175000001440000017350711015364561015626 0ustar helderusers AboutBox Special thanks to Specjalne podziękowania dla French Francuski German Niemiecki Portuguese Portugalski Russian Rosyjski Italian Włoski This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Ten program jest wolnym oprogramowaniem; możesz go rozpowszechniać i modyfikować zgodnie z zasadami licencji publicznej GNU opublikowanej przez Free Software Foundation; zarówno z wersją 2 Licencji, jak i (wg uznania) nowszą This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Ten program jest rozpowszechniany z nadzieją, że będzie użyteczny, ale BEZ ŻADNEJ GWARANCJI; nawet bez gwarancji bycia PRODUKTEM lub JAKIMKOLWIEK KONKRETNYM ZASTOSOWANIEM. Aby dowiedzieć się szczegółów, przeczytaj Licencję Publiczną GNU. SpeedCrunch version %1 SpeedCrunch - wersja %1 Norwegian Norweski About SpeedCrunch O SpeedCrunch Spanish Hiszpański Original author Pierwotny autor Current maintainer Obecny opiekun Based on original idea from Na podstawie pomysłu Thanks to Podziękowania dla następujących osób ...and many others... ...i wielu innych... Translations Tłumaczenia Brazilian Portuguese Brazylijski portugalski Copyright (C) Wszystkie prawa zastrzeżone (C) Visit <b>http://www.speedcrunch.org</b> for more information! Odwiedź <b>http://www.speedcrunch.org</b> aby uzyskać więcej informacji! Argentinian Spanish Argentyński hiszpański Dutch Holenderski Hebrew Hebrajski Swedish Szwedzki Finnish Fiński Czech Czeski Romanian Rumuński Developers Programiści Indonesian Indonezyjski Polish Polski Turkish Turecki Close Zamknij Graphics Basque Simplified Chinese Catalan BookDock Back Wstecz Forward Naprzód Index ConstantCompletion All Wszystko Constants Characteristic Impedance of Vacuum Impedancja właściwa próżni General Physics Fizyka ogólna Electric Constant Stała elektryczna Magnetic Constant Stała magnetyczna Gravitation Constant Stała grawitacji Planck's Constant Stała Plancka Dirac's Constant Stała Diraca Speed of Light in Vacuum Prędkość światła w próżni Bohr-Procopiu Magneton Magneton Bohra-Procopiu Electromagnetic Elektromagnetyzm Conductance Quantum Kwant konduktancji Coulomb's Constant Stała Coulomba Elementary Charge Ładunek elementarny Josephson Constant Stała Josephsona Magnetic Flux Quantum Nuclear Magneton Resistance Quantum von Klitzing Constant Bohr Radius Promień Bohra Atomic & Nuclear Fizyka jądrowa Fermi Coupling Constant Fine-structure Constant Hartree Energy Quantum of Circulation Rydberg Constant Stała Rydberga Thomson Cross Section Weak Mixing Angle Atomic Mass Unit Jednostka masy atomowej Physico-chemical Fizyka chemii Avogadro's Number Liczba Avogadro Boltzmann Constant Stała Boltzmanna Faraday Constant Stała Faradaya First Radiation Constant Loschmidt Constant Gas Constant Stała gazowa Molar Planck Constant Molowa stała Plancka Second Radiation Constant Stefan-Boltzmann Constant Stała Stefana-Boltzmanna Astronomical Unit Jednostka astronomiczna Astronomy Astronomia Light Year Rok świetlny Parsec Parsek Sidereal Year days dni Tropical Year Rok tropikalny Gregorian Year Rok gregoriański Earth Mass Masa Ziemi Sun Mass Masa Słońca Mean Earth Radius Średni promień Ziemi Sun Radius Promień Słońca Sun Luminosity Jasność Słońca ConstantsDock Constants Stałe Category Kategoria Search Szukaj No match found Nie znaleziono dopasowań All Wszystko DeleteVariableDlg Name Nazwa Value Wartość &Delete &Usuń Close Zamknij Delete Variable Usuń zmienną Editor Current result: <b>%1</b> Selection result: <b>%1</b> Evaluator invalid expression division by zero unknown function or variable variable cannot be overwritten identifier matches an existing function name Functions Absolute Value Wartość bezwzględna Average (Arithmetic Mean) Średnia arytmetyczna Binary Representation Reprezentacja dwójkowa Cube Root Pierwiastek sześcienny Decimal Representation Reprezentacja dziesiętna Fractional Part Część ułamkowa Geometric Mean Średnia geometryczna Hexadecimal Representation Reprezentacja szesnastkowa Integer Part Część całkowita Maximum Maksimum Minimum Minimum Octal Representation Reprezentacja ósemkowa Product Iloczyn Rounding Zaokrąglenie Signum Signum Square Root Pierwiastek kwadratowy Sum Suma Truncation Obcięcie Hyperbolic Cosine Kosinus hiperboliczny Base-2 Logarithm Logarytm o podstawie 2 Natural Logarithm Logarytm naturalny Base-10 Logarithm Logarytm dziesiętny Hyperbolic Sine Sinus hiperboliczny Hyperbolic Tangent Tangens hiperboliczny Greatest Common Divisor Największy wspólny dzielnik Combination (Binomial Coefficient) Kombinacja Permutation (Arrangement) Permutacja Arc Cosine Arkus kosinus Arc Sine Arkus sinus Arc Tangent Arkus tangens Cosine Kosinus Radians Radiany Sine Sinus Tangent Tangens cannot execute function %1 nie można wykonać funkcji %1 function accepts 1 argument funkcja przyjmuje jeden argument function accepts %1 arguments funkcja przyjmuje %1 argumentów function requires 1 or 2 arguments funkcja wymaga jednego lub dwóch argumentów function undefined for specified arguments funkcja dla podanych argumentów nie jest zdefiniowana function requires at least 2 arguments funkcja wymaga przynajmniej dwóch argumentów function requires integer arguments funkcja wymaga argumentów całkowitoliczbowych function undefined for specified argument funkcja dla podanego argumentu nie jest zdefiniowana underflow function requires at least 1 argument funkcja wymaga przynajmniej jednego argumentu Ceiling Floor Extension of Factorials [= (x-1)!] ln(abs(Gamma)) Area Hyperbolic Cosine Area Hyperbolic Sine Area Hyperbolic Tangent Exponential Binomial Cumulative Distribution Function Binomial Distribution Mean Binomial Probability Mass Function Binomial Distribution Variance Error Function Complementary Error Function Hypergeometric Cumulative Distribution Function Hypergeometric Distribution Mean Hypergeometric Probability Mass Function Hypergeometric Distribution Variance Poissonian Cumulative Distribution Function Poissonian Distribution Mean Poissonian Probability Mass Function Poissonian Distribution Variance Cotangent Cosecant Degrees of Arc Secant Mask to a bit size Sign-extent a value Logical NOT Logical AND Logical OR Logical XOR Arithmetic Shift Left Arithmetic Shift Right Integer Quotient Modulo FunctionsDock Functions Funkcje Search Szukaj No match found Nie znaleziono dopasowań HistoryDock History Historia InsertFunctionDlg Name Nazwa Description Opis &Insert &Wstaw Cancel Anuluj Insert Function Wstaw funkcję InsertVariableDlg Name Nazwa Value Wartość &Insert &Wstaw Cancel Anuluj Insert Variable Wstaw zmienną Keypad Inverse cosine Odwrotny kosinus The last result Inverse sine Odwotny sinus Inverse tangent Odwrotny tangens Clear expression Usuń wyrażenie Cosine Kosinus Scientific notation Notacja naukowa Exponential Natural logarithm Logarytm naturalny Sine Sinus Square root Pierwiastek kwadratowy Tangent Tangens Assign variable x Podstaw zmienną x The variable x Zmienna x MainWindow About Qt O Qt File %1 is not a valid session Plik %1 nie jest prawidłowym plikiem sesji SpeedCrunch Sessions (*.sch);;All Files (*) Sesje SpeedCrunch (*.sch);;Wszystkie pliki (*) Load Session Załaduj sesję Error Błąd Can't read from file %1 Nie można czytać z pliku %1 Merge session being loaded with current session? If no, current variables and display will be cleared. Czy połączyć aktualnie ładowaną sesję z bieżącą? Jeżeli nie, zawartość wyświetlacza i przypisane zmienne zostaną wyczyszczone. Question Pytanie Save Session Zapisz sesję Can't write to file %1 Nie można zapisać do pliku %1 Warning Ostrzeżenie To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Aby używając klawiatury wstawić funkcję, należy skorzystać ze skrótu Ctrl+F. Z okna dialogowego można następnie wybrać funkcję, którą chce się wstawić. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Aby używając klawiatury wstawić zmienną, należy skorzystać ze skrótu Ctrl+I. Z okna dialogowego można następnie wybrać zmienną, którą chce się wstawić. Use variable <i>pi</i> to use pi constant. Użyj zmiennej <i>pi</i> żeby uzyskać liczbę pi. Use <i>;</i> (semicolon) to separate the parameters in functions. Użyj znaku <i>;</i> (średnik) do rozdzielenia parametrów funkcji. Tip of the day Podpowiedź dnia SpeedCrunch is minimized. Left click the icon to restore it or right click for options. SpeedCrunch jest zminimalizowany. Kliknij lewym przyciskiem myszy na ikonce, żeby go przywrócić albo prawym żeby zobaczyć opcje. Degree All Files (*) Radian The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. Binary Engineering decimal Fixed decimal General decimal Hexadecimal Octal Scientific decimal Import Session Merge session being imported with current session? If no, current variables and display will be cleared. Export Session Math Book &Session &Sesja Clear E&xpression &Wyczyść Wyrażenie Clear &History Wyczyść &historię &Degree Delete All V&ariables D&elete Variable... Usuń &zmienną... &15 Decimal Digits &15 cyfr dziesiętnych &2 Decimal Digits &2 cyfry dziesiętne &3 Decimal Digits &3 cyfry dziesiętne &50 Decimal Digits &50 cyfr dziesiętnych &8 Decimal Digits &8 cyfr dziesiętnych &Automatic Precision Domyślna dokład&ność &Copy &Kopiuj Copy Last &Result &Paste &Wklej &About &O programie About &Qt O &Qt SpeedCrunch &Web Site... Strona &WWW SpeedCrunch... &Tip of the Day &Podpowiedź dnia Insert &Function... Wstaw &funkcję... Insert &Variable... Wstaw &zmienną... &Partial Results Automatic &Completion Automatyczne &dopełnianie Always On &Top &Minimize To System Tray &Minimalizuj do tacki systemowej Syntax &Highlighting &System Default &Dot &Kropka &Comma &Przecinek &Radian &Radiany Scroll Display Down Scroll Display Up &Select Expression &Import... &Load... &Załaduj... &Quit &Zakończ &Save... &Zapisz... &Export... Math &Book &Constants Full &Screen Mode &Tryb pełnoekranowy &Functions &History &Keypad Hide &Menu Bar Ukryj belkę &menu &Status Bar &Variables &Binary Dwój&kowy &Engineering &Inżynierski &Fixed Decimal &Stałoprzecinkowe &General O&gólne &Hexadecimal &Szesnastkowy &Octal Ósemk&owy &Scientific &Naukowy System &Default &Edit &Edycja &View &Widok Se&ttings Us&tawienia Result &Format &Decimal &Angle Unit &Behavior &Zachowanie Radix &Character &Language &Help &Pomoc Angle unit Result format Ignore error? VariablesDock Variables Zmienne Search Szukaj No match found Nie znaleziono dopasowań speedcrunch-0.10.1/src/i18n/ro.ts0000644000175000001440000017460111015364561015627 0ustar helderusers AboutBox Special thanks to Mulţumiri speciale French Franceză German Germană Portuguese Portugheză Russian Rusă Italian Italiană This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Acest program este liber; îl puteţi redistribui şi/sau modifica în conformitate cu termenii Licenţei Publice Generale GNU aşa cum este ea publicată de Free Software Foundation; fie versiunea 2 a Licenţei, fie (la latitudinea dumneavoastră) orice versiune ulterioară This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Acest program este distribuit cu speranţa că vă va fi util, dar FĂRĂ NICI O GARANŢIE, chiar fără garanţia implicită de vandabilitate sau conformitate unui anumit scop. Citiţi Licenţa Publică Generală GNU pentru detalii. SpeedCrunch version %1 SpeedCrunch versiunea %1 About SpeedCrunch Despre SpeedCrunch Norwegian Norvegiană Spanish Spaniolă Original author Autor Current maintainer Mentenanţă Based on original idea from În baza unei idei originale Thanks to Mulţumiri următorilor ...and many others... ...şi multor altora... Translations Traduceri Brazilian Portuguese Portugheză Braziliană Copyright (C) Copyright (C) Visit <b>http://www.speedcrunch.org</b> for more information! Vizitează <b>http://www.speedcrunch.org</b> pentru mai multe informaţii! Argentinian Spanish Spaniolă Argentiniană Dutch Olandeză Hebrew Ebraică Swedish Suedeză Finnish Finlandeză Czech Cehă Romanian Română Developers Dezvoltatori Indonesian Indoneziană Close Închide Graphics Grafică Polish Poloneză Turkish Turcă Basque Bască Simplified Chinese Chineză simplificată Catalan Catalană BookDock Back Înapoi Forward Înainte Index Index ConstantCompletion All Toate Constants Characteristic Impedance of Vacuum Impendanţa Caracteristică a Vidului General Physics Fizică Generală Electric Constant Permitivitatea Vidului Magnetic Constant Permebilitatea Vidului Gravitation Constant Constanta Gravitaţională Planck's Constant Constanta lui Planck Dirac's Constant Constanta lui Dirac Speed of Light in Vacuum Viteza Luminii în Vid Bohr-Procopiu Magneton Magnetonul Bohr-Procopiu Electromagnetic Electromagnetism Conductance Quantum Cuant de Conductanţă Coulomb's Constant Constanta lui Coulomb Elementary Charge Sarcina Elementară Josephson Constant Constanta lui Josephson Magnetic Flux Quantum Cuant de Flux Magnetic Nuclear Magneton Magnetonul Nuclear Resistance Quantum Cuant de Rezistentă von Klitzing Constant Constanta lui von Klitzing Bohr Radius Raza lui Bohr Atomic & Nuclear Atomică & Nucleară Fermi Coupling Constant Constanta de Cuplare lui Fermi Fine-structure Constant Constanta de Structură Fină Hartree Energy Energia Hartree Quantum of Circulation Cuant de Circulaţie Rydberg Constant Constanta lui Rydberg Thomson Cross Section Secţiunea Eficace lui Thomson Weak Mixing Angle Unghiul lui Weinberg Atomic Mass Unit Unitatea Atomică de Masă Physico-chemical Fizico-chimie Avogadro's Number Numarul lui Avogadro Boltzmann Constant Constanta lui Boltzmann Faraday Constant Constanta lui Faraday First Radiation Constant Prima Constantă Radiativă Loschmidt Constant Constanta lui Loschmidt Gas Constant Constanta Gazelor Ideale Molar Planck Constant Constanta Molară lui Planck Second Radiation Constant A Doua Constantă Radiativă Stefan-Boltzmann Constant Constanta Stefan-Boltzmann Astronomical Unit Unitatea Astronomică Astronomy Astronomie Light Year An-lumină Parsec Parsec Sidereal Year An Sideral days zile Tropical Year An Tropic Gregorian Year An Gregorian Earth Mass Masa Terrei Sun Mass Masa Soarelui Mean Earth Radius Raza Media a Pămîntului Sun Radius Raza Soarelui Sun Luminosity Luminozitatea Solară ConstantsDock Constants Constante Category Catogoria Search Caută No match found Nici un rezultat All Toate DeleteVariableDlg Name Nume Value Valoare &Delete &Şterge Close Închide Delete Variable Şterge variabila Editor Current result: <b>%1</b> Rezultatul curent: <b>%1</b> Selection result: <b>%1</b> Rezultatul selecţiei: <b>%1</b> Evaluator invalid expression expresie invalidă division by zero împartire la zero unknown function or variable funcţie/variabilă necunoscută variable cannot be overwritten variabila nu poate fi suprascrisă identifier matches an existing function name exista deja o funcţie cu acelasi nume Functions Absolute Value Valoare Asbolută Average (Arithmetic Mean) Medie Aritmetică Binary Representation Reprezentare Binară Cube Root Rădăcină Cubică Decimal Representation Reprezentare Zecimală Fractional Part Parte Fracţionară Geometric Mean Medie Geometrică Hexadecimal Representation Reprezentare Hexazecimala Integer Part Partea Întreagă Maximum Maximul Minimum Minimul Octal Representation Reprezentare Octală Product Produs Rounding Rotunjire Signum Signum Square Root Rădăcina Pătrată Sum Sumă Truncation Trunchiere Hyperbolic Cosine Cosinus Hiperbolic Exponential Exponenţial Base-2 Logarithm Logaritm în Baza 2 Natural Logarithm Logaritm Natural Base-10 Logarithm Logaritm în Baza 10 Hyperbolic Sine Sinus Hiperbolic Hyperbolic Tangent Tangenta Hiperbolică Greatest Common Divisor Cel Mai Mare Divisor Comun Combination (Binomial Coefficient) Combinari (Coeficient Binomial) Permutation (Arrangement) Permutări (Aranjamente) Binomial Cumulative Distribution Function Funcţia Distribuţiei Binomiale Cumulative Binomial Distribution Mean Media Distribuţiei Binomiale Binomial Probability Mass Function Funcţia Masă de Probabilitate Binomială Binomial Distribution Variance Varianţa Distribuţiei Binomiale Hypergeometric Cumulative Distribution Function Funcţia Distribuţiei Hipergeometrice Cumulative Hypergeometric Distribution Mean Media Distribuţieri Hipergeometrice Hypergeometric Probability Mass Function Funcţia Masă de Probabilitate Hipergeometrică Hypergeometric Distribution Variance Varianţa Distribuţiei Hipergeometrice Poissonian Cumulative Distribution Function Funcţia Distribuţiei Poissoniane Cumulative Poissonian Distribution Mean Media Distribuţiei Poissoniane Poissonian Probability Mass Function Funcţia Masă de Probabilitate Poissoniană Poissonian Distribution Variance Varianţa Distribuţiei Poissoniane Arc Cosine Arc Cosinus Arc Sine Arc Sinus Arc Tangent Arc Tangenta Cosine Cosinus Cotangent Co-tangent Cosecant Cosecanta Radians Radiani Secant Secanta Sine Sinus Tangent Tangenta cannot execute function %1 nu pot executa funcţia %1 function accepts 1 argument funcţia acceptă 1 argument function accepts %1 arguments funcţia acceptă %1 argumente function requires 1 or 2 arguments funcţia necesita 1 sau 2 argumente function undefined for specified arguments funcţia e nedefinită pentru argumente speciale function requires at least 2 arguments funcţia necesită cel puţin 2 argumente function requires integer arguments funcţia necesită argumente de tip intreg function undefined for specified argument funcţia e nedefinită pentru argumentul specificat underflow În afara limitelor function requires at least 1 argument funcţia necesită cel puţin 1 argument Ceiling Rotunjire prin adaos Floor Rontunjire prin lipsa Extension of Factorials [= (x-1)!] Factorial extins ln(abs(Gamma)) ln(abs(Gamma)) Area Hyperbolic Cosine Arc Cosinus Hiperbolic Area Hyperbolic Sine Arc Sinus Hiperbolic Area Hyperbolic Tangent Arc Tangenta Hiperbolica Error Function Funcţie de eroare Complementary Error Function Funcţie de eroare complementară Degrees of Arc Degrees of Arc Mask to a bit size Mască de biţi Sign-extent a value Elimină masca Logical NOT NOT logic Logical AND SI logic Logical OR OR logic Logical XOR XOR logic Arithmetic Shift Left Deplasare aritmetică la stânga Arithmetic Shift Right Deplasare aritmetică la dreapta Integer Quotient Cat intreg Modulo Rest FunctionsDock Functions Funcţii Search Caută No match found Nici un rezultat HistoryDock History Istoric InsertFunctionDlg Name Nume Description Descriere &Insert &Inserare Cancel Anulare Insert Function Inserare Funcţie InsertVariableDlg Name Nume Value Valoare &Insert &Inserare Cancel Anulare Insert Variable Inserarează variabila Keypad Inverse cosine Invers cosinus The last result Ultimul rezultat Inverse sine Invers sinus Inverse tangent Invers tangenta Clear expression Curăţă expresia Cosine Cosinus Scientific notation Notaţia ştiinţifică Exponential Exponenţial Natural logarithm Logaritm Natural Sine Sinus Square root Rădăcina Pătrată Tangent Tangenta Assign variable x Atribuie variabila x The variable x Variabila X MainWindow About Qt Despre Qt SpeedCrunch Sessions (*.sch);;All Files (*) Sesiune SpeedCrunch (*.sch);; Toate fişierele (*) Load Session Incarcă Sesiune Error Eroare Can't read from file %1 Nu se poate citi fişierul %1 Question Întrebare Save Session Salvează Sesiunea Can't write to file %1 Nu se poate scrie în fişierul %1 Warning Avertisment To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Pentru a insera o funcţie utilizând tastatura, foloseşte scurtătura Ctrl+F. Din dialog poţi alege ce funcţie doreşti să inserezi. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Pentru a insera o variabilă utilizînd tastatura, foloseşte scurtătura Ctrl+I. Din dialog poţi alege ce variabilă doreşti să inserezi. Use variable <i>pi</i> to use pi constant. Foloseşte variabila <i>pi</i> pentru constanta pi. Use <i>;</i> (semicolon) to separate the parameters in functions. Foloseşte <i>;</i> (punct şi virgulă) pentru a separa parametrii în funcţii. Tip of the day Sugestia zilei File %1 is not a valid session Fişierul %1 nu este o sesiune validă Merge session being loaded with current session? If no, current variables and display will be cleared. Vrei sa faci merge la sesiunea care se încarcă cu cea curentă? Daca nu, variabilele curente şi ecranul vor fi curaţate. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. Fereastra SpeedCrunch este minimizată. Apasă iconiţa din stânga pentru a o aduce la dimensiunile iniţiale sau click dreapta pentru alte opţiuni. Degree Grad All Files (*) Toate fişierele (*) Radian Radian The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. Meniul aplicaţiei este acum ascuns. Pentru a-l face vizibil din nou, apasă Ctrl+Alt+M. Binary Binar Engineering decimal Punct zecimal ingineresc Fixed decimal Punct zecimal fix General decimal Punct zecimal general Hexadecimal Hexazecimal Octal Octal Scientific decimal Punct zecimal sciinţific Import Session Importă Sesiune Merge session being imported with current session? If no, current variables and display will be cleared. Vrei sa faci merge la sesiunea care este importată cu cea curentă? Daca nu, variabilele curente şi ecranul vor fi curaţate. Export Session Exportă Sesiune Math Book Carte de matematică &Session &Sesiune Clear E&xpression Curătă e&xpresia Clear &History Goleşte &Istoricul &Degree &Grad Delete All V&ariables Şterge toate v&ariabilele D&elete Variable... Şt&erge variabila... &15 Decimal Digits &15 Cifre zecimale &2 Decimal Digits &2 Cifre zecimale &3 Decimal Digits &3 Cifre zecimale &50 Decimal Digits &50 Cifre zecimale &8 Decimal Digits &8 Cifre zecimale &Automatic Precision Precizie &Automatică &Copy &Copiază Copy Last &Result Copiază ultimul &rezultat &Paste In&serează &About &Despre About &Qt Despre &Qt SpeedCrunch &Web Site... SpeedCrunch &site... &Tip of the Day &Sugestia zilei Insert &Function... Inserează &funcţia... Insert &Variable... Inserează &variabila... &Partial Results &Rezultate Parţiale Automatic &Completion &Completare Automată Always On &Top Întotdeauna în &partea cea mai de sus &Minimize To System Tray Minimizează în system &tray Syntax &Highlighting Sintaxă şi &Subliniere &System Default &Valoarea implicită a sistemului &Dot &Punct &Comma &Virgulă &Radian &Radian Scroll Display Down Scroll în jos Scroll Display Up Scroll în sus &Select Expression &Selectează expresia &Import... &Importă... &Load... &Încarcă... &Quit &Ieşire &Save... &Salvează... &Export... &Exportă... Math &Book &Carte de Matematică &Constants &Constante Full &Screen Mode Afisează pe tot &ecranul &Functions &Funcţii &History &Istoric &Keypad &Keypad Hide &Menu Bar Ascunde &meniul aplicaţiei &Status Bar &Bara de status &Variables &Variabile &Binary &Binar &Engineering &Ingineresc &Fixed Decimal Punct Zecimal &Fix &General &General &Hexadecimal &Hexadecimal &Octal &Octal &Scientific &Ştiinţific System &Default &Valoarea implicită a sistemului &Edit &Editare &View &Vizualizare Se&ttings &Preferinţe Result &Format &Formatul rezultatului &Decimal &Zecimal &Angle Unit &Unitatea de masură a unghiului &Behavior &Setări Radix &Character Reprezentare punct &zecimal &Language &Limbaj &Help &Ajutor Angle unit Unitatea de masură a unui unghi Result format Formatul rezultatului Ignore error? Vrei să ignori eroarea? VariablesDock Variables Variabile Search Caută No match found Nici un rezultat speedcrunch-0.10.1/src/i18n/ru.ts0000644000175000001440000020316111015364561015627 0ustar helderusers AboutBox Special thanks to Особые благодарности French Французский German Немецкий Portuguese Португальский Russian Русский Italian Итальянский This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Эта программа является свободным программным обеспечением; вы можете распространять и/или изменять её на условиях GNU GPL (Основной Общественной Лицензии), изданной Организацией Свободного П/О второго или (на ваш выбор) более позднего издания This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Эта программа распространяется в надежде, что будет полезной, но БЕЗ ЛЮБЫХ ГАРАНТИЙ, даже без подразумеваемой гарантии ПРИГОДНОСТИ ДЛЯ КАКОЙ-ЛИБО ЦЕЛИ. Подробнее см. GNU GPL. SpeedCrunch version %1 SpeedCrunch версии %1 About SpeedCrunch О программе SpeedCrunch Norwegian Норвежский Spanish Испанский Original author Автор Current maintainer Ведущий проекта Based on original idea from На основе оригинальной идеи Thanks to Спасибо ...and many others... ...и всем остальным... Translations Переводчики Brazilian Portuguese Бразильско-португальский Copyright (C) Все права защищены (С) Visit <b>http://www.speedcrunch.org</b> for more information! Для большей информации посетите <b>http://www.speedcrunch.org</b>! Argentinian Spanish Аргентинско-Испанский Dutch Нидерландский Hebrew Древнееврейский Swedish Шведский Finnish Фи́нский язы́к Czech Чешский язык Romanian Румынский язык Developers Разработчики Indonesian Индонезийский Polish Польский Turkish Турецкий Close Закрыть Graphics Basque Simplified Chinese Catalan BookDock Back Forward Index ConstantCompletion All Все Constants Characteristic Impedance of Vacuum характеристический импеданс вакуума General Physics Основная Физика Electric Constant электрическая постоянная Magnetic Constant магнитная постоянная Gravitation Constant гравитационная постоянная Planck's Constant константа Планка Dirac's Constant константа Дирака Speed of Light in Vacuum скорость света в вакууме Bohr-Procopiu Magneton магнетон Бора Electromagnetic Электромагнетизм Conductance Quantum электропроводность Coulomb's Constant постоянная Кулона Elementary Charge Элементарный электрический заряд(sp)(sp) Josephson Constant постоянная Джозефсона Magnetic Flux Quantum квант магнитного потока Nuclear Magneton ядерный магнетон Resistance Quantum Сопротивление Фотона von Klitzing Constant постоянная Клитзинга Bohr Radius Боровский радиус Atomic & Nuclear Атомная и Ядерная физика Fermi Coupling Constant постоянная Ферми Fine-structure Constant постоянная тонкой структуры Hartree Energy энергия Хартри Quantum of Circulation Вращение Квантума Rydberg Constant постоянная Ридберга Thomson Cross Section эффективное поперечное сечение Томпсона Weak Mixing Angle Угол Вейнебрга Atomic Mass Unit атомная единица массы Physico-chemical Физико-химический Avogadro's Number число Авагадро Boltzmann Constant постоянная Больцмана Faraday Constant постоянная Фарадея First Radiation Constant первая радиационная постоянная Loschmidt Constant постоянная Лошмита Gas Constant универсальная газовая постоянная Molar Planck Constant молярная постоянная Планка Second Radiation Constant первая радиационная постоянная Stefan-Boltzmann Constant постоянная Стефана-Больцмана Astronomical Unit астрономическая единица Astronomy Астрономия Light Year световой год Parsec парсек Sidereal Year сидерический год days дней Tropical Year солнечный год Gregorian Year грегорианский год Earth Mass масса Земли Sun Mass масса Солнца Mean Earth Radius средний радиус Земли Sun Radius радиус Солнца Sun Luminosity светимость Солнца ConstantsDock Constants Постоянные Category Категория Search Поиск No match found Совпадения не найдены All Все DeleteVariableDlg Name Имя Value Значение &Delete &Удалить Close Закрыть Delete Variable Удаление переменной Editor Current result: <b>%1</b> Selection result: <b>%1</b> Evaluator invalid expression division by zero unknown function or variable variable cannot be overwritten identifier matches an existing function name Functions Absolute Value Модуль Average (Arithmetic Mean) Среднее значение Binary Representation Двоичное представление Cube Root Квадратный корень Ceiling Максимальный Decimal Representation Десятичное представление Floor Наибольшая целая часть Fractional Part Дробная часть Geometric Mean Геометрическое среднее Hexadecimal Representation Шестнадцатеричное представление Integer Part Целая часть Maximum Максимум Minimum Минимум Octal Representation Восьмеричное представление Product Произведение Rounding Округление Signum Знак Square Root Квадратный корень Sum Сумма Truncation Усечение Area Hyperbolic Cosine Обратная гиперболическая косинуса Area Hyperbolic Sine Обратная гиперболическая синуса Area Hyperbolic Tangent Обратная гиперболическая тангенса Hyperbolic Cosine Гиперболический косинус Exponential Экспонента Base-2 Logarithm Натуральный логарифм Natural Logarithm Натуральный логарифм Base-10 Logarithm Десятичный логарифм Hyperbolic Sine Гиперболический синус Hyperbolic Tangent Гиперболический тангенс Greatest Common Divisor Наибольший общий делитель Combination (Binomial Coefficient) Биномиальный коофицент Permutation (Arrangement) Перестановка Binomial Cumulative Distribution Function Биноминальное функция распределения Binomial Distribution Mean Серединное биномиальное распределение Binomial Probability Mass Function Вероятность биномиального распределения функции массы Binomial Distribution Variance Биномиальное распределение дисперсии Hypergeometric Cumulative Distribution Function Гипергеометрическая функция распределения Hypergeometric Distribution Mean Гипергеометрическая функция распределения среднего Hypergeometric Probability Mass Function Гипергеометрическая вероятность функции массы Hypergeometric Distribution Variance Гипергеометрическое распределение дисперсии Poissonian Cumulative Distribution Function Функция распределения Пуассона Poissonian Distribution Mean Среднее распределение Пуассона Poissonian Probability Mass Function Распределение Пуассона функции массы Poissonian Distribution Variance Распределение диспрерсии Пуассона Arc Cosine Арккосинус Arc Sine Арксинус Arc Tangent Арктангенс Cosine Косинус Cotangent Котангенс Cosecant Косеканс Radians Радианы Secant Секанс Sine Синус Tangent Тангенс cannot execute function %1 Не могу вычислить значение функции %1 function accepts 1 argument Функция поддерживает только 1 аргумент function accepts %1 arguments Функция поддерживает %1 аргумент(ов) function requires 1 or 2 arguments функции требуется 1 или 2 аргумента function undefined for specified arguments функция не определена для конкретных аргументов function requires at least 2 arguments функции требуется как минимум 2 аргумента function requires integer arguments функции требуется целочисленный аргумент function undefined for specified argument функция не определена для конкретных аргументов underflow function requires at least 1 argument функции требуется как минимум 1 аргумент Extension of Factorials [= (x-1)!] ln(abs(Gamma)) Error Function Complementary Error Function Degrees of Arc Mask to a bit size Sign-extent a value Logical NOT Logical AND Logical OR Logical XOR Arithmetic Shift Left Arithmetic Shift Right Integer Quotient Modulo FunctionsDock Functions Функции Search Поиск No match found Совпадения не найдены HistoryDock History История InsertFunctionDlg Name Имя Description Функция &Insert &Вставить Cancel Отмена Insert Function Вставка функции InsertVariableDlg Name Имя Value Значение &Insert &Вставить Cancel Отмена Insert Variable Вставка переменной Keypad Inverse cosine Инвертированный косинус The last result Inverse sine Инвертированный синус Inverse tangent ИНвертированный тангенс Clear expression Cosine Косинус Scientific notation Exponential Экспонента Natural logarithm Sine Синус Square root Квадратный корень Tangent Тангенс Assign variable x The variable x MainWindow About Qt О &Qt SpeedCrunch Sessions (*.sch);;All Files (*) Load Session Error Ошибка Can't read from file %1 Question Save Session Сохранить сеанс Can't write to file %1 Не могу записать файл %1 Warning To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Для вставки функции с клавиатуры используйте сочетание Ctrl+F. Вы можете также выбрать функцию из окна функций. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Для вставки переменной с клавиатуры используйте сочетание Ctrl+I. Вы можете также выбрать переменную из окна функций. Use variable <i>pi</i> to use pi constant. Используйте переменную <i>pi</i> для числа Пи. Use <i>;</i> (semicolon) to separate the parameters in functions. Используйте <i>;</i> (точку с запятой) для разделения параметров в функциях. Tip of the day File %1 is not a valid session Merge session being loaded with current session? If no, current variables and display will be cleared. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. Degree All Files (*) Radian The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. Binary Engineering decimal Fixed decimal General decimal Hexadecimal Octal Scientific decimal Import Session Merge session being imported with current session? If no, current variables and display will be cleared. Export Session Math Book &Session &Сеанс Clear E&xpression Clear &History Очистить &историю &Degree Delete All V&ariables D&elete Variable... &Удалить переменную... &15 Decimal Digits &15 цифр после запятой &2 Decimal Digits &2 цифры после запятой &3 Decimal Digits &3 цифры после запятой &50 Decimal Digits &50 цифр после запятой &8 Decimal Digits &8 цифр после запятой &Automatic Precision Автоматически &Copy &Копировать Copy Last &Result &Paste &Вставить &About &О программе SpeedCrunch About &Qt О &Qt SpeedCrunch &Web Site... Сайт SpeedCrunch... &Tip of the Day Заметка дня Insert &Function... Вставить &функцию... Insert &Variable... Вставить &переменную... &Partial Results Automatic &Completion Always On &Top &Minimize To System Tray Syntax &Highlighting &System Default &Dot &Comma &Radian Scroll Display Down Scroll Display Up &Select Expression &Import... &Load... &Quit В&ыход &Save... &Сохранить... &Export... Math &Book &Constants Full &Screen Mode &Functions &History &Keypad Hide &Menu Bar &Status Bar &Variables &Binary &Двоичная &Engineering Технический &Fixed Decimal С &точкой &General &По умолчанию &Hexadecimal &Шестнадцатеричная &Octal &Восьмеричная &Scientific Научный System &Default &Edit &Правка &View &Вид Se&ttings &Настройка Result &Format &Decimal &Angle Unit &Behavior Radix &Character &Language &Help &Справка Angle unit Result format Ignore error? VariablesDock Variables Переменные Search Поиск No match found Совпадения не найдены speedcrunch-0.10.1/src/i18n/nb.ts0000644000175000001440000017276411015364561015616 0ustar helderusers AboutBox About SpeedCrunch Om SpeedCrunch SpeedCrunch version %1 SpeedCrunch versjon %1 Original author Opprinnelig forfatter Current maintainer Nåværende vedlikeholder Based on original idea from Basert på en orginal idé av Special thanks to Spesiell takk til Thanks to Takk til ...and many others... ...med flere... Translations Oversettelser French Fransk German Tysk Italian Italiensk Norwegian Norsk Portuguese Portugisisk Brazilian Portuguese Brasilliansk Portugisisk Russian Russisk Spanish Spansk Copyright (C) Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Dette programmet er fri programvare. Du kan omdistribuere og/eller endre det i henhold til vilkårene spesifisert i GNU General Public Lisence av Free Softeware Foundation. Versjon 2 eller, på eget ønske, en senere versjon kan benyttes. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Dette programmet disitribueres i håpet at det vil være brukbart for noen. Det gis INGEN GARANTI for programmet, ikke en gang implisitt for spesifikk bruk eller for merkantile formål. Se GNU Public License for videre detaljer. Visit <b>http://www.speedcrunch.org</b> for more information! Se <b>http://www.speedcrunch.org</b> for mer informasjon! Argentinian Spanish Argentisnsk Spansk Dutch Nederlandsk Hebrew Hebraisk Swedish Svensk Finnish Finsk Czech Tsjekkisk Romanian Rumensk Developers Utviklere Indonesian Indonesisk Close Lukk Graphics Grafikk Polish Polsk Turkish Tyrkisk Basque Baskisk Simplified Chinese Forenklet kinesisk Catalan Katalansk BookDock Back Tilbake Forward Framover Index Stikkord ConstantCompletion All Alle Constants Characteristic Impedance of Vacuum Karakteristisk impedans i vakuum General Physics Generell Fysikk Electric Constant Elektrisk konstant Magnetic Constant Magnetisk konstant Gravitation Constant Tyngdekrafts konstant Planck's Constant Plancks konstant Dirac's Constant Diracs konstant Speed of Light in Vacuum Lysets hastighet i vakuum Bohr-Procopiu Magneton Bohr-Procopiu magneton Electromagnetic Elektromagnetisme Conductance Quantum Elektrisk ledningskvant Coulomb's Constant Coulombs konstant Elementary Charge Elementærladning Josephson Constant Josephson konstant Magnetic Flux Quantum Magnetisk flukskvant Nuclear Magneton Nukleært magneton Resistance Quantum Resistanskvant von Klitzing Constant von Klitzings konstant Bohr Radius Bohrradius Atomic & Nuclear Atomisk & Kjærne Fermi Coupling Constant Fermis koplingskonstant Fine-structure Constant Finstrukturkonstanten Hartree Energy Hartrees energi Quantum of Circulation Sirkulasjonskvant Rydberg Constant Rydbergs konstant Thomson Cross Section Thomsons spredningstverrsnitt Weak Mixing Angle Svak blandingsvinkel Atomic Mass Unit Atommasseenhet Physico-chemical Fysikk-kjemi Avogadro's Number Avogadros tall Boltzmann Constant Boltzmann konstant Faraday Constant Faradays konstant First Radiation Constant Først strålingskonstant Loschmidt Constant Loschmidts konstant Gas Constant Gasskonstant Molar Planck Constant Molar Plancks konstant Second Radiation Constant Andre strålingskonstant Stefan-Boltzmann Constant Stefan-Boltzmann konstant Astronomical Unit Astronomisk målenhet Astronomy Astronomi Light Year Lysår Parsec Parsec Sidereal Year Siderisk år days dager Tropical Year Tropisk år Gregorian Year Gregoriansk år Earth Mass Jordens masse Sun Mass Sols masse Mean Earth Radius Gjennomsnittsolradius Sun Radius Sols radius Sun Luminosity Sollysstyrke ConstantsDock Constants Konstanter Category Kategori Search Søk No match found Ingen treff funnet All Alle DeleteVariableDlg Delete Variable Slett variabel Name Navn Value Verdi &Delete &Slett Close Lukk Editor Current result: <b>%1</b> Resultat Selection result: <b>%1</b> Resultat av utvalg Evaluator invalid expression Ugyldig uttrykk division by zero Deling på null unknown function or variable Ukjent funskjon eller variabel variable cannot be overwritten Variabel kan ikke endres identifier matches an existing function name Identifikator navn kolliderer med et eksisternede funksjons navn Functions Absolute Value Absolutt verdi Average (Arithmetic Mean) Gjennomsnitt (Aritmetisk) Binary Representation Binær representasjon Cube Root Kubisk root Ceiling Takfunksjon Decimal Representation Desimal representasjon Floor Gulvfunksjon Fractional Part Desimalfraksjon Geometric Mean Geometrisk gjennomsnitt Hexadecimal Representation Hexadesimal representasjon Integer Part Heltallsfraksjon Maximum Maksimum Minimum Minimum Octal Representation Oktal representasjon Product Produkt Rounding Avrunding Signum Signum Square Root Kvadratrot Sum Total Truncation Trunkering Hyperbolic Cosine Hyperbolsk kosinus Exponential Exponentiell Base-2 Logarithm 2 base logaritme Natural Logarithm Naturlig logaritme Base-10 Logarithm 10-base logaritme Hyperbolic Sine Hyperbolsk sinus Hyperbolic Tangent Hyperbolisk tangent Greatest Common Divisor Minste felles multiplum Combination (Binomial Coefficient) Kombinasjon (Binomial kofisient) Permutation (Arrangement) Arrangering Binomial Cumulative Distribution Function Binomial oppsamlet distribusjonsfunksjon Binomial Distribution Mean Binomial distribusjoinssnitt Binomial Probability Mass Function Binomial sannsynlighetsmengdefunksjon Binomial Distribution Variance Binomial distriubusjons varianse Hypergeometric Cumulative Distribution Function Hypergeometrisk oppsamlingsdistribusjonssnitt Hypergeometric Distribution Mean Hypergeometrisk distribusjonssnitt Hypergeometric Probability Mass Function Hypergeometrisk sannsynlighetsmengdefunksjon Hypergeometric Distribution Variance Hyperbolsk distribusjons tangens Poissonian Cumulative Distribution Function Poissonian kumjulative distribusjonsfunksjon Poissonian Distribution Mean Poissonian distribusjonssnitt Poissonian Probability Mass Function Poissonian sannsynlighetsmengdefunksjon Poissonian Distribution Variance Poissonian distribusjonsvarians Arc Cosine Arc kosinus Arc Sine Arc sinus Arc Tangent Sirkel tangens Cosine Kosinus Cotangent Kotangens Cosecant Kosekant Radians Radianer Secant Sekant Sine Sinus Tangent Tangens cannot execute function %1 kan ikke utføre funksjon %1 function accepts 1 argument funksjon godtar bare ett argument function accepts %1 arguments funksjonen godtar %1 argumenter function requires 1 or 2 arguments funksjon krever ett eller to argumenter function undefined for specified arguments ingen funksjon med spesifisert argumentliste eksisterer function requires at least 2 arguments funksjonen krever minst to argumenter function requires integer arguments funksjonen krever heltallsargumenter function undefined for specified argument ingen funksjon med spesifisert argument eksisterer underflow underflyt function requires at least 1 argument funksjonen krever minst ett argument Extension of Factorials [= (x-1)!] ln(abs(Gamma)) Area Hyperbolic Cosine Area Hyperbolic Sine Area Hyperbolic Tangent Error Function Feilfunksjon Complementary Error Function Degrees of Arc Mask to a bit size Maskere til en bit størrelse Sign-extent a value Logical NOT Logisk IKKE Logical AND Logisk OG Logical OR Logisk ELLER Logical XOR Logisk EKSKLUSIV ELLER Arithmetic Shift Left Arithmetic Shift Right Integer Quotient Integer kvotient Modulo Modulo FunctionsDock Functions Funksjoner Search Søk No match found Ingen treff funnet HistoryDock History Historie InsertFunctionDlg Insert Function Sett inn funksjon Name Navn Description Beskrivelse &Insert &Sett inn Cancel Avbryt InsertVariableDlg Insert Variable Sett inn variabel Name Navn Value Verdi &Insert &Sett inn Cancel Avbryt Keypad Inverse cosine Invers kosinus The last result Siste resultat Inverse sine Invers sinus Inverse tangent Arc tangens Clear expression Fjern uttrykk Cosine Kosinus Scientific notation Teknisk notasjon Exponential Exponentiell Natural logarithm Naturlig logaritme Sine Sinus Square root Kvadratrot Tangent Tangens Assign variable x Gi variabel x en verdi The variable x Variabelen x MainWindow About Qt Om Qt SpeedCrunch Sessions (*.sch);;All Files (*) SpeedCrunch økt (*.sch);;Alle filer (*) Load Session Åpne økt Error Feil Can't read from file %1 Kan ikke lese fra fil %1 Question Spørsmål Save Session Lagre økt Can't write to file %1 Kan ikke lagre filen %1 Warning Advarsel To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. For å sette inn en funksjon vha. tastaturet, bruk Ctrl+F tastekombinasjonen. Fra dialogen kan du velge hvilken funksjon du vil sette inn. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. For å sette inn en variabel vha. tastaturet, bruk Ctrl+I tastekombinasjonen. Fra dialogen kan du velge hvilken variabel du vil sette inn. Use variable <i>pi</i> to use pi constant. Bruk variabelen PI for å bruke pi konstanten. Use <i>;</i> (semicolon) to separate the parameters in functions. Bruk <i>;</i> (semikolon) for å skille funksjonsparameter fra hverandre. Tip of the day Dagens hint File %1 is not a valid session %1 er ikke en gyldig øktfil Merge session being loaded with current session? If no, current variables and display will be cleared. Flett åpnet økt med pågående økt Hvis ikke vil inneværende variabler og skjerm bil tømt. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. SpeedCrunch er minimert Venstreklikk på ikonet for å gjenopprette eller høyreklikk for innstillinger. Degree Grader All Files (*) Alle filer (*) Radian Radian The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. Meny linjen er skjult. For å gjøre den synlig igjen trykk Ctrl+Alt+M. Binary Binær Engineering decimal Teknisk desimal Fixed decimal Fast desimal General decimal Generell desimal Hexadecimal Heksadesimal Octal Oktal Scientific decimal Vitenskapelig desimal Import Session Importer økt Merge session being imported with current session? If no, current variables and display will be cleared. Flett importert økt inn i pågående økt? Hvis ikke, vil inneværende variabler og skjerm bli tømt. Export Session Eksporter økt Math Book Mattebok &Session &Økt Clear E&xpression Fjern &uttryk Clear &History Slett &Historie &Degree &Grader Delete All V&ariables Slett alle v&ariabler D&elete Variable... &Slett variabel... &15 Decimal Digits &15 desimaler &2 Decimal Digits &2 desimaler &3 Decimal Digits &3 desimaler &50 Decimal Digits &50 desimaler &8 Decimal Digits &8 desimaler &Automatic Precision &Automatisk desimal presisjon &Copy &Kopier Copy Last &Result Kopier &siste resultat &Paste &Lim inn &About &Om About &Qt Om &Qt SpeedCrunch &Web Site... SpeedCrunch &Web Side... &Tip of the Day &Dagens tips Insert &Function... Sett inn &funksjon... Insert &Variable... Sett inn &variabel... &Partial Results &Delresultat Automatic &Completion Automatisk &fullføring Always On &Top Alltid &øverst &Minimize To System Tray Minimer til system &kurv Syntax &Highlighting Syntaks &fremheving &System Default Systemets standard&verdi &Dot &Punktum &Comma &Komma &Radian &Radian Scroll Display Down Rull skjerm ned Scroll Display Up Rull skjerm opp &Select Expression &Velg uttrykk &Import... &Importer... &Load... &Åpne... &Quit &Avslutt &Save... &Lagre... &Export... &Eksporter... Math &Book &Mattebok &Constants &Konstanter Full &Screen Mode &Fullskjerm modus &Functions &Funksjoner &History &Historie &Keypad &Nummertastatur Hide &Menu Bar Skjul &menulinje &Status Bar Status &linje &Variables &Variabler &Binary &Binær &Engineering &Ingeniør &Fixed Decimal &Fast antall desimaler &General &Generellt &Hexadecimal &Hexadesimal &Octal &Oktal &Scientific &Vitenskapelig System &Default Systemets standard&verdi &Edit &Editer &View &Se Se&ttings Ko&nfigurasjon Result &Format &Decimal &Desimal &Angle Unit &Behavior &Oppførsel Radix &Character &Tegn &Language &Språk &Help &Hjelp Angle unit Result format Ignore error? Overse feil? VariablesDock Variables Variabler Search Søk No match found Ingen treff funnet speedcrunch-0.10.1/src/i18n/pt.ts0000644000175000001440000017443411015364561015636 0ustar helderusers AboutBox Special thanks to Agradecimento especial a French Francês German Alemão Portuguese Português Russian Russo Italian Italiano This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Este programa é livre; pode redistribuí-lo e/ou modificá-lo sob os termos da Licença Pública Geral GNU (GNU General Public License) conforme publicada pela Fundação para o Software Livre (Free Software Foundation); tanto a versão 2 da licença ou (por sua opção) qualquer versão mais recente This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Este programa é distibuído na esperança de que seja útil, mas SEM QUALQUER GARANTIA. Veja a Licença Pública Geral GNU (GNU General Public License) para mais detalhes. SpeedCrunch version %1 SpeedCrunch versão %1 About SpeedCrunch Acerca do SpeedCrunch Norwegian Norueguês Spanish Espanhol Original author Autor original Current maintainer Responsável actual Based on original idea from Baseado numa ideia original de Thanks to Obrigado a ...and many others... ...e muitos mais... Translations Traduções Brazilian Portuguese Português do Brasil Copyright (C) Copyright (C) Visit <b>http://www.speedcrunch.org</b> for more information! Visite <b>http://www.speedcrunch.org</b> para mais informações! Argentinian Spanish Espanhol Argentino Dutch Neerlandês Hebrew Hebraico Swedish Sueco Finnish Finlandês Czech Checo Romanian Romeno Developers Autores Indonesian Indonésio Polish Polaco Turkish Turco Close Fechar Graphics Gráficos Basque Basco Simplified Chinese Chinês Simplificado Catalan Catalão BookDock Back Recuar Forward Avançar Index Índice ConstantCompletion All Todas Constants Characteristic Impedance of Vacuum Impedância Característica do Vácuo General Physics Física Geral Electric Constant Constante Eléctrica Magnetic Constant Constante Magnética Gravitation Constant Constante Gravitacional Planck's Constant Constante de Planck Dirac's Constant Constante de Dirac Speed of Light in Vacuum Velocidade da Luz no Vácuo Bohr-Procopiu Magneton Magnetão de Bohr-Procopiu Electromagnetic Electromagnetismo Conductance Quantum Quantum de Condutância Coulomb's Constant Constante de Colombo Elementary Charge Carga Elementar Josephson Constant Constante de Josephson Magnetic Flux Quantum Quantum de Fluxo Magnético Nuclear Magneton Magnetão Nuclear Resistance Quantum Quantum de Resistência von Klitzing Constant Constante de von Klitzing Bohr Radius Raio de Bohr Atomic & Nuclear Atómico & Nuclear Fermi Coupling Constant Constante de Fermi Fine-structure Constant Constante de Estrutura Fina Hartree Energy Energia de Hartree Quantum of Circulation Quantum de Circulação Rydberg Constant Constante de Rydberg Thomson Cross Section Secção de Choque de Thomson Weak Mixing Angle Ângulo de Weinberg Atomic Mass Unit Unidade de Massa Atómica Physico-chemical Fisico-química Avogadro's Number Número de Avogadro Boltzmann Constant Constante de Boltzmann Faraday Constant Constante de Faraday First Radiation Constant Constante Primária de Radiação Loschmidt Constant Constante de Loschmidt Gas Constant Constante dos Gases Ideais Molar Planck Constant Constante Molar de Planck Second Radiation Constant Constante Secundária de Radiação Stefan-Boltzmann Constant Constante de Stefan-Boltzmann Astronomical Unit Unidade Astronómica Astronomy Astronomia Light Year Ano-luz Parsec Parsec Sidereal Year Ano Sideral days dias Tropical Year Ano Tropical Gregorian Year Ano Gregoriano Earth Mass Massa Terrestre Sun Mass Massa Solar Mean Earth Radius Raio Médio Terrestre Sun Radius Raio Solar Sun Luminosity Luminosidade Solar ConstantsDock Constants Constantes Category Categoria Search Pesquisar No match found Sem resultados All Todas DeleteVariableDlg Name Nome Value Valor &Delete &Remover Close Fechar Delete Variable Remover Variável Editor Current result: <b>%1</b> Resultado actual: <b>%1</b> Selection result: <b>%1</b> Resultado da Selecção: <b>%1</b> Evaluator invalid expression expressão inválida division by zero divisão por zero unknown function or variable função ou variável desconhecida variable cannot be overwritten a variável não pode ser alterada identifier matches an existing function name o identificador corresponde a um nome de função já existente Functions Absolute Value Valor Absoluto Average (Arithmetic Mean) Média Aritmética Binary Representation Representação Binária Cube Root Raiz Cúbica Ceiling Tecto Decimal Representation Representação Decimal Floor Chão Fractional Part Parte Fraccionária Extension of Factorials [= (x-1)!] Extensão de Factoriais [= (x-1)!] Geometric Mean Média Geométrica Hexadecimal Representation Representação Hexadecimal Integer Part Parte Inteira ln(abs(Gamma)) ln(abs(Gamma)) Maximum Máximo Minimum Mínimo Octal Representation Representação Octal Product Produto Rounding Arredondamento Signum Sinal Square Root Raiz Quadrada Sum Soma Truncation Truncagem Area Hyperbolic Cosine Co-seno Hiperbólico de Área Area Hyperbolic Sine Seno Hiperbólico de Área Area Hyperbolic Tangent Tangente Hiperbólica de Área Hyperbolic Cosine Co-seno Hiperbólico Exponential Exponencial Base-2 Logarithm Logaritmo Base 2 Natural Logarithm Logaritmo Natural Base-10 Logarithm Logaritmo Base 10 Hyperbolic Sine Seno Hiperbólico Hyperbolic Tangent Tangente Hiperbólica Greatest Common Divisor Máximo Divisor Comum Combination (Binomial Coefficient) Combinações (Coeficiente Binomial) Permutation (Arrangement) Permutações (Arranjos) Binomial Cumulative Distribution Function Distribuição Cumulativa Binomial Binomial Distribution Mean Média Distribuição Binomial Binomial Probability Mass Function Massa Probabilidade Binomial Binomial Distribution Variance Variância Distribuição Binomial Error Function Função de Erro Complementary Error Function Função de Erro Complementar Hypergeometric Cumulative Distribution Function Distribuição Cumulativa Hipergeométrica Hypergeometric Distribution Mean Média Distribuição Hipergeométrica Hypergeometric Probability Mass Function Massa Probabilidade Hipergeométrica Hypergeometric Distribution Variance Variância Distribuição Hipergeométrica Poissonian Cumulative Distribution Function Distribuição Cumulativa Poissoniana Poissonian Distribution Mean Média Distribuição Poissoniana Poissonian Probability Mass Function Massa Probabilidade Poissoniana Poissonian Distribution Variance Variância Distribuição Poissoniana Arc Cosine Arco Co-seno Arc Sine Arco Seno Arc Tangent Arco Tangente Cosine Co-seno Cotangent Co-tangent Cosecant Co-secante Degrees of Arc Graus de Arco Radians Radianos Secant Secante Sine Seno Tangent Tangente Mask to a bit size Mascarar para um tamanho em bits Sign-extent a value Extender sinal de um valor Logical NOT NÃO lógico (NOT) Logical AND E lógico (AND) Logical OR OU lógico (OR) Logical XOR OU exclusivo lógico (XOR) Arithmetic Shift Left Deslize Aritmético para Esquerda (shift left) Arithmetic Shift Right Deslize Aritmético para Direita (shift right) Integer Quotient Divisão Inteira Modulo Resto da divisão inteira (modulo) cannot execute function %1 erro ao executar a função %1 function accepts 1 argument função aceita 1 argumento function accepts %1 arguments função aceita %1 argumentos function requires 1 or 2 arguments função requer 1 ou 2 argumentos function undefined for specified arguments função indefinida para os argumentos utilizados function requires at least 2 arguments função requer pelo menos 2 argumentos function requires integer arguments função requer argumentos inteiros function undefined for specified argument função indefinida para o argumento utilizado underflow erro por defeito function requires at least 1 argument função requer pelo menos 1 argumento FunctionsDock Functions Funções Search Pesquisar No match found Sem correspondências HistoryDock History Histórico InsertFunctionDlg Name Nome Description Descrição &Insert &Inserir Cancel Cancelar Insert Function Inserir uma função InsertVariableDlg Name Nome Value Valor &Insert &Inserir Cancel Cancelar Insert Variable Inserir uma variável Keypad Inverse cosine Arco Co-seno The last result O último resultado Inverse sine Arco Seno Inverse tangent Arco Tangente Clear expression Limpar expressão Cosine Co-seno Scientific notation Notação científica Exponential Exponencial Natural logarithm Logaritmo natural Sine Seno Square root Raiz quadrada Tangent Tangente Assign variable x Atribuir valor à variável x The variable x A variável x MainWindow About Qt Acerca do Qt SpeedCrunch Sessions (*.sch);;All Files (*) Sessões SpeedCrunch (*.sch);; Todos os Ficheiros (*) Load Session Carregar Sessão Error Erro Can't read from file %1 Erro ao ler do ficheiro %1 Question Pergunta Save Session Gravar a sessão Can't write to file %1 Erro ao escrever no ficheiro %1 Warning Aviso To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Para inserir uma função usando do teclado, utilize o atalho Ctrl+F. Uma vez aberta a janela de funções, pode escolher a que deseja inserir. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Para inserir uma variável usando o teclado, utilize o atalho Ctrl+I. Uma vez aberta a janela de variáveis, pode escolher a que deseja inserir. Use variable <i>pi</i> to use pi constant. Utilize a variável <i>pi</i> para usar a constante pi. Use <i>;</i> (semicolon) to separate the parameters in functions. Utilize <i>;</i> (ponto e vírgula) para separar os parâmetros de uma função. Tip of the day Dica do dia File %1 is not a valid session O ficheiro %1 não é uma sessão válida Merge session being loaded with current session? If no, current variables and display will be cleared. Fundir a sessão que está a ser carregada com a sessão actual? Se não, as variáveis actuais e o ecrã serão limpos. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. SpeedCrunch está minimizado. Para restaurar, clique com no ícone, ou com o botão direito para mais opções. Degree Grau (de Arco) All Files (*) Todos os Ficheiros (*) Radian Radiano The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. A barra de menus está agora invisível. Para torná-la novamente visível, pressione Ctrl+Alt+M. Binary Binário Engineering decimal Decimal para engenharia Fixed decimal Decimal fixo General decimal Decimal geral Hexadecimal Hexadecimal Octal Octal Scientific decimal Decimal científico Import Session Importar Sessão Merge session being imported with current session? If no, current variables and display will be cleared. Fundir a sessão que está a ser importada com a sessão actual?Se não, as variáveis actuais e o ecrã serão limpos. Export Session Exportar Sessão Math Book Livro de Matemática &Session &Sessão Clear E&xpression Limpar E&xpressão Clear &History Limpar &Histórico &Degree &Grau Delete All V&ariables Apagar Todas as V&ariáveis D&elete Variable... Apagar Variáv&el... &15 Decimal Digits &15 Casas Decimais &2 Decimal Digits &2 Casas Decimais &3 Decimal Digits &3 Casas Decimais &50 Decimal Digits &50 Casas Decimais &8 Decimal Digits &8 Casas Decimais &Automatic Precision Precisão &Automática &Copy &Copiar Copy Last &Result Copiar Último &Resultado &Paste Co&lar &About &Acerca About &Qt Acerca do &Qt SpeedCrunch &Web Site... &Página Internet... &Tip of the Day &Dica do Dia Insert &Function... Inserir &Função... Insert &Variable... Inserir &Variável... &Partial Results Resultados &Parciais Automatic &Completion &Completação Automática Always On &Top Sempre no &Topo &Minimize To System Tray &Minimizar para Bandeja do Sistema Syntax &Highlighting Realce de &Sintaxe &System Default &Predefinido do Sistema &Dot &Ponto &Comma &Vírgula &Radian &Radiano Scroll Display Down Deslizar Ecrã para Baixo Scroll Display Up Deslizar Ecrã para Cima &Select Expression &Seleccionar Expressão &Import... &Importar... &Load... &Carregar... &Quit &Sair &Save... &Guardar... &Export... &Exportar... Math &Book &Livro de Matemática &Constants &Constantes Full &Screen Mode Modo de &Ecrã Completo &Functions &Funções &History &Histórico &Keypad &Teclado Virtual Hide &Menu Bar Esconder Barra de &Menus &Status Bar &Barra de Estado &Variables &Variáveis &Binary &Binário &Engineering &Engenharia &Fixed Decimal Decimal Ponto &Fixo &General &Geral &Hexadecimal &Hexadecimal &Octal &Octal &Scientific &Científico System &Default &Predefinido do Sistema &Edit &Editar &View &Ver Se&ttings &Preferências Result &Format &Formato do Resultado &Decimal &Decimal &Angle Unit &Unidade de Ângulo &Behavior &Comportamento Radix &Character &Separador Fraccionário &Language &Língua &Help &Ajuda Angle unit Unidade de Ângulo Result format Formato do Resultado Ignore error? Ignorar erro? VariablesDock Variables Variáveis Search Pesquisar No match found Sem correspondências speedcrunch-0.10.1/src/i18n/id.ts0000644000175000001440000017252711015364561015610 0ustar helderusers AboutBox Special thanks to Terima kasih khususnya untuk French Bahasa Perancis German Bahasa Jerman Portuguese Bahasa Portugis Russian Bahasa Rusia Italian Bahasa Itali This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Program ini adalah perangkat lunak bebas; Anda dapat menyebarluaskannya dan/atau memodifikasinya di bawah ketentuan-ketentuan dari GNU General Public License seperti yang diterbitkan oleh Free Software Foundation; baik versi 2 dari Lisensi tersebut, atau (dengan pilihan Anda) versi lain yang lebih tinggi This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Program ini didistribusikan dengan harapan bahwa program ini akan berguna, tetapi TANPA GARANSI; tanpa garansi yang termasuk dari DAGANGAN atau KECOCOKAN UNTUK TUJUAN TERTENTU sekalipun. Lihat GNU General Public License untuk rincian lebih lanjut. SpeedCrunch version %1 SpeedCrunch versi %1 About SpeedCrunch Tentang SpeedCrunch Based on original idea from Berdasarkan idea dari Original author Pembuat Current maintainer Pemelihara Developers Pengembang Thanks to Terima kasih kepada ...and many others... ..dan masih banyak lainnya... Translations Terjemahan Argentinian Spanish Spanyol Argentina Brazilian Portuguese Portugis Brazil Czech Ceko Dutch Belanda Finnish Finlandia Hebrew Yahudi Indonesian Bahasa Indonesia Norwegian Norwegia Polish Polandia Romanian Romania Spanish Spanyol Swedish Swedia Turkish Turki Copyright (C) Hak cipta Visit <b>http://www.speedcrunch.org</b> for more information! Kunjungi <b>http://www.speedcrunch.org</b> untuk informasi lebih jauh! Close Tutup Graphics Basque Simplified Chinese Catalan BookDock Back Forward Index ConstantCompletion All Semua Constants Characteristic Impedance of Vacuum Impedansi Karakteristik Ruang Hampa General Physics Fisika Umum Electric Constant Konstanta Elektrik Magnetic Constant Konstanta Magnetik Gravitation Constant Konstanta Gravitasi Planck's Constant Konstanta Planck Dirac's Constant Konstanta Dirac Speed of Light in Vacuum Kecepatan Cahaya di Ruang Hampa Bohr-Procopiu Magneton Magneton Bohr-Procopiu Electromagnetic Elektromagnetik Conductance Quantum Quantum Konduktansi Coulomb's Constant Konstanta Coulomb Elementary Charge Muatan Dasar Josephson Constant Konstanta Josephson Magnetic Flux Quantum Quantum Fluks Magnetik Nuclear Magneton Magneton Nuklir Resistance Quantum Quantum Resistansi von Klitzing Constant Konstanta von Klitzing Bohr Radius Radius Bohr Atomic & Nuclear Atom & Inti Fermi Coupling Constant Konstant Coupling Fermi Fine-structure Constant Konstanta struktur padat Hartree Energy Energi Hartree Quantum of Circulation Quantum Sirkulasi Rydberg Constant Konstanta Rydberg Thomson Cross Section Penampang Thomson Weak Mixing Angle Sudut Pencampuran Lemah Atomic Mass Unit Satuan Massa Atom Physico-chemical Fisika-kimia Avogadro's Number Bilangan Avogadro Boltzmann Constant Konstanta Boltzmann Faraday Constant Konstanta Faraday First Radiation Constant Konstanta Radiasi Utama Loschmidt Constant Konstanta Loschmidt Gas Constant Konstanta Gas Molar Planck Constant Konstanta Molar Planck Second Radiation Constant Konstanta Radiasi Kedua Stefan-Boltzmann Constant Konstanta Stefan-Boltzmann Astronomical Unit Satuan Astronomi Astronomy Astronomi Light Year Tahun Cahaya Parsec Parsek Sidereal Year Tahun Sidereal days hari Tropical Year Tahun Tropik Gregorian Year Tahun Gregorian Earth Mass Massa Bumi Sun Mass Massa Matahari Mean Earth Radius Jari-jari rata-rata Bumi Sun Radius Jari-jari Matahari Sun Luminosity Luminositas Matahari ConstantsDock Constants Konstanta Category Kategori Search Cari No match found Tidak ada yang cocok All Semua DeleteVariableDlg Name Nama Value Nilai &Delete &Hapus Close Tutup Delete Variable Hapus Variabel Editor Current result: <b>%1</b> Selection result: <b>%1</b> Evaluator invalid expression division by zero unknown function or variable variable cannot be overwritten identifier matches an existing function name Functions Absolute Value Nilai Mutlak Average (Arithmetic Mean) Rata-rata Aritmetik Binary Representation Biner Cube Root Akar Kubik Ceiling Pembulatan ke atas Decimal Representation Desimal Floor Pembulatan ke bawah Fractional Part Bagian Pecahan Geometric Mean Rata-rata Geometrik Hexadecimal Representation Heksadesimal Integer Part Bagian Integer Maximum Maksimum Minimum Minimum Octal Representation Oktal Product Produk Rounding Pembulatan Signum Signum Square Root Akar Kuadrat Sum Jumlah Truncation Truncation Area Hyperbolic Cosine Kosinus Hiperbolik Area Area Hyperbolic Sine Sinus Hiperbolik Area Area Hyperbolic Tangent Tangen Hiperbolik Area Hyperbolic Cosine Kosinus Hiperbolik Exponential Eksponensial Base-2 Logarithm Logaritma Basis-10 {2 ?} Natural Logarithm Logaritma Natural Base-10 Logarithm Logaritma Basis-10 Hyperbolic Sine Sinus Hiperbolik Hyperbolic Tangent Tangen Hiperbolik Greatest Common Divisor Faktor Pembagi Terbesar Combination (Binomial Coefficient) Kombinasi (Koefisien Binomial) Permutation (Arrangement) Permutasi Binomial Cumulative Distribution Function Fungsi Distribusi Kumulatif Binomial Binomial Distribution Mean Rata-rata Distribusi Binomial Binomial Probability Mass Function Fungsi Massa Peluang Binomial Binomial Distribution Variance Varians Distribusi Binomial Hypergeometric Cumulative Distribution Function Fungsi Distribusi Kumulatif Hypergeometrik Hypergeometric Distribution Mean Rata-rata Distribusi Hypergeometrik Hypergeometric Probability Mass Function Fungsi Massa Peluang Hypergeometrik Hypergeometric Distribution Variance Varians Distribusi Hypergeometrik Poissonian Cumulative Distribution Function Fungsi Distribusi Kumulatif Poisson Poissonian Distribution Mean Rata-rata Distribusi Poisson Poissonian Probability Mass Function Fungsi Massa Peluang Poisson Poissonian Distribution Variance Varians Distribusi Poisson Arc Cosine Arc Kosinus Arc Sine Arc Sinus Arc Tangent Arc Tangen Cosine Kosinus Cotangent Kotangen Cosecant Kosekant Radians Radian Secant Secant Sine Sinus Tangent Tangen cannot execute function %1 tidak dapat menjalankan fungsi %1 function accepts 1 argument fungsi hanya menerima 1 argumen function accepts %1 arguments fungsi memerlukan %1 argumen function requires 1 or 2 arguments fungsi memerlukan 1 atau 2 argumen function undefined for specified arguments argumen untuk fungsi tidak valid function requires at least 2 arguments fungsi memerlukan 2 argumen atau lebih function requires integer arguments fungsi memerlukan argumen integer function undefined for specified argument argument untuk fungsi tidak valid underflow function requires at least 1 argument fungsi memerlukan 1 argumen atau lebih Extension of Factorials [= (x-1)!] ln(abs(Gamma)) Error Function Complementary Error Function Degrees of Arc Mask to a bit size Sign-extent a value Logical NOT Logical AND Logical OR Logical XOR Arithmetic Shift Left Arithmetic Shift Right Integer Quotient Modulo FunctionsDock Functions Fungsi Search Cari No match found Tidak ada yang cocok HistoryDock History History InsertFunctionDlg Name Nama Description Penjelasan &Insert &Sisipkan Cancel Batal Insert Function Sisipkan Fungsi InsertVariableDlg Name Nama Value Nilai &Insert &Sisipkan Cancel Batal Insert Variable Sisipkan Variabel Keypad Inverse cosine Arccos The last result Inverse sine Arcsin Inverse tangent Arctan Clear expression Cosine Kosinus Scientific notation Exponential Eksponensial Natural logarithm Sine Sinus Square root Akar kuadrat Tangent Tangen Assign variable x The variable x MainWindow About Qt Tentang Qt SpeedCrunch Sessions (*.sch);;All Files (*) Load Session Error Kesalahan Can't read from file %1 Question Save Session Simpan Sesi Can't write to file %1 Tidak dapat menulis ke berkas %1 Warning To insert a function using keyboard, use Ctrl+F shorcut. From the dialog, you can choose the function you want to insert. Untuk menyisipkan sebuah fungsi menggunakan keyboard, gunakan Ctrl+F. Dari dialog, pilih fungsi yang akan disisipkan. To insert a variable using keyboard, use Ctrl+I shorcut. From the dialog, you can choose the variable you want to insert. Untuk menyisipkan sebuah variabel menggunakan keyboard, gunakan Ctrl+I. Dari dialog, pilih variabel yang akan disisipkan. Use variable <i>pi</i> to use pi constant. Gunakan variabel <i>pi</i> untuk konstanta pi. Use <i>;</i> (semicolon) to separate the parameters in functions. Gunakan <i>;</i> (titik koma) untuk memisakan argument fungsi. Tip of the day File %1 is not a valid session Merge session being loaded with current session? If no, current variables and display will be cleared. SpeedCrunch is minimized. Left click the icon to restore it or right click for options. Degree All Files (*) Radian The menu bar is now hidden. To make it visible again, press Ctrl+Alt+M. Binary Engineering decimal Fixed decimal General decimal Hexadecimal Octal Scientific decimal Import Session Merge session being imported with current session? If no, current variables and display will be cleared. Export Session Math Book &Session &Sesi Clear E&xpression Clear &History Bersihkan Histor&y &Degree Delete All V&ariables D&elete Variable... Ha&pus Variabel... &15 Decimal Digits &15 Angka Desimal &2 Decimal Digits &2 Angka Desimal &3 Decimal Digits &3 Angka Desimal &50 Decimal Digits &50 Angka Desimal &8 Decimal Digits &8 Angka Desimal &Automatic Precision Ketelitian &Otomatis &Copy &Salin Copy Last &Result &Paste &Tempel &About &Tentang About &Qt Tentang &Qt SpeedCrunch &Web Site... Situs &Web SpeedCrunch... &Tip of the Day &Tip Hari Ini Insert &Function... Sisipkan &Fungsi... Insert &Variable... Sisipkan &Variabel... &Partial Results Automatic &Completion Always On &Top &Minimize To System Tray Syntax &Highlighting &System Default &Dot &Comma &Radian Scroll Display Down Scroll Display Up &Select Expression &Import... &Load... &Quit &Keluar &Save... &Simpan... &Export... Math &Book &Constants Full &Screen Mode &Functions &History &Keypad Hide &Menu Bar &Status Bar &Variables &Binary &Biner &Engineering &Engineering &Fixed Decimal Format Desimal &Tetap &General Format &Umum &Hexadecimal &Heksadesimal &Octal &Oktal &Scientific &Scientific System &Default &Edit &Ubah &View &Tilik Se&ttings &Pengaturan Result &Format &Decimal &Angle Unit &Behavior Radix &Character &Language &Help &Bantuan Angle unit Result format Ignore error? VariablesDock Variables Variabel Search Cari No match found Tidak ada yang cocok speedcrunch-0.10.1/INSTALL.txt0000644000175000001440000000105311015364561015126 0ustar helderusersInstruction to compile SpeedCrunch from source code Requirements: - CMake 2.4 or newer - Qt 4.2 or newer Steps: - Create a sub-directory named 'build' - Go to this sub-directory - Run CMake like this: cmake ../src - Then run make make - To install, run (you might need administration priveleges) make install NOTE: if you want to run SpeedCrunch translated in one of the supported languages, you really need to perform the last step in order to install the translation files (*.qm) to the directory where SpeedCrunch will look at for them. speedcrunch-0.10.1/ChangeLog0000644000175000001440000003271311015364561015040 0ustar helderusersSpeedCrunch 0.10.1 --------------------- Bug fixes: Fixed keypad button "=" [#176] Fixed incomplete math book link upon clicking [#177] Fixed potential crashes [#180] Fixed back and forward buttons have the opposite meaning in RTL [#185] Fixed missing window update on radix character change Updated binreloc to build in LSB environments Improvements: Better handling of math book translations with language codes that contain the country component and now correct behaviour defaulting to English when the system language (selected option) is not supported Internationalization: New Basque, Catalan and Simplified Chinese translation Updated translations Removed Slovenian language menu entry, since there is no such translation available Packaging: New Mac OS X Universal Binary finally available (first since version 0.7) SpeedCrunch 0.10 --------------------- New features: Preliminary support of logic functions Extended output of real-valued numbers to non-decimal modes Allow real-valued arguments for nPr and nCr Restore last session Save and load session Ability to change language on-the-fly Context menu for tray icon Support for RTL (right to left) written languages Batch calculation Minimal view version Default desktop file for menu integration New Turkish (incomplete) translation Math Book browsable pages in a dock window Compile-time option to build a "portable" target Full screen mode Automatic syntax highlighting color generation Status bar Auto-calc of the selected text New functions: ERF: the normalized error function (related to normal distribution) ERFC: the complementary error function GAMMA: the extension of the factorials (x-1)! LNGAMMA: ln(Gamma(x)) for x > 0 IDIV: integer division MOD: modulo Improvements: Improved binomCdf evaluation allows n to be as big as 20000 now Improved keypad Testevaluator independent of locale (does not use ',' any more) Exp/Log inconsistency New keyboard shortcuts (including PagDown/PgUp to scroll result display) Redesigned menus Optional widgets created and destroyed on the fly, optimal for mobile devices Click to copy and double click to insert an expression from the display into the expression editor Errors displayed in modal dialog instead of result display Selecting and inserting an expression does not trigger evaluation Bug fixes: Fixed loss of precision on variable saving Fixed clobbering of ans on radix change Fixed a bug in the math engine (float_frac) that could cause memory corruption Bugfix in the pochhammer symbol evaluating routine, affecting nPr when n and r are negative integers, and n == r-1 Bugfix: No freeze any more when evaluating (-n+0.5)! for very large integers n Bugfix: cbrt fixed for values 1+x with x << 1 No more short freeze after restoring from system tray on Windows All widgets reflect current preference for the radix character Results copied according to selected number base Translations work on Windows Restoring from minimize state hides dock windows Resizing of expression editor Close button closes dock windows instead Bad shortcuts on Windows installer Operator color set to system foreground in highlight mode Virtual desktop switching hides open dock windows Unsecure built-in variables Ans is saved but not recovered on startup Copy result uses prefered radix character Result window does not scroll to latest result Result screen resizing issues Docks windows don't close Result display scroll bar doesn't have system background color Autocalc tip according to prefered result format, precision and radix char Docks don't react to Return or Enter Display of completion popup when pasting text to the expression editor Hide function/variable completion after clicking mouse button somewhere else SpeedCrunch 0.9 --------------------- New features: Greatly extended number range Factorials extended to real values Stay always-on-top (#106) New functions: ARSINH: area hyperbolic sine, the reverse of sinh ARCOSH: area hyperbolic cosine, the reverse of cosh ARTANH: area hyperbolic tangent, the reverse of tanh Improvements and bug fixes: Replaced the math engine, Solving issue #53, #78, #98, Preparing a solution for issue #16, #62, #90, Better support for issue #47 Uniform and predictable accuracy Correct rounding (2.5 is rounded to 2 [even last digit rule]) Stable algorithms covering the whole range of numbers Faster evaluation of higher mathematical function (factor 9 on the average) Supports stable evaluation of basic higher functions near poles and zeros Built-in support of conversion of all (integer, real, huge, tiny) values to other bases Built-in support of logic operations Built-in support of the missing area hyperbolic functions Built-in support of a new class of functions, Gamma and friends Fixed incorrect evaluation of GEOMEAN Fixed dependency of sinh, cosh, tanh on degree setting Extended TRUNC to the new range of exponents. In addition, TRUNC accepts a negative second parameter now: TRUNC(1234.56; -2) is 1200, so not only digits from the fractional part can be cleared, but also the least significant digits from the integer part. Extended ROUND in a way similar to TRUNC SpeedCrunch 0.8 --------------------- New features: Support for different bases: hex, octal and binary Postfix factorial operator (!) Support inserting important physics constants History, functions, variables, constants in docked/floated windows Added engineering notation Added unmutable variable "phi" (golden number = 1.6180339887498948482...) "Tip of the day" Option to hide from taskbar and minimize to system tray Support for right-to-left languages (not perfect, but very close to it) Translations: de es es_AR fi fr he it nl no pt pt_BR ro ru sv (see TRANSLATORS) New functions: MIN: get the minimum MAX: get the maximum SUM: sum of all numbers PRODUCT: product of all numbers AVERAGE: average or mean GEOMEAN: geometrical mean SIGN: signum DEGREES: convert radian to degree RADIANS: convert degree to radian LG: base-2 logarithm CBRT: cube root TRUNC: truncate digits FLOOR: floor CEIL: ceiling ROUND: round number NCR: combination NPR: permutation GCD: greatest common divisor SEC: secant CSC: cosecant COT: cotangent BINOMPMF: binomial probability mass function BINOMCDF: binomial cumulative distribution function BINOMMEAN: binomial distribution mean BINOMVAR: binomial distribution variance HYPERPMF: hypergeometric probability mass function HYPERCDF: hypergeometric cumulative distribution function HYPERMEAN: hypergeometric distribution mean HYPERVAR: hypergeometric distribution variance POIPMF: poissonian probability mass function POICDF: poissonian cumulative distribution function POIMEAN: poissonian distribution mean POIVAR: poissonian distribution variance Improvements and bug fixes: Fixed accuracy problem when calculating 10^x where x is integer Variable names are now case sensitive in and between sessions Shortcut Ctrl+Q to quit (ubuntu bug#102734) Shortcut key F6 to focus and select input Shortcut key Esc to clear the input Improved (and non-intrusive) autocalc tip Reserved variable names are now case sensitive "pi" and "ans" Color for error messages can be customized Fixed exp(x) when x is large Improved error system and messages, introduced Px notation to refer parameters Fixed issue #33: exponential notation misnamed Fixed issue #32: crash when inserting ( after variable Minor fixed function tan(x) Binary is now relocatable (using BinReloc) All divisions by zero are now caught Fixed issue #63: incorrect acos(x) return value Arrow keys now work to hide completion popup SpeedCrunch 0.7 --------------- Fixed CMake build under Mac OS X Fixed very wide buttons when using Cleanlooks style Updated link to new homepage Fixed issue #17: crash with segmentation fault Fixed issue #22: segfault after equal,backspace,evaluate, operator Fixed issue #27: program closed unexpectedly Fixed issue #28: crash on pressing "/" Support for building using CMake Fixed issue #9: unary minus before a function Fixed issue #7: function argument in brackets Fixed issue #6: exponentiation of a negative number returns NaN Fixed issue #5: auto calculation shows up even on the first run Fixed issue #4: should scroll automatically to show the result Fixed issue #3: function argument starts with unary minus Patched crunch.pro to fix "make install" (thanks to Vladimir Pouzanov) Made the application look for translations in the current directory too Updated the russian, french and portuguese translations Changed from Qt 3 to Qt 4 Changed the configure script to be compatible with Qt 4 Converted the layout system from container widgets to layouts Added the keypad Added an application icon for windows systems SpeedCrunch 0.6-beta2 --------------------- Fixed mouse wheel scrolls do not recally history Too large or too small number yields NaN, instead of silently becomes 0 Added (partial) Czech translation by Blondak (blondak@neser.cz) Added Portuguese BR by Henrique Pinto (henrique.pinto@kdemail.net) Fixed Enter in numeric keypad does not evaluate Flicker-free about box, by Michael Pyne (pynm0001@comcast.net) Comma key is also mapped as gives decimal digit, by Thomas Luebking Copy displayed item by clicking on it, by Gary Cramblitt MS visual C++ fixes, by Philippe Fremy SpeedCrunch 0.6-beta1 ----------------------------------- Support for syntax highlight, with matched parenthesis indicator Calc-As-You-Type: show result even before you finish typing Autocomplete now also works for variables Fixed invisible pop-up completion for very long expression Show function description in function name autocomplete Show variable value in variable name autocomplete Dialog position/size are not saved anymore (leave it to the WM) Better display of long error message, Pieter Pareit (pieter.pareit@scarlet.be) Prompt error when trying to overwrite variable PI Translation (i18n) of all error messages Error when unknown variable is in the expression Always reuse already shown dialog, do not recreate Support deleting variable(s) (Ctrl+D) Prevent variable name like 'sin', 'tan', etc Simple tooltip on "clear input" button SpeedCrunch 0.5.4 ----------------- German translation by Damir Perisa (damir.perisa@solnet.ch) Fixed i18n problem caused by errorneous handling of LANG Minor fix in Portuguese translation Indonesian translation by Yolla Indria (yolla.indria@gmail.com) SpeedCrunch 0.5.3 ----------------- Fixed bug with function asin and acos Portuguese translation by Helder Correia (helder.pereira.correia@gmail.com) Russian translation by Alexey Kouznetsov (kouznetsov@phtf.stu.neva.ru) Italian translation by Francesco di Cugno (fdicugno@gmail.com) Fixed invisible popup completion in maximized window Removed unnecessary artwork in dialog box Fixed autocomplete in the middle of expression SpeedCrunch 0.5.2 ----------------- Fixed grave bug which made percentage operator did not work French translation by Vibet Alexis (bevi@netcourrier.com) SpeedCrunch 0.5.1 ----------------- Fixed bug related to degrees mode Fixed compile in FreeBSD SpeedCrunch 0.5 --------------- Higher precision, up to 50 decimal digits Format for numbers: general, fixed decimals or exponential Shown decimal digits can vary from 2 to 50 Merge Insert menu to Edit menu Optional clear input button Optional evaluate button Fixed shortcut conflict between Session and Settings menus Error messages shown in red color Pixmaps are handled better in the build system SpeedCrunch 0.4 --------------- Configuration dialog Session can be exported to text file (Ctrl+S) Customize font and color for the display History and variables are saved between sessions Auto-completion for function name New functions: int, frac, round Little margins (left and right) for the display Application icon, thanks to Kuswanto (aka Zeus) Every dialog's settings (size+position) are always saved Fixed wrong parsing for "sin -90" and similar syntax Show license and credits in the (new and fancier) about box SpeedCrunch 0.3 --------------- Now it has menubar Clear the screen, history, and/or variables Ctrl+I to activate Insert Variable dialog Ctrl+F to activate Insert Function dialog Simple function, e.g "cos" is treated as "cos(ans)" Ctrl+R to copy last result to clipboard Anything shown in the screen is also dumped to stdout tan 90 and tan 270 correctly gives error About box, to show program version SpeedCrunch 0.2 --------------- Percent operator, try e.g. "45%*75" or "price/80%" Support for simplified syntax, e.g. "sin x" instead of "sin(x)" Angle mode: Alt+D for degrees, Alt+R for radians Horizontal scrollbar appears when result becomes wider Fixed bug where built-in function always returns error Fixed wrong operator precedence ("2**3**2" now correctly gives 512) Source tarball includes GPL license file SpeedCrunch 0.1 --------------- History of last expressions (use up and down arrow) Result shown in scrollable window Built-in functions: abs, sqrt, pi, log, exp, ln, sin, cos, tan, sinh, cosh, tanh, asin, acos, atan Support for variables, e.g try "x=pi/3" and then "sin(x)" Special variable ans holds the last calculation result Automatic parentheses closing, e.g. "cos(pi/4" becomes "cos(pi/4)"